@saasicat/nest 1.0.0-rc.14 → 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/_entries.cjs +161 -5
- package/dist/billing/index.d.cts +1 -1
- package/dist/billing/index.d.ts +1 -1
- package/dist/billing/index.js +10 -11
- package/dist/catalog/index.js +6 -6
- package/dist/checkout-offer/index.d.cts +9 -3
- package/dist/checkout-offer/index.d.ts +9 -3
- package/dist/checkout-offer/index.js +7 -4
- package/dist/{checkout-offer.module-BVXEDXex.d.ts → checkout-offer.module-B-DF2I_-.d.ts} +15 -2
- package/dist/{checkout-offer.module-B1O0H8EQ.d.cts → checkout-offer.module-BOX9yAWq.d.cts} +15 -2
- package/dist/{checkout-offer.service-BIGkcWNe.d.ts → checkout-offer.service-BZumQOmZ.d.ts} +54 -3
- package/dist/{checkout-offer.service-C5-YWUrp.d.cts → checkout-offer.service-Dknxgj6W.d.cts} +54 -3
- package/dist/{chunk-KOZYQS53.js → chunk-2TACP6MQ.js} +2 -2
- package/dist/{chunk-FKAWM74T.js → chunk-45B4OQOO.js} +1 -1
- package/dist/{chunk-O4M5HC2B.js → chunk-62WEP34A.js} +20 -20
- package/dist/{chunk-PEOAEM2O.js → chunk-6NGMKJNI.js} +1 -1
- package/dist/{chunk-UO55F6JP.js → chunk-CJZPT7CR.js} +4 -4
- package/dist/{chunk-L7PTXFJE.js → chunk-H3GVIQVK.js} +138 -13
- package/dist/{chunk-E2GFA4J2.js → chunk-LEZ6KYQ7.js} +106 -5
- package/dist/{chunk-GORG6MWO.js → chunk-NQVW2R7V.js} +33 -24
- package/dist/{define-saasicat-DBJn20Sg.d.cts → define-saasicat-Bsa6GZKE.d.cts} +1 -1
- package/dist/{define-saasicat-kg0AC-pQ.d.ts → define-saasicat-OWvE7lJ1.d.ts} +1 -1
- package/dist/{enforce-quota.interceptor-W4tYHm_k.d.ts → enforce-quota.interceptor-C5kUQYit.d.ts} +1 -1
- package/dist/{enforce-quota.interceptor-D8CHDs6U.d.cts → enforce-quota.interceptor-Cz5z36qf.d.cts} +1 -1
- package/dist/entitlement/index.js +5 -5
- package/dist/index.d.cts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +104 -103
- package/dist/{module-options-zdnvldbv.d.ts → module-options-CCP890cz.d.ts} +7 -2
- package/dist/{module-options-BnLp7el-.d.cts → module-options-Cq0Lv2i0.d.cts} +7 -2
- package/dist/platform/index.d.cts +8 -8
- package/dist/platform/index.d.ts +8 -8
- package/dist/platform/index.js +34 -35
- package/dist/subscription-contract/index.d.cts +1 -1
- package/dist/subscription-contract/index.d.ts +1 -1
- package/dist/subscription-contract/index.js +2 -3
- package/dist/{subscription-contract.service-hD87MKyg.d.cts → subscription-contract.service-wMqIPFkS.d.cts} +13 -2
- package/dist/{subscription-contract.service-hD87MKyg.d.ts → subscription-contract.service-wMqIPFkS.d.ts} +13 -2
- package/dist/testing/index.d.cts +5 -4
- package/dist/testing/index.d.ts +5 -4
- package/dist/testing/index.js +21 -16
- package/package.json +3 -3
- package/dist/chunk-DR2SQNMX.js +0 -91
- package/dist/{chunk-AFZQ7GTQ.js → chunk-GYI3E2YY.js} +9 -9
- package/dist/{chunk-HRUVUY5E.js → chunk-JMV6J7YP.js} +9 -9
package/dist/.build-stamp
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
5b5c697fcb7f0f396443441223db4c63896950ff67b89351b80f193bfc738b7d
|
package/dist/_entries.cjs
CHANGED
|
@@ -4962,9 +4962,14 @@ var SubscriptionContractService = class {
|
|
|
4962
4962
|
}
|
|
4963
4963
|
return subscriptionContractToInvoiceSnapshot(contract);
|
|
4964
4964
|
}
|
|
4965
|
-
|
|
4965
|
+
/** With `tx`, the contract is written on that transaction and undone with it. */
|
|
4966
|
+
async create(data, tx) {
|
|
4966
4967
|
this.assertCreateData(data);
|
|
4967
|
-
return this.repo.create(this.cloneCreateData(data));
|
|
4968
|
+
return this.repo.create(this.cloneCreateData(data), tx);
|
|
4969
|
+
}
|
|
4970
|
+
/** The contract concluded from a checkout offer, or `null` when none was. */
|
|
4971
|
+
findByOriginalOfferId(offerId, tx) {
|
|
4972
|
+
return this.repo.findByOriginalOfferId(offerId, tx);
|
|
4968
4973
|
}
|
|
4969
4974
|
async terminate(contractId, data) {
|
|
4970
4975
|
const existing = await this.getById(contractId);
|
|
@@ -5002,6 +5007,20 @@ var SubscriptionContractService = class {
|
|
|
5002
5007
|
}
|
|
5003
5008
|
});
|
|
5004
5009
|
}
|
|
5010
|
+
return this.dataFromOffer(offer, options);
|
|
5011
|
+
}
|
|
5012
|
+
/**
|
|
5013
|
+
* The contract an offer becomes, checked the way `create` checks it, before
|
|
5014
|
+
* anything is written. Unlike `createDataFromOffer` it takes an offer that
|
|
5015
|
+
* is still open: concluding an offer refuses a contract it could not create
|
|
5016
|
+
* before the offer is consumed, rather than after.
|
|
5017
|
+
*/
|
|
5018
|
+
prepareFromOffer(offer, options) {
|
|
5019
|
+
const data = this.dataFromOffer(offer, options);
|
|
5020
|
+
this.assertCreateData(data);
|
|
5021
|
+
return data;
|
|
5022
|
+
}
|
|
5023
|
+
dataFromOffer(offer, options) {
|
|
5005
5024
|
const lineItems = this.lineItemsFromOffer(offer);
|
|
5006
5025
|
return {
|
|
5007
5026
|
tenantId: options.tenantId,
|
|
@@ -13933,6 +13952,7 @@ __name(runSeedGateFromFile, "runSeedGateFromFile");
|
|
|
13933
13952
|
var checkout_offer_exports = {};
|
|
13934
13953
|
__export(checkout_offer_exports, {
|
|
13935
13954
|
CHECKOUT_OFFER_REPOSITORY_TOKEN: () => CHECKOUT_OFFER_REPOSITORY_TOKEN,
|
|
13955
|
+
CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN: () => CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN,
|
|
13936
13956
|
CheckoutOfferModule: () => CheckoutOfferModule,
|
|
13937
13957
|
CheckoutOfferPricing: () => CheckoutOfferPricing,
|
|
13938
13958
|
CheckoutOfferService: () => CheckoutOfferService,
|
|
@@ -13942,6 +13962,7 @@ __export(checkout_offer_exports, {
|
|
|
13942
13962
|
});
|
|
13943
13963
|
|
|
13944
13964
|
// src/checkout-offer/checkout-offer.service.ts
|
|
13965
|
+
var import_node_util = require("util");
|
|
13945
13966
|
var import_common63 = require("@nestjs/common");
|
|
13946
13967
|
var import_core40 = require("@saasicat/core");
|
|
13947
13968
|
|
|
@@ -14349,6 +14370,7 @@ __name(promoCodeNotAccepted, "promoCodeNotAccepted");
|
|
|
14349
14370
|
|
|
14350
14371
|
// src/checkout-offer/checkout-offer.tokens.ts
|
|
14351
14372
|
var CHECKOUT_OFFER_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/CheckoutOfferRepository");
|
|
14373
|
+
var CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN = /* @__PURE__ */ Symbol.for("saasicat/nest/CheckoutOfferTransactionRunner");
|
|
14352
14374
|
|
|
14353
14375
|
// src/checkout-offer/checkout-offer.service.ts
|
|
14354
14376
|
function _ts_decorate67(decorators, target, key, desc) {
|
|
@@ -14378,12 +14400,16 @@ var CheckoutOfferService = class {
|
|
|
14378
14400
|
bundles;
|
|
14379
14401
|
plans;
|
|
14380
14402
|
catalogEntries;
|
|
14381
|
-
|
|
14403
|
+
contracts;
|
|
14404
|
+
transactions;
|
|
14405
|
+
constructor(repo, pricing, bundles = null, plans = null, catalogEntries = null, contracts = null, transactions = null) {
|
|
14382
14406
|
this.repo = repo;
|
|
14383
14407
|
this.pricing = pricing;
|
|
14384
14408
|
this.bundles = bundles;
|
|
14385
14409
|
this.plans = plans;
|
|
14386
14410
|
this.catalogEntries = catalogEntries;
|
|
14411
|
+
this.contracts = contracts;
|
|
14412
|
+
this.transactions = transactions;
|
|
14387
14413
|
}
|
|
14388
14414
|
list(filter) {
|
|
14389
14415
|
return this.repo.list(filter);
|
|
@@ -14473,11 +14499,101 @@ var CheckoutOfferService = class {
|
|
|
14473
14499
|
* is kept for amounts that no longer match.
|
|
14474
14500
|
*/
|
|
14475
14501
|
async consume(id) {
|
|
14502
|
+
await this.assertConsumable(id);
|
|
14503
|
+
return this.repo.consume(id);
|
|
14504
|
+
}
|
|
14505
|
+
/**
|
|
14506
|
+
* Consumes an offer and creates its contract in one transaction, together
|
|
14507
|
+
* with the application's own writes in `within`, so an offer is never
|
|
14508
|
+
* consumed without its contract, and no contract is written for an offer
|
|
14509
|
+
* that stays open.
|
|
14510
|
+
*
|
|
14511
|
+
* Everything that can refuse runs before the transaction: what `consume`
|
|
14512
|
+
* checks, and the checks the contract the offer becomes is held to. Inside
|
|
14513
|
+
* it, the offer is consumed on the condition that it is still open, the
|
|
14514
|
+
* contract is written, and `within` runs; an error in any of them undoes
|
|
14515
|
+
* the others, and the offer can be concluded again.
|
|
14516
|
+
*
|
|
14517
|
+
* An offer that is already concluded for the same tenant answers with its
|
|
14518
|
+
* contract rather than a refusal, so a caller retrying after a lost answer,
|
|
14519
|
+
* or losing a race to another call for that tenant, gets the conclusion that
|
|
14520
|
+
* stands; `within` does not run again, its writes committed with it. A
|
|
14521
|
+
* conclusion for another tenant is refused with
|
|
14522
|
+
* `CHECKOUT_OFFER_ALREADY_CONSUMED`, and an offer changed between the checks
|
|
14523
|
+
* and the transaction with `CHECKOUT_OFFER_CHANGED`, nothing written.
|
|
14524
|
+
*
|
|
14525
|
+
* A promo code on the offer is redeemed in `within`, with
|
|
14526
|
+
* `PromoCodesService.redeemInTransaction` on the same transaction. Before
|
|
14527
|
+
* the transaction the code is only checked the way pricing checks it; the
|
|
14528
|
+
* redemption checks the rest, the customer and the remaining redemptions,
|
|
14529
|
+
* where a refusal still undoes everything. Nothing checks the code again
|
|
14530
|
+
* after `within`, so a redemption that takes its last slot does not refuse
|
|
14531
|
+
* the offer it was redeemed for.
|
|
14532
|
+
*/
|
|
14533
|
+
async conclude(id, options, within) {
|
|
14534
|
+
const { contracts, transactions } = this.conclusionPorts();
|
|
14535
|
+
const { tenantId } = options;
|
|
14536
|
+
const standing = await this.standingConclusion(await this.getById(id), contracts, tenantId);
|
|
14537
|
+
if (standing) return standing;
|
|
14538
|
+
const existing = await this.assertConsumable(id);
|
|
14539
|
+
const checked = contracts.prepareFromOffer(existing, options);
|
|
14540
|
+
let consumeFailed = false;
|
|
14541
|
+
try {
|
|
14542
|
+
return await transactions.run(async (tx) => {
|
|
14543
|
+
consumeFailed = false;
|
|
14544
|
+
let offer;
|
|
14545
|
+
try {
|
|
14546
|
+
offer = await this.repo.consume(id, tx);
|
|
14547
|
+
} catch (error) {
|
|
14548
|
+
consumeFailed = true;
|
|
14549
|
+
throw error;
|
|
14550
|
+
}
|
|
14551
|
+
const data = contracts.prepareFromOffer(offer, options);
|
|
14552
|
+
if (!(0, import_node_util.isDeepStrictEqual)(data, checked)) throw offerChanged(id);
|
|
14553
|
+
const contract = await contracts.create(data, tx);
|
|
14554
|
+
const concluded = {
|
|
14555
|
+
offer,
|
|
14556
|
+
contract
|
|
14557
|
+
};
|
|
14558
|
+
if (within) await within(tx, concluded);
|
|
14559
|
+
return concluded;
|
|
14560
|
+
});
|
|
14561
|
+
} catch (error) {
|
|
14562
|
+
if (!consumeFailed) throw error;
|
|
14563
|
+
const offer = await this.repo.findById(id).catch(() => null);
|
|
14564
|
+
const concludedMeanwhile = await this.standingConclusion(offer, contracts, tenantId).catch(() => null);
|
|
14565
|
+
if (concludedMeanwhile) return concludedMeanwhile;
|
|
14566
|
+
throw error;
|
|
14567
|
+
}
|
|
14568
|
+
}
|
|
14569
|
+
async assertConsumable(id) {
|
|
14476
14570
|
const existing = await this.getById(id);
|
|
14477
14571
|
this.assertOpen(existing, "consumed");
|
|
14478
14572
|
await this.assertBundleVersionsStillBookable(existing);
|
|
14479
14573
|
await this.pricing.assertPricedByCatalogue(existing);
|
|
14480
|
-
return
|
|
14574
|
+
return existing;
|
|
14575
|
+
}
|
|
14576
|
+
/**
|
|
14577
|
+
* The conclusion that stands for this tenant, if the offer has one. An offer
|
|
14578
|
+
* carries no tenant and its id travels in a link, so a conclusion for
|
|
14579
|
+
* another tenant is not an answer: that caller is refused as before.
|
|
14580
|
+
*/
|
|
14581
|
+
async standingConclusion(offer, contracts, tenantId) {
|
|
14582
|
+
if (!offer || offer.status !== "consumed") return null;
|
|
14583
|
+
const contract = await contracts.findByOriginalOfferId(offer.id);
|
|
14584
|
+
return contract && contract.tenantId === tenantId ? {
|
|
14585
|
+
offer,
|
|
14586
|
+
contract
|
|
14587
|
+
} : null;
|
|
14588
|
+
}
|
|
14589
|
+
conclusionPorts() {
|
|
14590
|
+
if (!this.contracts || !this.transactions) {
|
|
14591
|
+
throw new Error("CheckoutOfferService.conclude needs the subscription contract repository and a transaction runner: pass `conclusion` to CheckoutOfferModule.forRoot, or give SaaSiCatModule.forRoot a persistence bundle that has both.");
|
|
14592
|
+
}
|
|
14593
|
+
return {
|
|
14594
|
+
contracts: this.contracts,
|
|
14595
|
+
transactions: this.transactions
|
|
14596
|
+
};
|
|
14481
14597
|
}
|
|
14482
14598
|
/**
|
|
14483
14599
|
* #35 P6 — server-side requires validation: the dependencies of all
|
|
@@ -14615,15 +14731,31 @@ CheckoutOfferService = _ts_decorate67([
|
|
|
14615
14731
|
_ts_param45(3, (0, import_common63.Inject)(PLAN_REPOSITORY_TOKEN)),
|
|
14616
14732
|
_ts_param45(4, (0, import_common63.Optional)()),
|
|
14617
14733
|
_ts_param45(4, (0, import_common63.Inject)(CATALOG_ENTRY_REPOSITORY_TOKEN)),
|
|
14734
|
+
_ts_param45(5, (0, import_common63.Optional)()),
|
|
14735
|
+
_ts_param45(5, (0, import_common63.Inject)(SubscriptionContractService)),
|
|
14736
|
+
_ts_param45(6, (0, import_common63.Optional)()),
|
|
14737
|
+
_ts_param45(6, (0, import_common63.Inject)(CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN)),
|
|
14618
14738
|
_ts_metadata55("design:type", Function),
|
|
14619
14739
|
_ts_metadata55("design:paramtypes", [
|
|
14620
14740
|
typeof CheckoutOfferRepository === "undefined" ? Object : CheckoutOfferRepository,
|
|
14621
14741
|
typeof CheckoutOfferPricing === "undefined" ? Object : CheckoutOfferPricing,
|
|
14622
14742
|
Object,
|
|
14623
14743
|
Object,
|
|
14744
|
+
Object,
|
|
14745
|
+
Object,
|
|
14624
14746
|
Object
|
|
14625
14747
|
])
|
|
14626
14748
|
], CheckoutOfferService);
|
|
14749
|
+
function offerChanged(offerId) {
|
|
14750
|
+
return new import_common63.ConflictException({
|
|
14751
|
+
code: import_core40.CONTRACT_ERROR_CODES.CHECKOUT_OFFER_CHANGED,
|
|
14752
|
+
message: `Checkout offer '${offerId}' changed while it was being concluded. Load it again.`,
|
|
14753
|
+
params: {
|
|
14754
|
+
offerId
|
|
14755
|
+
}
|
|
14756
|
+
});
|
|
14757
|
+
}
|
|
14758
|
+
__name(offerChanged, "offerChanged");
|
|
14627
14759
|
|
|
14628
14760
|
// src/checkout-offer/checkout-offer.controller.ts
|
|
14629
14761
|
var import_common64 = require("@nestjs/common");
|
|
@@ -14840,6 +14972,9 @@ var CheckoutOfferModule = class _CheckoutOfferModule {
|
|
|
14840
14972
|
if (!options.planRepository) {
|
|
14841
14973
|
throw new Error("CheckoutOfferModule: `planRepository` is required \u2014 every offer is priced from the plan version on sale, and an offer without it would have to take its price from the request.");
|
|
14842
14974
|
}
|
|
14975
|
+
if (options.conclusion && (!options.conclusion.subscriptionContractRepository || !options.conclusion.transactionRunner)) {
|
|
14976
|
+
throw new Error("CheckoutOfferModule: `conclusion` needs both `subscriptionContractRepository` and `transactionRunner` \u2014 concluding an offer writes the contract and consumes the offer in one transaction, and without either it would do only half.");
|
|
14977
|
+
}
|
|
14843
14978
|
const controllers = [];
|
|
14844
14979
|
if (options.controller) {
|
|
14845
14980
|
controllers.push(buildCheckoutOfferController(options.controller.guards));
|
|
@@ -14861,6 +14996,11 @@ var CheckoutOfferModule = class _CheckoutOfferModule {
|
|
|
14861
14996
|
...options.catalogEntryRepository ? [
|
|
14862
14997
|
asProvider(CATALOG_ENTRY_REPOSITORY_TOKEN, options.catalogEntryRepository)
|
|
14863
14998
|
] : [],
|
|
14999
|
+
...options.conclusion ? [
|
|
15000
|
+
asProvider(SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN, options.conclusion.subscriptionContractRepository),
|
|
15001
|
+
asProvider(CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN, options.conclusion.transactionRunner),
|
|
15002
|
+
SubscriptionContractService
|
|
15003
|
+
] : [],
|
|
14864
15004
|
CheckoutOfferPricing,
|
|
14865
15005
|
CheckoutOfferService,
|
|
14866
15006
|
...options.extraProviders ?? []
|
|
@@ -16122,9 +16262,11 @@ function composeAdminStats({ options, persistence }) {
|
|
|
16122
16262
|
];
|
|
16123
16263
|
}
|
|
16124
16264
|
__name(composeAdminStats, "composeAdminStats");
|
|
16125
|
-
function composeCheckoutOffer({ options, persistence }) {
|
|
16265
|
+
function composeCheckoutOffer({ options, adapters, persistence }) {
|
|
16126
16266
|
const config = options.checkoutOffer;
|
|
16127
16267
|
if (!config) return [];
|
|
16268
|
+
const contractRepository = config.conclusion?.subscriptionContractRepository ?? persistence?.entitlement?.subscriptionContractRepository;
|
|
16269
|
+
const transactionRunner = config.conclusion?.transactionRunner ?? adapters.transactionRunner;
|
|
16128
16270
|
return [
|
|
16129
16271
|
CheckoutOfferModule.forRoot({
|
|
16130
16272
|
...config,
|
|
@@ -16132,6 +16274,13 @@ function composeCheckoutOffer({ options, persistence }) {
|
|
|
16132
16274
|
planRepository: config.planRepository ?? persistence?.catalog?.planRepository,
|
|
16133
16275
|
promotionRepository: config.promotionRepository ?? persistence?.catalog?.promotionRepository,
|
|
16134
16276
|
catalogEntryRepository: config.catalogEntryRepository ?? persistence?.catalog?.catalogEntryRepository,
|
|
16277
|
+
// Named by hand, it is passed on even when half of it resolves to
|
|
16278
|
+
// nothing, so the module refuses to start the same way it does when
|
|
16279
|
+
// wired directly; derived from the bundle, it is wired when both exist.
|
|
16280
|
+
conclusion: config.conclusion || contractRepository && transactionRunner ? {
|
|
16281
|
+
subscriptionContractRepository: contractRepository,
|
|
16282
|
+
transactionRunner
|
|
16283
|
+
} : void 0,
|
|
16135
16284
|
imports: config.imports ?? options.imports
|
|
16136
16285
|
})
|
|
16137
16286
|
];
|
|
@@ -20098,6 +20247,7 @@ __export(src_exports, {
|
|
|
20098
20247
|
CATALOG_FEATURE_UI_REGISTRY_TOKEN: () => CATALOG_FEATURE_UI_REGISTRY_TOKEN,
|
|
20099
20248
|
CATALOG_SERVICE_CONFIG_TOKEN: () => CATALOG_SERVICE_CONFIG_TOKEN,
|
|
20100
20249
|
CHECKOUT_OFFER_REPOSITORY_TOKEN: () => CHECKOUT_OFFER_REPOSITORY_TOKEN,
|
|
20250
|
+
CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN: () => CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN,
|
|
20101
20251
|
CODE_MAX_LENGTH: () => CODE_MAX_LENGTH,
|
|
20102
20252
|
CODE_MIN_LENGTH: () => CODE_MIN_LENGTH,
|
|
20103
20253
|
CODE_PATTERN: () => CODE_PATTERN,
|
|
@@ -20615,6 +20765,12 @@ var FakeSubscriptionContractRepository = class {
|
|
|
20615
20765
|
].filter((row) => row.tenantId === tenantId).filter((row) => this.isActiveAt(row, asOf)).sort((a, b) => b.effectiveFrom.getTime() - a.effectiveFrom.getTime())[0];
|
|
20616
20766
|
return active ? this.cloneRecord(active) : null;
|
|
20617
20767
|
}
|
|
20768
|
+
async findByOriginalOfferId(offerId) {
|
|
20769
|
+
const first = [
|
|
20770
|
+
...this.byId.values()
|
|
20771
|
+
].find((row) => row.originalOfferId === offerId);
|
|
20772
|
+
return first ? this.cloneRecord(first) : null;
|
|
20773
|
+
}
|
|
20618
20774
|
async create(data) {
|
|
20619
20775
|
const now = /* @__PURE__ */ new Date();
|
|
20620
20776
|
const id = `contract-${this.nextContractId++}`;
|
package/dist/billing/index.d.cts
CHANGED
|
@@ -9,7 +9,7 @@ export { Type as NestType } from '@nestjs/common';
|
|
|
9
9
|
import { Reflector, BaseExceptionFilter } from '@nestjs/core';
|
|
10
10
|
import { c as EntitlementService } from '../aggregation-BHo7a_In.cjs';
|
|
11
11
|
import { P as ProviderSpec } from '../di-CcNeq9v-.cjs';
|
|
12
|
-
import { S as SubscriptionContractService } from '../subscription-contract.service-
|
|
12
|
+
import { S as SubscriptionContractService } from '../subscription-contract.service-wMqIPFkS.cjs';
|
|
13
13
|
import '../promo.service-CBMm9RU7.cjs';
|
|
14
14
|
import '../admin-audit.service-4P3Djdxk.cjs';
|
|
15
15
|
import '../contract-line-item-money-BWWQhRul.cjs';
|
package/dist/billing/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ export { Type as NestType } from '@nestjs/common';
|
|
|
9
9
|
import { Reflector, BaseExceptionFilter } from '@nestjs/core';
|
|
10
10
|
import { c as EntitlementService } from '../aggregation-CtIjlWHT.js';
|
|
11
11
|
import { P as ProviderSpec } from '../di-CcNeq9v-.js';
|
|
12
|
-
import { S as SubscriptionContractService } from '../subscription-contract.service-
|
|
12
|
+
import { S as SubscriptionContractService } from '../subscription-contract.service-wMqIPFkS.js';
|
|
13
13
|
import '../promo.service-CBMm9RU7.js';
|
|
14
14
|
import '../admin-audit.service-4P3Djdxk.js';
|
|
15
15
|
import '../contract-line-item-money-BWWQhRul.js';
|
package/dist/billing/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
computeCarriedTrialEndsAt,
|
|
21
21
|
computeNextPeriod,
|
|
22
22
|
decideRenewal
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-2TACP6MQ.js";
|
|
24
24
|
import {
|
|
25
25
|
AddSubscriptionBundleDto,
|
|
26
26
|
BILLING_FEATURE_UI_REGISTRY_TOKEN,
|
|
@@ -80,8 +80,7 @@ import {
|
|
|
80
80
|
resolveBundleCancelEffectiveAt,
|
|
81
81
|
resolvePlanAnchorDay,
|
|
82
82
|
retreatOneCycle
|
|
83
|
-
} from "../chunk-
|
|
84
|
-
import "../chunk-E2GFA4J2.js";
|
|
83
|
+
} from "../chunk-62WEP34A.js";
|
|
85
84
|
import {
|
|
86
85
|
AUDIT_CONTEXT_RESOLVER_TOKEN,
|
|
87
86
|
CANCELLATION_NOTICE_DAYS_TOKEN,
|
|
@@ -98,20 +97,22 @@ import {
|
|
|
98
97
|
classifyPlanDiff
|
|
99
98
|
} from "../chunk-O6I7X4OG.js";
|
|
100
99
|
import "../chunk-DQEU4UNU.js";
|
|
101
|
-
import "../chunk-
|
|
102
|
-
import "../chunk-FAH62CAJ.js";
|
|
103
|
-
import "../chunk-DR2SQNMX.js";
|
|
100
|
+
import "../chunk-LEZ6KYQ7.js";
|
|
104
101
|
import {
|
|
105
102
|
cyclesSoldFor,
|
|
106
103
|
resolveBundlePriceNet
|
|
107
104
|
} from "../chunk-KPEMTBOP.js";
|
|
108
|
-
import "../chunk-YSC46BGM.js";
|
|
109
105
|
import {
|
|
110
106
|
SUBSCRIPTION_BUNDLE_CONFIG_TOKEN,
|
|
111
107
|
SUBSCRIPTION_BUNDLE_REPOSITORY_TOKEN
|
|
112
|
-
} from "../chunk-
|
|
113
|
-
import "../chunk-VBRYPU7V.js";
|
|
108
|
+
} from "../chunk-JMV6J7YP.js";
|
|
114
109
|
import "../chunk-OUDSQ3PU.js";
|
|
110
|
+
import "../chunk-VBRYPU7V.js";
|
|
111
|
+
import "../chunk-AOQJEYOL.js";
|
|
112
|
+
import "../chunk-QUZU2M33.js";
|
|
113
|
+
import "../chunk-O2J2HDXA.js";
|
|
114
|
+
import "../chunk-FAH62CAJ.js";
|
|
115
|
+
import "../chunk-YSC46BGM.js";
|
|
115
116
|
import "../chunk-57V6ZTI6.js";
|
|
116
117
|
import {
|
|
117
118
|
PLAN_CATALOG_READ_SINK_TOKEN,
|
|
@@ -132,9 +133,7 @@ import {
|
|
|
132
133
|
} from "../chunk-UUDUEQXA.js";
|
|
133
134
|
import "../chunk-5BCYJ3QY.js";
|
|
134
135
|
import "../chunk-QSBMFY4I.js";
|
|
135
|
-
import "../chunk-AOQJEYOL.js";
|
|
136
136
|
import "../chunk-SABTXESR.js";
|
|
137
|
-
import "../chunk-QUZU2M33.js";
|
|
138
137
|
import "../chunk-SHUYVCID.js";
|
|
139
138
|
export {
|
|
140
139
|
AUDIT_CONTEXT_RESOLVER_TOKEN,
|
package/dist/catalog/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
runSeedGateFromFile,
|
|
7
7
|
seedGateExitCode,
|
|
8
8
|
validateSeedAgainstSnapshot
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-45B4OQOO.js";
|
|
10
10
|
import "../chunk-74SCJ4HF.js";
|
|
11
11
|
import {
|
|
12
12
|
ADVISORY_STRICT_MODE_CODES,
|
|
@@ -57,15 +57,12 @@ import {
|
|
|
57
57
|
resolveValidityWindow,
|
|
58
58
|
validateBundleDraft,
|
|
59
59
|
validatePlanDraft
|
|
60
|
-
} from "../chunk-
|
|
60
|
+
} from "../chunk-GYI3E2YY.js";
|
|
61
61
|
import "../chunk-O6I7X4OG.js";
|
|
62
62
|
import "../chunk-DQEU4UNU.js";
|
|
63
|
-
import "../chunk-O2J2HDXA.js";
|
|
64
63
|
import "../chunk-KPEMTBOP.js";
|
|
65
|
-
import "../chunk-YSC46BGM.js";
|
|
66
64
|
import "../chunk-JVAEKTJ4.js";
|
|
67
65
|
import "../chunk-OUDSQ3PU.js";
|
|
68
|
-
import "../chunk-57V6ZTI6.js";
|
|
69
66
|
import {
|
|
70
67
|
BUNDLE_REPOSITORY_TOKEN,
|
|
71
68
|
CATALOG_ENTRY_REPOSITORY_TOKEN,
|
|
@@ -76,8 +73,11 @@ import {
|
|
|
76
73
|
PLAN_REPOSITORY_TOKEN,
|
|
77
74
|
PROMOTION_REPOSITORY_TOKEN
|
|
78
75
|
} from "../chunk-AOQJEYOL.js";
|
|
79
|
-
import "../chunk-SABTXESR.js";
|
|
80
76
|
import "../chunk-QUZU2M33.js";
|
|
77
|
+
import "../chunk-O2J2HDXA.js";
|
|
78
|
+
import "../chunk-YSC46BGM.js";
|
|
79
|
+
import "../chunk-57V6ZTI6.js";
|
|
80
|
+
import "../chunk-SABTXESR.js";
|
|
81
81
|
import "../chunk-SHUYVCID.js";
|
|
82
82
|
export {
|
|
83
83
|
ADVISORY_STRICT_MODE_CODES,
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { C as CheckoutOfferPricing, a as CheckoutOfferPricingInput, b as CheckoutOfferService, P as PricedCheckoutOffer } from '../checkout-offer.service-
|
|
1
|
+
export { C as CheckoutOfferPricing, a as CheckoutOfferPricingInput, b as CheckoutOfferService, c as ConcludeCheckoutOfferWithin, d as ConcludedCheckoutOffer, P as PricedCheckoutOffer } from '../checkout-offer.service-Dknxgj6W.cjs';
|
|
2
2
|
import { Type, CanActivate } from '@nestjs/common';
|
|
3
|
-
export { a as
|
|
3
|
+
export { a as CheckoutOfferConclusionOptions, b as CheckoutOfferControllerConfig, c as CheckoutOfferModule, C as CheckoutOfferModuleOptions } from '../checkout-offer.module-BOX9yAWq.cjs';
|
|
4
4
|
import { CheckoutOfferSelection, CheckoutOfferSelectionUpdate } from '@saasicat/core';
|
|
5
|
+
import '../subscription-contract.service-wMqIPFkS.cjs';
|
|
5
6
|
import '../promo.service-CBMm9RU7.cjs';
|
|
6
7
|
import '../di-CcNeq9v-.cjs';
|
|
7
8
|
|
|
@@ -9,6 +10,11 @@ declare function buildCheckoutOfferController(guards: Array<Type<CanActivate>>):
|
|
|
9
10
|
|
|
10
11
|
/** Repository for `checkout_offers`. */
|
|
11
12
|
declare const CHECKOUT_OFFER_REPOSITORY_TOKEN: unique symbol;
|
|
13
|
+
/**
|
|
14
|
+
* The transaction an offer is concluded in: consuming it, writing its contract
|
|
15
|
+
* and the application's own writes commit or roll back together.
|
|
16
|
+
*/
|
|
17
|
+
declare const CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN: unique symbol;
|
|
12
18
|
|
|
13
19
|
declare class CreateCheckoutOfferDto implements CheckoutOfferSelection {
|
|
14
20
|
planKey: string;
|
|
@@ -26,4 +32,4 @@ declare class UpdateCheckoutOfferDto implements CheckoutOfferSelectionUpdate {
|
|
|
26
32
|
validUntil?: string | null;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
export { CHECKOUT_OFFER_REPOSITORY_TOKEN, CreateCheckoutOfferDto, UpdateCheckoutOfferDto, buildCheckoutOfferController };
|
|
35
|
+
export { CHECKOUT_OFFER_REPOSITORY_TOKEN, CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN, CreateCheckoutOfferDto, UpdateCheckoutOfferDto, buildCheckoutOfferController };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { C as CheckoutOfferPricing, a as CheckoutOfferPricingInput, b as CheckoutOfferService, P as PricedCheckoutOffer } from '../checkout-offer.service-
|
|
1
|
+
export { C as CheckoutOfferPricing, a as CheckoutOfferPricingInput, b as CheckoutOfferService, c as ConcludeCheckoutOfferWithin, d as ConcludedCheckoutOffer, P as PricedCheckoutOffer } from '../checkout-offer.service-BZumQOmZ.js';
|
|
2
2
|
import { Type, CanActivate } from '@nestjs/common';
|
|
3
|
-
export { a as
|
|
3
|
+
export { a as CheckoutOfferConclusionOptions, b as CheckoutOfferControllerConfig, c as CheckoutOfferModule, C as CheckoutOfferModuleOptions } from '../checkout-offer.module-B-DF2I_-.js';
|
|
4
4
|
import { CheckoutOfferSelection, CheckoutOfferSelectionUpdate } from '@saasicat/core';
|
|
5
|
+
import '../subscription-contract.service-wMqIPFkS.js';
|
|
5
6
|
import '../promo.service-CBMm9RU7.js';
|
|
6
7
|
import '../di-CcNeq9v-.js';
|
|
7
8
|
|
|
@@ -9,6 +10,11 @@ declare function buildCheckoutOfferController(guards: Array<Type<CanActivate>>):
|
|
|
9
10
|
|
|
10
11
|
/** Repository for `checkout_offers`. */
|
|
11
12
|
declare const CHECKOUT_OFFER_REPOSITORY_TOKEN: unique symbol;
|
|
13
|
+
/**
|
|
14
|
+
* The transaction an offer is concluded in: consuming it, writing its contract
|
|
15
|
+
* and the application's own writes commit or roll back together.
|
|
16
|
+
*/
|
|
17
|
+
declare const CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN: unique symbol;
|
|
12
18
|
|
|
13
19
|
declare class CreateCheckoutOfferDto implements CheckoutOfferSelection {
|
|
14
20
|
planKey: string;
|
|
@@ -26,4 +32,4 @@ declare class UpdateCheckoutOfferDto implements CheckoutOfferSelectionUpdate {
|
|
|
26
32
|
validUntil?: string | null;
|
|
27
33
|
}
|
|
28
34
|
|
|
29
|
-
export { CHECKOUT_OFFER_REPOSITORY_TOKEN, CreateCheckoutOfferDto, UpdateCheckoutOfferDto, buildCheckoutOfferController };
|
|
35
|
+
export { CHECKOUT_OFFER_REPOSITORY_TOKEN, CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN, CreateCheckoutOfferDto, UpdateCheckoutOfferDto, buildCheckoutOfferController };
|
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import "../chunk-DFOW3JVO.js";
|
|
2
2
|
import {
|
|
3
3
|
CHECKOUT_OFFER_REPOSITORY_TOKEN,
|
|
4
|
+
CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN,
|
|
4
5
|
CheckoutOfferModule,
|
|
5
6
|
CheckoutOfferPricing,
|
|
6
7
|
CheckoutOfferService,
|
|
7
8
|
CreateCheckoutOfferDto,
|
|
8
9
|
UpdateCheckoutOfferDto,
|
|
9
10
|
buildCheckoutOfferController
|
|
10
|
-
} from "../chunk-
|
|
11
|
-
import "../chunk-
|
|
12
|
-
import "../chunk-DR2SQNMX.js";
|
|
11
|
+
} from "../chunk-H3GVIQVK.js";
|
|
12
|
+
import "../chunk-LEZ6KYQ7.js";
|
|
13
13
|
import "../chunk-KPEMTBOP.js";
|
|
14
|
+
import "../chunk-VBRYPU7V.js";
|
|
15
|
+
import "../chunk-AOQJEYOL.js";
|
|
16
|
+
import "../chunk-FAH62CAJ.js";
|
|
14
17
|
import "../chunk-YSC46BGM.js";
|
|
15
18
|
import "../chunk-UUDUEQXA.js";
|
|
16
19
|
import "../chunk-5BCYJ3QY.js";
|
|
17
20
|
import "../chunk-QSBMFY4I.js";
|
|
18
|
-
import "../chunk-AOQJEYOL.js";
|
|
19
21
|
import "../chunk-SABTXESR.js";
|
|
20
22
|
import "../chunk-SHUYVCID.js";
|
|
21
23
|
export {
|
|
22
24
|
CHECKOUT_OFFER_REPOSITORY_TOKEN,
|
|
25
|
+
CHECKOUT_OFFER_TRANSACTION_RUNNER_TOKEN,
|
|
23
26
|
CheckoutOfferModule,
|
|
24
27
|
CheckoutOfferPricing,
|
|
25
28
|
CheckoutOfferService,
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { Type, CanActivate, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
|
|
2
|
-
import { CheckoutOfferRepository, BundleRepository, PlanRepository, PromotionRepository, CatalogEntryRepository } from '@saasicat/core';
|
|
2
|
+
import { SubscriptionContractRepository, TransactionRunner, CheckoutOfferRepository, BundleRepository, PlanRepository, PromotionRepository, CatalogEntryRepository } from '@saasicat/core';
|
|
3
3
|
import { P as ProviderSpec } from './di-CcNeq9v-.js';
|
|
4
4
|
|
|
5
5
|
interface CheckoutOfferControllerConfig {
|
|
6
6
|
/** Class-level guards; `[]` for auth-free public endpoints. */
|
|
7
7
|
guards: Array<Type<CanActivate>>;
|
|
8
8
|
}
|
|
9
|
+
/** What `CheckoutOfferService.conclude` writes through, and in one transaction. */
|
|
10
|
+
interface CheckoutOfferConclusionOptions {
|
|
11
|
+
/** Writes the contract an offer becomes, on the conclusion's transaction. */
|
|
12
|
+
subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
|
|
13
|
+
/** The transaction consuming the offer, the contract and the application's writes share. */
|
|
14
|
+
transactionRunner: ProviderSpec<TransactionRunner>;
|
|
15
|
+
}
|
|
9
16
|
interface CheckoutOfferModuleOptions {
|
|
10
17
|
checkoutOfferRepository: ProviderSpec<CheckoutOfferRepository>;
|
|
11
18
|
/**
|
|
@@ -30,6 +37,12 @@ interface CheckoutOfferModuleOptions {
|
|
|
30
37
|
* skipped (graceful).
|
|
31
38
|
*/
|
|
32
39
|
catalogEntryRepository?: ProviderSpec<CatalogEntryRepository>;
|
|
40
|
+
/**
|
|
41
|
+
* Enables `CheckoutOfferService.conclude`, which consumes an offer and
|
|
42
|
+
* writes its contract in one transaction. Without it, `conclude` refuses
|
|
43
|
+
* to run rather than writing the two apart.
|
|
44
|
+
*/
|
|
45
|
+
conclusion?: CheckoutOfferConclusionOptions;
|
|
33
46
|
/** Controller mount for `/public/checkout-offer`. Omitted = service only. */
|
|
34
47
|
controller?: CheckoutOfferControllerConfig;
|
|
35
48
|
imports?: Array<Type<unknown> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
|
|
@@ -40,4 +53,4 @@ declare class CheckoutOfferModule {
|
|
|
40
53
|
static forRoot(options: CheckoutOfferModuleOptions): DynamicModule;
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
export { type CheckoutOfferModuleOptions as C, type
|
|
56
|
+
export { type CheckoutOfferModuleOptions as C, type CheckoutOfferConclusionOptions as a, type CheckoutOfferControllerConfig as b, CheckoutOfferModule as c };
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { Type, CanActivate, DynamicModule, ForwardReference, Provider } from '@nestjs/common';
|
|
2
|
-
import { CheckoutOfferRepository, BundleRepository, PlanRepository, PromotionRepository, CatalogEntryRepository } from '@saasicat/core';
|
|
2
|
+
import { SubscriptionContractRepository, TransactionRunner, CheckoutOfferRepository, BundleRepository, PlanRepository, PromotionRepository, CatalogEntryRepository } from '@saasicat/core';
|
|
3
3
|
import { P as ProviderSpec } from './di-CcNeq9v-.cjs';
|
|
4
4
|
|
|
5
5
|
interface CheckoutOfferControllerConfig {
|
|
6
6
|
/** Class-level guards; `[]` for auth-free public endpoints. */
|
|
7
7
|
guards: Array<Type<CanActivate>>;
|
|
8
8
|
}
|
|
9
|
+
/** What `CheckoutOfferService.conclude` writes through, and in one transaction. */
|
|
10
|
+
interface CheckoutOfferConclusionOptions {
|
|
11
|
+
/** Writes the contract an offer becomes, on the conclusion's transaction. */
|
|
12
|
+
subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
|
|
13
|
+
/** The transaction consuming the offer, the contract and the application's writes share. */
|
|
14
|
+
transactionRunner: ProviderSpec<TransactionRunner>;
|
|
15
|
+
}
|
|
9
16
|
interface CheckoutOfferModuleOptions {
|
|
10
17
|
checkoutOfferRepository: ProviderSpec<CheckoutOfferRepository>;
|
|
11
18
|
/**
|
|
@@ -30,6 +37,12 @@ interface CheckoutOfferModuleOptions {
|
|
|
30
37
|
* skipped (graceful).
|
|
31
38
|
*/
|
|
32
39
|
catalogEntryRepository?: ProviderSpec<CatalogEntryRepository>;
|
|
40
|
+
/**
|
|
41
|
+
* Enables `CheckoutOfferService.conclude`, which consumes an offer and
|
|
42
|
+
* writes its contract in one transaction. Without it, `conclude` refuses
|
|
43
|
+
* to run rather than writing the two apart.
|
|
44
|
+
*/
|
|
45
|
+
conclusion?: CheckoutOfferConclusionOptions;
|
|
33
46
|
/** Controller mount for `/public/checkout-offer`. Omitted = service only. */
|
|
34
47
|
controller?: CheckoutOfferControllerConfig;
|
|
35
48
|
imports?: Array<Type<unknown> | DynamicModule | Promise<DynamicModule> | ForwardReference>;
|
|
@@ -40,4 +53,4 @@ declare class CheckoutOfferModule {
|
|
|
40
53
|
static forRoot(options: CheckoutOfferModuleOptions): DynamicModule;
|
|
41
54
|
}
|
|
42
55
|
|
|
43
|
-
export { type CheckoutOfferModuleOptions as C, type
|
|
56
|
+
export { type CheckoutOfferModuleOptions as C, type CheckoutOfferConclusionOptions as a, type CheckoutOfferControllerConfig as b, CheckoutOfferModule as c };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { PlanCatalog, PlanRepository, BundleRepository, PromotionRepository, CheckoutOfferPriceBreakdown, CheckoutOfferLineItem, CheckoutOfferPromotionSnapshot, CheckoutOfferPromoCodeSnapshot, CheckoutOfferRow, CheckoutOfferRepository, CatalogEntryRepository, CheckoutOfferFilter, CheckoutOfferSelection, CheckoutOfferSelectionUpdate } from '@saasicat/core';
|
|
1
|
+
import { PlanCatalog, PlanRepository, BundleRepository, PromotionRepository, CheckoutOfferPriceBreakdown, CheckoutOfferLineItem, CheckoutOfferPromotionSnapshot, CheckoutOfferPromoCodeSnapshot, CheckoutOfferRow, CheckoutOfferRepository, CatalogEntryRepository, TransactionRunner, CheckoutOfferFilter, CheckoutOfferSelection, CheckoutOfferSelectionUpdate, TransactionContext, SubscriptionContractRecord } from '@saasicat/core';
|
|
2
|
+
import { S as SubscriptionContractService, C as CreateContractFromOfferOptions } from './subscription-contract.service-wMqIPFkS.js';
|
|
2
3
|
import { a as PromoCodesService } from './promo.service-CBMm9RU7.js';
|
|
3
4
|
|
|
4
5
|
type Cycle = 'monthly' | 'yearly';
|
|
@@ -56,13 +57,26 @@ declare class CheckoutOfferPricing {
|
|
|
56
57
|
private pricePromoCode;
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
/** What concluding an offer produced: the consumed offer and its contract. */
|
|
61
|
+
interface ConcludedCheckoutOffer {
|
|
62
|
+
offer: CheckoutOfferRow;
|
|
63
|
+
contract: SubscriptionContractRecord;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The application's own writes that belong to concluding an offer, such as
|
|
67
|
+
* starting its subscription. They run on the same transaction, after the offer
|
|
68
|
+
* is consumed and its contract written; throwing undoes all of it.
|
|
69
|
+
*/
|
|
70
|
+
type ConcludeCheckoutOfferWithin = (tx: TransactionContext, concluded: ConcludedCheckoutOffer) => Promise<void>;
|
|
59
71
|
declare class CheckoutOfferService {
|
|
60
72
|
private readonly repo;
|
|
61
73
|
private readonly pricing;
|
|
62
74
|
private readonly bundles;
|
|
63
75
|
private readonly plans;
|
|
64
76
|
private readonly catalogEntries;
|
|
65
|
-
|
|
77
|
+
private readonly contracts;
|
|
78
|
+
private readonly transactions;
|
|
79
|
+
constructor(repo: CheckoutOfferRepository, pricing: CheckoutOfferPricing, bundles?: BundleRepository | null, plans?: PlanRepository | null, catalogEntries?: CatalogEntryRepository | null, contracts?: SubscriptionContractService | null, transactions?: TransactionRunner | null);
|
|
66
80
|
list(filter: CheckoutOfferFilter): Promise<CheckoutOfferRow[]>;
|
|
67
81
|
getById(id: string): Promise<CheckoutOfferRow>;
|
|
68
82
|
/** Prices what the caller chose and stores it as an open offer. */
|
|
@@ -89,6 +103,43 @@ declare class CheckoutOfferService {
|
|
|
89
103
|
* is kept for amounts that no longer match.
|
|
90
104
|
*/
|
|
91
105
|
consume(id: string): Promise<CheckoutOfferRow>;
|
|
106
|
+
/**
|
|
107
|
+
* Consumes an offer and creates its contract in one transaction, together
|
|
108
|
+
* with the application's own writes in `within`, so an offer is never
|
|
109
|
+
* consumed without its contract, and no contract is written for an offer
|
|
110
|
+
* that stays open.
|
|
111
|
+
*
|
|
112
|
+
* Everything that can refuse runs before the transaction: what `consume`
|
|
113
|
+
* checks, and the checks the contract the offer becomes is held to. Inside
|
|
114
|
+
* it, the offer is consumed on the condition that it is still open, the
|
|
115
|
+
* contract is written, and `within` runs; an error in any of them undoes
|
|
116
|
+
* the others, and the offer can be concluded again.
|
|
117
|
+
*
|
|
118
|
+
* An offer that is already concluded for the same tenant answers with its
|
|
119
|
+
* contract rather than a refusal, so a caller retrying after a lost answer,
|
|
120
|
+
* or losing a race to another call for that tenant, gets the conclusion that
|
|
121
|
+
* stands; `within` does not run again, its writes committed with it. A
|
|
122
|
+
* conclusion for another tenant is refused with
|
|
123
|
+
* `CHECKOUT_OFFER_ALREADY_CONSUMED`, and an offer changed between the checks
|
|
124
|
+
* and the transaction with `CHECKOUT_OFFER_CHANGED`, nothing written.
|
|
125
|
+
*
|
|
126
|
+
* A promo code on the offer is redeemed in `within`, with
|
|
127
|
+
* `PromoCodesService.redeemInTransaction` on the same transaction. Before
|
|
128
|
+
* the transaction the code is only checked the way pricing checks it; the
|
|
129
|
+
* redemption checks the rest, the customer and the remaining redemptions,
|
|
130
|
+
* where a refusal still undoes everything. Nothing checks the code again
|
|
131
|
+
* after `within`, so a redemption that takes its last slot does not refuse
|
|
132
|
+
* the offer it was redeemed for.
|
|
133
|
+
*/
|
|
134
|
+
conclude(id: string, options: CreateContractFromOfferOptions, within?: ConcludeCheckoutOfferWithin): Promise<ConcludedCheckoutOffer>;
|
|
135
|
+
private assertConsumable;
|
|
136
|
+
/**
|
|
137
|
+
* The conclusion that stands for this tenant, if the offer has one. An offer
|
|
138
|
+
* carries no tenant and its id travels in a link, so a conclusion for
|
|
139
|
+
* another tenant is not an answer: that caller is refused as before.
|
|
140
|
+
*/
|
|
141
|
+
private standingConclusion;
|
|
142
|
+
private conclusionPorts;
|
|
92
143
|
/**
|
|
93
144
|
* #35 P6 — server-side requires validation: the dependencies of all
|
|
94
145
|
* features (plan ∪ selected bundles) must be covered within the
|
|
@@ -112,4 +163,4 @@ declare class CheckoutOfferService {
|
|
|
112
163
|
private isExpired;
|
|
113
164
|
}
|
|
114
165
|
|
|
115
|
-
export { CheckoutOfferPricing as C, type PricedCheckoutOffer as P, type CheckoutOfferPricingInput as a, CheckoutOfferService as b };
|
|
166
|
+
export { CheckoutOfferPricing as C, type PricedCheckoutOffer as P, type CheckoutOfferPricingInput as a, CheckoutOfferService as b, type ConcludeCheckoutOfferWithin as c, type ConcludedCheckoutOffer as d };
|