facturas 0.7.1 → 0.9.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.
Files changed (37) hide show
  1. package/README.md +799 -27
  2. package/dist/{chunk-IOKZX6CA.mjs → chunk-4QVFXT35.mjs} +2 -2
  3. package/dist/chunk-76WU5BVI.mjs +109 -0
  4. package/dist/chunk-76WU5BVI.mjs.map +1 -0
  5. package/dist/{chunk-EDY3PNKJ.mjs → chunk-7LEKQ4P7.mjs} +2 -2
  6. package/dist/{chunk-OHHXHYLV.mjs → chunk-RCM4NAAG.mjs} +244 -48
  7. package/dist/chunk-RCM4NAAG.mjs.map +1 -0
  8. package/dist/{chunk-A3C3Y5PI.mjs → chunk-XNBD5NVL.mjs} +32 -31
  9. package/dist/chunk-XNBD5NVL.mjs.map +1 -0
  10. package/dist/{chunk-MBWOFO67.mjs → chunk-ZOSNASXB.mjs} +14 -2
  11. package/dist/chunk-ZOSNASXB.mjs.map +1 -0
  12. package/dist/constants.d.ts +49 -1
  13. package/dist/constants.mjs +9 -1
  14. package/dist/errors.d.ts +2 -2
  15. package/dist/errors.mjs +5 -3
  16. package/dist/{fiscal-evidence-BQuBbJ3h.d.ts → fiscal-evidence-DBzakqBE.d.ts} +11 -3
  17. package/dist/{index-CVpygFb0.d.ts → index-CVGQyyYM.d.ts} +1 -1
  18. package/dist/index.d.ts +238 -9
  19. package/dist/index.mjs +1343 -30
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/padron.d.ts +2 -2
  22. package/dist/padron.mjs +2 -2
  23. package/dist/{types-BXq0da71.d.ts → types-BiznC1-X.d.ts} +12 -1
  24. package/dist/types.d.ts +1 -1
  25. package/dist/wsfe-DF0jAE2k.d.ts +325 -0
  26. package/dist/wsfe.d.ts +4 -309
  27. package/dist/wsfe.mjs +4 -4
  28. package/dist/wsmtxca.d.ts +14 -5
  29. package/dist/wsmtxca.mjs +3 -3
  30. package/package.json +1 -1
  31. package/dist/chunk-A3C3Y5PI.mjs.map +0 -1
  32. package/dist/chunk-MBWOFO67.mjs.map +0 -1
  33. package/dist/chunk-OHHXHYLV.mjs.map +0 -1
  34. package/dist/chunk-VVY2LZIZ.mjs +0 -61
  35. package/dist/chunk-VVY2LZIZ.mjs.map +0 -1
  36. /package/dist/{chunk-IOKZX6CA.mjs.map → chunk-4QVFXT35.mjs.map} +0 -0
  37. /package/dist/{chunk-EDY3PNKJ.mjs.map → chunk-7LEKQ4P7.mjs.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  ArcaServiceError,
4
4
  ArcaSoapFaultError,
5
5
  isArcaAuthenticationError
6
- } from "./chunk-MBWOFO67.mjs";
6
+ } from "./chunk-ZOSNASXB.mjs";
7
7
 
8
8
  // src/internal/authentication.ts
