@reorderjs/reorder 1.0.7 → 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 (70) 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 +13142 -11709
  18. package/.medusa/server/src/admin/index.mjs +13136 -11703
  19. package/.medusa/server/src/admin/types/activity-log.js +2 -1
  20. package/.medusa/server/src/admin/types/analytics.js +2 -1
  21. package/.medusa/server/src/api/admin/cancellations/validators.js +2 -2
  22. package/.medusa/server/src/api/admin/dunning/validators.js +2 -2
  23. package/.medusa/server/src/api/admin/renewals/validators.js +2 -2
  24. package/.medusa/server/src/api/admin/subscription-analytics/validators.js +2 -2
  25. package/.medusa/server/src/api/admin/subscription-logs/validators.js +2 -2
  26. package/.medusa/server/src/api/admin/subscription-offers/validators.js +2 -2
  27. package/.medusa/server/src/api/admin/subscription-settings/validators.js +2 -2
  28. package/.medusa/server/src/api/admin/subscriptions/[id]/payment-method/route.js +19 -0
  29. package/.medusa/server/src/api/admin/subscriptions/[id]/payment-methods/route.js +10 -0
  30. package/.medusa/server/src/api/admin/subscriptions/middlewares.js +8 -1
  31. package/.medusa/server/src/api/admin/subscriptions/utils.js +5 -1
  32. package/.medusa/server/src/api/admin/subscriptions/validators.js +7 -3
  33. package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-method/route.js +26 -0
  34. package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/payment-methods/route.js +15 -0
  35. package/.medusa/server/src/api/store/customers/me/subscriptions/middlewares.js +8 -1
  36. package/.medusa/server/src/api/store/customers/me/subscriptions/utils.js +72 -1
  37. package/.medusa/server/src/api/store/customers/me/subscriptions/validators.js +7 -3
  38. package/.medusa/server/src/api/store/products/validators.js +2 -2
  39. package/.medusa/server/src/modules/activity-log/__tests__/create-subscription-log-event.spec.js +257 -0
  40. package/.medusa/server/src/modules/activity-log/__tests__/normalize-log-event.spec.js +231 -0
  41. package/.medusa/server/src/modules/activity-log/migrations/Migration20260524220933.js +16 -0
  42. package/.medusa/server/src/modules/activity-log/migrations/Migration20260524225625.js +16 -0
  43. package/.medusa/server/src/modules/activity-log/migrations/Migration20260818120000.js +16 -0
  44. package/.medusa/server/src/modules/activity-log/types/index.js +4 -1
  45. package/.medusa/server/src/modules/activity-log/utils/admin-query.js +15 -1
  46. package/.medusa/server/src/modules/analytics/__tests__/admin-query.spec.js +560 -0
  47. package/.medusa/server/src/modules/analytics/index.js +2 -2
  48. package/.medusa/server/src/modules/analytics/utils/admin-query.js +157 -5
  49. package/.medusa/server/src/modules/plan-offer/__tests__/service.spec.js +94 -0
  50. package/.medusa/server/src/modules/renewal/__tests__/service.spec.js +89 -0
  51. package/.medusa/server/src/modules/settings/__tests__/normalize-settings.spec.js +86 -0
  52. package/.medusa/server/src/modules/settings/__tests__/service.spec.js +124 -0
  53. package/.medusa/server/src/modules/subscription/__tests__/payment-methods.spec.js +186 -0
  54. package/.medusa/server/src/modules/subscription/__tests__/service.spec.js +124 -0
  55. package/.medusa/server/src/modules/subscription/utils/admin-query.js +196 -14
  56. package/.medusa/server/src/modules/subscription/utils/payment-methods.js +146 -0
  57. package/.medusa/server/src/subscription-flows/create-subscription-from-cart.js +55 -2
  58. package/.medusa/server/src/workflows/__tests__/cancel-subscription.spec.js +20 -0
  59. package/.medusa/server/src/workflows/__tests__/pause-subscription.spec.js +20 -0
  60. package/.medusa/server/src/workflows/__tests__/update-subscription-shipping-address.spec.js +49 -0
  61. package/.medusa/server/src/workflows/cancel-subscription.js +21 -1
  62. package/.medusa/server/src/workflows/index.js +6 -2
  63. package/.medusa/server/src/workflows/pause-subscription.js +21 -1
  64. package/.medusa/server/src/workflows/steps/rebuild-analytics-daily-snapshots.js +33 -10
  65. package/.medusa/server/src/workflows/steps/update-subscription-payment-method.js +110 -0
  66. package/.medusa/server/src/workflows/steps/validate-subscription-cart.js +7 -22
  67. package/.medusa/server/src/workflows/update-subscription-payment-method.js +65 -0
  68. package/.medusa/server/src/workflows/utils/analytics-incremental.js +1 -1
  69. package/README.md +89 -36
  70. package/package.json +25 -23
