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,96 +237,102 @@ 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 contasapagar cp FROM (
SELECT
cp.idcontasapagar,
cp.movimento,
cp.status,
cp.valor,
INNER JOIN bancos banco_origem CASE
ON banco_origem.idbancos = cp.idbancos WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
LEFT JOIN bancos banco_destino ELSE COALESCE(cp.dataentrada, cp.insert_date)
ON banco_destino.idbancos = cp.idbancos_p END AS data_dashboard,
LEFT JOIN centrodecustos cc CASE
ON cc.idcentrodecustos = cp.idcentrodecustos WHEN cp.movimento IN ('Entrada', 'Estorno')
AND banco_origem.idusuarios = contexto.idUsuario
THEN 'entrada'
WHERE cp.deleted_at IS NULL WHEN cp.movimento = 'Saida'
AND ( AND banco_origem.idusuarios = contexto.idUsuario
banco_origem.idusuarios = ? AND COALESCE(cc.investimento, 0) = 0
OR banco_destino.idusuarios = ? THEN 'saida'
)
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) WHEN cp.movimento = 'Saida'
BETWEEN ? AND ? 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
INNER JOIN bancos banco_origem
ON banco_origem.idbancos = cp.idbancos
LEFT JOIN bancos banco_destino
ON banco_destino.idbancos = cp.idbancos_p
LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL
AND (
banco_origem.idusuarios = contexto.idUsuario
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,
/* 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,66 +917,91 @@ 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 SELECT
cp.idcentrodecustos, base_gastos.idcentrodecustos,
COALESCE(cc.descricao, 'Sem centro de custo') AS descricao, base_gastos.descricao,
COALESCE(SUM(cp.valor), 0) AS valor COALESCE(SUM(base_gastos.valor), 0) AS valor
FROM contasapagar cp FROM (
SELECT
cp.idcentrodecustos,
COALESCE(cc.descricao, 'Sem centro de custo') AS descricao,
cp.valor,
INNER JOIN bancos banco_origem CASE
ON banco_origem.idbancos = cp.idbancos WHEN cp.status IN ('Pago', 'Recebido')
AND cp.databaixa IS NOT NULL
THEN cp.databaixa
LEFT JOIN bancos banco_destino ELSE COALESCE(cp.dataentrada, cp.insert_date)
ON banco_destino.idbancos = cp.idbancos_p END AS data_dashboard,
LEFT JOIN centrodecustos cc CASE
ON cc.idcentrodecustos = cp.idcentrodecustos WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 0
THEN 'saida'
WHERE cp.deleted_at IS NULL WHEN cp.movimento = 'Sangria'
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) AND banco_origem.idusuarios = contexto.idUsuario
BETWEEN ? AND ? AND banco_destino.idusuarios = contexto.idUsuario
AND COALESCE(cc.investimento, 0) = 0 AND COALESCE(banco_destino.investimento, 0) = 1
THEN 'investimento'
AND ( WHEN cp.movimento = 'Sangria'
( AND banco_origem.idusuarios = contexto.idUsuario
cp.movimento = 'Saida' AND banco_destino.idusuarios = contexto.idUsuario
AND banco_origem.idusuarios = ? 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
INNER JOIN bancos banco_origem
ON banco_origem.idbancos = cp.idbancos
LEFT JOIN bancos banco_destino
ON banco_destino.idbancos = cp.idbancos_p
LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL
AND (
banco_origem.idusuarios = contexto.idUsuario
OR banco_destino.idusuarios = contexto.idUsuario
) )
) base_gastos
OR WHERE DATE(base_gastos.data_dashboard)
BETWEEN ? AND ?
( AND base_gastos.direcao_financeira = 'saida'
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,135 +1010,125 @@ 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 WHEN base_resumo.direcao_financeira = 'entrada'
/* Entrada ou estorno normal */ THEN base_resumo.valor
WHEN cp.movimento IN ('Entrada', 'Estorno') ELSE 0
AND banco_origem.idusuarios = ? END
THEN cp.valor ), 0) AS entradas,
/* Sangria recebida de outro usuário */ COALESCE(SUM(
WHEN cp.movimento = 'Sangria' CASE
AND banco_destino.idusuarios = ? WHEN base_resumo.direcao_financeira = 'saida'
AND banco_origem.idusuarios <> ? THEN base_resumo.valor
THEN cp.valor ELSE 0
END
), 0) AS saidas,
ELSE 0 COALESCE(SUM(
END CASE
), WHEN base_resumo.direcao_financeira = 'investimento'
0 THEN base_resumo.valor
) AS entradas, ELSE 0
END
), 0) AS investimentos
COALESCE( FROM (
SUM( SELECT
CASE cp.valor,
/* Saída normal */
WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 0
THEN cp.valor
/* Sangria enviada para outro usuário */ CASE
WHEN cp.movimento = 'Sangria' WHEN cp.status IN ('Pago', 'Recebido')
AND banco_origem.idusuarios = ? AND cp.databaixa IS NOT NULL
AND ( THEN cp.databaixa
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> ?
)
AND COALESCE(cc.investimento, 0) = 0
THEN cp.valor
ELSE 0 ELSE COALESCE(cp.dataentrada, cp.insert_date)
END END AS data_dashboard,
),
0
) AS saidas,
COALESCE( CASE
SUM( WHEN cp.movimento IN ('Entrada', 'Estorno')
CASE AND banco_origem.idusuarios = contexto.idUsuario
WHEN cp.movimento = 'Saida' THEN 'entrada'
AND banco_origem.idusuarios = ?
AND COALESCE(cc.investimento, 0) = 1
THEN cp.valor
WHEN cp.movimento = 'Sangria' WHEN cp.movimento = 'Saida'
AND banco_origem.idusuarios = ? AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = ? AND COALESCE(cc.investimento, 0) = 0
AND COALESCE(banco_destino.investimento, 0) = 1 THEN 'saida'
THEN cp.valor
ELSE 0 WHEN cp.movimento = 'Saida'
END AND banco_origem.idusuarios = contexto.idUsuario
), AND COALESCE(cc.investimento, 0) = 1
0 THEN 'investimento'
) AS investimentos
FROM contasapagar cp 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'
INNER JOIN bancos banco_origem WHEN cp.movimento = 'Sangria'
ON banco_origem.idbancos = cp.idbancos AND banco_origem.idusuarios = contexto.idUsuario
AND banco_destino.idusuarios = contexto.idUsuario
THEN 'transferencia_interna'
LEFT JOIN bancos banco_destino WHEN cp.movimento = 'Sangria'
ON banco_destino.idbancos = cp.idbancos_p AND banco_origem.idusuarios = contexto.idUsuario
AND (
banco_destino.idusuarios IS NULL
OR banco_destino.idusuarios <> contexto.idUsuario
)
THEN 'saida'
LEFT JOIN centrodecustos cc WHEN cp.movimento = 'Sangria'
ON cc.idcentrodecustos = cp.idcentrodecustos AND banco_destino.idusuarios = contexto.idUsuario
AND (
banco_origem.idusuarios IS NULL
OR banco_origem.idusuarios <> contexto.idUsuario
)
THEN 'entrada'
WHERE cp.deleted_at IS NULL ELSE 'neutro'
AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) END AS direcao_financeira
BETWEEN ? AND ?
AND ( FROM contasapagar cp
banco_origem.idusuarios = ?
OR banco_destino.idusuarios = ? INNER JOIN bancos banco_origem
) ON banco_origem.idbancos = cp.idbancos
LEFT JOIN bancos banco_destino
ON banco_destino.idbancos = cp.idbancos_p
LEFT JOIN centrodecustos cc
ON cc.idcentrodecustos = cp.idcentrodecustos
CROSS JOIN (
SELECT ? AS idUsuario
) contexto
WHERE cp.deleted_at IS NULL
AND (
banco_origem.idusuarios = contexto.idUsuario
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,
/* ================================================== ${FROM_MOVIMENTO_JOIN}
* SAÍDAS OPERACIONAIS ${whereSql}
* ================================================== */ ) base_resumo
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}
${whereSql}
`, `,
[ [
/* 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,