@ramiidv/arca-mtxca 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/README.md CHANGED
@@ -1,386 +1,243 @@
1
1
  # @ramiidv/arca-mtxca
2
2
 
3
- SDK de TypeScript para el web service WSMTXCA de ARCA (ex AFIP). Facturacion electronica con detalle de articulos (item-level detail: codigos de barras, cantidades, precios unitarios, descripciones por linea).
3
+ SDK de TypeScript para el web service **WSMTXCA** de ARCA (ex AFIP): factura electrónica con detalle de ítems (código MTX/GTIN, cantidad, precio unitario e IVA por línea), con CAE y con CAEA.
4
4
 
5
- ## Caracteristicas
5
+ - Tipos fieles al WSDL/XSD de WSMTXCA y elementos en el orden de la secuencia (Axis2 valida el orden).
6
+ - Redondeo según el XSD: 2 decimales en importes, 6 en cantidad, precio unitario, bonificación y cotización.
7
+ - Validación local de las reglas excluyentes del manual (presencia de campos por unidad de medida, fórmulas por ítem, subtotales de IVA por alícuota, totales).
8
+ - Las emisiones nunca se reintentan y los errores con resultado desconocido se marcan como `uncertain`.
9
+ - Los errores de negocio de ARCA (`arrayErrores`) se lanzan como `ArcaServiceError` en las consultas.
10
+ - Autenticación WSAA automática (via `@ramiidv/arca-common`), con `ticketStorage` persistente opcional.
11
+ - ESM, Node 18+, `fetch` nativo.
6
12
 
7
- - Zero dependencias SOAP: construye los envelopes SOAP manualmente
8
- - Zero dependencias HTTP: usa `fetch` nativo (Node 18+)
9
- - Firma CMS/PKCS#7 con node-forge (via arca-common)
10
- - ESM only
11
- - TypeScript estricto con tipos completos
12
- - Cache automatico de tokens WSAA
13
- - Reintentos con backoff exponencial
14
- - Sistema de eventos para monitoreo
15
-
16
- ## Instalacion
13
+ ## Instalación
17
14
 
18
15
  ```bash
19
16
  npm install @ramiidv/arca-mtxca
20
17
  ```
21
18
 
22
- ## WSMTXCA vs WSFEv1
23
-
24
- | Caracteristica | WSFEv1 (`arca-facturacion`) | WSMTXCA (`arca-mtxca`) |
25
- |---|---|---|
26
- | Detalle de items | No | Si (codigo, descripcion, cantidad, precio unitario por linea) |
27
- | Protocolo | SOAP (.NET) | SOAP (Java) |
28
- | Formato fechas | YYYYMMDD | YYYY-MM-DD |
29
- | IVA por item | No (subtotales globales) | Si (codigoCondicionIVA + importeIVA por item) |
30
- | Tipos cbte | A, B, C, E, M, FCE | A, B, M |
31
- | Uso tipico | Facturas sin detalle de productos | Facturas con detalle de productos (ej: retail, e-commerce) |
32
-
33
- ## Inicio rapido
19
+ ## Inicio rápido
34
20
 