@@ -0,0 +1,279 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = resetSubscriptionsTestData;
4
+ const utils_1 = require("@medusajs/framework/utils");
5
+ const renewal_1 = require("../src/modules/renewal");
6
+ const subscription_1 = require("../src/modules/subscription");
7
+ const SEED_NAMESPACE = "subscriptions-test-data";
8
+ const IDS = {
9
+ settings: [
10
+ "set_seed_subscriptions_global",
11
+ ],
12
+ planOffers: [
13
+ "po_seed_subscriptions_success",
14
+ "po_seed_subscriptions_blocked",
15
+ ],
16
+ subscriptions: [
17
+ "sub_seed_subscriptions_success",
18
+ "sub_seed_subscriptions_paused",
19
+ "sub_seed_subscriptions_cancel_effective",
20
+ "sub_seed_subscriptions_approval_pending",
21
+ "sub_seed_subscriptions_policy_blocked",
22
+ "sub_seed_subscriptions_failed_history",
23
+ "sub_seed_dunning_retry_scheduled",
24
+ "sub_seed_dunning_awaiting_manual",
25
+ "sub_seed_dunning_recovered",
26
+ "sub_seed_dunning_unrecovered",
27
+ "sub_seed_dunning_manual_override",
28
+ "sub_seed_analytics_bimonthly",
29
+ ],
30
+ renewalCycles: [
31
+ "re_seed_subscriptions_success",
32
+ "re_seed_subscriptions_paused",
33
+ "re_seed_subscriptions_cancel_effective",
34
+ "re_seed_subscriptions_approval_pending",
35
+ "re_seed_subscriptions_policy_blocked",
36
+ "re_seed_subscriptions_failed_history",
37
+ "re_seed_dunning_retry_scheduled",
38
+ "re_seed_dunning_awaiting_manual",
39
+ "re_seed_dunning_recovered",
40
+ "re_seed_dunning_unrecovered",
41
+ "re_seed_dunning_manual_override",
42
+ ],
43
+ renewalAttempts: [
44
+ "rea_seed_subscriptions_failed_history",
45
+ ],
46
+ dunningCases: [
47
+ "dc_seed_dunning_retry_scheduled",
48
+ "dc_seed_dunning_awaiting_manual",
49
+ "dc_seed_dunning_recovered",
50
+ "dc_seed_dunning_unrecovered",
51
+ "dc_seed_dunning_manual_override",
52
+ ],
53
+ dunningAttempts: [
54
+ "da_seed_dunning_awaiting_manual_1",
55
+ "da_seed_dunning_recovered_1",
56
+ "da_seed_dunning_recovered_2",
57
+ "da_seed_dunning_unrecovered_1",
58
+ "da_seed_dunning_unrecovered_2",
59
+ "da_seed_dunning_unrecovered_3",
60
+ "da_seed_dunning_manual_override_1",
61
+ ],
62
+ cancellationCases: [
63
+ "cc_seed_cancellation_open_billing",
64
+ "cc_seed_cancellation_retained_discount",
65
+ "cc_seed_cancellation_paused",
66
+ "cc_seed_cancellation_canceled_immediate",
67
+ "cc_seed_cancellation_canceled_end_cycle",
68
+ "cc_seed_cancellation_open_price",
69
+ "cc_seed_cancellation_open_paused",
70
+ ],
71
+ retentionOfferEvents: [
72
+ "roe_seed_cancellation_discount_retained",
73
+ "roe_seed_cancellation_pause_applied",
74
+ ],
75
+ subscriptionLogs: [
76
+ "slog_seed_subscription_paused",
77
+ "slog_seed_renewal_succeeded",
78
+ "slog_seed_dunning_recovered",
79
+ ],
80
+ customerReferences: [
81
+ "SUB-QA-REN-SUCCESS",
82
+ "SUB-QA-REN-PAUSED",
83
+ "SUB-QA-REN-CANCEL-EFFECTIVE",
84
+ "SUB-QA-REN-APPROVAL-PENDING",
85
+ "SUB-QA-REN-POLICY-BLOCKED",
86
+ "SUB-QA-REN-FAILED-HISTORY",
87
+ "SUB-QA-DUN-RETRY-SCHEDULED",
88
+ "SUB-QA-DUN-AWAITING-MANUAL",
89
+ "SUB-QA-DUN-RECOVERED",
90
+ "SUB-QA-DUN-UNRECOVERED",
91
+ "SUB-QA-DUN-MANUAL-OVERRIDE",
92
+ "SUB-QA-CAN-OPEN-BILLING",
93
+ "SUB-QA-CAN-RETAINED-DISCOUNT",
94
+ "SUB-QA-CAN-PAUSED",
95
+ "SUB-QA-CAN-CANCELED-IMMEDIATE",
96
+ "SUB-QA-CAN-CANCELED-END-CYCLE",
97
+ "SUB-QA-CAN-OPEN-PRICE",
98
+ "SUB-QA-CAN-OPEN-PAUSED-SUB",
99
+ "SUB-QA-ANL-BI-MONTHLY",
100
+ ],
101
+ };
102
+ function hasSeedNamespace(record) {
103
+ return record.metadata?.seed_namespace === SEED_NAMESPACE;
104
+ }
105
+ async function listSeedRecordIds(query, entity, ids) {
106
+ if (!ids.length) {
107
+ return [];
108
+ }
109
+ const { data } = await query.graph({
110
+ entity,
111
+ fields: ["id", "metadata"],
112
+ filters: {
113
+ id: ids,
114
+ },
115
+ });
116
+ return (data ?? [])
117
+ .filter((record) => ids.includes(record.id))
118
+ .filter(hasSeedNamespace)
119
+ .map((record) => record.id);
120
+ }
121
+ async function deleteFromTable(pgConnection, tableName, ids) {
122
+ if (!ids.length) {
123
+ return 0;
124
+ }
125
+ return await pgConnection(tableName).whereIn("id", ids).del();
126
+ }
127
+ async function deleteFromTableByColumn(pgConnection, tableName, column, ids) {
128
+ if (!ids.length) {
129
+ return 0;
130
+ }
131
+ return await pgConnection(tableName).whereIn(column, ids).del();
132
+ }
133
+ async function resetSubscriptionsTestData({ container, }) {
134
+ const logger = container.resolve(utils_1.ContainerRegistrationKeys.LOGGER);
135
+ const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
136
+ const pgConnection = container.resolve(utils_1.ContainerRegistrationKeys.PG_CONNECTION);
137
+ const link = container.resolve(utils_1.ContainerRegistrationKeys.LINK);
138
+ const customerModule = container.resolve(utils_1.Modules.CUSTOMER);
139
+ const orderModule = container.resolve(utils_1.Modules.ORDER);
140
+ logger.info("[subscriptions-test-data-reset] Resolving seeded records");
141
+ const settingsIds = await listSeedRecordIds(query, "subscription_settings", [
142
+ ...IDS.settings,
143
+ ]);
144
+ const planOfferIds = await listSeedRecordIds(query, "plan_offer", [
145
+ ...IDS.planOffers,
146
+ ]);
147
+ const subscriptionIds = await listSeedRecordIds(query, "subscription", [
148
+ ...IDS.subscriptions,
149
+ ]);
150
+ const renewalCycleIds = await listSeedRecordIds(query, "renewal_cycle", [
151
+ ...IDS.renewalCycles,
152
+ ]);
153
+ const renewalAttemptIds = await listSeedRecordIds(query, "renewal_attempt", [
154
+ ...IDS.renewalAttempts,
155
+ ]);
156
+ const dunningCaseIds = await listSeedRecordIds(query, "dunning_case", [
157
+ ...IDS.dunningCases,
158
+ ]);
159
+ const dunningAttemptIds = await listSeedRecordIds(query, "dunning_attempt", [
160
+ ...IDS.dunningAttempts,
161
+ ]);
162
+ const cancellationCaseIds = await listSeedRecordIds(query, "cancellation_case", [
163
+ ...IDS.cancellationCases,
164
+ ]);
165
+ const retentionOfferEventIds = await listSeedRecordIds(query, "retention_offer_event", [...IDS.retentionOfferEvents]);
166
+ const subscriptionLogIds = await listSeedRecordIds(query, "subscription_log", [
167
+ ...IDS.subscriptionLogs,
168
+ ]);
169
+ const analyticsSnapshotIds = subscriptionIds.length
170
+ ? (await query.graph({
171
+ entity: "subscription_metrics_daily",
172
+ fields: ["id", "metadata"],
173
+ filters: {
174
+ subscription_id: subscriptionIds,
175
+ },
176
+ })).data
177
+ ?.filter((record) => hasSeedNamespace(record))
178
+ .map((record) => record.id) ?? []
179
+ : [];
180
+ const seededCustomerEmails = IDS.customerReferences.map((reference) => `${reference.toLowerCase()}@example.com`);
181
+ const seededCustomerIds = (await query.graph({
182
+ entity: "customer",
183
+ fields: ["id", "metadata", "email"],
184
+ filters: {
185
+ email: seededCustomerEmails,
186
+ },
187
+ })).data
188
+ ?.filter((record) => hasSeedNamespace(record))
189
+ .map((record) => record.id) ?? [];
190
+ const subscriptionOrderLinks = subscriptionIds.length
191
+ ? (await query.graph({
192
+ entity: "subscription_order",
193
+ fields: ["subscription.id", "order.id", "order.metadata"],
194
+ filters: {
195
+ subscription_id: subscriptionIds,
196
+ },
197
+ })).data ?? []
198
+ : [];
199
+ const renewalCycles = renewalCycleIds.length
200
+ ? (await query.graph({
201
+ entity: "renewal_cycle",
202
+ fields: ["id", "generated_order_id"],
203
+ filters: {
204
+ id: renewalCycleIds,
205
+ },
206
+ })).data ?? []
207
+ : [];
208
+ const renewalOrderIds = renewalCycles
209
+ .map((record) => record.generated_order_id)
210
+ .filter((id) => !!id);
211
+ const renewalOrders = renewalOrderIds.length
212
+ ? (await query.graph({
213
+ entity: "order",
214
+ fields: ["id", "metadata"],
215
+ filters: {
216
+ id: renewalOrderIds,
217
+ },
218
+ })).data ?? []
219
+ : [];
220
+ const subscriptionOrderLinkDefinitions = subscriptionOrderLinks
221
+ .filter((record) => record.subscription?.id && record.order?.id)
222
+ .map((record) => ({
223
+ [subscription_1.SUBSCRIPTION_MODULE]: {
224
+ subscription_id: record.subscription.id,
225
+ },
226
+ [utils_1.Modules.ORDER]: {
227
+ order_id: record.order.id,
228
+ },
229
+ }));
230
+ const renewalOrderLinkDefinitions = renewalCycles
231
+ .filter((record) => record.id && record.generated_order_id)
232
+ .map((record) => ({
233
+ [renewal_1.RENEWAL_MODULE]: {
234
+ renewal_cycle_id: record.id,
235
+ },
236
+ [utils_1.Modules.ORDER]: {
237
+ order_id: record.generated_order_id,
238
+ },
239
+ }));
240
+ const seededOrderIds = [
241
+ ...new Set([
242
+ ...subscriptionOrderLinks.map((record) => record.order),
243
+ ...renewalOrders,
244
+ ]
245
+ .filter((order) => !!order)
246
+ .filter((order) => order.metadata?.seed_namespace === SEED_NAMESPACE)
247
+ .map((order) => order.id)
248
+ .filter((id) => !!id)),
249
+ ];
250
+ if (renewalOrderLinkDefinitions.length) {
251
+ await link.dismiss(renewalOrderLinkDefinitions);
252
+ }
253
+ if (subscriptionOrderLinkDefinitions.length) {
254
+ await link.dismiss(subscriptionOrderLinkDefinitions);
255
+ }
256
+ if (seededOrderIds.length) {
257
+ await orderModule.deleteOrders(seededOrderIds);
258
+ }
259
+ const deletedSubscriptionLogs = await deleteFromTable(pgConnection, "subscription_log", subscriptionLogIds);
260
+ const deletedSettings = await deleteFromTable(pgConnection, "subscription_settings", settingsIds);
261
+ const deletedAnalyticsSnapshots = await deleteFromTable(pgConnection, "subscription_metrics_daily", analyticsSnapshotIds);
262
+ const deletedRetentionOfferEvents = await deleteFromTable(pgConnection, "retention_offer_event", retentionOfferEventIds);
263
+ const deletedRetentionOfferEventsByCase = await deleteFromTableByColumn(pgConnection, "retention_offer_event", "cancellation_case_id", cancellationCaseIds);
264
+ const deletedCancellationCases = await deleteFromTable(pgConnection, "cancellation_case", cancellationCaseIds);
265
+ const deletedDunningAttempts = await deleteFromTable(pgConnection, "dunning_attempt", dunningAttemptIds);
266
+ const deletedDunningAttemptsByCase = await deleteFromTableByColumn(pgConnection, "dunning_attempt", "dunning_case_id", dunningCaseIds);
267
+ const deletedDunningCases = await deleteFromTable(pgConnection, "dunning_case", dunningCaseIds);
268
+ const deletedRenewalAttempts = await deleteFromTable(pgConnection, "renewal_attempt", renewalAttemptIds);
269
+ const deletedRenewalAttemptsByCycle = await deleteFromTableByColumn(pgConnection, "renewal_attempt", "renewal_cycle_id", renewalCycleIds);
270
+ const deletedRenewalCycles = await deleteFromTable(pgConnection, "renewal_cycle", renewalCycleIds);
271
+ const deletedSubscriptions = await deleteFromTable(pgConnection, "subscription", subscriptionIds);
272
+ const deletedPlanOffers = await deleteFromTable(pgConnection, "plan_offer", planOfferIds);
273
+ if (seededCustomerIds.length) {
274
+ await customerModule.deleteCustomers(seededCustomerIds);
275
+ }
276
+ logger.info("[subscriptions-test-data-reset] Reset completed.");
277
+ logger.info(`[subscriptions-test-data-reset] Removed settings=${deletedSettings} plan_offers=${deletedPlanOffers} subscriptions=${deletedSubscriptions} renewal_cycles=${deletedRenewalCycles} renewal_attempts=${deletedRenewalAttempts + deletedRenewalAttemptsByCycle} dunning_cases=${deletedDunningCases} dunning_attempts=${deletedDunningAttempts + deletedDunningAttemptsByCase} cancellation_cases=${deletedCancellationCases} retention_offer_events=${deletedRetentionOfferEvents + deletedRetentionOfferEventsByCase} subscription_logs=${deletedSubscriptionLogs} analytics_snapshots=${deletedAnalyticsSnapshots} orders=${seededOrderIds.length} customers=${seededCustomerIds.length}`);
278
+ }
279
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzZXQtc3Vic2NyaXB0aW9ucy10ZXN0LWRhdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zY3JpcHRzL3Jlc2V0LXN1YnNjcmlwdGlvbnMtdGVzdC1kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBNExBLDZDQTZQQztBQXhiRCxxREFBOEU7QUFDOUUsb0RBQXVEO0FBQ3ZELDhEQUFpRTtBQUVqRSxNQUFNLGNBQWMsR0FBRyx5QkFBeUIsQ0FBQTtBQUVoRCxNQUFNLEdBQUcsR0FBRztJQUNWLFFBQVEsRUFBRTtRQUNSLCtCQUErQjtLQUNoQztJQUNELFVBQVUsRUFBRTtRQUNWLCtCQUErQjtRQUMvQiwrQkFBK0I7S0FDaEM7SUFDRCxhQUFhLEVBQUU7UUFDYixnQ0FBZ0M7UUFDaEMsK0JBQStCO1FBQy9CLHlDQUF5QztRQUN6Qyx5Q0FBeUM7UUFDekMsdUNBQXVDO1FBQ3ZDLHVDQUF1QztRQUN2QyxrQ0FBa0M7UUFDbEMsa0NBQWtDO1FBQ2xDLDRCQUE0QjtRQUM1Qiw4QkFBOEI7UUFDOUIsa0NBQWtDO1FBQ2xDLDhCQUE4QjtLQUMvQjtJQUNELGFBQWEsRUFBRTtRQUNiLCtCQUErQjtRQUMvQiw4QkFBOEI7UUFDOUIsd0NBQXdDO1FBQ3hDLHdDQUF3QztRQUN4QyxzQ0FBc0M7UUFDdEMsc0NBQXNDO1FBQ3RDLGlDQUFpQztRQUNqQyxpQ0FBaUM7UUFDakMsMkJBQTJCO1FBQzNCLDZCQUE2QjtRQUM3QixpQ0FBaUM7S0FDbEM7SUFDRCxlQUFlLEVBQUU7UUFDZix1Q0FBdUM7S0FDeEM7SUFDRCxZQUFZLEVBQUU7UUFDWixpQ0FBaUM7UUFDakMsaUNBQWlDO1FBQ2pDLDJCQUEyQjtRQUMzQiw2QkFBNkI7UUFDN0IsaUNBQWlDO0tBQ2xDO0lBQ0QsZUFBZSxFQUFFO1FBQ2YsbUNBQW1DO1FBQ25DLDZCQUE2QjtRQUM3Qiw2QkFBNkI7UUFDN0IsK0JBQStCO1FBQy9CLCtCQUErQjtRQUMvQiwrQkFBK0I7UUFDL0Is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