Skip to content

Commit

Permalink
feat(core): Return ErrorResult when setting ineligible ShippingMethod
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbromley committed Nov 5, 2020
1 parent 3f29f22 commit 0e09d51
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 9 deletions.
10 changes: 9 additions & 1 deletion packages/common/src/generated-shop-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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';
Expand Down Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion packages/core/src/api/schema/shop-api/shop.api.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -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!
Expand Down Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion packages/core/src/common/error/generated-graphql-shop-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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,
Expand Down
14 changes: 9 additions & 5 deletions packages/core/src/service/services/order.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import {
SettlePaymentError,
} from '../../common/error/generated-graphql-admin-errors';
import {
IneligibleShippingMethodError,
InsufficientStockError,
NegativeQuantityError,
OrderLimitError,
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion schema-shop.json

Large diffs are not rendered by default.

0 comments on commit 0e09d51

Please sign in to comment.