fix: Retrieve ancestors and/or descendants on product categories (#7226)
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
|
||||
import { IProductModuleService } from "@medusajs/types"
|
||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
||||
import { In } from "typeorm"
|
||||
import { breaking } from "../../../helpers/breaking"
|
||||
import {
|
||||
adminHeaders,
|
||||
@@ -16,7 +15,7 @@ let { Product } = {}
|
||||
medusaIntegrationTestRunner({
|
||||
env: {
|
||||
MEDUSA_FF_PRODUCT_CATEGORIES: true,
|
||||
// MEDUSA_FF_MEDUSA_V2: true,
|
||||
MEDUSA_FF_MEDUSA_V2: true,
|
||||
},
|
||||
testSuite: ({ dbConnection, getContainer, api }) => {
|
||||
let appContainer
|
||||
@@ -478,6 +477,37 @@ medusaIntegrationTestRunner({
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("adds all ancestors to categories in a nested way", async () => {
|
||||
const response = await api.get(
|
||||
`/admin/product-categories/${productCategoryChild1.id}?include_ancestors_tree=true`,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product_category).toEqual(
|
||||
expect.objectContaining({
|
||||
id: productCategoryChild1.id,
|
||||
name: "rank 1",
|
||||
rank: 1,
|
||||
parent_category: expect.objectContaining({
|
||||
id: productCategoryChild.id,
|
||||
name: "cashmere",
|
||||
rank: 0,
|
||||
parent_category: expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
name: "sweater",
|
||||
rank: 0,
|
||||
parent_category: expect.objectContaining({
|
||||
id: productCategoryParent.id,
|
||||
name: "Mens",
|
||||
rank: 0,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/product-categories", () => {
|
||||
@@ -525,25 +555,6 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: Remove in V2, unnecessary test
|
||||
it("throws an error when description is not a string", async () => {
|
||||
const payload = {
|
||||
name: "test",
|
||||
handle: "test",
|
||||
description: null,
|
||||
}
|
||||
|
||||
const error = await api
|
||||
.post(`/admin/product-categories`, payload, adminHeaders)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data.type).toEqual("invalid_data")
|
||||
// expect(error.response.data.message).toEqual(
|
||||
// "description must be a string"
|
||||
// )
|
||||
})
|
||||
|
||||
it("successfully creates a product category", async () => {
|
||||
const payload = {
|
||||
name: "test",
|
||||
@@ -570,16 +581,9 @@ medusaIntegrationTestRunner({
|
||||
is_active: false,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
...breaking(
|
||||
() => ({
|
||||
parent_category: expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
}),
|
||||
}),
|
||||
() => ({
|
||||
parent_category_id: productCategory.id,
|
||||
})
|
||||
),
|
||||
parent_category: expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
}),
|
||||
category_children: [],
|
||||
rank: 0,
|
||||
}),
|
||||
@@ -671,7 +675,8 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
describe("DELETE /admin/product-categories/:id", () => {
|
||||
// TODO: Should be migrate to V2
|
||||
describe.skip("DELETE /admin/product-categories/:id", () => {
|
||||
beforeEach(async () => {
|
||||
productCategoryParent = await simpleProductCategoryFactory(
|
||||
dbConnection,
|
||||
@@ -1221,245 +1226,7 @@ medusaIntegrationTestRunner({
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: Remove in V2, endpoint changed
|
||||
describe("POST /admin/product-categories/:id/products/batch", () => {
|
||||
beforeEach(async () => {
|
||||
productCategory = await simpleProductCategoryFactory(dbConnection, {
|
||||
id: "test-category",
|
||||
name: "test category",
|
||||
})
|
||||
})
|
||||
|
||||
it("should add products to a product category", async () => {
|
||||
const testProduct1 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-1",
|
||||
title: "test product 1",
|
||||
})
|
||||
|
||||
const testProduct2 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-2",
|
||||
title: "test product 2",
|
||||
})
|
||||
|
||||
const payload = {
|
||||
product_ids: [{ id: testProduct1.id }, { id: testProduct2.id }],
|
||||
}
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/product-categories/${productCategory.id}/products/batch`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product_category).toEqual(
|
||||
expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
const products = await dbConnection.manager.find(Product, {
|
||||
where: { id: In([testProduct1.id, testProduct2.id]) },
|
||||
relations: ["categories"],
|
||||
})
|
||||
|
||||
expect(products[0].categories).toEqual([
|
||||
expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
}),
|
||||
])
|
||||
|
||||
expect(products[1].categories).toEqual([
|
||||
expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
it("throws error when product ID is invalid", async () => {
|
||||
const payload = {
|
||||
product_ids: [{ id: "product-id-invalid" }],
|
||||
}
|
||||
|
||||
const error = await api
|
||||
.post(
|
||||
`/admin/product-categories/${productCategory.id}/products/batch`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data).toEqual({
|
||||
errors: ["Products product-id-invalid do not exist"],
|
||||
message:
|
||||
"Provided request body contains errors. Please check the data and retry the request",
|
||||
})
|
||||
})
|
||||
|
||||
it("throws error when category ID is invalid", async () => {
|
||||
const payload = { product_ids: [] }
|
||||
|
||||
const error = await api
|
||||
.post(
|
||||
`/admin/product-categories/invalid-category-id/products/batch`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(404)
|
||||
expect(error.response.data).toEqual({
|
||||
message: "ProductCategory with id: invalid-category-id was not found",
|
||||
type: "not_found",
|
||||
})
|
||||
})
|
||||
|
||||
it("throws error trying to expand not allowed relations", async () => {
|
||||
const payload = { product_ids: [] }
|
||||
|
||||
const error = await api
|
||||
.post(
|
||||
`/admin/product-categories/invalid-category-id/products/batch?expand=products`,
|
||||
payload,
|
||||
adminHeaders
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data).toEqual({
|
||||
message: "Requested fields [products] are not valid",
|
||||
type: "invalid_data",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// TODO: Remove in v2, endpoint changed
|
||||
describe("DELETE /admin/product-categories/:id/products/batch", () => {
|
||||
let testProduct1, testProduct2
|
||||
|
||||
beforeEach(async () => {
|
||||
testProduct1 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-1",
|
||||
title: "test product 1",
|
||||
})
|
||||
|
||||
testProduct2 = await simpleProductFactory(dbConnection, {
|
||||
id: "test-product-2",
|
||||
title: "test product 2",
|
||||
})
|
||||
|
||||
productCategory = await simpleProductCategoryFactory(dbConnection, {
|
||||
id: "test-category",
|
||||
name: "test category",
|
||||
products: [testProduct1, testProduct2],
|
||||
})
|
||||
})
|
||||
|
||||
it("should remove products from a product category", async () => {
|
||||
const payload = {
|
||||
product_ids: [{ id: testProduct2.id }],
|
||||
}
|
||||
|
||||
const response = await api.delete(
|
||||
`/admin/product-categories/${productCategory.id}/products/batch`,
|
||||
{
|
||||
...adminHeaders,
|
||||
data: payload,
|
||||
}
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.product_category).toEqual(
|
||||
expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
created_at: expect.any(String),
|
||||
updated_at: expect.any(String),
|
||||
})
|
||||
)
|
||||
|
||||
const products = await dbConnection.manager.find(Product, {
|
||||
where: { id: In([testProduct1.id, testProduct2.id]) },
|
||||
relations: ["categories"],
|
||||
})
|
||||
|
||||
expect(products[0].categories).toEqual([
|
||||
expect.objectContaining({
|
||||
id: productCategory.id,
|
||||
}),
|
||||
])
|
||||
|
||||
expect(products[1].categories).toEqual([])
|
||||
})
|
||||
|
||||
it("throws error when product ID is invalid", async () => {
|
||||
const payload = {
|
||||
product_ids: [{ id: "product-id-invalid" }],
|
||||
}
|
||||
|
||||
const error = await api
|
||||
.delete(
|
||||
`/admin/product-categories/${productCategory.id}/products/batch`,
|
||||
{
|
||||
...adminHeaders,
|
||||
data: payload,
|
||||
}
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data).toEqual({
|
||||
errors: ["Products product-id-invalid do not exist"],
|
||||
message:
|
||||
"Provided request body contains errors. Please check the data and retry the request",
|
||||
})
|
||||
})
|
||||
|
||||
it("throws error when category ID is invalid", async () => {
|
||||
const payload = { product_ids: [] }
|
||||
|
||||
const error = await api
|
||||
.delete(
|
||||
`/admin/product-categories/invalid-category-id/products/batch`,
|
||||
{
|
||||
...adminHeaders,
|
||||
data: payload,
|
||||
}
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(404)
|
||||
expect(error.response.data).toEqual({
|
||||
message: "ProductCategory with id: invalid-category-id was not found",
|
||||
type: "not_found",
|
||||
})
|
||||
})
|
||||
|
||||
it("throws error trying to expand not allowed relations", async () => {
|
||||
const payload = { product_ids: [] }
|
||||
|
||||
const error = await api
|
||||
.delete(
|
||||
`/admin/product-categories/invalid-category-id/products/batch?expand=products`,
|
||||
{
|
||||
...adminHeaders,
|
||||
data: payload,
|
||||
}
|
||||
)
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.response.status).toEqual(400)
|
||||
expect(error.response.data).toEqual({
|
||||
message: "Requested fields [products] are not valid",
|
||||
type: "invalid_data",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Skipping because the test is for V2 only
|
||||
describe.skip("POST /admin/product-categories/:id/products", () => {
|
||||
describe("POST /admin/product-categories/:id/products", () => {
|
||||
beforeEach(async () => {
|
||||
productCategory = await productModuleService.createCategory({
|
||||
name: "category parent",
|
||||
|
||||
@@ -369,6 +369,7 @@ export class RemoteJoiner {
|
||||
uniqueIds,
|
||||
relationship
|
||||
)
|
||||
|
||||
const isObj = isDefined(response.path)
|
||||
let resData = isObj ? response.data[response.path!] : response.data
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../types/routing"
|
||||
import { refetchCategory } from "../../helpers"
|
||||
import { refetchEntity } from "../../../../utils/refetch-entity"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<LinkMethodRequest>,
|
||||
@@ -24,11 +24,11 @@ export const POST = async (
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const category = await refetchCategory(
|
||||
req.params.id,
|
||||
const category = await refetchEntity(
|
||||
"product_category",
|
||||
id,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.filterableFields
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ product_category: category })
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import { refetchCategory } from "../helpers"
|
||||
import { refetchEntities } from "../../../utils/refetch-entity"
|
||||
import {
|
||||
AdminProductCategoryParamsType,
|
||||
AdminUpdateProductCategoryType,
|
||||
@@ -14,11 +14,11 @@ export const GET = async (
|
||||
req: AuthenticatedMedusaRequest<AdminProductCategoryParamsType>,
|
||||
res: MedusaResponse<AdminProductCategoryResponse>
|
||||
) => {
|
||||
const category = await refetchCategory(
|
||||
req.params.id,
|
||||
const [category] = await refetchEntities(
|
||||
"product_category",
|
||||
{ id: req.params.id, ...req.filterableFields },
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.filterableFields
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.json({ product_category: category })
|
||||
@@ -40,11 +40,11 @@ export const POST = async (
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const category = await refetchCategory(
|
||||
req.params.id,
|
||||
const [category] = await refetchEntities(
|
||||
"product_category",
|
||||
{ id, ...req.filterableFields },
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.filterableFields
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ product_category: category })
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export const refetchCategory = async (
|
||||
categoryId: string,
|
||||
scope: MedusaContainer,
|
||||
fields: string[],
|
||||
filterableFields: Record<string, any> = {}
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "product_category",
|
||||
variables: {
|
||||
filters: { ...filterableFields, id: categoryId },
|
||||
},
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
const categorys = await remoteQuery(queryObject)
|
||||
return categorys[0]
|
||||
}
|
||||
@@ -10,17 +10,36 @@ export const defaults = [
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"metadata",
|
||||
"*parent_category",
|
||||
"*category_children",
|
||||
"parent_category",
|
||||
"category_children",
|
||||
]
|
||||
|
||||
export const allowed = [
|
||||
"id",
|
||||
"name",
|
||||
"description",
|
||||
"handle",
|
||||
"is_active",
|
||||
"is_internal",
|
||||
"rank",
|
||||
"parent_category_id",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"metadata",
|
||||
"category_children",
|
||||
"parent_category",
|
||||
"products",
|
||||
]
|
||||
|
||||
export const retrieveProductCategoryConfig = {
|
||||
defaults,
|
||||
allowed,
|
||||
isList: false,
|
||||
}
|
||||
|
||||
export const listProductCategoryConfig = {
|
||||
defaults,
|
||||
allowed,
|
||||
defaultLimit: 50,
|
||||
isList: true,
|
||||
}
|
||||
|
||||
@@ -3,15 +3,11 @@ import {
|
||||
AdminProductCategoryListResponse,
|
||||
AdminProductCategoryResponse,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../types/routing"
|
||||
import { refetchCategory } from "./helpers"
|
||||
import { refetchEntities } from "../../utils/refetch-entity"
|
||||
import {
|
||||
AdminCreateProductCategoryType,
|
||||
AdminProductCategoriesParamsType,
|
||||
@@ -21,18 +17,13 @@ export const GET = async (
|
||||
req: AuthenticatedMedusaRequest<AdminProductCategoriesParamsType>,
|
||||
res: MedusaResponse<AdminProductCategoryListResponse>
|
||||
) => {
|
||||
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "product_category",
|
||||
variables: {
|
||||
filters: req.filterableFields,
|
||||
...req.remoteQueryConfig.pagination,
|
||||
},
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const { rows: product_categories, metadata } = await remoteQuery(queryObject)
|
||||
const { rows: product_categories, metadata } = await refetchEntities(
|
||||
"product_category",
|
||||
req.filterableFields,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.remoteQueryConfig.pagination
|
||||
)
|
||||
|
||||
res.json({
|
||||
product_categories,
|
||||
@@ -57,11 +48,11 @@ export const POST = async (
|
||||
throw errors[0].error
|
||||
}
|
||||
|
||||
const category = await refetchCategory(
|
||||
result.id,
|
||||
const [category] = await refetchEntities(
|
||||
"product_category",
|
||||
{ id: result.id, ...req.filterableFields },
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.filterableFields
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ product_category: category })
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
import { StoreProductCategoryResponse } from "@medusajs/types"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../types/routing"
|
||||
import { refetchCategory } from "../helpers"
|
||||
import { refetchEntities } from "../../../utils/refetch-entity"
|
||||
import { StoreProductCategoryParamsType } from "../validators"
|
||||
import { MedusaError } from "@medusajs/utils"
|
||||
|
||||
export const GET = async (
|
||||
req: AuthenticatedMedusaRequest<StoreProductCategoryParamsType>,
|
||||
res: MedusaResponse<StoreProductCategoryResponse>
|
||||
) => {
|
||||
const category = await refetchCategory(
|
||||
req.params.id,
|
||||
const category = await refetchEntities(
|
||||
"product_category",
|
||||
{ id: req.params.id, ...req.filterableFields },
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields,
|
||||
req.filterableFields
|
||||
req.remoteQueryConfig.pagination
|
||||
)
|
||||
|
||||
if (!category) {
|
||||
|
||||
@@ -9,7 +9,8 @@ export const refetchEntities = async (
|
||||
entryPoint: string,
|
||||
idOrFilter: string | object,
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
fields: string[],
|
||||
pagination: object = {}
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const filters = isString(idOrFilter) ? { id: idOrFilter } : idOrFilter
|
||||
@@ -23,7 +24,7 @@ export const refetchEntities = async (
|
||||
delete filters.context
|
||||
}
|
||||
|
||||
let variables = { filters, ...context }
|
||||
let variables = { filters, ...context, ...pagination }
|
||||
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint,
|
||||
|
||||
@@ -4,11 +4,11 @@ import {
|
||||
stringToSelectRelationObject,
|
||||
} from "@medusajs/utils"
|
||||
import { pick } from "lodash"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { MedusaError, isDefined } from "medusa-core-utils"
|
||||
import { BaseEntity } from "../interfaces"
|
||||
import { FindConfig, QueryConfig, RequestQueryFields } from "../types/common"
|
||||
import { featureFlagRouter } from "../loaders/feature-flags"
|
||||
import MedusaV2 from "../loaders/feature-flags/medusa-v2"
|
||||
import { FindConfig, QueryConfig, RequestQueryFields } from "../types/common"
|
||||
|
||||
export function pickByConfig<TModel extends BaseEntity>(
|
||||
obj: TModel | TModel[],
|
||||
|
||||
@@ -29,6 +29,51 @@ export const tempReorderRank = 99999
|
||||
|
||||
// eslint-disable-next-line max-len
|
||||
export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeRepository<ProductCategory> {
|
||||
buildFindOptions(
|
||||
findOptions: DAL.FindOptions<ProductCategory> = { where: {} },
|
||||
familyOptions: ProductCategoryTransformOptions = {}
|
||||
) {
|
||||
const findOptions_ = { ...findOptions }
|
||||
findOptions_.options ??= {}
|
||||
|
||||
const fields = (findOptions_.options.fields ??= [])
|
||||
const populate = (findOptions_.options.populate ??= [])
|
||||
|
||||
// Ref: Building descendants
|
||||
// mpath and parent_category_id needs to be added to the query for the tree building to be done accurately
|
||||
if (
|
||||
familyOptions.includeDescendantsTree ||
|
||||
familyOptions.includeAncestorsTree
|
||||
) {
|
||||
fields.indexOf("mpath") === -1 && fields.push("mpath")
|
||||
fields.indexOf("parent_category_id") === -1 &&
|
||||
fields.push("parent_category_id")
|
||||
}
|
||||
|
||||
const shouldExpandParent =
|
||||
familyOptions.includeAncestorsTree || fields.includes("parent_category")
|
||||
|
||||
if (shouldExpandParent) {
|
||||
populate.indexOf("parent_category") === -1 &&
|
||||
populate.push("parent_category")
|
||||
}
|
||||
|
||||
const shouldExpandChildren =
|
||||
familyOptions.includeDescendantsTree ||
|
||||
fields.includes("category_children")
|
||||
|
||||
if (shouldExpandChildren) {
|
||||
populate.indexOf("category_children") === -1 &&
|
||||
populate.push("category_children")
|
||||
}
|
||||
|
||||
Object.assign(findOptions_.options, {
|
||||
strategy: LoadStrategy.SELECT_IN,
|
||||
})
|
||||
|
||||
return findOptions_
|
||||
}
|
||||
|
||||
async find(
|
||||
findOptions: DAL.FindOptions<ProductCategory> = { where: {} },
|
||||
transformOptions: ProductCategoryTransformOptions = {},
|
||||
@@ -36,22 +81,7 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
|
||||
): Promise<ProductCategory[]> {
|
||||
const manager = super.getActiveManager<SqlEntityManager>(context)
|
||||
|
||||
const findOptions_ = { ...findOptions }
|
||||
const { includeDescendantsTree, includeAncestorsTree } = transformOptions
|
||||
findOptions_.options ??= {}
|
||||
const fields = (findOptions_.options.fields ??= [])
|
||||
|
||||
// Ref: Building descendants
|
||||
// mpath and parent_category_id needs to be added to the query for the tree building to be done accurately
|
||||
if (includeDescendantsTree || includeAncestorsTree) {
|
||||
fields.indexOf("mpath") === -1 && fields.push("mpath")
|
||||
fields.indexOf("parent_category_id") === -1 &&
|
||||
fields.push("parent_category_id")
|
||||
}
|
||||
|
||||
Object.assign(findOptions_.options, {
|
||||
strategy: LoadStrategy.SELECT_IN,
|
||||
})
|
||||
const findOptions_ = this.buildFindOptions(findOptions, transformOptions)
|
||||
|
||||
const productCategories = await manager.find(
|
||||
ProductCategory,
|
||||
@@ -59,14 +89,17 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
|
||||
findOptions_.options as MikroOptions<ProductCategory>
|
||||
)
|
||||
|
||||
if (!includeDescendantsTree && !includeAncestorsTree) {
|
||||
if (
|
||||
!transformOptions.includeDescendantsTree &&
|
||||
!transformOptions.includeAncestorsTree
|
||||
) {
|
||||
return productCategories
|
||||
}
|
||||
|
||||
return this.buildProductCategoriesWithTree(
|
||||
return await this.buildProductCategoriesWithTree(
|
||||
{
|
||||
descendants: includeDescendantsTree,
|
||||
ancestors: includeAncestorsTree,
|
||||
descendants: transformOptions.includeDescendantsTree,
|
||||
ancestors: transformOptions.includeAncestorsTree,
|
||||
},
|
||||
productCategories,
|
||||
findOptions_
|
||||
@@ -84,12 +117,6 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
|
||||
): Promise<ProductCategory[]> {
|
||||
const manager = super.getActiveManager<SqlEntityManager>(context)
|
||||
|
||||
const hasPopulateParentCategory = (
|
||||
findOptions.options?.populate ?? ([] as any)
|
||||
).find((pop) => pop.field === "parent_category")
|
||||
|
||||
include.ancestors = include.ancestors || hasPopulateParentCategory
|
||||
|
||||
const mpaths: any[] = []
|
||||
const parentMpaths = new Set()
|
||||
for (const cat of productCategories) {
|
||||
@@ -179,42 +206,27 @@ export class ProductCategoryRepository extends DALUtils.MikroOrmBaseTreeReposito
|
||||
context: Context = {}
|
||||
): Promise<[ProductCategory[], number]> {
|
||||
const manager = super.getActiveManager<SqlEntityManager>(context)
|
||||
|
||||
const findOptions_ = { ...findOptions }
|
||||
const { includeDescendantsTree, includeAncestorsTree } = transformOptions
|
||||
findOptions_.options ??= {}
|
||||
const fields = (findOptions_.options.fields ??= [])
|
||||
|
||||
// Ref: Building descendants
|
||||
// mpath and parent_category_id needs to be added to the query for the tree building to be done accurately
|
||||
if (includeDescendantsTree) {
|
||||
fields.indexOf("mpath") === -1 && fields.push("mpath")
|
||||
fields.indexOf("parent_category_id") === -1 &&
|
||||
fields.push("parent_category_id")
|
||||
}
|
||||
|
||||
Object.assign(findOptions_.options, {
|
||||
strategy: LoadStrategy.SELECT_IN,
|
||||
})
|
||||
|
||||
const findOptions_ = this.buildFindOptions(findOptions, transformOptions)
|
||||
|
||||
const [productCategories, count] = await manager.findAndCount(
|
||||
ProductCategory,
|
||||
findOptions_.where as MikroFilterQuery<ProductCategory>,
|
||||
findOptions_.options as MikroOptions<ProductCategory>
|
||||
)
|
||||
if (!includeDescendantsTree) {
|
||||
return [productCategories, count]
|
||||
}
|
||||
|
||||
if (!includeDescendantsTree && !includeAncestorsTree) {
|
||||
if (
|
||||
!transformOptions.includeDescendantsTree &&
|
||||
!transformOptions.includeAncestorsTree
|
||||
) {
|
||||
return [productCategories, count]
|
||||
}
|
||||
|
||||
return [
|
||||
await this.buildProductCategoriesWithTree(
|
||||
{
|
||||
descendants: includeDescendantsTree,
|
||||
ancestors: includeAncestorsTree,
|
||||
descendants: transformOptions.includeDescendantsTree,
|
||||
ancestors: transformOptions.includeAncestorsTree,
|
||||
},
|
||||
productCategories,
|
||||
findOptions_
|
||||
|
||||
Reference in New Issue
Block a user