@ramiidv/arca-fecred 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,124 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8c02c30: API uniforme entre los SDKs (los nombres anteriores siguen funcionando,
8
+ marcados `@deprecated`, hasta la próxima major):
9
+
10
+ - arca-facturacion: la clase principal es `ArcaFacturacion` (`Arca` queda como
11
+ alias). Nuevo `status()` → `{ wsfe, wsfex }` con `ServiceStatus` y el
12
+ `ServerStatus` de arca-common (`appserver`/`dbserver`/`authserver`);
13
+ `serverStatus()`/`serverStatusExpo()` y su `ServerStatus` en mayúsculas
14
+ quedan deprecados.
15
+ - arca-agro: `status()` (antes `serverStatus()`).
16
+ - arca-fecred: el cliente de bajo nivel es `client` (antes `fecred`).
17
+ - arca-common: `ServiceStatus` y `statusOf()` para el estado de varios servicios.
18
+ - bed68e8: Paquetes solo ESM y Node >= 20.19. `arca-common`, `arca-facturacion` y
19
+ `arca-padron` dejan de publicar un build CommonJS: desde CommonJS se cargan con
20
+ `require()` (require(esm), Node >= 20.19 / 22.12). Todos los paquetes pasan a
21
+ requerir Node >= 20.19.0 (Node 18 y 20 sin soporte). El código vive ahora en el
22
+ monorepo `arca-sdks`.
23
+ - f8bd053: Las clases principales extienden `ArcaSdkBase` de arca-common, así que todos
24
+ los SDKs tienen la misma base: `wsaa`, `cuit`, `production`, `on()`/`off()`,
25
+ `clearAuthCache()`, `config.wsaa` (WsaaClient compartido) y `config.signal`
26
+ (signal global). arca-mtxca acepta `endpoints: { mtxca, wsaa }` (`endpoint` y
27
+ `wsaaEndpoint` quedan deprecados). Los `dummy`/`status` validan la respuesta con
28
+ `parseServerStatus`: si falta un campo lanzan `ArcaSoapError`.
29
+ - c9f1444: Requests y respuestas se validan, serializan y decodifican con el DSL de
30
+ `@ramiidv/arca-common/schema`, transcripto del XSD oficial de cada servicio.
31
+
32
+ - Corrección: las respuestas se parsean sin conversión numérica, así que los
33
+ `xs:string` con contenido numérico ya no pierden ceros a la izquierda ni
34
+ decimales (ej: `"0012"`, `"1.50"`, `DocNro`, `codigoSeguridad`).
35
+ - Los campos desconocidos en el input se rechazan con `ArcaValidationError`
36
+ (antes se ignoraban).
37
+ - Todos los errores de validación se informan juntos (`details`), con mensajes
38
+ del tipo `campo: motivo`. Cambió el texto de los mensajes.
39
+ - arca-fecred deja de recortar espacios de los textos y envía `codCtaCte` tal
40
+ cual; porcentaje y cotización se envían con decimales fijos.
41
+
42
+ ### Patch Changes
43
+
44
+ - 20ecf7d: DSL de schemas, segunda versión:
45
+
46
+ - Corrección: `dec()` redondea sobre el valor decimal escrito (`8.575` →
47
+ `8.58`; antes daba `8.57` por la representación binaria). Afecta los importes
48
+ que los SDKs envían redondeados.
49
+ - `must()` rechaza también el valor vacío; los elementos `xsi:nil` cuentan
50
+ como ausentes (en una lista, como lista vacía); `must()` en listas exige el
51
+ elemento; un objeto opcional vacío se omite y uno obligatorio valida sus hijos.
52
+ - Al decodificar se validan enteros (`int()`) y valores permitidos
53
+ (`str({ values })`).
54
+ - Nuevos: `siNo()` (S/N ↔ boolean), `double()`, `xml(nombre, campo)` (nombre
55
+ distinto en el XML), `custom(encode, decode)`, `roundHalfUp()` y
56
+ `decodeResponse(..., { emptyLists: 'omit' })`.
57
+ - Updated dependencies [8c02c30]
58
+ - Updated dependencies [f8bd053]
59
+ - Updated dependencies [242fb5f]
60
+ - Updated dependencies [fd438bc]
61
+ - Updated dependencies [bed68e8]
62
+ - Updated dependencies [20ecf7d]
63
+ - Updated dependencies [b86db00]
64
+ - @ramiidv/arca-common@0.5.0
65
+
66
+ ## 0.3.0 (2026-11-01)
67
+
68
+ Revisión completa contra el WSDL de FECredService. La 0.2.0 no podía operar contra ARCA.
69
+
70
+ ### Breaking
71
+ - Requiere `@ramiidv/arca-common` `^0.4.0`. `ArcaFecredConfig` extiende `ArcaBaseConfig` (`cuit: number | string`).
72
+ - `consultarMontoObligadoRecepcion({ cuitConsultada, fechaEmision })`: ahora recibe un objeto (el XSD exige `fechaEmision`).
73
+ - `consultarCtasCtes` y `consultarComprobantes` reciben `{ rol, cuitContraparte?, fecha?: { tipo, desde, hasta }, ... }` (antes `fechaDesde`/`fechaHasta`/`cuitEmisor`/`cuitReceptor`, que no existen en el XSD) y devuelven `{ ctasCtes | comprobantes, nroPagina?, hayMas?, evento?, observaciones }` en lugar de un array.
74
+ - `aceptarFECred(params)`, `rechazarFECred(params)`: reciben `idCtaCte` (`{ codCtaCte }` o `{ idFactura }`) y los campos obligatorios del XSD (`saldoAceptado`, `codMoneda`, `cotizacionMonedaUlt`; `motivos[]` con `codMotivo`, `descMotivo`, `justificacion`). Devuelven `{ resultado, idCtaCte, evento?, observaciones }`.
75
+ - `informarFacturaAceptadaCancelada` se reemplaza por `informarCancelacionTotalFECred({ idCtaCte, formasCancelacion, importeCancelacion })` (la operación anterior no existe).
76
+ - `consultarTiposMotivoRechazo` → `consultarTiposMotivosRechazo`. Los `consultarTipos*` devuelven `{ codigo, descripcion }[]`; `consultarTiposRetenciones` devuelve `{ codigoJurisdiccion, descripcionJurisdiccion, porcentajeRetencion }[]`.
77
+ - Tipos de respuesta según el XSD (`InfoCtaCte`, `Comprobante`, `CuentaCorriente`, ...). `codCtaCte`, CUITs y `codAutorizacion` son `string`. Se eliminan `raw`, `CtaCte`, `ComprobanteFecred`, `RetencionFecred`, `*Item`, `WsFecredError`.
78
+ - `EstadoCtaCte` con los valores reales (`Modificable`, `Aceptada`, `Rechazada`, `CanceladaTotal`, `InformadaAgDpto`); `RolCtaCte`/`EstadoCtaCte` pasan a ser objetos `as const` + tipo literal.
79
+ - Se eliminan los enums inventados `MotivoRechazo`, `FormaCancelacion`, `TipoAjusteOperacion` y `TipoRetencion`: los códigos se obtienen con `consultarTipos*()`.
80
+ - `ENDPOINTS` ya no incluye `wsaa` (usar `WSAA_ENDPOINTS` de common) y `ENDPOINTS.wsfecred.namespace` es `http://ar.gob.afip.wsfecred/FECredService/`.
81
+ - `FecredClient`: recibe `{ token, sign, cuitRepresentada }` (o una función que lo devuelve), valida los parámetros y devuelve respuestas tipadas en lugar de `Record<string, unknown>`.
82
+ - `WsAuth` es `{ token, sign, cuitRepresentada }`.
83
+ - `clearAuthCache()` devuelve `Promise<void>`.
84
+ - Se eliminan `validateCuit` (usar el de common), `validateCodCtaCte`, `validateConsultaCtasCtes` y los re-exports de utilidades de common (`ensureArray`, `parseXml`, `buildXml`, `checkServiceErrors`, `SoapCallOptions`, `WsaaClientConfig`).
85
+
86
+ ### Features
87
+ - Nuevas operaciones del WSDL: `consultarObligadoRecepcion`, `consultarCtaCte`, `consultarHistorialEstadosComprobante`, `consultarHistorialEstadosCtaCte`, `obtenerRemitos`, `rechazarNotaDC`, `modificarOpcionTransferencia`, `informarFacturaAgtDptoCltv`, `consultarCuentasEnAgtDptoCltv` y `consultarFacturasAgtDptoCltv`.
88
+ - `aceptarFECred` soporta todos los opcionales del XSD (notas DC, formas de cancelación, retenciones, ajustes, tipo de cancelación, importes, CBU).
89
+ - Todos los métodos aceptan `opts?: CallOptions` (`signal`).
90
+ - Config: `ticketStorage`, `clockOffsetMs`, `autoClockSkew`, `loginErrorCooldownMs`, `tokenTTLMinutes`, `fetch`, `legacyTls`, `wsaa` (cliente propio) y `endpoints` (override).
91
+ - Enums del XSD: `EstadoComprobante`, `TipoFechaFiltro`, `OpcionTransferencia`, `TipoCancelacion`, `TipoAceptacion`, `Resultado`.
92
+ - Validación local según el XSD (CUIT con dígito verificador, fechas, importes con 2 decimales, rangos de punto de venta/número, textos 3..250, CBU) antes de pedir el ticket.
93
+ - Se exportan `ArcaValidationError`, `ArcaTicketVigenteError`, `FileTicketStorage` y `MemoryTicketStorage`.
94
+
95
+ ### Fixes
96
+ - Namespace correcto y `SOAPAction` en todas las operaciones (sin él ARCA responde `NullPointerException`); `dummy` con Body vacío.
97
+ - `authRequest` con `token`/`sign`/`cuitRepresentada` (ARCA respondía `wscommon_005`). La CUIT se envía como 11 dígitos.
98
+ - Wrapper `<operacionRequest>` según los elementos del XSD y campos en el orden del XSD (`idCtaCte` anidado, `fecha{tipo,desde,hasta}`, `rolCUITRepresentada`).
99
+ - `obligado` (`S`/`N`) se convertía a boolean con un cast: `'N'` era `true`.
100
+ - Los parsers leían contenedores inexistentes (`arrayCtasCtes`, `tipoComprobante`, ...) y devolvían listas vacías; ahora leen `arrayInfosCtaCte/infoCtaCte`, `arrayComprobantes/comprobante`, `codigoDescripcionReturn/arrayCodigoDescripcion/codigoDescripcion`, etc.
101
+ - Un campo obligatorio ausente en la respuesta lanza error en lugar de devolver `0`/`''`.
102
+ - `arrayErrores` y `arrayErroresFormato` (`codigoDescripcionString`) se lanzan como `ArcaServiceError`; `resultado = 'R'` también.
103
+ - Las operaciones se envían con `kind: 'emision'`: no se reintentan y un error de transporte queda `uncertain`.
104
+
105
+ ## 0.2.0 (2026-06-03)
106
+
107
+ - CI con GitHub Actions (Node 18/20/22) y workflow de release por tag.
108
+ - `homepage` apunta a arca-sdk.dev.
109
+ - Lockfile regenerado para resolver `@ramiidv/arca-common` desde npm (el build fallaba en CI).
110
+
111
+ ## 0.1.0 (2026-03-31)
112
+
113
+ ### Features
114
+ - Initial release
115
+ - Orchestrator class `ArcaFecred` with automatic WSAA authentication
116
+ - Check FCE obligation status (`consultarMontoObligadoRecepcion`)
117
+ - Query current accounts (`consultarCtasCtes`) and invoices (`consultarComprobantes`)
118
+ - Accept (`aceptarFECred`) and reject (`rechazarFECred`) electronic credit invoices
119
+ - Inform accepted FCE cancellation (`informarFacturaAceptadaCancelada`)
120
+ - Parameter queries: retention types, cancellation methods, adjustment types, rejection reasons
121
+ - Input validation with `ArcaValidationError` from `@ramiidv/arca-common`
122
+ - Low-level `FecredClient` for direct SOAP access
123
+ - Enums: `RolCtaCte`, `EstadoCtaCte`, `MotivoRechazo`, `FormaCancelacion`, `TipoAjusteOperacion`, `TipoRetencion`
124
+ - Health check via `status()` / `dummy()`
package/README.md CHANGED
@@ -4,347 +4,186 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Node >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
6
6
 
