feat: aggiunta ricerca spudorata. progress: ripreso con il tentativo di invio delle mail che non creino nuovi ticket
This commit is contained in:
1 parent
3650bf5790
commit
8d24759a15
18 files changed
+1661
-98
No files matched your search
+109
-48
@@ -890,8 +890,9 @@ router.patch('/:id', async (req, res) => {
|
||||
|
||||
if (setClauses.length > 0) {
|
||||
// Always update change_time and change_by
|
||||
setClauses.push(`change_time = NOW()`);
|
||||
setClauses.push(`change_time = $${pIdx++}`);
|
||||
setClauses.push(`change_by = $${pIdx++}`);
|
||||
setParams.push(localNow);
|
||||
setParams.push(operatorId);
|
||||
setParams.push(parseInt(id));
|
||||
|
||||
@@ -902,8 +903,8 @@ router.patch('/:id', async (req, res) => {
|
||||
} else {
|
||||
// If there are no fields modified but we have a note or time_unit, we still update change_time/change_by
|
||||
await client.query(
|
||||
`UPDATE ticket SET change_time = NOW(), change_by = $1 WHERE id = $2`,
|
||||
[operatorId, id]
|
||||
`UPDATE ticket SET change_time = $1, change_by = $2 WHERE id = $3`,
|
||||
[localNow, operatorId, id]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -950,13 +951,13 @@ router.patch('/:id', async (req, res) => {
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5,
|
||||
$6, $7, $8,
|
||||
NOW(), $9, NOW(), $9
|
||||
$9, $10, $9, $10
|
||||
)`,
|
||||
[
|
||||
historyName,
|
||||
htResult.rows[0].id, parseInt(id), newTypeId, newQueueId,
|
||||
newOwnerId, newPriorityId, newStateId,
|
||||
operatorId
|
||||
localNow, operatorId
|
||||
]
|
||||
);
|
||||
}
|
||||
@@ -983,9 +984,9 @@ router.patch('/:id', async (req, res) => {
|
||||
is_visible_for_customer, search_index_needs_rebuild,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES (
|
||||
$1, $2, $3, 0, 1, NOW(), $4, NOW(), $4
|
||||
$1, $2, $3, 0, 1, $4, $5, $4, $5
|
||||
) RETURNING id`,
|
||||
[id, senderTypeId, channelId, operatorId]
|
||||
[id, senderTypeId, channelId, localNow, operatorId]
|
||||
);
|
||||
|
||||
const articleId = articleResult.rows[0].id;
|
||||
@@ -1012,9 +1013,9 @@ router.patch('/:id', async (req, res) => {
|
||||
$1, $2, '', '', '', '', $3, $4,
|
||||
'', '', '',
|
||||
'text/html; charset=utf-8', EXTRACT(EPOCH FROM NOW())::INTEGER, $5,
|
||||
NOW(), $6, NOW(), $6
|
||||
$6, $7, $6, $7
|
||||
)`,
|
||||
[articleId, fromHeader, noteSubject, htmlBody, contentPath, operatorId]
|
||||
[articleId, fromHeader, noteSubject, htmlBody, contentPath, localNow, operatorId]
|
||||
);
|
||||
|
||||
// Create article_data_mime_attachment for OTRS CE HTML rendering
|
||||
@@ -1024,9 +1025,9 @@ router.patch('/:id', async (req, res) => {
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES (
|
||||
$1, 'file-1', $2, 'text/html; charset="utf-8"', '', $3,
|
||||
NOW(), $4, NOW(), $4
|
||||
$4, $5, $4, $5
|
||||
)`,
|
||||
[articleId, String(contentSize), base64Body, operatorId]
|
||||
[articleId, String(contentSize), base64Body, localNow, operatorId]
|
||||
);
|
||||
|
||||
// Log the time in time_accounting if provided
|
||||
@@ -1035,8 +1036,8 @@ router.patch('/:id', async (req, res) => {
|
||||
`INSERT INTO time_accounting (
|
||||
ticket_id, article_id, time_unit,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, $2, $3, NOW(), $4, NOW(), $4)`,
|
||||
[id, articleId, timeUnitVal, operatorId]
|
||||
) VALUES ($1, $2, $3, $4, $5, $4, $5)`,
|
||||
[id, articleId, timeUnitVal, localNow, operatorId]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1733,44 +1734,60 @@ router.post('/merge', async (req, res) => {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
const localNow = getLocalTimestamp();
|
||||
|
||||
// Fetch target ticket details
|
||||
const targetRes = await client.query('SELECT tn, title FROM ticket WHERE id = $1', [targetId]);
|
||||
const targetRes = await client.query(
|
||||
'SELECT tn, title, queue_id, user_id, ticket_priority_id, ticket_state_id, type_id FROM ticket WHERE id = $1',
|
||||
[targetId]
|
||||
);
|
||||
if (targetRes.rows.length === 0) {
|
||||
throw new Error(`Ticket di destinazione #${targetId} non trovato`);
|
||||
}
|
||||
const targetTn = targetRes.rows[0].tn;
|
||||
const targetTitle = targetRes.rows[0].title;
|
||||
const targetRow = targetRes.rows[0];
|
||||
|
||||
// Fetch history type IDs
|
||||
const htStateRes = await client.query(`SELECT id FROM ticket_history_type WHERE name = 'StateUpdate'`);
|
||||
const stateUpdateTypeId = htStateRes.rows.length > 0 ? htStateRes.rows[0].id : 1;
|
||||
|
||||
const htNoteRes = await client.query(`SELECT id FROM ticket_history_type WHERE name = 'AddNote'`);
|
||||
const addNoteTypeId = htNoteRes.rows.length > 0 ? htNoteRes.rows[0].id : 1;
|
||||
|
||||
for (const sourceId of sourceIds) {
|
||||
// Fetch source ticket details
|
||||
const sourceRes = await client.query('SELECT tn, title FROM ticket WHERE id = $1', [sourceId]);
|
||||
const sourceRes = await client.query(
|
||||
'SELECT tn, title, queue_id, user_id, ticket_priority_id, type_id FROM ticket WHERE id = $1',
|
||||
[sourceId]
|
||||
);
|
||||
if (sourceRes.rows.length === 0) continue;
|
||||
const sourceTn = sourceRes.rows[0].tn;
|
||||
const sourceTitle = sourceRes.rows[0].title;
|
||||
const sourceRow = sourceRes.rows[0];
|
||||
|
||||
// 1. Move all articles of source to target
|
||||
await client.query(
|
||||
`UPDATE article
|
||||
SET ticket_id = $1, change_time = NOW(), change_by = $2
|
||||
WHERE ticket_id = $3`,
|
||||
[targetId, operatorId, sourceId]
|
||||
SET ticket_id = $1, change_time = $2, change_by = $3
|
||||
WHERE ticket_id = $4`,
|
||||
[targetId, localNow, operatorId, sourceId]
|
||||
);
|
||||
|
||||
// 2. Move all time accounting entries
|
||||
await client.query(
|
||||
`UPDATE time_accounting
|
||||
SET ticket_id = $1, change_time = NOW(), change_by = $2
|
||||
WHERE ticket_id = $3`,
|
||||
[targetId, operatorId, sourceId]
|
||||
SET ticket_id = $1, change_time = $2, change_by = $3
|
||||
WHERE ticket_id = $4`,
|
||||
[targetId, localNow, operatorId, sourceId]
|
||||
);
|
||||
|
||||
// 3. Mark source ticket as merged (state_id = 9)
|
||||
await client.query(
|
||||
`UPDATE ticket
|
||||
SET ticket_state_id = 9, change_time = NOW(), change_by = $1
|
||||
WHERE id = $2`,
|
||||
[operatorId, sourceId]
|
||||
SET ticket_state_id = 9, change_time = $1, change_by = $2
|
||||
WHERE id = $3`,
|
||||
[localNow, operatorId, sourceId]
|
||||
);
|
||||
|
||||
// 4. Create ParentChild relation link (source B is child/merged of target A)
|
||||
@@ -1786,8 +1803,8 @@ router.post('/merge', async (req, res) => {
|
||||
`INSERT INTO link_relation (
|
||||
source_object_id, source_key, target_object_id, target_key,
|
||||
type_id, state_id, create_time, create_by
|
||||
) VALUES (1, $1, 1, $2, 2, 1, NOW(), $3)`,
|
||||
[String(sourceId), String(targetId), operatorId]
|
||||
) VALUES (1, $1, 1, $2, 2, 1, $3, $4)`,
|
||||
[String(sourceId), String(targetId), localNow, operatorId]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1801,8 +1818,8 @@ router.post('/merge', async (req, res) => {
|
||||
ticket_id, article_sender_type_id, communication_channel_id,
|
||||
is_visible_for_customer, search_index_needs_rebuild,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, 1, 1, 0, 1, NOW(), $2, NOW(), $2) RETURNING id`,
|
||||
[targetId, operatorId]
|
||||
) VALUES ($1, 1, 1, 0, 1, $2, $3, $2, $3) RETURNING id`,
|
||||
[targetId, localNow, operatorId]
|
||||
);
|
||||
const articleId = artResult.rows[0].id;
|
||||
|
||||
@@ -1818,9 +1835,9 @@ router.post('/merge', async (req, res) => {
|
||||
$1, 'Sistema OTRS Turbo', '', '', '', '', 'Ticket Unito', $2,
|
||||
'', '', '',
|
||||
'text/plain; charset=utf-8', EXTRACT(EPOCH FROM NOW())::INTEGER, $3,
|
||||
NOW(), $4, NOW(), $4
|
||||
$4, $5, $4, $5
|
||||
)`,
|
||||
[articleId, mergeNoteBody, contentPath, operatorId]
|
||||
[articleId, mergeNoteBody, contentPath, localNow, operatorId]
|
||||
);
|
||||
|
||||
// Create internal system note inside source ticket B (the merged ticket)
|
||||
@@ -1829,8 +1846,8 @@ router.post('/merge', async (req, res) => {
|
||||
ticket_id, article_sender_type_id, communication_channel_id,
|
||||
is_visible_for_customer, search_index_needs_rebuild,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, 1, 1, 0, 1, NOW(), $2, NOW(), $2) RETURNING id`,
|
||||
[sourceId, operatorId]
|
||||
) VALUES ($1, 1, 1, 0, 1, $2, $3, $2, $3) RETURNING id`,
|
||||
[sourceId, localNow, operatorId]
|
||||
);
|
||||
const sourceArticleId = sourceArtResult.rows[0].id;
|
||||
const sourceMergeNoteText = `Merged Ticket ${sourceTn} to ${targetTn}`;
|
||||
@@ -1845,12 +1862,54 @@ router.post('/merge', async (req, res) => {
|
||||
$1, 'Sistema OTRS Turbo', '', '', '', '', $2, $2,
|
||||
'', '', '',
|
||||
'text/plain; charset=utf-8', EXTRACT(EPOCH FROM NOW())::INTEGER, $3,
|
||||
NOW(), $4, NOW(), $4
|
||||
$4, $5, $4, $5
|
||||
)`,
|
||||
[sourceArticleId, sourceMergeNoteText, contentPath, operatorId]
|
||||
[sourceArticleId, sourceMergeNoteText, contentPath, localNow, operatorId]
|
||||
);
|
||||
|
||||
// 6. Record ticket history for source ticket (state changed to merged = 9)
|
||||
await client.query(
|
||||
`INSERT INTO ticket_history (
|
||||
name, history_type_id, ticket_id, type_id, queue_id,
|
||||
owner_id, priority_id, state_id,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES (
|
||||
'%%merged%%', $1, $2, $3, $4,
|
||||
$5, $6, 9,
|
||||
$7, $8, $7, $8
|
||||
)`,
|
||||
[
|
||||
stateUpdateTypeId, sourceId, sourceRow.type_id || 1, sourceRow.queue_id,
|
||||
sourceRow.user_id || 1, sourceRow.ticket_priority_id || 1,
|
||||
localNow, operatorId
|
||||
]
|
||||
);
|
||||
|
||||
// 7. Record ticket history for target ticket (note added for merge)
|
||||
await client.query(
|
||||
`INSERT INTO ticket_history (
|
||||
name, history_type_id, ticket_id, article_id, type_id, queue_id,
|
||||
owner_id, priority_id, state_id,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES (
|
||||
'%%', $1, $2, $3, $4, $5,
|
||||
$6, $7, $8,
|
||||
$9, $10, $9, $10
|
||||
)`,
|
||||
[
|
||||
addNoteTypeId, targetId, articleId, targetRow.type_id || 1, targetRow.queue_id,
|
||||
targetRow.user_id || 1, targetRow.ticket_priority_id || 1, targetRow.ticket_state_id || 1,
|
||||
localNow, operatorId
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// Update target ticket change_time & change_by
|
||||
await client.query(
|
||||
`UPDATE ticket SET change_time = $1, change_by = $2 WHERE id = $3`,
|
||||
[localNow, operatorId, targetId]
|
||||
);
|
||||
|
||||
await client.query('COMMIT');
|
||||
resolveAgentName(operatorId).then(agente_nome => {
|
||||
logAttivita({
|
||||
@@ -2185,6 +2244,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
const tn = `${datePrefix}${String(counter).padStart(counterPadding, '0')}`;
|
||||
|
||||
// 3. Create Ticket (lock = 1 [unlock], owner & responsible = operatorId)
|
||||
const localNow = getLocalTimestamp();
|
||||
|
||||
const ticketResult = await client.query(
|
||||
`INSERT INTO ticket (
|
||||
tn, title, queue_id, ticket_lock_id, type_id,
|
||||
@@ -2205,14 +2266,14 @@ router.post('/auto-time', async (req, res) => {
|
||||
0, 0,
|
||||
0, 0,
|
||||
0,
|
||||
NOW(), $10, NOW(), $10
|
||||
$10, $11, $10, $11
|
||||
) RETURNING id, tn`,
|
||||
[
|
||||
tn, title, queueId, typeId,
|
||||
operatorId,
|
||||
priorityId, stateId,
|
||||
customerId, customerUserId,
|
||||
operatorId
|
||||
localNow, operatorId
|
||||
]
|
||||
);
|
||||
const ticketId = ticketResult.rows[0].id;
|
||||
@@ -2227,8 +2288,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
name, history_type_id, ticket_id, type_id, queue_id,
|
||||
owner_id, priority_id, state_id,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, NOW(), $9, NOW(), $9)`,
|
||||
['%%', historyTypeId, ticketId, typeId || 1, queueId, operatorId, priorityId, stateId, operatorId]
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $9, $10)`,
|
||||
['%%', historyTypeId, ticketId, typeId || 1, queueId, operatorId, priorityId, stateId, localNow, operatorId]
|
||||
);
|
||||
|
||||
// 4. Create Article (Internal note)
|
||||
@@ -2247,8 +2308,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
ticket_id, article_sender_type_id, communication_channel_id,
|
||||
is_visible_for_customer, search_index_needs_rebuild,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, $2, $3, 0, 1, NOW(), $4, NOW(), $4) RETURNING id`,
|
||||
[ticketId, senderTypeId, channelId, operatorId]
|
||||
) VALUES ($1, $2, $3, 0, 1, $4, $5, $4, $5) RETURNING id`,
|
||||
[ticketId, senderTypeId, channelId, localNow, operatorId]
|
||||
);
|
||||
const articleId = articleResult.rows[0].id;
|
||||
|
||||
@@ -2269,9 +2330,9 @@ router.post('/auto-time', async (req, res) => {
|
||||
) VALUES (
|
||||
$1, $2, '', $3, $4,
|
||||
'text/html; charset=utf-8', EXTRACT(EPOCH FROM NOW())::INTEGER, $5,
|
||||
NOW(), $6, NOW(), $6
|
||||
$6, $7, $6, $7
|
||||
)`,
|
||||
[articleId, fromHeader, subject, htmlBody, contentPath, operatorId]
|
||||
[articleId, fromHeader, subject, htmlBody, contentPath, localNow, operatorId]
|
||||
);
|
||||
|
||||
// Create article attachment (file-1) for OTRS CE HTML display
|
||||
@@ -2279,8 +2340,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
`INSERT INTO article_data_mime_attachment (
|
||||
article_id, filename, content_size, content_type, disposition, content,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, 'file-1', $2, 'text/html; charset="utf-8"', '', $3, NOW(), $4, NOW(), $4)`,
|
||||
[articleId, String(contentSize), base64Body, operatorId]
|
||||
) VALUES ($1, 'file-1', $2, 'text/html; charset="utf-8"', '', $3, $4, $5, $4, $5)`,
|
||||
[articleId, String(contentSize), base64Body, localNow, operatorId]
|
||||
);
|
||||
|
||||
// 5. Create Time Accounting Entry for remaining minutes
|
||||
@@ -2288,8 +2349,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
`INSERT INTO time_accounting (
|
||||
ticket_id, article_id, time_unit,
|
||||
create_time, create_by, change_time, change_by
|
||||
) VALUES ($1, $2, $3, NOW(), $4, NOW(), $4)`,
|
||||
[ticketId, articleId, remaining, operatorId]
|
||||
) VALUES ($1, $2, $3, $4, $5, $4, $5)`,
|
||||
[ticketId, articleId, remaining, localNow, operatorId]
|
||||
);
|
||||
|
||||
// 6. Close tickets in default group 'CHIUDI A FINE GIORNATA'
|
||||
@@ -2303,8 +2364,8 @@ router.post('/auto-time', async (req, res) => {
|
||||
|
||||
// Update ticket state to closed in OTRS DB
|
||||
await client.query(
|
||||
`UPDATE ticket SET ticket_state_id = $${groupTicketIds.length + 1}, change_time = NOW(), change_by = $${groupTicketIds.length + 2} WHERE id IN (${idPlaceholders})`,
|
||||
[...groupTicketIds, stateId, operatorId]
|
||||
`UPDATE ticket SET ticket_state_id = $${groupTicketIds.length + 1}, change_time = $${groupTicketIds.length + 2}, change_by = $${groupTicketIds.length + 3} WHERE id IN (${idPlaceholders})`,
|
||||
[...groupTicketIds, stateId, localNow, operatorId]
|
||||
);
|
||||
|
||||
console.log(`[Auto-Time] Closed ${groupTicketIds.length} tickets from group 'CHIUDI A FINE GIORNATA'`);
|
||||
|
||||
Reference in new issue
Block a user