Files
Condominio_SeConectai/Schemas/07-financeiro-abacatepay.md
2026-09-29 12:12:31 -03:00

4.3 KiB
Raw Permalink Blame History

Prompt 07 — Financeiro: assinaturas, período de uso e AbacatePay

Contexto

Prompts 01–06 concluídos: CRUD completo do escritório funcionando. Leia 10-tracker-progresso.md antes de começar.

Este prompt implementa o menu Cliente → Financeiro (pagar mensalidade) e a automação de bloqueio/liberação de acesso conforme pagamento, usando AbacatePay para gerar cobrança PIX.

Objetivo

Criar/consultar periodos_uso do mês corrente, gerar cobrança PIX via AbacatePay, processar o webhook de confirmação, e rodar o job diário que bloqueia empresas inadimplentes.

Especificação

1. Cliente AbacatePay

Consultar a documentação oficial da AbacatePay (https://docs.abacatepay.com) para confirmar o formato exato do endpoint de criação de cobrança PIX e do payload do webhook — não assumir o formato sem checar, a API pode ter mudado. Implementar AbacatePayClient:

  • criarCobranca(valorCentavos, descricao, identificadorExterno) → retorna {chargeId, qrCodePayload, qrCodeBase64}
  • Validação de assinatura do webhook, se a AbacatePay oferecer esse mecanismo (verificar na doc).

2. Endpoints do escritório

GET    /api/financeiro/periodo-atual
       → busca (ou cria, se não existir) o periodos_uso do mes_referencia = mês corrente;
         retorna status, valor da assinatura vigente, se já tem pagamento pendente/gerado

POST   /api/financeiro/pagamentos
       → se já existe um pagamento 'pendente' pro período atual, retorna ele (não duplica
         cobrança); senão, chama AbacatePayClient.criarCobranca com o valor da assinatura,
         grava em `pagamentos`, retorna qr_code_base64 + qr_code_payload pro frontend renderizar

GET    /api/financeiro/pagamentos/{id}
       → status atual (útil pro frontend fazer polling enquanto o QR Code está na tela)

3. Webhook

POST   /api/master/webhooks/abacatepay
       → SEM autenticação de master/funcionário (é a AbacatePay chamando) — validar por
         assinatura/segredo do webhook, conforme a documentação da AbacatePay
       → identifica o pagamento pelo abacatepay_charge_id, marca status='pago', pago_em=now()
       → marca periodos_uso.status='pago', data_liberacao=now()
       → marca empresas.status='ativa' (caso estivesse 'bloqueada')
       → idempotente: se o webhook chegar duplicado (mesma cobrança já processada), não fazer
         nada de errado, só retornar 200 de novo

4. Job de bloqueio diário

BloqueioJob, rodando uma vez por dia (implementar com um ScheduledExecutorService simples dentro da própria aplicação Java — não precisa de cron externo nesta fase):

  1. Para cada empresa com status='ativa': busca (ou cria) o periodos_uso do mês corrente.
  2. Se hoje > dia_vencimento da assinatura E periodos_uso.status != 'pago': marca periodos_uso.status='bloqueado', data_bloqueio=now(), empresas.status='bloqueada'.
  3. Logar quantas empresas foram bloqueadas na execução.

5. Bloqueio de acesso

No middleware exigirFuncionario (Prompt 04), adicionar a checagem: se empresas.status='bloqueada', retornar 403 com corpo {"erro": "pendencia_financeira", "mensagem": "..."} em vez de deixar passar — mas sempre permitir o próprio GET /api/financeiro/periodo-atual e POST /api/financeiro/pagamentos mesmo bloqueado, senão o escritório não consegue nem pagar pra desbloquear.

Critérios de aceite

  • POST /api/financeiro/pagamentos gera de fato uma cobrança na AbacatePay (testar em ambiente sandbox, se a AbacatePay oferecer) e retorna QR Code válido.
  • Chamar POST /api/financeiro/pagamentos duas vezes seguidas não cria duas cobranças, retorna a mesma pendente.
  • Simular o webhook (chamada manual com um payload de teste) marca o período como pago e desbloqueia a empresa.
  • Rodar o webhook duas vezes com o mesmo charge_id não causa erro nem duplica nada.
  • BloqueioJob rodado manualmente (chamar o método direto, sem esperar o schedule) bloqueia corretamente uma empresa de teste com vencimento no passado e sem pagamento.
  • Empresa bloqueada consegue logar e acessar só /api/financeiro/**; qualquer outro endpoint retorna 403 com o erro pendencia_financeira.

Ao concluir

Atualizar 10-tracker-progresso.md: Prompt 07 concluído, data, resumo. Confirmar Prompts 01–06 seguem marcados.