Módulo Contábil
O módulo Contábil implementa um sistema de contabilidade por partidas dobradas (double-entry bookkeeping) integrado ao fluxo operacional do restaurante. Lançamentos são gerados automaticamente a partir de vendas, despesas e compras via fila assíncrona BullMQ.
Visão Geral
| Característica | Detalhe |
|---|---|
| Arquitetura | NestJS module: backend/src/accounting/ |
| Banco de dados | MongoDB/Mongoose — 6 schemas |
| Automação | BullMQ fila accounting-queue (fire-and-forget) |
| Permissão | manage_accounting (Role Admin ou Superadmin) |
| Rota principal | /t/:slug/admin/accounting |
Schemas
| Schema | Descrição | Arquivo |
|---|---|---|
ChartAccount | Plano de Contas — hierarquia de contas contábeis | schemas/chart-account.schema.ts |
JournalEntry | Lançamentos em partidas dobradas (débito=crédito) | schemas/journal-entry.schema.ts |
AccountsReceivable | Contas a receber — fiado, cartão D+N, PIX pendente | schemas/accounts-receivable.schema.ts |
BankAccount | Cadastro de contas bancárias | schemas/bank-account.schema.ts |
BankStatementLine | Linhas do extrato OFX/CSV importado | schemas/bank-statement-line.schema.ts |
PeriodClosing | Fechamento de competência com snapshot do balancete | schemas/period-closing.schema.ts |
Serviços
| Serviço | Responsabilidade | Arquivo |
|---|---|---|
ChartOfAccountsService | CRUD do plano de contas; seed dos defaults brasileiros | services/chart-of-accounts.service.ts |
JournalEntryService | Criar/listar/postar/estornar lançamentos | services/journal-entry.service.ts |
GeneralLedgerService | Balancete, razão geral, períodos e fechamento | services/general-ledger.service.ts |
AccountsReceivableService | Recebíveis — liquidar, baixar, aging report | services/accounts-receivable.service.ts |
BankReconciliationService | Importar OFX/CSV, conciliação automática | services/bank-reconciliation.service.ts |
AccountingAutomationService | Processa eventos da fila e gera lançamentos | accounting-queue/accounting-automation.service.ts |
Fila de Automação (BullMQ)
O módulo AccountingQueueModule (backend/src/accounting-queue/) gerencia a geração assíncrona de lançamentos:
OrdersService.closeTab() → evento sale_completed
DreService.createExpense() → evento expense_created
InboundNfeService.confirm() → evento inventory_purchase
↓
accounting-queue (Redis)
↓
AccountingAutomationService → gera JournalEntry automaticamenteOs hooks são fire-and-forget com @Optional() injection — o módulo funciona mesmo sem Redis configurado.
Plano de Contas
Estrutura hierárquica
Códigos no formato X.X.X.XX (ex: 1.1.2.03 — Contas a Receber – Fiado):
| Natureza | Grupo | Saldo normal |
|---|---|---|
ativo | 1 — Ativo | Devedor (debit) |
passivo | 2 — Passivo | Credor (credit) |
patrimonio_liquido | 2.3 — Patrimônio Líquido | Credor (credit) |
receita | 3 — Receitas | Credor (credit) |
custo | 4 — CMV | Devedor (debit) |
despesa | 5 — Despesas | Devedor (debit) |
Tipos de conta:
sintetica— Conta grupo (apenas agrupamento, não recebe lançamentos)analitica— Conta analítica (recebe lançamentos diretamente)
Seed de defaults
POST /t/:slug/accounting/chart/seed/defaults (Superadmin) — popula ~40 contas com hierarquia completa para restaurante brasileiro: Caixa, Bancos, Fiado, Cartões, Estoques, Fornecedores, Obrigações, Receitas, CMV, Folha, Aluguel, etc.
Lançamentos (Journal Entries)
Cada lançamento:
- Tem N linhas de débito + N linhas de crédito
totalDebit === totalCredit(invariante de partidas dobradas)- Passa pelos estados:
draft → posted → reversed - Estorno cria contra-lançamento automático
Contas a Receber
| Tipo | Gatilho de criação |
|---|---|
fiado | Pedido fechado com pagamento fiado no PDV |
card_credit | Pedido com cartão de crédito (recebimento D+N) |
card_debit | Pedido com cartão de débito |
pix_pending | PIX não confirmado |
other | Manual ou outros meios |
Status: open → partially_settled → settled ou open → written_off
Aging report: agrupa recebíveis por vencimento (Vencidos >90d, 60-90d, 30-60d, Até 30d, A Vencer) com totais e contagens.
Conciliação Bancária
- Importar extrato OFX (padrão Open Financial Exchange), CSV ou CNAB240 via upload
- Sistema pareia automaticamente linhas do extrato com lançamentos contábeis por valor + data (
auto-match) - Linhas podem ser:
unmatched → matchedouignored
Importação CNAB240
O formato CNAB 240 é o padrão brasileiro de remessa bancária usado pela maioria dos bancos (Bradesco, Itaú, Santander, BB, Caixa).
Como importar:
- Baixe o arquivo de extrato no internet banking do seu banco (extensão
.rem,.retou.txt, 240 caracteres por linha) - Acesse Contabilidade → Contas Bancárias
- Selecione a conta bancária correspondente
- Clique em Importar Extrato e selecione o arquivo CNAB240
- O sistema processa e exibe um resumo:
N lançamentos importados, N ignorados (duplicatas)
O que é extraído (Segmento T):
| Campo CNAB240 | Posição (0-indexed) | Mapeado para |
|---|---|---|
| Data | 20–27 (DDMMYYYY) | BankStatementLine.date |
| Indicador D/C | 118 (D=débito, C=crédito) | BankStatementLine.amount (negativo=D, positivo=C) |
| Valor | 119–131 (13 dígitos, 2 decimais) | BankStatementLine.amount |
| Histórico | 73–102 (30 chars) | BankStatementLine.description |
Deduplicação: Cada linha gera um hash SHA-1 de date|value|description. Linhas já importadas são ignoradas silenciosamente — reimportar o mesmo arquivo é seguro.
Encoding: Arquivos CNAB240 brasileiros usam latin1 (ISO-8859-1). O sistema converte automaticamente para UTF-8.
Auto-matching: Após a importação, BankReconciliationService.autoMatch() tenta parear cada linha com lançamentos contábeis existentes por valor exato e data próxima (±1 dia). Linhas pareadas recebem status: matched; as demais ficam unmatched para conciliação manual.
Serviço: backend/src/accounting/services/bank-reconciliation.service.ts → importCnab240()
Endpoint: POST /t/:slug/accounting/bank-accounts/:id/import-cnab240 (multipart/form-data, campo file)
Fechamento de Período
- Fecha uma competência mensal — impede novos lançamentos
- Captura snapshot do balancete no momento do fechamento (
trialBalanceSnapshot) - Pode ser reaberto para correções (
status: reopened)
Componentes Frontend
| View | Rota | Descrição |
|---|---|---|
AccountingOverviewView | /accounting | Dashboard KPIs + balancete resumido + quick links |
ChartOfAccountsView | /accounting/chart | Plano de Contas com filtros, form de criação, deactivate |
JournalEntriesView | /accounting/journal | Diário expandível, post/estorno paginado |
GeneralLedgerView | /accounting/ledger | Tabs Balancete / Razão Geral com running balance |
ReceivablesOverviewView | /accounting/receivables | Aging buckets, liquidar/baixar |
BankAccountsView | /accounting/bank-accounts | Contas bancárias, import OFX, conciliação |
PeriodClosingView | /accounting/closing | Fechamento de competência, expand snapshot |
Store Zustand
frontend-react/src/stores/accountingStore.ts — ver accountingStore
Componente AmountDisplay
AmountDisplay é o átomo padronizado de exibição de valores monetários em reais:
<AmountDisplay value={1234.56} size="md" color="auto" />
// color="auto": negativo=vermelho, zero=cinza, positivo=padrãoVer AmountDisplay
Balanço Patrimonial (Balance Sheet)
Endpoint: GET /t/:slug/admin/accounting/balance-sheet?asOf=YYYY-MM-DD
Permissão: Admin, Superadmin ou Accountant.
Retorna a estrutura do balanço patrimonial na data especificada (default: hoje, final do dia):
{
"asOf": "2026-05-28T23:59:59.999Z",
"ativo": {
"circulante": [ { "code": "1.1", "name": "Caixa e Bancos", "balance": 4500000 } ],
"naoCirculante": [ ... ],
"total": 12000000
},
"passivoEPatrimonio": {
"circulante": [ ... ],
"naoCirculante": [ ... ],
"patrimonioLiquido": [ ... ],
"total": 12000000
}
}Valores em centavos. Saldos calculados agregando JournalEntry postados até asOf.
Serviço: backend/src/accounting/services/balance-sheet.service.tsController: backend/src/accounting/controllers/balance-sheet.controller.tsView: frontend-react/src/views/admin/accounting/BalanceSheetView.tsx
Demonstração do Fluxo de Caixa (DFC)
Endpoint: GET /t/:slug/admin/accounting/cash-flow?start=YYYY-MM-DD&end=YYYY-MM-DD&method=direct|indirect
Permissão: Admin, Superadmin ou Accountant.
Parâmetros:
| Parâmetro | Default | Descrição |
|---|---|---|
start | 1º dia do mês atual | Data inicial |
end | hoje | Data final |
method | direct | direct (recebimentos/pagamentos) ou indirect (lucro líquido + ajustes) |
Retorna estrutura de DFC com seções: atividades operacionais, de investimento e de financiamento.
Serviço: backend/src/accounting/services/cash-flow.service.tsController: backend/src/accounting/controllers/cash-flow.controller.tsView: frontend-react/src/views/admin/accounting/CashFlowStatementView.tsx
Exportação Contábil
Endpoint: GET /t/:slug/admin/accounting/export?format=omie|contaazul|sap|sped&start=YYYY-MM-DD&end=YYYY-MM-DD
Permissão: Admin, Superadmin ou Accountant.
Retorna download de arquivo com lançamentos no formato solicitado:
| Formato | Tipo de arquivo | Descrição |
|---|---|---|
omie | JSON | Payload compatível com API Omie (/financas/contapagar/) |
contaazul | JSON | Payload compatível com API Conta Azul |
sap | CSV | SAP Business One Journal Entries (GL_Account, Debit, Credit) |
sped | TXT | SPED Contábil — Registro I010/I020/I050/I075/I150/I155/I200/I350 |
Serviço: backend/src/accounting/services/accounting-export.service.tsController: backend/src/accounting/controllers/accounting-export.controller.ts
Integrações ERP
O módulo de integrações permite configurar credenciais por provedor e enviar lançamentos contábeis diretamente às APIs externas.
Schema AccountingIntegration
| Campo | Tipo | Descrição |
|---|---|---|
tenant | ObjectId | |
provider | omie | contaazul | sap | sped | |
enabled | boolean | |
testMode | boolean | Usa sandbox/homologação do provedor |
apiKeyEncrypted | EncryptedField | Chave API criptografada com DEK do tenant |
apiSecretEncrypted | EncryptedField | Segredo criptografado |
baseUrlOverride | string? | URL customizada (obrigatória para SAP, opcional para outros) |
lastSyncAt | Date? | Último envio bem-sucedido |
lastError | string? | Último erro de sincronização |
Arquivo: backend/src/accounting/schemas/accounting-integration.schema.ts
Endpoints de Integrações
| Método | Rota | Descrição |
|---|---|---|
GET | /t/:slug/admin/accounting/integrations | Listar todas as integrações configuradas (apiKey/apiSecret mascarados como ****) |
PUT | /t/:slug/admin/accounting/integrations/:provider | Criar ou atualizar configuração (provider: omie, contaazul, sap, sped) |
POST | /t/:slug/admin/accounting/integrations/:provider/test | Testar credenciais contra endpoint low-cost do provedor |
Controller: backend/src/accounting/controllers/accounting-integration.controller.ts
Clientes ERP
| Provedor | Cliente | Base URL padrão |
|---|---|---|
| OMIE | backend/src/accounting/providers/omie.client.ts | https://app.omie.com.br/api/v1/ |
| Conta Azul | backend/src/accounting/providers/contaazul.client.ts | https://api.contaazul.com/ |
| SAP B1 | backend/src/accounting/providers/sap.client.ts | Configurável — ex: https://host:50000/b1s/v1 |
| SPED | backend/src/accounting/providers/sped.client.ts | file:/// local ou s3://bucket/prefix |
Todos os clientes usam retry com backoff exponencial (backend/src/accounting/providers/retry.util.ts).
Configuração por provedor
OMIE:
apiKey:app_keyda integração OmieapiSecret:app_secretda integração OmiebaseUrlOverride: opcional
Conta Azul:
apiKey: Client ID OAuth2apiSecret: Client Secret OAuth2baseUrlOverride: opcional
SAP Business One:
apiKey: usuário SAPapiSecret: senha SAPbaseUrlOverride: obrigatório — URL do Service Layer (https://hostname:50000/b1s/v1)
SPED:
- Sem credenciais — gera arquivo local ou S3
baseUrlOverride: caminho destino (file:///var/sped/ous3://meu-bucket/sped/)
Relacionados
- API — Accounting
- DRE — Integração via hook
expense_created - NF-e Entrada — Integração via hook
inventory_purchase - HCM — Folha de Pagamento — Bridge folha → lançamento via BullMQ
- Papel: Contador
- Relatórios Contábeis — Balanço, DFC, Exportação
- Integrações ERP — Omie/ContaAzul/SAP/SPED
- Guia: Relatórios Contábeis