12 KiB
Spec 023 — Cobrança recorrente & visibilidade Desk (empresa / billing)
Criado: 2026-06-17
Solicitado por: Roger
Status: Spec — implementação pendente (motor cobrança → ver Spec 024 FOSSBilling)
Prioridade: P1 (financeiro + operação)
Sistemas: Wizard VM112 · Desk VM122 · Motor de cobrança (fase 2)
Módulo Desk: billing-recurrence (novo — Spec 015)
Depende de: Spec 012 (tickets onboarding), Spec 018 (Serviços / clientes), Spec 021 (webhooks)
Relacionado: Card wizard «Dados da empresa e cobrança» (imagem Roger, 2026-06-17)
Resumo
Quando o utilizador preenche e confirma o card «Dados da empresa e cobrança» no wizard VM112, o Desk deve reflectir imediatamente o estado comercial/financeiro em três superfícies:
- Dashboard — KPI + feed de sessões/tickets em fase billing
- Audit Overview — domínio/tenant com badge «Empresa / Cobrança»
- Serviços — ícone de recorrência activa no card do cliente + link para conta do cliente (ficha financeira)
A fase 1 é visibilidade e orquestração no Desk (eventos, estados, links). A fase 2 liga o motor de cobrança recorrente (assinatura, boleto, PIX, inadimplência) ao company_profile já capturado.
Regra de ouro: o wizard não cobra no passo empresa — apenas recolhe dados e emite company.validated. A recorrência activa-se após validação OPS + provisionamento do plano no motor financeiro.
Problema
| Hoje | Necessidade |
|---|---|
Evento company.validated gera ticket [billing-validation] e billing_state no payload |
Ops não vê de relance quantos clientes estão em cobrança pendente / activa |
Card empresa existe no wizard (CNPJ, morada, email_billing, confirm_billing) |
Mesmo momento deve aparecer no Dashboard, Overview e Serviços |
| Serviços (Spec 018) mostra só saúde técnica (e-mail tenant activo) | Falta indicador 💳 recorrência e atalho para conta do cliente |
| Sem motor de cobrança ligado ao Desk | Boletos, débitos e MRR dispersos ou manuais |
Gatilho (wizard VM112)
Momento UX
O card «Dados da empresa e cobrança» é exibido após passos de conta/domínio (gate company_gate). O utilizador pode:
- Preencher agora (
confirm_billing+confirm_accurate) - Adiar — política ainda não registada na sessão (banner azul na imagem)
Webhook (já parcialmente implementado)
{
"event": "company.validated",
"domain": "myvexx.com",
"session_id": "<uuid>",
"data": {
"billing_state": "awaiting_billing_validation",
"company_profile": {
"trade_name": "Myvexx",
"legal_name": "Myvexx Ltda",
"tax_id_type": "cnpj",
"tax_id": "00000000000191",
"email_billing": "financeiro@myvexx.com",
"payment_method": "",
"confirm_billing": true,
"address": { "country": "BR", "city": "...", "postal_code": "..." }
}
}
}
Estados billing_state (Desk — normalizar)
| Estado | Significado | UI |
|---|---|---|
policy_pending |
Card visto mas empresa ainda não confirmada | Cinza — «Política pendente» |
awaiting_billing_validation |
company.validated — aguarda OPS |
Âmbar — «Validar cobrança» |
billing_active |
Plano + recorrência criados no motor financeiro | Verde — «Recorrência activa» |
billing_paused |
Suspenso manualmente (inadimplência / pedido cliente) | Vermelho suave |
billing_cancelled |
Cancelado — manter histórico | Cinza riscado |
Transição inicial automática no webhook: → awaiting_billing_validation.
Superfícies Desk (fase 1 — visibilidade)
1. Dashboard
| Elemento | Comportamento |
|---|---|
| KPI «Cobrança pendente» | Contagem tickets/sessões com billing_state = awaiting_billing_validation (48h) |
| KPI «Recorrência activa» | Contagem clientes com billing_active |
| Sessões activas | Badge billing no card quando current_stage >= company_validated |
| Tickets recentes | Prefixo [billing-validation] já existe — destacar com ícone 💳 |
| Feed rápido | Últimos 5 company.validated com domínio + razão social (mascarar CNPJ para NOC) |
2. Audit Overview
| Elemento | Comportamento |
|---|---|
| Domínio na lista | Badge «Empresa» quando funil ≥ company_validated |
| Modal domínio | Secção Cobrança com: estado, trade_name, email_billing (mascarado NOC), data confirmação |
| Card tenant VM112 | Contador «X domínios em validação billing» nas últimas 24h |
3. Serviços (overview-home — Spec 018)
| Elemento | Comportamento |
|---|---|
| Linha do cliente | Ícone pequeno 💳 ou servicos-billing-dot--active quando billing_active |
| Tooltip | «Recorrência activa — clique para conta do cliente» |
| Clique no ícone | Abre ficha Conta do cliente (drawer/modal) — não confundir com tile E-mail Tenant |
| Stats row | Novo contador: «N recorrências activas» |
Ficha «Conta do cliente» (nova — v1)
Painel lateral ou modal com:
- Dados empresa (
company_profile— RBAC Spec 003) - Estado billing + link externo motor financeiro (Odoo partner / Lago customer) quando fase 2
- Histórico:
company.validated, activação recorrência, últimos pagamentos (webhook fase 2) - Acções OPS (fase 1): «Marcar validado», «Activar recorrência» (manual)
- Acções OPS (fase 2): «Criar assinatura», «Reenviar boleto», «Suspender por inadimplência»
Modelo de dados Desk (fase 1)
Tabela billing_accounts (nova)
CREATE TABLE billing_accounts (
id INTEGER PRIMARY KEY,
domain TEXT NOT NULL,
session_id TEXT,
ticket_id INTEGER,
tax_id TEXT,
legal_name TEXT,
trade_name TEXT,
email_billing TEXT,
company_profile_json TEXT,
billing_state TEXT NOT NULL DEFAULT 'awaiting_billing_validation',
recurrence_active INTEGER NOT NULL DEFAULT 0,
external_customer_id TEXT, -- Odoo res.partner id ou Lago external_id
external_subscription_id TEXT,
payment_provider TEXT, -- asaas | iugu | stripe | manual
plan_code TEXT, -- email_tenant_monthly, etc.
activated_at TEXT,
activated_by TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE UNIQUE INDEX idx_billing_domain ON billing_accounts(domain);
Upsert no webhook
Em _process_ingress, após company.validated:
billing_store.upsert_from_company_validated(...)- Ligar
ticket_idewebhook_event_id - Não activar
recurrence_activeaté confirmação OPS ou webhook do motor financeiro
API (fase 1)
| Método | Rota | Descrição |
|---|---|---|
| GET | /api/v1/billing/accounts |
Lista (filtro billing_state, domain) |
| GET | /api/v1/billing/accounts/{id} |
Ficha conta cliente |
| GET | /api/v1/billing/accounts/by-domain/{domain} |
Lookup para Serviços |
| PATCH | /api/v1/billing/accounts/{id} |
OPS: mudar estado, recurrence_active |
| GET | /api/v1/billing/summary |
KPIs dashboard |
Motor de cobrança recorrente (fase 2)
Requisitos Ligbox (Brasil)
- Assinatura mensal/anual por domínio ou por utilizador
- Boleto + PIX + cartão (futuro)
- CNAB retorno / conciliação bancária
- NFSe / nota fiscal de serviço (quando aplicável)
- Inadimplência: lembretes, suspensão serviço, dunning
- API para o Desk criar cliente + plano a partir de
company_profile
Comparativo — aderência para o caso Ligbox
| Critério | Odoo 16 (+ OCA Brasil) | Lago (getlago/lago) |
|---|---|---|
| Já na stack Roger | ✅ API V16 existente (813f08e7…) |
❌ Novo deploy |
| Boleto nativo BR | ✅ l10n_br_account_payment_brcobranca (OCA) + CNAB |
⚠️ Via Stripe (boleto em BRL) — não CNAB tradicional |
| PIX | ✅ Módulos ASAAS / Iugu / PagBank | ⚠️ Stripe PIX (se configurado) |
| NFSe / fiscal BR | ✅ OCA l10n_br_* + integradores |
❌ Não é ERP fiscal |
| Assinatura recorrente | ✅ sale_subscription + ASAAS Subscriptions |
✅ Core product — excelente API |
| Metering (por caixa, GB) | ⚠️ Possível, menos natural | ✅ Event-based — ideal |
| Controle débitos / aging | ✅ Contabilidade + follow-up pagamentos | ✅ Dunning + invoices |
| Self-host | ✅ Já conhecido | ✅ Docker (Railway/K8s) |
| Integração Desk | JSON-RPC / REST Odoo | REST API limpa |
| Curva para MSP BR | Menor — um sistema fiscal + cobrança | Maior se precisar Odoo à parte para NF |
Recomendação (Roger)
Aderência principal: Odoo 16 — já tens instância e API; o ecossistema OCA Brasil cobre boleto/CNAB, e módulos ASAAS ou Iugu fecham PIX + assinatura recorrente + webhooks de pagamento sem reinventar fiscal.
Lago é excelente como motor de subscrição/metering (preço por utilizador, usage API) se no futuro quiseres billing estilo SaaS puro desacoplado do fiscal — mas para boletos, débitos e conformidade BR, continuarias a precisar de Odoo (ou similar) em paralelo.
Arquitectura sugerida
Wizard VM112 ──webhook──► Desk VM122 ──orquestra──► Odoo 16
│ │ │
company.validated billing_accounts res.partner
company_profile UI Dashboard/Overview/ sale.subscription
Serviços + ícone 💳 ASAAS/Iugu (boleto/PIX)
webhooks → Desk (fase 2)
Opção híbrida (fase 3+): Lago calcula usage (caixas extra, storage) → Odoo emite NF + boleto consolidado. Só vale a pena com volume e pricing complexo.
Projetos GitHub de referência
| Projeto | Uso |
|---|---|
| odoo/odoo | Core ERP + Subscriptions |
| OCA/l10n-brazil | Localização fiscal BR |
| getlago/lago | Metering + subscriptions API (complementar) |
| ASAAS / Iugu Odoo modules | Pagamentos BR (boleto, PIX, recorrência) |
Webhooks fase 2 (motor → Desk)
| Evento | Acção Desk |
|---|---|
billing.subscription.created |
recurrence_active=1, billing_state=billing_active |
billing.invoice.paid |
Registo pagamento; ícone 💳 verde |
billing.invoice.overdue |
Badge inadimplência; ticket automático |
billing.subscription.cancelled |
billing_cancelled |
Fonte: Odoo (sale.subscription + payment transaction) ou ASAAS webhooks via worker Desk.
RBAC (Spec 003)
| Acção | super_admin | ops_lead | technician | noc |
|---|---|---|---|---|
| Ver KPI billing dashboard | ✅ | ✅ | ✅ | ✅ (contagens) |
Ver company_profile completo |
✅ | ✅ | ✅ | ❌ mascarado |
| Abrir conta do cliente | ✅ | ✅ | ✅ | ❌ |
| Activar / suspender recorrência | ✅ | ✅ | ❌ | ❌ |
| Link motor financeiro | ✅ | ✅ | ✅ | ❌ |
UI — ícone recorrência (Serviços)
<!-- Na linha do cliente (accounts.js) -->
<span class="servicos-billing-badge servicos-billing-badge--active"
title="Recorrência activa"
data-billing-account="{id}">
💳
</span>
CSS: bolinha verde 8px ou emoji discreto à direita do nome; cursor:pointer; separado do badge «activo» técnico do e-mail tenant.
Fora de escopo v1
- Emissão real de boleto/NF (fase 2)
- Portal do cliente pagar fatura (fase 3)
- Multi-moeda
- Pricing dinâmico usage-based (Lago — fase 3)
Critérios de aceite (fase 1)
- Webhook
company.validatedcria/atualizabilling_accounts - Dashboard mostra KPI «Cobrança pendente» > 0 após teste wizard
- Overview mostra badge «Empresa» no domínio
- Serviços: ícone 💳 só quando
recurrence_active=1; clique abre ficha conta - NOC não vê CNPJ completo nem
email_billing - Módulo
billing-recurrenceactivável em Módulos Desk
Plano de implementação
| Fase | Entrega |
|---|---|
| 1a | billing_store + routes + hook webhook + API summary |
| 1b | Dashboard KPI + badges sessão/ticket |
| 1c | Overview badge + secção cobrança no modal |
| 1d | Serviços: ícone + modal conta cliente + PATCH manual OPS |
| 2 | Integração Odoo: res.partner + subscription ASAAS |
| 3 | Webhooks pagamento + inadimplência + suspensão serviço |