35
21
  ```typescript
36
- import { readFileSync } from 'fs';
37
- import { ArcaMtxca, CbteTipo, CodigoCondicionIVA } from '@ramiidv/arca-mtxca';
22
+ import { readFileSync } from 'node:fs';
23
+ import { ArcaMtxca, CbteTipo, Concepto, CodigoCondicionIVA, Moneda } from '@ramiidv/arca-mtxca';
38
24
 
39
25
  const mtxca = new ArcaMtxca({
40
26
  cert: readFileSync('./cert.pem', 'utf-8'),
41
27
  key: readFileSync('./key.pem', 'utf-8'),
42
- cuit: 20123456789,
43
- production: false, // false = homologacion
28
+ cuit: '20-12345678-6',
29
+ production: false, // homologación
44
30
  });
45
31
 
46
- // Autorizar factura B con detalle de articulos
47
- const result = await mtxca.autorizar({
48
- ptoVta: 1,
49
- cbteTipo: CbteTipo.FACTURA_B,
50
- invoice: {
51
- concepto: 1, // Productos
52
- docTipo: 99, // Consumidor Final
53
- docNro: 0,
54
- cbteFch: '2026-03-31',
55
- importeTotal: 121,
56
- importeGravado: 100,
57
- importeNoGravado: 0,
58
- importeExento: 0,
59
- subtotalesIVA: [
60
- { codigo: CodigoCondicionIVA.IVA_21, baseImponible: 100, importe: 21 },
61
- ],
62
- items: [
63
- {
64
- codigo: '7790001000012',
65
- descripcion: 'Producto de ejemplo',
66
- cantidad: 2,
67
- unidadMedida: 7, // unidades
68
- precioUnitario: 50,
69
- importeItem: 100,
70
- codigoCondicionIVA: CodigoCondicionIVA.IVA_21,
71
- importeIVA: 21,
72
- },
73
- ],
74
- },
32
+ // Factura A: 1 producto a $100 + IVA 21%
33
+ const res = await mtxca.autorizar({
34
+ codigoTipoComprobante: CbteTipo.FACTURA_A,
35
+ numeroPuntoVenta: 4000,
36
+ // numeroComprobante: omitido => último autorizado + 1
37
+ fechaEmision: new Date(),
38
+ codigoTipoDocumento: 80,
39
+ numeroDocumento: '30-00000000-7',
40
+ condicionIVAReceptor: 1, // RG 5616: ver getCondicionesIVAReceptor()
41
+ importeGravado: 100,
42
+ importeNoGravado: 0,
43
+ importeExento: 0,
44
+ importeSubtotal: 100,
45
+ importeTotal: 121,
46
+ codigoMoneda: Moneda.PESOS,
47
+ cotizacionMoneda: 1,
48
+ codigoConcepto: Concepto.PRODUCTOS,
49
+ items: [
50
+ {
51
+ unidadesMtx: 1,
52
+ codigoMtx: '7790001000012',
53
+ codigo: 'P0001',
54
+ descripcion: 'Producto de ejemplo',
55
+ cantidad: 1,
56
+ codigoUnidadMedida: 7,
57
+ precioUnitario: 100, // clase A: sin IVA
58
+ codigoCondicionIVA: CodigoCondicionIVA.IVA_21,
59
+ importeIVA: 21,
60
+ importeItem: 121, // con IVA incluido
61
+ },
62
+ ],
63
+ subtotalesIVA: [{ codigo: CodigoCondicionIVA.IVA_21, importe: 21 }],
75
64
  });
76
65
 
77
- if (result.resultado === 'A') {
78
- console.log('CAE:', result.cae);
79
- console.log('Vencimiento:', result.caeFchVto);
80
- console.log('Cbte Nro:', result.cbteNro);
66
+ if (res.resultado === 'R') {
67
+ console.error('Rechazado', res.errores);
68
+ } else {
69
+ // 'A' aprobado, 'O' aprobado con observaciones
70
+ console.log(res.comprobante.numeroComprobante, res.comprobante.cae, res.comprobante.fechaVencimientoCAE);
71
+ if (res.observaciones.length) console.warn(res.observaciones);
81
72
  }
82
73
  ```
83
74
 
84
- ## Configuracion
75
+ ## Configuración
85
76
 
86
- ```typescript
87
- interface ArcaMtxcaConfig {
88
- /** Certificado X.509 en formato PEM */
89
- cert: string;
90
- /** Clave privada RSA en formato PEM */
91
- key: string;
92
- /** CUIT del contribuyente (sin guiones) */
93
- cuit: number;
94
- /** Usar endpoints de produccion (default: false) */
95
- production?: boolean;
96
- /** Timeout en ms (default: 30000) */
97
- timeout?: number;
98
- /** Cantidad de reintentos en errores 5xx/red (default: 1) */
99
- retries?: number;
100
- /** Delay base en ms para backoff exponencial (default: 1000) */
101
- retryDelayMs?: number;
102
- /** Callback de eventos para monitoreo */
103
- onEvent?: (event: ArcaEvent) => void;
104
- }
105
- ```
77
+ `ArcaMtxcaConfig` extiende `ArcaSdkConfig` de `@ramiidv/arca-common`:
106
78
 