9
9
  var WSFE_AUTHENTICATION_CODES = {
@@ -192,4 +192,4 @@ export {
192
192
  createArcaAuthenticationErrorFromEvidence,
193
193
  executeWithAuthenticationRecovery
194
194
  };
195
- //# sourceMappingURL=chunk-IOKZX6CA.mjs.map
195
+ //# sourceMappingURL=chunk-4QVFXT35.mjs.map
@@ -0,0 +1,109 @@
1
+ // src/constants.ts
2
+ var ARCA_VOUCHER_TYPES = {
3
+ FACTURA_A: 1,
4
+ NOTA_DEBITO_A: 2,
5
+ NOTA_CREDITO_A: 3,
6
+ FACTURA_B: 6,
7
+ NOTA_DEBITO_B: 7,
8
+ NOTA_CREDITO_B: 8,
9
+ FACTURA_C: 11,
10
+ NOTA_DEBITO_C: 12,
11
+ NOTA_CREDITO_C: 13
12
+ };
13
+ var ARCA_DOCUMENT_TYPES = {
14
+ CUIT: 80,
15
+ DNI: 96,
16
+ CONSUMIDOR_FINAL: 99
17
+ };
18
+ var ARCA_RECEIVER_VAT_CONDITIONS = {
19
+ RESPONSABLE_INSCRIPTO: 1,
20
+ EXENTO: 4,
21
+ CONSUMIDOR_FINAL: 5,
22
+ MONOTRIBUTISTA: 6,
23
+ IVA_NO_ALCANZADO: 15
24
+ };
25
+ var ARCA_CONCEPT_TYPES = {
26
+ PRODUCTOS: 1,
27
+ SERVICIOS: 2,
28
+ PRODUCTOS_Y_SERVICIOS: 3
29
+ };
30
+ var ARCA_VAT_RATES = {
31
+ IVA_0: 3,
32
+ IVA_10_5: 4,
33
+ IVA_21: 5,
34
+ IVA_27: 6,
35
+ IVA_5: 8,
36
+ IVA_2_5: 9
37
+ };
38
+ var ISO_CURRENCIES = {
39
+ ARS: "ARS",
40
+ USD: "USD"
41
+ };
42
+ var ARCA_CURRENCY_IDS = {
43
+ ARS: "PES",
44
+ USD: "DOL"
45
+ };
46
+ var ARCA_CURRENCIES = {
47
+ PES: "PES",
48
+ DOL: "DOL"
49
+ };
50
+ var ARCA_RECEIVER_CONDITION_IDS = {
51
+ responsable_inscripto: ARCA_RECEIVER_VAT_CONDITIONS.RESPONSABLE_INSCRIPTO,
52
+ monotributo: ARCA_RECEIVER_VAT_CONDITIONS.MONOTRIBUTISTA,
53
+ exento: ARCA_RECEIVER_VAT_CONDITIONS.EXENTO,
54
+ consumidor_final: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,
55
+ no_alcanzado: ARCA_RECEIVER_VAT_CONDITIONS.IVA_NO_ALCANZADO
56
+ };
57
+ var ARCA_ISSUER_CONDITION_IDS = {
58
+ responsable_inscripto: 1,
59
+ monotributo: 6,
60
+ exento: 4,
61
+ no_alcanzado: 15
62
+ };
63
+ var ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS = 1000000000n;
64
+ var ARCA_INVOICE_CLASS_BY_ISSUER = {
65
+ responsable_inscripto: {
66
+ responsable_inscripto: "A",
67
+ monotributo: "A",
68
+ exento: "B",
69
+ consumidor_final: "B",
70
+ no_alcanzado: "B"
71
+ },
72
+ monotributo: {
73
+ responsable_inscripto: "C",
74
+ monotributo: "C",
75
+ exento: "C",
76
+ consumidor_final: "C",
77
+ no_alcanzado: "C"
78
+ },
79
+ exento: {
80
+ responsable_inscripto: "C",
81
+ monotributo: "C",
82
+ exento: "C",
83
+ consumidor_final: "C",
84
+ no_alcanzado: "C"
85
+ },
86
+ no_alcanzado: {
87
+ responsable_inscripto: "C",
88
+ monotributo: "C",
89
+ exento: "C",
90
+ consumidor_final: "C",
91
+ no_alcanzado: "C"
92
+ }
93
+ };
94
+
95
+ export {
96
+ ARCA_VOUCHER_TYPES,
97
+ ARCA_DOCUMENT_TYPES,
98
+ ARCA_RECEIVER_VAT_CONDITIONS,
99
+ ARCA_CONCEPT_TYPES,
100
+ ARCA_VAT_RATES,
101
+ ISO_CURRENCIES,
102
+ ARCA_CURRENCY_IDS,
103
+ ARCA_CURRENCIES,
104
+ ARCA_RECEIVER_CONDITION_IDS,
105
+ ARCA_ISSUER_CONDITION_IDS,
106
+ ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS,
107
+ ARCA_INVOICE_CLASS_BY_ISSUER
108
+ };
109
+ //# sourceMappingURL=chunk-76WU5BVI.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["/** Common ARCA reference data for readable userland code and examples. */\nexport const ARCA_VOUCHER_TYPES = {\n FACTURA_A: 1,\n NOTA_DEBITO_A: 2,\n NOTA_CREDITO_A: 3,\n FACTURA_B: 6,\n NOTA_DEBITO_B: 7,\n NOTA_CREDITO_B: 8,\n FACTURA_C: 11,\n NOTA_DEBITO_C: 12,\n NOTA_CREDITO_C: 13,\n} as const;\n\n/** Common document types accepted by ARCA services. */\nexport const ARCA_DOCUMENT_TYPES = {\n CUIT: 80,\n DNI: 96,\n CONSUMIDOR_FINAL: 99,\n} as const;\n\n/**\n * Common receiver IVA condition identifiers used by WSFE.\n * Allowed values depend on the voucher class and ARCA's live catalog.\n */\nexport const ARCA_RECEIVER_VAT_CONDITIONS = {\n RESPONSABLE_INSCRIPTO: 1,\n EXENTO: 4,\n CONSUMIDOR_FINAL: 5,\n MONOTRIBUTISTA: 6,\n IVA_NO_ALCANZADO: 15,\n} as const;\n\n/** Supported invoice concept types for WSFE requests. */\nexport const ARCA_CONCEPT_TYPES = {\n PRODUCTOS: 1,\n SERVICIOS: 2,\n PRODUCTOS_Y_SERVICIOS: 3,\n} as const;\n\n/** Common IVA rate identifiers used by WSFE. */\nexport const ARCA_VAT_RATES = {\n IVA_0: 3,\n IVA_10_5: 4,\n IVA_21: 5,\n IVA_27: 6,\n IVA_5: 8,\n IVA_2_5: 9,\n} as const;\n\n/** ISO currency codes accepted by the high-level WSFE builders. */\nexport const ISO_CURRENCIES = {\n ARS: \"ARS\",\n USD: \"USD\",\n} as const;\n\n/** ARCA currency identifiers keyed by their corresponding ISO currency. */\nexport const ARCA_CURRENCY_IDS = {\n ARS: \"PES\",\n USD: \"DOL\",\n} as const;\n\n/**\n * Common ARCA currency identifiers.\n * @deprecated Use ISO_CURRENCIES for builders or ARCA_CURRENCY_IDS at the exact provider boundary.\n */\nexport const ARCA_CURRENCIES = {\n PES: \"PES\",\n DOL: \"DOL\",\n} as const;\n\n/** Legal assertions supported by the invoice facade; never inferred from Padrón. */\nexport type IssuerCondition =\n | \"responsable_inscripto\"\n | \"monotributo\"\n | \"exento\"\n | \"no_alcanzado\";\nexport type ReceiverCondition = IssuerCondition | \"consumidor_final\";\nexport type VoucherClass = \"A\" | \"B\" | \"C\";\n\nexport const ARCA_RECEIVER_CONDITION_IDS = {\n responsable_inscripto: ARCA_RECEIVER_VAT_CONDITIONS.RESPONSABLE_INSCRIPTO,\n monotributo: ARCA_RECEIVER_VAT_CONDITIONS.MONOTRIBUTISTA,\n exento: ARCA_RECEIVER_VAT_CONDITIONS.EXENTO,\n consumidor_final: ARCA_RECEIVER_VAT_CONDITIONS.CONSUMIDOR_FINAL,\n no_alcanzado: ARCA_RECEIVER_VAT_CONDITIONS.IVA_NO_ALCANZADO,\n} as const satisfies Record<ReceiverCondition, number>;\n\nexport const ARCA_ISSUER_CONDITION_IDS = {\n responsable_inscripto: 1,\n monotributo: 6,\n exento: 4,\n no_alcanzado: 15,\n} as const satisfies Record<IssuerCondition, number>;\n\n// RG 5866/2026, art. 1(f), effective 2026-07-01 (art. 4).\n// https://www.argentina.gob.ar/normativa/nacional/norma-427092/texto\nexport const ARCA_FINAL_CONSUMER_IDENTIFICATION_THRESHOLD_MINOR_UNITS =\n 1_000_000_000n;\n\n// WSFE v4.7, physical PDF p. 203, validations 10243/10246; issuer asserted first.\n// ARCA checks actual issuer eligibility independently at authorization.\nexport const ARCA_INVOICE_CLASS_BY_ISSUER = {\n responsable_inscripto: {\n responsable_inscripto: \"A\",\n monotributo: \"A\",\n exento: \"B\",\n consumidor_final: \"B\",\n no_alcanzado: \"B\",\n },\n monotributo: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n exento: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n no_alcanzado: {\n responsable_inscripto: \"C\",\n monotributo: \"C\",\n exento: \"C\",\n consumidor_final: \"C\",\n no_alcanzado: \"C\",\n },\n} as const satisfies Record<\n IssuerCondition,\n Record<ReceiverCondition, VoucherClass>\n>;\n"],"mappings":";AACO,IAAM,qBAAqB;AAAA,EAChC,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,eAAe;AAAA,EACf,gBAAgB;AAClB;AAGO,IAAM,sBAAsB;AAAA,EACjC,MAAM;AAAA,EACN,KAAK;AAAA,EACL,kBAAkB;AACpB;AAMO,IAAM,+BAA+B;AAAA,EAC1C,uBAAuB;AAAA,EACvB,QAAQ;AAAA,EACR,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,kBAAkB;AACpB;AAGO,IAAM,qBAAqB;AAAA,EAChC,WAAW;AAAA,EACX,WAAW;AAAA,EACX,uBAAuB;AACzB;AAGO,IAAM,iBAAiB;AAAA,EAC5B,OAAO;AAAA,EACP,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AACX;AAGO,IAAM,iBAAiB;AAAA,EAC5B,KAAK;AAAA,EACL,KAAK;AACP;AAGO,IAAM,oBAAoB;AAAA,EAC/B,KAAK;AAAA,EACL,KAAK;AACP;AAMO,IAAM,kBAAkB;AAAA,EAC7B,KAAK;AAAA,EACL,KAAK;AACP;AAWO,IAAM,8BAA8B;AAAA,EACzC,uBAAuB,6BAA6B;AAAA,EACpD,aAAa,6BAA6B;AAAA,EAC1C,QAAQ,6BAA6B;AAAA,EACrC,kBAAkB,6BAA6B;AAAA,EAC/C,cAAc,6BAA6B;AAC7C;AAEO,IAAM,4BAA4B;AAAA,EACvC,uBAAuB;AAAA,EACvB,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,cAAc;AAChB;AAIO,IAAM,2DACX;AAIK,IAAM,+BAA+B;AAAA,EAC1C,uBAAuB;AAAA,IACrB,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,IACX,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,QAAQ;AAAA,IACN,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AAAA,EACA,cAAc;AAAA,IACZ,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,cAAc;AAAA,EAChB;AACF;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ArcaSoapFaultError
3
- } from "./chunk-MBWOFO67.mjs";
3
+ } from "./chunk-ZOSNASXB.mjs";
4
4
 
