diff --git a/src/modules/admin/controllers/brand.controller.ts b/src/modules/admin/controllers/brand.controller.ts index 719a73a..8e2ed11 100644 --- a/src/modules/admin/controllers/brand.controller.ts +++ b/src/modules/admin/controllers/brand.controller.ts @@ -1,6 +1,6 @@ import rateLimit from "express-rate-limit"; import { inject } from "inversify"; -import { controller, httpDelete, httpPatch, httpPost, requestBody, requestParam } from "inversify-express-utils"; +import { controller, httpDelete, httpGet, httpPatch, httpPost, requestBody, requestParam } from "inversify-express-utils"; import { HttpStatus } from "../../../common"; import { BaseController } from "../../../common/base/controller"; @@ -86,4 +86,14 @@ export class AdminBrandController extends BaseController { const data = await this.brandService.deleteById(id); return this.response({ data }); } + + @ApiOperation("get brand detail") + @ApiResponse("successful", HttpStatus.Ok) + @ApiParam("id", "id of brand") + @ApiAuth() + @httpGet("/:id", Guard.authAdmin()) + public async getBrand(@requestParam("id") id: string) { + const data = await this.brandService.getBrandDetail(id); + return this.response({ data }); + } } diff --git a/src/modules/admin/controllers/order.controller.ts b/src/modules/admin/controllers/order.controller.ts index 7b45e01..f928199 100644 --- a/src/modules/admin/controllers/order.controller.ts +++ b/src/modules/admin/controllers/order.controller.ts @@ -228,4 +228,24 @@ export class AdminOrderController extends BaseController { const { pager } = this.paginate(data.count); return this.response({ pager, orders: data.orders, priceRange }); } + + @ApiOperation("get an order details of user") + @ApiResponse("successful", HttpStatus.Ok) + @ApiParam("orderId", "id of order", true) + @ApiAuth() + @httpGet("/:orderId/user", Guard.authAdmin(), Guard.checkAdminPermissions([PermissionEnum.ORDER])) + public async getUserOrderDetail(@requestParam("orderId") orderId: string) { + const data = await this.orderService.getUserOrderDetailAsAdmin(+orderId); + return this.response(data); + } + + @ApiOperation("get an order details of seller") + @ApiResponse("successful", HttpStatus.Ok) + @ApiParam("orderId", "id of order", true) + @ApiAuth() + @httpGet("/:orderId/seller", Guard.authAdmin(), Guard.checkAdminPermissions([PermissionEnum.ORDER])) + public async getSellerOrderDetail(@requestParam("orderId") orderId: string) { + const data = await this.orderService.getSellerOrderDetailAsAdmin(+orderId); + return this.response(data); + } } diff --git a/src/modules/admin/controllers/warranty.controller.ts b/src/modules/admin/controllers/warranty.controller.ts index 60372f0..fea2d84 100644 --- a/src/modules/admin/controllers/warranty.controller.ts +++ b/src/modules/admin/controllers/warranty.controller.ts @@ -59,4 +59,14 @@ export class AdminWarrantyController extends BaseController { const data = await this.warrantyService.deleteById(+id); return this.response(data); } + + @ApiOperation("get warranty with its id") + @ApiResponse("successful", HttpStatus.Ok) + @ApiParam("id", "id of warranty") + @ApiAuth() + @httpDelete("/:id", Guard.authAdmin()) + public async getWarranty(@requestParam("id") id: string) { + const data = await this.warrantyService.getWarranty(id); + return this.response(data); + } } diff --git a/src/modules/brand/brand.service.ts b/src/modules/brand/brand.service.ts index 9b4a899..ecfa5a6 100644 --- a/src/modules/brand/brand.service.ts +++ b/src/modules/brand/brand.service.ts @@ -117,6 +117,15 @@ class BrandService { async getPendingBrandsCount() { return await this.brandRepo.getPendingBrandsCount(); } + + async getBrandDetail(id: string) { + const brand = await this.brandRepo.model.findOne({ _id: id, deleted: false }).populate("category"); + if (!brand) throw new BadRequestError(BrandMessage.NotFound); + + return { + brand, + }; + } } export { BrandService }; diff --git a/src/modules/order/order.repository.ts b/src/modules/order/order.repository.ts index b62606b..91a95f8 100644 --- a/src/modules/order/order.repository.ts +++ b/src/modules/order/order.repository.ts @@ -1641,6 +1641,204 @@ class OrderItemRepo extends BaseRepository { ]); } + async getSellerOrderDetailForAdminPanel(orderId: number, shopIds: Types.ObjectId[]) { + return this.model.aggregate([ + { + $match: { + order: orderId, + shop: { $in: shopIds }, + }, + }, + { + $lookup: { + from: "orders", + localField: "order", + foreignField: "_id", + as: "order", + }, + }, + { + $unwind: "$order", + }, + { + $lookup: { + from: "cartpayments", + localField: "order.payment", + foreignField: "_id", + as: "order.payment", + }, + }, + { + $unwind: "$order.payment", + }, + { + $lookup: { + from: "paymentmethods", + localField: "order.payment.payment_method", + foreignField: "_id", + as: "order.payment.payment_method", + }, + }, + { + $unwind: "$order.payment.payment_method", + }, + { + $lookup: { + from: "users", + localField: "order.user", + foreignField: "_id", + as: "order.user", + }, + }, + { + $unwind: "$order.user", + }, + { + $unwind: "$shipmentItems", + }, + { + $lookup: { + from: "products", + localField: "shipmentItems.product", + foreignField: "_id", + as: "shipmentItems.product", + }, + }, + { + $unwind: "$shipmentItems.product", + }, + { + $lookup: { + from: "productvariants", + localField: "shipmentItems.variant", + foreignField: "_id", + as: "shipmentItems.variant", + }, + }, + { + $unwind: "$shipmentItems.variant", + }, + { + $lookup: { + from: "warranties", + localField: "shipmentItems.variant.warranty", + foreignField: "_id", + as: "shipmentItems.variant.warranty", + }, + }, + { + $unwind: { + path: "$shipmentItems.variant.warranty", + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: "colors", + localField: "shipmentItems.variant.color", + foreignField: "_id", + as: "shipmentItems.variant.color", + }, + }, + { + $unwind: { + path: "$shipmentItems.variant.color", + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: "sizes", + localField: "shipmentItems.variant.size", + foreignField: "_id", + as: "shipmentItems.variant.size", + }, + }, + { + $unwind: { + path: "$shipmentItems.variant.size", + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: "meterages", + localField: "shipmentItems.variant.meterage", + foreignField: "_id", + as: "shipmentItems.variant.meterage", + }, + }, + { + $unwind: { + path: "$shipmentItems.variant.meterage", + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: "shipments", + localField: "shipper", + foreignField: "_id", + as: "shipper", + }, + }, + { + $unwind: "$shipper", + }, + { + $group: { + _id: "$order._id", + user: { $first: "$order.user" }, + payment: { $first: "$order.payment" }, + shipmentAddress: { $first: "$order.shipmentAddress" }, + orderStatus: { $first: "$order.orderStatus" }, + createdAt: { $first: "$order.createdAt" }, + orderItems: { + $first: { + _id: "$_id", + order_id: "$order._id", + shop: "$shop", + shipper: "$shipper", + totalSellingPrice: "$totalSellingPrice", + totalRetailPrice: "$totalRetailPrice", + totalShipmentCost: "$totalShipmentCost", + totalPaymentPrice: "$totalPaymentPrice", + itemsCount: "$itemsCount", + trackCode: "$trackCode", + postingDate: "$postingDate", + postingReceipt: "$postingReceipt", + status: "$status", + }, + }, + shipmentItems: { + $push: { + _id: "$shipmentItems._id", + product: "$shipmentItems.product", + variant: "$shipmentItems.variant", + quantity: "$shipmentItems.quantity", + cancelled_quantity: "$shipmentItems.cancelled_quantity", + returned_quantity: "$shipmentItems.returned_quantity", + selling_price: "$shipmentItems.selling_price", + retail_price: "$shipmentItems.retail_price", + discount_percent: "$shipmentItems.discount_percent", + shipmentCost: "$shipmentItems.shipmentCost", + }, + }, + // totalSellingPrice: { $sum: { $multiply: ["$shipmentItems.selling_price", "$shipmentItems.quantity"] } }, + // totalRetailPrice: { $sum: { $multiply: ["$shipmentItems.retail_price", "$shipmentItems.quantity"] } }, + // totalShipmentCost: { $sum: "$shipmentItems.shipmentCost" }, + // itemsCount: { $sum: "$shipmentItems.quantity" }, + }, + }, + { + $addFields: { + "orderItems.shipmentItems": "$shipmentItems", + // totalPaymentPrice: { $add: ["$totalSellingPrice", "$totalShipmentCost"] }, + }, + }, + ]); + } + async getSellerSalesStats(shopId: string, queries: { start?: string; end?: string }) { // Parse the date range from queries, converting from Persian to Gregorian if necessary const startDate = queries.start ? new Date(TimeService.convertPersianToGregorian(queries.start)) : null; diff --git a/src/modules/order/order.service.ts b/src/modules/order/order.service.ts index 015aa2a..4f716aa 100644 --- a/src/modules/order/order.service.ts +++ b/src/modules/order/order.service.ts @@ -322,6 +322,29 @@ class OrderService { } //####################################################### //####################################################### + + async getUserOrderDetailAsAdmin(orderId: number) { + const { order } = await this.validateAdminUserOrder(orderId); + + const doc = await this.orderRepo.getUserOrderDetail(orderId, order.user._id.toString()); + const cleanedOrder = SellerOrdersDTO.transformOrder(doc[0]); + + return { order: cleanedOrder }; + } + //####################################################### + //####################################################### + + async getSellerOrderDetailAsAdmin(orderId: number) { + const { shopIds } = await this.validateAdminSellerOrder(orderId); + + const doc = await this.orderItemRepo.getSellerOrderDetailForAdminPanel(orderId, shopIds); + + const cleanedOrder = SellerOrdersDTO.transformOrder(doc[0]); + + return { order: cleanedOrder }; + } + //####################################################### + //####################################################### async getSellerSalesStats(sellerId: string, queries: { start: string; end: string }) { const shop = await this.shopRepo.model.findOne({ owner: sellerId }); if (!shop) throw new BadRequestError(ShopMessage.ShopNotFound); @@ -365,6 +388,30 @@ class OrderService { return { order, orderItems }; } + //####################################################### + //####################################################### + private async validateAdminUserOrder(orderId: number) { + const order = await this.orderRepo.model.findOne({ _id: orderId }); + if (!order) throw new BadRequestError(OrderMessage.NotFound); + + const orderItems = await this.orderItemRepo.model.find({ order: order._id }); + if (!orderItems || orderItems.length === 0) throw new BadRequestError(OrderMessage.OrderItemsNotFound); + + return { order, orderItems }; + } + //####################################################### + //####################################################### + private async validateAdminSellerOrder(orderId: number) { + const order = await this.orderRepo.model.findOne({ _id: orderId }).lean(); + if (!order) throw new BadRequestError(OrderMessage.NotFound); + + const orderItems = await this.orderItemRepo.model.find({ order: orderId }).lean(); + const shopIds = orderItems.map((item) => item.shop._id); + + const orderItem = await this.orderItemRepo.model.findOne({ shop: { in: shopIds }, order: order._id }); + if (!orderItem) throw new BadRequestError(OrderMessage.OrderItemsNotFound); + return { order, orderItem, shopIds }; + } //####################################### //####################################### diff --git a/src/modules/warranty/warranty.service.ts b/src/modules/warranty/warranty.service.ts index 17033a1..08270ac 100644 --- a/src/modules/warranty/warranty.service.ts +++ b/src/modules/warranty/warranty.service.ts @@ -61,6 +61,15 @@ class WarrantyService { async getPendingWarranties() { return await this.warrantyRepo.pendingWarranties(); } + + async getWarranty(id: string) { + const warranty = await this.warrantyRepo.model.findOne({ _id: id, deleted: false }); + if (!warranty) throw new BadRequestError(CommonMessage.NotValidId); + + return { + warranty, + }; + } } export { WarrantyService };