diff --git a/packages/core/src/config/shipping-method/shipping-calculator.ts b/packages/core/src/config/shipping-method/shipping-calculator.ts index ee98b5dc03..c73d2dd558 100644 --- a/packages/core/src/config/shipping-method/shipping-calculator.ts +++ b/packages/core/src/config/shipping-method/shipping-calculator.ts @@ -59,7 +59,7 @@ export class ShippingCalculator extends C calculate( order: Order, args: ConfigArg[], - ): ShippingCalculationResult | Promise { + ): ShippingCalculationResult | Promise | undefined { return this.calculateFn(order, argsArrayToHash(args)); } } @@ -103,4 +103,4 @@ export interface ShippingCalculationResult { export type CalculateShippingFn = ( order: Order, args: ConfigArgValues, -) => ShippingCalculationResult | Promise; +) => ShippingCalculationResult | Promise | undefined; diff --git a/packages/core/src/entity/shipping-method/shipping-method.entity.ts b/packages/core/src/entity/shipping-method/shipping-method.entity.ts index 5f98e15145..0a03fd1f3f 100644 --- a/packages/core/src/entity/shipping-method/shipping-method.entity.ts +++ b/packages/core/src/entity/shipping-method/shipping-method.entity.ts @@ -59,12 +59,15 @@ export class ShippingMethod extends VendureEntity implements ChannelAware, SoftD async apply(order: Order): Promise { const calculator = this.allCalculators[this.calculator.code]; if (calculator) { - const { price, priceWithTax, metadata } = await calculator.calculate(order, this.calculator.args); - return { - price: Math.round(price), - priceWithTax: Math.round(priceWithTax), - metadata, - }; + const response = await calculator.calculate(order, this.calculator.args); + if (response) { + const { price, priceWithTax, metadata } = response; + return { + price: Math.round(price), + priceWithTax: Math.round(priceWithTax), + metadata, + }; + } } } diff --git a/packages/core/src/service/helpers/shipping-calculator/shipping-calculator.ts b/packages/core/src/service/helpers/shipping-calculator/shipping-calculator.ts index 9adfc5c76b..a308db2a06 100644 --- a/packages/core/src/service/helpers/shipping-calculator/shipping-calculator.ts +++ b/packages/core/src/service/helpers/shipping-calculator/shipping-calculator.ts @@ -1,4 +1,5 @@ import { Injectable } from '@nestjs/common'; +import { notNullOrUndefined } from '@vendure/common/lib/shared-utils'; import { RequestContext } from '../../../api/common/request-context'; import { ShippingCalculationResult } from '../../../config/shipping-method/shipping-calculator'; @@ -6,6 +7,11 @@ import { Order } from '../../../entity/order/order.entity'; import { ShippingMethod } from '../../../entity/shipping-method/shipping-method.entity'; import { ShippingMethodService } from '../../services/shipping-method.service'; +type EligibleShippingMethod = { + method: ShippingMethod; + result: ShippingCalculationResult; +}; + @Injectable() export class ShippingCalculator { constructor(private shippingMethodService: ShippingMethodService) {} @@ -14,21 +20,27 @@ export class ShippingCalculator { * Returns an array of each eligible ShippingMethod for the given Order and sorts them by * price, with the cheapest first. */ - async getEligibleShippingMethods( - ctx: RequestContext, - order: Order, - ): Promise> { + async getEligibleShippingMethods(ctx: RequestContext, order: Order): Promise { const shippingMethods = this.shippingMethodService.getActiveShippingMethods(ctx.channel); - const eligibleMethods: Array<{ method: ShippingMethod; result: ShippingCalculationResult }> = []; - for (const method of shippingMethods) { - const eligible = await method.test(order); - if (eligible) { - const result = await method.apply(order); - if (result) { - eligibleMethods.push({ method, result }); - } + + const checkEligibilityPromises = shippingMethods.map((method) => + this.checkEligibilityByShippingMethod(order, method), + ); + const eligibleMethods = await Promise.all(checkEligibilityPromises); + + return eligibleMethods.filter(notNullOrUndefined).sort((a, b) => a.result.price - b.result.price); + } + + private async checkEligibilityByShippingMethod( + order: Order, + method: ShippingMethod, + ): Promise { + const eligible = await method.test(order); + if (eligible) { + const result = await method.apply(order); + if (result) { + return { method, result }; } } - return eligibleMethods.sort((a, b) => a.result.price - b.result.price); } }