---
title: "OrderInterceptor"
isDefaultIndex: false
generated: true
---
<!-- This file was generated from the Vendure source. Do not modify. Instead, re-run the "docs:build" script -->
import MemberInfo from '@site/src/components/MemberInfo';
import GenerationInfo from '@site/src/components/GenerationInfo';
import MemberDescription from '@site/src/components/MemberDescription';


## OrderInterceptor

<GenerationInfo sourceFile="packages/core/src/config/order/order-interceptor.ts" sourceLine="214" packageName="@vendure/core" since="3.1.0" />

An OrderInterceptor is a class which can be used to intercept and modify the behavior of order-related
operations.

It does this by providing methods which are called whenever the contents of an order are about
to get changed. These methods are able to prevent the operation from proceeding by returning a string
error message.

Examples of use-cases for an OrderInterceptor include:

* Preventing certain products from being added to the order based on some criteria, e.g. if the
  product is already in another active order.
* Enforcing a minimum or maximum quantity of a given product in the order
* Using a CAPTCHA to prevent automated order creation

:::info

This is configured via the `orderOptions.orderInterceptors` property of
your VendureConfig.

:::

OrderInterceptors are executed when the following mutations are called:

- `addItemToOrder`
- `adjustOrderLine`
- `removeItemFromOrder`

Additionally, if you are working directly with the <a href='/reference/typescript-api/services/order-service#orderservice'>OrderService</a>, the following methods will trigger
any registered OrderInterceptors:

- `addItemToOrder`
- `addItemsToOrder`
- `adjustOrderLine`
- `adjustOrderLines`
- `removeItemFromOrder`
- `removeItemsFromOrder`

When an OrderInterceptor is registered, it will be called in the order in which it was registered.
If an interceptor method resolves to a string, the operation will be prevented and the string will be used as the error message.

When multiple interceptors are registered, the first interceptor to resolve to a string will prevent the operation from proceeding.

Errors returned by OrderInterceptors are surfaced to the GraphQL API as an `OrderInterceptorError` and can be
queried like this:

```graphql
mutation AddItemToOrder($productVariantId: ID!, $quantity: Int!) {
  addItemToOrder(productVariantId: $productVariantId, quantity: $quantity) {
    ... on Order {
      id
      code
      # ... other Order fields
    }
    ... on ErrorResult {
      errorCode
      message
    }
    // highlight-start
    ... on OrderInterceptorError {
      interceptorError
    }
    // highlight-end
  }
}
```

In the above example, the error message returned by the OrderInterceptor would be available in the `interceptorError` field.

## Example: Min/max order quantity

Let's say we want to allow ProductVariants to specify the minimum or maximum amount which may be added
to an order. We can define custom fields to store this information and
then use this custom field value to prevent an order line from being added to the order if the quantity
is below the minimum.

*Example*

