diff --git a/financeiro-api/src/modules/dashboard/services/dashboard.service.js b/financeiro-api/src/modules/dashboard/services/dashboard.service.js index ec67872..c4e7452 100644 --- a/financeiro-api/src/modules/dashboard/services/dashboard.service.js +++ b/financeiro-api/src/modules/dashboard/services/dashboard.service.js @@ -159,79 +159,41 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) { SELECT COALESCE(SUM( CASE - /* Entradas e estornos normais */ - WHEN cp.movimento IN ('Entrada', 'Estorno') - 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 - + WHEN base_resumo.direcao_financeira = 'entrada' + THEN base_resumo.valor ELSE 0 END ), 0) AS entradas, COALESCE(SUM( CASE - /* Saída operacional normal */ - WHEN cp.movimento = 'Saida' - 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 - + WHEN base_resumo.direcao_financeira = 'saida' + THEN base_resumo.valor ELSE 0 END ), 0) AS saidas, COALESCE(SUM( CASE - /* Saída marcada como investimento pelo centro de custo */ - WHEN cp.movimento = 'Saida' - 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 - + WHEN base_resumo.direcao_financeira = 'investimento' + THEN base_resumo.valor ELSE 0 END ), 0) AS investimentos, COALESCE(SUM( CASE - WHEN cp.status = 'A receber' - AND cp.movimento IN ('Entrada', 'Estorno') - AND banco_origem.idusuarios = ? - THEN cp.valor + WHEN base_resumo.direcao_financeira = 'entrada' + AND base_resumo.status IN ('A receber', 'A pagar') + THEN base_resumo.valor ELSE 0 END ), 0) AS abertoEntradas, COUNT( CASE - WHEN cp.status = 'A receber' - AND cp.movimento IN ('Entrada', 'Estorno') - AND banco_origem.idusuarios = ? + WHEN base_resumo.direcao_financeira = 'entrada' + AND base_resumo.status IN ('A receber', 'A pagar') THEN 1 ELSE NULL END @@ -239,21 +201,17 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) { COALESCE(SUM( CASE - WHEN cp.status = 'A pagar' - AND cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 0 - THEN cp.valor + WHEN base_resumo.direcao_financeira = 'saida' + AND base_resumo.status IN ('A pagar', 'A receber') + THEN base_resumo.valor ELSE 0 END ), 0) AS abertoSaidas, COUNT( CASE - WHEN cp.status = 'A pagar' - AND cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 0 + WHEN base_resumo.direcao_financeira = 'saida' + AND base_resumo.status IN ('A pagar', 'A receber') THEN 1 ELSE NULL END @@ -261,21 +219,17 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) { COALESCE(SUM( CASE - WHEN cp.status = 'A pagar' - AND cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 1 - THEN cp.valor + WHEN base_resumo.direcao_financeira = 'investimento' + AND base_resumo.status IN ('A pagar', 'A receber') + THEN base_resumo.valor ELSE 0 END ), 0) AS abertoInvestimentos, COUNT( CASE - WHEN cp.status = 'A pagar' - AND cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 1 + WHEN base_resumo.direcao_financeira = 'investimento' + AND base_resumo.status IN ('A pagar', 'A receber') THEN 1 ELSE NULL END @@ -283,96 +237,102 @@ async function buscarCardsMovimentos(idUsuario, dataInicio, dataFim) { COALESCE(SUM( CASE - WHEN cp.status IN ('Pago', 'Recebido') - AND ( - cp.movimento <> 'Sangria' - - 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 + WHEN base_resumo.direcao_financeira IN ('entrada', 'saida', 'investimento') + AND base_resumo.status IN ('Pago', 'Recebido') + THEN base_resumo.valor ELSE 0 END ), 0) AS baixado, COUNT(*) AS quantidadeMovimentos - FROM contasapagar cp + FROM ( + SELECT + cp.idcontasapagar, + cp.movimento, + cp.status, + cp.valor, - INNER JOIN bancos banco_origem - ON banco_origem.idbancos = cp.idbancos + CASE + WHEN cp.status IN ('Pago', 'Recebido') + AND cp.databaixa IS NOT NULL + THEN cp.databaixa - LEFT JOIN bancos banco_destino - ON banco_destino.idbancos = cp.idbancos_p + ELSE COALESCE(cp.dataentrada, cp.insert_date) + END AS data_dashboard, - LEFT JOIN centrodecustos cc - ON cc.idcentrodecustos = cp.idcentrodecustos + CASE + WHEN cp.movimento IN ('Entrada', 'Estorno') + AND banco_origem.idusuarios = contexto.idUsuario + THEN 'entrada' - WHERE cp.deleted_at IS NULL - AND ( - banco_origem.idusuarios = ? - OR banco_destino.idusuarios = ? - ) - AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) - BETWEEN ? AND ? + 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 + + 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, - - /* 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, dataFim, ] @@ -819,64 +779,69 @@ async function buscarUltimosMovimentos(idUsuario) { banco_destino.descricao AS banco_destino_descricao, banco_destino.debito AS banco_destino_debito, banco_destino.idusuarios AS idusuario_destino, + banco_destino.investimento AS banco_destino_investimento, usuario_destino.nome AS usuario_destino_nome, cp.idcentrodecustos, cc.descricao AS centro_custo_descricao, CASE - /* - * Movimento normal: - * mantém o tipo original. - */ + WHEN cp.movimento = 'Saida' + AND banco_origem.idusuarios = contexto.idUsuario + AND COALESCE(cc.investimento, 0) = 1 + THEN 'Investimento' + WHEN cp.movimento <> 'Sangria' THEN cp.movimento - /* - * Origem e destino pertencem ao usuário: - * transferência interna. - */ - WHEN banco_origem.idusuarios = ? - AND banco_destino.idusuarios = ? + 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 'TransferenciaInterna' - /* - * Usuário é o dono do banco de origem: - * dinheiro saiu para outro usuário. - */ - WHEN banco_origem.idusuarios = ? + WHEN cp.movimento = 'Sangria' + AND banco_origem.idusuarios = contexto.idUsuario THEN 'Saida' - /* - * Usuário é o dono do banco de destino: - * dinheiro entrou vindo de outro usuário. - */ - WHEN banco_destino.idusuarios = ? + WHEN cp.movimento = 'Sangria' + AND banco_destino.idusuarios = contexto.idUsuario THEN 'Entrada' ELSE cp.movimento END AS movimento_dashboard, CASE - WHEN cp.movimento <> 'Sangria' - AND cp.movimento IN ('Entrada', 'Estorno') + WHEN cp.movimento IN ('Entrada', 'Estorno') + AND banco_origem.idusuarios = contexto.idUsuario THEN 'entrada' - WHEN cp.movimento <> 'Sangria' - AND cp.movimento = 'Saida' + WHEN cp.movimento = 'Saida' + AND banco_origem.idusuarios = contexto.idUsuario THEN 'saida' WHEN cp.movimento = 'Sangria' - AND banco_origem.idusuarios = ? - AND banco_destino.idusuarios = ? + AND banco_origem.idusuarios = contexto.idUsuario + 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' WHEN cp.movimento = 'Sangria' - AND banco_origem.idusuarios = ? + AND banco_origem.idusuarios = contexto.idUsuario THEN 'saida' WHEN cp.movimento = 'Sangria' - AND banco_destino.idusuarios = ? + AND banco_destino.idusuarios = contexto.idUsuario THEN 'entrada' ELSE 'neutro' @@ -884,12 +849,28 @@ async function buscarUltimosMovimentos(idUsuario) { CASE WHEN cp.movimento = 'Sangria' - AND banco_origem.idusuarios = ? - AND banco_destino.idusuarios = ? + AND banco_origem.idusuarios = contexto.idUsuario + AND banco_destino.idusuarios = contexto.idUsuario + AND COALESCE(banco_destino.investimento, 0) = 0 THEN 1 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 @@ -908,10 +889,14 @@ async function buscarUltimosMovimentos(idUsuario) { 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 = ? - OR banco_destino.idusuarios = ? + banco_origem.idusuarios = contexto.idUsuario + OR banco_destino.idusuarios = contexto.idUsuario ) ORDER BY @@ -921,24 +906,6 @@ async function buscarUltimosMovimentos(idUsuario) { LIMIT 10 `, [ - /* movimento_dashboard */ - idUsuario, - idUsuario, - idUsuario, - idUsuario, - - /* direcao_dashboard */ - idUsuario, - idUsuario, - idUsuario, - idUsuario, - - /* transferencia_interna */ - idUsuario, - idUsuario, - - /* WHERE */ - idUsuario, idUsuario, ] ); @@ -950,66 +917,91 @@ async function buscarUltimosMovimentos(idUsuario) { transferencia_interna: Number(item.transferencia_interna || 0) === 1, + + investimento_dashboard: + Number(item.investimento_dashboard || 0) === 1, })); } 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( ` SELECT - cp.idcentrodecustos, - COALESCE(cc.descricao, 'Sem centro de custo') AS descricao, - COALESCE(SUM(cp.valor), 0) AS valor + base_gastos.idcentrodecustos, + base_gastos.descricao, + 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 - ON banco_origem.idbancos = cp.idbancos + CASE + WHEN cp.status IN ('Pago', 'Recebido') + AND cp.databaixa IS NOT NULL + THEN cp.databaixa - LEFT JOIN bancos banco_destino - ON banco_destino.idbancos = cp.idbancos_p + ELSE COALESCE(cp.dataentrada, cp.insert_date) + END AS data_dashboard, - LEFT JOIN centrodecustos cc - ON cc.idcentrodecustos = cp.idcentrodecustos + CASE + WHEN cp.movimento = 'Saida' + AND banco_origem.idusuarios = contexto.idUsuario + AND COALESCE(cc.investimento, 0) = 0 + THEN 'saida' - WHERE cp.deleted_at IS NULL - AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) - BETWEEN ? AND ? - AND COALESCE(cc.investimento, 0) = 0 + 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' - AND ( - ( - cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? + 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 + + 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 - - ( - cp.movimento = 'Sangria' - AND banco_origem.idusuarios = ? - AND ( - banco_destino.idusuarios IS NULL - OR banco_destino.idusuarios <> ? - ) - ) - ) + WHERE DATE(base_gastos.data_dashboard) + BETWEEN ? AND ? + AND base_gastos.direcao_financeira = 'saida' GROUP BY - cp.idcentrodecustos, - COALESCE(cc.descricao, 'Sem centro de custo') + base_gastos.idcentrodecustos, + base_gastos.descricao HAVING valor > 0 @@ -1018,135 +1010,125 @@ async function buscarGraficos(idUsuario, dataInicio, dataFim) { LIMIT 8 `, [ + idUsuario, dataInicio, 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( ` SELECT - COALESCE( - SUM( - CASE - /* Entrada ou estorno normal */ - WHEN cp.movimento IN ('Entrada', 'Estorno') - AND banco_origem.idusuarios = ? - THEN cp.valor + COALESCE(SUM( + CASE + WHEN base_resumo.direcao_financeira = 'entrada' + THEN base_resumo.valor + ELSE 0 + END + ), 0) AS entradas, - /* Sangria recebida de outro usuário */ - WHEN cp.movimento = 'Sangria' - AND banco_destino.idusuarios = ? - AND banco_origem.idusuarios <> ? - THEN cp.valor + COALESCE(SUM( + CASE + WHEN base_resumo.direcao_financeira = 'saida' + THEN base_resumo.valor + ELSE 0 + END + ), 0) AS saidas, - ELSE 0 - END - ), - 0 - ) AS entradas, + COALESCE(SUM( + CASE + WHEN base_resumo.direcao_financeira = 'investimento' + THEN base_resumo.valor + ELSE 0 + END + ), 0) AS investimentos - COALESCE( - SUM( - CASE - /* Saída normal */ - WHEN cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 0 - THEN cp.valor + FROM ( + SELECT + 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 <> ? - ) - AND COALESCE(cc.investimento, 0) = 0 - THEN cp.valor + CASE + WHEN cp.status IN ('Pago', 'Recebido') + AND cp.databaixa IS NOT NULL + THEN cp.databaixa - ELSE 0 - END - ), - 0 - ) AS saidas, + ELSE COALESCE(cp.dataentrada, cp.insert_date) + END AS data_dashboard, - COALESCE( - SUM( - CASE - WHEN cp.movimento = 'Saida' - AND banco_origem.idusuarios = ? - AND COALESCE(cc.investimento, 0) = 1 - THEN cp.valor + CASE + WHEN cp.movimento IN ('Entrada', 'Estorno') + AND banco_origem.idusuarios = contexto.idUsuario + THEN 'entrada' - WHEN cp.movimento = 'Sangria' - AND banco_origem.idusuarios = ? - AND banco_destino.idusuarios = ? - AND COALESCE(banco_destino.investimento, 0) = 1 - THEN cp.valor + WHEN cp.movimento = 'Saida' + AND banco_origem.idusuarios = contexto.idUsuario + AND COALESCE(cc.investimento, 0) = 0 + THEN 'saida' - ELSE 0 - END - ), - 0 - ) AS investimentos + WHEN cp.movimento = 'Saida' + AND banco_origem.idusuarios = contexto.idUsuario + AND COALESCE(cc.investimento, 0) = 1 + THEN 'investimento' - 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 - ON banco_origem.idbancos = cp.idbancos + WHEN cp.movimento = 'Sangria' + AND banco_origem.idusuarios = contexto.idUsuario + AND banco_destino.idusuarios = contexto.idUsuario + THEN 'transferencia_interna' - LEFT JOIN bancos banco_destino - ON banco_destino.idbancos = cp.idbancos_p + WHEN cp.movimento = 'Sangria' + AND banco_origem.idusuarios = contexto.idUsuario + AND ( + banco_destino.idusuarios IS NULL + OR banco_destino.idusuarios <> contexto.idUsuario + ) + THEN 'saida' - LEFT JOIN centrodecustos cc - ON cc.idcentrodecustos = cp.idcentrodecustos + WHEN cp.movimento = 'Sangria' + 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 - AND DATE(COALESCE(cp.dataentrada, cp.insert_date)) - BETWEEN ? AND ? + ELSE 'neutro' + END AS direcao_financeira - AND ( - banco_origem.idusuarios = ? - OR banco_destino.idusuarios = ? - ) + 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, - - /* Saídas */ - idUsuario, - idUsuario, - idUsuario, - - /* Investimentos */ - idUsuario, - idUsuario, - idUsuario, - - /* Período */ dataInicio, dataFim, - - /* Usuário presente em uma das pontas */ - idUsuario, - idUsuario, ] ); diff --git a/financeiro-api/src/modules/movimentos/services/movimentos.service.js b/financeiro-api/src/modules/movimentos/services/movimentos.service.js index 37668b7..92bf051 100644 --- a/financeiro-api/src/modules/movimentos/services/movimentos.service.js +++ b/financeiro-api/src/modules/movimentos/services/movimentos.service.js @@ -193,9 +193,12 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) { const usuarioAtual = Number(idUsuario); const usuarioOrigem = Number(item.idusuario_origem); const usuarioDestino = Number(item.idusuario_destino); + const destinoInvestimento = Number(item.banco_destino_investimento || 0) === 1; let movimentoDashboard = item.movimento; let direcaoDashboard = 'neutro'; + let transferenciaInterna = false; + let investimentoDashboard = false; if ( item.movimento === 'Entrada' @@ -205,16 +208,21 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) { } else if (item.movimento === 'Saida') { direcaoDashboard = 'saida'; } else if (item.movimento === 'Sangria') { - if ( - usuarioOrigem === usuarioAtual - && usuarioDestino === usuarioAtual - ) { + const origemEhUsuario = usuarioOrigem === usuarioAtual; + const destinoEhUsuario = usuarioDestino === usuarioAtual; + + if (origemEhUsuario && destinoEhUsuario && destinoInvestimento) { + movimentoDashboard = 'Investimento'; + direcaoDashboard = 'saida'; + investimentoDashboard = true; + } else if (origemEhUsuario && destinoEhUsuario) { movimentoDashboard = 'TransferenciaInterna'; direcaoDashboard = 'transferencia_interna'; - } else if (usuarioOrigem === usuarioAtual) { + transferenciaInterna = true; + } else if (origemEhUsuario) { movimentoDashboard = 'Saida'; direcaoDashboard = 'saida'; - } else if (usuarioDestino === usuarioAtual) { + } else if (destinoEhUsuario) { movimentoDashboard = 'Entrada'; direcaoDashboard = 'entrada'; } @@ -226,14 +234,8 @@ function enriquecerMovimentoParaUsuario(item, idUsuario) { movimento_dashboard: movimentoDashboard, direcao_dashboard: direcaoDashboard, - transferencia_interna: - movimentoDashboard === 'TransferenciaInterna', - - investimento_dashboard: - item.movimento === 'Sangria' - && usuarioOrigem === usuarioAtual - && usuarioDestino === usuarioAtual - && Number(item.banco_destino_investimento || 0) === 1, + transferencia_interna: transferenciaInterna, + investimento_dashboard: investimentoDashboard, }; } @@ -351,15 +353,26 @@ async function buscarResumoMovimentos( const paramsWhere = [...base.params]; /* - * No extrato financeiro, entradas, saídas e investimentos - * pertencem ao período de realização do movimento. + * No extrato financeiro, o ideal é usar a data de baixa + * quando o movimento já foi realizado. * - * Na tabela comum, o resumo respeita o campo de data - * selecionado pelo usuário. + * Isso evita o caso clássico: + * - 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 só dataentrada */ const campoDataSql = 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); if (filtros.dataInicio) { @@ -381,94 +394,198 @@ async function buscarResumoMovimentos( SELECT COUNT(*) AS quantidade, - /* ================================================== - * ENTRADAS - * ================================================== */ - COALESCE(SUM( CASE - WHEN cp.movimento IN ('Entrada', 'Estorno') - AND b.idusuarios = ? - THEN cp.valor - - WHEN cp.movimento = 'Sangria' - AND bp.idusuarios = ? - AND ( - b.idusuarios IS NULL - OR b.idusuarios <> ? - ) - THEN cp.valor - + WHEN base_resumo.direcao_financeira = 'entrada' + THEN base_resumo.valor ELSE 0 END ), 0) AS totalEntradas, COALESCE(SUM( CASE - WHEN cp.movimento IN ('Entrada', 'Estorno') - AND b.idusuarios = ? - AND cp.status = 'Recebido' - 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 - + WHEN base_resumo.direcao_financeira = 'entrada' + AND base_resumo.status IN ('Recebido', 'Pago') + THEN base_resumo.valor ELSE 0 END ), 0) AS entradasRecebidas, COALESCE(SUM( CASE - WHEN cp.movimento IN ('Entrada', 'Estorno') - AND b.idusuarios = ? - AND cp.status = 'A receber' - 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 - + WHEN base_resumo.direcao_financeira = 'entrada' + AND base_resumo.status IN ('A receber', 'A pagar') + THEN base_resumo.valor ELSE 0 END ), 0) AS entradasPendentes, COUNT( CASE - WHEN cp.movimento IN ('Entrada', 'Estorno') - AND b.idusuarios = ? - AND cp.status = 'Recebido' + WHEN base_resumo.direcao_financeira = 'entrada' + AND base_resumo.status IN ('Recebido', 'Pago') 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 END ) AS quantidadeEntradasRecebidas, 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 WHEN cp.movimento IN ('Entrada', 'Estorno') AND b.idusuarios = ? - AND cp.status = 'A receber' - THEN 1 + THEN 'entrada' + + 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' AND bp.idusuarios = ? @@ -476,267 +593,29 @@ async function buscarResumoMovimentos( b.idusuarios IS NULL OR b.idusuarios <> ? ) - AND cp.status IN ('A receber', 'A pagar') - THEN 1 + THEN 'entrada' - ELSE NULL - END - ) AS quantidadeEntradasPendentes, + ELSE 'neutro' + END AS direcao_financeira - /* ================================================== - * 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} - ${whereSql} + ${FROM_MOVIMENTO_JOIN} + ${whereSql} + ) base_resumo `, [ - /* Entradas: total, recebido, pendente e quantidades */ - 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 */ + /* totalEstornos */ idUsuario, - /* Filtros */ + /* direcao_financeira */ + idUsuario, + idUsuario, + idUsuario, + idUsuario, idUsuario, + idUsuario, idUsuario, + idUsuario, idUsuario, + idUsuario, idUsuario, + + /* filtros */ ...paramsWhere, ] ); @@ -856,10 +735,6 @@ async function buscarResumoMovimentos( saldo, - /* - * Campos antigos neutralizados temporariamente. - * Podem ser removidos após o front ser atualizado. - */ totalSangrias: 0, totalBaixado: 0, totalAberto: 0,