facturas 0.5.2 → 0.6.1

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/dist/wsfe.mjs CHANGED
@@ -15,20 +15,78 @@ var ArcaInputError = class extends ArcaError {
15
15
  this.detail = options?.detail;
16
16
  }
17
17
  };
18
+ var ArcaTransportError = class extends ArcaError {
19
+ name = "ArcaTransportError";
20
+ statusCode;
21
+ contentType;
22
+ responseBody;
23
+ constructor(message, options) {
24
+ super(message, "ARCA_TRANSPORT_ERROR", options);
25
+ this.statusCode = options?.statusCode;
26
+ this.contentType = options?.contentType;
27
+ this.responseBody = options?.responseBody;
28
+ }
29
+ };
30
+ var ArcaSoapFaultError = class extends ArcaError {
31
+ name = "ArcaSoapFaultError";
32
+ faultCode;
33
+ detail;
34
+ constructor(message, options) {
35
+ super(message, "ARCA_SOAP_FAULT", options);
36
+ this.faultCode = options?.faultCode;
37
+ this.detail = options?.detail;
38
+ }
39
+ };
40
+ var ArcaInvalidSoapResponseError = class extends ArcaError {
41
+ name = "ArcaInvalidSoapResponseError";
42
+ service;
43
+ operation;
44
+ endpointUrl;
45
+ statusCode;
46
+ contentType;
47
+ responseBodyLength;
48
+ responseBodyPreview;
49
+ parsedDetail;
50
+ constructor(message, options) {
51
+ super(message, "ARCA_INVALID_SOAP_RESPONSE", options);
52
+ this.service = options?.service;
53
+ this.operation = options?.operation;
54
+ this.endpointUrl = options?.endpointUrl;
55
+ this.statusCode = options?.statusCode;
56
+ this.contentType = options?.contentType;
57
+ this.responseBodyLength = options?.responseBodyLength;
58
+ this.responseBodyPreview = options?.responseBodyPreview;
59
+ this.parsedDetail = options?.parsedDetail;
60
+ }
61
+ };
18
62
  var ArcaServiceError = class extends ArcaError {
19
63
  name = "ArcaServiceError";
20
64
  serviceCode;
65
+ service;
66
+ operation;
67
+ result;
68
+ resultLevel;
69
+ results;
70
+ cae;
71
+ issues;
21
72
  detail;
22
73
  constructor(message, options) {
23
74
  super(message, "ARCA_SERVICE_ERROR", options);
24
75
  this.serviceCode = options?.serviceCode;
76
+ this.service = options?.service;
77
+ this.operation = options?.operation;
78
+ this.result = options?.result;
79
+ this.resultLevel = options?.resultLevel;
80
+ this.results = options?.results;
81
+ this.cae = options?.cae;
82
+ this.issues = options?.issues;
25
83
  this.detail = options?.detail;
26
84
  }
27
85
  };
28
86
 
29
87
  // src/services/wsfe.ts
