/** * Financial Queries Service * @author Descomplicar® | @link descomplicar.pt | @copyright 2026 */ import db from '../db.js' import type { RowDataPacket } from 'mysql2' export async function getFinancialData() { const [ [vendasMes], [vendasAno], [despesasMes], [despesasAno], categorias, evolucaoReceitas, evolucaoDespesas, ] = await Promise.all([ // Vendas mes actual (facturas nao-draft, nao-canceladas) db.query(` SELECT COALESCE(SUM(total), 0) as valor FROM tblinvoices WHERE YEAR(date) = YEAR(CURDATE()) AND MONTH(date) = MONTH(CURDATE()) AND status NOT IN (1, 5) `), // Vendas acumuladas ano db.query(` SELECT COALESCE(SUM(total), 0) as valor FROM tblinvoices WHERE YEAR(date) = YEAR(CURDATE()) AND status NOT IN (1, 5) `), // Despesas mes actual db.query(` SELECT COALESCE(SUM(amount), 0) as valor FROM tblexpenses WHERE YEAR(date) = YEAR(CURDATE()) AND MONTH(date) = MONTH(CURDATE()) `), // Despesas acumuladas ano db.query(` SELECT COALESCE(SUM(amount), 0) as valor FROM tblexpenses WHERE YEAR(date) = YEAR(CURDATE()) `), // Distribuicao por categoria db.query(` SELECT ec.name as categoria, ROUND(SUM(e.amount), 2) as total FROM tblexpenses e LEFT JOIN tblexpenses_categories ec ON e.category = ec.id WHERE YEAR(e.date) = YEAR(CURDATE()) GROUP BY e.category, ec.name ORDER BY total DESC `), // Evolucao mensal receitas (ultimos 12 meses) db.query(` SELECT DATE_FORMAT(date, '%Y-%m') as mes, ROUND(SUM(total), 2) as valor FROM tblinvoices WHERE status NOT IN (1, 5) AND date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) GROUP BY mes ORDER BY mes `), // Evolucao mensal despesas (ultimos 12 meses) db.query(` SELECT DATE_FORMAT(date, '%Y-%m') as mes, ROUND(SUM(amount), 2) as valor FROM tblexpenses WHERE date >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH) GROUP BY mes ORDER BY mes `), ]) const vendas_mes = Math.round((vendasMes[0]?.valor || 0) * 100) / 100 const vendas_ano = Math.round((vendasAno[0]?.valor || 0) * 100) / 100 const despesas_mes = Math.round((despesasMes[0]?.valor || 0) * 100) / 100 const despesas_ano = Math.round((despesasAno[0]?.valor || 0) * 100) / 100 const lucro_mes = Math.round((vendas_mes - despesas_mes) * 100) / 100 const lucro_ano = Math.round((vendas_ano - despesas_ano) * 100) / 100 // Build monthly evolution map const mesesMap = new Map() for (const r of evolucaoReceitas[0] as RowDataPacket[]) { mesesMap.set(r.mes, { receita: r.valor, despesa: 0 }) } for (const d of evolucaoDespesas[0] as RowDataPacket[]) { const existing = mesesMap.get(d.mes) || { receita: 0, despesa: 0 } existing.despesa = d.valor mesesMap.set(d.mes, existing) } const evolucao = Array.from(mesesMap.entries()) .sort(([a], [b]) => a.localeCompare(b)) .map(([mes, vals]) => ({ mes, receita: vals.receita, despesa: vals.despesa, })) return { vendas_mes, vendas_ano, despesas_mes, despesas_ano, lucro_mes, lucro_ano, categorias: (categorias[0] as RowDataPacket[]).map(c => ({ name: c.categoria || 'Sem categoria', value: c.total, })), evolucao, } }