order-management 0.0.27 → 0.0.29
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 +5 -11
- package/.medusa/server/src/admin/index.mjs +5 -11
- package/.medusa/server/src/api/admin/swaps/[id]/create-exchange/route.js +3 -0
- package/.medusa/server/src/api/admin/swaps/[id]/prepare-exchange/route.js +32 -28
- package/.medusa/server/src/api/admin/swaps/route.js +9 -1
- package/.medusa/server/src/subscribers/exchange-created.js +169 -184
- package/.medusa/server/src/subscribers/swap-fulfillment-created.js +139 -0
- package/.medusa/server/src/subscribers/swap-return-paid.js +236 -0
- package/.medusa/server/src/subscribers/swap-return-received.js +155 -0
- package/.medusa/server/src/subscribers/swap-shipment-delivered.js +304 -0
- package/.medusa/server/src/workflows/steps/swap/create-medusa-exchange-step.js +41 -1
- package/package.json +1 -1
|
@@ -849,10 +849,6 @@ const SwapDetailPage = () => {
|
|
|
849
849
|
if (!id) {
|
|
850
850
|
return;
|
|
851
851
|
}
|
|
852
|
-
if (!swap || !swap.order_id) {
|
|
853
|
-
setUpdateError("Swap must have an order_id to create exchange");
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
852
|
try {
|
|
857
853
|
setIsApproving(true);
|
|
858
854
|
setUpdateError(null);
|
|
@@ -865,16 +861,14 @@ const SwapDetailPage = () => {
|
|
|
865
861
|
credentials: "include"
|
|
866
862
|
});
|
|
867
863
|
if (!response.ok) {
|
|
868
|
-
const
|
|
869
|
-
throw new Error(
|
|
864
|
+
const message = await response.text();
|
|
865
|
+
throw new Error(message || "Unable to prepare swap for exchange");
|
|
870
866
|
}
|
|
871
867
|
const payload = await response.json();
|
|
872
868
|
setSwap(payload.swap);
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
} catch (updateErr) {
|
|
877
|
-
const message = updateErr instanceof Error ? updateErr.message : "Unable to prepare swap for exchange creation";
|
|
869
|
+
window.location.href = payload.redirect_url;
|
|
870
|
+
} catch (approveErr) {
|
|
871
|
+
const message = approveErr instanceof Error ? approveErr.message : "Unable to prepare swap for exchange";
|
|
878
872
|
setUpdateError(message);
|
|
879
873
|
} finally {
|
|
880
874
|
setIsApproving(false);
|
|
@@ -848,10 +848,6 @@ const SwapDetailPage = () => {
|
|
|
848
848
|
if (!id) {
|
|
849
849
|
return;
|
|
850
850
|
}
|
|
851
|
-
if (!swap || !swap.order_id) {
|
|
852
|
-
setUpdateError("Swap must have an order_id to create exchange");
|
|
853
|
-
return;
|
|
854
|
-
}
|
|
855
851
|
try {
|
|
856
852
|
setIsApproving(true);
|
|
857
853
|
setUpdateError(null);
|
|
@@ -864,16 +860,14 @@ const SwapDetailPage = () => {
|
|
|
864
860
|
credentials: "include"
|
|
865
861
|
});
|
|
866
862
|
if (!response.ok) {
|
|
867
|
-
const
|
|
868
|
-
throw new Error(
|
|
863
|
+
const message = await response.text();
|
|
864
|
+
throw new Error(message || "Unable to prepare swap for exchange");
|
|
869
865
|
}
|
|
870
866
|
const payload = await response.json();
|
|
871
867
|
setSwap(payload.swap);
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
} catch (updateErr) {
|
|
876
|
-
const message = updateErr instanceof Error ? updateErr.message : "Unable to prepare swap for exchange creation";
|
|
868
|
+
window.location.href = payload.redirect_url;
|
|
869
|
+
} catch (approveErr) {
|
|
870
|
+
const message = approveErr instanceof Error ? approveErr.message : "Unable to prepare swap for exchange";
|
|
877
871
|
setUpdateError(message);
|
|
878
872
|
} finally {
|
|
879
873
|
setIsApproving(false);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3N3YXBzL1tpZF0vY3JlYXRlLWV4Y2hhbmdlL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
|
|
@@ -14,50 +14,54 @@ const POST = async (req, res) => {
|
|
|
14
14
|
const adminId = authContext?.actor_id || authContext?.user_id || "admin";
|
|
15
15
|
try {
|
|
16
16
|
const swapService = req.scope.resolve(swap_1.SWAP_MODULE);
|
|
17
|
+
// Retrieve swap to validate it exists
|
|
17
18
|
const swap = await swapService.retrieveSwap(id);
|
|
18
19
|
const swapData = swap;
|
|
19
|
-
// Validate swap
|
|
20
|
-
if (!swapData) {
|
|
21
|
-
res.status(404).json({ message: "Swap not found" });
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
// Validate swap is in requested status
|
|
25
|
-
if (swapData.status !== "requested") {
|
|
20
|
+
// Validate swap has order_id (required for exchange creation)
|
|
21
|
+
if (!swapData.order_id) {
|
|
26
22
|
res.status(400).json({
|
|
27
|
-
message:
|
|
23
|
+
message: "Swap must have an order_id to create exchange",
|
|
28
24
|
});
|
|
29
25
|
return;
|
|
30
26
|
}
|
|
31
|
-
// Validate swap
|
|
32
|
-
if (
|
|
27
|
+
// Validate swap is in requested status
|
|
28
|
+
if (swapData.status !== "requested") {
|
|
33
29
|
res.status(400).json({
|
|
34
|
-
message:
|
|
30
|
+
message: `Swap cannot be prepared for exchange. Current status: ${swapData.status}`,
|
|
35
31
|
});
|
|
36
32
|
return;
|
|
37
33
|
}
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
//
|
|
41
|
-
const
|
|
34
|
+
// Set pending_exchange_creation flag in metadata
|
|
35
|
+
// This flag tells the exchange.created subscriber to auto-approve the swap
|
|
36
|
+
// when the exchange is created
|
|
37
|
+
const metadata = swapData.metadata || {};
|
|
38
|
+
const statusHistory = metadata.status_history || [];
|
|
39
|
+
await swapService.updateSwaps({
|
|
42
40
|
selector: { id },
|
|
43
41
|
data: {
|
|
44
42
|
metadata: {
|
|
45
|
-
...
|
|
43
|
+
...metadata,
|
|
46
44
|
pending_exchange_creation: true,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
exchange_preparation_started_at: new Date().toISOString(),
|
|
46
|
+
exchange_prepared_by: adminId,
|
|
47
|
+
status_history: [
|
|
48
|
+
...statusHistory,
|
|
49
|
+
{
|
|
50
|
+
status: swapData.status,
|
|
51
|
+
timestamp: new Date().toISOString(),
|
|
52
|
+
action: "exchange_preparation_started",
|
|
53
|
+
admin_id: adminId,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
54
56
|
},
|
|
55
57
|
},
|
|
56
58
|
});
|
|
57
|
-
|
|
59
|
+
// Retrieve updated swap
|
|
60
|
+
const updatedSwap = await swapService.retrieveSwap(id);
|
|
58
61
|
res.json({
|
|
59
|
-
swap:
|
|
60
|
-
|
|
62
|
+
swap: updatedSwap,
|
|
63
|
+
order_id: swapData.order_id,
|
|
64
|
+
redirect_url: `/app/orders/${swapData.order_id}/exchanges`,
|
|
61
65
|
});
|
|
62
66
|
}
|
|
63
67
|
catch (error) {
|
|
@@ -75,10 +79,10 @@ const POST = async (req, res) => {
|
|
|
75
79
|
}
|
|
76
80
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
77
81
|
res.status(500).json({
|
|
78
|
-
message: "Failed to prepare swap for exchange
|
|
82
|
+
message: "Failed to prepare swap for exchange",
|
|
79
83
|
error: errorMessage,
|
|
80
84
|
});
|
|
81
85
|
}
|
|
82
86
|
};
|
|
83
87
|
exports.POST = POST;
|
|
84
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3N3YXBzL1tpZF0vcHJlcGFyZS1leGNoYW5nZS9yb3V0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFDQSxxREFBdUQ7QUFDdkQsc0RBQXlEO0FBR2xELE1BQU0sSUFBSSxHQUFHLEtBQUssRUFDdkIsR0FBa0IsRUFDbEIsR0FBbUIsRUFDSixFQUFFO0lBQ2pCLE1BQU0sRUFBRSxFQUFFLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFBO0lBRXpCLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNSLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLHFCQUFxQixFQUFFLENBQUMsQ0FBQTtRQUN4RCxPQUFNO0lBQ1IsQ0FBQztJQUVELG1DQUFtQztJQUNuQyxNQUFNLFdBQVcsR0FBSSxHQUVuQixDQUFDLFlBQVksQ0FBQTtJQUVmLE1BQU0sT0FBTyxHQUFHLFdBQVcsRUFBRSxRQUFRLElBQUksV0FBVyxFQUFFLE9BQU8sSUFBSSxPQUFPLENBQUE7SUFFeEUsSUFBSSxDQUFDO1FBQ0gsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQWMsa0JBQVcsQ0FBQyxDQUFBO1FBRS9ELHNDQUFzQztRQUN0QyxNQUFNLElBQUksR0FBRyxNQUFNLFdBQVcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDL0MsTUFBTSxRQUFRLEdBQUcsSUFJaEIsQ0FBQTtRQUVELDhEQUE4RDtRQUM5RCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ3ZCLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNuQixPQUFPLEVBQUUsK0NBQStDO2FBQ3pELENBQUMsQ0FBQTtZQUNGLE9B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
|
|
@@ -26,6 +26,14 @@ const GET = async (req, res) => {
|
|
|
26
26
|
skip: offset,
|
|
27
27
|
});
|
|
28
28
|
const swapArray = Array.isArray(swaps) ? swaps : swaps ? [swaps] : [];
|
|
29
|
+
// Sort by created_at descending (latest first)
|
|
30
|
+
swapArray.sort((a, b) => {
|
|
31
|
+
const aData = a;
|
|
32
|
+
const bData = b;
|
|
33
|
+
const aDate = aData.created_at ? new Date(aData.created_at).getTime() : 0;
|
|
34
|
+
const bDate = bData.created_at ? new Date(bData.created_at).getTime() : 0;
|
|
35
|
+
return bDate - aDate; // Descending order (newest first)
|
|
36
|
+
});
|
|
29
37
|
res.json({
|
|
30
38
|
swaps: swapArray,
|
|
31
39
|
count: swapArray.length,
|
|
@@ -42,4 +50,4 @@ const GET = async (req, res) => {
|
|
|
42
50
|
}
|
|
43
51
|
};
|
|
44
52
|
exports.GET = GET;
|
|
45
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL3N3YXBzL3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLGdEQUFtRDtBQUc1QyxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQ3RCLEdBQWtCLEVBQ2xCLEdBQW1CLEVBQ0osRUFBRTtJQUNqQixJQUFJLENBQUM7UUFDSCxNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBYyxrQkFBVyxDQUFDLENBQUE7UUFFL0QsdUJBQXVCO1FBQ3ZCLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBNEIsQ0FBQTtRQUNyRCxNQUFNLE9BQU8sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLFFBQThCLENBQUE7UUFDeEQsTUFBTSxVQUFVLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFpQyxDQUFBO1FBQzlELE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFlLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtRQUM1RSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsTUFBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBRTlFLE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUE7UUFDM0MsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNYLE9BQU8sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1FBQ3pCLENBQUM7UUFDRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1lBQ1osT0FBTyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUE7UUFDNUIsQ0FBQztRQUNELElBQUksVUFBVSxFQUFFLENBQUM7WUFDZixPQUFPLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQTtRQUNsQyxDQUFDO1FBRUQsTUFBTSxLQUFLLEdBQUcsTUFBTSxXQUFXLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRTtZQUNqRCxJQUFJLEVBQUUsS0FBSztZQUNYLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQyxDQUFBO1FBRUYsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtRQUVyRSwrQ0FBK0M7UUFDL0MsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQVUsRUFBRSxDQUFVLEVBQUUsRUFBRTtZQUN4QyxNQUFNLEtBQUssR0FBRyxDQUFtQyxDQUFBO1lBQ2pELE1BQU0sS0FBSyxHQUFHLENBQW1DLENBQUE7WUFDakQsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDekUsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDekUsT0FBTyxLQUFLLEdBQUcsS0FBSyxDQUFBLENBQUMsa0NBQWtDO1FBQ3pELENBQUMsQ0FBQyxDQUFBO1FBRUYsR0FBRyxDQUFDLElBQUksQ0FBQztZQUNQLEtBQUssRUFBRSxTQUFTO1lBQ2hCLEtBQUssRUFBRSxTQUFTLENBQUMsTUFBTTtZQUN2QixLQUFLO1lBQ0wsTUFBTTtTQUNQLENBQUMsQ0FBQTtJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxZQUFZLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFBO1FBQzdFLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25CLE9BQU8sRUFBRSwwQkFBMEI7WUFDbkMsS0FBSyxFQUFFLFlBQVk7U0FDcEIsQ0FBQyxDQUFBO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQTtBQXREWSxRQUFBLEdBQUcsT0FzRGYifQ==
|
|
@@ -7,201 +7,186 @@ const swap_1 = require("../modules/swap");
|
|
|
7
7
|
/**
|
|
8
8
|
* Subscriber handler for exchange created events
|
|
9
9
|
* Automatically links exchanges created by admin to approved swaps
|
|
10
|
-
*
|
|
11
|
-
* When an exchange is created, this subscriber:
|
|
12
|
-
* 1. Finds the swap with matching order_id and status "approved" without exchange_id
|
|
13
|
-
* 2. Links the exchange to the swap by updating exchange_id field
|
|
14
|
-
* 3. Stores linking timestamp in metadata
|
|
15
10
|
*/
|
|
16
|
-
async function exchangeCreatedHandler({ event
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
//
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
11
|
+
async function exchangeCreatedHandler({ event, container, }) {
|
|
12
|
+
const logger = container.resolve("logger");
|
|
13
|
+
const data = event.data || {};
|
|
14
|
+
// Handle both event data formats:
|
|
15
|
+
// - Our custom event: { id, order_id, return_id, swap_id }
|
|
16
|
+
// - Medusa's event: { exchange_id, order_id }
|
|
17
|
+
const exchangeId = data.id || data.exchange_id;
|
|
18
|
+
const orderId = data.order_id;
|
|
19
|
+
if (!exchangeId) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (!orderId) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Execute with retry logic
|
|
26
|
+
await executeWithRetry(async () => await processExchangeLinking(exchangeId, orderId, container, logger), logger, exchangeId);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Main processing logic with proper error handling
|
|
30
|
+
*/
|
|
31
|
+
async function processExchangeLinking(exchangeId, orderId, container, logger) {
|
|
32
|
+
const swapService = container.resolve(swap_1.SWAP_MODULE);
|
|
33
|
+
const remoteQuery = container.resolve(utils_1.ContainerRegistrationKeys.REMOTE_QUERY);
|
|
34
|
+
// 1. Validate exchange exists in Medusa
|
|
35
|
+
const exchange = await validateExchangeExists(exchangeId, remoteQuery, logger);
|
|
36
|
+
if (!exchange) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// 2. Find eligible swap for this order
|
|
40
|
+
const swap = await findEligibleSwap(orderId, swapService, logger);
|
|
41
|
+
if (!swap) {
|
|
42
|
+
logger.debug(`[Exchange Created Subscriber] No unlinked swap found for order ${orderId}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// 3. Update swap with exchange linkage
|
|
46
|
+
await linkExchangeToSwap(swap, exchangeId, swapService, logger);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validate exchange exists using remote query
|
|
50
|
+
*/
|
|
51
|
+
async function validateExchangeExists(exchangeId, remoteQuery, logger) {
|
|
52
|
+
try {
|
|
53
|
+
const exchangeQuery = (0, utils_1.remoteQueryObjectFromString)({
|
|
54
|
+
entryPoint: "exchange",
|
|
55
|
+
fields: ["id", "order_id", "status"],
|
|
56
|
+
filters: { id: exchangeId },
|
|
57
|
+
});
|
|
58
|
+
const [exchange] = await remoteQuery(exchangeQuery);
|
|
59
|
+
if (!exchange) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return exchange;
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
// Continue anyway - exchange might be valid but query failed
|
|
66
|
+
return { id: exchangeId }; // Return minimal object to continue
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Find eligible swap for linking
|
|
71
|
+
*/
|
|
72
|
+
async function findEligibleSwap(orderId, swapService, logger) {
|
|
73
|
+
try {
|
|
74
|
+
// Get all swaps for this order and filter in memory
|
|
75
|
+
// This is more reliable than filtering by exchange_id: null in the query
|
|
76
|
+
const allSwaps = await swapService.listSwaps({ order_id: orderId }, { take: 100 } // Get up to 100 swaps to find unlinked ones
|
|
77
|
+
);
|
|
78
|
+
const swapsArray = Array.isArray(allSwaps) ? allSwaps : allSwaps ? [allSwaps] : [];
|
|
79
|
+
// Filter for unlinked swaps (exchange_id is null or undefined)
|
|
80
|
+
const unlinkedSwaps = swapsArray.filter((swap) => {
|
|
81
|
+
const exchangeId = swap.exchange_id;
|
|
82
|
+
return !exchangeId || exchangeId === null || exchangeId === "";
|
|
83
|
+
});
|
|
84
|
+
if (unlinkedSwaps.length === 0) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
// Priority 1: Approved swaps without exchange_id
|
|
88
|
+
const approvedSwaps = unlinkedSwaps.filter((swap) => swap.status === "approved");
|
|
89
|
+
if (approvedSwaps.length > 0) {
|
|
90
|
+
return approvedSwaps[0];
|
|
91
|
+
}
|
|
92
|
+
// Priority 2: Requested swaps with pending_exchange_creation flag
|
|
93
|
+
const requestedSwaps = unlinkedSwaps.filter((swap) => {
|
|
94
|
+
if (swap.status !== "requested")
|
|
95
|
+
return false;
|
|
96
|
+
const metadata = swap.metadata || {};
|
|
97
|
+
return metadata.pending_exchange_creation === true;
|
|
98
|
+
});
|
|
99
|
+
if (requestedSwaps.length > 0) {
|
|
100
|
+
return requestedSwaps[0];
|
|
101
|
+
}
|
|
102
|
+
// Priority 3: Any requested swap (fallback)
|
|
103
|
+
const anyRequestedSwaps = unlinkedSwaps.filter((swap) => swap.status === "requested");
|
|
104
|
+
if (anyRequestedSwaps.length > 0) {
|
|
105
|
+
return anyRequestedSwaps[0];
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
logger.error(`Error finding swap:`, error);
|
|
111
|
+
throw error; // Re-throw to trigger retry
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Link exchange to swap with metadata updates
|
|
116
|
+
*/
|
|
117
|
+
async function linkExchangeToSwap(swap, exchangeId, swapService, logger) {
|
|
118
|
+
const swapId = swap.id;
|
|
119
|
+
const swapStatus = swap.status;
|
|
120
|
+
const metadata = swap.metadata || {};
|
|
121
|
+
const pendingExchangeCreation = metadata.pending_exchange_creation === true;
|
|
122
|
+
const shouldApprove = swapStatus === "requested" && pendingExchangeCreation;
|
|
123
|
+
const linkingHistory = metadata.exchange_linking_history || [];
|
|
124
|
+
const statusHistory = metadata.status_history || [];
|
|
125
|
+
const updateData = {
|
|
126
|
+
exchange_id: exchangeId,
|
|
127
|
+
metadata: {
|
|
128
|
+
...metadata,
|
|
129
|
+
exchange_linking_history: [
|
|
130
|
+
...linkingHistory,
|
|
131
|
+
{
|
|
129
132
|
exchange_id: exchangeId,
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
exchange_linking_history: [
|
|
134
|
-
...linkingHistory,
|
|
135
|
-
{
|
|
136
|
-
exchange_id: exchangeId,
|
|
137
|
-
linked_at: new Date().toISOString(),
|
|
138
|
-
linked_by: "exchange_created_subscriber",
|
|
139
|
-
auto_approved: shouldApprove,
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
exchange_linked_at: new Date().toISOString(),
|
|
143
|
-
pending_exchange_creation: false,
|
|
144
|
-
...(shouldApprove ? {
|
|
145
|
-
status_history: [
|
|
146
|
-
...statusHistory,
|
|
147
|
-
{
|
|
148
|
-
status: "approved",
|
|
149
|
-
timestamp: new Date().toISOString(),
|
|
150
|
-
auto_approved: true,
|
|
151
|
-
approved_via: "exchange_created_subscriber",
|
|
152
|
-
},
|
|
153
|
-
],
|
|
154
|
-
} : {}),
|
|
155
|
-
},
|
|
133
|
+
linked_at: new Date().toISOString(),
|
|
134
|
+
linked_by: "exchange_created_subscriber",
|
|
135
|
+
auto_approved: shouldApprove,
|
|
156
136
|
},
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
137
|
+
],
|
|
138
|
+
exchange_linked_at: new Date().toISOString(),
|
|
139
|
+
pending_exchange_creation: false,
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
// Update status if needed
|
|
143
|
+
if (shouldApprove) {
|
|
144
|
+
updateData.status = "approved";
|
|
145
|
+
updateData.metadata.status_history = [
|
|
146
|
+
...statusHistory,
|
|
147
|
+
{
|
|
148
|
+
status: "approved",
|
|
149
|
+
timestamp: new Date().toISOString(),
|
|
150
|
+
auto_approved: true,
|
|
151
|
+
approved_via: "exchange_created_subscriber",
|
|
152
|
+
},
|
|
153
|
+
];
|
|
154
|
+
}
|
|
155
|
+
await swapService.updateSwaps({
|
|
156
|
+
selector: { id: swapId },
|
|
157
|
+
data: updateData,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Retry execution with exponential backoff
|
|
162
|
+
*/
|
|
163
|
+
async function executeWithRetry(operation, logger, exchangeId, maxRetries = 3, baseDelay = 1000) {
|
|
164
|
+
let lastError;
|
|
165
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
166
|
+
try {
|
|
167
|
+
return await operation();
|
|
164
168
|
}
|
|
165
169
|
catch (error) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
retryCount++;
|
|
171
|
-
const delay = retryDelay * Math.pow(2, retryCount - 1);
|
|
172
|
-
console.warn(`[Exchange Created Subscriber] Retry ${retryCount}/${maxRetries} after ${delay}ms:`, errorMessage);
|
|
173
|
-
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
174
|
-
return executeWithRetry();
|
|
170
|
+
lastError = error;
|
|
171
|
+
if (attempt < maxRetries - 1) {
|
|
172
|
+
const delay = baseDelay * Math.pow(2, attempt);
|
|
173
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
175
174
|
}
|
|
176
|
-
console.error("[Exchange Created Subscriber] Error linking exchange to swap (max retries exceeded):", {
|
|
177
|
-
error: errorMessage,
|
|
178
|
-
stack: errorStack,
|
|
179
|
-
retry_count: retryCount,
|
|
180
|
-
exchange_id: data.id,
|
|
181
|
-
order_id: data.order_id,
|
|
182
|
-
});
|
|
183
|
-
// Don't throw - subscriber errors shouldn't break the exchange flow
|
|
184
175
|
}
|
|
185
|
-
}
|
|
186
|
-
|
|
176
|
+
}
|
|
177
|
+
logger.error(`All ${maxRetries} attempts failed for exchange ${exchangeId}:`, lastError?.message || "Unknown error");
|
|
178
|
+
throw lastError;
|
|
187
179
|
}
|
|
188
180
|
/**
|
|
189
181
|
* Subscriber configuration
|
|
190
182
|
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
* This subscriber listens for exchange creation events in Medusa.
|
|
194
|
-
* When an exchange is created, it automatically links it to an approved swap
|
|
195
|
-
* if one exists for the same order.
|
|
196
|
-
*
|
|
197
|
-
* Event Data Structure Expected:
|
|
198
|
-
* {
|
|
199
|
-
* id: string (exchange ID)
|
|
200
|
-
* order_id?: string (order ID)
|
|
201
|
-
* [key: string]: unknown (other exchange fields)
|
|
202
|
-
* }
|
|
183
|
+
* Listen to exchange.created event emitted by create-medusa-exchange-step
|
|
184
|
+
* Also listen to order.exchange_created as fallback in case Medusa emits that instead
|
|
203
185
|
*/
|
|
204
186
|
exports.config = {
|
|
205
|
-
event:
|
|
187
|
+
event: [
|
|
188
|
+
"exchange.created",
|
|
189
|
+
"order.exchange_created",
|
|
190
|
+
],
|
|
206
191
|
};
|
|
207
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
192
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXhjaGFuZ2UtY3JlYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9zdWJzY3JpYmVycy9leGNoYW5nZS1jcmVhdGVkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlCQSx5Q0E0QkM7QUE1Q0QscURBQWtHO0FBRWxHLDBDQUE2QztBQVU3Qzs7O0dBR0c7QUFDWSxLQUFLLFVBQVUsc0JBQXNCLENBQUMsRUFDbkQsS0FBSyxFQUNMLFNBQVMsR0FDZ0M7SUFDekMsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUUxQyxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQTtJQUU3QixrQ0FBa0M7SUFDbEMsMkRBQTJEO0lBQzNELDhDQUE4QztJQUM5QyxNQUFNLFVBQVUsR0FBSSxJQUF3QixDQUFDLEVBQUUsSUFBSyxJQUFpQyxDQUFDLFdBQVcsQ0FBQTtJQUNqRyxNQUFNLE9BQU8sR0FBSSxJQUE4QixDQUFDLFFBQVEsQ0FBQTtJQUV4RCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDaEIsT0FBTTtJQUNSLENBQUM7SUFFRCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixPQUFNO0lBQ1IsQ0FBQztJQUVELDJCQUEyQjtJQUMzQixNQUFNLGdCQUFnQixDQUNwQixLQUFLLElBQUksRUFBRSxDQUFDLE1BQU0sc0JBQXNCLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLEVBQ2hGLE1BQU0sRUFDTixVQUFVLENBQ1gsQ0FBQTtBQUNILENBQUM7QUFFRDs7R0FFRztBQUNILEtBQUssVUFBVSxzQkFBc0IsQ0FDbkMsVUFBa0IsRUFDbEIsT0FBZSxFQUNmLFNBQXdCLEVBQ3hCLE1BQVc7SUFFWCxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFjLGtCQUFXLENBQUMsQ0FBQTtJQUMvRCxN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
|