@saasicat/nest 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +53 -0
  3. package/dist/admin/index.cjs +1283 -0
  4. package/dist/admin/index.d.cts +225 -0
  5. package/dist/admin/index.d.ts +225 -0
  6. package/dist/admin/index.js +58 -0
  7. package/dist/admin-audit.service-9IqXMlZm.d.cts +30 -0
  8. package/dist/admin-audit.service-9IqXMlZm.d.ts +30 -0
  9. package/dist/admin-manifest.config-DyrQNT7M.d.cts +10 -0
  10. package/dist/admin-manifest.config-DyrQNT7M.d.ts +10 -0
  11. package/dist/aggregation-CJ3qQf92.d.cts +288 -0
  12. package/dist/aggregation-Dvz9e8X2.d.ts +288 -0
  13. package/dist/billing/index.cjs +5205 -0
  14. package/dist/billing/index.d.cts +1326 -0
  15. package/dist/billing/index.d.ts +1326 -0
  16. package/dist/billing/index.js +197 -0
  17. package/dist/catalog/index.cjs +6449 -0
  18. package/dist/catalog/index.d.cts +1073 -0
  19. package/dist/catalog/index.d.ts +1073 -0
  20. package/dist/catalog/index.js +158 -0
  21. package/dist/checkout-offer/index.cjs +807 -0
  22. package/dist/checkout-offer/index.d.cts +120 -0
  23. package/dist/checkout-offer/index.d.ts +120 -0
  24. package/dist/checkout-offer/index.js +20 -0
  25. package/dist/chunk-2FR6ZL7R.js +0 -0
  26. package/dist/chunk-2PNX2QL2.js +347 -0
  27. package/dist/chunk-2VNZYRDV.js +326 -0
  28. package/dist/chunk-7MLGHWKO.js +12 -0
  29. package/dist/chunk-ABB2CRAS.js +31 -0
  30. package/dist/chunk-AJ3EPELS.js +157 -0
  31. package/dist/chunk-E56W4U2P.js +90 -0
  32. package/dist/chunk-HRU3CP57.js +71 -0
  33. package/dist/chunk-L4SUWH5B.js +14 -0
  34. package/dist/chunk-M6CZQYPY.js +314 -0
  35. package/dist/chunk-MDIZUVIK.js +87 -0
  36. package/dist/chunk-MV6LW5UB.js +217 -0
  37. package/dist/chunk-NYLON2VC.js +6 -0
  38. package/dist/chunk-P6MYZMXQ.js +951 -0
  39. package/dist/chunk-Q53N43LQ.js +13 -0
  40. package/dist/chunk-QJVPRD3R.js +573 -0
  41. package/dist/chunk-RIGLQ4BV.js +3367 -0
  42. package/dist/chunk-SABTXESR.js +24 -0
  43. package/dist/chunk-SHUYVCID.js +6 -0
  44. package/dist/chunk-SYEVGPFC.js +686 -0
  45. package/dist/chunk-V7HUZ6UQ.js +5923 -0
  46. package/dist/chunk-WPUVJRIN.js +29 -0
  47. package/dist/chunk-XCZ3TTFK.js +22 -0
  48. package/dist/chunk-XSGU2Y2O.js +1611 -0
  49. package/dist/chunk-YNEW3L63.js +190 -0
  50. package/dist/chunk-YXGHPILG.js +614 -0
  51. package/dist/chunk-ZL4LLE2Z.js +465 -0
  52. package/dist/di-CcNeq9v-.d.cts +16 -0
  53. package/dist/di-CcNeq9v-.d.ts +16 -0
  54. package/dist/discovery/index.cjs +588 -0
  55. package/dist/discovery/index.d.cts +299 -0
  56. package/dist/discovery/index.d.ts +299 -0
  57. package/dist/discovery/index.js +49 -0
  58. package/dist/discovery.scanner-CUYLKlYT.d.cts +59 -0
  59. package/dist/discovery.scanner-CUYLKlYT.d.ts +59 -0
  60. package/dist/entitlement/index.cjs +805 -0
  61. package/dist/entitlement/index.d.cts +60 -0
  62. package/dist/entitlement/index.d.ts +60 -0
  63. package/dist/entitlement/index.js +57 -0
  64. package/dist/index.cjs +15918 -0
  65. package/dist/index.d.cts +85 -0
  66. package/dist/index.d.ts +85 -0
  67. package/dist/index.js +956 -0
  68. package/dist/plan-resolution-CFCoUkrE.d.cts +41 -0
  69. package/dist/plan-resolution-CFCoUkrE.d.ts +41 -0
  70. package/dist/platform/index.cjs +2772 -0
  71. package/dist/platform/index.d.cts +118 -0
  72. package/dist/platform/index.d.ts +118 -0
  73. package/dist/platform/index.js +37 -0
  74. package/dist/promo/index.cjs +995 -0
  75. package/dist/promo/index.d.cts +121 -0
  76. package/dist/promo/index.d.ts +121 -0
  77. package/dist/promo/index.js +58 -0
  78. package/dist/registration/index.cjs +1687 -0
  79. package/dist/registration/index.d.cts +444 -0
  80. package/dist/registration/index.d.ts +444 -0
  81. package/dist/registration/index.js +82 -0
  82. package/dist/saas-platform.module-CgZ2omgg.d.cts +180 -0
  83. package/dist/saas-platform.module-DT9TnCzk.d.ts +180 -0
  84. package/dist/service-DX8KbGXl.d.cts +109 -0
  85. package/dist/service-DX8KbGXl.d.ts +109 -0
  86. package/dist/subscription-contract/index.cjs +471 -0
  87. package/dist/subscription-contract/index.d.cts +17 -0
  88. package/dist/subscription-contract/index.d.ts +17 -0
  89. package/dist/subscription-contract/index.js +21 -0
  90. package/dist/subscription-contract.service--cm47ZJJ.d.cts +39 -0
  91. package/dist/subscription-contract.service--cm47ZJJ.d.ts +39 -0
  92. package/dist/testing/index.cjs +3942 -0
  93. package/dist/testing/index.d.cts +279 -0
  94. package/dist/testing/index.d.ts +279 -0
  95. package/dist/testing/index.js +1195 -0
  96. package/package.json +185 -0
