@carlonicora/nextjs-jsonapi 5.4.0 → 5.6.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.
- package/dist/{BlockNoteEditor-4YCAIEPT.js → BlockNoteEditor-AE3ZTEEH.js} +20 -20
- package/dist/{BlockNoteEditor-4YCAIEPT.js.map → BlockNoteEditor-AE3ZTEEH.js.map} +1 -1
- package/dist/{BlockNoteEditor-YQL2SGFR.mjs → BlockNoteEditor-NEYG5L6W.mjs} +5 -5
- package/dist/{BlockNoteViewer-AEJKJ27Q.mjs → BlockNoteViewer-3OUT5UFY.mjs} +3 -3
- package/dist/{BlockNoteViewer-YL3J7J2Y.js → BlockNoteViewer-4CFKQM7U.js} +4 -4
- package/dist/{BlockNoteViewer-YL3J7J2Y.js.map → BlockNoteViewer-4CFKQM7U.js.map} +1 -1
- package/dist/billing/index.d.mts +186 -25
- package/dist/billing/index.d.ts +186 -25
- package/dist/billing/index.js +1149 -588
- package/dist/billing/index.js.map +1 -1
- package/dist/billing/index.mjs +786 -225
- package/dist/billing/index.mjs.map +1 -1
- package/dist/{chunk-5PPG6PL7.js → chunk-3I5AAJXV.js} +3 -3
- package/dist/{chunk-5PPG6PL7.js.map → chunk-3I5AAJXV.js.map} +1 -1
- package/dist/{chunk-YW4ZCEWB.js → chunk-53BAULDP.js} +4 -4
- package/dist/{chunk-YW4ZCEWB.js.map → chunk-53BAULDP.js.map} +1 -1
- package/dist/{chunk-XCHSX3VC.mjs → chunk-BTPUYUQ3.mjs} +2 -2
- package/dist/{chunk-WC63PJSC.mjs → chunk-EYA2F6AN.mjs} +756 -24
- package/dist/chunk-EYA2F6AN.mjs.map +1 -0
- package/dist/{chunk-NFBOSPNJ.js → chunk-HKZAESS6.js} +954 -222
- package/dist/chunk-HKZAESS6.js.map +1 -0
- package/dist/{chunk-6DC2WVVB.mjs → chunk-KQHBONL4.mjs} +2 -2
- package/dist/{chunk-3NLAXVIN.js → chunk-LQ4DK4JF.js} +1988 -1089
- package/dist/chunk-LQ4DK4JF.js.map +1 -0
- package/dist/{chunk-YNCQSWQW.js → chunk-RL3PL3KV.js} +8 -8
- package/dist/{chunk-YNCQSWQW.js.map → chunk-RL3PL3KV.js.map} +1 -1
- package/dist/{chunk-EUKTBOI2.mjs → chunk-SFYPXCK4.mjs} +3382 -2483
- package/dist/chunk-SFYPXCK4.mjs.map +1 -0
- package/dist/{chunk-QMYQRPQC.mjs → chunk-Y7RR57EW.mjs} +2 -2
- package/dist/client/index.js +5 -5
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +4 -4
- package/dist/components/editors/server.d.mts +15 -0
- package/dist/components/editors/server.d.ts +15 -0
- package/dist/components/editors/server.js +38 -0
- package/dist/components/editors/server.js.map +1 -0
- package/dist/components/editors/server.mjs +38 -0
- package/dist/components/editors/server.mjs.map +1 -0
- package/dist/components/index.d.mts +33 -10
- package/dist/components/index.d.ts +33 -10
- package/dist/components/index.js +7 -5
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +8 -6
- package/dist/contexts/index.d.mts +9 -1
- package/dist/contexts/index.d.ts +9 -1
- package/dist/contexts/index.js +5 -5
- package/dist/contexts/index.mjs +4 -4
- package/dist/core/index.d.mts +242 -3
- package/dist/core/index.d.ts +242 -3
- package/dist/core/index.js +36 -4
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.mjs +35 -3
- package/dist/email-automations/index.d.mts +3 -0
- package/dist/email-automations/index.d.ts +3 -0
- package/dist/email-automations/index.js +99 -95
- package/dist/email-automations/index.js.map +1 -1
- package/dist/email-automations/index.mjs +30 -26
- package/dist/email-automations/index.mjs.map +1 -1
- package/dist/features/analytics/index.d.mts +11 -4
- package/dist/features/analytics/index.d.ts +11 -4
- package/dist/features/analytics/index.js +127 -135
- package/dist/features/analytics/index.js.map +1 -1
- package/dist/features/analytics/index.mjs +16 -24
- package/dist/features/analytics/index.mjs.map +1 -1
- package/dist/features/analytics/server.d.mts +5 -2
- package/dist/features/analytics/server.d.ts +5 -2
- package/dist/features/analytics/server.js +7 -7
- package/dist/features/analytics/server.js.map +1 -1
- package/dist/features/analytics/server.mjs +5 -5
- package/dist/features/analytics/server.mjs.map +1 -1
- package/dist/features/blog/index.d.mts +12 -2
- package/dist/features/blog/index.d.ts +12 -2
- package/dist/features/blog/index.js +206 -195
- package/dist/features/blog/index.js.map +1 -1
- package/dist/features/blog/index.mjs +71 -60
- package/dist/features/blog/index.mjs.map +1 -1
- package/dist/features/blog/server.d.mts +4 -1
- package/dist/features/blog/server.d.ts +4 -1
- package/dist/features/blog/server.js +49 -21
- package/dist/features/blog/server.js.map +1 -1
- package/dist/features/blog/server.mjs +36 -8
- package/dist/features/blog/server.mjs.map +1 -1
- package/dist/features/help/index.js +38 -38
- package/dist/features/help/index.mjs +4 -4
- package/dist/features/tokenusage/index.d.mts +1 -3
- package/dist/features/tokenusage/index.d.ts +1 -3
- package/dist/features/tokenusage/index.js +127 -135
- package/dist/features/tokenusage/index.js.map +1 -1
- package/dist/features/tokenusage/index.mjs +10 -18
- package/dist/features/tokenusage/index.mjs.map +1 -1
- package/dist/{stripe-promotion-code.interface-C3qqh3mi.d.ts → format-options-BtX3o0Yu.d.ts} +104 -1
- package/dist/{stripe-promotion-code.interface-ClZ7DxS9.d.mts → format-options-D6c7FNDi.d.mts} +104 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +37 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -4
- package/dist/server/index.js +4 -4
- package/dist/server/index.mjs +3 -3
- package/messages/en.json +125 -3
- package/messages/it.json +125 -3
- package/package.json +9 -1
- package/scripts/validate-messages.mjs +1 -0
- package/src/billing/index.ts +1 -0
- package/src/client/index.ts +4 -0
- package/src/components/editors/server/BlockNoteServerContent.tsx +28 -0
- package/src/components/editors/server/__tests__/renderBlockNoteHTML.spec.ts +44 -0
- package/src/components/editors/server/renderBlockNoteHTML.ts +26 -0
- package/src/components/editors/server-entry.ts +7 -0
- package/src/components/index.ts +1 -0
- package/src/components/viewers/BlockNoteStaticViewer.tsx +44 -0
- package/src/core/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +3 -0
- package/src/features/administration/components/AdminIndexContainer.tsx +61 -33
- package/src/features/administration/components/__tests__/AdminIndexContainer.spec.tsx +61 -1
- package/src/features/administration/components/index.ts +2 -1
- package/src/features/administration/contexts/AdministrationContext.tsx +11 -3
- package/src/features/administration/contexts/__tests__/AdministrationContext.spec.tsx +40 -0
- package/src/features/ai-connection/ai-connection.module.ts +2 -0
- package/src/features/ai-connection/contexts/AiConnectionsContext.tsx +3 -16
- package/src/features/ai-connection/contexts/__tests__/AiConnectionsContext.spec.tsx +33 -0
- package/src/features/analytics/__tests__/server-entry.spec.tsx +2 -1
- package/src/features/analytics/analytics.modules.ts +22 -5
- package/src/features/analytics/components/AnalyticsAdminContainer.tsx +4 -3
- package/src/features/analytics/components/AnalyticsAdminPageContainer.tsx +6 -3
- package/src/features/analytics/components/AnalyticsJourneyContainer.tsx +4 -3
- package/src/features/analytics/components/__tests__/AnalyticsJourneyContainer.spec.tsx +11 -0
- package/src/features/analytics/components/__tests__/AnalyticsPageContainers.spec.tsx +12 -1
- package/src/features/analytics/components/server/AnalyticsAdminPage.tsx +6 -3
- package/src/features/analytics/contexts/AnalyticsAdminContext.tsx +8 -17
- package/src/features/analytics/contexts/__tests__/AnalyticsAdminContext.spec.tsx +17 -0
- package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +3 -2
- package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +4 -3
- package/src/features/billing/components/containers/BillingDashboardContainer.tsx +22 -5
- package/src/features/billing/components/utils/__tests__/discount.spec.ts +59 -0
- package/src/features/billing/components/utils/__tests__/url.spec.ts +32 -0
- package/src/features/billing/components/utils/discount.ts +38 -0
- package/src/features/billing/components/utils/index.ts +2 -0
- package/src/features/billing/components/utils/url.ts +12 -0
- package/src/features/billing/contexts/CouponContext.tsx +211 -0
- package/src/features/billing/contexts/index.ts +1 -0
- package/src/features/billing/i18n-keys.ts +79 -0
- package/src/features/billing/stripe-coupon/components/containers/CouponContainer.tsx +38 -0
- package/src/features/billing/stripe-coupon/components/containers/index.ts +1 -0
- package/src/features/billing/stripe-coupon/components/details/CouponDetails.tsx +69 -0
- package/src/features/billing/stripe-coupon/components/details/index.ts +1 -0
- package/src/features/billing/stripe-coupon/components/forms/CouponCodeEditor.tsx +79 -0
- package/src/features/billing/stripe-coupon/components/forms/CouponCodeFields.tsx +192 -0
- package/src/features/billing/stripe-coupon/components/forms/CouponEditor.tsx +333 -0
- package/src/features/billing/stripe-coupon/components/forms/CouponRefresher.tsx +45 -0
- package/src/features/billing/stripe-coupon/components/forms/index.ts +6 -0
- package/src/features/billing/stripe-coupon/components/index.ts +5 -0
- package/src/features/billing/stripe-coupon/components/lists/CouponCodesList.tsx +61 -0
- package/src/features/billing/stripe-coupon/components/lists/CouponsList.tsx +67 -0
- package/src/features/billing/stripe-coupon/components/lists/index.ts +2 -0
- package/src/features/billing/stripe-coupon/components/widgets/CouponCodeActions.tsx +80 -0
- package/src/features/billing/stripe-coupon/components/widgets/index.ts +1 -0
- package/src/features/billing/stripe-coupon/data/__tests__/stripe-coupon-models.spec.ts +114 -0
- package/src/features/billing/stripe-coupon/data/index.ts +10 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-code.fields.ts +8 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-code.interface.ts +44 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-code.service.ts +92 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-code.ts +132 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.interface.ts +17 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon-offer.ts +70 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon.fields.ts +7 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon.interface.ts +51 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon.service.ts +93 -0
- package/src/features/billing/stripe-coupon/data/stripe-coupon.ts +165 -0
- package/src/features/billing/stripe-coupon/hooks/useStripeCouponCodeTableStructure.tsx +154 -0
- package/src/features/billing/stripe-coupon/hooks/useStripeCouponTableStructure.tsx +113 -0
- package/src/features/billing/stripe-coupon/index.ts +5 -0
- package/src/features/billing/stripe-coupon/stripe-coupon-code.module.ts +14 -0
- package/src/features/billing/stripe-coupon/stripe-coupon-offer.module.ts +10 -0
- package/src/features/billing/stripe-coupon/stripe-coupon.module.ts +18 -0
- package/src/features/billing/stripe-coupon/utils/__tests__/coupon-places.spec.ts +19 -0
- package/src/features/billing/stripe-coupon/utils/__tests__/to-promotion-code-result.spec.ts +41 -0
- package/src/features/billing/stripe-coupon/utils/coupon-places.ts +23 -0
- package/src/features/billing/stripe-coupon/utils/format-coupon-discount.ts +36 -0
- package/src/features/billing/stripe-coupon/utils/index.ts +3 -0
- package/src/features/billing/stripe-coupon/utils/to-promotion-code-result.ts +23 -0
- package/src/features/billing/stripe-customer/components/forms/PaymentMethodForm.tsx +24 -8
- package/src/features/billing/stripe-price/stripe-price.module.ts +2 -0
- package/src/features/billing/stripe-product/components/containers/ProductsListContainer.tsx +21 -6
- package/src/features/billing/stripe-product/stripe-product.module.ts +2 -0
- package/src/features/billing/stripe-promotion-code/components/PromoCodeInput.tsx +60 -19
- package/src/features/billing/stripe-promotion-code/data/stripe-promotion-code.interface.ts +2 -0
- package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +24 -5
- package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +21 -2
- package/src/features/billing/stripe-subscription/components/wizards/SubscriptionWizard.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepPaymentMethod.tsx +1 -1
- package/src/features/billing/stripe-subscription/components/wizards/WizardStepReview.tsx +60 -49
- package/src/features/billing/stripe-subscription/components/wizards/__tests__/review-card.spec.ts +34 -0
- package/src/features/billing/stripe-subscription/components/wizards/review-card.ts +24 -0
- package/src/features/billing/stripe-subscription/data/__tests__/stripe-subscription.discount.spec.ts +67 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +14 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +39 -0
- package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +21 -0
- package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-payment.spec.ts +48 -0
- package/src/features/billing/stripe-subscription/hooks/__tests__/wizard-promotion.spec.ts +132 -0
- package/src/features/billing/stripe-subscription/hooks/useSubscriptionWizard.ts +138 -12
- package/src/features/billing/stripe-subscription/hooks/wizard-payment.ts +30 -0
- package/src/features/billing/stripe-subscription/hooks/wizard-promotion.ts +54 -0
- package/src/features/blog/components/admin/BlogAdminContainer.tsx +13 -6
- package/src/features/blog/components/admin/BlogCategoriesList.tsx +1 -1
- package/src/features/blog/components/admin/BlogCoverImageField.tsx +1 -1
- package/src/features/blog/components/admin/BlogPostContainer.tsx +0 -1
- package/src/features/blog/components/admin/BlogPostEditor.tsx +42 -33
- package/src/features/blog/components/admin/BlogPostTranslationEditor.tsx +12 -4
- package/src/features/blog/components/admin/BlogPostsList.tsx +1 -1
- package/src/features/blog/components/public/BlogPostCard.tsx +2 -9
- package/src/features/blog/components/public/BlogPostMeta.tsx +2 -2
- package/src/features/blog/components/public/BlogPostView.tsx +9 -3
- package/src/features/blog/components/public/__tests__/BlogList.spec.tsx +2 -0
- package/src/features/blog/components/public/__tests__/BlogPostView.spec.tsx +17 -11
- package/src/features/blog/server/fetchers.ts +57 -8
- package/src/features/email-automation/components/containers/EmailAutomationsListContainer.tsx +12 -3
- package/src/features/rbac/contexts/RbacContext.tsx +4 -7
- package/src/features/rbac/contexts/__tests__/RbacContext.spec.tsx +42 -0
- package/src/features/tokenusage/components/TokenUsageAdminContainer.tsx +4 -3
- package/src/features/tokenusage/contexts/TokenUsageAdminContext.tsx +3 -18
- package/src/features/tokenusage/contexts/__tests__/TokenUsageAdminContext.spec.tsx +17 -0
- package/src/features/tokenusage/tokenusage-admin.module.ts +4 -3
- package/src/features/tokenusage/tokenusage.modules.ts +12 -2
- package/src/features/user/contexts/CurrentUserContext.tsx +25 -0
- package/src/features/user/contexts/UserContext.tsx +18 -3
- package/src/features/user/contexts/__tests__/CurrentUserContext.spec.tsx +121 -2
- package/src/features/user/contexts/__tests__/UserContext.spec.tsx +95 -0
- package/dist/chunk-3NLAXVIN.js.map +0 -1
- package/dist/chunk-EUKTBOI2.mjs.map +0 -1
- package/dist/chunk-NFBOSPNJ.js.map +0 -1
- package/dist/chunk-WC63PJSC.mjs.map +0 -1
- /package/dist/{BlockNoteEditor-YQL2SGFR.mjs.map → BlockNoteEditor-NEYG5L6W.mjs.map} +0 -0
- /package/dist/{BlockNoteViewer-AEJKJ27Q.mjs.map → BlockNoteViewer-3OUT5UFY.mjs.map} +0 -0
- /package/dist/{chunk-XCHSX3VC.mjs.map → chunk-BTPUYUQ3.mjs.map} +0 -0
- /package/dist/{chunk-6DC2WVVB.mjs.map → chunk-KQHBONL4.mjs.map} +0 -0
- /package/dist/{chunk-QMYQRPQC.mjs.map → chunk-Y7RR57EW.mjs.map} +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { beforeAll, describe, expect, it } from "vitest";
|
|
2
|
+
import { DataClassRegistry } from "../../../../../core/registry/DataClassRegistry";
|
|
3
|
+
import { ModuleRegistry } from "../../../../../core/registry/ModuleRegistry";
|
|
4
|
+
import { ModuleFactory, ModuleWithPermissions } from "../../../../../permissions/types";
|
|
5
|
+
import { StripeCouponCodeModule } from "../../stripe-coupon-code.module";
|
|
6
|
+
import { StripeCouponModule } from "../../stripe-coupon.module";
|
|
7
|
+
import { StripeCouponOfferModule } from "../../stripe-coupon-offer.module";
|
|
8
|
+
import { StripeCoupon } from "../stripe-coupon";
|
|
9
|
+
import { StripeCouponCode } from "../stripe-coupon-code";
|
|
10
|
+
|
|
11
|
+
// createJsonApi reads Modules.X.name (resolved lazily via ModuleRegistry), and
|
|
12
|
+
// _readIncluded rehydrates through the registered model, so the modules must be
|
|
13
|
+
// registered first — mirrors email-automation-models.spec.
|
|
14
|
+
const moduleFactory: ModuleFactory = (params) =>
|
|
15
|
+
({
|
|
16
|
+
pageUrl: params.pageUrl,
|
|
17
|
+
name: params.name,
|
|
18
|
+
model: params.model,
|
|
19
|
+
}) as ModuleWithPermissions;
|
|
20
|
+
|
|
21
|
+
beforeAll(() => {
|
|
22
|
+
const coupon = StripeCouponModule(moduleFactory);
|
|
23
|
+
const code = StripeCouponCodeModule(moduleFactory);
|
|
24
|
+
ModuleRegistry.register("StripeCoupon", coupon);
|
|
25
|
+
ModuleRegistry.register("StripeCouponCode", code);
|
|
26
|
+
ModuleRegistry.register("StripeCouponOffer", StripeCouponOfferModule(moduleFactory));
|
|
27
|
+
// The included code is rehydrated through the class registry (normally filled by bootstrap()).
|
|
28
|
+
DataClassRegistry.registerObjectClass(coupon, StripeCoupon);
|
|
29
|
+
DataClassRegistry.registerObjectClass(code, StripeCouponCode);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("stripe coupon models", () => {
|
|
33
|
+
it("rehydrates redeemBy into a Date and reads the included codes", () => {
|
|
34
|
+
const coupon = new StripeCoupon().rehydrate({
|
|
35
|
+
jsonApi: {
|
|
36
|
+
id: "co-1",
|
|
37
|
+
type: "stripe-coupons",
|
|
38
|
+
attributes: {
|
|
39
|
+
stripeCouponId: "co_1",
|
|
40
|
+
name: "Founding GM",
|
|
41
|
+
discountType: "percent_off",
|
|
42
|
+
percentOff: 20,
|
|
43
|
+
duration: "forever",
|
|
44
|
+
redeemBy: "2027-01-01T00:00:00.000Z",
|
|
45
|
+
maxRedemptions: 50,
|
|
46
|
+
timesRedeemed: 13,
|
|
47
|
+
valid: true,
|
|
48
|
+
},
|
|
49
|
+
relationships: { codes: { data: [{ type: "stripe-coupon-codes", id: "cc-1" }] } },
|
|
50
|
+
},
|
|
51
|
+
included: [
|
|
52
|
+
{
|
|
53
|
+
id: "cc-1",
|
|
54
|
+
type: "stripe-coupon-codes",
|
|
55
|
+
attributes: {
|
|
56
|
+
stripePromotionCodeId: "promo_1",
|
|
57
|
+
code: "FOUNDER",
|
|
58
|
+
active: true,
|
|
59
|
+
automatic: true,
|
|
60
|
+
expiresAt: "2027-02-01T00:00:00.000Z",
|
|
61
|
+
timesRedeemed: 13,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
} as any);
|
|
66
|
+
|
|
67
|
+
expect(coupon.redeemBy).toBeInstanceOf(Date);
|
|
68
|
+
expect(coupon.redeemBy?.toISOString()).toBe("2027-01-01T00:00:00.000Z");
|
|
69
|
+
expect(coupon.codes.length).toBe(1);
|
|
70
|
+
expect(coupon.codes[0].code).toBe("FOUNDER");
|
|
71
|
+
expect(coupon.codes[0].expiresAt).toBeInstanceOf(Date);
|
|
72
|
+
expect(coupon.timesRedeemed).toBe(13);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("serialises the datetimes of the coupon and its first code as ISO strings", () => {
|
|
76
|
+
const body = new StripeCoupon().createJsonApi({
|
|
77
|
+
id: "co-1",
|
|
78
|
+
name: "Founding GM",
|
|
79
|
+
discountType: "percent_off",
|
|
80
|
+
percentOff: 20,
|
|
81
|
+
duration: "forever",
|
|
82
|
+
productIds: ["p1"],
|
|
83
|
+
redeemBy: new Date("2027-01-01T00:00:00.000Z"),
|
|
84
|
+
maxRedemptions: 50,
|
|
85
|
+
firstCode: { code: "FOUNDER", automatic: true, expiresAt: new Date("2027-02-01T00:00:00.000Z") },
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
expect(body.data.type).toBe("stripe-coupons");
|
|
89
|
+
expect(body.data.attributes.redeemBy).toBe("2027-01-01T00:00:00.000Z");
|
|
90
|
+
expect(body.data.attributes.firstCode.expiresAt).toBe("2027-02-01T00:00:00.000Z");
|
|
91
|
+
expect(body.data.attributes.firstCode.automatic).toBe(true);
|
|
92
|
+
expect(body.data.attributes.productIds).toEqual(["p1"]);
|
|
93
|
+
expect("amountOff" in body.data.attributes).toBe(false);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("builds the rename body with the name only", () => {
|
|
97
|
+
expect(new StripeCoupon().createRenameJsonApi({ id: "co-1", name: "Renamed" })).toEqual({
|
|
98
|
+
data: { type: "stripe-coupons", id: "co-1", attributes: { name: "Renamed" } },
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("writes the code's coupon relationship", () => {
|
|
103
|
+
const body = new StripeCouponCode().createJsonApi({ id: "c1", couponId: "co-1", code: "SPRING" });
|
|
104
|
+
expect(body.data.type).toBe("stripe-coupon-codes");
|
|
105
|
+
expect(body.data.attributes).toEqual({ code: "SPRING" });
|
|
106
|
+
expect(body.data.relationships.coupon).toEqual({ data: { type: "stripe-coupons", id: "co-1" } });
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("builds the flags body with only the flags that are set", () => {
|
|
110
|
+
const body = new StripeCouponCode().createFlagsJsonApi({ id: "c1", automatic: true });
|
|
111
|
+
expect(body).toEqual({ data: { type: "stripe-coupon-codes", id: "c1", attributes: { automatic: true } } });
|
|
112
|
+
expect("active" in body.data.attributes).toBe(false);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./stripe-coupon";
|
|
2
|
+
export * from "./stripe-coupon.fields";
|
|
3
|
+
export * from "./stripe-coupon.interface";
|
|
4
|
+
export * from "./stripe-coupon.service";
|
|
5
|
+
export * from "./stripe-coupon-code";
|
|
6
|
+
export * from "./stripe-coupon-code.fields";
|
|
7
|
+
export * from "./stripe-coupon-code.interface";
|
|
8
|
+
export * from "./stripe-coupon-code.service";
|
|
9
|
+
export * from "./stripe-coupon-offer";
|
|
10
|
+
export * from "./stripe-coupon-offer.interface";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ApiDataInterface } from "../../../../core";
|
|
2
|
+
import { StripeCouponInterface } from "./stripe-coupon.interface";
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Stripe Coupon Code Interfaces (a customer-facing promotion code of a coupon)
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
export interface StripeCouponCodeInterface extends ApiDataInterface {
|
|
9
|
+
get stripePromotionCodeId(): string;
|
|
10
|
+
get code(): string;
|
|
11
|
+
get active(): boolean;
|
|
12
|
+
get automatic(): boolean;
|
|
13
|
+
get firstTimeTransaction(): boolean;
|
|
14
|
+
get minimumAmount(): number | undefined; // minor units
|
|
15
|
+
get minimumAmountCurrency(): string | undefined;
|
|
16
|
+
get stripeCustomerId(): string | undefined;
|
|
17
|
+
get expiresAt(): Date | undefined;
|
|
18
|
+
get maxRedemptions(): number | undefined;
|
|
19
|
+
get timesRedeemed(): number;
|
|
20
|
+
get coupon(): StripeCouponInterface | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Stripe Coupon Code Input DTOs
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export type StripeCouponCodeInput = {
|
|
28
|
+
id: string;
|
|
29
|
+
couponId: string;
|
|
30
|
+
code?: string;
|
|
31
|
+
firstTimeTransaction?: boolean;
|
|
32
|
+
minimumAmount?: number;
|
|
33
|
+
minimumAmountCurrency?: string;
|
|
34
|
+
stripeCustomerId?: string;
|
|
35
|
+
expiresAt?: Date;
|
|
36
|
+
maxRedemptions?: number;
|
|
37
|
+
automatic?: boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type StripeCouponCodeFlagsInput = {
|
|
41
|
+
id: string;
|
|
42
|
+
active?: boolean;
|
|
43
|
+
automatic?: boolean;
|
|
44
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef, PreviousRef } from "../../../../core";
|
|
2
|
+
import { STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT } from "../stripe-coupon-code.module";
|
|
3
|
+
import { StripeCouponCode } from "./stripe-coupon-code";
|
|
4
|
+
import {
|
|
5
|
+
StripeCouponCodeFlagsInput,
|
|
6
|
+
StripeCouponCodeInput,
|
|
7
|
+
StripeCouponCodeInterface,
|
|
8
|
+
} from "./stripe-coupon-code.interface";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Billing service for the customer-facing codes of a coupon
|
|
12
|
+
*/
|
|
13
|
+
export class StripeCouponCodeService extends AbstractService {
|
|
14
|
+
/**
|
|
15
|
+
* List the codes of a coupon (admin)
|
|
16
|
+
*/
|
|
17
|
+
static async listByCoupon(params: {
|
|
18
|
+
couponId: string;
|
|
19
|
+
next?: NextRef;
|
|
20
|
+
prev?: PreviousRef;
|
|
21
|
+
}): Promise<StripeCouponCodeInterface[]> {
|
|
22
|
+
const endpoint = new EndpointCreator({
|
|
23
|
+
endpoint: Modules.StripeCoupon,
|
|
24
|
+
id: params.couponId,
|
|
25
|
+
childEndpoint: Modules.StripeCouponCode,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return this.callApi({
|
|
29
|
+
type: Modules.StripeCouponCode,
|
|
30
|
+
method: HttpMethod.GET,
|
|
31
|
+
endpoint: endpoint.generate(),
|
|
32
|
+
next: params.next,
|
|
33
|
+
previous: params.prev,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Create a code on an existing coupon (admin)
|
|
39
|
+
*/
|
|
40
|
+
static async createCode(params: StripeCouponCodeInput): Promise<StripeCouponCodeInterface> {
|
|
41
|
+
const endpoint = new EndpointCreator({
|
|
42
|
+
endpoint: Modules.StripeCouponCode,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return this.callApi<StripeCouponCodeInterface>({
|
|
46
|
+
type: Modules.StripeCouponCode,
|
|
47
|
+
method: HttpMethod.POST,
|
|
48
|
+
endpoint: endpoint.generate(),
|
|
49
|
+
input: params,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Switch "Apply automatically" and / or deactivate / reactivate a code (admin)
|
|
55
|
+
*/
|
|
56
|
+
static async updateFlags(params: StripeCouponCodeFlagsInput): Promise<StripeCouponCodeInterface> {
|
|
57
|
+
const endpoint = new EndpointCreator({
|
|
58
|
+
endpoint: Modules.StripeCouponCode,
|
|
59
|
+
id: params.id,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return this.callApi<StripeCouponCodeInterface>({
|
|
63
|
+
type: Modules.StripeCouponCode,
|
|
64
|
+
method: HttpMethod.PATCH,
|
|
65
|
+
endpoint: endpoint.generate(),
|
|
66
|
+
input: new StripeCouponCode().createFlagsJsonApi(params),
|
|
67
|
+
overridesJsonApiCreation: true,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The code the server would apply automatically for this price at a first
|
|
73
|
+
* payment, or null when none applies (logged-in company administrator)
|
|
74
|
+
*/
|
|
75
|
+
static async findAutomatic(params: { priceId: string }): Promise<StripeCouponCodeInterface | null> {
|
|
76
|
+
const endpoint = new EndpointCreator({
|
|
77
|
+
endpoint: Modules.StripeCouponCode,
|
|
78
|
+
id: STRIPE_COUPON_CODE_AUTOMATIC_SEGMENT,
|
|
79
|
+
});
|
|
80
|
+
endpoint.addAdditionalParam("priceId", params.priceId);
|
|
81
|
+
|
|
82
|
+
const codes = await this.callApi<StripeCouponCodeInterface[]>({
|
|
83
|
+
type: Modules.StripeCouponCode,
|
|
84
|
+
method: HttpMethod.GET,
|
|
85
|
+
endpoint: endpoint.generate(),
|
|
86
|
+
// A failed lookup must reach the wizard, which then refuses to show full price as the truth
|
|
87
|
+
suppressGlobalError: true,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
return codes?.[0] ?? null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { AbstractApiData, JsonApiHydratedDataInterface, Modules } from "../../../../core";
|
|
2
|
+
import {
|
|
3
|
+
StripeCouponCodeFlagsInput,
|
|
4
|
+
StripeCouponCodeInput,
|
|
5
|
+
StripeCouponCodeInterface,
|
|
6
|
+
} from "./stripe-coupon-code.interface";
|
|
7
|
+
import { StripeCouponInterface } from "./stripe-coupon.interface";
|
|
8
|
+
import { StripeCoupon } from "./stripe-coupon";
|
|
9
|
+
|
|
10
|
+
export class StripeCouponCode extends AbstractApiData implements StripeCouponCodeInterface {
|
|
11
|
+
private _stripePromotionCodeId?: string;
|
|
12
|
+
private _code: string = "";
|
|
13
|
+
private _active: boolean = true;
|
|
14
|
+
private _automatic: boolean = false;
|
|
15
|
+
private _firstTimeTransaction: boolean = false;
|
|
16
|
+
private _minimumAmount?: number;
|
|
17
|
+
private _minimumAmountCurrency?: string;
|
|
18
|
+
private _stripeCustomerId?: string;
|
|
19
|
+
private _expiresAt?: Date;
|
|
20
|
+
private _maxRedemptions?: number;
|
|
21
|
+
private _timesRedeemed: number = 0;
|
|
22
|
+
private _coupon?: StripeCouponInterface;
|
|
23
|
+
|
|
24
|
+
get stripePromotionCodeId(): string {
|
|
25
|
+
if (!this._stripePromotionCodeId) throw new Error("stripePromotionCodeId is not defined");
|
|
26
|
+
return this._stripePromotionCodeId;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get code(): string {
|
|
30
|
+
return this._code;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get active(): boolean {
|
|
34
|
+
return this._active;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
get automatic(): boolean {
|
|
38
|
+
return this._automatic;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
get firstTimeTransaction(): boolean {
|
|
42
|
+
return this._firstTimeTransaction;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get minimumAmount(): number | undefined {
|
|
46
|
+
return this._minimumAmount;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
get minimumAmountCurrency(): string | undefined {
|
|
50
|
+
return this._minimumAmountCurrency;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
get stripeCustomerId(): string | undefined {
|
|
54
|
+
return this._stripeCustomerId;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
get expiresAt(): Date | undefined {
|
|
58
|
+
return this._expiresAt;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
get maxRedemptions(): number | undefined {
|
|
62
|
+
return this._maxRedemptions;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
get timesRedeemed(): number {
|
|
66
|
+
return this._timesRedeemed;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get coupon(): StripeCouponInterface | undefined {
|
|
70
|
+
return this._coupon;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
rehydrate(data: JsonApiHydratedDataInterface): this {
|
|
74
|
+
super.rehydrate(data);
|
|
75
|
+
|
|
76
|
+
const attributes = data.jsonApi.attributes;
|
|
77
|
+
|
|
78
|
+
this._stripePromotionCodeId = attributes.stripePromotionCodeId;
|
|
79
|
+
this._code = attributes.code ?? "";
|
|
80
|
+
this._active = attributes.active ?? true;
|
|
81
|
+
this._automatic = attributes.automatic ?? false;
|
|
82
|
+
this._firstTimeTransaction = attributes.firstTimeTransaction ?? false;
|
|
83
|
+
this._minimumAmount = attributes.minimumAmount ?? undefined;
|
|
84
|
+
this._minimumAmountCurrency = attributes.minimumAmountCurrency ?? undefined;
|
|
85
|
+
this._stripeCustomerId = attributes.stripeCustomerId ?? undefined;
|
|
86
|
+
this._expiresAt = attributes.expiresAt ? new Date(attributes.expiresAt) : undefined;
|
|
87
|
+
this._maxRedemptions = attributes.maxRedemptions ?? undefined;
|
|
88
|
+
this._timesRedeemed = attributes.timesRedeemed ?? 0;
|
|
89
|
+
|
|
90
|
+
this._coupon = this._readIncluded(data, "coupon", Modules.StripeCoupon) as StripeCouponInterface | undefined;
|
|
91
|
+
|
|
92
|
+
return this;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
createJsonApi(data: StripeCouponCodeInput): any {
|
|
96
|
+
const { id, couponId, ...code } = data;
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
data: {
|
|
100
|
+
type: Modules.StripeCouponCode.name,
|
|
101
|
+
id,
|
|
102
|
+
attributes: StripeCoupon.codeAttributes(code),
|
|
103
|
+
relationships: {
|
|
104
|
+
coupon: {
|
|
105
|
+
data: {
|
|
106
|
+
type: Modules.StripeCoupon.name,
|
|
107
|
+
id: couponId,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* PATCH body for the flags a code can still change after creation.
|
|
117
|
+
* Only the flags that are set are sent, so switching one never touches the other.
|
|
118
|
+
*/
|
|
119
|
+
createFlagsJsonApi(data: StripeCouponCodeFlagsInput): any {
|
|
120
|
+
const attributes: Record<string, boolean> = {};
|
|
121
|
+
if (data.active !== undefined) attributes.active = data.active;
|
|
122
|
+
if (data.automatic !== undefined) attributes.automatic = data.automatic;
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
data: {
|
|
126
|
+
type: Modules.StripeCouponCode.name,
|
|
127
|
+
id: data.id,
|
|
128
|
+
attributes,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ApiDataInterface } from "../../../../core";
|
|
2
|
+
import { StripeCouponDiscountType, StripeCouponDurationType } from "./stripe-coupon.interface";
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Stripe Coupon Offer Interface (public, synthetic: the automatic code's places left)
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
export interface StripeCouponOfferInterface extends ApiDataInterface {
|
|
9
|
+
get discountType(): StripeCouponDiscountType;
|
|
10
|
+
get percentOff(): number | undefined;
|
|
11
|
+
get amountOff(): number | undefined; // minor units
|
|
12
|
+
get currency(): string | undefined;
|
|
13
|
+
get duration(): StripeCouponDurationType;
|
|
14
|
+
get durationInMonths(): number | undefined;
|
|
15
|
+
get placesLeft(): number;
|
|
16
|
+
get placesTotal(): number;
|
|
17
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { AbstractApiData, JsonApiHydratedDataInterface } from "../../../../core";
|
|
2
|
+
import { StripeCouponOfferInterface } from "./stripe-coupon-offer.interface";
|
|
3
|
+
import { StripeCouponDiscountType, StripeCouponDurationType } from "./stripe-coupon.interface";
|
|
4
|
+
|
|
5
|
+
/** Read-only public resource: never created or updated from the frontend. */
|
|
6
|
+
export class StripeCouponOffer extends AbstractApiData implements StripeCouponOfferInterface {
|
|
7
|
+
private _discountType?: StripeCouponDiscountType;
|
|
8
|
+
private _percentOff?: number;
|
|
9
|
+
private _amountOff?: number;
|
|
10
|
+
private _currency?: string;
|
|
11
|
+
private _duration?: StripeCouponDurationType;
|
|
12
|
+
private _durationInMonths?: number;
|
|
13
|
+
private _placesLeft: number = 0;
|
|
14
|
+
private _placesTotal: number = 0;
|
|
15
|
+
|
|
16
|
+
get discountType(): StripeCouponDiscountType {
|
|
17
|
+
if (!this._discountType) throw new Error("discountType is not defined");
|
|
18
|
+
return this._discountType;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
get percentOff(): number | undefined {
|
|
22
|
+
return this._percentOff;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get amountOff(): number | undefined {
|
|
26
|
+
return this._amountOff;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get currency(): string | undefined {
|
|
30
|
+
return this._currency;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get duration(): StripeCouponDurationType {
|
|
34
|
+
if (!this._duration) throw new Error("duration is not defined");
|
|
35
|
+
return this._duration;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
get durationInMonths(): number | undefined {
|
|
39
|
+
return this._durationInMonths;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
get placesLeft(): number {
|
|
43
|
+
return this._placesLeft;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get placesTotal(): number {
|
|
47
|
+
return this._placesTotal;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
rehydrate(data: JsonApiHydratedDataInterface): this {
|
|
51
|
+
super.rehydrate(data);
|
|
52
|
+
|
|
53
|
+
const attributes = data.jsonApi.attributes;
|
|
54
|
+
|
|
55
|
+
this._discountType = attributes.discountType;
|
|
56
|
+
this._percentOff = attributes.percentOff ?? undefined;
|
|
57
|
+
this._amountOff = attributes.amountOff ?? undefined;
|
|
58
|
+
this._currency = attributes.currency ?? undefined;
|
|
59
|
+
this._duration = attributes.duration;
|
|
60
|
+
this._durationInMonths = attributes.durationInMonths ?? undefined;
|
|
61
|
+
this._placesLeft = attributes.placesLeft ?? 0;
|
|
62
|
+
this._placesTotal = attributes.placesTotal ?? 0;
|
|
63
|
+
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
createJsonApi(_data?: any): any {
|
|
68
|
+
throw new Error("StripeCouponOffer is declared by the API and is read-only");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ApiDataInterface } from "../../../../core";
|
|
2
|
+
import { StripeCouponCodeInput, StripeCouponCodeInterface } from "./stripe-coupon-code.interface";
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// Stripe Coupon Interfaces
|
|
6
|
+
// ============================================================================
|
|
7
|
+
|
|
8
|
+
export type StripeCouponDiscountType = "percent_off" | "amount_off";
|
|
9
|
+
export type StripeCouponDurationType = "once" | "repeating" | "forever";
|
|
10
|
+
|
|
11
|
+
export interface StripeCouponInterface extends ApiDataInterface {
|
|
12
|
+
get stripeCouponId(): string;
|
|
13
|
+
get name(): string;
|
|
14
|
+
get discountType(): StripeCouponDiscountType;
|
|
15
|
+
get percentOff(): number | undefined;
|
|
16
|
+
get amountOff(): number | undefined; // minor units (cents)
|
|
17
|
+
get currency(): string | undefined;
|
|
18
|
+
get duration(): StripeCouponDurationType;
|
|
19
|
+
get durationInMonths(): number | undefined;
|
|
20
|
+
get stripeProductIds(): string[]; // empty = every product
|
|
21
|
+
get redeemBy(): Date | undefined;
|
|
22
|
+
get maxRedemptions(): number | undefined;
|
|
23
|
+
get timesRedeemed(): number;
|
|
24
|
+
get valid(): boolean;
|
|
25
|
+
get codes(): StripeCouponCodeInterface[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Stripe Coupon Input DTOs
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
export type StripeCouponInput = {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
stripeCouponId?: string;
|
|
36
|
+
discountType: StripeCouponDiscountType;
|
|
37
|
+
percentOff?: number;
|
|
38
|
+
amountOff?: number;
|
|
39
|
+
currency?: string;
|
|
40
|
+
duration: StripeCouponDurationType;
|
|
41
|
+
durationInMonths?: number;
|
|
42
|
+
productIds?: string[]; // our StripeProduct ids
|
|
43
|
+
redeemBy?: Date;
|
|
44
|
+
maxRedemptions?: number;
|
|
45
|
+
firstCode: Omit<StripeCouponCodeInput, "id" | "couponId">;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type StripeCouponRenameInput = {
|
|
49
|
+
id: string;
|
|
50
|
+
name: string;
|
|
51
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef, PreviousRef } from "../../../../core";
|
|
2
|
+
import { STRIPE_COUPON_REFRESH_SEGMENT } from "../stripe-coupon.module";
|
|
3
|
+
import { StripeCoupon } from "./stripe-coupon";
|
|
4
|
+
import { StripeCouponInput, StripeCouponInterface, StripeCouponRenameInput } from "./stripe-coupon.interface";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Admin billing service for managing coupons
|
|
8
|
+
*/
|
|
9
|
+
export class StripeCouponService extends AbstractService {
|
|
10
|
+
/**
|
|
11
|
+
* List all coupons with their codes (admin)
|
|
12
|
+
*/
|
|
13
|
+
static async listCoupons(params?: { next?: NextRef; prev?: PreviousRef }): Promise<StripeCouponInterface[]> {
|
|
14
|
+
const endpoint = new EndpointCreator({
|
|
15
|
+
endpoint: Modules.StripeCoupon,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return this.callApi({
|
|
19
|
+
type: Modules.StripeCoupon,
|
|
20
|
+
method: HttpMethod.GET,
|
|
21
|
+
endpoint: endpoint.generate(),
|
|
22
|
+
next: params?.next,
|
|
23
|
+
previous: params?.prev,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get a specific coupon by ID (admin)
|
|
29
|
+
*/
|
|
30
|
+
static async getCoupon(params: { id: string }): Promise<StripeCouponInterface> {
|
|
31
|
+
const endpoint = new EndpointCreator({
|
|
32
|
+
endpoint: Modules.StripeCoupon,
|
|
33
|
+
id: params.id,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
return this.callApi<StripeCouponInterface>({
|
|
37
|
+
type: Modules.StripeCoupon,
|
|
38
|
+
method: HttpMethod.GET,
|
|
39
|
+
endpoint: endpoint.generate(),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a coupon and its first code (admin)
|
|
45
|
+
*/
|
|
46
|
+
static async createCoupon(params: StripeCouponInput): Promise<StripeCouponInterface> {
|
|
47
|
+
const endpoint = new EndpointCreator({
|
|
48
|
+
endpoint: Modules.StripeCoupon,
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return this.callApi<StripeCouponInterface>({
|
|
52
|
+
type: Modules.StripeCoupon,
|
|
53
|
+
method: HttpMethod.POST,
|
|
54
|
+
endpoint: endpoint.generate(),
|
|
55
|
+
input: params,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Rename a coupon (admin). The only coupon field Stripe allows to change.
|
|
61
|
+
*/
|
|
62
|
+
static async renameCoupon(params: StripeCouponRenameInput): Promise<StripeCouponInterface> {
|
|
63
|
+
const endpoint = new EndpointCreator({
|
|
64
|
+
endpoint: Modules.StripeCoupon,
|
|
65
|
+
id: params.id,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
return this.callApi<StripeCouponInterface>({
|
|
69
|
+
type: Modules.StripeCoupon,
|
|
70
|
+
method: HttpMethod.PATCH,
|
|
71
|
+
endpoint: endpoint.generate(),
|
|
72
|
+
input: new StripeCoupon().createRenameJsonApi(params),
|
|
73
|
+
overridesJsonApiCreation: true,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Re-read the coupon and its codes from Stripe and store the counts (admin)
|
|
79
|
+
*/
|
|
80
|
+
static async refreshCounts(params: { id: string }): Promise<StripeCouponInterface> {
|
|
81
|
+
const endpoint = new EndpointCreator({
|
|
82
|
+
endpoint: Modules.StripeCoupon,
|
|
83
|
+
id: params.id,
|
|
84
|
+
childEndpoint: STRIPE_COUPON_REFRESH_SEGMENT,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
return this.callApi<StripeCouponInterface>({
|
|
88
|
+
type: Modules.StripeCoupon,
|
|
89
|
+
method: HttpMethod.POST,
|
|
90
|
+
endpoint: endpoint.generate(),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|