7
- SDK en TypeScript para el web service **WSFECRED** de **ARCA** (ex AFIP) -- Factura de Credito Electronica MiPyME (Ley 27440).
7
+ SDK en TypeScript para el web service **WSFECRED** (FECredService) de **ARCA** (ex AFIP): Factura de Crédito Electrónica MiPyME (Ley 27.440).
8
8
 
9
- Gestiona el ciclo de vida completo de las FCE: consulta de obligados, cuentas corrientes, comprobantes, aceptacion, rechazo e informar cancelacion.
9
+ Cubre todas las operaciones del WSDL: obligación de recepción, cuentas corrientes, comprobantes, historial de estados, remitos, aceptación, rechazo, cancelación total, rechazo de notas de débito/crédito, opción de transferencia, Agentes de Depósito Colectivo y tablas de parámetros.
10
10
 
11
- ## Instalacion
11
+ > **0.3.0 es un cambio incompatible**: la versión anterior no funcionaba contra ARCA (namespace, auth y nombres de operaciones incorrectos). Ver [CHANGELOG](./CHANGELOG.md).
12
+
13
+ ## Instalación
12
14
 
13
15
  ```bash
14
16
  npm install @ramiidv/arca-fecred
15
17
  ```
16
18
 
17
- ## Requisitos
18
-
19
- - Node.js >= 18
20
- - Certificado digital X.509 y clave privada de ARCA
21
- - **Testing**: generalo desde [WSASS Homologacion](https://wsass-homo.afip.gob.ar/wsass/portal/main.aspx)
22
- - **Produccion**: generalo desde [Administracion de Certificados Digitales](https://www.afip.gob.ar/ws/documentacion/certificados.asp) (requiere clave fiscal en [arca.gob.ar](https://arca.gob.ar))
19
+ Requisitos: Node.js >= 18 y un certificado de ARCA con el servicio `wsfecred` autorizado
20
+ ([WSASS homologación](https://wsass-homo.afip.gob.ar/wsass/portal/main.aspx) o
21
+ [Administración de Certificados Digitales](https://www.afip.gob.ar/ws/documentacion/certificados.asp) en producción).
23
22
 
24
- ## Uso rapido
23
+ ## Uso rápido
25
24
 
26
25
  ```typescript
27
26
  import { readFileSync } from 'fs';
28
- import { ArcaFecred, RolCtaCte, MotivoRechazo, FormaCancelacion } from '@ramiidv/arca-fecred';
27
+ import { ArcaFecred, FileTicketStorage } from '@ramiidv/arca-fecred';
29
28
 
30
29
  const fecred = new ArcaFecred({
31
30
  cert: readFileSync('./cert.pem', 'utf-8'),
32
31
  key: readFileSync('./key.pem', 'utf-8'),
33
- cuit: '20123456789',
34
- production: false, // true para produccion
32
+ cuit: '20-12345678-6', // CUIT representada (number o string, con o sin guiones)
33
+ production: false,
34
+ ticketStorage: new FileTicketStorage('./.arca-tickets'),
35
35
  });
36
36
 
37
- // Verificar si una CUIT esta obligada a recibir FCE
38
- const obligado = await fecred.consultarMontoObligadoRecepcion('30712345678');
39
- console.log(obligado.obligado); // true/false
40
-
41
- // Consultar cuentas corrientes como receptor
42
- const cuentas = await fecred.consultarCtasCtes({
43
- rol: RolCtaCte.RECEPTOR,
44
- fechaDesde: '2026-01-01',
45
- fechaHasta: '2026-03-31',
37
+ // ¿La CUIT receptora está obligada a recibir FCE?
38
+ const { obligado, montoDesde } = await fecred.consultarMontoObligadoRecepcion({
39
+ cuitConsultada: '30712345671',
40
+ fechaEmision: '2026-11-01',
46
41
  });
47
42
 
48
- for (const cta of cuentas) {
49
- console.log(`FCE #${cta.codCtaCte}: $${cta.importeTotal} - ${cta.estado}`);
50
- }
51
-
52
- // Aceptar una FCE
53
- const aceptar = await fecred.aceptarFECred(12345);
54
- console.log(aceptar.resultado);
55
-
56
- // Rechazar una FCE
57
- const rechazar = await fecred.rechazarFECred(12345, MotivoRechazo.CBU_INCORRECTO);
58
- console.log(rechazar.resultado);
59
-
60
- // Informar que una FCE aceptada fue pagada
61
- const cancelar = await fecred.informarFacturaAceptadaCancelada({
62
- codCtaCte: 12345,
63
- codFormaCancelacion: FormaCancelacion.TRANSFERENCIA,
43
+ // Cuentas corrientes recibidas en octubre (paginado)
44
+ const { ctasCtes, hayMas } = await fecred.consultarCtasCtes({
45
+ rol: 'Receptor',
46
+ fecha: { tipo: 'Emision', desde: '2026-10-01', hasta: '2026-10-31' },
64
47
  });
65
- console.log(cancelar.resultado);
66
- ```
67
48
 
68
- ## Configuracion
69
-
70
- ```typescript
71
- const fecred = new ArcaFecred({
72
- cert: '...', // Certificado X.509 (PEM)
73
- key: '...', // Clave privada (PEM)
74
- cuit: '20123456789', // CUIT representada
75
- production: false, // Default: false (testing/homologacion)
76
- timeout: 30_000, // Default: 30000 (30 segundos)
77
- retries: 1, // Default: 1 (reintentos en errores transitorios)
78
- retryDelayMs: 1_000, // Default: 1000 (backoff exponencial: 1s, 2s, ...)
79
- onEvent: (e) => { // Opcional: callback para logging/debugging
80
- console.log(e.type, e);
81
- },
82
- });
83
- ```
84
-
85
- ## Ejemplos
86
-
87
- ### Verificar obligacion de recepcion FCE
88
-
89
- ```typescript
90
- const resultado = await fecred.consultarMontoObligadoRecepcion('30712345678');
91
-
92
- if (resultado.obligado) {
93
- console.log(`CUIT obligada a recibir FCE desde $${resultado.montoDesde}`);
94
- } else {
95
- console.log('CUIT no obligada a recibir FCE');
96
- }
97
- ```
98
-
99
- ### Consultar cuentas corrientes
100
-
101
- ```typescript
102
- // Como emisor (mis facturas FCE emitidas)
103
- const misEmitidas = await fecred.consultarCtasCtes({
104
- rol: RolCtaCte.EMISOR,
105
- fechaDesde: '2026-01-01',
106
- fechaHasta: '2026-03-31',
107
- });
108
-
109
- // Como receptor (FCE que me enviaron)
110
- const recibidas = await fecred.consultarCtasCtes({
111
- rol: RolCtaCte.RECEPTOR,
112
- cuitEmisor: '30712345678', // opcional: filtrar por emisor
113
- fechaDesde: '2026-01-01',
114
- fechaHasta: '2026-03-31',
115
- });
116
- ```
117
-
118
- ### Consultar comprobantes FCE
119
-
120
- ```typescript
121
- // Buscar por CUIT emisor
122
- const comprobantes = await fecred.consultarComprobantes({
123
- cuitEmisor: '30712345678',
124
- fechaDesde: '2026-01-01',
125
- fechaHasta: '2026-03-31',
126
- });
127
-
128
- // Buscar un comprobante especifico por codigo de cuenta corriente
129
- const comprobante = await fecred.consultarComprobantes({
130
- codCtaCte: 12345,
131
- });
132
- ```
133
-
134
- ### Aceptar y luego informar cancelacion
135
-
136
- ```typescript
137
- import { FormaCancelacion } from '@ramiidv/arca-fecred';
138
-
139
- // 1. Aceptar la FCE
140
- await fecred.aceptarFECred(12345);
141
-
142
- // 2. Luego de pagar, informar la cancelacion
143
- await fecred.informarFacturaAceptadaCancelada({
144
- codCtaCte: 12345,
145
- codFormaCancelacion: FormaCancelacion.TRANSFERENCIA,
146
- observaciones: 'Transferencia realizada el 2026-03-15',
49
+ // Aceptar una FCE
50
+ const r = await fecred.aceptarFECred({
51
+ idCtaCte: { codCtaCte: ctasCtes[0].codCtaCte },
52
+ saldoAceptado: ctasCtes[0].saldo,
53
+ codMoneda: ctasCtes[0].codMoneda,
54
+ cotizacionMonedaUlt: 1,
147
55
  });
56
+ console.log(r.resultado); // 'A' o 'O' (un rechazo se lanza como ArcaServiceError)
148
57
  ```
149
58
 
150
- ### Rechazar una FCE
59
+ ## Configuración
60
+
61
+ `ArcaFecredConfig` extiende `ArcaBaseConfig` de `@ramiidv/arca-common`:
62
+
63
+ | Opción | Tipo | Default | Descripción |
64
+ | -------------------------------------------------------- | ------------------------------- | ------------------ | ----------------------------------------------------------------------------- |
65
+ | `cert`, `key` | `string` | — | Certificado y clave privada (PEM) |
66
+ | `cuit` | `number \| string` | — | CUIT representada; se valida el dígito verificador y se envía como 11 dígitos |
67
+ | `production` | `boolean` | `false` | Homologación o producción |
68
+ | `timeout` | `number` | `30000` | Timeout HTTP (ms) |
69
+ | `retries` / `retryDelayMs` | `number` | `1` / `1000` | Reintentos de **consultas** (las operaciones nunca se reintentan) |
70
+ | `tokenTTLMinutes` | `number` | `720` | Vigencia pedida a WSAA |
71
+ | `ticketStorage` | `TicketStorage` | — | Persistencia del TA (recomendado en producción: `FileTicketStorage` o propio) |
72
+ | `clockOffsetMs`, `autoClockSkew`, `loginErrorCooldownMs` | | | Opciones de WSAA (ver arca-common) |
73
+ | `fetch` | `typeof fetch` | `globalThis.fetch` | `fetch` propio (proxy, tests) |
74
+ | `legacyTls` | `'auto' \| 'never' \| 'always'` | `'auto'` | Transporte TLS legacy |
75
+ | `onEvent` | `(e: ArcaEvent) => void` | — | Eventos `auth:*` y `request:*` |
76
+ | `wsaa` | `WsaaClient` | — | `WsaaClient` propio (compartir tickets entre SDKs) |
77
+ | `endpoints` | `{ wsfecred?, wsaa? }` | — | Sobrescribe las URLs |
78
+
79
+ Todos los métodos aceptan un último parámetro opcional `opts?: CallOptions` (`{ signal }`) para cancelar.
80
+
81
+ ## Operaciones
82
+
83
+ Fuente: WSDL de FECredService (`https://fwshomo.afip.gob.ar/wsfecred/FECredService?wsdl`). Los nombres de campos siguen el XSD.
84
+
85
+ ### Consultas (se reintentan ante errores transitorios)
86
+
87
+ | Método | Operación | Devuelve |
88
+ | -------------------------------------------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------------------ |
89
+ | `status()` | `dummy` | `{ appserver, dbserver, authserver }` |
90
+ | `consultarMontoObligadoRecepcion({ cuitConsultada, fechaEmision })` | idem | `{ obligado, montoDesde?, evento?, observaciones }` |
91
+ | `consultarObligadoRecepcion(cuit)` | idem | `{ obligado, desde?, ... }` (campo `respuesta` del WS) |
92
+ | `consultarCtasCtes({ rol, cuitContraparte?, fecha?, estadoCtaCte?, nroPagina?, opcionTransferencia? })` | idem | `{ ctasCtes: InfoCtaCte[], nroPagina?, hayMas?, ... }` |
93
+ | `consultarCtaCte(idCtaCte)` | idem | `{ ctaCte: CuentaCorriente, ... }` |
94
+ | `consultarComprobantes({ rol, cuitContraparte?, codTipoCmp?, estadoCmp?, fecha?, codCtaCte?, estadoCtaCte?, nroPagina? })` | idem | `{ comprobantes: Comprobante[], nroPagina?, hayMas?, ... }` |
95
+ | `consultarHistorialEstadosComprobante(idComprobante)` | idem | `{ idComprobante, estados }` |
96
+ | `consultarHistorialEstadosCtaCte(idCtaCte)` | idem | `{ idCtaCte, estados }` |
97
+ | `obtenerRemitos(idComprobante)` | idem | `IdComprobante[]` |
98
+ | `consultarCuentasEnAgtDptoCltv()` | idem | `{ cuentas, ... }` |
99
+ | `consultarFacturasAgtDptoCltv({ idCtaCte?, fecha? })` | idem | `{ facturas, ... }` |
100
+ | `consultarTiposRetenciones()` | idem | `{ codigoJurisdiccion, descripcionJurisdiccion, porcentajeRetencion }[]` |
101
+ | `consultarTiposFormasCancelacion()` | idem | `{ codigo, descripcion }[]` |
102
+ | `consultarTiposMotivosRechazo()` | idem | `{ codigo, descripcion }[]` |
103
+ | `consultarTiposAjustesOperacion()` | idem | `{ codigo, descripcion }[]` |
104
+
105
+ ### Operaciones que cambian estado (emisiones: nunca se reintentan)
106
+
107
+ | Método | Operación | Devuelve |
108
+ | ------------------------------------------------------------------------------------- | --------- | ------------------------------------------------------------- |
109
+ | `aceptarFECred({ idCtaCte, saldoAceptado, codMoneda, cotizacionMonedaUlt, ... })` | idem | `{ resultado: 'A' \| 'O', idCtaCte, evento?, observaciones }` |
110
+ | `rechazarFECred({ idCtaCte, motivos })` | idem | idem |
111
+ | `informarCancelacionTotalFECred({ idCtaCte, formasCancelacion, importeCancelacion })` | idem | idem |
112
+ | `modificarOpcionTransferencia({ idCtaCte, opcionTransferencia })` | idem | idem |
113
+ | `informarFacturaAgtDptoCltv({ idCtaCte, ctaAgente })` | idem | idem |
114
+ | `rechazarNotaDC({ idComprobante, motivos })` | idem | `{ resultado, idComprobante, ... }` |
115
+
116
+ `aceptarFECred` acepta además los opcionales del XSD: `confirmarNotasDC` (`{ acepta, idNota }[]`), `formasCancelacion`, `retenciones` (`{ codTipo, importe, porcentaje, descMotivo? }[]`), `ajustesOperacion` (`{ codigo, importe }[]`), `tipoCancelacion` (`'PAR' | 'TOT'`), `importeCancelado`, `importeTotalRetPesos`, `importeEmbargoPesos`, `informaCBU` y `cbuComprador`.
117
+
118
+ ### Identificadores
151
119
 
152
120
  ```typescript
153
- import { MotivoRechazo } from '@ramiidv/arca-fecred';
121
+ // IdCtaCteType es un xsd:choice: por código de cuenta corriente o por factura
122
+ const porCodigo = { codCtaCte: '1234567890' };
123
+ const porFactura = { idFactura: { cuitEmisor: '30712345671', codTipoCmp: 201, ptoVta: 3, nroCmp: 125 } };
154
124
 
155
- await fecred.rechazarFECred(12345, MotivoRechazo.OTROS);
125
+ await fecred.consultarCtaCte(porFactura);
156
126
  ```
157
127
 
158
- ### Consultar parametros disponibles
128
+ Las respuestas devuelven `codCtaCte`, CUITs y `codAutorizacion` (CAE) como **string**; importes como `number`; fechas como el string que envía ARCA; los `S`/`N` como `boolean`.
159
129
 
160
- ```typescript
161
- // Tipos de retencion
162
- const retenciones = await fecred.consultarTiposRetenciones();
163
- for (const r of retenciones) {
164
- console.log(`${r.codTipoRetencion}: ${r.descTipoRetencion}`);
165
- }
130
+ ### Paginado
166
131
 
167
- // Formas de cancelacion
168
- const formas = await fecred.consultarTiposFormasCancelacion();
132
+ `consultarCtasCtes` y `consultarComprobantes` devuelven `nroPagina` y `hayMas`. Pedí la página siguiente con `nroPagina`.
169
133
 
170
- // Tipos de ajuste de operacion
171
- const ajustes = await fecred.consultarTiposAjustesOperacion();
134
+ ### Tablas de códigos
172
135
 
173
- // Motivos de rechazo
174
- const motivos = await fecred.consultarTiposMotivoRechazo();
175
- ```
136
+ Los códigos de formas de cancelación, motivos de rechazo, ajustes de operación y retenciones **no están en el WSDL**: obtenelos con `consultarTipos*()`. El SDK solo exporta las enumeraciones definidas en el XSD:
137
+ `RolCtaCte`, `EstadoCtaCte` (`Modificable`, `Aceptada`, `Rechazada`, `CanceladaTotal`, `InformadaAgDpto`), `EstadoComprobante`, `TipoFechaFiltro`, `OpcionTransferencia` (`SCA`, `ADC`), `TipoCancelacion` (`PAR`, `TOT`), `TipoAceptacion` y `Resultado`. Se pueden usar como `RolCtaCte.RECEPTOR` o con el literal (`'Receptor'`).
176
138
 
177
- ### Health check
139
+ ## Errores
178
140
 
179
- ```typescript
180
- const status = await fecred.status();
181
- console.log(status.appserver); // "OK"
182
- console.log(status.dbserver); // "OK"
183
- console.log(status.authserver); // "OK"
184
- ```
141
+ | Clase | Cuándo |
142
+ | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
143
+ | `ArcaValidationError` | Datos inválidos (CUIT con dígito verificador incorrecto, fechas inexistentes, importes NaN/negativos, textos fuera de 3..250, CBU inválido, etc.). No se llega a pedir el ticket ni a llamar a ARCA. `field` indica el parámetro. |
144
+ | `ArcaServiceError` | ARCA devolvió `arrayErrores` o `arrayErroresFormato`, o una operación terminó con `resultado = 'R'`. `errors: { code, msg, rawCode? }[]` (`rawCode` para los códigos alfanuméricos de `arrayErroresFormato`). |
145
+ | `ArcaSoapError` | HTTP, timeout, SOAP Fault (ej: `wscommon_005`/`wscommon_007` de auth) o respuesta sin un campo obligatorio del XSD. `uncertain` indica si ARCA pudo haber procesado el request. |
146
+ | `ArcaAuthError` / `ArcaTicketVigenteError` | Falla de WSAA / ya hay un TA vigente que no está en el `ticketStorage`. |
185
147
 
186
- ## Retry automatico
148
+ Las observaciones (`arrayObservaciones`) y el `evento` no son errores: vienen en el resultado.
187
149
 
188
- El SDK reintenta automaticamente en errores transitorios (timeout, HTTP 5xx, errores de red). No reintenta en errores de negocio (4xx, errores de ARCA).
150
+ ### Resultado incierto en operaciones
189
151
 
190
- - **Default**: 1 reintento con backoff exponencial (1s, 2s, ...)
191
- - **Configurable**: `retries: 0` para desactivar, `retries: 3` para mas intentos
152
+ Las emisiones (`aceptarFECred`, `rechazarFECred`, `informarCancelacionTotalFECred`, `rechazarNotaDC`, `modificarOpcionTransferencia`, `informarFacturaAgtDptoCltv`) se envían una sola vez. Si la respuesta se pierde (timeout, conexión cortada, HTTP 5xx, respuesta ilegible) se lanza `ArcaSoapError` con `uncertain = true`: la operación **pudo haberse registrado**. Antes de reintentar, consultá el estado:
192
153
 
193
154
  ```typescript
194
- const fecred = new ArcaFecred({
195
- ...config,
196
- retries: 2, // 2 reintentos (3 intentos totales)
197
- retryDelayMs: 2000, // empezar con 2s -> 4s -> 8s
198
- });
199
- ```
200
-
201
- ## Eventos / Logging
202
-
203
- El SDK emite eventos para debugging y monitoreo sin forzar un logger especifico.
204
-
205
- ```typescript
206
- const fecred = new ArcaFecred({
207
- ...config,
208
- onEvent: (e) => console.log(`[${e.type}]`, e),
209
- });
210
- ```
211
-
212
- | Evento | Cuando | Datos |
213
- | --- | --- | --- |
214
- | `auth:login` | Nuevo token obtenido | `service`, `durationMs` |
215
- | `auth:cache-hit` | Token cacheado reutilizado | `service` |
216
- | `request:start` | Antes de una llamada SOAP | `method`, `endpoint` |
217
- | `request:end` | Llamada SOAP completada | `method`, `durationMs` |
218
- | `request:retry` | Reintentando tras error | `method`, `attempt`, `error` |
219
- | `request:error` | Llamada SOAP fallo | `method`, `error` |
220
-
221
- ## Manejo de errores
222
-
223
- El SDK provee clases de error especificas para catch granular:
224
-
225
- ```typescript
226
- import {
227
- ArcaFecred,
228
- ArcaAuthError,
229
- ArcaServiceError,
230
- ArcaSoapError,
231
- } from '@ramiidv/arca-fecred';
232
-
233
155
  try {
234
- const resultado = await fecred.aceptarFECred(12345);
156
+ await fecred.aceptarFECred(params);
235
157
  } catch (e) {
236
- if (e instanceof ArcaAuthError) {
237
- // Error de autenticacion WSAA (certificado invalido, expirado, etc.)
238
- console.error('Auth error:', e.message);
239
- fecred.clearAuthCache(); // Limpiar cache e intentar de nuevo
240
- }
241
-
242
- if (e instanceof ArcaServiceError) {
243
- // Error de negocio de WSFECRED (FCE no encontrada, estado invalido, etc.)
244
- for (const err of e.errors) {
245
- console.error(`[${err.code}] ${err.msg}`);
246
- }
247
- }
248
-
249
- if (e instanceof ArcaSoapError) {
250
- // Error HTTP/SOAP (timeout, servidor caido, etc.)
251
- console.error('HTTP status:', e.statusCode);
158
+ if (e instanceof ArcaSoapError && e.uncertain) {
159
+ const { estados } = await fecred.consultarHistorialEstadosCtaCte(params.idCtaCte);
160
+ // o consultarCtaCte(params.idCtaCte) → ctaCte.estadoCtaCte.estado
161
+ // Si ya figura Aceptada/Rechazada, no reintentar.
252
162
  }
163
+ throw e;
253
164
  }
254
165
  ```
255
166
 
256
- | Clase | Cuando se lanza |
257
- | --- | --- |
258
- | `ArcaAuthError` | Falla en login WSAA, respuesta inesperada, token/sign invalidos |
259
- | `ArcaServiceError` | Error devuelto por WSFECRED (FCE no encontrada, operacion invalida, etc.). Contiene `errors: { code, msg }[]` |
260
- | `ArcaSoapError` | Error HTTP, timeout, SOAP Fault. Contiene `statusCode?: number` |
261
- | `ArcaError` | Clase base para todos los errores del SDK |
262
-
263
- ## API
264
-
265
- ### `new ArcaFecred(config)`
266
-
267
- | Parametro | Tipo | Default | Descripcion |
268
- | --- | --- | --- | --- |
269
- | `cert` | `string` | -- | Contenido del certificado X.509 (PEM) |
270
- | `key` | `string` | -- | Contenido de la clave privada (PEM) |
271
- | `cuit` | `string` | -- | CUIT de la entidad representada |
272
- | `production` | `boolean` | `false` | Entorno de produccion |
273
- | `timeout` | `number` | `30000` | Timeout HTTP en milisegundos |
274
- | `retries` | `number` | `1` | Reintentos en errores transitorios |
275
- | `retryDelayMs` | `number` | `1000` | Delay inicial entre reintentos (exponencial) |
276
- | `onEvent` | `function` | -- | Callback para eventos del SDK |
277
-
278
- ### Consultas de operaciones
279
-
280
- | Metodo | Descripcion |
281
- | --- | --- |
282
- | `consultarMontoObligadoRecepcion(cuit)` | Verifica si una CUIT esta obligada a recibir FCE |
283
- | `consultarCtasCtes(params)` | Consulta cuentas corrientes de actividad FCE |
284
- | `consultarComprobantes(params)` | Busca comprobantes FCE por filtros |
285
-
286
- ### Acciones sobre FCE
167
+ ## Cliente de bajo nivel
287
168
 
288
- | Metodo | Descripcion |
289
- | --- | --- |
290
- | `aceptarFECred(codCtaCte)` | Acepta una FCE |
291
- | `rechazarFECred(codCtaCte, codMotivoRechazo)` | Rechaza una FCE con motivo |
292
- | `informarFacturaAceptadaCancelada(params)` | Informa que una FCE aceptada fue pagada/cancelada |
293
-
294
- ### Consultas de parametros
295
-
296
- | Metodo | Descripcion |
297
- | --- | --- |
298
- | `consultarTiposRetenciones()` | Tipos de retenciones disponibles |
299
- | `consultarTiposFormasCancelacion()` | Formas de cancelacion disponibles |
300
- | `consultarTiposAjustesOperacion()` | Tipos de ajustes de operacion disponibles |
301
- | `consultarTiposMotivoRechazo()` | Motivos de rechazo disponibles |
302
-
303
- ### Estado y utilidades
304
-
305
- | Metodo | Descripcion |
306
- | --- | --- |
307
- | `status()` | Health check del servicio WSFECRED (no requiere autenticacion) |
308
- | `clearAuthCache()` | Invalida el ticket de acceso cacheado |
309
-
310
- ### Acceso a clientes de bajo nivel
311
-
312
- Para casos avanzados, se pueden usar los clientes individuales directamente:
169
+ `fecred.fecred` es un `FecredClient`: los mismos métodos con las credenciales como primer parámetro y respuestas tipadas.
313
170
 
314
171
  ```typescript
315
- const fecred = new ArcaFecred({ /* ... */ });
316
-
317
- // Obtener ticket de acceso manualmente
318
172
  const ticket = await fecred.wsaa.getAccessTicket('wsfecred');
319
-
320
- const credenciales = {
321
- Token: ticket.token,
322
- Sign: ticket.sign,
323
- Cuit: '20123456789',
324
- };
325
-
326
- // Llamar directamente al servicio
327
- const rawResult = await fecred.fecred.consultarMontoObligadoRecepcion(
328
- credenciales,
329
- '30712345678',
330
- );
173
+ const auth = { token: ticket.token, sign: ticket.sign, cuitRepresentada: '20123456786' };
174
+ const tipos = await fecred.client.consultarTiposMotivosRechazo(auth);
331
175
  ```
332
176
 
333
- ## Enums disponibles
334
-
335
- - `RolCtaCte` -- Rol en la cuenta corriente (EMISOR, RECEPTOR)
336
- - `EstadoCtaCte` -- Estado de la cuenta corriente (PENDIENTE_ACEPTACION, ACEPTADA, RECHAZADA, CANCELADA, ANULADA)
337
- - `MotivoRechazo` -- Motivos de rechazo (NOTA_CREDITO_DEBITO, CUIT_INCORRECTO, FECHA_INCORRECTA, CBU_INCORRECTO, OTROS)
338
- - `FormaCancelacion` -- Formas de cancelacion (ACREDITACION_CUENTA, TRANSFERENCIA, CHEQUE, PAGO_ELECTRONICO, COMPENSACION, ENDOSO, OTRO)
339
- - `TipoAjusteOperacion` -- Tipos de ajuste (NOTA_CREDITO, NOTA_DEBITO)
340
- - `TipoRetencion` -- Tipos de retencion (GANANCIAS, IVA, SUSS, INGRESOS_BRUTOS, OTRAS)
177
+ Detalles del protocolo (verificados contra homologación): namespace `http://ar.gob.afip.wsfecred/FECredService/`, wrapper `<operacionRequest>`, header `SOAPAction` = namespace + operación (obligatorio), `dummy` con Body vacío.
341
178
 
342
179
  ## Entornos
343
180
 
344
- | Entorno | WSAA | WSFECRED |
345
- | --- | --- | --- |
346
- | Testing | `wsaahomo.afip.gov.ar` | `fwshomo.afip.gob.ar` |
347
- | Produccion | `wsaa.afip.gov.ar` | `serviciosjava.afip.gob.ar` |
181
+ | Entorno | WSFECRED |
182
+ | ------------ | ---------------------------------------------------------- |
183
+ | Homologación | `https://fwshomo.afip.gob.ar/wsfecred/FECredService` |
184
+ | Producción | `https://serviciosjava.afip.gob.ar/wsfecred/FECredService` |
185
+
186
+ Los endpoints de WSAA están en `WSAA_ENDPOINTS` de `@ramiidv/arca-common`.
348
187
 
349
188
  ## Licencia
350
189