ajustado resumo

This commit is contained in:
Diego Freitas 2026-07-04 12:27:41 -03:00
parent 36aba1c646
commit f085f2623d
2 changed files with 534 additions and 677 deletions

View File

@ -159,79 +159,41 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) {
SELECT SELECT
COALESCE(SUM( COALESCE(SUM(
CASE CASE
/* Entradas e estornos normais */ WHEN base_resumo.direcao_financeira = 'entrada'
WHEN cp.movimento IN ('Entrada', 'Estorno') THEN base_resumo.valor
AND banco_origem.idusuarios = ?
THEN cp.valor
/* Sangria recebida de outro usuário */
WHEN cp.movimento = 'Sangria'
AND banco_destino.idusuarios = ?
AND (
banco_origem.idusuarios IS NULL
OR banco_origem.idusuarios <> ?
)
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS entradas, ), 0) AS entradas,
COALESCE(SUM( COALESCE(SUM(
CASE CASE
/* Saída operacional normal */ WHEN base_resumo.direcao_financeira = 'saida'
WHEN cp.movimento = 'Saida' THEN base_resumo.valor
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
THEN cp.valor
/* Sangria enviada para outro usuário */
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ?
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> ?
)
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS saidas, ), 0) AS saidas,
COALESCE(SUM( COALESCE(SUM(
CASE CASE
/* Saída marcada como investimento pelo centro de custo */ WHEN base_resumo.direcao_financeira = 'investimento'
WHEN cp.movimento = 'Saida' THEN base_resumo.valor
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN cp.valor
/* Transferência para banco de investimento do próprio usuário */
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ?
AND banco_destino.idusuarios = ?
AND COALESCE(banco_destino.investimento, 0) = 1
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS investimentos, ), 0) AS investimentos,
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.status = 'A receber' WHEN base_resumo.direcao_financeira = 'entrada'
AND cp.movimento IN ('Entrada', 'Estorno') AND base_resumo.status IN ('A receber', 'A pagar')
AND banco_origem.idusuarios = ? THEN base_resumo.valor
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS abertoEntradas, ), 0) AS abertoEntradas,
COUNT( COUNT(
CASE CASE
WHEN cp.status = 'A receber' WHEN base_resumo.direcao_financeira = 'entrada'
AND cp.movimento IN ('Entrada', 'Estorno') AND base_resumo.status IN ('A receber', 'A pagar')
AND banco_origem.idusuarios = ?
THEN 1 THEN 1
ELSE NULL ELSE NULL
END END
@ -239,21 +201,17 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) {
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.status = 'A pagar' WHEN base_resumo.direcao_financeira = 'saida'
AND cp.movimento = 'Saida' AND base_resumo.status IN ('A pagar', 'A receber')
AND banco_origem.idusuarios = ? THEN base_resumo.valor
AND COALESCE(cc.investimento, 0) = 0
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS abertoSaidas, ), 0) AS abertoSaidas,
COUNT( COUNT(
CASE CASE
WHEN cp.status = 'A pagar' WHEN base_resumo.direcao_financeira = 'saida'
AND cp.movimento = 'Saida' AND base_resumo.status IN ('A pagar', 'A receber')
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
THEN 1 THEN 1
ELSE NULL ELSE NULL
END END
@ -261,21 +219,17 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) {
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.status = 'A pagar' WHEN base_resumo.direcao_financeira = 'investimento'
AND cp.movimento = 'Saida' AND base_resumo.status IN ('A pagar', 'A receber')
AND banco_origem.idusuarios = ? THEN base_resumo.valor
AND COALESCE(cc.investimento, 0) = 1
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS abertoInvestimentos, ), 0) AS abertoInvestimentos,
COUNT( COUNT(
CASE CASE
WHEN cp.status = 'A pagar' WHEN base_resumo.direcao_financeira = 'investimento'
AND cp.movimento = 'Saida' AND base_resumo.status IN ('A pagar', 'A receber')
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN 1 THEN 1
ELSE NULL ELSE NULL
END END
@ -283,32 +237,75 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) {
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.status IN ('Pago', 'Recebido') WHEN base_resumo.direcao_financeira IN ('entrada', 'saida', 'investimento')
AND ( AND base_resumo.status IN ('Pago', 'Recebido')
cp.movimento <> 'Sangria' THEN base_resumo.valor
OR (
cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ?
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> ?
)
)
OR (
cp.movimento = 'Sangria'
AND banco_destino.idusuarios = ?
AND banco_origem.idusuarios <> ?
)
)
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS baixado, ), 0) AS baixado,
COUNT(*) AS quantidadeMovimentos COUNT(*) AS quantidadeMovimentos
FROM (
SELECT
cp.idcontasapagar,
cp.movimento,
cp.status,
cp.valor,
CASE
WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
ELSE COALESCE(cp.dataentrada, cp.insert_date)
END AS data_dashboard,
CASE
WHEN cp.movimento IN ('Entrada', 'Estorno')
AND banco_origem.idusuarios = contexto.idUsuario
THEN 'entrada'
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 0
THEN 'saida'
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'transferencia_interna'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> contexto.idUsuario
)
THEN 'saida'
WHEN cp.movimento = 'Sangria'
AND banco_destino.idusuarios = contexto.idUsuario
AND (
banco_origem.idusuarios IS NULL
OR banco_origem.idusuarios <> contexto.idUsuario
)
THEN 'entrada'
ELSE 'neutro'
END AS direcao_financeira
FROM contasapagar cp FROM contasapagar cp
INNER JOIN bancos banco_origem INNER JOIN bancos banco_origem
@ -320,59 +317,22 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) {
LEFT JOIN centrodecustos cc LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL WHERE cp.deleted_at IS NULL
AND ( AND (
banco_origem.idusuarios = ? banco_origem.idusuarios = contexto.idUsuario
OR banco_destino.idusuarios = ? OR banco_destino.idusuarios = contexto.idUsuario
) )
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) ) base_resumo
WHERE DATE(base_resumo.data_dashboard)
BETWEEN ? AND ? BETWEEN ? AND ?
`, `,
[ [
/* entradas */
idUsuario, idUsuario,
idUsuario,
idUsuario,
/* saídas */
idUsuario,
idUsuario,
idUsuario,
/* investimentos */
idUsuario,
idUsuario,
idUsuario,
/* abertoEntradas */
idUsuario,
/* quantidadeAbertoEntradas */
idUsuario,
/* abertoSaidas */
idUsuario,
/* quantidadeAbertoSaidas */
idUsuario,
/* abertoInvestimentos */
idUsuario,
/* quantidadeAbertoInvestimentos */
idUsuario,
/* baixado */
idUsuario,
idUsuario,
idUsuario,
idUsuario,
/* usuário na origem ou destino */
idUsuario,
idUsuario,
/* período */
dataInicio, dataInicio,
dataFim, dataFim,
] ]
@ -819,64 +779,69 @@ async function buscarUltimosMovimentos(idUsuario) {
banco_destino.descricao AS banco_destino_descricao, banco_destino.descricao AS banco_destino_descricao,
banco_destino.debito AS banco_destino_debito, banco_destino.debito AS banco_destino_debito,
banco_destino.idusuarios AS idusuario_destino, banco_destino.idusuarios AS idusuario_destino,
banco_destino.investimento AS banco_destino_investimento,
usuario_destino.nome AS usuario_destino_nome, usuario_destino.nome AS usuario_destino_nome,
cp.idcentrodecustos, cp.idcentrodecustos,
cc.descricao AS centro_custo_descricao, cc.descricao AS centro_custo_descricao,
CASE CASE
/* WHEN cp.movimento = 'Saida'
* Movimento normal: AND banco_origem.idusuarios = contexto.idUsuario
* mantém o tipo original. AND COALESCE(cc.investimento, 0) = 1
*/ THEN 'Investimento'
WHEN cp.movimento <> 'Sangria' WHEN cp.movimento <> 'Sangria'
THEN cp.movimento THEN cp.movimento
/* WHEN cp.movimento = 'Sangria'
* Origem e destino pertencem ao usuário: AND banco_origem.idusuarios = contexto.idUsuario
* transferência interna. AND banco_destino.idusuarios = contexto.idUsuario
*/ AND COALESCE(banco_destino.investimento, 0) = 1
WHEN banco_origem.idusuarios = ? THEN 'Investimento'
AND banco_destino.idusuarios = ?
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'TransferenciaInterna' THEN 'TransferenciaInterna'
/* WHEN cp.movimento = 'Sangria'
* Usuário é o dono do banco de origem: AND banco_origem.idusuarios = contexto.idUsuario
* dinheiro saiu para outro usuário.
*/
WHEN banco_origem.idusuarios = ?
THEN 'Saida' THEN 'Saida'
/* WHEN cp.movimento = 'Sangria'
* Usuário é o dono do banco de destino: AND banco_destino.idusuarios = contexto.idUsuario
* dinheiro entrou vindo de outro usuário.
*/
WHEN banco_destino.idusuarios = ?
THEN 'Entrada' THEN 'Entrada'
ELSE cp.movimento ELSE cp.movimento
END AS movimento_dashboard, END AS movimento_dashboard,
CASE CASE
WHEN cp.movimento <> 'Sangria' WHEN cp.movimento IN ('Entrada', 'Estorno')
AND cp.movimento IN ('Entrada', 'Estorno') AND banco_origem.idusuarios = contexto.idUsuario
THEN 'entrada' THEN 'entrada'
WHEN cp.movimento <> 'Sangria' WHEN cp.movimento = 'Saida'
AND cp.movimento = 'Saida' AND banco_origem.idusuarios = contexto.idUsuario
THEN 'saida' THEN 'saida'
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ? AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = ? AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 1
THEN 'saida'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'transferencia_interna' THEN 'transferencia_interna'
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ? AND banco_origem.idusuarios = contexto.idUsuario
THEN 'saida' THEN 'saida'
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_destino.idusuarios = ? AND banco_destino.idusuarios = contexto.idUsuario
THEN 'entrada' THEN 'entrada'
ELSE 'neutro' ELSE 'neutro'
@ -884,12 +849,28 @@ async function buscarUltimosMovimentos(idUsuario) {
CASE CASE
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ? AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = ? AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 0
THEN 1 THEN 1
ELSE 0 ELSE 0
END AS transferencia_interna END AS transferencia_interna,
CASE
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 1
THEN 1
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 1
THEN 1
ELSE 0
END AS investimento_dashboard
FROM contasapagar cp FROM contasapagar cp
@ -908,10 +889,14 @@ async function buscarUltimosMovimentos(idUsuario) {
LEFT JOIN centrodecustos cc LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL WHERE cp.deleted_at IS NULL
AND ( AND (
banco_origem.idusuarios = ? banco_origem.idusuarios = contexto.idUsuario
OR banco_destino.idusuarios = ? OR banco_destino.idusuarios = contexto.idUsuario
) )
ORDER BY ORDER BY
@ -921,24 +906,6 @@ async function buscarUltimosMovimentos(idUsuario) {
LIMIT 10 LIMIT 10
`, `,
[ [
/* movimento_dashboard */
idUsuario,
idUsuario,
idUsuario,
idUsuario,
/* direcao_dashboard */
idUsuario,
idUsuario,
idUsuario,
idUsuario,
/* transferencia_interna */
idUsuario,
idUsuario,
/* WHERE */
idUsuario,
idUsuario, idUsuario,
] ]
); );
@ -950,28 +917,61 @@ async function buscarUltimosMovimentos(idUsuario) {
transferencia_interna: transferencia_interna:
Number(item.transferencia_interna || 0) === 1, Number(item.transferencia_interna || 0) === 1,
investimento_dashboard:
Number(item.investimento_dashboard || 0) === 1,
})); }));
} }
async function buscarGraficos(idUsuario, dataInicio, dataFim) { async function buscarGraficos(idUsuario, dataInicio, dataFim) {
/*
* Gastos por centro de custo
*
* Aqui entram:
* - Saídas normais do usuário;
* - Sangrias enviadas para outro usuário;
*
* Não entram:
* - Sangrias entre bancos do próprio usuário;
* - Sangrias recebidas;
* - Movimentos classificados como investimento.
*/
const [centrosRows] = await pool.query( const [centrosRows] = await pool.query(
` `
SELECT
base_gastos.idcentrodecustos,
base_gastos.descricao,
COALESCE(SUM(base_gastos.valor), 0) AS valor
FROM (
SELECT SELECT
cp.idcentrodecustos, cp.idcentrodecustos,
COALESCE(cc.descricao, 'Sem centro de custo') AS descricao, COALESCE(cc.descricao, 'Sem centro de custo') AS descricao,
COALESCE(SUM(cp.valor), 0) AS valor cp.valor,
CASE
WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
ELSE COALESCE(cp.dataentrada, cp.insert_date)
END AS data_dashboard,
CASE
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 0
THEN 'saida'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'transferencia_interna'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> contexto.idUsuario
)
THEN 'saida'
ELSE 'neutro'
END AS direcao_financeira
FROM contasapagar cp FROM contasapagar cp
@ -984,32 +984,24 @@ async function buscarGraficos(idUsuario, dataInicio, dataFim) {
LEFT JOIN centrodecustos cc LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL WHERE cp.deleted_at IS NULL
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) AND (
banco_origem.idusuarios = contexto.idUsuario
OR banco_destino.idusuarios = contexto.idUsuario
)
) base_gastos
WHERE DATE(base_gastos.data_dashboard)
BETWEEN ? AND ? BETWEEN ? AND ?
AND COALESCE(cc.investimento, 0) = 0 AND base_gastos.direcao_financeira = 'saida'
AND (
(
cp.movimento = 'Saida'
AND banco_origem.idusuarios = ?
)
OR
(
cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ?
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> ?
)
)
)
GROUP BY GROUP BY
cp.idcentrodecustos, base_gastos.idcentrodecustos,
COALESCE(cc.descricao, 'Sem centro de custo') base_gastos.descricao
HAVING valor > 0 HAVING valor > 0
@ -1018,91 +1010,95 @@ async function buscarGraficos(idUsuario, dataInicio, dataFim) {
LIMIT 8 LIMIT 8
`, `,
[ [
idUsuario,
dataInicio, dataInicio,
dataFim, dataFim,
idUsuario,
idUsuario,
idUsuario,
] ]
); );
/*
* Resumo de entradas, saídas e investimentos.
*
* Para sangria:
* - destino é do usuário e origem é de outro usuário = entrada;
* - origem é do usuário e destino é de outro usuário = saída;
* - origem e destino são do usuário = transferência interna, ignorada.
*/
const [entradasSaidasRows] = await pool.query( const [entradasSaidasRows] = await pool.query(
` `
SELECT SELECT
COALESCE( COALESCE(SUM(
SUM(
CASE CASE
/* Entrada ou estorno normal */ WHEN base_resumo.direcao_financeira = 'entrada'
WHEN cp.movimento IN ('Entrada', 'Estorno') THEN base_resumo.valor
AND banco_origem.idusuarios = ?
THEN cp.valor
/* Sangria recebida de outro usuário */
WHEN cp.movimento = 'Sangria'
AND banco_destino.idusuarios = ?
AND banco_origem.idusuarios <> ?
THEN cp.valor
ELSE 0 ELSE 0
END END
), ), 0) AS entradas,
0
) AS entradas,
COALESCE( COALESCE(SUM(
SUM(
CASE CASE
/* Saída normal */ WHEN base_resumo.direcao_financeira = 'saida'
WHEN cp.movimento = 'Saida' THEN base_resumo.valor
AND banco_origem.idusuarios = ? ELSE 0
AND COALESCE(cc.investimento, 0) = 0 END
THEN cp.valor ), 0) AS saidas,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
THEN base_resumo.valor
ELSE 0
END
), 0) AS investimentos
FROM (
SELECT
cp.valor,
CASE
WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
ELSE COALESCE(cp.dataentrada, cp.insert_date)
END AS data_dashboard,
CASE
WHEN cp.movimento IN ('Entrada', 'Estorno')
AND banco_origem.idusuarios = contexto.idUsuario
THEN 'entrada'
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 0
THEN 'saida'
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 1
THEN 'investimento'
/* Sangria enviada para outro usuário */
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ? AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(banco_destino.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'transferencia_interna'
WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = contexto.idUsuario
AND ( AND (
banco_destino.idusuarios IS NULL banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> ? OR banco_destino.idusuarios <> contexto.idUsuario
) )
AND COALESCE(cc.investimento, 0) = 0 THEN 'saida'
THEN cp.valor
ELSE 0
END
),
0
) AS saidas,
COALESCE(
SUM(
CASE
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN cp.valor
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND banco_origem.idusuarios = ? AND banco_destino.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = ? AND (
AND COALESCE(banco_destino.investimento, 0) = 1 banco_origem.idusuarios IS NULL
THEN cp.valor OR banco_origem.idusuarios <> contexto.idUsuario
)
THEN 'entrada'
ELSE 0 ELSE 'neutro'
END END AS direcao_financeira
),
0
) AS investimentos
FROM contasapagar cp FROM contasapagar cp
@ -1115,38 +1111,24 @@ async function buscarGraficos(idUsuario, dataInicio, dataFim) {
LEFT JOIN centrodecustos cc LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos ON cc.idcentrodecustos = cp.idcentrodecustos
WHERE cp.deleted_at IS NULL CROSS JOIN (
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) SELECT ? AS idUsuario
BETWEEN ? AND ? ) contexto
WHERE cp.deleted_at IS NULL
AND ( AND (
banco_origem.idusuarios = ? banco_origem.idusuarios = contexto.idUsuario
OR banco_destino.idusuarios = ? OR banco_destino.idusuarios = contexto.idUsuario
) )
) base_resumo
WHERE DATE(base_resumo.data_dashboard)
BETWEEN ? AND ?
`, `,
[ [
/* Entradas */
idUsuario, idUsuario,
idUsuario,
idUsuario,
/* Saídas */
idUsuario,
idUsuario,
idUsuario,
/* Investimentos */
idUsuario,
idUsuario,
idUsuario,
/* Período */
dataInicio, dataInicio,
dataFim, dataFim,
/* Usuário presente em uma das pontas */
idUsuario,
idUsuario,
] ]
); );

