From cafee96f280149edcb5bda893ac1eff56bf84ba8 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 31 Oct 2025 10:50:19 +0330 Subject: [PATCH 1/3] populate : return list reason --- src/modules/return/DTO/return.dto.ts | 14 +++++-- src/modules/return/return.repository.ts | 55 ++++++++++++++++++------- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/modules/return/DTO/return.dto.ts b/src/modules/return/DTO/return.dto.ts index ad7274f..86a7c66 100644 --- a/src/modules/return/DTO/return.dto.ts +++ b/src/modules/return/DTO/return.dto.ts @@ -64,12 +64,18 @@ export class ReturnOrderDTO { @Expose() total_price: number; - @Expose() - @Transform(({ value }) => new Date(value).toISOString()) + @Transform(({ value }) => { + if (!value) return null; + const date = new Date(value); + return isNaN(date.getTime()) ? null : date.toISOString(); + }) createdAt: string; - @Expose() - @Transform(({ value }) => new Date(value).toISOString()) + @Transform(({ value }) => { + if (!value) return null; + const date = new Date(value); + return isNaN(date.getTime()) ? null : date.toISOString(); + }) updatedAt: string; @Expose() diff --git a/src/modules/return/return.repository.ts b/src/modules/return/return.repository.ts index 01f0647..26ddd77 100644 --- a/src/modules/return/return.repository.ts +++ b/src/modules/return/return.repository.ts @@ -14,8 +14,8 @@ export class ReturnOrderRepo extends BaseRepository { } async getAllReturnsForAdmin(skip: number, limit: number) { - const [result] = await this.model.aggregate([ - // --- 1. Lookup order --- + const docs = await this.model.aggregate([ + // 1) lookup order { $lookup: { from: "orders", @@ -26,7 +26,7 @@ export class ReturnOrderRepo extends BaseRepository { }, { $unwind: { path: "$order", preserveNullAndEmptyArrays: true } }, - // --- 2. Lookup return order items --- + // 2) lookup return order items { $lookup: { from: "returnorderitems", @@ -36,8 +36,22 @@ export class ReturnOrderRepo extends BaseRepository { }, }, { $unwind: { path: "$returnOrderItems", preserveNullAndEmptyArrays: true } }, + { + $lookup: { + from: "returnreasons", // collection name of ReturnReasonModel + localField: "returnOrderItems.reason", + foreignField: "_id", + as: "returnOrderItems.reason", + }, + }, + { + $unwind: { + path: "$returnOrderItems.reason", + preserveNullAndEmptyArrays: true, + }, + }, - // --- 3. Lookup order items --- + // 4) lookup orderItem (the original order item) { $lookup: { from: "orderitems", @@ -49,7 +63,7 @@ export class ReturnOrderRepo extends BaseRepository { { $unwind: { path: "$orderItem", preserveNullAndEmptyArrays: true } }, { $addFields: { "returnOrderItems.orderItem": "$orderItem" } }, - // --- 4. Lookup shop --- + // 5) lookup shop from the orderItem { $lookup: { from: "shops", @@ -61,10 +75,24 @@ export class ReturnOrderRepo extends BaseRepository { { $unwind: { path: "$shop", preserveNullAndEmptyArrays: true } }, { $addFields: { shopName: "$shop.shopName" } }, - // --- 5. Sort before pagination --- + // 6) group back so each return order is a single document with array of items + { + $group: { + _id: "$_id", + order: { $first: "$order" }, + status: { $first: "$status" }, + total_price: { $first: "$total_price" }, + shopName: { $first: "$shopName" }, + createdAt: { $first: "$createdAt" }, + updatedAt: { $first: "$updatedAt" }, + returnOrderItems: { $push: "$returnOrderItems" }, + }, + }, + + // 7) sort (by createdAt) before pagination { $sort: { createdAt: -1 } }, - // --- 6. Facet for pagination + count --- + // 8) facet for pagination + count { $facet: { data: [ @@ -85,10 +113,7 @@ export class ReturnOrderRepo extends BaseRepository { comment: 1, reason: 1, imagesUrl: 1, - orderItem: { - _id: 1, - totalSellingPrice: 1, - }, + orderItem: 1, }, }, }, @@ -97,7 +122,7 @@ export class ReturnOrderRepo extends BaseRepository { }, }, - // --- 7. Flatten count field --- + // // 9) flatten count field { $addFields: { totalCount: { $ifNull: [{ $arrayElemAt: ["$totalCount.count", 0] }, 0] }, @@ -105,9 +130,11 @@ export class ReturnOrderRepo extends BaseRepository { }, ]); + const result = docs[0] || { data: [], totalCount: 0 }; + return { - count: result?.totalCount || 0, - docs: result?.data || [], + count: result.totalCount || 0, + docs: result.data || [], }; } From 88cc00ae6b858db41d7d8327cf41307a6dc56a33 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 31 Oct 2025 11:42:49 +0330 Subject: [PATCH 2/3] order status : shipped --- src/common/enums/order.enum.ts | 1 + src/modules/order/order.service.ts | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/common/enums/order.enum.ts b/src/common/enums/order.enum.ts index 7e91fef..9b13d0d 100644 --- a/src/common/enums/order.enum.ts +++ b/src/common/enums/order.enum.ts @@ -6,6 +6,7 @@ export enum PaymentStatus { export enum OrdersStatus { wait_payment = "wait_payment", process_by_seller = "process_by_sellers", + shipped = "shipped", cancelled_system = "cancelled_system", Cancelled = "cancelled", Delivered = "Delivered", diff --git a/src/modules/order/order.service.ts b/src/modules/order/order.service.ts index a3f3b64..47ff5e4 100644 --- a/src/modules/order/order.service.ts +++ b/src/modules/order/order.service.ts @@ -210,15 +210,26 @@ class OrderService { //####################################################### //####################################################### async insertNativeShopTrackCode(orderId: number, adminId: string, insertDto: InsertTrackCodeDTO) { - const { orderItem } = await this.validateSellerOrder(orderId, adminId); + const { orderItem, order } = await this.validateSellerOrder(orderId, adminId); + order.orderStatus = OrdersStatus.shipped; orderItem.trackCode = insertDto.trackCode; orderItem.postingDate = insertDto.postingDate; orderItem.postingReceipt = insertDto.postingReceipt; orderItem.status = OrderItemsStatus.Shipped; - await orderItem.save(); + const session = await startSession(); + session.startTransaction(); + try { + await orderItem.save(); + await order.save(); + } catch (error) { + await session.abortTransaction(); + throw error; + } finally { + await session.endSession(); + } return { message: OrderMessage.TrackingDetailInserted, orderItem, From ddd662b3b6fddf964e8891b4f08066b5135e5b3b Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 31 Oct 2025 17:36:12 +0330 Subject: [PATCH 3/3] add: order status in orders get --- src/common/types/query.type.ts | 1 + .../admin/controllers/order.controller.ts | 16 ++++++++++++++-- src/modules/order/order.repository.ts | 7 +++++-- src/modules/seller/seller.controller.ts | 8 +++++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/common/types/query.type.ts b/src/common/types/query.type.ts index 36e240c..ace4d42 100644 --- a/src/common/types/query.type.ts +++ b/src/common/types/query.type.ts @@ -51,6 +51,7 @@ export type SellerOrdersQueries = { limit: number; shipperId: string; status: string; + paymentStatus: string; since: number; maxPrice: number; minPrice: number; diff --git a/src/modules/admin/controllers/order.controller.ts b/src/modules/admin/controllers/order.controller.ts index fbf0787..1696746 100644 --- a/src/modules/admin/controllers/order.controller.ts +++ b/src/modules/admin/controllers/order.controller.ts @@ -159,7 +159,11 @@ export class AdminOrderController extends BaseController { @ApiQuery("limit", "the limit of return data") @ApiQuery("page", "the page want to get") @ApiQuery("shipperId", "shipper id") - @ApiQuery("status", "status of payment ==> value = Completed | Cancelled | Pending ") + @ApiQuery( + "status", + "status of payment ==> value = wait_payment | process_by_sellers | shipped | cancelled_system | cancelled | Delivered", + ) + @ApiQuery("paymentStatus", "status of order ==> value = Completed | Cancelled | Pending ") @ApiQuery( "since", "time of order created ==> value should be standard timestamp since that time user want like == > Date.now() - (7 * 24 * 60 * 60 * 1000) ==> this mean from a week ago till now ", @@ -174,6 +178,7 @@ export class AdminOrderController extends BaseController { @queryParam("page") page: string, @queryParam("shipperId") shipperId: string, @queryParam("status") status: string, + @queryParam("paymentStatus") paymentStatus: string, @queryParam("since") since: string, @queryParam("maxPrice") maxPrice: string, @queryParam("minPrice") minPrice: string, @@ -183,6 +188,7 @@ export class AdminOrderController extends BaseController { page: parseInt(page), shipperId, status, + paymentStatus, since: +since, maxPrice: +maxPrice, minPrice: +minPrice, @@ -198,7 +204,11 @@ export class AdminOrderController extends BaseController { @ApiQuery("limit", "the limit of return data") @ApiQuery("page", "the page want to get") @ApiQuery("shipperId", "shipper id") - @ApiQuery("status", "status of payment ==> value = Completed | Cancelled | Pending ") + @ApiQuery( + "status", + "status of payment ==> value = wait_payment | process_by_sellers | shipped | cancelled_system | cancelled | Delivered", + ) + @ApiQuery("paymentStatus", "status of order ==> value = Completed | Cancelled | Pending ") @ApiQuery( "since", "time of order created ==> value should be standard timestamp since that time user want like == > Date.now() - (7 * 24 * 60 * 60 * 1000) ==> this mean from a week ago till now ", @@ -212,6 +222,7 @@ export class AdminOrderController extends BaseController { @queryParam("page") page: string, @queryParam("shipperId") shipperId: string, @queryParam("status") status: string, + @queryParam("paymentStatus") paymentStatus: string, @queryParam("since") since: string, @queryParam("maxPrice") maxPrice: string, @queryParam("minPrice") minPrice: string, @@ -221,6 +232,7 @@ export class AdminOrderController extends BaseController { page: parseInt(page), shipperId, status, + paymentStatus, since: +since, maxPrice: +maxPrice, minPrice: +minPrice, diff --git a/src/modules/order/order.repository.ts b/src/modules/order/order.repository.ts index bc25d33..b2ef8fd 100644 --- a/src/modules/order/order.repository.ts +++ b/src/modules/order/order.repository.ts @@ -768,7 +768,10 @@ class OrderItemRepo extends BaseRepository { { $match: { ...(queries.status && { - "order.payment.paymentStatus": queries.status, + "order.orderStatus": queries.status, + }), + ...(queries.paymentStatus && { + "order.payment.paymentStatus": queries.paymentStatus, }), ...(queries.shipperId && { shipper: +queries.shipperId, @@ -882,7 +885,7 @@ class OrderItemRepo extends BaseRepository { }, { $sort: { - "order.createdAt": -1, + createdAt: -1, }, }, { diff --git a/src/modules/seller/seller.controller.ts b/src/modules/seller/seller.controller.ts index 30ec2b0..69fe27e 100644 --- a/src/modules/seller/seller.controller.ts +++ b/src/modules/seller/seller.controller.ts @@ -75,7 +75,11 @@ class SellerController extends BaseController { @ApiQuery("limit", "the limit of return data") @ApiQuery("page", "the page want to get") @ApiQuery("shipperId", "shipper id") - @ApiQuery("status", "status of payment ==> value = Completed | Cancelled | Pending ") + @ApiQuery( + "status", + "status of payment ==> value = wait_payment | process_by_sellers | shipped | cancelled_system | cancelled | Delivered", + ) + @ApiQuery("paymentStatus", "status of order ==> value = Completed | Cancelled | Pending ") @ApiQuery( "since", "time of order created ==> value should be standard timestamp since that time user want like == > Date.now() - (7 * 24 * 60 * 60 * 1000) ==> this mean from a week ago till now ", @@ -91,6 +95,7 @@ class SellerController extends BaseController { @queryParam("page") page: string, @queryParam("shipperId") shipperId: string, @queryParam("status") status: string, + @queryParam("paymentStatus") paymentStatus: string, @queryParam("since") since: string, @queryParam("maxPrice") maxPrice: string, @queryParam("minPrice") minPrice: string, @@ -101,6 +106,7 @@ class SellerController extends BaseController { page: parseInt(page), shipperId, status, + paymentStatus, since: +since, maxPrice: +maxPrice, minPrice: +minPrice,