Concepto

El sistema diferencia automaticamente clientes en QuickBooks por moneda de transaccion. Un mismo cliente puede tener multiples entidades en QB — una por cada moneda con la que opera.

Regla clave: La CurrencyRef de un cliente en QuickBooks es inmutable despues de crearlo. Por eso se crean entidades separadas por moneda, cada una con su sufijo en el DisplayName.
Factura entrante
Detectar moneda
Buscar / crear cliente
Cliente CRC
Cliente USD
Monedas soportadas
MonedaNombreSimboloRol
CRCColon CostarricenseMoneda base (por defecto)
USDDolar Estadounidense$Moneda extranjera
Diferenciacion de clientes

Cada cliente lleva un sufijo de moneda en su DisplayName. Maximo 41 caracteres — el nombre se trunca para dejar espacio al sufijo.

Ejemplo practico

Cliente original: Cori Motors De Centroamerica S.A. — Codigo: 00190

MonedaDisplayName en QBNotesCurrencyRef
CRCCori Motors De Centroamerica... CRC00190CRC
USDCori Motors De Centroamerica... USD00190USD

Campos configurados

{
  DisplayName: "Empresa Prueba Costa Rica CRC",  // max 41 chars, con sufijo
  CompanyName: "Empresa Prueba Costa Rica",       // nombre completo sin sufijo
  Notes: "00TEST",                                // codigo interno para busqueda
  PrimaryTaxIdentifier: "31012345678",            // cedula / RUC
  CurrencyRef: { value: "CRC" }                   // INMUTABLE despues de crear
}
Algoritmo de busqueda

El sistema busca al cliente en 3 pasos. Si ninguno encuentra coincidencia, crea uno nuevo.

1. Buscar por Notes (codigo interno) + CurrencyRef
   cliente = clientes.find(c =>
       c.Notes === codigo &&
       c.CurrencyRef?.value === moneda
   );

2. Buscar por DisplayName exacto con sufijo
   const nombreConMoneda = `${nombre} ${moneda}`;
   cliente = clientes.find(c =>
       c.DisplayName === nombreConMoneda
   );

3. No encontrado → crear nuevo cliente con:
   - DisplayName con sufijo (truncado a 41 chars)
   - CurrencyRef con la moneda
   - Notes con codigo interno
Prioridad: La busqueda por Notes + CurrencyRef es el metodo preferido porque el codigo interno es unico y no cambia, mientras que el nombre puede variar.
Tipo de cambio (ExchangeRate)

Solo aplica a transacciones en moneda extranjera (USD). Debe ser siempre tipo number, nunca string.

MonedaExchangeRateRequiere configFuente
CRC1 (moneda base)No
USD~500–550SiCampo tipo_cambio o exchange_rate de la factura

Aplicacion a estructuras QB

Factura CRC
{
  CustomerRef: { value: "42" },
  CurrencyRef: { value: "CRC" },
  DocNumber: "FE-001-2025",
  Line: [...]
}
Factura USD
{
  CustomerRef: { value: "43" },
  CurrencyRef: { value: "USD" },
  ExchangeRate: 512.50,
  DocNumber: "FE-002-2025",
  Line: [...]
}
Valor por defecto: Si la factura no trae tipo_cambio, se usa 500 como fallback para USD.
CurrencyUtils — API de referencia

Modulo centralizado en src/utils/currencyUtils.js que elimina duplicacion de logica de moneda entre scripts.

FuncionDescripcion
determinarConfiguracionMoneda(factura)Detecta moneda y retorna config completa (moneda, exchangeRate, simbolo)
buscarEntidadPorMoneda(entidades, nombre, config, normFn)Busca cliente/proveedor considerando moneda especifica
crearNombreConMoneda(nombre, config, normFn)Genera DisplayName con sufijo, truncado a 41 chars
agregarConfiguracionMoneda(estructura, config)Agrega CurrencyRef y ExchangeRate a un objeto QB
formatearMonto(monto, config)Formatea con simbolo: $1,500.00 o ₡750,000.00

Deteccion de moneda

// Criterios para detectar USD:
1. Campo moneda o currency = 'USD'
2. Nombre del cliente/proveedor contiene 'USD'
3. Campo nombre o cliente contiene 'USD'

// Cualquier otro caso → CRC (moneda base por defecto)

Uso en scripts

const CurrencyUtils = require('../../src/utils/currencyUtils');

// 1. Detectar moneda
const config = CurrencyUtils.determinarConfiguracionMoneda(factura);

// 2. Buscar/crear entidad con diferenciacion
const cliente = await this.buscarOCrearClienteConMoneda(
    factura.cliente, config
);

// 3. Crear estructura QB
const invoiceData = { CustomerRef: { value: cliente.Id } };

// 4. Aplicar configuracion de moneda
CurrencyUtils.agregarConfiguracionMoneda(invoiceData, config);
// → agrega CurrencyRef y ExchangeRate si USD
Troubleshooting
ProblemaCausaSolucion
CurrencyRef inmutableSe intento cambiar moneda de cliente existenteCrear nuevo cliente con sufijo correcto
ExchangeRate como stringDato de factura llega como "512.50"Number(exchangeRate) — siempre convertir
Entidades duplicadasFuncion normalizarFn inconsistenteRevisar logica de normalizacion y busqueda
Tipo de cambio incorrectoCampo tipo_cambio ausenteVerificar datos de factura, fallback a 500
DisplayName excede 41 charsNombre muy largo + sufijoSe trunca automaticamente, verificar resultado

Verificar monedas en QuickBooks

node scripts/utilities/check-quickbooks-currencies.js
node scripts/utilities/debug-currency.js