Browse Source

feat(core): Return ErrorResult when setting ineligible ShippingMethod

Michael Bromley 5 years ago
parent
commit
0e09d518b6

+ 9 - 1
packages/common/src/generated-shop-types.ts

@@ -457,6 +457,7 @@ export enum ErrorCode {
     ORDER_LIMIT_ERROR = 'ORDER_LIMIT_ERROR',
     NEGATIVE_QUANTITY_ERROR = 'NEGATIVE_QUANTITY_ERROR',
     INSUFFICIENT_STOCK_ERROR = 'INSUFFICIENT_STOCK_ERROR',
+    INELIGIBLE_SHIPPING_METHOD_ERROR = 'INELIGIBLE_SHIPPING_METHOD_ERROR',
     ORDER_PAYMENT_STATE_ERROR = 'ORDER_PAYMENT_STATE_ERROR',
     PAYMENT_FAILED_ERROR = 'PAYMENT_FAILED_ERROR',
     PAYMENT_DECLINED_ERROR = 'PAYMENT_DECLINED_ERROR',
@@ -1438,6 +1439,13 @@ export type InsufficientStockError = ErrorResult & {
     order: Order;
 };
 
+/** Returned when attempting to set a ShippingMethod for which the order is not eligible */
+export type IneligibleShippingMethodError = ErrorResult & {
+    __typename?: 'IneligibleShippingMethodError';
+    errorCode: ErrorCode;
+    message: Scalars['String'];
+};
+
 /** Returned when attempting to add a Payment to an Order that is not in the `ArrangingPayment` state. */
 export type OrderPaymentStateError = ErrorResult & {
     __typename?: 'OrderPaymentStateError';
@@ -1586,7 +1594,7 @@ export type UpdateOrderItemsResult =
 
 export type RemoveOrderItemsResult = Order | OrderModificationError;
 
-export type SetOrderShippingMethodResult = Order | OrderModificationError;
+export type SetOrderShippingMethodResult = Order | OrderModificationError | IneligibleShippingMethodError;
 
 export type ApplyCouponCodeResult =
     | Order

+ 7 - 1
packages/core/src/api/schema/shop-api/shop.api.graphql

@@ -205,6 +205,12 @@ type InsufficientStockError implements ErrorResult {
     order: Order!
 }
 
+"Returned when attempting to set a ShippingMethod for which the order is not eligible"
+type IneligibleShippingMethodError implements ErrorResult {
+    errorCode: ErrorCode!
+    message: String!
+}
+
 "Returned when attempting to add a Payment to an Order that is not in the `ArrangingPayment` state."
 type OrderPaymentStateError implements ErrorResult {
     errorCode: ErrorCode!
@@ -342,7 +348,7 @@ union UpdateOrderItemsResult =
     | NegativeQuantityError
     | InsufficientStockError
 union RemoveOrderItemsResult = Order | OrderModificationError
-union SetOrderShippingMethodResult = Order | OrderModificationError
+union SetOrderShippingMethodResult = Order | OrderModificationError | IneligibleShippingMethodError
 union ApplyCouponCodeResult = Order | CouponCodeExpiredError | CouponCodeInvalidError | CouponCodeLimitError
 union AddPaymentToOrderResult =
       Order

+ 11 - 1
packages/core/src/common/error/generated-graphql-shop-errors.ts

@@ -105,6 +105,16 @@ export class InsufficientStockError extends ErrorResult {
   }
 }
 
+export class IneligibleShippingMethodError extends ErrorResult {
+  readonly __typename = 'IneligibleShippingMethodError';
+  readonly errorCode = 'INELIGIBLE_SHIPPING_METHOD_ERROR' as any;
+  readonly message = 'INELIGIBLE_SHIPPING_METHOD_ERROR';
+  constructor(
+  ) {
+    super();
+  }
+}
+
 export class OrderPaymentStateError extends ErrorResult {
   readonly __typename = 'OrderPaymentStateError';
   readonly errorCode = 'ORDER_PAYMENT_STATE_ERROR' as any;
@@ -272,7 +282,7 @@ export class NotVerifiedError extends ErrorResult {
 }
 
 
-const errorTypeNames = new Set(['NativeAuthStrategyError', 'InvalidCredentialsError', 'OrderStateTransitionError', 'EmailAddressConflictError', 'OrderModificationError', 'OrderLimitError', 'NegativeQuantityError', 'InsufficientStockError', 'OrderPaymentStateError', 'PaymentFailedError', 'PaymentDeclinedError', 'CouponCodeInvalidError', 'CouponCodeExpiredError', 'CouponCodeLimitError', 'AlreadyLoggedInError', 'MissingPasswordError', 'PasswordAlreadySetError', 'VerificationTokenInvalidError', 'VerificationTokenExpiredError', 'IdentifierChangeTokenInvalidError', 'IdentifierChangeTokenExpiredError', 'PasswordResetTokenInvalidError', 'PasswordResetTokenExpiredError', 'NotVerifiedError']);
+const errorTypeNames = new Set(['NativeAuthStrategyError', 'InvalidCredentialsError', 'OrderStateTransitionError', 'EmailAddressConflictError', 'OrderModificationError', 'OrderLimitError', 'NegativeQuantityError', 'InsufficientStockError', 'IneligibleShippingMethodError', 'OrderPaymentStateError', 'PaymentFailedError', 'PaymentDeclinedError', 'CouponCodeInvalidError', 'CouponCodeExpiredError', 'CouponCodeLimitError', 'AlreadyLoggedInError', 'MissingPasswordError', 'PasswordAlreadySetError', 'VerificationTokenInvalidError', 'VerificationTokenExpiredError', 'IdentifierChangeTokenInvalidError', 'IdentifierChangeTokenExpiredError', 'PasswordResetTokenInvalidError', 'PasswordResetTokenExpiredError', 'NotVerifiedError']);
 function isGraphQLError(input: any): input is import('@vendure/common/lib/generated-types').ErrorResult {
   return input instanceof ErrorResult || errorTypeNames.has(input.__typename);
 }

+ 1 - 0
packages/core/src/i18n/messages/en.json

@@ -50,6 +50,7 @@
     "EMAIL_ADDRESS_CONFLICT_ERROR": "The email address is not available.",
     "EMPTY_ORDER_LINE_SELECTION_ERROR": "At least one OrderLine must be specified",
     "IDENTIFIER_CHANGE_TOKEN_INVALID_ERROR": "Identifier change token not recognized",
+    "INELIGIBLE_SHIPPING_METHOD_ERROR": "This Order is not eligible for the selected ShippingMethod",
     "INSUFFICIENT_STOCK_ERROR": "{quantityAvailable, plural, =0 {No items were} one {Only 1 item was} other {Only # items were}} added to the order due to insufficient stock",
     "INSUFFICIENT_STOCK_ON_HAND_ERROR": "Cannot create a Fulfillment as '{productVariantName}' has insufficient stockOnHand ({stockOnHand})",
     "INVALID_CREDENTIALS_ERROR": "The provided credentials are invalid",

+ 15 - 0
packages/core/src/service/helpers/shipping-calculator/shipping-calculator.ts

@@ -1,4 +1,5 @@
 import { Injectable } from '@nestjs/common';
+import { ID } from '@vendure/common/lib/shared-types';
 import { notNullOrUndefined } from '@vendure/common/lib/shared-utils';
 
 import { RequestContext } from '../../../api/common/request-context';
@@ -31,6 +32,20 @@ export class ShippingCalculator {
         return eligibleMethods.filter(notNullOrUndefined).sort((a, b) => a.result.price - b.result.price);
     }
 
+    async getMethodIfEligible(
+        ctx: RequestContext,
+        order: Order,
+        shippingMethodId: ID,
+    ): Promise<ShippingMethod | undefined> {
+        const method = await this.shippingMethodService.findOne(ctx, shippingMethodId);
+        if (method) {
+            const eligible = await method.test(ctx, order);
+            if (eligible) {
+                return method;
+            }
+        }
+    }
+
     private async checkEligibilityByShippingMethod(
         ctx: RequestContext,
         order: Order,

+ 9 - 5
packages/core/src/service/services/order.service.ts

@@ -49,6 +49,7 @@ import {
     SettlePaymentError,
 } from '../../common/error/generated-graphql-admin-errors';
 import {
+    IneligibleShippingMethodError,
     InsufficientStockError,
     NegativeQuantityError,
     OrderLimitError,
@@ -536,12 +537,15 @@ export class OrderService {
         if (validationError) {
             return validationError;
         }
-        const eligibleMethods = await this.shippingCalculator.getEligibleShippingMethods(ctx, order);
-        const selectedMethod = eligibleMethods.find(m => idsAreEqual(m.method.id, shippingMethodId));
-        if (!selectedMethod) {
-            throw new UserInputError(`error.shipping-method-unavailable`);
+        const shippingMethod = await this.shippingCalculator.getMethodIfEligible(
+            ctx,
+            order,
+            shippingMethodId,
+        );
+        if (!shippingMethod) {
+            return new IneligibleShippingMethodError();
         }
-        order.shippingMethod = selectedMethod.method;
+        order.shippingMethod = shippingMethod;
         await this.connection.getRepository(ctx, Order).save(order, { reload: false });
         await this.applyPriceAdjustments(ctx, order);
         return this.connection.getRepository(ctx, Order).save(order);

File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff