diff --git a/backend/src/routes/applications.js b/backend/src/routes/applications.js index af941a0..8af992f 100644 --- a/backend/src/routes/applications.js +++ b/backend/src/routes/applications.js @@ -1008,6 +1008,8 @@ router.get('/logs', async (req, res, next) => { // @access Private router.post('/logs', validateRequest(applicationLogSchema), async (req, res, next) => { try { + console.log('Create log request received:', JSON.stringify(req.body, null, 2)); + const { planId, lawnSectionId, @@ -1052,6 +1054,18 @@ router.post('/logs', validateRequest(applicationLogSchema), async (req, res, nex } // Create application log + console.log('Inserting application log with values:', { + planId, + userId: req.user.id, + lawnSectionId, + equipmentId, + weatherConditions: JSON.stringify(weatherConditions), + gpsTrack: JSON.stringify(gpsTrack), + averageSpeed, + areaCovered, + notes + }); + const logResult = await client.query( `INSERT INTO application_logs (plan_id, user_id, lawn_section_id, equipment_id, weather_conditions, @@ -1064,8 +1078,10 @@ router.post('/logs', validateRequest(applicationLogSchema), async (req, res, nex ); const log = logResult.rows[0]; + console.log('Application log inserted successfully:', log); // Add products to log + console.log('Adding products to log:', products); for (const product of products) { const { productId, @@ -1077,6 +1093,11 @@ router.post('/logs', validateRequest(applicationLogSchema), async (req, res, nex actualSpeedMph } = product; + console.log('Inserting product:', { + logId: log.id, productId, userProductId, rateAmount, rateUnit, + actualProductAmount, actualWaterAmount, actualSpeedMph + }); + await client.query( `INSERT INTO application_log_products (log_id, product_id, user_product_id, rate_amount, rate_unit, @@ -1085,6 +1106,8 @@ router.post('/logs', validateRequest(applicationLogSchema), async (req, res, nex [log.id, productId, userProductId, rateAmount, rateUnit, actualProductAmount, actualWaterAmount, actualSpeedMph] ); + + console.log('Product inserted successfully'); } // If this was from a plan, mark the plan as completed diff --git a/backend/src/utils/validation.js b/backend/src/utils/validation.js index 77a9e60..38e24ac 100644 --- a/backend/src/utils/validation.js +++ b/backend/src/utils/validation.js @@ -177,7 +177,7 @@ const applicationLogSchema = Joi.object({ actualProductAmount: Joi.number().positive(), actualWaterAmount: Joi.number().positive(), actualSpeedMph: Joi.number().positive() - })).min(1).required() + }).or('productId', 'userProductId')).min(1).required() }); // Validation middleware diff --git a/frontend/src/components/Applications/ApplicationExecutionModal.js b/frontend/src/components/Applications/ApplicationExecutionModal.js index 945ffe5..fddeda4 100644 --- a/frontend/src/components/Applications/ApplicationExecutionModal.js +++ b/frontend/src/components/Applications/ApplicationExecutionModal.js @@ -245,30 +245,52 @@ const ApplicationExecutionModal = ({ application, propertyDetails, onClose, onCo // Validate required fields if (!validSectionId) { toast.error('No valid section found for this application'); + console.error('Invalid section ID:', validSectionId, 'Available sections:', sections); return; } if (!validEquipmentId) { toast.error('No equipment information found for this application'); + console.error('Invalid equipment ID:', validEquipmentId, 'Plan details:', planDetails); return; } if (validProducts.length === 0) { toast.error('No products found for this application'); + console.error('No valid products. Original products:', planDetails?.products, 'Filtered products:', validProducts); return; } + + // Validate GPS tracking data exists + if (gpsTrack.length === 0) { + console.warn('No GPS tracking data collected'); + toast.error('No GPS tracking data was collected. Please ensure location services are enabled.'); + return; + } + + console.log('All validations passed. GPS points:', gpsTrack.length, 'Total distance:', totalDistance, 'Duration:', duration); + + // Prepare GPS track data - ensure all required fields are present and valid + const gpsTrackData = { + points: gpsTrack.map(point => ({ + lat: point.lat, + lng: point.lng, + timestamp: point.timestamp, + accuracy: point.accuracy || 0, + speed: point.speed || 0 + })), + totalDistance: Math.round(totalDistance * 100) / 100, // Round to 2 decimal places + duration: Math.round(duration), // Duration in seconds + averageSpeed: Math.round(averageSpeed * 100) / 100 // Round to 2 decimal places + }; // Try minimal log data first const logData = { planId: application.id, lawnSectionId: validSectionId, equipmentId: validEquipmentId, - gpsTrack: { - points: gpsTrack, - totalDistance: totalDistance, - duration: duration - }, // Backend expects object format + gpsTrack: gpsTrackData, // Backend expects object format with points array averageSpeed: Math.max(averageSpeed, 0.1), // Ensure positive number - areaCovered: application.totalSectionArea || application.sectionArea || 0, - notes: `Application completed via mobile tracking. Duration: ${Math.round(duration/60)} minutes`, + areaCovered: Math.max(application.totalSectionArea || application.sectionArea || 0, 0.1), // Ensure positive + notes: `Application completed via mobile tracking. Duration: ${Math.round(duration/60)} minutes, Distance: ${(totalDistance * 3.28084).toFixed(0)} ft, Points: ${gpsTrack.length}`, products: validProducts }; @@ -277,12 +299,16 @@ const ApplicationExecutionModal = ({ application, propertyDetails, onClose, onCo try { // Save the application log to the backend - await applicationsAPI.createLog(logData); + console.log('About to call createLog with data:', JSON.stringify(logData, null, 2)); + const response = await applicationsAPI.createLog(logData); + console.log('CreateLog response:', response); toast.success('Application completed successfully'); onComplete(); } catch (error) { console.error('Failed to save application log:', error); - toast.error('Failed to save application log'); + console.error('Error details:', error.response?.data); + console.error('Full error object:', JSON.stringify(error.response || error, null, 2)); + toast.error(`Failed to save application log: ${error.response?.data?.message || error.message}`); } };