FJFrigo · Financeiro · menu388 — Posição de Tesouraria

Validações da Posição de Tesouraria

Painel de BI do financeiro para abrir de manhã: saldo das contas Banco, movimento do dia, o que vence e o que está vencido. O que cada número é, de onde sai, o que muda o resultado e como conferir.

Tela: Posição de Tesouraria (388)Tipo: Desenho novo, sem legadoMotor: o do Fluxo de Caixa Projetado (382)Gravação: só a escolha das contas do painel
A

O que a tela mostra

Para quem atende

Painel que o financeiro abre de manhã: quanto há nas contas bancárias agora, o que entrou e saiu no dia, o que vence hoje e na semana, o menor saldo dos próximos 30 dias e o que está vencido. Desenho novo, sem legado: não há tela no .prg para comparar. Só lê; não grava nada (a única gravação é a escolha das contas do painel, seção D).

É o motor do 382. O saldo das contas, a projeção de 30 dias, os títulos que vencem e a conversão de moeda vêm do FluxoCaixaService (Fluxo de Caixa Projetado, 31995/382). Quando um número do 388 não bate com o 382, quase sempre a diferença é o conjunto de contas: o 388 só conta contas do tipo Banco.

Menu: 3-Relatórios › 8-Indicadores › 8-Posição de Tesouraria (388). Sem linha em opcao_sistema (idOpcao: null); a permissão do menu é a da 31995.

Bloco da telaO que éOrigem
Saldo agoraSoma do saldo de hoje das contas do painel, e o fôlego em dias.Saldo do 382/3172 (seção C1)
Movimento do diaAbertura, recebimentos, pagamentos, transferências, outros e fechamento (gráfico em cascata).financeiro_lancamento_banco + financeiro_baixas (C2)
Vence hojeA receber e a pagar em aberto com vencimento hoje; os 10 maiores de cada lado.Projeção do 382, dia 0 (C4)
Próximos 7 dias / Saldo projetado 30 diasEntradas, saídas e saldo acumulado dia a dia, só com títulos.Projeção do 382 (C4)
Menor saldo em 30 diasPonto mais baixo da projeção, o dia, e o primeiro dia negativo.Projeção do 382 (C4)
Vencidos em abertoVencidos nos últimos 365 dias e os 10 maiores emitentes de cada lado; RJ à parte.financeiro_emissao (C5)
Saldo por banco / por moeda / grade das contasQuebras do saldo das contas do painel.Contas do painel (D)
E-mail das 7hSituação do envio e botão Enviar agora.E-mail (E)
B

Opções, filtros e endpoints

Defaults

A janela abre direto, sem painel de filtros. Tudo é recalculado ao abrir; a apuração fica em memória por 5 minutos (chave: banco + moeda + dia + contas). Atualizar refaz na hora (?atualizar=true).

OpçãoDefaultEfeito
Hoje / Ontem (dia)HojeDia do movimento. O saldo "agora" é sempre o de hoje; com Ontem, a abertura e o fechamento são deslocados (abertura = saldo de hoje − movimento do dia em diante − líquido do dia).
Converter para (idMoeda)Moeda local da filial da sessãoTudo numa moeda só, pela cotação mais recente até hoje de cada moeda (moeda_valores.valor). Moeda escolhida sem cotação: erro 400 "A moeda X não tem cotação até hoje".
Contas do painel (idsContas)Guardadas; senão todas as contas Banco ativasSeção D. "Só ver" manda os ids sem guardar.
EndpointCorpoPara quê
POST /lancamento/tesouraria/posicao?atualizar={idMoeda, dia, idsContas}A posição inteira
POST /lancamento/tesouraria/contas{idsContas}Guarda as contas do painel (vale para todos)
GET /lancamento/tesouraria/email/situacao—Ligado, destinatários, servidor, hora, último envio
POST /lancamento/tesouraria/email/enviar—"Enviar agora"
C

De onde vem cada número

SQL e filtros

Todos os valores são convertidos para a moeda escolhida. Título com cambio_fechado = 'T' usa o câmbio gravado no título (valor_cambio); moeda sem cotação usa o câmbio gravado e gera aviso.

Regra

C1. Saldo da conta (hoje)

