import { requireSalesOrAdmin } from '~/server/utils/auth'; import { getNocoDbConfiguration } from '~/server/utils/nocodb'; import { logAuditEvent } from '~/server/utils/audit-logger'; export default defineEventHandler(async (event) => { console.log('[INTERESTS] Merge duplicates request'); let body: any; try { // Require sales or admin access const session = await requireSalesOrAdmin(event); const userId = session.user?.id || 'unknown'; const userEmail = session.user?.email || 'unknown'; body = await readBody(event); const { masterId, duplicateIds, mergeData } = body; if (!masterId || !duplicateIds || !Array.isArray(duplicateIds) || duplicateIds.length === 0) { throw createError({ statusCode: 400, statusMessage: 'Invalid merge request. Master ID and duplicate IDs required.' }); } console.log('[INTERESTS] Merging', duplicateIds.length, 'duplicates into master interest', masterId); // Get NocoDB configuration const config = getNocoDbConfiguration(); const interestTableId = "mbs9hjauug4eseo"; // Interest table ID // First, get all interests involved const allIds = [masterId, ...duplicateIds]; const interestsToMerge: any[] = []; for (const id of allIds) { try { const interest = await $fetch(`${config.url}/api/v2/tables/${interestTableId}/records/${id}`, { headers: { 'xc-token': config.token } }); interestsToMerge.push(interest); } catch (error) { console.error(`[INTERESTS] Failed to fetch interest ${id}:`, error); } } if (interestsToMerge.length < 2) { throw createError({ statusCode: 404, statusMessage: 'Could not find enough interests to merge' }); } const masterInterest = interestsToMerge.find(i => i.Id === parseInt(masterId)); if (!masterInterest) { throw createError({ statusCode: 404, statusMessage: 'Master interest not found' }); } // Log the action before making changes await logAuditEvent(event, 'MERGE_INTEREST_DUPLICATES', 'interest', { resourceId: masterId, changes: { duplicateIds, mergeData, originalInterests: interestsToMerge } }); // Update master interest with merged data if provided if (mergeData && Object.keys(mergeData).length > 0) { const updateData: any = { Id: parseInt(masterId) }; // Copy allowed fields const allowedFields = [ 'Full Name', 'Email Address', 'Phone Number', 'Address', 'Extra Comments', 'Berth Size Desired', 'Sales Process Level', 'EOI Status', 'Contract Status', 'Lead Category' ]; allowedFields.forEach(field => { if (mergeData[field] !== undefined) { updateData[field] = mergeData[field]; } }); if (Object.keys(updateData).length > 1) { // More than just Id console.log('[INTERESTS] Updating master interest with:', updateData); await $fetch(`${config.url}/api/v2/tables/${interestTableId}/records`, { method: 'PATCH', headers: { 'xc-token': config.token, 'Content-Type': 'application/json' }, body: updateData }); } } // Delete duplicate interests const deleteResults = []; for (const duplicateId of duplicateIds) { try { console.log('[INTERESTS] Deleting duplicate interest:', duplicateId); await $fetch(`${config.url}/api/v2/tables/${interestTableId}/records`, { method: 'DELETE', headers: { 'xc-token': config.token, 'Content-Type': 'application/json' }, body: { Id: parseInt(duplicateId) } }); deleteResults.push({ id: duplicateId, success: true }); } catch (error: any) { console.error('[INTERESTS] Failed to delete duplicate:', duplicateId, error); deleteResults.push({ id: duplicateId, success: false, error: error.message || 'Delete failed' }); } } // Check if all deletes were successful const failedDeletes = deleteResults.filter(r => !r.success); if (failedDeletes.length > 0) { console.warn('[INTERESTS] Some duplicates could not be deleted:', failedDeletes); } // Log successful completion await logAuditEvent(event, 'MERGE_INTEREST_DUPLICATES_COMPLETE', 'interest', { resourceId: masterId, changes: { deletedCount: deleteResults.filter(r => r.success).length, failedDeletes, mergeData }, status: 'success' }); return { success: true, data: { masterId, mergedData: mergeData, deletedCount: deleteResults.filter(r => r.success).length, deleteResults, message: `Successfully merged ${deleteResults.filter(r => r.success).length} duplicates into interest ${masterId}` } }; } catch (error: any) { console.error('[INTERESTS] Failed to merge duplicates:', error); // Log the failure await logAuditEvent(event, 'MERGE_INTEREST_DUPLICATES_FAILED', 'interest', { resourceId: body?.masterId || 'unknown', changes: { error: error.message || 'Unknown error', requestBody: body }, status: 'failure', errorMessage: error.message || 'Unknown error' }); if (error.statusCode) { throw error; } throw createError({ statusCode: 500, statusMessage: 'Failed to merge duplicate interests' }); } });