# BI-CCC (Central Command Center) — CambioReal Sistema de Business Intelligence interno da CambioReal para monitoramento de operacoes cambiais, analise de clientes e gestao de agentes. ## O que faz O BI-CCC consolida dados de tres produtos de cambio em dashboards visuais: - **CambioPay** (BRL→USD): Clientes brasileiros enviam reais que sao convertidos em dolares para destinatarios nos EUA - **CambioPay Reverso** (USD→BRL): Clientes nos EUA enviam dolares convertidos em reais para o Brasil - **CambioCheckout** (BR→US via Cobranca): Merchants nos EUA recebem pagamentos de clientes brasileiros via links de cobranca Os dados transacionais vivem em um banco MySQL (RDS na AWS), acessivel via VPN Netbird. O sistema calcula receita, spread, volume, e indicadores de saude por cliente/agente/periodo. ## Stack Tecnica | Camada | Tecnologia | |--------|-----------| | Runtime | Node.js 20 (Alpine) | | Framework | Express 4 | | Banco transacional | MySQL 8 (AWS RDS) — read-only | | Banco local | SQLite (better-sqlite3) — usuarios/auth | | Graficos | Chart.js (inline, sem CDN) | | Autenticacao | bcrypt + express-session | | VPN | Netbird (acesso ao RDS) | | Deploy | Docker Compose | | Tema | Dark/Light toggle, estilo Bloomberg terminal | ## Arquitetura ``` ┌─────────────────────────────────────────────────┐ │ Browser │ │ HTML + CSS + JS (tudo server-side rendered) │ │ Chart.js para graficos │ └───────────────────┬─────────────────────────────┘ │ HTTP ┌───────────────────▼─────────────────────────────┐ │ server.js (Express) │ │ - Rotas HTML (GET /corporate, /admin/bi, etc) │ │ - API REST (GET /admin/api/bi, etc) │ │ - Auth middleware (session + roles) │ │ - Cache layer (stale-while-revalidate) │ ├──────────────────┬──────────────┬───────────────┤ │ src/queries.js │ src/auth.js │ src/*.js │ │ (MySQL queries) │ (bcrypt) │ (HTML builders)│ ├──────────┬───────┴──────────────┴───────────────┤ │ db-rds.js│ db-local.js │ │ (mysql2) │ (better-sqlite3) │ ├──────────┴──────────────────────────────────────┤ │ MySQL RDS (via Netbird VPN) │ SQLite local │ │ cambio_db — transacoes │ agentes.db │ └───────────────────────────────┴─────────────────┘ ``` ### Padrao de paginas Cada pagina e um modulo em `src/` que exporta uma funcao `buildXxxHTML(user)`. Essa funcao retorna uma string HTML completa com CSS e JS inline. Nao usa templates externos — tudo e construido server-side via template literals do JavaScript. 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 ## Estrutura de Arquivos ``` bi-agentes/ ├── server.js # Rotas + APIs + middleware ├── src/ │ ├── queries.js # Todas as queries MySQL (1786 linhas) │ ├── ui-template.js # Header, footer, CSS vars, tema, Chart.js │ ├── auth.js # Login/logout, bcrypt, requireRole middleware │ ├── cache.js # Cache em memoria com stale-while-revalidate │ ├── db-rds.js # Pool MySQL (read-only, 10 conexoes) │ ├── db-local.js # SQLite — tabela agentes (auth) │ ├── admin-bi.js # Pagina: BI Executive (2133 linhas) │ ├── admin-cliente.js # Pagina: Client 360 (1309 linhas) │ ├── admin-dashboard.js # Pagina: Corporate Dashboard (746 linhas) │ ├── admin-home.js # Pagina: Daily overview (510 linhas) │ ├── admin-panel.js # Pagina: Gestao de usuarios (523 linhas) │ └── dashboard.js # Pagina: Dashboard do agente (1585 linhas) ├── public/ │ ├── chart.umd.min.js # Chart.js (carregado inline) │ ├── login.html # Tela de login │ ├── logo.png # Logo CambioReal │ └── logo-small.png ├── data/ │ └── agentes.db # SQLite (persistido via Docker volume) ├── scripts/ │ ├── seed-admin.js # Cria usuario admin │ └── seed-agente.js # Cria usuario agente ├── Dockerfile ├── docker-compose.yml ├── docker-entrypoint.sh # Startup: Netbird VPN + node server.js └── .env # Credenciais (nao versionado) ``` ## Roles e Permissoes | Role | Acesso | Rota principal | |------|--------|---------------| | `admin` | Tudo: Corporate, BI, Clientes, Usuarios, Emular agente | `/corporate` | | `corporate` | Corporate Dashboard apenas | `/corporate` | | `agente` | Seu proprio dashboard de transacoes | `/dashboard` | Middleware `requireRole('admin')` protege rotas. Admins podem emular agentes via `/corporate/emular/:agente_id`. ## Paginas e Funcionalidades ### Corporate Dashboard (`/corporate`) - KPIs do periodo: volume, transacoes, ticket medio - Graficos de tendencia (30 dias default) - Tres fluxos separados: BRL→USD, USD→BRL, USD→USD (balance) - Filtros por periodo customizado ### BI Executive (`/admin/bi`) - Dashboard consolidado com KPIs comparativos (periodo atual vs anterior) - Revenue Analytics por produto com granularidade (dia/mes/ano) - Receita por produto: CambioPay, CambioCheckout, Balance - Ranking de agentes com spread revenue - Top 10 clientes por volume - Retencao, clientes em risco, netting - BI Estrategico: cohort retention, revenue expansion/contraction, cross-sell, maturidade ### Client 360 (`/admin/cliente`) - Busca de clientes (server-side, top 20 por volume) - Profile card: nome, lifetime stats, health score - **Merchant detection**: clientes que sao merchants CambioCheckout mostram badge roxo e secao dedicada - 6 KPI cards: volume, transacoes, receita, ticket medio, ARPA, spread - 6 KPI cards checkout (merchants): volume, payers, receita, ops, ticket, spread - Health Score (0-100): volume + frequencia + recencia + crescimento - Churn Risk: indicadores de risco com classificacao (baixo/medio/alto/critico) - Netting: posicao liquida BRL→USD vs USD→BRL - Revenue Intelligence: receita mensal + MoM growth - Timeline: volume + quantidade diaria com granularidade D/W/M - Analise de fluxo: donut BRL↔USD + tendencia de spread - Checkout Analytics (merchants): chart mensal volume+payers + top 10 pagadores clicaveis - Tabela de transacoes: ordenavel, paginada, exportavel CSV - Insights comportamentais: dia da semana, ticket medio, providers ### Gestao de Usuarios (`/admin`) - CRUD de usuarios (admin, corporate, agente) - Ativar/desativar usuarios - Reset de senha ### Dashboard Agente (`/dashboard`) - Transacoes do agente (filtradas por `agente_id`) - KPIs pessoais ## Banco de Dados ### MySQL RDS (`cambio_db`) — Transacoes | Tabela | Descricao | |--------|-----------| | `br_transaction_to_usa` | Transacoes 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: dlocal, bexs, braza, bs2, ouribank, msb) | | `br_cb_empresas` | Merchants CambioCheckout (id, id_conta, nome_empresa, active) | | `br_cb_cobranca` | Cobrancas/links de pagamento (id, empresa_id) | **Relacao 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 transacao a cobranca. O `id_conta` na transacao e o **pagador** (cliente BR), nao o merchant. ### SQLite Local (`data/agentes.db`) — Auth | Tabela | Descricao | |--------|-----------| | `agentes` | Usuarios do sistema (email, senha_hash, nome, role, agente_id, ativo) | ## Calculo de Receita A receita e calculada de forma diferente por produto: **BRL→USD (CambioPay/CambioCheckout)**: ``` receita = (amount_brl - fee_ajustado) / ptax - pfee - (amount_usd + bonus - taxa_cr) ``` Onde `fee_ajustado` depende do provider (ouribank/bs2 nao descontam fee). **USD→BRL**: ``` receita = ((ptax - cotacao) * valor) / ptax + fee ``` Balance: apenas `fee`. ## Cache O sistema usa cache em memoria (`src/cache.js`) com padrao stale-while-revalidate: - **KPIs**: TTL 5 min, auto-refresh - **Tendencia 30d**: TTL 10 min, auto-refresh - **Top agentes**: TTL 10 min, auto-refresh (7d, 30d, 90d) - **Top clientes**: TTL 15 min Dados "stale" sao retornados imediatamente enquanto o refresh acontece em background. ## Design System - **Tema**: Dark mode estilo Bloomberg terminal (verde #00FF88, monospace) - **Light mode**: Cores institucionais CambioReal (roxo #7600be, verde #2E7D32) - **Trading Console**: classe `body.trading-console` ativa estetica de terminal - **Console Nav**: Navegacao lateral fixa (folder tabs) no lado direito - **Hero Cards**: Cards de KPI com borda colorida superior via `::before` - **Charts**: Chart.js com `getChartTheme()` para cores que se adaptam ao tema - **Responsivo**: Breakpoints em 1200px, 900px, 768px, 480px - **Font**: Inter (Google Fonts) + SF Mono/Fira Code (dark mode) ## Deploy ```bash # Build + restart container docker compose build bi-ccc && docker compose down bi-ccc && docker compose up -d bi-ccc # Ver logs docker logs bi-ccc -f # Criar usuario admin docker exec -it bi-ccc node scripts/seed-admin.js ``` O container: 1. Inicia Netbird VPN daemon (acesso ao RDS via rede privada) 2. Aguarda conexao VPN (~10s) 3. Roda `node server.js` na porta 3080 ## Variaveis de Ambiente | Variavel | Descricao | |----------|-----------| | `MYSQL_URL` | Host do MySQL RDS | | `USER_MYSQL` | Usuario MySQL (read-only) | | `PW_MYSQL` | Senha MySQL | | `SESSION_SECRET` | Secret para express-session | | `PORT` | Porta do servidor (default: 3080) | | `NETBIRD_SETUP_KEY` | Chave de setup da VPN Netbird | | `NETBIRD_MANAGEMENT_URL` | URL do Netbird management | | `AWESOME_API_TOKEN` | Token para API de cotacao USD/BRL em tempo real | ## APIs Internas Todas as APIs retornam JSON e requerem autenticacao. | Endpoint | Descricao | |----------|-----------| | `GET /corporate/api/kpis` | KPIs hoje vs media 30d | | `GET /corporate/api/trend` | Tendencia 30 dias | | `GET /corporate/api/top-agentes?dias=N` | Top 5 agentes | | `GET /corporate/api/kpis-period?inicio=&fim=` | KPIs por periodo | | `GET /corporate/api/trend-period?inicio=&fim=` | Tendencia por periodo | | `GET /admin/api/bi?start=&end=` | BI completo (KPIs, trends, ranking, retencao) | | `GET /admin/api/bi/revenue?start=&end=&granularity=` | Revenue analytics | | `GET /admin/api/bi/strategic?start=&end=` | BI estrategico (cohort, expansion) | | `GET /admin/api/clientes/top` | Top 20 clientes por volume | | `GET /admin/api/clientes/search?q=` | Busca clientes por nome | | `GET /admin/api/cliente/:id/profile` | Profile lifetime do cliente | | `GET /admin/api/cliente/:id/data?start=&end=` | Dados do cliente por periodo | | `GET /api/cotacao` | Cotacao USD/BRL em tempo real (proxy) |