From 95d1b1798bac6f3413d8c31798767a1d7daaae87 Mon Sep 17 00:00:00 2001 From: Torben Sorensen Date: Mon, 1 Dec 2025 22:45:29 -0800 Subject: [PATCH] ai 'chat' is helping now --- src/routes/ai.ts | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/routes/ai.ts b/src/routes/ai.ts index ea7df3a2..097d3a5a 100644 --- a/src/routes/ai.ts +++ b/src/routes/ai.ts @@ -106,9 +106,30 @@ router.post('/flyers/process', optionalAuth, uploadToDisk.single('flyerImage'), return res.status(400).json({ message: 'Data payload is required.' }); } - const { checksum, originalFileName, extractedData } = JSON.parse(req.body.data); + const parsed = JSON.parse(req.body.data || '{}'); + const { checksum, originalFileName, extractedData } = parsed; const user = req.user as UserProfile | undefined; + // Validate extractedData to avoid database errors (e.g., null store_name) + if (!extractedData || typeof extractedData !== 'object') { + logger.warn('Missing extractedData in /api/ai/flyers/process payload.', { bodyData: parsed }); + return res.status(400).json({ message: 'Invalid request: extractedData is required.' }); + } + + // Ensure items is an array (DB function handles zero-items case) + const itemsArray = Array.isArray(extractedData.items) ? extractedData.items : []; + if (!Array.isArray(extractedData.items)) { + logger.warn('extractedData.items is missing or not an array; proceeding with empty items array.'); + } + + // Ensure we have a valid store name; the DB requires a non-null store name. + const storeName = extractedData.store_name && String(extractedData.store_name).trim().length > 0 + ? String(extractedData.store_name) + : 'Unknown Store (auto)'; + if (storeName.startsWith('Unknown')) { + logger.warn('extractedData.store_name missing; using fallback store name to avoid DB constraint error.'); + } + // 1. Check for duplicate flyer using checksum const existingFlyer = await db.findFlyerByChecksum(checksum); if (existingFlyer) { @@ -127,8 +148,8 @@ router.post('/flyers/process', optionalAuth, uploadToDisk.single('flyerImage'), image_url: `/flyer-images/${req.file.filename}`, // Update the URL to point to the new directory icon_url: iconUrl, // Add the new icon URL checksum: checksum, - // Pass the store_name directly to the DB function. - store_name: extractedData.store_name, + // Use normalized store name (fallback applied above). + store_name: storeName, valid_from: extractedData.valid_from, valid_to: extractedData.valid_to, store_address: extractedData.store_address, @@ -136,7 +157,7 @@ router.post('/flyers/process', optionalAuth, uploadToDisk.single('flyerImage'), }; // 3. Create flyer and its items in a transaction - const newFlyer = await db.createFlyerAndItems(flyerData, extractedData.items); + const newFlyer = await db.createFlyerAndItems(flyerData, itemsArray); logger.info(`Successfully processed and saved new flyer: ${newFlyer.file_name} (ID: ${newFlyer.flyer_id})`);