financeiro/financeiro-api/src/modules/relatorios/services/relatorios.service.js

275 lines
7.4 KiB
JavaScript

const pool = require('../../../database/mysql');
function resolverCampoData(dataCampo) {
const camposPermitidos = {
dataentrada: 'cp.dataentrada',
datavencimento: 'cp.datavencimento',
databaixa: 'cp.databaixa',
insert_date: 'cp.insert_date',
update_date: 'cp.update_date',
};
return camposPermitidos[dataCampo] || 'cp.datavencimento';
}
function montarWhereRelatorio(filtros = {}) {
const where = [];
const params = [];
const campoData = resolverCampoData(filtros.dataCampo);
if (filtros.dataInicio) {
where.push(`DATE(${campoData}) >= ?`);
params.push(filtros.dataInicio);
}
if (filtros.dataFim) {
where.push(`DATE(${campoData}) <= ?`);
params.push(filtros.dataFim);
}
if (filtros.movimento) {
where.push('cp.movimento = ?');
params.push(filtros.movimento);
}
if (filtros.status) {
where.push('cp.status = ?');
params.push(filtros.status);
}
if (filtros.idbancos) {
where.push('cp.idbancos = ?');
params.push(Number(filtros.idbancos));
}
if (filtros.idcentrodecustos) {
where.push('cp.idcentrodecustos = ?');
params.push(Number(filtros.idcentrodecustos));
}
if (filtros.idclientes) {
where.push('cp.idclientes = ?');
params.push(Number(filtros.idclientes));
}
const whereSql = where.length > 0 ? `WHERE ${where.join(' AND ')}` : '';
return {
campoData,
whereSql,
params,
};
}
async function buscarResumo(filtros = {}) {
const { whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
COUNT(*) AS quantidade,
COALESCE(SUM(CASE WHEN cp.movimento = 'Entrada' THEN cp.valor ELSE 0 END), 0) AS totalEntradas,
COALESCE(SUM(CASE WHEN cp.movimento = 'Saida' THEN cp.valor ELSE 0 END), 0) AS totalSaidas,
COALESCE(SUM(CASE WHEN cp.movimento = 'Sangria' THEN cp.valor ELSE 0 END), 0) AS totalSangrias,
COALESCE(SUM(CASE WHEN cp.movimento = 'Estorno' THEN cp.valor ELSE 0 END), 0) AS totalEstornos,
COALESCE(SUM(CASE WHEN cp.status = 'Pago' THEN cp.valor ELSE 0 END), 0) AS totalPago,
COALESCE(SUM(CASE WHEN cp.status = 'A pagar' THEN cp.valor ELSE 0 END), 0) AS totalAPagar,
COALESCE(SUM(CASE WHEN cp.status = 'Recebido' THEN cp.valor ELSE 0 END), 0) AS totalRecebido,
COALESCE(SUM(CASE WHEN cp.status = 'A receber' THEN cp.valor ELSE 0 END), 0) AS totalAReceber,
COALESCE(SUM(
CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') THEN cp.valor
WHEN cp.movimento IN ('Saida', 'Sangria') THEN -cp.valor
ELSE 0
END
), 0) AS saldo
FROM contasapagar cp
${whereSql}
`,
params
);
const item = rows[0] || {};
return {
quantidade: Number(item.quantidade || 0),
totalEntradas: Number(item.totalEntradas || 0),
totalSaidas: Number(item.totalSaidas || 0),
totalSangrias: Number(item.totalSangrias || 0),
totalEstornos: Number(item.totalEstornos || 0),
totalPago: Number(item.totalPago || 0),
totalAPagar: Number(item.totalAPagar || 0),
totalRecebido: Number(item.totalRecebido || 0),
totalAReceber: Number(item.totalAReceber || 0),
saldo: Number(item.saldo || 0),
};
}
async function buscarEvolucao(filtros = {}) {
const { campoData, whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
DATE_FORMAT(${campoData}, '%Y-%m') AS periodo,
COALESCE(SUM(CASE WHEN cp.movimento = 'Entrada' THEN cp.valor ELSE 0 END), 0) AS entradas,
COALESCE(SUM(CASE WHEN cp.movimento IN ('Saida', 'Sangria') THEN cp.valor ELSE 0 END), 0) AS saidas,
COALESCE(SUM(CASE WHEN cp.movimento = 'Estorno' THEN cp.valor ELSE 0 END), 0) AS estornos,
COALESCE(SUM(
CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') THEN cp.valor
WHEN cp.movimento IN ('Saida', 'Sangria') THEN -cp.valor
ELSE 0
END
), 0) AS saldo
FROM contasapagar cp
${whereSql}
GROUP BY DATE_FORMAT(${campoData}, '%Y-%m')
ORDER BY periodo ASC
`,
params
);
return rows.map((item) => ({
periodo: item.periodo,
entradas: Number(item.entradas || 0),
saidas: Number(item.saidas || 0),
estornos: Number(item.estornos || 0),
saldo: Number(item.saldo || 0),
}));
}
async function buscarPorCentroCusto(filtros = {}) {
const { whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
COALESCE(cc.descricao, 'Sem centro de custo') AS descricao,
COUNT(*) AS quantidade,
COALESCE(SUM(cp.valor), 0) AS total
FROM contasapagar cp
LEFT JOIN centrodecustos cc ON cc.idcentrodecustos = cp.idcentrodecustos
${whereSql}
GROUP BY COALESCE(cc.descricao, 'Sem centro de custo')
ORDER BY total DESC
LIMIT 10
`,
params
);
return rows.map((item) => ({
descricao: item.descricao,
quantidade: Number(item.quantidade || 0),
total: Number(item.total || 0),
}));
}
async function buscarPorBanco(filtros = {}) {
const { whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
COALESCE(b.descricao, 'Sem banco/carteira') AS descricao,
COUNT(*) AS quantidade,
COALESCE(SUM(cp.valor), 0) AS total
FROM contasapagar cp
LEFT JOIN bancos b ON b.idbancos = cp.idbancos
${whereSql}
GROUP BY COALESCE(b.descricao, 'Sem banco/carteira')
ORDER BY total DESC
LIMIT 10
`,
params
);
return rows.map((item) => ({
descricao: item.descricao,
quantidade: Number(item.quantidade || 0),
total: Number(item.total || 0),
}));
}
async function buscarPorStatus(filtros = {}) {
const { whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
COALESCE(cp.status, 'Sem situação') AS descricao,
COUNT(*) AS quantidade,
COALESCE(SUM(cp.valor), 0) AS total
FROM contasapagar cp
${whereSql}
GROUP BY COALESCE(cp.status, 'Sem situação')
ORDER BY total DESC
`,
params
);
return rows.map((item) => ({
descricao: item.descricao,
quantidade: Number(item.quantidade || 0),
total: Number(item.total || 0),
}));
}
async function buscarPorMovimento(filtros = {}) {
const { whereSql, params } = montarWhereRelatorio(filtros);
const [rows] = await pool.query(
`
SELECT
COALESCE(cp.movimento, 'Sem movimento') AS descricao,
COUNT(*) AS quantidade,
COALESCE(SUM(cp.valor), 0) AS total
FROM contasapagar cp
${whereSql}
GROUP BY COALESCE(cp.movimento, 'Sem movimento')
ORDER BY total DESC
`,
params
);
return rows.map((item) => ({
descricao: item.descricao,
quantidade: Number(item.quantidade || 0),
total: Number(item.total || 0),
}));
}
async function buscarDashboardRelatorios(filtros = {}) {
const [
resumo,
evolucao,
porCentroCusto,
porBanco,
porStatus,
porMovimento,
] = await Promise.all([
buscarResumo(filtros),
buscarEvolucao(filtros),
buscarPorCentroCusto(filtros),
buscarPorBanco(filtros),
buscarPorStatus(filtros),
buscarPorMovimento(filtros),
]);
return {
resumo,
evolucao,
porCentroCusto,
porBanco,
porStatus,
porMovimento,
};
}
module.exports = {
buscarDashboardRelatorios,
};