@unchainedshop/core-orders 1.1.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/.npm/package/README +7 -0
- package/.npm/package/npm-shrinkwrap.json +190 -0
- package/.versions +54 -0
- package/README.md +5 -0
- package/lib/db/OrderDeliveriesCollection.d.ts +3 -0
- package/lib/db/OrderDeliveriesCollection.js +8 -0
- package/lib/db/OrderDeliveriesCollection.js.map +1 -0
- package/lib/db/OrderDeliveriesSchema.d.ts +1 -0
- package/lib/db/OrderDeliveriesSchema.js +20 -0
- package/lib/db/OrderDeliveriesSchema.js.map +1 -0
- package/lib/db/OrderDiscountTrigger.d.ts +4 -0
- package/lib/db/OrderDiscountTrigger.js +6 -0
- package/lib/db/OrderDiscountTrigger.js.map +1 -0
- package/lib/db/OrderDiscountsCollection.d.ts +3 -0
- package/lib/db/OrderDiscountsCollection.js +11 -0
- package/lib/db/OrderDiscountsCollection.js.map +1 -0
- package/lib/db/OrderDiscountsSchema.d.ts +1 -0
- package/lib/db/OrderDiscountsSchema.js +12 -0
- package/lib/db/OrderDiscountsSchema.js.map +1 -0
- package/lib/db/OrderPaymentsCollection.d.ts +3 -0
- package/lib/db/OrderPaymentsCollection.js +8 -0
- package/lib/db/OrderPaymentsCollection.js.map +1 -0
- package/lib/db/OrderPaymentsSchema.d.ts +1 -0
- package/lib/db/OrderPaymentsSchema.js +20 -0
- package/lib/db/OrderPaymentsSchema.js.map +1 -0
- package/lib/db/OrderPositionsCollection.d.ts +3 -0
- package/lib/db/OrderPositionsCollection.js +11 -0
- package/lib/db/OrderPositionsCollection.js.map +1 -0
- package/lib/db/OrderPositionsSchema.d.ts +1 -0
- package/lib/db/OrderPositionsSchema.js +37 -0
- package/lib/db/OrderPositionsSchema.js.map +1 -0
- package/lib/db/OrdersCollection.d.ts +3 -0
- package/lib/db/OrdersCollection.js +33 -0
- package/lib/db/OrdersCollection.js.map +1 -0
- package/lib/db/OrdersSchema.d.ts +1 -0
- package/lib/db/OrdersSchema.js +30 -0
- package/lib/db/OrdersSchema.js.map +1 -0
- package/lib/director/OrderDiscountAdapter.d.ts +2 -0
- package/lib/director/OrderDiscountAdapter.js +3 -0
- package/lib/director/OrderDiscountAdapter.js.map +1 -0
- package/lib/director/OrderDiscountDirector.d.ts +2 -0
- package/lib/director/OrderDiscountDirector.js +3 -0
- package/lib/director/OrderDiscountDirector.js.map +1 -0
- package/lib/director/OrderPricingAdapter.d.ts +3 -0
- package/lib/director/OrderPricingAdapter.js +25 -0
- package/lib/director/OrderPricingAdapter.js.map +1 -0
- package/lib/director/OrderPricingDirector.d.ts +2 -0
- package/lib/director/OrderPricingDirector.js +48 -0
- package/lib/director/OrderPricingDirector.js.map +1 -0
- package/lib/director/OrderPricingSheet.d.ts +3 -0
- package/lib/director/OrderPricingSheet.js +113 -0
- package/lib/director/OrderPricingSheet.js.map +1 -0
- package/lib/module/configureOrderDeliveriesModule.d.ts +7 -0
- package/lib/module/configureOrderDeliveriesModule.js +164 -0
- package/lib/module/configureOrderDeliveriesModule.js.map +1 -0
- package/lib/module/configureOrderDiscountsModule.d.ts +7 -0
- package/lib/module/configureOrderDiscountsModule.js +183 -0
- package/lib/module/configureOrderDiscountsModule.js.map +1 -0
- package/lib/module/configureOrderPaymentsModule.d.ts +7 -0
- package/lib/module/configureOrderPaymentsModule.js +229 -0
- package/lib/module/configureOrderPaymentsModule.js.map +1 -0
- package/lib/module/configureOrderPositionsModule.d.ts +7 -0
- package/lib/module/configureOrderPositionsModule.js +213 -0
- package/lib/module/configureOrderPositionsModule.js.map +1 -0
- package/lib/module/configureOrdersModule-mutations.d.ts +12 -0
- package/lib/module/configureOrdersModule-mutations.js +162 -0
- package/lib/module/configureOrdersModule-mutations.js.map +1 -0
- package/lib/module/configureOrdersModule-processing.d.ts +13 -0
- package/lib/module/configureOrdersModule-processing.js +343 -0
- package/lib/module/configureOrdersModule-processing.js.map +1 -0
- package/lib/module/configureOrdersModule-queries.d.ts +5 -0
- package/lib/module/configureOrdersModule-queries.js +55 -0
- package/lib/module/configureOrdersModule-queries.js.map +1 -0
- package/lib/module/configureOrdersModule-transformations.d.ts +5 -0
- package/lib/module/configureOrdersModule-transformations.js +108 -0
- package/lib/module/configureOrdersModule-transformations.js.map +1 -0
- package/lib/module/configureOrdersModule.d.ts +3 -0
- package/lib/module/configureOrdersModule.js +239 -0
- package/lib/module/configureOrdersModule.js.map +1 -0
- package/lib/orders-index.d.ts +11 -0
- package/lib/orders-index.js +12 -0
- package/lib/orders-index.js.map +1 -0
- package/lib/orders-settings.d.ts +20 -0
- package/lib/orders-settings.js +17 -0
- package/lib/orders-settings.js.map +1 -0
- package/lib/service/createUserCartService.d.ts +2 -0
- package/lib/service/createUserCartService.js +23 -0
- package/lib/service/createUserCartService.js.map +1 -0
- package/lib/service/migrateOrderCartService.d.ts +2 -0
- package/lib/service/migrateOrderCartService.js +10 -0
- package/lib/service/migrateOrderCartService.js.map +1 -0
- package/lib/service/orderServices.d.ts +2 -0
- package/lib/service/orderServices.js +7 -0
- package/lib/service/orderServices.js.map +1 -0
- package/package.js +33 -0
- package/package.json +43 -0
- package/plugins/discount-100-off.ts +44 -0
- package/plugins/discount-half-price-manual.ts +43 -0
- package/plugins/discount-half-price.ts +46 -0
- package/plugins/order-delivery.ts +45 -0
- package/plugins/order-discount.ts +158 -0
- package/plugins/order-items-discount.ts +116 -0
- package/plugins/order-items.ts +61 -0
- package/plugins/order-payment.ts +46 -0
- package/src/db/OrderDeliveriesCollection.ts +12 -0
- package/src/db/OrderDeliveriesSchema.js +24 -0
- package/src/db/OrderDiscountTrigger.ts +4 -0
- package/src/db/OrderDiscountsCollection.ts +15 -0
- package/src/db/OrderDiscountsSchema.js +15 -0
- package/src/db/OrderPaymentsCollection.ts +12 -0
- package/src/db/OrderPaymentsSchema.js +24 -0
- package/src/db/OrderPositionsCollection.ts +15 -0
- package/src/db/OrderPositionsSchema.js +41 -0
- package/src/db/OrdersCollection.ts +37 -0
- package/src/db/OrdersSchema.js +34 -0
- package/src/director/OrderDiscountAdapter.ts +5 -0
- package/src/director/OrderDiscountDirector.ts +4 -0
- package/src/director/OrderPricingAdapter.ts +41 -0
- package/src/director/OrderPricingDirector.ts +68 -0
- package/src/director/OrderPricingSheet.ts +138 -0
- package/src/module/configureOrderDeliveriesModule.ts +240 -0
- package/src/module/configureOrderDiscountsModule.ts +245 -0
- package/src/module/configureOrderPaymentsModule.ts +331 -0
- package/src/module/configureOrderPositionsModule.ts +329 -0
- package/src/module/configureOrdersModule-mutations.ts +230 -0
- package/src/module/configureOrdersModule-processing.ts +506 -0
- package/src/module/configureOrdersModule-queries.ts +71 -0
- package/src/module/configureOrdersModule-transformations.ts +145 -0
- package/src/module/configureOrdersModule.ts +359 -0
- package/src/orders-index.ts +15 -0
- package/src/orders-settings.ts +23 -0
- package/src/service/createUserCartService.ts +38 -0
- package/src/service/migrateOrderCartService.ts +22 -0
- package/src/service/orderServices.ts +8 -0
- package/tests/orders-index.test.ts +50 -0
- package/tsconfig.build.json +26 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { Collection, Filter, ModuleMutations, Query } from '@unchainedshop/types/common';
|
|
2
|
+
import { OrdersModule } from '@unchainedshop/types/orders';
|
|
3
|
+
import { OrderPosition, OrderPositionsModule } from '@unchainedshop/types/orders.positions';
|
|
4
|
+
import { emit, registerEvents } from '@unchainedshop/events';
|
|
5
|
+
import { log } from '@unchainedshop/logger';
|
|
6
|
+
import { generateDbFilterById, generateDbMutations, generateDbObjectId } from '@unchainedshop/utils';
|
|
7
|
+
import { OrderPositionsSchema } from '../db/OrderPositionsSchema';
|
|
8
|
+
import { ordersSettings } from '../orders-settings';
|
|
9
|
+
|
|
10
|
+
const ORDER_POSITION_EVENTS: string[] = [
|
|
11
|
+
'ORDER_UPDATE_CART_ITEM',
|
|
12
|
+
'ORDER_REMOVE_CART_ITEM',
|
|
13
|
+
'ORDER_EMPTY_CART',
|
|
14
|
+
'ORDER_ADD_PRODUCT',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
const buildFindByIdSelector = (orderPositionId: string, orderId?: string) =>
|
|
18
|
+
generateDbFilterById(orderPositionId, orderId ? { orderId } : undefined) as Filter<OrderPosition>;
|
|
19
|
+
|
|
20
|
+
export const configureOrderPositionsModule = ({
|
|
21
|
+
OrderPositions,
|
|
22
|
+
updateCalculation,
|
|
23
|
+
}: {
|
|
24
|
+
OrderPositions: Collection<OrderPosition>;
|
|
25
|
+
updateCalculation: OrdersModule['updateCalculation'];
|
|
26
|
+
}): OrderPositionsModule => {
|
|
27
|
+
registerEvents(ORDER_POSITION_EVENTS);
|
|
28
|
+
|
|
29
|
+
const mutations = generateDbMutations<OrderPosition>(OrderPositions, OrderPositionsSchema, {
|
|
30
|
+
permanentlyDeleteByDefault: true,
|
|
31
|
+
hasCreateOnly: false,
|
|
32
|
+
}) as ModuleMutations<OrderPosition>;
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
// Queries
|
|
36
|
+
findOrderPosition: async ({ itemId }, options) => {
|
|
37
|
+
return OrderPositions.findOne(buildFindByIdSelector(itemId), options);
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
findOrderPositions: async ({ orderId }) => {
|
|
41
|
+
const positions = OrderPositions.find({ orderId, quantity: { $gt: 0 } });
|
|
42
|
+
return positions.toArray();
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
// Transformations
|
|
46
|
+
discounts: (orderPosition, { order, orderDiscount }, requestContext) => {
|
|
47
|
+
const pricingSheet = requestContext.modules.orders.positions.pricingSheet(
|
|
48
|
+
orderPosition,
|
|
49
|
+
order.currency,
|
|
50
|
+
requestContext,
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return pricingSheet.discountPrices(orderDiscount._id).map((discount) => ({
|
|
54
|
+
item: orderPosition,
|
|
55
|
+
...discount,
|
|
56
|
+
}));
|
|
57
|
+
},
|
|
58
|
+
|
|
59
|
+
pricingSheet: (orderPosition, currency, { modules }) => {
|
|
60
|
+
return modules.products.pricingSheet({
|
|
61
|
+
calculation: orderPosition.calculation,
|
|
62
|
+
currency,
|
|
63
|
+
quantity: orderPosition.quantity,
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
// Mutations
|
|
68
|
+
|
|
69
|
+
create: async (
|
|
70
|
+
{ configuration, context, quantity, quotationId },
|
|
71
|
+
{ order, product, originalProduct },
|
|
72
|
+
requestContext,
|
|
73
|
+
) => {
|
|
74
|
+
const orderId = order._id;
|
|
75
|
+
const productId = product._id;
|
|
76
|
+
const originalProductId = originalProduct ? originalProduct._id : undefined;
|
|
77
|
+
|
|
78
|
+
log(
|
|
79
|
+
`Create ${quantity}x Position with Product ${productId} ${quotationId ? ` (${quotationId})` : ''
|
|
80
|
+
}`,
|
|
81
|
+
{ orderId, productId, originalProductId, userId: requestContext.userId },
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const positionId = await mutations.create(
|
|
85
|
+
{
|
|
86
|
+
orderId,
|
|
87
|
+
productId,
|
|
88
|
+
originalProductId,
|
|
89
|
+
quotationId,
|
|
90
|
+
quantity,
|
|
91
|
+
configuration,
|
|
92
|
+
context,
|
|
93
|
+
calculation: [],
|
|
94
|
+
scheduling: [],
|
|
95
|
+
},
|
|
96
|
+
requestContext.userId,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
await updateCalculation(orderId, requestContext);
|
|
100
|
+
|
|
101
|
+
return OrderPositions.findOne(buildFindByIdSelector(positionId));
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
delete: async (orderPositionId, requestContext) => {
|
|
105
|
+
const selector = buildFindByIdSelector(orderPositionId);
|
|
106
|
+
const orderPosition = await OrderPositions.findOne(selector, {});
|
|
107
|
+
|
|
108
|
+
log(`Remove Position ${orderPositionId}`, {
|
|
109
|
+
orderId: orderPosition.orderId,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
await OrderPositions.deleteOne(selector);
|
|
113
|
+
|
|
114
|
+
await updateCalculation(orderPosition.orderId, requestContext);
|
|
115
|
+
|
|
116
|
+
emit('ORDER_REMOVE_CART_ITEM', {
|
|
117
|
+
orderPosition,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
return orderPosition;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
removePositions: async ({ orderId }, requestContext) => {
|
|
124
|
+
log('Remove Positions', { orderId });
|
|
125
|
+
|
|
126
|
+
const result = await OrderPositions.deleteMany({ orderId });
|
|
127
|
+
|
|
128
|
+
await updateCalculation(orderId, requestContext);
|
|
129
|
+
|
|
130
|
+
emit('ORDER_EMPTY_CART', { orderId, count: result.deletedCount });
|
|
131
|
+
|
|
132
|
+
return result.deletedCount;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
updateProductItem: async (
|
|
136
|
+
{ quantity, configuration },
|
|
137
|
+
{ order, product, orderPosition },
|
|
138
|
+
requestContext,
|
|
139
|
+
) => {
|
|
140
|
+
const selector = buildFindByIdSelector(orderPosition._id, order._id);
|
|
141
|
+
const modifier: any = {
|
|
142
|
+
$set: {
|
|
143
|
+
updated: new Date(),
|
|
144
|
+
updatedBy: requestContext.userId,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
if (quantity !== null && quantity !== orderPosition.quantity) {
|
|
149
|
+
modifier.$set.quantity = quantity;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (configuration !== null) {
|
|
153
|
+
const resolvedProduct = await requestContext.modules.products.resolveOrderableProduct(
|
|
154
|
+
product,
|
|
155
|
+
{ configuration },
|
|
156
|
+
requestContext,
|
|
157
|
+
);
|
|
158
|
+
modifier.$set.productId = resolvedProduct._id;
|
|
159
|
+
modifier.$set.configuration = configuration;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await ordersSettings.validateOrderPosition(
|
|
163
|
+
{
|
|
164
|
+
order,
|
|
165
|
+
product,
|
|
166
|
+
configuration,
|
|
167
|
+
quantityDiff: quantity - orderPosition.quantity,
|
|
168
|
+
},
|
|
169
|
+
requestContext,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
await OrderPositions.updateOne(selector, modifier);
|
|
173
|
+
|
|
174
|
+
await updateCalculation(order._id, requestContext);
|
|
175
|
+
|
|
176
|
+
const updatedOrderPosition = await OrderPositions.findOne(selector, {});
|
|
177
|
+
|
|
178
|
+
emit('ORDER_UPDATE_CART_ITEM', {
|
|
179
|
+
orderPosition: updatedOrderPosition,
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return updatedOrderPosition;
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
updateScheduling: async ({ order, orderDelivery, orderPosition }, requestContext) => {
|
|
186
|
+
const { modules } = requestContext;
|
|
187
|
+
// scheduling (store in db for auditing)
|
|
188
|
+
const product = await modules.products.findProduct({
|
|
189
|
+
productId: orderPosition.productId,
|
|
190
|
+
});
|
|
191
|
+
const deliveryProvider =
|
|
192
|
+
orderDelivery &&
|
|
193
|
+
(await modules.delivery.findProvider({
|
|
194
|
+
deliveryProviderId: orderDelivery.deliveryProviderId,
|
|
195
|
+
}));
|
|
196
|
+
const { countryCode, userId } = order;
|
|
197
|
+
|
|
198
|
+
const scheduling = await Promise.all(
|
|
199
|
+
(
|
|
200
|
+
await modules.warehousing.findSupported(
|
|
201
|
+
{
|
|
202
|
+
product,
|
|
203
|
+
deliveryProvider,
|
|
204
|
+
},
|
|
205
|
+
requestContext,
|
|
206
|
+
)
|
|
207
|
+
).map(async (warehousingProvider) => {
|
|
208
|
+
const context = {
|
|
209
|
+
warehousingProvider,
|
|
210
|
+
deliveryProvider,
|
|
211
|
+
product,
|
|
212
|
+
item: orderPosition,
|
|
213
|
+
delivery: deliveryProvider,
|
|
214
|
+
order,
|
|
215
|
+
userId,
|
|
216
|
+
country: countryCode,
|
|
217
|
+
referenceDate: order.ordered,
|
|
218
|
+
quantity: orderPosition.quantity,
|
|
219
|
+
};
|
|
220
|
+
const dispatch = await requestContext.modules.warehousing.estimatedDispatch(
|
|
221
|
+
warehousingProvider,
|
|
222
|
+
context,
|
|
223
|
+
requestContext,
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
warehousingProviderId: warehousingProvider._id,
|
|
228
|
+
...dispatch,
|
|
229
|
+
};
|
|
230
|
+
}),
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
await OrderPositions.updateOne(generateDbFilterById(orderPosition._id), {
|
|
234
|
+
$set: { scheduling },
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
return OrderPositions.findOne(generateDbFilterById(orderPosition._id), {});
|
|
238
|
+
},
|
|
239
|
+
|
|
240
|
+
updateCalculation: async (orderPosition, requestContext) => {
|
|
241
|
+
log(`OrderPosition ${orderPosition._id} -> Update Calculation`, {
|
|
242
|
+
orderId: orderPosition.orderId,
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const calculation = await requestContext.modules.products.calculate(
|
|
246
|
+
{ item: orderPosition },
|
|
247
|
+
requestContext,
|
|
248
|
+
);
|
|
249
|
+
const selector = buildFindByIdSelector(orderPosition._id);
|
|
250
|
+
|
|
251
|
+
await OrderPositions.updateOne(selector, {
|
|
252
|
+
$set: { calculation },
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
return OrderPositions.findOne(selector, {});
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
addProductItem: async (orderPosition: OrderPosition, { order, product }, requestContext) => {
|
|
259
|
+
const { modules } = requestContext;
|
|
260
|
+
const { configuration, orderId: positionOrderId, quantity, ...scope } = orderPosition;
|
|
261
|
+
const orderId = order._id || positionOrderId;
|
|
262
|
+
|
|
263
|
+
// Resolve product
|
|
264
|
+
const resolvedProduct = await modules.products.resolveOrderableProduct(
|
|
265
|
+
product,
|
|
266
|
+
{ configuration },
|
|
267
|
+
requestContext,
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
// Validate add to cart mutation
|
|
271
|
+
await ordersSettings.validateOrderPosition(
|
|
272
|
+
{
|
|
273
|
+
order,
|
|
274
|
+
product,
|
|
275
|
+
configuration,
|
|
276
|
+
quantityDiff: quantity,
|
|
277
|
+
},
|
|
278
|
+
requestContext,
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// Search for existing position
|
|
282
|
+
const selector: Query = {
|
|
283
|
+
orderId,
|
|
284
|
+
productId: resolvedProduct._id,
|
|
285
|
+
originalProductId: product._id,
|
|
286
|
+
configuration: configuration || { $exists: false },
|
|
287
|
+
...scope,
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
const { upsertedId } = await OrderPositions.updateOne(
|
|
291
|
+
selector,
|
|
292
|
+
{
|
|
293
|
+
$set: {
|
|
294
|
+
updated: new Date(),
|
|
295
|
+
updatedBy: requestContext.userId,
|
|
296
|
+
},
|
|
297
|
+
$inc: { quantity },
|
|
298
|
+
$setOnInsert: {
|
|
299
|
+
_id: generateDbObjectId(),
|
|
300
|
+
created: new Date(),
|
|
301
|
+
createdBy: requestContext.userId,
|
|
302
|
+
calculation: [],
|
|
303
|
+
scheduling: [],
|
|
304
|
+
orderId,
|
|
305
|
+
productId: resolvedProduct._id,
|
|
306
|
+
originalProductId: product._id,
|
|
307
|
+
configuration,
|
|
308
|
+
...scope,
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
{ upsert: true },
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
await updateCalculation(orderId, requestContext);
|
|
315
|
+
|
|
316
|
+
const upsertedOrderPosition = await OrderPositions.findOne(
|
|
317
|
+
upsertedId
|
|
318
|
+
? {
|
|
319
|
+
_id: upsertedId,
|
|
320
|
+
}
|
|
321
|
+
: selector,
|
|
322
|
+
);
|
|
323
|
+
|
|
324
|
+
emit('ORDER_ADD_PRODUCT', { orderPosition: upsertedOrderPosition });
|
|
325
|
+
|
|
326
|
+
return upsertedOrderPosition;
|
|
327
|
+
},
|
|
328
|
+
};
|
|
329
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { Collection, ModuleMutations } from '@unchainedshop/types/common';
|
|
2
|
+
import { Order, OrderStatus, OrderMutations, OrdersModule } from '@unchainedshop/types/orders';
|
|
3
|
+
import { OrderDelivery } from '@unchainedshop/types/orders.deliveries';
|
|
4
|
+
import { OrderPayment } from '@unchainedshop/types/orders.payments';
|
|
5
|
+
import { emit, registerEvents } from '@unchainedshop/events';
|
|
6
|
+
import { log, LogLevel } from '@unchainedshop/logger';
|
|
7
|
+
import { generateDbFilterById, generateDbMutations } from '@unchainedshop/utils';
|
|
8
|
+
import { OrdersSchema } from '../db/OrdersSchema';
|
|
9
|
+
|
|
10
|
+
const ORDER_EVENTS: string[] = [
|
|
11
|
+
'ORDER_CREATE',
|
|
12
|
+
'ORDER_REMOVE',
|
|
13
|
+
'ORDER_SET_DELIVERY_PROVIDER',
|
|
14
|
+
'ORDER_SET_PAYMENT_PROVIDER',
|
|
15
|
+
'ORDER_UPDATE',
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
export const configureOrderModuleMutations = ({
|
|
19
|
+
Orders,
|
|
20
|
+
OrderDeliveries,
|
|
21
|
+
OrderPayments,
|
|
22
|
+
initProviders,
|
|
23
|
+
updateStatus,
|
|
24
|
+
updateCalculation,
|
|
25
|
+
}: {
|
|
26
|
+
Orders: Collection<Order>;
|
|
27
|
+
OrderDeliveries: Collection<OrderDelivery>;
|
|
28
|
+
OrderPayments: Collection<OrderPayment>;
|
|
29
|
+
initProviders: OrdersModule['initProviders'];
|
|
30
|
+
updateStatus: OrdersModule['updateStatus'];
|
|
31
|
+
updateCalculation: OrdersModule['updateCalculation'];
|
|
32
|
+
}): OrderMutations => {
|
|
33
|
+
registerEvents(ORDER_EVENTS);
|
|
34
|
+
|
|
35
|
+
const mutations = generateDbMutations<Order>(Orders, OrdersSchema, {
|
|
36
|
+
permanentlyDeleteByDefault: true,
|
|
37
|
+
hasCreateOnly: false,
|
|
38
|
+
}) as ModuleMutations<Order>;
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
create: async ({ orderNumber, currency, countryCode, billingAddress, contact }, userId) => {
|
|
42
|
+
const orderId = await mutations.create(
|
|
43
|
+
{
|
|
44
|
+
created: new Date(),
|
|
45
|
+
createdBy: userId,
|
|
46
|
+
status: null,
|
|
47
|
+
billingAddress,
|
|
48
|
+
contact,
|
|
49
|
+
userId,
|
|
50
|
+
currency,
|
|
51
|
+
countryCode,
|
|
52
|
+
calculation: [],
|
|
53
|
+
log: [],
|
|
54
|
+
orderNumber,
|
|
55
|
+
},
|
|
56
|
+
userId,
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const order = await Orders.findOne(generateDbFilterById(orderId), {});
|
|
60
|
+
|
|
61
|
+
emit('ORDER_CREATE', { order });
|
|
62
|
+
return order;
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
delete: async (orderId, userId) => {
|
|
66
|
+
const deletedCount = await mutations.delete(orderId, userId);
|
|
67
|
+
emit('ORDER_REMOVE', { orderId });
|
|
68
|
+
return deletedCount;
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
initProviders,
|
|
72
|
+
|
|
73
|
+
invalidateProviders: async (requestContext, maxAgeDays = 30) => {
|
|
74
|
+
log('Orders: Start invalidating cart providers', {
|
|
75
|
+
level: LogLevel.Verbose,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const ONE_DAY_IN_MILLISECONDS = 86400000;
|
|
79
|
+
|
|
80
|
+
const minValidDate = new Date(new Date().getTime() - maxAgeDays * ONE_DAY_IN_MILLISECONDS);
|
|
81
|
+
|
|
82
|
+
const orders = await Orders.find({
|
|
83
|
+
status: { $eq: null },
|
|
84
|
+
updated: { $gte: minValidDate },
|
|
85
|
+
}).toArray();
|
|
86
|
+
|
|
87
|
+
await Promise.all(orders.map((order) => initProviders(order, requestContext)));
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
setDeliveryProvider: async (orderId, deliveryProviderId, requestContext) => {
|
|
91
|
+
const { modules } = requestContext;
|
|
92
|
+
const delivery = await OrderDeliveries.findOne({
|
|
93
|
+
orderId,
|
|
94
|
+
deliveryProviderId,
|
|
95
|
+
});
|
|
96
|
+
const deliveryId =
|
|
97
|
+
delivery?._id ||
|
|
98
|
+
(
|
|
99
|
+
await modules.orders.deliveries.create(
|
|
100
|
+
{
|
|
101
|
+
calculation: [],
|
|
102
|
+
deliveryProviderId,
|
|
103
|
+
log: [],
|
|
104
|
+
orderId,
|
|
105
|
+
status: null,
|
|
106
|
+
},
|
|
107
|
+
requestContext.userId,
|
|
108
|
+
)
|
|
109
|
+
)._id;
|
|
110
|
+
|
|
111
|
+
log(`Set Delivery Provider ${deliveryProviderId}`, { orderId });
|
|
112
|
+
|
|
113
|
+
const selector = generateDbFilterById(orderId);
|
|
114
|
+
await Orders.updateOne(selector, {
|
|
115
|
+
$set: {
|
|
116
|
+
deliveryId,
|
|
117
|
+
updated: new Date(),
|
|
118
|
+
updatedBy: requestContext.userId,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const order = await updateCalculation(orderId, requestContext);
|
|
123
|
+
|
|
124
|
+
emit('ORDER_SET_DELIVERY_PROVIDER', {
|
|
125
|
+
order,
|
|
126
|
+
deliveryProviderId,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
return order;
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
setPaymentProvider: async (orderId, paymentProviderId, requestContext) => {
|
|
133
|
+
const { modules, userId } = requestContext;
|
|
134
|
+
const payment = await OrderPayments.findOne({
|
|
135
|
+
orderId,
|
|
136
|
+
paymentProviderId,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const paymentId =
|
|
140
|
+
payment?._id ||
|
|
141
|
+
(
|
|
142
|
+
await modules.orders.payments.create(
|
|
143
|
+
{
|
|
144
|
+
calculation: [],
|
|
145
|
+
paymentProviderId,
|
|
146
|
+
log: [],
|
|
147
|
+
orderId,
|
|
148
|
+
status: null,
|
|
149
|
+
},
|
|
150
|
+
userId,
|
|
151
|
+
)
|
|
152
|
+
)._id;
|
|
153
|
+
log(`Set Payment Provider ${paymentProviderId}`, { orderId });
|
|
154
|
+
|
|
155
|
+
const selector = generateDbFilterById(orderId);
|
|
156
|
+
await Orders.updateOne(selector, {
|
|
157
|
+
$set: { paymentId, updated: new Date(), updatedBy: userId },
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const order = await updateCalculation(orderId, requestContext);
|
|
161
|
+
|
|
162
|
+
emit('ORDER_SET_PAYMENT_PROVIDER', {
|
|
163
|
+
order,
|
|
164
|
+
paymentProviderId,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
return order;
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
updateBillingAddress: async (orderId, billingAddress, requestContext) => {
|
|
171
|
+
log('Update Invoicing Address', { orderId });
|
|
172
|
+
|
|
173
|
+
const selector = generateDbFilterById(orderId);
|
|
174
|
+
await Orders.updateOne(selector, {
|
|
175
|
+
$set: {
|
|
176
|
+
billingAddress,
|
|
177
|
+
updated: new Date(),
|
|
178
|
+
updatedBy: requestContext.userId,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
const order = await updateCalculation(orderId, requestContext);
|
|
183
|
+
emit('ORDER_UPDATE', { order, field: 'billing' });
|
|
184
|
+
return order;
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
updateContact: async (orderId, contact, requestContext) => {
|
|
188
|
+
log('Update Contact', { orderId });
|
|
189
|
+
|
|
190
|
+
const selector = generateDbFilterById(orderId);
|
|
191
|
+
await Orders.updateOne(selector, {
|
|
192
|
+
$set: {
|
|
193
|
+
contact,
|
|
194
|
+
updated: new Date(),
|
|
195
|
+
updatedBy: requestContext.userId,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
const order = await updateCalculation(orderId, requestContext);
|
|
200
|
+
emit('ORDER_UPDATE', { order, field: 'contact' });
|
|
201
|
+
return order;
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
updateContext: async (orderId, context, requestContext) => {
|
|
205
|
+
log('Update Arbitrary Context', { orderId, context });
|
|
206
|
+
|
|
207
|
+
const selector = generateDbFilterById(orderId);
|
|
208
|
+
|
|
209
|
+
selector.status = { $in: [null, OrderStatus.PENDING] };
|
|
210
|
+
|
|
211
|
+
const result = await Orders.updateOne(selector, {
|
|
212
|
+
$set: {
|
|
213
|
+
context,
|
|
214
|
+
updated: new Date(),
|
|
215
|
+
updatedBy: requestContext.userId,
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
if (result.modifiedCount) {
|
|
220
|
+
const order = await updateCalculation(orderId, requestContext);
|
|
221
|
+
emit('ORDER_UPDATE', { order, field: 'context' });
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
return false;
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
updateStatus,
|
|
228
|
+
updateCalculation,
|
|
229
|
+
};
|
|
230
|
+
};
|