perform applications

This commit is contained in:
Jake Kasper
2025-08-27 09:10:43 -04:00
parent abff69cad6
commit a6d3435f1c
3 changed files with 664 additions and 4 deletions

View File

@@ -1246,4 +1246,189 @@ router.get('/spreader-settings/:equipmentId/:productId', async (req, res, next)
}
});
// @route POST /api/applications/logs
// @desc Create application log (actual execution)
// @access Private
router.post('/logs', validateRequest(applicationLogSchema), async (req, res, next) => {
try {
const {
planId,
lawnSectionId,
equipmentId,
applicationDate,
weatherConditions,
gpsTrack,
averageSpeed,
areaCovered,
notes,
products
} = req.body;
// Verify plan belongs to user if planId is provided
if (planId) {
const planCheck = await pool.query(`
SELECT ap.* FROM application_plans ap
JOIN application_plan_sections aps ON ap.id = aps.plan_id
JOIN lawn_sections ls ON aps.lawn_section_id = ls.id
JOIN properties p ON ls.property_id = p.id
WHERE ap.id = $1 AND p.user_id = $2
`, [planId, req.user.id]);
if (planCheck.rows.length === 0) {
throw new AppError('Plan not found', 404);
}
}
// Verify lawn section belongs to user
const sectionCheck = await pool.query(`
SELECT ls.* FROM lawn_sections ls
JOIN properties p ON ls.property_id = p.id
WHERE ls.id = $1 AND p.user_id = $2
`, [lawnSectionId, req.user.id]);
if (sectionCheck.rows.length === 0) {
throw new AppError('Lawn section not found', 404);
}
// Verify equipment belongs to user
const equipmentCheck = await pool.query(
'SELECT * FROM user_equipment WHERE id = $1 AND user_id = $2',
[equipmentId, req.user.id]
);
if (equipmentCheck.rows.length === 0) {
throw new AppError('Equipment not found', 404);
}
// Create application log
const logResult = await pool.query(`
INSERT INTO application_logs
(plan_id, user_id, lawn_section_id, equipment_id, application_date, weather_conditions, gps_track, average_speed, area_covered, notes)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
RETURNING *
`, [
planId,
req.user.id,
lawnSectionId,
equipmentId,
applicationDate || new Date(),
weatherConditions ? JSON.stringify(weatherConditions) : null,
gpsTrack ? JSON.stringify(gpsTrack) : null,
averageSpeed,
areaCovered,
notes
]);
const log = logResult.rows[0];
// Create product log entries
if (products && products.length > 0) {
for (const product of products) {
// Verify product ownership if it's a user product
if (product.userProductId) {
const productCheck = await pool.query(
'SELECT * FROM user_products WHERE id = $1 AND user_id = $2',
[product.userProductId, req.user.id]
);
if (productCheck.rows.length === 0) {
throw new AppError(`User product ${product.userProductId} not found`, 404);
}
}
await pool.query(`
INSERT INTO application_log_products
(log_id, product_id, user_product_id, rate_amount, rate_unit, actual_product_amount, actual_water_amount, actual_speed_mph)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
`, [
log.id,
product.productId || null,
product.userProductId || null,
product.rateAmount,
product.rateUnit,
product.actualProductAmount || null,
product.actualWaterAmount || null,
product.actualSpeedMph || null
]);
}
}
// Update plan status to completed if planId provided
if (planId) {
await pool.query(
'UPDATE application_plans SET status = $1 WHERE id = $2',
['completed', planId]
);
}
res.status(201).json({
success: true,
message: 'Application log created successfully',
data: {
log: {
id: log.id,
planId: log.plan_id,
lawnSectionId: log.lawn_section_id,
equipmentId: log.equipment_id,
applicationDate: log.application_date,
averageSpeed: log.average_speed,
areaCovered: log.area_covered,
createdAt: log.created_at
}
}
});
} catch (error) {
next(error);
}
});
// @route GET /api/applications/logs
// @desc Get application logs
// @access Private
router.get('/logs', async (req, res, next) => {
try {
const result = await pool.query(`
SELECT
al.*,
p.name as property_name,
p.address as property_address,
ls.name as section_name,
ue.custom_name as equipment_name,
et.name as equipment_type
FROM application_logs al
JOIN lawn_sections ls ON al.lawn_section_id = ls.id
JOIN properties p ON ls.property_id = p.id
JOIN user_equipment ue ON al.equipment_id = ue.id
LEFT JOIN equipment_types et ON ue.equipment_type_id = et.id
WHERE p.user_id = $1
ORDER BY al.application_date DESC, al.created_at DESC
`, [req.user.id]);
const logs = result.rows.map(row => ({
id: row.id,
planId: row.plan_id,
propertyName: row.property_name,
propertyAddress: row.property_address,
sectionName: row.section_name,
equipmentName: row.equipment_name,
equipmentType: row.equipment_type,
applicationDate: row.application_date,
gpsTrack: row.gps_track,
averageSpeed: row.average_speed,
areaCovered: row.area_covered,
notes: row.notes,
createdAt: row.created_at
}));
res.json({
success: true,
data: {
logs
}
});
} catch (error) {
next(error);
}
});
module.exports = router;