@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 CHANGED
@@ -1 +1 @@
1
- 785f84b789c4fbc325a4d35f81dec979a2575832412363bbcf2fbbe87995e875
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
  });