From d68c5473ff35b6d81bc9e4a17e8df4e8bfa6c0ba Mon Sep 17 00:00:00 2001 From: frakarr Date: Thu, 11 Dec 2025 00:14:17 +0100 Subject: [PATCH] Update server.js --- server/server.js | 70 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/server/server.js b/server/server.js index 36d7590..8c62afb 100644 --- a/server/server.js +++ b/server/server.js @@ -992,8 +992,7 @@ app.post('/api/expenses/:id/pay', authenticateToken, async (req, res) => { try { let familyId; - // Admin override logic: If familyId provided in body and user is admin, use it. - // Otherwise, use logged-in user's family. + // Admin override logic if (bodyFamilyId) { if (req.user.role === 'admin' || req.user.role === 'poweruser') { familyId = bodyFamilyId; @@ -1023,11 +1022,10 @@ app.post('/api/expenses/:id/pay', authenticateToken, async (req, res) => { // Update Share await connection.query('UPDATE expense_shares SET amount_paid = ?, status = ? WHERE id = ?', [newPaid, status, share.id]); - // Also record in global payments for visibility in reports (optional but requested to track family payments) - // We use a special month/year or notes to distinguish + // Insert Payment with link to Expense ID await connection.query( - 'INSERT INTO payments (id, family_id, amount, date_paid, for_month, for_year, notes) VALUES (?, ?, ?, NOW(), 13, YEAR(NOW()), ?)', - [uuidv4(), familyId, amount, `Spesa Straordinaria: ${notes || 'Pagamento Manuale'}`] + 'INSERT INTO payments (id, family_id, extraordinary_expense_id, amount, date_paid, for_month, for_year, notes) VALUES (?, ?, ?, ?, NOW(), 13, YEAR(NOW()), ?)', + [uuidv4(), familyId, expenseId, amount, `Spesa Straordinaria: ${notes || 'Pagamento Manuale'}`] ); await connection.commit(); @@ -1041,6 +1039,66 @@ app.post('/api/expenses/:id/pay', authenticateToken, async (req, res) => { } }); +// GET HISTORY OF PAYMENTS FOR A SHARE +app.get('/api/expenses/:id/shares/:familyId/payments', authenticateToken, requireAdmin, async (req, res) => { + try { + const [rows] = await pool.query( + 'SELECT id, amount, date_paid, notes FROM payments WHERE extraordinary_expense_id = ? AND family_id = ? ORDER BY date_paid DESC', + [req.params.id, req.params.familyId] + ); + res.json(rows.map(r => ({ + id: r.id, + amount: parseFloat(r.amount), + datePaid: r.date_paid, + notes: r.notes + }))); + } catch(e) { res.status(500).json({ error: e.message }); } +}); + +// DELETE PAYMENT (REVERT) +app.delete('/api/expenses/payments/:paymentId', authenticateToken, requireAdmin, async (req, res) => { + const paymentId = req.params.paymentId; + const connection = await pool.getConnection(); + + try { + // 1. Get Payment Info + const [payments] = await connection.query('SELECT amount, extraordinary_expense_id, family_id FROM payments WHERE id = ?', [paymentId]); + if (payments.length === 0) return res.status(404).json({ message: 'Payment not found' }); + + const payment = payments[0]; + if (!payment.extraordinary_expense_id) return res.status(400).json({ message: 'Not an extraordinary expense payment' }); + + await connection.beginTransaction(); + + // 2. Revert Share Amount + // Get current share status + const [shares] = await connection.query('SELECT id, amount_due, amount_paid FROM expense_shares WHERE expense_id = ? AND family_id = ?', [payment.extraordinary_expense_id, payment.family_id]); + + if (shares.length > 0) { + const share = shares[0]; + const newPaid = Math.max(0, parseFloat(share.amount_paid) - parseFloat(payment.amount)); + const due = parseFloat(share.amount_due); + let status = 'UNPAID'; + if (newPaid >= due - 0.01) status = 'PAID'; + else if (newPaid > 0) status = 'PARTIAL'; + + await connection.query('UPDATE expense_shares SET amount_paid = ?, status = ? WHERE id = ?', [newPaid, status, share.id]); + } + + // 3. Delete Payment Record + await connection.query('DELETE FROM payments WHERE id = ?', [paymentId]); + + await connection.commit(); + res.json({ success: true }); + + } catch (e) { + await connection.rollback(); + res.status(500).json({ error: e.message }); + } finally { + connection.release(); + } +}); + // Get User's Expenses app.get('/api/my-expenses', authenticateToken, async (req, res) => { const userId = req.user.id;