* initial * initial service * update pricing module service * add integration test for rule-type * update pricing-module integration tests * update pricing service interface * feat(pricing): PriceSets as entry point to pricing module * chore: add price set money amount * chore: add price set money amount * chore: change name of test * chore: added changeset * chore: use filterable props from money amount in price sets * chore: update migrations * test update integration test * fix weird behavior * Update packages/pricing/integration-tests/__fixtures__/rule-type/index.ts Co-authored-by: Riqwan Thamir <rmthamir@gmail.com> * Apply suggestions from code review Co-authored-by: Riqwan Thamir <rmthamir@gmail.com> * move rule-type to common * chore: reset migration * chore: remove incorrect conflicts * chore: address review * chore: remove ghost price list * Apply suggestions from code review Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> * update id prefix * use persist not persistAndflush * rename key_value to rule_attribute * more renaming --------- Co-authored-by: Riqwan Thamir <rmthamir@gmail.com> Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
524 lines
14 KiB
TypeScript
524 lines
14 KiB
TypeScript
import {
|
|
Context,
|
|
DAL,
|
|
FindConfig,
|
|
InternalModuleDeclaration,
|
|
ModuleJoinerConfig,
|
|
PricingContext,
|
|
PricingFilters,
|
|
PricingTypes,
|
|
} from "@medusajs/types"
|
|
import { Currency, MoneyAmount, PriceSet, RuleType } from "@models"
|
|
import {
|
|
CurrencyService,
|
|
MoneyAmountService,
|
|
PriceSetService,
|
|
RuleTypeService,
|
|
} from "@services"
|
|
|
|
import {
|
|
InjectManager,
|
|
InjectTransactionManager,
|
|
MedusaContext,
|
|
shouldForceTransaction,
|
|
} from "@medusajs/utils"
|
|
|
|
import { joinerConfig } from "../joiner-config"
|
|
|
|
type InjectedDependencies = {
|
|
baseRepository: DAL.RepositoryService
|
|
currencyService: CurrencyService<any>
|
|
moneyAmountService: MoneyAmountService<any>
|
|
ruleTypeService: RuleTypeService<any>
|
|
priceSetService: PriceSetService<any>
|
|
}
|
|
|
|
export default class PricingModuleService<
|
|
TPriceSet extends PriceSet = PriceSet,
|
|
TMoneyAmount extends MoneyAmount = MoneyAmount,
|
|
TCurrency extends Currency = Currency,
|
|
TRuleType extends RuleType = RuleType
|
|
> implements PricingTypes.IPricingModuleService
|
|
{
|
|
protected baseRepository_: DAL.RepositoryService
|
|
protected readonly currencyService_: CurrencyService<TCurrency>
|
|
protected readonly moneyAmountService_: MoneyAmountService<TMoneyAmount>
|
|
protected readonly ruleTypeService_: RuleTypeService<TRuleType>
|
|
protected readonly priceSetService_: PriceSetService<TPriceSet>
|
|
|
|
constructor(
|
|
{
|
|
baseRepository,
|
|
moneyAmountService,
|
|
currencyService,
|
|
ruleTypeService,
|
|
priceSetService,
|
|
}: InjectedDependencies,
|
|
protected readonly moduleDeclaration: InternalModuleDeclaration
|
|
) {
|
|
this.baseRepository_ = baseRepository
|
|
this.currencyService_ = currencyService
|
|
this.moneyAmountService_ = moneyAmountService
|
|
this.ruleTypeService_ = ruleTypeService
|
|
this.priceSetService_ = priceSetService
|
|
}
|
|
|
|
__joinerConfig(): ModuleJoinerConfig {
|
|
return joinerConfig
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async calculatePrices(
|
|
pricingFilters: PricingFilters,
|
|
pricingContext: PricingContext = { context: {} },
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.CalculatedPriceSetDTO> {
|
|
// Keeping this whole logic raw in here for now as they will undergo
|
|
// some changes, will abstract them out once we have a final version
|
|
const context = pricingContext.context || {}
|
|
const priceSetFilters: PricingTypes.FilterablePriceSetProps = {
|
|
id: pricingFilters.id,
|
|
}
|
|
|
|
const priceSets = await this.list(
|
|
priceSetFilters,
|
|
{
|
|
select: [
|
|
"id",
|
|
"money_amounts.id",
|
|
"money_amounts.currency_code",
|
|
"money_amounts.amount",
|
|
"money_amounts.min_quantity",
|
|
"money_amounts.max_quantity",
|
|
],
|
|
relations: ["money_amounts"],
|
|
},
|
|
sharedContext
|
|
)
|
|
|
|
const calculatedPrices = priceSets.map(
|
|
(priceSet): PricingTypes.CalculatedPriceSetDTO => {
|
|
// TODO: This will change with the rules engine selection,
|
|
// making a DB query directly instead
|
|
// This should look for a default price when no rules apply
|
|
// When no price is set, return null values for all cases
|
|
const selectedMoneyAmount = priceSet.money_amounts?.find(
|
|
(ma) =>
|
|
context.currency_code && ma.currency_code === context.currency_code
|
|
)
|
|
|
|
return {
|
|
id: priceSet.id,
|
|
amount: selectedMoneyAmount?.amount || null,
|
|
currency_code: selectedMoneyAmount?.currency_code || null,
|
|
min_quantity: selectedMoneyAmount?.min_quantity || null,
|
|
max_quantity: selectedMoneyAmount?.max_quantity || null,
|
|
}
|
|
}
|
|
)
|
|
|
|
return JSON.parse(JSON.stringify(calculatedPrices))
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async retrieve(
|
|
id: string,
|
|
config: FindConfig<PricingTypes.PriceSetDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.PriceSetDTO> {
|
|
const priceSet = await this.priceSetService_.retrieve(
|
|
id,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.PriceSetDTO>(priceSet, {
|
|
populate: true,
|
|
})
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async list(
|
|
filters: PricingTypes.FilterablePriceSetProps = {},
|
|
config: FindConfig<PricingTypes.PriceSetDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.PriceSetDTO[]> {
|
|
const priceSets = await this.priceSetService_.list(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.PriceSetDTO[]>(
|
|
priceSets,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listAndCount(
|
|
filters: PricingTypes.FilterablePriceSetProps = {},
|
|
config: FindConfig<PricingTypes.PriceSetDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<[PricingTypes.PriceSetDTO[], number]> {
|
|
const [priceSets, count] = await this.priceSetService_.listAndCount(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return [
|
|
await this.baseRepository_.serialize<PricingTypes.PriceSetDTO[]>(
|
|
priceSets,
|
|
{
|
|
populate: true,
|
|
}
|
|
),
|
|
count,
|
|
]
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async create(
|
|
data: PricingTypes.CreatePriceSetDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const priceSets = await this.priceSetService_.create(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.PriceSetDTO[]>(
|
|
priceSets,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async update(
|
|
data: PricingTypes.UpdatePriceSetDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const priceSets = await this.priceSetService_.update(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.PriceSetDTO[]>(
|
|
priceSets,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async delete(
|
|
ids: string[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
await this.priceSetService_.delete(ids, sharedContext)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async retrieveMoneyAmount(
|
|
id: string,
|
|
config: FindConfig<PricingTypes.MoneyAmountDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.MoneyAmountDTO> {
|
|
const moneyAmount = await this.moneyAmountService_.retrieve(
|
|
id,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.MoneyAmountDTO>(
|
|
moneyAmount,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listMoneyAmounts(
|
|
filters: PricingTypes.FilterableMoneyAmountProps = {},
|
|
config: FindConfig<PricingTypes.MoneyAmountDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.MoneyAmountDTO[]> {
|
|
const moneyAmounts = await this.moneyAmountService_.list(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.MoneyAmountDTO[]>(
|
|
moneyAmounts,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listAndCountMoneyAmounts(
|
|
filters: PricingTypes.FilterableMoneyAmountProps = {},
|
|
config: FindConfig<PricingTypes.MoneyAmountDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<[PricingTypes.MoneyAmountDTO[], number]> {
|
|
const [moneyAmounts, count] = await this.moneyAmountService_.listAndCount(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return [
|
|
await this.baseRepository_.serialize<PricingTypes.MoneyAmountDTO[]>(
|
|
moneyAmounts,
|
|
{
|
|
populate: true,
|
|
}
|
|
),
|
|
count,
|
|
]
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async createMoneyAmounts(
|
|
data: PricingTypes.CreateMoneyAmountDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const moneyAmounts = await this.moneyAmountService_.create(
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.MoneyAmountDTO[]>(
|
|
moneyAmounts,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async updateMoneyAmounts(
|
|
data: PricingTypes.UpdateMoneyAmountDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const moneyAmounts = await this.moneyAmountService_.update(
|
|
data,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.MoneyAmountDTO[]>(
|
|
moneyAmounts,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async deleteMoneyAmounts(
|
|
ids: string[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
await this.moneyAmountService_.delete(ids, sharedContext)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async retrieveCurrency(
|
|
code: string,
|
|
config: FindConfig<PricingTypes.CurrencyDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.CurrencyDTO> {
|
|
const currency = await this.currencyService_.retrieve(
|
|
code,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.CurrencyDTO>(currency, {
|
|
populate: true,
|
|
})
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listCurrencies(
|
|
filters: PricingTypes.FilterableCurrencyProps = {},
|
|
config: FindConfig<PricingTypes.CurrencyDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.CurrencyDTO[]> {
|
|
const currencies = await this.currencyService_.list(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
|
|
currencies,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listAndCountCurrencies(
|
|
filters: PricingTypes.FilterableCurrencyProps = {},
|
|
config: FindConfig<PricingTypes.CurrencyDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<[PricingTypes.CurrencyDTO[], number]> {
|
|
const [currencies, count] = await this.currencyService_.listAndCount(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return [
|
|
await this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
|
|
currencies,
|
|
{
|
|
populate: true,
|
|
}
|
|
),
|
|
count,
|
|
]
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async createCurrencies(
|
|
data: PricingTypes.CreateCurrencyDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const currencies = await this.currencyService_.create(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
|
|
currencies,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async updateCurrencies(
|
|
data: PricingTypes.UpdateCurrencyDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
) {
|
|
const currencies = await this.currencyService_.update(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.CurrencyDTO[]>(
|
|
currencies,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async deleteCurrencies(
|
|
currencyCodes: string[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
await this.currencyService_.delete(currencyCodes, sharedContext)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async retrieveRuleType(
|
|
id: string,
|
|
config: FindConfig<PricingTypes.RuleTypeDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.RuleTypeDTO> {
|
|
const ruleType = await this.ruleTypeService_.retrieve(
|
|
id,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.RuleTypeDTO>(ruleType, {
|
|
populate: true,
|
|
})
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listRuleTypes(
|
|
filters: PricingTypes.FilterableRuleTypeProps = {},
|
|
config: FindConfig<PricingTypes.RuleTypeDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.RuleTypeDTO[]> {
|
|
const ruleTypes = await this.ruleTypeService_.list(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.RuleTypeDTO[]>(
|
|
ruleTypes,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectManager("baseRepository_")
|
|
async listAndCountRuleTypes(
|
|
filters: PricingTypes.FilterableRuleTypeProps = {},
|
|
config: FindConfig<PricingTypes.RuleTypeDTO> = {},
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<[PricingTypes.RuleTypeDTO[], number]> {
|
|
const [ruleTypes, count] = await this.ruleTypeService_.listAndCount(
|
|
filters,
|
|
config,
|
|
sharedContext
|
|
)
|
|
|
|
return [
|
|
await this.baseRepository_.serialize<PricingTypes.RuleTypeDTO[]>(
|
|
ruleTypes,
|
|
{
|
|
populate: true,
|
|
}
|
|
),
|
|
count,
|
|
]
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async createRuleTypes(
|
|
data: PricingTypes.CreateRuleTypeDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.RuleTypeDTO[]> {
|
|
const ruleTypes = await this.ruleTypeService_.create(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.RuleTypeDTO[]>(
|
|
ruleTypes,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async updateRuleTypes(
|
|
data: PricingTypes.UpdateRuleTypeDTO[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<PricingTypes.RuleTypeDTO[]> {
|
|
const ruleTypes = await this.ruleTypeService_.update(data, sharedContext)
|
|
|
|
return this.baseRepository_.serialize<PricingTypes.RuleTypeDTO[]>(
|
|
ruleTypes,
|
|
{
|
|
populate: true,
|
|
}
|
|
)
|
|
}
|
|
|
|
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
|
|
async deleteRuleTypes(
|
|
ruleTypes: string[],
|
|
@MedusaContext() sharedContext: Context = {}
|
|
): Promise<void> {
|
|
await this.ruleTypeService_.delete(ruleTypes, sharedContext)
|
|
}
|
|
}
|