From 0a9820abfbbf285c15f7edadbe161b0fea95b599 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Sun, 2 Nov 2025 19:56:23 +0000 Subject: [PATCH] Fix composite submission dependency resolution --- .../process-selective-approval/index.ts | 131 ++++++++++++++++-- 1 file changed, 122 insertions(+), 9 deletions(-) diff --git a/supabase/functions/process-selective-approval/index.ts b/supabase/functions/process-selective-approval/index.ts index 452a6d16..616a3ed8 100644 --- a/supabase/functions/process-selective-approval/index.ts +++ b/supabase/functions/process-selective-approval/index.ts @@ -467,7 +467,7 @@ serve(async (req) => { } // Resolve dependencies in item data - const resolvedData = resolveDependencies(item.item_data, dependencyMap); + const resolvedData = resolveDependencies(item.item_data, dependencyMap, sortedItems); // Add submitter ID to the data for photo tracking resolvedData._submitter_id = submitterId; @@ -759,23 +759,136 @@ function topologicalSort(items: any[]): any[] { return sorted; } -function resolveDependencies(data: any, dependencyMap: Map): any { +function resolveDependencies(data: any, dependencyMap: Map, sortedItems: any[]): any { if (typeof data !== 'object' || data === null) { return data; } if (Array.isArray(data)) { - return data.map(item => resolveDependencies(item, dependencyMap)); + return data.map(item => resolveDependencies(item, dependencyMap, sortedItems)); } - const resolved: any = {}; - for (const [key, value] of Object.entries(data)) { - if (typeof value === 'string' && dependencyMap.has(value)) { - resolved[key] = dependencyMap.get(value); - } else { - resolved[key] = resolveDependencies(value, dependencyMap); + const resolved: any = { ...data }; + + // Phase 1: Resolve temporary index references FIRST + // These reference items by their position in the sorted items array + + if (resolved._temp_manufacturer_ref !== undefined) { + const refIndex = resolved._temp_manufacturer_ref; + if (refIndex >= 0 && refIndex < sortedItems.length) { + const refItemId = sortedItems[refIndex].id; + if (dependencyMap.has(refItemId)) { + resolved.manufacturer_id = dependencyMap.get(refItemId); + edgeLogger.info('Resolved temp manufacturer ref', { + action: 'dependency_resolve_temp_ref', + refIndex, + refItemId, + resolvedId: resolved.manufacturer_id + }); + } + } + delete resolved._temp_manufacturer_ref; + } + + if (resolved._temp_operator_ref !== undefined) { + const refIndex = resolved._temp_operator_ref; + if (refIndex >= 0 && refIndex < sortedItems.length) { + const refItemId = sortedItems[refIndex].id; + if (dependencyMap.has(refItemId)) { + resolved.operator_id = dependencyMap.get(refItemId); + edgeLogger.info('Resolved temp operator ref', { + action: 'dependency_resolve_temp_ref', + refIndex, + refItemId, + resolvedId: resolved.operator_id + }); + } + } + delete resolved._temp_operator_ref; + } + + if (resolved._temp_property_owner_ref !== undefined) { + const refIndex = resolved._temp_property_owner_ref; + if (refIndex >= 0 && refIndex < sortedItems.length) { + const refItemId = sortedItems[refIndex].id; + if (dependencyMap.has(refItemId)) { + resolved.property_owner_id = dependencyMap.get(refItemId); + edgeLogger.info('Resolved temp property owner ref', { + action: 'dependency_resolve_temp_ref', + refIndex, + refItemId, + resolvedId: resolved.property_owner_id + }); + } + } + delete resolved._temp_property_owner_ref; + } + + if (resolved._temp_ride_model_ref !== undefined) { + const refIndex = resolved._temp_ride_model_ref; + if (refIndex >= 0 && refIndex < sortedItems.length) { + const refItemId = sortedItems[refIndex].id; + if (dependencyMap.has(refItemId)) { + resolved.ride_model_id = dependencyMap.get(refItemId); + edgeLogger.info('Resolved temp ride model ref', { + action: 'dependency_resolve_temp_ref', + refIndex, + refItemId, + resolvedId: resolved.ride_model_id + }); + } + } + delete resolved._temp_ride_model_ref; + } + + if (resolved._temp_designer_ref !== undefined) { + const refIndex = resolved._temp_designer_ref; + if (refIndex >= 0 && refIndex < sortedItems.length) { + const refItemId = sortedItems[refIndex].id; + if (dependencyMap.has(refItemId)) { + resolved.designer_id = dependencyMap.get(refItemId); + edgeLogger.info('Resolved temp designer ref', { + action: 'dependency_resolve_temp_ref', + refIndex, + refItemId, + resolvedId: resolved.designer_id + }); + } + } + delete resolved._temp_designer_ref; + } + + // Phase 2: Resolve direct foreign key references + // These are submission_item IDs that reference other items in the same submission + const foreignKeys = [ + 'park_id', + 'manufacturer_id', + 'designer_id', + 'operator_id', + 'property_owner_id', + 'ride_model_id' + ]; + + for (const key of foreignKeys) { + if (resolved[key] && typeof resolved[key] === 'string' && dependencyMap.has(resolved[key])) { + const oldValue = resolved[key]; + resolved[key] = dependencyMap.get(resolved[key]); + edgeLogger.info('Resolved direct foreign key', { + action: 'dependency_resolve_fk', + key, + oldValue, + newValue: resolved[key] + }); } } + + // Phase 3: Recursively resolve nested objects + for (const [key, value] of Object.entries(resolved)) { + if (typeof value === 'object' && value !== null && !foreignKeys.includes(key)) { + resolved[key] = resolveDependencies(value, dependencyMap, sortedItems); + } + } + return resolved; }