107
- ## API
79
+ | Opción | Descripción |
80
+ | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
81
+ | `cert`, `key` | Certificado y clave privada PEM. |
82
+ | `cuit` | CUIT representada (número o string, con o sin guiones). Se valida el dígito verificador. |
83
+ | `production` | `false` (default) = homologación. |
84
+ | `endpoints` | `{ mtxca?, wsaa? }`: URLs propias (proxy, mock). Ignoran `production`. |
85
+ | `endpoint`, `wsaaEndpoint` | Deprecated: usar `endpoints.mtxca` / `endpoints.wsaa`. |
86
+ | `wsaa` | `WsaaClient` compartido con otros SDKs del mismo certificado. |
87
+ | `signal` | `AbortSignal` global: cancela todas las llamadas de la instancia. |
88
+ | `timeout`, `retries`, `retryDelayMs` | Transporte. `retries` solo aplica a consultas. |
89
+ | `ticketStorage` | Storage persistente de tickets WSAA (recomendado en producción). |
90
+ | `tokenTTLMinutes`, `clockOffsetMs`, `autoClockSkew`, `loginErrorCooldownMs` | Opciones de WSAA. |
91
+ | `fetch`, `legacyTls` | `fetch` propio (proxy, tests) y transporte TLS legacy. |
92
+ | `onEvent` | Callback de eventos (`auth:*`, `request:*`). |
108
93
 
109
- ### Metodos principales
94
+ Endpoints (manual WSMTXCA):
110
95
 
111
- #### `autorizar(request: AutorizarRequest): Promise<MtxcaInvoiceResult>`
96
+ | Entorno | URL |
97
+ | ------------ | ----------------------------------------------------------------- |
98
+ | Homologación | `https://fwshomo.afip.gov.ar/wsmtxca/services/MTXCAService` |
99
+ | Producción | `https://serviciosjava.afip.gob.ar/wsmtxca/services/MTXCAService` |
112
100
 
113
- Autoriza un comprobante con detalle de articulos. Retorna CAE si fue aprobado.
101
+ Todos los métodos aceptan un último parámetro `opts?: CallOptions` con `signal` para cancelar.
114
102
 
115
- ```typescript
116
- const result = await mtxca.autorizar({
117
- ptoVta: 1,
118
- cbteTipo: CbteTipo.FACTURA_A,
119
- invoice: {
120
- concepto: 1,
121
- docTipo: 80, // CUIT
122
- docNro: 30123456789,
123
- cbteFch: '2026-03-31',
124
- importeTotal: 242,
125
- importeGravado: 200,
126
- subtotalesIVA: [
127
- { codigo: CodigoCondicionIVA.IVA_21, baseImponible: 200, importe: 42 },
128
- ],
129
- items: [
130
- {
131
- codigo: '001',
132
- descripcion: 'Servicio de consultoria',
133
- cantidad: 1,
134
- unidadMedida: 7,
135
- precioUnitario: 200,
136
- importeItem: 200,
137
- codigoCondicionIVA: CodigoCondicionIVA.IVA_21,
138
- importeIVA: 42,
139
- },
140
- ],
141
- },
142
- });
143
- ```
103
+ ## Reglas de importes
144
104
 
145
- #### `ultimoComprobante(ptoVta, cbteTipo): Promise<number>`
105
+ Los campos del request se llaman igual que en el XSD (`ComprobanteType`, `ItemType`). Lo más importante del manual:
146
106
 