OrigemSoma, por conta, dos lançamentos bancários e das baixas com data anterior a amanhã (data futura só entra quando chegar). Sinal: lançamento de operação E em tipo_lancamento_bancario soma, o resto subtrai; baixa de título R soma, de P subtrai.

Filtrosexcluido <> 'T' nos dois lados; conta ativa (data_desativacao IS NULL OR > hoje); só entra conta com ao menos um lançamento ou baixa (a consulta é um JOIN).

TipoSó conta_bancaria.tipo_conta diferente de '1' aparece como "Banco" (o valor '1' é Caixa/adiantamento/empréstimo). Em central só existem os tipos 1 e 2.

SELECT x.idconta_bancaria, SUM(x.valor) saldo FROM (
  SELECT flb.idconta_bancaria, IF(tlb.operacao='E', flb.valor, -flb.valor) valor
    FROM financeiro_lancamento_banco flb
    LEFT JOIN tipo_lancamento_bancario tlb ON tlb.id = flb.idtipo_lancamento_bancario
   WHERE flb.excluido <> 'T' AND flb.data < CURDATE() + INTERVAL 1 DAY AND flb.idconta_bancaria = :conta
  UNION ALL
  SELECT fb.idconta_bancaria, IF(fe.tipo_emissao='R', fb.valor, -fb.valor)
    FROM financeiro_baixas fb
    LEFT JOIN financeiro_emissao fe ON fe.id = fb.idfinanceiro_emissao
   WHERE fb.excluido <> 'T' AND fb.data_baixa < CURDATE() + INTERVAL 1 DAY AND fb.idconta_bancaria = :conta) x
GROUP BY 1

CacheO saldo das contas tem um cache próprio de 5 minutos no 382 (por banco + dia), que o botão Atualizar do painel não limpa (ele só refaz a apuração do painel). Depois de um lançamento ou baixa novos, o saldo pode levar até 5 minutos para mudar; reportar "saldo desatualizado" só depois disso. Guardar as contas do painel limpa só o cache do painel.

Saldo
Regra

C2. Movimento do dia (abertura, recebido, pago, transferências, outros, fechamento)

OrigemUma consulta de dia até hoje sobre as mesmas duas tabelas, por conta. Categorias: R baixa de título a receber; P baixa de título a pagar; TE lançamento tipo 114 (transferência entrada); TS tipo 113 (saída); LE/LS demais lançamentos (operação E / outra).

Regra chumbadaOs tipos 113 e 114 são fixos no legado (menu224.prg, linhas 1111, 1222, 1238), iguais em central e fjfrigo_concepcion. idtransferencia vem preenchido em todo lançamento: não serve para separar.

Fechamentosaldo hoje − líquido do que veio depois do dia. Abertura = fechamento − líquido do dia. O líquido do dia é R − P + TE − TS + LE − LS.

GarantiaAbertura + líquido do dia = fechamento ao centavo (conferido em central, 02/10/2026, 205 contas sugeridas).

TransferênciasDesde que o painel só conta contas Banco, as transferências não fecham em zero: a outra ponta costuma ser um caixa, que está fora.

Movimento
Regra

C3. Saldo por banco, por moeda e grade das contas

Banco = conta_bancaria.banco (ou o grupo grupo_conta_bancaria.descricao quando a conta não tem banco). Por moeda: soma na moeda da conta e convertida. Negativos em vermelho. Só as contas marcadas no painel entram nos totais; a grade lista todas as contas Banco (as fora do painel aparecem sem marca).

Saldo
Regra

C4. Agenda, vence hoje, 7 dias, menor saldo, fôlego

ProjeçãoFluxoCaixaService.projetar com 30 dias, agrupamento DIA, só títulos (sem pedidos nem ordens de compra, sem filtros), saldo inicial = soma das contas do painel. Janela: hoje até hoje+29.

Título em abertofe.excluido <> 'T' AND tipo_emissao IN ('P','R'), a receber descontado fora (descontado = 'T'), pendente = valor_parcela − (baixas − acréscimo − juros + desconto + devolução + retenção) > 0,004. Título em recuperação judicial (recuperacao_judicial = 1) a pagar vai para a coluna pagar RJ, fora do saldo projetado.

