first
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import { Expose, Type, plainToInstance } from "class-transformer";
|
||||
|
||||
import { FineRuleListDTO } from "./fineRule.dto";
|
||||
import { ProductListDTO } from "../../product/DTO/product.dto";
|
||||
|
||||
export class FineDto {
|
||||
@Expose()
|
||||
product: string;
|
||||
|
||||
@Expose()
|
||||
seller: string;
|
||||
|
||||
@Expose()
|
||||
orderItem: string;
|
||||
|
||||
@Expose()
|
||||
reason: string;
|
||||
|
||||
@Expose()
|
||||
fine_rule: string;
|
||||
|
||||
@Expose()
|
||||
fine_amount: number;
|
||||
}
|
||||
|
||||
export class FineListDTO {
|
||||
@Expose()
|
||||
_id: string;
|
||||
|
||||
@Expose()
|
||||
orderItemRef: string;
|
||||
|
||||
@Expose()
|
||||
reasonRef: string;
|
||||
|
||||
@Expose()
|
||||
fine_amount: number;
|
||||
|
||||
@Expose()
|
||||
createdAt: Date;
|
||||
|
||||
@Expose()
|
||||
fineRuleDetails: FineRuleListDTO;
|
||||
|
||||
@Expose()
|
||||
reasonDetails: any;
|
||||
|
||||
@Expose()
|
||||
orderItemsDetails: any;
|
||||
|
||||
@Expose()
|
||||
shipmentItem: any;
|
||||
|
||||
@Expose()
|
||||
@Type(() => ProductListDTO)
|
||||
product: ProductListDTO;
|
||||
|
||||
public static transformFineList(data: any): FineListDTO {
|
||||
const fineListDTO = plainToInstance(FineListDTO, data, {
|
||||
excludeExtraneousValues: true,
|
||||
enableImplicitConversion: true,
|
||||
});
|
||||
return fineListDTO;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Expose } from "class-transformer";
|
||||
import { IsNotEmpty, IsNumber, IsString } from "class-validator";
|
||||
|
||||
import { ApiProperty } from "../../../common/decorator/swggerDocs";
|
||||
|
||||
export class FineRuleDTO {
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
@IsString()
|
||||
@ApiProperty({ type: "string", description: "the title of fine", example: "تاخیر در تحویل" })
|
||||
title: string;
|
||||
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
@IsNumber()
|
||||
@ApiProperty({ type: "number", description: "the fine percentage of fine", example: "20" })
|
||||
fine_percentage: number;
|
||||
}
|
||||
|
||||
export class FineRuleListDTO {
|
||||
@Expose()
|
||||
_id: string;
|
||||
|
||||
@Expose()
|
||||
title: string;
|
||||
|
||||
@Expose()
|
||||
fine_percentage: number;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Expose } from "class-transformer";
|
||||
import { IsNumber, IsOptional, IsString } from "class-validator";
|
||||
|
||||
import { ApiProperty } from "../../../common/decorator/swggerDocs";
|
||||
|
||||
export class UpdateFineRuleDTO {
|
||||
@Expose()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@ApiProperty({ type: "string", description: "the title of fine", example: "تاخیر در تحویل" })
|
||||
title: string;
|
||||
|
||||
@Expose()
|
||||
@IsOptional()
|
||||
@IsNumber()
|
||||
@ApiProperty({ type: "number", description: "the fine percentage of fine", example: "20" })
|
||||
fine_percentage: number;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { Request } from "express";
|
||||
import { inject } from "inversify";
|
||||
import { controller, httpGet, queryParam, request } from "inversify-express-utils";
|
||||
|
||||
import { FineService } from "./fine.service";
|
||||
import { HttpStatus } from "../../common";
|
||||
import { BaseController } from "../../common/base/controller";
|
||||
import { ApiAuth, ApiOperation, ApiQuery, ApiResponse, ApiTags } from "../../common/decorator/swggerDocs";
|
||||
import { Guard } from "../../core/middlewares/guard.middleware";
|
||||
import { IOCTYPES } from "../../IOC/ioc.types";
|
||||
import { ISeller } from "../seller/models/Abstraction/ISeller";
|
||||
|
||||
@controller("/fine")
|
||||
@ApiTags("Fine")
|
||||
class FineController extends BaseController {
|
||||
@inject(IOCTYPES.FineService) fineService: FineService;
|
||||
|
||||
//return all fine rules
|
||||
|
||||
@ApiOperation("get list of fine rules")
|
||||
@ApiResponse("successful", HttpStatus.Ok)
|
||||
@httpGet("/rules")
|
||||
public async getFineRules() {
|
||||
const data = await this.fineService.getFineRules();
|
||||
return this.response(data);
|
||||
}
|
||||
|
||||
@ApiOperation("get all fine ==> login as seller")
|
||||
@ApiResponse("successful", HttpStatus.Ok)
|
||||
@ApiQuery("limit", "the limit of fines data")
|
||||
@ApiQuery("page", "the page want to get")
|
||||
@ApiAuth()
|
||||
@httpGet("/fines", Guard.authSeller())
|
||||
public async getAllFinesBySeller(@request() req: Request, @queryParam("limit") limit: string, @queryParam("page") page: string) {
|
||||
const seller = req.user as ISeller;
|
||||
const queries = {
|
||||
limit: parseInt(limit),
|
||||
page: parseInt(page),
|
||||
};
|
||||
const data = await this.fineService.getAllFinesBySeller(seller?._id.toString(), queries);
|
||||
const { pager } = this.paginate(data.count);
|
||||
return this.response({ pager, fineList: data.fineList });
|
||||
}
|
||||
}
|
||||
|
||||
export { FineController };
|
||||
@@ -0,0 +1,59 @@
|
||||
import { inject, injectable } from "inversify";
|
||||
|
||||
import { FineListDTO } from "./DTO/fine.dto";
|
||||
import { FineRuleDTO } from "./DTO/fineRule.dto";
|
||||
import { UpdateFineRuleDTO } from "./DTO/role-update.dto";
|
||||
import { FineRepo } from "./repository/fine.repository";
|
||||
import { FineRuleRepo } from "./repository/fineRule.repository";
|
||||
import { AdminFinesQueries, SellerFinesQueries } from "../../common/types/query.type";
|
||||
import { IOCTYPES } from "../../IOC/ioc.types";
|
||||
|
||||
@injectable()
|
||||
class FineService {
|
||||
@inject(IOCTYPES.FineRuleRepo) private fineRuleRepo: FineRuleRepo;
|
||||
@inject(IOCTYPES.FineRepo) private fineRepo: FineRepo;
|
||||
|
||||
async createFineRule(fineRuleDto: FineRuleDTO) {
|
||||
const fineRule = await this.fineRuleRepo.model.create(fineRuleDto);
|
||||
return { fineRule };
|
||||
}
|
||||
|
||||
async getFineRules() {
|
||||
const fineRules = await this.fineRuleRepo.model.find({ deleted: false });
|
||||
return { fineRules };
|
||||
}
|
||||
|
||||
async updateFineRule(ruleId: string, updateDto: UpdateFineRuleDTO) {
|
||||
const fineRule = await this.fineRuleRepo.model.findOneAndUpdate({ _id: ruleId }, updateDto, { new: true });
|
||||
return { fineRule };
|
||||
}
|
||||
|
||||
async getRuleWithId(ruleId: string) {
|
||||
const fineRule = await this.fineRuleRepo.findById(ruleId);
|
||||
return { fineRule };
|
||||
}
|
||||
|
||||
async deleteRule(ruleId: string) {
|
||||
const fineRule = await this.fineRuleRepo.model.findOneAndUpdate({ _id: ruleId }, { deleted: true }, { new: true });
|
||||
return { fineRule };
|
||||
}
|
||||
|
||||
async getAllFines(queries: AdminFinesQueries) {
|
||||
const { docs, count } = await this.fineRepo.findAllForAdmin(queries);
|
||||
const fineList = docs.map((doc: any) => FineListDTO.transformFineList(doc));
|
||||
|
||||
return { fineList, count };
|
||||
}
|
||||
|
||||
async getAllFinesBySeller(sellerId: string, queries: SellerFinesQueries) {
|
||||
const { docs, count } = await this.fineRepo.findAllBySeller(sellerId, queries);
|
||||
const fineList = docs.map((doc: any) => FineListDTO.transformFineList(doc));
|
||||
console.log(fineList);
|
||||
return {
|
||||
fineList,
|
||||
count,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { FineService };
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Types } from "mongoose";
|
||||
|
||||
import { OrderItemRefEnum, ReasonRefEnum } from "../fine.model";
|
||||
|
||||
export interface IFine {
|
||||
product: Types.ObjectId;
|
||||
seller: Types.ObjectId;
|
||||
orderItem: Types.ObjectId;
|
||||
orderItemRef: OrderItemRefEnum;
|
||||
fine_rule: Types.ObjectId;
|
||||
reason: Types.ObjectId;
|
||||
reasonRef: ReasonRefEnum;
|
||||
fine_amount: number;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface IFineRule {
|
||||
title: string;
|
||||
fine_percentage: number;
|
||||
deleted: boolean;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
import { IFine } from "./Abstraction/IFine";
|
||||
|
||||
export enum ReasonRefEnum {
|
||||
Cancel = "Cancel",
|
||||
Return = "Return",
|
||||
}
|
||||
|
||||
export enum OrderItemRefEnum {
|
||||
CancelOrderItem = "CancelOrderItem",
|
||||
ReturnOrderItem = "ReturnOrderItem",
|
||||
}
|
||||
|
||||
const FineSchema = new Schema<IFine>(
|
||||
{
|
||||
seller: { type: Schema.Types.ObjectId, ref: "Seller", required: true },
|
||||
orderItem: { type: Schema.Types.ObjectId, ref: "orderItemRef", required: true },
|
||||
orderItemRef: { type: String, enum: OrderItemRefEnum, required: true },
|
||||
fine_rule: { type: Schema.Types.ObjectId, ref: "FineRule", required: true },
|
||||
reason: { type: Schema.Types.ObjectId, refPath: "reasonRef", required: true },
|
||||
reasonRef: { type: String, enum: ReasonRefEnum, required: true },
|
||||
fine_amount: { type: Number, required: true },
|
||||
},
|
||||
{ timestamps: true, toJSON: { versionKey: false, virtuals: true }, id: false },
|
||||
);
|
||||
|
||||
const FineModel = model<IFine>("Fine", FineSchema);
|
||||
|
||||
export { FineModel };
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
import { IFineRule } from "./Abstraction/IFineRule";
|
||||
|
||||
const FineRuleSchema = new Schema<IFineRule>(
|
||||
{
|
||||
title: { type: String, required: true },
|
||||
fine_percentage: { type: Number, required: true },
|
||||
deleted: { type: Boolean, default: false },
|
||||
},
|
||||
{ timestamps: true, toJSON: { versionKey: false, virtuals: true }, id: false },
|
||||
);
|
||||
|
||||
const FineRuleModel = model<IFineRule>("FineRule", FineRuleSchema);
|
||||
|
||||
export { FineRuleModel };
|
||||
@@ -0,0 +1,335 @@
|
||||
import { Types } from "mongoose";
|
||||
|
||||
import { BaseRepository } from "../../../common/base/repository";
|
||||
import { SellerFinesQueries } from "../../../common/types/query.type";
|
||||
import { IFine } from "../models/Abstraction/IFine";
|
||||
import { FineModel } from "../models/fine.model";
|
||||
|
||||
export class FineRepo extends BaseRepository<IFine> {
|
||||
constructor() {
|
||||
super(FineModel);
|
||||
}
|
||||
|
||||
async findAllBySeller(sellerId: string, queries: SellerFinesQueries) {
|
||||
const page = queries.page || 1;
|
||||
const limit = queries.limit || 10;
|
||||
const skip = (page - 1) * limit;
|
||||
const docs = await this.model.aggregate([
|
||||
{
|
||||
$match: {
|
||||
seller: new Types.ObjectId(sellerId),
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "finerules",
|
||||
localField: "fine_rule",
|
||||
foreignField: "_id",
|
||||
as: "fineRuleDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$unwind: "$fineRuleDetails",
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
sellerDetails: { $arrayElemAt: ["$sellerDetails", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "cancelreasons",
|
||||
localField: "reason",
|
||||
foreignField: "_id",
|
||||
as: "cancelReasonDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
cancelReasonDetails: { $ifNull: ["$cancelReasonDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "returnreasons",
|
||||
localField: "reason",
|
||||
foreignField: "_id",
|
||||
as: "returnReasonDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
returnReasonDetails: { $ifNull: ["$returnReasonDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
reasonDetails: {
|
||||
$cond: {
|
||||
if: { $eq: ["$reasonRef", "Cancel"] },
|
||||
then: { $arrayElemAt: ["$cancelReasonDetails", 0] },
|
||||
else: { $arrayElemAt: ["$returnReasonDetails", 0] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$unset: ["cancelReasonDetails", "returnReasonDetails"],
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "cancelorderitems",
|
||||
localField: "orderItem",
|
||||
foreignField: "_id",
|
||||
as: "cancelOrderItemDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
cancelOrderItemDetails: { $ifNull: ["$cancelOrderItemDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "returnorderitems",
|
||||
localField: "orderItem",
|
||||
foreignField: "_id",
|
||||
as: "returnOrderItemDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
returnOrderItemDetails: { $ifNull: ["$returnOrderItemDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
orderItemsDetails: {
|
||||
$cond: {
|
||||
if: { $eq: ["$orderItemRef", "CancelOrderItem"] },
|
||||
then: { $arrayElemAt: ["$cancelOrderItemDetails", 0] },
|
||||
else: { $arrayElemAt: ["$returnOrderItemDetails", 0] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$unset: ["cancelOrderItemDetails", "returnOrderItemDetails"],
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "orderitems",
|
||||
localField: "orderItemsDetails.orderItem",
|
||||
foreignField: "_id",
|
||||
as: "orderItemsDetails.orderItem",
|
||||
},
|
||||
},
|
||||
{
|
||||
$unwind: "$orderItemsDetails.orderItem",
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
shipmentItem: {
|
||||
$arrayElemAt: ["$orderItemsDetails.orderItem.shipmentItems", 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "products",
|
||||
localField: "shipmentItem.product",
|
||||
foreignField: "_id",
|
||||
as: "product",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
product: { $arrayElemAt: ["$product", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$facet: {
|
||||
data: [{ $skip: skip }, { $limit: limit }],
|
||||
totalCount: [{ $count: "count" }],
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
totalCount: { $arrayElemAt: ["$totalCount.count", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
createdAt: -1,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
console.dir(docs[0], { depth: null });
|
||||
return {
|
||||
count: (docs[0]?.totalCount as number) || 0,
|
||||
docs: docs[0]?.data || [],
|
||||
};
|
||||
}
|
||||
|
||||
async findAllForAdmin(queries: SellerFinesQueries) {
|
||||
const page = queries.page || 1;
|
||||
const limit = queries.limit || 10;
|
||||
const skip = (page - 1) * limit;
|
||||
const docs = await this.model.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "finerules",
|
||||
localField: "fine_rule",
|
||||
foreignField: "_id",
|
||||
as: "fineRuleDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$unwind: "$fineRuleDetails",
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
sellerDetails: { $arrayElemAt: ["$sellerDetails", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "cancelreasons",
|
||||
localField: "reason",
|
||||
foreignField: "_id",
|
||||
as: "cancelReasonDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
cancelReasonDetails: { $ifNull: ["$cancelReasonDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "returnreasons",
|
||||
localField: "reason",
|
||||
foreignField: "_id",
|
||||
as: "returnReasonDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
returnReasonDetails: { $ifNull: ["$returnReasonDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
reasonDetails: {
|
||||
$cond: {
|
||||
if: { $eq: ["$reasonRef", "Cancel"] },
|
||||
then: { $arrayElemAt: ["$cancelReasonDetails", 0] },
|
||||
else: { $arrayElemAt: ["$returnReasonDetails", 0] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$unset: ["cancelReasonDetails", "returnReasonDetails"],
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "cancelorderitems",
|
||||
localField: "orderItem",
|
||||
foreignField: "_id",
|
||||
as: "cancelOrderItemDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
cancelOrderItemDetails: { $ifNull: ["$cancelOrderItemDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "returnorderitems",
|
||||
localField: "orderItem",
|
||||
foreignField: "_id",
|
||||
as: "returnOrderItemDetails",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
returnOrderItemDetails: { $ifNull: ["$returnOrderItemDetails", []] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
orderItemsDetails: {
|
||||
$cond: {
|
||||
if: { $eq: ["$orderItemRef", "CancelOrderItem"] },
|
||||
then: { $arrayElemAt: ["$cancelOrderItemDetails", 0] },
|
||||
else: { $arrayElemAt: ["$returnOrderItemDetails", 0] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$unset: ["cancelOrderItemDetails", "returnOrderItemDetails"],
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "orderitems",
|
||||
localField: "orderItemsDetails.orderItem",
|
||||
foreignField: "_id",
|
||||
as: "orderItemsDetails.orderItem",
|
||||
},
|
||||
},
|
||||
{
|
||||
$unwind: "$orderItemsDetails.orderItem",
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
shipmentItem: {
|
||||
$arrayElemAt: ["$orderItemsDetails.orderItem.shipmentItems", 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
$lookup: {
|
||||
from: "products",
|
||||
localField: "shipmentItem.product",
|
||||
foreignField: "_id",
|
||||
as: "product",
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
product: { $arrayElemAt: ["$product", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$facet: {
|
||||
data: [{ $skip: skip }, { $limit: limit }],
|
||||
totalCount: [{ $count: "count" }],
|
||||
},
|
||||
},
|
||||
{
|
||||
$addFields: {
|
||||
totalCount: { $arrayElemAt: ["$totalCount.count", 0] },
|
||||
},
|
||||
},
|
||||
{
|
||||
$sort: {
|
||||
createdAt: -1,
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
console.dir(docs[0], { depth: null });
|
||||
return {
|
||||
count: (docs[0]?.totalCount as number) || 0,
|
||||
docs: docs[0]?.data || [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function createFineRepo(): FineRepo {
|
||||
return new FineRepo();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { BaseRepository } from "../../../common/base/repository";
|
||||
import { IFineRule } from "../models/Abstraction/IFineRule";
|
||||
import { FineRuleModel } from "../models/fineRule.model";
|
||||
|
||||
export class FineRuleRepo extends BaseRepository<IFineRule> {
|
||||
constructor() {
|
||||
super(FineRuleModel);
|
||||
}
|
||||
|
||||
async findFineRuleByCancelReasonId(cancelReasonId: string) {
|
||||
return this.model.findOne({ cancel_reason: cancelReasonId }).populate("cancel_reason");
|
||||
}
|
||||
}
|
||||
|
||||
export function createFineRuleRepo(): FineRuleRepo {
|
||||
return new FineRuleRepo();
|
||||
}
|
||||
Reference in New Issue
Block a user