@arcasdk/pdf 0.2.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 +114 -0
- package/lib/constants/index.d.ts +1 -0
- package/lib/constants/index.js +18 -0
- package/lib/constants/index.js.map +1 -0
- package/lib/constants/voucher.constants.d.ts +24 -0
- package/lib/constants/voucher.constants.js +99 -0
- package/lib/constants/voucher.constants.js.map +1 -0
- package/lib/generator/index.d.ts +1 -0
- package/lib/generator/index.js +18 -0
- package/lib/generator/index.js.map +1 -0
- package/lib/generator/invoice-pdf-generator.d.ts +11 -0
- package/lib/generator/invoice-pdf-generator.js +204 -0
- package/lib/generator/invoice-pdf-generator.js.map +1 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +20 -0
- package/lib/index.js.map +1 -0
- package/lib/templates/arca-default/index.d.ts +1 -0
- package/lib/templates/arca-default/index.js +7 -0
- package/lib/templates/arca-default/index.js.map +1 -0
- package/lib/templates/arca-default/invoice-document.d.ts +3 -0
- package/lib/templates/arca-default/invoice-document.hbs +336 -0
- package/lib/templates/arca-default/invoice-document.js +14 -0
- package/lib/templates/arca-default/invoice-document.js.map +1 -0
- package/lib/templates/engine/index.d.ts +1 -0
- package/lib/templates/engine/index.js +8 -0
- package/lib/templates/engine/index.js.map +1 -0
- package/lib/templates/engine/template-engine.d.ts +5 -0
- package/lib/templates/engine/template-engine.js +88 -0
- package/lib/templates/engine/template-engine.js.map +1 -0
- package/lib/templates/index.d.ts +1 -0
- package/lib/templates/index.js +6 -0
- package/lib/templates/index.js.map +1 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +18 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/invoice-data.types.d.ts +225 -0
- package/lib/types/invoice-data.types.js +3 -0
- package/lib/types/invoice-data.types.js.map +1 -0
- package/lib/utils/format.utils.d.ts +22 -0
- package/lib/utils/format.utils.js +56 -0
- package/lib/utils/format.utils.js.map +1 -0
- package/lib/utils/index.d.ts +3 -0
- package/lib/utils/index.js +20 -0
- package/lib/utils/index.js.map +1 -0
- package/lib/utils/number-to-words.utils.d.ts +1 -0
- package/lib/utils/number-to-words.utils.js +99 -0
- package/lib/utils/number-to-words.utils.js.map +1 -0
- package/lib/utils/qr.utils.d.ts +8 -0
- package/lib/utils/qr.utils.js +56 -0
- package/lib/utils/qr.utils.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Datos del emisor (quien emite la factura)
|
|
3
|
+
*/
|
|
4
|
+
export interface EmisorData {
|
|
5
|
+
razonSocial: string;
|
|
6
|
+
domicilioComercial: string;
|
|
7
|
+
condicionIva: string;
|
|
8
|
+
cuit: string;
|
|
9
|
+
iibb: string;
|
|
10
|
+
fechaInicioActividades: string;
|
|
11
|
+
/** Contacto del emisor (email, web, teléfono) */
|
|
12
|
+
contacto?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Datos del receptor (a quien va dirigida la factura)
|
|
16
|
+
*/
|
|
17
|
+
export interface ReceptorData {
|
|
18
|
+
razonSocial: string;
|
|
19
|
+
domicilio?: string;
|
|
20
|
+
condicionIva: string;
|
|
21
|
+
documentoTipo: string;
|
|
22
|
+
documentoNro: string;
|
|
23
|
+
/** CUIT del país destino con descripción (ej: "55000002126 (ESTADOS UNIDOS - Persona Jurídica)") */
|
|
24
|
+
cuitPais?: string;
|
|
25
|
+
/** ID impositivo del receptor en el país destino */
|
|
26
|
+
idImpositivo?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Item individual de la factura
|
|
30
|
+
*/
|
|
31
|
+
export interface InvoiceItem {
|
|
32
|
+
codigo?: string;
|
|
33
|
+
descripcion: string;
|
|
34
|
+
cantidad: number;
|
|
35
|
+
unidadMedida: string;
|
|
36
|
+
precioUnitario: number;
|
|
37
|
+
bonificacion?: number;
|
|
38
|
+
/** Importe de bonificación pre-calculado. Si no se provee, se calcula como precioUnitario * cantidad * (bonificacion / 100) */
|
|
39
|
+
importeBonificacion?: number;
|
|
40
|
+
subtotal: number;
|
|
41
|
+
alicuotaIva?: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Detalle de alícuota de IVA
|
|
45
|
+
*/
|
|
46
|
+
export interface IvaDetail {
|
|
47
|
+
id: number;
|
|
48
|
+
descripcion: string;
|
|
49
|
+
baseImponible: number;
|
|
50
|
+
importe: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Detalle de otros tributos
|
|
54
|
+
*/
|
|
55
|
+
export interface TributoDetail {
|
|
56
|
+
id: number;
|
|
57
|
+
descripcion: string;
|
|
58
|
+
baseImponible: number;
|
|
59
|
+
alicuota: number;
|
|
60
|
+
importe: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Comprobante asociado
|
|
64
|
+
*/
|
|
65
|
+
export interface ComprobanteAsociado {
|
|
66
|
+
tipo: number;
|
|
67
|
+
puntoVenta: number;
|
|
68
|
+
numero: number;
|
|
69
|
+
cuit?: string;
|
|
70
|
+
fecha?: string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Datos del comprobante electrónico para generar el PDF
|
|
74
|
+
* Independiente del package core - se puede construir manualmente
|
|
75
|
+
* o mapeando datos desde @arcasdk/core
|
|
76
|
+
*/
|
|
77
|
+
export interface InvoiceData {
|
|
78
|
+
/** Datos del emisor */
|
|
79
|
+
emisor: EmisorData;
|
|
80
|
+
/** Datos del receptor */
|
|
81
|
+
receptor: ReceptorData;
|
|
82
|
+
/** Tipo de comprobante (ej: 1=Factura A, 6=Factura B, 11=Factura C) */
|
|
83
|
+
cbteTipo: number;
|
|
84
|
+
/** Descripción del tipo de comprobante (ej: "FACTURA") */
|
|
85
|
+
cbteDescripcion?: string;
|
|
86
|
+
/** Letra del comprobante (A, B, C, etc) */
|
|
87
|
+
cbteLetra: string;
|
|
88
|
+
/** Punto de venta */
|
|
89
|
+
puntoVenta: number;
|
|
90
|
+
/** Número de comprobante desde */
|
|
91
|
+
cbteDesde: number;
|
|
92
|
+
/** Número de comprobante hasta */
|
|
93
|
+
cbteHasta: number;
|
|
94
|
+
/** Fecha del comprobante (formato YYYY-MM-DD o YYYYMMDD) */
|
|
95
|
+
cbteFecha: string;
|
|
96
|
+
/** Concepto: 1=Productos, 2=Servicios, 3=Productos y Servicios */
|
|
97
|
+
concepto: number;
|
|
98
|
+
/** Moneda (ej: "PES" para pesos argentinos) */
|
|
99
|
+
moneda?: string;
|
|
100
|
+
/** Cotización de la moneda */
|
|
101
|
+
cotizacion?: number;
|
|
102
|
+
/** Condición de venta (ej: "Contado", "Cuenta Corriente") */
|
|
103
|
+
condicionVenta?: string;
|
|
104
|
+
/** Fecha desde del servicio (para conceptos 2 y 3) */
|
|
105
|
+
fechaServicioDesde?: string;
|
|
106
|
+
/** Fecha hasta del servicio (para conceptos 2 y 3) */
|
|
107
|
+
fechaServicioHasta?: string;
|
|
108
|
+
/** Fecha de vencimiento de pago (para conceptos 2 y 3) */
|
|
109
|
+
fechaVtoPago?: string;
|
|
110
|
+
/** Items de la factura */
|
|
111
|
+
items: InvoiceItem[];
|
|
112
|
+
/** Importe neto gravado */
|
|
113
|
+
importeNetoGravado: number;
|
|
114
|
+
/** Importe neto no gravado */
|
|
115
|
+
importeNetoNoGravado?: number;
|
|
116
|
+
/** Importe exento */
|
|
117
|
+
importeExento?: number;
|
|
118
|
+
/** Detalle de IVA por alícuota */
|
|
119
|
+
iva?: IvaDetail[];
|
|
120
|
+
/** Importe total de IVA */
|
|
121
|
+
importeIva: number;
|
|
122
|
+
/** Detalle de otros tributos */
|
|
123
|
+
tributos?: TributoDetail[];
|
|
124
|
+
/** Importe total de otros tributos */
|
|
125
|
+
importeTributos?: number;
|
|
126
|
+
/** Importe total */
|
|
127
|
+
importeTotal: number;
|
|
128
|
+
/** CAE (Código de Autorización Electrónico) */
|
|
129
|
+
cae: string;
|
|
130
|
+
/** Fecha de vencimiento del CAE (formato YYYY-MM-DD o YYYYMMDD) */
|
|
131
|
+
caeFechaVencimiento: string;
|
|
132
|
+
/** Comprobantes asociados */
|
|
133
|
+
cbtesAsociados?: ComprobanteAsociado[];
|
|
134
|
+
/** Observaciones */
|
|
135
|
+
observaciones?: string;
|
|
136
|
+
/** Divisa con descripción completa (ej: "USD - Dólar Estadounidense") */
|
|
137
|
+
divisa?: string;
|
|
138
|
+
/** País destino del comprobante */
|
|
139
|
+
destinoComprobante?: string;
|
|
140
|
+
/** Forma de pago (ej: "Transferencia SWIFT - Moneda Extranjera") */
|
|
141
|
+
formaPago?: string;
|
|
142
|
+
/** Incoterms */
|
|
143
|
+
incoterms?: string;
|
|
144
|
+
/** Fecha de pago (formato YYYYMMDD) */
|
|
145
|
+
fechaPago?: string;
|
|
146
|
+
/** Leyenda de condición IVA en exportación (ej: "IVA EXENTO OPERACIÓN DE EXPORTACIÓN") */
|
|
147
|
+
condicionIvaExportacion?: string;
|
|
148
|
+
/** Importe total expresado en pesos argentinos (para comprobantes en moneda extranjera).
|
|
149
|
+
* Si no se provee, se calcula como importeTotal * cotizacion */
|
|
150
|
+
importeTotalPesos?: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Props recibidas por cualquier template de factura.
|
|
154
|
+
* Implementar este contrato para crear templates personalizados.
|
|
155
|
+
*/
|
|
156
|
+
export interface InvoiceTemplateProps {
|
|
157
|
+
data: InvoiceData;
|
|
158
|
+
options: ResolvedPdfOptions;
|
|
159
|
+
/** Data URL del QR code ya generado (undefined si includeQr=false) */
|
|
160
|
+
qrDataUrl?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Opciones resueltas (con defaults aplicados) que recibe el template.
|
|
164
|
+
*/
|
|
165
|
+
export type CopyType = "ORIGINAL" | "DUPLICADO" | "TRIPLICADO" | "CUADRUPLICADO";
|
|
166
|
+
export interface ResolvedPdfOptions {
|
|
167
|
+
pageSize: "A4" | "LETTER" | "LEGAL";
|
|
168
|
+
margin: number;
|
|
169
|
+
includeQr: boolean;
|
|
170
|
+
logo?: string;
|
|
171
|
+
logoWidth?: number;
|
|
172
|
+
footerText?: string;
|
|
173
|
+
copy?: CopyType;
|
|
174
|
+
copies?: CopyType[];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Opciones de configuración para la generación del PDF
|
|
178
|
+
*/
|
|
179
|
+
export interface PdfGeneratorOptions {
|
|
180
|
+
/** Tamaño de página (default: "A4") */
|
|
181
|
+
pageSize?: "A4" | "LETTER" | "LEGAL";
|
|
182
|
+
/** Márgenes en puntos (default: 10) */
|
|
183
|
+
margin?: number;
|
|
184
|
+
/** Incluir QR code de ARCA (default: true) */
|
|
185
|
+
includeQr?: boolean;
|
|
186
|
+
/** Logo del emisor como data URL (ej: "data:image/png;base64,...") */
|
|
187
|
+
logo?: string;
|
|
188
|
+
/** Ancho del logo en puntos (default: 60) */
|
|
189
|
+
logoWidth?: number;
|
|
190
|
+
/** Texto adicional en el pie de página */
|
|
191
|
+
footerText?: string;
|
|
192
|
+
/** Banner de copia individual: "ORIGINAL" | "DUPLICADO" | "TRIPLICADO" | "CUADRUPLICADO" */
|
|
193
|
+
copy?: CopyType;
|
|
194
|
+
/**
|
|
195
|
+
* Generar múltiples copias en un solo PDF.
|
|
196
|
+
* Cada entrada genera una copia completa con su banner.
|
|
197
|
+
* Si se provee, ignora `copy`.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* copies: ["ORIGINAL", "DUPLICADO", "TRIPLICADO"]
|
|
201
|
+
*/
|
|
202
|
+
copies?: CopyType[];
|
|
203
|
+
/**
|
|
204
|
+
* Template personalizado. Puede ser:
|
|
205
|
+
* - Una función que reciba InvoiceTemplateProps y retorne HTML string
|
|
206
|
+
* - Un string con template Handlebars (se compila automáticamente)
|
|
207
|
+
*
|
|
208
|
+
* Los templates Handlebars tienen acceso a helpers integrados:
|
|
209
|
+
* formatDate, formatCuit, formatCurrency, formatUnitPrice,
|
|
210
|
+
* voucherNumber, descTipo, numberToWords, currencyName, etc.
|
|
211
|
+
*
|
|
212
|
+
* @example
|
|
213
|
+
* // Como función
|
|
214
|
+
* const generator = new InvoicePdfGenerator({
|
|
215
|
+
* template: ({ data }) => `<h1>${data.emisor.razonSocial}</h1>`,
|
|
216
|
+
* });
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* // Como template Handlebars
|
|
220
|
+
* const generator = new InvoicePdfGenerator({
|
|
221
|
+
* template: "<h1>{{data.emisor.razonSocial}}</h1>",
|
|
222
|
+
* });
|
|
223
|
+
*/
|
|
224
|
+
template?: ((props: InvoiceTemplateProps) => string) | string;
|
|
225
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice-data.types.js","sourceRoot":"","sources":["../../src/types/invoice-data.types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formatea una fecha de YYYYMMDD o YYYY-MM-DD a DD/MM/YYYY
|
|
3
|
+
*/
|
|
4
|
+
export declare function formatDate(date: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Formatea un número de comprobante con ceros a la izquierda
|
|
7
|
+
*/
|
|
8
|
+
export declare function formatVoucherNumber(puntoVenta: number, numero: number): string;
|
|
9
|
+
/**
|
|
10
|
+
* Formatea un CUIT con guiones: XX-XXXXXXXX-X
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatCuit(cuit: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Formatea un monto como moneda con separador de miles
|
|
15
|
+
* Ejemplo: 1234567.89 -> "$ 1.234.567,89"
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatCurrency(amount: number, monedaId?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Formatea un número con separador de miles (.) y decimales (,)
|
|
20
|
+
* Formato argentino: 1.234.567,89
|
|
21
|
+
*/
|
|
22
|
+
export declare function formatNumber(value: number): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatDate = formatDate;
|
|
4
|
+
exports.formatVoucherNumber = formatVoucherNumber;
|
|
5
|
+
exports.formatCuit = formatCuit;
|
|
6
|
+
exports.formatCurrency = formatCurrency;
|
|
7
|
+
exports.formatNumber = formatNumber;
|
|
8
|
+
const voucher_constants_1 = require("../constants/voucher.constants");
|
|
9
|
+
/**
|
|
10
|
+
* Formatea una fecha de YYYYMMDD o YYYY-MM-DD a DD/MM/YYYY
|
|
11
|
+
*/
|
|
12
|
+
function formatDate(date) {
|
|
13
|
+
const clean = date.replace(/-/g, "");
|
|
14
|
+
if (clean.length !== 8)
|
|
15
|
+
return date;
|
|
16
|
+
const day = clean.substring(6, 8);
|
|
17
|
+
const month = clean.substring(4, 6);
|
|
18
|
+
const year = clean.substring(0, 4);
|
|
19
|
+
return `${day}/${month}/${year}`;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Formatea un número de comprobante con ceros a la izquierda
|
|
23
|
+
*/
|
|
24
|
+
function formatVoucherNumber(puntoVenta, numero) {
|
|
25
|
+
const pv = String(puntoVenta).padStart(5, "0");
|
|
26
|
+
const nro = String(numero).padStart(8, "0");
|
|
27
|
+
return `${pv}-${nro}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Formatea un CUIT con guiones: XX-XXXXXXXX-X
|
|
31
|
+
*/
|
|
32
|
+
function formatCuit(cuit) {
|
|
33
|
+
const clean = cuit.replace(/-/g, "");
|
|
34
|
+
if (clean.length !== 11)
|
|
35
|
+
return cuit;
|
|
36
|
+
return `${clean.substring(0, 2)}-${clean.substring(2, 10)}-${clean.substring(10)}`;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Formatea un monto como moneda con separador de miles
|
|
40
|
+
* Ejemplo: 1234567.89 -> "$ 1.234.567,89"
|
|
41
|
+
*/
|
|
42
|
+
function formatCurrency(amount, monedaId) {
|
|
43
|
+
const symbol = (monedaId && voucher_constants_1.CURRENCY_SYMBOL[monedaId]) || "$";
|
|
44
|
+
const formatted = formatNumber(amount);
|
|
45
|
+
return `${symbol}\u00a0${formatted}`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Formatea un número con separador de miles (.) y decimales (,)
|
|
49
|
+
* Formato argentino: 1.234.567,89
|
|
50
|
+
*/
|
|
51
|
+
function formatNumber(value) {
|
|
52
|
+
const [intPart, decPart] = value.toFixed(2).split(".");
|
|
53
|
+
const withDots = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
|
|
54
|
+
return `${withDots},${decPart}`;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=format.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.utils.js","sourceRoot":"","sources":["../../src/utils/format.utils.ts"],"names":[],"mappings":";;AAKA,gCAOC;AAKD,kDAOC;AAKD,gCAIC;AAMD,wCAIC;AAMD,oCAIC;AArDD,wEAAmE;AAEnE;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,OAAO,GAAG,GAAG,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CACjC,UAAkB,EAClB,MAAc;IAEd,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,GAAG,EAAE,IAAI,GAAG,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAY;IACrC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;AACrF,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,MAAc,EAAE,QAAiB;IAC9D,MAAM,MAAM,GAAG,CAAC,QAAQ,IAAI,mCAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,GAAG,CAAC;IAC9D,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,GAAG,MAAM,SAAS,SAAS,EAAE,CAAC;AACvC,CAAC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,KAAa;IACxC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,CAAC,CAAC;IAC/D,OAAO,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./format.utils"), exports);
|
|
18
|
+
__exportStar(require("./qr.utils"), exports);
|
|
19
|
+
__exportStar(require("./number-to-words.utils"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B;AAC/B,6CAA2B;AAC3B,0DAAwC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function numberToWords(n: number): string;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.numberToWords = numberToWords;
|
|
4
|
+
const UNITS = [
|
|
5
|
+
"",
|
|
6
|
+
"un",
|
|
7
|
+
"dos",
|
|
8
|
+
"tres",
|
|
9
|
+
"cuatro",
|
|
10
|
+
"cinco",
|
|
11
|
+
"seis",
|
|
12
|
+
"siete",
|
|
13
|
+
"ocho",
|
|
14
|
+
"nueve",
|
|
15
|
+
"diez",
|
|
16
|
+
"once",
|
|
17
|
+
"doce",
|
|
18
|
+
"trece",
|
|
19
|
+
"catorce",
|
|
20
|
+
"quince",
|
|
21
|
+
"dieciséis",
|
|
22
|
+
"diecisiete",
|
|
23
|
+
"dieciocho",
|
|
24
|
+
"diecinueve",
|
|
25
|
+
"veinte",
|
|
26
|
+
"veintiún",
|
|
27
|
+
"veintidós",
|
|
28
|
+
"veintitrés",
|
|
29
|
+
"veinticuatro",
|
|
30
|
+
"veinticinco",
|
|
31
|
+
"veintiséis",
|
|
32
|
+
"veintisiete",
|
|
33
|
+
"veintiocho",
|
|
34
|
+
"veintinueve",
|
|
35
|
+
];
|
|
36
|
+
const TENS = [
|
|
37
|
+
"",
|
|
38
|
+
"",
|
|
39
|
+
"",
|
|
40
|
+
"treinta",
|
|
41
|
+
"cuarenta",
|
|
42
|
+
"cincuenta",
|
|
43
|
+
"sesenta",
|
|
44
|
+
"setenta",
|
|
45
|
+
"ochenta",
|
|
46
|
+
"noventa",
|
|
47
|
+
];
|
|
48
|
+
const HUNDREDS = [
|
|
49
|
+
"",
|
|
50
|
+
"ciento",
|
|
51
|
+
"doscientos",
|
|
52
|
+
"trescientos",
|
|
53
|
+
"cuatrocientos",
|
|
54
|
+
"quinientos",
|
|
55
|
+
"seiscientos",
|
|
56
|
+
"setecientos",
|
|
57
|
+
"ochocientos",
|
|
58
|
+
"novecientos",
|
|
59
|
+
];
|
|
60
|
+
function intToWords(n) {
|
|
61
|
+
if (n === 0)
|
|
62
|
+
return "cero";
|
|
63
|
+
if (n < 30)
|
|
64
|
+
return UNITS[n];
|
|
65
|
+
if (n < 100) {
|
|
66
|
+
const t = Math.floor(n / 10);
|
|
67
|
+
const u = n % 10;
|
|
68
|
+
return u === 0 ? TENS[t] : `${TENS[t]} y ${UNITS[u]}`;
|
|
69
|
+
}
|
|
70
|
+
if (n === 100)
|
|
71
|
+
return "cien";
|
|
72
|
+
if (n < 1000) {
|
|
73
|
+
const h = Math.floor(n / 100);
|
|
74
|
+
const r = n % 100;
|
|
75
|
+
return r === 0 ? HUNDREDS[h] : `${HUNDREDS[h]} ${intToWords(r)}`;
|
|
76
|
+
}
|
|
77
|
+
if (n < 1000000) {
|
|
78
|
+
const thou = Math.floor(n / 1000);
|
|
79
|
+
const r = n % 1000;
|
|
80
|
+
const s = thou === 1 ? "mil" : `${intToWords(thou)} mil`;
|
|
81
|
+
return r === 0 ? s : `${s} ${intToWords(r)}`;
|
|
82
|
+
}
|
|
83
|
+
if (n < 1000000000) {
|
|
84
|
+
const mill = Math.floor(n / 1000000);
|
|
85
|
+
const r = n % 1000000;
|
|
86
|
+
const s = mill === 1 ? "un millón" : `${intToWords(mill)} millones`;
|
|
87
|
+
return r === 0 ? s : `${s} ${intToWords(r)}`;
|
|
88
|
+
}
|
|
89
|
+
return String(n);
|
|
90
|
+
}
|
|
91
|
+
function numberToWords(n) {
|
|
92
|
+
const cents = Math.round((n % 1) * 100);
|
|
93
|
+
const integer = Math.floor(n);
|
|
94
|
+
const centStr = `${String(cents).padStart(2, "0")}/100`;
|
|
95
|
+
if (integer === 0)
|
|
96
|
+
return `CERO CON ${centStr}`;
|
|
97
|
+
return `${intToWords(integer).toUpperCase()} CON ${centStr}`;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=number-to-words.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-to-words.utils.js","sourceRoot":"","sources":["../../src/utils/number-to-words.utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { InvoiceData } from "../types/invoice-data.types";
|
|
2
|
+
/**
|
|
3
|
+
* Genera la URL del QR de ARCA para un comprobante electrónico.
|
|
4
|
+
* El QR codifica los datos del comprobante en base64 como parámetro de la URL.
|
|
5
|
+
*
|
|
6
|
+
* @see https://www.afip.gob.ar/fe/qr/especificaciones.asp
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildArcaQrUrl(data: InvoiceData): string;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildArcaQrUrl = buildArcaQrUrl;
|
|
4
|
+
const ARCA_QR_BASE_URL = "https://www.afip.gob.ar/fe/qr/";
|
|
5
|
+
/**
|
|
6
|
+
* Genera la URL del QR de ARCA para un comprobante electrónico.
|
|
7
|
+
* El QR codifica los datos del comprobante en base64 como parámetro de la URL.
|
|
8
|
+
*
|
|
9
|
+
* @see https://www.afip.gob.ar/fe/qr/especificaciones.asp
|
|
10
|
+
*/
|
|
11
|
+
function buildArcaQrUrl(data) {
|
|
12
|
+
const cuitEmisor = data.emisor.cuit.replace(/-/g, "");
|
|
13
|
+
const cuitReceptor = data.receptor.documentoNro.replace(/-/g, "");
|
|
14
|
+
const fecha = normalizeDate(data.cbteFecha);
|
|
15
|
+
const qrData = {
|
|
16
|
+
ver: 1,
|
|
17
|
+
fecha,
|
|
18
|
+
cuit: Number(cuitEmisor),
|
|
19
|
+
ptoVta: data.puntoVenta,
|
|
20
|
+
tipoCmp: data.cbteTipo,
|
|
21
|
+
nroCmp: data.cbteDesde,
|
|
22
|
+
importe: data.importeTotal,
|
|
23
|
+
moneda: data.moneda || "PES",
|
|
24
|
+
ctz: data.cotizacion || 1,
|
|
25
|
+
tipoDocRec: getDocTipoNumber(data.receptor.documentoTipo),
|
|
26
|
+
nroDocRec: Number(cuitReceptor) || 0,
|
|
27
|
+
tipoCodAut: "E",
|
|
28
|
+
codAut: Number(data.cae),
|
|
29
|
+
};
|
|
30
|
+
const jsonStr = JSON.stringify(qrData);
|
|
31
|
+
const base64 = Buffer.from(jsonStr).toString("base64");
|
|
32
|
+
return `${ARCA_QR_BASE_URL}?p=${base64}`;
|
|
33
|
+
}
|
|
34
|
+
function normalizeDate(date) {
|
|
35
|
+
const clean = date.replace(/-/g, "");
|
|
36
|
+
if (clean.length !== 8)
|
|
37
|
+
return date;
|
|
38
|
+
return `${clean.substring(0, 4)}-${clean.substring(4, 6)}-${clean.substring(6, 8)}`;
|
|
39
|
+
}
|
|
40
|
+
function getDocTipoNumber(docTipo) {
|
|
41
|
+
var _a;
|
|
42
|
+
const mapping = {
|
|
43
|
+
CUIT: 80,
|
|
44
|
+
CUIL: 86,
|
|
45
|
+
CDI: 87,
|
|
46
|
+
DNI: 96,
|
|
47
|
+
LE: 89,
|
|
48
|
+
LC: 90,
|
|
49
|
+
"CI Extranjera": 91,
|
|
50
|
+
Pasaporte: 94,
|
|
51
|
+
"CI Buenos Aires": 0,
|
|
52
|
+
"Sin Identificar": 99,
|
|
53
|
+
};
|
|
54
|
+
return (_a = mapping[docTipo]) !== null && _a !== void 0 ? _a : (Number(docTipo) || 99);
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=qr.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr.utils.js","sourceRoot":"","sources":["../../src/utils/qr.utils.ts"],"names":[],"mappings":";;AAUA,wCAyBC;AAjCD,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AAE1D;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,IAAiB;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAE5C,MAAM,MAAM,GAAG;QACb,GAAG,EAAE,CAAC;QACN,KAAK;QACL,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC;QACxB,MAAM,EAAE,IAAI,CAAC,UAAU;QACvB,OAAO,EAAE,IAAI,CAAC,QAAQ;QACtB,MAAM,EAAE,IAAI,CAAC,SAAS;QACtB,OAAO,EAAE,IAAI,CAAC,YAAY;QAC1B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;QAC5B,GAAG,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC;QACzB,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;QACzD,SAAS,EAAE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC;QACpC,UAAU,EAAE,GAAG;QACf,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KACzB,CAAC;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEvD,OAAO,GAAG,gBAAgB,MAAM,MAAM,EAAE,CAAC;AAC3C,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACtF,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;;IACvC,MAAM,OAAO,GAA2B;QACtC,IAAI,EAAE,EAAE;QACR,IAAI,EAAE,EAAE;QACR,GAAG,EAAE,EAAE;QACP,GAAG,EAAE,EAAE;QACP,EAAE,EAAE,EAAE;QACN,EAAE,EAAE,EAAE;QACN,eAAe,EAAE,EAAE;QACnB,SAAS,EAAE,EAAE;QACb,iBAAiB,EAAE,CAAC;QACpB,iBAAiB,EAAE,EAAE;KACtB,CAAC;IACF,OAAO,MAAA,OAAO,CAAC,OAAO,CAAC,mCAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arcasdk/pdf",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Arca TypeScript SDK - PDF invoice generator for ARCA electronic billing",
|
|
5
|
+
"source": "src/index.ts",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "npx tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && rsync -a --include='*/' --include='*.hbs' --exclude='*' src/ lib/",
|
|
10
|
+
"test": "jest --config jest.config.js",
|
|
11
|
+
"test:unit": "jest --config jest.config.js",
|
|
12
|
+
"test:coverage": "jest --config jest.config.js --coverage",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"handlebars": "^4.7.9",
|
|
17
|
+
"html2pdf.js": "^0.14.0",
|
|
18
|
+
"jsdom": "^29.1.1",
|
|
19
|
+
"pdf-lib": "^1.17.1",
|
|
20
|
+
"puppeteer": "^24.43.1",
|
|
21
|
+
"qrcode": "^1.5.4"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@jest/globals": "^30.0.0",
|
|
25
|
+
"@types/handlebars": "^4.0.40",
|
|
26
|
+
"@types/jest": "^30.0.0",
|
|
27
|
+
"@types/node": "^24.10.1",
|
|
28
|
+
"@types/qrcode": "^1.5.5",
|
|
29
|
+
"jest": "^30.0.0",
|
|
30
|
+
"ts-jest": "^29.0.0",
|
|
31
|
+
"ts-node": "^10.9.1",
|
|
32
|
+
"tsc-alias": "^1.8.16",
|
|
33
|
+
"tsconfig-paths": "^4.2.0",
|
|
34
|
+
"typescript": "^6.0.3"
|
|
35
|
+
},
|
|
36
|
+
"author": "valiuLab",
|
|
37
|
+
"license": "ISC",
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/ralcorta/arcasdk.git",
|
|
44
|
+
"directory": "packages/pdf"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/ralcorta/arcasdk/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/ralcorta/arcasdk#readme",
|
|
50
|
+
"files": [
|
|
51
|
+
"lib/**/*"
|
|
52
|
+
],
|
|
53
|
+
"keywords": [
|
|
54
|
+
"factura-electronica",
|
|
55
|
+
"pdf",
|
|
56
|
+
"arca",
|
|
57
|
+
"afip",
|
|
58
|
+
"invoice",
|
|
59
|
+
"comprobante"
|
|
60
|
+
]
|
|
61
|
+
}
|