30
88
  function createWsfeService(options) {
31
- async function executeWsfeAuthenticatedOperation(operation, input, body = {}) {
89
+ async function executeWsfeAuthenticatedRawOperation(operation, input, body = {}, retries) {
32
90
  const auth = await options.auth.login("wsfe", {
33
91
  representedTaxId: input.representedTaxId,
34
92
  forceRefresh: input.forceRefresh
@@ -36,6 +94,7 @@ function createWsfeService(options) {
36
94
  const response = await options.soap.execute({
37
95
  service: "wsfe",
38
96
  operation,
97
+ ...retries === void 0 ? {} : { retries },
39
98
  body: {
40
99
  Auth: createWsfeAuth(
41
100
  input.representedTaxId ?? options.config.taxId,
@@ -45,7 +104,16 @@ function createWsfeService(options) {
45
104
  ...body
46
105
  }
47
106
  });
48
- return unwrapWsfeOperationResult(operation, response.result);
107
+ return unwrapWsfeOperationEnvelope(operation, response.result);
108
+ }
109
+ async function executeWsfeAuthenticatedOperation(operation, input, body = {}) {
110
+ const result = await executeWsfeAuthenticatedRawOperation(
111
+ operation,
112
+ input,
113
+ body
114
+ );
115
+ throwForWsfeOperationErrors(operation, result);
116
+ return result;
49
117
  }
50
118
  async function executeWsfeOperation(operation, body = {}) {
51
119
  const response = await options.soap.execute({
@@ -53,7 +121,9 @@ function createWsfeService(options) {
53
121
  operation,
54
122
  body
55
123
  });
56
- return unwrapWsfeOperationResult(operation, response.result);
124
+ const result = unwrapWsfeOperationEnvelope(operation, response.result);
125
+ throwForWsfeOperationErrors(operation, result);
126
+ return result;
57
127
  }
58
128
  async function getNextVoucherNumber({
59
129
  representedTaxId,
@@ -95,55 +165,148 @@ function createWsfeService(options) {
95
165
  forceRefresh
96
166
  });
97
167
  }
168
+ function authorizeVoucherOutcome({
169
+ representedTaxId,
170
+ data,
171
+ voucherNumber,
172
+ forceRefresh
173
+ }) {
174
+ const normalizedInput = normalizeWsfeVoucherInput(data);
175
+ return executeWsfeAuthorization({
176
+ representedTaxId,
177
+ data: normalizedInput,
178
+ voucherNumber,
179
+ forceRefresh
180
+ }).then(({ outcome }) => outcome);
181
+ }
98
182
  async function authorizeNormalizedVoucher({
99
183
  representedTaxId,
100
184
  data: normalizedInput,
101
185
  voucherNumber,
102
186
  forceRefresh
103
187
  }) {
104
- const requestData = mapWsfeVoucherInput(normalizedInput, voucherNumber);
105
- const auth = await options.auth.login("wsfe", {
188
+ const execution = await executeWsfeAuthorization({
106
189
  representedTaxId,
190
+ data: normalizedInput,
191
+ voucherNumber,
107
192
  forceRefresh
108
193
  });
109
- const response = await options.soap.execute({
110
- service: "wsfe",
111
- operation: "FECAESolicitar",
112
- body: {
113
- Auth: createWsfeAuth(
114
- representedTaxId ?? options.config.taxId,
115
- auth.token,
116
- auth.sign
117
- ),
118
- FeCAEReq: {
119
- FeCabReq: {
120
- CantReg: 1,
121
- PtoVta: normalizedInput.salesPoint,
122
- CbteTipo: normalizedInput.voucherType
123
- },
124
- FeDetReq: {
125
- FECAEDetRequest: requestData
194
+ if (execution.error) {
195
+ throw execution.error;
196
+ }
197
+ if (execution.outcome.kind !== "authorized") {
198
+ throw createWsfeOutcomeError(execution.outcome);
199
+ }
200
+ const { cae, caeExpiry, raw } = execution.outcome;
201
+ if (!(caeExpiry && raw)) {
202
+ throw new ArcaServiceError("WSFE did not return CAE authorization data", {
203
+ service: "wsfe",
204
+ operation: "FECAESolicitar",
205
+ result: execution.outcome.result,
206
+ resultLevel: execution.outcome.resultLevel,
207
+ results: execution.outcome.results,
208
+ cae,
209
+ issues: [
210
+ ...execution.outcome.errors,
211
+ ...execution.outcome.observations
212
+ ],
213
+ detail: raw
214
+ });
215
+ }
216
+ return {
217
+ cae,
218
+ caeExpiry,
219
+ voucherNumber,
220
+ raw
221
+ };
222
+ }
223
+ async function executeWsfeAuthorization({
224
+ representedTaxId,
225
+ data: normalizedInput,
226
+ voucherNumber,
227
+ forceRefresh
228
+ }) {
229
+ const requestData = mapWsfeVoucherInput(normalizedInput, voucherNumber);
230
+ try {
231
+ const result = await executeWsfeAuthenticatedRawOperation(
232
+ "FECAESolicitar",
233
+ { representedTaxId, forceRefresh },
234
+ {
235
+ FeCAEReq: {
236
+ FeCabReq: {
237
+ CantReg: 1,
238
+ PtoVta: normalizedInput.salesPoint,
239
+ CbteTipo: normalizedInput.voucherType
240
+ },
241
+ FeDetReq: {
242
+ FECAEDetRequest: requestData
243
+ }
126
244
  }
245
+ },
246
+ 0
247
+ );
248
+ return {
249
+ outcome: classifyWsfeAuthorization(result, voucherNumber)
250
+ };
251
+ } catch (error) {
252
+ return {
253
+ outcome: createWsfeIndeterminateOutcome(error),
254
+ error
255
+ };
256
+ }
257
+ }
258
+ async function lookupVoucher({
259
+ representedTaxId,
260
+ number,
261
+ salesPoint,
262
+ voucherType,
263
+ forceRefresh
264
+ }) {
265
+ const operation = "FECompConsultar";
266
+ const result = await executeWsfeAuthenticatedRawOperation(
267
+ operation,
268
+ { representedTaxId, forceRefresh },
269
+ {
270
+ FeCompConsReq: {
271
+ CbteNro: number,
272
+ PtoVta: salesPoint,
273
+ CbteTipo: voucherType
127
274
  }
128
275
  }
129
- });
130
- const result = unwrapWsfeOperationResult("FECAESolicitar", response.result);
131
- const detailResponse = normalizeWsfeDetailResponse(result);
132
- const cae = detailResponse.CAE;
133
- const caeExpiry = detailResponse.CAEFchVto;
134
- if (typeof cae !== "string" || typeof caeExpiry !== "string") {
135
- throw new ArcaServiceError("WSFE did not return CAE authorization data", {
276
+ );
277
+ const errors = extractWsfeGlobalIssues(result, operation);
278
+ if (errors.length > 0 && errors.every((issue) => issue.code === "602")) {
279
+ return {
280
+ kind: "not_found",
281
+ service: "wsfe",
282
+ operation,
283
+ errors,
284
+ observations: [],
285
+ raw: result
286
+ };
287
+ }
288
+ if (errors.length > 0) {
289
+ throw createWsfeServiceError(operation, result, errors);
290
+ }
291
+ const raw = toWsfeRecord(result.ResultGet);
292
+ if (!raw) {
293
+ throw new ArcaServiceError("WSFE did not return the consulted voucher", {
294
+ service: "wsfe",
295
+ operation,
136
296
  detail: result
137
297
  });
138
298
  }
139
299
  return {
140
- cae,
141
- caeExpiry: String(caeExpiry),
142
- voucherNumber,
300
+ kind: "found",
301
+ service: "wsfe",
302
+ operation,
303
+ voucher: mapWsfeVoucherInfo(raw),
304
+ observations: [],
143
305
  raw: result
144
306
  };
145
307
  }
146
308
  return {
309
+ authorizeVoucherOutcome,
147
310
  authorizeVoucher,
148
311
  async createNextVoucher({ representedTaxId, data, forceRefresh }) {
149
312
  const normalizedInput = normalizeWsfeVoucherInput(data);
@@ -255,42 +418,14 @@ function createWsfeService(options) {
255
418
  const raw = result.ResultGet ?? {};
256
419
  return mapWsfeQuotation(raw);
257
420
  },
258
- async getVoucherInfo({
259
- representedTaxId,
260
- number,
261
- salesPoint,
262
- voucherType,
263
- forceRefresh
264
- }) {
265
- const result = await executeWsfeAuthenticatedOperation(
266
- "FECompConsultar",
267
- {
268
- representedTaxId,
269
- forceRefresh
270
- },
271
- {
272
- FeCompConsReq: {
273
- CbteNro: number,
274
- PtoVta: salesPoint,
275
- CbteTipo: voucherType
276
- }
277
- }
278
- );
279
- const raw = result.ResultGet ?? null;
280
- if (!raw) {
281
- return null;
282
- }
283
- return mapWsfeVoucherInfo(raw);
284
- }
421
+ async getVoucherInfo(input) {
422
+ const lookup = await lookupVoucher(input);
423
+ return lookup.kind === "found" ? lookup.voucher : null;
424
+ },
425
+ lookupVoucher
285
426
  };
286
427
  }
287
428
  function mapWsfeVoucherInput(input, voucherNumber) {
288
- const sendsSameForeignCurrencyCancellation = input.currencyId !== "PES" && input.sameCurrencyForeignCancellation === "S";
289
- if (input.exchangeRate === void 0 && !sendsSameForeignCurrencyCancellation) {
290
- throw new ArcaInputError(
291
- "exchangeRate is required unless sameCurrencyForeignCancellation is S for a foreign-currency voucher."
292
- );
293
- }
294
429
  const data = {
295
430
  Concepto: input.concept,
296
431
  DocTipo: input.documentType,
@@ -308,7 +443,7 @@ function mapWsfeVoucherInput(input, voucherNumber) {
308
443
  PtoVta: input.salesPoint,
309
444
  CbteTipo: input.voucherType
310
445
  };
311
- if (!sendsSameForeignCurrencyCancellation) {
446
+ if (input.exchangeRate !== void 0) {
312
447
  data.MonCotiz = input.exchangeRate;
313
448
  }
314
449
  if (input.receiverVatConditionId !== void 0) {
@@ -392,6 +527,7 @@ function mapWsfeVoucherInput(input, voucherNumber) {
392
527
  function normalizeWsfeVoucherInput(input) {
393
528
  const {
394
529
  voucherDate,
530
+ exchangeRate,
395
531
  serviceStartDate,
396
532
  serviceEndDate,
397
533
  paymentDueDate,
@@ -399,9 +535,11 @@ function normalizeWsfeVoucherInput(input) {
399
535
  associatedPeriod,
400
536
  ...rest
401
537
  } = input;
538
+ const normalizedExchangeRate = normalizeWsfeExchangeRate(input, exchangeRate);
402
539
  return {
403
540
  ...rest,
404
541
  voucherDate: normalizeWsfeDateInput(voucherDate, "voucherDate"),
542
+ ...normalizedExchangeRate === void 0 ? {} : { exchangeRate: normalizedExchangeRate },
405
543
  ...serviceStartDate === void 0 ? {} : {
406
544
  serviceStartDate: normalizeWsfeDateInput(
407
545
  serviceStartDate,
@@ -448,6 +586,30 @@ function normalizeWsfeVoucherInput(input) {
448
586
  }
449
587
  };
450
588
  }
589
+ function normalizeWsfeExchangeRate(input, exchangeRate) {
590
+ if (input.currencyId === "PES") {
591
+ if (exchangeRate !== void 0 && exchangeRate !== 1) {
592
+ throw new ArcaInputError(
593
+ "exchangeRate must be 1 when currencyId is PES."
594
+ );
595
+ }
596
+ return 1;
597
+ }
598
+ if (exchangeRate === void 0) {
599
+ if (input.sameCurrencyForeignCancellation === "S") {
600
+ return void 0;
601
+ }
602
+ throw new ArcaInputError(
603
+ "exchangeRate is required unless sameCurrencyForeignCancellation is S for a foreign-currency voucher."
604
+ );
605
+ }
606
+ if (!(Number.isFinite(exchangeRate) && exchangeRate > 0)) {
607
+ throw new ArcaInputError(
608
+ "exchangeRate must be a positive finite number for a foreign-currency voucher."
609
+ );
610
+ }
611
+ return exchangeRate;
612
+ }
451
613
  function normalizeWsfeDateInput(value, fieldName) {
452
614
  if (typeof value !== "string") {
453
615
  throw new ArcaInputError(
@@ -547,17 +709,45 @@ function mapWsfeQuotation(raw) {
547
709
  };
548
710
  }
549
711
  function mapWsfeVoucherInfo(raw) {
550
- return {
712
+ const voucher = {
551
713
  voucherNumber: Number(raw.CbteDesde ?? raw.CbteHasta ?? 0),
552
- ...raw.CbteFch === void 0 ? {} : { voucherDate: String(raw.CbteFch) },
553
- ...raw.PtoVta === void 0 ? {} : { salesPoint: Number(raw.PtoVta) },
554
- ...raw.CbteTipo === void 0 ? {} : { voucherType: Number(raw.CbteTipo) },
555
- ...raw.ImpTotal === void 0 ? {} : { totalAmount: Number(raw.ImpTotal) },
556
- ...raw.Resultado === void 0 ? {} : { result: String(raw.Resultado) },
557
- ...raw.CAE === void 0 ? {} : { cae: String(raw.CAE) },
558
- ...raw.CAEFchVto === void 0 ? {} : { caeExpiry: String(raw.CAEFchVto) },
559
714
  raw
560
715
  };
716
+ assignWsfeValue(voucher, "voucherDate", normalizeWsfeString(raw.CbteFch));
717
+ assignWsfeValue(voucher, "salesPoint", normalizeWsfeNumber(raw.PtoVta));
718
+ assignWsfeValue(voucher, "voucherType", normalizeWsfeNumber(raw.CbteTipo));
719
+ assignWsfeValue(voucher, "concept", normalizeWsfeNumber(raw.Concepto));
720
+ assignWsfeValue(voucher, "documentType", normalizeWsfeNumber(raw.DocTipo));
721
+ assignWsfeValue(voucher, "documentNumber", normalizeWsfeString(raw.DocNro));
722
+ assignWsfeValue(
723
+ voucher,
724
+ "receiverVatConditionId",
725
+ normalizeWsfeNumber(raw.CondicionIVAReceptorId)
726
+ );
727
+ assignWsfeValue(voucher, "totalAmount", normalizeWsfeNumber(raw.ImpTotal));
728
+ assignWsfeValue(
729
+ voucher,
730
+ "nonTaxableAmount",
731
+ normalizeWsfeNumber(raw.ImpTotConc)
732
+ );
733
+ assignWsfeValue(voucher, "netAmount", normalizeWsfeNumber(raw.ImpNeto));
734
+ assignWsfeValue(voucher, "exemptAmount", normalizeWsfeNumber(raw.ImpOpEx));
735
+ assignWsfeValue(voucher, "taxAmount", normalizeWsfeNumber(raw.ImpTrib));
736
+ assignWsfeValue(voucher, "vatAmount", normalizeWsfeNumber(raw.ImpIVA));
737
+ assignWsfeValue(voucher, "currencyId", normalizeWsfeString(raw.MonId));
738
+ assignWsfeValue(voucher, "exchangeRate", normalizeWsfeNumber(raw.MonCotiz));
739
+ assignWsfeValue(voucher, "result", normalizeWsfeString(raw.Resultado));
740
+ assignWsfeValue(
741
+ voucher,
742
+ "cae",
743
+ normalizeWsfeString(raw.CodAutorizacion ?? raw.CAE)
744
+ );
745
+ assignWsfeValue(
746
+ voucher,
747
+ "caeExpiry",
748
+ normalizeWsfeString(raw.FchVto ?? raw.CAEFchVto)
749
+ );
750
+ return voucher;
561
751
  }
562
752
  function createWsfeAuth(representedTaxId, token, sign) {
563
753
  return {
@@ -566,47 +756,16 @@ function createWsfeAuth(representedTaxId, token, sign) {
566
756
  Cuit: Number.parseInt(String(representedTaxId), 10)
567
757
  };
568
758
  }
569
- function unwrapWsfeOperationResult(operation, response) {
759
+ function unwrapWsfeOperationEnvelope(operation, response) {
570
760
  const operationResponse = response[`${operation}Response`];
571
761
  const result = operationResponse?.[`${operation}Result`] ?? response[`${operation}Result`] ?? response;
572
- if (operation === "FECAESolicitar") {
573
- const detailResponse = normalizeWsfeDetailResponse(result);
574
- const resultCode = detailResponse.Resultado;
575
- if (resultCode && resultCode !== "A") {
576
- const observationsContainer = detailResponse.Observaciones;
577
- const observations = normalizeWsfeErrors(observationsContainer?.Obs);
578
- if (observations.length > 0) {
579
- const firstObservation = observations[0];
580
- if (!firstObservation) {
581
- throw new ArcaServiceError(
582
- "WSFE returned an empty observation list",
583
- {
584
- detail: result
585
- }
586
- );
587
- }
588
- throw new ArcaServiceError(firstObservation.message, {
589
- serviceCode: firstObservation.code,
590
- detail: result
591
- });
592
- }
593
- }
594
- }
595
- const errorsContainer = result.Errors;
596
- const errors = normalizeWsfeErrors(errorsContainer?.Err);
762
+ return result;
763
+ }
764
+ function throwForWsfeOperationErrors(operation, result) {
765
+ const errors = extractWsfeGlobalIssues(result, operation);
597
766
  if (errors.length > 0) {
598
- const firstError = errors[0];
599
- if (!firstError) {
600
- throw new ArcaServiceError("WSFE returned an empty error list", {
601
- detail: result
602
- });
603
- }
604
- throw new ArcaServiceError(firstError.message, {
605
- serviceCode: firstError.code,
606
- detail: result
607
- });
767
+ throw createWsfeServiceError(operation, result, errors);
608
768
  }
609
- return result;
610
769
  }
611
770
  function normalizeWsfeDetailResponse(result) {
612
771
  const detailResponse = result.FeDetResp;
@@ -616,17 +775,248 @@ function normalizeWsfeDetailResponse(result) {
616
775
  }
617
776
  return rawDetail ?? {};
618
777
  }
619
- function normalizeWsfeErrors(rawErrors) {
778
+ function classifyWsfeAuthorization(result, voucherNumber) {
779
+ const operation = "FECAESolicitar";
780
+ const header = toWsfeRecord(result.FeCabResp) ?? {};
781
+ const detail = normalizeWsfeDetailResponse(result);
782
+ const headerResult = normalizeWsfeResult(header.Resultado);
783
+ const detailResult = normalizeWsfeResult(detail.Resultado);
784
+ const resultCode = detailResult ?? headerResult;
785
+ const resultLevel = getWsfeResultLevel(headerResult, detailResult);
786
+ const cae = normalizeWsfeString(detail.CAE);
787
+ const caeExpiry = normalizeWsfeString(detail.CAEFchVto);
788
+ const errors = extractWsfeGlobalIssues(result, operation, "header");
789
+ const observations = extractWsfeObservations(
790
+ detail,
791
+ detailResult === "R" ? "business" : "observation"
792
+ );
793
+ const hasInfrastructureError = errors.some(
794
+ (issue) => issue.category === "infrastructure"
795
+ );
796
+ const base = {
797
+ service: "wsfe",
798
+ operation,
799
+ results: createWsfeResults(headerResult, detailResult),
800
+ errors,
801
+ observations,
802
+ raw: result
803
+ };
804
+ const context = {
805
+ base,
806
+ headerResult,
807
+ detailResult,
808
+ resultCode,
809
+ resultLevel,
810
+ cae,
811
+ caeExpiry
812
+ };
813
+ if (hasContradictoryWsfeResults(context)) {
814
+ return createWsfeStructuredIndeterminate(context, "contradictory_response");
815
+ }
816
+ if (hasInfrastructureError) {
817
+ return createWsfeStructuredIndeterminate(context, "incomplete_response");
818
+ }
819
+ if (isAuthorizedWsfeContext(context)) {
820
+ return {
821
+ ...base,
822
+ kind: "authorized",
823
+ result: "A",
824
+ resultLevel: "detail",
825
+ cae: context.cae,
826
+ caeExpiry: context.caeExpiry,
827
+ voucherNumber
828
+ };
829
+ }
830
+ if (isRejectedWsfeDetailContext(context)) {
831
+ return {
832
+ ...base,
833
+ kind: "rejected",
834
+ result: "R",
835
+ resultLevel: "detail"
836
+ };
837
+ }
838
+ if (isRejectedWsfeHeaderContext(context)) {
839
+ return {
840
+ ...base,
841
+ kind: "rejected",
842
+ result: "R",
843
+ resultLevel: "header"
844
+ };
845
+ }
846
+ return createWsfeStructuredIndeterminate(
847
+ context,
848
+ hasWsfeCaeContradiction(context) ? "contradictory_response" : "incomplete_response"
849
+ );
850
+ }
851
+ function getWsfeResultLevel(headerResult, detailResult) {
852
+ if (detailResult) {
853
+ return "detail";
854
+ }
855
+ return headerResult ? "header" : void 0;
856
+ }
857
+ function hasContradictoryWsfeResults(context) {
858
+ return Boolean(
859
+ context.headerResult && context.detailResult && context.headerResult !== context.detailResult
860
+ );
861
+ }
862
+ function isAuthorizedWsfeContext(context) {
863
+ return Boolean(
864
+ context.detailResult === "A" && context.headerResult !== "R" && context.base.errors.length === 0 && context.cae && context.caeExpiry
865
+ );
866
+ }
867
+ function isRejectedWsfeDetailContext(context) {
868
+ return context.detailResult === "R" && context.headerResult !== "A" && !context.cae;
869
+ }
870
+ function isRejectedWsfeHeaderContext(context) {
871
+ return context.headerResult === "R" && context.detailResult === void 0 && !context.cae && context.base.errors.length > 0 && context.base.errors.every((issue) => issue.category === "business");
872
+ }
873
+ function hasWsfeCaeContradiction(context) {
874
+ return (context.resultCode === "A" || context.resultCode === "R") && Boolean(context.cae);
875
+ }
876
+ function createWsfeStructuredIndeterminate(context, reason) {
877
+ const outcome = {
878
+ ...context.base,
879
+ kind: "indeterminate",
880
+ reason
881
+ };
882
+ assignWsfeValue(outcome, "result", context.resultCode);
883
+ assignWsfeValue(outcome, "resultLevel", context.resultLevel);
884
+ assignWsfeValue(outcome, "cae", context.cae);
885
+ assignWsfeValue(outcome, "caeExpiry", context.caeExpiry);
886
+ return outcome;
887
+ }
888
+ function createWsfeResults(headerResult, detailResult) {
889
+ const results = {};
890
+ assignWsfeValue(results, "header", headerResult);
891
+ assignWsfeValue(results, "detail", detailResult);
892
+ return results;
893
+ }
894
+ function createWsfeIndeterminateOutcome(error) {
895
+ return {
896
+ kind: "indeterminate",
897
+ service: "wsfe",
898
+ operation: "FECAESolicitar",
899
+ results: {},
900
+ reason: getArcaIndeterminateReason(error),
901
+ errors: [],
902
+ observations: []
903
+ };
904
+ }
905
+ function getArcaIndeterminateReason(error) {
906
+ if (error instanceof ArcaTransportError) {
907
+ return "transport_error";
908
+ }
909
+ if (error instanceof ArcaSoapFaultError) {
910
+ return "soap_fault";
911
+ }
912
+ if (error instanceof ArcaInvalidSoapResponseError) {
913
+ return "invalid_response";
914
+ }
915
+ return "unexpected_error";
916
+ }
917
+ function createWsfeOutcomeError(outcome) {
918
+ const issues = [...outcome.errors, ...outcome.observations];
919
+ const firstIssue = issues[0];
920
+ 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";
921
+ return new ArcaServiceError(message, {
922
+ service: "wsfe",
923
+ operation: outcome.operation,
924
+ ...firstIssue?.code === void 0 ? {} : { serviceCode: firstIssue.code },
925
+ ...outcome.result === void 0 ? {} : { result: outcome.result },
926
+ ...outcome.resultLevel === void 0 ? {} : { resultLevel: outcome.resultLevel },
927
+ results: outcome.results,
928
+ ...outcome.kind === "indeterminate" && outcome.cae ? { cae: outcome.cae } : {},
929
+ issues,
930
+ detail: outcome.raw
931
+ });
932
+ }
933
+ function createWsfeServiceError(operation, result, issues) {
934
+ const firstIssue = issues[0];
935
+ return new ArcaServiceError(
936
+ firstIssue ? formatWsfeIssue(firstIssue) : "WSFE returned a service error",
937
+ {
938
+ service: "wsfe",
939
+ operation,
940
+ ...firstIssue?.code === void 0 ? {} : { serviceCode: firstIssue.code },
941
+ issues,
942
+ detail: result
943
+ }
944
+ );
945
+ }
946
+ function extractWsfeGlobalIssues(result, operation, resultLevel) {
947
+ const errorsContainer = toWsfeRecord(result.Errors);
948
+ return normalizeWsfeIssueEntries(errorsContainer?.Err).map((entry) => ({
949
+ service: "wsfe",
950
+ operation,
951
+ source: "error",
952
+ category: operation === "FECAESolicitar" && WSFE_AUTHORIZATION_INFRASTRUCTURE_CODES.has(entry.code ?? "") ? "infrastructure" : operation === "FECAESolicitar" ? "business" : "unknown",
953
+ ...entry.code === void 0 ? {} : { code: entry.code },
954
+ message: entry.message,
955
+ ...resultLevel === void 0 ? {} : { resultLevel }
956
+ }));
957
+ }
958
+ function extractWsfeObservations(detail, category) {
959
+ const observationsContainer = toWsfeRecord(detail.Observaciones);
960
+ return normalizeWsfeIssueEntries(observationsContainer?.Obs).map((entry) => ({
961
+ service: "wsfe",
962
+ operation: "FECAESolicitar",
963
+ source: "observation",
964
+ category,
965
+ ...entry.code === void 0 ? {} : { code: entry.code },
966
+ message: entry.message,
967
+ resultLevel: "detail"
968
+ }));
969
+ }
970
+ function normalizeWsfeIssueEntries(rawErrors) {
620
971
  const entries = Array.isArray(rawErrors) ? rawErrors : rawErrors ? [rawErrors] : [];
621
972
  return entries.map((entry) => entry).map((entry) => {
622
- const code = entry.Code ?? entry.code ?? "N/A";
973
+ const code = entry.Code ?? entry.code;
623
974
  const message = entry.Msg ?? entry.msg ?? "Unknown WSFE error";
624
975
  return {
625
- code: String(code),
626
- message: `(${String(code)}) ${String(message)}`
976
+ ...code === void 0 ? {} : { code: String(code) },
977
+ message: String(message)
627
978
  };
628
979
  });
629
980
  }
981
+ function formatWsfeIssue(issue) {
982
+ return issue.code ? `(${issue.code}) ${issue.message}` : issue.message;
983
+ }
984
+ function normalizeWsfeResult(value) {
985
+ if (typeof value !== "string") {
986
+ return void 0;
987
+ }
988
+ const normalized = value.trim().toUpperCase();
989
+ return normalized || void 0;
990
+ }
991
+ function normalizeWsfeString(value) {
992
+ if (value === void 0 || value === null) {
993
+ return void 0;
994
+ }
995
+ const normalized = String(value).trim();
996
+ return normalized || void 0;
997
+ }
998
+ function normalizeWsfeNumber(value) {
999
+ if (value === void 0 || value === null || value === "") {
1000
+ return void 0;
1001
+ }
1002
+ const normalized = Number(value);
1003
+ return Number.isFinite(normalized) ? normalized : void 0;
1004
+ }
1005
+ function assignWsfeValue(target, key, value) {
1006
+ if (value !== void 0) {
1007
+ target[key] = value;
1008
+ }
1009
+ }
1010
+ function toWsfeRecord(value) {
1011
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1012
+ }
1013
+ var WSFE_AUTHORIZATION_INFRASTRUCTURE_CODES = /* @__PURE__ */ new Set([
1014
+ "500",
1015
+ "501",
1016
+ "502",
1017
+ "600",
1018
+ "601"
1019
+ ]);
630
1020
  function getWsfeResultEntries(result, key) {
631
1021
  const rawEntries = result.ResultGet?.[key];
632
1022
  if (!rawEntries) {