@reorderjs/reorder 1.0.8 → 1.1.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 (65) hide show
  1. package/.medusa/server/e2e/auth.setup.js +26 -0
  2. package/.medusa/server/e2e/cancellation-retention.spec.js +133 -0
  3. package/.medusa/server/e2e/pages/CancellationCaseDetailPage.js +69 -0
  4. package/.medusa/server/e2e/pages/CancellationsListPage.js +34 -0
  5. package/.medusa/server/e2e/pages/PlanFormPage.js +89 -0
  6. package/.medusa/server/e2e/pages/RenewalDetailPage.js +101 -0
  7. package/.medusa/server/e2e/pages/SubscriptionDetailPage.js +102 -0
  8. package/.medusa/server/e2e/plans-offers.spec.js +96 -0
  9. package/.medusa/server/e2e/renewal-force.spec.js +154 -0
  10. package/.medusa/server/e2e/seed.setup.js +80 -0
  11. package/.medusa/server/e2e/subscription-status.spec.js +109 -0
  12. package/.medusa/server/e2e/subscriptions-list.spec.js +84 -0
  13. package/.medusa/server/playwright.config.js +37 -0
  14. package/.medusa/server/scripts/reset-subscriptions-test-data.js +279 -0
  15. package/.medusa/server/scripts/seed-subscriptions-test-data.js +2425 -0
  16. package/.medusa/server/scripts/wipe-test-data.js +44 -0
  17. package/.medusa/server/src/admin/index.js +11106 -9689
  18. package/.medusa/server/src/admin/index.mjs +11099 -9682
  19. package/.medusa/server/src/admin/types/analytics.js +2 -1
  20. package/.medusa/server/src/api/admin/cancellations/validators.js +2 -2
  21. package/.medusa/server/src/api/admin/dunning/validators.js +2 -2
  22. package/.medusa/server/src/api/admin/renewals/validators.js +2 -2
  23. package/.medusa/server/src/api/admin/subscription-analytics/validators.js +2 -2
  24. package/.medusa/server/src/api/admin/subscription-logs/validators.js +2 -2
  25. package/.medusa/server/src/api/admin/subscription-offers/validators.js +2 -2
  26. package/.medusa/server/src/api/admin/subscription-settings/validators.js +2 -2
  27. package/.medusa/server/src/api/admin/subscriptions/[id]/payment-method/route.js +19 -0
  28. package/.medusa/server/src/api/admin/subscriptions/[id]/payment-methods/route.js +10 -0
  29. package/.medusa/server/src/api/admin/subscriptions/middlewares.js +8 -1
  30. package/.medusa/server/src/api/admin/subscriptions/utils.js +5 -1
  31. package/.medusa/server/src/api/admin/subscriptions/validators.js +7 -3
  32. package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-method/route.js +26 -0
  33. package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-methods/route.js +15 -0
  34. package/.medusa/server/src/api/store/customers/me/subscriptions/middlewares.js +8 -1
  35. package/.medusa/server/src/api/store/customers/me/subscriptions/utils.js +72 -1
  36. package/.medusa/server/src/api/store/customers/me/subscriptions/validators.js +7 -3
  37. package/.medusa/server/src/api/store/products/validators.js +2 -2
  38. package/.medusa/server/src/modules/activity-log/__tests__/create-subscription-log-event.spec.js +257 -0
  39. package/.medusa/server/src/modules/activity-log/__tests__/normalize-log-event.spec.js +231 -0
  40. package/.medusa/server/src/modules/activity-log/migrations/Migration20260818120000.js +16 -0
  41. package/.medusa/server/src/modules/activity-log/types/index.js +2 -1
  42. package/.medusa/server/src/modules/analytics/__tests__/admin-query.spec.js +560 -0
  43. package/.medusa/server/src/modules/analytics/index.js +2 -2
  44. package/.medusa/server/src/modules/analytics/utils/admin-query.js +157 -5
  45. package/.medusa/server/src/modules/plan-offer/__tests__/service.spec.js +94 -0
  46. package/.medusa/server/src/modules/renewal/__tests__/service.spec.js +89 -0
  47. package/.medusa/server/src/modules/settings/__tests__/normalize-settings.spec.js +86 -0
  48. package/.medusa/server/src/modules/settings/__tests__/service.spec.js +124 -0
  49. package/.medusa/server/src/modules/subscription/__tests__/payment-methods.spec.js +186 -0
  50. package/.medusa/server/src/modules/subscription/__tests__/service.spec.js +124 -0
  51. package/.medusa/server/src/modules/subscription/utils/admin-query.js +196 -14
  52. package/.medusa/server/src/modules/subscription/utils/payment-methods.js +146 -0
  53. package/.medusa/server/src/workflows/__tests__/cancel-subscription.spec.js +20 -0
  54. package/.medusa/server/src/workflows/__tests__/pause-subscription.spec.js +20 -0
  55. package/.medusa/server/src/workflows/__tests__/update-subscription-shipping-address.spec.js +49 -0
  56. package/.medusa/server/src/workflows/cancel-subscription.js +21 -1
  57. package/.medusa/server/src/workflows/index.js +6 -2
  58. package/.medusa/server/src/workflows/pause-subscription.js +21 -1
  59. package/.medusa/server/src/workflows/steps/rebuild-analytics-daily-snapshots.js +33 -10
  60. package/.medusa/server/src/workflows/steps/update-subscription-payment-method.js +110 -0
  61. package/.medusa/server/src/workflows/steps/validate-subscription-cart.js +7 -22
  62. package/.medusa/server/src/workflows/update-subscription-payment-method.js +65 -0
  63. package/.medusa/server/src/workflows/utils/analytics-incremental.js +1 -1
  64. package/README.md +89 -36
  65. package/package.json +25 -23
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ const normalize_settings_1 = require("../utils/normalize-settings");
5
+ const types_1 = require("../types");
6
+ describe("settings normalize-settings", () => {
7
+ it("builds default fallback settings", () => {
8
+ const defaults = (0, normalize_settings_1.buildDefaultSubscriptionSettings)();
9
+ expect(defaults).toMatchObject({
10
+ settings_key: "global",
11
+ default_trial_days: 0,
12
+ dunning_retry_intervals: [1440, 4320, 10080],
13
+ max_dunning_attempts: 3,
14
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.PROCESS_IMMEDIATELY,
15
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.RECOMMEND_RETENTION_FIRST,
16
+ version: 0,
17
+ updated_by: null,
18
+ updated_at: null,
19
+ metadata: null,
20
+ is_persisted: false,
21
+ });
22
+ });
23
+ it("normalizes retry intervals and infers max attempts when omitted", () => {
24
+ const normalized = (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
25
+ dunning_retry_intervals: [60, 180, 360],
26
+ updated_by: "admin_user",
27
+ });
28
+ expect(normalized).toMatchObject({
29
+ dunning_retry_intervals: [60, 180, 360],
30
+ max_dunning_attempts: 3,
31
+ updated_by: "admin_user",
32
+ metadata: null,
33
+ });
34
+ });
35
+ it("accepts an explicit valid settings payload", () => {
36
+ const normalized = (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
37
+ default_trial_days: 14,
38
+ dunning_retry_intervals: [1440, 2880],
39
+ max_dunning_attempts: 2,
40
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.REQUIRE_REVIEW_FOR_PENDING_CHANGES,
41
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.ALLOW_DIRECT_CANCELLATION,
42
+ updated_by: "admin_user",
43
+ metadata: {
44
+ source: "module-test",
45
+ },
46
+ });
47
+ expect(normalized).toMatchObject({
48
+ default_trial_days: 14,
49
+ dunning_retry_intervals: [1440, 2880],
50
+ max_dunning_attempts: 2,
51
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.REQUIRE_REVIEW_FOR_PENDING_CHANGES,
52
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.ALLOW_DIRECT_CANCELLATION,
53
+ updated_by: "admin_user",
54
+ metadata: {
55
+ source: "module-test",
56
+ },
57
+ });
58
+ });
59
+ it("rejects invalid default_trial_days", () => {
60
+ expect(() => (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
61
+ default_trial_days: -1,
62
+ })).toThrow(new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "'default_trial_days' must be greater than or equal to 0"));
63
+ });
64
+ it("rejects invalid max_dunning_attempts", () => {
65
+ expect(() => (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
66
+ max_dunning_attempts: 0,
67
+ })).toThrow(new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "'max_dunning_attempts' must be greater than 0"));
68
+ });
69
+ it("rejects non-positive retry intervals", () => {
70
+ expect(() => (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
71
+ dunning_retry_intervals: [60, 0, 180],
72
+ })).toThrow(new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "'dunning_retry_intervals' must contain positive values only"));
73
+ });
74
+ it("rejects retry intervals that are not strictly increasing", () => {
75
+ expect(() => (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
76
+ dunning_retry_intervals: [60, 60, 180],
77
+ })).toThrow(new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "'dunning_retry_intervals' must be strictly increasing without duplicates"));
78
+ });
79
+ it("rejects mismatch between max attempts and retry interval length", () => {
80
+ expect(() => (0, normalize_settings_1.normalizeSubscriptionSettingsPayload)({
81
+ dunning_retry_intervals: [60, 180, 360],
82
+ max_dunning_attempts: 2,
83
+ })).toThrow(new utils_1.MedusaError(utils_1.MedusaError.Types.INVALID_DATA, "'max_dunning_attempts' must match the number of 'dunning_retry_intervals'"));
84
+ });
85
+ });
86
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9ybWFsaXplLXNldHRpbmdzLnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9zZXR0aW5ncy9fX3Rlc3RzX18vbm9ybWFsaXplLXNldHRpbmdzLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBdUQ7QUFDdkQsb0VBR29DO0FBQ3BDLG9DQUdpQjtBQUVqQixRQUFRLENBQUMsNkJBQTZCLEVBQUUsR0FBRyxFQUFFO0lBQzNDLEVBQUUsQ0FBQyxrQ0FBa0MsRUFBRSxHQUFHLEVBQUU7UUFDMUMsTUFBTSxRQUFRLEdBQUcsSUFBQSxxREFBZ0MsR0FBRSxDQUFBO1FBRW5ELE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxhQUFhLENBQUM7WUFDN0IsWUFBWSxFQUFFLFFBQVE7WUFDdEIsa0JBQWtCLEVBQUUsQ0FBQztZQUNyQix1QkFBdUIsRUFBRSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDO1lBQzVDLG9CQUFvQixFQUFFLENBQUM7WUFDdkIsd0JBQXdCLEVBQ3RCLG1DQUEyQixDQUFDLG1CQUFtQjtZQUNqRCw2QkFBNkIsRUFDM0Isd0NBQWdDLENBQUMseUJBQXlCO1lBQzVELE9BQU8sRUFBRSxDQUFDO1lBQ1YsVUFBVSxFQUFFLElBQUk7WUFDaEIsVUFBVSxFQUFFLElBQUk7WUFDaEIsUUFBUSxFQUFFLElBQUk7WUFDZCxZQUFZLEVBQUUsS0FBSztTQUNwQixDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyxpRUFBaUUsRUFBRSxHQUFHLEVBQUU7UUFDekUsTUFBTSxVQUFVLEdBQUcsSUFBQSx5REFBb0MsRUFBQztZQUN0RCx1QkFBdUIsRUFBRSxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDO1lBQ3ZDLFVBQVUsRUFBRSxZQUFZO1NBQ3pCLENBQUMsQ0FBQTtRQUVGLE1BQU0sQ0FBQyxVQUFVLENB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
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const test_utils_1 = require("@medusajs/test-utils");
7
+ const __1 = require("..");
8
+ const subscription_settings_1 = __importDefault(require("../models/subscription-settings"));
9
+ const types_1 = require("../types");
10
+ (0, test_utils_1.moduleIntegrationTestRunner)({
11
+ moduleName: __1.SETTINGS_MODULE,
12
+ moduleModels: [subscription_settings_1.default],
13
+ resolve: "./src/modules/settings",
14
+ testSuite: ({ service }) => {
15
+ describe("SettingsModuleService", () => {
16
+ it("returns fallback defaults when no settings record exists", async () => {
17
+ const settings = await service.getSettings();
18
+ expect(settings).toMatchObject({
19
+ settings_key: "global",
20
+ default_trial_days: 0,
21
+ dunning_retry_intervals: [1440, 4320, 10080],
22
+ max_dunning_attempts: 3,
23
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.PROCESS_IMMEDIATELY,
24
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.RECOMMEND_RETENTION_FIRST,
25
+ version: 0,
26
+ updated_by: null,
27
+ updated_at: null,
28
+ is_persisted: false,
29
+ });
30
+ });
31
+ it("lazy-creates the singleton on first update", async () => {
32
+ const updated = await service.updateSettings({
33
+ default_trial_days: 14,
34
+ dunning_retry_intervals: [60, 180, 360],
35
+ max_dunning_attempts: 3,
36
+ updated_by: "admin_first",
37
+ });
38
+ expect(updated).toMatchObject({
39
+ settings_key: "global",
40
+ default_trial_days: 14,
41
+ dunning_retry_intervals: [60, 180, 360],
42
+ max_dunning_attempts: 3,
43
+ version: 1,
44
+ updated_by: "admin_first",
45
+ is_persisted: true,
46
+ });
47
+ expect(updated.updated_at).toBeTruthy();
48
+ const [records, count] = await service.listAndCountSubscriptionSettings({
49
+ settings_key: "global",
50
+ });
51
+ expect(count).toBe(1);
52
+ expect(records[0].settings_key).toBe("global");
53
+ });
54
+ it("updates the persisted singleton and increments version", async () => {
55
+ await service.updateSettings({
56
+ default_trial_days: 7,
57
+ dunning_retry_intervals: [60, 180],
58
+ max_dunning_attempts: 2,
59
+ updated_by: "admin_seed",
60
+ });
61
+ const updated = await service.updateSettings({
62
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.REQUIRE_REVIEW_FOR_PENDING_CHANGES,
63
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.ALLOW_DIRECT_CANCELLATION,
64
+ updated_by: "admin_second",
65
+ });
66
+ expect(updated).toMatchObject({
67
+ settings_key: "global",
68
+ default_trial_days: 7,
69
+ dunning_retry_intervals: [60, 180],
70
+ max_dunning_attempts: 2,
71
+ default_renewal_behavior: types_1.SubscriptionRenewalBehavior.REQUIRE_REVIEW_FOR_PENDING_CHANGES,
72
+ default_cancellation_behavior: types_1.SubscriptionCancellationBehavior.ALLOW_DIRECT_CANCELLATION,
73
+ version: 2,
74
+ updated_by: "admin_second",
75
+ is_persisted: true,
76
+ });
77
+ });
78
+ it("returns persisted settings from getSettings after update", async () => {
79
+ await service.updateSettings({
80
+ default_trial_days: 21,
81
+ dunning_retry_intervals: [120, 240, 480],
82
+ max_dunning_attempts: 3,
83
+ updated_by: "admin_reader",
84
+ });
85
+ const settings = await service.getSettings();
86
+ expect(settings).toMatchObject({
87
+ settings_key: "global",
88
+ default_trial_days: 21,
89
+ dunning_retry_intervals: [120, 240, 480],
90
+ max_dunning_attempts: 3,
91
+ version: 1,
92
+ updated_by: "admin_reader",
93
+ is_persisted: true,
94
+ });
95
+ });
96
+ it("resets persisted settings back to fallback defaults", async () => {
97
+ await service.updateSettings({
98
+ default_trial_days: 30,
99
+ dunning_retry_intervals: [60, 120, 180],
100
+ max_dunning_attempts: 3,
101
+ updated_by: "admin_reset",
102
+ });
103
+ const reset = await service.resetSettings();
104
+ expect(reset).toMatchObject({
105
+ settings_key: "global",
106
+ default_trial_days: 0,
107
+ dunning_retry_intervals: [1440, 4320, 10080],
108
+ max_dunning_attempts: 3,
109
+ version: 0,
110
+ updated_by: null,
111
+ updated_at: null,
112
+ is_persisted: false,
113
+ });
114
+ const [records, count] = await service.listAndCountSubscriptionSettings({
115
+ settings_key: "global",
116
+ });
117
+ expect(count).toBe(0);
118
+ expect(records).toHaveLength(0);
119
+ });
120
+ });
121
+ },
122
+ });
123
+ jest.setTimeout(60 * 1000);
124
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvc2V0dGluZ3MvX190ZXN0c19fL3NlcnZpY2Uuc3BlYy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFEQUFrRTtBQUNsRSwwQkFBb0M7QUFDcEMsNEZBQWtFO0FBRWxFLG9DQUdpQjtBQUVqQixJQUFBLHdDQUEyQixFQUF3QjtJQUNqRCxVQUFVLEVBQUUsbUJBQWU7SUFDM0IsWUFBWSxFQUFFLENBQUMsK0JBQW9CLENBQUM7SUFDcEMsT0FBTyxFQUFFLHdCQUF3QjtJQUNqQyxTQUFTLEVBQUUsQ0FBQyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUU7UUFDekIsUUFBUSxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRTtZQUNyQyxFQUFFLENBQUMsMERBQTBELEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQ3hFLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFBO2dCQUU1QyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsYUFBYSxDQUFDO29CQUM3QixZQUFZLEVBQUUsUUFBUTtvQkFDdEIsa0JBQWtCLEVBQUUsQ0FBQztvQkFDckIsdUJBQXVCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQztvQkFDNUMsb0JBQW9CLEVBQUUsQ0FBQztvQkFDdkIsd0JBQXdCLEVBQ3RCLG1DQUEyQixDQUFDLG1CQUFtQjtvQkFDakQsNkJBQTZCLEVBQzNCLHdDQUFnQyxDQUFDLHlCQUF5QjtvQkFDNUQsT0FBTyxFQUFFLENBQUM7b0JBQ1YsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixZQUFZLEVBQUUsS0FBSztpQkFDcEIsQ0FBQyxDQUFBO1lBQ0osQ0FBQyxDQUFDLENBQUE7WUFFRixFQUFFLENBQUMsNENBQTRDLEVBQUUsS0FBSyxJQUFJLEVB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
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("@medusajs/framework/utils");
4
+ const payment_methods_1 = require("../utils/payment-methods");
5
+ function buildContainer(input) {
6
+ const listPaymentMethods = jest.fn(async ({ provider_id }) => input.paymentMethodsByProvider[provider_id] ?? []);
7
+ const container = {
8
+ resolve: (key) => {
9
+ if (key === utils_1.ContainerRegistrationKeys.QUERY) {
10
+ return {
11
+ graph: async () => ({
12
+ data: [
13
+ {
14
+ id: "cus_1",
15
+ account_holders: input.accountHolders,
16
+ },
17
+ ],
18
+ }),
19
+ };
20
+ }
21
+ if (key === utils_1.Modules.PAYMENT) {
22
+ return { listPaymentMethods };
23
+ }
24
+ throw new Error(`Unexpected container key '${key}'`);
25
+ },
26
+ };
27
+ return { container, listPaymentMethods };
28
+ }
29
+ const stripeAccountHolder = {
30
+ id: "acch_1",
31
+ provider_id: "pp_stripe_stripe",
32
+ external_id: "cus_stripe_1",
33
+ data: { id: "cus_stripe_1" },
34
+ };
35
+ describe("toPaymentMethodSummary", () => {
36
+ it("normalizes card details exposed by the provider", () => {
37
+ const summary = (0, payment_methods_1.toPaymentMethodSummary)({
38
+ id: "pm_1",
39
+ data: {
40
+ type: "card",
41
+ created: 1_700_000_000,
42
+ card: {
43
+ brand: "visa",
44
+ last4: "4242",
45
+ exp_month: 4,
46
+ exp_year: 2030,
47
+ },
48
+ },
49
+ }, "pp_stripe_stripe");
50
+ expect(summary).toEqual({
51
+ id: "pm_1",
52
+ provider_id: "pp_stripe_stripe",
53
+ type: "card",
54
+ brand: "visa",
55
+ last4: "4242",
56
+ exp_month: 4,
57
+ exp_year: 2030,
58
+ created_at: 1_700_000_000,
59
+ });
60
+ });
61
+ it("degrades to null fields for providers that expose no card metadata", () => {
62
+ const summary = (0, payment_methods_1.toPaymentMethodSummary)({ id: "pm_2" }, "pp_system_default");
63
+ expect(summary).toEqual({
64
+ id: "pm_2",
65
+ provider_id: "pp_system_default",
66
+ type: null,
67
+ brand: null,
68
+ last4: null,
69
+ exp_month: null,
70
+ exp_year: null,
71
+ created_at: null,
72
+ });
73
+ });
74
+ it("parses numeric card fields returned as strings", () => {
75
+ const summary = (0, payment_methods_1.toPaymentMethodSummary)({
76
+ id: "pm_3",
77
+ data: {
78
+ card: {
79
+ exp_month: "07",
80
+ exp_year: "2031",
81
+ },
82
+ },
83
+ }, "pp_stripe_stripe");
84
+ expect(summary.exp_month).toEqual(7);
85
+ expect(summary.exp_year).toEqual(2031);
86
+ });
87
+ });
88
+ describe("listCustomerPaymentMethods", () => {
89
+ it("returns the customer's saved payment methods newest first", async () => {
90
+ const { container } = buildContainer({
91
+ accountHolders: [stripeAccountHolder],
92
+ paymentMethodsByProvider: {
93
+ pp_stripe_stripe: [
94
+ { id: "pm_old", data: { created: 1 } },
95
+ { id: "pm_new", data: { created: 2 } },
96
+ ],
97
+ },
98
+ });
99
+ const summaries = await (0, payment_methods_1.listCustomerPaymentMethods)(container, {
100
+ customer_id: "cus_1",
101
+ provider_id: "pp_stripe_stripe",
102
+ });
103
+ expect(summaries.map((summary) => summary.id)).toEqual([
104
+ "pm_new",
105
+ "pm_old",
106
+ ]);
107
+ });
108
+ it("returns an empty list when the customer has no account holder", async () => {
109
+ const { container, listPaymentMethods } = buildContainer({
110
+ accountHolders: [],
111
+ paymentMethodsByProvider: {},
112
+ });
113
+ const summaries = await (0, payment_methods_1.listCustomerPaymentMethods)(container, {
114
+ customer_id: "cus_1",
115
+ provider_id: "pp_stripe_stripe",
116
+ });
117
+ expect(summaries).toEqual([]);
118
+ expect(listPaymentMethods).not.toHaveBeenCalled();
119
+ });
120
+ it("ignores account holders of other providers", async () => {
121
+ const { container } = buildContainer({
122
+ accountHolders: [
123
+ stripeAccountHolder,
124
+ {
125
+ id: "acch_2",
126
+ provider_id: "pp_other_other",
127
+ data: { id: "cus_other_1" },
128
+ },
129
+ ],
130
+ paymentMethodsByProvider: {
131
+ pp_stripe_stripe: [{ id: "pm_stripe" }],
132
+ pp_other_other: [{ id: "pm_other" }],
133
+ },
134
+ });
135
+ const summaries = await (0, payment_methods_1.listCustomerPaymentMethods)(container, {
136
+ customer_id: "cus_1",
137
+ provider_id: "pp_stripe_stripe",
138
+ });
139
+ expect(summaries.map((summary) => summary.id)).toEqual(["pm_stripe"]);
140
+ });
141
+ });
142
+ describe("resolveCustomerPaymentMethod", () => {
143
+ it("resolves a payment method the customer owns", async () => {
144
+ const { container } = buildContainer({
145
+ accountHolders: [stripeAccountHolder],
146
+ paymentMethodsByProvider: {
147
+ pp_stripe_stripe: [
148
+ { id: "pm_1", data: { card: { brand: "visa", last4: "4242" } } },
149
+ ],
150
+ },
151
+ });
152
+ const resolved = await (0, payment_methods_1.resolveCustomerPaymentMethod)(container, {
153
+ customer_id: "cus_1",
154
+ provider_id: "pp_stripe_stripe",
155
+ payment_method_id: "pm_1",
156
+ });
157
+ expect(resolved.summary.id).toEqual("pm_1");
158
+ expect(resolved.summary.last4).toEqual("4242");
159
+ expect(resolved.account_holder.id).toEqual("acch_1");
160
+ });
161
+ it("rejects a payment method the customer does not own", async () => {
162
+ const { container } = buildContainer({
163
+ accountHolders: [stripeAccountHolder],
164
+ paymentMethodsByProvider: {
165
+ pp_stripe_stripe: [{ id: "pm_1" }],
166
+ },
167
+ });
168
+ await expect((0, payment_methods_1.resolveCustomerPaymentMethod)(container, {
169
+ customer_id: "cus_1",
170
+ provider_id: "pp_stripe_stripe",
171
+ payment_method_id: "pm_someone_else",
172
+ })).rejects.toThrow("Payment method 'pm_someone_else' is not a saved payment method of customer 'cus_1'");
173
+ });
174
+ it("rejects when the customer has no account holder for the provider", async () => {
175
+ const { container } = buildContainer({
176
+ accountHolders: [],
177
+ paymentMethodsByProvider: {},
178
+ });
179
+ await expect((0, payment_methods_1.resolveCustomerPaymentMethod)(container, {
180
+ customer_id: "cus_1",
181
+ provider_id: "pp_stripe_stripe",
182
+ payment_method_id: "pm_1",
183
+ })).rejects.toThrow("Customer 'cus_1' has no saved payment account holder for provider 'pp_stripe_stripe'");
184
+ });
185
+ });
186
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF5bWVudC1tZXRob2RzLnNwZWMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbW9kdWxlcy9zdWJzY3JpcHRpb24vX190ZXN0c19fL3BheW1lbnQtbWV0aG9kcy5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0EscURBQThFO0FBQzlFLDhEQUlpQztBQVFqQyxTQUFTLGNBQWMsQ0FBQyxLQUd2QjtJQUNDLE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FDaEMsS0FBSyxFQUFFLEVBQUUsV0FBVyxFQUEyQixFQUFFLEVBQUUsQ0FDakQsS0FBSyxDQUFDLHdCQUF3QixDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsQ0FDcEQsQ0FBQTtJQUVELE1BQU0sU0FBUyxHQUFHO1FBQ2hCLE9BQU8sRUFBRSxDQUFDLEdBQVcsRUFBRSxFQUFFO1lBQ3ZCLElBQUksR0FBRyxLQUFLLGlDQUF5QixDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUM1QyxPQUFPO29CQUNMLEtBQUssRUFBRSxLQUFLLElBQUksRUFBRSxDQUFDLENBQUM7d0JBQ2xCLElBQUksRUFBRTs0QkFDSjtnQ0FDRSxFQUFFLEVBQUUsT0FBTztnQ0FDWCxlQUFlLEVBQUUsS0FBSyxDQUFDLGNBQWM7NkJBQ3RDO3lCQUNGO3FCQUNGLENBQUM7aUJBQ0gsQ0FBQTtZQUNILENBQUM7WUFFRCxJQUFJLEdBQUcsS0FBSyxlQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQzVCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxDQUFBO1lBQy9CLENBQUM7WUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLDZCQUE2QixHQUFHLEdBQUcsQ0FBQyxDQUFBO1FBQ3RELENBQUM7S0FDNEIsQ0FBQTtJQUUvQixPQUFPLEVBQUUsU0FBUyxFQUFFLGtCQUFrQixFQUFFLENBQUE7QUFDMUMsQ0FBQztBQUVELE1BQU0sbUJBQW1CLEdBQW9DO0lBQzNELEVBQUUsRUFB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
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const test_utils_1 = require("@medusajs/test-utils");
7
+ const __1 = require("..");
8
+ const subscription_1 = __importDefault(require("../models/subscription"));
9
+ const types_1 = require("../types");
10
+ (0, test_utils_1.moduleIntegrationTestRunner)({
11
+ moduleName: __1.SUBSCRIPTION_MODULE,
12
+ moduleModels: [subscription_1.default],
13
+ resolve: "./src/modules/subscription",
14
+ testSuite: ({ service }) => {
15
+ describe("SubscriptionModuleService", () => {
16
+ it("creates and retrieves a subscription", async () => {
17
+ const created = await service.createSubscriptions({
18
+ reference: "SUB-MODULE-001",
19
+ status: types_1.SubscriptionStatus.ACTIVE,
20
+ customer_id: "cus_module_001",
21
+ product_id: "prod_module_001",
22
+ variant_id: "variant_module_001",
23
+ frequency_interval: types_1.SubscriptionFrequencyInterval.MONTH,
24
+ frequency_value: 1,
25
+ started_at: new Date(),
26
+ next_renewal_at: new Date(),
27
+ last_renewal_at: null,
28
+ paused_at: null,
29
+ cancelled_at: null,
30
+ cancel_effective_at: null,
31
+ skip_next_cycle: false,
32
+ is_trial: false,
33
+ trial_ends_at: null,
34
+ customer_snapshot: {
35
+ email: "module@example.com",
36
+ full_name: "Module Test",
37
+ },
38
+ product_snapshot: {
39
+ product_id: "prod_module_001",
40
+ product_title: "Module Product",
41
+ variant_id: "variant_module_001",
42
+ variant_title: "Default Variant",
43
+ sku: "MODULE-SKU-001",
44
+ },
45
+ pricing_snapshot: null,
46
+ shipping_address: {
47
+ first_name: "Jan",
48
+ last_name: "Kowalski",
49
+ company: null,
50
+ address_1: "Testowa 1",
51
+ address_2: null,
52
+ city: "Warszawa",
53
+ postal_code: "00-001",
54
+ province: "Mazowieckie",
55
+ country_code: "PL",
56
+ phone: null,
57
+ },
58
+ pending_update_data: null,
59
+ metadata: null,
60
+ });
61
+ const retrieved = await service.retrieveSubscription(created.id);
62
+ expect(retrieved.id).toEqual(created.id);
63
+ expect(retrieved.reference).toEqual("SUB-MODULE-001");
64
+ expect(retrieved.status).toEqual(types_1.SubscriptionStatus.ACTIVE);
65
+ });
66
+ it("updates subscription status", async () => {
67
+ const created = await service.createSubscriptions({
68
+ reference: "SUB-MODULE-002",
69
+ status: types_1.SubscriptionStatus.ACTIVE,
70
+ customer_id: "cus_module_002",
71
+ product_id: "prod_module_002",
72
+ variant_id: "variant_module_002",
73
+ frequency_interval: types_1.SubscriptionFrequencyInterval.MONTH,
74
+ frequency_value: 1,
75
+ started_at: new Date(),
76
+ next_renewal_at: new Date(),
77
+ last_renewal_at: null,
78
+ paused_at: null,
79
+ cancelled_at: null,
80
+ cancel_effective_at: null,
81
+ skip_next_cycle: false,
82
+ is_trial: false,
83
+ trial_ends_at: null,
84
+ customer_snapshot: {
85
+ email: "module2@example.com",
86
+ full_name: "Module Test 2",
87
+ },
88
+ product_snapshot: {
89
+ product_id: "prod_module_002",
90
+ product_title: "Module Product 2",
91
+ variant_id: "variant_module_002",
92
+ variant_title: "Default Variant",
93
+ sku: "MODULE-SKU-002",
94
+ },
95
+ pricing_snapshot: null,
96
+ shipping_address: {
97
+ first_name: "Jan",
98
+ last_name: "Kowalski",
99
+ company: null,
100
+ address_1: "Testowa 1",
101
+ address_2: null,
102
+ city: "Warszawa",
103
+ postal_code: "00-001",
104
+ province: "Mazowieckie",
105
+ country_code: "PL",
106
+ phone: null,
107
+ },
108
+ pending_update_data: null,
109
+ metadata: null,
110
+ });
111
+ await service.updateSubscriptions({
112
+ id: created.id,
113
+ status: types_1.SubscriptionStatus.PAUSED,
114
+ paused_at: new Date(),
115
+ });
116
+ const updated = await service.retrieveSubscription(created.id);
117
+ expect(updated.status).toEqual(types_1.SubscriptionStatus.PAUSED);
118
+ expect(updated.paused_at).toBeTruthy();
119
+ });
120
+ });
121
+ },
122
+ });
123
+ jest.setTimeout(60 * 1000);
124
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvc3Vic2NyaXB0aW9uL19fdGVzdHNfXy9zZXJ2aWNlLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFBa0U7QUFDbEUsMEJBQXdDO0FBQ3hDLDBFQUFpRDtBQUVqRCxvQ0FHaUI7QUFFakIsSUFBQSx3Q0FBMkIsRUFBNEI7SUFDckQsVUFBVSxFQUFFLHVCQUFtQjtJQUMvQixZQUFZLEVBQUUsQ0FBQyxzQkFBWSxDQUFDO0lBQzVCLE9BQU8sRUFBRSw0QkFBNEI7SUFDckMsU0FBUyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFO1FBQ3pCLFFBQVEsQ0FBQywyQkFBMkIsRUFBRSxHQUFHLEVBQUU7WUFDekMsRUFBRSxDQUFDLHNDQUFzQyxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNwRCxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQztvQkFDaEQsU0FBUyxFQUFFLGdCQUFnQjtvQkFDM0IsTUFBTSxFQUFFLDBCQUFrQixDQUFDLE1BQU07b0JBQ2pDLFdBQVcsRUFBRSxnQkFBZ0I7b0JBQzdCLFVBQVUsRUFBRSxpQkFBaUI7b0JBQzdCLFVBQVUsRUFBRSxvQkFBb0I7b0JBQ2hDLGtCQUFrQixFQUFFLHFDQUE2QixDQUFDLEtBQUs7b0JBQ3ZELGVBQWUsRUFBRSxDQUFDO29CQUNsQixVQUFVLEVBQUUsSUFBSSxJQUFJLEVBQUU7b0JBQ3RCLGVBQWUsRUFBRSxJQUFJLElBQUksRUFBRTtvQkFDM0IsZUFBZSxFQUFFLElBQUk7b0JBQ3JCLFNBQVMsRUFBRSxJQUFJO29CQUNmLFlBQVksRUFBRSxJQUFJO29CQUNsQixtQkFBbUIsRUFBRSxJQUFJO29CQUN6QixlQUFlLEVBQUUsS0FBSztvQkFDdEIsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsYUFBYSxFQUFFLElBQUk7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