Middleware que sincroniza datos contables de 2 sistemas operacionales costarricenses hacia QuickBooks Online. Stateless, multi-organizacion, multi-moneda (CRC/USD).
Arquitectura
APIs externas
api.admindual.com
api.flexmarketingcr.com
→
Middleware
Routes + Controllers
OrganizationQBService
Security + Rate Limit
→
QuickBooks Online
Customers
Invoices / Bills
CreditMemos / Payments
API REST - 22 endpoints
Interactivo en /api-docs — Seleccionar org con ?org=DUAL o header X-Organization
| Tag | Endpoints |
| Sistema |
GET /health-check, /status/:org, /sync-logs |
| Organizaciones |
GET /organizations, /connect/:org, /callback/:org, /test-connection/:org, /test-all-connections |
| Clientes |
GETPOST /customers GETDEL /customers/:id |
| Facturas |
GETPOST /invoices GETPUT /invoices/:id POST /invoices/simulate, /invoices/create-and-update GET /customers/:id/invoices |
| Notas de Credito |
GETPOST /creditmemos POST /payments |
| Impuestos |
GET /taxrates, /taxcodes |
| Reportes |
GET /reports/billing |
APIs Externas
Autenticacion via header apiKey con la clave de cada organizacion.
Dual Servicios — api.admindual.com
| Metodo | Endpoint | Descripcion |
| GET | /api/health | Health check de la API |
| GET | /api/facturas/reportefacturado?desde=&hasta= | Facturas de venta por rango de fechas |
DUAL es solo lectura — no soporta marcar facturas como sincronizadas.
Flex Marketing — api.flexmarketingcr.com
| Metodo | Endpoint | Descripcion |
| GET | /api/health | Health check de la API |
| GET | /facturas | Facturas de venta pendientes |
| PATCH | /facturas/:id | Marcar sincronizada (en_qb: 1) |
| GET | /factura-compras | Facturas de compra pendientes |
| PATCH | /factura-compras/:id | Marcar sincronizada |
| GET | /masters-ncs | Notas de credito pendientes |
| PATCH | /masters-ncs/:id | Marcar sincronizada |
Payload de actualizacion (PATCH)
{ "en_qb": 1, "quickbooks_id": "123" }
Flujo de sincronizacion
1. Consultar API externa → obtener facturas donde en_qb = 0
2. Por cada factura:
a. Determinar moneda (CRC / USD)
b. Buscar o crear cliente en QB (DisplayName + sufijo moneda, max 41 chars)
c. Mapear: consecutivo → DocNumber (max 21 chars), montos, impuestos
d. Crear Invoice / Bill / CreditMemo en QuickBooks
3. Actualizar factura en sistema externo → en_qb = 1
4. Generar resumen JSON en logs/{org}/sync_summary_*.json
5. Si hay errores → enviar notificacion email via SendGrid
6. Dashboard muestra ultimos sync logs via /sync-logs
Scripts de sincronizacion
# DUAL - Sync completo dia por dia (JSON + email)
./scripts/dual-servicios/sincronizar-por-dias-auto.sh
./scripts/dual-servicios/sincronizar-por-dias-auto.sh 2026-01-01 2026-01-31
# FLEX - Sync completo 3 pasos (JSON + email)
./scripts/flex-marketing/sincronizar-todo.sh
# Scripts individuales
node scripts/dual-servicios/facturas-organizacion.js sincronizar
node scripts/flex-marketing/facturas-organizacion.js ventas
node scripts/flex-marketing/factura-compras-organizacion.js sincronizar
node scripts/flex-marketing/credit-notes-organizacion.js procesar
Clases base (scripts/core/)
| Clase | Proposito |
| BaseApiService | HTTP client con retry exponencial (429, timeouts) |
| BaseInvoiceSync | Sync facturas: normalizar cliente, buscar/crear en QB, construir lineas |
| BaseBillSync | Sync compras: asignacion IA de cuentas contables, gestion proveedores |
| BaseCreditNoteSync | Sync NC: crear CreditMemo, buscar factura, aplicar Payment |
Impuestos Costa Rica
| Tasa | Tipo | TaxCode QB |
| 13% | IVA General | 18 |
| 13% | IVA Servicios | 17 |
| 4% | IVA Reducida | - |
| 2% | IVA Minima | - |
| 1% | IVA Especial | - |
| 0% | Exento / Exportacion | 12 |
Seguridad
| Componente | Detalle |
| Tokens | AES-256-GCM en .organization-secrets (permisos 0o600) |
| Access Token | Expira 1 hora, auto-refresh en 401 (1 retry) |
| Refresh Token | 100 dias, re-auth manual si expira |
| API Keys | Validadas via middleware validateApiKey |
| Rate Limiting | Backoff exponencial: 1s, 2s, 4s, 8s en 429 |
| Headers | Helmet + CORS configurado |
Autenticacion
El middleware usa OAuth 2.0 con QuickBooks Online via el SDK oficial de Intuit.
SDK y portal de desarrollo
Tokens
| Aspecto | Detalle |
| Protocolo | OAuth 2.0 (Authorization Code Flow) |
| Access Token | Expira cada hora, se renueva automaticamente |
| Refresh Token | Valido por 100 dias, requiere re-auth manual si expira |
| Almacenamiento | Tokens encriptados con AES-256-GCM |
Flujo de renovacion
1. Usuario inicia conexion desde el dashboard
2. Redirige a QuickBooks para autorizar la app
3. QuickBooks devuelve un authorization code via callback
4. El middleware intercambia el code por access + refresh token
5. Tokens se almacenan encriptados localmente
Cuando renovar manualmente
La renovacion es automatica en la mayoria de los casos. Solo se requiere intervencion manual cuando:
| Escenario | Accion |
| Refresh token expirado (100+ dias inactivo) | Re-autorizar desde el dashboard |
| Credenciales corruptas o eliminadas | Re-autorizar desde el dashboard |
| Cambio de permisos en la app QB | Re-autorizar para aceptar nuevos scopes |
Errores comunes
| Error | Causa | Solucion |
| 401 | Token expirado | Auto-refresh. Si falla → /connect/:org |
| 403 (3100) | Sin permisos | Se simula respuesta exitosa |
| 429 | Rate limit | Backoff exponencial automatico |
| DocNumber dup | Consecutivo existe | Se registra error y continua |
| CurrencyRef | Moneda inmutable | Crear nuevo cliente con sufijo correcto |
Guias detalladas
Facturas de Compras
Sistema con asignacion IA de cuentas contables, proveedores automaticos
Cronjobs
Automatizacion de sincronizaciones programadas
Multi-moneda
Logica de diferenciacion CRC/USD, tipo de cambio, sufijos
Impuestos
TaxCodes, tarifas IVA Costa Rica, configuracion en QB
Seguridad
Encriptacion, CORS, Helmet, sanitizacion, mejores practicas
Rate Limiting
Backoff exponencial, manejo de 429, limites de QuickBooks
Logging
Configuracion de logs en produccion con Winston
Notificaciones
Email automatico via SendGrid cuando fallan sincronizaciones
Currency Utils
Utilidades de conversion y manejo de monedas
Tarifas e Impuestos
Desglose de tarifas en facturas de compra, cuentas contables