facturas 0.9.0 → 0.11.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 (38) hide show
  1. package/README.md +95 -786
  2. package/bin/facturas.mjs +4 -0
  3. package/dist/{chunk-RCM4NAAG.mjs → chunk-5KCTRQJX.mjs} +83 -284
  4. package/dist/chunk-5KCTRQJX.mjs.map +1 -0
  5. package/dist/{chunk-XNBD5NVL.mjs → chunk-ALH5IPSY.mjs} +2 -57
  6. package/dist/chunk-ALH5IPSY.mjs.map +1 -0
  7. package/dist/{chunk-76WU5BVI.mjs → chunk-GX5ERXT6.mjs} +1 -1
  8. package/dist/chunk-GX5ERXT6.mjs.map +1 -0
  9. package/dist/chunk-LOWV7IF6.mjs +3758 -0
  10. package/dist/chunk-LOWV7IF6.mjs.map +1 -0
  11. package/dist/chunk-LR4M2AMG.mjs +169 -0
  12. package/dist/chunk-LR4M2AMG.mjs.map +1 -0
  13. package/dist/{chunk-4QVFXT35.mjs → chunk-UDX6HLAU.mjs} +1 -17
  14. package/dist/{chunk-4QVFXT35.mjs.map → chunk-UDX6HLAU.mjs.map} +1 -1
  15. package/dist/cli.d.ts +49 -0
  16. package/dist/cli.mjs +2316 -0
  17. package/dist/cli.mjs.map +1 -0
  18. package/dist/client-BZxeScuK.d.ts +521 -0
  19. package/dist/constants.d.ts +1 -1
  20. package/dist/constants.mjs +1 -1
  21. package/dist/{wsfe-DF0jAE2k.d.ts → decimal-B0HtrMFY.d.ts} +9 -66
  22. package/dist/errors.d.ts +2 -2
  23. package/dist/{fiscal-evidence-DBzakqBE.d.ts → fiscal-evidence-B1Qe6XMg.d.ts} +2 -2
  24. package/dist/{index-CVGQyyYM.d.ts → index-D8LGFvxV.d.ts} +1 -1
  25. package/dist/index.d.ts +11 -235
  26. package/dist/index.mjs +21 -2315
  27. package/dist/index.mjs.map +1 -1
  28. package/dist/padron.d.ts +2 -2
  29. package/dist/{types-BiznC1-X.d.ts → types-r2nf55gh.d.ts} +1 -1
  30. package/dist/types.d.ts +1 -1
  31. package/dist/wsfe.d.ts +45 -4
  32. package/dist/wsfe.mjs +6 -4
  33. package/dist/wsmtxca.d.ts +4 -20
  34. package/dist/wsmtxca.mjs +2 -2
  35. package/package.json +5 -1
  36. package/dist/chunk-76WU5BVI.mjs.map +0 -1
  37. package/dist/chunk-RCM4NAAG.mjs.map +0 -1
  38. package/dist/chunk-XNBD5NVL.mjs.map +0 -1
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { main } from "../dist/cli.mjs";
3
+
4
+ await main(process.argv.slice(2));
@@ -1,15 +1,12 @@
1
1
  import {
2
- ARCA_CURRENCY_IDS,
3
- ARCA_VAT_RATES,
4
- ARCA_VOUCHER_TYPES
5
- } from "./chunk-76WU5BVI.mjs";
2
+ ARCA_VAT_RATES
3
+ } from "./chunk-GX5ERXT6.mjs";
6
4
  import {
7
5
  classifyArcaAuthenticationError,
8
6
  classifyArcaAuthenticationIssues,
9
- createArcaAuthenticationErrorFromEvidence,
10
7
  createArcaAuthenticationEvidence,
11
8
  executeWithAuthenticationRecovery
12
- } from "./chunk-4QVFXT35.mjs";
9
+ } from "./chunk-UDX6HLAU.mjs";
13
10
  import {
14
11
  ArcaInputError,
15
12
  ArcaInvalidSoapResponseError,
@@ -297,20 +294,6 @@ function createWsfeService(options) {
297
294
  });
