feat(product, pricing, utils): Transaction issues and reference issues (#5533)

* feat(product, pricing, utils): Transaction issues and reference issues

* fixes decorators

* cleanup

* fix product module upsert

* fix missing active manager

* increase timeout

* revert package.json

* WIP

* try another node version based on findings with memory issues with jest introduced after 16.11 but fixed in 21

* re add bail

* fix variant options

* chore: bulk create pricing

* chore: workflow bulk

* Create big-chefs-dream.md

* fix missing update for upserty

* Add integration tests for product options upsert

* rm unnecessary return

* fix product prices workflow issue

* cleanup

* fix flag

* fix model

---------

Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
Co-authored-by: Carlos R. L. Rodrigues <rodrigolr@gmail.com>
Co-authored-by: Riqwan Thamir <rmthamir@gmail.com>
This commit is contained in:
Adrien de Peretti
2023-11-06 12:24:29 +01:00
committed by GitHub
parent 57c3a24ad3
commit f88d75b0a7
47 changed files with 624 additions and 475 deletions

View File

@@ -0,0 +1,6 @@
---
"@medusajs/pricing": patch
"@medusajs/product": patch
---
feat(product, pricing, utils): Transaction issues and reference issues + refactoring

View File

@@ -5,7 +5,7 @@ inputs:
node-version:
description: "Node version"
required: false
default: "16.20.2"
default: "16.10.0"
cache-extension:
description: "Extension for fetching cached dependencies"
required: true

View File

@@ -17,7 +17,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Assert changed
@@ -48,7 +48,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Assert changed
@@ -171,7 +171,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies
@@ -223,7 +223,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies
@@ -275,7 +275,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -25,7 +25,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -24,7 +24,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -22,7 +22,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -23,7 +23,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -26,7 +26,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies
@@ -89,7 +89,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -22,7 +22,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Install dependencies

View File

@@ -20,7 +20,7 @@ jobs:
- name: Setup Node.js environment
uses: actions/setup-node@v3
with:
node-version: "16.20.2"
node-version: "16.10.0"
cache: "yarn"
- name: Post to Slack channel

View File

@@ -54,6 +54,7 @@ module.exports = {
const shutdown = async () => {
await Promise.all([
container.dispose(),
expressServer.close(),
db?.destroy(),
pgConnection?.context?.destroy(),

View File

@@ -22,7 +22,7 @@ const env = {
MEDUSA_FF_ISOLATE_PRODUCT_DOMAIN: true,
}
describe.skip("[Product & Pricing Module] POST /admin/products", () => {
describe("[Product & Pricing Module] POST /admin/products", () => {
let dbConnection
let appContainer
let shutdownServer

View File

@@ -26,7 +26,7 @@ const env = {
MEDUSA_FF_ISOLATE_PRODUCT_DOMAIN: true,
}
describe.skip("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () => {
describe("[Product & Pricing Module] POST /admin/products/:id/variants/:id", () => {
let dbConnection
let appContainer
let shutdownServer

View File

@@ -24,7 +24,7 @@ const env = {
MEDUSA_FF_ISOLATE_PRODUCT_DOMAIN: true,
}
describe.skip("[Product & Pricing Module] POST /admin/products/:id", () => {
describe("[Product & Pricing Module] POST /admin/products/:id", () => {
let dbConnection
let appContainer
let shutdownServer
@@ -172,9 +172,7 @@ describe.skip("[Product & Pricing Module] POST /admin/products/:id", () => {
],
}
console.log("I am here first")
await api.post(`/admin/products/${product.id}`, data, adminHeaders)
console.log("I am here")
const response = await api.get(
`/admin/products/${product.id}`,

View File

@@ -12,7 +12,7 @@ import { getContainer } from "../../../../environment-helpers/use-container"
import { initDb, useDb } from "../../../../environment-helpers/use-db"
import { simpleProductFactory } from "../../../../factories"
jest.setTimeout(30000)
jest.setTimeout(100000)
describe("UpdateProduct workflow", function () {
let dbConnection

View File

@@ -9,7 +9,7 @@ module.exports = {
`/www/`,
`/dist/`,
`/node_modules/`,
"<rootDir>/node_modules",
`<rootDir>/node_modules/`,
`__tests__/fixtures`,
`__testfixtures__`,
`.cache`,

View File

@@ -5,7 +5,7 @@
"license": "MIT",
"private": true,
"scripts": {
"test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --logHeapUsage --forceExit",
"test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --detectOpenHandles --logHeapUsage --clearMocks --no-compilation-cache --forceExit",
"build": "babel src -d dist --extensions \".ts,.js\""
},
"dependencies": {

View File

@@ -27,7 +27,7 @@ export class PricingRepository
pricingContext: PricingContext = { context: {} },
sharedContext: Context = {}
): Promise<CalculatedPriceSetDTO[]> {
const manager = this.getActiveManager<SqlEntityManager>()
const manager = this.getActiveManager<SqlEntityManager>(sharedContext)
const knex = manager.getKnex()
const context = pricingContext.context || {}

View File

@@ -9,8 +9,6 @@ import {
import { Currency } from "@models"
import { CurrencyRepository } from "@repositories"
import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils"
type InjectedDependencies = {
currencyRepository: DAL.RepositoryService
}
@@ -75,7 +73,7 @@ export default class CurrencyService<TEntity extends Currency = Currency> {
return queryOptions
}
@InjectTransactionManager(shouldForceTransaction, "currencyRepository_")
@InjectTransactionManager("currencyRepository_")
async create(
data: PricingTypes.CreateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -86,7 +84,7 @@ export default class CurrencyService<TEntity extends Currency = Currency> {
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "currencyRepository_")
@InjectTransactionManager("currencyRepository_")
async update(
data: PricingTypes.UpdateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -97,7 +95,7 @@ export default class CurrencyService<TEntity extends Currency = Currency> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "currencyRepository_")
@InjectTransactionManager("currencyRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -9,8 +9,6 @@ import {
import { MoneyAmount } from "@models"
import { MoneyAmountRepository } from "@repositories"
import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils"
type InjectedDependencies = {
moneyAmountRepository: DAL.RepositoryService
}
@@ -73,7 +71,7 @@ export default class MoneyAmountService<
)) as [TEntity[], number]
}
@InjectTransactionManager(shouldForceTransaction, "moneyAmountRepository_")
@InjectTransactionManager("moneyAmountRepository_")
async create(
data: PricingTypes.CreateMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -84,7 +82,7 @@ export default class MoneyAmountService<
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "moneyAmountRepository_")
@InjectTransactionManager("moneyAmountRepository_")
async update(
data: PricingTypes.UpdateMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -95,7 +93,7 @@ export default class MoneyAmountService<
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "moneyAmountRepository_")
@InjectTransactionManager("moneyAmountRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -4,9 +4,7 @@ import {
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
doNotForceTransaction,
retrieveEntity,
shouldForceTransaction,
} from "@medusajs/utils"
import { PriceRule } from "@models"
import { PriceRuleRepository } from "@repositories"
@@ -65,7 +63,7 @@ export default class PriceRuleService<TEntity extends PriceRule = PriceRule> {
)) as [TEntity[], number]
}
@InjectTransactionManager(shouldForceTransaction, "priceRuleRepository_")
@InjectTransactionManager("priceRuleRepository_")
async create(
data: PricingTypes.CreatePriceRuleDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -76,7 +74,7 @@ export default class PriceRuleService<TEntity extends PriceRule = PriceRule> {
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "priceRuleRepository_")
@InjectTransactionManager("priceRuleRepository_")
async update(
data: PricingTypes.UpdatePriceRuleDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -87,7 +85,7 @@ export default class PriceRuleService<TEntity extends PriceRule = PriceRule> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "priceRuleRepository_")
@InjectTransactionManager("priceRuleRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -8,8 +8,6 @@ import {
} from "@medusajs/utils"
import { PriceSetMoneyAmountRules } from "@models"
import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils"
type InjectedDependencies = {
priceSetMoneyAmountRulesRepository: DAL.RepositoryService
}
@@ -79,10 +77,7 @@ export default class PriceSetMoneyAmountRulesService<
return queryOptions
}
@InjectTransactionManager(
shouldForceTransaction,
"priceSetMoneyAmountRulesRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRulesRepository_")
async create(
data: PricingTypes.CreatePriceSetMoneyAmountRulesDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -93,10 +88,7 @@ export default class PriceSetMoneyAmountRulesService<
)) as TEntity[]
}
@InjectTransactionManager(
shouldForceTransaction,
"priceSetMoneyAmountRulesRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRulesRepository_")
async update(
data: PricingTypes.UpdatePriceSetMoneyAmountRulesDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -107,10 +99,7 @@ export default class PriceSetMoneyAmountRulesService<
)) as TEntity[]
}
@InjectTransactionManager(
doNotForceTransaction,
"priceSetMoneyAmountRulesRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRulesRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -1,12 +1,11 @@
import { Context, DAL, FindConfig, PricingTypes } from "@medusajs/types"
import {
doNotForceTransaction,
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
doNotForceTransaction,
retrieveEntity,
shouldForceTransaction,
} from "@medusajs/utils"
import { PriceSet, PriceSetMoneyAmount } from "@models"
import { PriceSetMoneyAmountRepository } from "@repositories"
@@ -79,36 +78,29 @@ export default class PriceSetMoneyAmountService<
return queryOptions
}
@InjectTransactionManager(
shouldForceTransaction,
"priceSetMoneyAmountRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRepository_")
async create(
data: PricingTypes.CreatePriceSetMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (
this.priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository
this
.priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository
).create(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(
shouldForceTransaction,
"priceSetMoneyAmountRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRepository_")
async update(
data: PricingTypes.UpdatePriceSetMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (
this.priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository
this
.priceSetMoneyAmountRepository_ as unknown as PriceSetMoneyAmountRepository
).update(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(
doNotForceTransaction,
"priceSetMoneyAmountRepository_"
)
@InjectTransactionManager("priceSetMoneyAmountRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -4,9 +4,7 @@ import {
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
doNotForceTransaction,
retrieveEntity,
shouldForceTransaction,
} from "@medusajs/utils"
import { PriceSet, PriceSetRuleType } from "@models"
import { PriceSetRuleTypeRepository } from "src/repositories/price-set-rule-type"
@@ -15,7 +13,9 @@ type InjectedDependencies = {
priceSetRuleTypeRepository: DAL.RepositoryService
}
export default class PriceSetRuleTypeService<TEntity extends PriceSetRuleType = PriceSetRuleType> {
export default class PriceSetRuleTypeService<
TEntity extends PriceSetRuleType = PriceSetRuleType
> {
protected readonly priceSetRuleTypeRepository_: DAL.RepositoryService
constructor({ priceSetRuleTypeRepository }: InjectedDependencies) {
@@ -28,7 +28,10 @@ export default class PriceSetRuleTypeService<TEntity extends PriceSetRuleType =
config: FindConfig<PricingTypes.PriceSetRuleTypeDTO> = {},
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity> {
return (await retrieveEntity<PriceSetRuleType, PricingTypes.PriceSetRuleTypeDTO>({
return (await retrieveEntity<
PriceSetRuleType,
PricingTypes.PriceSetRuleTypeDTO
>({
id: priceSetId,
entityName: PriceSet.name,
repository: this.priceSetRuleTypeRepository_,
@@ -74,29 +77,27 @@ export default class PriceSetRuleTypeService<TEntity extends PriceSetRuleType =
return queryOptions
}
@InjectTransactionManager(shouldForceTransaction, "priceSetRuleTypeRepository_")
@InjectTransactionManager("priceSetRuleTypeRepository_")
async create(
data: PricingTypes.CreatePriceSetRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository).create(
data,
sharedContext
)) as TEntity[]
return (await (
this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository
).create(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "priceSetRuleTypeRepository_")
@InjectTransactionManager("priceSetRuleTypeRepository_")
async update(
data: PricingTypes.UpdatePriceSetRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository).update(
data,
sharedContext
)) as TEntity[]
return (await (
this.priceSetRuleTypeRepository_ as PriceSetRuleTypeRepository
).update(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "priceSetRuleTypeRepository_")
@InjectTransactionManager("priceSetRuleTypeRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -4,9 +4,7 @@ import {
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
doNotForceTransaction,
retrieveEntity,
shouldForceTransaction,
} from "@medusajs/utils"
import { PriceSet } from "@models"
import { PriceSetRepository } from "@repositories"
@@ -65,7 +63,7 @@ export default class PriceSetService<TEntity extends PriceSet = PriceSet> {
)) as [TEntity[], number]
}
@InjectTransactionManager(shouldForceTransaction, "priceSetRepository_")
@InjectTransactionManager("priceSetRepository_")
async create(
data: Omit<PricingTypes.CreatePriceSetDTO, "rules">[],
@MedusaContext() sharedContext: Context = {}
@@ -76,7 +74,7 @@ export default class PriceSetService<TEntity extends PriceSet = PriceSet> {
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "priceSetRepository_")
@InjectTransactionManager("priceSetRepository_")
async update(
data: Omit<PricingTypes.UpdatePriceSetDTO, "rules">[],
@MedusaContext() sharedContext: Context = {}
@@ -87,7 +85,7 @@ export default class PriceSetService<TEntity extends PriceSet = PriceSet> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "priceSetRepository_")
@InjectTransactionManager("priceSetRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -1,4 +1,5 @@
import {
AddPricesDTO,
Context,
CreateMoneyAmountDTO,
DAL,
@@ -35,16 +36,13 @@ import {
} from "@services"
import {
groupBy,
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
groupBy,
removeNullish,
shouldForceTransaction,
} from "@medusajs/utils"
import { AddPricesDTO } from "@medusajs/types"
import { joinerConfig } from "../joiner-config"
import { PricingRepositoryService } from "../types"
@@ -231,7 +229,8 @@ export default class PricingModuleService<
{ id: priceSets.filter((p) => !!p).map((p) => p!.id) },
{
relations: ["rule_types", "money_amounts", "price_rules"],
}
},
sharedContext
)
return (Array.isArray(data) ? dbPriceSets : dbPriceSets[0]) as unknown as
@@ -239,7 +238,7 @@ export default class PricingModuleService<
| PriceSetDTO[]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async create_(
data: PricingTypes.CreatePriceSetDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -286,74 +285,89 @@ export default class PricingModuleService<
)
}
const priceSets = await Promise.all(
data.map(async (d) => {
const { rules, prices, ...rest } = d
const [priceSet] = await this.priceSetService_.create(
[rest],
sharedContext
)
if (rules?.length) {
const priceSetRuleTypesCreate = rules!.map((r) => ({
rule_type: ruleTypeMap.get(r.rule_attribute),
price_set: priceSet,
}))
await this.priceSetRuleTypeService_.create(
priceSetRuleTypesCreate as unknown as PricingTypes.CreatePriceSetRuleTypeDTO[],
sharedContext
)
}
if (prices?.length) {
for (const ma of prices) {
const [moneyAmount] = await this.moneyAmountService_.create(
[ma] as unknown as CreateMoneyAmountDTO[],
sharedContext
)
const cleanRules = ma.rules ? removeNullish(ma.rules) : {}
const numberOfRules = Object.entries(cleanRules).length
const [priceSetMoneyAmount] =
await this.priceSetMoneyAmountService_.create(
[
{
price_set: priceSet,
money_amount: moneyAmount,
title: "test",
number_rules: numberOfRules,
},
] as unknown as PricingTypes.CreatePriceSetMoneyAmountDTO[],
sharedContext
)
if (numberOfRules) {
const priceSetRulesCreate = Object.entries(cleanRules).map(
([k, v]) => ({
price_set_money_amount: priceSetMoneyAmount,
rule_type: ruleTypeMap.get(k),
price_set: priceSet,
value: v,
price_list_id: "test",
})
)
await this.priceRuleService_.create(
priceSetRulesCreate as unknown as PricingTypes.CreatePriceRuleDTO[],
sharedContext
)
}
}
}
return priceSet
})
// Bulk create price sets
const priceSetData = data.map(({ rules, prices, ...rest }) => rest)
const createdPriceSets = await this.priceSetService_.create(
priceSetData,
sharedContext
)
return priceSets
// Price set rule types
const ruleTypeData = data.flatMap(
(item, index) =>
item.rules?.map((rule) => ({
rule_type: ruleTypeMap.get(rule.rule_attribute),
price_set: createdPriceSets[index],
})) || []
)
if (ruleTypeData.length > 0) {
await this.priceSetRuleTypeService_.create(
ruleTypeData as unknown as PricingTypes.CreatePriceSetRuleTypeDTO[],
sharedContext
)
}
// Money amounts
const moneyAmountData = data.flatMap((item) => item.prices || [])
const createdMoneyAmounts = await this.moneyAmountService_.create(
moneyAmountData,
sharedContext
)
let moneyAmountIndex = 0
const priceSetMoneyAmountData: unknown[] = []
const priceRulesData: unknown[] = []
for (const [index, item] of data.entries()) {
for (const ma of item.prices || []) {
const cleanRules = ma.rules ? removeNullish(ma.rules) : {}
const numberOfRules = Object.entries(cleanRules).length
const priceSetMoneyAmount = {
price_set: createdPriceSets[index],
money_amount: createdMoneyAmounts[moneyAmountIndex++],
title: "test", // TODO: accept title
number_rules: numberOfRules,
}
priceSetMoneyAmountData.push(priceSetMoneyAmount)
for (const [k, v] of Object.entries(cleanRules)) {
priceRulesData.push({
price_set_money_amount: null, // Updated later
rule_type: ruleTypeMap.get(k),
price_set: createdPriceSets[index],
value: v,
price_list_id: "test",
})
}
}
}
// Bulk create price set money amounts
const createdPriceSetMoneyAmounts =
await this.priceSetMoneyAmountService_.create(
priceSetMoneyAmountData as PricingTypes.CreatePriceSetMoneyAmountDTO[],
sharedContext
)
// Update price set money amount references
for (let i = 0, j = 0; i < priceSetMoneyAmountData.length; i++) {
const rulesCount = (priceSetMoneyAmountData[i] as any).number_rules
for (let k = 0; k < rulesCount; k++, j++) {
;(priceRulesData[j] as any).price_set_money_amount =
createdPriceSetMoneyAmounts[i]
}
}
// Price rules
if (priceRulesData.length > 0) {
await this.priceRuleService_.create(
priceRulesData as PricingTypes.CreatePriceRuleDTO[],
sharedContext
)
}
return createdPriceSets
}
async addRules(
@@ -380,14 +394,15 @@ export default class PricingModuleService<
| PricingTypes.PriceSetDTO
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async addRules_(
inputs: PricingTypes.AddRulesDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<PricingTypes.PriceSetDTO[]> {
const priceSets = await this.priceSetService_.list(
{ id: inputs.map((d) => d.priceSetId) },
{ relations: ["rule_types"] }
{ relations: ["rule_types"] },
sharedContext
)
const priceSetRuleTypeMap: Map<string, Map<string, RuleTypeDTO>> = new Map(
@@ -491,11 +506,12 @@ export default class PricingModuleService<
return (await this.list(
{ id: input.map((d) => d.priceSetId) },
{ relations: ["money_amounts"] }
{ relations: ["money_amounts"] },
sharedContext
)) as unknown as PricingTypes.PriceSetDTO[] | PricingTypes.PriceSetDTO
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async addPrices_(
input: AddPricesDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -543,73 +559,93 @@ export default class PricingModuleService<
}
})
for (const { priceSetId, prices } of input) {
await Promise.all(
prices.map(async (ma) => {
const [moneyAmount] = await this.moneyAmountService_.create(
[ma] as unknown as CreateMoneyAmountDTO[],
sharedContext
)
// Money amounts
const moneyAmountsBulkData = input.flatMap((entry) => entry.prices)
const createdMoneyAmounts = await this.moneyAmountService_.create(
moneyAmountsBulkData as unknown as CreateMoneyAmountDTO[],
sharedContext
)
const numberOfRules = Object.entries(ma?.rules ?? {}).length
const [priceSetMoneyAmount] =
await this.priceSetMoneyAmountService_.create(
[
{
price_set: priceSetId,
money_amount: moneyAmount,
title: "test",
number_rules: numberOfRules,
},
] as unknown as PricingTypes.CreatePriceSetMoneyAmountDTO[],
sharedContext
)
if (numberOfRules) {
const priceSetRulesCreate = Object.entries(ma.rules!).map(
([k, v]) => ({
price_set_money_amount: priceSetMoneyAmount,
rule_type: ruleTypeMap.get(priceSetId)!.get(k),
price_set: priceSetId,
value: v,
price_list_id: "test",
})
)
await this.priceRuleService_.create(
priceSetRulesCreate as unknown as PricingTypes.CreatePriceRuleDTO[],
sharedContext
)
// Price set money amounts
let maCursor = 0
const priceSetMoneyAmountsBulkData = input.flatMap(
({ priceSetId, prices }) =>
prices.map(() => {
const ma = createdMoneyAmounts[maCursor]
const numberOfRules = Object.entries(
prices[maCursor]?.rules ?? {}
).length
maCursor++
return {
price_set: priceSetId,
money_amount: ma,
title: "test", // TODO: accept title
number_rules: numberOfRules,
}
return moneyAmount
})
)
const createdPriceSetMoneyAmounts =
await this.priceSetMoneyAmountService_.create(
priceSetMoneyAmountsBulkData as unknown as PricingTypes.CreatePriceSetMoneyAmountDTO[],
sharedContext
)
// Price rules
let rulesCursor = 0
const priceRulesBulkData = input.flatMap(({ priceSetId, prices }) =>
prices.flatMap((ma) => {
const rules = ma.rules ?? {}
const priceSetMoneyAmount = createdPriceSetMoneyAmounts[rulesCursor]
rulesCursor++
return Object.entries(rules).map(([k, v]) => ({
price_set_money_amount: priceSetMoneyAmount,
rule_type: ruleTypeMap.get(priceSetId)!.get(k),
price_set: priceSetId,
value: v,
price_list_id: "test", // TODO: accept title
}))
})
)
if (priceRulesBulkData.length > 0) {
await this.priceRuleService_.create(
priceRulesBulkData as unknown as PricingTypes.CreatePriceRuleDTO[],
sharedContext
)
}
return priceSets
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async removeRules(
data: PricingTypes.RemovePriceSetRulesDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
const priceSets = await this.priceSetService_.list({
id: data.map((d) => d.id),
})
const priceSets = await this.priceSetService_.list(
{
id: data.map((d) => d.id),
},
undefined,
sharedContext
)
const priceSetIds = priceSets.map((ps) => ps.id)
const ruleTypes = await this.ruleTypeService_.list({
rule_attribute: data.map((d) => d.rules || []).flat(),
})
const ruleTypes = await this.ruleTypeService_.list(
{
rule_attribute: data.map((d) => d.rules || []).flat(),
},
undefined,
sharedContext
)
const ruleTypeIds = ruleTypes.map((rt) => rt.id)
const priceSetRuleTypes = await this.priceSetRuleTypeService_.list({
price_set_id: priceSetIds,
rule_type_id: ruleTypeIds,
})
const priceSetRuleTypes = await this.priceSetRuleTypeService_.list(
{
price_set_id: priceSetIds,
rule_type_id: ruleTypeIds,
},
undefined,
sharedContext
)
const priceRules = await this.priceRuleService_.list(
{
@@ -618,7 +654,8 @@ export default class PricingModuleService<
},
{
select: ["price_set_money_amount"],
}
},
sharedContext
)
await this.priceSetRuleTypeService_.delete(
@@ -632,7 +669,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async update(
data: PricingTypes.UpdatePriceSetDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -647,7 +684,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -718,7 +755,7 @@ export default class PricingModuleService<
]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createMoneyAmounts(
data: PricingTypes.CreateMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -736,7 +773,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateMoneyAmounts(
data: PricingTypes.UpdateMoneyAmountDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -754,7 +791,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteMoneyAmounts(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -822,7 +859,7 @@ export default class PricingModuleService<
]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createCurrencies(
data: PricingTypes.CreateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -837,7 +874,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateCurrencies(
data: PricingTypes.UpdateCurrencyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -852,7 +889,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteCurrencies(
currencyCodes: string[],
@MedusaContext() sharedContext: Context = {}
@@ -920,7 +957,7 @@ export default class PricingModuleService<
]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createRuleTypes(
data: PricingTypes.CreateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -935,7 +972,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateRuleTypes(
data: PricingTypes.UpdateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -950,7 +987,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteRuleTypes(
ruleTypeIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -1062,7 +1099,7 @@ export default class PricingModuleService<
]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createPriceSetMoneyAmountRules(
data: PricingTypes.CreatePriceSetMoneyAmountRulesDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -1079,7 +1116,7 @@ export default class PricingModuleService<
})
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updatePriceSetMoneyAmountRules(
data: PricingTypes.UpdatePriceSetMoneyAmountRulesDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -1096,7 +1133,7 @@ export default class PricingModuleService<
})
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deletePriceSetMoneyAmountRules(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -1167,7 +1204,7 @@ export default class PricingModuleService<
]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createPriceRules(
data: PricingTypes.CreatePriceRuleDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -1182,7 +1219,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updatePriceRules(
data: PricingTypes.UpdatePriceRuleDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -1197,7 +1234,7 @@ export default class PricingModuleService<
)
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deletePriceRules(
priceRuleIds: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -8,8 +8,6 @@ import {
} from "@medusajs/utils"
import { RuleType } from "@models"
import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils"
type InjectedDependencies = {
ruleTypeRepository: DAL.RepositoryService
}
@@ -65,7 +63,7 @@ export default class RuleTypeService<TEntity extends RuleType = RuleType> {
)) as [TEntity[], number]
}
@InjectTransactionManager(shouldForceTransaction, "ruleTypeRepository_")
@InjectTransactionManager("ruleTypeRepository_")
async create(
data: PricingTypes.CreateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -76,7 +74,7 @@ export default class RuleTypeService<TEntity extends RuleType = RuleType> {
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "ruleTypeRepository_")
@InjectTransactionManager("ruleTypeRepository_")
async update(
data: PricingTypes.UpdateRuleTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -87,7 +85,7 @@ export default class RuleTypeService<TEntity extends RuleType = RuleType> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "ruleTypeRepository_")
@InjectTransactionManager("ruleTypeRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -69,11 +69,6 @@ describe("ProductModuleService product collections", () => {
productCollectionOne = productCollections[0]
productCollectionTwo = productCollections[1]
await testManager.persistAndFlush([
productCollectionOne,
productCollectionTwo,
])
})
afterEach(async () => {
@@ -339,16 +334,17 @@ describe("ProductModuleService product collections", () => {
relations: ["products"],
})
expect(productCollection.products).toHaveLength(2)
expect(productCollection).toEqual(
expect.objectContaining({
products: [
products: expect.arrayContaining([
expect.objectContaining({
id: productOne.id,
}),
expect.objectContaining({
id: productTwo.id,
}),
],
]),
})
)
})

View File

@@ -121,7 +121,9 @@ describe("ProductOption Service", () => {
})
it("should return product option and count when filtered", async () => {
const [optionResults, count] = await service.listAndCount({ id: "option-2" })
const [optionResults, count] = await service.listAndCount({
id: "option-2",
})
expect(count).toEqual(1)
expect(optionResults).toEqual([
@@ -132,7 +134,10 @@ describe("ProductOption Service", () => {
})
it("should return product option and count when using skip and take", async () => {
const [optionResults, count] = await service.listAndCount({}, { skip: 1, take: 1 })
const [optionResults, count] = await service.listAndCount(
{},
{ skip: 1, take: 1 }
)
expect(count).toEqual(2)
expect(optionResults).toEqual([
@@ -143,10 +148,13 @@ describe("ProductOption Service", () => {
})
it("should return requested fields", async () => {
const [optionResults, count] = await service.listAndCount({}, {
take: 1,
select: ["title"],
})
const [optionResults, count] = await service.listAndCount(
{},
{
take: 1,
select: ["title"],
}
)
const serialized = JSON.parse(JSON.stringify(optionResults))
@@ -164,13 +172,11 @@ describe("ProductOption Service", () => {
const optionValue = "Option 1"
it("should return option for the given id", async () => {
const option = await service.retrieve(
optionId,
)
const option = await service.retrieve(optionId)
expect(option).toEqual(
expect.objectContaining({
id: optionId
id: optionId,
})
)
})
@@ -184,7 +190,9 @@ describe("ProductOption Service", () => {
error = e
}
expect(error.message).toEqual('ProductOption with id: does-not-exist was not found')
expect(error.message).toEqual(
"ProductOption with id: does-not-exist was not found"
)
})
it("should throw an error when an id is not provided", async () => {
@@ -200,21 +208,16 @@ describe("ProductOption Service", () => {
})
it("should return option based on config select param", async () => {
const option = await service.retrieve(
optionId,
{
select: ["id", "title"],
}
)
const option = await service.retrieve(optionId, {
select: ["id", "title"],
})
const serialized = JSON.parse(JSON.stringify(option))
expect(serialized).toEqual(
{
id: optionId,
title: optionValue,
}
)
expect(serialized).toEqual({
id: optionId,
title: optionValue,
})
})
})
@@ -222,13 +225,10 @@ describe("ProductOption Service", () => {
const optionId = "option-1"
it("should delete the product option given an ID successfully", async () => {
await service.delete(
[optionId],
)
await service.delete([optionId])
const options = await service.list({
id: optionId
id: optionId,
})
expect(options).toHaveLength(0)
@@ -239,12 +239,12 @@ describe("ProductOption Service", () => {
const optionId = "option-1"
it("should update the title of the option successfully", async () => {
await service.update(
[{
await service.update([
{
id: optionId,
title: "UK",
}]
)
},
])
const productOption = await service.retrieve(optionId)
@@ -252,23 +252,23 @@ describe("ProductOption Service", () => {
})
it("should update the relationship of the option successfully", async () => {
await service.update(
[{
await service.update([
{
id: optionId,
product_id: productTwo.id,
}]
)
},
])
const productOption = await service.retrieve(optionId, {
relations: ["product"]
relations: ["product"],
})
expect(productOption).toEqual(
expect.objectContaining({
id: optionId,
product: expect.objectContaining({
id: productTwo.id
})
id: productTwo.id,
}),
})
)
})
@@ -278,43 +278,98 @@ describe("ProductOption Service", () => {
try {
await service.update([
{
id: "does-not-exist",
title: "UK",
}
])
{
id: "does-not-exist",
title: "UK",
},
])
} catch (e) {
error = e
}
expect(error.message).toEqual('ProductOption with id "does-not-exist" not found')
expect(error.message).toEqual(
'ProductOption with id "does-not-exist" not found'
)
})
})
describe("create", () => {
it("should create a option successfully", async () => {
await service.create(
[{
await service.create([
{
title: "UK",
product: productOne
}]
product: productOne,
},
])
const [productOption] = await service.list(
{
title: "UK",
},
{
relations: ["product"],
}
)
const [productOption] = await service.list({
title: "UK"
}, {
relations: ["product"],
})
expect(productOption).toEqual(
expect.objectContaining({
title: "UK",
product: expect.objectContaining({
id: productOne.id
})
id: productOne.id,
}),
})
)
})
})
describe("upsert", function () {
it("should create an option and update another option successfully", async () => {
const productOption = (
await service.create([
{
title: "UK",
product: productOne,
},
])
)[0]
const optionToUpdate = {
id: productOption.id,
title: "US",
}
const newOption = {
title: "US2",
product_id: productOne.id,
}
await service.upsert([optionToUpdate, newOption])
const productOptions = await service.list(
{
title: "US%",
},
{
relations: ["product"],
}
)
expect(JSON.parse(JSON.stringify(productOptions))).toEqual(
expect.arrayContaining([
expect.objectContaining({
title: "US",
product: expect.objectContaining({
id: productOne.id,
}),
}),
expect.objectContaining({
title: newOption.title,
product: expect.objectContaining({
id: productOne.id,
}),
}),
])
)
})
})
})

View File

@@ -1,9 +1,9 @@
import { Context, DAL, ProductTypes } from "@medusajs/types"
import { DALUtils, MedusaError } from "@medusajs/utils"
import {
LoadStrategy,
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
} from "@mikro-orm/core"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { ProductCollection } from "@models"
@@ -31,8 +31,7 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository
findOptions: DAL.FindOptions<ProductCollection> = { where: {} },
context: Context = {}
): Promise<ProductCollection[]> {
const manager = (context.transactionManager ??
this.manager_) as SqlEntityManager
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}
@@ -52,8 +51,7 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository
findOptions: DAL.FindOptions<ProductCollection> = { where: {} },
context: Context = {}
): Promise<[ProductCollection[], number]> {
const manager = (context.transactionManager ??
this.manager_) as SqlEntityManager
const manager = this.getActiveManager<SqlEntityManager>(context)
const findOptions_ = { ...findOptions }
findOptions_.options ??= {}

View File

@@ -1,9 +1,9 @@
import { Context, DAL, ProductTypes } from "@medusajs/types"
import { DALUtils, MedusaError } from "@medusajs/utils"
import {
LoadStrategy,
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
} from "@mikro-orm/core"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { Product, ProductOption } from "@models"
@@ -149,4 +149,62 @@ export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseReposi
return productOptions
}
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
context: Context = {}
): Promise<ProductOption[]> {
const manager = this.getActiveManager<SqlEntityManager>(context)
const optionIds = data.map((optionData) => optionData.id).filter((o) => o)
let existingOptions
let existingOptionsMap = new Map()
if (optionIds.length) {
existingOptions = await this.find(
{
where: {
id: {
$in: optionIds,
},
},
},
context
)
existingOptionsMap = new Map(
existingOptions.map((option) => [option.id, option])
)
}
const upsertedOptions: ProductOption[] = []
const optionsToCreate: ProductOption[] = []
const optionsToUpdate: ProductOption[] = []
data.forEach((option) => {
const existingOption = existingOptionsMap.get(option.id)
if (existingOption) {
const updatedOption = manager.assign(existingOption, option)
optionsToUpdate.push(updatedOption)
} else {
const newOption = manager.create(ProductOption, option)
optionsToCreate.push(newOption)
}
})
if (optionsToCreate.length) {
manager.persist(optionsToCreate)
upsertedOptions.push(...optionsToCreate)
}
if (optionsToUpdate.length) {
manager.persist(optionsToUpdate)
upsertedOptions.push(...optionsToUpdate)
}
return upsertedOptions
}
}

View File

@@ -2,7 +2,6 @@ import {
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
RequiredEntityData,
} from "@mikro-orm/core"
import { ProductTag } from "@models"
import {
@@ -141,26 +140,28 @@ export class ProductTagRepository extends DALUtils.MikroOrmBaseRepository {
)
const upsertedTags: ProductTag[] = []
const tagsToCreate: RequiredEntityData<ProductTag>[] = []
const tagsToCreate: ProductTag[] = []
const tagsToUpdate: ProductTag[] = []
tags.forEach((tag) => {
const aTag = existingTagsMap.get(tag.value)
if (aTag) {
upsertedTags.push(aTag)
const updatedTag = manager.assign(aTag, tag)
tagsToUpdate.push(updatedTag)
} else {
const newTag = (manager as SqlEntityManager).create(ProductTag, tag)
const newTag = manager.create(ProductTag, tag)
tagsToCreate.push(newTag)
}
})
if (tagsToCreate.length) {
const newTags: ProductTag[] = []
tagsToCreate.forEach((tag) => {
newTags.push((manager as SqlEntityManager).create(ProductTag, tag))
})
manager.persist(tagsToCreate)
upsertedTags.push(...tagsToCreate)
}
manager.persist(newTags)
upsertedTags.push(...newTags)
if (tagsToUpdate.length) {
manager.persist(tagsToUpdate)
upsertedTags.push(...tagsToUpdate)
}
return upsertedTags

View File

@@ -2,7 +2,6 @@ import {
FilterQuery as MikroFilterQuery,
FindOptions as MikroOptions,
LoadStrategy,
RequiredEntityData,
} from "@mikro-orm/core"
import { ProductType } from "@models"
import {
@@ -87,26 +86,28 @@ export class ProductTypeRepository extends DALUtils.MikroOrmBaseRepository {
)
const upsertedTypes: ProductType[] = []
const typesToCreate: RequiredEntityData<ProductType>[] = []
const typesToCreate: ProductType[] = []
const typesToUpdate: ProductType[] = []
types.forEach((type) => {
const aType = existingTypesMap.get(type.value)
if (aType) {
upsertedTypes.push(aType)
const updatedType = manager.assign(aType, type)
typesToUpdate.push(updatedType)
} else {
const newType = (manager as SqlEntityManager).create(ProductType, type)
const newType = manager.create(ProductType, type)
typesToCreate.push(newType)
}
})
if (typesToCreate.length) {
const newTypes: ProductType[] = []
typesToCreate.forEach((type) => {
newTypes.push((manager as SqlEntityManager).create(ProductType, type))
})
manager.persist(typesToCreate)
upsertedTypes.push(...typesToCreate)
}
manager.persist(newTypes)
upsertedTypes.push(...newTypes)
if (typesToUpdate.length) {
manager.persist(typesToUpdate)
upsertedTypes.push(...typesToUpdate)
}
return upsertedTypes

View File

@@ -9,8 +9,6 @@ import {
MedusaError,
ModulesSdkUtils,
} from "@medusajs/utils"
import { shouldForceTransaction } from "../utils"
import { ProductCategoryServiceTypes } from "../types"
type InjectedDependencies = {
@@ -114,10 +112,7 @@ export default class ProductCategoryService<
)) as [TEntity[], number]
}
@InjectTransactionManager(
shouldForceTransaction,
"productCategoryRepository_"
)
@InjectTransactionManager("productCategoryRepository_")
async create(
data: ProductCategoryServiceTypes.CreateProductCategoryDTO,
@MedusaContext() sharedContext: Context = {}
@@ -127,10 +122,7 @@ export default class ProductCategoryService<
).create(data, sharedContext)) as TEntity
}
@InjectTransactionManager(
shouldForceTransaction,
"productCategoryRepository_"
)
@InjectTransactionManager("productCategoryRepository_")
async update(
id: string,
data: ProductCategoryServiceTypes.UpdateProductCategoryDTO,
@@ -141,10 +133,7 @@ export default class ProductCategoryService<
).update(id, data, sharedContext)) as TEntity
}
@InjectTransactionManager(
shouldForceTransaction,
"productCategoryRepository_"
)
@InjectTransactionManager("productCategoryRepository_")
async delete(
id: string,
@MedusaContext() sharedContext: Context = {}

View File

@@ -6,8 +6,6 @@ import {
ModulesSdkUtils,
retrieveEntity,
} from "@medusajs/utils"
import { shouldForceTransaction } from "../utils"
import { ProductCollectionRepository } from "../repositories"
import { ProductCollection } from "@models"
@@ -85,10 +83,7 @@ export default class ProductCollectionService<
return queryOptions
}
@InjectTransactionManager(
shouldForceTransaction,
"productCollectionRepository_"
)
@InjectTransactionManager("productCollectionRepository_")
async create(
data: ProductTypes.CreateProductCollectionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -98,10 +93,7 @@ export default class ProductCollectionService<
).create(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(
shouldForceTransaction,
"productCollectionRepository_"
)
@InjectTransactionManager("productCollectionRepository_")
async update(
data: ProductTypes.UpdateProductCollectionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -111,10 +103,7 @@ export default class ProductCollectionService<
).update(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(
shouldForceTransaction,
"productCollectionRepository_"
)
@InjectTransactionManager("productCollectionRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -1,7 +1,6 @@
import { Image } from "@models"
import { Context, DAL } from "@medusajs/types"
import { InjectTransactionManager, MedusaContext } from "@medusajs/utils"
import { doNotForceTransaction } from "../utils"
import { ProductImageRepository } from "@repositories"
type InjectedDependencies = {
@@ -15,7 +14,7 @@ export default class ProductImageService<TEntity extends Image = Image> {
this.productImageRepository_ = productImageRepository
}
@InjectTransactionManager(doNotForceTransaction, "productImageRepository_")
@InjectTransactionManager("productImageRepository_")
async upsert(
urls: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -62,8 +62,6 @@ import {
MedusaContext,
MedusaError,
} from "@medusajs/utils"
import { shouldForceTransaction } from "../utils"
import {
entityNameToLinkableKeysMap,
joinerConfig,
@@ -277,7 +275,7 @@ export default class ProductModuleService<
return [JSON.parse(JSON.stringify(tags)), count]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createTags(
data: ProductTypes.CreateProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -290,7 +288,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productTags))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateTags(
data: ProductTypes.UpdateProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -303,7 +301,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productTags))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteTags(
productTagIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -356,7 +354,7 @@ export default class ProductModuleService<
return [JSON.parse(JSON.stringify(types)), count]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createTypes(
data: ProductTypes.CreateProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -369,7 +367,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productTypes))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateTypes(
data: ProductTypes.UpdateProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -382,7 +380,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productTypes))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteTypes(
productTypeIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -436,7 +434,7 @@ export default class ProductModuleService<
return [JSON.parse(JSON.stringify(productOptions)), count]
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createOptions(
data: ProductTypes.CreateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -453,7 +451,7 @@ export default class ProductModuleService<
})
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateOptions(
data: ProductTypes.UpdateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -470,7 +468,7 @@ export default class ProductModuleService<
})
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteOptions(
productOptionIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -523,7 +521,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(collections))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createCollections(
data: ProductTypes.CreateProductCollectionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -543,7 +541,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productCollections))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateCollections(
data: ProductTypes.UpdateProductCollectionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -563,7 +561,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productCollections))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteCollections(
productCollectionIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -611,7 +609,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(categories))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async createCategory(
data: CreateProductCategoryDTO,
@MedusaContext() sharedContext: Context = {}
@@ -629,7 +627,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productCategory))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async updateCategory(
categoryId: string,
data: UpdateProductCategoryDTO,
@@ -649,7 +647,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(productCategory))
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async deleteCategory(
categoryId: string,
@MedusaContext() sharedContext: Context = {}
@@ -677,6 +675,7 @@ export default class ProductModuleService<
return JSON.parse(JSON.stringify(categories))
}
@InjectManager("baseRepository_")
async create(
data: ProductTypes.CreateProductDTO[],
sharedContext?: Context
@@ -698,6 +697,7 @@ export default class ProductModuleService<
return createdProducts
}
@InjectManager("baseRepository_")
async update(
data: ProductTypes.UpdateProductDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -720,7 +720,7 @@ export default class ProductModuleService<
return updatedProducts
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async create_(
data: ProductTypes.CreateProductDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -829,7 +829,7 @@ export default class ProductModuleService<
return products
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async update_(
data: ProductTypes.UpdateProductDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -859,14 +859,11 @@ export default class ProductModuleService<
)[]
>()
const productOptionsMap = new Map<
string,
ProductTypes.CreateProductOptionDTO[]
>()
const productOptionsMap = new Map<string, TProductOption[]>()
const productsData = await Promise.all(
data.map(async (product) => {
const { variants, options, ...productData } = product
const { variants, ...productData } = product
if (!isDefined(productData.id)) {
throw new MedusaError(
@@ -876,7 +873,6 @@ export default class ProductModuleService<
}
productVariantsMap.set(productData.id, variants ?? [])
productOptionsMap.set(productData.id, options ?? [])
if (productData.is_giftcard) {
productData.discountable = false
@@ -894,6 +890,15 @@ export default class ProductModuleService<
productData,
sharedContext
)
await this.upsertAndAssignOptionsToProductData(
productData,
sharedContext
)
productOptionsMap.set(
productData.id,
(productData.options ?? []) as TProductOption[]
)
return productData as UpdateProductDTO
})
@@ -908,20 +913,6 @@ export default class ProductModuleService<
products.map((product) => [product.id, product])
)
const productOptionsData = [...productOptionsMap]
.map(([id, options]) =>
options.map((option) => ({
...option,
product: productByIdMap.get(id)!,
}))
)
.flat()
const productOptions = await this.productOptionService_.create(
productOptionsData,
sharedContext
)
const productVariantIdsToDelete: string[] = []
const productVariantsToCreateMap = new Map<
string,
@@ -937,6 +928,7 @@ export default class ProductModuleService<
const variantsToCreate: ProductTypes.CreateProductVariantDTO[] = []
const variantsToUpdate: ProductTypes.UpdateProductVariantDTO[] = []
const existingVariants = existingProductVariantsMap.get(productId)
const productOptions = productOptionsMap.get(productId)!
variants.forEach((variant) => {
const isVariantIdDefined = "id" in variant && isDefined(variant.id)
@@ -955,7 +947,7 @@ export default class ProductModuleService<
}
})
if (variantOptions) {
if (variantOptions?.length) {
variant.options = variantOptions
}
})
@@ -1010,6 +1002,18 @@ export default class ProductModuleService<
return products
}
protected async upsertAndAssignOptionsToProductData(
productData: ProductTypes.CreateProductDTO | ProductTypes.UpdateProductDTO,
sharedContext: Context = {}
) {
if (productData.options?.length) {
productData.options = await this.productOptionService_.upsert(
productData.options,
sharedContext
)
}
}
protected async upsertAndAssignImagesToProductData(
productData: ProductTypes.CreateProductDTO | ProductTypes.UpdateProductDTO,
sharedContext: Context = {}
@@ -1060,7 +1064,7 @@ export default class ProductModuleService<
}
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async delete(
productIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -1075,6 +1079,7 @@ export default class ProductModuleService<
)
}
@InjectManager("baseRepository_")
async softDelete<
TReturnableLinkableKeys extends string = Lowercase<
keyof typeof LinkableKeys
@@ -1116,7 +1121,7 @@ export default class ProductModuleService<
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
protected async softDelete_(
productIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -1124,6 +1129,7 @@ export default class ProductModuleService<
return await this.productService_.softDelete(productIds, sharedContext)
}
@InjectManager("baseRepository_")
async restore<
TReturnableLinkableKeys extends string = Lowercase<
keyof typeof LinkableKeys
@@ -1152,7 +1158,7 @@ export default class ProductModuleService<
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
}
@InjectManager("baseRepository_")
@InjectTransactionManager("baseRepository_")
async restoreVariants<
TReturnableLinkableKeys extends string = Lowercase<
keyof typeof LinkableKeys
@@ -1179,7 +1185,7 @@ export default class ProductModuleService<
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
}
@InjectTransactionManager(shouldForceTransaction, "baseRepository_")
@InjectTransactionManager("baseRepository_")
async restore_(
productIds: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -2,15 +2,13 @@ import { ProductOption } from "@models"
import { Context, DAL, FindConfig, ProductTypes } from "@medusajs/types"
import { ProductOptionRepository } from "@repositories"
import {
InjectTransactionManager,
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
retrieveEntity,
} from "@medusajs/utils"
import { doNotForceTransaction, shouldForceTransaction } from "../utils"
type InjectedDependencies = {
productOptionRepository: DAL.RepositoryService
}
@@ -80,7 +78,7 @@ export default class ProductOptionService<
return queryOptions
}
@InjectTransactionManager(shouldForceTransaction, "productOptionRepository_")
@InjectTransactionManager("productOptionRepository_")
async create(
data: ProductTypes.CreateProductOptionOnlyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -92,7 +90,7 @@ export default class ProductOptionService<
})) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "productOptionRepository_")
@InjectTransactionManager("productOptionRepository_")
async update(
data: ProductTypes.UpdateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -102,11 +100,22 @@ export default class ProductOptionService<
).update(data, sharedContext)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productOptionRepository_")
@InjectTransactionManager("productOptionRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
): Promise<void> {
return await this.productOptionRepository_.delete(ids, sharedContext)
}
@InjectTransactionManager("productOptionRepository_")
async upsert(
data:
| ProductTypes.CreateProductOptionDTO[]
| ProductTypes.UpdateProductOptionDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise<TEntity[]> {
return (await (this.productOptionRepository_ as ProductOptionRepository)
.upsert!(data, sharedContext)) as TEntity[]
}
}

View File

@@ -2,22 +2,22 @@ import { ProductTag } from "@models"
import {
Context,
CreateProductTagDTO,
UpdateProductTagDTO,
UpsertProductTagDTO,
DAL,
FindConfig,
ProductTypes,
UpdateProductTagDTO,
UpsertProductTagDTO,
} from "@medusajs/types"
import {
InjectTransactionManager,
InjectManager,
InjectTransactionManager,
MedusaContext,
ModulesSdkUtils,
retrieveEntity,
} from "@medusajs/utils"
import { ProductTagRepository } from "@repositories"
import { doNotForceTransaction, shouldForceTransaction } from "../utils"
import { shouldForceTransaction } from "../utils"
type InjectedDependencies = {
productTagRepository: DAL.RepositoryService
@@ -84,7 +84,7 @@ export default class ProductTagService<
return queryOptions
}
@InjectTransactionManager(shouldForceTransaction, "productTagRepository_")
@InjectTransactionManager("productTagRepository_")
async create(
data: CreateProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -95,7 +95,7 @@ export default class ProductTagService<
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "productTagRepository_")
@InjectTransactionManager("productTagRepository_")
async update(
data: UpdateProductTagDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -106,7 +106,7 @@ export default class ProductTagService<
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productTagRepository_")
@InjectTransactionManager("productTagRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -114,7 +114,7 @@ export default class ProductTagService<
await this.productTagRepository_.delete(ids, sharedContext)
}
@InjectTransactionManager(doNotForceTransaction, "productTagRepository_")
@InjectTransactionManager("productTagRepository_")
async upsert(
data: UpsertProductTagDTO[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -2,11 +2,11 @@ import { ProductType } from "@models"
import {
Context,
CreateProductTypeDTO,
UpsertProductTypeDTO,
UpdateProductTypeDTO,
DAL,
FindConfig,
ProductTypes,
UpdateProductTypeDTO,
UpsertProductTypeDTO,
} from "@medusajs/types"
import { ProductTypeRepository } from "@repositories"
import {
@@ -17,7 +17,7 @@ import {
retrieveEntity,
} from "@medusajs/utils"
import { doNotForceTransaction, shouldForceTransaction } from "../utils"
import { shouldForceTransaction } from "../utils"
type InjectedDependencies = {
productTypeRepository: DAL.RepositoryService
@@ -87,7 +87,7 @@ export default class ProductTypeService<
return queryOptions
}
@InjectTransactionManager(doNotForceTransaction, "productTypeRepository_")
@InjectTransactionManager("productTypeRepository_")
async upsert(
types: UpsertProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -96,7 +96,7 @@ export default class ProductTypeService<
.upsert!(types, sharedContext)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "productTypeRepository_")
@InjectTransactionManager("productTypeRepository_")
async create(
data: CreateProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -107,7 +107,7 @@ export default class ProductTypeService<
)) as TEntity[]
}
@InjectTransactionManager(shouldForceTransaction, "productTypeRepository_")
@InjectTransactionManager("productTypeRepository_")
async update(
data: UpdateProductTypeDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -118,7 +118,7 @@ export default class ProductTypeService<
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productTypeRepository_")
@InjectTransactionManager("productTypeRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -12,7 +12,6 @@ import {
import { ProductVariantServiceTypes } from "../types/services"
import ProductService from "./product"
import { doNotForceTransaction } from "../utils"
type InjectedDependencies = {
productVariantRepository: DAL.RepositoryService
@@ -86,7 +85,7 @@ export default class ProductVariantService<
)) as [TEntity[], number]
}
@InjectTransactionManager(doNotForceTransaction, "productVariantRepository_")
@InjectTransactionManager("productVariantRepository_")
async create(
productOrId: TProduct | string,
data: ProductTypes.CreateProductVariantOnlyDTO[],
@@ -119,7 +118,7 @@ export default class ProductVariantService<
})) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productVariantRepository_")
@InjectTransactionManager("productVariantRepository_")
async update(
productOrId: TProduct | string,
data: ProductVariantServiceTypes.UpdateProductVariantDTO[],
@@ -145,7 +144,7 @@ export default class ProductVariantService<
})) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productVariantRepository_")
@InjectTransactionManager("productVariantRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -155,7 +154,7 @@ export default class ProductVariantService<
})
}
@InjectTransactionManager(doNotForceTransaction, "productVariantRepository_")
@InjectTransactionManager("productVariantRepository_")
async softDelete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -165,7 +164,7 @@ export default class ProductVariantService<
})
}
@InjectTransactionManager(doNotForceTransaction, "productVariantRepository_")
@InjectTransactionManager("productVariantRepository_")
async restore(
ids: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -8,17 +8,16 @@ import {
import {
InjectManager,
InjectTransactionManager,
isDefined,
MedusaContext,
MedusaError,
ModulesSdkUtils,
ProductUtils,
isDefined,
} from "@medusajs/utils"
import { Product } from "@models"
import { ProductRepository } from "@repositories"
import { ProductServiceTypes } from "../types/services"
import { doNotForceTransaction } from "../utils"
type InjectedDependencies = {
productRepository: DAL.RepositoryService
@@ -118,7 +117,7 @@ export default class ProductService<TEntity extends Product = Product> {
)) as [TEntity[], number]
}
@InjectTransactionManager(doNotForceTransaction, "productRepository_")
@InjectTransactionManager("productRepository_")
async create(
data: ProductTypes.CreateProductOnlyDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -138,7 +137,7 @@ export default class ProductService<TEntity extends Product = Product> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productRepository_")
@InjectTransactionManager("productRepository_")
async update(
data: ProductServiceTypes.UpdateProductDTO[],
@MedusaContext() sharedContext: Context = {}
@@ -154,7 +153,7 @@ export default class ProductService<TEntity extends Product = Product> {
)) as TEntity[]
}
@InjectTransactionManager(doNotForceTransaction, "productRepository_")
@InjectTransactionManager("productRepository_")
async delete(
ids: string[],
@MedusaContext() sharedContext: Context = {}
@@ -164,7 +163,7 @@ export default class ProductService<TEntity extends Product = Product> {
})
}
@InjectTransactionManager(doNotForceTransaction, "productRepository_")
@InjectTransactionManager("productRepository_")
async softDelete(
productIds: string[],
@MedusaContext() sharedContext: Context = {}
@@ -174,7 +173,7 @@ export default class ProductService<TEntity extends Product = Product> {
})
}
@InjectTransactionManager(doNotForceTransaction, "productRepository_")
@InjectTransactionManager("productRepository_")
async restore(
productIds: string[],
@MedusaContext() sharedContext: Context = {}

View File

@@ -1,7 +1,5 @@
import { MODULE_RESOURCE_TYPE } from "@medusajs/types"
export function shouldForceTransaction(target: any): boolean {
return target.moduleDeclaration?.resources === MODULE_RESOURCE_TYPE.ISOLATED
export function shouldForceTransaction(): boolean {
return true
}
export function doNotForceTransaction(): boolean {

View File

@@ -28,9 +28,12 @@ export async function transactionWrapper<TManager = unknown>(
Object.assign(options, { isolationLevel })
}
const freshManager = this.getFreshManager
? this.getFreshManager()
: this.manager_
const transactionMethod =
this.manager_.transaction ?? this.manager_.transactional
return await transactionMethod.bind(this.manager_)(task, options)
freshManager.transaction ?? freshManager.transactional
return await transactionMethod.bind(freshManager)(task, options)
}
/**

View File

@@ -16,13 +16,12 @@ export function InjectManager(managerProperty?: string): MethodDecorator {
const argIndex = target.MedusaContextIndex_[propertyKey]
descriptor.value = function (...args: any[]) {
const context: SharedContext | Context = args[argIndex] ?? {}
const resourceWithManager = (!managerProperty
const context: SharedContext | Context = { ...(args[argIndex] ?? {}) }
const resourceWithManager = !managerProperty
? this
: this[managerProperty])
: this[managerProperty]
context.manager =
context.manager ?? resourceWithManager.getFreshManager()
context.manager = context.manager ?? resourceWithManager.getFreshManager()
args[argIndex] = context
return originalMethod.apply(this, args)

View File

@@ -1,7 +1,10 @@
import { Context, SharedContext } from "@medusajs/types"
import { isString } from "../../common"
export function InjectTransactionManager(
shouldForceTransaction: (target: any) => boolean = () => false,
shouldForceTransactionOrManagerProperty:
| string
| ((target: any) => boolean) = () => false,
managerProperty?: string
): MethodDecorator {
return function (
@@ -16,6 +19,14 @@ export function InjectTransactionManager(
}
const originalMethod = descriptor.value
const shouldForceTransaction = !isString(
shouldForceTransactionOrManagerProperty
)
? shouldForceTransactionOrManagerProperty
: () => false
managerProperty = isString(shouldForceTransactionOrManagerProperty)
? shouldForceTransactionOrManagerProperty
: managerProperty
const argIndex = target.MedusaContextIndex_[propertyKey]
descriptor.value = async function (...args: any[]) {
@@ -31,7 +42,7 @@ export function InjectTransactionManager(
: this[managerProperty]
).transaction(
async (transactionManager) => {
args[argIndex] = args[argIndex] ?? {}
args[argIndex] = { ...(args[argIndex] ?? {}) }
args[argIndex].transactionManager = transactionManager
return await originalMethod.apply(this, args)

View File

@@ -2,6 +2,7 @@ import { ProductTypes, WorkflowTypes } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import { WorkflowArguments } from "../../helper"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
type ProductHandle = string
type VariantIndexAndPrices = {
@@ -37,6 +38,8 @@ export async function updateProductsVariantsPrices({
products.map((p) => [p.handle!, p])
)
const regionIds = new Set()
for (const mapData of productsHandleVariantsIndexPricesMap.entries()) {
const [handle, variantData] = mapData
@@ -55,9 +58,10 @@ export async function updateProductsVariantsPrices({
prices: item.prices,
})
variantPricesMap.set(variant.id, [])
const prices: any[] = []
variantPricesMap.set(variant.id, prices)
item.prices.forEach(async (price) => {
item.prices.forEach((price) => {
const obj = {
amount: price.amount,
currency_code: price.currency_code,
@@ -65,38 +69,59 @@ export async function updateProductsVariantsPrices({
}
if (price.region_id) {
const region = await regionService.retrieve(price.region_id)
obj.currency_code = region.currency_code
obj.rules = {
region_id: price.region_id,
}
regionIds.add(price.region_id)
;(obj as any).region_id = price.region_id
}
const variantPrices = variantPricesMap.get(variant.id)
variantPrices?.push(obj)
prices.push(obj)
})
})
}
if (featureFlagRouter.isFeatureEnabled("isolate_pricing_domain")) {
const remoteLink = container.resolve("remoteLink")
const pricingModuleService = container.resolve("pricingModuleService")
if (regionIds.size) {
const regions = await regionService.list({
id: [...regionIds],
})
const regionMap = new Map<string, any>(regions.map((r) => [r.id, r]))
for (let { variantId } of variantIdsPricesData) {
const priceSet = await pricingModuleService.create({
rules: [{ rule_attribute: "region_id" }],
prices: variantPricesMap.get(variantId),
})
for (const [, prices] of variantPricesMap.entries()) {
prices.forEach((price) => {
if (price.region_id) {
const region = regionMap.get(price.region_id)
price.currency_code = region?.currency_code
price.rules = {
region_id: price.region_id,
}
await remoteLink.create({
productService: {
variant_id: variantId,
},
pricingService: {
price_set_id: priceSet.id,
},
delete price.region_id
}
})
}
}
if (featureFlagRouter.isFeatureEnabled("isolate_pricing_domain")) {
const remoteLink = container.resolve("remoteLink")
const pricingModuleService = container.resolve(
ModuleRegistrationName.PRICING
)
const priceSetsToCreate = variantIdsPricesData.map(({ variantId }) => ({
rules: [{ rule_attribute: "region_id" }],
prices: variantPricesMap.get(variantId),
}))
const priceSets = await pricingModuleService.create(priceSetsToCreate)
const links = priceSets.map((priceSet, index) => ({
productService: {
variant_id: variantIdsPricesData[index].variantId,
},
pricingService: {
price_set_id: priceSet.id,
},
}))
await remoteLink.create(links)
} else {
await productVariantServiceTx.updateVariantPrices(variantIdsPricesData)
}