@reorderjs/reorder 1.0.1
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/.medusa/server/scripts/reset-reorder-plugin-data.js +175 -0
- package/.medusa/server/src/admin/index.js +17889 -0
- package/.medusa/server/src/admin/index.mjs +17871 -0
- package/.medusa/server/src/admin/types/activity-log.js +10 -0
- package/.medusa/server/src/admin/types/analytics.js +17 -0
- package/.medusa/server/src/admin/types/cancellation.js +27 -0
- package/.medusa/server/src/admin/types/dunning.js +19 -0
- package/.medusa/server/src/admin/types/plan-offer.js +25 -0
- package/.medusa/server/src/admin/types/renewal.js +23 -0
- package/.medusa/server/src/admin/types/subscription.js +22 -0
- package/.medusa/server/src/api/admin/cancellations/[id]/apply-offer/route.js +30 -0
- package/.medusa/server/src/api/admin/cancellations/[id]/finalize/route.js +31 -0
- package/.medusa/server/src/api/admin/cancellations/[id]/reason/route.js +31 -0
- package/.medusa/server/src/api/admin/cancellations/[id]/route.js +20 -0
- package/.medusa/server/src/api/admin/cancellations/middlewares.js +55 -0
- package/.medusa/server/src/api/admin/cancellations/route.js +20 -0
- package/.medusa/server/src/api/admin/cancellations/utils.js +116 -0
- package/.medusa/server/src/api/admin/cancellations/validators.js +130 -0
- package/.medusa/server/src/api/admin/dunning/[id]/mark-recovered/route.js +27 -0
- package/.medusa/server/src/api/admin/dunning/[id]/mark-unrecovered/route.js +27 -0
- package/.medusa/server/src/api/admin/dunning/[id]/retry-now/route.js +28 -0
- package/.medusa/server/src/api/admin/dunning/[id]/retry-schedule/route.js +29 -0
- package/.medusa/server/src/api/admin/dunning/[id]/route.js +20 -0
- package/.medusa/server/src/api/admin/dunning/middlewares.js +60 -0
- package/.medusa/server/src/api/admin/dunning/route.js +20 -0
- package/.medusa/server/src/api/admin/dunning/utils.js +70 -0
- package/.medusa/server/src/api/admin/dunning/validators.js +81 -0
- package/.medusa/server/src/api/admin/orders/[id]/subscription-summary/route.js +10 -0
- package/.medusa/server/src/api/admin/orders/utils.js +8 -0
- package/.medusa/server/src/api/admin/plugin/route.js +7 -0
- package/.medusa/server/src/api/admin/renewals/[id]/approve-changes/route.js +27 -0
- package/.medusa/server/src/api/admin/renewals/[id]/force/route.js +30 -0
- package/.medusa/server/src/api/admin/renewals/[id]/reject-changes/route.js +27 -0
- package/.medusa/server/src/api/admin/renewals/[id]/route.js +10 -0
- package/.medusa/server/src/api/admin/renewals/middlewares.js +61 -0
- package/.medusa/server/src/api/admin/renewals/route.js +10 -0
- package/.medusa/server/src/api/admin/renewals/utils.js +60 -0
- package/.medusa/server/src/api/admin/renewals/validators.js +62 -0
- package/.medusa/server/src/api/admin/subscription-analytics/export/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-analytics/kpis/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-analytics/middlewares.js +45 -0
- package/.medusa/server/src/api/admin/subscription-analytics/rebuild/route.js +75 -0
- package/.medusa/server/src/api/admin/subscription-analytics/trends/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-analytics/utils.js +81 -0
- package/.medusa/server/src/api/admin/subscription-analytics/validators.js +76 -0
- package/.medusa/server/src/api/admin/subscription-logs/[id]/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-logs/middlewares.js +66 -0
- package/.medusa/server/src/api/admin/subscription-logs/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-logs/utils.js +84 -0
- package/.medusa/server/src/api/admin/subscription-logs/validators.js +32 -0
- package/.medusa/server/src/api/admin/subscription-offers/[id]/route.js +22 -0
- package/.medusa/server/src/api/admin/subscription-offers/[id]/toggle/route.js +17 -0
- package/.medusa/server/src/api/admin/subscription-offers/middlewares.js +58 -0
- package/.medusa/server/src/api/admin/subscription-offers/route.js +20 -0
- package/.medusa/server/src/api/admin/subscription-offers/utils.js +41 -0
- package/.medusa/server/src/api/admin/subscription-offers/validators.js +112 -0
- package/.medusa/server/src/api/admin/subscription-settings/middlewares.js +15 -0
- package/.medusa/server/src/api/admin/subscription-settings/route.js +33 -0
- package/.medusa/server/src/api/admin/subscription-settings/utils.js +109 -0
- package/.medusa/server/src/api/admin/subscription-settings/validators.js +74 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/cancel/route.js +18 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/logs/route.js +20 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/pause/route.js +18 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/resume/route.js +18 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/route.js +10 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/schedule-plan-change/route.js +26 -0
- package/.medusa/server/src/api/admin/subscriptions/[id]/update-shipping-address/route.js +27 -0
- package/.medusa/server/src/api/admin/subscriptions/middlewares.js +79 -0
- package/.medusa/server/src/api/admin/subscriptions/route.js +10 -0
- package/.medusa/server/src/api/admin/subscriptions/utils.js +42 -0
- package/.medusa/server/src/api/admin/subscriptions/validators.js +76 -0
- package/.medusa/server/src/api/middlewares.js +32 -0
- package/.medusa/server/src/api/store/carts/[id]/subscribe/route.js +18 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/[id]/cancellation/route.js +37 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/route.js +10 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/utils.js +104 -0
- package/.medusa/server/src/api/store/customers/me/subscriptions/validators.js +13 -0
- package/.medusa/server/src/api/store/plugin/route.js +7 -0
- package/.medusa/server/src/jobs/process-analytics-daily-snapshots.js +149 -0
- package/.medusa/server/src/jobs/process-cancellation-operational-metrics.js +102 -0
- package/.medusa/server/src/jobs/process-dunning-retries.js +249 -0
- package/.medusa/server/src/jobs/process-renewal-cycles.js +180 -0
- package/.medusa/server/src/links/cancellation-subscription.js +13 -0
- package/.medusa/server/src/links/renewal-order.js +12 -0
- package/.medusa/server/src/links/renewal-subscription.js +13 -0
- package/.medusa/server/src/links/subscription-cart.js +12 -0
- package/.medusa/server/src/links/subscription-customer.js +13 -0
- package/.medusa/server/src/links/subscription-order.js +13 -0
- package/.medusa/server/src/links/subscription-product.js +13 -0
- package/.medusa/server/src/links/subscription-variant.js +13 -0
- package/.medusa/server/src/modules/activity-log/index.js +13 -0
- package/.medusa/server/src/modules/activity-log/migrations/Migration20260401204521.js +24 -0
- package/.medusa/server/src/modules/activity-log/migrations/Migration20260405112500.js +16 -0
- package/.medusa/server/src/modules/activity-log/models/subscription-log.js +52 -0
- package/.medusa/server/src/modules/activity-log/service.js +13 -0
- package/.medusa/server/src/modules/activity-log/types/index.js +33 -0
- package/.medusa/server/src/modules/activity-log/utils/admin-query.js +261 -0
- package/.medusa/server/src/modules/activity-log/utils/normalize-log-event.js +169 -0
- package/.medusa/server/src/modules/analytics/constants.js +8 -0
- package/.medusa/server/src/modules/analytics/index.js +13 -0
- package/.medusa/server/src/modules/analytics/migrations/Migration20260402183116.js +27 -0
- package/.medusa/server/src/modules/analytics/models/subscription-metrics-daily.js +65 -0
- package/.medusa/server/src/modules/analytics/service.js +13 -0
- package/.medusa/server/src/modules/analytics/utils/admin-query.js +632 -0
- package/.medusa/server/src/modules/analytics/utils/data-quality.js +101 -0
- package/.medusa/server/src/modules/analytics/utils/observability.js +127 -0
- package/.medusa/server/src/modules/cancellation/index.js +13 -0
- package/.medusa/server/src/modules/cancellation/migrations/Migration20260401143914.js +34 -0
- package/.medusa/server/src/modules/cancellation/migrations/Migration20260405112000.js +14 -0
- package/.medusa/server/src/modules/cancellation/models/cancellation-case.js +52 -0
- package/.medusa/server/src/modules/cancellation/models/retention-offer-event.js +47 -0
- package/.medusa/server/src/modules/cancellation/service.js +15 -0
- package/.medusa/server/src/modules/cancellation/types/index.js +43 -0
- package/.medusa/server/src/modules/cancellation/utils/admin-query.js +530 -0
- package/.medusa/server/src/modules/cancellation/utils/audit.js +21 -0
- package/.medusa/server/src/modules/cancellation/utils/errors.js +31 -0
- package/.medusa/server/src/modules/cancellation/utils/observability.js +77 -0
- package/.medusa/server/src/modules/cancellation/utils/operational-metrics.js +131 -0
- package/.medusa/server/src/modules/cancellation/utils/retention-offer-policy.js +31 -0
- package/.medusa/server/src/modules/dunning/index.js +13 -0
- package/.medusa/server/src/modules/dunning/migrations/Migration20260330190157.js +36 -0
- package/.medusa/server/src/modules/dunning/models/dunning-attempt.js +48 -0
- package/.medusa/server/src/modules/dunning/models/dunning-case.js +61 -0
- package/.medusa/server/src/modules/dunning/service.js +15 -0
- package/.medusa/server/src/modules/dunning/types/index.js +19 -0
- package/.medusa/server/src/modules/dunning/utils/admin-query.js +548 -0
- package/.medusa/server/src/modules/dunning/utils/errors.js +40 -0
- package/.medusa/server/src/modules/dunning/utils/observability.js +109 -0
- package/.medusa/server/src/modules/dunning/utils/retry-schedule.js +47 -0
- package/.medusa/server/src/modules/dunning/utils/scheduler-query.js +42 -0
- package/.medusa/server/src/modules/plan-offer/index.js +13 -0
- package/.medusa/server/src/modules/plan-offer/migrations/Migration20260329104245.js +22 -0
- package/.medusa/server/src/modules/plan-offer/migrations/Migration20260329153000.js +25 -0
- package/.medusa/server/src/modules/plan-offer/models/plan-offer.js +35 -0
- package/.medusa/server/src/modules/plan-offer/service.js +13 -0
- package/.medusa/server/src/modules/plan-offer/types/index.js +26 -0
- package/.medusa/server/src/modules/plan-offer/utils/admin-query.js +429 -0
- package/.medusa/server/src/modules/plan-offer/utils/effective-config.js +84 -0
- package/.medusa/server/src/modules/plan-offer/utils/errors.js +55 -0
- package/.medusa/server/src/modules/renewal/index.js +13 -0
- package/.medusa/server/src/modules/renewal/migrations/Migration20260329185930.js +34 -0
- package/.medusa/server/src/modules/renewal/models/renewal-attempt.js +49 -0
- package/.medusa/server/src/modules/renewal/models/renewal-cycle.js +56 -0
- package/.medusa/server/src/modules/renewal/service.js +15 -0
- package/.medusa/server/src/modules/renewal/types/index.js +23 -0
- package/.medusa/server/src/modules/renewal/utils/admin-query.js +450 -0
- package/.medusa/server/src/modules/renewal/utils/errors.js +39 -0
- package/.medusa/server/src/modules/renewal/utils/observability.js +89 -0
- package/.medusa/server/src/modules/renewal/utils/scheduler-query.js +48 -0
- package/.medusa/server/src/modules/renewal/utils/upcoming-cycle.js +54 -0
- package/.medusa/server/src/modules/settings/index.js +13 -0
- package/.medusa/server/src/modules/settings/migrations/Migration20260403121004.js +17 -0
- package/.medusa/server/src/modules/settings/migrations/Migration20260403132519.js +17 -0
- package/.medusa/server/src/modules/settings/models/subscription-settings.js +32 -0
- package/.medusa/server/src/modules/settings/service.js +82 -0
- package/.medusa/server/src/modules/settings/types.js +15 -0
- package/.medusa/server/src/modules/settings/utils/audit.js +43 -0
- package/.medusa/server/src/modules/settings/utils/normalize-settings.js +99 -0
- package/.medusa/server/src/modules/subscription/index.js +13 -0
- package/.medusa/server/src/modules/subscription/migrations/Migration20260327143452.js +24 -0
- package/.medusa/server/src/modules/subscription/migrations/Migration20260329194835.js +16 -0
- package/.medusa/server/src/modules/subscription/models/subscription.js +64 -0
- package/.medusa/server/src/modules/subscription/service.js +13 -0
- package/.medusa/server/src/modules/subscription/types/index.js +17 -0
- package/.medusa/server/src/modules/subscription/utils/admin-query.js +465 -0
- package/.medusa/server/src/modules/subscription/utils/errors.js +28 -0
- package/.medusa/server/src/subscription-flows/create-subscription-from-cart.js +178 -0
- package/.medusa/server/src/workflows/apply-retention-offer.js +52 -0
- package/.medusa/server/src/workflows/approve-renewal-changes.js +61 -0
- package/.medusa/server/src/workflows/cancel-subscription.js +64 -0
- package/.medusa/server/src/workflows/create-or-upsert-plan-offer.js +11 -0
- package/.medusa/server/src/workflows/ensure-next-renewal-cycle.js +11 -0
- package/.medusa/server/src/workflows/finalize-cancellation.js +88 -0
- package/.medusa/server/src/workflows/force-renewal-cycle.js +11 -0
- package/.medusa/server/src/workflows/index.js +79 -0
- package/.medusa/server/src/workflows/mark-dunning-recovered.js +11 -0
- package/.medusa/server/src/workflows/mark-dunning-unrecovered.js +11 -0
- package/.medusa/server/src/workflows/pause-subscription.js +61 -0
- package/.medusa/server/src/workflows/process-renewal-cycle.js +43 -0
- package/.medusa/server/src/workflows/rebuild-analytics-daily-snapshots.js +13 -0
- package/.medusa/server/src/workflows/reject-renewal-changes.js +61 -0
- package/.medusa/server/src/workflows/resume-subscription.js +76 -0
- package/.medusa/server/src/workflows/run-dunning-retry.js +23 -0
- package/.medusa/server/src/workflows/schedule-subscription-plan-change.js +57 -0
- package/.medusa/server/src/workflows/start-cancellation-case.js +58 -0
- package/.medusa/server/src/workflows/start-dunning.js +11 -0
- package/.medusa/server/src/workflows/steps/apply-retention-offer.js +200 -0
- package/.medusa/server/src/workflows/steps/approve-renewal-changes.js +48 -0
- package/.medusa/server/src/workflows/steps/cancel-subscription.js +48 -0
- package/.medusa/server/src/workflows/steps/create-initial-renewal-cycle.js +6 -0
- package/.medusa/server/src/workflows/steps/create-subscription-log-event.js +61 -0
- package/.medusa/server/src/workflows/steps/create-subscription-record.js +56 -0
- package/.medusa/server/src/workflows/steps/ensure-next-renewal-cycle.js +151 -0
- package/.medusa/server/src/workflows/steps/finalize-cancellation.js +161 -0
- package/.medusa/server/src/workflows/steps/force-renewal-cycle.js +120 -0
- package/.medusa/server/src/workflows/steps/link-subscription-commerce-entities.js +44 -0
- package/.medusa/server/src/workflows/steps/mark-dunning-recovered.js +72 -0
- package/.medusa/server/src/workflows/steps/mark-dunning-unrecovered.js +53 -0
- package/.medusa/server/src/workflows/steps/normalize-analytics-rebuild-range.js +59 -0
- package/.medusa/server/src/workflows/steps/pause-subscription.js +50 -0
- package/.medusa/server/src/workflows/steps/process-renewal-cycle.js +641 -0
- package/.medusa/server/src/workflows/steps/rebuild-analytics-daily-snapshots.js +519 -0
- package/.medusa/server/src/workflows/steps/reject-renewal-changes.js +48 -0
- package/.medusa/server/src/workflows/steps/resume-subscription.js +45 -0
- package/.medusa/server/src/workflows/steps/run-dunning-retry.js +592 -0
- package/.medusa/server/src/workflows/steps/schedule-subscription-plan-change.js +81 -0
- package/.medusa/server/src/workflows/steps/shared-cancellation-log.js +3 -0
- package/.medusa/server/src/workflows/steps/shared-plan-offer.js +280 -0
- package/.medusa/server/src/workflows/steps/shared-renewal-approval.js +34 -0
- package/.medusa/server/src/workflows/steps/start-cancellation-case.js +147 -0
- package/.medusa/server/src/workflows/steps/start-dunning.js +237 -0
- package/.medusa/server/src/workflows/steps/toggle-plan-offer.js +33 -0
- package/.medusa/server/src/workflows/steps/update-cancellation-reason.js +95 -0
- package/.medusa/server/src/workflows/steps/update-dunning-retry-schedule.js +91 -0
- package/.medusa/server/src/workflows/steps/update-plan-offer.js +51 -0
- package/.medusa/server/src/workflows/steps/update-subscription-settings.js +91 -0
- package/.medusa/server/src/workflows/steps/update-subscription-shipping-address.js +54 -0
- package/.medusa/server/src/workflows/steps/upsert-plan-offer.js +48 -0
- package/.medusa/server/src/workflows/steps/validate-subscription-cart.js +280 -0
- package/.medusa/server/src/workflows/toggle-plan-offer.js +11 -0
- package/.medusa/server/src/workflows/update-cancellation-reason.js +53 -0
- package/.medusa/server/src/workflows/update-dunning-retry-schedule.js +11 -0
- package/.medusa/server/src/workflows/update-plan-offer.js +11 -0
- package/.medusa/server/src/workflows/update-subscription-settings.js +11 -0
- package/.medusa/server/src/workflows/update-subscription-shipping-address.js +99 -0
- package/.medusa/server/src/workflows/utils/analytics-incremental.js +24 -0
- package/.medusa/server/src/workflows/utils/date-output.js +13 -0
- package/.medusa/server/src/workflows/utils/subscription-settings.js +13 -0
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/package.json +73 -0
|
@@ -0,0 +1,592 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runDunningRetryStep = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
6
|
+
const core_flows_1 = require("@medusajs/medusa/core-flows");
|
|
7
|
+
const dunning_1 = require("../../modules/dunning");
|
|
8
|
+
const types_1 = require("../../modules/dunning/types");
|
|
9
|
+
const errors_1 = require("../../modules/dunning/utils/errors");
|
|
10
|
+
const observability_1 = require("../../modules/dunning/utils/observability");
|
|
11
|
+
const retry_schedule_1 = require("../../modules/dunning/utils/retry-schedule");
|
|
12
|
+
const subscription_1 = require("../../modules/subscription");
|
|
13
|
+
const types_2 = require("../../modules/subscription/types");
|
|
14
|
+
const errors_2 = require("../../modules/subscription/utils/errors");
|
|
15
|
+
function appendRetryAuditMetadata(metadata, input, at) {
|
|
16
|
+
const nextMetadata = {
|
|
17
|
+
...(metadata ?? {}),
|
|
18
|
+
last_retry_triggered_by: input.triggered_by ?? null,
|
|
19
|
+
last_retry_reason: input.reason ?? null,
|
|
20
|
+
};
|
|
21
|
+
if (!input.ignore_schedule) {
|
|
22
|
+
return nextMetadata;
|
|
23
|
+
}
|
|
24
|
+
const existing = Array.isArray(metadata?.manual_actions)
|
|
25
|
+
? [...metadata?.manual_actions]
|
|
26
|
+
: [];
|
|
27
|
+
existing.push({
|
|
28
|
+
action: "retry_now",
|
|
29
|
+
who: input.triggered_by ?? null,
|
|
30
|
+
when: at,
|
|
31
|
+
reason: input.reason ?? null,
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
...nextMetadata,
|
|
35
|
+
manual_actions: existing,
|
|
36
|
+
last_manual_action: existing[existing.length - 1],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function normalizeNow(now) {
|
|
40
|
+
if (!now) {
|
|
41
|
+
return new Date();
|
|
42
|
+
}
|
|
43
|
+
const normalized = now instanceof Date ? now : new Date(now);
|
|
44
|
+
if (Number.isNaN(normalized.getTime())) {
|
|
45
|
+
throw errors_1.dunningErrors.invalidData("Dunning retry 'now' must be a valid date");
|
|
46
|
+
}
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
async function loadDunningCase(container, id) {
|
|
50
|
+
const dunningModule = container.resolve(dunning_1.DUNNING_MODULE);
|
|
51
|
+
try {
|
|
52
|
+
return (await dunningModule.retrieveDunningCase(id));
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
throw errors_1.dunningErrors.notFound("DunningCase", id);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function loadSubscription(container, id) {
|
|
59
|
+
const subscriptionModule = container.resolve(subscription_1.SUBSCRIPTION_MODULE);
|
|
60
|
+
try {
|
|
61
|
+
return (await subscriptionModule.retrieveSubscription(id));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
throw errors_2.subscriptionErrors.notFound("Subscription", id);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
async function getNextAttemptNo(container, dunningCase) {
|
|
68
|
+
const dunningModule = container.resolve(dunning_1.DUNNING_MODULE);
|
|
69
|
+
const attempts = (await dunningModule.listDunningAttempts({
|
|
70
|
+
dunning_case_id: dunningCase.id,
|
|
71
|
+
}));
|
|
72
|
+
const highestAttemptNo = attempts.reduce((max, attempt) => {
|
|
73
|
+
return Math.max(max, attempt.attempt_no ?? 0);
|
|
74
|
+
}, 0);
|
|
75
|
+
return Math.max(dunningCase.attempt_count, highestAttemptNo) + 1;
|
|
76
|
+
}
|
|
77
|
+
async function loadOrderTotal(container, id) {
|
|
78
|
+
const query = container.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
79
|
+
const { data } = await query.graph({
|
|
80
|
+
entity: "order",
|
|
81
|
+
fields: ["id", "total"],
|
|
82
|
+
filters: {
|
|
83
|
+
id: [id],
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
const order = data[0];
|
|
87
|
+
if (!order) {
|
|
88
|
+
throw errors_1.dunningErrors.notFound("Order", id);
|
|
89
|
+
}
|
|
90
|
+
return Number(order.total ?? 0);
|
|
91
|
+
}
|
|
92
|
+
function validateRetryableCase(dunningCase, now, ignoreSchedule) {
|
|
93
|
+
if (dunningCase.status === types_1.DunningCaseStatus.RECOVERED) {
|
|
94
|
+
throw errors_1.dunningErrors.alreadyRecovered(dunningCase.id);
|
|
95
|
+
}
|
|
96
|
+
if (dunningCase.status === types_1.DunningCaseStatus.UNRECOVERED) {
|
|
97
|
+
throw errors_1.dunningErrors.alreadyUnrecovered(dunningCase.id);
|
|
98
|
+
}
|
|
99
|
+
if (dunningCase.status === types_1.DunningCaseStatus.RETRYING) {
|
|
100
|
+
throw errors_1.dunningErrors.retryAlreadyProcessing(dunningCase.id);
|
|
101
|
+
}
|
|
102
|
+
if (!dunningCase.renewal_order_id) {
|
|
103
|
+
throw errors_1.dunningErrors.invalidData(`DunningCase '${dunningCase.id}' is missing renewal_order_id`);
|
|
104
|
+
}
|
|
105
|
+
if (!dunningCase.retry_schedule) {
|
|
106
|
+
throw errors_1.dunningErrors.invalidData(`DunningCase '${dunningCase.id}' is missing retry_schedule`);
|
|
107
|
+
}
|
|
108
|
+
if (!ignoreSchedule && !dunningCase.next_retry_at) {
|
|
109
|
+
throw errors_1.dunningErrors.retryNotDue(dunningCase.id);
|
|
110
|
+
}
|
|
111
|
+
if (!ignoreSchedule && dunningCase.next_retry_at && dunningCase.next_retry_at > now) {
|
|
112
|
+
throw errors_1.dunningErrors.retryNotDue(dunningCase.id);
|
|
113
|
+
}
|
|
114
|
+
if (dunningCase.attempt_count >= dunningCase.max_attempts) {
|
|
115
|
+
throw errors_1.dunningErrors.maxAttemptsExceeded(dunningCase.id);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function classifyPaymentRetryFailure(error, paymentSessionStatus) {
|
|
119
|
+
const message = error instanceof Error ? error.message : "Dunning payment retry failed";
|
|
120
|
+
const normalizedMessage = message.toLowerCase();
|
|
121
|
+
const normalizedStatus = String(paymentSessionStatus ?? "").toLowerCase();
|
|
122
|
+
const normalizedErrorCode = readPaymentErrorCode(error);
|
|
123
|
+
if (normalizedStatus === "requires_more" ||
|
|
124
|
+
normalizedStatus === "canceled" ||
|
|
125
|
+
normalizedStatus === "cancelled") {
|
|
126
|
+
return {
|
|
127
|
+
kind: "permanent_failure",
|
|
128
|
+
payment_reference: null,
|
|
129
|
+
error_code: normalizedStatus || "payment_requires_manual_action",
|
|
130
|
+
error_message: message,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
if (normalizedErrorCode === "insufficient_funds" ||
|
|
134
|
+
normalizedErrorCode === "generic_decline" ||
|
|
135
|
+
normalizedErrorCode === "do_not_honor") {
|
|
136
|
+
return {
|
|
137
|
+
kind: "temporary_failure",
|
|
138
|
+
payment_reference: null,
|
|
139
|
+
error_code: normalizedErrorCode,
|
|
140
|
+
error_message: message,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
if (normalizedMessage.includes("missing payment retry context") ||
|
|
144
|
+
normalizedMessage.includes("doesn't have a collectible total") ||
|
|
145
|
+
normalizedMessage.includes("no payment collection is available") ||
|
|
146
|
+
normalizedMessage.includes("expired") ||
|
|
147
|
+
normalizedMessage.includes("declined") ||
|
|
148
|
+
normalizedMessage.includes("requires payment method") ||
|
|
149
|
+
normalizedMessage.includes("requires more")) {
|
|
150
|
+
return {
|
|
151
|
+
kind: "permanent_failure",
|
|
152
|
+
payment_reference: null,
|
|
153
|
+
error_code: normalizedStatus || "payment_declined",
|
|
154
|
+
error_message: message,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (normalizedStatus === "pending" ||
|
|
158
|
+
normalizedStatus === "error" ||
|
|
159
|
+
normalizedMessage.includes("insufficient") ||
|
|
160
|
+
normalizedMessage.includes("generic_decline") ||
|
|
161
|
+
normalizedMessage.includes("do_not_honor") ||
|
|
162
|
+
normalizedMessage.includes("timeout") ||
|
|
163
|
+
normalizedMessage.includes("temporar") ||
|
|
164
|
+
normalizedMessage.includes("network") ||
|
|
165
|
+
normalizedMessage.includes("unavailable")) {
|
|
166
|
+
return {
|
|
167
|
+
kind: "temporary_failure",
|
|
168
|
+
payment_reference: null,
|
|
169
|
+
error_code: normalizedStatus || "payment_retryable_error",
|
|
170
|
+
error_message: message,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
kind: "temporary_failure",
|
|
175
|
+
payment_reference: null,
|
|
176
|
+
error_code: normalizedErrorCode || normalizedStatus || "payment_retry_failed",
|
|
177
|
+
error_message: message,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
function readPaymentErrorCode(error) {
|
|
181
|
+
if (!error || typeof error !== "object") {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const record = error;
|
|
185
|
+
const candidates = [
|
|
186
|
+
record.code,
|
|
187
|
+
record.decline_code,
|
|
188
|
+
record.cause?.code,
|
|
189
|
+
record.cause?.decline_code,
|
|
190
|
+
record.payment_intent?.last_payment_error,
|
|
191
|
+
record.raw?.code,
|
|
192
|
+
record.raw?.decline_code,
|
|
193
|
+
];
|
|
194
|
+
for (const candidate of candidates) {
|
|
195
|
+
const value = readNestedErrorCode(candidate);
|
|
196
|
+
if (value) {
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
function readNestedErrorCode(value) {
|
|
203
|
+
if (!value) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
if (typeof value === "string" && value.trim()) {
|
|
207
|
+
return value.trim().toLowerCase();
|
|
208
|
+
}
|
|
209
|
+
if (typeof value === "object") {
|
|
210
|
+
const record = value;
|
|
211
|
+
const candidates = [record.code, record.decline_code];
|
|
212
|
+
for (const candidate of candidates) {
|
|
213
|
+
if (typeof candidate === "string" && candidate.trim()) {
|
|
214
|
+
return candidate.trim().toLowerCase();
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
async function executePaymentRetry(container, subscription, renewalOrderId) {
|
|
221
|
+
let paymentSession = null;
|
|
222
|
+
try {
|
|
223
|
+
const paymentContext = subscription.payment_context;
|
|
224
|
+
if (!paymentContext?.payment_provider_id ||
|
|
225
|
+
!paymentContext.payment_method_reference) {
|
|
226
|
+
throw errors_1.dunningErrors.invalidData(`Subscription '${subscription.id}' is missing payment retry context`);
|
|
227
|
+
}
|
|
228
|
+
const total = await loadOrderTotal(container, renewalOrderId);
|
|
229
|
+
if (total <= 0) {
|
|
230
|
+
throw errors_1.dunningErrors.invalidData(`Renewal order '${renewalOrderId}' doesn't have a collectible total`);
|
|
231
|
+
}
|
|
232
|
+
const paymentCollections = await (0, core_flows_1.createOrUpdateOrderPaymentCollectionWorkflow)(container).run({
|
|
233
|
+
input: {
|
|
234
|
+
order_id: renewalOrderId,
|
|
235
|
+
amount: total,
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
const paymentCollection = paymentCollections.result[0];
|
|
239
|
+
if (!paymentCollection) {
|
|
240
|
+
throw errors_1.dunningErrors.invalidData(`No payment collection is available for renewal order '${renewalOrderId}'`);
|
|
241
|
+
}
|
|
242
|
+
const paymentSessionResult = await (0, core_flows_1.createPaymentSessionsWorkflow)(container).run({
|
|
243
|
+
input: {
|
|
244
|
+
payment_collection_id: paymentCollection.id,
|
|
245
|
+
provider_id: paymentContext.payment_provider_id,
|
|
246
|
+
customer_id: subscription.customer_id,
|
|
247
|
+
data: {
|
|
248
|
+
payment_method: paymentContext.payment_method_reference,
|
|
249
|
+
off_session: true,
|
|
250
|
+
confirm: true,
|
|
251
|
+
capture_method: "automatic",
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
});
|
|
255
|
+
paymentSession = paymentSessionResult.result;
|
|
256
|
+
const paymentModule = container.resolve(utils_1.Modules.PAYMENT);
|
|
257
|
+
const payment = (await paymentModule.authorizePaymentSession(paymentSession.id, paymentSession.context ?? {}));
|
|
258
|
+
if (!payment?.id) {
|
|
259
|
+
return {
|
|
260
|
+
kind: "temporary_failure",
|
|
261
|
+
payment_reference: paymentSession.id,
|
|
262
|
+
error_code: "payment_authorization_missing",
|
|
263
|
+
error_message: "Payment authorization did not return a payment reference",
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
await paymentModule.capturePayment({
|
|
267
|
+
payment_id: payment.id,
|
|
268
|
+
amount: payment.amount,
|
|
269
|
+
});
|
|
270
|
+
return {
|
|
271
|
+
kind: "recovery",
|
|
272
|
+
payment_reference: payment.id,
|
|
273
|
+
error_code: null,
|
|
274
|
+
error_message: null,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
let paymentSessionStatus = paymentSession?.status ?? null;
|
|
279
|
+
if (paymentSession?.id) {
|
|
280
|
+
const paymentModule = container.resolve(utils_1.Modules.PAYMENT);
|
|
281
|
+
const sessions = (await paymentModule.listPaymentSessions({
|
|
282
|
+
id: [paymentSession.id],
|
|
283
|
+
}));
|
|
284
|
+
paymentSessionStatus = sessions[0]?.status ?? paymentSessionStatus;
|
|
285
|
+
}
|
|
286
|
+
const outcome = classifyPaymentRetryFailure(error, paymentSessionStatus);
|
|
287
|
+
return {
|
|
288
|
+
...outcome,
|
|
289
|
+
payment_reference: paymentSession?.id ?? outcome.payment_reference,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
exports.runDunningRetryStep = (0, workflows_sdk_1.createStep)("run-dunning-retry", async function (input, { container }) {
|
|
294
|
+
const logger = container.resolve("logger");
|
|
295
|
+
const dunningModule = container.resolve(dunning_1.DUNNING_MODULE);
|
|
296
|
+
const subscriptionModule = container.resolve(subscription_1.SUBSCRIPTION_MODULE);
|
|
297
|
+
const now = normalizeNow(input.now);
|
|
298
|
+
const startedAtMs = Date.now();
|
|
299
|
+
const correlationId = input.correlation_id ??
|
|
300
|
+
(0, observability_1.createDunningCorrelationId)(`dunning-retry-${input.ignore_schedule ? "manual" : "scheduled"}`);
|
|
301
|
+
const dunningCase = await loadDunningCase(container, input.dunning_case_id);
|
|
302
|
+
const attemptNo = await getNextAttemptNo(container, dunningCase);
|
|
303
|
+
const transitionSnapshot = {
|
|
304
|
+
status: dunningCase.status,
|
|
305
|
+
attempt_count: dunningCase.attempt_count,
|
|
306
|
+
next_retry_at: dunningCase.next_retry_at,
|
|
307
|
+
last_attempt_at: dunningCase.last_attempt_at,
|
|
308
|
+
metadata: dunningCase.metadata ?? null,
|
|
309
|
+
};
|
|
310
|
+
let transitionedToRetrying = false;
|
|
311
|
+
(0, observability_1.logDunningEvent)(logger, "info", {
|
|
312
|
+
event: "dunning.retry",
|
|
313
|
+
outcome: "started",
|
|
314
|
+
correlation_id: correlationId,
|
|
315
|
+
dunning_case_id: dunningCase.id,
|
|
316
|
+
subscription_id: dunningCase.subscription_id,
|
|
317
|
+
renewal_cycle_id: dunningCase.renewal_cycle_id,
|
|
318
|
+
attempt_no: attemptNo,
|
|
319
|
+
metadata: {
|
|
320
|
+
triggered_by: input.triggered_by ?? null,
|
|
321
|
+
reason: input.reason ?? null,
|
|
322
|
+
ignore_schedule: Boolean(input.ignore_schedule),
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
try {
|
|
326
|
+
validateRetryableCase(dunningCase, now, input.ignore_schedule);
|
|
327
|
+
const subscription = await loadSubscription(container, dunningCase.subscription_id);
|
|
328
|
+
if (subscription.status !== types_2.SubscriptionStatus.PAST_DUE &&
|
|
329
|
+
subscription.status !== types_2.SubscriptionStatus.ACTIVE) {
|
|
330
|
+
throw errors_2.subscriptionErrors.invalidState(subscription.id, "run dunning retry", subscription.status);
|
|
331
|
+
}
|
|
332
|
+
const startedAt = now;
|
|
333
|
+
await dunningModule.updateDunningCases({
|
|
334
|
+
id: dunningCase.id,
|
|
335
|
+
status: types_1.DunningCaseStatus.RETRYING,
|
|
336
|
+
attempt_count: attemptNo,
|
|
337
|
+
next_retry_at: null,
|
|
338
|
+
last_attempt_at: startedAt,
|
|
339
|
+
metadata: appendRetryAuditMetadata(dunningCase.metadata, input, startedAt.toISOString()),
|
|
340
|
+
});
|
|
341
|
+
transitionedToRetrying = true;
|
|
342
|
+
const attempt = (await dunningModule.createDunningAttempts({
|
|
343
|
+
dunning_case_id: dunningCase.id,
|
|
344
|
+
attempt_no: attemptNo,
|
|
345
|
+
started_at: startedAt,
|
|
346
|
+
finished_at: null,
|
|
347
|
+
status: types_1.DunningAttemptStatus.PROCESSING,
|
|
348
|
+
error_code: null,
|
|
349
|
+
error_message: null,
|
|
350
|
+
payment_reference: null,
|
|
351
|
+
metadata: {
|
|
352
|
+
triggered_by: input.triggered_by ?? null,
|
|
353
|
+
reason: input.reason ?? null,
|
|
354
|
+
correlation_id: correlationId,
|
|
355
|
+
},
|
|
356
|
+
}));
|
|
357
|
+
const outcome = await executePaymentRetry(container, subscription, dunningCase.renewal_order_id);
|
|
358
|
+
const finishedAt = new Date();
|
|
359
|
+
if (outcome.kind === "recovery") {
|
|
360
|
+
await dunningModule.updateDunningAttempts({
|
|
361
|
+
id: attempt.id,
|
|
362
|
+
finished_at: finishedAt,
|
|
363
|
+
status: types_1.DunningAttemptStatus.SUCCEEDED,
|
|
364
|
+
error_code: null,
|
|
365
|
+
error_message: null,
|
|
366
|
+
payment_reference: outcome.payment_reference,
|
|
367
|
+
});
|
|
368
|
+
const updatedCase = await dunningModule.updateDunningCases({
|
|
369
|
+
id: dunningCase.id,
|
|
370
|
+
status: types_1.DunningCaseStatus.RECOVERED,
|
|
371
|
+
next_retry_at: null,
|
|
372
|
+
last_attempt_at: finishedAt,
|
|
373
|
+
last_payment_error_code: null,
|
|
374
|
+
last_payment_error_message: null,
|
|
375
|
+
recovered_at: finishedAt,
|
|
376
|
+
closed_at: finishedAt,
|
|
377
|
+
recovery_reason: "payment_recovered",
|
|
378
|
+
});
|
|
379
|
+
if (subscription.status === types_2.SubscriptionStatus.PAST_DUE) {
|
|
380
|
+
await subscriptionModule.updateSubscriptions({
|
|
381
|
+
id: subscription.id,
|
|
382
|
+
status: types_2.SubscriptionStatus.ACTIVE,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
const createdAt = updatedCase.created_at
|
|
386
|
+
? new Date(updatedCase.created_at)
|
|
387
|
+
: dunningCase.created_at
|
|
388
|
+
? new Date(dunningCase.created_at)
|
|
389
|
+
: null;
|
|
390
|
+
const timeToRecoverMs = createdAt
|
|
391
|
+
? finishedAt.getTime() - createdAt.getTime()
|
|
392
|
+
: null;
|
|
393
|
+
(0, observability_1.logDunningEvent)(logger, "info", {
|
|
394
|
+
event: "dunning.retry",
|
|
395
|
+
outcome: "succeeded",
|
|
396
|
+
correlation_id: correlationId,
|
|
397
|
+
dunning_case_id: updatedCase.id,
|
|
398
|
+
subscription_id: updatedCase.subscription_id,
|
|
399
|
+
renewal_cycle_id: updatedCase.renewal_cycle_id,
|
|
400
|
+
attempt_no: attemptNo,
|
|
401
|
+
duration_ms: Date.now() - startedAtMs,
|
|
402
|
+
success_count: 1,
|
|
403
|
+
recovered_count: 1,
|
|
404
|
+
avg_attempts: attemptNo,
|
|
405
|
+
avg_time_to_recover_ms: timeToRecoverMs ?? undefined,
|
|
406
|
+
metadata: {
|
|
407
|
+
retry_outcome: "recovered",
|
|
408
|
+
payment_reference: outcome.payment_reference,
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
return new workflows_sdk_1.StepResponse({
|
|
412
|
+
dunning_case_id: updatedCase.id,
|
|
413
|
+
dunning_attempt_id: attempt.id,
|
|
414
|
+
outcome: "recovered",
|
|
415
|
+
subscription_status: types_2.SubscriptionStatus.ACTIVE,
|
|
416
|
+
correlation_id: correlationId,
|
|
417
|
+
attempt_no: attemptNo,
|
|
418
|
+
time_to_recover_ms: timeToRecoverMs,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
await dunningModule.updateDunningAttempts({
|
|
422
|
+
id: attempt.id,
|
|
423
|
+
finished_at: finishedAt,
|
|
424
|
+
status: types_1.DunningAttemptStatus.FAILED,
|
|
425
|
+
error_code: outcome.error_code,
|
|
426
|
+
error_message: outcome.error_message,
|
|
427
|
+
payment_reference: outcome.payment_reference,
|
|
428
|
+
});
|
|
429
|
+
const shouldCloseAsUnrecovered = outcome.kind === "permanent_failure" ||
|
|
430
|
+
attemptNo >= dunningCase.max_attempts;
|
|
431
|
+
if (shouldCloseAsUnrecovered) {
|
|
432
|
+
const updatedCase = await dunningModule.updateDunningCases({
|
|
433
|
+
id: dunningCase.id,
|
|
434
|
+
status: types_1.DunningCaseStatus.UNRECOVERED,
|
|
435
|
+
next_retry_at: null,
|
|
436
|
+
last_attempt_at: finishedAt,
|
|
437
|
+
last_payment_error_code: outcome.error_code,
|
|
438
|
+
last_payment_error_message: outcome.error_message,
|
|
439
|
+
closed_at: finishedAt,
|
|
440
|
+
recovery_reason: outcome.kind === "permanent_failure"
|
|
441
|
+
? "permanent_payment_failure"
|
|
442
|
+
: "retry_limit_exhausted",
|
|
443
|
+
});
|
|
444
|
+
(0, observability_1.logDunningEvent)(logger, "warn", {
|
|
445
|
+
event: "dunning.retry",
|
|
446
|
+
outcome: "failed",
|
|
447
|
+
correlation_id: correlationId,
|
|
448
|
+
dunning_case_id: updatedCase.id,
|
|
449
|
+
subscription_id: updatedCase.subscription_id,
|
|
450
|
+
renewal_cycle_id: updatedCase.renewal_cycle_id,
|
|
451
|
+
attempt_no: attemptNo,
|
|
452
|
+
duration_ms: Date.now() - startedAtMs,
|
|
453
|
+
failure_count: 1,
|
|
454
|
+
unrecovered_count: 1,
|
|
455
|
+
avg_attempts: attemptNo,
|
|
456
|
+
failure_kind: "retry_exhausted",
|
|
457
|
+
alertable: outcome.kind === "permanent_failure",
|
|
458
|
+
message: outcome.error_message,
|
|
459
|
+
metadata: {
|
|
460
|
+
retry_outcome: "unrecovered",
|
|
461
|
+
error_code: outcome.error_code,
|
|
462
|
+
payment_reference: outcome.payment_reference,
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
return new workflows_sdk_1.StepResponse({
|
|
466
|
+
dunning_case_id: updatedCase.id,
|
|
467
|
+
dunning_attempt_id: attempt.id,
|
|
468
|
+
outcome: "unrecovered",
|
|
469
|
+
subscription_status: subscription.status,
|
|
470
|
+
correlation_id: correlationId,
|
|
471
|
+
attempt_no: attemptNo,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
const nextRetryAt = (0, retry_schedule_1.calculateNextRetryAt)(dunningCase.retry_schedule, attemptNo, finishedAt);
|
|
475
|
+
if (!nextRetryAt) {
|
|
476
|
+
const updatedCase = await dunningModule.updateDunningCases({
|
|
477
|
+
id: dunningCase.id,
|
|
478
|
+
status: types_1.DunningCaseStatus.UNRECOVERED,
|
|
479
|
+
next_retry_at: null,
|
|
480
|
+
last_attempt_at: finishedAt,
|
|
481
|
+
last_payment_error_code: outcome.error_code,
|
|
482
|
+
last_payment_error_message: outcome.error_message,
|
|
483
|
+
closed_at: finishedAt,
|
|
484
|
+
recovery_reason: "retry_schedule_exhausted",
|
|
485
|
+
});
|
|
486
|
+
(0, observability_1.logDunningEvent)(logger, "warn", {
|
|
487
|
+
event: "dunning.retry",
|
|
488
|
+
outcome: "failed",
|
|
489
|
+
correlation_id: correlationId,
|
|
490
|
+
dunning_case_id: updatedCase.id,
|
|
491
|
+
subscription_id: updatedCase.subscription_id,
|
|
492
|
+
renewal_cycle_id: updatedCase.renewal_cycle_id,
|
|
493
|
+
attempt_no: attemptNo,
|
|
494
|
+
duration_ms: Date.now() - startedAtMs,
|
|
495
|
+
failure_count: 1,
|
|
496
|
+
unrecovered_count: 1,
|
|
497
|
+
avg_attempts: attemptNo,
|
|
498
|
+
failure_kind: "retry_exhausted",
|
|
499
|
+
alertable: false,
|
|
500
|
+
message: outcome.error_message,
|
|
501
|
+
metadata: {
|
|
502
|
+
retry_outcome: "unrecovered",
|
|
503
|
+
error_code: outcome.error_code,
|
|
504
|
+
payment_reference: outcome.payment_reference,
|
|
505
|
+
},
|
|
506
|
+
});
|
|
507
|
+
return new workflows_sdk_1.StepResponse({
|
|
508
|
+
dunning_case_id: updatedCase.id,
|
|
509
|
+
dunning_attempt_id: attempt.id,
|
|
510
|
+
outcome: "unrecovered",
|
|
511
|
+
subscription_status: subscription.status,
|
|
512
|
+
correlation_id: correlationId,
|
|
513
|
+
attempt_no: attemptNo,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
const updatedCase = await dunningModule.updateDunningCases({
|
|
517
|
+
id: dunningCase.id,
|
|
518
|
+
status: types_1.DunningCaseStatus.RETRY_SCHEDULED,
|
|
519
|
+
next_retry_at: nextRetryAt,
|
|
520
|
+
last_attempt_at: finishedAt,
|
|
521
|
+
last_payment_error_code: outcome.error_code,
|
|
522
|
+
last_payment_error_message: outcome.error_message,
|
|
523
|
+
recovered_at: null,
|
|
524
|
+
closed_at: null,
|
|
525
|
+
recovery_reason: null,
|
|
526
|
+
});
|
|
527
|
+
(0, observability_1.logDunningEvent)(logger, "warn", {
|
|
528
|
+
event: "dunning.retry",
|
|
529
|
+
outcome: "failed",
|
|
530
|
+
correlation_id: correlationId,
|
|
531
|
+
dunning_case_id: updatedCase.id,
|
|
532
|
+
subscription_id: updatedCase.subscription_id,
|
|
533
|
+
renewal_cycle_id: updatedCase.renewal_cycle_id,
|
|
534
|
+
attempt_no: attemptNo,
|
|
535
|
+
duration_ms: Date.now() - startedAtMs,
|
|
536
|
+
failure_count: 1,
|
|
537
|
+
rescheduled_count: 1,
|
|
538
|
+
avg_attempts: attemptNo,
|
|
539
|
+
failure_kind: "unexpected_error",
|
|
540
|
+
alertable: outcome.kind === "temporary_failure",
|
|
541
|
+
message: outcome.error_message,
|
|
542
|
+
metadata: {
|
|
543
|
+
retry_outcome: "retry_scheduled",
|
|
544
|
+
error_code: outcome.error_code,
|
|
545
|
+
payment_reference: outcome.payment_reference,
|
|
546
|
+
next_retry_at: nextRetryAt.toISOString(),
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
return new workflows_sdk_1.StepResponse({
|
|
550
|
+
dunning_case_id: updatedCase.id,
|
|
551
|
+
dunning_attempt_id: attempt.id,
|
|
552
|
+
outcome: "retry_scheduled",
|
|
553
|
+
subscription_status: subscription.status,
|
|
554
|
+
correlation_id: correlationId,
|
|
555
|
+
attempt_no: attemptNo,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
catch (error) {
|
|
559
|
+
const failureKind = (0, observability_1.classifyDunningFailure)(error);
|
|
560
|
+
(0, observability_1.logDunningEvent)(logger, (0, observability_1.isAlertableDunningFailure)(failureKind) ? "error" : "warn", {
|
|
561
|
+
event: "dunning.retry",
|
|
562
|
+
outcome: (0, observability_1.isAlertableDunningFailure)(failureKind) ? "failed" : "blocked",
|
|
563
|
+
correlation_id: correlationId,
|
|
564
|
+
dunning_case_id: dunningCase.id,
|
|
565
|
+
subscription_id: dunningCase.subscription_id,
|
|
566
|
+
renewal_cycle_id: dunningCase.renewal_cycle_id,
|
|
567
|
+
attempt_no: attemptNo,
|
|
568
|
+
duration_ms: Date.now() - startedAtMs,
|
|
569
|
+
failure_count: 1,
|
|
570
|
+
failure_kind: failureKind,
|
|
571
|
+
alertable: (0, observability_1.isAlertableDunningFailure)(failureKind),
|
|
572
|
+
message: (0, observability_1.getDunningErrorMessage)(error),
|
|
573
|
+
metadata: {
|
|
574
|
+
triggered_by: input.triggered_by ?? null,
|
|
575
|
+
reason: input.reason ?? null,
|
|
576
|
+
ignore_schedule: Boolean(input.ignore_schedule),
|
|
577
|
+
},
|
|
578
|
+
});
|
|
579
|
+
if (transitionedToRetrying) {
|
|
580
|
+
await dunningModule.updateDunningCases({
|
|
581
|
+
id: dunningCase.id,
|
|
582
|
+
status: transitionSnapshot.status,
|
|
583
|
+
attempt_count: transitionSnapshot.attempt_count,
|
|
584
|
+
next_retry_at: transitionSnapshot.next_retry_at,
|
|
585
|
+
last_attempt_at: transitionSnapshot.last_attempt_at,
|
|
586
|
+
metadata: transitionSnapshot.metadata,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
throw error;
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVuLWR1bm5pbmctcmV0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvd29ya2Zsb3dzL3N0ZXBzL3J1bi1kdW5uaW5nLXJldHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUE4RTtBQUM5RSxxRUFBNEU7QUFFNUUsNERBR29DO0FBQ3BDLG1EQUFzRDtBQUV0RCx1REFJb0M7QUFDcEMsK0RBQWtFO0FBQ2xFLDZFQU1rRDtBQUNsRCwrRUFBaUY7QUFDakYsNkRBQWdFO0FBRWhFLDREQUFxRTtBQUNyRSxvRUFBNEU7QUFzRzVFLFNBQVMsd0JBQXdCLENBQy9CLFFBQXdDLEVBQ3hDLEtBQStCLEVBQy9CLEVBQVU7SUFFVixNQUFNLFlBQVksR0FBNEI7UUFDNUMsR0FBRyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFDbkIsdUJBQXVCLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxJQUFJO1FBQ25ELGlCQUFpQixFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksSUFBSTtLQUN4QyxDQUFBO0lBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUMzQixPQUFPLFlBQVksQ0FBQTtJQUNyQixDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUUsY0FBYyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDLEdBQUksUUFBUSxFQUFFLGNBQTRDLENBQUM7UUFDOUQsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtJQUVOLFFBQVEsQ0FBQyxJQUFJLENBQUM7UUFDWixNQUFNLEVBQUUsV0FBVztRQUNuQixHQUFHLEVBQUUsS0FBSyxDQUFDLFlBQVksSUFBSSxJQUFJO1FBQy9CLElBQUksRUFBRSxFQUFFO1FBQ1IsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNLElBQUksSUFBSTtLQUM3QixDQUFDLENBQUE7SUFFRixPQUFPO1FBQ0wsR0FBRyxZQUFZO1FB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
|