chore: fix problem of transcation beeing commited throw update the "

category variant
This commit is contained in:
mahyargdz
2025-09-21 11:45:24 +03:30
parent 3d1aa01f2e
commit 79f597cc90
23 changed files with 52 additions and 97 deletions
-2
View File
@@ -73,7 +73,6 @@ class Guard {
(req: Request, _res: Response, next: NextFunction) =>
async (err: Error, decoded: IUser | ISeller, info: string | object | JsonWebTokenError | TokenExpiredError): Promise<void> => {
if (err) {
console.log({ err });
return next(new UnauthorizedError(AuthMessage.AuthFailed));
}
if (info instanceof TokenExpiredError) {
@@ -83,7 +82,6 @@ class Guard {
return next(new UnauthorizedError(info.message));
}
if (info) {
console.log({ info });
return next(new UnauthorizedError(AuthMessage.AuthFailed));
}
if (!decoded) {
@@ -44,7 +44,6 @@ export class ValidationMiddleware {
excludeExtraneousValues: true,
enableImplicitConversion: true,
});
console.log(validationClass);
// Validate the DTO instance, including nested objects
const errors: ValidationError[] = await validate(validationClass, {
@@ -95,7 +95,7 @@ export class AdminCategoryController extends BaseController {
return this.response({ data }, HttpStatus.Created);
}
@ApiOperation("add a category variant")
@ApiOperation("update a category variant")
@ApiResponse("successful", HttpStatus.Created)
@ApiParam("id", "id of category", true)
@ApiModel(UpdateCategoryVariantDTO)
+12 -1
View File
@@ -1,8 +1,9 @@
import { Expose } from "class-transformer";
import { IsNotEmpty, IsOptional } from "class-validator";
import { IsEnum, IsNotEmpty, IsOptional } from "class-validator";
import { ApiProperty } from "../../../common/decorator/swggerDocs";
import { IsValidId } from "../../../common/decorator/validation.decorator";
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
import { CategoryModel } from "../models/category.model";
export class CreateCategoryDTO {
@@ -37,4 +38,14 @@ export class CreateCategoryDTO {
@IsValidId(CategoryModel)
@ApiProperty({ type: "string", description: "the id of parent category", example: "6103e3a9f9b1b5b27cd7c8e9" })
parent?: string;
@Expose()
@IsNotEmpty()
@IsEnum(CategoryThemeEnum)
@ApiProperty({
type: "string",
description: "the variation theme of a category ==> should be one of Color/Size/Meterage or noColor_noSize",
example: "Color",
})
theme: CategoryThemeEnum;
}
+5 -7
View File
@@ -105,9 +105,13 @@ class CategoryService {
await this.categoryRepository.model.findOneAndUpdate({ _id: category._id.toString() }, { theme: updateDto.theme, variants: [] });
}
if (updateDto.parent) {
// Set the parent category to leaf: false (since it now has a child)
await this.categoryRepository.model.findByIdAndUpdate(updateDto.parent, { leaf: false });
// Set the current category to leaf: true (since it has a parent)
const updatedCategory = await this.categoryRepository.model.findByIdAndUpdate(
category._id.toString(),
{ ...updateDto, leaf: false },
{ ...updateDto, leaf: true },
{ new: true },
);
return {
@@ -461,18 +465,12 @@ class CategoryService {
) {
for (const item of items) {
const query = { [field]: item[field] } as FilterQuery<V>;
console.log("query", query);
const all = await repo.model.find();
const existingItem = await repo.model.exists({ ...query });
console.log(existingItem);
console.log("all", all);
if (existingItem) {
variantRefs.push(existingItem._id);
} else {
console.log(item);
const newItem = await repo.model.create([{ ...item }], { session });
variantRefs.push(newItem[0]._id);
await session.commitTransaction();
}
}
}
+2 -1
View File
@@ -1,6 +1,7 @@
import mongoose, { Schema, model } from "mongoose";
import { IColor } from "./Abstraction/IColor";
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
const AutoIncrement = require("mongoose-sequence")(mongoose);
@@ -15,6 +16,6 @@ const ColorSchema = new Schema<IColor>(
);
ColorSchema.plugin(AutoIncrement, { id: "color_id", inc_field: "_id" });
const ColorModel = model<IColor>("Color", ColorSchema);
const ColorModel = model<IColor>(CategoryThemeEnum.Colored, ColorSchema);
export { ColorModel };
@@ -1,6 +1,7 @@
import mongoose, { Schema, model } from "mongoose";
import { IMeterage } from "./Abstraction/IMeterage";
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
const AutoIncrement = require("mongoose-sequence")(mongoose);
@@ -14,6 +15,6 @@ const MeterageSchema = new Schema<IMeterage>(
);
MeterageSchema.plugin(AutoIncrement, { id: "meterage_id", inc_field: "_id" });
const MeterageModel = model<IMeterage>("Meterage", MeterageSchema);
const MeterageModel = model<IMeterage>(CategoryThemeEnum.Meterage, MeterageSchema);
export { MeterageModel };
+2 -1
View File
@@ -1,6 +1,7 @@
import mongoose, { Schema, model } from "mongoose";
import { ISize } from "./Abstraction/ISize";
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
const AutoIncrement = require("mongoose-sequence")(mongoose);
@@ -14,6 +15,6 @@ const SizeSchema = new Schema<ISize>(
);
SizeSchema.plugin(AutoIncrement, { id: "size_id", inc_field: "_id" });
const SizeModel = model<ISize>("Size", SizeSchema);
const SizeModel = model<ISize>(CategoryThemeEnum.Sized, SizeSchema);
export { SizeModel };
-1
View File
@@ -48,7 +48,6 @@ class FineService {
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,
-5
View File
@@ -72,10 +72,8 @@ export class LearningService {
}
async update(learningId: string, updateDto: UpdateLearningDTO) {
console.log(learningId);
if (!isValidObjectId(learningId)) throw new BadRequestError(CommonMessage.NotValidId);
const learning = await this.learningRepo.model.findByIdAndUpdate(learningId, updateDto, { new: true });
console.log(learning);
if (!learning) throw new BadRequestError(CommonMessage.NotFoundById);
return {
message: CommonMessage.Updated,
@@ -86,7 +84,6 @@ export class LearningService {
async updateCategory(catId: string, updateDto: UpdateLearningCategoryDTO) {
if (!isValidObjectId(catId)) throw new BadRequestError(CommonMessage.NotValidId);
const learningCategory = await this.learningCategoryRepo.model.findByIdAndUpdate(catId, updateDto, { new: true });
console.log(learningCategory);
if (!learningCategory) throw new BadRequestError(CommonMessage.NotFoundById);
return {
message: CommonMessage.Updated,
@@ -128,13 +125,11 @@ export class LearningService {
async getLearningProgressBySellerForAdmin() {
const progress = await this.learningProgressRepo.getLearningProgressBySellers();
console.log(progress);
return { progress };
}
async getLearningProgressWatched(sellerId: string, catId: string) {
const progress = await this.learningRepo.getVideosWithWatchStatus(sellerId, catId);
console.log(progress);
return { progress };
}
}
@@ -131,7 +131,6 @@ class NotificationService {
},
}));
const notifications = await this.notificationRepo.model.bulkWrite(bulkOps);
console.log({ notifications });
// const notifications = await this.createNotification(
// "seller",
// createDto.sellerIds.join(","),
-15
View File
@@ -1720,10 +1720,8 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
async getDailyShipmentSalesReport() {
const today = new Date();
today.setHours(0, 0, 0, 0);
console.log(today);
const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 999);
console.log({ today, startOfDay, endOfDay });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1752,7 +1750,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
@@ -1763,7 +1760,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
startOfWeek.setDate(today.getDate() - 6); // 7 days ago
const endOfWeek = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 999);
console.log({ today, startOfWeek, endOfWeek });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1792,7 +1788,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
@@ -1801,7 +1796,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
const startOfMonth = new Date(today.getFullYear(), today.getMonth(), 1);
const endOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 1);
console.log({ today, startOfMonth, endOfMonth });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1830,7 +1824,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
@@ -1839,7 +1832,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
const startOfYear = new Date(today.getFullYear(), 0, 1);
const endOfYear = new Date(today.getFullYear() + 1, 0, 1);
console.log({ today, startOfYear, endOfYear });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1868,17 +1860,14 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
async getDailySalesReport() {
const today = new Date();
today.setHours(0, 0, 0, 0);
console.log(today);
const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate());
const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 999);
console.log({ today, startOfDay, endOfDay });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1909,7 +1898,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
@@ -1920,8 +1908,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
startOfWeek.setDate(today.getDate() - 6); // 7 days ago
const endOfWeek = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 999);
console.log({ today, startOfWeek, endOfWeek });
const salesData = await this.model.aggregate([
{
$match: {
@@ -1952,7 +1938,6 @@ class OrderItemRepo extends BaseRepository<IOrderItem> {
itemsSold: 0,
totalOrders: 0,
};
console.log(salesData);
return salesData.length > 0 ? salesData[0] : defaultData;
}
@@ -87,7 +87,6 @@ class CartPaymentRepository extends BaseRepository<ICartPayment> {
},
},
]);
console.log(docs[0]);
return {
count: (docs[0]?.totalCount as number) || 0,
docs: docs[0]?.data || [],
@@ -1,8 +1,14 @@
import { Types } from "mongoose";
import { CategoryThemeEnum } from "../../../../common/enums/category.enum";
import { ProductDiscountType, ProductMarketStatus } from "../../../../common/enums/product.enum";
export interface IProductVariant {
// Dynamic type for category theme fields
type CategoryThemeFields = {
[K in Lowercase<Exclude<CategoryThemeEnum, CategoryThemeEnum.No_color_No_sized>>]?: number;
};
export interface IProductVariant extends CategoryThemeFields {
_id: Types.ObjectId;
product: number;
statistics: IStatistics;
@@ -19,9 +25,6 @@ export interface IProductVariant {
saleFormat: ISaleFormat;
dimensions: IDimensions;
sellerSpecialCode: string;
color?: number;
size?: number;
meterage?: number;
}
export interface IPrice {
@@ -1,6 +1,7 @@
import { Schema, model } from "mongoose";
import { IDimensions, IPrice, IProductVariant, ISaleFormat, IStatistics } from "./Abstraction/IProductVariant";
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
import { ProductMarketStatus } from "../../../common/enums/product.enum";
const productStatisticsSchema = new Schema<IStatistics>(
@@ -44,6 +45,24 @@ const productPriceSchema = new Schema<IPrice>(
{ _id: false },
);
// Utility function to generate dynamic category theme fields
const generateCategoryThemeFields = () => {
const fields: Record<string, { type: NumberConstructor; ref: string; required: boolean }> = {};
Object.values(CategoryThemeEnum).forEach((theme) => {
if (theme !== CategoryThemeEnum.No_color_No_sized) {
const fieldName = theme.toLowerCase();
fields[fieldName] = {
type: Number,
ref: theme,
required: false,
};
}
});
return fields;
};
const productVariantSchema = new Schema<IProductVariant>(
{
product: { type: Number, ref: "Product", required: true },
@@ -59,9 +78,7 @@ const productVariantSchema = new Schema<IProductVariant>(
saleFormat: { type: productSaleFormat },
dimensions: { type: productDimensionsSchema, required: true },
sellerSpecialCode: { type: String },
color: { type: Number, ref: "Color", required: false },
size: { type: Number, ref: "Size", required: false },
meterage: { type: Number, ref: "Meterage", required: false },
...generateCategoryThemeFields(),
},
{ timestamps: true, toObject: { virtuals: true, versionKey: false }, toJSON: { virtuals: true, versionKey: false }, id: false },
);
@@ -239,7 +239,6 @@ class ProductService {
await this.checkForDuplicateProduct(createStepOneDto.model);
const shop = await this.shopeRepo.model.findById(shopId);
console.log({ shop, shopId });
if (!shop) throw new BadRequestError(ShopMessage.ShopNotFound);
const createdProduct = await this.productRepo.model.create({
@@ -1627,10 +1626,9 @@ class ProductService {
async deletePopularProduct(productId: number) {
await this.validateProduct(productId);
const deletedPopular = await this.popularProductRepo.model.findOneAndDelete({
await this.popularProductRepo.model.findOneAndDelete({
product: productId,
});
console.log(deletedPopular);
return {
message: CommonMessage.Deleted,
};
@@ -1674,7 +1672,6 @@ class ProductService {
async updateProduct(productId: number, updateDto: UpdateProductDTO) {
const product = await this.validateProduct(productId);
const updatedProduct = await this.productRepo.model.findByIdAndUpdate({ _id: product._id }, { ...updateDto }, { new: true });
console.log({ updatedProduct });
return { updatedProduct };
}
-1
View File
@@ -202,7 +202,6 @@ export class ReturnOrderRepo extends BaseRepository<IReturnOrder> {
},
},
]);
console.log(docs);
return docs;
}
}
-1
View File
@@ -199,7 +199,6 @@ class SellerService {
async deleteSellerDocument(documentId: string, rejectReason: string) {
const document = await this.sellerDocumentRepo.model.findByIdAndDelete(documentId);
console.log({ document });
if (!document) throw new BadRequestError(SellerMessage.SellerDocumentNotFound);
await this.notificationService.notifyRejectDocument(document.seller.toString(), rejectReason);
return {
-9
View File
@@ -80,7 +80,6 @@ class ShipmentService {
// get the cart for the user
const cart = await this.cartRepo.getCartWithPopulate(userId);
if (!cart) throw new BadRequestError(CartMessage.CartNotFound);
console.log({ cart });
const shipping = [];
const cartItems = cart.items as unknown as Items[];
@@ -97,11 +96,9 @@ class ShipmentService {
});
return acc;
}, {});
console.log({ itemsByShop });
// iterate through each shops items
for (const [shopId, items] of Object.entries(itemsByShop)) {
const shop = await this.shopRepo.model.findById(shopId).lean();
console.log(shop);
if (!shop) {
continue;
}
@@ -111,9 +108,7 @@ class ShipmentService {
// for each shop, check all available shippers
for (const shipperId of shop.shipmentMethod) {
const shipmentProvider = await this.shipmentRepo.model.findById(shipperId).lean();
console.log({ shipmentProvider });
if (!shipmentProvider) {
console.log("Shipment provider not found for shipper ID:", shipperId);
continue;
}
@@ -165,7 +160,6 @@ class ShipmentService {
items,
shippers: shopShippers,
});
console.log({ shipping });
}
return { shipping: shipping.map((ship) => ShippingOptionDTO.transformShipment(ship)) };
@@ -327,12 +321,9 @@ class ShipmentService {
// Helper function to calculate the shipping cost for a product variant based on shipment provider
private async calculateShippingCost(shipmentProvider: IShipmentProviders, package_weight: number, quantity: number): Promise<number> {
console.log({ package_weight });
console.dir({ shipmentProvider: shipmentProvider.costs }, { depth: null });
const cost = shipmentProvider.costs.find(
(cost) => package_weight / 1000 >= cost.weightRange.min && package_weight / 1000 <= cost.weightRange.max,
);
console.log({ cost });
// if (!cost) throw new BadRequestError("No shipping cost available for this weight range");
const defaulCost = cost ?? { cost_first: 100_000, cost_rest: 10_000 };
-7
View File
@@ -5,10 +5,3 @@ export const StartWorker = async () => {
return [OrderProcessor.worker];
};
// export const addJob = () => {
// console.log("job added");
// OrderQueue.addOrderToQueue(1, 1000);
// };
// addJob();
-18
View File
@@ -9,21 +9,3 @@ export function omit<T extends Record<string, never>, K extends keyof never>(obj
}
export const priceNumberFormat = (price: number) => Intl.NumberFormat("fa-IR").format(price);
// const omitKey = [
// "learningStatus",
// "contractStatus",
// "registerStatus",
// "documentStatus",
// "paymentStatus",
// "rate",
// "prodcuts",
// "purchases",
// "orders",
// ];
// const payload = omit(updateDto, omitKey);
// console.log(payload);
// const omitKey = ["basket", "favoriteProducts", "comments", "orders", "phoneNumber", "email"];
// const payload = omit(updateDto, omitKey);
// console.log(payload);
-1
View File
@@ -56,7 +56,6 @@ class PassportAuth {
if (!admin) {
return done(null, false);
}
console.log({ admin });
done(null, admin);
} catch (error) {
this.logger.error("error in AdminJwt verify", error);
-11
View File
@@ -77,14 +77,3 @@ class TimeService {
}
}
export { TimeService };
// const utcDate = new Date().toISOString();
// const iranTime = new Date(utcDate).toLocaleString('en-IR', { timeZone: 'Asia/Seoul' });
// console.log(iranTime);
// new Date().toLocaleString()
// console.log(
// TimeService.convertGregorianToPersian(
// TimeService.addTime(new Date(TimeService.convertPersianToGregorian(TimeService.getCurrentPersianDate())), 2, "year"),
// ),
// );