feat: Completely revamp the pricing module (#7852)

* feat: Completely revamp the pricing module

* chore: Update all places to the new pricing interfaces

* fix: Remove unnecessary join to itself

* chore: Add data migration for existing users

* fix: Apply the correct index to price rule
This commit is contained in:
Stevche Radevski
2024-07-01 09:47:03 +02:00
committed by GitHub
parent 1f360a3245
commit c661180c44
84 changed files with 661 additions and 3725 deletions
@@ -25,8 +25,6 @@ function buildPriceSet(
prices: StepInput[0]["prices"],
regionToCurrencyMap: Map<string, string>
): CreatePriceSetDTO {
const rules: CreatePriceSetDTO["rules"] = []
const shippingOptionPrices = prices.map((price) => {
if ("currency_code" in price) {
return {
@@ -35,10 +33,6 @@ function buildPriceSet(
}
}
rules.push({
rule_attribute: "region_id",
})
return {
currency_code: regionToCurrencyMap.get(price.region_id)!,
amount: price.amount,
@@ -48,7 +42,7 @@ function buildPriceSet(
}
})
return { rules, prices: shippingOptionPrices }
return { prices: shippingOptionPrices }
}
export const createShippingOptionsPriceSetsStepId =
@@ -1,4 +1,4 @@
import { CreateRuleTypeDTO, FulfillmentWorkflow } from "@medusajs/types"
import { FulfillmentWorkflow } from "@medusajs/types"
import {
createWorkflow,
transform,
@@ -9,7 +9,6 @@ import {
upsertShippingOptionsStep,
} from "../steps"
import { setShippingOptionsPriceSetsStep } from "../steps/set-shipping-options-price-sets"
import { createPricingRuleTypesStep } from "../../pricing"
export const createShippingOptionsWorkflowId =
"create-shipping-options-workflow"
@@ -45,18 +44,8 @@ export const createShippingOptionsWorkflow = createWorkflow(
shippingOptionsIndexToPrices: data.shippingOptionsIndexToPrices,
},
(data) => {
const ruleTypes = new Set<CreateRuleTypeDTO>()
const shippingOptionsPrices = data.shippingOptionsIndexToPrices.map(
({ shipping_option_index, prices }) => {
prices.forEach((price) => {
if ("region_id" in price) {
ruleTypes.add({
name: "region_id",
rule_attribute: "region_id",
})
}
})
return {
id: data.shippingOptions[shipping_option_index].id,
prices,
@@ -66,13 +55,10 @@ export const createShippingOptionsWorkflow = createWorkflow(
return {
shippingOptionsPrices,
ruleTypes: Array.from(ruleTypes) as CreateRuleTypeDTO[],
}
}
)
createPricingRuleTypesStep(normalizedShippingOptionsPrices.ruleTypes)
const shippingOptionsPriceSetsLinkData = createShippingOptionsPriceSetsStep(
normalizedShippingOptionsPrices.shippingOptionsPrices
)
@@ -1,8 +1,4 @@
import {
CreateRuleTypeDTO,
FulfillmentWorkflow,
RuleTypeDTO,
} from "@medusajs/types"
import { FulfillmentWorkflow } from "@medusajs/types"
import {
createWorkflow,
transform,
@@ -12,7 +8,6 @@ import {
setShippingOptionsPricesStep,
upsertShippingOptionsStep,
} from "../steps"
import { createPricingRuleTypesStep } from "../../pricing"
export const updateShippingOptionsWorkflowId =
"update-shipping-options-workflow"
@@ -49,18 +44,8 @@ export const updateShippingOptionsWorkflow = createWorkflow(
shippingOptionsIndexToPrices: data.shippingOptionsIndexToPrices,
},
(data) => {
const ruleTypes = new Set<Partial<RuleTypeDTO>>()
const shippingOptionsPrices = data.shippingOptionsIndexToPrices.map(
({ shipping_option_index, prices }) => {
prices?.forEach((price) => {
if ("region_id" in price) {
ruleTypes.add({
name: "region_id",
rule_attribute: "region_id",
})
}
})
return {
id: data.shippingOptions[shipping_option_index].id,
prices,
@@ -70,13 +55,10 @@ export const updateShippingOptionsWorkflow = createWorkflow(
return {
shippingOptionsPrices,
ruleTypes: Array.from(ruleTypes) as CreateRuleTypeDTO[],
}
}
)
createPricingRuleTypesStep(normalizedShippingOptionsPrices.ruleTypes)
setShippingOptionsPricesStep(
normalizedShippingOptionsPrices.shippingOptionsPrices
)
@@ -44,7 +44,7 @@ export const updatePriceListsStep = createStep(
await pricingModule.updatePriceLists(
dataBeforeUpdate.map((data) => {
const { price_list_rules: priceListRules = [], rules, ...rest } = data
const { price_list_rules: priceListRules = [], ...rest } = data
const updateData: UpdatePriceListDTO = {
...rest,
@@ -82,14 +82,8 @@ async function getDataBeforeUpdate(
selectsClone.splice(index, 1)
}
selectsClone.push(
"price_list_rules.price_list_rule_values.value",
"price_list_rules.rule_type.rule_attribute"
)
relationsClone.push(
"price_list_rules.price_list_rule_values",
"price_list_rules.rule_type"
)
selectsClone.push("price_list_rules.value", "price_list_rules.attribute")
relationsClone.push("price_list_rules")
}
const dataBeforeUpdate = await pricingModule.listPriceLists(
@@ -1,2 +1 @@
export * from "./steps"
export * from "./workflows"
@@ -1,47 +0,0 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { CreateRuleTypeDTO, IPricingModuleService } from "@medusajs/types"
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
export const createPricingRuleTypesStepId = "create-pricing-rule-types"
export const createPricingRuleTypesStep = createStep(
createPricingRuleTypesStepId,
async (data: CreateRuleTypeDTO[], { container }) => {
if (!data?.length) {
return
}
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
const existingRuleTypes = await pricingModule.listRuleTypes({
rule_attribute: data.map((d) => d.rule_attribute),
})
const existingRuleTypeAttributes = new Set(
existingRuleTypes.map((ruleType) => ruleType.rule_attribute)
)
const ruleTypesToCreate = data.filter(
(dataItem) => !existingRuleTypeAttributes.has(dataItem.rule_attribute)
)
const ruleTypes = await pricingModule.createRuleTypes(ruleTypesToCreate)
return new StepResponse(
ruleTypes,
ruleTypes.map((ruleType) => ruleType.id)
)
},
async (ruleTypeIds, { container }) => {
if (!ruleTypeIds?.length) {
return
}
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
await pricingModule.deleteRuleTypes(ruleTypeIds)
}
)
@@ -1,31 +0,0 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPricingModuleService } from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
export const deletePricingRuleTypesStepId = "delete-pricing-rule-types"
export const deletePricingRuleTypesStep = createStep(
deletePricingRuleTypesStepId,
async (ids: string[], { container }) => {
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
// TODO: implement soft deleting rule types
// await pricingModule.softDeleteRuleTypes(ids)
await pricingModule.deleteRuleTypes(ids)
return new StepResponse(void 0, ids)
},
async (ids, { container }) => {
if (!ids?.length) {
return
}
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
// TODO: implement restoring soft deleted rule types
// await pricingModule.restoreRuleTypes(ids)
}
)
@@ -1,5 +1,2 @@
export * from "./create-price-sets"
export * from "./update-price-sets"
export * from "./create-pricing-rule-types"
export * from "./delete-pricing-rule-types"
export * from "./update-pricing-rule-types"
@@ -1,48 +0,0 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { IPricingModuleService, UpdateRuleTypeDTO } from "@medusajs/types"
import {
convertItemResponseToUpdateRequest,
getSelectsAndRelationsFromObjectArray,
} from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
export const updatePricingRuleTypesStepId = "update-pricing-rule-types"
export const updatePricingRuleTypesStep = createStep(
updatePricingRuleTypesStepId,
async (data: UpdateRuleTypeDTO[], { container }) => {
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
const { selects, relations } = getSelectsAndRelationsFromObjectArray(data)
const dataBeforeUpdate = await pricingModule.listRuleTypes(
{ id: data.map((d) => d.id) },
{ relations, select: selects }
)
const updatedRuleTypes = await pricingModule.updateRuleTypes(data)
return new StepResponse(updatedRuleTypes, {
dataBeforeUpdate,
selects,
relations,
})
},
async (revertInput, { container }) => {
if (!revertInput) {
return
}
const { dataBeforeUpdate = [], selects, relations } = revertInput
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
await pricingModule.updateRuleTypes(
dataBeforeUpdate.map((data) =>
convertItemResponseToUpdateRequest(data, selects, relations)
)
)
}
)
@@ -1,13 +0,0 @@
import { CreateRuleTypeDTO, RuleTypeDTO } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { createPricingRuleTypesStep } from "../steps"
type WorkflowInput = { data: CreateRuleTypeDTO[] }
export const createPricingRuleTypesWorkflowId = "create-pricing-rule-types"
export const createPricingRuleTypesWorkflow = createWorkflow(
createPricingRuleTypesWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<RuleTypeDTO[]> => {
return createPricingRuleTypesStep(input.data)
}
)
@@ -1,12 +0,0 @@
import { createWorkflow, WorkflowData } from "@medusajs/workflows-sdk"
import { deletePricingRuleTypesStep } from "../steps"
type WorkflowInput = { ids: string[] }
export const deletePricingRuleTypesWorkflowId = "delete-pricing-rule-types"
export const deletePricingRuleTypesWorkflow = createWorkflow(
deletePricingRuleTypesWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<void> => {
deletePricingRuleTypesStep(input.ids)
}
)
@@ -1,3 +0,0 @@
export * from "./create-pricing-rule-types"
export * from "./delete-pricing-rule-types"
export * from "./update-pricing-rule-types"
@@ -1,13 +0,0 @@
import { RuleTypeDTO, UpdateRuleTypeDTO } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { updatePricingRuleTypesStep } from "../steps"
type WorkflowInput = { data: UpdateRuleTypeDTO[] }
export const updatePricingRuleTypesWorkflowId = "update-pricing-rule-types"
export const updatePricingRuleTypesWorkflow = createWorkflow(
updatePricingRuleTypesWorkflowId,
(input: WorkflowData<WorkflowInput>): WorkflowData<RuleTypeDTO[]> => {
return updatePricingRuleTypesStep(input.data)
}
)
@@ -3,6 +3,4 @@ export * from "./price"
export * from "./price-list"
export * from "./price-rule"
export * from "./price-set"
export * from "./price-set-rule-type"
export * from "./pricing-context"
export * from "./rule-type"
@@ -5,7 +5,6 @@ import {
UpdateMoneyAmountDTO,
} from "./money-amount"
import { PriceDTO } from "./price"
import { RuleTypeDTO } from "./rule-type"
/**
* @enum
@@ -63,7 +62,7 @@ export interface PriceListDTO {
*/
rules_count?: number
/**
* The associated price set money amounts.
* The associated price list money amounts.
*
* @expandable
*/
@@ -75,22 +74,7 @@ export interface PriceListDTO {
*/
money_amounts?: MoneyAmountDTO[]
/**
* The associated rule types.
*
* @expandable
*/
rule_types?: RuleTypeDTO[]
/**
* The price set's rules.
*
* @expandable
*/
rules?: PriceListRuleDTO[]
/**
* The price set's rules.
*
* @privateRemarks
* Do we need both this and `rules`?
* The price list's rules.
*
* @expandable
*/
@@ -108,9 +92,9 @@ export interface CreatePriceListPriceDTO extends CreateMoneyAmountDTO {
*/
price_set_id: string
/**
* The rules to add to the price. The object's keys are rule types' `rule_attribute` attribute, and values are the value of that rule associated with this price.
* The rules to add to the price. The object's keys are the attribute, and values are the value of that rule associated with this price.
*/
rules?: CreatePriceSetPriceRules
rules?: CreatePriceListPriceRules
}
export interface UpdatePriceListPriceDTO extends UpdateMoneyAmountDTO {
@@ -119,25 +103,25 @@ export interface UpdatePriceListPriceDTO extends UpdateMoneyAmountDTO {
*/
price_set_id: string
/**
* The rules to add to the price. The object's keys are rule types' `rule_attribute` attribute, and values are the value of that rule associated with this price.
* The rules to add to the price. The object's keys are the attribute, and values are the value of that rule associated with this price.
*/
rules?: CreatePriceSetPriceRules
rules?: CreatePriceListPriceRules
}
/**
* @interface
*
* The price rules to be set for each price in the price set.
* The price rules to be set for each price in the price list.
*
* Each key of the object is a rule type's `rule_attribute`, and its value
* Each key of the object is an attribute, and its value
* is the values of the rule.
*/
export interface CreatePriceSetPriceRules extends Record<string, string> {}
export interface CreatePriceListPriceRules extends Record<string, string> {}
/**
* @interface
*
* The price list's rules to be set. Each key of the object is a rule type's `rule_attribute`, and its value
* The price list's rules to be set. Each key of the object the attribute, and its value
* is the values of the rule.
*/
export interface CreatePriceListRules extends Record<string, string[]> {}
@@ -172,10 +156,6 @@ export interface CreatePriceListDTO {
* The price list's type.
*/
type?: PriceListType
/**
* The number of rules associated with the price list.
*/
rules_count?: number
/**
* The rules to be created and associated with the price list.
*/
@@ -216,10 +196,6 @@ export interface UpdatePriceListDTO {
* The price list's status.
*/
status?: PriceListStatus
/**
* The number of rules associated with the price list.
*/
rules_count?: number
/**
* The rules to be created and associated with the price list.
*/
@@ -274,23 +250,12 @@ export interface FilterablePriceListRuleProps
* The values to filter price list rules by.
*/
value?: string[]
/**
* Filter price list rules by the ID of their associated rule types.
*/
rule_type?: string[]
/**
* Filter price list rules by the ID of their associated price lists.
*/
price_list_id?: string[]
}
export interface FilterablePriceListRuleValueProps
extends BaseFilterable<FilterablePriceListRuleValueProps> {
id?: string[]
value?: string[]
price_list_rule_id?: string[]
}
/**
* @interface
*
@@ -301,31 +266,22 @@ export interface PriceListRuleDTO {
* The price list rule's ID.
*/
id: string
/**
* The attribute of the rule.
*
*/
attribute: string
/**
* The value of the rule.
*
* @privateRemarks
* Shouldn't this be in PriceListRuleValueDTO only?
*/
value: string
/**
* The associated rule type.
*
* @expandable
*/
rule_type: RuleTypeDTO
value: string | string[]
/**
* The associated price list.
*
* @expandable
*/
price_list: PriceListDTO
/**
* The associated rule values.
*
* @expandable
*/
price_list_rule_values?: PriceListRuleValueDTO[]
}
/**
@@ -334,14 +290,6 @@ export interface PriceListRuleDTO {
* The price list rule to create.
*/
export interface CreatePriceListRuleDTO {
/**
* The ID of a rule type to be associated with the price list rule.
*/
rule_type_id?: string
/**
* The ID of a rule type or the details of an existing rule type to be associated with the price list rule.
*/
rule_type?: string | RuleTypeDTO
/**
* The ID of a price list to be associated with the price list rule.
*/
@@ -352,68 +300,6 @@ export interface CreatePriceListRuleDTO {
price_list?: string | PriceListDTO
}
/**
* @interface
*
* The attributes to update in a price list rule.
*/
export interface UpdatePriceListRuleDTO {
/**
* The ID of the price list rule to update.
*/
id: string
/**
* The ID of a price list to be associated with the price list rule.
*/
price_list_id?: string
/**
* The ID of a rule type to be associated with the price list rule.
*/
rule_type_id?: string
/**
* The ID of a price list to be associated with the price list rule.
*/
price_list?: string
/**
* The ID of a rule type or the details of an existing rule type to be associated with the price list rule.
*/
rule_type?: string
}
/**
* @interface
*
* The price list rule value's details.
*/
export interface PriceListRuleValueDTO {
/**
* The price list rule value's ID.
*/
id: string
/**
* The rule's value.
*/
value: string
/**
* The associated price list rule.
*
* @expandable
*/
price_list_rule: PriceListRuleDTO
}
export interface CreatePriceListRuleValueDTO {
value: string
price_list_rule_id?: string
price_list_rule?: PriceListRuleDTO | string
}
export interface UpdatePriceListRuleValueDTO {
id: string
value: string
price_list_rule_id: string
}
/**
* @interface
*
@@ -457,7 +343,7 @@ export interface SetPriceListRulesDTO {
*/
price_list_id: string
/**
* The rules to add to the price list. Each key of the object is a rule type's `rule_attribute`, and its value
* The rules to add to the price list. Each key of the object is the attribute, and its value
* is the value(s) of the rule.
*/
rules: Record<string, string | string[]>
@@ -474,7 +360,7 @@ export interface RemovePriceListRulesDTO {
*/
price_list_id: string
/**
* The rules to remove from the price list. Each item being a rule type's `rule_attribute`.
* The rules to remove from the price list. Each item being the attribute.
*/
rules: string[]
}
@@ -1,6 +1,5 @@
import { BaseFilterable } from "../../dal"
import { PriceSetDTO } from "./price-set"
import { RuleTypeDTO } from "./rule-type"
/**
* @interface
@@ -22,15 +21,9 @@ export interface PriceRuleDTO {
*/
price_set: PriceSetDTO
/**
* The ID of the associated rule type.
* The attribute of the price rule
*/
rule_type_id: string
/**
* The associated rule type.
*
* @expandable
*/
rule_type: RuleTypeDTO
attribute: string
/**
* The value of the price rule.
*/
@@ -73,9 +66,9 @@ export interface CreatePriceRuleDTO {
*/
price_set_id?: string
/**
* The ID of the associated rule type.
* The attribute of the price rule
*/
rule_type_id?: string
attribute: string
/**
* The value of the price rule.
*/
@@ -99,7 +92,10 @@ export interface CreatePriceRuleDTO {
export interface UpdatePriceRuleDTO {
id: string
price_set_id?: string
rule_type_id?: string
/**
* The attribute of the price rule
*/
attribute?: string
/**
* The value of the price rule.
*/
@@ -136,8 +132,4 @@ export interface FilterablePriceRuleProps
* The IDs to filter the price rule's associated price set.
*/
price_set_id?: string[]
/**
* The IDs to filter the price rule's associated rule type.
*/
rule_type_id?: string[]
}
@@ -1,28 +0,0 @@
import { BaseFilterable } from "../../dal"
import { PriceSetDTO } from "./price-set"
import { RuleTypeDTO } from "./rule-type"
export interface PriceSetRuleTypeDTO {
id: string
price_set: PriceSetDTO
rule_type: RuleTypeDTO
value: string
}
export interface CreatePriceSetRuleTypeDTO {
price_set_id: string
rule_type_id: string
}
export interface UpdatePriceSetRuleTypeDTO {
id: string
price_set?: string
rule_type?: string
}
export interface FilterablePriceSetRuleTypeProps
extends BaseFilterable<FilterablePriceSetRuleTypeProps> {
id?: string[]
rule_type_id?: string[]
price_set_id?: string[]
}
@@ -6,8 +6,6 @@ import {
FilterableMoneyAmountProps,
MoneyAmountDTO,
} from "./money-amount"
import { CreatePriceSetPriceRules } from "./price-list"
import { RuleTypeDTO } from "./rule-type"
export interface PricingRepositoryService {
calculatePrices(
@@ -63,11 +61,6 @@ export interface PriceSetDTO {
* The calculated price based on the context.
*/
calculated_price?: CalculatedPriceSet
/**
* The rule types applied on this price set.
*/
rule_types?: RuleTypeDTO[]
}
/**
@@ -204,23 +197,12 @@ export interface CalculatedPriceSet {
/**
* @interface
*
* The rules to add to a price set.
* The price rules to be set for each price in the price set.
*
* Each key of the object is a the attribute, and its value
* is the values of the rule.
*/
export interface AddRulesDTO {
/**
* The ID of the price set to add the rules to.
*/
priceSetId: string
/**
* The rules to add to a price set.
*/
rules: {
/**
* The value of the rule's `rule_attribute` attribute.
*/
attribute: string
}[]
}
export interface CreatePriceSetPriceRules extends Record<string, string> {}
/**
* @interface
@@ -229,7 +211,7 @@ export interface AddRulesDTO {
*/
export interface CreatePricesDTO extends CreateMoneyAmountDTO {
/**
* The rules to add to the price. The object's keys are rule types' `rule_attribute` attribute, and values are the value of that rule associated with this price.
* The rules to add to the price. The object's keys are the attribute, and values are the value of that rule associated with this price.
*/
rules?: CreatePriceSetPriceRules
}
@@ -250,37 +232,12 @@ export interface AddPricesDTO {
prices: CreatePricesDTO[]
}
/**
* @interface
*
* The rules to remove from a price set.
*/
export interface RemovePriceSetRulesDTO {
/**
* The ID of the price set.
*/
id: string
/**
* The rules to remove. Each string is the `rule_attribute` of a rule to remove.
*/
rules: string[]
}
/**
* @interface
*
* A price set to create.
*/
export interface CreatePriceSetDTO {
/**
* The rules to associate with the price set.
*/
rules?: {
/**
* the value of the rule's `rule_attribute` attribute.
*/
rule_attribute: string
}[]
/**
* The prices to create and add to this price set.
*/
@@ -306,15 +263,6 @@ export interface UpsertPriceSetDTO extends UpdatePriceSetDTO {
* The data to update in a price set.
*/
export interface UpdatePriceSetDTO {
/**
* The rules to associate with the price set.
*/
rules?: {
/**
* the value of the rule's `rule_attribute` attribute.
*/
rule_attribute: string
}[]
/**
* The prices to create and add to this price set.
*/
@@ -1,106 +0,0 @@
import { BaseFilterable } from "../../dal"
/**
* @interface
*
* A rule type's data.
*/
export interface RuleTypeDTO {
/**
* The ID of the rule type.
*/
id: string
/**
* The display name of the rule type.
*/
name: string
/**
* The unique name used to later identify the rule_attribute. For example, it can be used in the `context` parameter of
* the `calculatePrices` method to specify a rule for calculating the price.
*/
rule_attribute: string
/**
* The priority of the rule type. This is useful when calculating the price of a price set, and multiple rules satisfy
* the provided context. The higher the value, the higher the priority of the rule type.
*/
default_priority: number
/**
* The creation date of the rule type.
*/
created_at?: Date | string
/**
* The update date of the rule type.
*/
updated_at?: Date | string
}
/**
* @interface
*
* The rule type to create.
*/
export interface CreateRuleTypeDTO {
/**
* The ID of the rule type.
*/
id?: string
/**
* The display name of the rule type.
*/
name: string
/**
* The unique name used to later identify the rule_attribute. For example, it can be used in the `context` parameter of the `calculatePrices`
* method to specify a rule for calculating the price.
*/
rule_attribute: string
/**
* The priority of the rule type. This is useful when calculating the price of a price set, and multiple rules satisfy the provided context.
* The higher the value, the higher the priority of the rule type.
*/
default_priority?: number
}
/**
* @interface
*
* The data to update in a rule type. The `id` is used to identify which price set to update.
*/
export interface UpdateRuleTypeDTO {
/**
* The ID of the rule type to update.
*/
id: string
/**
* The display name of the rule type.
*/
name?: string
/**
* The unique name used to later identify the rule_attribute. For example, it can be used in the `context` parameter of the `calculatePrices` method to specify a rule for calculating the price.
*/
rule_attribute?: string
/**
* The priority of the rule type. This is useful when calculating the price of a price set, and multiple rules satisfy the provided context. The higher the value, the higher the priority of the rule type.
*/
default_priority?: number
}
/**
* @interface
*
* Filters to apply on rule types.
*/
export interface FilterableRuleTypeProps
extends BaseFilterable<FilterableRuleTypeProps> {
/**
* The IDs to filter rule types by.
*/
id?: string[]
/**
* The names to filter rule types by.
*/
name?: string[]
/**
* The rule attributes to filter rule types by.
*/
rule_attribute?: string[]
}
+4 -229
View File
@@ -9,13 +9,11 @@ import {
CreatePriceListDTO,
CreatePriceRuleDTO,
CreatePriceSetDTO,
CreateRuleTypeDTO,
FilterablePriceListProps,
FilterablePriceListRuleProps,
FilterablePriceProps,
FilterablePriceRuleProps,
FilterablePriceSetProps,
FilterableRuleTypeProps,
PriceDTO,
PriceListDTO,
PriceListRuleDTO,
@@ -24,13 +22,11 @@ import {
PricingContext,
PricingFilters,
RemovePriceListRulesDTO,
RuleTypeDTO,
SetPriceListRulesDTO,
UpdatePriceListDTO,
UpdatePriceListPricesDTO,
UpdatePriceRuleDTO,
UpdatePriceSetDTO,
UpdateRuleTypeDTO,
UpsertPriceSetDTO,
} from "./common"
@@ -284,10 +280,6 @@ export interface IPricingModuleService extends IModuleService {
*
* ```ts
* const priceSet = await pricingModuleService.createPriceSets({
* rules: [
* { rule_attribute: "region_id" },
* { rule_attribute: "city" },
* ],
* prices: [
* {
* amount: 300,
@@ -351,10 +343,6 @@ export interface IPricingModuleService extends IModuleService {
* },
* // price set with rules
* {
* rules: [
* { rule_attribute: "region_id" },
* { rule_attribute: "city" },
* ],
* prices: [
* {
* amount: 300,
@@ -404,10 +392,6 @@ export interface IPricingModuleService extends IModuleService {
* },
* ],
* },
* {
* id: "pset_123",
* rules: [{ rule_attribute: "region_id" }],
* },
* ])
*/
upsertPriceSets(
@@ -425,7 +409,7 @@ export interface IPricingModuleService extends IModuleService {
* @example
* const priceSet = await pricingModuleService.upsertPriceSets({
* id: "pset_123",
* rules: [{ rule_attribute: "region_id" }],
* prices: [{ amount: 100, currency_code: "USD" }],
* })
*/
upsertPriceSets(
@@ -445,7 +429,7 @@ export interface IPricingModuleService extends IModuleService {
* const priceSet = await pricingModuleService.updatePriceSets(
* "pset_123",
* {
* rules: [{ rule_attribute: "region_id" }],
* prices: [{ amount: 100, currency_code: "USD" }],
* }
* )
*/
@@ -469,7 +453,7 @@ export interface IPricingModuleService extends IModuleService {
* id: ["pset_123", "pset_321"],
* },
* {
* rules: [{ rule_attribute: "region_id" }],
* prices: [{ amount: 100, currency_code: "USD" }],
* }
* )
*/
@@ -593,215 +577,6 @@ export interface IPricingModuleService extends IModuleService {
sharedContext?: Context
): Promise<PriceSetDTO[]>
/**
* This method is used to retrieve a rule type by its ID and and optionally based on the provided configurations.
*
* @param {string} id - The ID of the rule type to retrieve.
* @param {FindConfig<RuleTypeDTO>} config -
* The configurations determining how the rule type is retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a rule type.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<RuleTypeDTO>} The retrieved rule type.
*
* @example
* A simple example that retrieves a rule type by its code:
*
* ```ts
* const ruleType =
* await pricingModuleService.retrieveRuleType("rul-typ_123")
* ```
*
* To specify relations that should be retrieved:
*
* ```ts
* const ruleType = await pricingModuleService.retrieveRuleType(
* "rul-typ_123",
* {
* relations: ["price_sets"],
* }
* )
* ```
*/
retrieveRuleType(
id: string,
config?: FindConfig<RuleTypeDTO>,
sharedContext?: Context
): Promise<RuleTypeDTO>
/**
* This method is used to retrieve a paginated list of rule types based on optional filters and configuration.
*
* @param {FilterableRuleTypeProps} filters - The filters to apply on the retrieved rule types.
* @param {FindConfig<RuleTypeDTO>} config -
* The configurations determining how the rule types are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a rule type.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<RuleTypeDTO[]>} The list of rule types.
*
* @example
*
* To retrieve a list of rule types using their IDs:
*
* ```ts
* const ruleTypes = await pricingModuleService.listRuleTypes({
* id: ["rul-typ_123", "rul-typ_321"],
* })
* ```
*
* To specify relations that should be retrieved:
*
* ```ts
* const ruleTypes = await pricingModuleService.listRuleTypes(
* {
* id: ["rul-typ_123", "rul-typ_321"],
* },
* {
* relations: ["price_sets"],
* }
* )
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* const ruleTypes = await pricingModuleService.listRuleTypes(
* {
* id: ["rul-typ_123", "rul-typ_321"],
* },
* {
* relations: ["price_sets"],
* take: 20,
* skip: 2,
* }
* )
* ```
*/
listRuleTypes(
filters?: FilterableRuleTypeProps,
config?: FindConfig<RuleTypeDTO>,
sharedContext?: Context
): Promise<RuleTypeDTO[]>
/**
* This method is used to retrieve a paginated list of rule types along with the total count of available rule types satisfying the provided filters.
*
* @param {FilterableRuleTypeProps} filters - The filters to apply on the retrieved rule types.
* @param {FindConfig<RuleTypeDTO>} config -
* The configurations determining how the rule types are retrieved. Its properties, such as `select` or `relations`, accept the
* attributes or relations associated with a rule type.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<[RuleTypeDTO[], number]>} The list of rule types along with their total count.
*
* @example
*
* To retrieve a list of rule types using their IDs:
*
* ```ts
* const [ruleTypes, count] =
* await pricingModuleService.listAndCountRuleTypes({
* id: ["rul-typ_123", "rul-typ_321"],
* })
* ```
*
* To specify attributes that should be retrieved within the rule types:
*
* ```ts
* const [ruleTypes, count] =
* await pricingModuleService.listAndCountRuleTypes(
* {
* id: ["rul-typ_123", "rul-typ_321"],
* },
* {
* relations: ["price_sets"],
* }
* )
* ```
*
* By default, only the first `15` records are retrieved. You can control pagination by specifying the `skip` and `take` properties of the `config` parameter:
*
* ```ts
* const [ruleTypes, count] =
* await pricingModuleService.listAndCountRuleTypes(
* {
* id: ["rul-typ_123", "rul-typ_321"],
* },
* {
* relations: ["price_sets"],
* take: 20,
* skip: 2,
* }
* )
* ```
*/
listAndCountRuleTypes(
filters?: FilterableRuleTypeProps,
config?: FindConfig<RuleTypeDTO>,
sharedContext?: Context
): Promise<[RuleTypeDTO[], number]>
/**
* This method is used to create new rule types.
*
* @param {CreateRuleTypeDTO[]} data - The rule types to create.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<RuleTypeDTO[]>} The list of created rule types.
*
* @example
* const ruleTypes = await pricingModuleService.createRuleTypes([
* {
* name: "Region",
* rule_attribute: "region_id",
* },
* {
* name: "Customer Group",
* rule_attribute: "customer_group_id",
* },
* ])
*/
createRuleTypes(
data: CreateRuleTypeDTO[],
sharedContext?: Context
): Promise<RuleTypeDTO[]>
/**
* This method is used to update existing rule types with the provided data.
*
* @param {UpdateRuleTypeDTO[]} data - The rule types to update, each having the attributes that should be updated in a rule type.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<RuleTypeDTO[]>} The list of updated rule types.
*
* @example
* const ruleTypes = await pricingModuleService.updateRuleTypes([
* {
* id: "rul-typ_123",
* name: "Region",
* },
* {
* id: "rul-typ_321",
* name: "Customer Group",
* },
* ])
*/
updateRuleTypes(
data: UpdateRuleTypeDTO[],
sharedContext?: Context
): Promise<RuleTypeDTO[]>
/**
* This method is used to delete rule types based on the provided IDs.
*
* @param {string[]} ruleTypeIds - The IDs of the rule types to delete.
* @param {Context} sharedContext - A context used to share resources, such as transaction manager, between the application and the module.
* @returns {Promise<void>} Resolves once the rule types are deleted.
*
* @example
* const ruleTypes = await pricingModuleService.deleteRuleTypes([
* "rul-typ_123",
* "rul-typ_321",
* ])
*/
deleteRuleTypes(ruleTypeIds: string[], sharedContext?: Context): Promise<void>
/**
* This method is used to retrieve a paginated list of prices based on optional filters and configuration.
*
@@ -1119,7 +894,7 @@ export interface IPricingModuleService extends IModuleService {
* await pricingModuleService.createPriceRules([
* {
* value: "VIP",
* rule_type_id: "rul-typ_123",
* attribute: "customer_group",
* price_set_id: "pset_123",
* },
* ])
@@ -8,7 +8,6 @@ export interface CreatePriceListDTO {
starts_at?: string
ends_at?: string
status?: PriceListStatus
rules_count?: number
rules?: PriceListRuleDTO[]
prices?: {
amount: number
@@ -23,7 +22,7 @@ export interface CreatePriceListDTO {
}
export interface CreatePriceListRuleDTO {
rule_attribute: string
attribute: string
value: string[]
}
@@ -1,17 +0,0 @@
import { getInvalidRuleAttributes } from ".."
describe("getInvalidRuleAttributes", function () {
it("should return list of rule attributes that matches reserved keywords", function () {
let result = getInvalidRuleAttributes(["shouldnotmatch"])
expect(result).toEqual([])
result = getInvalidRuleAttributes(["currency_code", "shouldnotmatch"])
expect(result).toEqual(["currency_code"])
result = getInvalidRuleAttributes(["currency_code", "price_list_id"])
expect(result).toEqual(["currency_code", "price_list_id"])
result = getInvalidRuleAttributes(["shouldnotmatch", "quantity"])
expect(result).toEqual(["quantity"])
})
})
@@ -1,28 +0,0 @@
import { validateRuleAttributes } from ".."
describe("validateRuleAttributes", function () {
it("should return void if there are no validation errors", function () {
let result = validateRuleAttributes(["shouldpasswithouterrors"])
expect(result).toEqual(undefined)
})
it("should throw an error if one of the array strings matches a reserved keyword", function () {
let error
try {
validateRuleAttributes([
"currency_code",
"shouldnotbepresent",
"quantity",
"price_list_id",
])
} catch (e) {
error = e
}
expect(error.message).toEqual(
"Can't create rule_attribute with reserved keywords [quantity, currency_code, price_list_id] - quantity, currency_code, price_list_id"
)
})
})
+4 -6
View File
@@ -10,11 +10,10 @@ export function buildPriceListRules(
priceListRules?: PriceListRuleDTO[]
): Record<string, string[]> | undefined {
return priceListRules?.reduce((acc, curr) => {
const ruleAttribute = curr.rule_type.rule_attribute
const ruleValues = curr.price_list_rule_values || []
acc[ruleAttribute] = ruleValues.map((ruleValue) => ruleValue.value)
const ruleAttribute = curr.attribute
const ruleValues = curr.value || []
acc[ruleAttribute] = ruleValues
return acc
}, {})
}
@@ -27,11 +26,10 @@ export function buildPriceSetRules(
}
return priceRules?.reduce((acc, curr) => {
const ruleAttribute = curr.rule_type.rule_attribute
const ruleAttribute = curr.attribute
const ruleValue = curr.value
acc[ruleAttribute] = ruleValue
return acc
}, {})
}
+2 -14
View File
@@ -2,24 +2,12 @@ import { buildEventNamesFromEntityName } from "../event-bus"
import { Modules } from "../modules-sdk"
const eventBaseNames: [
"priceListRuleValue",
"priceListRule",
"priceList",
"priceRule",
"priceSetRuleType",
"priceSet",
"price",
"ruleType"
] = [
"priceListRuleValue",
"priceListRule",
"priceList",
"priceRule",
"priceSetRuleType",
"priceSet",
"price",
"ruleType",
]
"price"
] = ["priceListRule", "priceList", "priceRule", "priceSet", "price"]
export const PricingEvents = buildEventNamesFromEntityName(
eventBaseNames,
-1
View File
@@ -1,4 +1,3 @@
export * from "./builders"
export * from "./price-list"
export * from "./rule-type"
export * from "./events"
@@ -1,38 +0,0 @@
import { MedusaError } from "../common"
type RuleAttributeInput = string | undefined
export const ReservedPricingRuleAttributes = [
"quantity",
"currency_code",
"price_list_id",
]
export const getInvalidRuleAttributes = (
ruleAttributes: RuleAttributeInput[]
): string[] => {
const invalidRuleAttributes: string[] = []
for (const attribute of ReservedPricingRuleAttributes) {
if (ruleAttributes.indexOf(attribute) > -1) {
invalidRuleAttributes.push(attribute)
}
}
return invalidRuleAttributes
}
export const validateRuleAttributes = (
ruleAttributes: RuleAttributeInput[]
): void => {
const invalidRuleAttributes = getInvalidRuleAttributes(ruleAttributes)
if (invalidRuleAttributes.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Can't create rule_attribute with reserved keywords [${ReservedPricingRuleAttributes.join(
", "
)}] - ${invalidRuleAttributes.join(", ")}`
)
}
}