@saasicat/core 1.0.0-rc.15 → 1.0.0-rc.17
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/.build-stamp +1 -1
- package/dist/index.cjs +319 -0
- package/dist/index.d.cts +867 -84
- package/dist/index.d.ts +867 -84
- package/dist/index.js +304 -0
- package/package.json +1 -1
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5a529cc8f17f234940c3b0844d6f20fce18fadd196d3b3485274b711635819af
|
package/dist/index.cjs
CHANGED
|
@@ -37,11 +37,14 @@ __export(index_exports, {
|
|
|
37
37
|
OTP_TTL_MINUTES: () => OTP_TTL_MINUTES,
|
|
38
38
|
OTP_VERIFY_MAX_ATTEMPTS: () => OTP_VERIFY_MAX_ATTEMPTS,
|
|
39
39
|
PASSWORD_RESET_TTL_MINUTES: () => PASSWORD_RESET_TTL_MINUTES,
|
|
40
|
+
PAYMENT_ERROR_CODES: () => PAYMENT_ERROR_CODES,
|
|
41
|
+
PAYMENT_METHOD_TYPES: () => PAYMENT_METHOD_TYPES,
|
|
40
42
|
PENDING_CHECKOUT_TTL_DAYS: () => PENDING_CHECKOUT_TTL_DAYS,
|
|
41
43
|
PENDING_EMAIL_TTL_HOURS: () => PENDING_EMAIL_TTL_HOURS,
|
|
42
44
|
PENDING_ONBOARDING_TTL_DAYS: () => PENDING_ONBOARDING_TTL_DAYS,
|
|
43
45
|
PLATFORM_ERROR_CODES: () => PLATFORM_ERROR_CODES,
|
|
44
46
|
PROMO_ERROR_CODES: () => PROMO_ERROR_CODES,
|
|
47
|
+
PaymentCallbackRejectedError: () => PaymentCallbackRejectedError,
|
|
45
48
|
PersistenceCapabilityError: () => PersistenceCapabilityError,
|
|
46
49
|
PlatformUserExistsError: () => PlatformUserExistsError,
|
|
47
50
|
REGISTRATION_ERROR_CODES: () => REGISTRATION_ERROR_CODES,
|
|
@@ -49,6 +52,8 @@ __export(index_exports, {
|
|
|
49
52
|
REGISTRATION_STEP_BY_STATUS: () => REGISTRATION_STEP_BY_STATUS,
|
|
50
53
|
SETTINGS_ERROR_CODES: () => SETTINGS_ERROR_CODES,
|
|
51
54
|
SETUP_ERROR_CODES: () => SETUP_ERROR_CODES,
|
|
55
|
+
SUBSCRIBER_ERROR_CODES: () => SUBSCRIBER_ERROR_CODES,
|
|
56
|
+
SUBSCRIBER_IDENTITY_FIELDS: () => SUBSCRIBER_IDENTITY_FIELDS,
|
|
52
57
|
applyPromo: () => applyPromo,
|
|
53
58
|
assertPersistenceCapabilities: () => assertPersistenceCapabilities,
|
|
54
59
|
buildActivePlanVersionWhere: () => buildActivePlanVersionWhere,
|
|
@@ -60,16 +65,21 @@ __export(index_exports, {
|
|
|
60
65
|
classifyBundleVersionDiff: () => classifyBundleVersionDiff,
|
|
61
66
|
classifyPlanDiff: () => classifyPlanDiff,
|
|
62
67
|
collectUnsatisfiedRequires: () => collectUnsatisfiedRequires,
|
|
68
|
+
contractPartiesOf: () => contractPartiesOf,
|
|
63
69
|
coverageExcludingSelf: () => coverageExcludingSelf,
|
|
64
70
|
definedFields: () => definedFields,
|
|
65
71
|
diffSettings: () => diffSettings,
|
|
72
|
+
formatCustomerNumber: () => formatCustomerNumber,
|
|
66
73
|
formatErrorMessage: () => formatErrorMessage,
|
|
74
|
+
identityCorrectionDelta: () => identityCorrectionDelta,
|
|
67
75
|
isBundleRedundant: () => isBundleRedundant,
|
|
76
|
+
isPaymentCallbackRejectedError: () => isPaymentCallbackRejectedError,
|
|
68
77
|
isPlatformUserExistsError: () => isPlatformUserExistsError,
|
|
69
78
|
isVersionEditable: () => isVersionEditable,
|
|
70
79
|
keepOneRecommended: () => keepOneRecommended,
|
|
71
80
|
missingRequiresFor: () => missingRequiresFor,
|
|
72
81
|
pickActivePromo: () => pickActivePromo,
|
|
82
|
+
planCatalogSettingsOf: () => planCatalogSettingsOf,
|
|
73
83
|
previousUtcDay: () => previousUtcDay,
|
|
74
84
|
promoStatus: () => promoStatus,
|
|
75
85
|
readQuotaRecord: () => readQuotaRecord,
|
|
@@ -79,10 +89,15 @@ __export(index_exports, {
|
|
|
79
89
|
selectChargeableBundles: () => selectChargeableBundles,
|
|
80
90
|
settingsSubtreeOf: () => settingsSubtreeOf,
|
|
81
91
|
startOfUtcDay: () => startOfUtcDay,
|
|
92
|
+
subscriberFromRegistration: () => subscriberFromRegistration,
|
|
93
|
+
subscriberPaymentMethodColumns: () => subscriberPaymentMethodColumns,
|
|
82
94
|
toBundleStemRow: () => toBundleStemRow,
|
|
83
95
|
toContractLineItemRecord: () => toContractLineItemRecord,
|
|
84
96
|
toPlanRow: () => toPlanRow,
|
|
85
97
|
toPlanVersionRow: () => toPlanVersionRow,
|
|
98
|
+
toSubscriberCorrectionRecord: () => toSubscriberCorrectionRecord,
|
|
99
|
+
toSubscriberPaymentMethodRecord: () => toSubscriberPaymentMethodRecord,
|
|
100
|
+
toSubscriberRecord: () => toSubscriberRecord,
|
|
86
101
|
toSubscriptionContractRecord: () => toSubscriptionContractRecord
|
|
87
102
|
});
|
|
88
103
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -364,6 +379,9 @@ var CATALOGUE_KEYS = /* @__PURE__ */ new Set([
|
|
|
364
379
|
"features",
|
|
365
380
|
"plans"
|
|
366
381
|
]);
|
|
382
|
+
function planCatalogSettingsOf(catalog) {
|
|
383
|
+
return settingsSubtreeOf(catalog);
|
|
384
|
+
}
|
|
367
385
|
function settingsSubtreeOf(catalog) {
|
|
368
386
|
const settings = {};
|
|
369
387
|
for (const [key, value] of Object.entries(catalog)) {
|
|
@@ -674,6 +692,30 @@ var CONTRACT_ERROR_CODES = {
|
|
|
674
692
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT",
|
|
675
693
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED"
|
|
676
694
|
};
|
|
695
|
+
var SUBSCRIBER_ERROR_CODES = {
|
|
696
|
+
/**
|
|
697
|
+
* A contract, a plan change or a booking for a tenant that has no
|
|
698
|
+
* subscriber. Nothing is agreed or charged without the party to it.
|
|
699
|
+
* Carries `tenantId`.
|
|
700
|
+
*/
|
|
701
|
+
SUBSCRIBER_REQUIRED: "SUBSCRIBER_REQUIRED",
|
|
702
|
+
/** The tenant already has a live subscriber. Carries `tenantId`. */
|
|
703
|
+
SUBSCRIBER_ALREADY_EXISTS: "SUBSCRIBER_ALREADY_EXISTS",
|
|
704
|
+
SUBSCRIBER_NOT_FOUND: "SUBSCRIBER_NOT_FOUND",
|
|
705
|
+
SUBSCRIBER_LEGAL_NAME_REQUIRED: "SUBSCRIBER_LEGAL_NAME_REQUIRED",
|
|
706
|
+
/**
|
|
707
|
+
* A detail that has a form — the country, the invoice email — is not in it,
|
|
708
|
+
* or one sign-up requires — the billing address — is missing. Carries `field`.
|
|
709
|
+
*/
|
|
710
|
+
SUBSCRIBER_DETAIL_INVALID: "SUBSCRIBER_DETAIL_INVALID",
|
|
711
|
+
/** A contact change named a field of the legal identity. Carries `field`. */
|
|
712
|
+
SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "SUBSCRIBER_IDENTITY_NOT_A_CONTACT",
|
|
713
|
+
SUBSCRIBER_CORRECTION_REASON_REQUIRED: "SUBSCRIBER_CORRECTION_REASON_REQUIRED",
|
|
714
|
+
SUBSCRIBER_CORRECTION_ACTOR_REQUIRED: "SUBSCRIBER_CORRECTION_ACTOR_REQUIRED",
|
|
715
|
+
SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "SUBSCRIBER_CORRECTION_CHANGES_NOTHING",
|
|
716
|
+
/** The operator declared another legal entity: that is a transfer, not an edit. */
|
|
717
|
+
SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "SUBSCRIBER_TAKEOVER_IS_A_TRANSFER"
|
|
718
|
+
};
|
|
677
719
|
var REGISTRATION_ERROR_CODES = {
|
|
678
720
|
PENDING_REGISTRATION_NOT_FOUND: "PENDING_REGISTRATION_NOT_FOUND",
|
|
679
721
|
PENDING_REGISTRATION_EXPIRED: "PENDING_REGISTRATION_EXPIRED",
|
|
@@ -699,6 +741,12 @@ var AUTH_ERROR_CODES = {
|
|
|
699
741
|
/** Neither `tenantId` nor `userId` could be resolved from the request. */
|
|
700
742
|
TENANT_CONTEXT_MISSING: "TENANT_CONTEXT_MISSING",
|
|
701
743
|
TENANT_ADMIN_REQUIRED: "TENANT_ADMIN_REQUIRED",
|
|
744
|
+
/**
|
|
745
|
+
* The tenant's billing area — its payment method, and later its invoices
|
|
746
|
+
* and account — needs the billing permission, which the application maps
|
|
747
|
+
* to its roles and the tenant's administrator holds by default.
|
|
748
|
+
*/
|
|
749
|
+
BILLING_PERMISSION_REQUIRED: "BILLING_PERMISSION_REQUIRED",
|
|
702
750
|
SUPER_ADMIN_REQUIRED: "SUPER_ADMIN_REQUIRED",
|
|
703
751
|
/** TOTP MFA has never been set up for this user. */
|
|
704
752
|
MFA_NOT_SET_UP: "MFA_NOT_SET_UP",
|
|
@@ -726,6 +774,22 @@ var PROMO_ERROR_CODES = {
|
|
|
726
774
|
PROMO_WOULD_PRODUCE_ZERO_INVOICE: "PROMO_WOULD_PRODUCE_ZERO_INVOICE",
|
|
727
775
|
PROMO_MAX_REDEMPTIONS_LOWERED: "PROMO_MAX_REDEMPTIONS_LOWERED"
|
|
728
776
|
};
|
|
777
|
+
var PAYMENT_ERROR_CODES = {
|
|
778
|
+
/**
|
|
779
|
+
* No gateway account takes new payment methods:
|
|
780
|
+
* `config/saas.yaml#payments.newPaymentMethods` names none.
|
|
781
|
+
*/
|
|
782
|
+
PAYMENTS_NOT_CONFIGURED: "PAYMENTS_NOT_CONFIGURED",
|
|
783
|
+
/** A callback arrived for an account `config/saas.yaml#payments.accounts` does not name. Carries `account`. */
|
|
784
|
+
PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "PAYMENT_GATEWAY_ACCOUNT_UNKNOWN",
|
|
785
|
+
/** A callback the gateway did not send: its signature does not verify. */
|
|
786
|
+
PAYMENT_CALLBACK_REJECTED: "PAYMENT_CALLBACK_REJECTED",
|
|
787
|
+
/**
|
|
788
|
+
* A success or cancel URL at an origin `config/saas.yaml#payments.returnUrlOrigins`
|
|
789
|
+
* does not name. Carries `field`.
|
|
790
|
+
*/
|
|
791
|
+
PAYMENT_RETURN_URL_NOT_ALLOWED: "PAYMENT_RETURN_URL_NOT_ALLOWED"
|
|
792
|
+
};
|
|
729
793
|
var SETTINGS_ERROR_CODES = {
|
|
730
794
|
/** No recorded change has this id, or the installation keeps no record at all. */
|
|
731
795
|
SETTINGS_CHANGE_NOT_FOUND: "SETTINGS_CHANGE_NOT_FOUND"
|
|
@@ -737,7 +801,9 @@ var PLATFORM_ERROR_CODES = {
|
|
|
737
801
|
...CATALOG_ERROR_CODES,
|
|
738
802
|
...BILLING_ERROR_CODES,
|
|
739
803
|
...CONTRACT_ERROR_CODES,
|
|
804
|
+
...SUBSCRIBER_ERROR_CODES,
|
|
740
805
|
...REGISTRATION_ERROR_CODES,
|
|
806
|
+
...PAYMENT_ERROR_CODES,
|
|
741
807
|
...SETTINGS_ERROR_CODES
|
|
742
808
|
};
|
|
743
809
|
|
|
@@ -817,6 +883,19 @@ function selectChargeableBundles(planFeatures, selectedBundles) {
|
|
|
817
883
|
}
|
|
818
884
|
}
|
|
819
885
|
|
|
886
|
+
// src/payment-gateway.types.ts
|
|
887
|
+
var PAYMENT_CALLBACK_REJECTED = "PAYMENT_CALLBACK_REJECTED";
|
|
888
|
+
var PaymentCallbackRejectedError = class extends Error {
|
|
889
|
+
code = PAYMENT_CALLBACK_REJECTED;
|
|
890
|
+
constructor(reason) {
|
|
891
|
+
super(`Payment callback rejected: ${reason}`);
|
|
892
|
+
this.name = "PaymentCallbackRejectedError";
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
function isPaymentCallbackRejectedError(err) {
|
|
896
|
+
return err instanceof Error && err.code === PAYMENT_CALLBACK_REJECTED;
|
|
897
|
+
}
|
|
898
|
+
|
|
820
899
|
// src/registration.types.ts
|
|
821
900
|
var PENDING_EMAIL_TTL_HOURS = 72;
|
|
822
901
|
var PENDING_ONBOARDING_TTL_DAYS = 14;
|
|
@@ -896,11 +975,176 @@ function toQuotaEffects(value) {
|
|
|
896
975
|
return quotas;
|
|
897
976
|
}
|
|
898
977
|
|
|
978
|
+
// src/subscriber-mapping.ts
|
|
979
|
+
var SUBSCRIBER_IDENTITY_FIELDS = [
|
|
980
|
+
"legalName",
|
|
981
|
+
"vatId",
|
|
982
|
+
"taxNumber"
|
|
983
|
+
];
|
|
984
|
+
function formatCustomerNumber(prefix, sequence) {
|
|
985
|
+
return `${prefix}${sequence}`;
|
|
986
|
+
}
|
|
987
|
+
function toSubscriberRecord(row, tenantId) {
|
|
988
|
+
return {
|
|
989
|
+
id: row.id,
|
|
990
|
+
customerNumber: formatCustomerNumber(row.customerNumberPrefix, row.customerSequence),
|
|
991
|
+
legalName: row.legalName,
|
|
992
|
+
addressLine1: row.addressLine1,
|
|
993
|
+
addressLine2: row.addressLine2,
|
|
994
|
+
postalCode: row.postalCode,
|
|
995
|
+
city: row.city,
|
|
996
|
+
country: row.country,
|
|
997
|
+
vatId: row.vatId,
|
|
998
|
+
taxNumber: row.taxNumber,
|
|
999
|
+
invoiceEmail: row.invoiceEmail,
|
|
1000
|
+
tenantId,
|
|
1001
|
+
migrated: row.migrated,
|
|
1002
|
+
createdAt: row.createdAt,
|
|
1003
|
+
updatedAt: row.updatedAt
|
|
1004
|
+
};
|
|
1005
|
+
}
|
|
1006
|
+
function toSubscriberCorrectionRecord(row) {
|
|
1007
|
+
return {
|
|
1008
|
+
id: row.id,
|
|
1009
|
+
subscriberId: row.subscriberId,
|
|
1010
|
+
previous: toIdentityValues(row.previous),
|
|
1011
|
+
corrected: toIdentityValues(row.corrected),
|
|
1012
|
+
reason: row.reason,
|
|
1013
|
+
correctedBy: row.correctedBy,
|
|
1014
|
+
correctedAt: row.correctedAt
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
function identityCorrectionDelta(current, corrected) {
|
|
1018
|
+
const previous = {};
|
|
1019
|
+
const next = {};
|
|
1020
|
+
for (const field of SUBSCRIBER_IDENTITY_FIELDS) {
|
|
1021
|
+
const value = corrected[field];
|
|
1022
|
+
if (value === void 0 || value === current[field]) continue;
|
|
1023
|
+
previous[field] = current[field];
|
|
1024
|
+
next[field] = value;
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
previous,
|
|
1028
|
+
corrected: next
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
1031
|
+
function contractPartiesOf(subscriber, issuer) {
|
|
1032
|
+
const party = {
|
|
1033
|
+
customerNumber: subscriber.customerNumber,
|
|
1034
|
+
legalName: subscriber.legalName,
|
|
1035
|
+
vatId: subscriber.vatId,
|
|
1036
|
+
taxNumber: subscriber.taxNumber,
|
|
1037
|
+
addressLine1: subscriber.addressLine1,
|
|
1038
|
+
addressLine2: subscriber.addressLine2,
|
|
1039
|
+
postalCode: subscriber.postalCode,
|
|
1040
|
+
city: subscriber.city,
|
|
1041
|
+
country: subscriber.country
|
|
1042
|
+
};
|
|
1043
|
+
return {
|
|
1044
|
+
subscriberId: subscriber.id,
|
|
1045
|
+
subscriber: party,
|
|
1046
|
+
issuer: issuer ? issuerPartyOf(issuer) : null
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function issuerPartyOf(issuer) {
|
|
1050
|
+
return {
|
|
1051
|
+
legalName: issuer.legalName,
|
|
1052
|
+
vatId: issuer.vatId ?? null,
|
|
1053
|
+
taxNumber: issuer.taxNumber ?? null,
|
|
1054
|
+
addressLine1: issuer.addressLine1 ?? null,
|
|
1055
|
+
addressLine2: issuer.addressLine2 ?? null,
|
|
1056
|
+
postalCode: issuer.postalCode ?? null,
|
|
1057
|
+
city: issuer.city ?? null,
|
|
1058
|
+
country: issuer.country ?? null
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
function subscriberFromRegistration(pending) {
|
|
1062
|
+
return {
|
|
1063
|
+
legalName: pending.tenantName,
|
|
1064
|
+
invoiceEmail: pending.email,
|
|
1065
|
+
addressLine1: pending.addressLine1,
|
|
1066
|
+
addressLine2: pending.addressLine2,
|
|
1067
|
+
postalCode: pending.postalCode,
|
|
1068
|
+
city: pending.city,
|
|
1069
|
+
country: pending.country,
|
|
1070
|
+
vatId: pending.vatId,
|
|
1071
|
+
taxNumber: pending.taxNumber
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
function toIdentityValues(value) {
|
|
1075
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
|
|
1076
|
+
const source = value;
|
|
1077
|
+
const values = {};
|
|
1078
|
+
for (const field of SUBSCRIBER_IDENTITY_FIELDS) {
|
|
1079
|
+
if (!Object.prototype.hasOwnProperty.call(source, field)) continue;
|
|
1080
|
+
const entry = source[field];
|
|
1081
|
+
values[field] = typeof entry === "string" ? entry : null;
|
|
1082
|
+
}
|
|
1083
|
+
return values;
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
// src/subscriber-payment-method-mapping.ts
|
|
1087
|
+
var PAYMENT_METHOD_TYPES = ["card", "sepa_debit"];
|
|
1088
|
+
var STATUSES = ["ACTIVE", "REPLACED"];
|
|
1089
|
+
function toSubscriberPaymentMethodRecord(row) {
|
|
1090
|
+
return {
|
|
1091
|
+
id: row.id,
|
|
1092
|
+
subscriberId: row.subscriberId,
|
|
1093
|
+
gatewayAccount: row.gatewayAccount,
|
|
1094
|
+
provider: row.provider,
|
|
1095
|
+
customerRef: row.customerRef,
|
|
1096
|
+
paymentMethodRef: row.paymentMethodRef,
|
|
1097
|
+
type: oneOf(PAYMENT_METHOD_TYPES, row.type, "type", row.id),
|
|
1098
|
+
brand: row.brand,
|
|
1099
|
+
last4: row.last4,
|
|
1100
|
+
expiryMonth: row.expiryMonth,
|
|
1101
|
+
expiryYear: row.expiryYear,
|
|
1102
|
+
country: row.country,
|
|
1103
|
+
bankCode: row.bankCode,
|
|
1104
|
+
mandateReference: row.mandateReference,
|
|
1105
|
+
status: oneOf(STATUSES, row.status, "status", row.id),
|
|
1106
|
+
confirmedAt: row.confirmedAt,
|
|
1107
|
+
replacedAt: row.replacedAt,
|
|
1108
|
+
createdAt: row.createdAt
|
|
1109
|
+
};
|
|
1110
|
+
}
|
|
1111
|
+
function subscriberPaymentMethodColumns(data) {
|
|
1112
|
+
return {
|
|
1113
|
+
subscriberId: data.subscriberId,
|
|
1114
|
+
gatewayAccount: data.gatewayAccount,
|
|
1115
|
+
provider: data.provider,
|
|
1116
|
+
customerRef: data.customerRef,
|
|
1117
|
+
paymentMethodRef: data.paymentMethodRef,
|
|
1118
|
+
type: data.type,
|
|
1119
|
+
brand: data.brand,
|
|
1120
|
+
last4: data.last4,
|
|
1121
|
+
expiryMonth: data.expiryMonth,
|
|
1122
|
+
expiryYear: data.expiryYear,
|
|
1123
|
+
country: data.country,
|
|
1124
|
+
bankCode: data.bankCode,
|
|
1125
|
+
mandateReference: data.mandateReference,
|
|
1126
|
+
confirmedAt: data.confirmedAt
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
function oneOf(allowed, value, column, id) {
|
|
1130
|
+
const match = allowed.find((entry) => entry === value);
|
|
1131
|
+
if (match === void 0) {
|
|
1132
|
+
throw new Error(
|
|
1133
|
+
`subscriber_payment_methods row '${id}' holds ${column} '${value}', which is none of ${allowed.join(", ")}.`
|
|
1134
|
+
);
|
|
1135
|
+
}
|
|
1136
|
+
return match;
|
|
1137
|
+
}
|
|
1138
|
+
|
|
899
1139
|
// src/subscription-contract-mapping.ts
|
|
900
1140
|
function toSubscriptionContractRecord(row, lineItems) {
|
|
901
1141
|
return {
|
|
902
1142
|
id: row.id,
|
|
903
1143
|
tenantId: row.tenantId,
|
|
1144
|
+
subscriberId: row.subscriberId,
|
|
1145
|
+
subscriber: toSubscriberParty(row.subscriberSnapshot),
|
|
1146
|
+
issuer: isPlainObject2(row.issuerSnapshot) ? toIssuerParty(row.issuerSnapshot) : null,
|
|
1147
|
+
partiesMigrated: row.partiesMigrated,
|
|
904
1148
|
status: row.status,
|
|
905
1149
|
effectiveFrom: row.effectiveFrom,
|
|
906
1150
|
effectiveUntil: row.effectiveUntil,
|
|
@@ -941,6 +1185,32 @@ function toContractLineItemRecord(row) {
|
|
|
941
1185
|
createdAt: row.createdAt
|
|
942
1186
|
};
|
|
943
1187
|
}
|
|
1188
|
+
function toSubscriberParty(value) {
|
|
1189
|
+
const source = isPlainObject2(value) ? value : {};
|
|
1190
|
+
return {
|
|
1191
|
+
customerNumber: stringOr(source.customerNumber, ""),
|
|
1192
|
+
...toIssuerParty(source)
|
|
1193
|
+
};
|
|
1194
|
+
}
|
|
1195
|
+
function toIssuerParty(value) {
|
|
1196
|
+
const source = value;
|
|
1197
|
+
return {
|
|
1198
|
+
legalName: stringOr(source.legalName, ""),
|
|
1199
|
+
vatId: stringOrNull(source.vatId),
|
|
1200
|
+
taxNumber: stringOrNull(source.taxNumber),
|
|
1201
|
+
addressLine1: stringOrNull(source.addressLine1),
|
|
1202
|
+
addressLine2: stringOrNull(source.addressLine2),
|
|
1203
|
+
postalCode: stringOrNull(source.postalCode),
|
|
1204
|
+
city: stringOrNull(source.city),
|
|
1205
|
+
country: stringOrNull(source.country)
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
function stringOr(value, fallback) {
|
|
1209
|
+
return typeof value === "string" ? value : fallback;
|
|
1210
|
+
}
|
|
1211
|
+
function stringOrNull(value) {
|
|
1212
|
+
return typeof value === "string" ? value : null;
|
|
1213
|
+
}
|
|
944
1214
|
function isPlainObject2(value) {
|
|
945
1215
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
946
1216
|
}
|
|
@@ -1016,6 +1286,7 @@ var ERROR_MESSAGES_EN = {
|
|
|
1016
1286
|
NO_TENANT_ASSIGNED: "No tenant assigned",
|
|
1017
1287
|
TENANT_CONTEXT_MISSING: "No tenant ID found on the request",
|
|
1018
1288
|
TENANT_ADMIN_REQUIRED: "This action requires the TENANT_ADMIN role.",
|
|
1289
|
+
BILLING_PERMISSION_REQUIRED: "This part of the billing area requires the billing permission.",
|
|
1019
1290
|
SUPER_ADMIN_REQUIRED: "Only the SUPER_ADMIN role is allowed",
|
|
1020
1291
|
MFA_NOT_SET_UP: "Run the MFA setup via the CLI first.",
|
|
1021
1292
|
MFA_REQUIRED: "TOTP code required in the X-Mfa-Code header.",
|
|
@@ -1157,6 +1428,17 @@ var ERROR_MESSAGES_EN = {
|
|
|
1157
1428
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' not found",
|
|
1158
1429
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "No active subscription contract for tenant {tenantId}",
|
|
1159
1430
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' is already closed",
|
|
1431
|
+
// ── subscriber ──
|
|
1432
|
+
SUBSCRIBER_REQUIRED: "Tenant '{tenantId}' has no subscriber. Nothing is agreed or charged without the party to it: create the tenant's subscriber first.",
|
|
1433
|
+
SUBSCRIBER_ALREADY_EXISTS: "Tenant '{tenantId}' already has a subscriber.",
|
|
1434
|
+
SUBSCRIBER_NOT_FOUND: "Subscriber '{subscriberId}' not found",
|
|
1435
|
+
SUBSCRIBER_LEGAL_NAME_REQUIRED: "A subscriber needs its legal name.",
|
|
1436
|
+
SUBSCRIBER_DETAIL_INVALID: "The subscriber's {field} is not valid.",
|
|
1437
|
+
SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "{field} is part of the subscriber's legal identity and changes only as a correction, with a reason.",
|
|
1438
|
+
SUBSCRIBER_CORRECTION_REASON_REQUIRED: "A correction of the legal identity needs a reason.",
|
|
1439
|
+
SUBSCRIBER_CORRECTION_ACTOR_REQUIRED: "A correction of the legal identity has to say who makes it.",
|
|
1440
|
+
SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "The correction changes nothing: every value it names is already recorded.",
|
|
1441
|
+
SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "Another legal entity taking over a subscriber is a transfer, not a correction, and cannot be recorded as an edit.",
|
|
1160
1442
|
// ── registration ──
|
|
1161
1443
|
PENDING_REGISTRATION_NOT_FOUND: "This registration could not be found. It may have already been completed or discarded.",
|
|
1162
1444
|
PENDING_REGISTRATION_EXPIRED: "This registration has expired. Please start again.",
|
|
@@ -1172,6 +1454,11 @@ var ERROR_MESSAGES_EN = {
|
|
|
1172
1454
|
PLAN_NOT_AVAILABLE: "This plan is not available.",
|
|
1173
1455
|
PLAN_NOT_SELECTED: "Please select a plan first.",
|
|
1174
1456
|
MODEL_NOT_AVAILABLE: "This option is not available.",
|
|
1457
|
+
// ── payments ──
|
|
1458
|
+
PAYMENTS_NOT_CONFIGURED: "Payment methods cannot be set up here yet.",
|
|
1459
|
+
PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "No payment gateway account is configured under '{account}'.",
|
|
1460
|
+
PAYMENT_CALLBACK_REJECTED: "The payment callback could not be verified.",
|
|
1461
|
+
PAYMENT_RETURN_URL_NOT_ALLOWED: "The {field} leads to a site this installation does not return to.",
|
|
1175
1462
|
// ── entitlement (code lives in upsell.types.ts) ──
|
|
1176
1463
|
[FEATURE_NOT_LICENSED]: "Feature {featureKeys} is not included in the current plan.",
|
|
1177
1464
|
// ── settings ──
|
|
@@ -1206,6 +1493,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
1206
1493
|
NO_TENANT_ASSIGNED: "Kein Mandant zugeordnet",
|
|
1207
1494
|
TENANT_CONTEXT_MISSING: "Am Request wurde keine Mandanten-ID gefunden",
|
|
1208
1495
|
TENANT_ADMIN_REQUIRED: "Diese Aktion erfordert die Rolle TENANT_ADMIN.",
|
|
1496
|
+
BILLING_PERMISSION_REQUIRED: "Dieser Teil der Abrechnung erfordert die Abrechnungs-Berechtigung.",
|
|
1209
1497
|
SUPER_ADMIN_REQUIRED: "Nur die Rolle SUPER_ADMIN ist zugelassen",
|
|
1210
1498
|
MFA_NOT_SET_UP: "Richte MFA zuerst \xFCber die CLI ein.",
|
|
1211
1499
|
MFA_REQUIRED: "TOTP-Code im Header X-Mfa-Code erforderlich.",
|
|
@@ -1347,6 +1635,17 @@ var ERROR_MESSAGES_DE = {
|
|
|
1347
1635
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' nicht gefunden",
|
|
1348
1636
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "Kein aktiver Abo-Vertrag f\xFCr Mandant {tenantId}",
|
|
1349
1637
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' ist bereits geschlossen",
|
|
1638
|
+
// ── subscriber ──
|
|
1639
|
+
SUBSCRIBER_REQUIRED: "Mandant '{tenantId}' hat keinen Vertragspartner. Ohne ihn wird nichts vereinbart oder berechnet: Zuerst muss der Vertragspartner des Mandanten angelegt werden.",
|
|
1640
|
+
SUBSCRIBER_ALREADY_EXISTS: "Mandant '{tenantId}' hat bereits einen Vertragspartner.",
|
|
1641
|
+
SUBSCRIBER_NOT_FOUND: "Vertragspartner '{subscriberId}' nicht gefunden",
|
|
1642
|
+
SUBSCRIBER_LEGAL_NAME_REQUIRED: "Ein Vertragspartner braucht seinen rechtlichen Namen.",
|
|
1643
|
+
SUBSCRIBER_DETAIL_INVALID: "Das Feld {field} des Vertragspartners ist ung\xFCltig.",
|
|
1644
|
+
SUBSCRIBER_IDENTITY_NOT_A_CONTACT: "{field} geh\xF6rt zur rechtlichen Identit\xE4t des Vertragspartners und \xE4ndert sich nur als Korrektur mit Begr\xFCndung.",
|
|
1645
|
+
SUBSCRIBER_CORRECTION_REASON_REQUIRED: "Eine Korrektur der rechtlichen Identit\xE4t braucht eine Begr\xFCndung.",
|
|
1646
|
+
SUBSCRIBER_CORRECTION_ACTOR_REQUIRED: "Eine Korrektur der rechtlichen Identit\xE4t muss nennen, wer sie vornimmt.",
|
|
1647
|
+
SUBSCRIBER_CORRECTION_CHANGES_NOTHING: "Die Korrektur \xE4ndert nichts: Jeder genannte Wert ist bereits erfasst.",
|
|
1648
|
+
SUBSCRIBER_TAKEOVER_IS_A_TRANSFER: "\xDCbernimmt eine andere Rechtsperson, ist das eine \xDCbertragung und keine Korrektur; sie l\xE4sst sich nicht als \xC4nderung erfassen.",
|
|
1350
1649
|
// ── registration ──
|
|
1351
1650
|
PENDING_REGISTRATION_NOT_FOUND: "Diese Registrierung konnten wir nicht finden. Vielleicht ist sie bereits abgeschlossen oder verworfen.",
|
|
1352
1651
|
PENDING_REGISTRATION_EXPIRED: "Diese Registrierung ist abgelaufen. Bitte fange noch einmal von vorn an.",
|
|
@@ -1362,6 +1661,11 @@ var ERROR_MESSAGES_DE = {
|
|
|
1362
1661
|
PLAN_NOT_AVAILABLE: "Dieser Plan steht nicht zur Verf\xFCgung.",
|
|
1363
1662
|
PLAN_NOT_SELECTED: "Bitte w\xE4hle zuerst einen Plan aus.",
|
|
1364
1663
|
MODEL_NOT_AVAILABLE: "Diese Option steht nicht zur Verf\xFCgung.",
|
|
1664
|
+
// ── payments ──
|
|
1665
|
+
PAYMENTS_NOT_CONFIGURED: "Zahlungsmethoden k\xF6nnen hier noch nicht hinterlegt werden.",
|
|
1666
|
+
PAYMENT_GATEWAY_ACCOUNT_UNKNOWN: "Unter '{account}' ist kein Konto eines Zahlungsanbieters eingerichtet.",
|
|
1667
|
+
PAYMENT_CALLBACK_REJECTED: "Die R\xFCckmeldung des Zahlungsanbieters lie\xDF sich nicht pr\xFCfen.",
|
|
1668
|
+
PAYMENT_RETURN_URL_NOT_ALLOWED: "Die {field} f\xFChrt auf eine Seite, zu der diese Installation nicht zur\xFCckleitet.",
|
|
1365
1669
|
// ── entitlement (code lives in upsell.types.ts) ──
|
|
1366
1670
|
[FEATURE_NOT_LICENSED]: "Das Feature {featureKeys} ist im aktuellen Plan nicht enthalten.",
|
|
1367
1671
|
// ── settings ──
|
|
@@ -1386,11 +1690,14 @@ var ERROR_MESSAGES_DE = {
|
|
|
1386
1690
|
OTP_TTL_MINUTES,
|
|
1387
1691
|
OTP_VERIFY_MAX_ATTEMPTS,
|
|
1388
1692
|
PASSWORD_RESET_TTL_MINUTES,
|
|
1693
|
+
PAYMENT_ERROR_CODES,
|
|
1694
|
+
PAYMENT_METHOD_TYPES,
|
|
1389
1695
|
PENDING_CHECKOUT_TTL_DAYS,
|
|
1390
1696
|
PENDING_EMAIL_TTL_HOURS,
|
|
1391
1697
|
PENDING_ONBOARDING_TTL_DAYS,
|
|
1392
1698
|
PLATFORM_ERROR_CODES,
|
|
1393
1699
|
PROMO_ERROR_CODES,
|
|
1700
|
+
PaymentCallbackRejectedError,
|
|
1394
1701
|
PersistenceCapabilityError,
|
|
1395
1702
|
PlatformUserExistsError,
|
|
1396
1703
|
REGISTRATION_ERROR_CODES,
|
|
@@ -1398,6 +1705,8 @@ var ERROR_MESSAGES_DE = {
|
|
|
1398
1705
|
REGISTRATION_STEP_BY_STATUS,
|
|
1399
1706
|
SETTINGS_ERROR_CODES,
|
|
1400
1707
|
SETUP_ERROR_CODES,
|
|
1708
|
+
SUBSCRIBER_ERROR_CODES,
|
|
1709
|
+
SUBSCRIBER_IDENTITY_FIELDS,
|
|
1401
1710
|
applyPromo,
|
|
1402
1711
|
assertPersistenceCapabilities,
|
|
1403
1712
|
buildActivePlanVersionWhere,
|
|
@@ -1409,16 +1718,21 @@ var ERROR_MESSAGES_DE = {
|
|
|
1409
1718
|
classifyBundleVersionDiff,
|
|
1410
1719
|
classifyPlanDiff,
|
|
1411
1720
|
collectUnsatisfiedRequires,
|
|
1721
|
+
contractPartiesOf,
|
|
1412
1722
|
coverageExcludingSelf,
|
|
1413
1723
|
definedFields,
|
|
1414
1724
|
diffSettings,
|
|
1725
|
+
formatCustomerNumber,
|
|
1415
1726
|
formatErrorMessage,
|
|
1727
|
+
identityCorrectionDelta,
|
|
1416
1728
|
isBundleRedundant,
|
|
1729
|
+
isPaymentCallbackRejectedError,
|
|
1417
1730
|
isPlatformUserExistsError,
|
|
1418
1731
|
isVersionEditable,
|
|
1419
1732
|
keepOneRecommended,
|
|
1420
1733
|
missingRequiresFor,
|
|
1421
1734
|
pickActivePromo,
|
|
1735
|
+
planCatalogSettingsOf,
|
|
1422
1736
|
previousUtcDay,
|
|
1423
1737
|
promoStatus,
|
|
1424
1738
|
readQuotaRecord,
|
|
@@ -1428,9 +1742,14 @@ var ERROR_MESSAGES_DE = {
|
|
|
1428
1742
|
selectChargeableBundles,
|
|
1429
1743
|
settingsSubtreeOf,
|
|
1430
1744
|
startOfUtcDay,
|
|
1745
|
+
subscriberFromRegistration,
|
|
1746
|
+
subscriberPaymentMethodColumns,
|
|
1431
1747
|
toBundleStemRow,
|
|
1432
1748
|
toContractLineItemRecord,
|
|
1433
1749
|
toPlanRow,
|
|
1434
1750
|
toPlanVersionRow,
|
|
1751
|
+
toSubscriberCorrectionRecord,
|
|
1752
|
+
toSubscriberPaymentMethodRecord,
|
|
1753
|
+
toSubscriberRecord,
|
|
1435
1754
|
toSubscriptionContractRecord
|
|
1436
1755
|
});
|