5
5
  // src/services/padron.ts
6
6
  function createPadronService(options) {
@@ -103,4 +103,4 @@ async function executePadronOperation(options, service, operation, body) {
103
103
  export {
104
104
  createPadronService
105
105
  };
106
- //# sourceMappingURL=chunk-EDY3PNKJ.mjs.map
106
+ //# sourceMappingURL=chunk-7LEKQ4P7.mjs.map
@@ -2,21 +2,21 @@ import {
2
2
  ARCA_CURRENCY_IDS,
3
3
  ARCA_VAT_RATES,
4
4
  ARCA_VOUCHER_TYPES
5
- } from "./chunk-VVY2LZIZ.mjs";
5
+ } from "./chunk-76WU5BVI.mjs";
6
6
  import {
7
7
  classifyArcaAuthenticationError,
8
8
  classifyArcaAuthenticationIssues,
9
9
  createArcaAuthenticationErrorFromEvidence,
10
10
  createArcaAuthenticationEvidence,
11
11
  executeWithAuthenticationRecovery
12
- } from "./chunk-IOKZX6CA.mjs";
12
+ } from "./chunk-4QVFXT35.mjs";
13
13
  import {
14
14
  ArcaInputError,
15
15
  ArcaInvalidSoapResponseError,
16
16
  ArcaServiceError,
17
17
  ArcaSoapFaultError,
18
18
  ArcaTransportError
19
- } from "./chunk-MBWOFO67.mjs";
19
+ } from "./chunk-ZOSNASXB.mjs";
20
20
 
