arca-sdk 0.4.0 → 1.0.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 +142 -0
- package/README.md +125 -202
- package/dist/index.cjs +532 -329
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +283 -172
- package/dist/index.d.ts +283 -172
- package/dist/index.js +527 -325
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Todos los cambios notables de este proyecto se documentan en este archivo.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## [1.0.0] — 2026-02-23
|
|
8
|
+
|
|
9
|
+
### 🔴 Breaking Changes
|
|
10
|
+
|
|
11
|
+
Esta versión establece la API pública definitiva. **Requiere actualizar todos los imports** si venís de v0.x.
|
|
12
|
+
|
|
13
|
+
#### Métodos renombrados en WsfeService
|
|
14
|
+
| v0.x | v1.0.0 |
|
|
15
|
+
|-------|--------|
|
|
16
|
+
| `emitirTicketCSimple()` | `issueSimpleReceipt()` |
|
|
17
|
+
| `emitirTicketC()` | `issueReceipt()` |
|
|
18
|
+
| `emitirFacturaC()` | `issueInvoiceC()` |
|
|
19
|
+
| `emitirFacturaB()` | `issueInvoiceB()` |
|
|
20
|
+
| `emitirFacturaA()` | `issueInvoiceA()` |
|
|
21
|
+
| `emitirComprobante()` | *(privado — ya no accesible)* |
|
|
22
|
+
|
|
23
|
+
#### Método renombrado en PadronService
|
|
24
|
+
| v0.x | v1.0.0 |
|
|
25
|
+
|-------|--------|
|
|
26
|
+
| `getPersona(cuit)` | `getTaxpayer(cuit)` |
|
|
27
|
+
|
|
28
|
+
#### Configuración de WsfeService
|
|
29
|
+
| v0.x | v1.0.0 |
|
|
30
|
+
|-------|--------|
|
|
31
|
+
| `puntoVenta: 4` | `pointOfSale: 4` |
|
|
32
|
+
|
|
33
|
+
#### Tipos renombrados
|
|
34
|
+
| v0.x | v1.0.0 |
|
|
35
|
+
|-------|--------|
|
|
36
|
+
| `TipoComprobante` | `InvoiceType` |
|
|
37
|
+
| `TipoDocumento` | `TaxIdType` |
|
|
38
|
+
| `Concepto` | `BillingConcept` |
|
|
39
|
+
| `FacturaItem` | `InvoiceItem` |
|
|
40
|
+
| `Comprador` | `Buyer` |
|
|
41
|
+
| `EmitirFacturaRequest` | `IssueInvoiceRequest` |
|
|
42
|
+
| `Persona` | `Taxpayer` |
|
|
43
|
+
| `Domicilio` | `Address` |
|
|
44
|
+
| `Actividad` | `Activity` |
|
|
45
|
+
| `Impuesto` | `TaxRecord` |
|
|
46
|
+
| `PadronResponse` | `TaxpayerResponse` |
|
|
47
|
+
| `PadronConfig` | `TaxpayerServiceConfig` |
|
|
48
|
+
|
|
49
|
+
#### Fields renombrados en tipos
|
|
50
|
+
| Tipo | v0.x | v1.0.0 |
|
|
51
|
+
|------|-------|--------|
|
|
52
|
+
| `InvoiceItem` | `descripcion` | `description` |
|
|
53
|
+
| `InvoiceItem` | `cantidad` | `quantity` |
|
|
54
|
+
| `InvoiceItem` | `precioUnitario` | `unitPrice` |
|
|
55
|
+
| `InvoiceItem` | `alicuotaIva` | `vatRate` |
|
|
56
|
+
| `Buyer` | `tipoDocumento` | `docType` |
|
|
57
|
+
| `Buyer` | `nroDocumento` | `docNumber` |
|
|
58
|
+
| `CAEResponse` | `tipoComprobante` | `invoiceType` |
|
|
59
|
+
| `CAEResponse` | `puntoVenta` | `pointOfSale` |
|
|
60
|
+
| `CAEResponse` | `nroComprobante` | `invoiceNumber` |
|
|
61
|
+
| `CAEResponse` | `fecha` | `date` |
|
|
62
|
+
| `CAEResponse` | `vencimientoCae` | `caeExpiry` |
|
|
63
|
+
| `CAEResponse` | `resultado` | `result` |
|
|
64
|
+
| `CAEResponse` | `observaciones` | `observations` |
|
|
65
|
+
| `CAEResponse` | `iva` | `vat` |
|
|
66
|
+
| `CAEResponse` | `urlQr` | `qrUrl` |
|
|
67
|
+
| `ServiceStatus` | `AppServer` | `appServer` |
|
|
68
|
+
| `ServiceStatus` | `DbServer` | `dbServer` |
|
|
69
|
+
| `ServiceStatus` | `AuthServer` | `authServer` |
|
|
70
|
+
| `Taxpayer` | `idPersona` | `taxId` |
|
|
71
|
+
| `Taxpayer` | `tipoPersona` | `personType` |
|
|
72
|
+
| `Taxpayer` | `nombre` | `firstName` |
|
|
73
|
+
| `Taxpayer` | `apellido` | `lastName` |
|
|
74
|
+
| `Taxpayer` | `razonSocial` | `companyName` |
|
|
75
|
+
| `Taxpayer` | `estadoClave` | `status` |
|
|
76
|
+
| `Taxpayer` | `domicilio` | `addresses` |
|
|
77
|
+
| `Taxpayer` | `actividad` | `activities` |
|
|
78
|
+
| `Taxpayer` | `impuesto` | `taxes` |
|
|
79
|
+
| `Taxpayer` | `descripcionActividadPrincipal` | `mainActivity` |
|
|
80
|
+
| `Taxpayer` | `esInscriptoIVA` | `isVATRegistered` |
|
|
81
|
+
| `Taxpayer` | `esMonotributista` | `isMonotax` |
|
|
82
|
+
| `Taxpayer` | `esExento` | `isVATExempt` |
|
|
83
|
+
| `Address` | `direccion` | `street` |
|
|
84
|
+
| `Address` | `localidad` | `city` |
|
|
85
|
+
| `Address` | `codPostal` | `postalCode` |
|
|
86
|
+
| `Address` | `idProvincia` | `provinceId` |
|
|
87
|
+
| `Address` | `descripcionProvincia` | `province` |
|
|
88
|
+
| `Address` | `tipoDomicilio` | `type` |
|
|
89
|
+
|
|
90
|
+
#### Función renombrada en utils
|
|
91
|
+
| v0.x | v1.0.0 |
|
|
92
|
+
|-------|--------|
|
|
93
|
+
| `generarUrlQR()` | `generateQRUrl()` |
|
|
94
|
+
|
|
95
|
+
#### Enums — valores constantes renombrados
|
|
96
|
+
| Enum | v0.x | v1.0.0 |
|
|
97
|
+
|------|-------|--------|
|
|
98
|
+
| `TaxIdType` | `CONSUMIDOR_FINAL` | `FINAL_CONSUMER` |
|
|
99
|
+
| `TaxIdType` | `CI_EXTRANJERA` | `FOREIGN_ID` |
|
|
100
|
+
| `TaxIdType` | `CI_BUENOS_AIRES` | `BUENOS_AIRES_ID` |
|
|
101
|
+
| `TaxIdType` | `CI_POLICIA_FEDERAL` | `NATIONAL_POLICE_ID` |
|
|
102
|
+
| `BillingConcept` | `PRODUCTOS` | `PRODUCTS` |
|
|
103
|
+
| `BillingConcept` | `SERVICIOS` | `SERVICES` |
|
|
104
|
+
| `BillingConcept` | `PRODUCTOS_Y_SERVICIOS` | `PRODUCTS_AND_SERVICES` |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
### ✅ Nuevas funcionalidades
|
|
109
|
+
|
|
110
|
+
- **`WsfeService.getInvoice(type, number)`**: Consulta un comprobante ya emitido (FECompConsultar).
|
|
111
|
+
- **`WsfeService.getPointsOfSale()`**: Lista los puntos de venta habilitados (FEParamGetPtosVenta).
|
|
112
|
+
- **`ArcaNetworkError`**: Ahora exportado públicamente para manejo de errores de red.
|
|
113
|
+
- **`InvoiceDetails`**: Nuevo tipo para la respuesta de `getInvoice()`.
|
|
114
|
+
- **`PointOfSale`**: Nuevo tipo para la respuesta de `getPointsOfSale()`.
|
|
115
|
+
|
|
116
|
+
### 🐛 Fixes
|
|
117
|
+
|
|
118
|
+
- `ServiceStatus` ahora tiene campos `camelCase` (`appServer`, `dbServer`, `authServer`) en lugar de `PascalCase`.
|
|
119
|
+
- `emitirComprobante` (ahora `issueDocument`) se volvió privado — ya no es accesible desde fuera del servicio.
|
|
120
|
+
- Diccionario de hints de errores (`ARCA_ERROR_HINTS`) expandido a 15+ códigos documentados.
|
|
121
|
+
- Eliminado `WsaaResponse` (tipo sin uso).
|
|
122
|
+
- Tipado explícito en `PadronService`: eliminados todos los `any` en métodos privados.
|
|
123
|
+
|
|
124
|
+
### 🧪 Tests
|
|
125
|
+
|
|
126
|
+
- Nuevo suite de tests para `WsfeService` (`wsfe.test.ts`).
|
|
127
|
+
- Tests existentes actualizados a la nueva API.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## [0.5.0] — 2026-02-22
|
|
132
|
+
|
|
133
|
+
- Agregado Padrón A13 service (`PadronService`)
|
|
134
|
+
- `ArcaError` con campo `hint` para guiar al desarrollador
|
|
135
|
+
- `checkStatus()` con default seguro en `homologacion`
|
|
136
|
+
|
|
137
|
+
## [0.4.0] — 2026-02-21
|
|
138
|
+
|
|
139
|
+
- Primera versión pública del SDK
|
|
140
|
+
- `WsaaService` con cache en memoria + persistencia opcional
|
|
141
|
+
- `WsfeService` con Ticket C, Factura A, B, C
|
|
142
|
+
- Generador de QR oficial de ARCA
|
package/README.md
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
**La SDK moderna de ARCA (ex-AFIP) que no te rompe las bolas.**
|
|
4
4
|
|
|
5
5
|
SDK en TypeScript para integración con servicios de ARCA:
|
|
6
|
-
- ✅ **Type-safe**: TypeScript strict mode
|
|
7
|
-
- ✅ **Simple**:
|
|
8
|
-
- ✅ **Automático**: Cache de tokens
|
|
9
|
-
- ✅ **Fiscal**: Generador de QR oficial
|
|
6
|
+
- ✅ **Type-safe**: TypeScript strict mode, 100% tipado
|
|
7
|
+
- ✅ **Simple**: API en inglés, sin XML manual, sin magia negra
|
|
8
|
+
- ✅ **Automático**: Cache de tokens + persistencia opcional (God Mode)
|
|
9
|
+
- ✅ **Fiscal**: Generador de QR oficial de ARCA ultra-robusto
|
|
10
|
+
- ✅ **Padrón**: Consulta de CUIT (A13) para autocompletado de datos
|
|
10
11
|
- ✅ **Resiliente**: Maneja errores SSL ("dh key too small") y timeouts
|
|
11
|
-
- ✅ **Moderno**: ESM + CJS nativo, Node.js 18
|
|
12
|
+
- ✅ **Moderno**: ESM + CJS nativo, Node.js 18+, Bun compatible
|
|
12
13
|
|
|
13
14
|
---
|
|
14
15
|
|
|
@@ -23,283 +24,205 @@ bun add arca-sdk
|
|
|
23
24
|
|
|
24
25
|
## ⚡ Quick Start
|
|
25
26
|
```typescript
|
|
26
|
-
import { WsaaService } from 'arca-sdk';
|
|
27
|
-
import * as fs from '
|
|
27
|
+
import { WsaaService, WsfeService } from 'arca-sdk';
|
|
28
|
+
import * as fs from 'fs';
|
|
28
29
|
|
|
29
|
-
// 1.
|
|
30
|
+
// 1. Autenticar con WSAA
|
|
30
31
|
const wsaa = new WsaaService({
|
|
31
|
-
environment: 'homologacion',
|
|
32
|
+
environment: 'homologacion',
|
|
32
33
|
cuit: '20123456789',
|
|
33
|
-
cert: fs.readFileSync('
|
|
34
|
-
key: fs.readFileSync('
|
|
34
|
+
cert: fs.readFileSync('cert.pem', 'utf-8'),
|
|
35
|
+
key: fs.readFileSync('key.pem', 'utf-8'),
|
|
35
36
|
service: 'wsfe',
|
|
36
37
|
});
|
|
37
38
|
|
|
38
|
-
// 2. Obtener ticket (automático, con cache)
|
|
39
39
|
const ticket = await wsaa.login();
|
|
40
40
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
// 2. Crear servicio de facturación
|
|
42
|
+
const wsfe = new WsfeService({
|
|
43
|
+
environment: 'homologacion',
|
|
44
|
+
cuit: '20123456789',
|
|
45
|
+
ticket,
|
|
46
|
+
pointOfSale: 4,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// 3. Emitir un Ticket C
|
|
50
|
+
const result = await wsfe.issueSimpleReceipt({ total: 1500 });
|
|
44
51
|
|
|
45
|
-
|
|
52
|
+
console.log('CAE:', result.cae);
|
|
53
|
+
console.log('QR URL:', result.qrUrl); // ← Ya viene integrado!
|
|
54
|
+
```
|
|
46
55
|
|
|
47
56
|
---
|
|
48
57
|
|
|
49
|
-
##
|
|
58
|
+
## 👑 God Mode: Persistencia Automática
|
|
59
|
+
No manejes tokens manualmente. Pasale un `storage` al SDK y se encargará de guardar, recuperar y renovar el TA solo cuando expire.
|
|
50
60
|
|
|
51
|
-
### WSAA - Autenticación
|
|
52
61
|
```typescript
|
|
53
|
-
import { WsaaService } from 'arca-sdk';
|
|
54
|
-
|
|
55
62
|
const wsaa = new WsaaService({
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
...config,
|
|
64
|
+
service: 'wsfe',
|
|
65
|
+
storage: {
|
|
66
|
+
get: async (cuit, env) => await db.token.findUnique({ where: { cuit, env } }),
|
|
67
|
+
save: async (cuit, env, ticket) => await db.token.upsert({ ... }),
|
|
68
|
+
}
|
|
61
69
|
});
|
|
62
70
|
|
|
71
|
+
// El SDK chequea el storage antes de pedir un nuevo ticket a ARCA
|
|
63
72
|
const ticket = await wsaa.login();
|
|
64
|
-
// Ticket válido por ~12 horas
|
|
65
|
-
// Se renueva automáticamente
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### WSFE - Facturación
|
|
69
|
-
```typescript
|
|
70
|
-
const wsfe = new WsfeService(config);
|
|
71
|
-
const cae = await wsfe.emitirFacturaC({ items });
|
|
72
|
-
console.log('CAE:', cae.cae);
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
77
|
-
##
|
|
77
|
+
## 🔍 Consulta de Padrón (A13)
|
|
78
|
+
Obtené los datos de un contribuyente (nombre, domicilio, condición IVA) solo con su CUIT.
|
|
78
79
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
- `key.pem`: Clave privada
|
|
80
|
+
```typescript
|
|
81
|
+
import { PadronService } from 'arca-sdk';
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
2. Generar certificado de prueba
|
|
86
|
-
3. Descargar cert + key
|
|
83
|
+
const padron = new PadronService(config);
|
|
84
|
+
const { taxpayer, error } = await padron.getTaxpayer('30111111118');
|
|
87
85
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
86
|
+
if (taxpayer) {
|
|
87
|
+
const name = taxpayer.companyName || `${taxpayer.firstName} ${taxpayer.lastName}`;
|
|
88
|
+
console.log('Nombre:', name);
|
|
89
|
+
console.log('Provincia:', taxpayer.addresses[0].province);
|
|
90
|
+
console.log('¿Inscripto IVA?:', taxpayer.isVATRegistered);
|
|
91
|
+
console.log('¿Monotributista?:', taxpayer.isMonotax);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
92
94
|
|
|
93
95
|
---
|
|
94
96
|
|
|
95
|
-
##
|
|
97
|
+
## 📱 Comprobantes soportados
|
|
96
98
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
99
|
+
```typescript
|
|
100
|
+
// Ticket C — Consumidor Final (solo total)
|
|
101
|
+
const cae = await wsfe.issueSimpleReceipt({ total: 1500 });
|
|
100
102
|
|
|
101
|
-
|
|
103
|
+
// Ticket C — con detalle de items (los items se guardan localmente, no van a ARCA)
|
|
104
|
+
const cae = await wsfe.issueReceipt({
|
|
105
|
+
items: [
|
|
106
|
+
{ description: 'Café con leche', quantity: 2, unitPrice: 750 },
|
|
107
|
+
{ description: 'Medialunas x3', quantity: 1, unitPrice: 500 },
|
|
108
|
+
],
|
|
109
|
+
});
|
|
102
110
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
# Tests unitarios
|
|
106
|
-
bun test
|
|
111
|
+
// Factura C — Consumidor Final con items
|
|
112
|
+
const cae = await wsfe.issueInvoiceC({ items: [...] });
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
// Factura B — con IVA discriminado (requiere vatRate en cada item)
|
|
115
|
+
const cae = await wsfe.issueInvoiceB({
|
|
116
|
+
items: [
|
|
117
|
+
{ description: 'Servicio de diseño', quantity: 10, unitPrice: 1000, vatRate: 21 },
|
|
118
|
+
],
|
|
119
|
+
buyer: { docType: TaxIdType.CUIT, docNumber: '20987654321' },
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Factura A — entre Responsables Inscriptos
|
|
123
|
+
const cae = await wsfe.issueInvoiceA({
|
|
124
|
+
items: [...],
|
|
125
|
+
buyer: { docType: TaxIdType.CUIT, docNumber: '30123456789' },
|
|
126
|
+
});
|
|
110
127
|
```
|
|
111
128
|
|
|
112
129
|
---
|
|
113
130
|
|
|
114
|
-
##
|
|
131
|
+
## 🔎 Consultar un comprobante ya emitido
|
|
115
132
|
|
|
116
|
-
La SDK exporta todos los tipos:
|
|
117
133
|
```typescript
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Environment
|
|
122
|
-
} from 'arca-sdk';
|
|
134
|
+
const invoice = await wsfe.getInvoice(InvoiceType.TICKET_C, 42);
|
|
135
|
+
console.log('Total:', invoice.total);
|
|
136
|
+
console.log('CAE:', invoice.cae);
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
Autocomplete completo en tu IDE. ✨
|
|
126
|
-
|
|
127
139
|
---
|
|
128
140
|
|
|
129
|
-
##
|
|
130
|
-
```typescript
|
|
131
|
-
import { ArcaAuthError, ArcaValidationError } from 'arca-sdk';
|
|
132
|
-
|
|
133
|
-
try {
|
|
134
|
-
const ticket = await wsaa.login();
|
|
135
|
-
} catch (error) {
|
|
136
|
-
if (error instanceof ArcaAuthError) {
|
|
137
|
-
console.error('Error de autenticación:', error.message);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (error instanceof ArcaValidationError) {
|
|
141
|
-
console.error('Configuración inválida:', error.message);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
```
|
|
141
|
+
## 🏪 Listar puntos de venta
|
|
145
142
|
|
|
146
|
-
Los errores incluyen contexto útil en `error.details`.
|
|
147
|
-
|
|
148
|
-
#### Timeouts
|
|
149
|
-
Por defecto, las peticiones tienen un timeout de **15 segundos**. Podés ajustarlo en la configuración:
|
|
150
143
|
```typescript
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
144
|
+
const points = await wsfe.getPointsOfSale();
|
|
145
|
+
points.forEach(p => {
|
|
146
|
+
console.log(`PdV ${p.number}: ${p.type} — ${p.isBlocked ? '🔴 Bloqueado' : '✅ Activo'}`);
|
|
154
147
|
});
|
|
155
148
|
```
|
|
156
149
|
|
|
157
150
|
---
|
|
158
151
|
|
|
159
|
-
|
|
152
|
+
## 📱 QR Oficial de ARCA
|
|
160
153
|
|
|
161
|
-
#### Ticket C Simple (solo total)
|
|
162
154
|
```typescript
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const wsaa = new WsaaService({ ... });
|
|
167
|
-
const ticket = await wsaa.login();
|
|
155
|
+
// 1. Integrado automáticamente en todos los métodos de emisión
|
|
156
|
+
const result = await wsfe.issueSimpleReceipt({ total: 1500 });
|
|
157
|
+
console.log(result.qrUrl);
|
|
168
158
|
|
|
169
|
-
// 2.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
cuit: '20123456789',
|
|
173
|
-
ticket,
|
|
174
|
-
puntoVenta: 4,
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
// 3. Emitir ticket (modo simple)
|
|
178
|
-
const cae = await wsfe.emitirTicketCSimple({
|
|
179
|
-
total: 3500
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
console.log('CAE:', cae.cae);
|
|
159
|
+
// 2. O generalo manualmente
|
|
160
|
+
import { generateQRUrl } from 'arca-sdk';
|
|
161
|
+
const url = generateQRUrl(caeResponse, '20123456789', 1500);
|
|
183
162
|
```
|
|
184
163
|
|
|
185
|
-
|
|
186
|
-
```typescript
|
|
187
|
-
// Modo completo: con detalle de items
|
|
188
|
-
const cae = await wsfe.emitirTicketC({
|
|
189
|
-
items: [
|
|
190
|
-
{ descripcion: 'Producto 1', cantidad: 2, precioUnitario: 500 },
|
|
191
|
-
{ descripcion: 'Producto 2', cantidad: 1, precioUnitario: 1000 },
|
|
192
|
-
],
|
|
193
|
-
});
|
|
164
|
+
---
|
|
194
165
|
|
|
195
|
-
|
|
196
|
-
// Pero se retornan en la respuesta para que los guardes
|
|
197
|
-
console.log('Items:', cae.items);
|
|
198
|
-
```
|
|
166
|
+
## 🩺 Estado de los servidores
|
|
199
167
|
|
|
200
|
-
#### Factura B (IVA discriminado)
|
|
201
168
|
```typescript
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
descripcion: 'Servicio',
|
|
208
|
-
cantidad: 10,
|
|
209
|
-
precioUnitario: 1000,
|
|
210
|
-
alicuotaIva: 21, // ← OBLIGATORIO
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
comprador: {
|
|
214
|
-
tipoDocumento: TipoDocumento.CUIT,
|
|
215
|
-
nroDocumento: '20987654321',
|
|
216
|
-
},
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
console.log('CAE:', cae.cae);
|
|
220
|
-
console.log('IVA:', cae.iva);
|
|
169
|
+
// Sin necesidad de autenticación
|
|
170
|
+
const status = await WsfeService.checkStatus('produccion');
|
|
171
|
+
console.log('AppServer:', status.appServer); // 'OK'
|
|
172
|
+
console.log('DbServer:', status.dbServer);
|
|
173
|
+
console.log('AuthServer:', status.authServer);
|
|
221
174
|
```
|
|
222
175
|
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
const cae = await wsfe.emitirFacturaA({
|
|
226
|
-
items: [
|
|
227
|
-
{ descripcion: 'Producto', cantidad: 5, precioUnitario: 2000, alicuotaIva: 21 },
|
|
228
|
-
],
|
|
229
|
-
comprador: {
|
|
230
|
-
tipoDocumento: TipoDocumento.CUIT,
|
|
231
|
-
nroDocumento: '20111111119',
|
|
232
|
-
},
|
|
233
|
-
});
|
|
234
|
-
```
|
|
176
|
+
---
|
|
235
177
|
|
|
236
|
-
|
|
237
|
-
Si tus precios ya tienen el IVA (típico en venta minorista/POS), podés usar el flag `incluyeIva`:
|
|
238
|
-
```typescript
|
|
239
|
-
const cae = await wsfe.emitirFacturaB({
|
|
240
|
-
incluyeIva: true, // ← El SDK calculará el neto y el IVA automáticamente
|
|
241
|
-
items: [
|
|
242
|
-
{ descripcion: 'Producto', cantidad: 1, precioUnitario: 1210, alicuotaIva: 21 },
|
|
243
|
-
],
|
|
244
|
-
// ... comprador
|
|
245
|
-
});
|
|
246
|
-
// Internamente enviará: Subtotal: 1000, IVA: 210, Total: 1210
|
|
247
|
-
```
|
|
178
|
+
## 📝 Referencia de Servicios
|
|
248
179
|
|
|
249
|
-
|
|
180
|
+
| Clase | Servicio ARCA | Descripción |
|
|
181
|
+
|-------|---------------|-------------|
|
|
182
|
+
| `WsaaService` | `wsaa` | Autenticación y Autorización |
|
|
183
|
+
| `WsfeService` | `wsfev1` | Facturación Electrónica (A, B, C) |
|
|
184
|
+
| `PadronService` | `ws_sr_padron_a13` | Consulta de datos de contribuyentes |
|
|
250
185
|
|
|
251
|
-
|
|
252
|
-
AFIP exige que los comprobantes impresos tengan un código QR con los datos fiscales. La SDK lo genera por vos:
|
|
186
|
+
### Enums disponibles
|
|
253
187
|
|
|
254
188
|
```typescript
|
|
255
|
-
import {
|
|
256
|
-
|
|
257
|
-
// Usá la respuesta del CAE para generar la URL del QR
|
|
258
|
-
const urlQr = generarUrlQR(cae);
|
|
189
|
+
import { InvoiceType, BillingConcept, TaxIdType } from 'arca-sdk';
|
|
259
190
|
|
|
260
|
-
|
|
261
|
-
//
|
|
262
|
-
|
|
191
|
+
InvoiceType.FACTURA_A // 1
|
|
192
|
+
InvoiceType.FACTURA_B // 6
|
|
193
|
+
InvoiceType.FACTURA_C // 11
|
|
194
|
+
InvoiceType.TICKET_C // 83
|
|
263
195
|
|
|
264
|
-
|
|
196
|
+
BillingConcept.PRODUCTS // 1
|
|
197
|
+
BillingConcept.SERVICES // 2
|
|
198
|
+
BillingConcept.PRODUCTS_AND_SERVICES // 3
|
|
265
199
|
|
|
266
|
-
|
|
200
|
+
TaxIdType.CUIT // 80
|
|
201
|
+
TaxIdType.DNI // 96
|
|
202
|
+
TaxIdType.FINAL_CONSUMER // 99
|
|
203
|
+
```
|
|
267
204
|
|
|
268
205
|
---
|
|
269
206
|
|
|
270
|
-
##
|
|
271
|
-
|
|
272
|
-
| Tipo | Uso | IVA Discriminado | Items requeridos |
|
|
273
|
-
|------|-----|------------------|------------------|
|
|
274
|
-
| **Ticket C** | Consumidor final | No | Opcional (solo local) |
|
|
275
|
-
| **Factura C** | Consumidor final | No | Opcional |
|
|
276
|
-
| **Factura B** | Monotributo → RI | Sí | **Obligatorio** |
|
|
277
|
-
| **Factura A** | RI → RI | Sí | **Obligatorio** |
|
|
207
|
+
## 🛠️ Desarrollo y Tests
|
|
278
208
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
209
|
+
```bash
|
|
210
|
+
# Correr tests (unit + mocks de ARCA)
|
|
211
|
+
bun test
|
|
282
212
|
|
|
283
|
-
|
|
213
|
+
# Verificar tipos TypeScript
|
|
214
|
+
bun run lint
|
|
284
215
|
|
|
285
|
-
|
|
216
|
+
# Build para producción (CJS + ESM + .d.ts)
|
|
217
|
+
bun run build
|
|
218
|
+
```
|
|
286
219
|
|
|
287
220
|
---
|
|
288
221
|
|
|
289
222
|
## 📄 Licencia
|
|
290
|
-
|
|
291
223
|
MIT © [Marcela Borgarello](https://github.com/marcelaborgarello)
|
|
292
224
|
|
|
293
225
|
---
|
|
294
226
|
|
|
295
|
-
## 🔗 Links
|
|
296
|
-
|
|
297
|
-
- [Documentación ARCA](https://www.afip.gob.ar/ws/)
|
|
298
|
-
- [Issues](https://github.com/marcelaborgarello/arca-sdk/issues)
|
|
299
|
-
- [NPM](https://www.npmjs.com/package/arca-sdk)
|
|
300
|
-
|
|
301
|
-
---
|
|
302
|
-
|
|
303
227
|
**Hecho con ❤️ en Argentina 🇦🇷**
|
|
304
|
-
|
|
305
228
|
*Porque integrar con ARCA no tiene por qué ser un infierno.*
|