298
295
  return getWsfeResultEntries(result, resultKey).map(mapWsfeCatalogEntry);
299
296
  }
300
- function authorizeVoucher({
301
- representedTaxId,
302
- data,
303
- voucherNumber,
304
- forceRefresh
305
- }) {
306
- const normalizedInput = normalizeWsfeVoucherInput(data);
307
- return authorizeNormalizedVoucher({
308
- representedTaxId,
309
- data: normalizedInput,
310
- voucherNumber,
311
- forceRefresh
312
- });
313
- }
314
297
  function issue({
315
298
  representedTaxId,
316
299
  data,
@@ -325,66 +308,6 @@ function createWsfeService(options) {
325
308
  forceRefresh
326
309
  }).then(({ outcome }) => outcome);
327
310
  }
328
- function authorizeNormalizedVoucher({
329
- representedTaxId,
330
- data: normalizedInput,
331
- voucherNumber,
332
- forceRefresh,
333
- allowAuthenticationRecovery
334
- }) {
335
- return executeWithAuthenticationRecovery({
336
- service: "wsfe",
337
- operation: "FECAESolicitar",
338
- forceRefresh,
339
- allowRetry: allowAuthenticationRecovery,
340
- execute: (attemptForceRefresh) => authorizeNormalizedVoucherOnce({
341
- representedTaxId,
342
- data: normalizedInput,
343
- voucherNumber,
344
- forceRefresh: attemptForceRefresh
345
- })
346
- });
347
- }
348
- async function authorizeNormalizedVoucherOnce({
349
- representedTaxId,
350
- data: normalizedInput,
351
- voucherNumber,
352
- forceRefresh
353
- }) {
354
- const execution = await executeWsfeAuthorization({
355
- representedTaxId,
356
- data: normalizedInput,
357
- voucherNumber,
358
- forceRefresh
359
- });
360
- if (execution.error) {
361
- throw execution.error;
362
- }
363
- if (execution.outcome.kind !== "authorized") {
364
- throw createWsfeOutcomeError(execution.outcome);
365
- }
366
- const { cae, caeExpiry, raw } = execution.outcome;
367
- if (!(caeExpiry && raw)) {
368
- throw new ArcaServiceError("WSFE did not return CAE authorization data", {
369
- service: "wsfe",
370
- operation: "FECAESolicitar",
371
- result: execution.outcome.result,
372
- resultLevel: execution.outcome.resultLevel,
373
- results: execution.outcome.results,
374
- cae,
375
- issues: [
376
- ...execution.outcome.errors,
377
- ...execution.outcome.observations
378
- ]
379
- });
380
- }
381
- return {
382
- cae,
383
- caeExpiry,
384
- voucherNumber,
385
- raw
386
- };
387
- }
388
311
  async function executeWsfeAuthorization({
389
312
  representedTaxId,
390
313
  data: normalizedInput,
@@ -491,35 +414,30 @@ function createWsfeService(options) {
491
414
  }
492
415
  return {
493
416
  issue,
494
- authorizeVoucherOutcome: issue,
495
- authorizeVoucher,
496
- async createNextVoucher({ representedTaxId, data, forceRefresh }) {
497
- const normalizedInput = normalizeWsfeVoucherInput(data);
498
- const voucherNumber = await getNextVoucherNumber({
499
- representedTaxId,
500
- salesPoint: normalizedInput.salesPoint,
501
- voucherType: normalizedInput.voucherType,
502
- forceRefresh
503
- });
504
- return authorizeNormalizedVoucher({
505
- representedTaxId,
506
- data: normalizedInput,
507
- voucherNumber,
508
- allowAuthenticationRecovery: forceRefresh !== true
509
- });
510
- },
511
417
  getNextVoucherNumber,
512
418
  getLastVoucher(input) {
513
419
  return getNextVoucherNumber(input);
514
420
  },
515
421
  async getSalesPoints({ representedTaxId, forceRefresh }) {
516
- const result = await executeWsfeAuthenticatedOperation(
517
- "FEParamGetPtosVenta",
518
- {
519
- representedTaxId,
520
- forceRefresh
422
+ const operation = "FEParamGetPtosVenta";
423
+ const result = await executeWithAuthenticationRecovery({
424
+ service: "wsfe",
425
+ operation,
426
+ forceRefresh,
427
+ async execute(attemptForceRefresh) {
428
+ const raw = await executeWsfeAuthenticatedRawOperation(
429
+ operation,
430
+ { representedTaxId, forceRefresh: attemptForceRefresh },
431
+ {}
432
+ );
433
+ const errors = extractWsfeGlobalIssues(raw, operation);
434
+ if (errors.length > 0 && errors.every((issue2) => issue2.code === "602")) {
435
+ return {};
436
+ }
437
+ throwForWsfeOperationErrors(operation, raw);
438
+ return raw;
521
439
  }
522
- );
440
+ });
523
441
  const rawPoints = result.ResultGet?.PtoVenta;
524
442
  if (!rawPoints) {
525
443
  return [];
@@ -925,7 +843,25 @@ function normalizeAndValidateWsfeAmounts(input) {
925
843
  };
926
844
  }
927
845
  function requiresWsfeVatBaseReconciliation(voucherType) {
928
- return ![2, 3, 7, 8, 11, 12, 13, 15, 52, 53].includes(voucherType);
846
+ return ![
847
+ 2,
848
+ 3,
849
+ 7,
850
+ 8,
851
+ 11,
852
+ 12,
853
+ 13,
854
+ 15,
855
+ 52,
856
+ 53,
857
+ 202,
858
+ 203,
859
+ 207,
860
+ 208,
861
+ 211,
862
+ 212,
863
+ 213
864
+ ].includes(voucherType);
929
865
  }
930
866
  function assertWsfeAmountMatch(actual, expectedAmount, field, expectedDescription, absoluteCentAllowance = 1) {
931
867
  if (!isWithinArcaTolerance(actual, expectedAmount, absoluteCentAllowance)) {
@@ -1150,10 +1086,42 @@ function mapWsfeVoucherInfo(raw) {
1150
1086
  type,
1151
1087
  salesPoint,
1152
1088
  number,
1089
+ ...normalizeWsfeString(item.Cuit) ? { taxId: normalizeWsfeString(item.Cuit) } : {},
1153
1090
  ...normalizeWsfeString(item.CbteFch) ? { voucherDate: normalizeWsfeString(item.CbteFch) } : {}
1154
1091
  };
1155
1092
  })
1156
1093
  );
1094
+ const period = toWsfeRecord(raw.PeriodoAsoc);
1095
+ if (period?.FchDesde && period.FchHasta) {
1096
+ voucher.associatedPeriod = {
1097
+ startDate: String(period.FchDesde),
1098
+ endDate: String(period.FchHasta)
1099
+ };
1100
+ }
1101
+ if (raw.CanMisMonExt === "S" || raw.CanMisMonExt === "N") {
1102
+ voucher.sameCurrencyForeignCancellation = raw.CanMisMonExt;
1103
+ }
1104
+ voucher.optionalFields = mapWsfeLookupDetails(
1105
+ raw.Opcionales,
1106
+ "Opcional",
1107
+ (item) => item.Id === void 0 || item.Valor === void 0 ? void 0 : { id: String(item.Id), value: String(item.Valor) }
1108
+ );
1109
+ voucher.buyers = mapWsfeLookupDetails(
1110
+ raw.Compradores,
1111
+ "Comprador",
1112
+ (item) => {
1113
+ const documentType = normalizeWsfeNumber(item.DocTipo), documentNumber = normalizeWsfeNumber(item.DocNro), percentage = normalizeWsfeNumber(item.Porcentaje);
1114
+ return documentType === void 0 || documentNumber === void 0 || percentage === void 0 ? void 0 : { documentType, documentNumber, percentage };
1115
+ }
1116
+ );
1117
+ voucher.activities = mapWsfeLookupDetails(
1118
+ raw.Actividades,
1119
+ "Actividad",
1120
+ (item) => {
1121
+ const id = normalizeWsfeNumber(item.Id);
1122
+ return id === void 0 ? void 0 : { id };
1123
+ }
1124
+ );
1157
1125
  return voucher;
1158
1126
  }
1159
1127
  function mapWsfeLookupDetails(container, key, map) {
@@ -1377,27 +1345,6 @@ function getArcaIndeterminateReason(error) {
1377
1345
  }
1378
1346
  return "unexpected_error";
1379
1347
  }
1380
- function createWsfeOutcomeError(outcome) {
1381
- if (outcome.kind === "indeterminate" && outcome.authentication) {
1382
- return createArcaAuthenticationErrorFromEvidence(outcome.authentication, {
1383
- service: "wsfe",
1384
- operation: outcome.operation
1385
- });
1386
- }
1387
- const issues = [...outcome.errors, ...outcome.observations];
1388
- const firstIssue = issues[0];
1389
- const message = firstIssue ? formatWsfeIssue(firstIssue) : outcome.kind === "rejected" ? "WSFE rejected the voucher authorization" : outcome.result === "A" ? "WSFE did not return CAE authorization data" : "WSFE did not return conclusive voucher authorization data";
1390
- return new ArcaServiceError(message, {
1391
- service: "wsfe",
1392
- operation: outcome.operation,
1393
- ...firstIssue?.code === void 0 ? {} : { serviceCode: firstIssue.code },
1394
- ...outcome.result === void 0 ? {} : { result: outcome.result },
1395
- ...outcome.resultLevel === void 0 ? {} : { resultLevel: outcome.resultLevel },
1396
- results: outcome.results,
1397
- ...outcome.kind === "indeterminate" && outcome.cae ? { cae: outcome.cae } : {},
1398
- issues
1399
- });
1400
- }
1401
1348
  function createWsfeServiceError(operation, issues) {
1402
1349
  const authenticationError = classifyArcaAuthenticationIssues(issues, {
1403
1350
  service: "wsfe",
@@ -1514,9 +1461,9 @@ function calculateWsfeAmounts(input) {
1514
1461
  if (!Array.isArray(input.items) || input.items.length === 0) {
1515
1462
  invalidItem("items", "a non-empty array of items");
1516
1463
  }
1517
- const isVat = input.issuer === "responsable_inscripto";
1518
- if (!(isVat || ["monotributo", "exento", "no_alcanzado"].includes(input.issuer))) {
1519
- invalidItem("issuer", "a supported issuer condition");
1464
+ const isVat = input.voucherClass === "A" || input.voucherClass === "B";
1465
+ if (!(isVat || input.voucherClass === "C")) {
1466
+ invalidItem("voucherClass", "A, B or C");
1520
1467
  }
1521
1468
  const totals = collectItems(input.items, isVat);
1522
1469
  let net = totals.net;
@@ -1605,7 +1552,7 @@ function collectItems(items, isVat) {
1605
1552
  }
1606
1553
  function classCAmount(item, path) {
1607
1554
  if ("vat" in item || "net" in item || "gross" in item) {
1608
- invalidItem("items", "amount items for a non-RI issuer");
1555
+ invalidItem("items", "amount items for a class C voucher");
1609
1556
  }
1610
1557
  return assertArcaMinorUnits(item.amount, `${path}.amount`);
1611
1558
  }
@@ -1613,7 +1560,7 @@ function vatItemAmount(item, path) {
1613
1560
  if ("amount" in item || "net" in item === "gross" in item) {
1614
1561
  invalidItem(
1615
1562
  "items",
1616
- "exactly one of net or gross, and vat, for an RI issuer"
1563
+ "exactly one of net or gross, and vat, for a class A or B voucher"
1617
1564
  );
1618
1565
  }
1619
1566
  const field = "net" in item ? "net" : "gross";
@@ -1635,164 +1582,16 @@ function invalidItem(field, expected) {
1635
1582
  });
1636
1583
  }
1637
1584
 
1638
- // src/services/wsfe-builders.ts
1639
- function buildFacturaB(input) {
1640
- const taxableMinorUnits = assertArcaMinorUnits(
1641
- input.taxableAmount,
1642
- "taxableAmount"
1643
- );
1644
- if (taxableMinorUnits === 0n) {
1645
- throw new ArcaInputError(
1646
- "taxableAmount must be greater than zero for Factura B.",
1647
- {
1648
- code: "ARCA_INPUT_INVALID_AMOUNT",
1649
- field: "taxableAmount",
1650
- expected: "a positive safe integer in currency minor units"
1651
- }
1652
- );
1653
- }
1654
- const vatMinorUnits = calculateVatMinorUnits(
1655
- taxableMinorUnits,
1656
- input.vatRate,
1657
- "vatRate"
1658
- );
1659
- if (input.vatRate !== 0 && vatMinorUnits === 0n) {
1660
- throw new ArcaInputError(
1661
- "taxableAmount is too small to produce VAT at the selected positive vatRate.",
1662
- {
1663
- code: "ARCA_INPUT_INVALID_AMOUNT",
1664
- field: "taxableAmount",
1665
- expected: "an amount that rounds to at least one currency minor unit of VAT for a positive vatRate"
1666
- }
1667
- );
1668
- }
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);
1677
- return Object.freeze({
1678
- ...buildCommonExactInput(input),
1679
- voucherType: ARCA_VOUCHER_TYPES.FACTURA_B,
1680
- ...data
1681
- });
1682
- }
1683
- function buildFacturaC(input) {
1684
- assertArcaMinorUnits(input.amount, "amount");
1685
- const { data } = calculateWsfeAmounts({
1686
- issuer: "monotributo",
1687
- items: [{ amount: input.amount }]
1688
- });
1689
- return Object.freeze({
1690
- ...buildCommonExactInput(input),
1691
- voucherType: ARCA_VOUCHER_TYPES.FACTURA_C,
1692
- ...data
1693
- });
1694
- }
1695
- function buildCommonExactInput(input) {
1696
- return {
1697
- salesPoint: input.salesPoint,
1698
- concept: input.concept,
1699
- documentType: input.documentType,
1700
- documentNumber: input.documentNumber,
1701
- receiverVatConditionId: input.receiverVatConditionId,
1702
- voucherDate: input.voucherDate,
1703
- ...normalizeBuilderCurrency(input),
1704
- ...input.serviceStartDate === void 0 ? {} : { serviceStartDate: input.serviceStartDate },
1705
- ...input.serviceEndDate === void 0 ? {} : { serviceEndDate: input.serviceEndDate },
1706
- ...input.paymentDueDate === void 0 ? {} : { paymentDueDate: input.paymentDueDate }
1707
- };
1708
- }
1709
- function normalizeBuilderCurrency(input) {
1710
- const unsafeInput = input;
1711
- const currency = unsafeInput.currency ?? "ARS";
1712
- if (unsafeInput.sameCurrencyForeignCancellation !== void 0 && typeof unsafeInput.sameCurrencyForeignCancellation !== "boolean") {
1713
- throw new ArcaInputError(
1714
- "sameCurrencyForeignCancellation must be a boolean when provided.",
1715
- {
1716
- code: "ARCA_INPUT_INVALID_VALUE",
1717
- field: "sameCurrencyForeignCancellation",
1718
- expected: "true, false, or omitted"
1719
- }
1720
- );
1721
- }
1722
- if (currency === "ARS") {
1723
- if (unsafeInput.exchangeRate !== void 0) {
1724
- throw new ArcaInputError(
1725
- "exchangeRate must be omitted when currency is ARS.",
1726
- {
1727
- code: "ARCA_INPUT_INVALID_EXCHANGE_RATE",
1728
- field: "exchangeRate",
1729
- expected: "omitted when currency is ARS"
1730
- }
1731
- );
1732
- }
1733
- if (unsafeInput.sameCurrencyForeignCancellation !== void 0) {
1734
- throw new ArcaInputError(
1735
- "sameCurrencyForeignCancellation applies only when currency is USD.",
1736
- {
1737
- code: "ARCA_INPUT_INVALID_VALUE",
1738
- field: "sameCurrencyForeignCancellation",
1739
- expected: "omitted when currency is ARS"
1740
- }
1741
- );
1742
- }
1743
- return {
1744
- currencyId: ARCA_CURRENCY_IDS.ARS,
1745
- exchangeRate: "1"
1746
- };
1747
- }
1748
- if (currency !== "USD") {
1749
- throw new ArcaInputError("currency is not supported by this builder.", {
1750
- code: "ARCA_INPUT_INVALID_VALUE",
1751
- field: "currency",
1752
- expected: "ARS or USD"
1753
- });
1754
- }
1755
- if (unsafeInput.sameCurrencyForeignCancellation === true) {
1756
- if (unsafeInput.exchangeRate !== void 0) {
1757
- throw new ArcaInputError(
1758
- "exchangeRate must be omitted for same-currency foreign cancellation.",
1759
- {
1760
- code: "ARCA_INPUT_INVALID_EXCHANGE_RATE",
1761
- field: "exchangeRate",
1762
- expected: "omitted when sameCurrencyForeignCancellation is true"
1763
- }
1764
- );
1765
- }
1766
- return {
1767
- currencyId: ARCA_CURRENCY_IDS.USD,
1768
- sameCurrencyForeignCancellation: "S"
1769
- };
1770
- }
1771
- if (typeof unsafeInput.exchangeRate !== "string") {
1772
- throw new ArcaInputError("exchangeRate is required for USD invoices.", {
1773
- code: "ARCA_INPUT_MISSING_FIELD",
1774
- field: "exchangeRate",
1775
- expected: "a decimal string unless sameCurrencyForeignCancellation is true"
1776
- });
1777
- }
1778
- return {
1779
- currencyId: ARCA_CURRENCY_IDS.USD,
1780
- exchangeRate: serializeArcaExchangeRate(
1781
- unsafeInput.exchangeRate,
1782
- "exchangeRate"
1783
- ),
1784
- ...unsafeInput.sameCurrencyForeignCancellation === false ? { sameCurrencyForeignCancellation: "N" } : {}
1785
- };
1786
- }
1787
-
1788
1585
  export {
1789
1586
  normalizeArcaAmountToMinorUnits,
1790
1587
  serializeArcaExchangeRate,
1588
+ assertArcaMinorUnits,
1589
+ arcaMinorUnitsToNumber,
1590
+ calculateVatMinorUnits,
1591
+ isWithinArcaTolerance,
1791
1592
  createWsfeService,
1792
1593
  normalizeWsfeVoucherInput,
1793
1594
  normalizeWsfeDateInput,
1794
- calculateWsfeAmounts,
1795
- buildFacturaB,
1796
- buildFacturaC
1595
+ calculateWsfeAmounts
1797
1596
  };
1798
- //# sourceMappingURL=chunk-RCM4NAAG.mjs.map
1597
+ //# sourceMappingURL=chunk-5KCTRQJX.mjs.map