@unchainedshop/core-orders 2.9.4 → 2.10.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/lib/module/configureOrderDeliveriesModule.js +16 -23
- package/lib/module/configureOrderDeliveriesModule.js.map +1 -1
- package/lib/module/configureOrderPaymentsModule.js +15 -21
- package/lib/module/configureOrderPaymentsModule.js.map +1 -1
- package/lib/module/configureOrderPositionsModule.js +8 -8
- package/lib/module/configureOrderPositionsModule.js.map +1 -1
- package/lib/module/configureOrdersModule-mutations.js +10 -10
- package/lib/module/configureOrdersModule-mutations.js.map +1 -1
- package/lib/module/configureOrdersModule-processing.d.ts +3 -1
- package/lib/module/configureOrdersModule-processing.js +50 -49
- package/lib/module/configureOrdersModule-processing.js.map +1 -1
- package/lib/module/configureOrdersModule-transformations.js +3 -3
- package/lib/module/configureOrdersModule-transformations.js.map +1 -1
- package/lib/module/configureOrdersModule.js +13 -0
- package/lib/module/configureOrdersModule.js.map +1 -1
- package/lib/orders-settings.d.ts +2 -1
- package/lib/orders-settings.js +3 -1
- package/lib/orders-settings.js.map +1 -1
- package/lib/service/migrateOrderCartService.js +10 -4
- package/lib/service/migrateOrderCartService.js.map +1 -1
- package/lib/service/nextUserCartService.d.ts +2 -0
- package/lib/service/{createUserCartService.js → nextUserCartService.js} +13 -2
- package/lib/service/nextUserCartService.js.map +1 -0
- package/lib/service/orderServices.js +2 -2
- package/lib/service/orderServices.js.map +1 -1
- package/package.json +7 -6
- package/src/module/configureOrderDeliveriesModule.ts +31 -30
- package/src/module/configureOrderPaymentsModule.ts +30 -28
- package/src/module/configureOrderPositionsModule.ts +20 -15
- package/src/module/configureOrdersModule-mutations.ts +18 -12
- package/src/module/configureOrdersModule-processing.ts +70 -73
- package/src/module/configureOrdersModule-transformations.ts +3 -3
- package/src/module/configureOrdersModule.ts +15 -0
- package/src/orders-settings.ts +3 -0
- package/src/service/migrateOrderCartService.ts +10 -4
- package/src/service/{createUserCartService.ts → nextUserCartService.ts} +14 -3
- package/src/service/orderServices.ts +2 -2
- package/lib/service/createUserCartService.d.ts +0 -2
- package/lib/service/createUserCartService.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mongodb, generateDbFilterById } from '@unchainedshop/mongodb';
|
|
2
2
|
import { Order, OrderStatus, OrderProcessing, OrdersModule } from '@unchainedshop/types/orders.js';
|
|
3
|
+
import type { Locker } from '@kontsedal/locco';
|
|
3
4
|
import { OrderDelivery } from '@unchainedshop/types/orders.deliveries.js';
|
|
4
5
|
import { OrderPayment } from '@unchainedshop/types/orders.payments.js';
|
|
5
6
|
import { OrderPosition } from '@unchainedshop/types/orders.positions.js';
|
|
@@ -21,11 +22,13 @@ export const configureOrderModuleProcessing = ({
|
|
|
21
22
|
OrderPositions,
|
|
22
23
|
OrderDeliveries,
|
|
23
24
|
OrderPayments,
|
|
25
|
+
locker,
|
|
24
26
|
}: {
|
|
25
27
|
Orders: mongodb.Collection<Order>;
|
|
26
28
|
OrderPositions: mongodb.Collection<OrderPosition>;
|
|
27
29
|
OrderDeliveries: mongodb.Collection<OrderDelivery>;
|
|
28
30
|
OrderPayments: mongodb.Collection<OrderPayment>;
|
|
31
|
+
locker: Locker;
|
|
29
32
|
}): OrderProcessing => {
|
|
30
33
|
registerEvents(ORDER_PROCESSING_EVENTS);
|
|
31
34
|
|
|
@@ -250,12 +253,10 @@ export const configureOrderModuleProcessing = ({
|
|
|
250
253
|
};
|
|
251
254
|
|
|
252
255
|
return {
|
|
253
|
-
checkout: async (orderId, {
|
|
254
|
-
const { modules } = unchainedAPI;
|
|
255
|
-
|
|
256
|
-
await modules.orders.updateContext(orderId, orderContext, unchainedAPI);
|
|
257
|
-
let order = await modules.orders.findOrder({ orderId });
|
|
256
|
+
checkout: async (orderId, { paymentContext, deliveryContext }, unchainedAPI) => {
|
|
257
|
+
const { modules, services } = unchainedAPI;
|
|
258
258
|
|
|
259
|
+
const order = await Orders.findOne(generateDbFilterById(orderId), {});
|
|
259
260
|
if (order.status !== null) return order;
|
|
260
261
|
|
|
261
262
|
const errors = [
|
|
@@ -267,87 +268,83 @@ export const configureOrderModuleProcessing = ({
|
|
|
267
268
|
throw new Error(errors[0]);
|
|
268
269
|
}
|
|
269
270
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
// After checkout, store last checkout information on user
|
|
281
|
-
await modules.users.updateLastBillingAddress(order.userId, order.billingAddress);
|
|
282
|
-
await modules.users.updateLastContact(order.userId, order.contact);
|
|
283
|
-
|
|
284
|
-
// Then ensure new cart is created before we return from checkout
|
|
285
|
-
const user = await modules.users.findUserById(order.userId);
|
|
286
|
-
const locale = modules.users.userLocale(user);
|
|
287
|
-
await modules.orders.ensureCartForUser(
|
|
288
|
-
{
|
|
289
|
-
user,
|
|
290
|
-
countryCode: locale.country,
|
|
291
|
-
},
|
|
292
|
-
unchainedAPI,
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
return order;
|
|
296
|
-
},
|
|
297
|
-
|
|
298
|
-
confirm: async (orderId, { orderContext, paymentContext, deliveryContext }, unchainedAPI) => {
|
|
299
|
-
const { modules } = unchainedAPI;
|
|
271
|
+
const lock = await locker.lock(`order:checkout:${order._id}`, 1500).acquire();
|
|
272
|
+
try {
|
|
273
|
+
const processedOrder = await modules.orders.processOrder(
|
|
274
|
+
order,
|
|
275
|
+
{
|
|
276
|
+
paymentContext,
|
|
277
|
+
deliveryContext,
|
|
278
|
+
},
|
|
279
|
+
unchainedAPI,
|
|
280
|
+
);
|
|
300
281
|
|
|
301
|
-
|
|
302
|
-
const order = await modules.orders.findOrder({ orderId });
|
|
282
|
+
await lock.extend(500);
|
|
303
283
|
|
|
304
|
-
|
|
284
|
+
// After checkout, store last checkout information on user
|
|
285
|
+
await modules.users.updateLastBillingAddress(
|
|
286
|
+
processedOrder.userId,
|
|
287
|
+
processedOrder.billingAddress,
|
|
288
|
+
);
|
|
289
|
+
await modules.users.updateLastContact(processedOrder.userId, processedOrder.contact);
|
|
290
|
+
|
|
291
|
+
// Then eventually build next cart
|
|
292
|
+
const user = await modules.users.findUserById(processedOrder.userId);
|
|
293
|
+
const locale = modules.users.userLocale(user);
|
|
294
|
+
await services.orders.nextUserCart(
|
|
295
|
+
{
|
|
296
|
+
user,
|
|
297
|
+
countryCode: locale.country,
|
|
298
|
+
},
|
|
299
|
+
unchainedAPI,
|
|
300
|
+
);
|
|
305
301
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
deliveryContext,
|
|
311
|
-
nextStatus: OrderStatus.CONFIRMED,
|
|
312
|
-
},
|
|
313
|
-
unchainedAPI,
|
|
314
|
-
);
|
|
302
|
+
return processedOrder;
|
|
303
|
+
} finally {
|
|
304
|
+
await lock.release();
|
|
305
|
+
}
|
|
315
306
|
},
|
|
316
307
|
|
|
317
|
-
|
|
308
|
+
confirm: async (order, { paymentContext, deliveryContext }, unchainedAPI) => {
|
|
318
309
|
const { modules } = unchainedAPI;
|
|
319
310
|
|
|
320
|
-
await modules.orders.updateContext(orderId, orderContext, unchainedAPI);
|
|
321
|
-
const order = await modules.orders.findOrder({ orderId });
|
|
322
|
-
|
|
323
311
|
if (order.status !== OrderStatus.PENDING) return order;
|
|
324
312
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
313
|
+
const lock = await locker.lock(`order:confirm-reject:${order._id}`, 1500).acquire();
|
|
314
|
+
try {
|
|
315
|
+
return await modules.orders.processOrder(
|
|
316
|
+
order,
|
|
317
|
+
{
|
|
318
|
+
paymentContext,
|
|
319
|
+
deliveryContext,
|
|
320
|
+
nextStatus: OrderStatus.CONFIRMED,
|
|
321
|
+
},
|
|
322
|
+
unchainedAPI,
|
|
323
|
+
);
|
|
324
|
+
} finally {
|
|
325
|
+
await lock.release();
|
|
326
|
+
}
|
|
334
327
|
},
|
|
335
328
|
|
|
336
|
-
|
|
337
|
-
const { modules
|
|
338
|
-
|
|
339
|
-
if (!ordersSettings.ensureUserHasCart) return null;
|
|
329
|
+
reject: async (order, { paymentContext, deliveryContext }, unchainedAPI) => {
|
|
330
|
+
const { modules } = unchainedAPI;
|
|
340
331
|
|
|
341
|
-
|
|
342
|
-
if (cart) return cart;
|
|
332
|
+
if (order.status !== OrderStatus.PENDING) return order;
|
|
343
333
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
334
|
+
const lock = await locker.lock(`order:confirm-reject:${order._id}`, 1500).acquire();
|
|
335
|
+
try {
|
|
336
|
+
return await modules.orders.processOrder(
|
|
337
|
+
order,
|
|
338
|
+
{
|
|
339
|
+
paymentContext,
|
|
340
|
+
deliveryContext,
|
|
341
|
+
nextStatus: OrderStatus.REJECTED,
|
|
342
|
+
},
|
|
343
|
+
unchainedAPI,
|
|
344
|
+
);
|
|
345
|
+
} finally {
|
|
346
|
+
await lock.release();
|
|
347
|
+
}
|
|
351
348
|
},
|
|
352
349
|
|
|
353
350
|
processOrder: async (initialOrder, params, unchainedAPI) => {
|
|
@@ -120,11 +120,11 @@ export const configureOrderModuleTransformations = ({
|
|
|
120
120
|
isCart: (order) => {
|
|
121
121
|
return order.status === null;
|
|
122
122
|
},
|
|
123
|
-
cart: async ({ orderNumber, countryContext }
|
|
123
|
+
cart: async ({ orderNumber, countryContext, userId }) => {
|
|
124
124
|
const selector: mongodb.Filter<Order> = {
|
|
125
|
-
countryCode: countryContext
|
|
125
|
+
countryCode: countryContext,
|
|
126
126
|
status: { $eq: null },
|
|
127
|
-
userId
|
|
127
|
+
userId,
|
|
128
128
|
};
|
|
129
129
|
|
|
130
130
|
if (orderNumber) {
|
|
@@ -4,6 +4,7 @@ import { OrderDelivery } from '@unchainedshop/types/orders.deliveries.js';
|
|
|
4
4
|
import { OrderPayment } from '@unchainedshop/types/orders.payments.js';
|
|
5
5
|
import { OrderPosition } from '@unchainedshop/types/orders.positions.js';
|
|
6
6
|
import { generateDbFilterById } from '@unchainedshop/mongodb';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
7
8
|
import { OrderDeliveriesCollection } from '../db/OrderDeliveriesCollection.js';
|
|
8
9
|
import { OrderDiscountsCollection } from '../db/OrderDiscountsCollection.js';
|
|
9
10
|
import { OrderDiscountTrigger } from '../db/OrderDiscountTrigger.js';
|
|
@@ -22,6 +23,9 @@ import { configureOrderModuleProcessing } from './configureOrdersModule-processi
|
|
|
22
23
|
import { configureOrdersModuleQueries } from './configureOrdersModule-queries.js';
|
|
23
24
|
import { configureOrderModuleTransformations } from './configureOrdersModule-transformations.js';
|
|
24
25
|
|
|
26
|
+
const require = createRequire(import.meta.url);
|
|
27
|
+
const { Locker, MongoAdapter } = require('@kontsedal/locco');
|
|
28
|
+
|
|
25
29
|
export const configureOrdersModule = async ({
|
|
26
30
|
db,
|
|
27
31
|
options: orderOptions = {},
|
|
@@ -34,6 +38,16 @@ export const configureOrdersModule = async ({
|
|
|
34
38
|
const OrderPayments = await OrderPaymentsCollection(db);
|
|
35
39
|
const OrderPositions = await OrderPositionsCollection(db);
|
|
36
40
|
|
|
41
|
+
const mongoAdapter = new MongoAdapter({
|
|
42
|
+
client: {
|
|
43
|
+
db: () => db,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const locker = new Locker({
|
|
47
|
+
adapter: mongoAdapter,
|
|
48
|
+
retrySettings: { retryDelay: 200, retryTimes: 10 },
|
|
49
|
+
});
|
|
50
|
+
|
|
37
51
|
const findOrderPositions = async (order: Order) =>
|
|
38
52
|
OrderPositions.find(
|
|
39
53
|
{
|
|
@@ -251,6 +265,7 @@ export const configureOrdersModule = async ({
|
|
|
251
265
|
OrderDeliveries,
|
|
252
266
|
OrderPayments,
|
|
253
267
|
OrderPositions,
|
|
268
|
+
locker,
|
|
254
269
|
});
|
|
255
270
|
const orderMutations = configureOrderModuleMutations({
|
|
256
271
|
Orders,
|
package/src/orders-settings.ts
CHANGED
|
@@ -11,14 +11,17 @@ export const ordersSettings = {
|
|
|
11
11
|
ensureUserHasCart: null,
|
|
12
12
|
orderNumberHashFn: null,
|
|
13
13
|
validateOrderPosition: null,
|
|
14
|
+
lockOrderDuringCheckout: false,
|
|
14
15
|
|
|
15
16
|
configureSettings({
|
|
16
17
|
ensureUserHasCart = false,
|
|
17
18
|
orderNumberHashFn = generateRandomHash,
|
|
18
19
|
validateOrderPosition = defaultValidateOrderPosition,
|
|
20
|
+
lockOrderDuringCheckout = false,
|
|
19
21
|
}: OrdersSettingsOptions = {}) {
|
|
20
22
|
this.ensureUserHasCart = ensureUserHasCart;
|
|
21
23
|
this.orderNumberHashFn = orderNumberHashFn;
|
|
22
24
|
this.validateOrderPosition = validateOrderPosition;
|
|
25
|
+
this.lockOrderDuringCheckout = lockOrderDuringCheckout;
|
|
23
26
|
},
|
|
24
27
|
};
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { MigrateOrderCartsService } from '@unchainedshop/types/orders.js';
|
|
2
2
|
|
|
3
3
|
export const migrateOrderCartsService: MigrateOrderCartsService = async (
|
|
4
|
-
{
|
|
4
|
+
{ fromUserId, toUserId, shouldMerge, countryContext },
|
|
5
5
|
unchainedAPI,
|
|
6
6
|
) => {
|
|
7
|
-
const fromCart = await unchainedAPI.modules.orders.cart({
|
|
8
|
-
|
|
7
|
+
const fromCart = await unchainedAPI.modules.orders.cart({
|
|
8
|
+
countryContext,
|
|
9
|
+
userId: fromUserId,
|
|
10
|
+
});
|
|
11
|
+
const toCart = await unchainedAPI.modules.orders.cart({
|
|
12
|
+
countryContext,
|
|
13
|
+
userId: toUserId,
|
|
14
|
+
});
|
|
9
15
|
|
|
10
16
|
if (!fromCart) {
|
|
11
17
|
// No cart, don't copy
|
|
@@ -14,7 +20,7 @@ export const migrateOrderCartsService: MigrateOrderCartsService = async (
|
|
|
14
20
|
|
|
15
21
|
if (!toCart || !shouldMerge) {
|
|
16
22
|
// No destination cart, move whole cart
|
|
17
|
-
unchainedAPI.modules.orders.setCartOwner({ orderId: fromCart._id, userId:
|
|
23
|
+
unchainedAPI.modules.orders.setCartOwner({ orderId: fromCart._id, userId: toUserId });
|
|
18
24
|
return unchainedAPI.modules.orders.updateCalculation(fromCart._id, unchainedAPI);
|
|
19
25
|
}
|
|
20
26
|
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NextUserCartService } from '@unchainedshop/types/orders.js';
|
|
2
|
+
import { ordersSettings } from '../orders-settings.js';
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
-
{ user, orderNumber, countryCode },
|
|
4
|
+
export const nextUserCartService: NextUserCartService = async (
|
|
5
|
+
{ user, orderNumber, countryCode, forceCartCreation },
|
|
5
6
|
unchainedAPI,
|
|
6
7
|
) => {
|
|
7
8
|
const { modules, services } = unchainedAPI;
|
|
8
9
|
|
|
10
|
+
const cart = await modules.orders.cart({
|
|
11
|
+
countryContext: countryCode || user.lastLogin?.countryCode,
|
|
12
|
+
orderNumber,
|
|
13
|
+
userId: user._id,
|
|
14
|
+
});
|
|
15
|
+
if (cart) return cart;
|
|
16
|
+
|
|
17
|
+
const shouldCreateNewCart = forceCartCreation || !ordersSettings.ensureUserHasCart;
|
|
18
|
+
if (!shouldCreateNewCart) return null;
|
|
19
|
+
|
|
9
20
|
const currency = await services.countries.resolveDefaultCurrencyCode(
|
|
10
21
|
{
|
|
11
22
|
isoCode: countryCode,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { OrderServices } from '@unchainedshop/types/orders.js';
|
|
2
2
|
import { migrateOrderCartsService } from './migrateOrderCartService.js';
|
|
3
|
-
import {
|
|
3
|
+
import { nextUserCartService } from './nextUserCartService.js';
|
|
4
4
|
|
|
5
5
|
export const orderServices: OrderServices = {
|
|
6
6
|
migrateOrderCarts: migrateOrderCartsService,
|
|
7
|
-
|
|
7
|
+
nextUserCart: nextUserCartService,
|
|
8
8
|
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"createUserCartService.js","sourceRoot":"","sources":["../../src/service/createUserCartService.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,qBAAqB,GAA0B,KAAK,EAC/D,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,EAClC,YAAY,EACZ,EAAE;IACF,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC;IAE3C,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,SAAS,CAAC,0BAA0B,CAClE;QACE,OAAO,EAAE,WAAW;KACrB,EACD,YAAY,CACb,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QACxC,MAAM,EAAE,IAAI,CAAC,GAAG;QAChB,WAAW;QACX,QAAQ;QACR,WAAW;QACX,cAAc,EAAE,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,OAAO,EAAE,OAAO;QAChE,OAAO,EACL,IAAI,CAAC,WAAW;YAChB,CAAC,CAAC,IAAI,CAAC,KAAK;gBACV,CAAC,CAAC;oBACE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW;oBACpC,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,OAAO;iBACxD;gBACH,CAAC,CAAC,EAAE,CAAC;KACV,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;AAC3D,CAAC,CAAC"}
|