# 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 |