Skip to main content

PAMI SII

Trae y sincroniza las autorizaciones (OP) de PAMI, y empuja los movimientos de cumplimiento. Es la fuente de casi todo el trabajo que después procesa el sistema.

No es una API: es scraping

Se navega el portal de efectores de PAMI (efectores.pami.org.ar) con axios + axios-cookiejar-support: login por formulario, cookie de sesión en un CookieJar, y navegación por index2.php, pami_nc y pami_rest.

El HTML cambia sin aviso. Cualquier "dejó de traer autorizaciones" empieza por verificar el login y el parseo, no la lógica de negocio.

Código nuestro

ArchivoRol
src/services/v2/PamiSIIService.tsEl vigente (~2.1k líneas). Login, búsqueda de OP, detalle, getMovements
src/services/v2/PamiSIIFinancesService.tsLa parte de facturación y movimientos
src/migrations/PAMIAuthorizationMigration.tsstartAutoAuthorizationLoop(), el bot de sincronización
src/services/v1/PamiSIIService.tsVersión anterior — no la uses de referencia

Credenciales (nombres de env): PAMI_SII_USERNAME, PAMI_SII_PASSWORD, PAMI_AGREEMENT_ID, PAMI_MAX_SESSION_MINUTES.

Cómo corre

Tres roles, cada uno en su container — ver Workers y colas:

  • bot-publisher — scrapea y publica. Corre en ventana horaria (EXECUTION_START_HOUR / EXECUTION_END_HOUR, default 3–24) y días hábiles (ALLOWED_DAYS), con lock en Redis (fetcher_lock) para que no se pisen instancias.
  • bot-consumer — persiste. En compose hay cuatro.
  • bot-authorization — se activa con EXECUTION_MODE=bot-authorization y PAMI_SII_BOT_AUTHORIZATION=true. Ese flag cortocircuita el switch de mainWorker().

Trazabilidad

Cada corrida deja una fila en logs.PAMIEXECUTIONEVENTLOG con duración, status (IN_PROGRESS / COMPLETED / ERROR) y error; y una fila por ítem procesado en PAMIEXECUTIONEVENTLOGDETAIL.

…EVENTLOGDETAIL es donde se ve qué ítem falló realmente, porque los fallos individuales pueden quedar tragados y reportarse como éxito global.

Mapeo de catálogos

El catálogo de prácticas PAMI vive en configuration.ELEMENTSPAMI. El mapeo contra nuestros elementos está en ELEMENTSPAMIRELATIONSHIP y se hace por code (string), no por id numérico.

Cómo falla en la vida real

Un error dentro del ciclo tira abajo TODO el sync

Caso real: una fila de EventLog con eventType en NULL hacía crashear getMovements, el rollback dejaba la base local congelada en un estado viejo, y mientras tanto el SII ya mostraba la OP como validada.

Si el SII dice una cosa y la consola dice otra, buscá una excepción en el sync, no un problema de datos.

Otros síntomas conocidos:

  • Si el login falla, todo lo posterior falla con errores de parseo sin sentido, no con un 401 claro. El CookieJar vacío se propaga silenciosamente.
  • Un fallo de un ítem individual puede no propagarse al status de la corrida.