fix(medusa): fixes bug for mpath incorrectly updated for nested categories (#3311)
* chore: fix issue with mpath being incorrectly set * chore: address review changes
This commit is contained in:
1 parent
e8e7d7bb53
commit
68496ffe60
4 files changed
+152
-17
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(medusa): fixes bug for mpath incorrectly updated for nested categories
|
||||||
@@ -243,6 +243,17 @@ describe("/admin/product-categories", () => {
|
|||||||
describe("POST /admin/product-categories", () => {
|
describe("POST /admin/product-categories", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await adminSeeder(dbConnection)
|
await adminSeeder(dbConnection)
|
||||||
|
|
||||||
|
productCategoryParent = await simpleProductCategoryFactory(dbConnection, {
|
||||||
|
name: "category parent",
|
||||||
|
handle: "category-parent",
|
||||||
|
})
|
||||||
|
|
||||||
|
productCategory = await simpleProductCategoryFactory(dbConnection, {
|
||||||
|
name: "category",
|
||||||
|
handle: "category",
|
||||||
|
parent_category: productCategoryParent,
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@@ -267,11 +278,6 @@ describe("/admin/product-categories", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it("successfully creates a product category", async () => {
|
it("successfully creates a product category", async () => {
|
||||||
productCategoryParent = await simpleProductCategoryFactory(dbConnection, {
|
|
||||||
name: "category parent",
|
|
||||||
handle: "category-parent",
|
|
||||||
})
|
|
||||||
|
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
const response = await api.post(
|
const response = await api.post(
|
||||||
@@ -280,7 +286,7 @@ describe("/admin/product-categories", () => {
|
|||||||
name: "test",
|
name: "test",
|
||||||
handle: "test",
|
handle: "test",
|
||||||
is_internal: true,
|
is_internal: true,
|
||||||
parent_category_id: productCategoryParent.id,
|
parent_category_id: productCategory.id,
|
||||||
},
|
},
|
||||||
adminHeaders
|
adminHeaders
|
||||||
)
|
)
|
||||||
@@ -296,13 +302,49 @@ describe("/admin/product-categories", () => {
|
|||||||
created_at: expect.any(String),
|
created_at: expect.any(String),
|
||||||
updated_at: expect.any(String),
|
updated_at: expect.any(String),
|
||||||
parent_category: expect.objectContaining({
|
parent_category: expect.objectContaining({
|
||||||
id: productCategoryParent.id
|
id: productCategory.id
|
||||||
}),
|
}),
|
||||||
category_children: []
|
category_children: []
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("root parent returns children correctly on creating new category", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.post(
|
||||||
|
`/admin/product-categories`,
|
||||||
|
{
|
||||||
|
name: "last descendant",
|
||||||
|
parent_category_id: productCategory.id,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
const lastDescendant = response.data.product_category
|
||||||
|
|
||||||
|
const parentResponse = await api.get(
|
||||||
|
`/admin/product-categories/${productCategoryParent.id}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(parentResponse.data.product_category).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategoryParent.id,
|
||||||
|
category_children: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategory.id,
|
||||||
|
category_children: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: lastDescendant.id,
|
||||||
|
category_children: []
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("DELETE /admin/product-categories/:id", () => {
|
describe("DELETE /admin/product-categories/:id", () => {
|
||||||
@@ -381,14 +423,27 @@ describe("/admin/product-categories", () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await adminSeeder(dbConnection)
|
await adminSeeder(dbConnection)
|
||||||
|
|
||||||
productCategory = await simpleProductCategoryFactory(dbConnection, {
|
productCategoryParent = await simpleProductCategoryFactory(dbConnection, {
|
||||||
name: "skinny jeans",
|
name: "category parent",
|
||||||
handle: "skinny-jeans",
|
handle: "category-parent",
|
||||||
})
|
})
|
||||||
|
|
||||||
productCategory2 = await simpleProductCategoryFactory(dbConnection, {
|
productCategory = await simpleProductCategoryFactory(dbConnection, {
|
||||||
name: "sweater",
|
name: "category",
|
||||||
handle: "sweater",
|
handle: "category",
|
||||||
|
parent_category: productCategoryParent,
|
||||||
|
})
|
||||||
|
|
||||||
|
productCategoryChild = await simpleProductCategoryFactory(dbConnection, {
|
||||||
|
name: "category child",
|
||||||
|
handle: "category-child",
|
||||||
|
parent_category: productCategory,
|
||||||
|
})
|
||||||
|
|
||||||
|
productCategoryChild2 = await simpleProductCategoryFactory(dbConnection, {
|
||||||
|
name: "category child 2",
|
||||||
|
handle: "category-child-2",
|
||||||
|
parent_category: productCategoryChild,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -437,13 +492,13 @@ describe("/admin/product-categories", () => {
|
|||||||
const api = useApi()
|
const api = useApi()
|
||||||
|
|
||||||
const response = await api.post(
|
const response = await api.post(
|
||||||
`/admin/product-categories/${productCategory.id}`,
|
`/admin/product-categories/${productCategoryChild2.id}`,
|
||||||
{
|
{
|
||||||
name: "test",
|
name: "test",
|
||||||
handle: "test",
|
handle: "test",
|
||||||
is_internal: true,
|
is_internal: true,
|
||||||
is_active: true,
|
is_active: true,
|
||||||
parent_category_id: productCategory2.id,
|
parent_category_id: productCategory.id,
|
||||||
},
|
},
|
||||||
adminHeaders
|
adminHeaders
|
||||||
)
|
)
|
||||||
@@ -459,13 +514,52 @@ describe("/admin/product-categories", () => {
|
|||||||
created_at: expect.any(String),
|
created_at: expect.any(String),
|
||||||
updated_at: expect.any(String),
|
updated_at: expect.any(String),
|
||||||
parent_category: expect.objectContaining({
|
parent_category: expect.objectContaining({
|
||||||
id: productCategory2.id,
|
id: productCategory.id,
|
||||||
}),
|
}),
|
||||||
category_children: []
|
category_children: []
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("root parent returns children correctly on updating new category", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.post(
|
||||||
|
`/admin/product-categories/${productCategoryChild2.id}`,
|
||||||
|
{
|
||||||
|
parent_category_id: productCategory.id,
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
const lastDescendant = response.data.product_category
|
||||||
|
|
||||||
|
const parentResponse = await api.get(
|
||||||
|
`/admin/product-categories/${productCategoryParent.id}`,
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(parentResponse.data.product_category).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategoryParent.id,
|
||||||
|
category_children: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategory.id,
|
||||||
|
category_children: [
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategoryChild.id,
|
||||||
|
category_children: []
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: productCategoryChild2.id,
|
||||||
|
category_children: []
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("POST /admin/product-categories/:id/products/batch", () => {
|
describe("POST /admin/product-categories/:id/products/batch", () => {
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ class ProductCategoryService extends TransactionBaseService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a product category
|
* Creates a product category
|
||||||
* @param productCategory - params used to create
|
* @param productCategoryInput - parameters to create a product category
|
||||||
* @return created product category
|
* @return created product category
|
||||||
*/
|
*/
|
||||||
async create(
|
async create(
|
||||||
@@ -129,6 +129,9 @@ class ProductCategoryService extends TransactionBaseService {
|
|||||||
): Promise<ProductCategory> {
|
): Promise<ProductCategory> {
|
||||||
return await this.atomicPhase_(async (manager) => {
|
return await this.atomicPhase_(async (manager) => {
|
||||||
const pcRepo = manager.withRepository(this.productCategoryRepo_)
|
const pcRepo = manager.withRepository(this.productCategoryRepo_)
|
||||||
|
|
||||||
|
await this.transformParentIdToEntity(productCategoryInput)
|
||||||
|
|
||||||
let productCategory = pcRepo.create(productCategoryInput)
|
let productCategory = pcRepo.create(productCategoryInput)
|
||||||
productCategory = await pcRepo.save(productCategory)
|
productCategory = await pcRepo.save(productCategory)
|
||||||
|
|
||||||
@@ -157,6 +160,8 @@ class ProductCategoryService extends TransactionBaseService {
|
|||||||
this.productCategoryRepo_
|
this.productCategoryRepo_
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await this.transformParentIdToEntity(productCategoryInput)
|
||||||
|
|
||||||
let productCategory = await this.retrieve(productCategoryId)
|
let productCategory = await this.retrieve(productCategoryId)
|
||||||
|
|
||||||
for (const key in productCategoryInput) {
|
for (const key in productCategoryInput) {
|
||||||
@@ -253,6 +258,34 @@ class ProductCategoryService extends TransactionBaseService {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts an input object and transforms product_category_id
|
||||||
|
* into product_category entity.
|
||||||
|
* @param productCategoryInput - params used to create/update
|
||||||
|
* @return transformed productCategoryInput
|
||||||
|
*/
|
||||||
|
protected async transformParentIdToEntity(
|
||||||
|
productCategoryInput:
|
||||||
|
| CreateProductCategoryInput
|
||||||
|
| UpdateProductCategoryInput
|
||||||
|
): Promise<CreateProductCategoryInput | UpdateProductCategoryInput> {
|
||||||
|
// Typeorm only updates mpath when the category entity of the parent
|
||||||
|
// is passed into create/save. For this reason, everytime we create a
|
||||||
|
// category, we must fetch the entity and push to create
|
||||||
|
const parentCategoryId = productCategoryInput.parent_category_id
|
||||||
|
|
||||||
|
if (!parentCategoryId) {
|
||||||
|
return productCategoryInput
|
||||||
|
}
|
||||||
|
|
||||||
|
const parentCategory = await this.retrieve(parentCategoryId)
|
||||||
|
|
||||||
|
productCategoryInput.parent_category = parentCategory
|
||||||
|
delete productCategoryInput.parent_category_id
|
||||||
|
|
||||||
|
return productCategoryInput
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ProductCategoryService
|
export default ProductCategoryService
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Transform } from "class-transformer"
|
import { Transform } from "class-transformer"
|
||||||
import { IsNotEmpty, IsOptional, IsString, IsBoolean } from "class-validator"
|
import { IsNotEmpty, IsOptional, IsString, IsBoolean } from "class-validator"
|
||||||
|
import { ProductCategory } from "../models"
|
||||||
|
|
||||||
export type CreateProductCategoryInput = {
|
export type CreateProductCategoryInput = {
|
||||||
name: string
|
name: string
|
||||||
@@ -7,6 +8,7 @@ export type CreateProductCategoryInput = {
|
|||||||
is_internal?: boolean
|
is_internal?: boolean
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
parent_category_id?: string | null
|
parent_category_id?: string | null
|
||||||
|
parent_category?: ProductCategory | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UpdateProductCategoryInput = {
|
export type UpdateProductCategoryInput = {
|
||||||
@@ -15,6 +17,7 @@ export type UpdateProductCategoryInput = {
|
|||||||
is_internal?: boolean
|
is_internal?: boolean
|
||||||
is_active?: boolean
|
is_active?: boolean
|
||||||
parent_category_id?: string | null
|
parent_category_id?: string | null
|
||||||
|
parent_category?: ProductCategory | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AdminProductCategoriesReqBase {
|
export class AdminProductCategoriesReqBase {
|
||||||
|
|||||||
Reference in new issue
Block a user