From ac79acd82bbc9968aed3c8f6dcb66f4ffd33d552 Mon Sep 17 00:00:00 2001 From: ronakmaheshwari Date: Sun, 3 Aug 2025 09:38:53 +0530 Subject: [PATCH 1/2] Added Issue 3698 fix --- .../src/service/services/order.service.ts | 67 +++++++++++++------ 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/packages/core/src/service/services/order.service.ts b/packages/core/src/service/services/order.service.ts index bbcead57ee..b58c78693c 100644 --- a/packages/core/src/service/services/order.service.ts +++ b/packages/core/src/service/services/order.service.ts @@ -581,7 +581,7 @@ export class OrderService { } else { return result.order; } - } + } /** * @description @@ -600,30 +600,39 @@ export class OrderService { items: Array<{ productVariantId: ID; quantity: number; - customFields?: { [key: string]: any }; + customFields?: Record; }>, relations?: RelationPaths, ): Promise<{ order: Order; errorResults: Array> }> { const order = await this.getOrderOrThrow(ctx, orderId); + if (order.state !== 'Modifying') { + await this.orderStateMachine.transition(ctx, order, 'Modify'); + } + const errorResults: Array> = []; const updatedOrderLines: OrderLine[] = []; + addItem: 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: { @@ -632,9 +641,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 => @@ -643,6 +654,7 @@ export class OrderService { ), 'quantity', ); + const correctedQuantity = await this.orderModifier.constrainQuantityToSaleable( ctx, variant, @@ -650,50 +662,59 @@ export class OrderService { 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 (customFields != null) { + const mergedCustomFields = { + ...(orderLine.customFields ?? {}), + ...customFields, + }; + orderLine.customFields = mergedCustomFields; + await this.customFieldRelationService.updateRelations( + ctx, + OrderLine, + { customFields: mergedCustomFields }, + orderLine, + ); + } + if (correctedQuantity < quantity) { - const newQuantity = (existingOrderLine ? existingOrderLine?.quantity : 0) + correctedQuantity; + const newQuantity = (existingOrderLine?.quantity ?? 0) + correctedQuantity; await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, newQuantity, order); } else { await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, correctedQuantity, order); } + updatedOrderLines.push(orderLine); + const quantityWasAdjustedDown = correctedQuantity < quantity; if (quantityWasAdjustedDown) { 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({ @@ -702,12 +723,14 @@ export class OrderService { }); } } + return { order: updatedOrder, errorResults, }; } + /** * @description * Adjusts the quantity and/or custom field values of an existing OrderLine. From bcc38c8820bf58d27b979625d8d2f89350056f0c Mon Sep 17 00:00:00 2001 From: ronakmaheshwari Date: Sun, 3 Aug 2025 09:47:35 +0530 Subject: [PATCH 2/2] Added Issue 3698 fix --- .../src/service/services/order.service.ts | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/packages/core/src/service/services/order.service.ts b/packages/core/src/service/services/order.service.ts index b58c78693c..9196a536ef 100644 --- a/packages/core/src/service/services/order.service.ts +++ b/packages/core/src/service/services/order.service.ts @@ -594,25 +594,33 @@ export class OrderService { * * @since 3.1.0 */ + async addItemsToOrder( - ctx: RequestContext, - orderId: ID, - items: Array<{ - productVariantId: ID; - quantity: number; - customFields?: Record; - }>, + ctx: RequestContext, + orderId: ID, + items: Array<{ + productVariantId: ID; + quantity: number; + customFields?: Record; + }>, relations?: RelationPaths, ): Promise<{ order: Order; errorResults: Array> }> { - const order = await this.getOrderOrThrow(ctx, orderId); + const order = await this.getOrderOrThrow(ctx, orderId, relations); + + // StateChecking Happens here Early if (order.state !== 'Modifying') { - await this.orderStateMachine.transition(ctx, order, 'Modify'); + 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> = []; 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( @@ -679,6 +687,7 @@ export class OrderService { productVariantId, customFields, ); + if (customFields != null) { const mergedCustomFields = { ...(orderLine.customFields ?? {}), @@ -693,37 +702,21 @@ export class OrderService { ); } - if (correctedQuantity < quantity) { - const newQuantity = (existingOrderLine?.quantity ?? 0) + correctedQuantity; - await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, newQuantity, order); - } else { - await this.orderModifier.updateOrderLineQuantity(ctx, orderLine, correctedQuantity, order); - } - + 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, }), ); - continue; - } - } - - const updatedOrder = await this.applyPriceAdjustments(ctx, order, updatedOrderLines, relations); - 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, @@ -731,6 +724,7 @@ export class OrderService { } + /** * @description * Adjusts the quantity and/or custom field values of an existing OrderLine.