From 5f1f59b834e8f4904b0d24bcde894927abb3e751 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 12:10:16 +0100 Subject: [PATCH 01/21] feat(product, pricing, utils): Transaction issues and reference issues --- .../__tests__/product/admin/create-product.ts | 2 +- integration-tests/plugins/jest.config.js | 1 + packages/pricing/src/services/currency.ts | 9 +- packages/pricing/src/services/money-amount.ts | 8 +- packages/pricing/src/services/price-rule.ts | 8 +- .../services/price-set-money-amount-rules.ts | 17 +--- .../src/services/price-set-money-amount.ts | 24 ++--- .../src/services/price-set-rule-type.ts | 31 +++--- packages/pricing/src/services/price-set.ts | 8 +- .../pricing/src/services/pricing-module.ts | 97 +++++++++++-------- packages/pricing/src/services/rule-type.ts | 8 +- .../product/src/services/product-category.ts | 17 +--- .../src/services/product-collection.ts | 17 +--- .../product/src/services/product-image.ts | 3 +- .../src/services/product-module-service.ts | 42 ++++---- .../product/src/services/product-option.ts | 10 +- packages/product/src/services/product-tag.ts | 16 +-- packages/product/src/services/product-type.ts | 14 +-- .../product/src/services/product-variant.ts | 11 +-- packages/product/src/services/product.ts | 13 ++- packages/product/src/utils/index.ts | 6 +- .../modules-sdk/decorators/inject-manager.ts | 9 +- .../decorators/inject-transaction-manager.ts | 15 ++- 23 files changed, 177 insertions(+), 209 deletions(-) diff --git a/integration-tests/plugins/__tests__/product/admin/create-product.ts b/integration-tests/plugins/__tests__/product/admin/create-product.ts index ef1af2b397282..8fa4dbd136bfe 100644 --- a/integration-tests/plugins/__tests__/product/admin/create-product.ts +++ b/integration-tests/plugins/__tests__/product/admin/create-product.ts @@ -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 diff --git a/integration-tests/plugins/jest.config.js b/integration-tests/plugins/jest.config.js index 298282f80931f..17a23c30b82af 100644 --- a/integration-tests/plugins/jest.config.js +++ b/integration-tests/plugins/jest.config.js @@ -9,6 +9,7 @@ module.exports = { `/www/`, `/dist/`, `/node_modules/`, + `/node_modules/`, `__tests__/fixtures`, `__testfixtures__`, `.cache`, diff --git a/packages/pricing/src/services/currency.ts b/packages/pricing/src/services/currency.ts index cf806794c4630..356ab53d892b5 100644 --- a/packages/pricing/src/services/currency.ts +++ b/packages/pricing/src/services/currency.ts @@ -1,5 +1,6 @@ import { Context, DAL, FindConfig, PricingTypes } from "@medusajs/types" import { + doNotForceTransaction, InjectManager, InjectTransactionManager, MedusaContext, @@ -9,8 +10,6 @@ import { import { Currency } from "@models" import { CurrencyRepository } from "@repositories" -import { doNotForceTransaction, shouldForceTransaction } from "@medusajs/utils" - type InjectedDependencies = { currencyRepository: DAL.RepositoryService } @@ -75,7 +74,7 @@ export default class CurrencyService { return queryOptions } - @InjectTransactionManager(shouldForceTransaction, "currencyRepository_") + @InjectTransactionManager("currencyRepository_") async create( data: PricingTypes.CreateCurrencyDTO[], @MedusaContext() sharedContext: Context = {} @@ -86,7 +85,7 @@ export default class CurrencyService { )) as TEntity[] } - @InjectTransactionManager(shouldForceTransaction, "currencyRepository_") + @InjectTransactionManager("currencyRepository_") async update( data: PricingTypes.UpdateCurrencyDTO[], @MedusaContext() sharedContext: Context = {} @@ -97,7 +96,7 @@ export default class CurrencyService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "currencyRepository_") + @InjectTransactionManager("currencyRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/pricing/src/services/money-amount.ts b/packages/pricing/src/services/money-amount.ts index 9ef7655561c03..78ce4cfa13379 100644 --- a/packages/pricing/src/services/money-amount.ts +++ b/packages/pricing/src/services/money-amount.ts @@ -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 = {} diff --git a/packages/pricing/src/services/price-rule.ts b/packages/pricing/src/services/price-rule.ts index 0fc7c8f2c0a3c..7735d2a0c5c4a 100644 --- a/packages/pricing/src/services/price-rule.ts +++ b/packages/pricing/src/services/price-rule.ts @@ -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 { )) as [TEntity[], number] } - @InjectTransactionManager(shouldForceTransaction, "priceRuleRepository_") + @InjectTransactionManager("priceRuleRepository_") async create( data: PricingTypes.CreatePriceRuleDTO[], @MedusaContext() sharedContext: Context = {} @@ -76,7 +74,7 @@ export default class PriceRuleService { )) as TEntity[] } - @InjectTransactionManager(shouldForceTransaction, "priceRuleRepository_") + @InjectTransactionManager("priceRuleRepository_") async update( data: PricingTypes.UpdatePriceRuleDTO[], @MedusaContext() sharedContext: Context = {} @@ -87,7 +85,7 @@ export default class PriceRuleService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "priceRuleRepository_") + @InjectTransactionManager("priceRuleRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/pricing/src/services/price-set-money-amount-rules.ts b/packages/pricing/src/services/price-set-money-amount-rules.ts index a8c2eb4151c78..883d580fe1c81 100644 --- a/packages/pricing/src/services/price-set-money-amount-rules.ts +++ b/packages/pricing/src/services/price-set-money-amount-rules.ts @@ -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 = {} diff --git a/packages/pricing/src/services/price-set-money-amount.ts b/packages/pricing/src/services/price-set-money-amount.ts index de1a45aa323ec..b660c7238506d 100644 --- a/packages/pricing/src/services/price-set-money-amount.ts +++ b/packages/pricing/src/services/price-set-money-amount.ts @@ -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 { 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 { 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 = {} diff --git a/packages/pricing/src/services/price-set-rule-type.ts b/packages/pricing/src/services/price-set-rule-type.ts index fbe719ca90d47..2f376084989ea 100644 --- a/packages/pricing/src/services/price-set-rule-type.ts +++ b/packages/pricing/src/services/price-set-rule-type.ts @@ -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 { +export default class PriceSetRuleTypeService< + TEntity extends PriceSetRuleType = PriceSetRuleType +> { protected readonly priceSetRuleTypeRepository_: DAL.RepositoryService constructor({ priceSetRuleTypeRepository }: InjectedDependencies) { @@ -28,7 +28,10 @@ export default class PriceSetRuleTypeService = {}, @MedusaContext() sharedContext: Context = {} ): Promise { - return (await retrieveEntity({ + return (await retrieveEntity< + PriceSetRuleType, + PricingTypes.PriceSetRuleTypeDTO + >({ id: priceSetId, entityName: PriceSet.name, repository: this.priceSetRuleTypeRepository_, @@ -74,29 +77,27 @@ export default class PriceSetRuleTypeService { - 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 { - 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 = {} diff --git a/packages/pricing/src/services/price-set.ts b/packages/pricing/src/services/price-set.ts index b3fe10189f9f4..ab9f552ccc83f 100644 --- a/packages/pricing/src/services/price-set.ts +++ b/packages/pricing/src/services/price-set.ts @@ -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 { )) as [TEntity[], number] } - @InjectTransactionManager(shouldForceTransaction, "priceSetRepository_") + @InjectTransactionManager("priceSetRepository_") async create( data: Omit[], @MedusaContext() sharedContext: Context = {} @@ -76,7 +74,7 @@ export default class PriceSetService { )) as TEntity[] } - @InjectTransactionManager(shouldForceTransaction, "priceSetRepository_") + @InjectTransactionManager("priceSetRepository_") async update( data: Omit[], @MedusaContext() sharedContext: Context = {} @@ -87,7 +85,7 @@ export default class PriceSetService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "priceSetRepository_") + @InjectTransactionManager("priceSetRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index fc3dcc3641d2a..128251f863180 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -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" @@ -218,7 +216,6 @@ export default class PricingModuleService< sharedContext?: Context ): Promise - @InjectManager("baseRepository_") async create( data: PricingTypes.CreatePriceSetDTO | PricingTypes.CreatePriceSetDTO[], @MedusaContext() sharedContext: Context = {} @@ -231,7 +228,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 +237,7 @@ export default class PricingModuleService< | PriceSetDTO[] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async create_( data: PricingTypes.CreatePriceSetDTO[], @MedusaContext() sharedContext: Context = {} @@ -380,14 +378,15 @@ export default class PricingModuleService< | PricingTypes.PriceSetDTO } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async addRules_( inputs: PricingTypes.AddRulesDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { const priceSets = await this.priceSetService_.list( { id: inputs.map((d) => d.priceSetId) }, - { relations: ["rule_types"] } + { relations: ["rule_types"] }, + sharedContext ) const priceSetRuleTypeMap: Map> = new Map( @@ -480,7 +479,6 @@ export default class PricingModuleService< sharedContext?: Context ): Promise - @InjectManager("baseRepository_") async addPrices( data: AddPricesDTO | AddPricesDTO[], @MedusaContext() sharedContext: Context = {} @@ -492,10 +490,14 @@ export default class PricingModuleService< return (await this.list( { id: input.map((d) => d.priceSetId) }, { relations: ["money_amounts"] } - )) as unknown as PricingTypes.PriceSetDTO[] | PricingTypes.PriceSetDTO + ), + undefined, + sharedContext) as unknown as + | PricingTypes.PriceSetDTO[] + | PricingTypes.PriceSetDTO } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async addPrices_( input: AddPricesDTO[], @MedusaContext() sharedContext: Context = {} @@ -591,25 +593,37 @@ export default class PricingModuleService< return priceSets } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async removeRules( data: PricingTypes.RemovePriceSetRulesDTO[], @MedusaContext() sharedContext: Context = {} ): Promise { - 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 +632,8 @@ export default class PricingModuleService< }, { select: ["price_set_money_amount"], - } + }, + sharedContext ) await this.priceSetRuleTypeService_.delete( @@ -632,7 +647,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async update( data: PricingTypes.UpdatePriceSetDTO[], @MedusaContext() sharedContext: Context = {} @@ -647,7 +662,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} @@ -718,7 +733,7 @@ export default class PricingModuleService< ] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async createMoneyAmounts( data: PricingTypes.CreateMoneyAmountDTO[], @MedusaContext() sharedContext: Context = {} @@ -736,7 +751,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async updateMoneyAmounts( data: PricingTypes.UpdateMoneyAmountDTO[], @MedusaContext() sharedContext: Context = {} @@ -754,7 +769,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async deleteMoneyAmounts( ids: string[], @MedusaContext() sharedContext: Context = {} @@ -822,7 +837,7 @@ export default class PricingModuleService< ] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async createCurrencies( data: PricingTypes.CreateCurrencyDTO[], @MedusaContext() sharedContext: Context = {} @@ -837,7 +852,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async updateCurrencies( data: PricingTypes.UpdateCurrencyDTO[], @MedusaContext() sharedContext: Context = {} @@ -852,7 +867,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async deleteCurrencies( currencyCodes: string[], @MedusaContext() sharedContext: Context = {} @@ -920,7 +935,7 @@ export default class PricingModuleService< ] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async createRuleTypes( data: PricingTypes.CreateRuleTypeDTO[], @MedusaContext() sharedContext: Context = {} @@ -935,7 +950,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async updateRuleTypes( data: PricingTypes.UpdateRuleTypeDTO[], @MedusaContext() sharedContext: Context = {} @@ -950,7 +965,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async deleteRuleTypes( ruleTypeIds: string[], @MedusaContext() sharedContext: Context = {} @@ -1062,7 +1077,7 @@ export default class PricingModuleService< ] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async createPriceSetMoneyAmountRules( data: PricingTypes.CreatePriceSetMoneyAmountRulesDTO[], @MedusaContext() sharedContext: Context = {} @@ -1079,7 +1094,7 @@ export default class PricingModuleService< }) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async updatePriceSetMoneyAmountRules( data: PricingTypes.UpdatePriceSetMoneyAmountRulesDTO[], @MedusaContext() sharedContext: Context = {} @@ -1096,7 +1111,7 @@ export default class PricingModuleService< }) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async deletePriceSetMoneyAmountRules( ids: string[], @MedusaContext() sharedContext: Context = {} @@ -1167,7 +1182,7 @@ export default class PricingModuleService< ] } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async createPriceRules( data: PricingTypes.CreatePriceRuleDTO[], @MedusaContext() sharedContext: Context = {} @@ -1182,7 +1197,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async updatePriceRules( data: PricingTypes.UpdatePriceRuleDTO[], @MedusaContext() sharedContext: Context = {} @@ -1197,7 +1212,7 @@ export default class PricingModuleService< ) } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async deletePriceRules( priceRuleIds: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/pricing/src/services/rule-type.ts b/packages/pricing/src/services/rule-type.ts index 7dadbbc070128..7f0e34561683b 100644 --- a/packages/pricing/src/services/rule-type.ts +++ b/packages/pricing/src/services/rule-type.ts @@ -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 { )) as [TEntity[], number] } - @InjectTransactionManager(shouldForceTransaction, "ruleTypeRepository_") + @InjectTransactionManager("ruleTypeRepository_") async create( data: PricingTypes.CreateRuleTypeDTO[], @MedusaContext() sharedContext: Context = {} @@ -76,7 +74,7 @@ export default class RuleTypeService { )) as TEntity[] } - @InjectTransactionManager(shouldForceTransaction, "ruleTypeRepository_") + @InjectTransactionManager("ruleTypeRepository_") async update( data: PricingTypes.UpdateRuleTypeDTO[], @MedusaContext() sharedContext: Context = {} @@ -87,7 +85,7 @@ export default class RuleTypeService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "ruleTypeRepository_") + @InjectTransactionManager("ruleTypeRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/product/src/services/product-category.ts b/packages/product/src/services/product-category.ts index 1886fdd9b30a5..a2ef62a041f06 100644 --- a/packages/product/src/services/product-category.ts +++ b/packages/product/src/services/product-category.ts @@ -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 = {} diff --git a/packages/product/src/services/product-collection.ts b/packages/product/src/services/product-collection.ts index 93f5d1ca70c11..08199ab1ae400 100644 --- a/packages/product/src/services/product-collection.ts +++ b/packages/product/src/services/product-collection.ts @@ -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 = {} diff --git a/packages/product/src/services/product-image.ts b/packages/product/src/services/product-image.ts index 7149c7c0ca5eb..134ba87a7d8be 100644 --- a/packages/product/src/services/product-image.ts +++ b/packages/product/src/services/product-image.ts @@ -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 { this.productImageRepository_ = productImageRepository } - @InjectTransactionManager(doNotForceTransaction, "productImageRepository_") + @InjectTransactionManager("productImageRepository_") async upsert( urls: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index e632324873a50..0a804eb5a16a4 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -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 = {} @@ -720,7 +718,7 @@ export default class ProductModuleService< return updatedProducts } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async create_( data: ProductTypes.CreateProductDTO[], @MedusaContext() sharedContext: Context = {} @@ -829,7 +827,7 @@ export default class ProductModuleService< return products } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async update_( data: ProductTypes.UpdateProductDTO[], @MedusaContext() sharedContext: Context = {} @@ -1060,7 +1058,7 @@ export default class ProductModuleService< } } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async delete( productIds: string[], @MedusaContext() sharedContext: Context = {} @@ -1116,7 +1114,7 @@ export default class ProductModuleService< return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0 } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") protected async softDelete_( productIds: string[], @MedusaContext() sharedContext: Context = {} @@ -1179,7 +1177,7 @@ export default class ProductModuleService< return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0 } - @InjectTransactionManager(shouldForceTransaction, "baseRepository_") + @InjectTransactionManager("baseRepository_") async restore_( productIds: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/product/src/services/product-option.ts b/packages/product/src/services/product-option.ts index c5d796ccdec97..298ad8fcbb5d3 100644 --- a/packages/product/src/services/product-option.ts +++ b/packages/product/src/services/product-option.ts @@ -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,7 +100,7 @@ export default class ProductOptionService< ).update(data, sharedContext)) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "productOptionRepository_") + @InjectTransactionManager("productOptionRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/product/src/services/product-tag.ts b/packages/product/src/services/product-tag.ts index 6c5aa39606d51..90a33aa352732 100644 --- a/packages/product/src/services/product-tag.ts +++ b/packages/product/src/services/product-tag.ts @@ -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 = {} diff --git a/packages/product/src/services/product-type.ts b/packages/product/src/services/product-type.ts index bbf1182aa5b22..2d510a3430f82 100644 --- a/packages/product/src/services/product-type.ts +++ b/packages/product/src/services/product-type.ts @@ -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 = {} diff --git a/packages/product/src/services/product-variant.ts b/packages/product/src/services/product-variant.ts index d41300ccb3840..de7a776f67f80 100644 --- a/packages/product/src/services/product-variant.ts +++ b/packages/product/src/services/product-variant.ts @@ -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 = {} diff --git a/packages/product/src/services/product.ts b/packages/product/src/services/product.ts index 7c6c88967570e..15d3c010b74e1 100644 --- a/packages/product/src/services/product.ts +++ b/packages/product/src/services/product.ts @@ -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 { )) as [TEntity[], number] } - @InjectTransactionManager(doNotForceTransaction, "productRepository_") + @InjectTransactionManager("productRepository_") async create( data: ProductTypes.CreateProductOnlyDTO[], @MedusaContext() sharedContext: Context = {} @@ -138,7 +137,7 @@ export default class ProductService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "productRepository_") + @InjectTransactionManager("productRepository_") async update( data: ProductServiceTypes.UpdateProductDTO[], @MedusaContext() sharedContext: Context = {} @@ -154,7 +153,7 @@ export default class ProductService { )) as TEntity[] } - @InjectTransactionManager(doNotForceTransaction, "productRepository_") + @InjectTransactionManager("productRepository_") async delete( ids: string[], @MedusaContext() sharedContext: Context = {} @@ -164,7 +163,7 @@ export default class ProductService { }) } - @InjectTransactionManager(doNotForceTransaction, "productRepository_") + @InjectTransactionManager("productRepository_") async softDelete( productIds: string[], @MedusaContext() sharedContext: Context = {} @@ -174,7 +173,7 @@ export default class ProductService { }) } - @InjectTransactionManager(doNotForceTransaction, "productRepository_") + @InjectTransactionManager("productRepository_") async restore( productIds: string[], @MedusaContext() sharedContext: Context = {} diff --git a/packages/product/src/utils/index.ts b/packages/product/src/utils/index.ts index 8188a4c10e6bd..9e37c3cbf0c24 100644 --- a/packages/product/src/utils/index.ts +++ b/packages/product/src/utils/index.ts @@ -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 { diff --git a/packages/utils/src/modules-sdk/decorators/inject-manager.ts b/packages/utils/src/modules-sdk/decorators/inject-manager.ts index e0c007d9c9fc2..8650a613952c4 100644 --- a/packages/utils/src/modules-sdk/decorators/inject-manager.ts +++ b/packages/utils/src/modules-sdk/decorators/inject-manager.ts @@ -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) diff --git a/packages/utils/src/modules-sdk/decorators/inject-transaction-manager.ts b/packages/utils/src/modules-sdk/decorators/inject-transaction-manager.ts index 4cb557ea59aa2..30d9ca8550484 100644 --- a/packages/utils/src/modules-sdk/decorators/inject-transaction-manager.ts +++ b/packages/utils/src/modules-sdk/decorators/inject-transaction-manager.ts @@ -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) From 5817a97e6344aa74e09c56a0775f4de1cbdf6973 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 14:18:02 +0100 Subject: [PATCH 02/21] fixes decorators --- .../product/admin/update-product-variant.spec.ts | 2 +- .../__tests__/product/admin/update-product.spec.ts | 10 +++++----- integration-tests/plugins/package.json | 2 +- packages/pricing/src/repositories/pricing.ts | 2 +- packages/pricing/src/services/pricing-module.ts | 11 +++++------ packages/utils/src/dal/utils.ts | 7 +++++-- 6 files changed, 18 insertions(+), 16 deletions(-) diff --git a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts index 7fc8bc53e18c1..b65d75560ac4b 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product-variant.spec.ts @@ -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 diff --git a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts index c88f37457e786..f4b040478d558 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts @@ -11,7 +11,7 @@ import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" -jest.setTimeout(50000) +jest.setTimeout(5000000) const adminHeaders = { headers: { @@ -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 @@ -142,7 +142,9 @@ describe.skip("[Product & Pricing Module] POST /admin/products/:id", () => { { amount: 3000, currency_code: "usd", - rules: {}, + rules: { + region_id: "test-region", + }, }, ], }) @@ -172,9 +174,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}`, diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index 0b1b18de06da5..a1a030a8e3669 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -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 --logHeapUsage --forceExit -- __tests__/product/admin/update-product.spec.ts", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { diff --git a/packages/pricing/src/repositories/pricing.ts b/packages/pricing/src/repositories/pricing.ts index f2766b7efa142..b27c0be1266cb 100644 --- a/packages/pricing/src/repositories/pricing.ts +++ b/packages/pricing/src/repositories/pricing.ts @@ -27,7 +27,7 @@ export class PricingRepository pricingContext: PricingContext = { context: {} }, sharedContext: Context = {} ): Promise { - const manager = this.getActiveManager() + const manager = this.getActiveManager(sharedContext) const knex = manager.getKnex() const context = pricingContext.context || {} diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index 128251f863180..727e365608f03 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -216,6 +216,7 @@ export default class PricingModuleService< sharedContext?: Context ): Promise + @InjectManager("baseRepository_") async create( data: PricingTypes.CreatePriceSetDTO | PricingTypes.CreatePriceSetDTO[], @MedusaContext() sharedContext: Context = {} @@ -479,6 +480,7 @@ export default class PricingModuleService< sharedContext?: Context ): Promise + @InjectManager("baseRepository_") async addPrices( data: AddPricesDTO | AddPricesDTO[], @MedusaContext() sharedContext: Context = {} @@ -489,12 +491,9 @@ export default class PricingModuleService< return (await this.list( { id: input.map((d) => d.priceSetId) }, - { relations: ["money_amounts"] } - ), - undefined, - sharedContext) as unknown as - | PricingTypes.PriceSetDTO[] - | PricingTypes.PriceSetDTO + { relations: ["money_amounts"] }, + sharedContext + )) as unknown as PricingTypes.PriceSetDTO[] | PricingTypes.PriceSetDTO } @InjectTransactionManager("baseRepository_") diff --git a/packages/utils/src/dal/utils.ts b/packages/utils/src/dal/utils.ts index 457a7ab0eb426..de3e0aa8ad239 100644 --- a/packages/utils/src/dal/utils.ts +++ b/packages/utils/src/dal/utils.ts @@ -28,9 +28,12 @@ export async function transactionWrapper( 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) } /** From ff8ff5cfd80d7c75780b3f8da6bff87209bc8be7 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 14:20:12 +0100 Subject: [PATCH 03/21] cleanup --- .../plugins/__tests__/product/admin/update-product.spec.ts | 6 ++---- integration-tests/plugins/package.json | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts index f4b040478d558..547a531ed9166 100644 --- a/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts +++ b/integration-tests/plugins/__tests__/product/admin/update-product.spec.ts @@ -11,7 +11,7 @@ import adminSeeder from "../../../../helpers/admin-seeder" import { createDefaultRuleTypes } from "../../../helpers/create-default-rule-types" import { createVariantPriceSet } from "../../../helpers/create-variant-price-set" -jest.setTimeout(5000000) +jest.setTimeout(50000) const adminHeaders = { headers: { @@ -142,9 +142,7 @@ describe("[Product & Pricing Module] POST /admin/products/:id", () => { { amount: 3000, currency_code: "usd", - rules: { - region_id: "test-region", - }, + rules: {}, }, ], }) diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index a1a030a8e3669..0b1b18de06da5 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --logHeapUsage --forceExit -- __tests__/product/admin/update-product.spec.ts", + "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --logHeapUsage --forceExit", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { From aa4da68b7ca7436e3d3e861cdda4307c36eb32e0 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 15:00:52 +0100 Subject: [PATCH 04/21] fix product module upsert --- integration-tests/plugins/package.json | 2 +- .../src/repositories/product-option.ts | 57 ++++++++++++++++++- .../src/services/product-module-service.ts | 42 +++++++++----- .../product/src/services/product-option.ts | 11 ++++ 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index 0b1b18de06da5..6129ed2192084 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -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 --logHeapUsage --forceExit -- __tests__/workflows/product/update-product.ts", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { diff --git a/packages/product/src/repositories/product-option.ts b/packages/product/src/repositories/product-option.ts index f06ae8b538f99..fa1584a97a852 100644 --- a/packages/product/src/repositories/product-option.ts +++ b/packages/product/src/repositories/product-option.ts @@ -1,9 +1,10 @@ import { Context, DAL, ProductTypes } from "@medusajs/types" import { DALUtils, MedusaError } from "@medusajs/utils" import { - LoadStrategy, FilterQuery as MikroFilterQuery, FindOptions as MikroOptions, + LoadStrategy, + RequiredEntityData, } from "@mikro-orm/core" import { SqlEntityManager } from "@mikro-orm/postgresql" import { Product, ProductOption } from "@models" @@ -149,4 +150,58 @@ export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseReposi return productOptions } + + async upsert( + data: + | ProductTypes.CreateProductOptionDTO[] + | ProductTypes.UpdateProductOptionDTO[], + context: Context = {} + ): Promise { + const manager = this.getActiveManager(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 optionToCreate: ProductOption[] = [] + + data.forEach((option) => { + const existingOption = existingOptionsMap.get(option.id) + if (existingOption) { + upsertedOptions.push(existingOption) + } else { + const newOption = (manager as SqlEntityManager).create( + ProductOption, + option as RequiredEntityData + ) + optionToCreate.push(newOption) + } + }) + + if (optionToCreate.length) { + manager.persist(optionToCreate) + upsertedOptions.push(...optionToCreate) + } + + return upsertedOptions + } } diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index 0a804eb5a16a4..d304367cb9ebd 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -675,6 +675,7 @@ export default class ProductModuleService< return JSON.parse(JSON.stringify(categories)) } + @InjectManager("baseRepository_") async create( data: ProductTypes.CreateProductDTO[], sharedContext?: Context @@ -696,6 +697,7 @@ export default class ProductModuleService< return createdProducts } + @InjectManager("baseRepository_") async update( data: ProductTypes.UpdateProductDTO[], @MedusaContext() sharedContext: Context = {} @@ -857,14 +859,11 @@ export default class ProductModuleService< )[] >() - const productOptionsMap = new Map< - string, - ProductTypes.CreateProductOptionDTO[] - >() + const productOptionsMap = new Map() 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( @@ -874,7 +873,6 @@ export default class ProductModuleService< } productVariantsMap.set(productData.id, variants ?? []) - productOptionsMap.set(productData.id, options ?? []) if (productData.is_giftcard) { productData.discountable = false @@ -892,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 }) @@ -906,7 +913,7 @@ export default class ProductModuleService< products.map((product) => [product.id, product]) ) - const productOptionsData = [...productOptionsMap] + const productOptions = [...productOptionsMap] .map(([id, options]) => options.map((option) => ({ ...option, @@ -915,11 +922,6 @@ export default class ProductModuleService< ) .flat() - const productOptions = await this.productOptionService_.create( - productOptionsData, - sharedContext - ) - const productVariantIdsToDelete: string[] = [] const productVariantsToCreateMap = new Map< string, @@ -1008,6 +1010,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 = {} @@ -1073,6 +1087,7 @@ export default class ProductModuleService< ) } + @InjectManager("baseRepository_") async softDelete< TReturnableLinkableKeys extends string = Lowercase< keyof typeof LinkableKeys @@ -1122,6 +1137,7 @@ export default class ProductModuleService< return await this.productService_.softDelete(productIds, sharedContext) } + @InjectManager("baseRepository_") async restore< TReturnableLinkableKeys extends string = Lowercase< keyof typeof LinkableKeys @@ -1150,7 +1166,7 @@ export default class ProductModuleService< return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0 } - @InjectManager("baseRepository_") + @InjectTransactionManager("baseRepository_") async restoreVariants< TReturnableLinkableKeys extends string = Lowercase< keyof typeof LinkableKeys diff --git a/packages/product/src/services/product-option.ts b/packages/product/src/services/product-option.ts index 298ad8fcbb5d3..0a2b3910330e4 100644 --- a/packages/product/src/services/product-option.ts +++ b/packages/product/src/services/product-option.ts @@ -107,4 +107,15 @@ export default class ProductOptionService< ): Promise { return await this.productOptionRepository_.delete(ids, sharedContext) } + + @InjectTransactionManager("productOptionRepository_") + async upsert( + data: + | ProductTypes.CreateProductOptionDTO[] + | ProductTypes.UpdateProductOptionDTO[], + @MedusaContext() sharedContext: Context = {} + ): Promise { + return (await (this.productOptionRepository_ as ProductOptionRepository) + .upsert!(data, sharedContext)) as TEntity[] + } } From a109dc21b774c093789ae7f4d147db7882506e1b Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 15:36:00 +0100 Subject: [PATCH 05/21] fix missing active manager --- .../product-module-service/product-collections.spec.ts | 10 +++------- .../product/src/repositories/product-collection.ts | 8 +++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts b/packages/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts index d1227ef5a5015..856dd05a5ee83 100644 --- a/packages/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts +++ b/packages/product/integration-tests/__tests__/services/product-module-service/product-collections.spec.ts @@ -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, }), - ], + ]), }) ) }) diff --git a/packages/product/src/repositories/product-collection.ts b/packages/product/src/repositories/product-collection.ts index a672d6f6a3342..26ef2631de06b 100644 --- a/packages/product/src/repositories/product-collection.ts +++ b/packages/product/src/repositories/product-collection.ts @@ -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 = { where: {} }, context: Context = {} ): Promise { - const manager = (context.transactionManager ?? - this.manager_) as SqlEntityManager + const manager = this.getActiveManager(context) const findOptions_ = { ...findOptions } findOptions_.options ??= {} @@ -52,8 +51,7 @@ export class ProductCollectionRepository extends DALUtils.MikroOrmBaseRepository findOptions: DAL.FindOptions = { where: {} }, context: Context = {} ): Promise<[ProductCollection[], number]> { - const manager = (context.transactionManager ?? - this.manager_) as SqlEntityManager + const manager = this.getActiveManager(context) const findOptions_ = { ...findOptions } findOptions_.options ??= {} From 42b37611df98746fcc91423429d4b9d014e0d8cd Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 15:40:30 +0100 Subject: [PATCH 06/21] increase timeout --- .../plugins/__tests__/workflows/product/update-product.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/plugins/__tests__/workflows/product/update-product.ts b/integration-tests/plugins/__tests__/workflows/product/update-product.ts index 26e0863f60ff8..987637892015b 100644 --- a/integration-tests/plugins/__tests__/workflows/product/update-product.ts +++ b/integration-tests/plugins/__tests__/workflows/product/update-product.ts @@ -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 From 56a021ec0674fece8e1c6d7e77aaa1661d56e16a Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 15:59:17 +0100 Subject: [PATCH 07/21] revert package.json --- integration-tests/plugins/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index 6129ed2192084..0b1b18de06da5 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --logHeapUsage --forceExit -- __tests__/workflows/product/update-product.ts", + "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --bail --logHeapUsage --forceExit", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { From 5b99e6464678165aa1eaf56131d58b7cde126ec7 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 16:28:52 +0100 Subject: [PATCH 08/21] WIP --- integration-tests/environment-helpers/bootstrap-app.js | 1 + .../plugins/__tests__/product/admin/create-product.ts | 2 +- integration-tests/plugins/package.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integration-tests/environment-helpers/bootstrap-app.js b/integration-tests/environment-helpers/bootstrap-app.js index 13a1ce01501a7..6e0e987131ad5 100644 --- a/integration-tests/environment-helpers/bootstrap-app.js +++ b/integration-tests/environment-helpers/bootstrap-app.js @@ -52,6 +52,7 @@ module.exports = { const shutdown = async () => { await Promise.all([ + container.dispose(), expressServer.close(), db?.destroy(), pgConnection?.context?.destroy(), diff --git a/integration-tests/plugins/__tests__/product/admin/create-product.ts b/integration-tests/plugins/__tests__/product/admin/create-product.ts index 8fa4dbd136bfe..ef1af2b397282 100644 --- a/integration-tests/plugins/__tests__/product/admin/create-product.ts +++ b/integration-tests/plugins/__tests__/product/admin/create-product.ts @@ -22,7 +22,7 @@ const env = { MEDUSA_FF_ISOLATE_PRODUCT_DOMAIN: true, } -describe("[Product & Pricing Module] POST /admin/products", () => { +describe.skip("[Product & Pricing Module] POST /admin/products", () => { let dbConnection let appContainer let shutdownServer diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index 0b1b18de06da5..5c993d54ea2a5 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -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 --detectOpenHandles --logHeapUsage --clearMocks --no-compilation-cache --forceExit", "build": "babel src -d dist --extensions \".ts,.js\"" }, "dependencies": { From 5d5f4927e5b6b98ca0f5c0d28ef8cbbe342fe294 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 16:47:26 +0100 Subject: [PATCH 09/21] try another node version based on findings with memory issues with jest introduced after 16.11 but fixed in 21 --- .github/actions/setup-server/action.yml | 2 +- .github/workflows/action.yml | 10 +++++----- .github/workflows/codegen-test.yml | 2 +- .github/workflows/docs-freshness-check.yml | 2 +- .github/workflows/docs-new-announcement.yml | 2 +- .github/workflows/docs-remove-announcement.yml | 2 +- .github/workflows/generate-references.yml | 4 ++-- .github/workflows/oas-test.yml | 2 +- .github/workflows/release-notifications.yml | 2 +- .../plugins/__tests__/product/admin/create-product.ts | 2 +- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/actions/setup-server/action.yml b/.github/actions/setup-server/action.yml index 3b494931f01b9..806d266a219a9 100644 --- a/.github/actions/setup-server/action.yml +++ b/.github/actions/setup-server/action.yml @@ -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 diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml index c10d96f5a7a60..5abe7f362b4cf 100644 --- a/.github/workflows/action.yml +++ b/.github/workflows/action.yml @@ -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 diff --git a/.github/workflows/codegen-test.yml b/.github/workflows/codegen-test.yml index 81afbb1f04d33..9f0a5913173c1 100644 --- a/.github/workflows/codegen-test.yml +++ b/.github/workflows/codegen-test.yml @@ -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 diff --git a/.github/workflows/docs-freshness-check.yml b/.github/workflows/docs-freshness-check.yml index bf0268921e629..45e88dbb60357 100644 --- a/.github/workflows/docs-freshness-check.yml +++ b/.github/workflows/docs-freshness-check.yml @@ -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 diff --git a/.github/workflows/docs-new-announcement.yml b/.github/workflows/docs-new-announcement.yml index c4f68a8eca26e..457feaf4553fa 100644 --- a/.github/workflows/docs-new-announcement.yml +++ b/.github/workflows/docs-new-announcement.yml @@ -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 diff --git a/.github/workflows/docs-remove-announcement.yml b/.github/workflows/docs-remove-announcement.yml index 0f141bd8d2b27..06bf788c9cbb5 100644 --- a/.github/workflows/docs-remove-announcement.yml +++ b/.github/workflows/docs-remove-announcement.yml @@ -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 diff --git a/.github/workflows/generate-references.yml b/.github/workflows/generate-references.yml index 046cfe9f52616..a6bbb23354567 100644 --- a/.github/workflows/generate-references.yml +++ b/.github/workflows/generate-references.yml @@ -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 diff --git a/.github/workflows/oas-test.yml b/.github/workflows/oas-test.yml index ec4e1a17eb189..f5f253bbf3fd8 100644 --- a/.github/workflows/oas-test.yml +++ b/.github/workflows/oas-test.yml @@ -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 diff --git a/.github/workflows/release-notifications.yml b/.github/workflows/release-notifications.yml index 3c677890752d2..1551a3c4c0f79 100644 --- a/.github/workflows/release-notifications.yml +++ b/.github/workflows/release-notifications.yml @@ -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 diff --git a/integration-tests/plugins/__tests__/product/admin/create-product.ts b/integration-tests/plugins/__tests__/product/admin/create-product.ts index ef1af2b397282..8fa4dbd136bfe 100644 --- a/integration-tests/plugins/__tests__/product/admin/create-product.ts +++ b/integration-tests/plugins/__tests__/product/admin/create-product.ts @@ -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 From 7fed0e458e59544d7bb2516c08142a4dca1c6e49 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 17:09:39 +0100 Subject: [PATCH 10/21] re add bail --- integration-tests/plugins/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/plugins/package.json b/integration-tests/plugins/package.json index 5c993d54ea2a5..e3c07aa393c05 100644 --- a/integration-tests/plugins/package.json +++ b/integration-tests/plugins/package.json @@ -5,7 +5,7 @@ "license": "MIT", "private": true, "scripts": { - "test:integration": "node --expose-gc ./../../node_modules/.bin/jest --silent=false --runInBand --detectOpenHandles --logHeapUsage --clearMocks --no-compilation-cache --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": { From 6b26fbd9f0d22b43ec9aff030129f5b27bacbca6 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Thu, 2 Nov 2023 18:32:50 +0100 Subject: [PATCH 11/21] fix variant options --- .../product/src/services/product-module-service.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/packages/product/src/services/product-module-service.ts b/packages/product/src/services/product-module-service.ts index d304367cb9ebd..21182de4ed1b7 100644 --- a/packages/product/src/services/product-module-service.ts +++ b/packages/product/src/services/product-module-service.ts @@ -913,15 +913,6 @@ export default class ProductModuleService< products.map((product) => [product.id, product]) ) - const productOptions = [...productOptionsMap] - .map(([id, options]) => - options.map((option) => ({ - ...option, - product: productByIdMap.get(id)!, - })) - ) - .flat() - 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 } }) From 6cab021af1f846599d37857d9c3a8897946ec289 Mon Sep 17 00:00:00 2001 From: "Carlos R. L. Rodrigues" Date: Thu, 2 Nov 2023 16:23:37 -0400 Subject: [PATCH 12/21] chore: bulk create pricing --- .../pricing/src/services/pricing-module.ts | 229 ++++++++++-------- 1 file changed, 127 insertions(+), 102 deletions(-) diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index 727e365608f03..7d432006f406d 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -285,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 - ) + // Bulk create price sets + const priceSetData = data.map(({ rules, prices, ...rest }) => rest) + const createdPriceSets = await this.priceSetService_.create( + priceSetData, + sharedContext + ) - if (rules?.length) { - const priceSetRuleTypesCreate = rules!.map((r) => ({ - rule_type: ruleTypeMap.get(r.rule_attribute), - price_set: priceSet, - })) + // 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 + ) + } - await this.priceSetRuleTypeService_.create( - priceSetRuleTypesCreate as unknown as PricingTypes.CreatePriceSetRuleTypeDTO[], - sharedContext - ) - } + // Money amounts + const moneyAmountData = data.flatMap((item) => item.prices || []) + const createdMoneyAmounts = await this.moneyAmountService_.create( + moneyAmountData, + 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 - ) - } - } + 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", + }) + } + } + } - return priceSet - }) - ) + // Bulk create price set money amounts + const createdPriceSetMoneyAmounts = + await this.priceSetMoneyAmountService_.create( + priceSetMoneyAmountData as PricingTypes.CreatePriceSetMoneyAmountDTO[], + sharedContext + ) - return priceSets + // 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( @@ -544,48 +559,58 @@ 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 - ) - - 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 - ) - } + // Money amounts + const moneyAmountsBulkData = input.flatMap((entry) => entry.prices) + const createdMoneyAmounts = await this.moneyAmountService_.create( + moneyAmountsBulkData as unknown as CreateMoneyAmountDTO[], + sharedContext + ) - return moneyAmount + // 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, + } }) + ) + 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 ) } From f03f3cc61d9528814b3907314271a810b1a470ae Mon Sep 17 00:00:00 2001 From: "Carlos R. L. Rodrigues" Date: Thu, 2 Nov 2023 16:55:34 -0400 Subject: [PATCH 13/21] chore: workflow bulk --- .../update-products-variants-prices.ts | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/packages/workflows/src/handlers/product/update-products-variants-prices.ts b/packages/workflows/src/handlers/product/update-products-variants-prices.ts index 9934e645fdfd3..548de0b0df66e 100644 --- a/packages/workflows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/workflows/src/handlers/product/update-products-variants-prices.ts @@ -64,6 +64,7 @@ export async function updateProductsVariantsPrices({ rules: {}, } + // TODO: fetch all regions using .list and associate them here if (price.region_id) { const region = await regionService.retrieve(price.region_id) obj.currency_code = region.currency_code @@ -82,21 +83,23 @@ export async function updateProductsVariantsPrices({ const remoteLink = container.resolve("remoteLink") const pricingModuleService = container.resolve("pricingModuleService") - for (let { variantId } of variantIdsPricesData) { - const priceSet = await pricingModuleService.create({ - rules: [{ rule_attribute: "region_id" }], - prices: variantPricesMap.get(variantId), - }) + const priceSetsToCreate = variantIdsPricesData.map(({ variantId }) => ({ + rules: [{ rule_attribute: "region_id" }], + prices: variantPricesMap.get(variantId), + })) - await remoteLink.create({ - productService: { - variant_id: variantId, - }, - pricingService: { - price_set_id: priceSet.id, - }, - }) - } + 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) } From 19e6fdbc3a50d2f0c866f222fdaf3611689ff959 Mon Sep 17 00:00:00 2001 From: Adrien de Peretti Date: Fri, 3 Nov 2023 09:59:37 +0100 Subject: [PATCH 14/21] Create big-chefs-dream.md --- .changeset/big-chefs-dream.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/big-chefs-dream.md diff --git a/.changeset/big-chefs-dream.md b/.changeset/big-chefs-dream.md new file mode 100644 index 0000000000000..caf4dd22c9ff9 --- /dev/null +++ b/.changeset/big-chefs-dream.md @@ -0,0 +1,6 @@ +--- +"@medusajs/pricing": patch +"@medusajs/product": patch +--- + +feat(product, pricing, utils): Transaction issues and reference issues + refactoring From 67afc3a178ed5d3de21b4470b0bacd6e652b6f41 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 10:12:13 +0100 Subject: [PATCH 15/21] fix missing update for upserty --- packages/pricing/src/services/currency.ts | 1 - .../src/repositories/product-option.ts | 19 +++++++++++------ .../product/src/repositories/product-tag.ts | 21 ++++++++++--------- .../product/src/repositories/product-type.ts | 21 ++++++++++--------- 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/packages/pricing/src/services/currency.ts b/packages/pricing/src/services/currency.ts index 356ab53d892b5..53a87037dcb45 100644 --- a/packages/pricing/src/services/currency.ts +++ b/packages/pricing/src/services/currency.ts @@ -1,6 +1,5 @@ import { Context, DAL, FindConfig, PricingTypes } from "@medusajs/types" import { - doNotForceTransaction, InjectManager, InjectTransactionManager, MedusaContext, diff --git a/packages/product/src/repositories/product-option.ts b/packages/product/src/repositories/product-option.ts index fa1584a97a852..6531b479286d7 100644 --- a/packages/product/src/repositories/product-option.ts +++ b/packages/product/src/repositories/product-option.ts @@ -182,24 +182,31 @@ export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseReposi } const upsertedOptions: ProductOption[] = [] - const optionToCreate: ProductOption[] = [] + const optionsToCreate: ProductOption[] = [] + const optionsToUpdate: ProductOption[] = [] data.forEach((option) => { const existingOption = existingOptionsMap.get(option.id) if (existingOption) { - upsertedOptions.push(existingOption) + const updatedOption = manager.assign(existingOption, option) + optionsToUpdate.push(updatedOption) } else { const newOption = (manager as SqlEntityManager).create( ProductOption, option as RequiredEntityData ) - optionToCreate.push(newOption) + optionsToCreate.push(newOption) } }) - if (optionToCreate.length) { - manager.persist(optionToCreate) - upsertedOptions.push(...optionToCreate) + if (optionsToCreate.length) { + manager.persist(optionsToCreate) + upsertedOptions.push(...optionsToCreate) + } + + if (optionsToUpdate.length) { + manager.persist(optionsToUpdate) + upsertedOptions.push(...optionsToUpdate) } return upsertedOptions diff --git a/packages/product/src/repositories/product-tag.ts b/packages/product/src/repositories/product-tag.ts index fb04e13d6bf4b..88628bdd8b9e7 100644 --- a/packages/product/src/repositories/product-tag.ts +++ b/packages/product/src/repositories/product-tag.ts @@ -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[] = [] + 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 diff --git a/packages/product/src/repositories/product-type.ts b/packages/product/src/repositories/product-type.ts index b23989f538d70..d2f3e2171067e 100644 --- a/packages/product/src/repositories/product-type.ts +++ b/packages/product/src/repositories/product-type.ts @@ -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[] = [] + 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 From 453541c5b8431f762d0f5e900ace5c17b6759128 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 10:41:05 +0100 Subject: [PATCH 16/21] Add integration tests for product options upsert --- .../services/product-option/index.ts | 171 ++++++++++++------ .../src/repositories/product-option.ts | 6 +- 2 files changed, 114 insertions(+), 63 deletions(-) diff --git a/packages/product/integration-tests/__tests__/services/product-option/index.ts b/packages/product/integration-tests/__tests__/services/product-option/index.ts index 514f03a1a3258..61f552c29261a 100644 --- a/packages/product/integration-tests/__tests__/services/product-option/index.ts +++ b/packages/product/integration-tests/__tests__/services/product-option/index.ts @@ -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 - }] - ) - - const [productOption] = await service.list({ - title: "UK" - }, { - relations: ["product"], - }) + product: productOne, + }, + ]) + 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, + }), + }), + ]) + ) + }) + }) }) diff --git a/packages/product/src/repositories/product-option.ts b/packages/product/src/repositories/product-option.ts index 6531b479286d7..5f7c10e8d85df 100644 --- a/packages/product/src/repositories/product-option.ts +++ b/packages/product/src/repositories/product-option.ts @@ -4,7 +4,6 @@ import { FilterQuery as MikroFilterQuery, FindOptions as MikroOptions, LoadStrategy, - RequiredEntityData, } from "@mikro-orm/core" import { SqlEntityManager } from "@mikro-orm/postgresql" import { Product, ProductOption } from "@models" @@ -191,10 +190,7 @@ export class ProductOptionRepository extends DALUtils.MikroOrmAbstractBaseReposi const updatedOption = manager.assign(existingOption, option) optionsToUpdate.push(updatedOption) } else { - const newOption = (manager as SqlEntityManager).create( - ProductOption, - option as RequiredEntityData - ) + const newOption = manager.create(ProductOption, option) optionsToCreate.push(newOption) } }) From 7af03cb2a259356f794757ae5858a35f61b80f49 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 10:43:49 +0100 Subject: [PATCH 17/21] rm unnecessary return --- packages/pricing/src/services/pricing-module.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/pricing/src/services/pricing-module.ts b/packages/pricing/src/services/pricing-module.ts index 7d432006f406d..a0b853c4fc93e 100644 --- a/packages/pricing/src/services/pricing-module.ts +++ b/packages/pricing/src/services/pricing-module.ts @@ -613,8 +613,6 @@ export default class PricingModuleService< sharedContext ) } - - return priceSets } @InjectTransactionManager("baseRepository_") From fbee853ecde67c35f82718fbbb17b30edb0101d1 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 11:30:55 +0100 Subject: [PATCH 18/21] fix product prices workflow issue --- .../update-products-variants-prices.ts | 52 ++++++++++++++----- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/packages/workflows/src/handlers/product/update-products-variants-prices.ts b/packages/workflows/src/handlers/product/update-products-variants-prices.ts index 548de0b0df66e..86f9f6ccd64b6 100644 --- a/packages/workflows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/workflows/src/handlers/product/update-products-variants-prices.ts @@ -2,6 +2,9 @@ import { ProductTypes, WorkflowTypes } from "@medusajs/types" import { MedusaError } from "@medusajs/utils" import { WorkflowArguments } from "../../helper" +import IsolatePricingDomainFeatureFlag from "@medusajs/medusa/dist/loaders/feature-flags/isolate-pricing-domain" +import { ModuleRegistrationName } from "@medusajs/modules-sdk" +import { Region } from "@medusajs/medusa" type ProductHandle = string type VariantIndexAndPrices = { @@ -37,6 +40,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,33 +60,56 @@ 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, rules: {}, } - // TODO: fetch all regions using .list and associate them here 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")) { + let regions: Region[] = [] + let regionMap = new Map() + if (regionIds.size) { + regions = await regionService.list({ + id: [...regionIds], + }) + regionMap = new Map(regions.map((r) => [r.id, r])) + } + + if (regions.length) { + 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, + } + + delete price.region_id + } + }) + } + } + + if (featureFlagRouter.isFeatureEnabled(IsolatePricingDomainFeatureFlag.key)) { const remoteLink = container.resolve("remoteLink") - const pricingModuleService = container.resolve("pricingModuleService") + const pricingModuleService = container.resolve( + ModuleRegistrationName.PRICING + ) const priceSetsToCreate = variantIdsPricesData.map(({ variantId }) => ({ rules: [{ rule_attribute: "region_id" }], From 9ba71eda9660e1f70898d9e941c0c6015acfde5d Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 11:37:58 +0100 Subject: [PATCH 19/21] cleanup --- .../handlers/product/update-products-variants-prices.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/workflows/src/handlers/product/update-products-variants-prices.ts b/packages/workflows/src/handlers/product/update-products-variants-prices.ts index 86f9f6ccd64b6..879d429d4b12f 100644 --- a/packages/workflows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/workflows/src/handlers/product/update-products-variants-prices.ts @@ -80,16 +80,12 @@ export async function updateProductsVariantsPrices({ }) } - let regions: Region[] = [] - let regionMap = new Map() if (regionIds.size) { - regions = await regionService.list({ + const regions = await regionService.list({ id: [...regionIds], }) - regionMap = new Map(regions.map((r) => [r.id, r])) - } + const regionMap = new Map(regions.map((r) => [r.id, r])) - if (regions.length) { for (const [, prices] of variantPricesMap.entries()) { prices.forEach((price) => { if (price.region_id) { From d6551f114015fa7c120f709ec00d09e33e1d2bbd Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 11:58:29 +0100 Subject: [PATCH 20/21] fix flag --- .../src/handlers/product/update-products-variants-prices.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/workflows/src/handlers/product/update-products-variants-prices.ts b/packages/workflows/src/handlers/product/update-products-variants-prices.ts index 879d429d4b12f..d865ef076f7e3 100644 --- a/packages/workflows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/workflows/src/handlers/product/update-products-variants-prices.ts @@ -2,7 +2,6 @@ import { ProductTypes, WorkflowTypes } from "@medusajs/types" import { MedusaError } from "@medusajs/utils" import { WorkflowArguments } from "../../helper" -import IsolatePricingDomainFeatureFlag from "@medusajs/medusa/dist/loaders/feature-flags/isolate-pricing-domain" import { ModuleRegistrationName } from "@medusajs/modules-sdk" import { Region } from "@medusajs/medusa" @@ -101,7 +100,7 @@ export async function updateProductsVariantsPrices({ } } - if (featureFlagRouter.isFeatureEnabled(IsolatePricingDomainFeatureFlag.key)) { + if (featureFlagRouter.isFeatureEnabled("isolate_pricing_domain")) { const remoteLink = container.resolve("remoteLink") const pricingModuleService = container.resolve( ModuleRegistrationName.PRICING From 104023d409c9acf1b2010126d5aef23504393618 Mon Sep 17 00:00:00 2001 From: adrien2p Date: Fri, 3 Nov 2023 12:06:43 +0100 Subject: [PATCH 21/21] fix model --- .../src/handlers/product/update-products-variants-prices.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/workflows/src/handlers/product/update-products-variants-prices.ts b/packages/workflows/src/handlers/product/update-products-variants-prices.ts index d865ef076f7e3..49c2f049e3063 100644 --- a/packages/workflows/src/handlers/product/update-products-variants-prices.ts +++ b/packages/workflows/src/handlers/product/update-products-variants-prices.ts @@ -3,7 +3,6 @@ import { ProductTypes, WorkflowTypes } from "@medusajs/types" import { MedusaError } from "@medusajs/utils" import { WorkflowArguments } from "../../helper" import { ModuleRegistrationName } from "@medusajs/modules-sdk" -import { Region } from "@medusajs/medusa" type ProductHandle = string type VariantIndexAndPrices = { @@ -83,7 +82,7 @@ export async function updateProductsVariantsPrices({ const regions = await regionService.list({ id: [...regionIds], }) - const regionMap = new Map(regions.map((r) => [r.id, r])) + const regionMap = new Map(regions.map((r) => [r.id, r])) for (const [, prices] of variantPricesMap.entries()) { prices.forEach((price) => {