Fôlego (dias)Só com saldo inicial > 0 e total a pagar > 0: saldo inicial ÷ (total a pagar dos 30 dias ÷ 30), truncado. Sem as duas condições, a tela não mostra.

Menor saldoMínimo do saldo acumulado (inclui o saldo inicial, no dia de hoje) e o dia; primeiroNegativo = primeiro dia com saldo acumulado < 0.

Vence hojeOs totais são os do dia 0 da agenda; a lista é FluxoCaixaService.titulos de hoje, ordenada pelo valor convertido, 10 maiores (RJ fica fora da lista).

Não entramTítulos já vencidos (estão em "Vencidos") e títulos de pedido/ordem previstos. Por isso o saldo projetado é otimista quando há muito atrasado a receber/pagar.

Agenda
Regra

C5. Vencidos em aberto

JanelaVencimento de hoje − 365 dias até ontem (data_vencimento >= desde AND < hoje). O que vence hoje não é vencido.

AgrupamentoUma consulta agrupada por emitente + tipo + RJ + moeda + câmbio fechado; os 10 maiores de cada lado vêm com o nome (razao_social ou nome_fantasia), a quantidade de títulos e o vencimento mais antigo. Sem emitente aparece "(sem emitente)".

RJA pagar em RJ entra só no total "pagar RJ"; não aparece na lista dos maiores. A receber não separa RJ.

Vencidos
Regra

C6. Cotações e avisos de conversão

A linha "Cotações usadas" mostra cada moeda e o dia da cotação. Avisos possíveis: "Moeda X sem cotação até hoje: usado o câmbio gravado no documento."; "A cotação de X usada na conversão é de dd/mm/aaaa (a última lançada)." (cotação com mais de 7 dias).

Moeda
D

Contas do painel

system_config

A escolha das contas é a única coisa que a tela grava.

Config.

PAINEL_TESOURARIA_CONTAS (system_config, valor_blob)

O que éLista de ids de conta separados por vírgula, em valor_blob (não cabe nos 255 de valor_string). Sem coluna nova; a chave não aparece na Config. Globais, é escolhida na janela.

Gravação"Guardar para o painel" (com confirmação) faz UPDATE system_config SET valor_blob = ? WHERE chave = ? e, se nenhuma linha mudou, INSERT (a tabela não tem chave única em todo tenant). Zera o cache do banco. Vale para todos os usuários e para o e-mail.

Origem (campo origemContas)TELA = a janela mandou ids ("Só ver"); PAINEL = escolha guardada; BANCOS = ninguém guardou, entram todas as contas Banco ativas.

InterseçãoOs ids escolhidos são cruzados com as contas Banco existentes (retainAll): conta desativada, sem movimento ou de tipo Caixa guardada antes some sem aviso.

SELECT chave, CONVERT(valor_blob USING latin1) FROM system_config WHERE chave = 'PAINEL_TESOURARIA_CONTAS';
Contas
Regra

Só contas do tipo Banco (decisão do usuário, 03/10/2026)

Caixas e contas de adiantamento/empréstimo (tipo_conta = '1') saem da lista e do saldo. A resposta caiu de 1.529 para 278 contas em central. O 38J usa o mesmo critério para a dívida líquida.

Contas
Aviso

"Nenhuma conta no painel: escolha as contas em Contas do painel."

Aparece quando a interseção fica vazia (nenhuma conta Banco no banco, ou todas as guardadas deixaram de existir). Saldo e agenda saem zerados.

E

E-mail das 7h

RotinaTesouraria

Resumo diário por e-mail, no desenho do 381 (Painel de Faturamento). Ligado por banco, desligado por padrão.

Chave / propriedadeOndeEfeito
PAINEL_TESOURARIAConfig. Globais, grupo financeiro (liga/desliga, padrão 0)Liga a rotina automática do banco. O botão "Enviar agora" funciona mesmo desligado, se houver destinatário.
PAINEL_TESOURARIA_EMAILSConfig. Globais, grupo financeiroDestinatários separados por vírgula, ponto-e-vírgula ou espaço; só entram textos com @.
PAINEL_TESOURARIA_ULTIMO_ENVIOSomente leituraaaaa-mm-dd hh:mm|OK ou ERRO|destinatários|mensagem, até 255 caracteres. Só um OK conta como enviado: ERRO não impede nova tentativa no mesmo dia.
app.painel-tesouraria.hora-emailapplication.yml; padrão = app.painel-faturamento.hora-email (7)Hora cheia (0-23) em que a rotina age.
app.painel-tesouraria.automaticoapplication.yml (padrão true)Liga o agendador do backend.
app.painel-faturamento.bases / remetenteapplication.ymlBancos a visitar (somados aos pools já abertos) e remetente.
Regra

