mowing
This commit is contained in:
129
backend/src/routes/mowing.js
Normal file
129
backend/src/routes/mowing.js
Normal file
@@ -0,0 +1,129 @@
|
||||
const express = require('express');
|
||||
const pool = require('../config/database');
|
||||
const { AppError } = require('../middleware/errorHandler');
|
||||
const { validateRequest } = require('../utils/validation');
|
||||
const { mowingSessionSchema } = require('../utils/validation');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// POST /api/mowing/sessions - create a completed mowing session
|
||||
router.post('/sessions', validateRequest(mowingSessionSchema), async (req, res, next) => {
|
||||
try {
|
||||
const {
|
||||
propertyId,
|
||||
lawnSectionIds,
|
||||
equipmentId,
|
||||
cutHeightInches,
|
||||
direction,
|
||||
gpsTrack,
|
||||
averageSpeed,
|
||||
durationSeconds,
|
||||
totalDistanceMeters,
|
||||
areaCoveredSqft,
|
||||
notes
|
||||
} = req.body;
|
||||
|
||||
// Verify ownership of property, sections, equipment
|
||||
const prop = await pool.query('SELECT id FROM properties WHERE id=$1 AND user_id=$2', [propertyId, req.user.id]);
|
||||
if (prop.rows.length === 0) throw new AppError('Property not found', 404);
|
||||
|
||||
const sections = await pool.query(
|
||||
`SELECT ls.id FROM lawn_sections ls JOIN properties p ON ls.property_id=p.id
|
||||
WHERE ls.id = ANY($1::int[]) AND p.user_id=$2`,
|
||||
[lawnSectionIds, req.user.id]
|
||||
);
|
||||
if (sections.rows.length !== lawnSectionIds.length) throw new AppError('One or more sections not found', 404);
|
||||
|
||||
const equip = await pool.query('SELECT id FROM user_equipment WHERE id=$1 AND user_id=$2', [equipmentId, req.user.id]);
|
||||
if (equip.rows.length === 0) throw new AppError('Equipment not found', 404);
|
||||
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
const ins = await client.query(
|
||||
`INSERT INTO mowing_sessions
|
||||
(user_id, property_id, equipment_id, cut_height_inches, direction, gps_track,
|
||||
duration_seconds, total_distance_meters, average_speed_mph, area_covered_sqft, notes)
|
||||
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11)
|
||||
RETURNING *`,
|
||||
[
|
||||
req.user.id,
|
||||
propertyId,
|
||||
equipmentId,
|
||||
cutHeightInches,
|
||||
direction,
|
||||
JSON.stringify(gpsTrack),
|
||||
durationSeconds,
|
||||
totalDistanceMeters,
|
||||
averageSpeed,
|
||||
areaCoveredSqft || null,
|
||||
notes || null
|
||||
]
|
||||
);
|
||||
const session = ins.rows[0];
|
||||
for (const sid of lawnSectionIds) {
|
||||
await client.query(
|
||||
`INSERT INTO mowing_session_sections (session_id, lawn_section_id) VALUES ($1,$2)`,
|
||||
[session.id, sid]
|
||||
);
|
||||
}
|
||||
await client.query('COMMIT');
|
||||
return res.status(201).json({ success: true, data: { session: { id: session.id } } });
|
||||
} catch (e) {
|
||||
await client.query('ROLLBACK');
|
||||
throw e;
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/mowing/sessions - list sessions for user
|
||||
router.get('/sessions', async (req, res, next) => {
|
||||
try {
|
||||
const result = await pool.query(
|
||||
`SELECT ms.*, p.name as property_name, ue.custom_name as equipment_name
|
||||
FROM mowing_sessions ms
|
||||
JOIN properties p ON ms.property_id=p.id
|
||||
LEFT JOIN user_equipment ue ON ms.equipment_id=ue.id
|
||||
WHERE ms.user_id=$1
|
||||
ORDER BY ms.created_at DESC
|
||||
LIMIT 200`,
|
||||
[req.user.id]
|
||||
);
|
||||
res.json({ success: true, data: { sessions: result.rows } });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/mowing/sessions/:id - details
|
||||
router.get('/sessions/:id', async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const sessionRes = await pool.query(
|
||||
`SELECT ms.*, p.name as property_name, ue.custom_name as equipment_name
|
||||
FROM mowing_sessions ms
|
||||
JOIN properties p ON ms.property_id=p.id
|
||||
LEFT JOIN user_equipment ue ON ms.equipment_id=ue.id
|
||||
WHERE ms.id=$1 AND ms.user_id=$2`,
|
||||
[id, req.user.id]
|
||||
);
|
||||
if (sessionRes.rows.length === 0) throw new AppError('Session not found', 404);
|
||||
const sectionsRes = await pool.query(
|
||||
`SELECT lss.lawn_section_id, ls.name, ls.area, ls.polygon_data
|
||||
FROM mowing_session_sections lss
|
||||
JOIN lawn_sections ls ON lss.lawn_section_id=ls.id
|
||||
WHERE lss.session_id=$1`,
|
||||
[id]
|
||||
);
|
||||
res.json({ success: true, data: { session: sessionRes.rows[0], sections: sectionsRes.rows } });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
Reference in New Issue
Block a user