147
- Ultimo numero de comprobante autorizado.
107
+ - `importeItem` incluye el IVA. En clase A (1, 2, 3, 51, 52, 53) `precioUnitario` va **sin** IVA y el ítem lleva `importeIVA`; en clase B (6, 7, 8) `precioUnitario` va **con** IVA y el ítem no lleva `importeIVA`.
108
+ - `importeItem` = (`precioUnitario` × `cantidad` − `importeBonificacion`) × (1 + alícuota) en clase A; = `precioUnitario` × `cantidad` − `importeBonificacion` en clase B.
109
+ - Unidad 99 (bonificación) y 97 (seña): sin `cantidad`, `precioUnitario` ni `importeBonificacion`; la bonificación tiene `importeItem` negativo y requiere otro ítem con la misma condición de IVA. En clase A, `importeIVA` = `importeItem` − `importeItem` / (1 + alícuota).
110
+ - Fuera de 97/99, `unidadesMtx` y `codigoMtx` son obligatorios.
111
+ - `importeGravado` = Σ (`importeItem` − IVA) de los ítems con condición 3–6; `importeNoGravado` = Σ ítems condición 1; `importeExento` = Σ ítems condición 2; `importeSubtotal` = gravado + no gravado + exento.
112
+ - `subtotalesIVA`: uno por cada condición 4, 5 o 6 presente, con la suma del IVA de esos ítems.
113
+ - `importeTotal` = `importeSubtotal` + `importeOtrosTributos` + Σ subtotales de IVA = `importeOtrosTributos` + Σ `importeItem`.
114
+ - Margen de error del manual: error relativo ≤ 0,01% o absoluto ≤ 0,01 × cantidad de elementos.
148
115
 
149
- ```typescript
150
- const ultimo = await mtxca.ultimoComprobante(1, CbteTipo.FACTURA_B);
151
- ```
116
+ `autorizar()` valida todo esto antes de enviar y lanza `ArcaValidationError` con el detalle (incluye el código de error de ARCA que se evita y el valor esperado). Si ARCA acepta un caso que la validación local rechaza, pasá `{ validarImportes: false }`. Para redondear como el SDK: `roundImporte()` y `roundDecimal()`.
152
117
 
153
- #### `siguienteComprobante(ptoVta, cbteTipo): Promise<number>`
154
-
155
- Siguiente numero de comprobante (ultimo + 1).
118
+ Ejemplo de bonificación en clase A:
156
119
 
157
120
  ```typescript
158
- const siguiente = await mtxca.siguienteComprobante(1, CbteTipo.FACTURA_B);
121
+ items: [
122
+ { unidadesMtx: 1, codigoMtx: '7790001000012', descripcion: 'Producto', cantidad: 1, codigoUnidadMedida: 7,
123
+ precioUnitario: 100, codigoCondicionIVA: 5, importeIVA: 21, importeItem: 121 },
124
+ { descripcion: 'Bonificación 10%', codigoUnidadMedida: 99, codigoCondicionIVA: 5, importeIVA: -2.1, importeItem: -12.1 },
125
+ ],
126
+ importeGravado: 90, importeSubtotal: 90, importeTotal: 108.9,
127
+ subtotalesIVA: [{ codigo: 5, importe: 18.9 }],
159
128
  ```
160
129
 
161
- #### `consultarComprobante(cbteTipo, ptoVta, cbteNro): Promise<MtxcaComprobante>`
130
+ ## Resultado de una autorización y manejo de errores
162
131
 
163
- Consulta un comprobante previamente autorizado, incluyendo el detalle de items.
132
+ | Situación | Qué pasa |
133
+ | ------------------------------ | -------------------------------------------------------------------- |
134
+ | Datos inválidos localmente | `ArcaValidationError` (no se hace ningún request). |
135
+ | ARCA aprueba | `{ resultado: 'A', comprobante: { cae, fechaVencimientoCAE, ... } }` |
136
+ | ARCA aprueba con observaciones | `{ resultado: 'O', comprobante, observaciones }` |
137
+ | ARCA rechaza | `{ resultado: 'R', errores }` — **no lanza**; revisá `resultado`. |
138
+ | Consulta con `arrayErrores` | `ArcaServiceError` con `errors[]` (`code`, `msg`). |
139
+ | Fault SOAP, HTTP, red, timeout | `ArcaSoapError` (`uncertain`, `faultString`, `statusCode`). |
140
+ | Login WSAA | `ArcaAuthError` / `ArcaTicketVigenteError`. |
164
141
 
165
- ```typescript
166
- const comprobante = await mtxca.consultarComprobante(CbteTipo.FACTURA_B, 1, 150);
167
- console.log(comprobante.items); // Detalle de articulos
168
- ```
142
+ `ultimoComprobante()` devuelve 0 solo ante el error 1502 de ARCA ("no hay comprobantes para ese punto de venta y tipo"); cualquier otro error lanza.
169
143
 