Como a rotina decide enviar

CadênciaUm relógio roda a cada 15 minutos (primeira vez 3 min depois de subir). Só age quando a hora do relógio é igual a hora-email. Para cada banco aberto/configurado: "ligado" e "ainda não enviado hoje" (último envio OK com a data de hoje) → envia.

ConteúdoA posição é recalculada com atualizar = true, dia ONTEM (às 7h o dia de hoje quase não tem movimento), moeda local, contas do painel. Usuário fictício id 0 e a menor filial da tabela filial (MIN(id_filial)); o nome da empresa vem dessa filial. O usuário 0 não passa pelo alcance de filiais (FluxoCaixaService.alcance devolve nulo): o e-mail é da empresa inteira, de propósito — vai para a diretoria configurada em system_config, não para um usuário.

ServidorSMTP da NF-e da filial 1 (PainelFaturamento.correioDaFilial); sem ele, o spring.mail. Sem nenhum: não envia, grava ERRO "sem servidor de e-mail (filial 1, aba NF-e)".

AssuntoTesouraria de dd/mm/aaaa - <empresa>.

Rotina
Trava

"Cadastre os e-mails do resumo na Config. Globais (PAINEL_TESOURARIA_EMAILS) antes de enviar."

QuandoEnviar agora sem destinatário válido. Sem servidor de e-mail o botão devolve a situação com o ERRO gravado em ULTIMO_ENVIO, sem essa mensagem.

Enviar agora
F

Regras e travas

Acesso e erros
Regra

Permissão

