Fix: Improve validation error handling

This commit is contained in:
gpt-engineer-app[bot]
2025-11-05 20:36:02 +00:00
parent c8018b827e
commit f9c11cb064

View File

@@ -837,107 +837,108 @@ serve(withRateLimit(async (req) => {
// Process items in order
for (const item of sortedItems) {
try {
edgeLogger.info('Processing item', { action: 'approval_process_item', itemId: item.id, itemType: item.item_type });
// Extract data from relational tables based on item_type
let itemData: any;
switch (item.item_type) {
case 'park':
itemData = {
...(item as any).park_submission,
// Merge temp refs for this item
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'ride':
itemData = {
...(item as any).ride_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'manufacturer':
case 'operator':
case 'property_owner':
case 'designer':
itemData = {
...(item as any).company_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'ride_model':
itemData = {
...(item as any).ride_model_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'photo':
// Combine photo_submission with its photo_items array
itemData = {
...(item as any).photo_submission,
photos: (item as any).photo_submission?.photo_items || [],
...(tempRefsByItemId.get(item.id) || {})
};
break;
default:
// For timeline/other items not yet migrated, fall back to item_data (JSONB)
itemData = item.item_data;
}
if (!itemData && item.item_data) {
// Fallback to item_data if relational data not found (for backwards compatibility)
edgeLogger.info('Processing item', { action: 'approval_process_item', itemId: item.id, itemType: item.item_type });
// Extract data from relational tables based on item_type (OUTSIDE try-catch)
let itemData: any;
switch (item.item_type) {
case 'park':
itemData = {
...(item as any).park_submission,
// Merge temp refs for this item
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'ride':
itemData = {
...(item as any).ride_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'manufacturer':
case 'operator':
case 'property_owner':
case 'designer':
itemData = {
...(item as any).company_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'ride_model':
itemData = {
...(item as any).ride_model_submission,
...(tempRefsByItemId.get(item.id) || {})
};
break;
case 'photo':
// Combine photo_submission with its photo_items array
itemData = {
...(item as any).photo_submission,
photos: (item as any).photo_submission?.photo_items || [],
...(tempRefsByItemId.get(item.id) || {})
};
break;
default:
// For timeline/other items not yet migrated, fall back to item_data (JSONB)
itemData = item.item_data;
}
}
if (!itemData && item.item_data) {
// Fallback to item_data if relational data not found (for backwards compatibility)
itemData = item.item_data;
}
// Log if temp refs were found for this item
if (tempRefsByItemId.has(item.id)) {
edgeLogger.info('Item has temp refs', {
action: 'approval_item_temp_refs',
itemId: item.id,
itemType: item.item_type,
tempRefs: tempRefsByItemId.get(item.id),
requestId: tracking.requestId
});
}
// Validate entity data with strict validation, passing original_data for edits
const validation = validateEntityDataStrict(item.item_type, itemData, item.original_data);
if (validation.blockingErrors.length > 0) {
edgeLogger.error('Blocking validation errors', {
action: 'approval_validation_fail',
itemId: item.id,
errors: validation.blockingErrors,
requestId: tracking.requestId
});
// Fail the entire batch if ANY item has blocking errors
return new Response(JSON.stringify({
success: false,
message: 'Validation failed: Items have blocking errors that must be fixed',
errors: validation.blockingErrors,
failedItemId: item.id,
failedItemType: item.item_type,
requestId: tracking.requestId
}), {
status: 400,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
});
}
if (validation.warnings.length > 0) {
edgeLogger.warn('Validation warnings', {
action: 'approval_validation_warning',
itemId: item.id,
warnings: validation.warnings
});
// Continue processing - warnings don't block approval
}
// Log if temp refs were found for this item
if (tempRefsByItemId.has(item.id)) {
edgeLogger.info('Item has temp refs', {
action: 'approval_item_temp_refs',
itemId: item.id,
itemType: item.item_type,
tempRefs: tempRefsByItemId.get(item.id),
requestId: tracking.requestId
});
}
// Validate entity data BEFORE entering try-catch (so 400 returns immediately)
const validation = validateEntityDataStrict(item.item_type, itemData, item.original_data);
if (validation.blockingErrors.length > 0) {
edgeLogger.error('Blocking validation errors', {
action: 'approval_validation_fail',
itemId: item.id,
errors: validation.blockingErrors,
requestId: tracking.requestId
});
// Return 400 immediately - NOT caught by try-catch below
return new Response(JSON.stringify({
success: false,
message: 'Validation failed: Items have blocking errors that must be fixed',
errors: validation.blockingErrors,
failedItemId: item.id,
failedItemType: item.item_type,
requestId: tracking.requestId
}), {
status: 400,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
});
}
if (validation.warnings.length > 0) {
edgeLogger.warn('Validation warnings', {
action: 'approval_validation_warning',
itemId: item.id,
warnings: validation.warnings
});
// Continue processing - warnings don't block approval
}
// Now enter try-catch ONLY for database operations
try {
// Set user context for versioning trigger
// This allows create_relational_version() trigger to capture the submitter
const { error: setUserIdError } = await supabase.rpc('set_config_value', {