Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 63 additions & 46 deletions packages/core/src/service/services/order.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ export class OrderService {
} else {
return result.order;
}
}
}

/**
* @description
Expand All @@ -594,36 +594,53 @@ export class OrderService {
*
* @since 3.1.0
*/

async addItemsToOrder(
ctx: RequestContext,
orderId: ID,
items: Array<{
productVariantId: ID;
quantity: number;
customFields?: { [key: string]: any };
}>,
ctx: RequestContext,
orderId: ID,
items: Array<{
productVariantId: ID;
quantity: number;
customFields?: Record<string, any>;
}>,
relations?: RelationPaths<Order>,
): Promise<{ order: Order; errorResults: Array<JustErrorResults<UpdateOrderItemsResult>> }> {
const order = await this.getOrderOrThrow(ctx, orderId);
const order = await this.getOrderOrThrow(ctx, orderId, relations);

// StateChecking Happens here Early
if (order.state !== 'Modifying') {
const canTransition = await this.orderStateMachine.canTransition(order.state, 'Modify');
if (canTransition) {
await this.orderStateMachine.transition(ctx, order, 'Modify');
} else {
throw new IllegalOperationError('Cannot add items unless order is in Modifying state');
}
}

const errorResults: Array<JustErrorResults<UpdateOrderItemsResult>> = [];
const updatedOrderLines: OrderLine[] = [];
addItem: for (const item of items) {

for (const item of items) {
const { productVariantId, quantity, customFields } = item;

const existingOrderLine = await this.orderModifier.getExistingOrderLine(
ctx,
order,
productVariantId,
customFields,
);

const validationError =
this.assertQuantityIsPositive(quantity) ||
this.assertAddingItemsState(order) ||
this.assertNotOverOrderItemsLimit(order, quantity) ||
this.assertNotOverOrderLineItemsLimit(existingOrderLine, quantity);

if (validationError) {
errorResults.push(validationError);
continue;
}

const variant = await this.connection.getEntityOrThrow(ctx, ProductVariant, productVariantId, {
relations: ['product'],
where: {
Expand All @@ -632,9 +649,11 @@ export class OrderService {
},
loadEagerRelations: false,
});
if (variant.product.enabled === false) {

if (!variant.product.enabled) {
throw new EntityNotFoundError('ProductVariant', productVariantId);
}

const existingQuantityInOtherLines = summate(
order.lines.filter(
l =>
Expand All @@ -643,71 +662,69 @@ export class OrderService {
),
'quantity',
);

const correctedQuantity = await this.orderModifier.constrainQuantityToSaleable(
ctx,
variant,
quantity,
existingOrderLine?.quantity,
existingQuantityInOtherLines,
);

if (correctedQuantity === 0) {
errorResults.push(
new InsufficientStockError({ order, quantityAvailable: correctedQuantity }),
new InsufficientStockError({
quantityAvailable: correctedQuantity,
order,
}),
);
continue;
}
const { orderInterceptors } = this.configService.orderOptions;
for (const interceptor of orderInterceptors) {
if (interceptor.willAddItemToOrder) {
const error = await interceptor.willAddItemToOrder(ctx, order, {
productVariant: variant,
quantity: correctedQuantity,
customFields,
});
if (error) {
errorResults.push(new OrderInterceptorError({ interceptorError: error }));
continue addItem;
}
}
}

const orderLine = await this.orderModifier.getOrCreateOrderLine(
ctx,
order,
productVariantId,
customFields,
);
if (correctedQuantity < quantity) {
const newQuantity = (existingOrderLine ? existingOrderLine?.quantity : 0) + correctedQuantity;
await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, newQuantity, order);
} else {
await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, correctedQuantity, order);

if (customFields != null) {
const mergedCustomFields = {
...(orderLine.customFields ?? {}),
...customFields,
};
orderLine.customFields = mergedCustomFields;
await this.customFieldRelationService.updateRelations(
ctx,
OrderLine,
{ customFields: mergedCustomFields },
orderLine,
);
}

const newQuantity = (existingOrderLine?.quantity ?? 0) + correctedQuantity;
await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, newQuantity, order);
updatedOrderLines.push(orderLine);
const quantityWasAdjustedDown = correctedQuantity < quantity;
if (quantityWasAdjustedDown) {

if (correctedQuantity < quantity) {
errorResults.push(
new InsufficientStockError({ quantityAvailable: correctedQuantity, order }),
new InsufficientStockError({
quantityAvailable: correctedQuantity,
order,
}),
);
continue;
}
}
const updatedOrder = await this.applyPriceAdjustments(ctx, order, updatedOrderLines, relations);
// for any InsufficientStockError errors, we want to make sure we use the final updatedOrder
// after having applied all price adjustments
for (const [i, errorResult] of Object.entries(errorResults)) {
if (errorResult.__typename === 'InsufficientStockError') {
errorResults[+i] = new InsufficientStockError({
quantityAvailable: errorResult.quantityAvailable,
order: updatedOrder,
});
}
}

const updatedOrder = await this.getOrderOrThrow(ctx, orderId, relations);
return {
order: updatedOrder,
errorResults,
};
}



/**
* @description
* Adjusts the quantity and/or custom field values of an existing OrderLine.
Expand Down
Loading