mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 00:31:12 -05:00
Fix ticket merging implementation
This commit is contained in:
@@ -507,7 +507,26 @@ export default function AdminContact() {
|
|||||||
const handleConfirmMerge = () => {
|
const handleConfirmMerge = () => {
|
||||||
if (!primaryTicketId || selectedForMerge.length < 2) return;
|
if (!primaryTicketId || selectedForMerge.length < 2) return;
|
||||||
|
|
||||||
|
// Ensure primary is actually in the selected list
|
||||||
|
if (!selectedForMerge.includes(primaryTicketId)) {
|
||||||
|
handleError(
|
||||||
|
new Error('Primary ticket must be one of the selected tickets'),
|
||||||
|
{ action: 'Merge Tickets' }
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const mergeIds = selectedForMerge.filter(id => id !== primaryTicketId);
|
const mergeIds = selectedForMerge.filter(id => id !== primaryTicketId);
|
||||||
|
|
||||||
|
// Additional validation: ensure we have tickets to merge
|
||||||
|
if (mergeIds.length === 0) {
|
||||||
|
handleError(
|
||||||
|
new Error('No tickets to merge. Please select at least 2 tickets.'),
|
||||||
|
{ action: 'Merge Tickets' }
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mergeTicketsMutation.mutate({
|
mergeTicketsMutation.mutate({
|
||||||
primaryId: primaryTicketId,
|
primaryId: primaryTicketId,
|
||||||
mergeIds,
|
mergeIds,
|
||||||
|
|||||||
@@ -124,6 +124,11 @@ serve(async (req) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Step 1: Move all email threads to primary ticket
|
// Step 1: Move all email threads to primary ticket
|
||||||
|
edgeLogger.info('Step 1: Moving email threads', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
fromTickets: mergeTickets.map(t => t.ticket_number)
|
||||||
|
});
|
||||||
|
|
||||||
const { data: movedThreads, error: moveError } = await supabase
|
const { data: movedThreads, error: moveError } = await supabase
|
||||||
.from('contact_email_threads')
|
.from('contact_email_threads')
|
||||||
.update({ submission_id: primaryTicketId })
|
.update({ submission_id: primaryTicketId })
|
||||||
@@ -134,18 +139,34 @@ serve(async (req) => {
|
|||||||
|
|
||||||
const threadsMovedCount = movedThreads?.length || 0;
|
const threadsMovedCount = movedThreads?.length || 0;
|
||||||
|
|
||||||
|
edgeLogger.info('Threads moved successfully', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
threadsMovedCount
|
||||||
|
});
|
||||||
|
|
||||||
|
if (threadsMovedCount === 0) {
|
||||||
|
edgeLogger.warn('No email threads found to move', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
mergeTicketIds
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Step 2: Consolidate admin notes
|
// Step 2: Consolidate admin notes
|
||||||
|
edgeLogger.info('Step 2: Consolidating admin notes', { requestId: tracking.requestId });
|
||||||
|
|
||||||
let consolidatedNotes = primaryTicket.admin_notes || '';
|
let consolidatedNotes = primaryTicket.admin_notes || '';
|
||||||
|
|
||||||
for (const ticket of mergeTickets) {
|
for (const ticket of mergeTickets) {
|
||||||
if (ticket.admin_notes) {
|
if (ticket.admin_notes) {
|
||||||
consolidatedNotes = consolidatedNotes
|
consolidatedNotes = consolidatedNotes.trim()
|
||||||
? `${consolidatedNotes}\n\n${ticket.admin_notes}`
|
? `${consolidatedNotes}\n\n${ticket.admin_notes}`
|
||||||
: ticket.admin_notes;
|
: ticket.admin_notes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 3: Recalculate metadata from consolidated threads
|
// Step 3: Recalculate metadata from consolidated threads
|
||||||
|
edgeLogger.info('Step 3: Recalculating metadata from threads', { requestId: tracking.requestId });
|
||||||
|
|
||||||
const { data: threadStats, error: statsError } = await supabase
|
const { data: threadStats, error: statsError } = await supabase
|
||||||
.from('contact_email_threads')
|
.from('contact_email_threads')
|
||||||
.select('direction, created_at')
|
.select('direction, created_at')
|
||||||
@@ -161,10 +182,19 @@ serve(async (req) => {
|
|||||||
?.filter(t => t.direction === 'inbound')
|
?.filter(t => t.direction === 'inbound')
|
||||||
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0]?.created_at;
|
.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())[0]?.created_at;
|
||||||
|
|
||||||
|
edgeLogger.info('Metadata recalculated', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
outboundCount,
|
||||||
|
lastAdminResponse,
|
||||||
|
lastUserResponse
|
||||||
|
});
|
||||||
|
|
||||||
// Get merged ticket numbers
|
// Get merged ticket numbers
|
||||||
const mergedTicketNumbers = mergeTickets.map(t => t.ticket_number);
|
const mergedTicketNumbers = mergeTickets.map(t => t.ticket_number);
|
||||||
|
|
||||||
// Step 4: Update primary ticket with consolidated data
|
// Step 4: Update primary ticket with consolidated data
|
||||||
|
edgeLogger.info('Step 4: Updating primary ticket', { requestId: tracking.requestId });
|
||||||
|
|
||||||
const { error: updateError } = await supabase
|
const { error: updateError } = await supabase
|
||||||
.from('contact_submissions')
|
.from('contact_submissions')
|
||||||
.update({
|
.update({
|
||||||
@@ -181,7 +211,14 @@ serve(async (req) => {
|
|||||||
|
|
||||||
if (updateError) throw updateError;
|
if (updateError) throw updateError;
|
||||||
|
|
||||||
|
edgeLogger.info('Primary ticket updated successfully', { requestId: tracking.requestId });
|
||||||
|
|
||||||
// Step 5: Delete merged tickets
|
// Step 5: Delete merged tickets
|
||||||
|
edgeLogger.info('Step 5: Deleting merged tickets', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
ticketsToDelete: mergeTicketIds.length
|
||||||
|
});
|
||||||
|
|
||||||
const { error: deleteError } = await supabase
|
const { error: deleteError } = await supabase
|
||||||
.from('contact_submissions')
|
.from('contact_submissions')
|
||||||
.delete()
|
.delete()
|
||||||
@@ -189,8 +226,12 @@ serve(async (req) => {
|
|||||||
|
|
||||||
if (deleteError) throw deleteError;
|
if (deleteError) throw deleteError;
|
||||||
|
|
||||||
|
edgeLogger.info('Merged tickets deleted successfully', { requestId: tracking.requestId });
|
||||||
|
|
||||||
// Step 6: Audit log
|
// Step 6: Audit log
|
||||||
await supabase.from('admin_audit_log').insert({
|
edgeLogger.info('Step 6: Creating audit log', { requestId: tracking.requestId });
|
||||||
|
|
||||||
|
const { error: auditError } = await supabase.from('admin_audit_log').insert({
|
||||||
admin_user_id: user.id,
|
admin_user_id: user.id,
|
||||||
target_user_id: user.id, // No specific target user for this action
|
target_user_id: user.id, // No specific target user for this action
|
||||||
action: 'merge_contact_tickets',
|
action: 'merge_contact_tickets',
|
||||||
@@ -205,6 +246,15 @@ serve(async (req) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (auditError) {
|
||||||
|
edgeLogger.warn('Failed to create audit log for merge', {
|
||||||
|
requestId: tracking.requestId,
|
||||||
|
error: auditError.message,
|
||||||
|
primaryTicket: primaryTicket.ticket_number
|
||||||
|
});
|
||||||
|
// Don't throw - merge already succeeded
|
||||||
|
}
|
||||||
|
|
||||||
const duration = endRequest(tracking);
|
const duration = endRequest(tracking);
|
||||||
edgeLogger.info('Merge tickets completed successfully', {
|
edgeLogger.info('Merge tickets completed successfully', {
|
||||||
requestId: tracking.requestId,
|
requestId: tracking.requestId,
|
||||||
|
|||||||
Reference in New Issue
Block a user