Files
medusa-store/www/apps/docs/content/references/medusa/classes/medusa.AbstractPriceSelectionStrategy.mdx
Shahed Nasser bb87db8342 docs: prep for v2 documentation (#6710)
This PR includes documentation that preps for v2 docs (but doesn't introduce new docs).

_Note: The number of file changes in the PR is due to find-and-replace within the `references` which is unavoidable. Let me know if I should move it to another PR._

## Changes

- Change Medusa version in base OAS used for v2.
- Fix to docblock generator related to not catching all path parameters.
- Added typedoc plugin that generates ER Diagrams, which will be used specifically for data model references in commerce modules.
- Changed OAS tool to output references in `www/apps/api-reference/specs-v2` directory when the `--v2` option is used.
- Added a version switcher to the API reference to switch between V1 and V2. This switcher is enabled by an environment variable, so it won't be visible/usable at the moment.
- Upgraded docusaurus to v3.0.1
- Added new Vale rules to ensure correct spelling of Medusa Admin and module names.
- Added new components to the `docs-ui` package that will be used in future documentation changes.
2024-03-18 07:47:35 +00:00

292 lines
14 KiB
Plaintext

---
displayed_sidebar: homepage
---
import TypeList from "@site/src/components/TypeList"
# 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<Map<string, PriceSelectionResult>> {
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
<TypeList types={[{"name":"container","type":"`Record<string, unknown>`","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<string, unknown>`","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
<TypeList types={[{"name":"container","type":"`Record<string, unknown>`","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<string, unknown>`","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<string, unknown>`","description":"","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"__moduleDeclaration__","type":"`Record<string, unknown>`","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
<TypeList types={[{"name":"EntityManager","type":"`EntityManager`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="activeManager_"/>
___
## 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<Map<string, PriceSelectionResult>> {
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<string, PriceSelectionResult>()
if (!context.ignore_cache) {
const cacheHits = await promiseAll(
[...cacheKeysMap].map(async ([, cacheKey]) => {
return await this.cacheService_.get<PriceSelectionResult>(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<string, PriceSelectionResult> = 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
<TypeList types={[{"name":"data","type":"`object`[]","description":"The necessary data to perform the price selection for each variant ID.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"variantId","type":"`string`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"quantity","type":"`number`","description":"","optional":true,"defaultValue":"","expandable":false,"children":[]}]},{"name":"context","type":"[PriceSelectionContext](../interfaces/medusa.PriceSelectionContext.mdx)","description":"The context of the price selection.","optional":false,"defaultValue":"","expandable":false,"children":[{"name":"cart_id","type":"`string`","description":"The cart's ID. This is used when the prices are being retrieved for the variant of a line item,\nas it is used to determine the current region and currency code of the context.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"customer_id","type":"`string`","description":"The ID of the customer viewing the variant.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"region_id","type":"`string`","description":"The region's ID.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"quantity","type":"`number`","description":"The quantity of the item in the cart. This is used to filter out price lists that have\n`min_quantity` or `max_quantity` conditions set.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"currency_code","type":"`string`","description":"The currency code the customer is using.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"include_discount_prices","type":"`boolean`","description":"Whether the price list's prices should be retrieved or not.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"tax_rates","type":"[TaxServiceRate](../types/medusa.TaxServiceRate.mdx)[]","description":"The tax rates to be applied. This is only used for\n[Tax-Inclusive Pricing](https://docs.medusajs.com/modules/taxes/inclusive-pricing).","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"ignore_cache","type":"`boolean`","description":"Whether to calculate the prices even if the value of an earlier price calculation\nis available in the cache.","optional":true,"defaultValue":"","expandable":false,"children":[]}]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="calculateVariantPrice"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;Map&#60;string, [PriceSelectionResult](../interfaces/medusa.PriceSelectionResult.mdx)&#62;&#62;","optional":false,"defaultValue":"","description":"A map, each key is an ID of a variant, and its value is an object holding the price selection result.","expandable":false,"children":[{"name":"Map","type":"Map&#60;string, [PriceSelectionResult](../interfaces/medusa.PriceSelectionResult.mdx)&#62;","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="calculateVariantPrice"/>
### 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<void> {
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
<TypeList types={[{"name":"variantIds","type":"`string`[]","description":"The IDs of the updated variants.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="onVariantsPricesUpdate"/>
#### Returns
<TypeList types={[{"name":"Promise","type":"Promise&#60;void&#62;","optional":false,"defaultValue":"","description":"Resolves after any necessary actions are performed.","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="onVariantsPricesUpdate"/>
### withTransaction
#### Parameters
<TypeList types={[{"name":"transactionManager","type":"`EntityManager`","description":"","optional":true,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="withTransaction"/>
#### Returns
<TypeList types={[{"name":"this","type":"`this`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="withTransaction"/>
### shouldRetryTransaction\_
#### Parameters
<TypeList types={[{"name":"err","type":"`Record<string, unknown>` \\| `object`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="shouldRetryTransaction_"/>
#### Returns
<TypeList types={[{"name":"boolean","type":"`boolean`","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="shouldRetryTransaction_"/>
### 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
<TypeList types={[{"name":"TResult","type":"`object`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"TError","type":"`object`","description":"","optional":false,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="atomicPhase_"/>
#### Parameters
<TypeList types={[{"name":"work","type":"(`transactionManager`: `EntityManager`) => Promise&#60;TResult&#62;","description":"the transactional work to be done","optional":false,"defaultValue":"","expandable":false,"children":[]},{"name":"isolationOrErrorHandler","type":"`IsolationLevel` \\| (`error`: TError) => Promise&#60;void \\| TResult&#62;","description":"the isolation level to be used for the work.","optional":true,"defaultValue":"","expandable":false,"children":[]},{"name":"maybeErrorHandlerOrDontFail","type":"(`error`: TError) => Promise&#60;void \\| TResult&#62;","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
<TypeList types={[{"name":"Promise","type":"Promise&#60;TResult&#62;","optional":false,"defaultValue":"","description":"the result of the transactional work","expandable":false,"children":[{"name":"TResult","type":"TResult","optional":false,"defaultValue":"","description":"","expandable":false,"children":[]}]}]} expandUrl="https://docs.medusajs.com/development/entities/repositories#retrieving-a-list-of-records" sectionTitle="atomicPhase_"/>