From 3c0289b1daf4fadf247465a4bf7b07f272f5d562 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Mon, 13 Jul 2026 22:43:13 +0330 Subject: [PATCH] fix bug in category products --- src/modules/category/category.repository.ts | 34 +++++++++++++++++++ src/modules/product/Repository/product.ts | 24 +++++++++---- .../product/providers/product.service.ts | 6 ++-- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/src/modules/category/category.repository.ts b/src/modules/category/category.repository.ts index c09e8cb..855facd 100644 --- a/src/modules/category/category.repository.ts +++ b/src/modules/category/category.repository.ts @@ -19,6 +19,40 @@ class CategoryRepository extends BaseRepository { constructor() { super(CategoryModel); } + + async getDescendantCategoryIds(rootCategoryId: string): Promise { + const docs = await this.model.aggregate<{ _id: Types.ObjectId; descendants: { _id: Types.ObjectId }[] }>([ + { + $match: { + _id: new ObjectId(rootCategoryId), + deleted: false, + }, + }, + { + $graphLookup: { + from: "categories", + startWith: "$_id", + connectFromField: "_id", + connectToField: "parent", + as: "descendants", + restrictSearchWithMatch: { deleted: false }, + }, + }, + { + $project: { + _id: 1, + descendants: { _id: 1 }, + }, + }, + ]); + + if (!docs[0]) return []; + + const ids = new Set([docs[0]._id.toString()]); + for (const child of docs[0].descendants || []) ids.add(child._id.toString()); + return Array.from(ids); + } + async findByTitle(title_en: string, id?: string) { const query: Record = { title_en, deleted: false }; diff --git a/src/modules/product/Repository/product.ts b/src/modules/product/Repository/product.ts index 5cb4aab..134f9c5 100644 --- a/src/modules/product/Repository/product.ts +++ b/src/modules/product/Repository/product.ts @@ -16,16 +16,22 @@ export class ProductRepository extends BaseRepository { super(ProductModel); } - async getSellersProducts(shopIds: Types.ObjectId[], queryDto: SellerProductQueryDTO) { + async getSellersProducts(shopIds: Types.ObjectId[], queryDto: SellerProductQueryDTO & { categoryIds?: string[] }) { const { limit, skip } = paginationUtils(queryDto); + const categoryIds = queryDto.categoryIds?.length + ? queryDto.categoryIds.map((id) => new Types.ObjectId(id)) + : queryDto.categoryId + ? [new Types.ObjectId(queryDto.categoryId)] + : null; + const products = await this.model.aggregate([ { $match: { deleted: false, shop: { $in: shopIds }, - ...(queryDto.categoryId && { - category: new Types.ObjectId(queryDto.categoryId), + ...(categoryIds && { + category: { $in: categoryIds }, }), ...(queryDto.status && { status: queryDto.status as ProductStatus, @@ -249,16 +255,22 @@ export class ProductRepository extends BaseRepository { }; } - async getSellerProducts(shopId: string, queries: SellerProductQueryDTO) { + async getSellerProducts(shopId: string, queries: SellerProductQueryDTO & { categoryIds?: string[] }) { const { skip, limit } = paginationUtils(queries); + const categoryIds = queries.categoryIds?.length + ? queries.categoryIds.map((id) => new Types.ObjectId(id)) + : queries.categoryId + ? [new Types.ObjectId(queries.categoryId)] + : null; + const products = await this.model.aggregate([ { $match: { deleted: false, shop: new Types.ObjectId(shopId), - ...(queries.categoryId && { - category: new Types.ObjectId(queries.categoryId), + ...(categoryIds && { + category: { $in: categoryIds }, }), ...(queries.status && { status: queries.status as ProductStatus, diff --git a/src/modules/product/providers/product.service.ts b/src/modules/product/providers/product.service.ts index eef1239..e9b731c 100644 --- a/src/modules/product/providers/product.service.ts +++ b/src/modules/product/providers/product.service.ts @@ -853,7 +853,8 @@ class ProductService { async getAdminPanelProducts(ownerRef: OwnerRef, queryDto: SellerProductQueryDTO) { const shops = await this.shopeRepo.model.find({ ownerRef }).select("_id"); const shopIds = shops.map((shop) => shop._id); - const { docs, count } = await this.productRepo.getSellersProducts(shopIds, queryDto); + const categoryIds = queryDto.categoryId ? await this.categoryRepo.getDescendantCategoryIds(queryDto.categoryId) : undefined; + const { docs, count } = await this.productRepo.getSellersProducts(shopIds, { ...queryDto, categoryIds }); const brands = docs.map(({ brand }: any) => BrandDTO.transformBrand(brand)); const categories = docs.map(({ category }: any) => CategoryTreeDTO.transformCategory(category)); const products = docs.map((doc: IProduct) => SellerPanelProductDTO.transformProduct(doc)); @@ -870,7 +871,8 @@ class ProductService { const shop = await this.shopeRepo.model.findOne({ owner: ownerId }); if (!shop) throw new BadRequestError(ShopMessage.ShopNotFound); - const { docs, count, category } = await this.productRepo.getSellerProducts(shop._id.toString(), queryDto); + const categoryIds = queryDto.categoryId ? await this.categoryRepo.getDescendantCategoryIds(queryDto.categoryId) : undefined; + const { docs, count, category } = await this.productRepo.getSellerProducts(shop._id.toString(), { ...queryDto, categoryIds }); const brands = docs.map(({ brand }: any) => BrandDTO.transformBrand(brand)); const categories = category.map((cat: any) => CategoryTreeDTO.transformCategory(cat));