Compare commits
3 Commits
5d9c034a42
...
423bf752db
| Author | SHA1 | Date |
|---|---|---|
|
|
423bf752db | |
|
|
21e953be83 | |
|
|
2807a9d9dd |
|
|
@ -1,733 +0,0 @@
|
||||||
# PLANO SOE CENTRAL — Arcádia Suite
|
|
||||||
## Orquestração Inteligente: Plus + ERPNext invisíveis, Central visível
|
|
||||||
### Versão 1.0 — Março 2026
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. ONDE ESTAMOS (Orientação Geral)
|
|
||||||
|
|
||||||
### O Projeto nasceu no Replit como…
|
|
||||||
- Uma plataforma de **escritório empresarial com IA central** (Manus Agent)
|
|
||||||
- Com proxy para o **Arcádia Plus** (Laravel/PHP, porta 8080) — ERP fiscal completo
|
|
||||||
- Com integração ao **ERPNext/Frappe** via API
|
|
||||||
- Stack principal: **React 18 + Express.js + PostgreSQL + FastAPI (Python)**
|
|
||||||
|
|
||||||
### O que JÁ existe e funciona:
|
|
||||||
| Componente | Status | Onde vive |
|
|
||||||
|---|---|---|
|
|
||||||
| Manus Agent (IA, 30+ tools) | ✅ Funcionando | `server/manus/` |
|
|
||||||
| Arcádia Plus (Laravel ERP) | ✅ Funcionando | `plus/` → porta 8080 |
|
|
||||||
| SSO Plus ↔ Suite | ✅ Funcionando | `server/plus/` |
|
|
||||||
| Motor Fiscal (nfelib) | ✅ Funcionando | `server/python/` → porta 8002 |
|
|
||||||
| Motor Contábil | ✅ Funcionando | `server/python/` → porta 8003 |
|
|
||||||
| Motor BI | ✅ Funcionando | `server/python/` → porta 8004 |
|
|
||||||
| Motor Automação | ✅ Funcionando | `server/python/` → porta 8005 |
|
|
||||||
| Motor Comunicação (Comm) | ✅ Funcionando | porta 8006 |
|
|
||||||
| Dev Center XOS (6 agentes) | ✅ Funcionando | `server/blackboard/` |
|
|
||||||
| LiteLLM Gateway | ✅ Configurado | porta 4000 |
|
|
||||||
| CRM, WhatsApp, Chat | ✅ Funcionando | `server/crm/`, `server/whatsapp/` |
|
|
||||||
| ERPNext integração | ⚠️ Parcial | `server/erp/routes.ts` |
|
|
||||||
|
|
||||||
### O que FALTA para o plano atual:
|
|
||||||
| Componente | Status |
|
|
||||||
|---|---|
|
|
||||||
| **SOE Central (Regras Unificadas)** | ❌ Não existe — este é o plano |
|
|
||||||
| Fiscal rules centralizadas (acima do Plus) | ❌ Dispersas no Plus |
|
|
||||||
| ERPNext rules centralizadas | ❌ Não existe camada de abstração |
|
|
||||||
| Contábil Avançado (lançamentos automáticos) | ❌ Motor existe, regras não |
|
|
||||||
| Financeiro Avançado (previsão, DRE automático) | ❌ Motor existe, regras não |
|
|
||||||
| Testes automatizados / CI-CD | ❌ |
|
|
||||||
| Monitoramento (APM, Sentry) | ❌ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. O PROBLEMA QUE VAMOS RESOLVER
|
|
||||||
|
|
||||||
### Situação Atual (problemática)
|
|
||||||
```
|
|
||||||
Usuário → Arcádia Suite
|
|
||||||
├── /plus → acessa Laravel diretamente (usuário VÊ o Plus)
|
|
||||||
├── /erp → acessa ERPNext diretamente (usuário VÊ o ERPNext)
|
|
||||||
└── Regras fiscais ficam dentro do Plus
|
|
||||||
Regras contábeis ficam no Motor 8003
|
|
||||||
Regras ERP ficam no ERPNext
|
|
||||||
→ Fragmentado, sem governança central
|
|
||||||
```
|
|
||||||
|
|
||||||
### Situação Desejada (SOE Central)
|
|
||||||
```
|
|
||||||
Usuário → Arcádia Suite (SOE)
|
|
||||||
│
|
|
||||||
▼ [Central de Regras SOE]
|
|
||||||
├── Fiscal: regras unificadas (CFOP, NCM, tributação, NF-e, CT-e...)
|
|
||||||
├── ERP: regras de negócio (pedidos, estoque, compras...)
|
|
||||||
├── Contábil: regras de lançamentos, plano de contas, DRE...
|
|
||||||
└── Financeiro: regras de fluxo, provisões, conciliação...
|
|
||||||
│
|
|
||||||
▼ [Execução invisível]
|
|
||||||
├── Plus → emite documentos, registra no banco
|
|
||||||
└── ERPNext → executa operações, registra no banco
|
|
||||||
|
|
||||||
O usuário NUNCA VÊ o Plus nem o ERPNext.
|
|
||||||
Só vê a Central SOE do Arcádia.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. ARQUITETURA SOE CENTRAL
|
|
||||||
|
|
||||||
### 3.1 Diagrama Completo
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ ARCÁDIA SUITE (Frontend React) │
|
|
||||||
│ /financeiro /contabil /fisco /erp /people /production /bi │
|
|
||||||
│ Usuário nunca acessa /plus ou ERPNext diretamente │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ SOE — SISTEMA OPERACIONAL EMPRESARIAL (Nova Camada) │
|
|
||||||
│ Express.js / porta 5000 / server/soe/ │
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
||||||
│ │ CENTRAL FISCAL │ │ CENTRAL ERP │ │
|
|
||||||
│ │ server/soe/fiscal/ │ │ server/soe/erp/ │ │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ │ • Regras NCM/CFOP │ │ • Regras de pedidos │ │
|
|
||||||
│ │ • Políticas tribut. │ │ • Regras de estoque │ │
|
|
||||||
│ │ • Emissão NF-e/NFC-e │ │ • Regras de compras │ │
|
|
||||||
│ │ • Cancelamento │ │ • Regras de pessoas │ │
|
|
||||||
│ │ • SPED/SINTEGRA │ │ • Integrações ext. │ │
|
|
||||||
│ └──────────┬───────────┘ └──────────┬─────────────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
||||||
│ │ CENTRAL CONTÁBIL │ │ CENTRAL FINANCEIRO │ │
|
|
||||||
│ │ server/soe/contabil/│ │ server/soe/financ/ │ │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ │ • Plano de contas │ │ • Fluxo de caixa │ │
|
|
||||||
│ │ • Regras de lanç. │ │ • Contas a P/R │ │
|
|
||||||
│ │ • DRE automático │ │ • Conciliação │ │
|
|
||||||
│ │ • Balancete │ │ • Previsão (IA) │ │
|
|
||||||
│ │ • Fechamento │ │ • Impostos │ │
|
|
||||||
│ └──────────┬───────────┘ └──────────┬─────────────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
│ └────────────┬─────────────┘ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────────────────────┐ │
|
|
||||||
│ │ SOE RULE ENGINE (Núcleo) │ │
|
|
||||||
│ │ server/soe/rule-engine.ts │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ • Resolução de conflitos │ │
|
|
||||||
│ │ • Aplicação de políticas XOS │ │
|
|
||||||
│ │ • Audit trail de todas regras │ │
|
|
||||||
│ │ • Manus consulta este engine │ │
|
|
||||||
│ └─────────────────┬───────────────┘ │
|
|
||||||
└────────────────────────────┼────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────┼───────────────┐
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐
|
|
||||||
│ ARCÁDIA PLUS │ │ ERPNEXT │ │ MOTORES PYTHON │
|
|
||||||
│ Laravel :8080 │ │ Frappe : │ │ 8002 Fiscal │
|
|
||||||
│ (invisível) │ │ (invisível) │ │ 8003 Contábil │
|
|
||||||
│ │ │ │ │ 8004 BI │
|
|
||||||
│ Emite docs │ │ Executa ERP │ │ 8005 Automação │
|
|
||||||
│ fiscais │ │ operacional │ │ │
|
|
||||||
└─────────────────┘ └──────────────┘ └──────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. CENTRAL FISCAL — Detalhamento
|
|
||||||
|
|
||||||
### 4.1 O que ela resolve
|
|
||||||
O Plus tem **376 controllers** e **1.546 rotas** — tudo fiscal/operacional. A Central Fiscal **não substitui** o Plus, ela **orquestra** o Plus com regras definidas no SOE.
|
|
||||||
|
|
||||||
### 4.2 Regras que vão para a Central (tiradas do Plus)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/fiscal/rules.ts — Exemplo de estrutura
|
|
||||||
|
|
||||||
interface FiscalRule {
|
|
||||||
id: string
|
|
||||||
nome: string
|
|
||||||
trigger: 'pre_emissao' | 'pos_emissao' | 'cancelamento' | 'validacao'
|
|
||||||
condicao: FiscalCondition
|
|
||||||
acao: FiscalAction
|
|
||||||
prioridade: number
|
|
||||||
ativo: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exemplos de regras:
|
|
||||||
const REGRAS_FISCAIS: FiscalRule[] = [
|
|
||||||
{
|
|
||||||
id: 'NFE_CFOP_INTERESTADUAL',
|
|
||||||
nome: 'Ajusta CFOP para operação interestadual',
|
|
||||||
trigger: 'pre_emissao',
|
|
||||||
condicao: { uf_emitente: '!=', uf_destinatario: true },
|
|
||||||
acao: { ajustar_cfop: 'interestadual' },
|
|
||||||
prioridade: 1,
|
|
||||||
ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NFE_SIMPLES_NACIONAL',
|
|
||||||
nome: 'Aplica tributação Simples Nacional',
|
|
||||||
trigger: 'pre_emissao',
|
|
||||||
condicao: { regime_tributario: 'simples_nacional' },
|
|
||||||
acao: { aplicar_cst: 'tabela_simples', remover_pis_cofins: true },
|
|
||||||
prioridade: 2,
|
|
||||||
ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NFE_VALIDACAO_NCM',
|
|
||||||
nome: 'Valida NCM obrigatório para NF-e',
|
|
||||||
trigger: 'validacao',
|
|
||||||
condicao: { tipo_documento: 'nfe' },
|
|
||||||
acao: { validar_campo: 'ncm', obrigatorio: true },
|
|
||||||
prioridade: 1,
|
|
||||||
ativo: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 Fluxo de Emissão via SOE Central
|
|
||||||
|
|
||||||
```
|
|
||||||
Usuário clica "Emitir NF-e" no Arcádia
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
POST /api/soe/fiscal/emitir-nfe
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE Rule Engine: aplica REGRAS_FISCAIS (pre_emissao)
|
|
||||||
• Verifica regime tributário
|
|
||||||
• Aplica CFOP correto
|
|
||||||
• Calcula impostos (ICMS, PIS, COFINS, IPI)
|
|
||||||
• Valida NCM obrigatório
|
|
||||||
• Adiciona dados da empresa emitente
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE envia para Plus via API interna (invisível)
|
|
||||||
POST http://plus:8080/api/nfe/emitir
|
|
||||||
+ token SSO automático
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Plus emite via Cloud-DFE → SEFAZ
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE recebe retorno
|
|
||||||
• Registra no banco SOE (tabela soe_fiscal_eventos)
|
|
||||||
• Dispara lançamento contábil automático
|
|
||||||
• Notifica via WebSocket o frontend
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Usuário vê resultado no Arcádia (nunca soube do Plus)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 Tabelas SOE para Fiscal
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- Tabelas a criar no schema Arcádia (PostgreSQL)
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_regras (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
nome VARCHAR(200) NOT NULL,
|
|
||||||
trigger VARCHAR(50) NOT NULL,
|
|
||||||
condicao JSONB NOT NULL,
|
|
||||||
acao JSONB NOT NULL,
|
|
||||||
prioridade INTEGER DEFAULT 10,
|
|
||||||
ativo BOOLEAN DEFAULT true,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_eventos (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
tipo VARCHAR(50) NOT NULL, -- 'emissao_nfe', 'cancelamento', etc.
|
|
||||||
empresa_id INTEGER NOT NULL,
|
|
||||||
documento_chave VARCHAR(100),
|
|
||||||
regras_aplicadas JSONB, -- quais regras foram aplicadas
|
|
||||||
payload_enviado JSONB, -- o que foi enviado ao Plus
|
|
||||||
payload_retorno JSONB, -- o que o Plus/SEFAZ respondeu
|
|
||||||
status VARCHAR(50) NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_configuracoes (
|
|
||||||
empresa_id INTEGER PRIMARY KEY,
|
|
||||||
regime_tributario VARCHAR(50), -- simples, lucro_presumido, lucro_real
|
|
||||||
uf VARCHAR(2),
|
|
||||||
cnpj VARCHAR(18),
|
|
||||||
certificado_tipo VARCHAR(20),
|
|
||||||
aliquotas JSONB, -- alíquotas padrão por operação
|
|
||||||
cfops_padrao JSONB, -- CFOPs padrão por tipo de operação
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. CENTRAL ERP (ERPNext/Frappe) — Detalhamento
|
|
||||||
|
|
||||||
### 5.1 O que ela resolve
|
|
||||||
O ERPNext tem **APIs complexas**. A Central ERP abstrai tudo isso em operações simples que o Arcádia entende.
|
|
||||||
|
|
||||||
### 5.2 Adapter Layer ERPNext
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/erp/frappe-adapter.ts
|
|
||||||
|
|
||||||
interface ERPAdapter {
|
|
||||||
// Produtos
|
|
||||||
criarProduto(data: ProdutoSOE): Promise<ERPProduto>
|
|
||||||
buscarProduto(codigo: string): Promise<ProdutoSOE>
|
|
||||||
atualizarEstoque(movimentacao: MovimentacaoEstoque): Promise<void>
|
|
||||||
|
|
||||||
// Pedidos
|
|
||||||
criarPedidoVenda(pedido: PedidoSOE): Promise<ERPPedido>
|
|
||||||
aprovarPedido(id: string): Promise<void>
|
|
||||||
faturarPedido(id: string): Promise<ERPFatura>
|
|
||||||
|
|
||||||
// Financeiro
|
|
||||||
criarLancamento(lancamento: LancamentoSOE): Promise<ERPLancamento>
|
|
||||||
buscarPlanoContas(): Promise<ContaContabil[]>
|
|
||||||
|
|
||||||
// Compras
|
|
||||||
criarPedidoCompra(data: PedidoCompraSOE): Promise<ERPPedidoCompra>
|
|
||||||
receberMercadoria(data: RecebimentoSOE): Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
// As regras ficam no SOE, o adapter só traduz
|
|
||||||
class FrappeAdapter implements ERPAdapter {
|
|
||||||
private baseUrl: string
|
|
||||||
private apiKey: string
|
|
||||||
|
|
||||||
async criarPedidoVenda(pedido: PedidoSOE): Promise<ERPPedido> {
|
|
||||||
// Traduz do modelo SOE para o modelo Frappe
|
|
||||||
const frappePedido = this.traduzirParaFrappe(pedido)
|
|
||||||
|
|
||||||
// Envia para ERPNext (invisível para o usuário)
|
|
||||||
const response = await fetch(`${this.baseUrl}/api/resource/Sales Order`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Authorization': `token ${this.apiKey}` },
|
|
||||||
body: JSON.stringify(frappePedido)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Traduz retorno de volta para modelo SOE
|
|
||||||
return this.traduzirDeVoltaSOE(await response.json())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 Regras de Negócio ERP no SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/erp/rules.ts
|
|
||||||
|
|
||||||
const REGRAS_ERP = [
|
|
||||||
{
|
|
||||||
id: 'PEDIDO_APROVACAO_AUTOMATICA',
|
|
||||||
nome: 'Aprovação automática até R$ 5.000',
|
|
||||||
trigger: 'pre_aprovacao_pedido',
|
|
||||||
condicao: { valor_total: { menor_que: 5000 } },
|
|
||||||
acao: { aprovar_automaticamente: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ESTOQUE_RESERVA_VENDA',
|
|
||||||
nome: 'Reservar estoque ao confirmar venda',
|
|
||||||
trigger: 'pos_confirmacao_venda',
|
|
||||||
condicao: { status: 'confirmado' },
|
|
||||||
acao: { reservar_estoque: true, gerar_separacao: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NF_AUTOMATICA_FATURAMENTO',
|
|
||||||
nome: 'Emite NF-e automaticamente ao faturar',
|
|
||||||
trigger: 'pos_faturamento',
|
|
||||||
condicao: { tipo_cliente: ['pj', 'pf_contribuinte'] },
|
|
||||||
acao: { emitir_nfe: true, via_soe_fiscal: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. CENTRAL CONTÁBIL AVANÇADA
|
|
||||||
|
|
||||||
### 6.1 Motor Atual (porta 8003) + Regras SOE
|
|
||||||
|
|
||||||
O Motor Contábil Python já faz DRE e Balancete. O que falta é **alimentação automática**.
|
|
||||||
|
|
||||||
### 6.2 Lançamentos Automáticos (grande salto)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/contabil/auto-lancamentos.ts
|
|
||||||
|
|
||||||
interface RegrasLancamentoAuto {
|
|
||||||
gatilho: string
|
|
||||||
debito: string // Conta contábil
|
|
||||||
credito: string // Conta contábil
|
|
||||||
historico: string
|
|
||||||
formula: string // Como calcular o valor
|
|
||||||
}
|
|
||||||
|
|
||||||
const LANCAMENTOS_AUTOMATICOS: RegrasLancamentoAuto[] = [
|
|
||||||
// Quando emite NF-e de venda
|
|
||||||
{
|
|
||||||
gatilho: 'emissao_nfe_venda',
|
|
||||||
debito: '1.1.3.01', // Clientes
|
|
||||||
credito: '3.1.1.01', // Receita Bruta de Vendas
|
|
||||||
historico: 'Venda conforme NF-e {numero}',
|
|
||||||
formula: 'valor_total_nota'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gatilho: 'emissao_nfe_venda',
|
|
||||||
debito: '3.1.2.01', // Dedução de Receita (ICMS)
|
|
||||||
credito: '2.1.2.01', // ICMS a Recolher
|
|
||||||
historico: 'ICMS s/ Venda NF-e {numero}',
|
|
||||||
formula: 'valor_icms'
|
|
||||||
},
|
|
||||||
// Quando paga conta
|
|
||||||
{
|
|
||||||
gatilho: 'pagamento_conta',
|
|
||||||
debito: '2.1.1.{categoria}', // Conta a Pagar específica
|
|
||||||
credito: '1.1.1.01', // Banco/Caixa
|
|
||||||
historico: 'Pagamento: {descricao}',
|
|
||||||
formula: 'valor_pago'
|
|
||||||
},
|
|
||||||
// Quando recebe pagamento
|
|
||||||
{
|
|
||||||
gatilho: 'recebimento',
|
|
||||||
debito: '1.1.1.01', // Banco/Caixa
|
|
||||||
credito: '1.1.3.01', // Clientes
|
|
||||||
historico: 'Recebimento: {descricao}',
|
|
||||||
formula: 'valor_recebido'
|
|
||||||
},
|
|
||||||
// Compra de mercadoria
|
|
||||||
{
|
|
||||||
gatilho: 'entrada_nfe_compra',
|
|
||||||
debito: '1.1.4.01', // Estoque
|
|
||||||
credito: '2.1.1.01', // Fornecedores
|
|
||||||
historico: 'Compra conforme NF-e {numero} / {fornecedor}',
|
|
||||||
formula: 'valor_mercadorias'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 DRE Automático via SOE
|
|
||||||
|
|
||||||
```
|
|
||||||
Usuário pede DRE do mês
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE Contábil consulta:
|
|
||||||
1. Todos lançamentos do período (tabela soe_lancamentos)
|
|
||||||
2. Agrupa por conta contábil
|
|
||||||
3. Aplica estrutura DRE configurada
|
|
||||||
4. Envia para Motor Python 8003 para cálculos
|
|
||||||
5. Retorna DRE formatado
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Usuário vê DRE no /contabil do Arcádia
|
|
||||||
(Nunca soube que teve lançamentos automáticos de NF-e, pagamentos, etc.)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. CENTRAL FINANCEIRO AVANÇADO
|
|
||||||
|
|
||||||
### 7.1 Regras Financeiras no SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/financeiro/rules.ts
|
|
||||||
|
|
||||||
const REGRAS_FINANCEIRO = [
|
|
||||||
{
|
|
||||||
id: 'BOLETO_AUTO_VENCIMENTO',
|
|
||||||
nome: 'Gerar boleto automático para vendas a prazo',
|
|
||||||
trigger: 'pos_confirmacao_venda_prazo',
|
|
||||||
acao: { gerar_boleto: true, via: 'asaas', vencimento: '+{prazo}_dias' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ALERTA_VENCIMENTO_3DIAS',
|
|
||||||
nome: 'Alerta de vencimento 3 dias antes',
|
|
||||||
trigger: 'cron_diario',
|
|
||||||
condicao: { vencimento_em: 3 },
|
|
||||||
acao: { notificar: ['whatsapp', 'email'], via_manus: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'PROVISAO_IMPOSTOS',
|
|
||||||
nome: 'Provisão mensal de impostos',
|
|
||||||
trigger: 'cron_mensal',
|
|
||||||
acao: { calcular_provisao: ['icms', 'pis', 'cofins', 'csll', 'irpj'], registrar_lancamento: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'CONCILIACAO_AUTO',
|
|
||||||
nome: 'Conciliação bancária automática via OFX',
|
|
||||||
trigger: 'importacao_ofx',
|
|
||||||
acao: { tentar_conciliar: true, confianca_minima: 0.85, pendentes_para_revisao: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. MANUS AGENT + SOE CENTRAL
|
|
||||||
|
|
||||||
### 8.1 O Manus consulta a Central
|
|
||||||
|
|
||||||
```
|
|
||||||
Pergunta: "Qual foi o resultado do mês passado?"
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Manus → SOE Central
|
|
||||||
• GET /api/soe/contabil/dre?periodo=2026-02
|
|
||||||
• GET /api/soe/financeiro/fluxo?periodo=2026-02
|
|
||||||
• GET /api/soe/fiscal/resumo?periodo=2026-02
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE agrega dados dos motores (Python) + Plus + ERPNext
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Manus recebe contexto completo e responde:
|
|
||||||
"Faturamento: R$ 120.000
|
|
||||||
Deduções (impostos): R$ 18.000
|
|
||||||
Receita Líquida: R$ 102.000
|
|
||||||
Custo das mercadorias: R$ 65.000
|
|
||||||
Lucro Bruto: R$ 37.000
|
|
||||||
..."
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Tools do Manus para o SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Novas tools do Manus que consultam o SOE Central
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'consultar_situacao_fiscal',
|
|
||||||
description: 'Consulta situação fiscal da empresa (NFs pendentes, impostos, SPED)',
|
|
||||||
endpoint: 'GET /api/soe/fiscal/situacao'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'emitir_documento_fiscal',
|
|
||||||
description: 'Emite NF-e, NFC-e, CT-e ou MDF-e',
|
|
||||||
endpoint: 'POST /api/soe/fiscal/emitir'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'consultar_dre',
|
|
||||||
description: 'Gera DRE de qualquer período',
|
|
||||||
endpoint: 'GET /api/soe/contabil/dre'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'consultar_fluxo_caixa',
|
|
||||||
description: 'Consulta fluxo de caixa e previsões',
|
|
||||||
endpoint: 'GET /api/soe/financeiro/fluxo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'registrar_lancamento_contabil',
|
|
||||||
description: 'Registra lançamento contábil manualmente',
|
|
||||||
endpoint: 'POST /api/soe/contabil/lancamento'
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. ESTRUTURA DE PASTAS A CRIAR
|
|
||||||
|
|
||||||
```
|
|
||||||
server/
|
|
||||||
└── soe/ ← Nova pasta (Central SOE)
|
|
||||||
├── index.ts ← Router principal do SOE
|
|
||||||
├── rule-engine.ts ← Motor de regras central
|
|
||||||
│
|
|
||||||
├── fiscal/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/fiscal/*
|
|
||||||
│ ├── rules.ts ← Regras fiscais (CFOP, NCM, tributação)
|
|
||||||
│ ├── emissao.ts ← Orquestração de emissão (→ Plus)
|
|
||||||
│ ├── plus-adapter.ts ← Adaptador para o Plus (invisível)
|
|
||||||
│ └── sefaz-adapter.ts ← Comunicação direta SEFAZ (via Python 8002)
|
|
||||||
│
|
|
||||||
├── erp/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/erp/*
|
|
||||||
│ ├── rules.ts ← Regras de negócio ERP
|
|
||||||
│ ├── frappe-adapter.ts ← Adaptador ERPNext (invisível)
|
|
||||||
│ └── plus-erp-adapter.ts ← Adaptador Plus-ERP (para dados de venda)
|
|
||||||
│
|
|
||||||
├── contabil/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/contabil/*
|
|
||||||
│ ├── rules.ts ← Regras contábeis
|
|
||||||
│ ├── auto-lancamentos.ts ← Lançamentos automáticos
|
|
||||||
│ ├── plano-contas.ts ← Plano de contas SOE
|
|
||||||
│ └── python-adapter.ts ← Adaptador Motor Python 8003
|
|
||||||
│
|
|
||||||
├── financeiro/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/financeiro/*
|
|
||||||
│ ├── rules.ts ← Regras financeiras
|
|
||||||
│ ├── previsao.ts ← Previsão com IA
|
|
||||||
│ └── conciliacao.ts ← Conciliação bancária
|
|
||||||
│
|
|
||||||
└── shared/
|
|
||||||
├── types.ts ← Tipos SOE compartilhados
|
|
||||||
├── audit.ts ← Registro de todas as operações
|
|
||||||
└── event-bus.ts ← Eventos entre Centrais
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. TABELAS DO BANCO A CRIAR (Drizzle ORM)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// shared/schema.ts — Adicionar:
|
|
||||||
|
|
||||||
// Configuração da empresa no SOE
|
|
||||||
export const soeEmpresaConfig = pgTable('soe_empresa_config', {
|
|
||||||
id: serial('id').primaryKey(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
regimeTributario: varchar('regime_tributario', { length: 50 }), // simples, presumido, real
|
|
||||||
uf: varchar('uf', { length: 2 }),
|
|
||||||
cnpj: varchar('cnpj', { length: 18 }),
|
|
||||||
planoContasId: integer('plano_contas_id'),
|
|
||||||
configFiscal: jsonb('config_fiscal'), // alíquotas, CFOPs padrão
|
|
||||||
configErp: jsonb('config_erp'), // qual ERP: plus, erpnext, ambos
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Regras configuráveis (editáveis pelo usuário)
|
|
||||||
export const soeRegras = pgTable('soe_regras', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id'), // null = regra global
|
|
||||||
dominio: varchar('dominio', { length: 50 }).notNull(), // 'fiscal', 'erp', 'contabil', 'financeiro'
|
|
||||||
nome: varchar('nome', { length: 200 }).notNull(),
|
|
||||||
trigger: varchar('trigger', { length: 100 }).notNull(),
|
|
||||||
condicao: jsonb('condicao').notNull(),
|
|
||||||
acao: jsonb('acao').notNull(),
|
|
||||||
prioridade: integer('prioridade').default(10),
|
|
||||||
ativo: boolean('ativo').default(true),
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Log de todas as operações SOE (audit trail)
|
|
||||||
export const soeEventos = pgTable('soe_eventos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
dominio: varchar('dominio', { length: 50 }).notNull(),
|
|
||||||
tipo: varchar('tipo', { length: 100 }).notNull(),
|
|
||||||
regraIds: jsonb('regra_ids'), // regras aplicadas
|
|
||||||
payloadEntrada: jsonb('payload_entrada'),
|
|
||||||
payloadSaida: jsonb('payload_saida'),
|
|
||||||
erp: varchar('erp', { length: 50 }), // 'plus', 'erpnext', 'python_8003', etc.
|
|
||||||
status: varchar('status', { length: 50 }).notNull(),
|
|
||||||
duracao: integer('duracao'), // ms
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Lançamentos contábeis centralizados
|
|
||||||
export const soeLancamentos = pgTable('soe_lancamentos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
data: date('data').notNull(),
|
|
||||||
contaDebito: varchar('conta_debito', { length: 30 }).notNull(),
|
|
||||||
contaCredito: varchar('conta_credito', { length: 30 }).notNull(),
|
|
||||||
valor: numeric('valor', { precision: 15, scale: 2 }).notNull(),
|
|
||||||
historico: text('historico').notNull(),
|
|
||||||
origem: varchar('origem', { length: 100 }), // 'emissao_nfe', 'pagamento', etc.
|
|
||||||
origemId: varchar('origem_id', { length: 100 }),
|
|
||||||
period: varchar('period', { length: 7 }), // '2026-03'
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. ROADMAP DE IMPLEMENTAÇÃO
|
|
||||||
|
|
||||||
### Fase 1 — Fundação (2–3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 1. Criar server/soe/ com estrutura básica
|
|
||||||
[ ] 2. Criar tabelas: soe_empresa_config, soe_regras, soe_eventos, soe_lancamentos
|
|
||||||
[ ] 3. Implementar Plus Adapter (encapsula chamadas ao Laravel)
|
|
||||||
[ ] 4. Implementar Frappe Adapter (encapsula chamadas ao ERPNext)
|
|
||||||
[ ] 5. Endpoint GET /api/soe/status (health check de todos os motores)
|
|
||||||
[ ] 6. Migrar /api/fisco/* para passar pelo SOE
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 2 — Central Fiscal (2–3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 7. Implementar Rule Engine para fiscal
|
|
||||||
[ ] 8. Criar regras fiscais base (NCM, CFOP, tributação por regime)
|
|
||||||
[ ] 9. POST /api/soe/fiscal/emitir-nfe → Plus (invisível)
|
|
||||||
[ ] 10. POST /api/soe/fiscal/cancelar-nfe → Plus (invisível)
|
|
||||||
[ ] 11. GET /api/soe/fiscal/situacao → agrega Plus + Python 8002
|
|
||||||
[ ] 12. Atualizar frontend /fisco para usar /api/soe/fiscal/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 3 — Central Contábil (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] 13. Implementar auto-lancamentos para eventos fiscais
|
|
||||||
[ ] 14. Integrar Motor Python 8003 via SOE
|
|
||||||
[ ] 15. GET /api/soe/contabil/dre → resultado automático
|
|
||||||
[ ] 16. GET /api/soe/contabil/balancete → atualizado em tempo real
|
|
||||||
[ ] 17. Atualizar frontend /contabil para usar /api/soe/contabil/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 4 — Central Financeiro (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] 18. Regras de boleto automático (via Asaas)
|
|
||||||
[ ] 19. Alertas de vencimento (via Manus/WhatsApp)
|
|
||||||
[ ] 20. Conciliação bancária semi-automática
|
|
||||||
[ ] 21. Previsão financeira com IA (Motor Python 8003 + Manus)
|
|
||||||
[ ] 22. Atualizar frontend /financeiro para usar /api/soe/financeiro/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 5 — Manus + SOE (1 semana)
|
|
||||||
```
|
|
||||||
[ ] 23. Registrar novas tools Manus apontando para SOE
|
|
||||||
[ ] 24. Manus usa SOE para responder perguntas de negócio
|
|
||||||
[ ] 25. Dashboard SOE: visão geral de todos os eventos
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 6 — Central ERP (3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 26. Frappe Adapter completo (produtos, pedidos, estoque, compras)
|
|
||||||
[ ] 27. Regras de negócio ERP no SOE
|
|
||||||
[ ] 28. Sincronização bidirecional SOE ↔ ERPNext (via eventos)
|
|
||||||
[ ] 29. Atualizar /erp para usar /api/soe/erp/*
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12. RESULTADO FINAL — O QUE O USUÁRIO EXPERIMENTA
|
|
||||||
|
|
||||||
```
|
|
||||||
Antes (fragmentado):
|
|
||||||
Usuário → /plus → vê Laravel diretamente
|
|
||||||
Usuário → /erp → vê ERPNext diretamente
|
|
||||||
Regras fiscais só no Plus
|
|
||||||
Contabilidade manual
|
|
||||||
Financeiro sem automação
|
|
||||||
|
|
||||||
Depois (SOE Central):
|
|
||||||
Usuário → /fisco → emite NF-e, Plus executa invisível
|
|
||||||
Usuário → /contabil → vê DRE gerado automaticamente
|
|
||||||
Usuário → /financeiro → vê fluxo, previsões, alertas automáticos
|
|
||||||
Usuário → Manus → pergunta "qual meu resultado?" → resposta completa
|
|
||||||
|
|
||||||
Plus e ERPNext: INVISÍVEIS, executando em background
|
|
||||||
Regras: CENTRALIZADAS no SOE, editáveis
|
|
||||||
Lançamentos: AUTOMÁTICOS baseados em eventos (NF-e, pagamentos, etc.)
|
|
||||||
Auditoria: TOTAL de todas as operações
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13. PRINCÍPIO ORIENTADOR
|
|
||||||
|
|
||||||
> **"O usuário não sabe o que está por trás. Ele só sabe que funciona."**
|
|
||||||
>
|
|
||||||
> O Arcádia Suite é o **Sistema Operacional** da empresa.
|
|
||||||
> O Plus e o ERPNext são **drivers de hardware** — poderosos, mas invisíveis.
|
|
||||||
> O SOE Central é o **kernel** que os orquestra com regras e inteligência.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*PLANO_SOE_CENTRAL.md — Arcádia Suite v3.0*
|
|
||||||
*Gerado em: 2026-03-16*
|
|
||||||
|
|
@ -1,733 +0,0 @@
|
||||||
# PLANO SOE CENTRAL — Arcádia Suite
|
|
||||||
## Orquestração Inteligente: Plus + ERPNext invisíveis, Central visível
|
|
||||||
### Versão 1.0 — Março 2026
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. ONDE ESTAMOS (Orientação Geral)
|
|
||||||
|
|
||||||
### O Projeto nasceu no Replit como…
|
|
||||||
- Uma plataforma de **escritório empresarial com IA central** (Manus Agent)
|
|
||||||
- Com proxy para o **Arcádia Plus** (Laravel/PHP, porta 8080) — ERP fiscal completo
|
|
||||||
- Com integração ao **ERPNext/Frappe** via API
|
|
||||||
- Stack principal: **React 18 + Express.js + PostgreSQL + FastAPI (Python)**
|
|
||||||
|
|
||||||
### O que JÁ existe e funciona:
|
|
||||||
| Componente | Status | Onde vive |
|
|
||||||
|---|---|---|
|
|
||||||
| Manus Agent (IA, 30+ tools) | ✅ Funcionando | `server/manus/` |
|
|
||||||
| Arcádia Plus (Laravel ERP) | ✅ Funcionando | `plus/` → porta 8080 |
|
|
||||||
| SSO Plus ↔ Suite | ✅ Funcionando | `server/plus/` |
|
|
||||||
| Motor Fiscal (nfelib) | ✅ Funcionando | `server/python/` → porta 8002 |
|
|
||||||
| Motor Contábil | ✅ Funcionando | `server/python/` → porta 8003 |
|
|
||||||
| Motor BI | ✅ Funcionando | `server/python/` → porta 8004 |
|
|
||||||
| Motor Automação | ✅ Funcionando | `server/python/` → porta 8005 |
|
|
||||||
| Motor Comunicação (Comm) | ✅ Funcionando | porta 8006 |
|
|
||||||
| Dev Center XOS (6 agentes) | ✅ Funcionando | `server/blackboard/` |
|
|
||||||
| LiteLLM Gateway | ✅ Configurado | porta 4000 |
|
|
||||||
| CRM, WhatsApp, Chat | ✅ Funcionando | `server/crm/`, `server/whatsapp/` |
|
|
||||||
| ERPNext integração | ⚠️ Parcial | `server/erp/routes.ts` |
|
|
||||||
|
|
||||||
### O que FALTA para o plano atual:
|
|
||||||
| Componente | Status |
|
|
||||||
|---|---|
|
|
||||||
| **SOE Central (Regras Unificadas)** | ❌ Não existe — este é o plano |
|
|
||||||
| Fiscal rules centralizadas (acima do Plus) | ❌ Dispersas no Plus |
|
|
||||||
| ERPNext rules centralizadas | ❌ Não existe camada de abstração |
|
|
||||||
| Contábil Avançado (lançamentos automáticos) | ❌ Motor existe, regras não |
|
|
||||||
| Financeiro Avançado (previsão, DRE automático) | ❌ Motor existe, regras não |
|
|
||||||
| Testes automatizados / CI-CD | ❌ |
|
|
||||||
| Monitoramento (APM, Sentry) | ❌ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. O PROBLEMA QUE VAMOS RESOLVER
|
|
||||||
|
|
||||||
### Situação Atual (problemática)
|
|
||||||
```
|
|
||||||
Usuário → Arcádia Suite
|
|
||||||
├── /plus → acessa Laravel diretamente (usuário VÊ o Plus)
|
|
||||||
├── /erp → acessa ERPNext diretamente (usuário VÊ o ERPNext)
|
|
||||||
└── Regras fiscais ficam dentro do Plus
|
|
||||||
Regras contábeis ficam no Motor 8003
|
|
||||||
Regras ERP ficam no ERPNext
|
|
||||||
→ Fragmentado, sem governança central
|
|
||||||
```
|
|
||||||
|
|
||||||
### Situação Desejada (SOE Central)
|
|
||||||
```
|
|
||||||
Usuário → Arcádia Suite (SOE)
|
|
||||||
│
|
|
||||||
▼ [Central de Regras SOE]
|
|
||||||
├── Fiscal: regras unificadas (CFOP, NCM, tributação, NF-e, CT-e...)
|
|
||||||
├── ERP: regras de negócio (pedidos, estoque, compras...)
|
|
||||||
├── Contábil: regras de lançamentos, plano de contas, DRE...
|
|
||||||
└── Financeiro: regras de fluxo, provisões, conciliação...
|
|
||||||
│
|
|
||||||
▼ [Execução invisível]
|
|
||||||
├── Plus → emite documentos, registra no banco
|
|
||||||
└── ERPNext → executa operações, registra no banco
|
|
||||||
|
|
||||||
O usuário NUNCA VÊ o Plus nem o ERPNext.
|
|
||||||
Só vê a Central SOE do Arcádia.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. ARQUITETURA SOE CENTRAL
|
|
||||||
|
|
||||||
### 3.1 Diagrama Completo
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ ARCÁDIA SUITE (Frontend React) │
|
|
||||||
│ /financeiro /contabil /fisco /erp /people /production /bi │
|
|
||||||
│ Usuário nunca acessa /plus ou ERPNext diretamente │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ SOE — SISTEMA OPERACIONAL EMPRESARIAL (Nova Camada) │
|
|
||||||
│ Express.js / porta 5000 / server/soe/ │
|
|
||||||
│ │
|
|
||||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
||||||
│ │ CENTRAL FISCAL │ │ CENTRAL ERP │ │
|
|
||||||
│ │ server/soe/fiscal/ │ │ server/soe/erp/ │ │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ │ • Regras NCM/CFOP │ │ • Regras de pedidos │ │
|
|
||||||
│ │ • Políticas tribut. │ │ • Regras de estoque │ │
|
|
||||||
│ │ • Emissão NF-e/NFC-e │ │ • Regras de compras │ │
|
|
||||||
│ │ • Cancelamento │ │ • Regras de pessoas │ │
|
|
||||||
│ │ • SPED/SINTEGRA │ │ • Integrações ext. │ │
|
|
||||||
│ └──────────┬───────────┘ └──────────┬─────────────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
│ ┌──────────────────────┐ ┌──────────────────────┐ │
|
|
||||||
│ │ CENTRAL CONTÁBIL │ │ CENTRAL FINANCEIRO │ │
|
|
||||||
│ │ server/soe/contabil/│ │ server/soe/financ/ │ │
|
|
||||||
│ │ │ │ │ │
|
|
||||||
│ │ • Plano de contas │ │ • Fluxo de caixa │ │
|
|
||||||
│ │ • Regras de lanç. │ │ • Contas a P/R │ │
|
|
||||||
│ │ • DRE automático │ │ • Conciliação │ │
|
|
||||||
│ │ • Balancete │ │ • Previsão (IA) │ │
|
|
||||||
│ │ • Fechamento │ │ • Impostos │ │
|
|
||||||
│ └──────────┬───────────┘ └──────────┬─────────────┘ │
|
|
||||||
│ │ │ │
|
|
||||||
│ └────────────┬─────────────┘ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────────────────────┐ │
|
|
||||||
│ │ SOE RULE ENGINE (Núcleo) │ │
|
|
||||||
│ │ server/soe/rule-engine.ts │ │
|
|
||||||
│ │ │ │
|
|
||||||
│ │ • Resolução de conflitos │ │
|
|
||||||
│ │ • Aplicação de políticas XOS │ │
|
|
||||||
│ │ • Audit trail de todas regras │ │
|
|
||||||
│ │ • Manus consulta este engine │ │
|
|
||||||
│ └─────────────────┬───────────────┘ │
|
|
||||||
└────────────────────────────┼────────────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
┌──────────────┼───────────────┐
|
|
||||||
▼ ▼ ▼
|
|
||||||
┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐
|
|
||||||
│ ARCÁDIA PLUS │ │ ERPNEXT │ │ MOTORES PYTHON │
|
|
||||||
│ Laravel :8080 │ │ Frappe : │ │ 8002 Fiscal │
|
|
||||||
│ (invisível) │ │ (invisível) │ │ 8003 Contábil │
|
|
||||||
│ │ │ │ │ 8004 BI │
|
|
||||||
│ Emite docs │ │ Executa ERP │ │ 8005 Automação │
|
|
||||||
│ fiscais │ │ operacional │ │ │
|
|
||||||
└─────────────────┘ └──────────────┘ └──────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. CENTRAL FISCAL — Detalhamento
|
|
||||||
|
|
||||||
### 4.1 O que ela resolve
|
|
||||||
O Plus tem **376 controllers** e **1.546 rotas** — tudo fiscal/operacional. A Central Fiscal **não substitui** o Plus, ela **orquestra** o Plus com regras definidas no SOE.
|
|
||||||
|
|
||||||
### 4.2 Regras que vão para a Central (tiradas do Plus)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/fiscal/rules.ts — Exemplo de estrutura
|
|
||||||
|
|
||||||
interface FiscalRule {
|
|
||||||
id: string
|
|
||||||
nome: string
|
|
||||||
trigger: 'pre_emissao' | 'pos_emissao' | 'cancelamento' | 'validacao'
|
|
||||||
condicao: FiscalCondition
|
|
||||||
acao: FiscalAction
|
|
||||||
prioridade: number
|
|
||||||
ativo: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exemplos de regras:
|
|
||||||
const REGRAS_FISCAIS: FiscalRule[] = [
|
|
||||||
{
|
|
||||||
id: 'NFE_CFOP_INTERESTADUAL',
|
|
||||||
nome: 'Ajusta CFOP para operação interestadual',
|
|
||||||
trigger: 'pre_emissao',
|
|
||||||
condicao: { uf_emitente: '!=', uf_destinatario: true },
|
|
||||||
acao: { ajustar_cfop: 'interestadual' },
|
|
||||||
prioridade: 1,
|
|
||||||
ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NFE_SIMPLES_NACIONAL',
|
|
||||||
nome: 'Aplica tributação Simples Nacional',
|
|
||||||
trigger: 'pre_emissao',
|
|
||||||
condicao: { regime_tributario: 'simples_nacional' },
|
|
||||||
acao: { aplicar_cst: 'tabela_simples', remover_pis_cofins: true },
|
|
||||||
prioridade: 2,
|
|
||||||
ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NFE_VALIDACAO_NCM',
|
|
||||||
nome: 'Valida NCM obrigatório para NF-e',
|
|
||||||
trigger: 'validacao',
|
|
||||||
condicao: { tipo_documento: 'nfe' },
|
|
||||||
acao: { validar_campo: 'ncm', obrigatorio: true },
|
|
||||||
prioridade: 1,
|
|
||||||
ativo: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 Fluxo de Emissão via SOE Central
|
|
||||||
|
|
||||||
```
|
|
||||||
Usuário clica "Emitir NF-e" no Arcádia
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
POST /api/soe/fiscal/emitir-nfe
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE Rule Engine: aplica REGRAS_FISCAIS (pre_emissao)
|
|
||||||
• Verifica regime tributário
|
|
||||||
• Aplica CFOP correto
|
|
||||||
• Calcula impostos (ICMS, PIS, COFINS, IPI)
|
|
||||||
• Valida NCM obrigatório
|
|
||||||
• Adiciona dados da empresa emitente
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE envia para Plus via API interna (invisível)
|
|
||||||
POST http://plus:8080/api/nfe/emitir
|
|
||||||
+ token SSO automático
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Plus emite via Cloud-DFE → SEFAZ
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE recebe retorno
|
|
||||||
• Registra no banco SOE (tabela soe_fiscal_eventos)
|
|
||||||
• Dispara lançamento contábil automático
|
|
||||||
• Notifica via WebSocket o frontend
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Usuário vê resultado no Arcádia (nunca soube do Plus)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 Tabelas SOE para Fiscal
|
|
||||||
|
|
||||||
```sql
|
|
||||||
-- Tabelas a criar no schema Arcádia (PostgreSQL)
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_regras (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
nome VARCHAR(200) NOT NULL,
|
|
||||||
trigger VARCHAR(50) NOT NULL,
|
|
||||||
condicao JSONB NOT NULL,
|
|
||||||
acao JSONB NOT NULL,
|
|
||||||
prioridade INTEGER DEFAULT 10,
|
|
||||||
ativo BOOLEAN DEFAULT true,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_eventos (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
tipo VARCHAR(50) NOT NULL, -- 'emissao_nfe', 'cancelamento', etc.
|
|
||||||
empresa_id INTEGER NOT NULL,
|
|
||||||
documento_chave VARCHAR(100),
|
|
||||||
regras_aplicadas JSONB, -- quais regras foram aplicadas
|
|
||||||
payload_enviado JSONB, -- o que foi enviado ao Plus
|
|
||||||
payload_retorno JSONB, -- o que o Plus/SEFAZ respondeu
|
|
||||||
status VARCHAR(50) NOT NULL,
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE TABLE soe_fiscal_configuracoes (
|
|
||||||
empresa_id INTEGER PRIMARY KEY,
|
|
||||||
regime_tributario VARCHAR(50), -- simples, lucro_presumido, lucro_real
|
|
||||||
uf VARCHAR(2),
|
|
||||||
cnpj VARCHAR(18),
|
|
||||||
certificado_tipo VARCHAR(20),
|
|
||||||
aliquotas JSONB, -- alíquotas padrão por operação
|
|
||||||
cfops_padrao JSONB, -- CFOPs padrão por tipo de operação
|
|
||||||
created_at TIMESTAMP DEFAULT NOW()
|
|
||||||
);
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. CENTRAL ERP (ERPNext/Frappe) — Detalhamento
|
|
||||||
|
|
||||||
### 5.1 O que ela resolve
|
|
||||||
O ERPNext tem **APIs complexas**. A Central ERP abstrai tudo isso em operações simples que o Arcádia entende.
|
|
||||||
|
|
||||||
### 5.2 Adapter Layer ERPNext
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/erp/frappe-adapter.ts
|
|
||||||
|
|
||||||
interface ERPAdapter {
|
|
||||||
// Produtos
|
|
||||||
criarProduto(data: ProdutoSOE): Promise<ERPProduto>
|
|
||||||
buscarProduto(codigo: string): Promise<ProdutoSOE>
|
|
||||||
atualizarEstoque(movimentacao: MovimentacaoEstoque): Promise<void>
|
|
||||||
|
|
||||||
// Pedidos
|
|
||||||
criarPedidoVenda(pedido: PedidoSOE): Promise<ERPPedido>
|
|
||||||
aprovarPedido(id: string): Promise<void>
|
|
||||||
faturarPedido(id: string): Promise<ERPFatura>
|
|
||||||
|
|
||||||
// Financeiro
|
|
||||||
criarLancamento(lancamento: LancamentoSOE): Promise<ERPLancamento>
|
|
||||||
buscarPlanoContas(): Promise<ContaContabil[]>
|
|
||||||
|
|
||||||
// Compras
|
|
||||||
criarPedidoCompra(data: PedidoCompraSOE): Promise<ERPPedidoCompra>
|
|
||||||
receberMercadoria(data: RecebimentoSOE): Promise<void>
|
|
||||||
}
|
|
||||||
|
|
||||||
// As regras ficam no SOE, o adapter só traduz
|
|
||||||
class FrappeAdapter implements ERPAdapter {
|
|
||||||
private baseUrl: string
|
|
||||||
private apiKey: string
|
|
||||||
|
|
||||||
async criarPedidoVenda(pedido: PedidoSOE): Promise<ERPPedido> {
|
|
||||||
// Traduz do modelo SOE para o modelo Frappe
|
|
||||||
const frappePedido = this.traduzirParaFrappe(pedido)
|
|
||||||
|
|
||||||
// Envia para ERPNext (invisível para o usuário)
|
|
||||||
const response = await fetch(`${this.baseUrl}/api/resource/Sales Order`, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Authorization': `token ${this.apiKey}` },
|
|
||||||
body: JSON.stringify(frappePedido)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Traduz retorno de volta para modelo SOE
|
|
||||||
return this.traduzirDeVoltaSOE(await response.json())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5.3 Regras de Negócio ERP no SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/erp/rules.ts
|
|
||||||
|
|
||||||
const REGRAS_ERP = [
|
|
||||||
{
|
|
||||||
id: 'PEDIDO_APROVACAO_AUTOMATICA',
|
|
||||||
nome: 'Aprovação automática até R$ 5.000',
|
|
||||||
trigger: 'pre_aprovacao_pedido',
|
|
||||||
condicao: { valor_total: { menor_que: 5000 } },
|
|
||||||
acao: { aprovar_automaticamente: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ESTOQUE_RESERVA_VENDA',
|
|
||||||
nome: 'Reservar estoque ao confirmar venda',
|
|
||||||
trigger: 'pos_confirmacao_venda',
|
|
||||||
condicao: { status: 'confirmado' },
|
|
||||||
acao: { reservar_estoque: true, gerar_separacao: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'NF_AUTOMATICA_FATURAMENTO',
|
|
||||||
nome: 'Emite NF-e automaticamente ao faturar',
|
|
||||||
trigger: 'pos_faturamento',
|
|
||||||
condicao: { tipo_cliente: ['pj', 'pf_contribuinte'] },
|
|
||||||
acao: { emitir_nfe: true, via_soe_fiscal: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. CENTRAL CONTÁBIL AVANÇADA
|
|
||||||
|
|
||||||
### 6.1 Motor Atual (porta 8003) + Regras SOE
|
|
||||||
|
|
||||||
O Motor Contábil Python já faz DRE e Balancete. O que falta é **alimentação automática**.
|
|
||||||
|
|
||||||
### 6.2 Lançamentos Automáticos (grande salto)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/contabil/auto-lancamentos.ts
|
|
||||||
|
|
||||||
interface RegrasLancamentoAuto {
|
|
||||||
gatilho: string
|
|
||||||
debito: string // Conta contábil
|
|
||||||
credito: string // Conta contábil
|
|
||||||
historico: string
|
|
||||||
formula: string // Como calcular o valor
|
|
||||||
}
|
|
||||||
|
|
||||||
const LANCAMENTOS_AUTOMATICOS: RegrasLancamentoAuto[] = [
|
|
||||||
// Quando emite NF-e de venda
|
|
||||||
{
|
|
||||||
gatilho: 'emissao_nfe_venda',
|
|
||||||
debito: '1.1.3.01', // Clientes
|
|
||||||
credito: '3.1.1.01', // Receita Bruta de Vendas
|
|
||||||
historico: 'Venda conforme NF-e {numero}',
|
|
||||||
formula: 'valor_total_nota'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
gatilho: 'emissao_nfe_venda',
|
|
||||||
debito: '3.1.2.01', // Dedução de Receita (ICMS)
|
|
||||||
credito: '2.1.2.01', // ICMS a Recolher
|
|
||||||
historico: 'ICMS s/ Venda NF-e {numero}',
|
|
||||||
formula: 'valor_icms'
|
|
||||||
},
|
|
||||||
// Quando paga conta
|
|
||||||
{
|
|
||||||
gatilho: 'pagamento_conta',
|
|
||||||
debito: '2.1.1.{categoria}', // Conta a Pagar específica
|
|
||||||
credito: '1.1.1.01', // Banco/Caixa
|
|
||||||
historico: 'Pagamento: {descricao}',
|
|
||||||
formula: 'valor_pago'
|
|
||||||
},
|
|
||||||
// Quando recebe pagamento
|
|
||||||
{
|
|
||||||
gatilho: 'recebimento',
|
|
||||||
debito: '1.1.1.01', // Banco/Caixa
|
|
||||||
credito: '1.1.3.01', // Clientes
|
|
||||||
historico: 'Recebimento: {descricao}',
|
|
||||||
formula: 'valor_recebido'
|
|
||||||
},
|
|
||||||
// Compra de mercadoria
|
|
||||||
{
|
|
||||||
gatilho: 'entrada_nfe_compra',
|
|
||||||
debito: '1.1.4.01', // Estoque
|
|
||||||
credito: '2.1.1.01', // Fornecedores
|
|
||||||
historico: 'Compra conforme NF-e {numero} / {fornecedor}',
|
|
||||||
formula: 'valor_mercadorias'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6.3 DRE Automático via SOE
|
|
||||||
|
|
||||||
```
|
|
||||||
Usuário pede DRE do mês
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE Contábil consulta:
|
|
||||||
1. Todos lançamentos do período (tabela soe_lancamentos)
|
|
||||||
2. Agrupa por conta contábil
|
|
||||||
3. Aplica estrutura DRE configurada
|
|
||||||
4. Envia para Motor Python 8003 para cálculos
|
|
||||||
5. Retorna DRE formatado
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Usuário vê DRE no /contabil do Arcádia
|
|
||||||
(Nunca soube que teve lançamentos automáticos de NF-e, pagamentos, etc.)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. CENTRAL FINANCEIRO AVANÇADO
|
|
||||||
|
|
||||||
### 7.1 Regras Financeiras no SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/financeiro/rules.ts
|
|
||||||
|
|
||||||
const REGRAS_FINANCEIRO = [
|
|
||||||
{
|
|
||||||
id: 'BOLETO_AUTO_VENCIMENTO',
|
|
||||||
nome: 'Gerar boleto automático para vendas a prazo',
|
|
||||||
trigger: 'pos_confirmacao_venda_prazo',
|
|
||||||
acao: { gerar_boleto: true, via: 'asaas', vencimento: '+{prazo}_dias' }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'ALERTA_VENCIMENTO_3DIAS',
|
|
||||||
nome: 'Alerta de vencimento 3 dias antes',
|
|
||||||
trigger: 'cron_diario',
|
|
||||||
condicao: { vencimento_em: 3 },
|
|
||||||
acao: { notificar: ['whatsapp', 'email'], via_manus: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'PROVISAO_IMPOSTOS',
|
|
||||||
nome: 'Provisão mensal de impostos',
|
|
||||||
trigger: 'cron_mensal',
|
|
||||||
acao: { calcular_provisao: ['icms', 'pis', 'cofins', 'csll', 'irpj'], registrar_lancamento: true }
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'CONCILIACAO_AUTO',
|
|
||||||
nome: 'Conciliação bancária automática via OFX',
|
|
||||||
trigger: 'importacao_ofx',
|
|
||||||
acao: { tentar_conciliar: true, confianca_minima: 0.85, pendentes_para_revisao: true }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. MANUS AGENT + SOE CENTRAL
|
|
||||||
|
|
||||||
### 8.1 O Manus consulta a Central
|
|
||||||
|
|
||||||
```
|
|
||||||
Pergunta: "Qual foi o resultado do mês passado?"
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Manus → SOE Central
|
|
||||||
• GET /api/soe/contabil/dre?periodo=2026-02
|
|
||||||
• GET /api/soe/financeiro/fluxo?periodo=2026-02
|
|
||||||
• GET /api/soe/fiscal/resumo?periodo=2026-02
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
SOE agrega dados dos motores (Python) + Plus + ERPNext
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Manus recebe contexto completo e responde:
|
|
||||||
"Faturamento: R$ 120.000
|
|
||||||
Deduções (impostos): R$ 18.000
|
|
||||||
Receita Líquida: R$ 102.000
|
|
||||||
Custo das mercadorias: R$ 65.000
|
|
||||||
Lucro Bruto: R$ 37.000
|
|
||||||
..."
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8.2 Tools do Manus para o SOE
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// Novas tools do Manus que consultam o SOE Central
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'consultar_situacao_fiscal',
|
|
||||||
description: 'Consulta situação fiscal da empresa (NFs pendentes, impostos, SPED)',
|
|
||||||
endpoint: 'GET /api/soe/fiscal/situacao'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'emitir_documento_fiscal',
|
|
||||||
description: 'Emite NF-e, NFC-e, CT-e ou MDF-e',
|
|
||||||
endpoint: 'POST /api/soe/fiscal/emitir'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'consultar_dre',
|
|
||||||
description: 'Gera DRE de qualquer período',
|
|
||||||
endpoint: 'GET /api/soe/contabil/dre'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'consultar_fluxo_caixa',
|
|
||||||
description: 'Consulta fluxo de caixa e previsões',
|
|
||||||
endpoint: 'GET /api/soe/financeiro/fluxo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'registrar_lancamento_contabil',
|
|
||||||
description: 'Registra lançamento contábil manualmente',
|
|
||||||
endpoint: 'POST /api/soe/contabil/lancamento'
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. ESTRUTURA DE PASTAS A CRIAR
|
|
||||||
|
|
||||||
```
|
|
||||||
server/
|
|
||||||
└── soe/ ← Nova pasta (Central SOE)
|
|
||||||
├── index.ts ← Router principal do SOE
|
|
||||||
├── rule-engine.ts ← Motor de regras central
|
|
||||||
│
|
|
||||||
├── fiscal/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/fiscal/*
|
|
||||||
│ ├── rules.ts ← Regras fiscais (CFOP, NCM, tributação)
|
|
||||||
│ ├── emissao.ts ← Orquestração de emissão (→ Plus)
|
|
||||||
│ ├── plus-adapter.ts ← Adaptador para o Plus (invisível)
|
|
||||||
│ └── sefaz-adapter.ts ← Comunicação direta SEFAZ (via Python 8002)
|
|
||||||
│
|
|
||||||
├── erp/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/erp/*
|
|
||||||
│ ├── rules.ts ← Regras de negócio ERP
|
|
||||||
│ ├── frappe-adapter.ts ← Adaptador ERPNext (invisível)
|
|
||||||
│ └── plus-erp-adapter.ts ← Adaptador Plus-ERP (para dados de venda)
|
|
||||||
│
|
|
||||||
├── contabil/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/contabil/*
|
|
||||||
│ ├── rules.ts ← Regras contábeis
|
|
||||||
│ ├── auto-lancamentos.ts ← Lançamentos automáticos
|
|
||||||
│ ├── plano-contas.ts ← Plano de contas SOE
|
|
||||||
│ └── python-adapter.ts ← Adaptador Motor Python 8003
|
|
||||||
│
|
|
||||||
├── financeiro/
|
|
||||||
│ ├── routes.ts ← GET/POST /api/soe/financeiro/*
|
|
||||||
│ ├── rules.ts ← Regras financeiras
|
|
||||||
│ ├── previsao.ts ← Previsão com IA
|
|
||||||
│ └── conciliacao.ts ← Conciliação bancária
|
|
||||||
│
|
|
||||||
└── shared/
|
|
||||||
├── types.ts ← Tipos SOE compartilhados
|
|
||||||
├── audit.ts ← Registro de todas as operações
|
|
||||||
└── event-bus.ts ← Eventos entre Centrais
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. TABELAS DO BANCO A CRIAR (Drizzle ORM)
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// shared/schema.ts — Adicionar:
|
|
||||||
|
|
||||||
// Configuração da empresa no SOE
|
|
||||||
export const soeEmpresaConfig = pgTable('soe_empresa_config', {
|
|
||||||
id: serial('id').primaryKey(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
regimeTributario: varchar('regime_tributario', { length: 50 }), // simples, presumido, real
|
|
||||||
uf: varchar('uf', { length: 2 }),
|
|
||||||
cnpj: varchar('cnpj', { length: 18 }),
|
|
||||||
planoContasId: integer('plano_contas_id'),
|
|
||||||
configFiscal: jsonb('config_fiscal'), // alíquotas, CFOPs padrão
|
|
||||||
configErp: jsonb('config_erp'), // qual ERP: plus, erpnext, ambos
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Regras configuráveis (editáveis pelo usuário)
|
|
||||||
export const soeRegras = pgTable('soe_regras', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id'), // null = regra global
|
|
||||||
dominio: varchar('dominio', { length: 50 }).notNull(), // 'fiscal', 'erp', 'contabil', 'financeiro'
|
|
||||||
nome: varchar('nome', { length: 200 }).notNull(),
|
|
||||||
trigger: varchar('trigger', { length: 100 }).notNull(),
|
|
||||||
condicao: jsonb('condicao').notNull(),
|
|
||||||
acao: jsonb('acao').notNull(),
|
|
||||||
prioridade: integer('prioridade').default(10),
|
|
||||||
ativo: boolean('ativo').default(true),
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Log de todas as operações SOE (audit trail)
|
|
||||||
export const soeEventos = pgTable('soe_eventos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
dominio: varchar('dominio', { length: 50 }).notNull(),
|
|
||||||
tipo: varchar('tipo', { length: 100 }).notNull(),
|
|
||||||
regraIds: jsonb('regra_ids'), // regras aplicadas
|
|
||||||
payloadEntrada: jsonb('payload_entrada'),
|
|
||||||
payloadSaida: jsonb('payload_saida'),
|
|
||||||
erp: varchar('erp', { length: 50 }), // 'plus', 'erpnext', 'python_8003', etc.
|
|
||||||
status: varchar('status', { length: 50 }).notNull(),
|
|
||||||
duracao: integer('duracao'), // ms
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Lançamentos contábeis centralizados
|
|
||||||
export const soeLancamentos = pgTable('soe_lancamentos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
data: date('data').notNull(),
|
|
||||||
contaDebito: varchar('conta_debito', { length: 30 }).notNull(),
|
|
||||||
contaCredito: varchar('conta_credito', { length: 30 }).notNull(),
|
|
||||||
valor: numeric('valor', { precision: 15, scale: 2 }).notNull(),
|
|
||||||
historico: text('historico').notNull(),
|
|
||||||
origem: varchar('origem', { length: 100 }), // 'emissao_nfe', 'pagamento', etc.
|
|
||||||
origemId: varchar('origem_id', { length: 100 }),
|
|
||||||
period: varchar('period', { length: 7 }), // '2026-03'
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11. ROADMAP DE IMPLEMENTAÇÃO
|
|
||||||
|
|
||||||
### Fase 1 — Fundação (2–3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 1. Criar server/soe/ com estrutura básica
|
|
||||||
[ ] 2. Criar tabelas: soe_empresa_config, soe_regras, soe_eventos, soe_lancamentos
|
|
||||||
[ ] 3. Implementar Plus Adapter (encapsula chamadas ao Laravel)
|
|
||||||
[ ] 4. Implementar Frappe Adapter (encapsula chamadas ao ERPNext)
|
|
||||||
[ ] 5. Endpoint GET /api/soe/status (health check de todos os motores)
|
|
||||||
[ ] 6. Migrar /api/fisco/* para passar pelo SOE
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 2 — Central Fiscal (2–3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 7. Implementar Rule Engine para fiscal
|
|
||||||
[ ] 8. Criar regras fiscais base (NCM, CFOP, tributação por regime)
|
|
||||||
[ ] 9. POST /api/soe/fiscal/emitir-nfe → Plus (invisível)
|
|
||||||
[ ] 10. POST /api/soe/fiscal/cancelar-nfe → Plus (invisível)
|
|
||||||
[ ] 11. GET /api/soe/fiscal/situacao → agrega Plus + Python 8002
|
|
||||||
[ ] 12. Atualizar frontend /fisco para usar /api/soe/fiscal/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 3 — Central Contábil (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] 13. Implementar auto-lancamentos para eventos fiscais
|
|
||||||
[ ] 14. Integrar Motor Python 8003 via SOE
|
|
||||||
[ ] 15. GET /api/soe/contabil/dre → resultado automático
|
|
||||||
[ ] 16. GET /api/soe/contabil/balancete → atualizado em tempo real
|
|
||||||
[ ] 17. Atualizar frontend /contabil para usar /api/soe/contabil/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 4 — Central Financeiro (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] 18. Regras de boleto automático (via Asaas)
|
|
||||||
[ ] 19. Alertas de vencimento (via Manus/WhatsApp)
|
|
||||||
[ ] 20. Conciliação bancária semi-automática
|
|
||||||
[ ] 21. Previsão financeira com IA (Motor Python 8003 + Manus)
|
|
||||||
[ ] 22. Atualizar frontend /financeiro para usar /api/soe/financeiro/*
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 5 — Manus + SOE (1 semana)
|
|
||||||
```
|
|
||||||
[ ] 23. Registrar novas tools Manus apontando para SOE
|
|
||||||
[ ] 24. Manus usa SOE para responder perguntas de negócio
|
|
||||||
[ ] 25. Dashboard SOE: visão geral de todos os eventos
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 6 — Central ERP (3 semanas)
|
|
||||||
```
|
|
||||||
[ ] 26. Frappe Adapter completo (produtos, pedidos, estoque, compras)
|
|
||||||
[ ] 27. Regras de negócio ERP no SOE
|
|
||||||
[ ] 28. Sincronização bidirecional SOE ↔ ERPNext (via eventos)
|
|
||||||
[ ] 29. Atualizar /erp para usar /api/soe/erp/*
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12. RESULTADO FINAL — O QUE O USUÁRIO EXPERIMENTA
|
|
||||||
|
|
||||||
```
|
|
||||||
Antes (fragmentado):
|
|
||||||
Usuário → /plus → vê Laravel diretamente
|
|
||||||
Usuário → /erp → vê ERPNext diretamente
|
|
||||||
Regras fiscais só no Plus
|
|
||||||
Contabilidade manual
|
|
||||||
Financeiro sem automação
|
|
||||||
|
|
||||||
Depois (SOE Central):
|
|
||||||
Usuário → /fisco → emite NF-e, Plus executa invisível
|
|
||||||
Usuário → /contabil → vê DRE gerado automaticamente
|
|
||||||
Usuário → /financeiro → vê fluxo, previsões, alertas automáticos
|
|
||||||
Usuário → Manus → pergunta "qual meu resultado?" → resposta completa
|
|
||||||
|
|
||||||
Plus e ERPNext: INVISÍVEIS, executando em background
|
|
||||||
Regras: CENTRALIZADAS no SOE, editáveis
|
|
||||||
Lançamentos: AUTOMÁTICOS baseados em eventos (NF-e, pagamentos, etc.)
|
|
||||||
Auditoria: TOTAL de todas as operações
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13. PRINCÍPIO ORIENTADOR
|
|
||||||
|
|
||||||
> **"O usuário não sabe o que está por trás. Ele só sabe que funciona."**
|
|
||||||
>
|
|
||||||
> O Arcádia Suite é o **Sistema Operacional** da empresa.
|
|
||||||
> O Plus e o ERPNext são **drivers de hardware** — poderosos, mas invisíveis.
|
|
||||||
> O SOE Central é o **kernel** que os orquestra com regras e inteligência.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*PLANO_SOE_CENTRAL.md — Arcádia Suite v3.0*
|
|
||||||
*Gerado em: 2026-03-16*
|
|
||||||
|
|
@ -1,666 +0,0 @@
|
||||||
# PLANO SOE CENTRAL v2 — Análise Real + Evolução
|
|
||||||
## Baseado no MAPA_SOE_ARCADIA.md (Replit) + Auditoria do Código
|
|
||||||
### Versão 2.0 — Março 2026
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1. DIAGNÓSTICO — O QUE JÁ EXISTE (e o plano v1 não sabia)
|
|
||||||
|
|
||||||
O MAPA_SOE_ARCADIA.md do Replit revelou que **o SOE já é uma realidade arquitetural robusta**, não apenas um conceito. Antes de planejar qualquer coisa, é crítico entender o que já funciona.
|
|
||||||
|
|
||||||
### 1.1 O que já está construído e funcionando
|
|
||||||
|
|
||||||
| Componente | Status | Localização |
|
|
||||||
|---|---|---|
|
|
||||||
| `SOE.tsx` | ✅ 2.414 linhas — UI completa com 9 tabs | `client/src/pages/SOE.tsx` |
|
|
||||||
| `SoeMotorContext.tsx` | ✅ Seletor de motor (plus/erpnext) | `client/src/contexts/` |
|
|
||||||
| `ErpApiClient` (interface) | ✅ Interface unificada definida | `server/erp/index.ts` |
|
|
||||||
| `ArcadiaPlusClient` | ✅ Adaptador HTTP → Plus:8080 | `server/erp/index.ts` |
|
|
||||||
| `ArcadiaNextClient` | ✅ Adaptador HTTP → ERPNext API | `server/erp/index.ts` |
|
|
||||||
| `registerSoeRoutes()` | ✅ 60+ endpoints em /api/soe/* | `server/erp/routes.ts` |
|
|
||||||
| `server/plus/proxy.ts` | ✅ Proxy reverso para Plus | `server/plus/` |
|
|
||||||
| `server/plus/sso.ts` | ✅ SSO automático Plus ↔ Suite | `server/plus/` |
|
|
||||||
| `server/plus/launcher.ts` | ✅ Lança PHP artisan serve | `server/plus/` |
|
|
||||||
| Módulo de Pessoas unificado | ✅ `persons` + `person_roles` | Schema PostgreSQL |
|
|
||||||
| Módulo de Produtos | ✅ Com NCM, CST, CFOP, IMEI | Schema PostgreSQL |
|
|
||||||
| Módulo Financeiro | ✅ Contas a P/R + transações | Schema PostgreSQL |
|
|
||||||
| Motor Fisco (:8002) | ✅ NF-e/NFC-e via nfelib | `server/python/` |
|
|
||||||
| Motor Contábil (:8003) | ✅ DRE, Balanço, SPED | `server/python/` |
|
|
||||||
| Sistema de módulos por tenant | ✅ `tenants.features` (JSONB) | Schema PostgreSQL |
|
|
||||||
| Middleware de gating | ✅ `requireModule()` | `server/` |
|
|
||||||
|
|
||||||
### 1.2 Bancos de Dados por Motor (detalhe crítico)
|
|
||||||
|
|
||||||
```
|
|
||||||
Arcádia Suite → PostgreSQL 16 (dados do SOE, pessoas, produtos, vendas...)
|
|
||||||
Arcádia Plus → MySQL 8.0 (dados do Laravel — vendas, estoque, NF-e...)
|
|
||||||
ERPNext → MariaDB (dados do Frappe — CRM, HR, projetos...)
|
|
||||||
Motor Fisco → sem banco (só processa, retorna resultado)
|
|
||||||
Motor Contábil → sem banco (só processa, retorna resultado)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Implicação:** Não há sincronização automática entre esses bancos. Um pedido criado no SOE (PostgreSQL) não aparece no Plus (MySQL) automaticamente — e vice-versa.
|
|
||||||
|
|
||||||
### 1.3 O padrão motor/adaptador atual
|
|
||||||
|
|
||||||
```
|
|
||||||
Request do usuário
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
/api/soe/sales-orders (POST)
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
Verifica motor ativo (localStorage: arcadia_soe_motor)
|
|
||||||
│
|
|
||||||
├── motor = "local" → INSERT direto no PostgreSQL
|
|
||||||
├── motor = "plus" → POST → Plus:8080 → MySQL
|
|
||||||
└── motor = "erpnext" → POST → ERPNext API → MariaDB
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2. O PROBLEMA REAL — Onde o SOE atual para
|
|
||||||
|
|
||||||
O SOE atual é um **roteador inteligente**: recebe o request, decide para qual motor enviar, e despacha. Ele **não tem inteligência própria**.
|
|
||||||
|
|
||||||
### 2.1 O que falta (lacuna real)
|
|
||||||
|
|
||||||
```
|
|
||||||
Situação atual:
|
|
||||||
|
|
||||||
SOE.tsx → /api/soe/* ────────────────────────────► Plus/ERPNext
|
|
||||||
(sem regras, sem processamento)
|
|
||||||
Regras ficam DENTRO do Plus
|
|
||||||
Regras ficam DENTRO do ERPNext
|
|
||||||
|
|
||||||
Situação desejada:
|
|
||||||
|
|
||||||
SOE.tsx → /api/soe/* → [RULE ENGINE SOE] ──────► Plus/ERPNext
|
|
||||||
│ (só executa)
|
|
||||||
├── Regras Fiscais
|
|
||||||
├── Regras Contábeis
|
|
||||||
├── Regras Financeiras
|
|
||||||
└── Regras de Negócio
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2.2 Problemas concretos hoje
|
|
||||||
|
|
||||||
| Problema | Impacto |
|
|
||||||
|---|---|
|
|
||||||
| Fiscal rules dentro do Plus | Se trocar de motor (Plus→ERPNext), perde todas as regras |
|
|
||||||
| Nenhum lançamento contábil automático | DRE fica vazio, contabilidade manual |
|
|
||||||
| Motor Contábil (:8003) existe mas nada alimenta ele | 0 lançamentos automáticos |
|
|
||||||
| Plus tem UI própria (/plus) | Usuário pode bypassar o SOE e ir direto ao Plus |
|
|
||||||
| Sem event bus entre motores | Uma NF-e emitida no Plus não dispara nada no SOE |
|
|
||||||
| 25 conectores ERP definidos, zero chamadas reais | Integração existe no papel, não funciona |
|
|
||||||
|
|
||||||
### 2.3 O que o usuário vê hoje vs o que deveria ver
|
|
||||||
|
|
||||||
```
|
|
||||||
Hoje:
|
|
||||||
/soe → UI do SOE (tabs: dashboard, pessoas, produtos, vendas...)
|
|
||||||
/plus → UI do Plus (Laravel) — direto, sem passar pelo SOE
|
|
||||||
/erp → UI do ERP legado
|
|
||||||
(usuário VÊ o Plus se quiser)
|
|
||||||
|
|
||||||
Desejado:
|
|
||||||
/soe → UI do SOE (mesma, mas com inteligência)
|
|
||||||
/plus → BLOQUEADO ou redirecionado para /soe
|
|
||||||
/erp → BLOQUEADO ou redirecionado para /soe
|
|
||||||
(Plus e ERPNext = invisíveis, executando em background)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3. ARQUITETURA EVOLUÍDA — SOE com Rule Engine
|
|
||||||
|
|
||||||
### 3.1 O que muda (e o que fica igual)
|
|
||||||
|
|
||||||
**NÃO MUDA:**
|
|
||||||
- `SOE.tsx` — a UI continua a mesma (só ganha funcionalidades)
|
|
||||||
- `SoeMotorContext.tsx` — seleção de motor continua existindo
|
|
||||||
- `ArcadiaPlusClient` / `ArcadiaNextClient` — adaptadores continuam
|
|
||||||
- Todas as rotas `/api/soe/*` — continuam funcionando
|
|
||||||
- Todos os bancos — PostgreSQL, MySQL, MariaDB — continuam separados
|
|
||||||
|
|
||||||
**MUDA / ADICIONA:**
|
|
||||||
- Uma **camada de Rule Engine** entre as rotas e os adaptadores
|
|
||||||
- **Event Bus SOE** que dispara lançamentos contábeis automaticamente
|
|
||||||
- **Ocultação do Plus** — `/plus` passa a ser controlado pelo SOE
|
|
||||||
- **Regras fiscais** saem do Plus e entram no SOE
|
|
||||||
|
|
||||||
### 3.2 Diagrama completo com Rule Engine
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ ARCÁDIA SUITE — CAMADA DE APRESENTAÇÃO │
|
|
||||||
│ │
|
|
||||||
│ SOE.tsx (2.414+ linhas) │
|
|
||||||
│ Tabs: Dashboard | Pessoas | Produtos | Vendas | Compras │
|
|
||||||
│ Financeiro | CRM | Sincronização | Config │
|
|
||||||
│ │
|
|
||||||
│ SoeMotorContext.tsx → motor = "plus" | "erpnext" | "local" │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ /api/soe/* — CAMADA DE API (já existe) │
|
|
||||||
│ registerSoeRoutes() em server/erp/routes.ts │
|
|
||||||
│ requireAuth + requireModule middleware │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼ ◄── INSERIR AQUI (novo)
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ SOE RULE ENGINE (NOVO) │
|
|
||||||
│ server/soe/rule-engine/ │
|
|
||||||
│ │
|
|
||||||
│ Antes de despachar para o motor, o Rule Engine: │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ 1. FISCAL RULES (server/soe/rule-engine/fiscal.ts) │ │
|
|
||||||
│ │ • Resolve CFOP correto (intra/interestadual) │ │
|
|
||||||
│ │ • Aplica tributação por regime (Simples/Presumido/Real) │ │
|
|
||||||
│ │ • Valida NCM obrigatório │ │
|
|
||||||
│ │ • Define CST/CSOSN automático │ │
|
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ 2. BUSINESS RULES (server/soe/rule-engine/business.ts) │ │
|
|
||||||
│ │ • Aprovação automática de pedidos < R$ X │ │
|
|
||||||
│ │ • Reserva de estoque ao confirmar venda │ │
|
|
||||||
│ │ • Trigger de NF-e ao faturar pedido │ │
|
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
|
||||||
│ │
|
|
||||||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
|
||||||
│ │ 3. ACCOUNTING RULES (server/soe/rule-engine/accounting.ts) │ │
|
|
||||||
│ │ • Emitiu NF-e → lançamento automático D: Clientes │ │
|
|
||||||
│ │ C: Receita │ │
|
|
||||||
│ │ • Pagou conta → lançamento automático D: Fornecedor │ │
|
|
||||||
│ │ C: Banco │ │
|
|
||||||
│ └─────────────────────────────────────────────────────────────┘ │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ DESPACHADOR DE MOTOR (já existe, aprimorado) │
|
|
||||||
│ createErpClient(connection) em server/erp/index.ts │
|
|
||||||
│ │
|
|
||||||
│ motor = "local" → INSERT PostgreSQL │
|
|
||||||
│ motor = "plus" → ArcadiaPlusClient → Plus:8080 → MySQL │
|
|
||||||
│ motor = "erpnext" → ArcadiaNextClient → ERPNext API → MariaDB │
|
|
||||||
└───────────────────────────────┬─────────────────────────────────────┘
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
┌─────────────────────────────────────────────────────────────────────┐
|
|
||||||
│ SOE EVENT BUS (NOVO) │
|
|
||||||
│ server/soe/event-bus.ts │
|
|
||||||
│ │
|
|
||||||
│ Depois que o motor executa, o Event Bus dispara: │
|
|
||||||
│ │
|
|
||||||
│ evento: "nfe_emitida" → Motor Contábil (lançamento auto) │
|
|
||||||
│ evento: "venda_confirmada" → Reserva estoque + alerta WhatsApp │
|
|
||||||
│ evento: "pagamento_feito" → Baixa C/P + lançamento contábil │
|
|
||||||
│ evento: "recebimento" → Baixa C/R + lançamento contábil │
|
|
||||||
└─────────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4. O QUE CONSTRUIR — Detalhamento por Módulo
|
|
||||||
|
|
||||||
### 4.1 SOE Rule Engine (PRIORIDADE MÁXIMA)
|
|
||||||
|
|
||||||
**Localização:** `server/soe/rule-engine/`
|
|
||||||
|
|
||||||
Este é o coração da evolução. É um middleware que intercepta as chamadas às rotas SOE **antes** de despachar para o motor.
|
|
||||||
|
|
||||||
#### Como funciona na prática
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/erp/routes.ts — modificação cirúrgica
|
|
||||||
|
|
||||||
// ANTES (atual):
|
|
||||||
app.post("/api/soe/sales-orders", requireAuth, async (req, res) => {
|
|
||||||
const client = getActiveClient(req) // pega Plus ou ERPNext
|
|
||||||
const result = await client.createSalesOrder(req.body) // despacha direto
|
|
||||||
res.json(result)
|
|
||||||
})
|
|
||||||
|
|
||||||
// DEPOIS (com Rule Engine):
|
|
||||||
app.post("/api/soe/sales-orders", requireAuth, async (req, res) => {
|
|
||||||
// 1. Aplica regras ANTES de despachar
|
|
||||||
const enriched = await ruleEngine.apply('pre_sales_order', req.body, req.user)
|
|
||||||
|
|
||||||
// 2. Despacha para o motor com dados enriquecidos
|
|
||||||
const client = getActiveClient(req)
|
|
||||||
const result = await client.createSalesOrder(enriched.payload)
|
|
||||||
|
|
||||||
// 3. Dispara eventos DEPOIS da execução
|
|
||||||
await eventBus.emit('sales_order_created', { result, rules: enriched.appliedRules })
|
|
||||||
|
|
||||||
res.json(result)
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Estrutura do Rule Engine
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/rule-engine/index.ts
|
|
||||||
|
|
||||||
interface SoeRule {
|
|
||||||
id: string
|
|
||||||
dominio: 'fiscal' | 'business' | 'accounting' | 'financial'
|
|
||||||
trigger: string // ex: 'pre_sales_order', 'post_nfe_emitida'
|
|
||||||
condicao: RuleCondition // quando esta regra se aplica
|
|
||||||
acao: RuleAction // o que ela faz ao payload
|
|
||||||
prioridade: number
|
|
||||||
ativo: boolean
|
|
||||||
empresaId?: number // null = regra global de todos os tenants
|
|
||||||
}
|
|
||||||
|
|
||||||
class SoeRuleEngine {
|
|
||||||
async apply(trigger: string, payload: any, context: RuleContext): Promise<EnrichedPayload> {
|
|
||||||
// 1. Busca regras ativas para este trigger (do banco + defaults hardcoded)
|
|
||||||
const rules = await this.getActiveRules(trigger, context.tenantId)
|
|
||||||
|
|
||||||
// 2. Filtra regras cuja condição se aplica ao payload
|
|
||||||
const applicable = rules.filter(r => this.avaliarCondicao(r.condicao, payload, context))
|
|
||||||
|
|
||||||
// 3. Aplica cada regra em ordem de prioridade
|
|
||||||
let enriched = { ...payload }
|
|
||||||
const applied: string[] = []
|
|
||||||
for (const rule of applicable.sort((a, b) => a.prioridade - b.prioridade)) {
|
|
||||||
enriched = await this.aplicarAcao(rule.acao, enriched, context)
|
|
||||||
applied.push(rule.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
return { payload: enriched, appliedRules: applied }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.2 Regras Fiscais no SOE
|
|
||||||
|
|
||||||
Estas regras **hoje vivem dentro do Plus** (Laravel controllers). A ideia é trazê-las para o SOE.
|
|
||||||
|
|
||||||
**Nota importante:** Não é mover o código PHP para TypeScript. É criar regras **declarativas** no SOE que enriquecem o payload **antes** de enviar ao Plus. O Plus ainda processa e emite — mas recebe o payload já correto.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/rule-engine/fiscal-rules.ts
|
|
||||||
|
|
||||||
export const FISCAL_RULES_PADRAO: SoeRule[] = [
|
|
||||||
|
|
||||||
// CFOP — resolve automaticamente por operação
|
|
||||||
{
|
|
||||||
id: 'CFOP_VENDA_DENTRO_ESTADO',
|
|
||||||
dominio: 'fiscal',
|
|
||||||
trigger: 'pre_sales_order',
|
|
||||||
condicao: { uf_emitente: '==', uf_destinatario: true, tipo_op: 'venda_produto' },
|
|
||||||
acao: { set: { 'items[*].cfop': '5.102' } },
|
|
||||||
prioridade: 10, ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'CFOP_VENDA_OUTRO_ESTADO',
|
|
||||||
dominio: 'fiscal',
|
|
||||||
trigger: 'pre_sales_order',
|
|
||||||
condicao: { uf_emitente: '!=', uf_destinatario: true, tipo_op: 'venda_produto' },
|
|
||||||
acao: { set: { 'items[*].cfop': '6.102' } },
|
|
||||||
prioridade: 10, ativo: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Tributação por Regime
|
|
||||||
{
|
|
||||||
id: 'CST_SIMPLES_NACIONAL',
|
|
||||||
dominio: 'fiscal',
|
|
||||||
trigger: 'pre_nfe_emissao',
|
|
||||||
condicao: { regime_tributario: 'simples_nacional' },
|
|
||||||
acao: {
|
|
||||||
set: { 'items[*].cst_icms': '400', 'items[*].pis': null, 'items[*].cofins': null },
|
|
||||||
// No Simples Nacional: CSOSN 400 = tributado, sem destaque PIS/COFINS
|
|
||||||
},
|
|
||||||
prioridade: 5, ativo: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'CST_LUCRO_PRESUMIDO',
|
|
||||||
dominio: 'fiscal',
|
|
||||||
trigger: 'pre_nfe_emissao',
|
|
||||||
condicao: { regime_tributario: 'lucro_presumido' },
|
|
||||||
acao: { set: { 'items[*].cst_pis': '01', 'items[*].cst_cofins': '01' } },
|
|
||||||
prioridade: 5, ativo: true
|
|
||||||
},
|
|
||||||
|
|
||||||
// Validações obrigatórias
|
|
||||||
{
|
|
||||||
id: 'VALIDAR_NCM_NFE',
|
|
||||||
dominio: 'fiscal',
|
|
||||||
trigger: 'pre_nfe_emissao',
|
|
||||||
condicao: { tipo_documento: ['nfe', 'nfce'] },
|
|
||||||
acao: { validar: { campo: 'items[*].ncm', obrigatorio: true, formato: /^\d{8}$/ } },
|
|
||||||
prioridade: 1, ativo: true
|
|
||||||
},
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.3 SOE Event Bus — Lançamentos Contábeis Automáticos
|
|
||||||
|
|
||||||
Este é o **maior salto de valor**. Hoje o Motor Contábil (:8003) existe mas nada o alimenta automaticamente.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// server/soe/event-bus.ts
|
|
||||||
|
|
||||||
type SoeEvent =
|
|
||||||
| 'nfe_emitida'
|
|
||||||
| 'nfe_cancelada'
|
|
||||||
| 'venda_confirmada'
|
|
||||||
| 'compra_recebida'
|
|
||||||
| 'pagamento_realizado'
|
|
||||||
| 'recebimento_realizado'
|
|
||||||
| 'boleto_gerado'
|
|
||||||
|
|
||||||
interface SoeEventPayload {
|
|
||||||
empresaId: number
|
|
||||||
tenantId: number
|
|
||||||
evento: SoeEvent
|
|
||||||
dados: Record<string, any>
|
|
||||||
motorOrigem: 'plus' | 'erpnext' | 'local'
|
|
||||||
}
|
|
||||||
|
|
||||||
class SoeEventBus {
|
|
||||||
async emit(evento: SoeEvent, payload: SoeEventPayload) {
|
|
||||||
// Registra no banco (audit trail)
|
|
||||||
await db.insert(soeEventos).values({ ...payload, createdAt: new Date() })
|
|
||||||
|
|
||||||
// Dispara handlers
|
|
||||||
await Promise.allSettled(
|
|
||||||
this.getHandlers(evento).map(h => h(payload))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handlers por evento
|
|
||||||
private handlers: Record<SoeEvent, EventHandler[]> = {
|
|
||||||
'nfe_emitida': [
|
|
||||||
contabilHandler.lancamentoVenda, // D: Clientes / C: Receita Bruta
|
|
||||||
contabilHandler.lancamentoImpostos, // D: Impostos / C: ICMS/PIS/COFINS a Recolher
|
|
||||||
financialHandler.gerarRecebivel, // Cria C/R automaticamente
|
|
||||||
],
|
|
||||||
'pagamento_realizado': [
|
|
||||||
contabilHandler.lancamentoPagamento, // D: Fornecedores / C: Banco
|
|
||||||
financialHandler.baixarContaPagar, // Baixa C/P
|
|
||||||
],
|
|
||||||
'recebimento_realizado': [
|
|
||||||
contabilHandler.lancamentoRecebimento, // D: Banco / C: Clientes
|
|
||||||
financialHandler.baixarContaReceber, // Baixa C/R
|
|
||||||
],
|
|
||||||
'compra_recebida': [
|
|
||||||
contabilHandler.lancamentoCompra, // D: Estoque / C: Fornecedores
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Lançamentos automáticos para cada evento
|
|
||||||
|
|
||||||
```
|
|
||||||
NF-e emitida (venda):
|
|
||||||
D: 1.1.3.01 — Clientes (valor total da nota)
|
|
||||||
C: 3.1.1.01 — Receita Bruta de Vendas
|
|
||||||
|
|
||||||
D: 3.1.2.01 — Deduções (ICMS)
|
|
||||||
C: 2.1.2.01 — ICMS a Recolher
|
|
||||||
|
|
||||||
D: 3.1.2.02 — Deduções (PIS)
|
|
||||||
C: 2.1.2.02 — PIS a Recolher
|
|
||||||
|
|
||||||
D: 3.1.2.03 — Deduções (COFINS)
|
|
||||||
C: 2.1.2.03 — COFINS a Recolher
|
|
||||||
|
|
||||||
Pagamento de fornecedor:
|
|
||||||
D: 2.1.1.{categoria} — Fornecedores
|
|
||||||
C: 1.1.1.01 — Banco (conta configurada)
|
|
||||||
|
|
||||||
Recebimento de cliente:
|
|
||||||
D: 1.1.1.01 — Banco
|
|
||||||
C: 1.1.3.01 — Clientes
|
|
||||||
|
|
||||||
Compra recebida (NF-e entrada):
|
|
||||||
D: 1.1.4.01 — Estoque / Mercadorias
|
|
||||||
C: 2.1.1.01 — Fornecedores
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4.4 Ocultação do Plus e ERPNext
|
|
||||||
|
|
||||||
O Plus tem página própria em `/plus` (client/src/pages/Plus.tsx). O usuário pode acessá-la diretamente. Precisamos de 3 mudanças:
|
|
||||||
|
|
||||||
#### a) Redirecionar `/plus` para `/soe`
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// client/src/App.tsx — modificação simples
|
|
||||||
// Trocar: <Route path="/plus" component={Plus} />
|
|
||||||
// Por: <Route path="/plus" render={() => <Redirect to="/soe" />} />
|
|
||||||
```
|
|
||||||
|
|
||||||
**Mas manter o proxy reverso Plus ativo** — o Plus continua funcionando em background, só não fica visível como página separada.
|
|
||||||
|
|
||||||
#### b) Ocultar o seletor de motor do usuário final
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// client/src/contexts/SoeMotorContext.tsx
|
|
||||||
// O seletor fica SOMENTE na tab Config do SOE, e somente para admins
|
|
||||||
|
|
||||||
// A tab Config na SOE.tsx — adicionar role check:
|
|
||||||
{user?.role === 'admin' && <TabsTrigger value="config">Config</TabsTrigger>}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### c) Na tab Config (admin), o label muda
|
|
||||||
|
|
||||||
```
|
|
||||||
Antes: "Selecione o motor: Plus | ERPNext"
|
|
||||||
Depois: "Motor de execução: Plus | ERPNext | Local"
|
|
||||||
(invisível para usuário final, só admin de tenant vê)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5. TABELAS A CRIAR (complemento ao schema existente)
|
|
||||||
|
|
||||||
As tabelas canônicas do SOE já existem. Precisamos adicionar apenas as tabelas do Rule Engine.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
// shared/schema.ts — adicionar ao final
|
|
||||||
|
|
||||||
// Regras do SOE — configuráveis por tenant
|
|
||||||
export const soeRegras = pgTable('soe_regras', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
tenantId: integer('tenant_id'), // null = regra global (todas as empresas)
|
|
||||||
empresaId: integer('empresa_id'), // null = todas as empresas do tenant
|
|
||||||
dominio: varchar('dominio', { length: 50 }).notNull(),
|
|
||||||
trigger: varchar('trigger', { length: 100 }).notNull(),
|
|
||||||
nome: varchar('nome', { length: 200 }).notNull(),
|
|
||||||
condicao: jsonb('condicao').notNull(),
|
|
||||||
acao: jsonb('acao').notNull(),
|
|
||||||
prioridade: integer('prioridade').default(10),
|
|
||||||
ativo: boolean('ativo').default(true),
|
|
||||||
origemPadrao: boolean('origem_padrao').default(false), // true = regra default do sistema
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
updatedAt: timestamp('updated_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Log de todos os eventos SOE (audit trail completo)
|
|
||||||
export const soeEventos = pgTable('soe_eventos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
tenantId: integer('tenant_id').notNull(),
|
|
||||||
empresaId: integer('empresa_id'),
|
|
||||||
evento: varchar('evento', { length: 100 }).notNull(),
|
|
||||||
motorOrigem: varchar('motor_origem', { length: 50 }), // 'plus', 'erpnext', 'local'
|
|
||||||
regraIds: jsonb('regra_ids'), // regras aplicadas
|
|
||||||
payloadEntrada: jsonb('payload_entrada'),
|
|
||||||
payloadSaida: jsonb('payload_saida'),
|
|
||||||
status: varchar('status', { length: 50 }).notNull(),
|
|
||||||
duracaoMs: integer('duracao_ms'),
|
|
||||||
erro: text('erro'),
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Lançamentos contábeis automáticos do SOE
|
|
||||||
export const soeLancamentos = pgTable('soe_lancamentos', {
|
|
||||||
id: uuid('id').primaryKey().defaultRandom(),
|
|
||||||
tenantId: integer('tenant_id').notNull(),
|
|
||||||
empresaId: integer('empresa_id').notNull(),
|
|
||||||
data: date('data').notNull(),
|
|
||||||
contaDebito: varchar('conta_debito', { length: 30 }).notNull(),
|
|
||||||
contaCredito: varchar('conta_credito', { length: 30 }).notNull(),
|
|
||||||
valor: numeric('valor', { precision: 15, scale: 2 }).notNull(),
|
|
||||||
historico: text('historico').notNull(),
|
|
||||||
origemEvento: varchar('origem_evento', { length: 100 }), // 'nfe_emitida', etc.
|
|
||||||
origemEventoId: uuid('origem_evento_id'), // FK para soe_eventos
|
|
||||||
periodo: varchar('periodo', { length: 7 }), // '2026-03'
|
|
||||||
enviado8003: boolean('enviado_8003').default(false), // sincronizado com Motor Contábil
|
|
||||||
createdAt: timestamp('created_at').defaultNow(),
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6. ESTRUTURA DE PASTAS (Novo código a criar)
|
|
||||||
|
|
||||||
```
|
|
||||||
server/
|
|
||||||
└── soe/ ← NOVA PASTA
|
|
||||||
├── rule-engine/
|
|
||||||
│ ├── index.ts ← SoeRuleEngine class
|
|
||||||
│ ├── fiscal-rules.ts ← Regras fiscais padrão
|
|
||||||
│ ├── business-rules.ts ← Regras de negócio
|
|
||||||
│ └── accounting-rules.ts ← Regras de lançamento contábil
|
|
||||||
│
|
|
||||||
├── event-bus.ts ← SoeEventBus class
|
|
||||||
│
|
|
||||||
├── handlers/
|
|
||||||
│ ├── contabil-handler.ts ← Lançamentos automáticos
|
|
||||||
│ └── financial-handler.ts ← Automação financeira
|
|
||||||
│
|
|
||||||
└── fiscal/
|
|
||||||
└── cfop-resolver.ts ← Resolução de CFOP (lógica complexa)
|
|
||||||
```
|
|
||||||
|
|
||||||
**Modificações em arquivos existentes:**
|
|
||||||
```
|
|
||||||
server/erp/routes.ts ← Inserir ruleEngine.apply() antes do dispatch
|
|
||||||
client/src/App.tsx ← Redirecionar /plus para /soe
|
|
||||||
client/src/pages/SOE.tsx ← Ocultar Config tab para não-admins
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7. ROADMAP — Fases de Implementação
|
|
||||||
|
|
||||||
### Fase 1 — Rule Engine Básico ✅ CONCLUÍDA (2026-03-19) — João
|
|
||||||
```
|
|
||||||
[x] Criar server/soe/rule-engine/index.ts (SoeRuleEngine) — já existia | João | 2026-03-19
|
|
||||||
[x] Criar tabelas soe_regras e soe_eventos (drizzle push) — já existiam no schema | João | 2026-03-19
|
|
||||||
[x] Inserir ruleEngine.apply() em 3 rotas críticas:
|
|
||||||
- POST /api/soe/sales-orders ✅ plugado | João | 2026-03-19
|
|
||||||
- POST /api/soe/sales-orders/:id/generate-nfe ✅ plugado | João | 2026-03-19
|
|
||||||
- POST /api/soe/purchase-orders ✅ plugado | João | 2026-03-19
|
|
||||||
[x] Seed das regras fiscais padrão (CFOP, CST, validações NCM) — fiscal-rules.ts hardcoded | João | 2026-03-19
|
|
||||||
[ ] Testar: criar pedido → verificar que payload está sendo enriquecido
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 2 — Event Bus + Contabilidade Automática ✅ CONCLUÍDA (2026-03-19) — João
|
|
||||||
```
|
|
||||||
[x] Criar server/soe/event-bus.ts — já existia | João | 2026-03-19
|
|
||||||
[x] Criar tabela soe_lancamentos (drizzle push) — já existia no schema | João | 2026-03-19
|
|
||||||
[x] Criar handlers: contabil-handler.ts + financial-handler.ts — já existiam | João | 2026-03-19
|
|
||||||
[x] Conectar: POST generate-nfe → emit('nfe_emitida') → lançamentos ✅ plugado | João | 2026-03-19
|
|
||||||
[ ] Conectar: pagamento/recebimento → emit() → lançamentos
|
|
||||||
[ ] Criar endpoint: GET /api/soe/contabil/lancamentos?periodo=YYYY-MM
|
|
||||||
[ ] DRE: agora tem dados reais (via soe_lancamentos → Motor :8003)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 3 — Ocultar Plus/ERPNext ✅ CONCLUÍDA (2026-03-19) — João
|
|
||||||
```
|
|
||||||
[x] client/src/App.tsx: /plus → redirect para /soe ✅ | João | 2026-03-19
|
|
||||||
[x] client/src/pages/SOE.tsx: Config tab só para admins ✅ | João | 2026-03-19
|
|
||||||
[x] Manter proxy Plus funcionando (invisível) — proxy já existia, não alterado | João | 2026-03-19
|
|
||||||
[ ] Testar: fluxo completo sem nenhum acesso direto ao Plus UI
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 4 — Regras Configuráveis pelo Usuário (1 semana)
|
|
||||||
```
|
|
||||||
[ ] UI na tab Config do SOE: "Regras de Negócio"
|
|
||||||
[ ] CRUD de regras via /api/soe/rules
|
|
||||||
[ ] Admin pode criar regras custom sem código
|
|
||||||
[ ] Exemplo: "Pedidos acima de R$10.000 requerem aprovação manual"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 5 — Financeiro Avançado (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] Auto-boleto ao confirmar venda (Asaas API)
|
|
||||||
[ ] Alertas de vencimento (Manus → WhatsApp)
|
|
||||||
[ ] Conciliação bancária OFX semi-automática
|
|
||||||
[ ] Previsão financeira (Motor BI :8004 + histórico soe_lancamentos)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Fase 6 — Contábil Avançado (2 semanas)
|
|
||||||
```
|
|
||||||
[ ] DRE automático mensal (100% alimentado pelo Event Bus)
|
|
||||||
[ ] Balanço Patrimonial automático
|
|
||||||
[ ] Fechamento contábil mensal
|
|
||||||
[ ] SPED ECD/ECF alimentado por soe_lancamentos
|
|
||||||
[ ] Exportação para escritório contábil (OFX, Excel, PDF)
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8. COMPARAÇÃO: PLANO v1 vs PLANO v2
|
|
||||||
|
|
||||||
| Aspecto | Plano v1 (antes do Replit .md) | Plano v2 (com conhecimento real) |
|
|
||||||
|---|---|---|
|
|
||||||
| Adaptadores Plus/ERPNext | "Precisam ser criados" | Já existem — não tocar |
|
|
||||||
| SOE Routes | "Precisam ser criadas" | 60+ endpoints já existem |
|
|
||||||
| SOE.tsx | "Precisa ser construída" | 2.414 linhas — já funciona |
|
|
||||||
| Onde adicionar código | server/soe/ do zero | Middleware nas rotas existentes |
|
|
||||||
| Esforço estimado | Alto (refatoração total) | Médio (adição cirúrgica) |
|
|
||||||
| Risco de quebrar | Alto | Baixo (adição, não substituição) |
|
|
||||||
| Banco Plus | Ignorado | MySQL — separado, nunca tocar direto |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9. PRINCÍPIO ORIENTADOR (REVISADO)
|
|
||||||
|
|
||||||
> O SOE já é o roteador certo. Agora vamos torná-lo o **árbitro de regras**.
|
|
||||||
>
|
|
||||||
> O padrão motor/adaptador está perfeito. O que falta é a **inteligência entre a rota e o adaptador**.
|
|
||||||
>
|
|
||||||
> Plus e ERPNext continuam existindo e funcionando — só que o usuário final não sabe.
|
|
||||||
> Ele só vê a Central SOE. O restante é infraestrutura.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10. RESUMO EXECUTIVO — O que fazer agora
|
|
||||||
|
|
||||||
**1 ação que entrega valor imediato:**
|
|
||||||
```
|
|
||||||
Criar o SoeRuleEngine e plugar nas rotas de venda/NF-e.
|
|
||||||
Resultado: Ao emitir uma NF-e, o CFOP correto é calculado
|
|
||||||
automaticamente pelo SOE — sem o usuário saber que o Plus está
|
|
||||||
sendo chamado por baixo.
|
|
||||||
```
|
|
||||||
|
|
||||||
**1 ação que entrega valor a médio prazo:**
|
|
||||||
```
|
|
||||||
Criar o Event Bus com o handler de contabilidade.
|
|
||||||
Resultado: Cada NF-e emitida gera lançamentos contábeis
|
|
||||||
automaticamente. O DRE do mês é gerado sem entrada manual de dados.
|
|
||||||
```
|
|
||||||
|
|
||||||
**1 ação que fecha o conceito:**
|
|
||||||
```
|
|
||||||
Redirecionar /plus → /soe.
|
|
||||||
Resultado: O usuário não tem mais acesso ao Plus diretamente.
|
|
||||||
Ele só vê o Arcádia. O Plus é infraestrutura invisível.
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*PLANO_SOE_CENTRAL_v2.md — Arcádia Suite v3.0*
|
|
||||||
*Gerado em: 2026-03-16 — Baseado na análise real do MAPA_SOE_ARCADIA.md (Replit)*
|
|
||||||
Loading…
Reference in New Issue