170
- #### `status(): Promise<ServerStatus>`
144
+ ### Emisiones con resultado incierto
171
145
 
172
- Health check del servicio. No requiere autenticacion.
146
+ `autorizar`, `autorizarAjusteIVA`, `solicitarCAEA`, `informarComprobanteCAEA`, `informarAjusteIVACAEA`, `informarCAEANoUtilizado` e `informarCAEANoUtilizadoPtoVta` se envían una sola vez (nunca se reintentan). Si fallan con `ArcaSoapError` y `uncertain === true` (timeout, conexión cortada, HTTP 5xx, respuesta ilegible), ARCA pudo haber procesado el request. **No reintentes a ciegas**: si el comprobante ya fue autorizado, un reenvío con el mismo número es rechazado por correlatividad (102) y uno con el número siguiente duplica la factura.
173
147
 
174
148
  ```typescript
175
- const estado = await mtxca.status();
176
- console.log(estado.appserver); // "OK"
177
- ```
178
-
179
- ### Consulta de parametros
180
-
181
- ```typescript
182
- const tiposCbte = await mtxca.getTiposComprobante();
183
- const tiposDoc = await mtxca.getTiposDocumento();
184
- const alicuotas = await mtxca.getAlicuotasIVA();
185
- const condiciones = await mtxca.getCondicionesIVA();
186
- const monedas = await mtxca.getMonedas();
187
- const unidades = await mtxca.getUnidadesMedida();
188
- const ptosVenta = await mtxca.getPuntosVenta();
189
- const ptosVentaCAE = await mtxca.getPuntosVentaCAE();
190
- const ptosVentaCAEA = await mtxca.getPuntosVentaCAEA();
191
- const cotizacion = await mtxca.getCotizacionMoneda('DOL');
192
- ```
193
-
194
- ### Acceso a clientes de bajo nivel
195
-
196
- Para casos avanzados, se pueden usar los clientes individuales directamente:
197
-
198
- ```typescript
199
- const mtxca = new ArcaMtxca({ /* ... */ });
200
-
201
- // Obtener ticket de acceso manualmente
202
- const ticket = await mtxca.wsaa.getAccessTicket('wsmtxca');
203
-
204
- const auth = {
205
- Token: ticket.token,
206
- Sign: ticket.sign,
207
- Cuit: 20123456789,
208
- };
209
-
210
- // Llamar directamente al servicio
211
- const result = await mtxca.client.autorizarComprobante(auth, request);
212
- ```
213
-
214
- ## Tipos principales
149
+ import { ArcaSoapError } from '@ramiidv/arca-mtxca';
215
150
 
216
- ### MtxcaItem
217
-
218
- ```typescript
219
- interface MtxcaItem {
220
- codigo?: string; // Codigo/barcode del producto
221
- descripcion: string; // Descripcion del producto/servicio
222
- cantidad: number; // Cantidad
223
- unidadMedida: number; // Codigo unidad de medida
224
- precioUnitario: number; // Precio unitario
225
- importeItem: number; // Importe total del item
226
- codigoCondicionIVA: number; // Condicion de IVA del item
227
- importeIVA: number; // Importe de IVA del item
228
- importeBonificacion?: number; // Descuento
151
+ const numero = (await mtxca.ultimoComprobante(4000, CbteTipo.FACTURA_A)) + 1;
152
+ try {
153
+ return await mtxca.autorizar({ ...comprobante, numeroComprobante: numero });
154
+ } catch (e) {
155
+ if (e instanceof ArcaSoapError && e.uncertain) {
156
+ // ¿Llegó a autorizarse?
157
+ const ultimo = await mtxca.ultimoComprobante(4000, CbteTipo.FACTURA_A);
158
+ if (ultimo >= numero) {
159
+ const { comprobante } = await mtxca.consultarComprobante(CbteTipo.FACTURA_A, 4000, numero);
160
+ return comprobante; // codigoAutorizacion = CAE
161
+ }
162
+ // No se autorizó: se puede reenviar con el mismo número.
163
+ }
164
+ throw e;
229
165
  }
230
166
  ```
