fix: Medusa service base method transaction (#7758)

**What**
Remove transaction decorator from the base medusa service method, the transaction will always be coming from the shared context. It fixes the issue that when you consume a base method directly it will return a proper tuple from the DB instead of the one from the entity map cc @VariableVic 

**NOTE**
This pr also fix some categories issues in the product module which was preventing the tests from working. if @sradevski you could have a look later, in the mean time we can still merge it

FIXES CORE-2342
This commit is contained in:
Adrien de Peretti authored and GitHub committed 2024-06-18 10:58:54 +00:00
1 parent 8410592239
commit e0b14519f1
8 files changed
+42 -42

No files matched your search

@@ -9,7 +9,7 @@ const baseRepoMock = {
const defaultContext = { __type: "MedusaContext", manager: baseRepoMock } const defaultContext = { __type: "MedusaContext", manager: baseRepoMock }
const defaultTransactionContext = { const defaultTransactionContext = {
__type: "MedusaContext", __type: "MedusaContext",
transactionManager: "transactionManager", manager: baseRepoMock,
} }
describe("Abstract Module Service Factory", () => { describe("Abstract Module Service Factory", () => {
@@ -20,11 +20,7 @@ import {
pluralize, pluralize,
upperCaseFirst, upperCaseFirst,
} from "../common" } from "../common"
import { import { InjectManager, MedusaContext } from "./decorators"
InjectManager,
InjectTransactionManager,
MedusaContext,
} from "./decorators"
import { ModuleRegistrationName } from "./definition" import { ModuleRegistrationName } from "./definition"
type BaseMethods = type BaseMethods =
@@ -384,11 +380,7 @@ export function MedusaService<
MedusaContext()(klassPrototype, methodName, contextIndex) MedusaContext()(klassPrototype, methodName, contextIndex)
const ManagerDecorator = readMethods.includes(method as BaseMethods) InjectManager("baseRepository_")(
? InjectManager
: InjectTransactionManager
ManagerDecorator("baseRepository_")(
klassPrototype, klassPrototype,
methodName, methodName,
descriptorMockRef descriptorMockRef
@@ -413,9 +405,7 @@ export function MedusaService<
serviceRegistrationName serviceRegistrationName
].retrieve(id, config, sharedContext) ].retrieve(id, config, sharedContext)
return await this.baseRepository_.serialize<T>(entities, { return await this.baseRepository_.serialize<T>(entities)
populate: true,
})
} }
applyMethod(methodImplementation, 2) applyMethod(methodImplementation, 2)
@@ -432,9 +422,7 @@ export function MedusaService<
const entities = await service.create(serviceData, sharedContext) const entities = await service.create(serviceData, sharedContext)
const response = Array.isArray(data) ? entities : entities[0] const response = Array.isArray(data) ? entities : entities[0]
return await this.baseRepository_.serialize<T | T[]>(response, { return await this.baseRepository_.serialize<T | T[]>(response)
populate: true,
})
} }
applyMethod(methodImplementation, 1) applyMethod(methodImplementation, 1)
@@ -451,9 +439,7 @@ export function MedusaService<
const entities = await service.update(serviceData, sharedContext) const entities = await service.update(serviceData, sharedContext)
const response = Array.isArray(data) ? entities : entities[0] const response = Array.isArray(data) ? entities : entities[0]
return await this.baseRepository_.serialize<T | T[]>(response, { return await this.baseRepository_.serialize<T | T[]>(response)
populate: true,
})
} }
applyMethod(methodImplementation, 1) applyMethod(methodImplementation, 1)
@@ -469,9 +455,7 @@ export function MedusaService<
const service = this.__container__[serviceRegistrationName] const service = this.__container__[serviceRegistrationName]
const entities = await service.list(filters, config, sharedContext) const entities = await service.list(filters, config, sharedContext)
return await this.baseRepository_.serialize<T[]>(entities, { return await this.baseRepository_.serialize<T[]>(entities)
populate: true,
})
} }
applyMethod(methodImplementation, 2) applyMethod(methodImplementation, 2)
@@ -488,12 +472,7 @@ export function MedusaService<
serviceRegistrationName serviceRegistrationName
].listAndCount(filters, config, sharedContext) ].listAndCount(filters, config, sharedContext)
return [ return [await this.baseRepository_.serialize<T[]>(entities), count]
await this.baseRepository_.serialize<T[]>(entities, {
populate: true,
}),
count,
]
} }
applyMethod(methodImplementation, 2) applyMethod(methodImplementation, 2)
@@ -542,10 +521,7 @@ export function MedusaService<
].softDelete(primaryKeyValues_, sharedContext) ].softDelete(primaryKeyValues_, sharedContext)
const softDeletedEntities = await this.baseRepository_.serialize<T[]>( const softDeletedEntities = await this.baseRepository_.serialize<T[]>(
entities, entities
{
populate: true,
}
) )
await this.eventBusModuleService_?.emit( await this.eventBusModuleService_?.emit(
@@ -1015,7 +1015,7 @@ moduleIntegrationTestRunner<Service>({
} }
expect(error.message).toEqual( expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })` `ProductCategory with id: does-not-exist was not found`
) )
}) })
@@ -1162,7 +1162,7 @@ moduleIntegrationTestRunner<Service>({
} }
expect(error.message).toEqual( expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })` `ProductCategory with id: does-not-exist was not found`
) )
}) })
@@ -565,7 +565,7 @@ moduleIntegrationTestRunner<IProductModuleService>({
} }
expect(error.message).toEqual( expect(error.message).toEqual(
`ProductCategory not found ({ id: 'does-not-exist' })` `ProductCategory with id: does-not-exist was not found`
) )
}) })
@@ -274,9 +274,17 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
const categories = await Promise.all( const categories = await Promise.all(
ids.map(async (id) => { ids.map(async (id) => {
const productCategory = await manager.findOneOrFail(ProductCategory, { const productCategory = await manager.findOne(ProductCategory, {
id, id,
}) })
if (!productCategory) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`ProductCategory with id: ${id} was not found`
)
}
manager.assign(productCategory, { deleted_at: new Date() }) manager.assign(productCategory, { deleted_at: new Date() })
return productCategory return productCategory
}) })
@@ -310,7 +318,7 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
await Promise.all( await Promise.all(
ids.map(async (id) => { ids.map(async (id) => {
const productCategory = await manager.findOneOrFail( const productCategory = await manager.findOne(
ProductCategory, ProductCategory,
{ id }, { id },
{ {
@@ -318,6 +326,13 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
} }
) )
if (!productCategory) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`ProductCategory with id: ${id} was not found`
)
}
if (productCategory.category_children.length > 0) { if (productCategory.category_children.length > 0) {
throw new MedusaError( throw new MedusaError(
MedusaError.Types.NOT_ALLOWED, MedusaError.Types.NOT_ALLOWED,
@@ -389,10 +404,17 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
const categories = await Promise.all( const categories = await Promise.all(
data.map(async (entry, i) => { data.map(async (entry, i) => {
const categoryData: Partial<ProductCategory> = { ...entry } const categoryData: Partial<ProductCategory> = { ...entry }
const productCategory = await manager.findOneOrFail(ProductCategory, { const productCategory = await manager.findOne(ProductCategory, {
id: categoryData.id, id: categoryData.id,
}) })
if (!productCategory) {
throw new MedusaError(
MedusaError.Types.NOT_FOUND,
`ProductCategory with id: ${categoryData.id} was not found`
)
}
// If the parent or rank are not changed, no need to reorder anything. // If the parent or rank are not changed, no need to reorder anything.
if ( if (
!isDefined(categoryData.parent_category_id) && !isDefined(categoryData.parent_category_id) &&
@@ -3,10 +3,10 @@ import {
FreeTextSearchFilterKey, FreeTextSearchFilterKey,
InjectManager, InjectManager,
InjectTransactionManager, InjectTransactionManager,
isDefined,
MedusaContext, MedusaContext,
MedusaError, MedusaError,
ModulesSdkUtils, ModulesSdkUtils,
isDefined,
} from "@medusajs/utils" } from "@medusajs/utils"
import { ProductCategory } from "@models" import { ProductCategory } from "@models"
import { ProductCategoryRepository } from "@repositories" import { ProductCategoryRepository } from "@repositories"
@@ -169,6 +169,7 @@ export default class ProductCategoryService<
await this.productCategoryRepository_.delete(ids, sharedContext) await this.productCategoryRepository_.delete(ids, sharedContext)
} }
@InjectTransactionManager("productCategoryRepository_")
async softDelete( async softDelete(
ids: string[], ids: string[],
@MedusaContext() sharedContext?: Context @MedusaContext() sharedContext?: Context
@@ -178,6 +179,7 @@ export default class ProductCategoryService<
).softDelete(ids, sharedContext)) as any ).softDelete(ids, sharedContext)) as any
} }
@InjectTransactionManager("productCategoryRepository_")
async restore( async restore(
ids: string[], ids: string[],
@MedusaContext() sharedContext?: Context @MedusaContext() sharedContext?: Context
@@ -31,7 +31,7 @@ const afterEach_ = async () => {
await TestDatabase.clearTables(sharedPgConnection) await TestDatabase.clearTables(sharedPgConnection)
} }
jest.setTimeout(50000) jest.setTimeout(100000)
describe("Workflow Orchestrator module", function () { describe("Workflow Orchestrator module", function () {
let workflowOrcModule: IWorkflowEngineService let workflowOrcModule: IWorkflowEngineService
@@ -12,7 +12,7 @@ import "../__fixtures__"
import { createScheduled } from "../__fixtures__/workflow_scheduled" import { createScheduled } from "../__fixtures__/workflow_scheduled"
import { DB_URL, TestDatabase } from "../utils" import { DB_URL, TestDatabase } from "../utils"
jest.setTimeout(50000) jest.setTimeout(100000)
const sharedPgConnection = knex<any, any>({ const sharedPgConnection = knex<any, any>({
client: "pg", client: "pg",