No front, o menu segue a permissão 31995 (a mesma do 382). No backend os endpoints não conferem essa permissão: qualquer usuário logado (JWT, allowlist /lancamento/*) consegue chamar /posicao, /contas (que grava) e /email/enviar. Para o QA: testar o menu escondido, mas saber que a API está aberta ao usuário logado.

Segurança
Regra

Alcance de filiais

Desde 04/10/2026 o painel só mostra as filiais do usuário (FiliaisDoUsuario: usuario_filial; sem linha, a filial do cadastro; sem ela, a da sessão): contas (pela conta_bancaria.idfilial), agenda, vence hoje e vencidos (pela financeiro_emissao.idfilial). Antes somava a empresa inteira para qualquer sessão. Quem alcança todas as filiais vê o mesmo de antes. O cache da posição leva o alcance na chave; o cache das contas do 382 guarda a base inteira e o alcance recorta depois dele. Exceção: o e-mail das 7h (usuário 0) segue com a empresa inteira.

Segurança
Trava

Erros esperados

"A moeda X não tem cotação até hoje: não há como converter para ela." (400). "Escolha a moeda (a filial está sem moeda local).". "Vence hoje: ..." vira aviso (a lista de vence hoje falhou, o resto sai). Apuração lenta: 12,5 s na primeira vez do dia em central (saldo de todas as contas), 0,2 s do cache.

400
G

Casos de teste sugeridos

QA

Use um banco com movimento recente. Para conferir no banco, troque :conta e as datas.

Teste

T1. Abertura + movimento = fechamento

PassosAbrir o painel (Hoje). Ver a cascata e, na grade das contas, escolher uma conta com movimento.

EsperadoPara cada conta e para o total: abertura + recebido − pago + transferido entrada − saída + outras entradas − outras saídas = fechamento, ao centavo. Fechamento do dia = saldo agora quando o dia é hoje.

ConferirRodar a consulta C1 com data < amanhã (saldo agora) e data < hoje (abertura de hoje).

Teste

T2. Hoje × Ontem

PassosAlternar Hoje/Ontem.

EsperadoSaldo agora não muda. Fechamento de ontem = abertura de hoje (quando não há lançamento com data futura). O fechamento de ontem não inclui movimento de hoje.

Teste

T3. Só contas Banco

PassosComparar o saldo agora com o do 382 usando todas as contas, e com o do 3172.

EsperadoO 388 é menor/igual conforme os caixas. A grade não lista conta com tipo_conta = '1'.

Conferir

SELECT cb.tipo_conta, COUNT(*) FROM conta_bancaria cb GROUP BY 1;

Teste

T4. Guardar contas

PassosDesmarcar uma conta, "Guardar para o painel", confirmar. Entrar com outro usuário.

EsperadoO outro usuário vê a mesma escolha (origem PAINEL). A linha de system_config existe com valor_blob preenchido. "Só ver" não grava.

Teste

T5. Vence hoje e vencidos

PassosAbrir "Vence hoje"; comparar com o 382 do mesmo dia. Conferir o maior vencido por emitente.

EsperadoTotal a receber/pagar de hoje = dia 0 da agenda; lista = 10 maiores. Vencidos = pendente de títulos com vencimento entre hoje−365 e ontem; RJ só no total "pagar RJ".

Conferir

SELECT fe.tipo_emissao, COUNT(*), SUM(fe.valor_parcela - IFNULL((SELECT SUM(b.valor)-SUM(b.valor_acrescimo)-SUM(b.valor_juros)+SUM(b.valor_desconto)+SUM(b.valor_devolucao)+SUM(b.valor_retencao)
  FROM financeiro_baixas b WHERE b.idfinanceiro_emissao = fe.id AND b.excluido <> 'T'), 0)) pend
FROM financeiro_emissao fe
WHERE fe.excluido <> 'T' AND fe.tipo_emissao IN ('P','R') AND NOT (fe.tipo_emissao='R' AND fe.descontado='T')
  AND fe.data_vencimento >= CURDATE() - INTERVAL 365 DAY AND fe.data_vencimento < CURDATE()
GROUP BY 1;

Teste

T6. Outra moeda

PassosConverter para uma moeda estrangeira com cotação, depois para uma sem cotação.

EsperadoValores = valor local ÷ cotação mais recente. Linha de cotações usadas preenchida. Sem cotação: mensagem 400 e nenhuma tela quebrada.

Teste

T7. E-mail

PassosConfig. Globais: PAINEL_TESOURARIA_EMAILS com um e-mail seu; botão "Enviar agora".

EsperadoE-mail "Tesouraria de dd/mm/aaaa - empresa" com o movimento de ontem. PAINEL_TESOURARIA_ULTIMO_ENVIO com OK. Envio real ainda não foi testado (histórico 390). Para a rotina: ligar PAINEL_TESOURARIA = 1 e esperar a hora; segundo envio no mesmo dia não ocorre.

H

Limitações e pendências

Histórico 390
Aviso

Status

PARCIAL em docs/status-porte.csv (03/10/2026): falta teste na tela real (os endpoints são novos: o backend precisa reiniciar) e o envio real do e-mail.

Aviso

O que a conferência já mostrou

Em central, movimento de 02/10/2026, 205 contas sugeridas (antes do filtro por Banco): saldo 83.621.237,15; recebido 1.251.365,08; pago 3.511.365,71; fecha ao centavo. Depois do filtro por Banco (278 contas): saldo 2.724.646,05; a projeção fica negativa a partir de 07/10 (mínimo −2,32 mi em 15/10). Conta 100576 (Santander Iporã) batida com SQL independente. Dados de homologação: caixas e contas de empréstimo davam saldos sem sentido (+245 mi e −227 mi) — razão da escolha guardada.

Aviso

Pontos a saber

O JSON da posição leva todas as contas Banco para a escolha (~760 KB quando eram 1.529 contas). Se pesar, separar a lista de escolha em outro endpoint.

Limites de crédito da conta (conta_bancaria_credito, só no Paraguai) ficaram de fora: candidato a "crédito disponível".

Conta Banco sem nenhum lançamento/baixa não aparece (o saldo é um JOIN com as movimentações).

O saldo não considera lançamento com data futura; é uma regra do 382/3172, não do 388.

A projeção ignora vencidos e pedidos/ordens; o "menor saldo" é uma projeção só de títulos.

Nada bate com essa busca. Tente um trecho menor, ou limpe o filtro.