You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

238 lines
6.8 KiB

const { pool } = require('../config/databases');
// GET /finances
const getDashboard = async (req, res) => {
try {
const [payments] = await pool.query(`
SELECT id, description, payment_date AS date_transaction, 'Paiement' AS type_transaction, 'Recette' AS categorie, amount
FROM payments
ORDER BY payment_date DESC
LIMIT 10
`);
const [[{ totalRevenue }]] = await pool.query(`SELECT SUM(amount) AS totalRevenue FROM payments`);
let expenses = [], totalExpenses = 0, depenses_change = 0;
const [expensesTable] = await pool.query(`SHOW TABLES LIKE 'expenses'`);
if (expensesTable.length > 0) {
[expenses] = await db.query(`
SELECT id, description, expense_date AS date_transaction, 'Dépense' AS type_transaction, 'Dépense' AS categorie, amount
FROM expenses
ORDER BY expense_date DESC
LIMIT 10
`);
const [[{ total }]] = await pool.query(`SELECT SUM(amount) AS total FROM expenses`);
totalExpenses = total || 0;
const previousMonthExpenses = 800000;
if (previousMonthExpenses > 0) {
depenses_change = ((totalExpenses - previousMonthExpenses) / previousMonthExpenses) * 100;
}
}
const previousMonthRevenue = 2000000;
const chiffre_affaires_change = (previousMonthRevenue > 0)
? ((totalRevenue - previousMonthRevenue) / previousMonthRevenue) * 100
: 0;
const benefice_net = totalRevenue - totalExpenses;
const benefice_net_marge = totalRevenue > 0 ? (benefice_net / totalRevenue) * 100 : 0;
const tresorerie = benefice_net;
const dashboard_stats = {
chiffre_affaires: totalRevenue,
chiffre_affaires_change,
depenses: totalExpenses,
depenses_change,
benefices: benefice_net,
benefice_net,
benefice_net_marge,
tresorerie,
tresorerie_solde: tresorerie,
total_liabilities: 0
};
const profitLoss = {
revenu_total: totalRevenue,
depense_total: totalExpenses,
benefice_net,
marge: benefice_net_marge
};
const balanceSheet = {
total_assets: 0,
total_liabilities: 0,
total_equity: 0,
net_worth: 0
};
const transactions = [...payments, ...expenses].sort((a, b) =>
new Date(b.date_transaction) - new Date(a.date_transaction)
);
const [[invoiceTable]] = await pool.query(`SHOW TABLES LIKE 'invoices'`);
let invoices = [];
if (invoiceTable) {
[invoices] = await pool.query(`
SELECT id, invoice_number, client_name, invoice_date, status, total_amount
FROM invoices
ORDER BY invoice_date DESC
LIMIT 10
`);
}
res.json({
transactions,
dashboard_stats,
reportDate: new Date().toISOString().slice(0, 10),
profitLoss,
balanceSheet,
invoices
});
} catch (err) {
console.error("Erreur dans getDashboard:", err.message);
res.status(500).json({ error: "Erreur serveur" });
}
};
// POST /finances/invoices
const generateInvoice = async (req, res) => {
const {
invoice_number,
client_name,
client_email,
client_address,
invoice_date,
due_date,
total_amount,
status = 'Draft',
notes
} = req.body;
try {
await pool.query(`
INSERT INTO invoices (invoice_number, client_name, client_email, client_address, invoice_date, due_date, total_amount, status, notes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`, [
invoice_number.trim(),
client_name.trim(),
client_email?.trim() || null,
client_address.trim(),
invoice_date || new Date(),
due_date || null,
parseFloat(total_amount),
status.trim(),
notes?.trim()
]);
res.status(201).json({ message: 'Facture ajoutée avec succès.' });
} catch (err) {
console.error("Erreur dans generateInvoice:", err.message);
res.status(500).json({ error: err.message });
}
};
// POST /finances/payments
const processPayment = async (req, res) => {
const { invoice_id, payment_date, amount, payment_method, description } = req.body;
const conn = await pool.getConnection();
try {
await conn.beginTransaction();
await conn.query(`
INSERT INTO payments (invoice_id, payment_date, amount, payment_method, description)
VALUES (?, ?, ?, ?, ?)
`, [
invoice_id,
payment_date || new Date(),
parseFloat(amount),
payment_method.trim(),
description.trim()
]);
const [[{ total_amount }]] = await conn.query(`SELECT total_amount FROM invoices WHERE id = ?`, [invoice_id]);
const [[{ total_paid }]] = await conn.query(`SELECT SUM(amount) AS total_paid FROM payments WHERE invoice_id = ?`, [invoice_id]);
let status = 'Partially Paid';
if (Math.abs(total_amount - total_paid) < 0.01) {
status = 'Paid';
}
await conn.query(`UPDATE invoices SET status = ? WHERE id = ?`, [status, invoice_id]);
await conn.query(`
UPDATE balance_sheet_accounts
SET amount = amount + ?
WHERE name = 'Trésorerie' AND account_type = 'Asset'
`, [amount]);
await conn.commit();
res.status(200).json({ message: 'Paiement enregistré avec succès.' });
} catch (err) {
await conn.rollback();
console.error("Erreur dans processPayment:", err.message);
res.status(500).json({ error: err.message });
} finally {
conn.release();
}
};
// GET + POST /finances/taxes
const getTaxes = async (req, res) => {
const [taxes] = await pool.query(`SELECT * FROM taxes ORDER BY name ASC`);
res.json(taxes);
};
const createOrUpdateTax = async (req, res) => {
const { id, name, rate, description, is_active } = req.body;
if (!name || isNaN(rate)) {
return res.status(400).json({ error: 'Nom et taux valides requis.' });
}
try {
if (id) {
await pool.query(`
UPDATE taxes SET name = ?, rate = ?, description = ?, is_active = ?
WHERE id = ?
`, [name.trim(), rate, description?.trim(), is_active ? 1 : 0, id]);
} else {
await pool.query(`
INSERT INTO taxes (name, rate, description, is_active)
VALUES (?, ?, ?, ?)
`, [name.trim(), rate, description?.trim(), is_active ? 1 : 0]);
}
res.json({ message: 'Taxe enregistrée.' });
} catch (err) {
console.error("Erreur dans createOrUpdateTax:", err.message);
res.status(500).json({ error: err.message });
}
};
// DELETE /finances/taxes/:id
const disableTax = async (req, res) => {
const id = parseInt(req.params.id);
if (!id) return res.status(400).json({ error: "ID invalide" });
try {
await pool.query(`UPDATE taxes SET is_active = 0 WHERE id = ?`, [id]);
res.json({ message: 'Taxe désactivée.' });
} catch (err) {
console.error("Erreur dans disableTax:", err.message);
res.status(500).json({ error: err.message });
}
};
module.exports = {
getDashboard,
generateInvoice,
processPayment,
getTaxes,
createOrUpdateTax,
disableTax
};