---
description: 'Learn how to override the price selection strategy. The price selection strategy is used to determine the best price based on a specific context.'
addHowToData: true
---

import ParameterTypes from "@site/src/components/ParameterTypes"

# How to Override Price Selection Strategy

In this document, you’ll learn how to override Medusa’s price selection strategy to create a custom pricing strategy.

:::note

If you’re interested in learning what a price selection strategy is and how it works, check out [this documentation](../price-selection-strategy.md) instead.

:::

## 1. Create Class

Create a TypeScript or JavaScript file in `src/strategies` of your Medusa backend project with a class that extends the `AbstractPriceSelectionStrategy` class:

```ts title="src/strategies/price.ts"
import { 
  AbstractPriceSelectionStrategy, 
  PriceSelectionContext, 
  PriceSelectionResult,
} from "@medusajs/medusa"
import { 
  TaxServiceRate,
} from "@medusajs/medusa/dist/types/tax-service"

export default class MyStrategy extends 
  AbstractPriceSelectionStrategy {

  async calculateVariantPrice(
    data: { 
      variantId: string; 
      taxRates: TaxServiceRate[]; 
      quantity?: number 
    }[], 
    context: PriceSelectionContext
  ): Promise<Map<string, PriceSelectionResult>> {
    throw new Error("Method not implemented.")
  }
}
```

### Resolve Resources

You can resolve resources like services or repositories using [dependency injection](../../../development/fundamentals/dependency-injection.md).

For example:

```ts title="src/strategies/price.ts"
import { 
  AbstractPriceSelectionStrategy, 
  CustomerService, 
  PriceSelectionContext, 
  PriceSelectionResult,
} from "@medusajs/medusa"
import { 
  TaxServiceRate,
} from "@medusajs/medusa/dist/types/tax-service"

type InjectedDependencies = {
  customerService: CustomerService
}

export default class MyStrategy extends 
  AbstractPriceSelectionStrategy {
  
  protected customerService_: CustomerService

  constructor(container: InjectedDependencies) {
    super(container)
    this.customerService_ = container.customerService
  }

  // ...
}
```

---

## 2. Implement calculateVariantPrice

In this method, you can implement your price selection strategy.

### Parameters

You can learn more about optional properties and the meaning behind every property [here](../price-selection-strategy.md#calculatevariantprice-method).

<ParameterTypes parameters={[
  {
    name: "data",
    type: "object[]",
    description: "Holds the data necessary to perform the price selection for each variant ID.",
    optional: false,
    children: [
      {
        name: "variantId",
        type: "string",
        description: "The ID of the variant to retrieve the prices for.",
        optional: false,
      },
      {
        name: "taxRates",
        type: "object[]",
        description: "The tax rates to be applied. This is only used for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
        optional: false,
        children: [
          {
            name: "rate",
            type: "number | null",
            description: "The tax rate",
            optional: true
          },
          {
            name: "name",
            type: "string",
            description: "The name of the tax rate",
            optional: false
          },
          {
            name: "code",
            type: "string | null",
            description: "The code of the tax rate",
            optional: false
          }
        ],
      },
      {
        name: "quantity",
        type: "number",
        description: "The quantity of the variant",
        optional: true
      }
    ],
  },
  {
    name: "context",
    type: "[PriceSelectionContext](../price-selection-strategy.md#context-object)",
    description: "The context of the price selection",
    optional: false,
    children: [
      {
        name: "cart_id",
        type: "string",
        description: "The ID of the customer’s cart. This is used when the prices are being retrieved for the variant of a line item, as it is used to determine the current region and currency code of the context.",
        optional: true
      },
      {
        name: "customer_id",
        type: "string",
        description: "The ID of the customer. This is used to filter out price lists for a customer group that this customer doesn’t belong to.",
        optional: true
      },
      {
        name: "region_id",
        type: "string",
        description: "The ID of the region the customer is using.",
        optional: true
      },
      {
        name: "quantity",
        type: "number",
        description: "The quantity of the item in the cart. This is used to filter out price lists that have `min_quantity` or `max_quantity` conditions set.",
        optional: true
      },
      {
        name: "currency_code",
        type: "string",
        description: "The currency code the customer is using.",
        optional: true
      },
      {
        name: "include_discount_prices",
        type: "boolean",
        description: "Whether the price list's prices should be retrieved or not.",
        optional: true
      },
      {
        name: "taxRates",
        type: "object[]",
        description: "The tax rates to be applied. This is only used for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
        optional: false,
        children: [
          {
            name: "rate",
            type: "number | null",
            description: "The tax rate",
            optional: true
          },
          {
            name: "name",
            type: "string",
            description: "The name of the tax rate",
            optional: false
          },
          {
            name: "code",
            type: "string | null",
            description: "The code of the tax rate",
            optional: false
          }
        ],
      },
      {
        name: "ignore_cache",
        type: "boolean",
        description: "Whether to calculate the prices even if the value of an earlier price calculation is available in the cache.",
        optional: true
      },
    ]
  }
]} />

### Returns

<ParameterTypes parameters={[
  {
    name: "Promise",
    type: "Promise<Map<string, PriceSelectionResult>>",
    description: "A map, each key is an ID of a variant, and its value is an object holding the price selection result.",
    optional: false,
    children: [
      {
        name: "PriceSelectionResult",
        type: "PriceSelectionResult",
        description: "The price selection result of a variant.",
        optional: false,
        children: [
          {
            name: "originalPrice",
            type: "number | null",
            description: "The original price of the variant which depends on the selected region or currency code in the context object. If both region ID and currency code are available in the context object, the region has higher precedence.",
            optional: false
          },
          {
            name: "originalPriceIncludesTax",
            type: "boolean | null",
            description: "Whether the original price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
            optional: true
          },
          {
            name: "calculatedPrice",
            type: "number | null",
            description: "The lowest price among the prices of the product variant retrieved using the context object.",
            optional: false
          },
          {
            name: "calculatedPriceIncludesTax",
            type: "boolean | null",
            description: "Whether the calculated price includes taxes or not. This is only available for [Tax-Inclusive Pricing](../../taxes/inclusive-pricing.md).",
            optional: true
          },
          {
            name: "calculatedPriceType",
            type: "enum",
            description: "Either `default` if the `calculatedPrice` is the original price, or the type of the price list applied, which can be `override` or `sale`.",
            optional: true
          },
          {
            name: "prices",
            type: "[MoneyAmount](../../../references/entities/classes/entities.MoneyAmount.mdx)[]",
            description: "The prices of the variant retrieved using the `context` object. It can include its original price and its price lists if there are any.",
            optional: false
          }
        ],
      }
    ],
  },
]} />

---

## 3. Run Build Command

In your terminal, run the build command to transpile the files in the `src` directory into the `dist` directory:

```bash npm2yarn
npm run build
```

---

## Test it Out

Run your backend to test it out:

```bash npm2yarn
npx medusa develop
```

Then, try out your strategy using any of the [Products](https://docs.medusajs.com/api/store#products) or [Carts](https://docs.medusajs.com/api/store#carts) API Routes which include retrieving product variants and line items respectively. You should then see the prices in the response based on your implemented strategy.