231
167
 
232
- ### MtxcaInvoiceResult
168
+ Para CAEA: `solicitarCAEA` incierto → `consultarCAEAEntreFechas()`; `informarComprobanteCAEA` incierto → `consultarComprobante()`.
233
169
 
234
- ```typescript
235
- interface MtxcaInvoiceResult {
236
- resultado: string; // "A" = Aprobado, "R" = Rechazado
237
- cae?: string; // CAE otorgado
238
- caeFchVto?: string; // Vencimiento del CAE (YYYY-MM-DD)
239
- cbteNro: number; // Numero de comprobante
240
- observaciones: MtxcaObservacion[];
241
- errores: MtxcaObservacion[];
242
- }
243
- ```
170
+ Las solicitudes de un mismo punto de venta y tipo deben ser secuenciales (ARCA rechaza con 135 una solicitud concurrente), y la numeración automática supone un único emisor por punto de venta.
244
171
 
245
- ### MtxcaComprobante
172
+ ## API
246
173
 
247
- ```typescript
248
- interface MtxcaComprobante {
249
- codigoTipoComprobante: number;
250
- numeroPuntoVenta: number;
251
- numeroComprobante: number;
252
- fechaEmision: string;
253
- codigoTipoDocumento: number;
254
- numeroDocumento: number;
255
- importeTotal: number;
256
- importeNoGravado: number;
257
- importeGravado: number;
258
- importeExento: number;
259
- importeOtrosTributos: number;
260
- importeSubtotal: number;
261
- codigoMoneda: string;
262
- cotizacionMoneda: number;
263
- resultado: string;
264
- codigoAutorizacion?: string;
265
- fechaVencimiento?: string;
266
- observaciones: MtxcaObservacion[];
267
- items: MtxcaItem[];
268
- }
269
- ```
174
+ ### Comprobantes con CAE
270
175
 
271
- ## Manejo de errores
176
+ | Método | Operación WSMTXCA |
177
+ | -------------------------------------------------------- | ------------------------------------------------------------------ |
178
+ | `autorizar(req, opts?)` | `autorizarComprobante` (número automático si se omite) |
179
+ | `autorizarAjusteIVA(req, opts?)` | `autorizarAjusteIVA` (solo valida el XSD: tiene reglas propias) |
180
+ | `ultimoComprobante(ptoVta, cbteTipo, opts?)` | `consultarUltimoComprobanteAutorizado` |
181
+ | `siguienteComprobante(ptoVta, cbteTipo, opts?)` | último + 1 |
182
+ | `consultarComprobante(cbteTipo, ptoVta, cbteNro, opts?)` | `consultarComprobante` → `{ comprobante, observaciones, evento? }` |
272
183
 
273
- El SDK usa la jerarquia de errores de `@ramiidv/arca-common`:
184
+ ### CAEA
274
185
 
275
- ```
276
- Error
277
- └── ArcaError (base)
278
- ├── ArcaAuthError (errores de WSAA)
279
- ├── ArcaServiceError (errores de negocio)
280
- └── ArcaSoapError (errores HTTP/transporte)
281
- ```
186
+ | Método | Operación WSMTXCA |
187
+ | ---------------------------------------------------- | ---------------------------------------------------- |
188
+ | `solicitarCAEA(periodo, orden, opts?)` | `solicitarCAEA` (`periodo` AAAAMM, `orden` 1 o 2) |
189
+ | `consultarCAEA(caea, opts?)` | `consultarCAEA` |
190
+ | `consultarCAEAEntreFechas(desde, hasta, opts?)` | `consultarCAEAEntreFechas` |
191
+ | `informarComprobanteCAEA(comp, opts?)` | `informarComprobanteCAEA` (`comp.caea` = CAEA usado) |
192
+ | `informarAjusteIVACAEA(comp, opts?)` | `informarAjusteIVACAEA` |
193
+ | `informarCAEANoUtilizado(caea, opts?)` | `informarCAEANoUtilizado` |
194
+ | `informarCAEANoUtilizadoPtoVta(caea, ptoVta, opts?)` | `informarCAEANoUtilizadoPtoVta` |
195
+ | `consultarPtosVtaCAEANoInformados(caea, opts?)` | `consultarPtosVtaCAEANoInformados` |
282
196
 
