_evo-output/planning-artifacts/integracao-api-titulos/implementation-plan.md
EVO Plan: Integracao de Nova Fonte de Titulos via API
LEGACY
MD
EVO Plan: Integracao de Nova Fonte de Titulos via API
Contexto
Objetivo: incorporar uma nova fonte de titulos de clientes em /var/www/html/cobranca, com reflexo nas areas atuais do sistema de cobranca, mantendo o comportamento funcional da fonte atual baseada em SQL Server + MySQL.
Nova necessidade:
- consumir titulos vindos de uma API externa
- exibir esses titulos junto com os dados atuais
- refletir a nova fonte nos indicadores e grids existentes
- classificar cada titulo como
Travessia ou Bralar
- implantar primeiro em ambiente separado de homologacao
Confirmacoes de regra recebidas
- As consultas atuais ao SQL Server nao devem ser alteradas sem confirmacao explicita.
- A regra atual com
SuspenderFaturamento = 0 deve permanecer intacta.
- A API nova existe para trazer os titulos suspensos que hoje nao aparecem no ERP.
- Todo titulo vindo da API Chronos/Planeta Serv deve ser classificado como
Travessia.
- Todo titulo vindo das fontes atuais do sistema permanece classificado como
Bralar.
- Um cliente possui varios titulos; em indicadores os valores devem ser somados, e nos grids todos os titulos devem ser listados.
- O filtro de pertencimento da carteira pode usar
cpf_cnpj, mas a linha de exibicao de titulo continua granular por proposta.
- Na primeira entrega, titulos da API nova devem ser enquadrados apenas em:
quebras
renegociacoes
30 dias
advogado da API nova fica fora da primeira entrega.
Escopo funcional confirmado
A nova fonte deve impactar:
Diagnostico brownfield
O sistema atual nao possui uma camada unificada de "titulos".
Cada endpoint implementa sua propria logica:
- busca carteira no MySQL
- consulta SQL Server com regras especificas
- cruza com
cobranca_30dias_registros
- remove ou soma registros conforme regras locais
Conclusao:
- integrar diretamente a API em cada endpoint vai duplicar regra e aumentar risco
- a melhor abordagem e criar uma camada de consolidacao interna para "titulos normalizados"
Decisao arquitetural
Criar uma camada interna de agregacao com contrato unico para titulos.
Proposta
Introduzir um modulo novo, por exemplo:
src/lib/titulos_normalizer.php
src/lib/titulos_api_client.php
src/lib/titulos_repository.php
src/lib/titulos_service.php
Responsabilidades
titulos_api_client.php
- chamar a nova API
- autenticar com token
- tratar timeout, retry controlado e falhas
- devolver payload bruto validado
titulos_normalizer.php
- converter ERP e API nova para um mesmo shape interno
- padronizar:
- proposta
- cpf_cnpj
- cliente
- residencial
- valor
- data_vencimento
- data_pagamento
- em_advogado
- tipo_recebimento
- origem_sistema
- marca_empresa (
Travessia ou Bralar)
titulos_repository.php
- encapsular a consulta SQL Server atual
- reduzir SQL duplicado
titulos_service.php
- unir fontes
- aplicar regras de deduplicacao
- aplicar filtros por cobrador/carteira
- devolver colecoes prontas para grids e indicadores
Contrato interno proposto
[
'titulo_id' => 'string-estavel',
'proposta' => 'string',
'cpf_cnpj' => 'somente-digitos',
'cliente' => 'string',
'residencial' => 'string|null',
'valor' => 0.0,
'data_vencimento' => 'YYYY-MM-DD|null',
'data_pagamento' => 'YYYY-MM-DD|null',
'dias_atraso' => 0,
'em_advogado' => false,
'tipo_recebimento' => 'renegociacao|dias30|advogado|quebra|outro',
'origem_sistema' => 'erp|api_externa|mysql_auxiliar',
'marca_empresa' => 'Bralar|Travessia',
'cobrador_usuario_id' => 0,
]
Regra de ouro da implementacao
Nao alterar primeiro os grids.
Ordem correta:
- criar contrato unico
- criar consolidacao unica
- migrar endpoints existentes para usar essa consolidacao
- so depois ajustar interface com coluna
Travessia/Bralar
Impactos tecnicos mapeados
1. Impacto de backend
- alto
- motivo: hoje os endpoints repetem logicas diferentes
2. Impacto de regra de negocio
- alto
- motivo: sera necessario decidir precedencia entre ERP, MySQL e API nova
3. Impacto de UX
- medio
- motivo: todos os grids precisarao mostrar
Travessia ou Bralar
4. Impacto operacional
- alto
- motivo: sistema em producao e qualquer divergencia em soma/quantidade gera ruído operacional
Riscos principais
- duplicidade de titulos entre ERP e API externa
- divergencia de identificadores entre proposta/cpf
- performance ruim se a API for chamada sincronicamente em cada request
- dependencia externa instavel afetando dashboard em producao
- contagens inconsistentes entre cards e grids
Decisoes obrigatorias antes de codar
- A categoria
30 dias da API nova sera definida exclusivamente pelo vinculo em cobranca_30dias_registros?
- Para
renegociacao, a heuristica por texto RENEGOC no campo descritivo da parcela e suficiente para a primeira entrega?
- Em caso de timeout ou indisponibilidade da API, o dashboard deve:
- falhar o bloco inteiro
- ou seguir exibindo apenas ERP/MySQL
Estrategia recomendada de rollout
Fase 0. Homologacao
- criar ambiente separado completo
- apontar para:
- banco MySQL de homologacao
- token de homologacao da API nova
- dominio separado
Fase 1. Leitura espelho
- integrar a API nova sem exibir ao usuario final
- registrar logs comparativos
- validar volume, formato e deduplicacao
Fase 2. Backend consolidado
- refatorar endpoints para usar
titulos_service
- manter a UI igual
- comparar totais ERP-only x consolidado
Fase 3. UI e marca de empresa
- adicionar coluna/badge
Travessia ou Bralar
- validar em todos os grids
Fase 4. Publicacao controlada
- liberar para usuarios de homologacao
- validar com dados reais
- publicar em producao
Critérios de aceite
- totais dos cards fecham com os grids
- nenhum titulo duplicado
- nenhum titulo atual desaparece
- a origem nova aparece com
Travessia/Bralar
- ambiente de homologacao replica o comportamento funcional do ambiente atual
- rollback e simples: desligar feature flag e voltar ao ERP-only
Dados tecnicos confirmados da API
- Producao:
https://api.chronosapp.com.br
- Homologacao:
https://api-qa.chronosapp.com.br
- Swagger:
https://api.chronosapp.com.br/swagger/
- OAuth2 Client Credentials
- Token URL identificada no Swagger:
https://api.chronosapp.com.br/v1/oauth/access-token
Endpoints candidatos:
GET /v1/credits
GET /v1/credits/{id}
GET /v1/credits/{id}/parcels
GET /v1/credits/parcels
Validacao pratica executada em 2026-04-09
Autenticacao validada com sucesso:
POST https://api.chronosapp.com.br/v1/oauth/access-token
- fluxo
client_credentials
- retorno confirmado com
access_token, token_type=bearer e expires_in
Endpoint GET /v1/credits validado com retorno real:
- responde paginado em objeto com:
- campos de credito confirmados em producao:
id
principalDebtorName
principalDebtorDocument
contractNumber
status
paymentStatus
parcelQuantity
parcelPaidQuantity
parcelOverdueQuantity
parcelNotPaidQuantity
overdueTotalAmount
paymentTotalAmount
nextDueDate
Endpoint GET /v1/credits/{id}/parcels validado com retorno real:
- responde como lista simples, nao como objeto paginado
- campos de parcela confirmados em producao:
id
creditId
key
number
numberDescription
status
statusName
amount
currentAmount
currentTotalAmount
dueDate
paymentDate
paymentType
paymentAmount
paymentTotalAmount
parcelTypeName
negotiationId
negotiationParcelId
negotiationStatus
negotiationStatusName
obs
Endpoint GET /v1/credits/parcels testado e nao deve ser usado:
- em teste real retornou erro de parametro
id nulo
- para a implementacao, o endpoint seguro e
GET /v1/credits/{id}/parcels
Campos relevantes identificados no Swagger:
- Em
credits:
Id
PrincipalDebtorDocument
PrincipalDebtorName
ContractNumber
UnityName
EnterpriseName
Status
PaymentStatus
NextDueDate
CurrentTotalAmount
- Em
parcels:
Number
CurrentAmount
PaymentDate
DueDate
ParcelTypeName
NumberDescription
Status
Regras inferidas a partir dos retornos reais
Estados de parcela observados em amostra real:
Mapeamento recomendado para a primeira entrega:
quebras:
- usar parcelas com
status = OVERDUE
- valor da linha pela API:
currentTotalAmount
- vencimento da linha:
dueDate
- pagos candidatos a
30 dias ou renegociacoes:
- usar parcelas com
status = PAID
- data de recebimento:
paymentDate
- valor recebido:
paymentTotalAmount
- parcelas com
status = CREATED:
- nao sao pagas
- nao sao vencidas em atraso
- representam agenda futura/em aberto ainda nao vencida
Regra RENEGOC validada ate o momento
O melhor candidato de campo continua sendo numberDescription, por aderencia ao criterio funcional informado pelo negocio.
Entretanto, na amostra real testada em producao:
- nao apareceu nenhum
RENEGOC em:
numberDescription
obs
paymentType
parcelTypeName
statusReason
negotiationStatusName
- tambem nao apareceram
negotiationId ou negotiationStatusName preenchidos nos 20 primeiros creditos analisados
Decisao recomendada:
- implementar a heuristica primaria em
numberDescription
- manter fallback tecnico de auditoria em
obs e negotiationStatusName
- registrar log quando uma parcela entrar em renegociacao por regra alternativa
- validar em homologacao com pelo menos um contrato conhecido e renegociado antes de publicar
Decisao de enquadramento da primeira entrega
Quebras
- API nova entra com titulos em aberto/vencidos.
- O botao de registrar 30 dias continua gravando no MySQL.
- Um titulo da API nova marcado no MySQL deve passar a obedecer a mesma regra dos demais titulos.
30 dias
- O criterio continua sendo o MySQL
cobranca_30dias_registros.
- Se o titulo/cliente Travessia estiver registrado ali e pago, ele aparece em
30 dias.
Renegociacoes
- Se nao estiver classificado como
30 dias, e a descricao da parcela da API contiver RENEGOC, ele entra em renegociacoes.
Advogado