@reactionary/source 0.3.16 → 0.3.18
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 +2 -2
- package/core/src/initialization.ts +2 -2
- package/core/src/providers/price.provider.ts +2 -1
- package/core/src/schemas/models/cart.model.ts +7 -2
- package/core/src/schemas/models/identifiers.model.ts +12 -8
- package/core/src/schemas/models/price.model.ts +12 -0
- package/examples/node/package.json +7 -7
- package/examples/node/src/capabilities/cart.spec.ts +97 -15
- package/examples/node/src/capabilities/category.spec.ts +27 -32
- package/examples/node/src/capabilities/checkout.spec.ts +5 -5
- package/examples/node/src/capabilities/identity.spec.ts +6 -2
- package/examples/node/src/capabilities/inventory.spec.ts +1 -1
- package/examples/node/src/capabilities/price.spec.ts +7 -7
- package/examples/node/src/utils.ts +4 -1
- package/package.json +3 -3
- package/providers/algolia/src/providers/product-search.provider.ts +19 -14
- package/providers/commercetools/src/core/client.ts +112 -9
- package/providers/commercetools/src/core/token-cache.ts +4 -5
- package/providers/commercetools/src/providers/cart.provider.ts +76 -11
- package/providers/commercetools/src/providers/inventory.provider.ts +5 -7
- package/providers/commercetools/src/providers/price.provider.ts +17 -30
- package/providers/commercetools/src/schema/configuration.schema.ts +4 -0
- package/providers/commercetools/src/schema/session.schema.ts +3 -1
- package/providers/fake/src/providers/cart.provider.ts +1 -0
- package/providers/fake/src/providers/price.provider.ts +54 -95
- package/providers/medusa/src/providers/cart.provider.ts +159 -70
- package/providers/medusa/src/providers/category.provider.ts +35 -23
- package/providers/medusa/src/providers/checkout.provider.ts +78 -41
- package/providers/medusa/src/providers/order-search.provider.ts +21 -10
- package/providers/medusa/src/providers/price.provider.ts +18 -9
- package/providers/medusa/src/providers/product-recommendations.provider.ts +10 -6
- package/providers/medusa/src/providers/product-search.provider.ts +19 -10
- package/providers/medusa/src/providers/product.provider.ts +20 -12
- package/providers/medusa/src/providers/profile.provider.ts +38 -13
- package/providers/meilisearch/src/providers/order-search.provider.ts +17 -12
- package/providers/meilisearch/src/providers/product-recommendations.provider.ts +10 -11
- package/providers/meilisearch/src/providers/product-search.provider.ts +23 -18
|
@@ -93,6 +93,14 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
93
93
|
return success(this.parseSingle(candidate));
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
protected getBySlugPayload(payload: CategoryQueryBySlug) {
|
|
97
|
+
return {
|
|
98
|
+
handle: payload.slug,
|
|
99
|
+
limit: 1,
|
|
100
|
+
offset: 0,
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
96
104
|
@Reactionary({
|
|
97
105
|
inputSchema: CategoryQueryBySlugSchema,
|
|
98
106
|
outputSchema: CategorySchema.nullable(),
|
|
@@ -102,11 +110,7 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
102
110
|
): Promise<Result<Category, NotFoundError>> {
|
|
103
111
|
const sdk = await this.medusaApi.getClient();
|
|
104
112
|
|
|
105
|
-
const categoryResult = await sdk.store.category.list(
|
|
106
|
-
handle: payload.slug,
|
|
107
|
-
limit: 1,
|
|
108
|
-
offset: 0,
|
|
109
|
-
});
|
|
113
|
+
const categoryResult = await sdk.store.category.list(this.getBySlugPayload(payload));
|
|
110
114
|
if (categoryResult.count === 0) {
|
|
111
115
|
return error<NotFoundError>({
|
|
112
116
|
type: 'NotFound',
|
|
@@ -146,6 +150,17 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
146
150
|
return success(results);
|
|
147
151
|
}
|
|
148
152
|
|
|
153
|
+
|
|
154
|
+
protected findChildCategoriesPayload(payload: CategoryQueryForChildCategories, actualParent: StoreProductCategory) {
|
|
155
|
+
return {
|
|
156
|
+
fields: '+metadata,+parent_category.metadata',
|
|
157
|
+
parent_category_id: actualParent.id,
|
|
158
|
+
limit: payload.paginationOptions.pageSize,
|
|
159
|
+
offset:
|
|
160
|
+
(payload.paginationOptions.pageNumber - 1) *
|
|
161
|
+
payload.paginationOptions.pageSize,
|
|
162
|
+
}
|
|
163
|
+
}
|
|
149
164
|
@Reactionary({
|
|
150
165
|
inputSchema: CategoryQueryForChildCategoriesSchema,
|
|
151
166
|
outputSchema: CategoryPaginatedResultSchema,
|
|
@@ -155,24 +170,28 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
155
170
|
) {
|
|
156
171
|
const sdk = await this.medusaApi.getClient();
|
|
157
172
|
|
|
158
|
-
const
|
|
173
|
+
const actualParent = await this.resolveCategoryIdByExternalId(
|
|
159
174
|
payload.parentId.key
|
|
160
175
|
);
|
|
161
|
-
if (!
|
|
176
|
+
if (!actualParent) {
|
|
162
177
|
throw new Error('Parent category not found ' + payload.parentId.key);
|
|
163
178
|
}
|
|
164
179
|
|
|
165
|
-
const response = await sdk.store.category.list(
|
|
166
|
-
|
|
167
|
-
|
|
180
|
+
const response = await sdk.store.category.list(this.findChildCategoriesPayload(payload, actualParent));
|
|
181
|
+
|
|
182
|
+
const result = this.parsePaginatedResult(response);
|
|
183
|
+
return success(result);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
protected findTopCategoriesPayload(payload: CategoryQueryForTopCategories) {
|
|
187
|
+
return {
|
|
188
|
+
fields: '+metadata',
|
|
189
|
+
parent_category_id: 'null',
|
|
168
190
|
limit: payload.paginationOptions.pageSize,
|
|
169
191
|
offset:
|
|
170
192
|
(payload.paginationOptions.pageNumber - 1) *
|
|
171
193
|
payload.paginationOptions.pageSize,
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const result = this.parsePaginatedResult(response);
|
|
175
|
-
return success(result);
|
|
194
|
+
}
|
|
176
195
|
}
|
|
177
196
|
|
|
178
197
|
@Reactionary({
|
|
@@ -184,17 +203,9 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
184
203
|
) {
|
|
185
204
|
const sdk = await this.medusaApi.getClient();
|
|
186
205
|
|
|
187
|
-
const response = await sdk.store.category.list(
|
|
188
|
-
fields: '+metadata',
|
|
189
|
-
parent_category_id: 'null',
|
|
190
|
-
limit: payload.paginationOptions.pageSize,
|
|
191
|
-
offset:
|
|
192
|
-
(payload.paginationOptions.pageNumber - 1) *
|
|
193
|
-
payload.paginationOptions.pageSize,
|
|
194
|
-
});
|
|
206
|
+
const response = await sdk.store.category.list(this.findTopCategoriesPayload(payload));
|
|
195
207
|
|
|
196
208
|
const result = this.parsePaginatedResult(response);
|
|
197
|
-
|
|
198
209
|
return success(result);
|
|
199
210
|
}
|
|
200
211
|
|
|
@@ -246,3 +257,4 @@ export class MedusaCategoryProvider extends CategoryProvider {
|
|
|
246
257
|
return result;
|
|
247
258
|
}
|
|
248
259
|
}
|
|
260
|
+
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StoreCart, StoreCartAddress, StoreCartLineItem } from '@medusajs/types';
|
|
1
|
+
import type { StoreAddCartShippingMethods, StoreCart, StoreCartAddress, StoreCartLineItem, StoreInitializePaymentSession, StoreUpdateCart } from '@medusajs/types';
|
|
2
2
|
import type {
|
|
3
3
|
Address,
|
|
4
4
|
AddressIdentifier,
|
|
@@ -97,6 +97,21 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
97
97
|
this.config = config;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
protected initiateCheckoutForCartPayload(payload: CheckoutMutationInitiateCheckout): StoreUpdateCart {
|
|
101
|
+
return {
|
|
102
|
+
billing_address: payload.billingAddress
|
|
103
|
+
? this.mapAddressToStoreAddress(payload.billingAddress)
|
|
104
|
+
: undefined,
|
|
105
|
+
shipping_address: payload.billingAddress
|
|
106
|
+
? this.mapAddressToStoreAddress(payload.billingAddress)
|
|
107
|
+
: undefined,
|
|
108
|
+
email: payload.notificationEmail,
|
|
109
|
+
metadata: {
|
|
110
|
+
sms_notification: payload.notificationPhone,
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
100
115
|
@Reactionary({
|
|
101
116
|
inputSchema: CheckoutMutationInitiateCheckoutSchema,
|
|
102
117
|
outputSchema: CheckoutSchema,
|
|
@@ -114,18 +129,7 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
114
129
|
// zero out existing checkout data?
|
|
115
130
|
const response = await client.store.cart.update(
|
|
116
131
|
payload.cart.identifier.key,
|
|
117
|
-
|
|
118
|
-
billing_address: payload.billingAddress
|
|
119
|
-
? this.mapAddressToStoreAddress(payload.billingAddress)
|
|
120
|
-
: undefined,
|
|
121
|
-
shipping_address: payload.billingAddress
|
|
122
|
-
? this.mapAddressToStoreAddress(payload.billingAddress)
|
|
123
|
-
: undefined,
|
|
124
|
-
email: payload.notificationEmail,
|
|
125
|
-
metadata: {
|
|
126
|
-
sms_notification: payload.notificationPhone,
|
|
127
|
-
},
|
|
128
|
-
},
|
|
132
|
+
this.initiateCheckoutForCartPayload(payload),
|
|
129
133
|
{
|
|
130
134
|
fields: this.includedFields,
|
|
131
135
|
}
|
|
@@ -148,6 +152,13 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
148
152
|
return success(this.parseSingle(response.cart));
|
|
149
153
|
}
|
|
150
154
|
|
|
155
|
+
|
|
156
|
+
protected setShippingAddressPayload(payload: CheckoutMutationSetShippingAddress): StoreUpdateCart {
|
|
157
|
+
return {
|
|
158
|
+
shipping_address: this.mapAddressToStoreAddress(payload.shippingAddress),
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
151
162
|
@Reactionary({
|
|
152
163
|
inputSchema: CheckoutMutationSetShippingAddressSchema,
|
|
153
164
|
outputSchema: CheckoutSchema,
|
|
@@ -159,18 +170,21 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
159
170
|
|
|
160
171
|
const response = await client.store.cart.update(
|
|
161
172
|
payload.checkout.key,
|
|
162
|
-
|
|
163
|
-
shipping_address: this.mapAddressToStoreAddress(
|
|
164
|
-
payload.shippingAddress
|
|
165
|
-
),
|
|
166
|
-
},
|
|
173
|
+
this.setShippingAddressPayload(payload),
|
|
167
174
|
{
|
|
168
175
|
fields: this.includedFields,
|
|
169
|
-
}
|
|
176
|
+
},
|
|
170
177
|
);
|
|
171
178
|
return success(this.parseSingle(response.cart));
|
|
172
179
|
}
|
|
173
180
|
|
|
181
|
+
|
|
182
|
+
protected getAvailableShippingMethodsPayload(payload: CheckoutQueryForAvailableShippingMethods) {
|
|
183
|
+
return {
|
|
184
|
+
cart_id: payload.checkout.key,
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
174
188
|
@Reactionary({
|
|
175
189
|
inputSchema: CheckoutQueryForAvailableShippingMethodsSchema,
|
|
176
190
|
outputSchema: z.array(ShippingMethodSchema),
|
|
@@ -187,9 +201,9 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
187
201
|
}
|
|
188
202
|
|
|
189
203
|
const shippingMethodResponse =
|
|
190
|
-
await client.store.fulfillment.listCartOptions(
|
|
191
|
-
|
|
192
|
-
|
|
204
|
+
await client.store.fulfillment.listCartOptions(
|
|
205
|
+
this.getAvailableShippingMethodsPayload(payload)
|
|
206
|
+
);
|
|
193
207
|
|
|
194
208
|
const shippingMethods: ShippingMethod[] = [];
|
|
195
209
|
|
|
@@ -218,6 +232,12 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
218
232
|
return success(shippingMethods);
|
|
219
233
|
}
|
|
220
234
|
|
|
235
|
+
protected getAvailablePaymentMethodsPayload(payload: CheckoutQueryForAvailablePaymentMethods, regionId: string) {
|
|
236
|
+
return {
|
|
237
|
+
region_id: regionId,
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
221
241
|
@Reactionary({
|
|
222
242
|
inputSchema: CheckoutQueryForAvailablePaymentMethodsSchema,
|
|
223
243
|
outputSchema: z.array(PaymentMethodSchema),
|
|
@@ -234,10 +254,12 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
234
254
|
}
|
|
235
255
|
const checkout = await client.store.cart.retrieve(payload.checkout.key);
|
|
236
256
|
const paymentMethodResponse =
|
|
237
|
-
await client.store.payment.listPaymentProviders(
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
257
|
+
await client.store.payment.listPaymentProviders(
|
|
258
|
+
this.getAvailablePaymentMethodsPayload(
|
|
259
|
+
payload,
|
|
260
|
+
checkout.cart.region_id || (await this.medusaApi.getActiveRegion()).id
|
|
261
|
+
)
|
|
262
|
+
);
|
|
241
263
|
|
|
242
264
|
const paymentMethods: PaymentMethod[] = [];
|
|
243
265
|
|
|
@@ -267,6 +289,18 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
267
289
|
return success(paymentMethods);
|
|
268
290
|
}
|
|
269
291
|
|
|
292
|
+
|
|
293
|
+
protected addPaymentInstructionPayload(payload: CheckoutMutationAddPaymentInstruction): StoreInitializePaymentSession {
|
|
294
|
+
return {
|
|
295
|
+
provider_id: payload.paymentInstruction.paymentMethod.method,
|
|
296
|
+
data: payload.paymentInstruction.protocolData.reduce((acc, curr) => {
|
|
297
|
+
acc[curr.key] = curr.value;
|
|
298
|
+
return acc;
|
|
299
|
+
}, {} as Record<string, string>),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
270
304
|
@Reactionary({
|
|
271
305
|
inputSchema: CheckoutMutationAddPaymentInstructionSchema,
|
|
272
306
|
outputSchema: CheckoutSchema,
|
|
@@ -287,13 +321,7 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
287
321
|
);
|
|
288
322
|
|
|
289
323
|
const paymentSessionResponse =
|
|
290
|
-
await client.store.payment.initiatePaymentSession(cartResponse.cart,
|
|
291
|
-
provider_id: payload.paymentInstruction.paymentMethod.method,
|
|
292
|
-
data: payload.paymentInstruction.protocolData.reduce((acc, curr) => {
|
|
293
|
-
acc[curr.key] = curr.value;
|
|
294
|
-
return acc;
|
|
295
|
-
}, {} as Record<string, string>),
|
|
296
|
-
});
|
|
324
|
+
await client.store.payment.initiatePaymentSession(cartResponse.cart, this.addPaymentInstructionPayload(payload));
|
|
297
325
|
|
|
298
326
|
const updatedCartResponse = await client.store.cart.retrieve(
|
|
299
327
|
payload.checkout.key,
|
|
@@ -323,6 +351,17 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
323
351
|
throw new Error('Method not implemented.');
|
|
324
352
|
}
|
|
325
353
|
|
|
354
|
+
protected setShippingInstructionPayload(payload: CheckoutMutationSetShippingInstruction): StoreAddCartShippingMethods {
|
|
355
|
+
return {
|
|
356
|
+
option_id: payload.shippingInstruction.shippingMethod.key,
|
|
357
|
+
data: {
|
|
358
|
+
consent_for_unattended_delivery:
|
|
359
|
+
payload.shippingInstruction.consentForUnattendedDelivery + '',
|
|
360
|
+
instructions: payload.shippingInstruction.instructions || '',
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
326
365
|
@Reactionary({
|
|
327
366
|
inputSchema: CheckoutMutationSetShippingInstructionSchema,
|
|
328
367
|
outputSchema: CheckoutSchema,
|
|
@@ -335,14 +374,7 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
335
374
|
try {
|
|
336
375
|
// Set shipping method
|
|
337
376
|
if (payload.shippingInstruction.shippingMethod) {
|
|
338
|
-
await client.store.cart.addShippingMethod(medusaId.key,
|
|
339
|
-
option_id: payload.shippingInstruction.shippingMethod.key,
|
|
340
|
-
data: {
|
|
341
|
-
consent_for_unattended_delivery:
|
|
342
|
-
payload.shippingInstruction.consentForUnattendedDelivery + '',
|
|
343
|
-
instructions: payload.shippingInstruction.instructions || '',
|
|
344
|
-
},
|
|
345
|
-
});
|
|
377
|
+
await client.store.cart.addShippingMethod(medusaId.key, this.setShippingInstructionPayload(payload));
|
|
346
378
|
}
|
|
347
379
|
|
|
348
380
|
// for now, we store a backup of the shipping instruction in metadata
|
|
@@ -369,6 +401,11 @@ export class MedusaCheckoutProvider extends CheckoutProvider {
|
|
|
369
401
|
handleProviderError('set shipping method', error);
|
|
370
402
|
}
|
|
371
403
|
}
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
|
|
372
409
|
@Reactionary({
|
|
373
410
|
inputSchema: CheckoutMutationFinalizeCheckoutSchema,
|
|
374
411
|
outputSchema: CheckoutSchema,
|
|
@@ -44,14 +44,9 @@ export class MedusaOrderSearchProvider extends OrderSearchProvider {
|
|
|
44
44
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
outputSchema: OrderSearchResultSchema,
|
|
50
|
-
})
|
|
51
|
-
public async queryByTerm(payload: OrderSearchQueryByTerm): Promise<Result<OrderSearchResult>> {
|
|
52
|
-
debug('queryByTerm', payload);
|
|
47
|
+
protected queryByTermPayload(payload: OrderSearchQueryByTerm): any {
|
|
48
|
+
const filters: any = {};
|
|
53
49
|
|
|
54
|
-
const medusa = await this.medusaApi.getClient();
|
|
55
50
|
|
|
56
51
|
if (payload.search.term) {
|
|
57
52
|
debug('Searching orders by term is not supported in Medusa');
|
|
@@ -67,10 +62,12 @@ export class MedusaOrderSearchProvider extends OrderSearchProvider {
|
|
|
67
62
|
if (payload.search.endDate) {
|
|
68
63
|
debug('Searching orders by end date is not supported in Medusa');
|
|
69
64
|
}
|
|
65
|
+
|
|
70
66
|
/*
|
|
71
67
|
if (payload.search.user && payload.search.user.userId) {
|
|
72
68
|
debug('Searching orders by customer ID is not supported in Medusa');
|
|
73
69
|
} */
|
|
70
|
+
|
|
74
71
|
const statusFilter: MedusaOrderStatus[] = (payload.search.orderStatus ?? []).map((status) => {
|
|
75
72
|
let retStatus: MedusaOrderStatus = 'draft';
|
|
76
73
|
if (status === 'AwaitingPayment') {
|
|
@@ -88,15 +85,29 @@ export class MedusaOrderSearchProvider extends OrderSearchProvider {
|
|
|
88
85
|
return retStatus;
|
|
89
86
|
});
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
const response = await medusa.store.order.list({
|
|
88
|
+
return {
|
|
93
89
|
status: statusFilter,
|
|
94
90
|
limit: payload.search.paginationOptions.pageSize,
|
|
95
91
|
offset:
|
|
96
92
|
(payload.search.paginationOptions.pageNumber - 1) *
|
|
97
93
|
payload.search.paginationOptions.pageSize,
|
|
98
94
|
|
|
99
|
-
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
@Reactionary({
|
|
99
|
+
inputSchema: OrderSearchQueryByTermSchema,
|
|
100
|
+
outputSchema: OrderSearchResultSchema,
|
|
101
|
+
})
|
|
102
|
+
public async queryByTerm(payload: OrderSearchQueryByTerm): Promise<Result<OrderSearchResult>> {
|
|
103
|
+
debug('queryByTerm', payload);
|
|
104
|
+
|
|
105
|
+
const medusa = await this.medusaApi.getClient();
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
const response = await medusa.store.order.list(this.queryByTermPayload(payload));
|
|
100
111
|
|
|
101
112
|
const result = this.parsePaginatedResult(response, payload) as OrderSearchResult;
|
|
102
113
|
if (debug.enabled) {
|
|
@@ -41,7 +41,7 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
41
41
|
outputSchema: PriceSchema,
|
|
42
42
|
})
|
|
43
43
|
public override async getListPrice(payload: ListPriceQuery): Promise<Result<Price>> {
|
|
44
|
-
const result = await this.getBySKU(payload);
|
|
44
|
+
const result = await this.getBySKU(payload, 'list');
|
|
45
45
|
|
|
46
46
|
return success(result);
|
|
47
47
|
}
|
|
@@ -51,13 +51,13 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
51
51
|
outputSchema: PriceSchema,
|
|
52
52
|
})
|
|
53
53
|
public override async getCustomerPrice(payload: CustomerPriceQuery): Promise<Result<Price>> {
|
|
54
|
-
const result = await this.getBySKU(payload);
|
|
54
|
+
const result = await this.getBySKU(payload, 'customer');
|
|
55
55
|
|
|
56
56
|
return success(result);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
protected async getBySKU(payload: ListPriceQuery | CustomerPriceQuery ): Promise<Price> {
|
|
60
|
+
protected async getBySKU(payload: ListPriceQuery | CustomerPriceQuery, mode: 'list' | 'customer' ): Promise<Price> {
|
|
61
61
|
const sku = payload.variant.sku;
|
|
62
62
|
|
|
63
63
|
if (debug.enabled) {
|
|
@@ -71,7 +71,7 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
71
71
|
const product = (
|
|
72
72
|
await client.store.product.retrieve(
|
|
73
73
|
productForSKU.id || '',
|
|
74
|
-
{ region_id: (await this.medusaApi.getActiveRegion()).id }
|
|
74
|
+
{ region_id: (await this.medusaApi.getActiveRegion()).id },
|
|
75
75
|
)
|
|
76
76
|
).product;
|
|
77
77
|
|
|
@@ -87,7 +87,7 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// For simplicity, return the first matched product
|
|
90
|
-
return this.parseSingle(variant);
|
|
90
|
+
return this.parseSingle(variant, mode);
|
|
91
91
|
} catch (error) {
|
|
92
92
|
if (debug.enabled) {
|
|
93
93
|
debug(
|
|
@@ -98,7 +98,7 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
protected parseSingle(variant: StoreProductVariant): Price {
|
|
101
|
+
protected parseSingle(variant: StoreProductVariant, mode: 'list' | 'customer'): Price {
|
|
102
102
|
const identifier = {
|
|
103
103
|
variant: {
|
|
104
104
|
sku: variant.sku || '',
|
|
@@ -108,11 +108,19 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
108
108
|
// In Medusa v2, calculated_price contains the final price for the variant
|
|
109
109
|
// based on the region, currency, and any applicable price lists
|
|
110
110
|
const calculatedPrice = variant.calculated_price;
|
|
111
|
-
|
|
112
111
|
let unitPrice;
|
|
112
|
+
let isOnSale = false;
|
|
113
113
|
if (calculatedPrice) {
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
const priceToUse = mode === 'customer' ? calculatedPrice.calculated_amount : calculatedPrice.original_amount;
|
|
117
|
+
|
|
118
|
+
if (mode === 'customer') {
|
|
119
|
+
isOnSale = calculatedPrice.calculated_price?.price_list_type === 'sale'
|
|
120
|
+
}
|
|
121
|
+
|
|
114
122
|
unitPrice = {
|
|
115
|
-
value:
|
|
123
|
+
value: priceToUse || 0,
|
|
116
124
|
currency: (calculatedPrice.currency_code?.toUpperCase() ||
|
|
117
125
|
this.context.languageContext.currencyCode) as Currency,
|
|
118
126
|
} satisfies MonetaryAmount;
|
|
@@ -127,7 +135,8 @@ export class MedusaPriceProvider extends PriceProvider {
|
|
|
127
135
|
const result = {
|
|
128
136
|
identifier,
|
|
129
137
|
tieredPrices: [],
|
|
130
|
-
unitPrice
|
|
138
|
+
unitPrice,
|
|
139
|
+
onSale: isOnSale,
|
|
131
140
|
} satisfies Price;
|
|
132
141
|
|
|
133
142
|
return result;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StoreProduct, StoreProductVariant } from '@medusajs/types';
|
|
1
|
+
import type { StoreCollection, StoreProduct, StoreProductVariant } from '@medusajs/types';
|
|
2
2
|
import {
|
|
3
3
|
error,
|
|
4
4
|
ImageSchema,
|
|
@@ -42,6 +42,14 @@ export class MedusaProductRecommendationsProvider extends ProductRecommendations
|
|
|
42
42
|
this.medusaApi = medusaApi;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
|
|
46
|
+
protected getCollectionPayload(query: ProductRecommendationsByCollectionQuery, collection: StoreCollection) {
|
|
47
|
+
return {
|
|
48
|
+
collection_id: [collection.id],
|
|
49
|
+
limit: query.numberOfRecommendations,
|
|
50
|
+
fields: '+variants.id,+variants.sku,+external_id',
|
|
51
|
+
}
|
|
52
|
+
}
|
|
45
53
|
/**
|
|
46
54
|
* Get product recommendations from a Medusa collection
|
|
47
55
|
*
|
|
@@ -82,11 +90,7 @@ export class MedusaProductRecommendationsProvider extends ProductRecommendations
|
|
|
82
90
|
}
|
|
83
91
|
|
|
84
92
|
// Fetch products from the collection
|
|
85
|
-
const productsResponse = await client.store.product.list(
|
|
86
|
-
collection_id: [collection.id],
|
|
87
|
-
limit: query.numberOfRecommendations,
|
|
88
|
-
fields: '+variants.id,+variants.sku,+external_id',
|
|
89
|
-
});
|
|
93
|
+
const productsResponse = await client.store.product.list(this.getCollectionPayload(query, collection));
|
|
90
94
|
|
|
91
95
|
if (debug.enabled) {
|
|
92
96
|
debug(`Found ${productsResponse.products.length} products in collection`);
|
|
@@ -88,6 +88,22 @@ export class MedusaSearchProvider extends ProductSearchProvider {
|
|
|
88
88
|
return candidate || null;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
|
|
92
|
+
protected queryByTermPayload(payload: ProductSearchQueryByTerm, categoryIdToFind: string | null): any {
|
|
93
|
+
|
|
94
|
+
const finalSearch = (payload.search.term || '').trim().replace('*', '');
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
q: finalSearch,
|
|
98
|
+
...(categoryIdToFind ? { category_id: categoryIdToFind } : {}),
|
|
99
|
+
limit: payload.search.paginationOptions.pageSize,
|
|
100
|
+
fields: '+metadata.*,+external_id',
|
|
101
|
+
offset:
|
|
102
|
+
(payload.search.paginationOptions.pageNumber - 1) *
|
|
103
|
+
payload.search.paginationOptions.pageSize,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
91
107
|
@Reactionary({
|
|
92
108
|
inputSchema: ProductSearchQueryByTermSchema,
|
|
93
109
|
outputSchema: ProductSearchResultSchema,
|
|
@@ -121,16 +137,9 @@ export class MedusaSearchProvider extends ProductSearchProvider {
|
|
|
121
137
|
);
|
|
122
138
|
}
|
|
123
139
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
...(categoryIdToFind ? { category_id: categoryIdToFind } : {}),
|
|
128
|
-
limit: payload.search.paginationOptions.pageSize,
|
|
129
|
-
fields: '+metadata.*,+external_id',
|
|
130
|
-
offset:
|
|
131
|
-
(payload.search.paginationOptions.pageNumber - 1) *
|
|
132
|
-
payload.search.paginationOptions.pageSize,
|
|
133
|
-
});
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
const response = await client.store.product.list(this.queryByTermPayload(payload, categoryIdToFind));
|
|
134
143
|
|
|
135
144
|
const result = this.parsePaginatedResult(response) as ProductSearchResult;
|
|
136
145
|
if (debug.enabled) {
|
|
@@ -28,6 +28,15 @@ export class MedusaProductProvider extends ProductProvider {
|
|
|
28
28
|
this.config = config;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
protected getByIdPayload(payload: ProductQueryById) {
|
|
32
|
+
return {
|
|
33
|
+
external_id: payload.identifier.key,
|
|
34
|
+
limit: 1,
|
|
35
|
+
offset: 0,
|
|
36
|
+
fields: this.alwaysIncludedFields.join(','),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
@Reactionary({
|
|
32
41
|
inputSchema: ProductQueryByIdSchema,
|
|
33
42
|
outputSchema: ProductSchema,
|
|
@@ -42,12 +51,7 @@ export class MedusaProductProvider extends ProductProvider {
|
|
|
42
51
|
debug(`Fetching product by ID: ${payload.identifier.key}`);
|
|
43
52
|
}
|
|
44
53
|
const response = await client.store.product.list(
|
|
45
|
-
|
|
46
|
-
external_id: payload.identifier.key,
|
|
47
|
-
limit: 1,
|
|
48
|
-
offset: 0,
|
|
49
|
-
fields: this.alwaysIncludedFields.join(','),
|
|
50
|
-
},
|
|
54
|
+
this.getByIdPayload(payload)
|
|
51
55
|
);
|
|
52
56
|
|
|
53
57
|
if (response.count === 0) {
|
|
@@ -59,6 +63,15 @@ export class MedusaProductProvider extends ProductProvider {
|
|
|
59
63
|
return success(this.parseSingle(response.products[0]));
|
|
60
64
|
}
|
|
61
65
|
|
|
66
|
+
protected getBySlugPayload(payload: ProductQueryBySlug) {
|
|
67
|
+
return {
|
|
68
|
+
handle: payload.slug,
|
|
69
|
+
limit: 1,
|
|
70
|
+
offset: 0,
|
|
71
|
+
fields: this.alwaysIncludedFields.join(','),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
62
75
|
|
|
63
76
|
@Reactionary({
|
|
64
77
|
inputSchema: ProductQueryBySlugSchema,
|
|
@@ -74,12 +87,7 @@ export class MedusaProductProvider extends ProductProvider {
|
|
|
74
87
|
debug(`Fetching product by slug: ${payload.slug}`);
|
|
75
88
|
}
|
|
76
89
|
|
|
77
|
-
const response = await client.store.product.list(
|
|
78
|
-
handle: payload.slug,
|
|
79
|
-
limit: 1,
|
|
80
|
-
offset: 0,
|
|
81
|
-
fields: this.alwaysIncludedFields.join(','),
|
|
82
|
-
});
|
|
90
|
+
const response = await client.store.product.list(this.getBySlugPayload(payload));
|
|
83
91
|
|
|
84
92
|
if (debug.enabled) {
|
|
85
93
|
debug(`Found ${response.count} products for slug: ${payload.slug}`);
|