283
- ```typescript
284
- import { ArcaAuthError, ArcaServiceError, ArcaSoapError } from '@ramiidv/arca-mtxca';
197
+ ### Parámetros y estado
285
198
 
286
- try {
287
- await mtxca.autorizar(request);
288
- } catch (error) {
289
- if (error instanceof ArcaAuthError) {
290
- // Certificado vencido, servicio no autorizado, WSAA caido
291
- console.error('Error de autenticacion:', error.message);
292
- } else if (error instanceof ArcaServiceError) {
293
- // Errores de negocio (comprobante rechazado, etc.)
294
- for (const detalle of error.errors) {
295
- console.error(`[${detalle.code}] ${detalle.msg}`);
296
- }
297
- } else if (error instanceof ArcaSoapError) {
298
- // Errores HTTP/red
299
- console.error('Error HTTP:', error.statusCode, error.message);
300
- }
301
- }
302
- ```
199
+ | Método | Operación | Devuelve |
200
+ | ------------------------------------------------------------------- | --------------------------------- | --------------------------------------------------------------- |
201
+ | `status()` | `dummy` (sin auth) | `{ appserver, dbserver, authserver }` |
202
+ | `getTiposComprobante()` | `consultarTiposComprobante` | `CodigoDescripcion[]` |
203
+ | `getTiposDocumento()` | `consultarTiposDocumento` | `CodigoDescripcion[]` |
204
+ | `getAlicuotasIVA()` | `consultarAlicuotasIVA` | `CodigoDescripcion[]` |
205
+ | `getCondicionesIVA()` | `consultarCondicionesIVA` | `CodigoDescripcion[]` |
206
+ | `getCondicionesIVAReceptor(cbteTipo)` | `consultarCondicionesIVAReceptor` | `CodigoDescripcion[]` |
207
+ | `getMonedas()` | `consultarMonedas` | `{ codigo: string, descripcion }[]` |
208
+ | `getCotizacionMoneda(codigo, fecha?)` | `consultarCotizacionMoneda` | `{ codigoMoneda, fechaCotizacion, cotizacion: number \| null }` |
209
+ | `getUnidadesMedida()` | `consultarUnidadesMedida` | `CodigoDescripcion[]` |
210
+ | `getTiposTributo()` | `consultarTiposTributo` | `CodigoDescripcion[]` |
211
+ | `getTiposDatosAdicionales()` | `consultarTiposDatosAdicionales` | `CodigoDescripcion[]` |
212
+ | `getActividadesVigentes()` | `consultarActividadesVigentes` | `{ codigo, orden, descripcion }[]` |
213
+ | `getPuntosVenta()` / `getPuntosVentaCAE()` / `getPuntosVentaCAEA()` | `consultarPuntosVenta*` | `{ numeroPuntoVenta, bloqueado, fechaBaja? }[]` |
303
214
 
304
- Ademas, las respuestas de `autorizar()` pueden tener `resultado === 'R'` con observaciones/errores sin lanzar excepcion. Siempre verificar `result.resultado`:
215
+ `getCotizacionMoneda` usa la fecha de hoy si no se indica; `cotizacion` es `null` cuando ARCA no tiene cotización (responde sin valor y sin error).
305
216
 
306
- ```typescript
307
- const result = await mtxca.autorizar(request);
308
- if (result.resultado !== 'A') {
309
- console.error('Rechazado:', result.errores);
310
- console.warn('Observaciones:', result.observaciones);
311
- }
312
- ```
217
+ `clearAuthCache()` (async) descarta el ticket WSAA de `wsmtxca`.
218
+
219
+ ### Cliente de bajo nivel
313
220
 
314
- ## Eventos
221
+ `mtxca.client` (`MtxcaClient`) expone una función por operación del WSDL (`autorizarComprobante`, `consultarCAEA`, ...) que recibe `MtxcaAuth` (`{ token, sign, cuitRepresentada }`) y `numeroComprobante` explícito. Valida contra el XSD y redondea, pero no valida la coherencia de importes. Se puede usar sin `ArcaMtxca`:
315
222
 
