@taxora/sdk 1.9.0 → 1.10.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/dist/index.cjs CHANGED
@@ -27,12 +27,16 @@ __export(index_exports, {
27
27
  BillingEndpoint: () => BillingEndpoint,
28
28
  CompanyAddress: () => CompanyAddress,
29
29
  CompanyEndpoint: () => CompanyEndpoint,
30
+ ComplianceDeliveryAction: () => ComplianceDeliveryAction,
31
+ ComplianceDeliveryDecision: () => ComplianceDeliveryDecision,
30
32
  ComplianceDocumentType: () => ComplianceDocumentType,
31
33
  ComplianceEnrollment: () => ComplianceEnrollment,
32
34
  ComplianceEnrollmentPage: () => ComplianceEnrollmentPage,
33
35
  ComplianceEnrollmentStatus: () => ComplianceEnrollmentStatus,
34
36
  ComplianceOfferings: () => ComplianceOfferings,
35
37
  ComplianceService: () => ComplianceService,
38
+ ComplianceTax: () => ComplianceTax,
39
+ ComplianceTaxCategory: () => ComplianceTaxCategory,
36
40
  ComplianceTaxReport: () => ComplianceTaxReport,
37
41
  ComplianceTaxReportPage: () => ComplianceTaxReportPage,
38
42
  ComplianceTaxReportState: () => ComplianceTaxReportState,
@@ -41,6 +45,8 @@ __export(index_exports, {
41
45
  ComplianceTransactionState: () => ComplianceTransactionState,
42
46
  ComplianceTransactionType: () => ComplianceTransactionType,
43
47
  DEFAULT_WEBHOOK_TOLERANCE_SECONDS: () => DEFAULT_WEBHOOK_TOLERANCE_SECONDS,
48
+ EInvoicingQuota: () => EInvoicingQuota,
49
+ EInvoicingQuotaPeriod: () => EInvoicingQuotaPeriod,
44
50
  EReportingEndpoint: () => EReportingEndpoint,
45
51
  Environment: () => Environment,
46
52
  FetchHttpClient: () => FetchHttpClient,
@@ -88,6 +94,7 @@ __export(index_exports, {
88
94
  WEBHOOK_ID_HEADER: () => WEBHOOK_ID_HEADER,
89
95
  WEBHOOK_SIGNATURE_HEADER: () => WEBHOOK_SIGNATURE_HEADER,
90
96
  WebhookSignatureVerificationError: () => WebhookSignatureVerificationError,
97
+ calculateInvoiceTotals: () => calculateInvoiceTotals,
91
98
  computeWebhookSignature: () => computeWebhookSignature,
92
99
  constructWebhookEvent: () => constructWebhookEvent,
93
100
  describeApiError: () => describeApiError,
@@ -106,6 +113,7 @@ __export(index_exports, {
106
113
  getBaseUrl: () => getBaseUrl,
107
114
  getFailedVatStates: () => getFailedVatStates,
108
115
  isTransactionBuyerRejected: () => isTransactionBuyerRejected,
116
+ parseComplianceTaxCategory: () => parseComplianceTaxCategory,
109
117
  parseLocalTaxNumbersCsv: () => parseLocalTaxNumbersCsv,
110
118
  parseWebhookSignatureHeader: () => parseWebhookSignatureHeader,
111
119
  toComplianceDocumentType: () => toComplianceDocumentType,
@@ -564,17 +572,144 @@ var AuthEndpoint = class {
564
572
  }
565
573
  };
566
574
 
567
- // src/dto/UsageSummary.ts
575
+ // src/dto/EInvoicingQuota.ts
576
+ function asString(value, fallback = "") {
577
+ return typeof value === "string" ? value : fallback;
578
+ }
579
+ function asNullableString(value) {
580
+ return typeof value === "string" ? value : null;
581
+ }
582
+ function asInt(value) {
583
+ return typeof value === "number" ? Math.trunc(value) : Number(value ?? 0) || 0;
584
+ }
568
585
  function asRecord(value) {
569
586
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
570
587
  }
588
+ var EInvoicingQuotaPeriod = class _EInvoicingQuotaPeriod {
589
+ constructor(period, used, included, freeUsed, freeRemaining, billableUnits, amount, monthlyFee, total, state, byCountry, billedAt, manualReference, monthlyFeeReference) {
590
+ this.period = period;
591
+ this.used = used;
592
+ this.included = included;
593
+ this.freeUsed = freeUsed;
594
+ this.freeRemaining = freeRemaining;
595
+ this.billableUnits = billableUnits;
596
+ this.amount = amount;
597
+ this.monthlyFee = monthlyFee;
598
+ this.total = total;
599
+ this.state = state;
600
+ this.byCountry = byCountry;
601
+ this.billedAt = billedAt;
602
+ this.manualReference = manualReference;
603
+ this.monthlyFeeReference = monthlyFeeReference;
604
+ }
605
+ period;
606
+ used;
607
+ included;
608
+ freeUsed;
609
+ freeRemaining;
610
+ billableUnits;
611
+ amount;
612
+ monthlyFee;
613
+ total;
614
+ state;
615
+ byCountry;
616
+ billedAt;
617
+ manualReference;
618
+ monthlyFeeReference;
619
+ static fromArray(data) {
620
+ const byCountry = {};
621
+ if (Array.isArray(data["by_country"])) {
622
+ for (const row of data["by_country"]) {
623
+ const entry = asRecord(row);
624
+ if (entry && typeof entry["country"] === "string") {
625
+ byCountry[entry["country"]] = asInt(entry["used"]);
626
+ }
627
+ }
628
+ }
629
+ return new _EInvoicingQuotaPeriod(
630
+ asString(data["period"]),
631
+ asInt(data["used"]),
632
+ asInt(data["included"]),
633
+ asInt(data["free_used"]),
634
+ asInt(data["free_remaining"]),
635
+ asInt(data["billable_units"]),
636
+ asString(data["amount"], "0.00"),
637
+ asNullableString(data["monthly_fee"]),
638
+ asString(data["total"], "0.00"),
639
+ asString(data["state"], "open"),
640
+ byCountry,
641
+ asNullableString(data["billed_at"]),
642
+ asNullableString(data["manual_reference"]),
643
+ asNullableString(data["monthly_fee_reference"])
644
+ );
645
+ }
646
+ };
647
+ var EInvoicingQuota = class _EInvoicingQuota {
648
+ constructor(billing, plan, currency, included, tiers, countries, monthlyFee, current, history) {
649
+ this.billing = billing;
650
+ this.plan = plan;
651
+ this.currency = currency;
652
+ this.included = included;
653
+ this.tiers = tiers;
654
+ this.countries = countries;
655
+ this.monthlyFee = monthlyFee;
656
+ this.current = current;
657
+ this.history = history;
658
+ }
659
+ billing;
660
+ plan;
661
+ currency;
662
+ included;
663
+ tiers;
664
+ countries;
665
+ monthlyFee;
666
+ current;
667
+ history;
668
+ static fromArray(data) {
669
+ const tiers = [];
670
+ if (Array.isArray(data["tiers"])) {
671
+ for (const row of data["tiers"]) {
672
+ const tier = asRecord(row);
673
+ if (tier) {
674
+ tiers.push({
675
+ upTo: tier["up_to"] === null || tier["up_to"] === void 0 ? null : asInt(tier["up_to"]),
676
+ unitPrice: asString(tier["unit_price"], "0")
677
+ });
678
+ }
679
+ }
680
+ }
681
+ const history = [];
682
+ if (Array.isArray(data["history"])) {
683
+ for (const row of data["history"]) {
684
+ const period = asRecord(row);
685
+ if (period) history.push(EInvoicingQuotaPeriod.fromArray(period));
686
+ }
687
+ }
688
+ return new _EInvoicingQuota(
689
+ asString(data["billing"], "invoice"),
690
+ asNullableString(data["plan"]),
691
+ asString(data["currency"], "EUR"),
692
+ asInt(data["included"]),
693
+ tiers,
694
+ Array.isArray(data["countries"]) ? data["countries"].map(String) : [],
695
+ asNullableString(data["monthly_fee"]),
696
+ EInvoicingQuotaPeriod.fromArray(asRecord(data["current"]) ?? {}),
697
+ history
698
+ );
699
+ }
700
+ };
701
+
702
+ // src/dto/UsageSummary.ts
703
+ function asRecord2(value) {
704
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
705
+ }
571
706
  function asRecordList(value) {
572
- return Array.isArray(value) ? value.filter((row) => asRecord(row) !== null) : [];
707
+ return Array.isArray(value) ? value.filter((row) => asRecord2(row) !== null) : [];
573
708
  }
574
- function asString(value, fallback = "") {
709
+ function asString2(value, fallback = "") {
575
710
  return typeof value === "string" ? value : fallback;
576
711
  }
577
- function asNullableString(value) {
712
+ function asNullableString2(value) {
578
713
  return typeof value === "string" ? value : null;
579
714
  }
580
715
  function asNumber(value) {
@@ -631,35 +766,35 @@ var UsageSummary = class _UsageSummary {
631
766
  return new _UsageSummary(
632
767
  asNumber(data["id"]),
633
768
  asNumber(data["company_id"]),
634
- asString(data["feature"]),
635
- asNullableString(data["country"]),
636
- asNullableString(data["regime"]),
637
- asString(data["billing_period"]),
769
+ asString2(data["feature"]),
770
+ asNullableString2(data["country"]),
771
+ asNullableString2(data["regime"]),
772
+ asString2(data["billing_period"]),
638
773
  asNumber(data["event_count"]),
639
774
  typeof amount === "string" ? amount : typeof amount === "number" ? String(amount) : null,
640
- asNullableString(data["state"]),
641
- asNullableString(data["state_label"]),
642
- asNullableString(data["period_closed_at"]),
643
- asNullableString(data["billing_triggered_at"]),
644
- asNullableString(data["billed_at"]),
645
- asNullableString(data["stripe_invoice_id"]),
646
- asNullableString(data["stripe_subscription_item_id"]),
647
- asNullableString(data["billing_notes"]),
775
+ asNullableString2(data["state"]),
776
+ asNullableString2(data["state_label"]),
777
+ asNullableString2(data["period_closed_at"]),
778
+ asNullableString2(data["billing_triggered_at"]),
779
+ asNullableString2(data["billed_at"]),
780
+ asNullableString2(data["stripe_invoice_id"]),
781
+ asNullableString2(data["stripe_subscription_item_id"]),
782
+ asNullableString2(data["billing_notes"]),
648
783
  asRecordList(data["events"]).map((event) => ({
649
784
  id: asNumber(event["id"]),
650
785
  usageSummaryId: asNullableNumber(event["usage_summary_id"]),
651
- feature: asString(event["feature"]),
652
- country: asNullableString(event["country"]),
653
- regime: asNullableString(event["regime"]),
654
- billingPeriod: asString(event["billing_period"]),
655
- resourceType: asNullableString(event["resource_type"]),
786
+ feature: asString2(event["feature"]),
787
+ country: asNullableString2(event["country"]),
788
+ regime: asNullableString2(event["regime"]),
789
+ billingPeriod: asString2(event["billing_period"]),
790
+ resourceType: asNullableString2(event["resource_type"]),
656
791
  resourceId: asNullableNumber(event["resource_id"]),
657
- stripeUsageRecordId: asNullableString(event["stripe_usage_record_id"]),
658
- stripeReportedAt: asNullableString(event["stripe_reported_at"]),
659
- createdAt: asNullableString(event["created_at"])
792
+ stripeUsageRecordId: asNullableString2(event["stripe_usage_record_id"]),
793
+ stripeReportedAt: asNullableString2(event["stripe_reported_at"]),
794
+ createdAt: asNullableString2(event["created_at"])
660
795
  })),
661
- asNullableString(data["created_at"]),
662
- asNullableString(data["updated_at"])
796
+ asNullableString2(data["created_at"]),
797
+ asNullableString2(data["updated_at"])
663
798
  );
664
799
  }
665
800
  };
@@ -677,9 +812,9 @@ var UsageSummaryPage = class _UsageSummaryPage {
677
812
  total;
678
813
  lastPage;
679
814
  static fromResponse(payload) {
680
- const obj = asRecord(payload) ?? {};
815
+ const obj = asRecord2(payload) ?? {};
681
816
  const rows = asRecordList(obj["data"]).map(UsageSummary.fromArray);
682
- const meta = asRecord(obj["meta"]) ?? {};
817
+ const meta = asRecord2(obj["meta"]) ?? {};
683
818
  const num = (value, fallback) => typeof value === "number" ? value : fallback;
684
819
  return new _UsageSummaryPage(
685
820
  rows,
@@ -731,6 +866,22 @@ var BillingEndpoint = class {
731
866
  const data = await this.getJson(`${this.baseUrl}/billing/usage-summaries/${period}`);
732
867
  return Array.isArray(data) ? data.filter((row) => typeof row === "object" && row !== null).map(UsageSummary.fromArray) : [];
733
868
  }
869
+ /**
870
+ * The e-invoicing allowance: documents included per month, used, still free and
871
+ * what is due for the documents beyond it — one pool over all e-invoicing
872
+ * countries, current month first, then up to `months - 1` earlier months (1-24).
873
+ * Resolves to null when the company has no e-invoicing.
874
+ */
875
+ async getEInvoicingQuota(months = 6) {
876
+ if (!Number.isInteger(months) || months < 1 || months > 24) {
877
+ throw new TaxoraException("months must be an integer between 1 and 24.");
878
+ }
879
+ const data = await this.getJson(`${this.baseUrl}/billing/einvoicing-quota?months=${months}`);
880
+ if (typeof data !== "object" || data === null || Array.isArray(data) || !("billing" in data)) {
881
+ return null;
882
+ }
883
+ return EInvoicingQuota.fromArray(data);
884
+ }
734
885
  buildHeaders() {
735
886
  const headers = {
736
887
  "Content-Type": "application/json",
@@ -836,6 +987,67 @@ var CompanyEndpoint = class {
836
987
  }
837
988
  };
838
989
 
990
+ // src/enums/ComplianceDeliveryAction.ts
991
+ var ComplianceDeliveryAction = {
992
+ /** The buyer can receive e-invoices: create the transaction, Taxora sends it. */
993
+ EINVOICE: "einvoice",
994
+ /** The buyer is not on the network: send your regular invoice yourself (a transaction would end as not_required and is not billed). */
995
+ REGULAR_INVOICE: "regular_invoice",
996
+ /** No definite directory answer yet: create the transaction anyway, Taxora asks again before sending. */
997
+ EINVOICE_PENDING: "einvoice_pending"
998
+ };
999
+
1000
+ // src/enums/PeppolLookupStatus.ts
1001
+ var PeppolLookupStatus = {
1002
+ REACHABLE: "reachable",
1003
+ NOT_REACHABLE: "not_reachable",
1004
+ PENDING: "pending",
1005
+ UNKNOWN: "unknown"
1006
+ };
1007
+ var VALUES = Object.values(PeppolLookupStatus);
1008
+ function toPeppolLookupStatus(value) {
1009
+ if (typeof value === "string") {
1010
+ const normalized = value.trim().toLowerCase();
1011
+ if (VALUES.includes(normalized)) {
1012
+ return normalized;
1013
+ }
1014
+ }
1015
+ return PeppolLookupStatus.UNKNOWN;
1016
+ }
1017
+ var DESCRIPTIONS = {
1018
+ [PeppolLookupStatus.REACHABLE]: "The participant is registered on Peppol and can receive e-invoices.",
1019
+ [PeppolLookupStatus.NOT_REACHABLE]: "The participant is not registered on Peppol.",
1020
+ [PeppolLookupStatus.PENDING]: "The directory lookup is still resolving \u2014 ask again in a few seconds.",
1021
+ [PeppolLookupStatus.UNKNOWN]: "Unknown lookup status."
1022
+ };
1023
+ function describePeppolLookupStatus(status) {
1024
+ return DESCRIPTIONS[status];
1025
+ }
1026
+
1027
+ // src/dto/ComplianceDeliveryDecision.ts
1028
+ var ComplianceDeliveryDecision = class _ComplianceDeliveryDecision {
1029
+ constructor(action, lookup) {
1030
+ this.action = action;
1031
+ this.lookup = lookup;
1032
+ }
1033
+ action;
1034
+ lookup;
1035
+ /** True unless the buyer is not on the network. */
1036
+ get sendsEInvoice() {
1037
+ return this.action !== ComplianceDeliveryAction.REGULAR_INVOICE;
1038
+ }
1039
+ static fromLookup(lookup) {
1040
+ switch (lookup.status) {
1041
+ case PeppolLookupStatus.REACHABLE:
1042
+ return new _ComplianceDeliveryDecision(ComplianceDeliveryAction.EINVOICE, lookup);
1043
+ case PeppolLookupStatus.NOT_REACHABLE:
1044
+ return new _ComplianceDeliveryDecision(ComplianceDeliveryAction.REGULAR_INVOICE, lookup);
1045
+ default:
1046
+ return new _ComplianceDeliveryDecision(ComplianceDeliveryAction.EINVOICE_PENDING, lookup);
1047
+ }
1048
+ }
1049
+ };
1050
+
839
1051
  // src/enums/ComplianceEnrollmentStatus.ts
840
1052
  var ComplianceEnrollmentStatus = {
841
1053
  PENDING_DATA: "pending_data",
@@ -847,17 +1059,17 @@ var ComplianceEnrollmentStatus = {
847
1059
  ERROR_ACTIVATION: "error_activation",
848
1060
  UNKNOWN: "unknown"
849
1061
  };
850
- var VALUES = Object.values(ComplianceEnrollmentStatus);
1062
+ var VALUES2 = Object.values(ComplianceEnrollmentStatus);
851
1063
  function toComplianceEnrollmentStatus(value) {
852
1064
  if (typeof value === "string") {
853
1065
  const normalized = value.trim().toLowerCase();
854
- if (VALUES.includes(normalized)) {
1066
+ if (VALUES2.includes(normalized)) {
855
1067
  return normalized;
856
1068
  }
857
1069
  }
858
1070
  return ComplianceEnrollmentStatus.UNKNOWN;
859
1071
  }
860
- var DESCRIPTIONS = {
1072
+ var DESCRIPTIONS2 = {
861
1073
  [ComplianceEnrollmentStatus.PENDING_DATA]: "Awaiting merchant data before provisioning can start.",
862
1074
  [ComplianceEnrollmentStatus.ACCOUNT_CREATED]: "Provider account exists. Regime not yet activated.",
863
1075
  [ComplianceEnrollmentStatus.REGIME_ACTIVATED]: "Compliance regime activated at provider. Ready to submit transactions.",
@@ -868,7 +1080,7 @@ var DESCRIPTIONS = {
868
1080
  [ComplianceEnrollmentStatus.UNKNOWN]: "Unknown status."
869
1081
  };
870
1082
  function describeComplianceEnrollmentStatus(status) {
871
- return DESCRIPTIONS[status];
1083
+ return DESCRIPTIONS2[status];
872
1084
  }
873
1085
 
874
1086
  // src/enums/ComplianceService.ts
@@ -877,30 +1089,30 @@ var ComplianceService = {
877
1089
  E_INVOICING: "e_invoicing",
878
1090
  UNKNOWN: "unknown"
879
1091
  };
880
- var VALUES2 = Object.values(ComplianceService);
1092
+ var VALUES3 = Object.values(ComplianceService);
881
1093
  function toComplianceService(value) {
882
1094
  if (typeof value === "string") {
883
1095
  const normalized = value.trim().toLowerCase();
884
- if (VALUES2.includes(normalized)) {
1096
+ if (VALUES3.includes(normalized)) {
885
1097
  return normalized;
886
1098
  }
887
1099
  }
888
1100
  return ComplianceService.UNKNOWN;
889
1101
  }
890
- var DESCRIPTIONS2 = {
1102
+ var DESCRIPTIONS3 = {
891
1103
  [ComplianceService.E_REPORTING]: "E-reporting of transaction data to the tax authority (France: DGFiP Flux 10).",
892
1104
  [ComplianceService.E_INVOICING]: "Structured e-invoices delivered to the buyer (Norway: EHF / Peppol BIS 3.0).",
893
1105
  [ComplianceService.UNKNOWN]: "Unknown service."
894
1106
  };
895
1107
  function describeComplianceService(service) {
896
- return DESCRIPTIONS2[service];
1108
+ return DESCRIPTIONS3[service];
897
1109
  }
898
1110
 
899
1111
  // src/dto/ComplianceEnrollment.ts
900
- function asString2(value, fallback = "") {
1112
+ function asString3(value, fallback = "") {
901
1113
  return typeof value === "string" ? value : fallback;
902
1114
  }
903
- function asNullableString2(value) {
1115
+ function asNullableString3(value) {
904
1116
  return typeof value === "string" ? value : null;
905
1117
  }
906
1118
  function asNumber2(value) {
@@ -952,38 +1164,38 @@ var ComplianceEnrollment = class _ComplianceEnrollment {
952
1164
  return new _ComplianceEnrollment(
953
1165
  asNumber2(data["id"]),
954
1166
  asNumber2(data["company_id"]),
955
- asString2(data["country"]),
956
- asString2(data["regime"]),
957
- asString2(data["provider"]),
1167
+ asString3(data["country"]),
1168
+ asString3(data["regime"]),
1169
+ asString3(data["provider"]),
958
1170
  toComplianceEnrollmentStatus(data["status"]),
959
- asString2(data["status_label"]),
960
- asNullableString2(data["status_error"]),
961
- asNullableString2(data["provider_account_id"]),
962
- asNullableString2(data["tax_id"]),
963
- asNullableString2(data["company_register_id"]),
964
- asNullableString2(data["company_register_scheme"]),
1171
+ asString3(data["status_label"]),
1172
+ asNullableString3(data["status_error"]),
1173
+ asNullableString3(data["provider_account_id"]),
1174
+ asNullableString3(data["tax_id"]),
1175
+ asNullableString3(data["company_register_id"]),
1176
+ asNullableString3(data["company_register_scheme"]),
965
1177
  regimeConfig,
966
- asNullableString2(data["reporting_start_date"]),
967
- asNullableString2(data["notification_email"]),
1178
+ asNullableString3(data["reporting_start_date"]),
1179
+ asNullableString3(data["notification_email"]),
968
1180
  data["auto_send"] === true,
969
- asNullableString2(data["created_at"]),
970
- asNullableString2(data["updated_at"]),
1181
+ asNullableString3(data["created_at"]),
1182
+ asNullableString3(data["updated_at"]),
971
1183
  toComplianceService(data["service"])
972
1184
  );
973
1185
  }
974
1186
  };
975
1187
 
976
1188
  // src/dto/ComplianceOfferings.ts
977
- function asRecord2(value) {
1189
+ function asRecord3(value) {
978
1190
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
979
1191
  }
980
1192
  function asRecordList2(value) {
981
- return Array.isArray(value) ? value.filter((row) => asRecord2(row) !== null) : [];
1193
+ return Array.isArray(value) ? value.filter((row) => asRecord3(row) !== null) : [];
982
1194
  }
983
- function asString3(value, fallback = "") {
1195
+ function asString4(value, fallback = "") {
984
1196
  return typeof value === "string" ? value : fallback;
985
1197
  }
986
- function asNullableString3(value) {
1198
+ function asNullableString4(value) {
987
1199
  return typeof value === "string" ? value : null;
988
1200
  }
989
1201
  function asNullableNumber2(value) {
@@ -995,8 +1207,8 @@ function asStringList(value) {
995
1207
  return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
996
1208
  }
997
1209
  function toRequires(value) {
998
- const record = asRecord2(value);
999
- return record === null ? null : { country: asString3(record["country"]), service: asString3(record["service"]) };
1210
+ const record = asRecord3(value);
1211
+ return record === null ? null : { country: asString4(record["country"]), service: asString4(record["service"]) };
1000
1212
  }
1001
1213
  var ComplianceOfferings = class _ComplianceOfferings {
1002
1214
  constructor(offerings, coverage, access, accessByCountry) {
@@ -1011,16 +1223,16 @@ var ComplianceOfferings = class _ComplianceOfferings {
1011
1223
  accessByCountry;
1012
1224
  static fromArray(data) {
1013
1225
  const offerings = asRecordList2(data["data"]).map((row) => ({
1014
- country: asString3(row["country"]),
1015
- service: asString3(row["service"]),
1016
- currency: asString3(row["currency"], "EUR"),
1226
+ country: asString4(row["country"]),
1227
+ service: asString4(row["service"]),
1228
+ currency: asString4(row["currency"], "EUR"),
1017
1229
  active: row["active"] === true,
1018
1230
  viaStripe: row["via_stripe"] === true,
1019
- plan: asNullableString3(row["plan"]),
1020
- status: asNullableString3(row["status"]),
1231
+ plan: asNullableString4(row["plan"]),
1232
+ status: asNullableString4(row["status"]),
1021
1233
  enrolled: row["enrolled"] === true,
1022
1234
  plans: asRecordList2(row["plans"]).map((plan) => ({
1023
- key: asString3(plan["key"]),
1235
+ key: asString4(plan["key"]),
1024
1236
  monthlyFee: asNullableNumber2(plan["monthly_fee"]),
1025
1237
  setupFee: asNullableNumber2(plan["setup_fee"]),
1026
1238
  usageTiers: Array.isArray(plan["usage_tiers"]) ? plan["usage_tiers"] : [],
@@ -1032,19 +1244,19 @@ var ComplianceOfferings = class _ComplianceOfferings {
1032
1244
  }))
1033
1245
  }));
1034
1246
  const coverage = asRecordList2(data["coverage"]).map((row) => ({
1035
- country: asString3(row["country"]),
1036
- availability: asString3(row["availability"]),
1247
+ country: asString4(row["country"]),
1248
+ availability: asString4(row["availability"]),
1037
1249
  services: asStringList(row["services"]),
1038
- network: asNullableString3(row["network"]),
1039
- format: asNullableString3(row["format"]),
1040
- mandate: asNullableString3(row["mandate"]),
1041
- support: asString3(row["support"], "yes")
1250
+ network: asNullableString4(row["network"]),
1251
+ format: asNullableString4(row["format"]),
1252
+ mandate: asNullableString4(row["mandate"]),
1253
+ support: asString4(row["support"], "yes")
1042
1254
  }));
1043
- const access = asRecord2(data["access"]) ?? {};
1255
+ const access = asRecord3(data["access"]) ?? {};
1044
1256
  const accessByCountry = {};
1045
- for (const [country, services] of Object.entries(asRecord2(data["access_by_country"]) ?? {})) {
1257
+ for (const [country, services] of Object.entries(asRecord3(data["access_by_country"]) ?? {})) {
1046
1258
  const flags = {};
1047
- for (const [service, value] of Object.entries(asRecord2(services) ?? {})) {
1259
+ for (const [service, value] of Object.entries(asRecord3(services) ?? {})) {
1048
1260
  flags[service] = value === true;
1049
1261
  }
1050
1262
  accessByCountry[country] = flags;
@@ -1103,17 +1315,17 @@ var ComplianceTaxReportState = {
1103
1315
  ERROR: "error",
1104
1316
  UNKNOWN: "unknown"
1105
1317
  };
1106
- var VALUES3 = Object.values(ComplianceTaxReportState);
1318
+ var VALUES4 = Object.values(ComplianceTaxReportState);
1107
1319
  function toComplianceTaxReportState(value) {
1108
1320
  if (typeof value === "string") {
1109
1321
  const normalized = value.trim().toLowerCase();
1110
- if (VALUES3.includes(normalized)) {
1322
+ if (VALUES4.includes(normalized)) {
1111
1323
  return normalized;
1112
1324
  }
1113
1325
  }
1114
1326
  return ComplianceTaxReportState.UNKNOWN;
1115
1327
  }
1116
- var DESCRIPTIONS3 = {
1328
+ var DESCRIPTIONS4 = {
1117
1329
  [ComplianceTaxReportState.NEW]: "Created at provider, waiting for the daily ledger batch.",
1118
1330
  [ComplianceTaxReportState.SENT]: "Ledger transmitted to PPF.",
1119
1331
  [ComplianceTaxReportState.ACKNOWLEDGED]: "PPF acknowledged receipt of the ledger.",
@@ -1123,14 +1335,14 @@ var DESCRIPTIONS3 = {
1123
1335
  [ComplianceTaxReportState.UNKNOWN]: "Unknown state."
1124
1336
  };
1125
1337
  function describeComplianceTaxReportState(state) {
1126
- return DESCRIPTIONS3[state];
1338
+ return DESCRIPTIONS4[state];
1127
1339
  }
1128
1340
 
1129
1341
  // src/dto/ComplianceTaxReport.ts
1130
- function asString4(value, fallback = "") {
1342
+ function asString5(value, fallback = "") {
1131
1343
  return typeof value === "string" ? value : fallback;
1132
1344
  }
1133
- function asNullableString4(value) {
1345
+ function asNullableString5(value) {
1134
1346
  return typeof value === "string" ? value : null;
1135
1347
  }
1136
1348
  function asNumber3(value) {
@@ -1191,21 +1403,21 @@ var ComplianceTaxReport = class _ComplianceTaxReport {
1191
1403
  asNumber3(data["company_id"]),
1192
1404
  asNullableNumber3(data["compliance_transaction_id"]),
1193
1405
  asNullableNumber3(data["ledger_id"]),
1194
- asString4(data["country"]),
1195
- asString4(data["regime"]),
1406
+ asString5(data["country"]),
1407
+ asString5(data["regime"]),
1196
1408
  toComplianceTaxReportState(data["state"]),
1197
- asString4(data["state_label"]),
1409
+ asString5(data["state_label"]),
1198
1410
  data["is_terminal"] === true,
1199
- asNullableString4(data["provider_tax_report_id"]),
1200
- asNullableString4(data["provider_ledger_id"]),
1411
+ asNullableString5(data["provider_tax_report_id"]),
1412
+ asNullableString5(data["provider_ledger_id"]),
1201
1413
  asMoney(data["base_amount"]),
1202
1414
  asMoney(data["tax_amount"]),
1203
1415
  asMoney(data["total_amount"]),
1204
- asNullableString4(data["refusal_reason"]),
1205
- asNullableString4(data["registered_at"]),
1206
- asNullableString4(data["refused_at"]),
1207
- asNullableString4(data["created_at"]),
1208
- asNullableString4(data["updated_at"])
1416
+ asNullableString5(data["refusal_reason"]),
1417
+ asNullableString5(data["registered_at"]),
1418
+ asNullableString5(data["refused_at"]),
1419
+ asNullableString5(data["created_at"]),
1420
+ asNullableString5(data["updated_at"])
1209
1421
  );
1210
1422
  }
1211
1423
  };
@@ -1251,23 +1463,23 @@ var ComplianceDocumentType = {
1251
1463
  CREDIT_NOTE: "credit_note",
1252
1464
  UNKNOWN: "unknown"
1253
1465
  };
1254
- var VALUES4 = Object.values(ComplianceDocumentType);
1466
+ var VALUES5 = Object.values(ComplianceDocumentType);
1255
1467
  function toComplianceDocumentType(value) {
1256
1468
  if (typeof value === "string") {
1257
1469
  const normalized = value.trim().toLowerCase();
1258
- if (VALUES4.includes(normalized)) {
1470
+ if (VALUES5.includes(normalized)) {
1259
1471
  return normalized;
1260
1472
  }
1261
1473
  }
1262
1474
  return ComplianceDocumentType.UNKNOWN;
1263
1475
  }
1264
- var DESCRIPTIONS4 = {
1476
+ var DESCRIPTIONS5 = {
1265
1477
  [ComplianceDocumentType.INVOICE]: "Commercial invoice.",
1266
1478
  [ComplianceDocumentType.CREDIT_NOTE]: "Credit note correcting a previously issued invoice.",
1267
1479
  [ComplianceDocumentType.UNKNOWN]: "Unknown document type."
1268
1480
  };
1269
1481
  function describeComplianceDocumentType(type) {
1270
- return DESCRIPTIONS4[type];
1482
+ return DESCRIPTIONS5[type];
1271
1483
  }
1272
1484
 
1273
1485
  // src/enums/ComplianceTransactionState.ts
@@ -1280,17 +1492,17 @@ var ComplianceTransactionState = {
1280
1492
  NOT_REQUIRED: "not_required",
1281
1493
  UNKNOWN: "unknown"
1282
1494
  };
1283
- var VALUES5 = Object.values(ComplianceTransactionState);
1495
+ var VALUES6 = Object.values(ComplianceTransactionState);
1284
1496
  function toComplianceTransactionState(value) {
1285
1497
  if (typeof value === "string") {
1286
1498
  const normalized = value.trim().toLowerCase();
1287
- if (VALUES5.includes(normalized)) {
1499
+ if (VALUES6.includes(normalized)) {
1288
1500
  return normalized;
1289
1501
  }
1290
1502
  }
1291
1503
  return ComplianceTransactionState.UNKNOWN;
1292
1504
  }
1293
- var DESCRIPTIONS5 = {
1505
+ var DESCRIPTIONS6 = {
1294
1506
  [ComplianceTransactionState.PENDING]: "Recorded locally, not yet submitted to the provider.",
1295
1507
  [ComplianceTransactionState.SENDING]: "Submission to the provider in progress.",
1296
1508
  [ComplianceTransactionState.SUBMITTED]: "Successfully submitted to the provider.",
@@ -1299,7 +1511,7 @@ var DESCRIPTIONS5 = {
1299
1511
  [ComplianceTransactionState.UNKNOWN]: "Unknown state."
1300
1512
  };
1301
1513
  function describeComplianceTransactionState(state) {
1302
- return DESCRIPTIONS5[state];
1514
+ return DESCRIPTIONS6[state];
1303
1515
  }
1304
1516
 
1305
1517
  // src/enums/ComplianceTransactionType.ts
@@ -1311,17 +1523,17 @@ var ComplianceTransactionType = {
1311
1523
  CROSSBORDER_INBOUND: "crossborder_inbound",
1312
1524
  UNKNOWN: "unknown"
1313
1525
  };
1314
- var VALUES6 = Object.values(ComplianceTransactionType);
1526
+ var VALUES7 = Object.values(ComplianceTransactionType);
1315
1527
  function toComplianceTransactionType(value) {
1316
1528
  if (typeof value === "string") {
1317
1529
  const normalized = value.trim().toLowerCase();
1318
- if (VALUES6.includes(normalized)) {
1530
+ if (VALUES7.includes(normalized)) {
1319
1531
  return normalized;
1320
1532
  }
1321
1533
  }
1322
1534
  return ComplianceTransactionType.UNKNOWN;
1323
1535
  }
1324
- var DESCRIPTIONS6 = {
1536
+ var DESCRIPTIONS7 = {
1325
1537
  [ComplianceTransactionType.B2C_OUTBOUND]: "Sale to a private person in the merchant country (DGFiP Flux 10.3).",
1326
1538
  [ComplianceTransactionType.B2B_DOMESTIC_OUTBOUND]: "Sale to a domestic business (DGFiP Flux 1, Phase 2).",
1327
1539
  [ComplianceTransactionType.B2B_DOMESTIC_INBOUND]: "Purchase from a domestic business (DGFiP Flux 1, Phase 2).",
@@ -1330,14 +1542,14 @@ var DESCRIPTIONS6 = {
1330
1542
  [ComplianceTransactionType.UNKNOWN]: "Unknown transaction type."
1331
1543
  };
1332
1544
  function describeComplianceTransactionType(type) {
1333
- return DESCRIPTIONS6[type];
1545
+ return DESCRIPTIONS7[type];
1334
1546
  }
1335
1547
 
1336
1548
  // src/dto/ComplianceTransaction.ts
1337
- function asString5(value, fallback = "") {
1549
+ function asString6(value, fallback = "") {
1338
1550
  return typeof value === "string" ? value : fallback;
1339
1551
  }
1340
- function asNullableString5(value) {
1552
+ function asNullableString6(value) {
1341
1553
  return typeof value === "string" ? value : null;
1342
1554
  }
1343
1555
  function asNumber4(value) {
@@ -1353,45 +1565,45 @@ function asNullableNumber4(value) {
1353
1565
  if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
1354
1566
  return null;
1355
1567
  }
1356
- function asRecord3(value) {
1568
+ function asRecord4(value) {
1357
1569
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
1358
1570
  }
1359
1571
  function asRecordList3(value) {
1360
- return Array.isArray(value) ? value.filter((row) => asRecord3(row) !== null) : [];
1572
+ return Array.isArray(value) ? value.filter((row) => asRecord4(row) !== null) : [];
1361
1573
  }
1362
1574
  function toInvoicePdf(value) {
1363
- const pdf = asRecord3(value);
1575
+ const pdf = asRecord4(value);
1364
1576
  if (pdf === null) return null;
1365
1577
  return {
1366
- filename: asNullableString5(pdf["filename"]),
1578
+ filename: asNullableString6(pdf["filename"]),
1367
1579
  size: asNullableNumber4(pdf["size"]),
1368
1580
  attached: pdf["attached"] === true
1369
1581
  };
1370
1582
  }
1371
1583
  function toEurEquivalent(value) {
1372
- const eur = asRecord3(value);
1584
+ const eur = asRecord4(value);
1373
1585
  if (eur === null) return null;
1374
1586
  return {
1375
1587
  subtotal: asMoney2(eur["subtotal"]),
1376
1588
  taxAmount: asMoney2(eur["tax_amount"]),
1377
1589
  total: asMoney2(eur["total"]),
1378
- rate: asString5(eur["rate"]),
1379
- rateDate: asNullableString5(eur["rate_date"]),
1380
- source: asString5(eur["source"], "ECB")
1590
+ rate: asString6(eur["rate"]),
1591
+ rateDate: asNullableString6(eur["rate_date"]),
1592
+ source: asString6(eur["source"], "ECB")
1381
1593
  };
1382
1594
  }
1383
1595
  function toInvoiceLines(providerPayload) {
1384
- const invoice = asRecord3(asRecord3(providerPayload)?.["invoice"]);
1596
+ const invoice = asRecord4(asRecord4(providerPayload)?.["invoice"]);
1385
1597
  return asRecordList3(invoice?.["invoice_lines_attributes"]).map((line) => ({
1386
- description: asString5(line["description"]),
1598
+ description: asString6(line["description"]),
1387
1599
  quantity: asNullableNumber4(line["quantity"]),
1388
1600
  price: asMoney2(line["price"]),
1389
1601
  unit: asNullableNumber4(line["unit"]),
1390
1602
  taxes: asRecordList3(line["taxes_attributes"]).map((tax) => ({
1391
- name: asString5(tax["name"]),
1603
+ name: asString6(tax["name"]),
1392
1604
  percent: asNullableNumber4(tax["percent"]),
1393
- category: asNullableString5(tax["category"]),
1394
- comment: asNullableString5(tax["comment"])
1605
+ category: asNullableString6(tax["category"]),
1606
+ comment: asNullableString6(tax["comment"])
1395
1607
  }))
1396
1608
  }));
1397
1609
  }
@@ -1499,48 +1711,48 @@ var ComplianceTransaction = class _ComplianceTransaction {
1499
1711
  asNumber4(data["id"]),
1500
1712
  asNumber4(data["company_id"]),
1501
1713
  asNumber4(data["compliance_enrollment_id"]),
1502
- asString5(data["country"]),
1503
- asString5(data["regime"]),
1714
+ asString6(data["country"]),
1715
+ asString6(data["regime"]),
1504
1716
  toComplianceTransactionType(data["transaction_type"]),
1505
- asString5(data["transaction_type_label"]),
1717
+ asString6(data["transaction_type_label"]),
1506
1718
  toComplianceTransactionState(data["state"]),
1507
- asString5(data["state_label"]),
1508
- asString5(data["invoice_number"]),
1509
- asNullableString5(data["invoice_date"]),
1510
- asNullableString5(data["due_date"]),
1511
- asString5(data["currency"], "EUR"),
1719
+ asString6(data["state_label"]),
1720
+ asString6(data["invoice_number"]),
1721
+ asNullableString6(data["invoice_date"]),
1722
+ asNullableString6(data["due_date"]),
1723
+ asString6(data["currency"], "EUR"),
1512
1724
  asMoney2(data["subtotal"]),
1513
1725
  asMoney2(data["tax_amount"]),
1514
1726
  asMoney2(data["total"]),
1515
- asNullableString5(data["counterparty_name"]),
1516
- asNullableString5(data["counterparty_country"]),
1517
- asNullableString5(data["counterparty_vat_number"]),
1727
+ asNullableString6(data["counterparty_name"]),
1728
+ asNullableString6(data["counterparty_country"]),
1729
+ asNullableString6(data["counterparty_vat_number"]),
1518
1730
  data["is_paid"] === true,
1519
- asNullableString5(data["paid_at"]),
1520
- asNullableString5(data["provider_invoice_id"]),
1521
- asNullableString5(data["submission_error"]),
1522
- asNullableString5(data["reported_at"]),
1731
+ asNullableString6(data["paid_at"]),
1732
+ asNullableString6(data["provider_invoice_id"]),
1733
+ asNullableString6(data["submission_error"]),
1734
+ asNullableString6(data["reported_at"]),
1523
1735
  taxReport,
1524
- asNullableString5(data["created_at"]),
1525
- asNullableString5(data["updated_at"]),
1526
- asNullableString5(data["counterparty_register_id"]),
1527
- asNullableString5(data["counterparty_address"]),
1528
- asNullableString5(data["counterparty_city"]),
1529
- asNullableString5(data["counterparty_postalcode"]),
1530
- asNullableString5(data["counterparty_email"]),
1531
- asNullableString5(data["buyer_reference"]),
1736
+ asNullableString6(data["created_at"]),
1737
+ asNullableString6(data["updated_at"]),
1738
+ asNullableString6(data["counterparty_register_id"]),
1739
+ asNullableString6(data["counterparty_address"]),
1740
+ asNullableString6(data["counterparty_city"]),
1741
+ asNullableString6(data["counterparty_postalcode"]),
1742
+ asNullableString6(data["counterparty_email"]),
1743
+ asNullableString6(data["buyer_reference"]),
1532
1744
  data["document_type"] === void 0 || data["document_type"] === null ? ComplianceDocumentType.INVOICE : toComplianceDocumentType(data["document_type"]),
1533
- asNullableString5(data["amended_number"]),
1534
- asNullableString5(data["amended_date"]),
1535
- asNullableString5(data["provider_state"]),
1745
+ asNullableString6(data["amended_number"]),
1746
+ asNullableString6(data["amended_date"]),
1747
+ asNullableString6(data["provider_state"]),
1536
1748
  toInvoiceLines(data["provider_payload"]),
1537
- asNullableString5(data["document_url"]),
1538
- asRecord3(data["delivery_check"]),
1749
+ asNullableString6(data["document_url"]),
1750
+ asRecord4(data["delivery_check"]),
1539
1751
  toInvoicePdf(data["invoice_pdf"]),
1540
- asNullableString5(data["internal_reference"]),
1541
- asNullableString5(data["pdf_url"]),
1752
+ asNullableString6(data["internal_reference"]),
1753
+ asNullableString6(data["pdf_url"]),
1542
1754
  data["buyer_rejected"] === true,
1543
- asNullableString5(data["rejection_reason"]),
1755
+ asNullableString6(data["rejection_reason"]),
1544
1756
  toEurEquivalent(data["eur_equivalent"])
1545
1757
  );
1546
1758
  }
@@ -1600,38 +1812,11 @@ var ImportResult = class _ImportResult {
1600
1812
  }
1601
1813
  };
1602
1814
 
1603
- // src/enums/PeppolLookupStatus.ts
1604
- var PeppolLookupStatus = {
1605
- REACHABLE: "reachable",
1606
- NOT_REACHABLE: "not_reachable",
1607
- PENDING: "pending",
1608
- UNKNOWN: "unknown"
1609
- };
1610
- var VALUES7 = Object.values(PeppolLookupStatus);
1611
- function toPeppolLookupStatus(value) {
1612
- if (typeof value === "string") {
1613
- const normalized = value.trim().toLowerCase();
1614
- if (VALUES7.includes(normalized)) {
1615
- return normalized;
1616
- }
1617
- }
1618
- return PeppolLookupStatus.UNKNOWN;
1619
- }
1620
- var DESCRIPTIONS7 = {
1621
- [PeppolLookupStatus.REACHABLE]: "The participant is registered on Peppol and can receive e-invoices.",
1622
- [PeppolLookupStatus.NOT_REACHABLE]: "The participant is not registered on Peppol.",
1623
- [PeppolLookupStatus.PENDING]: "The directory lookup is still resolving \u2014 ask again in a few seconds.",
1624
- [PeppolLookupStatus.UNKNOWN]: "Unknown lookup status."
1625
- };
1626
- function describePeppolLookupStatus(status) {
1627
- return DESCRIPTIONS7[status];
1628
- }
1629
-
1630
1815
  // src/dto/PeppolLookupResult.ts
1631
- function asString6(value, fallback = "") {
1816
+ function asString7(value, fallback = "") {
1632
1817
  return typeof value === "string" ? value : fallback;
1633
1818
  }
1634
- function asNullableString6(value) {
1819
+ function asNullableString7(value) {
1635
1820
  return typeof value === "string" ? value : null;
1636
1821
  }
1637
1822
  var PeppolLookupResult = class _PeppolLookupResult {
@@ -1662,21 +1847,21 @@ var PeppolLookupResult = class _PeppolLookupResult {
1662
1847
  return new _PeppolLookupResult(
1663
1848
  toPeppolLookupStatus(data["status"]),
1664
1849
  typeof data["reachable"] === "boolean" ? data["reachable"] : null,
1665
- asString6(data["country"]),
1666
- asString6(data["scheme"]),
1667
- asString6(data["id"]),
1850
+ asString7(data["country"]),
1851
+ asString7(data["scheme"]),
1852
+ asString7(data["id"]),
1668
1853
  documentTypes,
1669
- asNullableString6(data["transport_type_code"]),
1670
- asNullableString6(data["checked_at"])
1854
+ asNullableString7(data["transport_type_code"]),
1855
+ asNullableString7(data["checked_at"])
1671
1856
  );
1672
1857
  }
1673
1858
  };
1674
1859
 
1675
1860
  // src/dto/RegistryCompany.ts
1676
- function asString7(value, fallback = "") {
1861
+ function asString8(value, fallback = "") {
1677
1862
  return typeof value === "string" ? value : fallback;
1678
1863
  }
1679
- function asNullableString7(value) {
1864
+ function asNullableString8(value) {
1680
1865
  return typeof value === "string" ? value : null;
1681
1866
  }
1682
1867
  var RegistryCompany = class _RegistryCompany {
@@ -1708,24 +1893,24 @@ var RegistryCompany = class _RegistryCompany {
1708
1893
  country;
1709
1894
  static fromArray(data) {
1710
1895
  return new _RegistryCompany(
1711
- asString7(data["org_number"]),
1712
- asString7(data["company_name"]),
1713
- asNullableString7(data["organisation_form"]),
1896
+ asString8(data["org_number"]),
1897
+ asString8(data["company_name"]),
1898
+ asNullableString8(data["organisation_form"]),
1714
1899
  data["vat_registered"] === true,
1715
- asNullableString7(data["vat_number"]),
1900
+ asNullableString8(data["vat_number"]),
1716
1901
  data["enterprise_register"] === true,
1717
1902
  data["bankrupt"] === true,
1718
1903
  data["under_liquidation"] === true,
1719
- asNullableString7(data["address"]),
1720
- asNullableString7(data["postalcode"]),
1721
- asNullableString7(data["city"]),
1722
- asString7(data["country"])
1904
+ asNullableString8(data["address"]),
1905
+ asNullableString8(data["postalcode"]),
1906
+ asNullableString8(data["city"]),
1907
+ asString8(data["country"])
1723
1908
  );
1724
1909
  }
1725
1910
  };
1726
1911
 
1727
1912
  // src/dto/RevenueStatistics.ts
1728
- function asString8(value, fallback = "") {
1913
+ function asString9(value, fallback = "") {
1729
1914
  return typeof value === "string" ? value : fallback;
1730
1915
  }
1731
1916
  function asNumber5(value) {
@@ -1777,35 +1962,35 @@ var RevenueStatistics = class _RevenueStatistics {
1777
1962
  typeof data["totals"] === "object" && data["totals"] !== null ? data["totals"] : {}
1778
1963
  );
1779
1964
  const timeSeries = asRecords(data["time_series"]).map((row) => ({
1780
- bucket: asString8(row["bucket"]),
1965
+ bucket: asString9(row["bucket"]),
1781
1966
  ...toTotals(row)
1782
1967
  }));
1783
1968
  const byType = asRecords(data["by_type"]).map((row) => ({
1784
- type: asString8(row["type"]),
1785
- typeLabel: asString8(row["type_label"]),
1969
+ type: asString9(row["type"]),
1970
+ typeLabel: asString9(row["type_label"]),
1786
1971
  count: asNumber5(row["count"]),
1787
1972
  total: asMoney3(row["total"])
1788
1973
  }));
1789
1974
  const byCountry = asRecords(data["by_country"]).map((row) => ({
1790
- country: asString8(row["country"], "unknown"),
1975
+ country: asString9(row["country"], "unknown"),
1791
1976
  count: asNumber5(row["count"]),
1792
1977
  total: asMoney3(row["total"])
1793
1978
  }));
1794
1979
  const byState = asRecords(data["by_state"]).map((row) => ({
1795
- state: asString8(row["state"]),
1796
- stateLabel: asString8(row["state_label"]),
1980
+ state: asString9(row["state"]),
1981
+ stateLabel: asString9(row["state_label"]),
1797
1982
  count: asNumber5(row["count"]),
1798
1983
  total: asMoney3(row["total"])
1799
1984
  }));
1800
1985
  const byCurrency = asRecords(data["by_currency"]).map((row) => ({
1801
- currency: asString8(row["currency"]),
1986
+ currency: asString9(row["currency"]),
1802
1987
  ...toTotals(row)
1803
1988
  }));
1804
1989
  return new _RevenueStatistics(
1805
- asString8(range["date_from"]) || void 0,
1806
- asString8(range["date_to"]) || void 0,
1807
- asString8(range["interval"]) || void 0,
1808
- asString8(data["primary_currency"], "EUR"),
1990
+ asString9(range["date_from"]) || void 0,
1991
+ asString9(range["date_to"]) || void 0,
1992
+ asString9(range["interval"]) || void 0,
1993
+ asString9(data["primary_currency"], "EUR"),
1809
1994
  data["is_multi_currency"] === true,
1810
1995
  totals,
1811
1996
  timeSeries,
@@ -1818,10 +2003,10 @@ var RevenueStatistics = class _RevenueStatistics {
1818
2003
  };
1819
2004
 
1820
2005
  // src/dto/SireneLookupResult.ts
1821
- function asString9(value, fallback = "") {
2006
+ function asString10(value, fallback = "") {
1822
2007
  return typeof value === "string" ? value : fallback;
1823
2008
  }
1824
- function asNullableString8(value) {
2009
+ function asNullableString9(value) {
1825
2010
  return typeof value === "string" ? value : null;
1826
2011
  }
1827
2012
  var SireneLookupResult = class _SireneLookupResult {
@@ -1847,21 +2032,21 @@ var SireneLookupResult = class _SireneLookupResult {
1847
2032
  postalcode;
1848
2033
  static fromArray(data) {
1849
2034
  return new _SireneLookupResult(
1850
- asString9(data["company_name"]),
1851
- asString9(data["siren"]),
1852
- asNullableString8(data["siret"]),
1853
- asNullableString8(data["naf_code"]),
1854
- asNullableString8(data["naf_full"]),
1855
- asNullableString8(data["enterprise_size"]),
1856
- asNullableString8(data["address"]),
1857
- asNullableString8(data["city"]),
1858
- asNullableString8(data["postalcode"])
2035
+ asString10(data["company_name"]),
2036
+ asString10(data["siren"]),
2037
+ asNullableString9(data["siret"]),
2038
+ asNullableString9(data["naf_code"]),
2039
+ asNullableString9(data["naf_full"]),
2040
+ asNullableString9(data["enterprise_size"]),
2041
+ asNullableString9(data["address"]),
2042
+ asNullableString9(data["city"]),
2043
+ asNullableString9(data["postalcode"])
1859
2044
  );
1860
2045
  }
1861
2046
  };
1862
2047
 
1863
2048
  // src/dto/VatRates.ts
1864
- function asString10(value, fallback = "") {
2049
+ function asString11(value, fallback = "") {
1865
2050
  return typeof value === "string" ? value : fallback;
1866
2051
  }
1867
2052
  function asNumber6(value) {
@@ -1879,12 +2064,12 @@ var VatRates = class _VatRates {
1879
2064
  static fromArray(data) {
1880
2065
  const rates = (Array.isArray(data["rates"]) ? data["rates"] : []).filter((row) => typeof row === "object" && row !== null).map((row) => ({
1881
2066
  percent: asNumber6(row["percent"]),
1882
- category: asString10(row["category"]),
1883
- labelKey: asString10(row["label_key"]),
1884
- taxName: asString10(row["tax_name"]),
2067
+ category: asString11(row["category"]),
2068
+ labelKey: asString11(row["label_key"]),
2069
+ taxName: asString11(row["tax_name"]),
1885
2070
  requiresVatex: row["requires_vatex"] === true
1886
2071
  }));
1887
- return new _VatRates(asString10(data["country"]), asString10(data["currency"], "EUR"), rates);
2072
+ return new _VatRates(asString11(data["country"]), asString11(data["currency"], "EUR"), rates);
1888
2073
  }
1889
2074
  };
1890
2075
 
@@ -1938,6 +2123,25 @@ var NorwegianOrgNumber = {
1938
2123
  }
1939
2124
  };
1940
2125
 
2126
+ // src/enums/ComplianceTaxCategory.ts
2127
+ var ComplianceTaxCategory = {
2128
+ STANDARD: "S",
2129
+ REDUCED: "AA",
2130
+ SUPER_REDUCED: "AAA",
2131
+ INTRA_COMMUNITY: "K",
2132
+ EXPORT: "G",
2133
+ REVERSE_CHARGE: "AE",
2134
+ EXEMPT: "E",
2135
+ ZERO: "Z"
2136
+ };
2137
+ var CODES = Object.values(ComplianceTaxCategory);
2138
+ function parseComplianceTaxCategory(value) {
2139
+ if (typeof value !== "string") return null;
2140
+ const code = value.trim().toUpperCase();
2141
+ return CODES.includes(code) ? code : null;
2142
+ }
2143
+ var COMPLIANCE_TAX_CATEGORY_CODES = CODES;
2144
+
1941
2145
  // src/endpoints/EReportingEndpoint.ts
1942
2146
  var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
1943
2147
  var NAF_CODE_REGEX = /^\d{2}$/;
@@ -2122,6 +2326,19 @@ var EReportingEndpoint = class {
2122
2326
  const data = await this.parseJsonResponse(response);
2123
2327
  return PeppolLookupResult.fromArray(data);
2124
2328
  }
2329
+ /**
2330
+ * What to do with an invoice to this buyer: peppolLookup() turned into an action,
2331
+ * e.g. in a shop checkout when a business buyer enters its number.
2332
+ *
2333
+ * - `einvoice`: create the transaction, Taxora sends the e-invoice;
2334
+ * - `regular_invoice`: the buyer is not on the network — send your regular invoice
2335
+ * yourself (a transaction would end as not_required and is not billed);
2336
+ * - `einvoice_pending`: no definite answer yet — create the transaction anyway,
2337
+ * Taxora asks the directory again before sending.
2338
+ */
2339
+ async decideDelivery(country, id, scheme) {
2340
+ return ComplianceDeliveryDecision.fromLookup(await this.peppolLookup(country, id, scheme));
2341
+ }
2125
2342
  // ---------------------------------------------------------------------
2126
2343
  // Transactions
2127
2344
  // ---------------------------------------------------------------------
@@ -2148,6 +2365,7 @@ var EReportingEndpoint = class {
2148
2365
  this.validateBuyerFields(input);
2149
2366
  this.validateInternalReference(input.internalReference);
2150
2367
  this.validateInvoicePdfFilename(input);
2368
+ this.validateDocument(input);
2151
2369
  const body = {
2152
2370
  compliance_enrollment_id: input.complianceEnrollmentId,
2153
2371
  transaction_type: input.transactionType,
@@ -2163,6 +2381,101 @@ var EReportingEndpoint = class {
2163
2381
  const data = await this.parseJsonResponse(response);
2164
2382
  return ComplianceTransaction.fromArray(data);
2165
2383
  }
2384
+ /**
2385
+ * Issue a credit note for an invoice you sent through Taxora. Everything that must
2386
+ * match the corrected invoice is taken from `original`: enrollment, transaction type,
2387
+ * currency, buyer (name, register id, address, e-mail, VAT number, buyer reference) —
2388
+ * and the reference to the corrected invoice (number and date) is set for you.
2389
+ *
2390
+ * Without invoiceLines and amounts it credits the whole invoice: lines and amounts are
2391
+ * taken over as they are (the document type, not the sign, makes it a credit note).
2392
+ * For a partial credit pass invoiceLines, subtotal, taxAmount and total together.
2393
+ *
2394
+ * Not possible for an invoice that was never sent to the buyer (state not_required)
2395
+ * or for a credit note. A buyer rejected the invoice? Correct it with a credit note and
2396
+ * send a new invoice (`original.buyerRejected`).
2397
+ */
2398
+ async createCreditNote(original, input) {
2399
+ if (original.documentType === ComplianceDocumentType.CREDIT_NOTE) {
2400
+ throw new TaxoraException("A credit note cannot be credited again; issue a new invoice instead.");
2401
+ }
2402
+ if (original.state === ComplianceTransactionState.NOT_REQUIRED) {
2403
+ throw new TaxoraException(
2404
+ "The invoice was never sent as an e-invoice (the buyer is not on the network), so there is nothing to credit; correct your regular invoice instead."
2405
+ );
2406
+ }
2407
+ if (original.invoiceNumber === "") {
2408
+ throw new TaxoraException("The original transaction has no invoice number.");
2409
+ }
2410
+ if (original.transactionType === "unknown") {
2411
+ throw new TaxoraException("The original transaction has an unknown transaction type.");
2412
+ }
2413
+ const partial = [input.invoiceLines, input.subtotal, input.taxAmount, input.total];
2414
+ if (![0, 4].includes(partial.filter((value) => value !== void 0).length)) {
2415
+ throw new TaxoraException("For a partial credit pass invoiceLines, subtotal, taxAmount and total together.");
2416
+ }
2417
+ let invoiceLines;
2418
+ let subtotal = input.subtotal;
2419
+ let taxAmount = input.taxAmount;
2420
+ let total = input.total;
2421
+ if (input.invoiceLines !== void 0) {
2422
+ invoiceLines = input.invoiceLines;
2423
+ } else {
2424
+ invoiceLines = original.invoiceLines.map((line) => ({
2425
+ description: line.description,
2426
+ quantity: line.quantity ?? 0,
2427
+ price: Number(line.price),
2428
+ ...line.unit !== null ? { unit: line.unit } : {},
2429
+ taxes: line.taxes.map((tax) => ({
2430
+ name: tax.name,
2431
+ percent: tax.percent ?? 0,
2432
+ category: this.storedTaxCategory(tax.category),
2433
+ ...tax.comment !== null ? { comment: tax.comment } : {}
2434
+ }))
2435
+ }));
2436
+ if (invoiceLines.length === 0) {
2437
+ throw new TaxoraException(
2438
+ "The original transaction carries no invoice lines; pass invoiceLines and the amounts explicitly."
2439
+ );
2440
+ }
2441
+ subtotal = Number(original.subtotal);
2442
+ taxAmount = Number(original.taxAmount);
2443
+ total = Number(original.total);
2444
+ }
2445
+ const buyer = Object.fromEntries(
2446
+ Object.entries({
2447
+ counterpartyName: original.counterpartyName,
2448
+ counterpartyCountry: original.counterpartyCountry,
2449
+ counterpartyVatNumber: original.counterpartyVatNumber,
2450
+ counterpartyRegisterId: original.counterpartyRegisterId,
2451
+ counterpartyAddress: original.counterpartyAddress,
2452
+ counterpartyCity: original.counterpartyCity,
2453
+ counterpartyPostalcode: original.counterpartyPostalcode,
2454
+ counterpartyEmail: original.counterpartyEmail,
2455
+ buyerReference: original.buyerReference
2456
+ }).filter(([, value]) => value !== null && value !== "")
2457
+ );
2458
+ return this.createTransaction({
2459
+ complianceEnrollmentId: original.complianceEnrollmentId,
2460
+ transactionType: original.transactionType,
2461
+ invoiceNumber: input.creditNoteNumber,
2462
+ invoiceDate: input.invoiceDate ?? /* @__PURE__ */ new Date(),
2463
+ subtotal: subtotal ?? 0,
2464
+ total: total ?? 0,
2465
+ invoiceLines,
2466
+ currency: original.currency,
2467
+ ...taxAmount !== void 0 ? { taxAmount } : {},
2468
+ ...buyer,
2469
+ isCreditNote: true,
2470
+ amendedNumber: original.invoiceNumber,
2471
+ ...original.invoiceDate !== null ? { amendedDate: original.invoiceDate } : {},
2472
+ ...input.extraInfo !== void 0 ? { extraInfo: input.extraInfo } : {},
2473
+ ...input.internalReference !== void 0 ? { internalReference: input.internalReference } : {},
2474
+ ...input.submitNow !== void 0 ? { submitNow: input.submitNow } : {},
2475
+ ...input.invoicePdf !== void 0 ? { invoicePdf: input.invoicePdf } : {},
2476
+ ...input.invoicePdfFilename !== void 0 ? { invoicePdfFilename: input.invoicePdfFilename } : {}
2477
+ });
2478
+ }
2166
2479
  /** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country / search / internal reference / provider state. */
2167
2480
  async listTransactions(filters = {}) {
2168
2481
  const params = this.buildTransactionFilterParams(filters);
@@ -2731,6 +3044,26 @@ var EReportingEndpoint = class {
2731
3044
  if (line.taxes.length === 0) {
2732
3045
  throw new TaxoraException(`invoiceLines[${index}].taxes must contain at least one tax.`);
2733
3046
  }
3047
+ line.taxes.forEach((tax, taxIndex) => {
3048
+ const where = `invoiceLines[${index}].taxes[${taxIndex}]`;
3049
+ const category = parseComplianceTaxCategory(tax.category);
3050
+ if (category === null) {
3051
+ throw new TaxoraException(
3052
+ `${where}.category "${String(tax.category)}" is unknown. Valid: ${COMPLIANCE_TAX_CATEGORY_CODES.join(", ")}.`
3053
+ );
3054
+ }
3055
+ if (!Number.isFinite(tax.percent) || tax.percent < 0 || tax.percent > 100) {
3056
+ throw new TaxoraException(`${where}.percent must be between 0 and 100.`);
3057
+ }
3058
+ if (category === "E" && (tax.comment === void 0 || tax.comment.trim() === "")) {
3059
+ throw new TaxoraException(
3060
+ `${where}: an exempt (category E) tax needs the exemption code (VATEX) as comment.`
3061
+ );
3062
+ }
3063
+ if (tax.comment !== void 0 && tax.comment.length > 255) {
3064
+ throw new TaxoraException(`${where}.comment must not exceed 255 characters.`);
3065
+ }
3066
+ });
2734
3067
  });
2735
3068
  }
2736
3069
  validateInvoicePdfFilename(input) {
@@ -2747,12 +3080,65 @@ var EReportingEndpoint = class {
2747
3080
  throw new TaxoraException("internalReference must not exceed 100 characters.");
2748
3081
  }
2749
3082
  }
3083
+ /**
3084
+ * Relations that cannot be right: a due date before the invoice date, a credit note without (or an
3085
+ * invoice with) a corrected invoice, a credit note that reuses the number it corrects, a corrected
3086
+ * invoice dated after the credit note.
3087
+ */
3088
+ validateDocument(input) {
3089
+ for (const [field, value] of [
3090
+ ["subtotal", input.subtotal],
3091
+ ["taxAmount", input.taxAmount],
3092
+ ["total", input.total]
3093
+ ]) {
3094
+ if (value !== void 0 && !Number.isFinite(Number(value))) {
3095
+ throw new TaxoraException(`${field} must be a finite number.`);
3096
+ }
3097
+ }
3098
+ for (const line of input.invoiceLines ?? []) {
3099
+ if (!Number.isFinite(line.quantity) || !Number.isFinite(line.price)) {
3100
+ throw new TaxoraException("Every invoice line needs a numeric quantity and price.");
3101
+ }
3102
+ }
3103
+ const invoiceDate = this.formatDate(input.invoiceDate);
3104
+ if (input.dueDate !== void 0 && this.formatDate(input.dueDate) < invoiceDate) {
3105
+ throw new TaxoraException("dueDate must not be before invoiceDate.");
3106
+ }
3107
+ if (input.counterpartyVatNumber !== void 0 && input.counterpartyVatNumber.length > 50) {
3108
+ throw new TaxoraException("counterpartyVatNumber must not exceed 50 characters.");
3109
+ }
3110
+ const amended = input.amendedNumber?.trim() ?? "";
3111
+ if (input.isCreditNote === true && amended === "") {
3112
+ throw new TaxoraException("A credit note needs amendedNumber, the number of the invoice it corrects.");
3113
+ }
3114
+ if (input.isCreditNote !== true && amended !== "") {
3115
+ throw new TaxoraException("amendedNumber is only for credit notes; set isCreditNote to issue one.");
3116
+ }
3117
+ if (amended !== "" && amended === input.invoiceNumber.trim()) {
3118
+ throw new TaxoraException(
3119
+ "A credit note needs its own number; it cannot reuse the number of the invoice it corrects."
3120
+ );
3121
+ }
3122
+ if (input.amendedDate !== void 0 && this.formatDate(input.amendedDate) > invoiceDate) {
3123
+ throw new TaxoraException("amendedDate (the corrected invoice) must not be after the credit note date.");
3124
+ }
3125
+ }
3126
+ /** A category read back from a stored invoice; one that is not a known code cannot be re-sent. */
3127
+ storedTaxCategory(category) {
3128
+ const parsed = parseComplianceTaxCategory(category);
3129
+ if (parsed === null) {
3130
+ throw new TaxoraException(
3131
+ `The original invoice has an unknown tax category "${String(category)}"; pass invoiceLines and the amounts explicitly.`
3132
+ );
3133
+ }
3134
+ return parsed;
3135
+ }
2750
3136
  validateOptionalCodes(input) {
2751
- if (input.currency !== void 0 && input.currency.length !== 3) {
2752
- throw new TaxoraException("currency must be a 3-character ISO 4217 code.");
3137
+ if (input.currency !== void 0 && !/^[A-Za-z]{3}$/.test(input.currency)) {
3138
+ throw new TaxoraException("currency must be an ISO 4217 code, three letters (e.g. NOK, EUR).");
2753
3139
  }
2754
- if (input.counterpartyCountry !== void 0 && input.counterpartyCountry.length !== 2) {
2755
- throw new TaxoraException("counterpartyCountry must be a 2-character ISO 3166-1 alpha-2 code.");
3140
+ if (input.counterpartyCountry !== void 0 && !/^[A-Za-z]{2}$/.test(input.counterpartyCountry)) {
3141
+ throw new TaxoraException("counterpartyCountry must be an ISO 3166-1 alpha-2 code, two letters (e.g. NO).");
2756
3142
  }
2757
3143
  }
2758
3144
  /**
@@ -2795,7 +3181,7 @@ var EReportingEndpoint = class {
2795
3181
  const taxBuilt = {
2796
3182
  name: tax.name,
2797
3183
  percent: tax.percent,
2798
- category: tax.category
3184
+ category: parseComplianceTaxCategory(tax.category) ?? tax.category
2799
3185
  };
2800
3186
  if (tax.comment !== void 0) taxBuilt["comment"] = tax.comment;
2801
3187
  return taxBuilt;
@@ -2808,10 +3194,10 @@ var EReportingEndpoint = class {
2808
3194
  /** Applies the optional scalar fields shared by create and update. */
2809
3195
  applyOptionalTransactionFields(body, input) {
2810
3196
  if (input.dueDate !== void 0) body["due_date"] = this.formatDate(input.dueDate);
2811
- if (input.currency !== void 0) body["currency"] = input.currency;
3197
+ if (input.currency !== void 0) body["currency"] = input.currency.toUpperCase();
2812
3198
  if (input.taxAmount !== void 0) body["tax_amount"] = input.taxAmount;
2813
3199
  if (input.counterpartyName !== void 0) body["counterparty_name"] = input.counterpartyName;
2814
- if (input.counterpartyCountry !== void 0) body["counterparty_country"] = input.counterpartyCountry;
3200
+ if (input.counterpartyCountry !== void 0) body["counterparty_country"] = input.counterpartyCountry.toUpperCase();
2815
3201
  if (input.counterpartyVatNumber !== void 0) body["counterparty_vat_number"] = input.counterpartyVatNumber;
2816
3202
  if (input.providerContactId !== void 0) body["provider_contact_id"] = input.providerContactId;
2817
3203
  if (input.paymentMethod !== void 0) body["payment_method"] = input.paymentMethod;
@@ -3479,13 +3865,13 @@ var SmartEnrichmentHistoryPage = class _SmartEnrichmentHistoryPage {
3479
3865
  };
3480
3866
 
3481
3867
  // src/dto/SmartEnrichmentStatistics.ts
3482
- function asString11(value, fallback = "") {
3868
+ function asString12(value, fallback = "") {
3483
3869
  return typeof value === "string" ? value : fallback;
3484
3870
  }
3485
3871
  function asNumber7(value) {
3486
3872
  return typeof value === "number" ? value : Number(value ?? 0) || 0;
3487
3873
  }
3488
- function asRecord4(value) {
3874
+ function asRecord5(value) {
3489
3875
  return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
3490
3876
  }
3491
3877
  function asRecords2(value) {
@@ -3508,32 +3894,32 @@ var SmartEnrichmentStatistics = class _SmartEnrichmentStatistics {
3508
3894
  byOutcome;
3509
3895
  confidenceBuckets;
3510
3896
  static fromArray(data) {
3511
- const range = asRecord4(data["range"]);
3512
- const totals = asRecord4(data["totals"]);
3897
+ const range = asRecord5(data["range"]);
3898
+ const totals = asRecord5(data["totals"]);
3513
3899
  const timeSeries = asRecords2(data["time_series"]).map((row) => ({
3514
- bucket: asString11(row["bucket"]),
3900
+ bucket: asString12(row["bucket"]),
3515
3901
  jobs: asNumber7(row["jobs"]),
3516
3902
  items: asNumber7(row["items"]),
3517
3903
  found: asNumber7(row["found"])
3518
3904
  }));
3519
3905
  const bySource = asRecords2(data["by_source"]).map((row) => ({
3520
- source: asString11(row["source"]),
3906
+ source: asString12(row["source"]),
3521
3907
  jobs: asNumber7(row["jobs"]),
3522
3908
  found: asNumber7(row["found"])
3523
3909
  }));
3524
3910
  const byOutcome = asRecords2(data["by_outcome"]).map((row) => ({
3525
- outcome: asString11(row["outcome"]),
3911
+ outcome: asString12(row["outcome"]),
3526
3912
  count: asNumber7(row["count"])
3527
3913
  }));
3528
3914
  const confidenceBuckets = asRecords2(data["confidence_buckets"]).map((row) => ({
3529
- bucket: asString11(row["bucket"]),
3915
+ bucket: asString12(row["bucket"]),
3530
3916
  count: asNumber7(row["count"])
3531
3917
  }));
3532
3918
  return new _SmartEnrichmentStatistics(
3533
3919
  {
3534
- dateFrom: asString11(range["date_from"]),
3535
- dateTo: asString11(range["date_to"]),
3536
- interval: asString11(range["interval"])
3920
+ dateFrom: asString12(range["date_from"]),
3921
+ dateTo: asString12(range["date_to"]),
3922
+ interval: asString12(range["interval"])
3537
3923
  },
3538
3924
  {
3539
3925
  jobs: asNumber7(totals["jobs"]),
@@ -4890,6 +5276,68 @@ var Language = {
4890
5276
  GERMAN: "de"
4891
5277
  };
4892
5278
 
5279
+ // src/support/calculateInvoiceTotals.ts
5280
+ function round2(value) {
5281
+ const magnitude = Math.round(Number((Math.abs(value) * 100).toPrecision(15)));
5282
+ return (value < 0 ? -magnitude : magnitude) / 100;
5283
+ }
5284
+ function calculateInvoiceTotals(lines, options = {}) {
5285
+ let net = 0;
5286
+ let tax = 0;
5287
+ for (const line of lines) {
5288
+ const lineNet = round2(line.quantity * line.price);
5289
+ const percent = line.taxes.reduce((sum, t) => sum + t.percent, 0);
5290
+ net += lineNet;
5291
+ tax += round2(lineNet * percent / 100);
5292
+ }
5293
+ const subtotal = round2(net);
5294
+ const taxAmount = round2(tax);
5295
+ const total = round2(subtotal + taxAmount);
5296
+ let roundingDifference = 0;
5297
+ if (options.expectedTotal !== void 0) {
5298
+ if (!Number.isFinite(options.expectedTotal)) {
5299
+ throw new Error("The expected total must be numeric.");
5300
+ }
5301
+ const tolerance = options.tolerance ?? 0.05;
5302
+ roundingDifference = round2(options.expectedTotal - total);
5303
+ if (Math.abs(roundingDifference) > tolerance) {
5304
+ throw new Error(
5305
+ `The expected total ${options.expectedTotal.toFixed(2)} differs from the invoice lines (${total.toFixed(2)}) by ${roundingDifference.toFixed(2)}, more than the rounding tolerance of ${tolerance.toFixed(2)}. Check quantities, prices and tax rates.`
5306
+ );
5307
+ }
5308
+ }
5309
+ return { subtotal, taxAmount, total, roundingDifference };
5310
+ }
5311
+
5312
+ // src/support/complianceTax.ts
5313
+ var ComplianceTax = {
5314
+ /**
5315
+ * A taxed rate above 0 %, category S (Norway: 25 / 15 / 12 % are all S). Where a country files reduced rates
5316
+ * under their own category (France: AA / AAA), pass it as `category`.
5317
+ */
5318
+ rate(percent, name = "VAT", category = ComplianceTaxCategory.STANDARD) {
5319
+ if (!Number.isFinite(percent) || percent <= 0) {
5320
+ throw new Error("rate() needs a percent above 0; for 0 % use zeroRated(), exempt() or reverseCharge().");
5321
+ }
5322
+ return { name, percent, category };
5323
+ },
5324
+ /** 0 % but taxable (category Z). */
5325
+ zeroRated(name = "VAT") {
5326
+ return { name, percent: 0, category: ComplianceTaxCategory.ZERO };
5327
+ },
5328
+ /** Exempt from VAT (category E); the VATEX exemption code is mandatory. */
5329
+ exempt(exemptionCode, name = "VAT") {
5330
+ if (exemptionCode.trim() === "") {
5331
+ throw new Error("An exempt (category E) tax needs the exemption code (VATEX).");
5332
+ }
5333
+ return { name, percent: 0, category: ComplianceTaxCategory.EXEMPT, comment: exemptionCode };
5334
+ },
5335
+ /** Reverse charge (category AE); the mandatory legal text is added by Taxora. */
5336
+ reverseCharge(name = "VAT") {
5337
+ return { name, percent: 0, category: ComplianceTaxCategory.REVERSE_CHARGE };
5338
+ }
5339
+ };
5340
+
4893
5341
  // src/webhooks/WebhookSignature.ts
4894
5342
  var import_node_crypto = require("crypto");
4895
5343
  var WEBHOOK_SIGNATURE_HEADER = "Taxora-Signature";
@@ -5022,12 +5470,16 @@ function isTransactionBuyerRejected(object) {
5022
5470
  BillingEndpoint,
5023
5471
  CompanyAddress,
5024
5472
  CompanyEndpoint,
5473
+ ComplianceDeliveryAction,
5474
+ ComplianceDeliveryDecision,
5025
5475
  ComplianceDocumentType,
5026
5476
  ComplianceEnrollment,
5027
5477
  ComplianceEnrollmentPage,
5028
5478
  ComplianceEnrollmentStatus,
5029
5479
  ComplianceOfferings,
5030
5480
  ComplianceService,
5481
+ ComplianceTax,
5482
+ ComplianceTaxCategory,
5031
5483
  ComplianceTaxReport,
5032
5484
  ComplianceTaxReportPage,
5033
5485
  ComplianceTaxReportState,
@@ -5036,6 +5488,8 @@ function isTransactionBuyerRejected(object) {
5036
5488
  ComplianceTransactionState,
5037
5489
  ComplianceTransactionType,
5038
5490
  DEFAULT_WEBHOOK_TOLERANCE_SECONDS,
5491
+ EInvoicingQuota,
5492
+ EInvoicingQuotaPeriod,
5039
5493
  EReportingEndpoint,
5040
5494
  Environment,
5041
5495
  FetchHttpClient,
@@ -5083,6 +5537,7 @@ function isTransactionBuyerRejected(object) {
5083
5537
  WEBHOOK_ID_HEADER,
5084
5538
  WEBHOOK_SIGNATURE_HEADER,
5085
5539
  WebhookSignatureVerificationError,
5540
+ calculateInvoiceTotals,
5086
5541
  computeWebhookSignature,
5087
5542
  constructWebhookEvent,
5088
5543
  describeApiError,
@@ -5101,6 +5556,7 @@ function isTransactionBuyerRejected(object) {
5101
5556
  getBaseUrl,
5102
5557
  getFailedVatStates,
5103
5558
  isTransactionBuyerRejected,
5559
+ parseComplianceTaxCategory,
5104
5560
  parseLocalTaxNumbersCsv,
5105
5561
  parseWebhookSignatureHeader,
5106
5562
  toComplianceDocumentType,