perform applications
This commit is contained in:
@@ -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;
|
||||
Reference in New Issue
Block a user