316
223
  ```typescript
317
- const mtxca = new ArcaMtxca({
318
- // ...
319
- onEvent: (evento) => {
320
- switch (evento.type) {
321
- case 'auth:login':
322
- console.log(`Login para ${evento.service}`);
323
- break;
324
- case 'auth:cache-hit':
325
- console.log(`Token cacheado para ${evento.service}`);
326
- break;
327
- case 'request:start':
328
- console.log(`Inicio ${evento.method}`);
329
- break;
330
- case 'request:end':
331
- console.log(`Fin ${evento.method} (${evento.durationMs}ms)`);
332
- break;
333
- case 'request:retry':
334
- console.log(`Reintento #${evento.attempt}`);
335
- break;
336
- case 'request:error':
337
- console.error(`Error: ${evento.error}`);
338
- break;
339
- }
340
- },
341
- });
224
+ import { MtxcaClient, MTXCA_ENDPOINTS } from '@ramiidv/arca-mtxca';
225
+ const client = new MtxcaClient({ endpoint: MTXCA_ENDPOINTS.testing });
226
+ await client.dummy();
342
227
  ```
343
228
 
344
- ## Enums utiles
229
+ ## Enums y constantes
345
230
 
346
- ```typescript
347
- import { CbteTipo, Concepto, CodigoCondicionIVA, Moneda } from '@ramiidv/arca-mtxca';
348
-
349
- // Tipos de comprobante
350
- CbteTipo.FACTURA_A // 1
351
- CbteTipo.NOTA_DEBITO_A // 2
352
- CbteTipo.NOTA_CREDITO_A // 3
353
- CbteTipo.FACTURA_B // 6
354
- CbteTipo.NOTA_DEBITO_B // 7
355
- CbteTipo.NOTA_CREDITO_B // 8
356
-
357
- // Concepto
358
- Concepto.PRODUCTOS // 1
359
- Concepto.SERVICIOS // 2
360
- Concepto.PRODUCTOS_Y_SERVICIOS // 3
361
-
362
- // Condicion IVA del item
363
- CodigoCondicionIVA.NO_GRAVADO // 1
364
- CodigoCondicionIVA.EXENTO // 2
365
- CodigoCondicionIVA.IVA_0 // 3
366
- CodigoCondicionIVA.IVA_10_5 // 4
367
- CodigoCondicionIVA.IVA_21 // 5
368
- CodigoCondicionIVA.IVA_27 // 6
369
- CodigoCondicionIVA.GRAVADO // 7
370
- CodigoCondicionIVA.IVA_5 // 8
371
- CodigoCondicionIVA.IVA_2_5 // 9
372
-
373
- // Monedas
374
- Moneda.PESOS // "PES"
375
- Moneda.DOLARES // "DOL"
376
- Moneda.EUROS // "060"
377
- ```
231
+ - `CbteTipo`: 1, 2, 3, 6, 7, 8, 51, 52, 53 (A con leyenda "OPERACIÓN SUJETA A RETENCIÓN") y FCE 201–203, 206–208.
232
+ - `Concepto`: 1 productos, 2 servicios, 3 ambos.
233
+ - `CodigoCondicionIVA`: 1 no gravado, 2 exento, 3 0%, 4 10,5%, 5 21%, 6 27% (y `ALICUOTAS_IVA`).
234
+ - `UnidadMedidaEspecial`: 95, 97 (seña), 99 (bonificación).
235
+ - `Moneda`: `PES`, `DOL`, `060` (euro). Lista completa: `getMonedas()`.
378
236
 
379
237
  ## Requisitos
380
238
 
381
- - Node.js >= 18 (soporte nativo de `fetch`)
382
- - Certificado digital emitido por ARCA/AFIP
383
- - Autorizacion para el servicio `wsmtxca`
239
+ - Node.js >= 18.
240
+ - Certificado digital de ARCA asociado al servicio `wsmtxca` y empadronamiento en "Codificación de Productos – Factura con Detalle".
384
241
 
385
242
  ## Licencia
386
243