@reactionary/medusa 0.6.3
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/README.md +11 -0
- package/capabilities/cart.capability.js +517 -0
- package/capabilities/category.capability.js +216 -0
- package/capabilities/checkout.capability.js +533 -0
- package/capabilities/identity.capability.js +128 -0
- package/capabilities/inventory.capability.js +142 -0
- package/capabilities/order-search.capability.js +161 -0
- package/capabilities/order.capability.js +179 -0
- package/capabilities/price.capability.js +120 -0
- package/capabilities/product-associations.capability.js +148 -0
- package/capabilities/product-recommendations.capability.js +116 -0
- package/capabilities/product-search.capability.js +177 -0
- package/capabilities/product.capability.js +252 -0
- package/capabilities/profile.capability.js +333 -0
- package/core/client.js +269 -0
- package/core/initialize.js +290 -0
- package/core/initialize.types.js +13 -0
- package/factories/cart/cart.factory.js +17 -0
- package/factories/category/category.factory.js +17 -0
- package/factories/checkout/checkout.factory.js +22 -0
- package/factories/identity/identity.factory.js +12 -0
- package/factories/index.js +12 -0
- package/factories/inventory/inventory.factory.js +12 -0
- package/factories/order/order.factory.js +12 -0
- package/factories/order-search/order-search.factory.js +12 -0
- package/factories/price/price.factory.js +12 -0
- package/factories/product/product.factory.js +12 -0
- package/factories/product-associations/product-associations.factory.js +12 -0
- package/factories/product-search/product-search.factory.js +12 -0
- package/factories/profile/profile.factory.js +12 -0
- package/index.js +17 -0
- package/package.json +17 -0
- package/schema/capabilities.schema.js +43 -0
- package/schema/configuration.schema.js +11 -0
- package/schema/medusa.schema.js +26 -0
- package/src/capabilities/cart.capability.d.ts +100 -0
- package/src/capabilities/category.capability.d.ts +36 -0
- package/src/capabilities/checkout.capability.d.ts +88 -0
- package/src/capabilities/identity.capability.d.ts +13 -0
- package/src/capabilities/inventory.capability.d.ts +21 -0
- package/src/capabilities/order-search.capability.d.ts +53 -0
- package/src/capabilities/order.capability.d.ts +49 -0
- package/src/capabilities/price.capability.d.ts +16 -0
- package/src/capabilities/product-associations.capability.d.ts +19 -0
- package/src/capabilities/product-recommendations.capability.d.ts +41 -0
- package/src/capabilities/product-search.capability.d.ts +45 -0
- package/src/capabilities/product.capability.d.ts +32 -0
- package/src/capabilities/profile.capability.d.ts +39 -0
- package/src/core/client.d.ts +81 -0
- package/src/core/initialize.d.ts +5 -0
- package/src/core/initialize.types.d.ts +108 -0
- package/src/factories/cart/cart.factory.d.ts +9 -0
- package/src/factories/category/category.factory.d.ts +9 -0
- package/src/factories/checkout/checkout.factory.d.ts +11 -0
- package/src/factories/identity/identity.factory.d.ts +7 -0
- package/src/factories/index.d.ts +12 -0
- package/src/factories/inventory/inventory.factory.d.ts +7 -0
- package/src/factories/order/order.factory.d.ts +7 -0
- package/src/factories/order-search/order-search.factory.d.ts +7 -0
- package/src/factories/price/price.factory.d.ts +9 -0
- package/src/factories/product/product.factory.d.ts +7 -0
- package/src/factories/product-associations/product-associations.factory.d.ts +7 -0
- package/src/factories/product-search/product-search.factory.d.ts +7 -0
- package/src/factories/profile/profile.factory.d.ts +7 -0
- package/src/index.d.ts +17 -0
- package/src/schema/capabilities.schema.d.ts +116 -0
- package/src/schema/configuration.schema.d.ts +9 -0
- package/src/schema/medusa.schema.d.ts +33 -0
- package/src/test/test-utils.d.ts +2 -0
- package/src/utils/medusa-helpers.d.ts +35 -0
- package/test/test-utils.js +12 -0
- package/utils/medusa-helpers.js +72 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
InventoryCapability,
|
|
14
|
+
InventorySchema,
|
|
15
|
+
InventoryQueryBySKUSchema,
|
|
16
|
+
Reactionary,
|
|
17
|
+
success
|
|
18
|
+
} from "@reactionary/core";
|
|
19
|
+
import { MedusaAdminAPI } from "../core/client.js";
|
|
20
|
+
import createDebug from "debug";
|
|
21
|
+
const debug = createDebug("reactionary:medusa:inventory");
|
|
22
|
+
class MedusaInventoryCapability extends InventoryCapability {
|
|
23
|
+
constructor(config, cache, context, medusaApi, factory) {
|
|
24
|
+
super(cache, context);
|
|
25
|
+
this.medusaApi = medusaApi;
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.factory = factory;
|
|
28
|
+
}
|
|
29
|
+
config;
|
|
30
|
+
factory;
|
|
31
|
+
async getBySKU(payload) {
|
|
32
|
+
const sku = payload.variant.sku;
|
|
33
|
+
const fulfillmentCenterKey = payload.fulfilmentCenter.key;
|
|
34
|
+
if (debug.enabled) {
|
|
35
|
+
debug(`Fetching inventory for SKU: ${sku}, fulfillment center: ${fulfillmentCenterKey}`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const adminClient = await new MedusaAdminAPI(this.config, this.context).getClient();
|
|
39
|
+
const inventoryResponse = await adminClient.admin.inventoryItem.list({
|
|
40
|
+
sku: [sku],
|
|
41
|
+
limit: 1,
|
|
42
|
+
offset: 0
|
|
43
|
+
});
|
|
44
|
+
if (!inventoryResponse.inventory_items || inventoryResponse.inventory_items.length === 0) {
|
|
45
|
+
if (debug.enabled) {
|
|
46
|
+
debug(`No inventory items found for SKU: ${sku}`);
|
|
47
|
+
}
|
|
48
|
+
return success(this.createEmptyInventoryResult(sku, fulfillmentCenterKey));
|
|
49
|
+
}
|
|
50
|
+
const inventoryItem = inventoryResponse.inventory_items[0];
|
|
51
|
+
const locationsResponse = await adminClient.admin.stockLocation.list({
|
|
52
|
+
name: fulfillmentCenterKey,
|
|
53
|
+
limit: 1,
|
|
54
|
+
offset: 0
|
|
55
|
+
});
|
|
56
|
+
let quantity = 0;
|
|
57
|
+
let locationFound = false;
|
|
58
|
+
if (locationsResponse.stock_locations && locationsResponse.stock_locations.length > 0) {
|
|
59
|
+
const location = locationsResponse.stock_locations[0];
|
|
60
|
+
locationFound = true;
|
|
61
|
+
const levelsResponse = await adminClient.admin.inventoryItem.listLevels(inventoryItem.id, {
|
|
62
|
+
location_id: [location.id]
|
|
63
|
+
});
|
|
64
|
+
if (levelsResponse.inventory_levels && levelsResponse.inventory_levels.length > 0) {
|
|
65
|
+
const level = levelsResponse.inventory_levels[0];
|
|
66
|
+
quantity = level.stocked_quantity - level.reserved_quantity;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
if (!locationFound) {
|
|
70
|
+
if (debug.enabled) {
|
|
71
|
+
debug(`No stock location found with name: ${fulfillmentCenterKey}`);
|
|
72
|
+
}
|
|
73
|
+
return success(this.createEmptyInventoryResult(sku, fulfillmentCenterKey));
|
|
74
|
+
}
|
|
75
|
+
return success(this.parseSingle({
|
|
76
|
+
sku: payload.variant.sku,
|
|
77
|
+
fulfillmentCenterKey,
|
|
78
|
+
quantity,
|
|
79
|
+
inventoryItemId: inventoryItem.id
|
|
80
|
+
}));
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (debug.enabled) {
|
|
83
|
+
debug(`Error fetching inventory for SKU: ${sku}`, error);
|
|
84
|
+
}
|
|
85
|
+
return success(this.createEmptyInventoryResult(sku, fulfillmentCenterKey));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
parseSingle(_body) {
|
|
89
|
+
const { sku, fulfillmentCenterKey, quantity } = _body;
|
|
90
|
+
const identifier = {
|
|
91
|
+
variant: {
|
|
92
|
+
sku
|
|
93
|
+
},
|
|
94
|
+
fulfillmentCenter: {
|
|
95
|
+
key: fulfillmentCenterKey
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
let status = "outOfStock";
|
|
99
|
+
if (quantity > 0) {
|
|
100
|
+
status = "inStock";
|
|
101
|
+
}
|
|
102
|
+
const result = {
|
|
103
|
+
identifier,
|
|
104
|
+
quantity,
|
|
105
|
+
status
|
|
106
|
+
};
|
|
107
|
+
return this.factory.parseInventory(this.context, result);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Utility function to create an empty inventory result.
|
|
111
|
+
* This is used when no inventory is found for a given SKU + fulfillment center combination.
|
|
112
|
+
* @param sku
|
|
113
|
+
* @param fulfillmentCenterKey
|
|
114
|
+
* @returns
|
|
115
|
+
*/
|
|
116
|
+
createEmptyInventoryResult(sku, fulfillmentCenterKey) {
|
|
117
|
+
const identifier = {
|
|
118
|
+
variant: { sku },
|
|
119
|
+
fulfillmentCenter: { key: fulfillmentCenterKey }
|
|
120
|
+
};
|
|
121
|
+
const quantity = 0;
|
|
122
|
+
const status = "outOfStock";
|
|
123
|
+
const result = {
|
|
124
|
+
identifier,
|
|
125
|
+
quantity,
|
|
126
|
+
status
|
|
127
|
+
};
|
|
128
|
+
return this.factory.parseInventory(this.context, result);
|
|
129
|
+
}
|
|
130
|
+
getResourceName() {
|
|
131
|
+
return "inventory";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
__decorateClass([
|
|
135
|
+
Reactionary({
|
|
136
|
+
inputSchema: InventoryQueryBySKUSchema,
|
|
137
|
+
outputSchema: InventorySchema
|
|
138
|
+
})
|
|
139
|
+
], MedusaInventoryCapability.prototype, "getBySKU", 1);
|
|
140
|
+
export {
|
|
141
|
+
MedusaInventoryCapability
|
|
142
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
AddressIdentifierSchema,
|
|
14
|
+
OrderSearchCapability,
|
|
15
|
+
OrderSearchQueryByTermSchema,
|
|
16
|
+
OrderSearchResultSchema,
|
|
17
|
+
Reactionary,
|
|
18
|
+
success
|
|
19
|
+
} from "@reactionary/core";
|
|
20
|
+
import createDebug from "debug";
|
|
21
|
+
const debug = createDebug("reactionary:medusa:order-search");
|
|
22
|
+
class MedusaOrderSearchCapability extends OrderSearchCapability {
|
|
23
|
+
constructor(config, cache, context, medusaApi, factory) {
|
|
24
|
+
super(cache, context);
|
|
25
|
+
this.medusaApi = medusaApi;
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.factory = factory;
|
|
28
|
+
}
|
|
29
|
+
config;
|
|
30
|
+
factory;
|
|
31
|
+
queryByTermPayload(payload) {
|
|
32
|
+
const filters = {};
|
|
33
|
+
if (payload.search.term) {
|
|
34
|
+
debug("Searching orders by term is not supported in Medusa");
|
|
35
|
+
}
|
|
36
|
+
if (payload.search.partNumber) {
|
|
37
|
+
debug("Searching orders by part number is not supported in Medusa");
|
|
38
|
+
}
|
|
39
|
+
if (payload.search.startDate) {
|
|
40
|
+
debug("Searching orders by start date is not supported in Medusa");
|
|
41
|
+
}
|
|
42
|
+
if (payload.search.endDate) {
|
|
43
|
+
debug("Searching orders by end date is not supported in Medusa");
|
|
44
|
+
}
|
|
45
|
+
const statusFilter = (payload.search.orderStatus ?? []).map((status) => {
|
|
46
|
+
let retStatus = "draft";
|
|
47
|
+
if (status === "AwaitingPayment") {
|
|
48
|
+
retStatus = "draft";
|
|
49
|
+
}
|
|
50
|
+
if (status === "ReleasedToFulfillment") {
|
|
51
|
+
retStatus = "pending";
|
|
52
|
+
}
|
|
53
|
+
if (status === "Shipped") {
|
|
54
|
+
retStatus = "completed";
|
|
55
|
+
}
|
|
56
|
+
if (status === "Cancelled") {
|
|
57
|
+
retStatus = "canceled";
|
|
58
|
+
}
|
|
59
|
+
return retStatus;
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
status: statusFilter,
|
|
63
|
+
limit: payload.search.paginationOptions.pageSize,
|
|
64
|
+
offset: (payload.search.paginationOptions.pageNumber - 1) * payload.search.paginationOptions.pageSize
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async queryByTerm(payload) {
|
|
68
|
+
debug("queryByTerm", payload);
|
|
69
|
+
const medusa = await this.medusaApi.getClient();
|
|
70
|
+
const response = await medusa.store.order.list(this.queryByTermPayload(payload));
|
|
71
|
+
const result = this.parsePaginatedResult(response, payload);
|
|
72
|
+
if (debug.enabled) {
|
|
73
|
+
debug(
|
|
74
|
+
`Search for term "${payload.search.term}" returned ${response.orders.length} orders (page ${payload.search.paginationOptions.pageNumber} of ${result.totalPages})`
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return success(this.factory.parseOrderSearchResult(this.context, result, payload));
|
|
78
|
+
}
|
|
79
|
+
composeAddressFromStoreAddress(storeAddress) {
|
|
80
|
+
return {
|
|
81
|
+
identifier: AddressIdentifierSchema.parse({
|
|
82
|
+
nickName: storeAddress.id
|
|
83
|
+
}),
|
|
84
|
+
firstName: storeAddress.first_name || "",
|
|
85
|
+
lastName: storeAddress.last_name || "",
|
|
86
|
+
streetAddress: storeAddress.address_1 || "",
|
|
87
|
+
streetNumber: storeAddress.address_2 || "",
|
|
88
|
+
city: storeAddress.city || "",
|
|
89
|
+
postalCode: storeAddress.postal_code || "",
|
|
90
|
+
countryCode: storeAddress.country_code || "",
|
|
91
|
+
region: ""
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
parseSingle(body) {
|
|
95
|
+
const identifier = { key: body.id };
|
|
96
|
+
const userId = {
|
|
97
|
+
userId: body.customer_id || ""
|
|
98
|
+
};
|
|
99
|
+
const customerName = `${body.billing_address?.first_name} ${body.billing_address?.last_name}`;
|
|
100
|
+
const shippingAddress = this.composeAddressFromStoreAddress(body.shipping_address);
|
|
101
|
+
const orderDate = new Date(body.created_at).toISOString();
|
|
102
|
+
let orderStatus = "AwaitingPayment";
|
|
103
|
+
if (body.status === "draft") {
|
|
104
|
+
orderStatus = "AwaitingPayment";
|
|
105
|
+
}
|
|
106
|
+
if (body.status === "pending") {
|
|
107
|
+
orderStatus = "ReleasedToFulfillment";
|
|
108
|
+
}
|
|
109
|
+
if (body.status === "completed") {
|
|
110
|
+
orderStatus = "Shipped";
|
|
111
|
+
}
|
|
112
|
+
if (body.status === "canceled") {
|
|
113
|
+
orderStatus = "Cancelled";
|
|
114
|
+
}
|
|
115
|
+
let inventoryStatus = "NotAllocated";
|
|
116
|
+
if (body.fulfillment_status === "fulfilled") {
|
|
117
|
+
inventoryStatus = "Allocated";
|
|
118
|
+
}
|
|
119
|
+
const totalAmount = {
|
|
120
|
+
currency: body.currency_code.toUpperCase(),
|
|
121
|
+
value: body.total ? body.total : 0
|
|
122
|
+
};
|
|
123
|
+
const order = {
|
|
124
|
+
identifier,
|
|
125
|
+
userId,
|
|
126
|
+
customerName,
|
|
127
|
+
shippingAddress,
|
|
128
|
+
orderDate,
|
|
129
|
+
orderStatus,
|
|
130
|
+
inventoryStatus,
|
|
131
|
+
totalAmount
|
|
132
|
+
};
|
|
133
|
+
return order;
|
|
134
|
+
}
|
|
135
|
+
parsePaginatedResult(body, query) {
|
|
136
|
+
const identifier = {
|
|
137
|
+
...query.search
|
|
138
|
+
};
|
|
139
|
+
const orders = body.orders.map((o) => {
|
|
140
|
+
return this.parseSingle(o);
|
|
141
|
+
});
|
|
142
|
+
const result = {
|
|
143
|
+
identifier,
|
|
144
|
+
pageNumber: (Math.ceil(body.offset / body.limit) || 0) + 1,
|
|
145
|
+
pageSize: body.limit,
|
|
146
|
+
totalCount: body.count,
|
|
147
|
+
totalPages: Math.ceil(body.count / body.limit || 0) + 1,
|
|
148
|
+
items: orders
|
|
149
|
+
};
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
__decorateClass([
|
|
154
|
+
Reactionary({
|
|
155
|
+
inputSchema: OrderSearchQueryByTermSchema,
|
|
156
|
+
outputSchema: OrderSearchResultSchema
|
|
157
|
+
})
|
|
158
|
+
], MedusaOrderSearchCapability.prototype, "queryByTerm", 1);
|
|
159
|
+
export {
|
|
160
|
+
MedusaOrderSearchCapability
|
|
161
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
OrderCapability,
|
|
14
|
+
OrderQueryByIdSchema,
|
|
15
|
+
OrderSchema,
|
|
16
|
+
Reactionary,
|
|
17
|
+
success,
|
|
18
|
+
error,
|
|
19
|
+
ProductVariantIdentifierSchema
|
|
20
|
+
} from "@reactionary/core";
|
|
21
|
+
import createDebug from "debug";
|
|
22
|
+
import { handleProviderError } from "../utils/medusa-helpers.js";
|
|
23
|
+
import { parseMedusaItemPrice, parseMedusaCostBreakdown } from "../utils/medusa-helpers.js";
|
|
24
|
+
const debug = createDebug("reactionary:medusa:order");
|
|
25
|
+
class MedusaOrderCapability extends OrderCapability {
|
|
26
|
+
constructor(config, cache, context, medusaApi, factory) {
|
|
27
|
+
super(cache, context);
|
|
28
|
+
this.medusaApi = medusaApi;
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.factory = factory;
|
|
31
|
+
}
|
|
32
|
+
config;
|
|
33
|
+
factory;
|
|
34
|
+
async getById(payload) {
|
|
35
|
+
debug("getById", payload);
|
|
36
|
+
const medusa = await this.medusaApi.getClient();
|
|
37
|
+
try {
|
|
38
|
+
const response = await medusa.store.order.retrieve(payload.order.key);
|
|
39
|
+
const order = this.parseSingle(response.order);
|
|
40
|
+
return success(order);
|
|
41
|
+
} catch (err) {
|
|
42
|
+
return handleProviderError("order", err);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extension point to control the parsing of a single cart item price
|
|
47
|
+
* @param remoteItem
|
|
48
|
+
* @param currency
|
|
49
|
+
* @returns
|
|
50
|
+
*/
|
|
51
|
+
parseItemPrice(remoteItem, currency) {
|
|
52
|
+
return parseMedusaItemPrice(remoteItem, currency);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extension point to control the parsing of the cost breakdown of a cart
|
|
56
|
+
* @param remote
|
|
57
|
+
* @returns
|
|
58
|
+
*/
|
|
59
|
+
parseCostBreakdown(remote) {
|
|
60
|
+
return parseMedusaCostBreakdown(remote);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Extension point to control the parsing of a single cart item
|
|
64
|
+
* @param remoteItem
|
|
65
|
+
* @param currency
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
parseOrderItem(remoteItem, currency) {
|
|
69
|
+
const item = {
|
|
70
|
+
identifier: {
|
|
71
|
+
key: remoteItem.id
|
|
72
|
+
},
|
|
73
|
+
variant: ProductVariantIdentifierSchema.parse({
|
|
74
|
+
sku: remoteItem.variant_sku || ""
|
|
75
|
+
}),
|
|
76
|
+
quantity: remoteItem.quantity || 1,
|
|
77
|
+
price: this.parseItemPrice(remoteItem, currency),
|
|
78
|
+
inventoryStatus: "Allocated"
|
|
79
|
+
};
|
|
80
|
+
return item;
|
|
81
|
+
}
|
|
82
|
+
parsePaymentInstruction(remotePayment, order) {
|
|
83
|
+
const paymentMethodIdentifier = {
|
|
84
|
+
method: remotePayment.payment_providers?.[0]?.id || "unknown",
|
|
85
|
+
name: remotePayment.payment_providers?.[0]?.id || "unknown",
|
|
86
|
+
paymentProcessor: remotePayment.payment_providers?.[0]?.id || "unknown"
|
|
87
|
+
};
|
|
88
|
+
let status = "pending";
|
|
89
|
+
switch (remotePayment.status) {
|
|
90
|
+
case "not_paid":
|
|
91
|
+
status = "pending";
|
|
92
|
+
break;
|
|
93
|
+
case "awaiting":
|
|
94
|
+
status = "pending";
|
|
95
|
+
break;
|
|
96
|
+
case "authorized":
|
|
97
|
+
status = "authorized";
|
|
98
|
+
break;
|
|
99
|
+
case "partially_authorized":
|
|
100
|
+
status = "pending";
|
|
101
|
+
break;
|
|
102
|
+
case "canceled":
|
|
103
|
+
status = "canceled";
|
|
104
|
+
break;
|
|
105
|
+
case "failed":
|
|
106
|
+
status = "canceled";
|
|
107
|
+
break;
|
|
108
|
+
case "completed":
|
|
109
|
+
status = "capture";
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
const paymentData = remotePayment.payments?.[0].data || {};
|
|
113
|
+
const pi = {
|
|
114
|
+
identifier: {
|
|
115
|
+
key: remotePayment.id
|
|
116
|
+
},
|
|
117
|
+
amount: {
|
|
118
|
+
value: remotePayment.amount,
|
|
119
|
+
currency: remotePayment.currency_code?.toUpperCase()
|
|
120
|
+
},
|
|
121
|
+
paymentMethod: paymentMethodIdentifier,
|
|
122
|
+
protocolData: paymentData ? Object.entries(paymentData).map(([key, value]) => ({
|
|
123
|
+
key,
|
|
124
|
+
value: String(value)
|
|
125
|
+
})) : [],
|
|
126
|
+
status
|
|
127
|
+
};
|
|
128
|
+
return pi;
|
|
129
|
+
}
|
|
130
|
+
parseSingle(body) {
|
|
131
|
+
const identifier = { key: body.id };
|
|
132
|
+
const userId = {
|
|
133
|
+
userId: body.customer_id || ""
|
|
134
|
+
};
|
|
135
|
+
const items = (body.items || []).map((item) => {
|
|
136
|
+
return this.parseOrderItem(item, body.currency_code.toUpperCase());
|
|
137
|
+
});
|
|
138
|
+
const price = this.parseCostBreakdown(body);
|
|
139
|
+
let orderStatus = "AwaitingPayment";
|
|
140
|
+
if (body.status === "draft") {
|
|
141
|
+
orderStatus = "AwaitingPayment";
|
|
142
|
+
}
|
|
143
|
+
if (body.status === "pending") {
|
|
144
|
+
orderStatus = "ReleasedToFulfillment";
|
|
145
|
+
}
|
|
146
|
+
if (body.status === "completed") {
|
|
147
|
+
orderStatus = "Shipped";
|
|
148
|
+
}
|
|
149
|
+
if (body.status === "canceled") {
|
|
150
|
+
orderStatus = "Cancelled";
|
|
151
|
+
}
|
|
152
|
+
let inventoryStatus = "NotAllocated";
|
|
153
|
+
if (body.fulfillment_status === "fulfilled") {
|
|
154
|
+
inventoryStatus = "Allocated";
|
|
155
|
+
}
|
|
156
|
+
const paymentInstructions = body.payment_collections?.map((pc) => {
|
|
157
|
+
return this.parsePaymentInstruction(pc, body);
|
|
158
|
+
}) || [];
|
|
159
|
+
const result = {
|
|
160
|
+
identifier,
|
|
161
|
+
userId,
|
|
162
|
+
items,
|
|
163
|
+
price,
|
|
164
|
+
orderStatus,
|
|
165
|
+
inventoryStatus,
|
|
166
|
+
paymentInstructions
|
|
167
|
+
};
|
|
168
|
+
return this.factory.parseOrder(this.context, result);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
__decorateClass([
|
|
172
|
+
Reactionary({
|
|
173
|
+
inputSchema: OrderQueryByIdSchema,
|
|
174
|
+
outputSchema: OrderSchema
|
|
175
|
+
})
|
|
176
|
+
], MedusaOrderCapability.prototype, "getById", 1);
|
|
177
|
+
export {
|
|
178
|
+
MedusaOrderCapability
|
|
179
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import {
|
|
13
|
+
PriceCapability,
|
|
14
|
+
PriceSchema,
|
|
15
|
+
CustomerPriceQuerySchema,
|
|
16
|
+
ListPriceQuerySchema,
|
|
17
|
+
Reactionary,
|
|
18
|
+
success
|
|
19
|
+
} from "@reactionary/core";
|
|
20
|
+
import createDebug from "debug";
|
|
21
|
+
const debug = createDebug("reactionary:medusa:price");
|
|
22
|
+
class MedusaPriceCapability extends PriceCapability {
|
|
23
|
+
constructor(config, cache, context, medusaApi, factory) {
|
|
24
|
+
super(cache, context);
|
|
25
|
+
this.medusaApi = medusaApi;
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.factory = factory;
|
|
28
|
+
}
|
|
29
|
+
config;
|
|
30
|
+
factory;
|
|
31
|
+
async getListPrice(payload) {
|
|
32
|
+
const result = await this.getBySKU(payload, "list");
|
|
33
|
+
return success(result);
|
|
34
|
+
}
|
|
35
|
+
async getCustomerPrice(payload) {
|
|
36
|
+
const result = await this.getBySKU(payload, "customer");
|
|
37
|
+
return success(result);
|
|
38
|
+
}
|
|
39
|
+
async getBySKU(payload, mode) {
|
|
40
|
+
const sku = payload.variant.sku;
|
|
41
|
+
if (debug.enabled) {
|
|
42
|
+
debug(`Fetching price for SKU: ${sku}`);
|
|
43
|
+
}
|
|
44
|
+
try {
|
|
45
|
+
const productForSKU = await this.medusaApi.resolveProductForSKU(payload.variant.sku);
|
|
46
|
+
const client = await this.medusaApi.getClient();
|
|
47
|
+
const product = (await client.store.product.retrieve(
|
|
48
|
+
productForSKU.id || "",
|
|
49
|
+
{ region_id: (await this.medusaApi.getActiveRegion()).id }
|
|
50
|
+
)).product;
|
|
51
|
+
const variant = product.variants?.find((v) => v.sku === sku);
|
|
52
|
+
if (!variant) {
|
|
53
|
+
if (debug.enabled) {
|
|
54
|
+
debug(
|
|
55
|
+
`Variant with SKU ${sku} not found in product ${product.id}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
return this.createEmptyPriceResult(sku);
|
|
59
|
+
}
|
|
60
|
+
return this.parseSingle(variant, mode);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (debug.enabled) {
|
|
63
|
+
debug(
|
|
64
|
+
`Error fetching price for SKU ${sku}: ${error.message}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
return this.createEmptyPriceResult(sku);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
parseSingle(variant, mode) {
|
|
71
|
+
const identifier = {
|
|
72
|
+
variant: {
|
|
73
|
+
sku: variant.sku || ""
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const calculatedPrice = variant.calculated_price;
|
|
77
|
+
let unitPrice;
|
|
78
|
+
let isOnSale = false;
|
|
79
|
+
if (calculatedPrice) {
|
|
80
|
+
const priceToUse = mode === "customer" ? calculatedPrice.calculated_amount : calculatedPrice.original_amount;
|
|
81
|
+
if (mode === "customer") {
|
|
82
|
+
isOnSale = calculatedPrice.calculated_price?.price_list_type === "sale";
|
|
83
|
+
}
|
|
84
|
+
unitPrice = {
|
|
85
|
+
value: priceToUse || 0,
|
|
86
|
+
currency: calculatedPrice.currency_code?.toUpperCase() || this.context.languageContext.currencyCode
|
|
87
|
+
};
|
|
88
|
+
} else {
|
|
89
|
+
unitPrice = {
|
|
90
|
+
value: -1,
|
|
91
|
+
currency: this.context.languageContext.currencyCode
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
const result = {
|
|
95
|
+
identifier,
|
|
96
|
+
tieredPrices: [],
|
|
97
|
+
unitPrice,
|
|
98
|
+
onSale: isOnSale
|
|
99
|
+
};
|
|
100
|
+
return this.factory.parsePrice(this.context, result);
|
|
101
|
+
}
|
|
102
|
+
getResourceName() {
|
|
103
|
+
return "price";
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
__decorateClass([
|
|
107
|
+
Reactionary({
|
|
108
|
+
inputSchema: ListPriceQuerySchema,
|
|
109
|
+
outputSchema: PriceSchema
|
|
110
|
+
})
|
|
111
|
+
], MedusaPriceCapability.prototype, "getListPrice", 1);
|
|
112
|
+
__decorateClass([
|
|
113
|
+
Reactionary({
|
|
114
|
+
inputSchema: CustomerPriceQuerySchema,
|
|
115
|
+
outputSchema: PriceSchema
|
|
116
|
+
})
|
|
117
|
+
], MedusaPriceCapability.prototype, "getCustomerPrice", 1);
|
|
118
|
+
export {
|
|
119
|
+
MedusaPriceCapability
|
|
120
|
+
};
|