// POST / - create report (validate body, use req.user) // GET / - list reports (filters: by user, store, date; admin sees all) // PUT /:id - update report (owner or admin) // DELETE /:id - delete (admin only) const express = require("express"); const { body, param, query, validationResult } = require("express-validator"); const { db } = require("../database/init"); const verifyToken = require("../middleware/auth"); const router = express.Router(); // POST /api/reports - create a report router.post( "/", verifyToken, [ body("storeId").isInt({ min: 1 }).withMessage("Valid storeId required"), body("reportDate").isISO8601().withMessage("Valid reportDate required"), body("income").isFloat().withMessage("Valid income required"), body("initialCash").isFloat().withMessage("Valid initialCash required"), body("totalIncome").isFloat().withMessage("Valid totalIncome required"), body("wages").optional().isString(), body("expenses").optional().isString(), body("totalWages").isFloat(), body("totalExpenses").isFloat(), body("envelope").isFloat(), body("finalCash").isFloat(), ], async (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); const { storeId, reportDate, income, initialCash, totalIncome, wages, expenses, totalWages, totalExpenses, envelope, finalCash, } = req.body; const userId = req.user.userId; db.run( `INSERT INTO reports (userId, storeId, reportDate, income, initialCash, totalIncome, wages, expenses, totalWages, totalExpenses, envelope, finalCash) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ userId, storeId, reportDate, income, initialCash, totalIncome, wages, expenses, totalWages, totalExpenses, envelope, finalCash, ], function (err) { if (err) { if ( err.message && err.message.toLowerCase().includes("unique constraint failed") ) { return res.status(409).json({ error: "Отчет за этот магазин и дату уже был отправлен этим пользователем.", }); } console.error("DB error:", err); return res.status(500).json({ error: "Database error" }); } res.status(201).json({ id: this.lastID }); } ); } ); // GET /api/reports - list reports, optional filters router.get( "/", verifyToken, [ query("userId").optional().isInt(), query("storeId").optional().isInt(), query("reportDate").optional().isISO8601(), ], (req, res) => { let sql = ` SELECT reports.*, stores.name AS storeName, users.username AS username, users.fullName AS fullName FROM reports JOIN stores ON reports.storeId = stores.id JOIN users ON reports.userId = users.id WHERE 1=1 `; const params = []; if (req.user.role !== "admin") { sql += " AND reports.userId = ?"; params.push(req.user.userId); } else { if (req.query.userId) { sql += " AND reports.userId = ?"; params.push(req.query.userId); } } if (req.query.storeId) { sql += " AND reports.storeId = ?"; params.push(req.query.storeId); } if (req.query.reportDate) { sql += " AND reports.reportDate = ?"; params.push(req.query.reportDate); } sql += " ORDER BY reports.reportDate DESC"; db.all(sql, params, (err, rows) => { if (err) return res.status(500).json({ error: "Database error" }); res.json({ reports: rows }); }); } ); // PUT /api/reports/:id - update a report router.put( "/:id", verifyToken, [ param("id").isInt(), body("income").optional().isFloat(), body("initialCash").optional().isFloat(), body("totalIncome").optional().isFloat(), body("wages").optional().isString(), body("expenses").optional().isString(), body("totalWages").optional().isFloat(), body("totalExpenses").optional().isFloat(), body("envelope").optional().isFloat(), body("finalCash").optional().isFloat(), body("isVerified").optional().isInt({ min: 0, max: 1 }), ], (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); const reportId = req.params.id; // Only owner or admin can update db.get("SELECT * FROM reports WHERE id = ?", [reportId], (err, report) => { if (err || !report) return res.status(404).json({ error: "Report not found" }); if (req.user.role !== "admin" && report.userId !== req.user.userId) { return res.status(403).json({ error: "Forbidden" }); } const fields = []; const values = []; for (const key of [ "income", "initialCash", "totalIncome", "wages", "expenses", "totalWages", "totalExpenses", "envelope", "finalCash", "isVerified", ]) { if (req.body[key] !== undefined) { fields.push(`${key} = ?`); values.push(req.body[key]); } } if (fields.length === 0) return res.status(400).json({ error: "No data to update" }); values.push(reportId); db.run( `UPDATE reports SET ${fields.join( ", " )}, updatedAt = CURRENT_TIMESTAMP WHERE id = ?`, values, function (err) { if (err) return res.status(500).json({ error: "Database error" }); res.json({ updated: this.changes }); } ); }); } ); // POST /api/reports/:id/verify - admin only router.post("/:id/verify", verifyToken, [param("id").isInt()], (req, res) => { if (req.user.role !== "admin") return res.status(403).json({ error: "Admin only" }); const reportId = req.params.id; const verifiedBy = req.user.userId; const verifiedAt = new Date().toISOString(); db.run( `UPDATE reports SET isVerified = 1, verifiedBy = ?, verifiedAt = ?, updatedAt = CURRENT_TIMESTAMP WHERE id = ?`, [verifiedBy, verifiedAt, reportId], function (err) { if (err) return res.status(500).json({ error: "Database error" }); if (this.changes === 0) return res.status(404).json({ error: "Report not found" }); res.json({ verified: true, reportId }); } ); }); // DELETE /api/reports/:id - admin only router.delete("/:id", verifyToken, [param("id").isInt()], (req, res) => { if (req.user.role !== "admin") return res.status(403).json({ error: "Admin only" }); db.run("DELETE FROM reports WHERE id = ?", [req.params.id], function (err) { if (err) return res.status(500).json({ error: "Database error" }); res.json({ deleted: this.changes }); }); }); module.exports = router;