@saasicat/core 1.0.0-rc.13 → 1.0.0-rc.15
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 +18 -0
- package/dist/index.d.cts +62 -17
- package/dist/index.d.ts +62 -17
- package/dist/index.js +18 -0
- package/package.json +1 -1
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
785f84b789c4fbc325a4d35f81dec979a2575832412363bbcf2fbbe87995e875
|
package/dist/index.cjs
CHANGED
|
@@ -543,6 +543,11 @@ var BILLING_ERROR_CODES = {
|
|
|
543
543
|
PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG",
|
|
544
544
|
/** Plan exists but cannot be booked via self-service. */
|
|
545
545
|
PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE",
|
|
546
|
+
/**
|
|
547
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
548
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
549
|
+
*/
|
|
550
|
+
PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE",
|
|
546
551
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
547
552
|
PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED",
|
|
548
553
|
/**
|
|
@@ -651,6 +656,7 @@ var CONTRACT_ERROR_CODES = {
|
|
|
651
656
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE",
|
|
652
657
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW",
|
|
653
658
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH",
|
|
659
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT",
|
|
654
660
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH",
|
|
655
661
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START",
|
|
656
662
|
// ── stage 3 ──
|
|
@@ -658,6 +664,12 @@ var CONTRACT_ERROR_CODES = {
|
|
|
658
664
|
CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED",
|
|
659
665
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED",
|
|
660
666
|
CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED",
|
|
667
|
+
/**
|
|
668
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
669
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
670
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
671
|
+
*/
|
|
672
|
+
CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED",
|
|
661
673
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND",
|
|
662
674
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT",
|
|
663
675
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED"
|
|
@@ -1081,6 +1093,7 @@ var ERROR_MESSAGES_EN = {
|
|
|
1081
1093
|
NO_ACTIVE_PLAN_VERSION: "No plan version for {planId} active as of {asOf} \u2014 neither the validFrom window is satisfied nor is a latest-live version available.",
|
|
1082
1094
|
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" is not in the catalog',
|
|
1083
1095
|
PLAN_NOT_SELF_SERVICE: "{planName} is only activated via a special contract. Please contact the contract manager.",
|
|
1096
|
+
PLAN_NOT_SOLD_IN_CYCLE: "{planName} has no price for this billing rhythm and cannot be booked in it.",
|
|
1084
1097
|
PLAN_CHANGE_BLOCKED: "Plan change during onboarding is blocked.",
|
|
1085
1098
|
SUBSCRIPTION_CHANGED: "This subscription changed while the request was being decided. Reload it.",
|
|
1086
1099
|
NO_SUBSCRIPTION: "This tenant has no subscription to cancel.",
|
|
@@ -1133,12 +1146,14 @@ var ERROR_MESSAGES_EN = {
|
|
|
1133
1146
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "{field} must be a valid date.",
|
|
1134
1147
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "effectiveUntil must be after effectiveFrom.",
|
|
1135
1148
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "A line item's taxAmount must be exactly priceGross minus priceNet.",
|
|
1149
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "A subscription contract states a tax rate of {taxRate} at {field}, which is not a percentage: a rate lies from 0 to 100, and a value between 0 and 1 is refused as a fraction.",
|
|
1136
1150
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "effectiveUntil must be after the effectiveFrom of the contract.",
|
|
1137
1151
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "A line item must be booked in the currency its contract was priced in.",
|
|
1138
1152
|
CHECKOUT_OFFER_NOT_FOUND: "CheckoutOffer '{offerId}' not found",
|
|
1139
1153
|
CHECKOUT_OFFER_EXPIRED: "Checkout offer '{offerId}' has expired and cannot be {action}",
|
|
1140
1154
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "Checkout offer '{offerId}' has already been consumed and cannot be {action}",
|
|
1141
1155
|
CHECKOUT_OFFER_NOT_CONSUMED: "CheckoutOffer '{offerId}' must be consumed before the contract is created",
|
|
1156
|
+
CHECKOUT_OFFER_CHANGED: "Checkout offer '{offerId}' changed while it was being concluded. Load it again.",
|
|
1142
1157
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' not found",
|
|
1143
1158
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "No active subscription contract for tenant {tenantId}",
|
|
1144
1159
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' is already closed",
|
|
@@ -1268,6 +1283,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
1268
1283
|
NO_ACTIVE_PLAN_VERSION: "Zum {asOf} ist keine Planversion f\xFCr {planId} aktiv \u2014 weder ist das validFrom-Fenster erf\xFCllt, noch steht eine j\xFCngste Live-Version bereit.",
|
|
1269
1284
|
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" steht nicht im Katalog',
|
|
1270
1285
|
PLAN_NOT_SELF_SERVICE: "{planName} wird nur \xFCber einen Sondervertrag freigeschaltet. Bitte wenden Sie sich an die Vertragsverwaltung.",
|
|
1286
|
+
PLAN_NOT_SOLD_IN_CYCLE: "{planName} hat f\xFCr diesen Abrechnungsrhythmus keinen Preis und kann darin nicht gebucht werden.",
|
|
1271
1287
|
PLAN_CHANGE_BLOCKED: "W\xE4hrend des Onboardings ist ein Planwechsel gesperrt.",
|
|
1272
1288
|
SUBSCRIPTION_CHANGED: "Dieses Abonnement hat sich ge\xE4ndert, w\xE4hrend die Anfrage entschieden wurde. Bitte lade es neu.",
|
|
1273
1289
|
NO_SUBSCRIPTION: "Dieser Mandant hat kein Abonnement, das gek\xFCndigt werden kann.",
|
|
@@ -1320,12 +1336,14 @@ var ERROR_MESSAGES_DE = {
|
|
|
1320
1336
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "{field} muss ein g\xFCltiges Datum sein.",
|
|
1321
1337
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "effectiveUntil muss nach effectiveFrom liegen.",
|
|
1322
1338
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "taxAmount einer Position muss exakt priceGross minus priceNet sein.",
|
|
1339
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "Ein Abo-Vertrag nennt bei {field} einen Steuersatz von {taxRate}, der kein Prozentsatz ist: Ein Satz liegt zwischen 0 und 100, und ein Wert zwischen 0 und 1 wird als Bruch abgelehnt.",
|
|
1323
1340
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "Eine Position muss in der W\xE4hrung gebucht sein, in der ihr Vertrag bepreist ist.",
|
|
1324
1341
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "effectiveUntil muss nach dem effectiveFrom des Vertrags liegen.",
|
|
1325
1342
|
CHECKOUT_OFFER_NOT_FOUND: "CheckoutOffer '{offerId}' nicht gefunden",
|
|
1326
1343
|
CHECKOUT_OFFER_EXPIRED: "Checkout-Angebot '{offerId}' ist abgelaufen \u2014 '{action}' ist nicht mehr m\xF6glich",
|
|
1327
1344
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "Checkout-Angebot '{offerId}' wurde bereits eingel\xF6st \u2014 '{action}' ist nicht mehr m\xF6glich",
|
|
1328
1345
|
CHECKOUT_OFFER_NOT_CONSUMED: "CheckoutOffer '{offerId}' muss eingel\xF6st sein, bevor der Vertrag entsteht",
|
|
1346
|
+
CHECKOUT_OFFER_CHANGED: "Checkout-Angebot '{offerId}' hat sich w\xE4hrend des Abschlusses ge\xE4ndert. Bitte neu laden.",
|
|
1329
1347
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' nicht gefunden",
|
|
1330
1348
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "Kein aktiver Abo-Vertrag f\xFCr Mandant {tenantId}",
|
|
1331
1349
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' ist bereits geschlossen",
|
package/dist/index.d.cts
CHANGED
|
@@ -2003,6 +2003,11 @@ interface PromoPreviewValidResponse {
|
|
|
2003
2003
|
/** Decimal-as-string, e.g. "199.00". */
|
|
2004
2004
|
originalGross: string;
|
|
2005
2005
|
discountGross: string;
|
|
2006
|
+
/**
|
|
2007
|
+
* `discountGross` in net, converted at the installation's VAT rate —
|
|
2008
|
+
* the figure a page showing net prices takes off the plan price.
|
|
2009
|
+
*/
|
|
2010
|
+
discountNet: string;
|
|
2006
2011
|
discountedGross: string;
|
|
2007
2012
|
includedVat: string;
|
|
2008
2013
|
nextRegularAmountGross: string;
|
|
@@ -2821,16 +2826,8 @@ interface SubscriptionContractPriceSnapshot {
|
|
|
2821
2826
|
discountNet: number;
|
|
2822
2827
|
totalNet: number;
|
|
2823
2828
|
/**
|
|
2824
|
-
* The rate this contract's total was computed at
|
|
2825
|
-
*
|
|
2826
|
-
* it was concluded from one.
|
|
2827
|
-
*
|
|
2828
|
-
* A checkout offer prices its lines as `net * (1 + vatRate)`, so it states
|
|
2829
|
-
* a fraction, and the value is copied here as it stands. The field
|
|
2830
|
-
* therefore carries both units across a history and cannot be compared
|
|
2831
|
-
* across contracts. `ContractLineItemRecord.taxRate` is always per cent and
|
|
2832
|
-
* is the one to read; this is kept as written because it is the record of
|
|
2833
|
-
* what the contract was concluded with.
|
|
2829
|
+
* The tax rate this contract's total was computed at, as a percentage:
|
|
2830
|
+
* 19 means 19 %, as every tax rate in SaaSiCat is.
|
|
2834
2831
|
*/
|
|
2835
2832
|
vatRate: number;
|
|
2836
2833
|
totalGross: number;
|
|
@@ -3088,7 +3085,15 @@ interface SubscriptionContractRepository {
|
|
|
3088
3085
|
* instead of drawing an extra pool connection (starvation guard, #70).
|
|
3089
3086
|
*/
|
|
3090
3087
|
findActiveByTenantId(tenantId: string, asOf?: Date, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3091
|
-
|
|
3088
|
+
/** With `tx`, the contract is written on that transaction and undone with it. */
|
|
3089
|
+
create(data: CreateSubscriptionContractData, tx?: TransactionContext): Promise<SubscriptionContractRecord>;
|
|
3090
|
+
/**
|
|
3091
|
+
* The contract concluded from a checkout offer (`originalOfferId`), or
|
|
3092
|
+
* `null` when none was. An offer is consumed once and so yields one
|
|
3093
|
+
* contract (`SC-MKT-017`); where an application's own path wrote two, the
|
|
3094
|
+
* earliest is returned, so the answer does not depend on read order.
|
|
3095
|
+
*/
|
|
3096
|
+
findByOriginalOfferId(offerId: string, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3092
3097
|
terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
|
|
3093
3098
|
}
|
|
3094
3099
|
/**
|
|
@@ -3404,6 +3409,8 @@ interface PlanVersionRepository {
|
|
|
3404
3409
|
*
|
|
3405
3410
|
* Note: ignores `validFrom`/`validUntil`. For time-aware
|
|
3406
3411
|
* resolution (onboarding, plan fallback for TRIAL) use `findActive`.
|
|
3412
|
+
*
|
|
3413
|
+
* A plan key no plan has finds `null`, not an error.
|
|
3407
3414
|
*/
|
|
3408
3415
|
findLatestLive(planId: string, tx?: TransactionContext): Promise<PlanVersionRecord | null>;
|
|
3409
3416
|
/**
|
|
@@ -3416,6 +3423,8 @@ interface PlanVersionRepository {
|
|
|
3416
3423
|
* return the highest `validFrom`, explicitly ordering null start dates
|
|
3417
3424
|
* last as a legacy fallback. Adapters without validity columns may omit
|
|
3418
3425
|
* the method (consumers fall back to `findLatestLive`).
|
|
3426
|
+
*
|
|
3427
|
+
* A plan key no plan has finds `null`, not an error.
|
|
3419
3428
|
*/
|
|
3420
3429
|
findActive?(planId: string, asOf?: Date, tx?: TransactionContext): Promise<PlanVersionRecord | null>;
|
|
3421
3430
|
}
|
|
@@ -4029,8 +4038,19 @@ interface CheckoutOfferRepository {
|
|
|
4029
4038
|
findById(id: string): Promise<CheckoutOfferRow | null>;
|
|
4030
4039
|
create(data: CreateCheckoutOfferData): Promise<CheckoutOfferRow>;
|
|
4031
4040
|
update(id: string, data: UpdateCheckoutOfferData): Promise<CheckoutOfferRow>;
|
|
4032
|
-
/**
|
|
4033
|
-
|
|
4041
|
+
/**
|
|
4042
|
+
* Sets `status = 'consumed'` + `consumedAt = NOW()`, and only while the
|
|
4043
|
+
* offer is still `open`: the write carries that condition, so of two
|
|
4044
|
+
* callers consuming at once one succeeds and the other is refused with
|
|
4045
|
+
* `CHECKOUT_OFFER_ALREADY_CONSUMED` (or `CHECKOUT_OFFER_EXPIRED`). A check
|
|
4046
|
+
* before the write cannot decide it, because the status can change in
|
|
4047
|
+
* between.
|
|
4048
|
+
*
|
|
4049
|
+
* With `tx`, the write runs on that transaction, so it is undone with
|
|
4050
|
+
* everything else the transaction wrote. `CheckoutOfferService.conclude`
|
|
4051
|
+
* depends on that; the persistence contract holds both.
|
|
4052
|
+
*/
|
|
4053
|
+
consume(id: string, tx?: TransactionContext): Promise<CheckoutOfferRow>;
|
|
4034
4054
|
}
|
|
4035
4055
|
|
|
4036
4056
|
/** Which changes to list. */
|
|
@@ -4351,6 +4371,11 @@ declare const BILLING_ERROR_CODES: {
|
|
|
4351
4371
|
readonly PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG";
|
|
4352
4372
|
/** Plan exists but cannot be booked via self-service. */
|
|
4353
4373
|
readonly PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE";
|
|
4374
|
+
/**
|
|
4375
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
4376
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
4377
|
+
*/
|
|
4378
|
+
readonly PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE";
|
|
4354
4379
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
4355
4380
|
readonly PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED";
|
|
4356
4381
|
/**
|
|
@@ -4448,12 +4473,19 @@ declare const CONTRACT_ERROR_CODES: {
|
|
|
4448
4473
|
readonly SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE";
|
|
4449
4474
|
readonly SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW";
|
|
4450
4475
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
|
|
4476
|
+
readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
|
|
4451
4477
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
|
|
4452
4478
|
readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
|
|
4453
4479
|
readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
|
|
4454
4480
|
readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
|
|
4455
4481
|
readonly CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED";
|
|
4456
4482
|
readonly CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED";
|
|
4483
|
+
/**
|
|
4484
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
4485
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
4486
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
4487
|
+
*/
|
|
4488
|
+
readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
|
|
4457
4489
|
readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
|
|
4458
4490
|
readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
|
|
4459
4491
|
readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
|
|
@@ -4562,12 +4594,19 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4562
4594
|
readonly SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE";
|
|
4563
4595
|
readonly SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW";
|
|
4564
4596
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
|
|
4597
|
+
readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
|
|
4565
4598
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
|
|
4566
4599
|
readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
|
|
4567
4600
|
readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
|
|
4568
4601
|
readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
|
|
4569
4602
|
readonly CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED";
|
|
4570
4603
|
readonly CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED";
|
|
4604
|
+
/**
|
|
4605
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
4606
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
4607
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
4608
|
+
*/
|
|
4609
|
+
readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
|
|
4571
4610
|
readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
|
|
4572
4611
|
readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
|
|
4573
4612
|
readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
|
|
@@ -4595,6 +4634,11 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4595
4634
|
readonly PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG";
|
|
4596
4635
|
/** Plan exists but cannot be booked via self-service. */
|
|
4597
4636
|
readonly PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE";
|
|
4637
|
+
/**
|
|
4638
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
4639
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
4640
|
+
*/
|
|
4641
|
+
readonly PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE";
|
|
4598
4642
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
4599
4643
|
readonly PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED";
|
|
4600
4644
|
/**
|
|
@@ -5186,8 +5230,6 @@ interface ConfiguratorModel {
|
|
|
5186
5230
|
popular?: boolean;
|
|
5187
5231
|
}
|
|
5188
5232
|
interface ConfiguratorCatalog {
|
|
5189
|
-
/** Factor `yearlyNet = monthlyNet * cycleDiscount` (typically 10 = 2 months free). */
|
|
5190
|
-
cycleDiscount: number;
|
|
5191
5233
|
currency: string;
|
|
5192
5234
|
vatRate: number;
|
|
5193
5235
|
models: ConfiguratorModel[];
|
|
@@ -5212,6 +5254,10 @@ interface ConfiguratorPriceBreakdown {
|
|
|
5212
5254
|
modelMonthlyNet: number;
|
|
5213
5255
|
subtotalMonthlyNet: number;
|
|
5214
5256
|
subtotalNet: number;
|
|
5257
|
+
/**
|
|
5258
|
+
* Net amount taken off `subtotalNet`: the promo preview's gross discount
|
|
5259
|
+
* converted at `vatRate`.
|
|
5260
|
+
*/
|
|
5215
5261
|
discountAmount: number;
|
|
5216
5262
|
totalNet: number;
|
|
5217
5263
|
vatRate: number;
|
|
@@ -5288,8 +5334,6 @@ interface ConfiguratorPlanMarketing {
|
|
|
5288
5334
|
*/
|
|
5289
5335
|
interface ConfiguratorMarketingProvider {
|
|
5290
5336
|
listPlanMarketing(): ConfiguratorPlanMarketing[];
|
|
5291
|
-
/** Factor `yearlyNet = monthlyNet * cycleDiscount`. Default `10`. */
|
|
5292
|
-
getCycleDiscount(): number;
|
|
5293
5337
|
getVatRate(): number;
|
|
5294
5338
|
getCurrency(): string;
|
|
5295
5339
|
}
|
|
@@ -5310,6 +5354,7 @@ interface RegistrationPromoPreview {
|
|
|
5310
5354
|
reason?: string;
|
|
5311
5355
|
percent?: number;
|
|
5312
5356
|
label?: string;
|
|
5357
|
+
/** The discount in gross, reckoned against `subtotalGross`. */
|
|
5313
5358
|
discountAmount?: number;
|
|
5314
5359
|
}>;
|
|
5315
5360
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2003,6 +2003,11 @@ interface PromoPreviewValidResponse {
|
|
|
2003
2003
|
/** Decimal-as-string, e.g. "199.00". */
|
|
2004
2004
|
originalGross: string;
|
|
2005
2005
|
discountGross: string;
|
|
2006
|
+
/**
|
|
2007
|
+
* `discountGross` in net, converted at the installation's VAT rate —
|
|
2008
|
+
* the figure a page showing net prices takes off the plan price.
|
|
2009
|
+
*/
|
|
2010
|
+
discountNet: string;
|
|
2006
2011
|
discountedGross: string;
|
|
2007
2012
|
includedVat: string;
|
|
2008
2013
|
nextRegularAmountGross: string;
|
|
@@ -2821,16 +2826,8 @@ interface SubscriptionContractPriceSnapshot {
|
|
|
2821
2826
|
discountNet: number;
|
|
2822
2827
|
totalNet: number;
|
|
2823
2828
|
/**
|
|
2824
|
-
* The rate this contract's total was computed at
|
|
2825
|
-
*
|
|
2826
|
-
* it was concluded from one.
|
|
2827
|
-
*
|
|
2828
|
-
* A checkout offer prices its lines as `net * (1 + vatRate)`, so it states
|
|
2829
|
-
* a fraction, and the value is copied here as it stands. The field
|
|
2830
|
-
* therefore carries both units across a history and cannot be compared
|
|
2831
|
-
* across contracts. `ContractLineItemRecord.taxRate` is always per cent and
|
|
2832
|
-
* is the one to read; this is kept as written because it is the record of
|
|
2833
|
-
* what the contract was concluded with.
|
|
2829
|
+
* The tax rate this contract's total was computed at, as a percentage:
|
|
2830
|
+
* 19 means 19 %, as every tax rate in SaaSiCat is.
|
|
2834
2831
|
*/
|
|
2835
2832
|
vatRate: number;
|
|
2836
2833
|
totalGross: number;
|
|
@@ -3088,7 +3085,15 @@ interface SubscriptionContractRepository {
|
|
|
3088
3085
|
* instead of drawing an extra pool connection (starvation guard, #70).
|
|
3089
3086
|
*/
|
|
3090
3087
|
findActiveByTenantId(tenantId: string, asOf?: Date, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3091
|
-
|
|
3088
|
+
/** With `tx`, the contract is written on that transaction and undone with it. */
|
|
3089
|
+
create(data: CreateSubscriptionContractData, tx?: TransactionContext): Promise<SubscriptionContractRecord>;
|
|
3090
|
+
/**
|
|
3091
|
+
* The contract concluded from a checkout offer (`originalOfferId`), or
|
|
3092
|
+
* `null` when none was. An offer is consumed once and so yields one
|
|
3093
|
+
* contract (`SC-MKT-017`); where an application's own path wrote two, the
|
|
3094
|
+
* earliest is returned, so the answer does not depend on read order.
|
|
3095
|
+
*/
|
|
3096
|
+
findByOriginalOfferId(offerId: string, tx?: TransactionContext): Promise<SubscriptionContractRecord | null>;
|
|
3092
3097
|
terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
|
|
3093
3098
|
}
|
|
3094
3099
|
/**
|
|
@@ -3404,6 +3409,8 @@ interface PlanVersionRepository {
|
|
|
3404
3409
|
*
|
|
3405
3410
|
* Note: ignores `validFrom`/`validUntil`. For time-aware
|
|
3406
3411
|
* resolution (onboarding, plan fallback for TRIAL) use `findActive`.
|
|
3412
|
+
*
|
|
3413
|
+
* A plan key no plan has finds `null`, not an error.
|
|
3407
3414
|
*/
|
|
3408
3415
|
findLatestLive(planId: string, tx?: TransactionContext): Promise<PlanVersionRecord | null>;
|
|
3409
3416
|
/**
|
|
@@ -3416,6 +3423,8 @@ interface PlanVersionRepository {
|
|
|
3416
3423
|
* return the highest `validFrom`, explicitly ordering null start dates
|
|
3417
3424
|
* last as a legacy fallback. Adapters without validity columns may omit
|
|
3418
3425
|
* the method (consumers fall back to `findLatestLive`).
|
|
3426
|
+
*
|
|
3427
|
+
* A plan key no plan has finds `null`, not an error.
|
|
3419
3428
|
*/
|
|
3420
3429
|
findActive?(planId: string, asOf?: Date, tx?: TransactionContext): Promise<PlanVersionRecord | null>;
|
|
3421
3430
|
}
|
|
@@ -4029,8 +4038,19 @@ interface CheckoutOfferRepository {
|
|
|
4029
4038
|
findById(id: string): Promise<CheckoutOfferRow | null>;
|
|
4030
4039
|
create(data: CreateCheckoutOfferData): Promise<CheckoutOfferRow>;
|
|
4031
4040
|
update(id: string, data: UpdateCheckoutOfferData): Promise<CheckoutOfferRow>;
|
|
4032
|
-
/**
|
|
4033
|
-
|
|
4041
|
+
/**
|
|
4042
|
+
* Sets `status = 'consumed'` + `consumedAt = NOW()`, and only while the
|
|
4043
|
+
* offer is still `open`: the write carries that condition, so of two
|
|
4044
|
+
* callers consuming at once one succeeds and the other is refused with
|
|
4045
|
+
* `CHECKOUT_OFFER_ALREADY_CONSUMED` (or `CHECKOUT_OFFER_EXPIRED`). A check
|
|
4046
|
+
* before the write cannot decide it, because the status can change in
|
|
4047
|
+
* between.
|
|
4048
|
+
*
|
|
4049
|
+
* With `tx`, the write runs on that transaction, so it is undone with
|
|
4050
|
+
* everything else the transaction wrote. `CheckoutOfferService.conclude`
|
|
4051
|
+
* depends on that; the persistence contract holds both.
|
|
4052
|
+
*/
|
|
4053
|
+
consume(id: string, tx?: TransactionContext): Promise<CheckoutOfferRow>;
|
|
4034
4054
|
}
|
|
4035
4055
|
|
|
4036
4056
|
/** Which changes to list. */
|
|
@@ -4351,6 +4371,11 @@ declare const BILLING_ERROR_CODES: {
|
|
|
4351
4371
|
readonly PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG";
|
|
4352
4372
|
/** Plan exists but cannot be booked via self-service. */
|
|
4353
4373
|
readonly PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE";
|
|
4374
|
+
/**
|
|
4375
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
4376
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
4377
|
+
*/
|
|
4378
|
+
readonly PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE";
|
|
4354
4379
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
4355
4380
|
readonly PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED";
|
|
4356
4381
|
/**
|
|
@@ -4448,12 +4473,19 @@ declare const CONTRACT_ERROR_CODES: {
|
|
|
4448
4473
|
readonly SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE";
|
|
4449
4474
|
readonly SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW";
|
|
4450
4475
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
|
|
4476
|
+
readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
|
|
4451
4477
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
|
|
4452
4478
|
readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
|
|
4453
4479
|
readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
|
|
4454
4480
|
readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
|
|
4455
4481
|
readonly CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED";
|
|
4456
4482
|
readonly CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED";
|
|
4483
|
+
/**
|
|
4484
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
4485
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
4486
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
4487
|
+
*/
|
|
4488
|
+
readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
|
|
4457
4489
|
readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
|
|
4458
4490
|
readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
|
|
4459
4491
|
readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
|
|
@@ -4562,12 +4594,19 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4562
4594
|
readonly SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE";
|
|
4563
4595
|
readonly SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW";
|
|
4564
4596
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH";
|
|
4597
|
+
readonly SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT";
|
|
4565
4598
|
readonly SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH";
|
|
4566
4599
|
readonly SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START";
|
|
4567
4600
|
readonly CHECKOUT_OFFER_NOT_FOUND: "CHECKOUT_OFFER_NOT_FOUND";
|
|
4568
4601
|
readonly CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED";
|
|
4569
4602
|
readonly CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED";
|
|
4570
4603
|
readonly CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED";
|
|
4604
|
+
/**
|
|
4605
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
4606
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
4607
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
4608
|
+
*/
|
|
4609
|
+
readonly CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED";
|
|
4571
4610
|
readonly SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND";
|
|
4572
4611
|
readonly NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT";
|
|
4573
4612
|
readonly SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED";
|
|
@@ -4595,6 +4634,11 @@ declare const PLATFORM_ERROR_CODES: {
|
|
|
4595
4634
|
readonly PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG";
|
|
4596
4635
|
/** Plan exists but cannot be booked via self-service. */
|
|
4597
4636
|
readonly PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE";
|
|
4637
|
+
/**
|
|
4638
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
4639
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
4640
|
+
*/
|
|
4641
|
+
readonly PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE";
|
|
4598
4642
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
4599
4643
|
readonly PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED";
|
|
4600
4644
|
/**
|
|
@@ -5186,8 +5230,6 @@ interface ConfiguratorModel {
|
|
|
5186
5230
|
popular?: boolean;
|
|
5187
5231
|
}
|
|
5188
5232
|
interface ConfiguratorCatalog {
|
|
5189
|
-
/** Factor `yearlyNet = monthlyNet * cycleDiscount` (typically 10 = 2 months free). */
|
|
5190
|
-
cycleDiscount: number;
|
|
5191
5233
|
currency: string;
|
|
5192
5234
|
vatRate: number;
|
|
5193
5235
|
models: ConfiguratorModel[];
|
|
@@ -5212,6 +5254,10 @@ interface ConfiguratorPriceBreakdown {
|
|
|
5212
5254
|
modelMonthlyNet: number;
|
|
5213
5255
|
subtotalMonthlyNet: number;
|
|
5214
5256
|
subtotalNet: number;
|
|
5257
|
+
/**
|
|
5258
|
+
* Net amount taken off `subtotalNet`: the promo preview's gross discount
|
|
5259
|
+
* converted at `vatRate`.
|
|
5260
|
+
*/
|
|
5215
5261
|
discountAmount: number;
|
|
5216
5262
|
totalNet: number;
|
|
5217
5263
|
vatRate: number;
|
|
@@ -5288,8 +5334,6 @@ interface ConfiguratorPlanMarketing {
|
|
|
5288
5334
|
*/
|
|
5289
5335
|
interface ConfiguratorMarketingProvider {
|
|
5290
5336
|
listPlanMarketing(): ConfiguratorPlanMarketing[];
|
|
5291
|
-
/** Factor `yearlyNet = monthlyNet * cycleDiscount`. Default `10`. */
|
|
5292
|
-
getCycleDiscount(): number;
|
|
5293
5337
|
getVatRate(): number;
|
|
5294
5338
|
getCurrency(): string;
|
|
5295
5339
|
}
|
|
@@ -5310,6 +5354,7 @@ interface RegistrationPromoPreview {
|
|
|
5310
5354
|
reason?: string;
|
|
5311
5355
|
percent?: number;
|
|
5312
5356
|
label?: string;
|
|
5357
|
+
/** The discount in gross, reckoned against `subtotalGross`. */
|
|
5313
5358
|
discountAmount?: number;
|
|
5314
5359
|
}>;
|
|
5315
5360
|
}
|
package/dist/index.js
CHANGED
|
@@ -454,6 +454,11 @@ var BILLING_ERROR_CODES = {
|
|
|
454
454
|
PLAN_NOT_IN_CATALOG: "PLAN_NOT_IN_CATALOG",
|
|
455
455
|
/** Plan exists but cannot be booked via self-service. */
|
|
456
456
|
PLAN_NOT_SELF_SERVICE: "PLAN_NOT_SELF_SERVICE",
|
|
457
|
+
/**
|
|
458
|
+
* Plan carries no price for the requested billing cycle, so it is not sold
|
|
459
|
+
* in it: a plan without a yearly price is a monthly plan.
|
|
460
|
+
*/
|
|
461
|
+
PLAN_NOT_SOLD_IN_CYCLE: "PLAN_NOT_SOLD_IN_CYCLE",
|
|
457
462
|
/** Plan change refused. Carries `blockers[]` with their own codes. */
|
|
458
463
|
PLAN_CHANGE_BLOCKED: "PLAN_CHANGE_BLOCKED",
|
|
459
464
|
/**
|
|
@@ -562,6 +567,7 @@ var CONTRACT_ERROR_CODES = {
|
|
|
562
567
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "SUBSCRIPTION_CONTRACT_INVALID_DATE",
|
|
563
568
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW",
|
|
564
569
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH",
|
|
570
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT",
|
|
565
571
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH",
|
|
566
572
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START",
|
|
567
573
|
// ── stage 3 ──
|
|
@@ -569,6 +575,12 @@ var CONTRACT_ERROR_CODES = {
|
|
|
569
575
|
CHECKOUT_OFFER_EXPIRED: "CHECKOUT_OFFER_EXPIRED",
|
|
570
576
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "CHECKOUT_OFFER_ALREADY_CONSUMED",
|
|
571
577
|
CHECKOUT_OFFER_NOT_CONSUMED: "CHECKOUT_OFFER_NOT_CONSUMED",
|
|
578
|
+
/**
|
|
579
|
+
* The offer changed between the checks of `conclude` and the transaction
|
|
580
|
+
* that consumed it, so the contract checked is not the one the offer now
|
|
581
|
+
* describes. Nothing was written; load the offer and conclude it again.
|
|
582
|
+
*/
|
|
583
|
+
CHECKOUT_OFFER_CHANGED: "CHECKOUT_OFFER_CHANGED",
|
|
572
584
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SUBSCRIPTION_CONTRACT_NOT_FOUND",
|
|
573
585
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "NO_ACTIVE_SUBSCRIPTION_CONTRACT",
|
|
574
586
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SUBSCRIPTION_CONTRACT_ALREADY_CLOSED"
|
|
@@ -992,6 +1004,7 @@ var ERROR_MESSAGES_EN = {
|
|
|
992
1004
|
NO_ACTIVE_PLAN_VERSION: "No plan version for {planId} active as of {asOf} \u2014 neither the validFrom window is satisfied nor is a latest-live version available.",
|
|
993
1005
|
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" is not in the catalog',
|
|
994
1006
|
PLAN_NOT_SELF_SERVICE: "{planName} is only activated via a special contract. Please contact the contract manager.",
|
|
1007
|
+
PLAN_NOT_SOLD_IN_CYCLE: "{planName} has no price for this billing rhythm and cannot be booked in it.",
|
|
995
1008
|
PLAN_CHANGE_BLOCKED: "Plan change during onboarding is blocked.",
|
|
996
1009
|
SUBSCRIPTION_CHANGED: "This subscription changed while the request was being decided. Reload it.",
|
|
997
1010
|
NO_SUBSCRIPTION: "This tenant has no subscription to cancel.",
|
|
@@ -1044,12 +1057,14 @@ var ERROR_MESSAGES_EN = {
|
|
|
1044
1057
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "{field} must be a valid date.",
|
|
1045
1058
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "effectiveUntil must be after effectiveFrom.",
|
|
1046
1059
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "A line item's taxAmount must be exactly priceGross minus priceNet.",
|
|
1060
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "A subscription contract states a tax rate of {taxRate} at {field}, which is not a percentage: a rate lies from 0 to 100, and a value between 0 and 1 is refused as a fraction.",
|
|
1047
1061
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "effectiveUntil must be after the effectiveFrom of the contract.",
|
|
1048
1062
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "A line item must be booked in the currency its contract was priced in.",
|
|
1049
1063
|
CHECKOUT_OFFER_NOT_FOUND: "CheckoutOffer '{offerId}' not found",
|
|
1050
1064
|
CHECKOUT_OFFER_EXPIRED: "Checkout offer '{offerId}' has expired and cannot be {action}",
|
|
1051
1065
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "Checkout offer '{offerId}' has already been consumed and cannot be {action}",
|
|
1052
1066
|
CHECKOUT_OFFER_NOT_CONSUMED: "CheckoutOffer '{offerId}' must be consumed before the contract is created",
|
|
1067
|
+
CHECKOUT_OFFER_CHANGED: "Checkout offer '{offerId}' changed while it was being concluded. Load it again.",
|
|
1053
1068
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' not found",
|
|
1054
1069
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "No active subscription contract for tenant {tenantId}",
|
|
1055
1070
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' is already closed",
|
|
@@ -1179,6 +1194,7 @@ var ERROR_MESSAGES_DE = {
|
|
|
1179
1194
|
NO_ACTIVE_PLAN_VERSION: "Zum {asOf} ist keine Planversion f\xFCr {planId} aktiv \u2014 weder ist das validFrom-Fenster erf\xFCllt, noch steht eine j\xFCngste Live-Version bereit.",
|
|
1180
1195
|
PLAN_NOT_IN_CATALOG: 'Plan "{planKey}" steht nicht im Katalog',
|
|
1181
1196
|
PLAN_NOT_SELF_SERVICE: "{planName} wird nur \xFCber einen Sondervertrag freigeschaltet. Bitte wenden Sie sich an die Vertragsverwaltung.",
|
|
1197
|
+
PLAN_NOT_SOLD_IN_CYCLE: "{planName} hat f\xFCr diesen Abrechnungsrhythmus keinen Preis und kann darin nicht gebucht werden.",
|
|
1182
1198
|
PLAN_CHANGE_BLOCKED: "W\xE4hrend des Onboardings ist ein Planwechsel gesperrt.",
|
|
1183
1199
|
SUBSCRIPTION_CHANGED: "Dieses Abonnement hat sich ge\xE4ndert, w\xE4hrend die Anfrage entschieden wurde. Bitte lade es neu.",
|
|
1184
1200
|
NO_SUBSCRIPTION: "Dieser Mandant hat kein Abonnement, das gek\xFCndigt werden kann.",
|
|
@@ -1231,12 +1247,14 @@ var ERROR_MESSAGES_DE = {
|
|
|
1231
1247
|
SUBSCRIPTION_CONTRACT_INVALID_DATE: "{field} muss ein g\xFCltiges Datum sein.",
|
|
1232
1248
|
SUBSCRIPTION_CONTRACT_INVALID_WINDOW: "effectiveUntil muss nach effectiveFrom liegen.",
|
|
1233
1249
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_TAX_MISMATCH: "taxAmount einer Position muss exakt priceGross minus priceNet sein.",
|
|
1250
|
+
SUBSCRIPTION_CONTRACT_TAX_RATE_NOT_PERCENT: "Ein Abo-Vertrag nennt bei {field} einen Steuersatz von {taxRate}, der kein Prozentsatz ist: Ein Satz liegt zwischen 0 und 100, und ein Wert zwischen 0 und 1 wird als Bruch abgelehnt.",
|
|
1234
1251
|
SUBSCRIPTION_CONTRACT_LINE_ITEM_CURRENCY_MISMATCH: "Eine Position muss in der W\xE4hrung gebucht sein, in der ihr Vertrag bepreist ist.",
|
|
1235
1252
|
SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START: "effectiveUntil muss nach dem effectiveFrom des Vertrags liegen.",
|
|
1236
1253
|
CHECKOUT_OFFER_NOT_FOUND: "CheckoutOffer '{offerId}' nicht gefunden",
|
|
1237
1254
|
CHECKOUT_OFFER_EXPIRED: "Checkout-Angebot '{offerId}' ist abgelaufen \u2014 '{action}' ist nicht mehr m\xF6glich",
|
|
1238
1255
|
CHECKOUT_OFFER_ALREADY_CONSUMED: "Checkout-Angebot '{offerId}' wurde bereits eingel\xF6st \u2014 '{action}' ist nicht mehr m\xF6glich",
|
|
1239
1256
|
CHECKOUT_OFFER_NOT_CONSUMED: "CheckoutOffer '{offerId}' muss eingel\xF6st sein, bevor der Vertrag entsteht",
|
|
1257
|
+
CHECKOUT_OFFER_CHANGED: "Checkout-Angebot '{offerId}' hat sich w\xE4hrend des Abschlusses ge\xE4ndert. Bitte neu laden.",
|
|
1240
1258
|
SUBSCRIPTION_CONTRACT_NOT_FOUND: "SubscriptionContract '{contractId}' nicht gefunden",
|
|
1241
1259
|
NO_ACTIVE_SUBSCRIPTION_CONTRACT: "Kein aktiver Abo-Vertrag f\xFCr Mandant {tenantId}",
|
|
1242
1260
|
SUBSCRIPTION_CONTRACT_ALREADY_CLOSED: "SubscriptionContract '{contractId}' ist bereits geschlossen",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saasicat/core",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.15",
|
|
4
4
|
"description": "TypeScript contracts for SaaSiCat — capabilities, catalogs, subscriptions, entitlements, admin manifests, persistence ports — and the pure domain logic both server and browser run: error catalogues, plan-diff classification, promo arithmetic, feature requirements.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|