npm package: @plenti.org/ccl
Description: Currency Conversion Library (Compra/Venta USD-COP con comisión)
Author: Finity Team
Latest version: 1.7.0

# @plenti.org/ccl

Currency Conversion Library (CCL) es la librería TypeScript que replica la lógica USD/COP usada en PlentiAll.

## Características clave
- Integración directa con SET-ICAP (mercados 71 y 76) con Yahoo Finance como respaldo automático.
- Horarios, reglas de selección de tasa y validaciones idénticas al backend de producción.
- Caché rotativo con persistencia de la última tasa válida y manejador de errores con códigos tipados.

## Instalación

```bash
npm install @plenti.org/ccl
# o
yarn add @plenti.org/ccl
# o
pnpm add @plenti.org/ccl
```

## Configuración rápida

1. Expone la contraseña de SET-ICAP en tu entorno:

```env
SETICAP_PWD=tu_password_de_seticap
```

2. Importa la librería desde cualquier parte de tu proyecto. Fuera de entornos de test, el token manager y el job de actualización se inician solos:

```ts
import { APIService } from '@plenti.org/ccl';
```

3. Usa utilidades opcionales cuando necesites control manual:

```ts
import { startTokenManager, isTokenAvailable, getCurrentToken } from '@plenti.org/ccl';

startTokenManager();

if (!isTokenAvailable()) {
  throw new Error('Token de Set-ICAP no disponible');
}

const token = getCurrentToken();
```

## Uso rápido

```ts
import { getExchangeRate, checkMarketStatus, getYahooFx, APIService } from '@plenti.org/ccl';

// Orquestación completa con proveedores internos
const rate = await getExchangeRate({
  fetchSeticapSpotRate: async () => (await APIService.getExchangeRates()).usdToCop,
  fetchSeticapNextDayRate: async () => (await APIService.getNextDayExchangeRate()).usdToCop,
  fetchYahooRate: async () => (await getYahooFx()).usdToCop
});

console.log(rate); // { rate, source, marketCondition, timestamp }

// Estado del mercado colombiano en cualquier momento
const status = checkMarketStatus();
console.log(status); // { isOpen, status, condition, description, timeInfo }
```

## Diagrama de flujo

```mermaid
flowchart TD
    A[Aplicación cliente] -->|1. getExchangeRate| B{Token SET-ICAP disponible}
    B -->|Sí| C[Orquestador de mercado]
    B -->|No| D[startTokenManager]
    D --> E[Renueva token y reintenta]
    E --> B
    C --> F[/SET-ICAP mercado 71/]
    F -->|Éxito| J[Selecciona tasa final]
    F -->|Error| G[/SET-ICAP mercado 76/]
    G -->|Éxito| J
    G -->|Error| H[/Yahoo Finance/]
    H -->|Éxito| J
    H -->|Error| I[Última tasa válida o tasa de emergencia]
    J --> K[Actualiza caché rotativo]
    K --> L[Retorna rate, source, marketCondition, timestamp]
    L --> M[Logs y métricas opcionales]
```

## Cómo funciona

- **SET-ICAP**: utiliza `entity: "SOMOSPLENTI"` y `usr_name: "nicolas"`, reintenta hasta 5 veces y renueva token cada 6 horas con `SETICAP_PWD`.
- **Reglas de mercado**: 08:00–13:00 usa tasa spot (71); 13:00–16:30 usa tasa next day (76); fuera de horario se compara SET-ICAP vs Yahoo Finance.
- **Caché**: dos niveles (principal y fallback) que rotan con cada tasa válida; puedes depurarlo con `clearCache()` o inspeccionarlo con `getCacheStatistics()`.
- **Fallbacks y errores**: orden de recuperación 71 → 76 → Yahoo → última tasa → tasa de emergencia, normalizando errores con `ErrorCodes`.

## API esencial

- `getExchangeRate(providers, date?)`: orquesta los proveedores y entrega `{ rate, source, marketCondition, timestamp }`.
- `initializeMarketSystem(config?)`: ajusta caché, fallbacks y timeouts.
- `checkMarketStatus(date?)`: expone metadatos del mercado.
- `globalMarketOrchestrator`: instancia para ejecutar `orchestrateRateProcessing`.
- `APIService`: llamadas directas a SET-ICAP, limpieza de caché y forzado de refresh.
- `getYahooFx()`: proveedor Yahoo Finance sin procesar.
- `globalExchangeRateCache`: gestión manual del caché rotativo.

## Desarrollo

```bash
npm test           # tests unitarios e integración
npm run build      # genera artefactos en dist/
```

## Contribución y licencia

Aceptamos contribuciones vía pull requests. Ejecuta `npm run build` y `npm test` antes de enviarlas. Distribuimos la librería bajo licencia MIT.