Update server.js
This commit is contained in:
@@ -992,8 +992,7 @@ app.post('/api/expenses/:id/pay', authenticateToken, async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
let familyId;
|
let familyId;
|
||||||
|
|
||||||
// Admin override logic: If familyId provided in body and user is admin, use it.
|
// Admin override logic
|
||||||
// Otherwise, use logged-in user's family.
|
|
||||||
if (bodyFamilyId) {
|
if (bodyFamilyId) {
|
||||||
if (req.user.role === 'admin' || req.user.role === 'poweruser') {
|
if (req.user.role === 'admin' || req.user.role === 'poweruser') {
|
||||||
familyId = bodyFamilyId;
|
familyId = bodyFamilyId;
|
||||||
@@ -1023,11 +1022,10 @@ app.post('/api/expenses/:id/pay', authenticateToken, async (req, res) => {
|
|||||||
// Update Share
|
// Update Share
|
||||||
await connection.query('UPDATE expense_shares SET amount_paid = ?, status = ? WHERE id = ?', [newPaid, status, share.id]);
|
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)
|
// Insert Payment with link to Expense ID
|
||||||
// We use a special month/year or notes to distinguish
|
|
||||||
await connection.query(
|
await connection.query(
|
||||||
'INSERT INTO payments (id, family_id, amount, date_paid, for_month, for_year, notes) VALUES (?, ?, ?, NOW(), 13, YEAR(NOW()), ?)',
|
'INSERT INTO payments (id, family_id, extraordinary_expense_id, amount, date_paid, for_month, for_year, notes) VALUES (?, ?, ?, ?, NOW(), 13, YEAR(NOW()), ?)',
|
||||||
[uuidv4(), familyId, amount, `Spesa Straordinaria: ${notes || 'Pagamento Manuale'}`]
|
[uuidv4(), familyId, expenseId, amount, `Spesa Straordinaria: ${notes || 'Pagamento Manuale'}`]
|
||||||
);
|
);
|
||||||
|
|
||||||
await connection.commit();
|
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
|
// Get User's Expenses
|
||||||
app.get('/api/my-expenses', authenticateToken, async (req, res) => {
|
app.get('/api/my-expenses', authenticateToken, async (req, res) => {
|
||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
|
|||||||
Reference in New Issue
Block a user