21
21
  // src/internal/decimal.ts
22
22
  var AMOUNT_SCALE = 100;
@@ -311,7 +311,7 @@ function createWsfeService(options) {
311
311
  forceRefresh
312
312
  });
313
313
  }
314
- function authorizeVoucherOutcome({
314
+ function issue({
315
315
  representedTaxId,
316
316
  data,
317
317
  voucherNumber,
@@ -460,7 +460,7 @@ function createWsfeService(options) {
460
460
  }
461
461
  );
462
462
  const errors = extractWsfeGlobalIssues(result, operation);
463
- if (errors.length > 0 && errors.every((issue) => issue.code === "602")) {
463
+ if (errors.length > 0 && errors.every((issue2) => issue2.code === "602")) {
464
464
  return {
465
465
  kind: "not_found",
466
466
  service: "wsfe",
@@ -490,7 +490,8 @@ function createWsfeService(options) {
490
490
  };
491
491
  }
492
492
  return {
493
- authorizeVoucherOutcome,
493
+ issue,
494
+ authorizeVoucherOutcome: issue,
494
495
  authorizeVoucher,
495
496
  async createNextVoucher({ representedTaxId, data, forceRefresh }) {
496
497
  const normalizedInput = normalizeWsfeVoucherInput(data);
@@ -1110,8 +1111,90 @@ function mapWsfeVoucherInfo(raw) {
1110
1111
  "caeExpiry",
1111
1112
  normalizeWsfeString(raw.FchVto ?? raw.CAEFchVto)
1112
1113
  );
1114
+ assignWsfeValue(
1115
+ voucher,
1116
+ "serviceStartDate",
1117
+ normalizeWsfeString(raw.FchServDesde)
1118
+ );
1119
+ assignWsfeValue(
1120
+ voucher,
1121
+ "serviceEndDate",
1122
+ normalizeWsfeString(raw.FchServHasta)
1123
+ );
1124
+ assignWsfeValue(
1125
+ voucher,
1126
+ "paymentDueDate",
1127
+ normalizeWsfeString(raw.FchVtoPago)
1128
+ );
1129
+ assignWsfeValue(
1130
+ voucher,
1131
+ "vatRates",
1132
+ mapWsfeLookupDetails(raw.Iva, "AlicIva", mapWsfeLookupVat)
1133
+ );
1134
+ assignWsfeValue(
1135
+ voucher,
1136
+ "taxes",
1137
+ mapWsfeLookupDetails(raw.Tributos, "Tributo", mapWsfeLookupTax)
1138
+ );
1139
+ assignWsfeValue(
1140
+ voucher,
1141
+ "associatedVouchers",
1142
+ mapWsfeLookupDetails(raw.CbtesAsoc, "CbteAsoc", (item) => {
1143
+ const type = normalizeWsfeNumber(item.Tipo);
1144
+ const salesPoint = normalizeWsfeNumber(item.PtoVta);
1145
+ const number = normalizeWsfeNumber(item.Nro);
1146
+ if (type === void 0 || salesPoint === void 0 || number === void 0) {
1147
+ return void 0;
1148
+ }
1149
+ return {
1150
+ type,
1151
+ salesPoint,
1152
+ number,
1153
+ ...normalizeWsfeString(item.CbteFch) ? { voucherDate: normalizeWsfeString(item.CbteFch) } : {}
1154
+ };
1155
+ })
1156
+ );
1113
1157
  return voucher;
1114
1158
  }
1159
+ function mapWsfeLookupDetails(container, key, map) {
1160
+ const record = toWsfeRecord(container);
1161
+ if (!record || record[key] === void 0) {
1162
+ return void 0;
1163
+ }
1164
+ const rows = Array.isArray(record[key]) ? record[key] : [record[key]];
1165
+ const result = [];
1166
+ for (const value of rows) {
1167
+ const row = toWsfeRecord(value);
1168
+ const mapped = row ? map(row) : void 0;
1169
+ if (mapped === void 0) {
1170
+ return void 0;
1171
+ }
1172
+ result.push(mapped);
1173
+ }
1174
+ return result;
1175
+ }
1176
+ function mapWsfeLookupVat(row) {
1177
+ const id = normalizeWsfeNumber(row.Id);
1178
+ const baseAmount = normalizeWsfeNumber(row.BaseImp);
1179
+ const amount = normalizeWsfeNumber(row.Importe);
1180
+ if (id === void 0 || baseAmount === void 0 || amount === void 0) {
1181
+ return void 0;
1182
+ }
1183
+ return { id, baseAmount, amount };
1184
+ }
1185
+ function mapWsfeLookupTax(row) {
1186
+ const vat = mapWsfeLookupVat(row);
1187
+ const rate = normalizeWsfeNumber(row.Alic);
1188
+ if (!vat || rate === void 0) {
1189
+ return void 0;
1190
+ }
1191
+ const description = normalizeWsfeString(row.Desc);
1192
+ return {
1193
+ ...vat,
1194
+ rate,
1195
+ ...description === void 0 ? {} : { description }
1196
+ };
1197
+ }
1115
1198
  function createWsfeAuth(representedTaxId, token, sign) {
1116
1199
  return {
1117
1200
  Token: token,
@@ -1418,15 +1501,141 @@ function getWsfeResultEntries(result, key) {
1418
1501
  );
1419
1502
  }
1420
1503
 
1421
- // src/services/wsfe-builders.ts
1422
- var VAT_RATE_IDS = {
1423
- 0: ARCA_VAT_RATES.IVA_0,
1424
- 2.5: ARCA_VAT_RATES.IVA_2_5,
1425
- 5: ARCA_VAT_RATES.IVA_5,
1426
- 10.5: ARCA_VAT_RATES.IVA_10_5,
1427
- 21: ARCA_VAT_RATES.IVA_21,
1428
- 27: ARCA_VAT_RATES.IVA_27
1504
+ // src/services/wsfe-amounts.ts
1505
+ var RATES = {
1506
+ 0: { id: ARCA_VAT_RATES.IVA_0, basisPoints: 0n },
1507
+ 2.5: { id: ARCA_VAT_RATES.IVA_2_5, basisPoints: 250n },
1508
+ 5: { id: ARCA_VAT_RATES.IVA_5, basisPoints: 500n },
1509
+ 10.5: { id: ARCA_VAT_RATES.IVA_10_5, basisPoints: 1050n },
1510
+ 21: { id: ARCA_VAT_RATES.IVA_21, basisPoints: 2100n },
1511
+ 27: { id: ARCA_VAT_RATES.IVA_27, basisPoints: 2700n }
1429
1512
  };
1513
+ function calculateWsfeAmounts(input) {
1514
+ if (!Array.isArray(input.items) || input.items.length === 0) {
1515
+ invalidItem("items", "a non-empty array of items");
1516
+ }
1517
+ const isVat = input.issuer === "responsable_inscripto";
1518
+ if (!(isVat || ["monotributo", "exento", "no_alcanzado"].includes(input.issuer))) {
1519
+ invalidItem("issuer", "a supported issuer condition");
1520
+ }
1521
+ const totals = collectItems(input.items, isVat);
1522
+ let net = totals.net;
1523
+ let vat = 0n;
1524
+ const { exempt, untaxed, groups } = totals;
1525
+ const vatRates = [];
1526
+ for (const [rate, group] of groups) {
1527
+ const { id, basisPoints } = RATES[rate];
1528
+ const netFromGross = roundHalfEvenRatio(
1529
+ group.gross * 10000n,
1530
+ 10000n + basisPoints
1531
+ );
1532
+ const base = group.net + netFromGross;
1533
+ const tax = roundHalfEvenRatio(group.net * basisPoints, 10000n) + group.gross - netFromGross;
1534
+ if (base === 0n) {
1535
+ continue;
1536
+ }
1537
+ net += base;
1538
+ vat += tax;
1539
+ vatRates.push({
1540
+ id,
1541
+ baseAmount: arcaMinorUnitsToNumber(base, "netAmount"),
1542
+ amount: arcaMinorUnitsToNumber(tax, "vatAmount")
1543
+ });
1544
+ }
1545
+ const computed = net + vat + exempt + untaxed;
1546
+ arcaMinorUnitsToNumber(computed, "totalAmount");
1547
+ const sent = input.total === void 0 ? computed : assertArcaMinorUnits(input.total, "total");
1548
+ const adjustment = sent - computed;
1549
+ const allowance = BigInt(vatRates.length);
1550
+ if (adjustment < -allowance || adjustment > allowance || vat + adjustment < 0n) {
1551
+ throw new ArcaInputError(
1552
+ "total does not match the computed amount within the VAT allowance.",
1553
+ {
1554
+ code: "ARCA_INPUT_AMOUNT_MISMATCH",
1555
+ field: "total",
1556
+ expected: `${computed} minor units (at most ${allowance} minor units of VAT adjustment, with non-negative VAT)`
1557
+ }
1558
+ );
1559
+ }
1560
+ return {
1561
+ data: {
1562
+ totalAmount: arcaMinorUnitsToNumber(sent, "totalAmount"),
1563
+ netAmount: arcaMinorUnitsToNumber(net, "netAmount"),
1564
+ vatAmount: arcaMinorUnitsToNumber(vat + adjustment, "vatAmount"),
1565
+ nonTaxableAmount: arcaMinorUnitsToNumber(untaxed, "nonTaxableAmount"),
1566
+ exemptAmount: arcaMinorUnitsToNumber(exempt, "exemptAmount"),
1567
+ taxAmount: 0,
1568
+ ...isVat ? { vatRates } : {}
1569
+ },
1570
+ amounts: {
1571
+ computedTotal: Number(computed),
1572
+ sentTotal: Number(sent),
1573
+ vatAdjustment: Number(adjustment)
1574
+ }
1575
+ };
1576
+ }
1577
+ function collectItems(items, isVat) {
1578
+ let net = 0n;
1579
+ let exempt = 0n;
1580
+ let untaxed = 0n;
1581
+ const groups = /* @__PURE__ */ new Map();
1582
+ for (const [index, item] of items.entries()) {
1583
+ const path = `items[${index}]`;
1584
+ if (item === null || typeof item !== "object" || Array.isArray(item)) {
1585
+ invalidItem(path, "an item object");
1586
+ }
1587
+ if (!isVat) {
1588
+ net += classCAmount(item, path);
1589
+ continue;
1590
+ }
1591
+ const { amount, field, rate } = vatItemAmount(item, path);
1592
+ if (rate === "exempt") {
1593
+ exempt += amount;
1594
+ continue;
1595
+ }
1596
+ if (rate === "untaxed") {
1597
+ untaxed += amount;
1598
+ continue;
1599
+ }
1600
+ const group = groups.get(rate) ?? { net: 0n, gross: 0n };
1601
+ group[field] += amount;
1602
+ groups.set(rate, group);
1603
+ }
1604
+ return { net, exempt, untaxed, groups };
1605
+ }
1606
+ function classCAmount(item, path) {
1607
+ if ("vat" in item || "net" in item || "gross" in item) {
1608
+ invalidItem("items", "amount items for a non-RI issuer");
1609
+ }
1610
+ return assertArcaMinorUnits(item.amount, `${path}.amount`);
1611
+ }
1612
+ function vatItemAmount(item, path) {
1613
+ if ("amount" in item || "net" in item === "gross" in item) {
1614
+ invalidItem(
1615
+ "items",
1616
+ "exactly one of net or gross, and vat, for an RI issuer"
1617
+ );
1618
+ }
1619
+ const field = "net" in item ? "net" : "gross";
1620
+ const amount = assertArcaMinorUnits(
1621
+ item[field],
1622
+ `${path}.${field}`
1623
+ );
1624
+ const rate = item.vat;
1625
+ if (rate !== "exempt" && rate !== "untaxed" && (typeof rate !== "number" || !Object.hasOwn(RATES, rate))) {
1626
+ invalidItem(`${path}.vat`, "0, 2.5, 5, 10.5, 21, 27, exempt, or untaxed");
1627
+ }
1628
+ return { amount, field, rate };
1629
+ }
1630
+ function invalidItem(field, expected) {
1631
+ throw new ArcaInputError(`${field} must be ${expected}.`, {
1632
+ code: "ARCA_INPUT_INVALID_VALUE",
1633
+ field,
1634
+ expected
1635
+ });
1636
+ }
1637
+
1638
+ // src/services/wsfe-builders.ts
1430
1639
  function buildFacturaB(input) {
1431
1640
  const taxableMinorUnits = assertArcaMinorUnits(
1432
1641
  input.taxableAmount,
@@ -1447,15 +1656,6 @@ function buildFacturaB(input) {
1447
1656
  input.vatRate,
1448
1657
  "vatRate"
1449
1658
  );
1450
- const totalMinorUnits = taxableMinorUnits + vatMinorUnits;
1451
- const vatRateId = VAT_RATE_IDS[input.vatRate];
1452
- if (vatRateId === void 0) {
1453
- throw new ArcaInputError("vatRate is not a supported VAT rate.", {
1454
- code: "ARCA_INPUT_INVALID_VALUE",
1455
- field: "vatRate",
1456
- expected: "one of 0, 2.5, 5, 10.5, 21, or 27"
1457
- });
1458
- }
1459
1659
  if (input.vatRate !== 0 && vatMinorUnits === 0n) {
1460
1660
  throw new ArcaInputError(
1461
1661
  "taxableAmount is too small to produce VAT at the selected positive vatRate.",
@@ -1466,39 +1666,30 @@ function buildFacturaB(input) {
1466
1666
  }
1467
1667
  );
1468
1668
  }
1469
- const vatRates = [
1470
- Object.freeze({
1471
- id: vatRateId,
1472
- baseAmount: arcaMinorUnitsToNumber(taxableMinorUnits, "taxableAmount"),
1473
- amount: arcaMinorUnitsToNumber(vatMinorUnits, "vatAmount")
1474
- })
1475
- ];
1476
- Object.freeze(vatRates);
1669
+ const { data } = calculateWsfeAmounts({
1670
+ issuer: "responsable_inscripto",
1671
+ items: [{ net: input.taxableAmount, vat: input.vatRate }]
1672
+ });
1673
+ for (const rate of data.vatRates ?? []) {
1674
+ Object.freeze(rate);
1675
+ }
1676
+ Object.freeze(data.vatRates);
1477
1677
  return Object.freeze({
1478
1678
  ...buildCommonExactInput(input),
1479
1679
  voucherType: ARCA_VOUCHER_TYPES.FACTURA_B,
1480
- totalAmount: arcaMinorUnitsToNumber(totalMinorUnits, "totalAmount"),
1481
- nonTaxableAmount: 0,
1482
- netAmount: arcaMinorUnitsToNumber(taxableMinorUnits, "taxableAmount"),
1483
- exemptAmount: 0,
1484
- taxAmount: 0,
1485
- vatAmount: arcaMinorUnitsToNumber(vatMinorUnits, "vatAmount"),
1486
- vatRates
1680
+ ...data
1487
1681
  });
1488
1682
  }
1489
1683
  function buildFacturaC(input) {
1490
- const amountMinorUnits = assertArcaMinorUnits(input.amount, "amount");
1491
- const amount = arcaMinorUnitsToNumber(amountMinorUnits, "amount");
1684
+ assertArcaMinorUnits(input.amount, "amount");
1685
+ const { data } = calculateWsfeAmounts({
1686
+ issuer: "monotributo",
1687
+ items: [{ amount: input.amount }]
1688
+ });
1492
1689
  return Object.freeze({
1493
1690
  ...buildCommonExactInput(input),
1494
1691
  voucherType: ARCA_VOUCHER_TYPES.FACTURA_C,
1495
- totalAmount: amount,
1496
- nonTaxableAmount: 0,
1497
- // ARCA defines ImpNeto as the subtotal for class C vouchers.
1498
- netAmount: amount,
1499
- exemptAmount: 0,
1500
- taxAmount: 0,
1501
- vatAmount: 0
1692
+ ...data
1502
1693
  });
1503
1694
  }
1504
1695
  function buildCommonExactInput(input) {
@@ -1595,8 +1786,13 @@ function normalizeBuilderCurrency(input) {
1595
1786
  }
1596
1787
 
1597
1788
  export {
1789
+ normalizeArcaAmountToMinorUnits,
1790
+ serializeArcaExchangeRate,
1598
1791
  createWsfeService,
1792
+ normalizeWsfeVoucherInput,
1793
+ normalizeWsfeDateInput,
1794
+ calculateWsfeAmounts,
1599
1795
  buildFacturaB,
1600
1796
  buildFacturaC
1601
1797
  };
1602
- //# sourceMappingURL=chunk-OHHXHYLV.mjs.map
1798
+ //# sourceMappingURL=chunk-RCM4NAAG.mjs.map