--- displayed_sidebar: homepage --- import ParameterTypes from "@site/src/components/ParameterTypes" # AbstractPriceSelectionStrategy ## Overview The price selection strategy retrieves the best price for a product variant for a specific context such as selected region, taxes applied, the quantity in cart, and more. Medusa provides a default price selection strategy, but you can override it. A price selecion strategy is a TypeScript or JavaScript file in the `src/strategies` directory of your Medusa backend project. It exports a class that extends the `AbstractPriceSelectionStrategy` class. For example: ```ts title="src/strategies/price.ts" import { AbstractPriceSelectionStrategy, PriceSelectionContext, PriceSelectionResult, } from "@medusajs/medusa" export default class MyStrategy extends AbstractPriceSelectionStrategy { async calculateVariantPrice( data: { variantId: string; quantity?: number }[], context: PriceSelectionContext ): Promise> { throw new Error("Method not implemented.") } } ``` --- ## constructor You can use the `constructor` of your price-selection strategy to access the different services in Medusa through dependency injection. ### Example ```ts // ... import { AbstractPriceSelectionStrategy, CustomerService, } from "@medusajs/medusa" type InjectedDependencies = { customerService: CustomerService } class MyStrategy extends AbstractPriceSelectionStrategy { protected customerService_: CustomerService constructor(container: InjectedDependencies) { super(container) this.customerService_ = container.customerService } // ... } export default MyStrategy ``` ### Parameters `","description":"An instance of `MedusaContainer` that allows you to access other resources, such as services, in your Medusa backend.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"config","type":"`Record`","description":"If this price-selection strategy is created in a plugin, the plugin's options are passed in this parameter.","optional":true,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="new AbstractPriceSelectionStrategy"/> ___ ## Properties `","description":"An instance of `MedusaContainer` that allows you to access other resources, such as services, in your Medusa backend.","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"manager_","type":"`EntityManager`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"transactionManager_","type":"`undefined` \\| `EntityManager`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"__container__","type":"`any`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"config","type":"`Record`","description":"If this price-selection strategy is created in a plugin, the plugin's options are passed in this parameter.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"__configModule__","type":"`Record`","description":"","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"__moduleDeclaration__","type":"`Record`","description":"","optional":true,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="AbstractPriceSelectionStrategy"/> ___ ## Accessors ### activeManager\_ #### Returns ___ ## Methods ### calculateVariantPrice This method retrieves one or more product variants' prices. It's used when retrieving product variants or their associated line items. It's also used when retrieving other entities that product variants and line items belong to, such as products and carts respectively. #### Example For example, here's a snippet of how the price selection strategy is implemented in the Medusa backend: ```ts import { AbstractPriceSelectionStrategy, CustomerService, PriceSelectionContext, PriceSelectionResult, } from "@medusajs/medusa" type InjectedDependencies = { customerService: CustomerService } export default class MyStrategy extends AbstractPriceSelectionStrategy { async calculateVariantPrice( data: { variantId: string quantity?: number }[], context: PriceSelectionContext ): Promise> { const dataMap = new Map(data.map((d) => [d.variantId, d])) const cacheKeysMap = new Map( data.map(({ variantId, quantity }) => [ variantId, this.getCacheKey(variantId, { ...context, quantity }), ]) ) const nonCachedData: { variantId: string quantity?: number }[] = [] const variantPricesMap = new Map() if (!context.ignore_cache) { const cacheHits = await promiseAll( [...cacheKeysMap].map(async ([, cacheKey]) => { return await this.cacheService_.get(cacheKey) }) ) if (!cacheHits.length) { nonCachedData.push(...dataMap.values()) } for (const [index, cacheHit] of cacheHits.entries()) { const variantId = data[index].variantId if (cacheHit) { variantPricesMap.set(variantId, cacheHit) continue } nonCachedData.push(dataMap.get(variantId)!) } } else { nonCachedData.push(...dataMap.values()) } let results: Map = new Map() if ( this.featureFlagRouter_.isFeatureEnabled( TaxInclusivePricingFeatureFlag.key ) ) { results = await this.calculateVariantPrice_new(nonCachedData, context) } else { results = await this.calculateVariantPrice_old(nonCachedData, context) } await promiseAll( [...results].map(async ([variantId, prices]) => { variantPricesMap.set(variantId, prices) if (!context.ignore_cache) { await this.cacheService_.set(cacheKeysMap.get(variantId)!, prices) } }) ) return variantPricesMap } // ... } ``` #### Parameters #### Returns ### onVariantsPricesUpdate This method is called when prices of product variants have changed. You can use it to invalidate prices stored in the cache. #### Example For example, this is how this method is implemented in the Medusa backend's default price selection strategy: ```ts import { AbstractPriceSelectionStrategy, CustomerService, } from "@medusajs/medusa" import { promiseAll } from "@medusajs/utils" type InjectedDependencies = { customerService: CustomerService } export default class MyStrategy extends AbstractPriceSelectionStrategy { public async onVariantsPricesUpdate(variantIds: string[]): Promise { await promiseAll( variantIds.map( async (id: string) => await this.cacheService_.invalidate(`ps:${id}:*`) ) ) } // ... } ``` :::note Learn more about the cache service in [this documentation](https://docs.medusajs.com/development/cache/overview). ::: #### Parameters #### Returns ### withTransaction #### Parameters #### Returns ### shouldRetryTransaction\_ #### Parameters ` \\| `object`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="shouldRetryTransaction_"/> #### Returns ### atomicPhase\_ Wraps some work within a transactional block. If the service already has a transaction manager attached this will be reused, otherwise a new transaction manager is created. #### Type Parameters #### Parameters Promise<TResult>","description":"the transactional work to be done","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"isolationOrErrorHandler","type":"`IsolationLevel` \\| (`error`: TError) => Promise<void \\| TResult>","description":"the isolation level to be used for the work.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"maybeErrorHandlerOrDontFail","type":"(`error`: TError) => Promise<void \\| TResult>","description":"Potential error handler","optional":true,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="atomicPhase_"/> #### Returns