View File

@ -193,9 +193,12 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) {
const usuarioAtual = Number(idUsuario); const usuarioAtual = Number(idUsuario);
const usuarioOrigem = Number(item.idusuario_origem); const usuarioOrigem = Number(item.idusuario_origem);
const usuarioDestino = Number(item.idusuario_destino); const usuarioDestino = Number(item.idusuario_destino);
const destinoInvestimento = Number(item.banco_destino_investimento || 0) === 1;
let movimentoDashboard = item.movimento; let movimentoDashboard = item.movimento;
let direcaoDashboard = 'neutro'; let direcaoDashboard = 'neutro';
let transferenciaInterna = false;
let investimentoDashboard = false;
if ( if (
item.movimento === 'Entrada' item.movimento === 'Entrada'
@ -205,16 +208,21 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) {
} else if (item.movimento === 'Saida') { } else if (item.movimento === 'Saida') {
direcaoDashboard = 'saida'; direcaoDashboard = 'saida';
} else if (item.movimento === 'Sangria') { } else if (item.movimento === 'Sangria') {
if ( const origemEhUsuario = usuarioOrigem === usuarioAtual;
usuarioOrigem === usuarioAtual const destinoEhUsuario = usuarioDestino === usuarioAtual;
&& usuarioDestino === usuarioAtual
) { if (origemEhUsuario && destinoEhUsuario && destinoInvestimento) {
movimentoDashboard = 'Investimento';
direcaoDashboard = 'saida';
investimentoDashboard = true;
} else if (origemEhUsuario && destinoEhUsuario) {
movimentoDashboard = 'TransferenciaInterna'; movimentoDashboard = 'TransferenciaInterna';
direcaoDashboard = 'transferencia_interna'; direcaoDashboard = 'transferencia_interna';
} else if (usuarioOrigem === usuarioAtual) { transferenciaInterna = true;
} else if (origemEhUsuario) {
movimentoDashboard = 'Saida'; movimentoDashboard = 'Saida';
direcaoDashboard = 'saida'; direcaoDashboard = 'saida';
} else if (usuarioDestino === usuarioAtual) { } else if (destinoEhUsuario) {
movimentoDashboard = 'Entrada'; movimentoDashboard = 'Entrada';
direcaoDashboard = 'entrada'; direcaoDashboard = 'entrada';
} }
@ -226,14 +234,8 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) {
movimento_dashboard: movimentoDashboard, movimento_dashboard: movimentoDashboard,
direcao_dashboard: direcaoDashboard, direcao_dashboard: direcaoDashboard,
transferencia_interna: transferencia_interna: transferenciaInterna,
movimentoDashboard === 'TransferenciaInterna', investimento_dashboard: investimentoDashboard,
investimento_dashboard:
item.movimento === 'Sangria'
&& usuarioOrigem === usuarioAtual
&& usuarioDestino === usuarioAtual
&& Number(item.banco_destino_investimento || 0) === 1,
}; };
} }
@ -351,15 +353,26 @@ async function buscarResumoMovimentos(
const paramsWhere = [...base.params]; const paramsWhere = [...base.params];
/* /*
* No extrato financeiro, entradas, saídas e investimentos * No extrato financeiro, o ideal é usar a data de baixa
* pertencem ao período de realização do movimento. * quando o movimento foi realizado.
* *
* Na tabela comum, o resumo respeita o campo de data * Isso evita o caso clássico:
* selecionado pelo usuário. * - movimento lançado em um mês
* - pago/baixado em outro
* - aparece no extrato pela baixa
* - mas não entra no summary porque o summary olhava dataentrada
*/ */
const campoDataSql = const campoDataSql =
opcoes.modoExtrato === true opcoes.modoExtrato === true
? 'COALESCE(cp.dataentrada, cp.insert_date)' ? `
CASE
WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
ELSE COALESCE(cp.dataentrada, cp.insert_date)
END
`
: resolverCampoData(filtros.dataCampo); : resolverCampoData(filtros.dataCampo);
if (filtros.dataInicio) { if (filtros.dataInicio) {
@ -381,94 +394,198 @@ async function buscarResumoMovimentos(
SELECT SELECT
COUNT(*) AS quantidade, COUNT(*) AS quantidade,
/* ==================================================
* ENTRADAS
* ================================================== */
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') WHEN base_resumo.direcao_financeira = 'entrada'
AND b.idusuarios = ? THEN base_resumo.valor
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND bp.idusuarios = ?
AND (
b.idusuarios IS NULL
OR b.idusuarios <> ?
)
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS totalEntradas, ), 0) AS totalEntradas,
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') WHEN base_resumo.direcao_financeira = 'entrada'
AND b.idusuarios = ? AND base_resumo.status IN ('Recebido', 'Pago')
AND cp.status = 'Recebido' THEN base_resumo.valor
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND bp.idusuarios = ?
AND (
b.idusuarios IS NULL
OR b.idusuarios <> ?
)
AND cp.status IN ('Pago', 'Recebido')
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS entradasRecebidas, ), 0) AS entradasRecebidas,
COALESCE(SUM( COALESCE(SUM(
CASE CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') WHEN base_resumo.direcao_financeira = 'entrada'
AND b.idusuarios = ? AND base_resumo.status IN ('A receber', 'A pagar')
AND cp.status = 'A receber' THEN base_resumo.valor
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND bp.idusuarios = ?
AND (
b.idusuarios IS NULL
OR b.idusuarios <> ?
)
AND cp.status IN ('A receber', 'A pagar')
THEN cp.valor
ELSE 0 ELSE 0
END END
), 0) AS entradasPendentes, ), 0) AS entradasPendentes,
COUNT( COUNT(
CASE CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') WHEN base_resumo.direcao_financeira = 'entrada'
AND b.idusuarios = ? AND base_resumo.status IN ('Recebido', 'Pago')
AND cp.status = 'Recebido'
THEN 1 THEN 1
WHEN cp.movimento = 'Sangria'
AND bp.idusuarios = ?
AND (
b.idusuarios IS NULL
OR b.idusuarios <> ?
)
AND cp.status IN ('Pago', 'Recebido')
THEN 1
ELSE NULL ELSE NULL
END END
) AS quantidadeEntradasRecebidas, ) AS quantidadeEntradasRecebidas,
COUNT( COUNT(
CASE
WHEN base_resumo.direcao_financeira = 'entrada'
AND base_resumo.status IN ('A receber', 'A pagar')
THEN 1
ELSE NULL
END
) AS quantidadeEntradasPendentes,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'saida'
THEN base_resumo.valor
ELSE 0
END
), 0) AS totalSaidas,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'saida'
AND base_resumo.status IN ('Pago', 'Recebido')
THEN base_resumo.valor
ELSE 0
END
), 0) AS saidasPagas,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'saida'
AND base_resumo.status IN ('A pagar', 'A receber')
THEN base_resumo.valor
ELSE 0
END
), 0) AS saidasPendentes,
COUNT(
CASE
WHEN base_resumo.direcao_financeira = 'saida'
AND base_resumo.status IN ('Pago', 'Recebido')
THEN 1
ELSE NULL
END
) AS quantidadeSaidasPagas,
COUNT(
CASE
WHEN base_resumo.direcao_financeira = 'saida'
AND base_resumo.status IN ('A pagar', 'A receber')
THEN 1
ELSE NULL
END
) AS quantidadeSaidasPendentes,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
THEN base_resumo.valor
ELSE 0
END
), 0) AS totalInvestimentos,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
AND base_resumo.status IN ('Pago', 'Recebido')
THEN base_resumo.valor
ELSE 0
END
), 0) AS investimentosRealizados,
COALESCE(SUM(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
AND base_resumo.status IN ('A pagar', 'A receber')
THEN base_resumo.valor
ELSE 0
END
), 0) AS investimentosPendentes,
COUNT(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
AND base_resumo.status IN ('Pago', 'Recebido')
THEN 1
ELSE NULL
END
) AS quantidadeInvestimentosRealizados,
COUNT(
CASE
WHEN base_resumo.direcao_financeira = 'investimento'
AND base_resumo.status IN ('A pagar', 'A receber')
THEN 1
ELSE NULL
END
) AS quantidadeInvestimentosPendentes,
COALESCE(SUM(
CASE
WHEN base_resumo.movimento = 'Estorno'
AND base_resumo.idusuario_origem = ?
THEN base_resumo.valor
ELSE 0
END
), 0) AS totalEstornos,
COALESCE(SUM(
CASE
WHEN base_resumo.saldo_processado = 1
THEN 1
ELSE 0
END
), 0) AS saldoProcessado
FROM (
SELECT
cp.idcontasapagar,
cp.movimento,
cp.status,
cp.valor,
cp.saldo_processado,
b.idusuarios AS idusuario_origem,
bp.idusuarios AS idusuario_destino,
CASE CASE
WHEN cp.movimento IN ('Entrada', 'Estorno') WHEN cp.movimento IN ('Entrada', 'Estorno')
AND b.idusuarios = ? AND b.idusuarios = ?
AND cp.status = 'A receber' THEN 'entrada'
THEN 1
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
THEN 'saida'
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
THEN 'investimento'
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
THEN 'transferencia_interna'
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
THEN 'saida'
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Sangria'
AND bp.idusuarios = ? AND bp.idusuarios = ?
@ -476,267 +593,29 @@ async function buscarResumoMovimentos(
b.idusuarios IS NULL b.idusuarios IS NULL
OR b.idusuarios <> ? OR b.idusuarios <> ?
) )
AND cp.status IN ('A receber', 'A pagar') THEN 'entrada'
THEN 1
ELSE NULL ELSE 'neutro'
END END AS direcao_financeira
) AS quantidadeEntradasPendentes,
/* ==================================================
* SAÍDAS OPERACIONAIS
* ================================================== */
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
THEN cp.valor
ELSE 0
END
), 0) AS totalSaidas,
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
AND cp.status = 'Pago'
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
AND cp.status IN ('Pago', 'Recebido')
THEN cp.valor
ELSE 0
END
), 0) AS saidasPagas,
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
AND cp.status = 'A pagar'
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
AND cp.status IN ('A pagar', 'A receber')
THEN cp.valor
ELSE 0
END
), 0) AS saidasPendentes,
COUNT(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
AND cp.status = 'Pago'
THEN 1
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
AND cp.status IN ('Pago', 'Recebido')
THEN 1
ELSE NULL
END
) AS quantidadeSaidasPagas,
COUNT(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
AND cp.status = 'A pagar'
THEN 1
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND (
bp.idusuarios IS NULL
OR bp.idusuarios <> ?
)
AND cp.status IN ('A pagar', 'A receber')
THEN 1
ELSE NULL
END
) AS quantidadeSaidasPendentes,
/* ==================================================
* INVESTIMENTOS
* ================================================== */
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
THEN cp.valor
ELSE 0
END
), 0) AS totalInvestimentos,
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
AND cp.status = 'Pago'
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
AND cp.status IN ('Pago', 'Recebido')
THEN cp.valor
ELSE 0
END
), 0) AS investimentosRealizados,
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
AND cp.status = 'A pagar'
THEN cp.valor
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
AND cp.status IN ('A pagar', 'A receber')
THEN cp.valor
ELSE 0
END
), 0) AS investimentosPendentes,
COUNT(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
AND cp.status = 'Pago'
THEN 1
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
AND cp.status IN ('Pago', 'Recebido')
THEN 1
ELSE NULL
END
) AS quantidadeInvestimentosRealizados,
COUNT(
CASE
WHEN cp.movimento = 'Saida'
AND b.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
AND cp.status = 'A pagar'
THEN 1
WHEN cp.movimento = 'Sangria'
AND b.idusuarios = ?
AND bp.idusuarios = ?
AND COALESCE(bp.investimento, 0) = 1
AND cp.status IN ('A pagar', 'A receber')
THEN 1
ELSE NULL
END
) AS quantidadeInvestimentosPendentes,
/* ==================================================
* INFORMAÇÕES AUXILIARES
* ================================================== */
COALESCE(SUM(
CASE
WHEN cp.movimento = 'Estorno'
AND b.idusuarios = ?
THEN cp.valor
ELSE 0
END
), 0) AS totalEstornos,
COALESCE(SUM(
CASE
WHEN cp.saldo_processado = 1
THEN 1
ELSE 0
END
), 0) AS saldoProcessado
${FROM_MOVIMENTO_JOIN} ${FROM_MOVIMENTO_JOIN}
${whereSql} ${whereSql}
) base_resumo
`, `,
[ [
/* Entradas: total, recebido, pendente e quantidades */ /* totalEstornos */
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
/* Saídas: total, pago, pendente e quantidades */
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
/* Investimentos: total, realizado, pendente e quantidades */
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
idUsuario, idUsuario, idUsuario,
/* Estornos */
idUsuario, idUsuario,
/* Filtros */ /* direcao_financeira */
idUsuario,
idUsuario,
idUsuario,
idUsuario, idUsuario,
idUsuario, idUsuario,
idUsuario, idUsuario,
idUsuario, idUsuario,
/* filtros */
...paramsWhere, ...paramsWhere,
] ]
); );
@ -856,10 +735,6 @@ async function buscarResumoMovimentos(
saldo, saldo,
/*
* Campos antigos neutralizados temporariamente.
* Podem ser removidos após o front ser atualizado.
*/
totalSangrias: 0, totalSangrias: 0,
totalBaixado: 0, totalBaixado: 0,
totalAberto: 0, totalAberto: 0,