- Rewrite README.md with current architecture, features and stack - Update docs/API.md with all current endpoints (corporate, BI, client 360) - Update docs/ARCHITECTURE.md with cache, modular queries, services, ETL - Update docs/GUIA-USUARIO.md for all roles (admin, corporate, agente) - Add docs/INDEX.md documentation index - Add PROJETO.md comprehensive project reference - Add BI-CCC-Implementation-Guide.md - Include AI agent configs (.claude, .agents, .gemini, _bmad) - Add netbird VPN configuration - Add status report Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
245 lines
13 KiB
Markdown
245 lines
13 KiB
Markdown
# Arquitetura — BI-CCC
|
|
|
|
Documentação técnica da arquitetura do sistema BI-CCC (Central Command Center).
|
|
|
|
## Visão Geral
|
|
|
|
O BI-CCC é uma aplicação web monolítica construída com Node.js/Express que serve dashboards de BI para a operação de câmbio da CambioReal. A arquitetura prioriza simplicidade, segurança, isolamento de dados e performance via cache inteligente.
|
|
|
|
## Diagrama de Arquitetura
|
|
|
|
```
|
|
INTERNET
|
|
│
|
|
▼
|
|
┌──────────────────────────────────────────────────────────────────────┐
|
|
│ Docker Container (bi-ccc) │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────────────────────┐ │
|
|
│ │ Express Server (PORT 3080) │ │
|
|
│ │ │ │
|
|
│ │ ┌──────────┐ ┌───────────┐ ┌───────────┐ ┌──────────────┐ │ │
|
|
│ │ │ Session │ │requireAuth│ │requireRole│ │ Static │ │ │
|
|
│ │ │Middleware│─▶│ │─▶│ │─▶│ /public │ │ │
|
|
│ │ └──────────┘ └───────────┘ └───────────┘ └──────────────┘ │ │
|
|
│ │ │ │
|
|
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
|
|
│ │ │ Route Handlers │ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ /corporate ──▶ admin-dashboard.js ──▶ buildCorporateHTML│ │ │
|
|
│ │ │ /admin/bi ──▶ admin-bi.js ──▶ buildBiHTML │ │ │
|
|
│ │ │ /admin/cliente ▶ admin-cliente.js ──▶ buildClienteHTML │ │ │
|
|
│ │ │ /admin ──▶ admin-panel.js ──▶ buildPanelHTML │ │ │
|
|
│ │ │ /admin/home ─▶ admin-home.js ──▶ buildHomeHTML │ │ │
|
|
│ │ │ /admin/providers ▶ admin-providers ▶ buildProvidersHTML │ │ │
|
|
│ │ │ /dashboard ──▶ dashboard.js ──▶ buildDashHTML │ │ │
|
|
│ │ └──────────────────────────────────────────────────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ │ ┌─────────────┼─────────────┐ │ │
|
|
│ │ ▼ ▼ ▼ │ │
|
|
│ │ ┌──────────────┐ ┌──────────┐ ┌──────────────┐ │ │
|
|
│ │ │ cache.js │ │ services │ │ export/ │ │ │
|
|
│ │ │ (SWR cache) │ │ churn │ │ excel-export│ │ │
|
|
│ │ │ │ │ forecast │ │ │ │ │
|
|
│ │ └──────┬───────┘ └──────────┘ └──────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ │ ▼ │ │
|
|
│ │ ┌──────────────────────────────────────────────┐ │ │
|
|
│ │ │ src/queries/ │ │ │
|
|
│ │ │ bi.queries │ client.queries │ corporate.q │ │ │
|
|
│ │ │ payin.q │ payout.q │ provider.q │ │ │
|
|
│ │ │ compliance.q│ helpers.js │ │ │
|
|
│ │ └──────────────────────┬───────────────────────┘ │ │
|
|
│ │ │ │ │
|
|
│ └─────────────────────────┼────────────────────────────────────────┘ │
|
|
│ │ │
|
|
│ ┌─────────────────────────┼───────────────────────────────────────┐ │
|
|
│ │ Netbird VPN daemon │ │ │
|
|
│ └─────────────────────────┼───────────────────────────────────────┘ │
|
|
└────────────────────────────┼──────────────────────────────────────────┘
|
|
┌─────────────┴─────────────┐
|
|
▼ ▼
|
|
┌───────────────────┐ ┌───────────────────┐
|
|
│ SQLite │ │ AWS RDS │
|
|
│ (agentes.db) │ │ (cambio_db) │
|
|
│ LOCAL / R+W │ │ REMOTE / R.O. │
|
|
│ │ │ via Netbird VPN │
|
|
│ agentes (auth) │ │ │
|
|
└───────────────────┘ │ br_transaction │
|
|
│ pagamento_br │
|
|
│ conta │
|
|
│ ag_contas │
|
|
│ br_payment_methods│
|
|
│ br_cb_empresas │
|
|
│ br_cb_cobranca │
|
|
└───────────────────┘
|
|
```
|
|
|
|
## Componentes
|
|
|
|
### 1. Camada de Apresentação
|
|
|
|
**Padrão:** Server-Side Rendering — cada página é um módulo em `src/` que exporta `buildXxxHTML(user)` retornando uma string HTML completa com CSS e JS inline.
|
|
|
|
| Módulo | Página | Linhas |
|
|
|--------|--------|--------|
|
|
| `admin-bi.js` | BI Executive | ~2250 |
|
|
| `admin-cliente.js` | Client 360 | ~1400 |
|
|
| `admin-dashboard.js` | Corporate Dashboard | ~750 |
|
|
| `admin-home.js` | Daily Overview | ~510 |
|
|
| `admin-panel.js` | Gestão de Usuários | ~620 |
|
|
| `admin-providers.js` | Payment Providers | ~1070 |
|
|
| `dashboard.js` | Dashboard do Agente | ~1585 |
|
|
| `ui-template.js` | Header, footer, CSS, tema | ~600 |
|
|
|
|
**Fluxo:**
|
|
1. Express recebe request → verifica auth/role
|
|
2. Chama `buildXxxHTML(user)` → retorna HTML string
|
|
3. Frontend faz `fetch()` para APIs de dados
|
|
4. JavaScript inline renderiza Chart.js e popula o DOM
|
|
|
|
### 2. Sistema de Temas
|
|
|
|
- **Dark Mode:** Estilo Bloomberg terminal — verde #00FF88, fontes monospace (SF Mono/Fira Code)
|
|
- **Light Mode:** Cores institucionais CambioReal — roxo #7600be, verde #2E7D32
|
|
- **Toggle:** Atributo `data-theme` no HTML, persistido no localStorage
|
|
- **Charts:** `getChartTheme()` retorna cores adaptadas ao tema ativo
|
|
- **CSS:** Variáveis CSS com breakpoints em 1200px, 900px, 768px, 480px
|
|
|
|
### 3. Cache Layer
|
|
|
|
**Módulo:** `src/cache.js` — Cache em memória com padrão stale-while-revalidate.
|
|
|
|
| Dado | TTL | Auto-refresh |
|
|
|------|-----|-------------|
|
|
| KPIs | 5 min | Sim |
|
|
| Tendência 30d | 10 min | Sim |
|
|
| Top agentes | 10 min | Sim |
|
|
| Top clientes | 15 min | Não |
|
|
|
|
Dados "stale" são retornados imediatamente enquanto o refresh acontece em background.
|
|
|
|
### 4. Queries Modulares
|
|
|
|
**Diretório:** `src/queries/` — Queries SQL separadas por domínio.
|
|
|
|
| Módulo | Responsabilidade |
|
|
|--------|------------------|
|
|
| `bi.queries.js` | KPIs executivos, revenue analytics, cohort, strategic |
|
|
| `client.queries.js` | Profile, health score, churn risk, timeline |
|
|
| `corporate.queries.js` | KPIs corporate, tendências, top agentes |
|
|
| `payin.queries.js` | Transações BRL→USD |
|
|
| `payout.queries.js` | Pagamentos USD→BRL |
|
|
| `provider.queries.js` | Análise de provedores de pagamento |
|
|
| `compliance.queries.js` | Queries de compliance |
|
|
| `helpers.js` | Utilitários de query (formatação, cálculos) |
|
|
|
|
### 5. Serviços
|
|
|
|
| Módulo | Responsabilidade |
|
|
|--------|------------------|
|
|
| `services/churn-predictor.js` | Predição de churn baseada em recência, frequência, volume |
|
|
| `services/forecast.js` | Previsão de receita com tendência histórica |
|
|
|
|
### 6. ETL & Data Quality
|
|
|
|
| Módulo | Responsabilidade |
|
|
|--------|------------------|
|
|
| `etl/daily-sync.js` | Sincronização diária de dados agregados |
|
|
| `etl/data-quality.js` | Validação e checagem de qualidade dos dados |
|
|
|
|
### 7. Alertas
|
|
|
|
| Módulo | Responsabilidade |
|
|
|--------|------------------|
|
|
| `alerts/alert-engine.js` | Motor de regras para disparar alertas |
|
|
| `alerts/channels.js` | Canais de notificação (email via nodemailer) |
|
|
|
|
### 8. Export
|
|
|
|
| Módulo | Responsabilidade |
|
|
|--------|------------------|
|
|
| `export/excel-export.js` | Exportação de dados para Excel (ExcelJS) |
|
|
|
|
## Banco de Dados
|
|
|
|
### MySQL RDS (`cambio_db`) — Transações
|
|
|
|
| Tabela | Descrição |
|
|
|--------|-----------|
|
|
| `br_transaction_to_usa` | Transações BRL→USD (amount_brl, amount_usd, exchange_rate, ptax, iof, status, cobranca_id) |
|
|
| `pagamento_br` | Pagamentos USD→BRL (valor, cotacao, ptax, valor_sol, tipo_envio, pgto, fee) |
|
|
| `conta` | Contas/clientes (id_conta, nome) |
|
|
| `ag_contas` | Mapeamento agente→conta (agente_id, conta_id) |
|
|
| `br_payment_methods` | Provedores de pagamento (id, provider) |
|
|
| `br_cb_empresas` | Merchants CambioCheckout (id, id_conta, nome_empresa, active) |
|
|
| `br_cb_cobranca` | Cobranças/links de pagamento (id, empresa_id) |
|
|
|
|
**Relação Merchant/Checkout:** `br_cb_empresas.id_conta` identifica o merchant. `br_cb_cobranca.empresa_id` liga ao merchant. `br_transaction_to_usa.cobranca_id` liga a transação à cobrança. O `id_conta` na transação é o **pagador** (cliente BR), não o merchant.
|
|
|
|
### SQLite Local (`data/agentes.db`) — Auth
|
|
|
|
```sql
|
|
CREATE TABLE agentes (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
email TEXT UNIQUE NOT NULL,
|
|
senha_hash TEXT NOT NULL,
|
|
agente_id INTEGER,
|
|
nome TEXT NOT NULL,
|
|
role TEXT DEFAULT 'agente',
|
|
ativo INTEGER DEFAULT 1,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
## Cálculo de Receita
|
|
|
|
**BRL→USD (CambioPay/CambioCheckout):**
|
|
```
|
|
receita = (amount_brl - fee_ajustado) / ptax - pfee - (amount_usd + bonus - taxa_cr)
|
|
```
|
|
Onde `fee_ajustado` depende do provider (ouribank/bs2 não descontam fee).
|
|
|
|
**USD→BRL:**
|
|
```
|
|
receita = ((ptax - cotacao) * valor) / ptax + fee
|
|
```
|
|
|
|
**Balance:** apenas `fee`.
|
|
|
|
## Segurança
|
|
|
|
| Aspecto | Implementação |
|
|
|---------|---------------|
|
|
| Hash de senha | bcrypt, 10 salt rounds |
|
|
| Sessão | express-session, in-memory, 8h timeout |
|
|
| SQL Injection | Queries parametrizadas (?) |
|
|
| Isolamento | WHERE agente_id = ? em todas queries de agente |
|
|
| RDS Access | Usuário read-only (sem INSERT/UPDATE/DELETE) |
|
|
| VPN | Netbird — acesso ao RDS somente via rede privada |
|
|
|
|
## Deploy
|
|
|
|
**Docker Compose** com Netbird VPN integrado:
|
|
|
|
1. `docker-entrypoint.sh` inicia Netbird VPN daemon
|
|
2. Aguarda conexão VPN (~10s)
|
|
3. Inicia `node server.js` na porta 3080
|
|
|
|
```bash
|
|
docker compose build bi-ccc && docker compose down bi-ccc && docker compose up -d bi-ccc
|
|
```
|
|
|
|
## Decisões de Arquitetura
|
|
|
|
| Decisão | Justificativa |
|
|
|---------|---------------|
|
|
| Monolito | Simplicidade para equipe pequena |
|
|
| SSR com HTML inline | Sem build step, deploy simples |
|
|
| SQLite para auth | Independência do RDS, portabilidade |
|
|
| MySQL pool async | 10 conexões reutilizáveis para RDS |
|
|
| Cache SWR | Resposta rápida sem stale data prolongado |
|
|
| Queries modulares | Separação por domínio, manutenibilidade |
|
|
| Chart.js inline | Sem CDN, funciona offline via VPN |
|
|
| Netbird VPN | Acesso seguro ao RDS sem expor porta pública |
|