vonpay-medusa 1.2.0 → 1.2.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/src/admin/index.js +378 -173
- package/.medusa/server/src/admin/index.mjs +381 -176
- package/.medusa/server/src/api/admin/vonpay/holds/resolve/route.js +6 -0
- package/.medusa/server/src/api/admin/vonpay/holds/route.js +2 -1
- package/.medusa/server/src/api/admin/vonpay/setup-check/move-to-held/route.js +14 -0
- package/.medusa/server/src/api/middlewares.js +1 -0
- package/.medusa/server/src/lib/errors.js +9 -1
- package/.medusa/server/src/lib/held-charge-copy.js +176 -0
- package/.medusa/server/src/modules/vonpay-jobs/index.js +11 -0
- package/.medusa/server/src/modules/vonpay-jobs/key.js +4 -0
- package/.medusa/server/src/modules/vonpay-jobs/migrations/Migration20261105120000.js +15 -0
- package/.medusa/server/src/modules/vonpay-jobs/models/job-beat.js +20 -0
- package/.medusa/server/src/modules/vonpay-jobs/service.js +7 -0
- package/.medusa/server/src/providers/vonpay/admin-holds.js +45 -39
- package/.medusa/server/src/providers/vonpay/charge-hold.js +124 -0
- package/.medusa/server/src/providers/vonpay/deadline.js +26 -0
- package/.medusa/server/src/providers/vonpay/descriptor.js +4 -4
- package/.medusa/server/src/providers/vonpay/held-list.js +168 -26
- package/.medusa/server/src/providers/vonpay/job-beat.js +57 -0
- package/.medusa/server/src/providers/vonpay/move-to-held.js +95 -0
- package/.medusa/server/src/providers/vonpay/options.js +11 -1
- package/.medusa/server/src/providers/vonpay/reading.js +25 -2
- package/.medusa/server/src/providers/vonpay/recovery.js +44 -11
- package/.medusa/server/src/providers/vonpay/refund-after-order.js +35 -0
- package/.medusa/server/src/providers/vonpay/renewal-check.js +435 -0
- package/.medusa/server/src/providers/vonpay/renewal-recovery.js +425 -25
- package/.medusa/server/src/providers/vonpay/renewal.js +542 -39
- package/.medusa/server/src/providers/vonpay/service.js +534 -86
- package/.medusa/server/src/providers/vonpay/session-data.js +243 -9
- package/.medusa/server/src/providers/vonpay/setup-check.js +505 -5
- package/.medusa/server/src/providers/vonpay/upsell-accept.js +99 -35
- package/.medusa/server/src/scripts/vonpay-check.js +23 -1
- package/.medusa/server/src/subscribers/vonpay-order-placed.js +2 -0
- package/README.md +219 -9
- package/bin/vonpay-medusa-check.cjs +23 -3
- package/bin/vonpay-medusa.cjs +229 -4
- package/package.json +4 -3
- package/storefront/src/cache-tag.ts +7 -0
- package/storefront/src/cart-fields.ts +1 -0
- package/storefront/src/checkout-steps.ts +27 -0
- package/storefront/src/context.tsx +1 -1
- package/storefront/src/csp.ts +1 -1
- package/storefront/src/index.ts +2 -0
- package/storefront/src/offer-prepare.ts +3 -2
- package/storefront/src/payment-step.ts +99 -0
- package/storefront/src/server.ts +49 -12
- package/storefront/src/shared.ts +1 -0
- package/storefront/src/vonpay-card-payment.tsx +13 -3
- package/storefront/src/vora-csp.json +17 -3
|
@@ -9,6 +9,47 @@ const icons = require("@medusajs/icons");
|
|
|
9
9
|
const react = require("react");
|
|
10
10
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
11
11
|
const Medusa__default = /* @__PURE__ */ _interopDefault(Medusa);
|
|
12
|
+
const TIME_SLOT = "{time}";
|
|
13
|
+
function fillTime(text, at, format) {
|
|
14
|
+
return at && text.includes(TIME_SLOT) ? text.split(TIME_SLOT).join(format(at)) : text;
|
|
15
|
+
}
|
|
16
|
+
const NOT_SAVED_TEXT = "That couldn't be saved. The list is read again: check the row as it stands now before you try again.";
|
|
17
|
+
const CHARGE_REASON_LABEL = {
|
|
18
|
+
renewal_outcome_unknown: "Renewal charge — result unknown",
|
|
19
|
+
renewal_not_settled: "Renewal charge not completed",
|
|
20
|
+
renewal_charged_unrecorded: "Renewal charged, order unpaid",
|
|
21
|
+
renewal_paid_twice: "Renewal charged — order also paid another way",
|
|
22
|
+
renewal_buyer_mismatch: "Renewal charged to a different customer",
|
|
23
|
+
upsell_outcome_unknown: "Offer charge — result unknown",
|
|
24
|
+
upsell_not_settled: "Offer charge not completed",
|
|
25
|
+
upsell_paid_not_added: "Offer paid, item not added",
|
|
26
|
+
upsell_paid_unsettled: "Offer paid — check the order",
|
|
27
|
+
upsell_paid_unrecorded: "Offer paid, payment not recorded",
|
|
28
|
+
upsell_hold_not_released: "Offer payment held — release not confirmed",
|
|
29
|
+
upsell_bank_check_open: "Offer bank check still open",
|
|
30
|
+
upsell_refund_failed: "Late offer charge — refund failed",
|
|
31
|
+
upsell_refund_unclear: "Late offer charge — refund unclear",
|
|
32
|
+
upsell_refund_pending: "Late offer charge — refund in progress",
|
|
33
|
+
upsell_refunded_late: "Late offer charge refunded",
|
|
34
|
+
upsell_hold_unsettled: "Offer payment held — not finished yet",
|
|
35
|
+
upsell_take_unconfirmed: "Offer payment — collection not confirmed"
|
|
36
|
+
};
|
|
37
|
+
const CHARGE_RESOLVED_HOW_LABEL = {
|
|
38
|
+
closed_blocking: "Closed by a person — no more renewal charges for this order",
|
|
39
|
+
freed: "Freed — later renewals of this order may charge the customer",
|
|
40
|
+
closed_no_change: "Closed by a person — no change to money"
|
|
41
|
+
};
|
|
42
|
+
function chargeHandStep(paymentIntentId) {
|
|
43
|
+
return { title: "Check this order in Vonpay", body: `Find ${paymentIntentId ? `payment ${paymentIntentId}` : "any payment"} in the Vonpay dashboard by the order id, and settle it there if it needs it.` };
|
|
44
|
+
}
|
|
45
|
+
const OFFER_CLOSED_MONEY_TEXT = {
|
|
46
|
+
upsell_paid_not_added: "The buyer paid for this offer. Closing this row did not refund it or add the item: that was yours to settle in Vonpay or on the order.",
|
|
47
|
+
upsell_paid_unsettled: "The buyer paid for this offer. Closing this row did not refund it or add the item: that was yours to settle in Vonpay or on the order.",
|
|
48
|
+
upsell_paid_unrecorded: "The buyer paid, and the item is on the order. Closing this row did not mark that balance paid in Medusa: that was yours to do.",
|
|
49
|
+
upsell_refund_failed: "The buyer was charged and the item was not added. Closing this row sent no refund: that was yours to send in Vonpay.",
|
|
50
|
+
upsell_refund_unclear: "The buyer was charged and the item was not added. Closing this row sent no refund: that was yours to send in Vonpay."
|
|
51
|
+
};
|
|
52
|
+
const OFFER_CLOSED_MONEY_DEFAULT = "Closing this row moved no money. What Vonpay holds for this payment is as it was.";
|
|
12
53
|
const REASON_COPY = {
|
|
13
54
|
deleted_while_charged: {
|
|
14
55
|
label: "Charged, then cart changed",
|
|
@@ -82,78 +123,7 @@ const REASON_COPY = {
|
|
|
82
123
|
label: "Paid, order not created",
|
|
83
124
|
what: "The buyer paid, but Medusa did not create the order, even after the plugin retried it automatically. Check the cart and the payment in Vonpay, then complete the order with the buyer or refund it."
|
|
84
125
|
},
|
|
85
|
-
|
|
86
|
-
label: "Renewal charge — result unknown",
|
|
87
|
-
what: "A subscription renewal charged the customer's saved card, but Vonpay's answer could not be read, so the customer may have been charged. No further renewal charge is sent for this order. Check the payment in Vonpay before charging or refunding anything."
|
|
88
|
-
},
|
|
89
|
-
renewal_not_settled: {
|
|
90
|
-
label: "Renewal charge not completed",
|
|
91
|
-
what: "Vonpay answered the subscription renewal charge, but the payment had not completed. No further renewal charge is sent for this order. Check the payment in Vonpay."
|
|
92
|
-
},
|
|
93
|
-
renewal_charged_unrecorded: {
|
|
94
|
-
label: "Renewal charged, order unpaid",
|
|
95
|
-
what: "Vonpay charged the customer's saved card for this subscription renewal, but Medusa's records do not show the payment, even after the plugin retried it automatically (or Medusa recorded it and then cancelled it). The customer has paid; the order shows unpaid. No further renewal charge is sent for this order. Find the payment in Vonpay by the order id, then mark the order paid in Medusa — do not charge again."
|
|
96
|
-
},
|
|
97
|
-
renewal_paid_twice: {
|
|
98
|
-
label: "Renewal charged — order also paid another way",
|
|
99
|
-
what: "Vonpay charged the customer's saved card for this subscription renewal, and the order was also marked paid another way. The customer may have paid twice. Check the payment in Vonpay and the order in Medusa, then refund the extra payment. No further renewal charge is sent for this order."
|
|
100
|
-
},
|
|
101
|
-
renewal_buyer_mismatch: {
|
|
102
|
-
label: "Renewal charged to a different customer",
|
|
103
|
-
what: "Vonpay recorded the subscription renewal charge against a different customer than the order's. No further renewal charge is sent for this order. Check the payment in Vonpay."
|
|
104
|
-
},
|
|
105
|
-
upsell_outcome_unknown: {
|
|
106
|
-
label: "Offer charge — result unknown",
|
|
107
|
-
what: "The buyer accepted an offer after their order and the plugin charged their card for it, but Vonpay's answer could not be read, so the buyer may have been charged. The item was NOT added to the order, and the plugin will not try that offer again. Check the payment in Vonpay by the order id: if it was charged, add the item to the order (or refund it in Vonpay); if not, cancel the open order edit in Medusa."
|
|
108
|
-
},
|
|
109
|
-
upsell_not_settled: {
|
|
110
|
-
label: "Offer charge not completed",
|
|
111
|
-
what: "The buyer accepted an offer after their order, and Vonpay answered the charge, but the payment had not completed. The item was NOT added to the order. Check the payment in Vonpay by the order id, then cancel the open order edit in Medusa if nothing was charged."
|
|
112
|
-
},
|
|
113
|
-
upsell_paid_not_added: {
|
|
114
|
-
label: "Offer paid, item not added",
|
|
115
|
-
what: "The buyer accepted an offer after their order and paid for it, but the item was NOT added to the order, even after the plugin retried. The buyer has paid. Either add the item to the order in Medusa, or refund the charge in Vonpay — not both, and do not charge again."
|
|
116
|
-
},
|
|
117
|
-
upsell_paid_unsettled: {
|
|
118
|
-
label: "Offer paid — check the order",
|
|
119
|
-
what: "The buyer accepted an offer after their order and paid for it, but the plugin could not finish recording it. Open the order first. If the item is on it, mark that balance paid in Medusa (do NOT refund — the item ships). If the item is not on it, either add it or refund the charge in Vonpay — not both. Never charge again."
|
|
120
|
-
},
|
|
121
|
-
upsell_paid_unrecorded: {
|
|
122
|
-
label: "Offer paid, payment not recorded",
|
|
123
|
-
what: "The buyer accepted an offer after their order and paid for it, and the item IS on the order, but Medusa did not record the payment, even after the plugin retried — so the order shows an unpaid balance. The buyer has paid. Find the payment in Vonpay by the order id and mark that balance paid in Medusa. Do NOT refund it (the item ships) and do not charge again."
|
|
124
|
-
},
|
|
125
|
-
upsell_hold_not_released: {
|
|
126
|
-
label: "Offer payment held — release not confirmed",
|
|
127
|
-
what: "The buyer approved an offer after their order with Apple Pay or Google Pay, which only held the money. The item could not be added, so the plugin released the hold, but Vonpay has not confirmed the release. Nothing was taken and the item was NOT added. The plugin keeps releasing it on every run. If this row stays, find the payment in Vonpay by the order id and void it there. Do not take it."
|
|
128
|
-
},
|
|
129
|
-
upsell_bank_check_open: {
|
|
130
|
-
label: "Offer bank check still open",
|
|
131
|
-
what: "The offer ended while the buyer's bank check was still open, so nothing was added and the order change was undone. If the bank approves it later, the plugin refunds it automatically. Nothing to do unless this stays for a few days; then check the payment in Vonpay by the order id."
|
|
132
|
-
},
|
|
133
|
-
upsell_refund_failed: {
|
|
134
|
-
label: "Late offer charge — refund failed",
|
|
135
|
-
what: "The buyer was charged for an offer whose item was NOT added to the order — the bank approved it after the offer had ended, the item could not be added, or an earlier declined attempt was approved after all — so the plugin tried to refund that charge in full, but the refund did not go through (refused, or not settled within 48 hours). Refund the payment in Vonpay by the order id. Do not add the item."
|
|
136
|
-
},
|
|
137
|
-
upsell_refund_unclear: {
|
|
138
|
-
label: "Late offer charge — refund unclear",
|
|
139
|
-
what: "The buyer was charged for an offer whose item was NOT added to the order, and the plugin's automatic refund got an unclear answer: Vonpay reported an error, then recorded that refund as failed, but the money may have gone back anyway. The plugin will not send another refund. First check the payment in Vonpay by the order id: refund it there ONLY if no refund went through. Do not add the item."
|
|
140
|
-
},
|
|
141
|
-
upsell_refund_pending: {
|
|
142
|
-
label: "Late offer charge — refund in progress",
|
|
143
|
-
what: "The buyer's bank approved an offer after the offer had ended, so nothing was added and the plugin is refunding the charge in full. It keeps retrying. If this row stays for a day, refund the payment in Vonpay by the order id."
|
|
144
|
-
},
|
|
145
|
-
upsell_refunded_late: {
|
|
146
|
-
label: "Late offer charge refunded",
|
|
147
|
-
what: "The buyer's bank approved an offer after the offer had ended, so nothing was added and the plugin refunded the charge in full. Nothing to do."
|
|
148
|
-
},
|
|
149
|
-
upsell_hold_unsettled: {
|
|
150
|
-
label: "Offer payment held — not finished yet",
|
|
151
|
-
what: "The buyer approved an offer after their order with Apple Pay or Google Pay, which only held the money, and the plugin has not finished it yet. Nothing was taken. The plugin keeps working on it: it adds the item and takes the money, or releases the hold if the item cannot be added. Do not take or void it yourself unless this row stays for more than a day; then check the payment in Vonpay by the order id."
|
|
152
|
-
},
|
|
153
|
-
upsell_take_unconfirmed: {
|
|
154
|
-
label: "Offer payment — collection not confirmed",
|
|
155
|
-
what: "The buyer approved an offer after their order with Apple Pay or Google Pay, and the plugin asked Vonpay to take the held money, but Vonpay has not confirmed whether it was taken. The plugin re-checks it on every run: if it was taken, the plugin adds the item; if it was released, it closes the open order edit. Check the payment in Vonpay by the order id. Do not take it again."
|
|
156
|
-
},
|
|
126
|
+
...Object.fromEntries(Object.entries(CHARGE_REASON_LABEL).map(([reason, label]) => [reason, { label }])),
|
|
157
127
|
cancel_refund_missing: {
|
|
158
128
|
label: "Cancelled, refund failed",
|
|
159
129
|
what: "The order was cancelled, but Medusa's refund to the buyer did not go through. The buyer may still be charged."
|
|
@@ -207,6 +177,7 @@ const RESOLVED_HOW_LABEL = {
|
|
|
207
177
|
refunded_earlier: "Already refunded with this payment's key (for example from the command line)",
|
|
208
178
|
nothing_left: "Vonpay showed nothing left to refund — confirm in the Vonpay dashboard that the buyer got it back",
|
|
209
179
|
marked: "Marked resolved",
|
|
180
|
+
...CHARGE_RESOLVED_HOW_LABEL,
|
|
210
181
|
auto_closed: "Closed automatically — Vonpay confirmed nothing was charged and the payment can no longer be used",
|
|
211
182
|
paid_after_auto_close: "Re-opened automatically — money arrived after the automatic close",
|
|
212
183
|
paid_after_resolution: "Re-opened automatically — Vonpay reported this payment as paid after it was marked resolved",
|
|
@@ -250,6 +221,9 @@ function isConfirmedRefund(row) {
|
|
|
250
221
|
function canRefund(row) {
|
|
251
222
|
return row.vp_session_id !== null && !isConfirmedRefund(row) && !isAutoClosed(row) && !isUnrecognisedRecord(row) && REFUNDABLE_REASONS.includes(row.reason);
|
|
252
223
|
}
|
|
224
|
+
function isChargeRow(row) {
|
|
225
|
+
return row.source === "renewal" || row.source === "upsell";
|
|
226
|
+
}
|
|
253
227
|
function canRelease(row) {
|
|
254
228
|
return row.source === "collection" && row.vp_session_id !== null && row.status === "open" && WALLET_REASONS.includes(row.reason);
|
|
255
229
|
}
|
|
@@ -257,9 +231,20 @@ function canComplete(row) {
|
|
|
257
231
|
return row.source === "collection" && row.vp_session_id !== null && row.status === "open" && row.reason === "wallet_held_no_order";
|
|
258
232
|
}
|
|
259
233
|
function canMarkResolved(row) {
|
|
234
|
+
if (isChargeRow(row)) return false;
|
|
260
235
|
return row.vp_session_id !== null && row.status !== "resolved" && !isUnrecognisedRecord(row) && !WALLET_REASONS.includes(row.reason) && !TAKE_REASONS.includes(row.reason);
|
|
261
236
|
}
|
|
262
237
|
function locatorFor(row) {
|
|
238
|
+
if (isChargeRow(row)) {
|
|
239
|
+
return {
|
|
240
|
+
source: row.source,
|
|
241
|
+
payment_collection_id: row.payment_collection_id,
|
|
242
|
+
...row.order_id ? { order_id: row.order_id } : {},
|
|
243
|
+
...row.medusa_payment_session_id ? { medusa_payment_session_id: row.medusa_payment_session_id } : {},
|
|
244
|
+
...row.acceptance_id ? { acceptance_id: row.acceptance_id } : {},
|
|
245
|
+
...row.prior_intent_id ? { prior_intent_id: row.prior_intent_id } : {}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
263
248
|
return {
|
|
264
249
|
source: row.source,
|
|
265
250
|
vp_session_id: row.vp_session_id ?? "",
|
|
@@ -269,6 +254,9 @@ function locatorFor(row) {
|
|
|
269
254
|
};
|
|
270
255
|
}
|
|
271
256
|
function resolutionSteps(row) {
|
|
257
|
+
if (isChargeRow(row)) {
|
|
258
|
+
return [chargeHandStep(row.vp_payment_intent_id)];
|
|
259
|
+
}
|
|
272
260
|
if (!row.vp_session_id || row.reason === "unrecognised") {
|
|
273
261
|
return [{ title: "Check this payment in Vonpay", body: "Find the payment in the Vonpay dashboard before refunding or fulfilling anything." }];
|
|
274
262
|
}
|
|
@@ -348,6 +336,14 @@ function reconcileCopy(o) {
|
|
|
348
336
|
function markConfirmMatches(typed, row) {
|
|
349
337
|
return row.vp_session_id !== null && typed.trim() === row.vp_session_id;
|
|
350
338
|
}
|
|
339
|
+
function closedMoneyNote(row) {
|
|
340
|
+
if (row.status !== "resolved" || row.resolution?.how !== "closed_no_change") return null;
|
|
341
|
+
return OFFER_CLOSED_MONEY_TEXT[row.reason] ?? OFFER_CLOSED_MONEY_DEFAULT;
|
|
342
|
+
}
|
|
343
|
+
function chargedUncheckedNote(count) {
|
|
344
|
+
if (!(count > 0)) return null;
|
|
345
|
+
return `${count} paid ${count === 1 ? "renewal was" : "renewals were"} not checked against Medusa on this load, because a load checks a limited number or Medusa did not answer. One that Medusa has no record of may be missing from this list. Reload to check the next ones.`;
|
|
346
|
+
}
|
|
351
347
|
const REFUSAL_TEXT = {
|
|
352
348
|
hold_release_not_eligible: "Only a held wallet payment can be released here. Nothing was changed.",
|
|
353
349
|
hold_release_payment_active: "This held payment belongs to an order. Take it or cancel it from the order. Nothing was changed.",
|
|
@@ -369,7 +365,7 @@ const REFUSAL_TEXT = {
|
|
|
369
365
|
hold_refund_auto_closed: "This payment was closed automatically because Vonpay confirmed nothing was charged. There's nothing to refund.",
|
|
370
366
|
hold_refund_not_eligible: "This held payment has no single charge that can be refunded from here. Nothing was refunded — check it in Vonpay.",
|
|
371
367
|
hold_record_unrecognised: "This payment's record in the list isn't one the plugin recognises. Nothing was changed — check it in Vonpay.",
|
|
372
|
-
refund_refused: "Vonpay refused the refund. Nothing was refunded.",
|
|
368
|
+
refund_refused: "Vonpay refused the refund. Nothing was refunded. If the buyer already has the money back (a dispute, or a refund made in the Vonpay dashboard), close this row with Mark resolved.",
|
|
373
369
|
refund_exceeds_remaining: "Vonpay shows nothing left to refund on this payment. Nothing new was refunded.",
|
|
374
370
|
hold_provider_unavailable: "The Vonpay payment provider couldn't be reached from the admin. Nothing was changed — try again.",
|
|
375
371
|
hold_provider_ambiguous: "More than one Vonpay provider could own this payment. Nothing was changed — check the store's payment setup.",
|
|
@@ -377,7 +373,7 @@ const REFUSAL_TEXT = {
|
|
|
377
373
|
hold_refund_key_conflict: "A refund with this payment's key was already made with different details (for example a partial amount from the command line). Nothing new was refunded — check it in Vonpay.",
|
|
378
374
|
refund_declined: "The payment provider declined the refund. No money moved.",
|
|
379
375
|
refund_not_completed: "Vonpay recorded this refund as failed. No money moved.",
|
|
380
|
-
hold_refund_not_refundable_now: "Vonpay says nothing can be refunded on this payment right now (not settled yet, disputed, or already refunded). Nothing was refunded.",
|
|
376
|
+
hold_refund_not_refundable_now: "Vonpay says nothing can be refunded on this payment right now (not settled yet, disputed, or already refunded). Nothing was refunded. Once the buyer has the money back (a dispute, or a refund made in the Vonpay dashboard), close this row with Mark resolved; if it has not settled yet, try again later.",
|
|
381
377
|
hold_checkout_busy: "The buyer's checkout for this payment is in progress right now. Nothing was changed — try again in a moment.",
|
|
382
378
|
hold_checkout_lock_unavailable: "This payment's checkout couldn't be locked, so nothing was changed. Check the store's locking setup, or refund from the command line.",
|
|
383
379
|
hold_recheck_failed: "The order couldn't be re-checked just before acting. Nothing was changed — try again.",
|
|
@@ -387,6 +383,14 @@ const REFUSAL_TEXT = {
|
|
|
387
383
|
hold_refund_payment_active: "This payment now belongs to an order that isn't cancelled. Nothing was refunded — refund it from the order.",
|
|
388
384
|
hold_resolve_wallet_held: "Use Release for a held wallet payment. It checks Vonpay first, then releases the hold, lists it for a refund, or clears it with its order. Nothing was changed.",
|
|
389
385
|
hold_resolve_payment_active: "This payment now belongs to an order that isn't cancelled, so it isn't held. Nothing was changed.",
|
|
386
|
+
move_request_invalid: "That request was missing the payment's ids. Run the check again. Nothing was changed.",
|
|
387
|
+
hold_resolve_confirm_mismatch: "To mark a payment resolved, type its Vonpay session id exactly as the row shows it. Nothing was changed.",
|
|
388
|
+
move_not_listed: "This payment isn't one the check lists any more (it may have become an order, or already be on Held payments). Run the check again. Nothing was changed.",
|
|
389
|
+
move_not_paid: "Vonpay doesn't show money taken or held on this payment, so there is nothing to move. Nothing was changed.",
|
|
390
|
+
move_refunded: "Vonpay shows this payment refunded in full (or a full refund still in progress), so there is nothing to move. Nothing was changed.",
|
|
391
|
+
move_not_this_checkout: "Vonpay's record of this payment names a different checkout. Check it in the Vonpay dashboard. Nothing was changed.",
|
|
392
|
+
move_lock_not_shared: "The command can't move a payment on a store without a shared lock (Redis or Postgres locking). Use the Move to Held payments button in the admin instead. Nothing was changed.",
|
|
393
|
+
move_vonpay_unavailable: "Vonpay couldn't be reached to check this payment again. Nothing was changed — try again shortly.",
|
|
390
394
|
hold_not_found: "This held payment is no longer on the list. It may already have been completed, released or refunded. Reload the list and check the order."
|
|
391
395
|
};
|
|
392
396
|
function outcomeCopy(o) {
|
|
@@ -456,6 +460,23 @@ function completeOutcomeCopy(o) {
|
|
|
456
460
|
return UNKNOWN_OUTCOME;
|
|
457
461
|
}
|
|
458
462
|
}
|
|
463
|
+
function moveOutcomeCopy(o) {
|
|
464
|
+
switch (o.outcome) {
|
|
465
|
+
case "moved":
|
|
466
|
+
return {
|
|
467
|
+
variant: "success",
|
|
468
|
+
text: o.reason === "wallet_held_no_order" ? "Moved to Held payments. Release the held payment or complete the order there." : "Moved to Held payments. Refund it or mark it resolved there."
|
|
469
|
+
};
|
|
470
|
+
case "already_held":
|
|
471
|
+
return { variant: "success", text: "It is already on Held payments. Nothing was changed." };
|
|
472
|
+
case "ordered":
|
|
473
|
+
return { variant: "warning", text: "An order holds this payment now, so it was not moved. Nothing was changed." };
|
|
474
|
+
case "refused":
|
|
475
|
+
return { variant: "error", text: o.code && REFUSAL_TEXT[o.code] || "That couldn't be done. Nothing was changed." };
|
|
476
|
+
default:
|
|
477
|
+
return UNKNOWN_OUTCOME;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
459
480
|
function resolveOutcomeCopy(o) {
|
|
460
481
|
if (o.outcome === "refused") return { variant: "error", text: o.code && REFUSAL_TEXT[o.code] || "That couldn't be done. Nothing was changed." };
|
|
461
482
|
if (!o.recorded) return { variant: "warning", text: "Couldn't save that. Try again." };
|
|
@@ -466,6 +487,7 @@ const authType = typeof __AUTH_TYPE__ !== "undefined" && __AUTH_TYPE__ ? __AUTH_
|
|
|
466
487
|
const sdk = new Medusa__default.default({ baseUrl: backendUrl, auth: { type: authType } });
|
|
467
488
|
const HELD_PAGE_SIZE = 20;
|
|
468
489
|
const LIST_KEY = "vonpay-held-payments";
|
|
490
|
+
const HELD_LIST_KEY = LIST_KEY;
|
|
469
491
|
function useHeldPayments(page) {
|
|
470
492
|
const status = page.status ?? "open";
|
|
471
493
|
return reactQuery.useQuery({
|
|
@@ -528,6 +550,22 @@ function useMarkResolved() {
|
|
|
528
550
|
onSettled: () => qc.invalidateQueries({ queryKey: [LIST_KEY] })
|
|
529
551
|
});
|
|
530
552
|
}
|
|
553
|
+
function useChargeAction() {
|
|
554
|
+
const qc = reactQuery.useQueryClient();
|
|
555
|
+
return reactQuery.useMutation({
|
|
556
|
+
mutationFn: (v) => sdk.client.fetch("/admin/vonpay/holds/resolve", {
|
|
557
|
+
method: "POST",
|
|
558
|
+
body: {
|
|
559
|
+
...locatorFor(v.row),
|
|
560
|
+
action: v.action,
|
|
561
|
+
...v.typed_order_id !== void 0 ? { confirm_order_id: v.typed_order_id.trim(), confirm_checked_in_vonpay: v.checked_in_vonpay === true } : {},
|
|
562
|
+
...v.action === "close_unreadable" && v.row.record_sha256 ? { confirm_record_sha256: v.row.record_sha256 } : {}
|
|
563
|
+
}
|
|
564
|
+
}),
|
|
565
|
+
retry: false,
|
|
566
|
+
onSettled: () => qc.invalidateQueries({ queryKey: [LIST_KEY] })
|
|
567
|
+
});
|
|
568
|
+
}
|
|
531
569
|
function useReconcileHold() {
|
|
532
570
|
const qc = reactQuery.useQueryClient();
|
|
533
571
|
return reactQuery.useMutation({
|
|
@@ -626,92 +664,48 @@ const UpdateBanner = () => {
|
|
|
626
664
|
] }) });
|
|
627
665
|
};
|
|
628
666
|
adminSdk.defineWidgetConfig({ zone: "order.list.before" });
|
|
629
|
-
const EVENT_LABEL = {
|
|
630
|
-
"subscription.created": "Signed up",
|
|
631
|
-
"subscription.renewed": "Renewal paid",
|
|
632
|
-
"subscription.payment_failed": "Renewal declined",
|
|
633
|
-
"subscription.cancelled": "Cancelled",
|
|
634
|
-
"subscription.updated": "Changed"
|
|
635
|
-
};
|
|
636
|
-
const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
|
|
637
|
-
const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
|
|
638
|
-
const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
|
|
639
|
-
const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
|
|
640
|
-
const SUBSCRIPTION_PAGE_SIZE = 20;
|
|
641
|
-
function useSubscriptionEvents(page) {
|
|
642
|
-
return reactQuery.useQuery({
|
|
643
|
-
queryKey: ["vonpay-subscription-events", page.limit, page.offset],
|
|
644
|
-
queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
|
|
645
|
-
placeholderData: reactQuery.keepPreviousData
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
const pageCountFor = (count) => {
|
|
649
|
-
const remainder = count % SUBSCRIPTION_PAGE_SIZE;
|
|
650
|
-
return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
|
|
651
|
-
};
|
|
652
|
-
const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
|
|
653
|
-
const VonpaySubscriptionsPage = () => {
|
|
654
|
-
const [pageIndex, setPageIndex] = react.useState(0);
|
|
655
|
-
const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
|
|
656
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
657
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
|
|
658
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Vonpay subscriptions" }),
|
|
659
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
|
|
660
|
-
] }),
|
|
661
|
-
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
662
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
|
|
663
|
-
data.events.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
664
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
665
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
666
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "What happened" }),
|
|
667
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Subscription" }),
|
|
668
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Period" }),
|
|
669
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
|
|
670
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Next bill" }),
|
|
671
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Received" })
|
|
672
|
-
] }) }),
|
|
673
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
674
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
675
|
-
eventLabel(e.type),
|
|
676
|
-
e.mode === "test" ? " (test)" : ""
|
|
677
|
-
] }),
|
|
678
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
|
|
679
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: e.billing_cycle ?? "—" }),
|
|
680
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
|
|
681
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.next_bill_at) }),
|
|
682
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.received_at) })
|
|
683
|
-
] }, e.id)) })
|
|
684
|
-
] }) }),
|
|
685
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
686
|
-
ui.Table.Pagination,
|
|
687
|
-
{
|
|
688
|
-
count: data.count,
|
|
689
|
-
pageSize: SUBSCRIPTION_PAGE_SIZE,
|
|
690
|
-
pageIndex,
|
|
691
|
-
pageCount: pageCountFor(data.count),
|
|
692
|
-
canPreviousPage: pageIndex > 0,
|
|
693
|
-
canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
|
|
694
|
-
previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
|
|
695
|
-
nextPage: () => setPageIndex((p) => p + 1)
|
|
696
|
-
}
|
|
697
|
-
)
|
|
698
|
-
] })
|
|
699
|
-
] })
|
|
700
|
-
] });
|
|
701
|
-
};
|
|
702
|
-
const config$2 = adminSdk.defineRouteConfig({
|
|
703
|
-
label: "Vonpay subscriptions",
|
|
704
|
-
icon: icons.ArrowPath,
|
|
705
|
-
nested: "/orders"
|
|
706
|
-
});
|
|
707
667
|
function useSetupCheck() {
|
|
708
668
|
return reactQuery.useMutation({
|
|
709
669
|
mutationFn: () => sdk.client.fetch("/admin/vonpay/setup-check", { method: "POST", body: {} }),
|
|
710
670
|
retry: false
|
|
711
671
|
});
|
|
712
672
|
}
|
|
673
|
+
function useMoveToHeld() {
|
|
674
|
+
const qc = reactQuery.useQueryClient();
|
|
675
|
+
return reactQuery.useMutation({
|
|
676
|
+
mutationFn: (m) => sdk.client.fetch("/admin/vonpay/setup-check/move-to-held", { method: "POST", body: { vp_session_id: m.vp_session_id, medusa_payment_session_id: m.medusa_payment_session_id } }),
|
|
677
|
+
retry: false,
|
|
678
|
+
onSettled: () => qc.invalidateQueries({ queryKey: [HELD_LIST_KEY] })
|
|
679
|
+
});
|
|
680
|
+
}
|
|
713
681
|
const LABEL = { pass: "OK", warn: "Check", fail: "Fix", not_checked: "Not checked" };
|
|
714
682
|
const COLOR = { pass: "green", warn: "orange", fail: "red", not_checked: "grey" };
|
|
683
|
+
function uniqueMoves(moves) {
|
|
684
|
+
const seen = /* @__PURE__ */ new Set();
|
|
685
|
+
return (moves ?? []).filter((m) => !seen.has(m.vp_session_id) && (seen.add(m.vp_session_id), true));
|
|
686
|
+
}
|
|
687
|
+
const MoveRow = ({ move }) => {
|
|
688
|
+
const mutation = useMoveToHeld();
|
|
689
|
+
const [result, setResult] = react.useState(null);
|
|
690
|
+
const done = result !== null && result.variant !== "error";
|
|
691
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex flex-col gap-y-1 sm:flex-row sm:items-center sm:gap-x-3", children: [
|
|
692
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "font-mono", children: move.vp_session_id }),
|
|
693
|
+
!done && /* @__PURE__ */ jsxRuntime.jsx(
|
|
694
|
+
ui.Button,
|
|
695
|
+
{
|
|
696
|
+
size: "small",
|
|
697
|
+
variant: "secondary",
|
|
698
|
+
isLoading: mutation.isPending,
|
|
699
|
+
onClick: () => mutation.mutate(move, {
|
|
700
|
+
onSuccess: (o) => setResult(moveOutcomeCopy(o)),
|
|
701
|
+
onError: () => setResult({ variant: "error", text: "That couldn't be done. Nothing was changed — try again." })
|
|
702
|
+
}),
|
|
703
|
+
children: "Move to Held payments"
|
|
704
|
+
}
|
|
705
|
+
),
|
|
706
|
+
result && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: result.variant === "error" ? "text-ui-fg-error" : "text-ui-fg-subtle", children: result.text })
|
|
707
|
+
] });
|
|
708
|
+
};
|
|
715
709
|
const SetupCheckPanel = () => {
|
|
716
710
|
const check = useSetupCheck();
|
|
717
711
|
const items = check.data?.items ?? [];
|
|
@@ -730,7 +724,8 @@ const SetupCheckPanel = () => {
|
|
|
730
724
|
/* @__PURE__ */ jsxRuntime.jsx(ui.StatusBadge, { color: COLOR[i.status], className: "w-fit shrink-0", children: LABEL[i.status] }),
|
|
731
725
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
732
726
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: i.detail }),
|
|
733
|
-
i.fix && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: i.fix })
|
|
727
|
+
i.fix && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: i.fix }),
|
|
728
|
+
uniqueMoves(i.moves).length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-2 flex flex-col gap-y-2", "aria-label": "Paid checkouts with no order", children: uniqueMoves(i.moves).map((m) => /* @__PURE__ */ jsxRuntime.jsx(MoveRow, { move: m }, m.vp_session_id)) })
|
|
734
729
|
] })
|
|
735
730
|
] }, `${i.id}:${i.provider ?? ""}:${n}`)) })
|
|
736
731
|
] })
|
|
@@ -903,6 +898,130 @@ const MarkResolvedAction = ({ row, onResult }) => {
|
|
|
903
898
|
] }) })
|
|
904
899
|
] });
|
|
905
900
|
};
|
|
901
|
+
const localTime = (iso) => new Date(iso).toLocaleString();
|
|
902
|
+
const TIMER_MAX_MS = 2147483647;
|
|
903
|
+
const REPOLL_MS = 15e3;
|
|
904
|
+
const REPOLL_MAX = 8;
|
|
905
|
+
const ChargeActions = ({ row, listAt, onResult }) => {
|
|
906
|
+
const [answered, setAnswer] = react.useState(null);
|
|
907
|
+
const answer = answered && !(listAt > answered.receivedAt) ? answered : null;
|
|
908
|
+
const [asking, setAsking] = react.useState(null);
|
|
909
|
+
const [typed, setTyped] = react.useState("");
|
|
910
|
+
const [checked, setChecked] = react.useState(false);
|
|
911
|
+
const act = useChargeAction();
|
|
912
|
+
const qc = reactQuery.useQueryClient();
|
|
913
|
+
const rowSays = JSON.stringify([row.held_at, row.actions ?? null, row.hint ?? null]);
|
|
914
|
+
react.useEffect(() => setAnswer(null), [rowSays]);
|
|
915
|
+
const actions = answer?.actions ?? row.actions ?? [];
|
|
916
|
+
const hint = answer ? answer.hint : row.hint ?? null;
|
|
917
|
+
const closedUntil = actions.filter((a) => !a.available && a.available_at).map((a) => Date.parse(a.available_at)).filter((t) => Number.isFinite(t));
|
|
918
|
+
const opensAt = closedUntil.filter((t) => t > Date.now());
|
|
919
|
+
const nextOpen = opensAt.length > 0 ? Math.min(...opensAt) : null;
|
|
920
|
+
react.useEffect(() => {
|
|
921
|
+
if (nextOpen === null) return;
|
|
922
|
+
const timer = setTimeout(() => {
|
|
923
|
+
setAnswer(null);
|
|
924
|
+
void qc.invalidateQueries({ queryKey: [HELD_LIST_KEY] });
|
|
925
|
+
}, Math.min(TIMER_MAX_MS, Math.max(0, nextOpen - Date.now()) + 1e3));
|
|
926
|
+
return () => clearTimeout(timer);
|
|
927
|
+
}, [nextOpen, qc]);
|
|
928
|
+
const overdue = closedUntil.filter((t) => t <= Date.now());
|
|
929
|
+
const pastDue = overdue.length > 0 ? Math.min(...overdue) : null;
|
|
930
|
+
const repolls = react.useRef(0);
|
|
931
|
+
react.useEffect(() => {
|
|
932
|
+
if (pastDue === null || repolls.current >= REPOLL_MAX) return;
|
|
933
|
+
const timer = setTimeout(() => {
|
|
934
|
+
repolls.current += 1;
|
|
935
|
+
void qc.invalidateQueries({ queryKey: [HELD_LIST_KEY] });
|
|
936
|
+
}, REPOLL_MS);
|
|
937
|
+
return () => clearTimeout(timer);
|
|
938
|
+
}, [pastDue, listAt, qc]);
|
|
939
|
+
const run = (a) => act.mutate(
|
|
940
|
+
{ row, action: a.id, ...a.confirm === "type_order_id" ? { typed_order_id: typed, checked_in_vonpay: checked } : {} },
|
|
941
|
+
{
|
|
942
|
+
onSuccess: (o) => {
|
|
943
|
+
if (o.recorded === false || o.outcome === "not_saved") {
|
|
944
|
+
setAnswer({ ...o, actions: [], hint: null, receivedAt: Date.now() });
|
|
945
|
+
onResult({ variant: "warning", text: NOT_SAVED_TEXT });
|
|
946
|
+
void qc.invalidateQueries({ queryKey: [HELD_LIST_KEY] });
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
setAnswer({ ...o, receivedAt: Date.now() });
|
|
950
|
+
onResult({ variant: o.tone, text: fillTime(o.text, o.at, localTime) });
|
|
951
|
+
},
|
|
952
|
+
onError: (e) => {
|
|
953
|
+
const f = postFailure(e);
|
|
954
|
+
onResult(f.variant === "error" ? f : { variant: "warning", text: "Couldn't confirm the outcome. Reload the list." });
|
|
955
|
+
},
|
|
956
|
+
onSettled: () => setAsking(null)
|
|
957
|
+
}
|
|
958
|
+
);
|
|
959
|
+
const typedOk = !asking || asking.confirm !== "type_order_id" || typed.trim() === row.order_id && checked;
|
|
960
|
+
const inputId = `vonpay-charge-confirm-${row.payment_collection_id}-${row.medusa_payment_session_id ?? row.acceptance_id ?? ""}`;
|
|
961
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
962
|
+
hint && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: fillTime(hint.text, hint.at, localTime) }),
|
|
963
|
+
actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: actions.map((a) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
965
|
+
ui.Button,
|
|
966
|
+
{
|
|
967
|
+
size: "small",
|
|
968
|
+
variant: a.id === "check" ? "primary" : "secondary",
|
|
969
|
+
disabled: !a.available || act.isPending,
|
|
970
|
+
isLoading: act.isPending && (asking?.id === a.id || a.id === "check" && !asking),
|
|
971
|
+
onClick: () => {
|
|
972
|
+
if (!a.available) return;
|
|
973
|
+
if (!a.confirm) {
|
|
974
|
+
run(a);
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
setTyped("");
|
|
978
|
+
setChecked(false);
|
|
979
|
+
setAsking(a);
|
|
980
|
+
},
|
|
981
|
+
children: a.label
|
|
982
|
+
}
|
|
983
|
+
),
|
|
984
|
+
!a.available && a.available_at && /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
985
|
+
"Opens ",
|
|
986
|
+
localTime(a.available_at)
|
|
987
|
+
] })
|
|
988
|
+
] }, a.id)) }),
|
|
989
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt, { open: asking !== null, onOpenChange: (o) => !act.isPending && !o && setAsking(null), variant: "confirmation", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
|
|
990
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
|
|
991
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Title, { children: [
|
|
992
|
+
asking?.label.replace(/…$/, ""),
|
|
993
|
+
"?"
|
|
994
|
+
] }),
|
|
995
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Description, { children: asking?.confirm_text })
|
|
996
|
+
] }),
|
|
997
|
+
asking?.confirm === "type_order_id" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2 px-6 pb-4", children: [
|
|
998
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { htmlFor: inputId, size: "small", children: [
|
|
999
|
+
"Type the order id to confirm: ",
|
|
1000
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-mono", children: row.order_id })
|
|
1001
|
+
] }),
|
|
1002
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Input, { id: inputId, size: "small", autoComplete: "off", value: typed, onChange: (e) => setTyped(e.target.value) }),
|
|
1003
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex items-center gap-x-2", children: [
|
|
1004
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "checkbox", checked, onChange: (e) => setChecked(e.target.checked) }),
|
|
1005
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "txt-compact-small", children: "I checked this order in the Vonpay dashboard" })
|
|
1006
|
+
] })
|
|
1007
|
+
] }),
|
|
1008
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Footer, { children: [
|
|
1009
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Cancel, { disabled: act.isPending, children: "Cancel" }),
|
|
1010
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1011
|
+
ui.Prompt.Action,
|
|
1012
|
+
{
|
|
1013
|
+
disabled: act.isPending || !typedOk,
|
|
1014
|
+
onClick: (e) => {
|
|
1015
|
+
e.preventDefault();
|
|
1016
|
+
if (asking && typedOk) run(asking);
|
|
1017
|
+
},
|
|
1018
|
+
children: asking?.label.replace(/…$/, "")
|
|
1019
|
+
}
|
|
1020
|
+
)
|
|
1021
|
+
] })
|
|
1022
|
+
] }) })
|
|
1023
|
+
] });
|
|
1024
|
+
};
|
|
906
1025
|
const WalletHoldAction = ({ row, kind, onResult }) => {
|
|
907
1026
|
const [open, setOpen] = react.useState(false);
|
|
908
1027
|
const release = useReleaseHold();
|
|
@@ -938,7 +1057,7 @@ const WalletHoldAction = ({ row, kind, onResult }) => {
|
|
|
938
1057
|
] }) })
|
|
939
1058
|
] });
|
|
940
1059
|
};
|
|
941
|
-
const HoldDrawer = ({ row, onClose }) => {
|
|
1060
|
+
const HoldDrawer = ({ row, listAt, onClose }) => {
|
|
942
1061
|
const copy = row ? reasonCopy(row.reason) : void 0;
|
|
943
1062
|
const known = row ? isKnownStatus(row.status) && !isUnrecognisedRecord(row) : false;
|
|
944
1063
|
const showRefund = !!row && known && canRefund(row);
|
|
@@ -955,7 +1074,7 @@ const HoldDrawer = ({ row, onClose }) => {
|
|
|
955
1074
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open: row !== null, onOpenChange: (open) => !open && close(), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
956
1075
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Header, { children: [
|
|
957
1076
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: copy?.label ?? "Held payment" }),
|
|
958
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { children: copy?.what })
|
|
1077
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Description, { children: row && isChargeRow(row) ? void 0 : copy?.what })
|
|
959
1078
|
] }),
|
|
960
1079
|
row && /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Body, { className: "flex flex-col gap-y-6 overflow-y-auto", children: [
|
|
961
1080
|
/* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-[auto_1fr] gap-x-4 gap-y-2", children: [
|
|
@@ -980,6 +1099,10 @@ const HoldDrawer = ({ row, onClose }) => {
|
|
|
980
1099
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "txt-compact-small text-ui-fg-subtle", children: "Order" }),
|
|
981
1100
|
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx(Mono, { value: row.order_id, label: "order id" }) })
|
|
982
1101
|
] }),
|
|
1102
|
+
row.vp_payment_intent_id && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1103
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "txt-compact-small text-ui-fg-subtle", children: "Vonpay payment" }),
|
|
1104
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx(Mono, { value: row.vp_payment_intent_id, label: "Vonpay payment id" }) })
|
|
1105
|
+
] }),
|
|
983
1106
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "txt-compact-small text-ui-fg-subtle", children: "Vonpay session" }),
|
|
984
1107
|
/* @__PURE__ */ jsxRuntime.jsx("dd", { children: /* @__PURE__ */ jsxRuntime.jsx(Mono, { value: row.vp_session_id, label: "Vonpay session id" }) }),
|
|
985
1108
|
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "txt-compact-small text-ui-fg-subtle", children: "Medusa payment session" }),
|
|
@@ -1008,6 +1131,7 @@ const HoldDrawer = ({ row, onClose }) => {
|
|
|
1008
1131
|
] })
|
|
1009
1132
|
] }),
|
|
1010
1133
|
result && /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: result.variant, children: result.text }),
|
|
1134
|
+
closedMoneyNote(row) && /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "warning", children: closedMoneyNote(row) }),
|
|
1011
1135
|
(showRefund || showMark || showRelease || showComplete || showOpenOrder) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
1012
1136
|
showOpenOrder && /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "primary", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: orderPath(row.order_id), children: "Open order" }) }),
|
|
1013
1137
|
showComplete && /* @__PURE__ */ jsxRuntime.jsx(WalletHoldAction, { row, kind: "complete", onResult: setResult }),
|
|
@@ -1016,6 +1140,7 @@ const HoldDrawer = ({ row, onClose }) => {
|
|
|
1016
1140
|
showRefund && /* @__PURE__ */ jsxRuntime.jsx(CheckWithVonpayAction, { row, onResult: setResult }),
|
|
1017
1141
|
showMark && /* @__PURE__ */ jsxRuntime.jsx(MarkResolvedAction, { row, onResult: setResult })
|
|
1018
1142
|
] }),
|
|
1143
|
+
row && isChargeRow(row) && /* @__PURE__ */ jsxRuntime.jsx(ChargeActions, { row, listAt, onResult: setResult }, `${row.payment_collection_id}:${row.medusa_payment_session_id ?? row.acceptance_id ?? ""}:${row.prior_intent_id ?? ""}`),
|
|
1019
1144
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
1020
1145
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Or do it by hand" }),
|
|
1021
1146
|
steps.map((step) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-2", children: [
|
|
@@ -1026,7 +1151,7 @@ const HoldDrawer = ({ row, onClose }) => {
|
|
|
1026
1151
|
/* @__PURE__ */ jsxRuntime.jsx(ui.CodeBlock.Body, {})
|
|
1027
1152
|
] })
|
|
1028
1153
|
] }, step.title)),
|
|
1029
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: STILL_LISTED_NOTE })
|
|
1154
|
+
!isChargeRow(row) && /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted", children: STILL_LISTED_NOTE })
|
|
1030
1155
|
] })
|
|
1031
1156
|
] })
|
|
1032
1157
|
] }) });
|
|
@@ -1036,11 +1161,11 @@ const HeldPaymentsPage = () => {
|
|
|
1036
1161
|
const [pageIndex, setPageIndex] = react.useState(0);
|
|
1037
1162
|
const [filter, setFilter] = react.useState("open");
|
|
1038
1163
|
const [opened, setOpened] = react.useState(null);
|
|
1039
|
-
const { data, isLoading, isError, refetch } = useHeldPayments({ limit: HELD_PAGE_SIZE, offset: pageIndex * HELD_PAGE_SIZE, status: filter });
|
|
1164
|
+
const { data, dataUpdatedAt, isLoading, isError, refetch } = useHeldPayments({ limit: HELD_PAGE_SIZE, offset: pageIndex * HELD_PAGE_SIZE, status: filter });
|
|
1040
1165
|
const count = data?.count ?? 0;
|
|
1041
1166
|
const remainder = count % HELD_PAGE_SIZE;
|
|
1042
1167
|
const pageCount = Math.max(1, (count - remainder) / HELD_PAGE_SIZE + (remainder > 0 ? 1 : 0));
|
|
1043
|
-
const keyOf = (row) => `${row.payment_collection_id}:${row.vp_session_id ?? "unreadable"}:${row.source}:${row.payment_id ?? ""}:${row.medusa_payment_session_id ?? ""}`;
|
|
1168
|
+
const keyOf = (row) => `${row.payment_collection_id}:${row.vp_session_id ?? "unreadable"}:${row.source}:${row.payment_id ?? ""}:${row.medusa_payment_session_id ?? ""}:${row.acceptance_id ?? ""}:${row.prior_intent_id ?? ""}`;
|
|
1044
1169
|
const open = opened ? data?.holds.find((r) => keyOf(r) === keyOf(opened)) ?? opened : null;
|
|
1045
1170
|
const onRowKey = (row) => (e) => {
|
|
1046
1171
|
if (e.key === "Enter" || e.key === " ") {
|
|
@@ -1072,6 +1197,8 @@ const HeldPaymentsPage = () => {
|
|
|
1072
1197
|
) })
|
|
1073
1198
|
] }),
|
|
1074
1199
|
data && !data.scan_complete && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "warning", children: "This list may be incomplete: the store has more records than one page load can check." }) }),
|
|
1200
|
+
data?.job?.filter((j) => j.banner).map((j) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "warning", children: j.banner }) }, j.mode)),
|
|
1201
|
+
data && chargedUncheckedNote(data.charged_unchecked) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "warning", children: chargedUncheckedNote(data.charged_unchecked) }) }),
|
|
1075
1202
|
isError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-start gap-y-3 px-6 py-6", children: [
|
|
1076
1203
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: "Couldn't load held payments." }),
|
|
1077
1204
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { size: "small", variant: "secondary", onClick: () => refetch(), children: "Try again" })
|
|
@@ -1123,12 +1250,12 @@ const HeldPaymentsPage = () => {
|
|
|
1123
1250
|
}
|
|
1124
1251
|
)
|
|
1125
1252
|
] }),
|
|
1126
|
-
/* @__PURE__ */ jsxRuntime.jsx(HoldDrawer, { row: open, onClose: () => setOpened(null) })
|
|
1253
|
+
/* @__PURE__ */ jsxRuntime.jsx(HoldDrawer, { row: open, listAt: dataUpdatedAt, onClose: () => setOpened(null) })
|
|
1127
1254
|
] }),
|
|
1128
1255
|
/* @__PURE__ */ jsxRuntime.jsx(SetupCheckPanel, {})
|
|
1129
1256
|
] });
|
|
1130
1257
|
};
|
|
1131
|
-
const config$
|
|
1258
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
1132
1259
|
label: "Held payments",
|
|
1133
1260
|
icon: icons.ExclamationCircle,
|
|
1134
1261
|
nested: "/orders"
|
|
@@ -1592,11 +1719,89 @@ const VonpayOffersPage = () => {
|
|
|
1592
1719
|
] })
|
|
1593
1720
|
] });
|
|
1594
1721
|
};
|
|
1595
|
-
const config = adminSdk.defineRouteConfig({
|
|
1722
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
1596
1723
|
label: "One-click offers",
|
|
1597
1724
|
icon: icons.Sparkles,
|
|
1598
1725
|
nested: "/orders"
|
|
1599
1726
|
});
|
|
1727
|
+
const EVENT_LABEL = {
|
|
1728
|
+
"subscription.created": "Signed up",
|
|
1729
|
+
"subscription.renewed": "Renewal paid",
|
|
1730
|
+
"subscription.payment_failed": "Renewal declined",
|
|
1731
|
+
"subscription.cancelled": "Cancelled",
|
|
1732
|
+
"subscription.updated": "Changed"
|
|
1733
|
+
};
|
|
1734
|
+
const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
|
|
1735
|
+
const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
|
|
1736
|
+
const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
|
|
1737
|
+
const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
|
|
1738
|
+
const SUBSCRIPTION_PAGE_SIZE = 20;
|
|
1739
|
+
function useSubscriptionEvents(page) {
|
|
1740
|
+
return reactQuery.useQuery({
|
|
1741
|
+
queryKey: ["vonpay-subscription-events", page.limit, page.offset],
|
|
1742
|
+
queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
|
|
1743
|
+
placeholderData: reactQuery.keepPreviousData
|
|
1744
|
+
});
|
|
1745
|
+
}
|
|
1746
|
+
const pageCountFor = (count) => {
|
|
1747
|
+
const remainder = count % SUBSCRIPTION_PAGE_SIZE;
|
|
1748
|
+
return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
|
|
1749
|
+
};
|
|
1750
|
+
const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
|
|
1751
|
+
const VonpaySubscriptionsPage = () => {
|
|
1752
|
+
const [pageIndex, setPageIndex] = react.useState(0);
|
|
1753
|
+
const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
|
|
1754
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
|
|
1755
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
|
|
1756
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Vonpay subscriptions" }),
|
|
1757
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
|
|
1758
|
+
] }),
|
|
1759
|
+
isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1760
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
|
|
1761
|
+
data.events.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1762
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
1763
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1764
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "What happened" }),
|
|
1765
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Subscription" }),
|
|
1766
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Period" }),
|
|
1767
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
|
|
1768
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Next bill" }),
|
|
1769
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Received" })
|
|
1770
|
+
] }) }),
|
|
1771
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1772
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
1773
|
+
eventLabel(e.type),
|
|
1774
|
+
e.mode === "test" ? " (test)" : ""
|
|
1775
|
+
] }),
|
|
1776
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
|
|
1777
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: e.billing_cycle ?? "—" }),
|
|
1778
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
|
|
1779
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.next_bill_at) }),
|
|
1780
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.received_at) })
|
|
1781
|
+
] }, e.id)) })
|
|
1782
|
+
] }) }),
|
|
1783
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1784
|
+
ui.Table.Pagination,
|
|
1785
|
+
{
|
|
1786
|
+
count: data.count,
|
|
1787
|
+
pageSize: SUBSCRIPTION_PAGE_SIZE,
|
|
1788
|
+
pageIndex,
|
|
1789
|
+
pageCount: pageCountFor(data.count),
|
|
1790
|
+
canPreviousPage: pageIndex > 0,
|
|
1791
|
+
canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
|
|
1792
|
+
previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
|
|
1793
|
+
nextPage: () => setPageIndex((p) => p + 1)
|
|
1794
|
+
}
|
|
1795
|
+
)
|
|
1796
|
+
] })
|
|
1797
|
+
] })
|
|
1798
|
+
] });
|
|
1799
|
+
};
|
|
1800
|
+
const config = adminSdk.defineRouteConfig({
|
|
1801
|
+
label: "Vonpay subscriptions",
|
|
1802
|
+
icon: icons.ArrowPath,
|
|
1803
|
+
nested: "/orders"
|
|
1804
|
+
});
|
|
1600
1805
|
const i18nTranslations0 = {};
|
|
1601
1806
|
const widgetModule = { widgets: [
|
|
1602
1807
|
{
|
|
@@ -1617,19 +1822,19 @@ const widgetModule = { widgets: [
|
|
|
1617
1822
|
] };
|
|
1618
1823
|
const routeModule = {
|
|
1619
1824
|
routes: [
|
|
1620
|
-
{
|
|
1621
|
-
Component: VonpaySubscriptionsPage,
|
|
1622
|
-
path: "/vonpay-subscriptions",
|
|
1623
|
-
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
1624
|
-
},
|
|
1625
1825
|
{
|
|
1626
1826
|
Component: HeldPaymentsPage,
|
|
1627
1827
|
path: "/vonpay-holds",
|
|
1628
|
-
handle: { label: config$
|
|
1828
|
+
handle: { label: config$2.label, translationNs: config$2.translationNs }
|
|
1629
1829
|
},
|
|
1630
1830
|
{
|
|
1631
1831
|
Component: VonpayOffersPage,
|
|
1632
1832
|
path: "/vonpay-offers",
|
|
1833
|
+
handle: { label: config$1.label, translationNs: config$1.translationNs }
|
|
1834
|
+
},
|
|
1835
|
+
{
|
|
1836
|
+
Component: VonpaySubscriptionsPage,
|
|
1837
|
+
path: "/vonpay-subscriptions",
|
|
1633
1838
|
handle: { label: config.label, translationNs: config.translationNs }
|
|
1634
1839
|
}
|
|
1635
1840
|
]
|
|
@@ -1637,24 +1842,24 @@ const routeModule = {
|
|
|
1637
1842
|
const menuItemModule = {
|
|
1638
1843
|
menuItems: [
|
|
1639
1844
|
{
|
|
1640
|
-
label: config$
|
|
1641
|
-
icon: config$
|
|
1845
|
+
label: config$2.label,
|
|
1846
|
+
icon: config$2.icon,
|
|
1642
1847
|
path: "/vonpay-holds",
|
|
1643
1848
|
nested: "/orders",
|
|
1644
1849
|
rank: void 0,
|
|
1645
1850
|
translationNs: void 0
|
|
1646
1851
|
},
|
|
1647
1852
|
{
|
|
1648
|
-
label: config.label,
|
|
1649
|
-
icon: config.icon,
|
|
1853
|
+
label: config$1.label,
|
|
1854
|
+
icon: config$1.icon,
|
|
1650
1855
|
path: "/vonpay-offers",
|
|
1651
1856
|
nested: "/orders",
|
|
1652
1857
|
rank: void 0,
|
|
1653
1858
|
translationNs: void 0
|
|
1654
1859
|
},
|
|
1655
1860
|
{
|
|
1656
|
-
label: config
|
|
1657
|
-
icon: config
|
|
1861
|
+
label: config.label,
|
|
1862
|
+
icon: config.icon,
|
|
1658
1863
|
path: "/vonpay-subscriptions",
|
|
1659
1864
|
nested: "/orders",
|
|
1660
1865
|
rank: void 0,
|