@@ -0,0 +1,471 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/subscription-contract/index.ts
22
+ var subscription_contract_exports = {};
23
+ __export(subscription_contract_exports, {
24
+ SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN: () => SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN,
25
+ SubscriptionContractModule: () => SubscriptionContractModule,
26
+ SubscriptionContractService: () => SubscriptionContractService,
27
+ contractLineItemToInvoiceLineItem: () => contractLineItemToInvoiceLineItem,
28
+ sortContractLineItemsForInvoice: () => sortContractLineItemsForInvoice,
29
+ subscriptionContractToInvoiceSnapshot: () => subscriptionContractToInvoiceSnapshot
30
+ });
31
+ module.exports = __toCommonJS(subscription_contract_exports);
32
+
33
+ // src/subscription-contract/subscription-contract.service.ts
34
+ var import_common = require("@nestjs/common");
35
+
36
+ // src/checkout-offer/discount-line-items.ts
37
+ function appendImplicitDiscountLineItem(input) {
38
+ const lineItems = input.lineItems.map((item) => cloneCheckoutOfferLineItem(item));
39
+ const discountNet = roundMoney(input.priceBreakdown.regularNet - input.priceBreakdown.effectiveNet);
40
+ if (lineItems.some((item) => item.kind === "discount" && !isGeneratedDiscount(item))) {
41
+ return lineItems;
42
+ }
43
+ const lineItemsWithoutGeneratedDiscount = lineItems.filter((item) => !isGeneratedDiscount(item));
44
+ if (discountNet <= 0) {
45
+ return lineItemsWithoutGeneratedDiscount;
46
+ }
47
+ return [
48
+ ...lineItemsWithoutGeneratedDiscount,
49
+ createDiscountLineItem(input, discountNet)
50
+ ];
51
+ }
52
+ __name(appendImplicitDiscountLineItem, "appendImplicitDiscountLineItem");
53
+ function cloneCheckoutOfferLineItem(item) {
54
+ return {
55
+ ...item,
56
+ featuresSnapshot: [
57
+ ...item.featuresSnapshot ?? []
58
+ ],
59
+ quotaEffectsSnapshot: {
60
+ ...item.quotaEffectsSnapshot ?? {}
61
+ },
62
+ metadata: cloneRecord(item.metadata)
63
+ };
64
+ }
65
+ __name(cloneCheckoutOfferLineItem, "cloneCheckoutOfferLineItem");
66
+ function createDiscountLineItem(input, discountNet) {
67
+ const promoCode = input.promoCodeSnapshot ?? null;
68
+ const firstPromotion = input.promotionSnapshots?.[0] ?? null;
69
+ const discountGross = roundMoney(discountNet * (1 + input.priceBreakdown.vatRate));
70
+ return {
71
+ kind: "discount",
72
+ sourceKey: promoCode?.code ?? firstPromotion?.id ?? "price-discount",
73
+ sourceVersionId: null,
74
+ titleSnapshot: promoCode?.label ?? firstPromotion?.label ?? "Rabatt",
75
+ descriptionSnapshot: promoCode ? `Promo-Code ${promoCode.code}` : null,
76
+ quantity: 1,
77
+ unit: null,
78
+ priceNet: -discountNet,
79
+ priceGross: -discountGross,
80
+ billingCycle: input.billingCycle,
81
+ featuresSnapshot: [],
82
+ quotaEffectsSnapshot: {},
83
+ metadata: {
84
+ generated: true,
85
+ source: promoCode ? "promo_code" : firstPromotion ? "promotion" : "price_breakdown",
86
+ discountNet,
87
+ discountGross,
88
+ promotionSnapshots: cloneArray(input.promotionSnapshots ?? []),
89
+ promoCodeSnapshot: cloneJsonValue(promoCode)
90
+ }
91
+ };
92
+ }
93
+ __name(createDiscountLineItem, "createDiscountLineItem");
94
+ function roundMoney(value) {
95
+ return Math.round((value + Number.EPSILON) * 100) / 100;
96
+ }
97
+ __name(roundMoney, "roundMoney");
98
+ function isGeneratedDiscount(item) {
99
+ return item.kind === "discount" && item.metadata?.generated === true;
100
+ }
101
+ __name(isGeneratedDiscount, "isGeneratedDiscount");
102
+ function cloneRecord(value) {
103
+ if (!value) return null;
104
+ return cloneJsonValue(value);
105
+ }
106
+ __name(cloneRecord, "cloneRecord");
107
+ function cloneArray(value) {
108
+ return cloneJsonValue(value);
109
+ }
110
+ __name(cloneArray, "cloneArray");
111
+ function cloneJsonValue(value) {
112
+ return value == null ? value : JSON.parse(JSON.stringify(value));
113
+ }
114
+ __name(cloneJsonValue, "cloneJsonValue");
115
+
116
+ // src/subscription-contract/tokens.ts
117
+ var SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN = /* @__PURE__ */ Symbol.for("saas-platform/SubscriptionContractRepository");
118
+
119
+ // src/subscription-contract/subscription-contract.service.ts
120
+ function _ts_decorate(decorators, target, key, desc) {
121
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
122
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
123
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
124
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
125
+ }
126
+ __name(_ts_decorate, "_ts_decorate");
127
+ function _ts_metadata(k, v) {
128
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
129
+ }
130
+ __name(_ts_metadata, "_ts_metadata");
131
+ function _ts_param(paramIndex, decorator) {
132
+ return function(target, key) {
133
+ decorator(target, key, paramIndex);
134
+ };
135
+ }
136
+ __name(_ts_param, "_ts_param");
137
+ var SubscriptionContractService = class {
138
+ static {
139
+ __name(this, "SubscriptionContractService");
140
+ }
141
+ repo;
142
+ constructor(repo) {
143
+ this.repo = repo;
144
+ }
145
+ list(filter) {
146
+ return this.repo.list(filter);
147
+ }
148
+ async getById(contractId) {
149
+ const row = await this.repo.findById(contractId);
150
+ if (!row) {
151
+ throw new import_common.NotFoundException(`SubscriptionContract '${contractId}' nicht gefunden`);
152
+ }
153
+ return row;
154
+ }
155
+ async findActiveByTenantId(tenantId, asOf = /* @__PURE__ */ new Date()) {
156
+ return this.repo.findActiveByTenantId(tenantId, asOf);
157
+ }
158
+ async getActiveInvoiceSnapshotForTenant(tenantId, asOf = /* @__PURE__ */ new Date()) {
159
+ const contract = await this.repo.findActiveByTenantId(tenantId, asOf);
160
+ if (!contract) {
161
+ throw new import_common.NotFoundException(`Kein aktiver SubscriptionContract f\xFCr Tenant ${tenantId}`);
162
+ }
163
+ return subscriptionContractToInvoiceSnapshot(contract);
164
+ }
165
+ async create(data) {
166
+ this.assertCreateData(data);
167
+ return this.repo.create(this.cloneCreateData(data));
168
+ }
169
+ async terminate(contractId, data) {
170
+ const existing = await this.getById(contractId);
171
+ this.assertTerminable(existing, data);
172
+ return this.repo.terminate(contractId, data);
173
+ }
174
+ async replaceActiveContract(tenantId, data, terminateAt) {
175
+ const previous = await this.repo.findActiveByTenantId(tenantId, terminateAt);
176
+ if (previous) {
177
+ await this.terminate(previous.id, {
178
+ effectiveUntil: terminateAt,
179
+ status: "superseded"
180
+ });
181
+ }
182
+ const next = await this.create({
183
+ ...data,
184
+ tenantId,
185
+ effectiveFrom: data.effectiveFrom ?? terminateAt
186
+ });
187
+ return {
188
+ previous,
189
+ next
190
+ };
191
+ }
192
+ createDataFromOffer(offer, options) {
193
+ if (offer.status !== "consumed") {
194
+ throw new import_common.ConflictException(`CheckoutOffer '${offer.id}' muss vor Contract-Erstellung consumed sein`);
195
+ }
196
+ const lineItems = this.lineItemsFromOffer(offer);
197
+ return {
198
+ projectKey: offer.projectKey,
199
+ tenantId: options.tenantId,
200
+ status: options.status ?? "active",
201
+ effectiveFrom: options.effectiveFrom,
202
+ effectiveUntil: options.effectiveUntil ?? null,
203
+ originalOfferId: offer.id,
204
+ originalPlanVersionId: offer.planVersionId,
205
+ originalBundleVersionIds: [
206
+ ...offer.bundleVersionIds ?? []
207
+ ],
208
+ entitlementSnapshot: options.entitlementSnapshot ?? null,
209
+ priceSnapshot: this.priceSnapshotFromOffer(offer),
210
+ promotionSnapshots: [
211
+ ...offer.promotionSnapshots ?? []
212
+ ],
213
+ promoCodeSnapshots: offer.promoCodeSnapshot ? [
214
+ offer.promoCodeSnapshot
215
+ ] : [],
216
+ termsSnapshot: options.termsSnapshot ?? null,
217
+ lineItems
218
+ };
219
+ }
220
+ async createFromOffer(offer, options) {
221
+ return this.create(this.createDataFromOffer(offer, options));
222
+ }
223
+ lineItemsFromOffer(offer) {
224
+ const source = offer.lineItems ?? [];
225
+ if (source.length === 0) {
226
+ throw new import_common.UnprocessableEntityException({
227
+ code: "CHECKOUT_OFFER_LINE_ITEMS_REQUIRED",
228
+ message: "Aus einem CheckoutOffer kann nur ein Contract entstehen, wenn LineItems eingefroren sind."
229
+ });
230
+ }
231
+ return appendImplicitDiscountLineItem({
232
+ billingCycle: offer.billingCycle,
233
+ priceBreakdown: offer.priceBreakdown,
234
+ lineItems: source,
235
+ promotionSnapshots: offer.promotionSnapshots ?? [],
236
+ promoCodeSnapshot: offer.promoCodeSnapshot ?? null
237
+ }).map((item) => this.offerLineItemToContractLineItem(item));
238
+ }
239
+ offerLineItemToContractLineItem(item) {
240
+ return {
241
+ kind: item.kind,
242
+ sourceKey: item.sourceKey,
243
+ sourceVersionId: item.sourceVersionId ?? null,
244
+ titleSnapshot: item.titleSnapshot,
245
+ descriptionSnapshot: item.descriptionSnapshot ?? null,
246
+ quantity: item.quantity,
247
+ unit: item.unit ?? null,
248
+ priceNet: item.priceNet,
249
+ priceGross: item.priceGross,
250
+ billingCycle: item.billingCycle,
251
+ minimumTermUntil: this.parseOptionalDate(item.minimumTermUntil, "lineItems.minimumTermUntil"),
252
+ featuresSnapshot: [
253
+ ...item.featuresSnapshot ?? []
254
+ ],
255
+ quotaEffectsSnapshot: {
256
+ ...item.quotaEffectsSnapshot ?? {}
257
+ },
258
+ metadata: item.metadata ?? null
259
+ };
260
+ }
261
+ parseOptionalDate(value, field) {
262
+ if (value === null || value === void 0) return null;
263
+ const date = value instanceof Date ? new Date(value) : new Date(value);
264
+ if (Number.isNaN(date.getTime())) {
265
+ throw new import_common.UnprocessableEntityException({
266
+ code: "SUBSCRIPTION_CONTRACT_INVALID_DATE",
267
+ message: `${field} muss ein g\xFCltiges Datum sein.`
268
+ });
269
+ }
270
+ return date;
271
+ }
272
+ priceSnapshotFromOffer(offer) {
273
+ const breakdown = offer.priceBreakdown;
274
+ return {
275
+ currency: breakdown.currency,
276
+ billingCycle: breakdown.billingCycle,
277
+ subtotalNet: breakdown.regularNet,
278
+ discountNet: Math.max(0, breakdown.regularNet - breakdown.effectiveNet),
279
+ totalNet: breakdown.effectiveNet,
280
+ vatRate: breakdown.vatRate,
281
+ totalGross: breakdown.effectiveGross
282
+ };
283
+ }
284
+ assertCreateData(data) {
285
+ if (data.lineItems.length === 0) {
286
+ throw new import_common.UnprocessableEntityException({
287
+ code: "SUBSCRIPTION_CONTRACT_LINE_ITEMS_REQUIRED",
288
+ message: "SubscriptionContract ben\xF6tigt mindestens eine LineItem."
289
+ });
290
+ }
291
+ if (data.effectiveUntil && data.effectiveUntil <= data.effectiveFrom) {
292
+ throw new import_common.UnprocessableEntityException({
293
+ code: "SUBSCRIPTION_CONTRACT_INVALID_WINDOW",
294
+ message: "effectiveUntil muss nach effectiveFrom liegen."
295
+ });
296
+ }
297
+ const planLineItems = data.lineItems.filter((item) => item.kind === "plan");
298
+ if (planLineItems.length !== 1) {
299
+ throw new import_common.UnprocessableEntityException({
300
+ code: "SUBSCRIPTION_CONTRACT_PLAN_LINE_ITEM_REQUIRED",
301
+ message: "SubscriptionContract ben\xF6tigt genau eine Plan-Grundposition."
302
+ });
303
+ }
304
+ }
305
+ assertTerminable(existing, data) {
306
+ if (existing.status === "terminated" || existing.status === "superseded") {
307
+ throw new import_common.ConflictException(`SubscriptionContract '${existing.id}' ist bereits geschlossen`);
308
+ }
309
+ if (data.effectiveUntil <= existing.effectiveFrom) {
310
+ throw new import_common.UnprocessableEntityException({
311
+ code: "SUBSCRIPTION_CONTRACT_TERMINATION_BEFORE_START",
312
+ message: "effectiveUntil muss nach effectiveFrom des Contracts liegen."
313
+ });
314
+ }
315
+ }
316
+ cloneCreateData(data) {
317
+ return {
318
+ ...data,
319
+ originalBundleVersionIds: [
320
+ ...data.originalBundleVersionIds ?? []
321
+ ],
322
+ promotionSnapshots: [
323
+ ...data.promotionSnapshots ?? []
324
+ ],
325
+ promoCodeSnapshots: [
326
+ ...data.promoCodeSnapshots ?? []
327
+ ],
328
+ termsSnapshot: data.termsSnapshot ? {
329
+ ...data.termsSnapshot
330
+ } : null,
331
+ lineItems: data.lineItems.map((item) => this.cloneLineItemData(item))
332
+ };
333
+ }
334
+ cloneLineItemData(item) {
335
+ return {
336
+ ...item,
337
+ featuresSnapshot: [
338
+ ...item.featuresSnapshot
339
+ ],
340
+ quotaEffectsSnapshot: {
341
+ ...item.quotaEffectsSnapshot
342
+ },
343
+ metadata: item.metadata ? {
344
+ ...item.metadata
345
+ } : null
346
+ };
347
+ }
348
+ };
349
+ SubscriptionContractService = _ts_decorate([
350
+ (0, import_common.Injectable)(),
351
+ _ts_param(0, (0, import_common.Inject)(SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN)),
352
+ _ts_metadata("design:type", Function),
353
+ _ts_metadata("design:paramtypes", [
354
+ typeof SubscriptionContractRepository === "undefined" ? Object : SubscriptionContractRepository
355
+ ])
356
+ ], SubscriptionContractService);
357
+ function contractLineItemToInvoiceLineItem(item) {
358
+ return {
359
+ sourceContractLineItemId: item.id,
360
+ sourceKey: item.sourceKey,
361
+ sourceVersionId: item.sourceVersionId,
362
+ kind: item.kind,
363
+ title: item.titleSnapshot,
364
+ description: item.descriptionSnapshot,
365
+ quantity: item.quantity,
366
+ unit: item.unit,
367
+ priceNet: item.priceNet,
368
+ priceGross: item.priceGross,
369
+ billingCycle: item.billingCycle,
370
+ minimumTermUntil: item.minimumTermUntil,
371
+ metadata: item.metadata
372
+ };
373
+ }
374
+ __name(contractLineItemToInvoiceLineItem, "contractLineItemToInvoiceLineItem");
375
+ function subscriptionContractToInvoiceSnapshot(contract) {
376
+ return {
377
+ contractId: contract.id,
378
+ projectKey: contract.projectKey,
379
+ tenantId: contract.tenantId,
380
+ originalOfferId: contract.originalOfferId,
381
+ currency: contract.priceSnapshot.currency,
382
+ billingCycle: contract.priceSnapshot.billingCycle,
383
+ effectiveFrom: contract.effectiveFrom,
384
+ effectiveUntil: contract.effectiveUntil,
385
+ subtotalNet: contract.priceSnapshot.subtotalNet,
386
+ discountNet: contract.priceSnapshot.discountNet,
387
+ totalNet: contract.priceSnapshot.totalNet,
388
+ vatRate: contract.priceSnapshot.vatRate,
389
+ totalGross: contract.priceSnapshot.totalGross,
390
+ lineItems: sortContractLineItemsForInvoice(contract.lineItems).map(contractLineItemToInvoiceLineItem)
391
+ };
392
+ }
393
+ __name(subscriptionContractToInvoiceSnapshot, "subscriptionContractToInvoiceSnapshot");
394
+ function sortContractLineItemsForInvoice(lineItems) {
395
+ return [
396
+ ...lineItems
397
+ ].sort((a, b) => lineItemKindPriority(a.kind) - lineItemKindPriority(b.kind) || a.createdAt.getTime() - b.createdAt.getTime() || a.id.localeCompare(b.id));
398
+ }
399
+ __name(sortContractLineItemsForInvoice, "sortContractLineItemsForInvoice");
400
+ function lineItemKindPriority(kind) {
401
+ switch (kind) {
402
+ case "plan":
403
+ return 10;
404
+ case "bundle":
405
+ return 20;
406
+ case "discount":
407
+ return 90;
408
+ }
409
+ }
410
+ __name(lineItemKindPriority, "lineItemKindPriority");
411
+
412
+ // src/subscription-contract/subscription-contract.module.ts
413
+ var import_common2 = require("@nestjs/common");
414
+
415
+ // src/core/di.ts
416
+ function asProvider(token, impl) {
417
+ if (typeof impl === "object" && impl !== null && "useFactory" in impl && typeof impl.useFactory === "function") {
418
+ const factory = impl;
419
+ return {
420
+ provide: token,
421
+ useFactory: factory.useFactory,
422
+ inject: factory.inject
423
+ };
424
+ }
425
+ return {
426
+ provide: token,
427
+ useValue: impl
428
+ };
429
+ }
430
+ __name(asProvider, "asProvider");
431
+
432
+ // src/subscription-contract/subscription-contract.module.ts
433
+ function _ts_decorate2(decorators, target, key, desc) {
434
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
435
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
436
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
437
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
438
+ }
439
+ __name(_ts_decorate2, "_ts_decorate");
440
+ var SubscriptionContractModule = class _SubscriptionContractModule {
441
+ static {
442
+ __name(this, "SubscriptionContractModule");
443
+ }
444
+ static forRoot(options) {
445
+ return {
446
+ module: _SubscriptionContractModule,
447
+ global: options.global ?? false,
448
+ providers: [
449
+ asProvider(SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN, options.subscriptionContractRepository),
450
+ SubscriptionContractService,
451
+ ...options.extraProviders ?? []
452
+ ],
453
+ exports: [
454
+ SubscriptionContractService,
455
+ SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN
456
+ ]
457
+ };
458
+ }
459
+ };
460
+ SubscriptionContractModule = _ts_decorate2([
461
+ (0, import_common2.Module)({})
462
+ ], SubscriptionContractModule);
463
+ // Annotate the CommonJS export names for ESM import in node:
464
+ 0 && (module.exports = {
465
+ SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN,
466
+ SubscriptionContractModule,
467
+ SubscriptionContractService,
468
+ contractLineItemToInvoiceLineItem,
469
+ sortContractLineItemsForInvoice,
470
+ subscriptionContractToInvoiceSnapshot
471
+ });
@@ -0,0 +1,17 @@
1
+ export { C as CreateContractFromOfferOptions, S as SubscriptionContractService, c as contractLineItemToInvoiceLineItem, s as sortContractLineItemsForInvoice, a as subscriptionContractToInvoiceSnapshot } from '../subscription-contract.service--cm47ZJJ.cjs';
2
+ import { Provider, DynamicModule } from '@nestjs/common';
3
+ import { SubscriptionContractRepository } from '@saasicat/types';
4
+ import { P as ProviderSpec } from '../di-CcNeq9v-.cjs';
5
+
6
+ interface SubscriptionContractModuleOptions {
7
+ subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
8
+ extraProviders?: Provider[];
9
+ global?: boolean;
10
+ }
11
+ declare class SubscriptionContractModule {
12
+ static forRoot(options: SubscriptionContractModuleOptions): DynamicModule;
13
+ }
14
+
15
+ declare const SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN: unique symbol;
16
+
17
+ export { SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN, SubscriptionContractModule, type SubscriptionContractModuleOptions };
@@ -0,0 +1,17 @@
1
+ export { C as CreateContractFromOfferOptions, S as SubscriptionContractService, c as contractLineItemToInvoiceLineItem, s as sortContractLineItemsForInvoice, a as subscriptionContractToInvoiceSnapshot } from '../subscription-contract.service--cm47ZJJ.js';
2
+ import { Provider, DynamicModule } from '@nestjs/common';
3
+ import { SubscriptionContractRepository } from '@saasicat/types';
4
+ import { P as ProviderSpec } from '../di-CcNeq9v-.js';
5
+
6
+ interface SubscriptionContractModuleOptions {
7
+ subscriptionContractRepository: ProviderSpec<SubscriptionContractRepository>;
8
+ extraProviders?: Provider[];
9
+ global?: boolean;
10
+ }
11
+ declare class SubscriptionContractModule {
12
+ static forRoot(options: SubscriptionContractModuleOptions): DynamicModule;
13
+ }
14
+
15
+ declare const SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN: unique symbol;
16
+
17
+ export { SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN, SubscriptionContractModule, type SubscriptionContractModuleOptions };
@@ -0,0 +1,21 @@
1
+ import {
2
+ SubscriptionContractModule,
3
+ SubscriptionContractService,
4
+ contractLineItemToInvoiceLineItem,
5
+ sortContractLineItemsForInvoice,
6
+ subscriptionContractToInvoiceSnapshot
7
+ } from "../chunk-2PNX2QL2.js";
8
+ import "../chunk-MDIZUVIK.js";
9
+ import {
10
+ SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN
11
+ } from "../chunk-NYLON2VC.js";
12
+ import "../chunk-SABTXESR.js";
13
+ import "../chunk-SHUYVCID.js";
14
+ export {
15
+ SUBSCRIPTION_CONTRACT_REPOSITORY_TOKEN,
16
+ SubscriptionContractModule,
17
+ SubscriptionContractService,
18
+ contractLineItemToInvoiceLineItem,
19
+ sortContractLineItemsForInvoice,
20
+ subscriptionContractToInvoiceSnapshot
21
+ };
@@ -0,0 +1,39 @@
1
+ import { SubscriptionContractRepository, SubscriptionContractRecord, SubscriptionContractInvoiceSnapshot, CreateSubscriptionContractData, TerminateSubscriptionContractData, CheckoutOfferRow, ContractLineItemRecord, InvoiceLineItemSnapshot } from '@saasicat/types';
2
+
3
+ interface CreateContractFromOfferOptions {
4
+ tenantId: string;
5
+ effectiveFrom: Date;
6
+ effectiveUntil?: Date | null;
7
+ status?: CreateSubscriptionContractData['status'];
8
+ entitlementSnapshot?: CreateSubscriptionContractData['entitlementSnapshot'];
9
+ termsSnapshot?: Record<string, unknown> | null;
10
+ }
11
+ declare class SubscriptionContractService {
12
+ private readonly repo;
13
+ constructor(repo: SubscriptionContractRepository);
14
+ list(filter: Parameters<SubscriptionContractRepository['list']>[0]): Promise<SubscriptionContractRecord[]>;
15
+ getById(contractId: string): Promise<SubscriptionContractRecord>;
16
+ findActiveByTenantId(tenantId: string, asOf?: Date): Promise<SubscriptionContractRecord | null>;
17
+ getActiveInvoiceSnapshotForTenant(tenantId: string, asOf?: Date): Promise<SubscriptionContractInvoiceSnapshot>;
18
+ create(data: CreateSubscriptionContractData): Promise<SubscriptionContractRecord>;
19
+ terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
20
+ replaceActiveContract(tenantId: string, data: CreateSubscriptionContractData, terminateAt: Date): Promise<{
21
+ previous: SubscriptionContractRecord | null;
22
+ next: SubscriptionContractRecord;
23
+ }>;
24
+ createDataFromOffer(offer: CheckoutOfferRow, options: CreateContractFromOfferOptions): CreateSubscriptionContractData;
25
+ createFromOffer(offer: CheckoutOfferRow, options: CreateContractFromOfferOptions): Promise<SubscriptionContractRecord>;
26
+ private lineItemsFromOffer;
27
+ private offerLineItemToContractLineItem;
28
+ private parseOptionalDate;
29
+ private priceSnapshotFromOffer;
30
+ private assertCreateData;
31
+ private assertTerminable;
32
+ private cloneCreateData;
33
+ private cloneLineItemData;
34
+ }
35
+ declare function contractLineItemToInvoiceLineItem(item: ContractLineItemRecord): InvoiceLineItemSnapshot;
36
+ declare function subscriptionContractToInvoiceSnapshot(contract: SubscriptionContractRecord): SubscriptionContractInvoiceSnapshot;
37
+ declare function sortContractLineItemsForInvoice(lineItems: readonly ContractLineItemRecord[]): ContractLineItemRecord[];
38
+
39
+ export { type CreateContractFromOfferOptions as C, SubscriptionContractService as S, subscriptionContractToInvoiceSnapshot as a, contractLineItemToInvoiceLineItem as c, sortContractLineItemsForInvoice as s };
@@ -0,0 +1,39 @@
1
+ import { SubscriptionContractRepository, SubscriptionContractRecord, SubscriptionContractInvoiceSnapshot, CreateSubscriptionContractData, TerminateSubscriptionContractData, CheckoutOfferRow, ContractLineItemRecord, InvoiceLineItemSnapshot } from '@saasicat/types';
2
+
3
+ interface CreateContractFromOfferOptions {
4
+ tenantId: string;
5
+ effectiveFrom: Date;
6
+ effectiveUntil?: Date | null;
7
+ status?: CreateSubscriptionContractData['status'];
8
+ entitlementSnapshot?: CreateSubscriptionContractData['entitlementSnapshot'];
9
+ termsSnapshot?: Record<string, unknown> | null;
10
+ }
11
+ declare class SubscriptionContractService {
12
+ private readonly repo;
13
+ constructor(repo: SubscriptionContractRepository);
14
+ list(filter: Parameters<SubscriptionContractRepository['list']>[0]): Promise<SubscriptionContractRecord[]>;
15
+ getById(contractId: string): Promise<SubscriptionContractRecord>;
16
+ findActiveByTenantId(tenantId: string, asOf?: Date): Promise<SubscriptionContractRecord | null>;
17
+ getActiveInvoiceSnapshotForTenant(tenantId: string, asOf?: Date): Promise<SubscriptionContractInvoiceSnapshot>;
18
+ create(data: CreateSubscriptionContractData): Promise<SubscriptionContractRecord>;
19
+ terminate(contractId: string, data: TerminateSubscriptionContractData): Promise<SubscriptionContractRecord>;
20
+ replaceActiveContract(tenantId: string, data: CreateSubscriptionContractData, terminateAt: Date): Promise<{
21
+ previous: SubscriptionContractRecord | null;
22
+ next: SubscriptionContractRecord;
23
+ }>;
24
+ createDataFromOffer(offer: CheckoutOfferRow, options: CreateContractFromOfferOptions): CreateSubscriptionContractData;
25
+ createFromOffer(offer: CheckoutOfferRow, options: CreateContractFromOfferOptions): Promise<SubscriptionContractRecord>;
26
+ private lineItemsFromOffer;
27
+ private offerLineItemToContractLineItem;
28
+ private parseOptionalDate;
29
+ private priceSnapshotFromOffer;
30
+ private assertCreateData;
31
+ private assertTerminable;
32
+ private cloneCreateData;
33
+ private cloneLineItemData;
34
+ }
35
+ declare function contractLineItemToInvoiceLineItem(item: ContractLineItemRecord): InvoiceLineItemSnapshot;
36
+ declare function subscriptionContractToInvoiceSnapshot(contract: SubscriptionContractRecord): SubscriptionContractInvoiceSnapshot;
37
+ declare function sortContractLineItemsForInvoice(lineItems: readonly ContractLineItemRecord[]): ContractLineItemRecord[];
38
+
39
+ export { type CreateContractFromOfferOptions as C, SubscriptionContractService as S, subscriptionContractToInvoiceSnapshot as a, contractLineItemToInvoiceLineItem as c, sortContractLineItemsForInvoice as s };