Skip to content

v0.74.0

Choose a tag to compare

@adrianfiio adrianfiio released this 02 Aug 12:23

AFService Map v0.74.0 — Módulo financeiro

Backup/ponto de rollback desta rodada: tag v0.73.1. Trabalho feito
diretamente por mim (Claude), a pedido do usuário ("vamos criar 1 base
de financeiro, para controle de pagamento etc dos meus clientes").
Com migration (apps.billing.0001_initial, roda automaticamente no
apply).

Contexto

O sistema não tinha nenhum controle de pagamento — os únicos dados
vindos do IXCSoft ficam soltos em raw_data (JSON), sem estrutura de
fatura, mensalidade ou pagamento em lugar nenhum. Também não existia uma
página de detalhe por cliente — o único lugar onde um cliente aparecia
era como popup no mapa. Como a plataforma atende empresa com ou sem
ERP, o cadastro financeiro do cliente não podia depender do
AccessPoint (que só existe quando há sincronização) — é um cadastro
próprio, com vínculo opcional.

Decisões confirmadas com o usuário antes de implementar

Perguntei diretamente antes de desenhar o banco, pra não ter que
redesenhar depois:

  1. Controle manual agora, com o schema pronto pra gateway depois
    (Efí, Inter, Mercado Pago — escolhido por empresa no futuro). Os
    campos existem, mas nenhuma integração real entrou nesta rodada.
  2. Página de detalhe do cliente nova, em vez de um botão no popup do
    mapa.
  3. Mensalidade recorrente automática via Celery Beat, em vez de
    lançamento manual mês a mês.
  4. Mesmo acesso EDIT de hoje — sem controle de permissão novo.

O que entrou

Cadastro de cliente (apps.billing.Customer)

Nome, documento, e-mail, telefone, endereço, situação
(ativo/inativo/suspenso), mensalidade e dia de vencimento (opcionais —
sem eles, o cliente só recebe lançamento manual), e um vínculo opcional
com um AccessPoint já existente (pra quem já usa mapa/ERP).

Mensalidade recorrente automática

apps.billing.tasks.generate_monthly_invoices, agendada de hora em hora
no CELERY_BEAT_SCHEDULE (config/settings.py): para cada cliente com
mensalidade ativa, cria a fatura (Invoice) do mês corrente se ainda
não existir. Idempotente de verdade — protegida por
UniqueConstraint(customer, reference_month), então rodar de novo (ou
com mais frequência) nunca duplica fatura. O dia de vencimento é
ajustado automaticamente pra sempre existir no mês (dia 31 cadastrado
vira o último dia de fevereiro, por exemplo).

apps.billing.tasks.mark_overdue_invoices, mesmo agendamento: fatura
pendente com vencimento no passado vira "Atrasada" sozinha.

Registro de pagamento

Cada fatura aceita um ou mais pagamentos (Payment) — dinheiro, PIX,
transferência, cartão ou outro, com observação e quem registrou. A
fatura só fecha como "Paga" quando a soma dos pagamentos atinge o valor
devido; pagamento parcial fica registrado sem fechar a fatura.

Página de cliente nova

  • Lista (/painel/financeiro/): clientes da empresa, busca por
    nome, resumo (faturas atrasadas, pendentes, pagas no mês).
  • Detalhe (/painel/financeiro/<id>/): dados do cliente, histórico
    completo de faturas com status, e um formulário de pagamento pra cada
    fatura ainda em aberto.
  • Menu lateral ganhou o item "Financeiro" (mesma regra de acesso de
    "Alertas": some para empresa em modo projetista).

Reservado para o futuro, não integrado

Invoice.gateway_provider (nenhum/Efí/Inter/Mercado Pago) e
Invoice.gateway_charge_id existem no schema desde já, mas nenhuma
chamada de API, webhook ou geração de boleto/PIX cobrável de verdade
entrou nesta versão — só evita ter que alterar o banco quando isso for
implementado.

O que ficou de fora, de propósito

  • Integração real de gateway de pagamento.
  • Botão de financeiro no popup do mapa (o usuário escolheu a página de
    detalhe nova).
  • Visão financeira consolidada entre empresas na "Visão da plataforma"
    — fica igual às outras seções, só por empresa.

Verificação feita

  • clamp_due_day/due_date_for (o cálculo que garante um dia de
    vencimento sempre válido no mês, incluindo fevereiro e meses de 30
    dias) são funções puras, sem banco — executei de verdade via
    script Python direto nesta sessão (mesmo método já usado com
    apps/snmp_monitoring/link_status.py este ano): 5 asserções, todas
    passaram, incluindo o caso de fevereiro bissexto vs. não-bissexto.
  • python -m py_compile em todos os arquivos Python novos
    (apps/billing/*) e nos tocados (config/settings.py,
    config/urls.py).
  • Migration escrita à mão, campo a campo, contra models.py (sem GDAL
    neste ambiente de preparação — não dá pra rodar makemigrations).
    Dependências (core.0013_dashboard_widget_layout,
    access.0002_add_ftth_fields) conferidas como as últimas migrations
    de cada app antes de referenciá-las.
  • Chaves do static/css/app.css balanceadas (276/276, só 3 classes
    novas pequenas — reaproveitei .overview-table, .sync-pill,
    .metric-card, .panel, .platform-form e .info-list
    existentes em vez de criar CSS novo pra tudo).
  • {% if %}/{% endif %}/{% for %}/{% endfor %}/{% block %}/
    {% endblock %} balanceados nos 3 templates novos
    (templates/billing/) e no base.html tocado.
  • YAML do docker-compose.yml válido.

manage.py check, manage.py migrate, manage.py test e o teste
visual real dependem de banco, GDAL e navegador — não rodam neste
ambiente de preparação. Precisam ser feitos no servidor.

Atualização

Execute apply no servidor — esta versão tem migration
(apps.billing.0001_initial), roda automaticamente. Depois, um
Ctrl+F5 no navegador.

Teste sugerido: abrir "Financeiro" no menu, cadastrar um cliente com
mensalidade e dia de vencimento, confirmar que a fatura do mês aparece
(pode rodar generate_monthly_invoices manualmente via
manage.py shell na primeira vez, já que o Celery Beat só passa a rodar
a cada hora a partir do próximo ciclo), registrar um pagamento parcial e
depois o restante, e confirmar que a fatura vira "Paga" só quando o
total bate.