```ts
import {
  EntityHydrator,
  Injector,
  LanguageCode,
  Order,
  OrderInterceptor,
  ProductVariant,
  RequestContext,
  TranslatorService,
  VendurePlugin,
  WillAddItemToOrderInput,
  WillAdjustOrderLineInput,
} from '@vendure/core';

declare module '@vendure/core/dist/entity/custom-entity-fields' {
  interface CustomProductVariantFields {
    minOrderQuantity?: number;
    maxOrderQuantity?: number;
  }
}

// This OrderInterceptor enforces minimum and maximum order quantities on ProductVariants.
export class MinMaxOrderInterceptor implements OrderInterceptor {
 private entityHydrator: EntityHydrator;
 private translatorService: TranslatorService;

 init(injector: Injector) {
   this.entityHydrator = injector.get(EntityHydrator);
   this.translatorService = injector.get(TranslatorService);
 }

 willAddItemToOrder(
   ctx: RequestContext,
   order: Order,
   input: WillAddItemToOrderInput,
 ): Promise<void | string> | void | string {
   const { productVariant, quantity } = input;
   const min = productVariant.customFields?.minOrderQuantity;
   const max = productVariant.customFields?.maxOrderQuantity;
   if (min && quantity < min) {
     return this.minErrorMessage(ctx, productVariant, min);
   }
   if (max && quantity > max) {
     return this.maxErrorMessage(ctx, productVariant, max);
   }
 }

 willAdjustOrderLine(
   ctx: RequestContext,
   order: Order,
   input: WillAdjustOrderLineInput,
 ): Promise<void | string> | void | string {
   const { orderLine, quantity } = input;
   const min = orderLine.productVariant.customFields?.minOrderQuantity;
   const max = orderLine.productVariant.customFields?.maxOrderQuantity;
   if (min && quantity < min) {
     return this.minErrorMessage(ctx, orderLine.productVariant, min);
   }
   if (max && quantity > max) {
     return this.maxErrorMessage(ctx, orderLine.productVariant, max);
   }
 }

 private async minErrorMessage(ctx: RequestContext, variant: ProductVariant, min: number) {
   const variantName = await this.getTranslatedVariantName(ctx, variant);
   return `Minimum order quantity for "${variantName}" is ${min}`;
 }

 private async maxErrorMessage(ctx: RequestContext, variant: ProductVariant, max: number) {
   const variantName = await this.getTranslatedVariantName(ctx, variant);
   return `Maximum order quantity for "${variantName}" is ${max}`;
 }

 private async getTranslatedVariantName(ctx: RequestContext, variant: ProductVariant) {
   await this.entityHydrator.hydrate(ctx, variant, { relations: ['translations'] });
   const translated = this.translatorService.translate(variant, ctx);
   return translated.name;
 }
}

// This plugin enforces minimum and maximum order quantities on ProductVariants.
// It adds two new custom fields to ProductVariant:
// - minOrderQuantity
// - maxOrderQuantity
//
// It also adds an OrderInterceptor which enforces these limits.
@VendurePlugin({
 configuration: config => {
 // Here we add the custom fields to the ProductVariant entity
   config.customFields.ProductVariant.push({
     type: 'int',
     min: 0,
     name: 'minOrderQuantity',
     label: [{ languageCode: LanguageCode.en, value: 'Minimum order quantity' }],
     nullable: true,
   });
   config.customFields.ProductVariant.push({
     type: 'int',
     min: 0,
     name: 'maxOrderQuantity',
     label: [{ languageCode: LanguageCode.en, value: 'Maximum order quantity' }],
     nullable: true,
   });

   // Here we add the MinMaxOrderInterceptor to the orderInterceptors array
   config.orderOptions.orderInterceptors.push(new MinMaxOrderInterceptor());
   return config;
 },
})
export class OrderQuantityLimitsPlugin {}
```

```ts title="Signature"
interface OrderInterceptor extends InjectableStrategy {
    willAddItemToOrder?(
        ctx: RequestContext,
        order: Order,
        input: WillAddItemToOrderInput,
    ): Promise<void | string> | void | string;
    willAdjustOrderLine?(
        ctx: RequestContext,
        order: Order,
        input: WillAdjustOrderLineInput,
    ): Promise<void | string> | void | string;
    willRemoveItemFromOrder?(
        ctx: RequestContext,
        order: Order,
        orderLine: OrderLine,
    ): Promise<void | string> | void | string;
}
```
* Extends: <code><a href='/reference/typescript-api/common/injectable-strategy#injectablestrategy'>InjectableStrategy</a></code>



<div className="members-wrapper">

### willAddItemToOrder

<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, input: WillAddItemToOrderInput) => Promise&#60;void | string&#62; | void | string`}   />

Called when a new item is about to be added to the order,
as in the `addItemToOrder` mutation or the `addItemToOrder()` / `addItemsToOrder()` method
of the <a href='/reference/typescript-api/services/order-service#orderservice'>OrderService</a>.
### willAdjustOrderLine

<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, input: WillAdjustOrderLineInput) => Promise&#60;void | string&#62; | void | string`}   />

Called when an existing order line is about to be adjusted,
as in the `adjustOrderLine` mutation or the `adjustOrderLine()` / `adjustOrderLines()` method
of the <a href='/reference/typescript-api/services/order-service#orderservice'>OrderService</a>.
### willRemoveItemFromOrder

<MemberInfo kind="method" type={`(ctx: <a href='/reference/typescript-api/request/request-context#requestcontext'>RequestContext</a>, order: <a href='/reference/typescript-api/entities/order#order'>Order</a>, orderLine: <a href='/reference/typescript-api/entities/order-line#orderline'>OrderLine</a>) => Promise&#60;void | string&#62; | void | string`}   />

Called when an item is about to be removed from the order,
as in the `removeItemFromOrder` mutation or the `removeItemFromOrder()` / `removeItemsFromOrder()` method
of the <a href='/reference/typescript-api/services/order-service#orderservice'>OrderService</a>.


</div>
