@taxora/sdk 1.7.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +84 -0
- package/README.md +205 -4
- package/dist/index.cjs +985 -184
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +564 -16
- package/dist/index.d.ts +564 -16
- package/dist/index.js +978 -184
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -24,12 +24,14 @@ __export(index_exports, {
|
|
|
24
24
|
AuthEndpoint: () => AuthEndpoint,
|
|
25
25
|
AuthRetryHttpClient: () => AuthRetryHttpClient,
|
|
26
26
|
AuthenticationException: () => AuthenticationException,
|
|
27
|
+
BillingEndpoint: () => BillingEndpoint,
|
|
27
28
|
CompanyAddress: () => CompanyAddress,
|
|
28
29
|
CompanyEndpoint: () => CompanyEndpoint,
|
|
29
30
|
ComplianceDocumentType: () => ComplianceDocumentType,
|
|
30
31
|
ComplianceEnrollment: () => ComplianceEnrollment,
|
|
31
32
|
ComplianceEnrollmentPage: () => ComplianceEnrollmentPage,
|
|
32
33
|
ComplianceEnrollmentStatus: () => ComplianceEnrollmentStatus,
|
|
34
|
+
ComplianceOfferings: () => ComplianceOfferings,
|
|
33
35
|
ComplianceService: () => ComplianceService,
|
|
34
36
|
ComplianceTaxReport: () => ComplianceTaxReport,
|
|
35
37
|
ComplianceTaxReportPage: () => ComplianceTaxReportPage,
|
|
@@ -63,6 +65,8 @@ __export(index_exports, {
|
|
|
63
65
|
SmartEnrichmentHistoryRow: () => SmartEnrichmentHistoryRow,
|
|
64
66
|
SmartEnrichmentJob: () => SmartEnrichmentJob,
|
|
65
67
|
SmartEnrichmentMode: () => SmartEnrichmentMode,
|
|
68
|
+
SmartEnrichmentRecheck: () => SmartEnrichmentRecheck,
|
|
69
|
+
SmartEnrichmentRecheckState: () => SmartEnrichmentRecheckState,
|
|
66
70
|
SmartEnrichmentRejectionReason: () => SmartEnrichmentRejectionReason,
|
|
67
71
|
SmartEnrichmentResource: () => SmartEnrichmentResource,
|
|
68
72
|
SmartEnrichmentStatistics: () => SmartEnrichmentStatistics,
|
|
@@ -71,6 +75,8 @@ __export(index_exports, {
|
|
|
71
75
|
TaxoraClientFactory: () => TaxoraClientFactory,
|
|
72
76
|
TaxoraException: () => TaxoraException,
|
|
73
77
|
Token: () => Token,
|
|
78
|
+
UsageSummary: () => UsageSummary,
|
|
79
|
+
UsageSummaryPage: () => UsageSummaryPage,
|
|
74
80
|
ValidationException: () => ValidationException,
|
|
75
81
|
VatCertificateExport: () => VatCertificateExport,
|
|
76
82
|
VatCollection: () => VatCollection,
|
|
@@ -99,6 +105,7 @@ __export(index_exports, {
|
|
|
99
105
|
generateWebhookSignatureHeader: () => generateWebhookSignatureHeader,
|
|
100
106
|
getBaseUrl: () => getBaseUrl,
|
|
101
107
|
getFailedVatStates: () => getFailedVatStates,
|
|
108
|
+
isTransactionBuyerRejected: () => isTransactionBuyerRejected,
|
|
102
109
|
parseLocalTaxNumbersCsv: () => parseLocalTaxNumbersCsv,
|
|
103
110
|
parseWebhookSignatureHeader: () => parseWebhookSignatureHeader,
|
|
104
111
|
toComplianceDocumentType: () => toComplianceDocumentType,
|
|
@@ -557,6 +564,213 @@ var AuthEndpoint = class {
|
|
|
557
564
|
}
|
|
558
565
|
};
|
|
559
566
|
|
|
567
|
+
// src/dto/UsageSummary.ts
|
|
568
|
+
function asRecord(value) {
|
|
569
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
570
|
+
}
|
|
571
|
+
function asRecordList(value) {
|
|
572
|
+
return Array.isArray(value) ? value.filter((row) => asRecord(row) !== null) : [];
|
|
573
|
+
}
|
|
574
|
+
function asString(value, fallback = "") {
|
|
575
|
+
return typeof value === "string" ? value : fallback;
|
|
576
|
+
}
|
|
577
|
+
function asNullableString(value) {
|
|
578
|
+
return typeof value === "string" ? value : null;
|
|
579
|
+
}
|
|
580
|
+
function asNumber(value) {
|
|
581
|
+
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
582
|
+
}
|
|
583
|
+
function asNullableNumber(value) {
|
|
584
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
585
|
+
const num = Number(value);
|
|
586
|
+
return Number.isFinite(num) ? num : null;
|
|
587
|
+
}
|
|
588
|
+
var UsageSummary = class _UsageSummary {
|
|
589
|
+
constructor(id, companyId, feature, country, regime, billingPeriod, eventCount, billableAmount, state, stateLabel, periodClosedAt, billingTriggeredAt, billedAt, stripeInvoiceId, stripeSubscriptionItemId, billingNotes, events, createdAt, updatedAt) {
|
|
590
|
+
this.id = id;
|
|
591
|
+
this.companyId = companyId;
|
|
592
|
+
this.feature = feature;
|
|
593
|
+
this.country = country;
|
|
594
|
+
this.regime = regime;
|
|
595
|
+
this.billingPeriod = billingPeriod;
|
|
596
|
+
this.eventCount = eventCount;
|
|
597
|
+
this.billableAmount = billableAmount;
|
|
598
|
+
this.state = state;
|
|
599
|
+
this.stateLabel = stateLabel;
|
|
600
|
+
this.periodClosedAt = periodClosedAt;
|
|
601
|
+
this.billingTriggeredAt = billingTriggeredAt;
|
|
602
|
+
this.billedAt = billedAt;
|
|
603
|
+
this.stripeInvoiceId = stripeInvoiceId;
|
|
604
|
+
this.stripeSubscriptionItemId = stripeSubscriptionItemId;
|
|
605
|
+
this.billingNotes = billingNotes;
|
|
606
|
+
this.events = events;
|
|
607
|
+
this.createdAt = createdAt;
|
|
608
|
+
this.updatedAt = updatedAt;
|
|
609
|
+
}
|
|
610
|
+
id;
|
|
611
|
+
companyId;
|
|
612
|
+
feature;
|
|
613
|
+
country;
|
|
614
|
+
regime;
|
|
615
|
+
billingPeriod;
|
|
616
|
+
eventCount;
|
|
617
|
+
billableAmount;
|
|
618
|
+
state;
|
|
619
|
+
stateLabel;
|
|
620
|
+
periodClosedAt;
|
|
621
|
+
billingTriggeredAt;
|
|
622
|
+
billedAt;
|
|
623
|
+
stripeInvoiceId;
|
|
624
|
+
stripeSubscriptionItemId;
|
|
625
|
+
billingNotes;
|
|
626
|
+
events;
|
|
627
|
+
createdAt;
|
|
628
|
+
updatedAt;
|
|
629
|
+
static fromArray(data) {
|
|
630
|
+
const amount = data["billable_amount"];
|
|
631
|
+
return new _UsageSummary(
|
|
632
|
+
asNumber(data["id"]),
|
|
633
|
+
asNumber(data["company_id"]),
|
|
634
|
+
asString(data["feature"]),
|
|
635
|
+
asNullableString(data["country"]),
|
|
636
|
+
asNullableString(data["regime"]),
|
|
637
|
+
asString(data["billing_period"]),
|
|
638
|
+
asNumber(data["event_count"]),
|
|
639
|
+
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"]),
|
|
648
|
+
asRecordList(data["events"]).map((event) => ({
|
|
649
|
+
id: asNumber(event["id"]),
|
|
650
|
+
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"]),
|
|
656
|
+
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"])
|
|
660
|
+
})),
|
|
661
|
+
asNullableString(data["created_at"]),
|
|
662
|
+
asNullableString(data["updated_at"])
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
var UsageSummaryPage = class _UsageSummaryPage {
|
|
667
|
+
constructor(rows, currentPage, perPage, total, lastPage) {
|
|
668
|
+
this.rows = rows;
|
|
669
|
+
this.currentPage = currentPage;
|
|
670
|
+
this.perPage = perPage;
|
|
671
|
+
this.total = total;
|
|
672
|
+
this.lastPage = lastPage;
|
|
673
|
+
}
|
|
674
|
+
rows;
|
|
675
|
+
currentPage;
|
|
676
|
+
perPage;
|
|
677
|
+
total;
|
|
678
|
+
lastPage;
|
|
679
|
+
static fromResponse(payload) {
|
|
680
|
+
const obj = asRecord(payload) ?? {};
|
|
681
|
+
const rows = asRecordList(obj["data"]).map(UsageSummary.fromArray);
|
|
682
|
+
const meta = asRecord(obj["meta"]) ?? {};
|
|
683
|
+
const num = (value, fallback) => typeof value === "number" ? value : fallback;
|
|
684
|
+
return new _UsageSummaryPage(
|
|
685
|
+
rows,
|
|
686
|
+
num(meta["current_page"], 1),
|
|
687
|
+
num(meta["per_page"], rows.length),
|
|
688
|
+
num(meta["total"], rows.length),
|
|
689
|
+
num(meta["last_page"], 1)
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
[Symbol.iterator]() {
|
|
693
|
+
return this.rows[Symbol.iterator]();
|
|
694
|
+
}
|
|
695
|
+
get length() {
|
|
696
|
+
return this.rows.length;
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
|
|
700
|
+
// src/endpoints/BillingEndpoint.ts
|
|
701
|
+
var PERIOD_REGEX = /^\d{4}-(0[1-9]|1[0-2])$/;
|
|
702
|
+
var BillingEndpoint = class {
|
|
703
|
+
constructor(baseUrl, apiKey, tokenStorage, httpClient, retryPolicy = new RetryPolicy()) {
|
|
704
|
+
this.baseUrl = baseUrl;
|
|
705
|
+
this.apiKey = apiKey;
|
|
706
|
+
this.tokenStorage = tokenStorage;
|
|
707
|
+
this.httpClient = httpClient;
|
|
708
|
+
this.retryPolicy = retryPolicy;
|
|
709
|
+
}
|
|
710
|
+
baseUrl;
|
|
711
|
+
apiKey;
|
|
712
|
+
tokenStorage;
|
|
713
|
+
httpClient;
|
|
714
|
+
retryPolicy;
|
|
715
|
+
/** Paginated usage summaries, newest billing period first. `perPage` is clamped to 1-100 server-side. */
|
|
716
|
+
async listUsageSummaries(page = 1, perPage = 25) {
|
|
717
|
+
const params = new URLSearchParams();
|
|
718
|
+
params.set("page", String(page));
|
|
719
|
+
params.set("per_page", String(perPage));
|
|
720
|
+
const data = await this.getJson(`${this.baseUrl}/billing/usage-summaries?${params.toString()}`);
|
|
721
|
+
return UsageSummaryPage.fromResponse(data);
|
|
722
|
+
}
|
|
723
|
+
/**
|
|
724
|
+
* The usage summaries of one billing period (YYYY-MM), one per feature,
|
|
725
|
+
* each with its usage events. A period without usage yields a 404 (HttpException).
|
|
726
|
+
*/
|
|
727
|
+
async getUsageSummaries(period) {
|
|
728
|
+
if (!PERIOD_REGEX.test(period)) {
|
|
729
|
+
throw new TaxoraException(`Invalid billing period "${period}". Expected YYYY-MM, e.g. "2026-09".`);
|
|
730
|
+
}
|
|
731
|
+
const data = await this.getJson(`${this.baseUrl}/billing/usage-summaries/${period}`);
|
|
732
|
+
return Array.isArray(data) ? data.filter((row) => typeof row === "object" && row !== null).map(UsageSummary.fromArray) : [];
|
|
733
|
+
}
|
|
734
|
+
buildHeaders() {
|
|
735
|
+
const headers = {
|
|
736
|
+
"Content-Type": "application/json",
|
|
737
|
+
"x-api-key": this.apiKey
|
|
738
|
+
};
|
|
739
|
+
const token = this.tokenStorage.get();
|
|
740
|
+
if (token) {
|
|
741
|
+
headers["Authorization"] = `Bearer ${token.accessToken}`;
|
|
742
|
+
}
|
|
743
|
+
return headers;
|
|
744
|
+
}
|
|
745
|
+
/** GET + envelope unwrap (`{success, data}` → data, which may be an object or an array). */
|
|
746
|
+
async getJson(url) {
|
|
747
|
+
return withRetries(this.retryPolicy, "billing request", async () => {
|
|
748
|
+
const response = await this.httpClient.request("GET", url, { headers: this.buildHeaders() });
|
|
749
|
+
const responseText = await response.text();
|
|
750
|
+
if (!response.ok) {
|
|
751
|
+
throw new HttpException(
|
|
752
|
+
describeApiError(responseText, response.status),
|
|
753
|
+
response.status,
|
|
754
|
+
responseText,
|
|
755
|
+
{},
|
|
756
|
+
response.headers.get("retry-after")
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
let parsed;
|
|
760
|
+
try {
|
|
761
|
+
parsed = JSON.parse(responseText);
|
|
762
|
+
} catch {
|
|
763
|
+
throw new HttpException("Invalid JSON response", response.status, responseText);
|
|
764
|
+
}
|
|
765
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
766
|
+
throw new HttpException("Unexpected response format", response.status, responseText);
|
|
767
|
+
}
|
|
768
|
+
const obj = parsed;
|
|
769
|
+
return obj["data"] !== void 0 && obj["data"] !== null ? obj["data"] : obj;
|
|
770
|
+
});
|
|
771
|
+
}
|
|
772
|
+
};
|
|
773
|
+
|
|
560
774
|
// src/dto/CompanyResource.ts
|
|
561
775
|
function normalizeCompanyResource(data) {
|
|
562
776
|
const apiRateLimit = typeof data["api_rate_limit"] === "number" ? data["api_rate_limit"] : void 0;
|
|
@@ -683,13 +897,13 @@ function describeComplianceService(service) {
|
|
|
683
897
|
}
|
|
684
898
|
|
|
685
899
|
// src/dto/ComplianceEnrollment.ts
|
|
686
|
-
function
|
|
900
|
+
function asString2(value, fallback = "") {
|
|
687
901
|
return typeof value === "string" ? value : fallback;
|
|
688
902
|
}
|
|
689
|
-
function
|
|
903
|
+
function asNullableString2(value) {
|
|
690
904
|
return typeof value === "string" ? value : null;
|
|
691
905
|
}
|
|
692
|
-
function
|
|
906
|
+
function asNumber2(value) {
|
|
693
907
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
694
908
|
}
|
|
695
909
|
var ComplianceEnrollment = class _ComplianceEnrollment {
|
|
@@ -736,29 +950,114 @@ var ComplianceEnrollment = class _ComplianceEnrollment {
|
|
|
736
950
|
static fromArray(data) {
|
|
737
951
|
const regimeConfig = typeof data["regime_config"] === "object" && data["regime_config"] !== null && !Array.isArray(data["regime_config"]) ? data["regime_config"] : null;
|
|
738
952
|
return new _ComplianceEnrollment(
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
953
|
+
asNumber2(data["id"]),
|
|
954
|
+
asNumber2(data["company_id"]),
|
|
955
|
+
asString2(data["country"]),
|
|
956
|
+
asString2(data["regime"]),
|
|
957
|
+
asString2(data["provider"]),
|
|
744
958
|
toComplianceEnrollmentStatus(data["status"]),
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
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"]),
|
|
751
965
|
regimeConfig,
|
|
752
|
-
|
|
753
|
-
|
|
966
|
+
asNullableString2(data["reporting_start_date"]),
|
|
967
|
+
asNullableString2(data["notification_email"]),
|
|
754
968
|
data["auto_send"] === true,
|
|
755
|
-
|
|
756
|
-
|
|
969
|
+
asNullableString2(data["created_at"]),
|
|
970
|
+
asNullableString2(data["updated_at"]),
|
|
757
971
|
toComplianceService(data["service"])
|
|
758
972
|
);
|
|
759
973
|
}
|
|
760
974
|
};
|
|
761
975
|
|
|
976
|
+
// src/dto/ComplianceOfferings.ts
|
|
977
|
+
function asRecord2(value) {
|
|
978
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
979
|
+
}
|
|
980
|
+
function asRecordList2(value) {
|
|
981
|
+
return Array.isArray(value) ? value.filter((row) => asRecord2(row) !== null) : [];
|
|
982
|
+
}
|
|
983
|
+
function asString3(value, fallback = "") {
|
|
984
|
+
return typeof value === "string" ? value : fallback;
|
|
985
|
+
}
|
|
986
|
+
function asNullableString3(value) {
|
|
987
|
+
return typeof value === "string" ? value : null;
|
|
988
|
+
}
|
|
989
|
+
function asNullableNumber2(value) {
|
|
990
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
991
|
+
if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
|
|
992
|
+
return null;
|
|
993
|
+
}
|
|
994
|
+
function asStringList(value) {
|
|
995
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
996
|
+
}
|
|
997
|
+
function toRequires(value) {
|
|
998
|
+
const record = asRecord2(value);
|
|
999
|
+
return record === null ? null : { country: asString3(record["country"]), service: asString3(record["service"]) };
|
|
1000
|
+
}
|
|
1001
|
+
var ComplianceOfferings = class _ComplianceOfferings {
|
|
1002
|
+
constructor(offerings, coverage, access, accessByCountry) {
|
|
1003
|
+
this.offerings = offerings;
|
|
1004
|
+
this.coverage = coverage;
|
|
1005
|
+
this.access = access;
|
|
1006
|
+
this.accessByCountry = accessByCountry;
|
|
1007
|
+
}
|
|
1008
|
+
offerings;
|
|
1009
|
+
coverage;
|
|
1010
|
+
access;
|
|
1011
|
+
accessByCountry;
|
|
1012
|
+
static fromArray(data) {
|
|
1013
|
+
const offerings = asRecordList2(data["data"]).map((row) => ({
|
|
1014
|
+
country: asString3(row["country"]),
|
|
1015
|
+
service: asString3(row["service"]),
|
|
1016
|
+
currency: asString3(row["currency"], "EUR"),
|
|
1017
|
+
active: row["active"] === true,
|
|
1018
|
+
viaStripe: row["via_stripe"] === true,
|
|
1019
|
+
plan: asNullableString3(row["plan"]),
|
|
1020
|
+
status: asNullableString3(row["status"]),
|
|
1021
|
+
enrolled: row["enrolled"] === true,
|
|
1022
|
+
plans: asRecordList2(row["plans"]).map((plan) => ({
|
|
1023
|
+
key: asString3(plan["key"]),
|
|
1024
|
+
monthlyFee: asNullableNumber2(plan["monthly_fee"]),
|
|
1025
|
+
setupFee: asNullableNumber2(plan["setup_fee"]),
|
|
1026
|
+
usageTiers: Array.isArray(plan["usage_tiers"]) ? plan["usage_tiers"] : [],
|
|
1027
|
+
volumeLimit: plan["volume_limit"] ?? null,
|
|
1028
|
+
contactOnly: plan["contact_only"] === true,
|
|
1029
|
+
checkoutAvailable: plan["checkout_available"] === true,
|
|
1030
|
+
requires: toRequires(plan["requires"]),
|
|
1031
|
+
eligible: plan["eligible"] === true
|
|
1032
|
+
}))
|
|
1033
|
+
}));
|
|
1034
|
+
const coverage = asRecordList2(data["coverage"]).map((row) => ({
|
|
1035
|
+
country: asString3(row["country"]),
|
|
1036
|
+
availability: asString3(row["availability"]),
|
|
1037
|
+
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")
|
|
1042
|
+
}));
|
|
1043
|
+
const access = asRecord2(data["access"]) ?? {};
|
|
1044
|
+
const accessByCountry = {};
|
|
1045
|
+
for (const [country, services] of Object.entries(asRecord2(data["access_by_country"]) ?? {})) {
|
|
1046
|
+
const flags = {};
|
|
1047
|
+
for (const [service, value] of Object.entries(asRecord2(services) ?? {})) {
|
|
1048
|
+
flags[service] = value === true;
|
|
1049
|
+
}
|
|
1050
|
+
accessByCountry[country] = flags;
|
|
1051
|
+
}
|
|
1052
|
+
return new _ComplianceOfferings(
|
|
1053
|
+
offerings,
|
|
1054
|
+
coverage,
|
|
1055
|
+
{ eReporting: access["e_reporting"] === true, eInvoicing: access["e_invoicing"] === true },
|
|
1056
|
+
accessByCountry
|
|
1057
|
+
);
|
|
1058
|
+
}
|
|
1059
|
+
};
|
|
1060
|
+
|
|
762
1061
|
// src/dto/ComplianceEnrollmentPage.ts
|
|
763
1062
|
var ComplianceEnrollmentPage = class _ComplianceEnrollmentPage {
|
|
764
1063
|
constructor(rows, currentPage, perPage, total, lastPage) {
|
|
@@ -828,16 +1127,16 @@ function describeComplianceTaxReportState(state) {
|
|
|
828
1127
|
}
|
|
829
1128
|
|
|
830
1129
|
// src/dto/ComplianceTaxReport.ts
|
|
831
|
-
function
|
|
1130
|
+
function asString4(value, fallback = "") {
|
|
832
1131
|
return typeof value === "string" ? value : fallback;
|
|
833
1132
|
}
|
|
834
|
-
function
|
|
1133
|
+
function asNullableString4(value) {
|
|
835
1134
|
return typeof value === "string" ? value : null;
|
|
836
1135
|
}
|
|
837
|
-
function
|
|
1136
|
+
function asNumber3(value) {
|
|
838
1137
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
839
1138
|
}
|
|
840
|
-
function
|
|
1139
|
+
function asNullableNumber3(value) {
|
|
841
1140
|
return typeof value === "number" ? value : null;
|
|
842
1141
|
}
|
|
843
1142
|
function asMoney(value) {
|
|
@@ -888,25 +1187,25 @@ var ComplianceTaxReport = class _ComplianceTaxReport {
|
|
|
888
1187
|
updatedAt;
|
|
889
1188
|
static fromArray(data) {
|
|
890
1189
|
return new _ComplianceTaxReport(
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
1190
|
+
asNumber3(data["id"]),
|
|
1191
|
+
asNumber3(data["company_id"]),
|
|
1192
|
+
asNullableNumber3(data["compliance_transaction_id"]),
|
|
1193
|
+
asNullableNumber3(data["ledger_id"]),
|
|
1194
|
+
asString4(data["country"]),
|
|
1195
|
+
asString4(data["regime"]),
|
|
897
1196
|
toComplianceTaxReportState(data["state"]),
|
|
898
|
-
|
|
1197
|
+
asString4(data["state_label"]),
|
|
899
1198
|
data["is_terminal"] === true,
|
|
900
|
-
|
|
901
|
-
|
|
1199
|
+
asNullableString4(data["provider_tax_report_id"]),
|
|
1200
|
+
asNullableString4(data["provider_ledger_id"]),
|
|
902
1201
|
asMoney(data["base_amount"]),
|
|
903
1202
|
asMoney(data["tax_amount"]),
|
|
904
1203
|
asMoney(data["total_amount"]),
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
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"])
|
|
910
1209
|
);
|
|
911
1210
|
}
|
|
912
1211
|
};
|
|
@@ -977,6 +1276,8 @@ var ComplianceTransactionState = {
|
|
|
977
1276
|
SENDING: "sending",
|
|
978
1277
|
SUBMITTED: "submitted",
|
|
979
1278
|
ERROR: "error",
|
|
1279
|
+
/** E-invoicing only: the buyer cannot receive e-invoices — nothing was sent or billed; send your regular invoice. */
|
|
1280
|
+
NOT_REQUIRED: "not_required",
|
|
980
1281
|
UNKNOWN: "unknown"
|
|
981
1282
|
};
|
|
982
1283
|
var VALUES5 = Object.values(ComplianceTransactionState);
|
|
@@ -994,6 +1295,7 @@ var DESCRIPTIONS5 = {
|
|
|
994
1295
|
[ComplianceTransactionState.SENDING]: "Submission to the provider in progress.",
|
|
995
1296
|
[ComplianceTransactionState.SUBMITTED]: "Successfully submitted to the provider.",
|
|
996
1297
|
[ComplianceTransactionState.ERROR]: "Submission failed. See submissionError.",
|
|
1298
|
+
[ComplianceTransactionState.NOT_REQUIRED]: "The buyer cannot receive e-invoices, so none was sent or billed. Send your regular invoice instead.",
|
|
997
1299
|
[ComplianceTransactionState.UNKNOWN]: "Unknown state."
|
|
998
1300
|
};
|
|
999
1301
|
function describeComplianceTransactionState(state) {
|
|
@@ -1032,13 +1334,13 @@ function describeComplianceTransactionType(type) {
|
|
|
1032
1334
|
}
|
|
1033
1335
|
|
|
1034
1336
|
// src/dto/ComplianceTransaction.ts
|
|
1035
|
-
function
|
|
1337
|
+
function asString5(value, fallback = "") {
|
|
1036
1338
|
return typeof value === "string" ? value : fallback;
|
|
1037
1339
|
}
|
|
1038
|
-
function
|
|
1340
|
+
function asNullableString5(value) {
|
|
1039
1341
|
return typeof value === "string" ? value : null;
|
|
1040
1342
|
}
|
|
1041
|
-
function
|
|
1343
|
+
function asNumber4(value) {
|
|
1042
1344
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
1043
1345
|
}
|
|
1044
1346
|
function asMoney2(value) {
|
|
@@ -1046,34 +1348,55 @@ function asMoney2(value) {
|
|
|
1046
1348
|
if (typeof value === "number" && Number.isFinite(value)) return String(value);
|
|
1047
1349
|
return "0.00";
|
|
1048
1350
|
}
|
|
1049
|
-
function
|
|
1351
|
+
function asNullableNumber4(value) {
|
|
1050
1352
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
1051
1353
|
if (typeof value === "string" && value.trim() !== "" && Number.isFinite(Number(value))) return Number(value);
|
|
1052
1354
|
return null;
|
|
1053
1355
|
}
|
|
1054
|
-
function
|
|
1356
|
+
function asRecord3(value) {
|
|
1055
1357
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
1056
1358
|
}
|
|
1057
|
-
function
|
|
1058
|
-
return Array.isArray(value) ? value.filter((row) =>
|
|
1359
|
+
function asRecordList3(value) {
|
|
1360
|
+
return Array.isArray(value) ? value.filter((row) => asRecord3(row) !== null) : [];
|
|
1361
|
+
}
|
|
1362
|
+
function toInvoicePdf(value) {
|
|
1363
|
+
const pdf = asRecord3(value);
|
|
1364
|
+
if (pdf === null) return null;
|
|
1365
|
+
return {
|
|
1366
|
+
filename: asNullableString5(pdf["filename"]),
|
|
1367
|
+
size: asNullableNumber4(pdf["size"]),
|
|
1368
|
+
attached: pdf["attached"] === true
|
|
1369
|
+
};
|
|
1370
|
+
}
|
|
1371
|
+
function toEurEquivalent(value) {
|
|
1372
|
+
const eur = asRecord3(value);
|
|
1373
|
+
if (eur === null) return null;
|
|
1374
|
+
return {
|
|
1375
|
+
subtotal: asMoney2(eur["subtotal"]),
|
|
1376
|
+
taxAmount: asMoney2(eur["tax_amount"]),
|
|
1377
|
+
total: asMoney2(eur["total"]),
|
|
1378
|
+
rate: asString5(eur["rate"]),
|
|
1379
|
+
rateDate: asNullableString5(eur["rate_date"]),
|
|
1380
|
+
source: asString5(eur["source"], "ECB")
|
|
1381
|
+
};
|
|
1059
1382
|
}
|
|
1060
1383
|
function toInvoiceLines(providerPayload) {
|
|
1061
|
-
const invoice =
|
|
1062
|
-
return
|
|
1063
|
-
description:
|
|
1064
|
-
quantity:
|
|
1384
|
+
const invoice = asRecord3(asRecord3(providerPayload)?.["invoice"]);
|
|
1385
|
+
return asRecordList3(invoice?.["invoice_lines_attributes"]).map((line) => ({
|
|
1386
|
+
description: asString5(line["description"]),
|
|
1387
|
+
quantity: asNullableNumber4(line["quantity"]),
|
|
1065
1388
|
price: asMoney2(line["price"]),
|
|
1066
|
-
unit:
|
|
1067
|
-
taxes:
|
|
1068
|
-
name:
|
|
1069
|
-
percent:
|
|
1070
|
-
category:
|
|
1071
|
-
comment:
|
|
1389
|
+
unit: asNullableNumber4(line["unit"]),
|
|
1390
|
+
taxes: asRecordList3(line["taxes_attributes"]).map((tax) => ({
|
|
1391
|
+
name: asString5(tax["name"]),
|
|
1392
|
+
percent: asNullableNumber4(tax["percent"]),
|
|
1393
|
+
category: asNullableString5(tax["category"]),
|
|
1394
|
+
comment: asNullableString5(tax["comment"])
|
|
1072
1395
|
}))
|
|
1073
1396
|
}));
|
|
1074
1397
|
}
|
|
1075
1398
|
var ComplianceTransaction = class _ComplianceTransaction {
|
|
1076
|
-
constructor(id, companyId, complianceEnrollmentId, country, regime, transactionType, transactionTypeLabel, state, stateLabel, invoiceNumber, invoiceDate, dueDate, currency, subtotal, taxAmount, total, counterpartyName, counterpartyCountry, counterpartyVatNumber, isPaid, paidAt, providerInvoiceId, submissionError, reportedAt, taxReport, createdAt, updatedAt, counterpartyRegisterId = null, counterpartyAddress = null, counterpartyCity = null, counterpartyPostalcode = null, counterpartyEmail = null, buyerReference = null, documentType = ComplianceDocumentType.INVOICE, amendedNumber = null, amendedDate = null, providerState = null, invoiceLines = []) {
|
|
1399
|
+
constructor(id, companyId, complianceEnrollmentId, country, regime, transactionType, transactionTypeLabel, state, stateLabel, invoiceNumber, invoiceDate, dueDate, currency, subtotal, taxAmount, total, counterpartyName, counterpartyCountry, counterpartyVatNumber, isPaid, paidAt, providerInvoiceId, submissionError, reportedAt, taxReport, createdAt, updatedAt, counterpartyRegisterId = null, counterpartyAddress = null, counterpartyCity = null, counterpartyPostalcode = null, counterpartyEmail = null, buyerReference = null, documentType = ComplianceDocumentType.INVOICE, amendedNumber = null, amendedDate = null, providerState = null, invoiceLines = [], documentUrl = null, deliveryCheck = null, invoicePdf = null, internalReference = null, pdfUrl = null, buyerRejected = false, rejectionReason = null, eurEquivalent = null) {
|
|
1077
1400
|
this.id = id;
|
|
1078
1401
|
this.companyId = companyId;
|
|
1079
1402
|
this.complianceEnrollmentId = complianceEnrollmentId;
|
|
@@ -1112,6 +1435,14 @@ var ComplianceTransaction = class _ComplianceTransaction {
|
|
|
1112
1435
|
this.amendedDate = amendedDate;
|
|
1113
1436
|
this.providerState = providerState;
|
|
1114
1437
|
this.invoiceLines = invoiceLines;
|
|
1438
|
+
this.documentUrl = documentUrl;
|
|
1439
|
+
this.deliveryCheck = deliveryCheck;
|
|
1440
|
+
this.invoicePdf = invoicePdf;
|
|
1441
|
+
this.internalReference = internalReference;
|
|
1442
|
+
this.pdfUrl = pdfUrl;
|
|
1443
|
+
this.buyerRejected = buyerRejected;
|
|
1444
|
+
this.rejectionReason = rejectionReason;
|
|
1445
|
+
this.eurEquivalent = eurEquivalent;
|
|
1115
1446
|
}
|
|
1116
1447
|
id;
|
|
1117
1448
|
companyId;
|
|
@@ -1151,50 +1482,66 @@ var ComplianceTransaction = class _ComplianceTransaction {
|
|
|
1151
1482
|
amendedDate;
|
|
1152
1483
|
providerState;
|
|
1153
1484
|
invoiceLines;
|
|
1485
|
+
documentUrl;
|
|
1486
|
+
deliveryCheck;
|
|
1487
|
+
invoicePdf;
|
|
1488
|
+
internalReference;
|
|
1489
|
+
pdfUrl;
|
|
1490
|
+
buyerRejected;
|
|
1491
|
+
rejectionReason;
|
|
1492
|
+
eurEquivalent;
|
|
1154
1493
|
get isCreditNote() {
|
|
1155
1494
|
return this.documentType === ComplianceDocumentType.CREDIT_NOTE;
|
|
1156
1495
|
}
|
|
1157
1496
|
static fromArray(data) {
|
|
1158
1497
|
const taxReport = typeof data["tax_report"] === "object" && data["tax_report"] !== null && !Array.isArray(data["tax_report"]) ? ComplianceTaxReport.fromArray(data["tax_report"]) : void 0;
|
|
1159
1498
|
return new _ComplianceTransaction(
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1499
|
+
asNumber4(data["id"]),
|
|
1500
|
+
asNumber4(data["company_id"]),
|
|
1501
|
+
asNumber4(data["compliance_enrollment_id"]),
|
|
1502
|
+
asString5(data["country"]),
|
|
1503
|
+
asString5(data["regime"]),
|
|
1165
1504
|
toComplianceTransactionType(data["transaction_type"]),
|
|
1166
|
-
|
|
1505
|
+
asString5(data["transaction_type_label"]),
|
|
1167
1506
|
toComplianceTransactionState(data["state"]),
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
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"),
|
|
1173
1512
|
asMoney2(data["subtotal"]),
|
|
1174
1513
|
asMoney2(data["tax_amount"]),
|
|
1175
1514
|
asMoney2(data["total"]),
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1515
|
+
asNullableString5(data["counterparty_name"]),
|
|
1516
|
+
asNullableString5(data["counterparty_country"]),
|
|
1517
|
+
asNullableString5(data["counterparty_vat_number"]),
|
|
1179
1518
|
data["is_paid"] === true,
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1519
|
+
asNullableString5(data["paid_at"]),
|
|
1520
|
+
asNullableString5(data["provider_invoice_id"]),
|
|
1521
|
+
asNullableString5(data["submission_error"]),
|
|
1522
|
+
asNullableString5(data["reported_at"]),
|
|
1184
1523
|
taxReport,
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
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"]),
|
|
1193
1532
|
data["document_type"] === void 0 || data["document_type"] === null ? ComplianceDocumentType.INVOICE : toComplianceDocumentType(data["document_type"]),
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
toInvoiceLines(data["provider_payload"])
|
|
1533
|
+
asNullableString5(data["amended_number"]),
|
|
1534
|
+
asNullableString5(data["amended_date"]),
|
|
1535
|
+
asNullableString5(data["provider_state"]),
|
|
1536
|
+
toInvoiceLines(data["provider_payload"]),
|
|
1537
|
+
asNullableString5(data["document_url"]),
|
|
1538
|
+
asRecord3(data["delivery_check"]),
|
|
1539
|
+
toInvoicePdf(data["invoice_pdf"]),
|
|
1540
|
+
asNullableString5(data["internal_reference"]),
|
|
1541
|
+
asNullableString5(data["pdf_url"]),
|
|
1542
|
+
data["buyer_rejected"] === true,
|
|
1543
|
+
asNullableString5(data["rejection_reason"]),
|
|
1544
|
+
toEurEquivalent(data["eur_equivalent"])
|
|
1198
1545
|
);
|
|
1199
1546
|
}
|
|
1200
1547
|
};
|
|
@@ -1281,10 +1628,10 @@ function describePeppolLookupStatus(status) {
|
|
|
1281
1628
|
}
|
|
1282
1629
|
|
|
1283
1630
|
// src/dto/PeppolLookupResult.ts
|
|
1284
|
-
function
|
|
1631
|
+
function asString6(value, fallback = "") {
|
|
1285
1632
|
return typeof value === "string" ? value : fallback;
|
|
1286
1633
|
}
|
|
1287
|
-
function
|
|
1634
|
+
function asNullableString6(value) {
|
|
1288
1635
|
return typeof value === "string" ? value : null;
|
|
1289
1636
|
}
|
|
1290
1637
|
var PeppolLookupResult = class _PeppolLookupResult {
|
|
@@ -1315,21 +1662,21 @@ var PeppolLookupResult = class _PeppolLookupResult {
|
|
|
1315
1662
|
return new _PeppolLookupResult(
|
|
1316
1663
|
toPeppolLookupStatus(data["status"]),
|
|
1317
1664
|
typeof data["reachable"] === "boolean" ? data["reachable"] : null,
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1665
|
+
asString6(data["country"]),
|
|
1666
|
+
asString6(data["scheme"]),
|
|
1667
|
+
asString6(data["id"]),
|
|
1321
1668
|
documentTypes,
|
|
1322
|
-
|
|
1323
|
-
|
|
1669
|
+
asNullableString6(data["transport_type_code"]),
|
|
1670
|
+
asNullableString6(data["checked_at"])
|
|
1324
1671
|
);
|
|
1325
1672
|
}
|
|
1326
1673
|
};
|
|
1327
1674
|
|
|
1328
1675
|
// src/dto/RegistryCompany.ts
|
|
1329
|
-
function
|
|
1676
|
+
function asString7(value, fallback = "") {
|
|
1330
1677
|
return typeof value === "string" ? value : fallback;
|
|
1331
1678
|
}
|
|
1332
|
-
function
|
|
1679
|
+
function asNullableString7(value) {
|
|
1333
1680
|
return typeof value === "string" ? value : null;
|
|
1334
1681
|
}
|
|
1335
1682
|
var RegistryCompany = class _RegistryCompany {
|
|
@@ -1361,27 +1708,27 @@ var RegistryCompany = class _RegistryCompany {
|
|
|
1361
1708
|
country;
|
|
1362
1709
|
static fromArray(data) {
|
|
1363
1710
|
return new _RegistryCompany(
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1711
|
+
asString7(data["org_number"]),
|
|
1712
|
+
asString7(data["company_name"]),
|
|
1713
|
+
asNullableString7(data["organisation_form"]),
|
|
1367
1714
|
data["vat_registered"] === true,
|
|
1368
|
-
|
|
1715
|
+
asNullableString7(data["vat_number"]),
|
|
1369
1716
|
data["enterprise_register"] === true,
|
|
1370
1717
|
data["bankrupt"] === true,
|
|
1371
1718
|
data["under_liquidation"] === true,
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1719
|
+
asNullableString7(data["address"]),
|
|
1720
|
+
asNullableString7(data["postalcode"]),
|
|
1721
|
+
asNullableString7(data["city"]),
|
|
1722
|
+
asString7(data["country"])
|
|
1376
1723
|
);
|
|
1377
1724
|
}
|
|
1378
1725
|
};
|
|
1379
1726
|
|
|
1380
1727
|
// src/dto/RevenueStatistics.ts
|
|
1381
|
-
function
|
|
1728
|
+
function asString8(value, fallback = "") {
|
|
1382
1729
|
return typeof value === "string" ? value : fallback;
|
|
1383
1730
|
}
|
|
1384
|
-
function
|
|
1731
|
+
function asNumber5(value) {
|
|
1385
1732
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
1386
1733
|
}
|
|
1387
1734
|
function asMoney3(value) {
|
|
@@ -1393,7 +1740,7 @@ function asRecords(value) {
|
|
|
1393
1740
|
}
|
|
1394
1741
|
function toTotals(data) {
|
|
1395
1742
|
return {
|
|
1396
|
-
count:
|
|
1743
|
+
count: asNumber5(data["count"]),
|
|
1397
1744
|
subtotal: asMoney3(data["subtotal"]),
|
|
1398
1745
|
taxAmount: asMoney3(data["tax_amount"]),
|
|
1399
1746
|
total: asMoney3(data["total"])
|
|
@@ -1430,35 +1777,35 @@ var RevenueStatistics = class _RevenueStatistics {
|
|
|
1430
1777
|
typeof data["totals"] === "object" && data["totals"] !== null ? data["totals"] : {}
|
|
1431
1778
|
);
|
|
1432
1779
|
const timeSeries = asRecords(data["time_series"]).map((row) => ({
|
|
1433
|
-
bucket:
|
|
1780
|
+
bucket: asString8(row["bucket"]),
|
|
1434
1781
|
...toTotals(row)
|
|
1435
1782
|
}));
|
|
1436
1783
|
const byType = asRecords(data["by_type"]).map((row) => ({
|
|
1437
|
-
type:
|
|
1438
|
-
typeLabel:
|
|
1439
|
-
count:
|
|
1784
|
+
type: asString8(row["type"]),
|
|
1785
|
+
typeLabel: asString8(row["type_label"]),
|
|
1786
|
+
count: asNumber5(row["count"]),
|
|
1440
1787
|
total: asMoney3(row["total"])
|
|
1441
1788
|
}));
|
|
1442
1789
|
const byCountry = asRecords(data["by_country"]).map((row) => ({
|
|
1443
|
-
country:
|
|
1444
|
-
count:
|
|
1790
|
+
country: asString8(row["country"], "unknown"),
|
|
1791
|
+
count: asNumber5(row["count"]),
|
|
1445
1792
|
total: asMoney3(row["total"])
|
|
1446
1793
|
}));
|
|
1447
1794
|
const byState = asRecords(data["by_state"]).map((row) => ({
|
|
1448
|
-
state:
|
|
1449
|
-
stateLabel:
|
|
1450
|
-
count:
|
|
1795
|
+
state: asString8(row["state"]),
|
|
1796
|
+
stateLabel: asString8(row["state_label"]),
|
|
1797
|
+
count: asNumber5(row["count"]),
|
|
1451
1798
|
total: asMoney3(row["total"])
|
|
1452
1799
|
}));
|
|
1453
1800
|
const byCurrency = asRecords(data["by_currency"]).map((row) => ({
|
|
1454
|
-
currency:
|
|
1801
|
+
currency: asString8(row["currency"]),
|
|
1455
1802
|
...toTotals(row)
|
|
1456
1803
|
}));
|
|
1457
1804
|
return new _RevenueStatistics(
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
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"),
|
|
1462
1809
|
data["is_multi_currency"] === true,
|
|
1463
1810
|
totals,
|
|
1464
1811
|
timeSeries,
|
|
@@ -1471,10 +1818,10 @@ var RevenueStatistics = class _RevenueStatistics {
|
|
|
1471
1818
|
};
|
|
1472
1819
|
|
|
1473
1820
|
// src/dto/SireneLookupResult.ts
|
|
1474
|
-
function
|
|
1821
|
+
function asString9(value, fallback = "") {
|
|
1475
1822
|
return typeof value === "string" ? value : fallback;
|
|
1476
1823
|
}
|
|
1477
|
-
function
|
|
1824
|
+
function asNullableString8(value) {
|
|
1478
1825
|
return typeof value === "string" ? value : null;
|
|
1479
1826
|
}
|
|
1480
1827
|
var SireneLookupResult = class _SireneLookupResult {
|
|
@@ -1500,24 +1847,24 @@ var SireneLookupResult = class _SireneLookupResult {
|
|
|
1500
1847
|
postalcode;
|
|
1501
1848
|
static fromArray(data) {
|
|
1502
1849
|
return new _SireneLookupResult(
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
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"])
|
|
1512
1859
|
);
|
|
1513
1860
|
}
|
|
1514
1861
|
};
|
|
1515
1862
|
|
|
1516
1863
|
// src/dto/VatRates.ts
|
|
1517
|
-
function
|
|
1864
|
+
function asString10(value, fallback = "") {
|
|
1518
1865
|
return typeof value === "string" ? value : fallback;
|
|
1519
1866
|
}
|
|
1520
|
-
function
|
|
1867
|
+
function asNumber6(value) {
|
|
1521
1868
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
1522
1869
|
}
|
|
1523
1870
|
var VatRates = class _VatRates {
|
|
@@ -1531,13 +1878,13 @@ var VatRates = class _VatRates {
|
|
|
1531
1878
|
rates;
|
|
1532
1879
|
static fromArray(data) {
|
|
1533
1880
|
const rates = (Array.isArray(data["rates"]) ? data["rates"] : []).filter((row) => typeof row === "object" && row !== null).map((row) => ({
|
|
1534
|
-
percent:
|
|
1535
|
-
category:
|
|
1536
|
-
labelKey:
|
|
1537
|
-
taxName:
|
|
1881
|
+
percent: asNumber6(row["percent"]),
|
|
1882
|
+
category: asString10(row["category"]),
|
|
1883
|
+
labelKey: asString10(row["label_key"]),
|
|
1884
|
+
taxName: asString10(row["tax_name"]),
|
|
1538
1885
|
requiresVatex: row["requires_vatex"] === true
|
|
1539
1886
|
}));
|
|
1540
|
-
return new _VatRates(
|
|
1887
|
+
return new _VatRates(asString10(data["country"]), asString10(data["currency"], "EUR"), rates);
|
|
1541
1888
|
}
|
|
1542
1889
|
};
|
|
1543
1890
|
|
|
@@ -1596,10 +1943,15 @@ var DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
1596
1943
|
var NAF_CODE_REGEX = /^\d{2}$/;
|
|
1597
1944
|
var COUNTRY_REGEX = /^[A-Za-z]{2}$/;
|
|
1598
1945
|
var PEPPOL_SCHEME_REGEX = /^\d{4}$/;
|
|
1946
|
+
var INVOICE_PDF_MAX_BYTES = 10 * 1024 * 1024;
|
|
1947
|
+
var INVOICE_PDF_MAGIC = [37, 80, 68, 70, 45];
|
|
1599
1948
|
var INTERVALS = ["day", "week", "month"];
|
|
1600
1949
|
var SERVICES = ["e_reporting", "e_invoicing"];
|
|
1601
1950
|
var ENTERPRISE_SIZES = ["micro", "pme", "eti", "ge"];
|
|
1602
1951
|
var TYPE_OPERATIONS = ["services", "goods", "mixed"];
|
|
1952
|
+
var NOTIFICATION_LANGUAGES = ["de", "en"];
|
|
1953
|
+
var NOTIFICATION_DIGESTS = ["off", "daily", "weekly"];
|
|
1954
|
+
var NOTIFICATION_MAX_RECIPIENTS = 5;
|
|
1603
1955
|
var TRANSACTION_TYPES = [
|
|
1604
1956
|
"b2c_outbound",
|
|
1605
1957
|
"b2b_domestic_outbound",
|
|
@@ -1794,6 +2146,8 @@ var EReportingEndpoint = class {
|
|
|
1794
2146
|
this.validateInvoiceLines(input.invoiceLines);
|
|
1795
2147
|
this.validateOptionalCodes(input);
|
|
1796
2148
|
this.validateBuyerFields(input);
|
|
2149
|
+
this.validateInternalReference(input.internalReference);
|
|
2150
|
+
this.validateInvoicePdfFilename(input);
|
|
1797
2151
|
const body = {
|
|
1798
2152
|
compliance_enrollment_id: input.complianceEnrollmentId,
|
|
1799
2153
|
transaction_type: input.transactionType,
|
|
@@ -1809,23 +2163,9 @@ var EReportingEndpoint = class {
|
|
|
1809
2163
|
const data = await this.parseJsonResponse(response);
|
|
1810
2164
|
return ComplianceTransaction.fromArray(data);
|
|
1811
2165
|
}
|
|
1812
|
-
/** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country. */
|
|
2166
|
+
/** Paginated list of the company's transactions (newest invoice date first), filterable by date / state / type / enrollment / country / search / internal reference / provider state. */
|
|
1813
2167
|
async listTransactions(filters = {}) {
|
|
1814
|
-
|
|
1815
|
-
this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
|
|
1816
|
-
}
|
|
1817
|
-
if (filters.country !== void 0 && !COUNTRY_REGEX.test(filters.country)) {
|
|
1818
|
-
throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
|
|
1819
|
-
}
|
|
1820
|
-
const params = new URLSearchParams();
|
|
1821
|
-
if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
|
|
1822
|
-
if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
|
|
1823
|
-
if (filters.state !== void 0) params.set("state", filters.state);
|
|
1824
|
-
if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
|
|
1825
|
-
if (filters.complianceEnrollmentId !== void 0) {
|
|
1826
|
-
params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
|
|
1827
|
-
}
|
|
1828
|
-
if (filters.country !== void 0) params.set("country", filters.country.toUpperCase());
|
|
2168
|
+
const params = this.buildTransactionFilterParams(filters);
|
|
1829
2169
|
if (filters.page !== void 0) params.set("page", String(filters.page));
|
|
1830
2170
|
if (filters.perPage !== void 0) params.set("per_page", String(filters.perPage));
|
|
1831
2171
|
const queryString = params.toString();
|
|
@@ -1833,6 +2173,27 @@ var EReportingEndpoint = class {
|
|
|
1833
2173
|
const response = await this.sendRequest("GET", url);
|
|
1834
2174
|
return ComplianceTransactionPage.fromResponse(await this.parseJsonResponse(response));
|
|
1835
2175
|
}
|
|
2176
|
+
/**
|
|
2177
|
+
* All transactions matching the filters as raw CSV for bookkeeping
|
|
2178
|
+
* (semicolon-separated) — the same filters as listTransactions() without
|
|
2179
|
+
* pagination. Columns: invoice_number, internal_reference, invoice_date,
|
|
2180
|
+
* due_date, country, transaction_type, document_type, state, delivery_state,
|
|
2181
|
+
* buyer_rejected, rejection_reason, counterparty_name, counterparty_country,
|
|
2182
|
+
* counterparty_vat_number, currency, subtotal, tax_amount, total, eur_rate,
|
|
2183
|
+
* eur_rate_date, eur_subtotal, eur_tax_amount, eur_total, provider_invoice_id,
|
|
2184
|
+
* created_at. The eur_* columns hold the ECB reference conversion for non-EUR
|
|
2185
|
+
* invoices (empty for EUR). Max 50,000 rows server-side. The body is returned
|
|
2186
|
+
* verbatim, a UTF-8 BOM included when the API sends one.
|
|
2187
|
+
*/
|
|
2188
|
+
async exportTransactionsCsv(filters = {}) {
|
|
2189
|
+
const queryString = this.buildTransactionFilterParams(filters).toString();
|
|
2190
|
+
const url = `${this.baseUrl}/compliance/transactions/export.csv${queryString ? `?${queryString}` : ""}`;
|
|
2191
|
+
const response = await this.sendDownloadRequest(url, "text/csv, application/json");
|
|
2192
|
+
if (!response.ok) {
|
|
2193
|
+
await this.parseJsonResponse(response);
|
|
2194
|
+
}
|
|
2195
|
+
return new TextDecoder("utf-8", { ignoreBOM: true }).decode(await response.arrayBuffer());
|
|
2196
|
+
}
|
|
1836
2197
|
/** Get a single transaction by id (includes its tax report when one exists). */
|
|
1837
2198
|
async getTransaction(id) {
|
|
1838
2199
|
this.validateId(id, "id");
|
|
@@ -1848,6 +2209,8 @@ var EReportingEndpoint = class {
|
|
|
1848
2209
|
if (input.invoiceLines !== void 0) this.validateInvoiceLines(input.invoiceLines);
|
|
1849
2210
|
this.validateOptionalCodes(input);
|
|
1850
2211
|
this.validateBuyerFields(input);
|
|
2212
|
+
this.validateInternalReference(input.internalReference);
|
|
2213
|
+
this.validateInvoicePdfFilename(input);
|
|
1851
2214
|
const body = {};
|
|
1852
2215
|
if (input.transactionType !== void 0) body["transaction_type"] = input.transactionType;
|
|
1853
2216
|
if (input.invoiceNumber !== void 0) body["invoice_number"] = input.invoiceNumber;
|
|
@@ -1882,6 +2245,47 @@ var EReportingEndpoint = class {
|
|
|
1882
2245
|
const data = await this.parseJsonResponse(response);
|
|
1883
2246
|
return ComplianceTransaction.fromArray(data);
|
|
1884
2247
|
}
|
|
2248
|
+
/**
|
|
2249
|
+
* Download the legal e-invoice document of a sent transaction (e-invoicing,
|
|
2250
|
+
* e.g. the EHF/UBL XML for Norway). Available once `documentUrl` on the
|
|
2251
|
+
* transaction is set.
|
|
2252
|
+
*
|
|
2253
|
+
* Errors: 404 (HttpException) for an unknown transaction; 409 (HttpException)
|
|
2254
|
+
* when no document exists (yet) — e.g. e-reporting, not sent, or the network
|
|
2255
|
+
* has not produced it yet (try again in a few minutes); 502 on provider failure.
|
|
2256
|
+
*/
|
|
2257
|
+
async getTransactionDocument(id) {
|
|
2258
|
+
this.validateId(id, "id");
|
|
2259
|
+
const response = await this.sendDownloadRequest(`${this.baseUrl}/compliance/transactions/${id}/document`, "*/*");
|
|
2260
|
+
if (!response.ok) {
|
|
2261
|
+
await this.parseJsonResponse(response);
|
|
2262
|
+
}
|
|
2263
|
+
return {
|
|
2264
|
+
content: new Uint8Array(await response.arrayBuffer()),
|
|
2265
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
2266
|
+
filename: this.filenameFromDisposition(response.headers.get("content-disposition"))
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
/**
|
|
2270
|
+
* Download the invoice as a readable PDF — the seller's attached PDF, or the
|
|
2271
|
+
* provider's rendering of the e-invoice. Available once `pdfUrl` on the
|
|
2272
|
+
* transaction is set.
|
|
2273
|
+
*
|
|
2274
|
+
* Errors: 404 (HttpException) for an unknown transaction; 409 (HttpException)
|
|
2275
|
+
* when no PDF exists (yet); 502 on provider failure.
|
|
2276
|
+
*/
|
|
2277
|
+
async getTransactionPdf(id) {
|
|
2278
|
+
this.validateId(id, "id");
|
|
2279
|
+
const response = await this.sendDownloadRequest(`${this.baseUrl}/compliance/transactions/${id}/pdf`, "*/*");
|
|
2280
|
+
if (!response.ok) {
|
|
2281
|
+
await this.parseJsonResponse(response);
|
|
2282
|
+
}
|
|
2283
|
+
return {
|
|
2284
|
+
content: new Uint8Array(await response.arrayBuffer()),
|
|
2285
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
2286
|
+
filename: this.filenameFromDisposition(response.headers.get("content-disposition"))
|
|
2287
|
+
};
|
|
2288
|
+
}
|
|
1885
2289
|
/**
|
|
1886
2290
|
* Bulk-import transactions from a semicolon-separated CSV (one row per invoice
|
|
1887
2291
|
* line; rows sharing an invoice_number are grouped into one transaction).
|
|
@@ -1913,6 +2317,9 @@ var EReportingEndpoint = class {
|
|
|
1913
2317
|
* months and a monthly interval.
|
|
1914
2318
|
*/
|
|
1915
2319
|
async getRevenueStatistics(filters = {}) {
|
|
2320
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2321
|
+
this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
|
|
2322
|
+
}
|
|
1916
2323
|
if (filters.interval !== void 0 && !INTERVALS.includes(filters.interval)) {
|
|
1917
2324
|
throw new TaxoraException(
|
|
1918
2325
|
`Invalid statistics interval "${String(filters.interval)}". Expected one of: ${INTERVALS.join(", ")}.`
|
|
@@ -1924,12 +2331,42 @@ var EReportingEndpoint = class {
|
|
|
1924
2331
|
if (filters.interval !== void 0) params.set("interval", filters.interval);
|
|
1925
2332
|
if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
|
|
1926
2333
|
if (filters.state !== void 0) params.set("state", filters.state);
|
|
2334
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2335
|
+
params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
|
|
2336
|
+
}
|
|
1927
2337
|
const queryString = params.toString();
|
|
1928
2338
|
const url = `${this.baseUrl}/compliance/revenue-statistics${queryString ? `?${queryString}` : ""}`;
|
|
1929
2339
|
const response = await this.sendRequest("GET", url);
|
|
1930
2340
|
const data = await this.parseJsonResponse(response);
|
|
1931
2341
|
return RevenueStatistics.fromArray(data);
|
|
1932
2342
|
}
|
|
2343
|
+
/**
|
|
2344
|
+
* Net and VAT per month, currency and tax rate as raw CSV (semicolon-separated,
|
|
2345
|
+
* computed from the invoice lines) — for reconciling the reported figures with
|
|
2346
|
+
* your VAT return. Same filters as getRevenueStatistics() (without
|
|
2347
|
+
* `interval`); defaults to the last 12 months. The body is returned verbatim,
|
|
2348
|
+
* a UTF-8 BOM included when the API sends one.
|
|
2349
|
+
*/
|
|
2350
|
+
async exportRevenueTaxRatesCsv(filters = {}) {
|
|
2351
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2352
|
+
this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
|
|
2353
|
+
}
|
|
2354
|
+
const params = new URLSearchParams();
|
|
2355
|
+
if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
|
|
2356
|
+
if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
|
|
2357
|
+
if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
|
|
2358
|
+
if (filters.state !== void 0) params.set("state", filters.state);
|
|
2359
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2360
|
+
params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
|
|
2361
|
+
}
|
|
2362
|
+
const queryString = params.toString();
|
|
2363
|
+
const url = `${this.baseUrl}/compliance/revenue-statistics/tax-rates.csv${queryString ? `?${queryString}` : ""}`;
|
|
2364
|
+
const response = await this.sendDownloadRequest(url, "text/csv, application/json");
|
|
2365
|
+
if (!response.ok) {
|
|
2366
|
+
await this.parseJsonResponse(response);
|
|
2367
|
+
}
|
|
2368
|
+
return new TextDecoder("utf-8", { ignoreBOM: true }).decode(await response.arrayBuffer());
|
|
2369
|
+
}
|
|
1933
2370
|
/**
|
|
1934
2371
|
* The canonical VAT rates & DGFiP tax categories for a reporting country
|
|
1935
2372
|
* (the seller's reporting-country rates, not the counterparty's). Falls back
|
|
@@ -1944,12 +2381,19 @@ var EReportingEndpoint = class {
|
|
|
1944
2381
|
const data = await this.parseJsonResponse(response);
|
|
1945
2382
|
return VatRates.fromArray(data);
|
|
1946
2383
|
}
|
|
1947
|
-
/**
|
|
1948
|
-
|
|
2384
|
+
/**
|
|
2385
|
+
* Paginated list of the company's tax reports (newest first), optionally
|
|
2386
|
+
* filtered by state and by country (2-letter ISO code, case-insensitive).
|
|
2387
|
+
*/
|
|
2388
|
+
async listTaxReports(page = 1, perPage = 25, state, country) {
|
|
2389
|
+
if (country !== void 0 && !COUNTRY_REGEX.test(country)) {
|
|
2390
|
+
throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
|
|
2391
|
+
}
|
|
1949
2392
|
const params = new URLSearchParams();
|
|
1950
2393
|
params.set("page", String(page));
|
|
1951
2394
|
params.set("per_page", String(perPage));
|
|
1952
2395
|
if (state !== void 0) params.set("state", state);
|
|
2396
|
+
if (country !== void 0) params.set("country", country.toUpperCase());
|
|
1953
2397
|
const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/tax-reports?${params.toString()}`);
|
|
1954
2398
|
return ComplianceTaxReportPage.fromResponse(await this.parseJsonResponse(response));
|
|
1955
2399
|
}
|
|
@@ -1991,8 +2435,177 @@ var EReportingEndpoint = class {
|
|
|
1991
2435
|
await this.parseJsonResponse(response);
|
|
1992
2436
|
}
|
|
1993
2437
|
// ---------------------------------------------------------------------
|
|
2438
|
+
// Self-service plans (Stripe) — not gated by compliance access
|
|
2439
|
+
// ---------------------------------------------------------------------
|
|
2440
|
+
/**
|
|
2441
|
+
* Bookable compliance plans per country (net EUR prices), every country
|
|
2442
|
+
* Taxora reaches, and which services the company has unlocked. Works for
|
|
2443
|
+
* companies without compliance access.
|
|
2444
|
+
*/
|
|
2445
|
+
async getOfferings() {
|
|
2446
|
+
const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/offerings`);
|
|
2447
|
+
return ComplianceOfferings.fromArray(await this.parseJsonResponse(response));
|
|
2448
|
+
}
|
|
2449
|
+
/**
|
|
2450
|
+
* Start a Stripe Checkout for a plan (see getOfferings() — `checkoutAvailable`).
|
|
2451
|
+
* Open the returned `url` in the browser. After payment Stripe redirects to
|
|
2452
|
+
* the Taxora portal, which activates the plan; call confirmCheckout() with the
|
|
2453
|
+
* session id to activate it from your side (idempotent).
|
|
2454
|
+
*
|
|
2455
|
+
* Errors: 422 (ValidationException) for an unknown or contact-only plan or a
|
|
2456
|
+
* plan that is already active; 502 (HttpException) on a Stripe error.
|
|
2457
|
+
*/
|
|
2458
|
+
async createCheckout(country, plan) {
|
|
2459
|
+
if (!COUNTRY_REGEX.test(country)) {
|
|
2460
|
+
throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
|
|
2461
|
+
}
|
|
2462
|
+
if (plan.trim() === "" || plan.length > 30) {
|
|
2463
|
+
throw new TaxoraException("plan must be a non-empty plan key of at most 30 characters.");
|
|
2464
|
+
}
|
|
2465
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/checkout`, {
|
|
2466
|
+
country: country.toUpperCase(),
|
|
2467
|
+
plan
|
|
2468
|
+
});
|
|
2469
|
+
const data = await this.parseJsonResponse(response);
|
|
2470
|
+
return { id: String(data["id"] ?? ""), url: String(data["url"] ?? "") };
|
|
2471
|
+
}
|
|
2472
|
+
/** Confirm a finished Stripe Checkout and activate its plan. Idempotent. */
|
|
2473
|
+
async confirmCheckout(sessionId) {
|
|
2474
|
+
if (sessionId.trim() === "" || sessionId.length > 255) {
|
|
2475
|
+
throw new TaxoraException("sessionId must be a non-empty string of at most 255 characters.");
|
|
2476
|
+
}
|
|
2477
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/checkout/confirm`, {
|
|
2478
|
+
session_id: sessionId
|
|
2479
|
+
});
|
|
2480
|
+
const data = await this.parseJsonResponse(response);
|
|
2481
|
+
const str = (value) => typeof value === "string" ? value : null;
|
|
2482
|
+
return {
|
|
2483
|
+
active: data["active"] === true,
|
|
2484
|
+
country: str(data["country"]),
|
|
2485
|
+
service: str(data["service"]),
|
|
2486
|
+
plan: str(data["plan"]),
|
|
2487
|
+
status: str(data["status"])
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
/**
|
|
2491
|
+
* URL of the Stripe billing portal for the company's compliance plans
|
|
2492
|
+
* (invoices, payment method, cancellation). The portal returns to the Taxora
|
|
2493
|
+
* portal. 404 (HttpException) when no plan was bought via Stripe.
|
|
2494
|
+
*/
|
|
2495
|
+
async createBillingPortalSession() {
|
|
2496
|
+
const response = await this.sendRequest("POST", `${this.baseUrl}/compliance/billing-portal`);
|
|
2497
|
+
const data = await this.parseJsonResponse(response);
|
|
2498
|
+
return String(data["url"] ?? "");
|
|
2499
|
+
}
|
|
2500
|
+
// ---------------------------------------------------------------------
|
|
2501
|
+
// Notification emails
|
|
2502
|
+
// ---------------------------------------------------------------------
|
|
2503
|
+
/**
|
|
2504
|
+
* The company's opt-in e-reporting / e-invoicing emails: recipients, language,
|
|
2505
|
+
* the "buyer not on Peppol" email and the digest. Readable by every member.
|
|
2506
|
+
*/
|
|
2507
|
+
async getNotificationSettings() {
|
|
2508
|
+
const response = await this.sendRequest("GET", `${this.baseUrl}/compliance/notification-settings`);
|
|
2509
|
+
return this.toNotificationSettings(await this.parseJsonResponse(response));
|
|
2510
|
+
}
|
|
2511
|
+
/**
|
|
2512
|
+
* Change the company's e-reporting / e-invoicing emails; only the provided
|
|
2513
|
+
* fields change. `notOnPeppol` only reports invoices held back after it was
|
|
2514
|
+
* switched on.
|
|
2515
|
+
*
|
|
2516
|
+
* Errors: 422 (ValidationException) when an email is switched on without any
|
|
2517
|
+
* recipient; 403 (HttpException, body code `admin_only` or `read_only_role`)
|
|
2518
|
+
* for users who are not company admins.
|
|
2519
|
+
*/
|
|
2520
|
+
async updateNotificationSettings(input) {
|
|
2521
|
+
const body = {};
|
|
2522
|
+
if (input.recipients !== void 0) {
|
|
2523
|
+
if (!Array.isArray(input.recipients)) {
|
|
2524
|
+
throw new TaxoraException("recipients must be an array of email addresses.");
|
|
2525
|
+
}
|
|
2526
|
+
if (input.recipients.length > NOTIFICATION_MAX_RECIPIENTS) {
|
|
2527
|
+
throw new TaxoraException(`recipients must not contain more than ${NOTIFICATION_MAX_RECIPIENTS} entries.`);
|
|
2528
|
+
}
|
|
2529
|
+
body["recipients"] = input.recipients.map((recipient, index) => {
|
|
2530
|
+
const email = typeof recipient === "string" ? recipient.trim() : recipient;
|
|
2531
|
+
this.validateEmail(email, `recipients[${index}]`);
|
|
2532
|
+
if (email.length > 191) {
|
|
2533
|
+
throw new TaxoraException(`recipients[${index}] must not exceed 191 characters.`);
|
|
2534
|
+
}
|
|
2535
|
+
return email;
|
|
2536
|
+
});
|
|
2537
|
+
}
|
|
2538
|
+
if (input.language !== void 0) {
|
|
2539
|
+
if (!NOTIFICATION_LANGUAGES.includes(input.language)) {
|
|
2540
|
+
throw new TaxoraException(
|
|
2541
|
+
`Invalid language "${String(input.language)}". Expected one of: ${NOTIFICATION_LANGUAGES.join(", ")}.`
|
|
2542
|
+
);
|
|
2543
|
+
}
|
|
2544
|
+
body["language"] = input.language;
|
|
2545
|
+
}
|
|
2546
|
+
if (input.notOnPeppol !== void 0) {
|
|
2547
|
+
if (typeof input.notOnPeppol !== "boolean") {
|
|
2548
|
+
throw new TaxoraException("notOnPeppol must be a boolean.");
|
|
2549
|
+
}
|
|
2550
|
+
body["not_on_peppol"] = input.notOnPeppol;
|
|
2551
|
+
}
|
|
2552
|
+
if (input.digest !== void 0) {
|
|
2553
|
+
if (!NOTIFICATION_DIGESTS.includes(input.digest)) {
|
|
2554
|
+
throw new TaxoraException(
|
|
2555
|
+
`Invalid digest "${String(input.digest)}". Expected one of: ${NOTIFICATION_DIGESTS.join(", ")}.`
|
|
2556
|
+
);
|
|
2557
|
+
}
|
|
2558
|
+
body["digest"] = input.digest;
|
|
2559
|
+
}
|
|
2560
|
+
if (Object.keys(body).length === 0) {
|
|
2561
|
+
throw new TaxoraException("updateNotificationSettings requires at least one field to update.");
|
|
2562
|
+
}
|
|
2563
|
+
const response = await this.sendRequest("PUT", `${this.baseUrl}/compliance/notification-settings`, body);
|
|
2564
|
+
return this.toNotificationSettings(await this.parseJsonResponse(response));
|
|
2565
|
+
}
|
|
2566
|
+
toNotificationSettings(data) {
|
|
2567
|
+
const recipients = Array.isArray(data["recipients"]) ? data["recipients"].filter((r) => typeof r === "string" && r !== "") : [];
|
|
2568
|
+
const digest = data["digest"];
|
|
2569
|
+
return {
|
|
2570
|
+
recipients,
|
|
2571
|
+
language: data["language"] === "en" ? "en" : "de",
|
|
2572
|
+
notOnPeppol: data["not_on_peppol"] === true,
|
|
2573
|
+
digest: digest === "daily" || digest === "weekly" ? digest : "off",
|
|
2574
|
+
digestSentAt: typeof data["digest_sent_at"] === "string" ? data["digest_sent_at"] : null
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
// ---------------------------------------------------------------------
|
|
1994
2578
|
// Input validation (fail fast, before any request is sent)
|
|
1995
2579
|
// ---------------------------------------------------------------------
|
|
2580
|
+
/** Validated transaction-list filters as query params (shared by listTransactions and exportTransactionsCsv). */
|
|
2581
|
+
buildTransactionFilterParams(filters) {
|
|
2582
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2583
|
+
this.validateId(filters.complianceEnrollmentId, "complianceEnrollmentId");
|
|
2584
|
+
}
|
|
2585
|
+
if (filters.country !== void 0 && !COUNTRY_REGEX.test(filters.country)) {
|
|
2586
|
+
throw new TaxoraException("country must be a 2-character ISO 3166-1 alpha-2 code.");
|
|
2587
|
+
}
|
|
2588
|
+
if (filters.search !== void 0 && filters.search.length > 100) {
|
|
2589
|
+
throw new TaxoraException("search must not exceed 100 characters.");
|
|
2590
|
+
}
|
|
2591
|
+
this.validateInternalReference(filters.internalReference);
|
|
2592
|
+
if (filters.providerState !== void 0 && !/^[a-z_]{1,30}$/.test(filters.providerState)) {
|
|
2593
|
+
throw new TaxoraException('providerState must be 1-30 lowercase letters or underscores (e.g. "refused").');
|
|
2594
|
+
}
|
|
2595
|
+
const params = new URLSearchParams();
|
|
2596
|
+
if (filters.dateFrom !== void 0) params.set("date_from", this.formatDate(filters.dateFrom));
|
|
2597
|
+
if (filters.dateTo !== void 0) params.set("date_to", this.formatDate(filters.dateTo));
|
|
2598
|
+
if (filters.state !== void 0) params.set("state", filters.state);
|
|
2599
|
+
if (filters.transactionType !== void 0) params.set("transaction_type", filters.transactionType);
|
|
2600
|
+
if (filters.complianceEnrollmentId !== void 0) {
|
|
2601
|
+
params.set("compliance_enrollment_id", String(filters.complianceEnrollmentId));
|
|
2602
|
+
}
|
|
2603
|
+
if (filters.country !== void 0) params.set("country", filters.country.toUpperCase());
|
|
2604
|
+
if (filters.search !== void 0) params.set("search", filters.search);
|
|
2605
|
+
if (filters.internalReference !== void 0) params.set("internal_reference", filters.internalReference);
|
|
2606
|
+
if (filters.providerState !== void 0) params.set("provider_state", filters.providerState);
|
|
2607
|
+
return params;
|
|
2608
|
+
}
|
|
1996
2609
|
validateEnrollmentInput(input) {
|
|
1997
2610
|
if (input.siret === void 0 && input.siren === void 0) {
|
|
1998
2611
|
throw new TaxoraException("Either siret or siren is required.");
|
|
@@ -2120,6 +2733,20 @@ var EReportingEndpoint = class {
|
|
|
2120
2733
|
}
|
|
2121
2734
|
});
|
|
2122
2735
|
}
|
|
2736
|
+
validateInvoicePdfFilename(input) {
|
|
2737
|
+
if (input.invoicePdfFilename === void 0) return;
|
|
2738
|
+
if (input.invoicePdfFilename.length > 120) {
|
|
2739
|
+
throw new TaxoraException("invoicePdfFilename must not exceed 120 characters.");
|
|
2740
|
+
}
|
|
2741
|
+
if (input.invoicePdf === void 0) {
|
|
2742
|
+
throw new TaxoraException("invoicePdfFilename requires invoicePdf.");
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
validateInternalReference(internalReference) {
|
|
2746
|
+
if (internalReference !== void 0 && internalReference.length > 100) {
|
|
2747
|
+
throw new TaxoraException("internalReference must not exceed 100 characters.");
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2123
2750
|
validateOptionalCodes(input) {
|
|
2124
2751
|
if (input.currency !== void 0 && input.currency.length !== 3) {
|
|
2125
2752
|
throw new TaxoraException("currency must be a 3-character ISO 4217 code.");
|
|
@@ -2201,6 +2828,29 @@ var EReportingEndpoint = class {
|
|
|
2201
2828
|
if (input.amendedNumber !== void 0) body["amended_number"] = input.amendedNumber;
|
|
2202
2829
|
if (input.amendedDate !== void 0) body["amended_date"] = this.formatDate(input.amendedDate);
|
|
2203
2830
|
if (input.extraInfo !== void 0) body["extra_info"] = input.extraInfo;
|
|
2831
|
+
if (input.internalReference !== void 0) body["internal_reference"] = input.internalReference;
|
|
2832
|
+
if (input.invoicePdf !== void 0) body["invoice_pdf"] = this.encodeInvoicePdf(input.invoicePdf);
|
|
2833
|
+
if (input.invoicePdfFilename !== void 0) body["invoice_pdf_filename"] = input.invoicePdfFilename;
|
|
2834
|
+
}
|
|
2835
|
+
/** Bytes → base64 (validated as a PDF of at most 10 MB); strings are taken as already base64. */
|
|
2836
|
+
encodeInvoicePdf(pdf) {
|
|
2837
|
+
if (typeof pdf === "string") {
|
|
2838
|
+
if (pdf.trim() === "") {
|
|
2839
|
+
throw new TaxoraException("invoicePdf must not be empty.");
|
|
2840
|
+
}
|
|
2841
|
+
return pdf;
|
|
2842
|
+
}
|
|
2843
|
+
const bytes = pdf instanceof Uint8Array ? pdf : new Uint8Array(pdf);
|
|
2844
|
+
if (bytes.byteLength === 0) {
|
|
2845
|
+
throw new TaxoraException("invoicePdf must not be empty.");
|
|
2846
|
+
}
|
|
2847
|
+
if (bytes.byteLength > INVOICE_PDF_MAX_BYTES) {
|
|
2848
|
+
throw new TaxoraException("invoicePdf must not exceed 10 MB.");
|
|
2849
|
+
}
|
|
2850
|
+
if (!INVOICE_PDF_MAGIC.every((byte, index) => bytes[index] === byte)) {
|
|
2851
|
+
throw new TaxoraException('invoicePdf must be a PDF file (content must start with "%PDF-").');
|
|
2852
|
+
}
|
|
2853
|
+
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("base64");
|
|
2204
2854
|
}
|
|
2205
2855
|
// ---------------------------------------------------------------------
|
|
2206
2856
|
// HTTP plumbing (kept in sync with SmartEnrichmentEndpoint)
|
|
@@ -2224,6 +2874,30 @@ var EReportingEndpoint = class {
|
|
|
2224
2874
|
const send = () => this.httpClient.request(method, url, options);
|
|
2225
2875
|
return method === "GET" ? withResponseRetries(this.retryPolicy, "e-reporting request", send) : send();
|
|
2226
2876
|
}
|
|
2877
|
+
/** GET for a non-JSON download (CSV / document): no JSON Content-Type, retried like other GETs. */
|
|
2878
|
+
async sendDownloadRequest(url, accept) {
|
|
2879
|
+
const headers = this.buildHeaders(false);
|
|
2880
|
+
headers["Accept"] = accept;
|
|
2881
|
+
return withResponseRetries(
|
|
2882
|
+
this.retryPolicy,
|
|
2883
|
+
"e-reporting download",
|
|
2884
|
+
() => this.httpClient.request("GET", url, { headers })
|
|
2885
|
+
);
|
|
2886
|
+
}
|
|
2887
|
+
/** `attachment; filename="x.xml"` (or RFC 5987 `filename*=UTF-8''x.xml`) → "x.xml". */
|
|
2888
|
+
filenameFromDisposition(header) {
|
|
2889
|
+
if (header === null) return null;
|
|
2890
|
+
const extended = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;]+)/.exec(header);
|
|
2891
|
+
if (extended?.[1] !== void 0) {
|
|
2892
|
+
try {
|
|
2893
|
+
return decodeURIComponent(extended[1].trim());
|
|
2894
|
+
} catch {
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
const plain = /filename\s*=\s*"([^"]*)"|filename\s*=\s*([^;]+)/.exec(header);
|
|
2898
|
+
const name = (plain?.[1] ?? plain?.[2])?.trim();
|
|
2899
|
+
return name !== void 0 && name !== "" ? name : null;
|
|
2900
|
+
}
|
|
2227
2901
|
/** Multipart upload: Content-Type is left to fetch so the boundary is set correctly. */
|
|
2228
2902
|
async sendMultipartRequest(method, url, form) {
|
|
2229
2903
|
return this.httpClient.request(method, url, { headers: this.buildHeaders(false), body: form });
|
|
@@ -2318,6 +2992,73 @@ var EReportingEndpoint = class {
|
|
|
2318
2992
|
}
|
|
2319
2993
|
};
|
|
2320
2994
|
|
|
2995
|
+
// src/dto/SmartEnrichmentRecheck.ts
|
|
2996
|
+
var toIndexes = (value) => Array.isArray(value) ? value.filter((v) => typeof v === "number" && Number.isInteger(v)) : [];
|
|
2997
|
+
var SmartEnrichmentRecheck = class _SmartEnrichmentRecheck {
|
|
2998
|
+
constructor(jobId, rows, checks, skipped, dryRun) {
|
|
2999
|
+
this.jobId = jobId;
|
|
3000
|
+
this.rows = rows;
|
|
3001
|
+
this.checks = checks;
|
|
3002
|
+
this.skipped = skipped;
|
|
3003
|
+
this.dryRun = dryRun;
|
|
3004
|
+
}
|
|
3005
|
+
jobId;
|
|
3006
|
+
rows;
|
|
3007
|
+
checks;
|
|
3008
|
+
skipped;
|
|
3009
|
+
dryRun;
|
|
3010
|
+
static fromArray(data) {
|
|
3011
|
+
const skipped = {};
|
|
3012
|
+
const rawSkipped = data["skipped"];
|
|
3013
|
+
if (typeof rawSkipped === "object" && rawSkipped !== null && !Array.isArray(rawSkipped)) {
|
|
3014
|
+
for (const [reason, count] of Object.entries(rawSkipped)) {
|
|
3015
|
+
if (typeof count === "number") skipped[reason] = count;
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
return new _SmartEnrichmentRecheck(
|
|
3019
|
+
typeof data["jobId"] === "string" ? data["jobId"] : "",
|
|
3020
|
+
toIndexes(data["rows"]),
|
|
3021
|
+
typeof data["checks"] === "number" ? data["checks"] : 0,
|
|
3022
|
+
skipped,
|
|
3023
|
+
data["dryRun"] === true
|
|
3024
|
+
);
|
|
3025
|
+
}
|
|
3026
|
+
};
|
|
3027
|
+
var SmartEnrichmentRecheckState = class _SmartEnrichmentRecheckState {
|
|
3028
|
+
constructor(eligible, runs, maxPerRow, cooldownDays) {
|
|
3029
|
+
this.eligible = eligible;
|
|
3030
|
+
this.runs = runs;
|
|
3031
|
+
this.maxPerRow = maxPerRow;
|
|
3032
|
+
this.cooldownDays = cooldownDays;
|
|
3033
|
+
}
|
|
3034
|
+
eligible;
|
|
3035
|
+
runs;
|
|
3036
|
+
maxPerRow;
|
|
3037
|
+
cooldownDays;
|
|
3038
|
+
static fromArray(data) {
|
|
3039
|
+
const runs = {};
|
|
3040
|
+
const rawRuns = data["runs"];
|
|
3041
|
+
if (typeof rawRuns === "object" && rawRuns !== null && !Array.isArray(rawRuns)) {
|
|
3042
|
+
for (const [index, run] of Object.entries(rawRuns)) {
|
|
3043
|
+
if (!/^\d+$/.test(index) || typeof run !== "object" || run === null) continue;
|
|
3044
|
+
const { state, resolved } = run;
|
|
3045
|
+
if (state !== "queued" && state !== "running" && state !== "finished" && state !== "failed") continue;
|
|
3046
|
+
runs[Number(index)] = typeof resolved === "boolean" ? { state, resolved } : { state };
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
return new _SmartEnrichmentRecheckState(
|
|
3050
|
+
toIndexes(data["eligible"]),
|
|
3051
|
+
runs,
|
|
3052
|
+
typeof data["maxPerRow"] === "number" ? data["maxPerRow"] : 3,
|
|
3053
|
+
typeof data["cooldownDays"] === "number" ? data["cooldownDays"] : 7
|
|
3054
|
+
);
|
|
3055
|
+
}
|
|
3056
|
+
/** True while any recheck of this lookup is queued or running. */
|
|
3057
|
+
isActive() {
|
|
3058
|
+
return Object.values(this.runs).some((run) => run.state === "queued" || run.state === "running");
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
|
|
2321
3062
|
// src/enums/SmartEnrichmentMode.ts
|
|
2322
3063
|
var SmartEnrichmentMode = {
|
|
2323
3064
|
DEFAULT: "default",
|
|
@@ -2447,7 +3188,7 @@ function toOfficialAddress(value) {
|
|
|
2447
3188
|
return Object.keys(address).length > 0 ? address : void 0;
|
|
2448
3189
|
}
|
|
2449
3190
|
var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
2450
|
-
constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0, rejectedCandidates = [], sourceUrl = void 0, registeredOwner = void 0, sourceUrls = [], taxNumber = void 0, vatValid = void 0, aiScore = void 0, nameMatch = void 0, officialName = void 0, officialAddress = void 0, taxNumberType = void 0, taxNumberLabel = void 0, taxNumberSource = void 0) {
|
|
3191
|
+
constructor(status, vatNumber, vatType, confidence, matchedCompanyName, matchedAddress, country, source, mode = void 0, providerVerdicts = [], addressQuality = void 0, rejectedCandidates = [], sourceUrl = void 0, registeredOwner = void 0, sourceUrls = [], taxNumber = void 0, vatValid = void 0, aiScore = void 0, nameMatch = void 0, officialName = void 0, officialAddress = void 0, taxNumberType = void 0, taxNumberLabel = void 0, taxNumberSource = void 0, recheckCount = void 0, lastRecheckedAt = void 0) {
|
|
2451
3192
|
this.status = status;
|
|
2452
3193
|
this.vatNumber = vatNumber;
|
|
2453
3194
|
this.vatType = vatType;
|
|
@@ -2472,6 +3213,8 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2472
3213
|
this.taxNumberType = taxNumberType;
|
|
2473
3214
|
this.taxNumberLabel = taxNumberLabel;
|
|
2474
3215
|
this.taxNumberSource = taxNumberSource;
|
|
3216
|
+
this.recheckCount = recheckCount;
|
|
3217
|
+
this.lastRecheckedAt = lastRecheckedAt;
|
|
2475
3218
|
}
|
|
2476
3219
|
status;
|
|
2477
3220
|
vatNumber;
|
|
@@ -2497,6 +3240,8 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2497
3240
|
taxNumberType;
|
|
2498
3241
|
taxNumberLabel;
|
|
2499
3242
|
taxNumberSource;
|
|
3243
|
+
recheckCount;
|
|
3244
|
+
lastRecheckedAt;
|
|
2500
3245
|
/** True when the register knows the number under a different name than the one requested. */
|
|
2501
3246
|
nameMismatch() {
|
|
2502
3247
|
return this.nameMatch === "mismatch";
|
|
@@ -2547,7 +3292,9 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2547
3292
|
toOfficialAddress(data["officialAddress"]),
|
|
2548
3293
|
text("taxNumberType"),
|
|
2549
3294
|
text("taxNumberLabel"),
|
|
2550
|
-
data["taxNumberSource"] === "vat_id" || data["taxNumberSource"] === "company_website" ? data["taxNumberSource"] : void 0
|
|
3295
|
+
data["taxNumberSource"] === "vat_id" || data["taxNumberSource"] === "company_website" ? data["taxNumberSource"] : void 0,
|
|
3296
|
+
num("recheckCount"),
|
|
3297
|
+
text("lastRecheckedAt")
|
|
2551
3298
|
);
|
|
2552
3299
|
}
|
|
2553
3300
|
toArray() {
|
|
@@ -2575,20 +3322,23 @@ var SmartEnrichmentResource = class _SmartEnrichmentResource {
|
|
|
2575
3322
|
officialAddress: this.officialAddress ?? null,
|
|
2576
3323
|
taxNumberType: this.taxNumberType ?? null,
|
|
2577
3324
|
taxNumberLabel: this.taxNumberLabel ?? null,
|
|
2578
|
-
taxNumberSource: this.taxNumberSource ?? null
|
|
3325
|
+
taxNumberSource: this.taxNumberSource ?? null,
|
|
3326
|
+
recheckCount: this.recheckCount ?? null,
|
|
3327
|
+
lastRecheckedAt: this.lastRecheckedAt ?? null
|
|
2579
3328
|
};
|
|
2580
3329
|
}
|
|
2581
3330
|
};
|
|
2582
3331
|
|
|
2583
3332
|
// src/dto/SmartEnrichmentJob.ts
|
|
2584
3333
|
var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
2585
|
-
constructor(jobId, status, itemCount, completedCount, foundCount, results) {
|
|
3334
|
+
constructor(jobId, status, itemCount, completedCount, foundCount, results, recheck = void 0) {
|
|
2586
3335
|
this.jobId = jobId;
|
|
2587
3336
|
this.status = status;
|
|
2588
3337
|
this.itemCount = itemCount;
|
|
2589
3338
|
this.completedCount = completedCount;
|
|
2590
3339
|
this.foundCount = foundCount;
|
|
2591
3340
|
this.results = results;
|
|
3341
|
+
this.recheck = recheck;
|
|
2592
3342
|
}
|
|
2593
3343
|
jobId;
|
|
2594
3344
|
status;
|
|
@@ -2596,6 +3346,7 @@ var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
|
2596
3346
|
completedCount;
|
|
2597
3347
|
foundCount;
|
|
2598
3348
|
results;
|
|
3349
|
+
recheck;
|
|
2599
3350
|
static fromArray(data) {
|
|
2600
3351
|
const num = (key) => {
|
|
2601
3352
|
const v = data[key];
|
|
@@ -2613,7 +3364,8 @@ var SmartEnrichmentJob = class _SmartEnrichmentJob {
|
|
|
2613
3364
|
num("itemCount"),
|
|
2614
3365
|
num("completedCount"),
|
|
2615
3366
|
num("foundCount"),
|
|
2616
|
-
results
|
|
3367
|
+
results,
|
|
3368
|
+
typeof data["recheck"] === "object" && data["recheck"] !== null && !Array.isArray(data["recheck"]) ? SmartEnrichmentRecheckState.fromArray(data["recheck"]) : void 0
|
|
2617
3369
|
);
|
|
2618
3370
|
}
|
|
2619
3371
|
isProcessing() {
|
|
@@ -2727,13 +3479,13 @@ var SmartEnrichmentHistoryPage = class _SmartEnrichmentHistoryPage {
|
|
|
2727
3479
|
};
|
|
2728
3480
|
|
|
2729
3481
|
// src/dto/SmartEnrichmentStatistics.ts
|
|
2730
|
-
function
|
|
3482
|
+
function asString11(value, fallback = "") {
|
|
2731
3483
|
return typeof value === "string" ? value : fallback;
|
|
2732
3484
|
}
|
|
2733
|
-
function
|
|
3485
|
+
function asNumber7(value) {
|
|
2734
3486
|
return typeof value === "number" ? value : Number(value ?? 0) || 0;
|
|
2735
3487
|
}
|
|
2736
|
-
function
|
|
3488
|
+
function asRecord4(value) {
|
|
2737
3489
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
2738
3490
|
}
|
|
2739
3491
|
function asRecords2(value) {
|
|
@@ -2756,39 +3508,39 @@ var SmartEnrichmentStatistics = class _SmartEnrichmentStatistics {
|
|
|
2756
3508
|
byOutcome;
|
|
2757
3509
|
confidenceBuckets;
|
|
2758
3510
|
static fromArray(data) {
|
|
2759
|
-
const range =
|
|
2760
|
-
const totals =
|
|
3511
|
+
const range = asRecord4(data["range"]);
|
|
3512
|
+
const totals = asRecord4(data["totals"]);
|
|
2761
3513
|
const timeSeries = asRecords2(data["time_series"]).map((row) => ({
|
|
2762
|
-
bucket:
|
|
2763
|
-
jobs:
|
|
2764
|
-
items:
|
|
2765
|
-
found:
|
|
3514
|
+
bucket: asString11(row["bucket"]),
|
|
3515
|
+
jobs: asNumber7(row["jobs"]),
|
|
3516
|
+
items: asNumber7(row["items"]),
|
|
3517
|
+
found: asNumber7(row["found"])
|
|
2766
3518
|
}));
|
|
2767
3519
|
const bySource = asRecords2(data["by_source"]).map((row) => ({
|
|
2768
|
-
source:
|
|
2769
|
-
jobs:
|
|
2770
|
-
found:
|
|
3520
|
+
source: asString11(row["source"]),
|
|
3521
|
+
jobs: asNumber7(row["jobs"]),
|
|
3522
|
+
found: asNumber7(row["found"])
|
|
2771
3523
|
}));
|
|
2772
3524
|
const byOutcome = asRecords2(data["by_outcome"]).map((row) => ({
|
|
2773
|
-
outcome:
|
|
2774
|
-
count:
|
|
3525
|
+
outcome: asString11(row["outcome"]),
|
|
3526
|
+
count: asNumber7(row["count"])
|
|
2775
3527
|
}));
|
|
2776
3528
|
const confidenceBuckets = asRecords2(data["confidence_buckets"]).map((row) => ({
|
|
2777
|
-
bucket:
|
|
2778
|
-
count:
|
|
3529
|
+
bucket: asString11(row["bucket"]),
|
|
3530
|
+
count: asNumber7(row["count"])
|
|
2779
3531
|
}));
|
|
2780
3532
|
return new _SmartEnrichmentStatistics(
|
|
2781
3533
|
{
|
|
2782
|
-
dateFrom:
|
|
2783
|
-
dateTo:
|
|
2784
|
-
interval:
|
|
3534
|
+
dateFrom: asString11(range["date_from"]),
|
|
3535
|
+
dateTo: asString11(range["date_to"]),
|
|
3536
|
+
interval: asString11(range["interval"])
|
|
2785
3537
|
},
|
|
2786
3538
|
{
|
|
2787
|
-
jobs:
|
|
2788
|
-
items:
|
|
2789
|
-
found:
|
|
2790
|
-
foundRate:
|
|
2791
|
-
avgConfidence:
|
|
3539
|
+
jobs: asNumber7(totals["jobs"]),
|
|
3540
|
+
items: asNumber7(totals["items"]),
|
|
3541
|
+
found: asNumber7(totals["found"]),
|
|
3542
|
+
foundRate: asNumber7(totals["found_rate"]),
|
|
3543
|
+
avgConfidence: asNumber7(totals["avg_confidence"])
|
|
2792
3544
|
},
|
|
2793
3545
|
timeSeries,
|
|
2794
3546
|
bySource,
|
|
@@ -2859,6 +3611,41 @@ var SmartEnrichmentEndpoint = class {
|
|
|
2859
3611
|
const data = await this.parseJsonResponse(response);
|
|
2860
3612
|
return SmartEnrichmentJob.fromArray(data);
|
|
2861
3613
|
}
|
|
3614
|
+
/**
|
|
3615
|
+
* Search again for rows of a finished lookup that have no usable answer (`not_found`, or a
|
|
3616
|
+
* number registered to another company). Without `rows` every row that qualifies is rechecked.
|
|
3617
|
+
*
|
|
3618
|
+
* Every recheck counts as a check like a new lookup (Deep Verify ×2), whether a VAT number is
|
|
3619
|
+
* found or not. A row can be rechecked up to 3 times, with 7 days between two rechecks;
|
|
3620
|
+
* `no_vat_exists` and found rows are never rechecked. Pass `dryRun` to see which rows would run
|
|
3621
|
+
* and what they cost without starting anything. Improved rows arrive via the
|
|
3622
|
+
* `enrichment.updated` webhook; `get(jobId).recheck` shows the progress.
|
|
3623
|
+
*
|
|
3624
|
+
* Throws a ValidationException when nothing can be rechecked, the lookup is still running, or
|
|
3625
|
+
* rechecks are not available (sandbox, flat-fee import), and an HttpException (429) when the
|
|
3626
|
+
* start credit or monthly hard cap does not cover it.
|
|
3627
|
+
*/
|
|
3628
|
+
async recheck(jobId, options = {}) {
|
|
3629
|
+
this.validateJobId(jobId);
|
|
3630
|
+
const body = {};
|
|
3631
|
+
if (options.rows !== void 0) {
|
|
3632
|
+
if (options.rows.length === 0) {
|
|
3633
|
+
throw new TaxoraException("rows must not be empty; omit it to recheck every row that qualifies.");
|
|
3634
|
+
}
|
|
3635
|
+
if (options.rows.some((index) => !Number.isInteger(index) || index < 0)) {
|
|
3636
|
+
throw new TaxoraException("rows must contain 0-based row indexes (integers >= 0).");
|
|
3637
|
+
}
|
|
3638
|
+
body["rows"] = [...new Set(options.rows)];
|
|
3639
|
+
}
|
|
3640
|
+
if (options.dryRun) body["dryRun"] = true;
|
|
3641
|
+
const response = await this.sendRequest(
|
|
3642
|
+
"POST",
|
|
3643
|
+
`${this.baseUrl}/smart-enrichment/${encodeURIComponent(jobId)}/recheck`,
|
|
3644
|
+
body
|
|
3645
|
+
);
|
|
3646
|
+
const data = await this.parseJsonResponse(response, [200, 202]);
|
|
3647
|
+
return SmartEnrichmentRecheck.fromArray(data);
|
|
3648
|
+
}
|
|
2862
3649
|
/**
|
|
2863
3650
|
* Poll get(jobId) until the job is no longer processing (completed, failed or resolved).
|
|
2864
3651
|
* Throws a TaxoraException when the job does not finish within `timeoutMs`.
|
|
@@ -4033,7 +4820,7 @@ var AuthRetryHttpClient = class {
|
|
|
4033
4820
|
};
|
|
4034
4821
|
|
|
4035
4822
|
// src/version.ts
|
|
4036
|
-
var SDK_VERSION = "1.
|
|
4823
|
+
var SDK_VERSION = "1.9.0";
|
|
4037
4824
|
|
|
4038
4825
|
// src/http/SdkVersionHttpClient.ts
|
|
4039
4826
|
var SDK_VERSION_HEADER = "X-Taxora-SDK-Version";
|
|
@@ -4060,6 +4847,7 @@ var TaxoraClient = class {
|
|
|
4060
4847
|
company;
|
|
4061
4848
|
smartEnrichment;
|
|
4062
4849
|
eReporting;
|
|
4850
|
+
billing;
|
|
4063
4851
|
baseUrl;
|
|
4064
4852
|
constructor(options) {
|
|
4065
4853
|
const environment = options.environment ?? Environment.SANDBOX;
|
|
@@ -4080,6 +4868,7 @@ var TaxoraClient = class {
|
|
|
4080
4868
|
retryPolicy
|
|
4081
4869
|
);
|
|
4082
4870
|
this.eReporting = new EReportingEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient, retryPolicy);
|
|
4871
|
+
this.billing = new BillingEndpoint(this.baseUrl, options.apiKey, tokenStorage, retryClient, retryPolicy);
|
|
4083
4872
|
}
|
|
4084
4873
|
};
|
|
4085
4874
|
|
|
@@ -4219,18 +5008,25 @@ function toBytes(rawBody) {
|
|
|
4219
5008
|
"invalid_body"
|
|
4220
5009
|
);
|
|
4221
5010
|
}
|
|
5011
|
+
|
|
5012
|
+
// src/webhooks/WebhookEvent.ts
|
|
5013
|
+
function isTransactionBuyerRejected(object) {
|
|
5014
|
+
return object.buyer_rejected === true;
|
|
5015
|
+
}
|
|
4222
5016
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4223
5017
|
0 && (module.exports = {
|
|
4224
5018
|
ApiVersion,
|
|
4225
5019
|
AuthEndpoint,
|
|
4226
5020
|
AuthRetryHttpClient,
|
|
4227
5021
|
AuthenticationException,
|
|
5022
|
+
BillingEndpoint,
|
|
4228
5023
|
CompanyAddress,
|
|
4229
5024
|
CompanyEndpoint,
|
|
4230
5025
|
ComplianceDocumentType,
|
|
4231
5026
|
ComplianceEnrollment,
|
|
4232
5027
|
ComplianceEnrollmentPage,
|
|
4233
5028
|
ComplianceEnrollmentStatus,
|
|
5029
|
+
ComplianceOfferings,
|
|
4234
5030
|
ComplianceService,
|
|
4235
5031
|
ComplianceTaxReport,
|
|
4236
5032
|
ComplianceTaxReportPage,
|
|
@@ -4264,6 +5060,8 @@ function toBytes(rawBody) {
|
|
|
4264
5060
|
SmartEnrichmentHistoryRow,
|
|
4265
5061
|
SmartEnrichmentJob,
|
|
4266
5062
|
SmartEnrichmentMode,
|
|
5063
|
+
SmartEnrichmentRecheck,
|
|
5064
|
+
SmartEnrichmentRecheckState,
|
|
4267
5065
|
SmartEnrichmentRejectionReason,
|
|
4268
5066
|
SmartEnrichmentResource,
|
|
4269
5067
|
SmartEnrichmentStatistics,
|
|
@@ -4272,6 +5070,8 @@ function toBytes(rawBody) {
|
|
|
4272
5070
|
TaxoraClientFactory,
|
|
4273
5071
|
TaxoraException,
|
|
4274
5072
|
Token,
|
|
5073
|
+
UsageSummary,
|
|
5074
|
+
UsageSummaryPage,
|
|
4275
5075
|
ValidationException,
|
|
4276
5076
|
VatCertificateExport,
|
|
4277
5077
|
VatCollection,
|
|
@@ -4300,6 +5100,7 @@ function toBytes(rawBody) {
|
|
|
4300
5100
|
generateWebhookSignatureHeader,
|
|
4301
5101
|
getBaseUrl,
|
|
4302
5102
|
getFailedVatStates,
|
|
5103
|
+
isTransactionBuyerRejected,
|
|
4303
5104
|
parseLocalTaxNumbersCsv,
|
|
4304
5105
|
parseWebhookSignatureHeader,
|
|
4305
5106
|
toComplianceDocumentType,
|