product verity
This commit is contained in:
@@ -3,9 +3,7 @@ import { IsNotEmpty, IsNumber, IsOptional, Min } from "class-validator";
|
||||
|
||||
import { ApiProperty } from "../../../common/decorator/swggerDocs";
|
||||
import { IsValidId } from "../../../common/decorator/validation.decorator";
|
||||
import { ColorModel } from "../../category/models/color.model";
|
||||
import { MeterageModel } from "../../category/models/meterage.model";
|
||||
import { SizeModel } from "../../category/models/size.model";
|
||||
import { ThemeValueModel } from "../../category/models/themeValue.model";
|
||||
import { WarrantyModel } from "../../warranty/models/warranty.model";
|
||||
// import { ShipmentModel } from "../../../models/shipment.model";
|
||||
|
||||
@@ -19,23 +17,9 @@ export class AddVariantDTO {
|
||||
@Expose()
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@IsValidId(ColorModel)
|
||||
@ApiProperty({ type: "number", description: "color id ==> one of color,size or meterage should send", example: 1 })
|
||||
colorId?: number;
|
||||
|
||||
@Expose()
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@IsValidId(SizeModel)
|
||||
@ApiProperty({ type: "number", description: "size id ==> one of color,size or meterage should send", example: 5 })
|
||||
sizeId?: number;
|
||||
|
||||
@Expose()
|
||||
@IsOptional()
|
||||
@IsNotEmpty()
|
||||
@IsValidId(MeterageModel)
|
||||
@ApiProperty({ type: "number", description: "meterage id ==> one of color,size or meterage should send", example: 5 })
|
||||
meterageId?: number;
|
||||
@IsValidId(ThemeValueModel)
|
||||
@ApiProperty({ type: "string", description: "theme value id" })
|
||||
themeValueId?: string;
|
||||
|
||||
@Expose()
|
||||
@IsNotEmpty()
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { Types } from "mongoose";
|
||||
|
||||
import { CategoryThemeEnum } from "../../../../common/enums/category.enum";
|
||||
import { ProductDiscountType, ProductMarketStatus } from "../../../../common/enums/product.enum";
|
||||
|
||||
// Dynamic type for category theme fields
|
||||
type CategoryThemeFields = {
|
||||
[K in Lowercase<Exclude<CategoryThemeEnum, CategoryThemeEnum.No_color_No_sized>>]?: number;
|
||||
};
|
||||
|
||||
export interface IProductVariant extends CategoryThemeFields {
|
||||
export interface IProductVariant {
|
||||
_id: Types.ObjectId;
|
||||
product: number;
|
||||
statistics: IStatistics;
|
||||
@@ -25,6 +21,7 @@ export interface IProductVariant extends CategoryThemeFields {
|
||||
saleFormat: ISaleFormat;
|
||||
dimensions: IDimensions;
|
||||
sellerSpecialCode: string;
|
||||
themeValue: Types.ObjectId;
|
||||
}
|
||||
|
||||
export interface IPrice {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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>(
|
||||
@@ -45,24 +44,6 @@ 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 },
|
||||
@@ -78,7 +59,7 @@ const productVariantSchema = new Schema<IProductVariant>(
|
||||
saleFormat: { type: productSaleFormat },
|
||||
dimensions: { type: productDimensionsSchema, required: true },
|
||||
sellerSpecialCode: { type: String },
|
||||
...generateCategoryThemeFields(),
|
||||
themeValue: { type: Schema.Types.ObjectId, ref: "ThemeValue", required: true },
|
||||
},
|
||||
{ timestamps: true, toObject: { virtuals: true, versionKey: false }, toJSON: { virtuals: true, versionKey: false }, id: false },
|
||||
);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { inject, injectable } from "inversify";
|
||||
import { ClientSession, FilterQuery, isValidObjectId, startSession } from "mongoose";
|
||||
import { ClientSession, Types, isValidObjectId, startSession } from "mongoose";
|
||||
import slugify from "slugify";
|
||||
|
||||
import { PaginationDTO } from "../../../common/dto/pagination.dto";
|
||||
import { CategoryThemeEnum } from "../../../common/enums/category.enum";
|
||||
import {
|
||||
AdMessage,
|
||||
AttributeMessage,
|
||||
@@ -29,7 +28,7 @@ import { paginationUtils } from "../../../utils/pagination.utils";
|
||||
import { TimeService } from "../../../utils/time.service";
|
||||
import { AddIncredibleOffersParamDto } from "../../admin/DTO/product-param.dto";
|
||||
import { BrandDTO } from "../../brand/DTO/brand.dto";
|
||||
import { AttributeValueRepo, CategoryAttributeRepo, CategoryRepository } from "../../category/category.repository";
|
||||
import { AttributeValueRepo, CategoryAttributeRepo, CategoryRepository, ThemeValueRepository } from "../../category/category.repository";
|
||||
import { CategoryTreeDTO } from "../../category/DTO/category.dto";
|
||||
import { NotificationService } from "../../notification/notification.service";
|
||||
import { PricingRepository } from "../../pricing/pricing.repository";
|
||||
@@ -96,6 +95,7 @@ class ProductService {
|
||||
@inject(IOCTYPES.ShopRepo) shopeRepo: ShopRepo;
|
||||
@inject(IOCTYPES.IncredibleOffersRepo) incredibleOffersRepo: IncredibleOffersRepo;
|
||||
@inject(IOCTYPES.NotificationService) notificationService: NotificationService;
|
||||
@inject(IOCTYPES.ThemeValueRepository) themeValueRepo: ThemeValueRepository;
|
||||
|
||||
//###############################################################
|
||||
async searchProducts(q: string) {
|
||||
@@ -557,41 +557,30 @@ class ProductService {
|
||||
if (!shop) throw new BadRequestError(ShopMessage.ShopNotFound);
|
||||
|
||||
this.ensureProductIsNotInDraft(product);
|
||||
const category = await this.ensureCategoryTheme(product.category.toString(), addVariantDto);
|
||||
await this.ensureCategoryTheme(product.category.toString(), addVariantDto);
|
||||
|
||||
await this.checkVariantCount(product, category.theme);
|
||||
// await this.checkVariantCount(product, category.theme);
|
||||
|
||||
// Check if a variant with the same colorId, meterageId, or sizeId already exists
|
||||
// Check if a variant with the same colorId, meterageId, or sizeId already exists
|
||||
const query: FilterQuery<IProductVariant> = { product: product._id };
|
||||
// Check if a variant with the same themeValue already exists
|
||||
// const query: FilterQuery<IProductVariant> = { product: product._id };
|
||||
|
||||
if (addVariantDto.colorId) {
|
||||
query.color = addVariantDto.colorId;
|
||||
}
|
||||
if (addVariantDto.meterageId) {
|
||||
query.meterage = addVariantDto.meterageId;
|
||||
}
|
||||
if (addVariantDto.sizeId) {
|
||||
query.size = addVariantDto.sizeId;
|
||||
}
|
||||
// if (addVariantDto.themeValueId) {
|
||||
// const existingVariant = await this.productVariantRepo.model.findOne({
|
||||
// product: product._id,
|
||||
// themeValue: addVariantDto.themeValueId,
|
||||
// });
|
||||
|
||||
if (category.toString() !== CategoryThemeEnum.No_color_No_sized) {
|
||||
const existingVariant = await this.productVariantRepo.model.findOne(query);
|
||||
|
||||
if (existingVariant) throw new BadRequestError(ProductMessage.VariantAlreadyExists);
|
||||
}
|
||||
// if (existingVariant) throw new BadRequestError(ProductMessage.VariantAlreadyExists);
|
||||
// }
|
||||
|
||||
const productVariant = await this.createProductVariant(addVariantDto, product._id, shop._id.toString(), session);
|
||||
|
||||
await this.productRepo.model.findByIdAndUpdate(product._id, { $push: { variants: productVariant } }, { session });
|
||||
// product.variants.push(productVariant[0]._id);
|
||||
// await product.save({ session });
|
||||
const { colorId, sizeId, meterageId } = addVariantDto;
|
||||
|
||||
PriceChangeEvent.emitPriceChange({
|
||||
colorId,
|
||||
sizeId,
|
||||
meterageId,
|
||||
themeValueId: addVariantDto.themeValueId,
|
||||
product: productId,
|
||||
variantId: productVariant[0]._id.toString(),
|
||||
shop: shop._id.toString(),
|
||||
@@ -654,9 +643,6 @@ class ProductService {
|
||||
);
|
||||
|
||||
PriceChangeEvent.emitPriceChange({
|
||||
colorId: updatedVariant?.color,
|
||||
sizeId: updatedVariant?.size,
|
||||
meterageId: updatedVariant?.meterage,
|
||||
product: productId,
|
||||
variantId: updatedVariant?._id.toString() as string,
|
||||
shop: shop._id.toString(),
|
||||
@@ -1447,33 +1433,10 @@ class ProductService {
|
||||
throw new BadRequestError(CategoryMessage.NotValidId);
|
||||
}
|
||||
|
||||
// Check if the category theme is color, size, or meterage
|
||||
if (category.theme === CategoryThemeEnum.Colored) {
|
||||
if (addVariantDto.sizeId || addVariantDto.meterageId) {
|
||||
throw new BadRequestError(AttributeMessage.SizeNotAllowedForColoredTheme);
|
||||
}
|
||||
if (!addVariantDto.colorId) {
|
||||
throw new BadRequestError(AttributeMessage.ColorRequiredForColoredTheme);
|
||||
}
|
||||
} else if (category.theme === CategoryThemeEnum.Sized) {
|
||||
if (addVariantDto.colorId || addVariantDto.meterageId) {
|
||||
throw new BadRequestError(AttributeMessage.ColorNotAllowedForSizedTheme);
|
||||
}
|
||||
if (!addVariantDto.sizeId) {
|
||||
throw new BadRequestError(AttributeMessage.SizeRequiredForSizedTheme);
|
||||
}
|
||||
} else if (category.theme === CategoryThemeEnum.Meterage) {
|
||||
if (addVariantDto.colorId || addVariantDto.sizeId) {
|
||||
throw new BadRequestError(AttributeMessage.ColorOrSizeNotAllowedForMeterageTheme);
|
||||
}
|
||||
if (!addVariantDto.meterageId) {
|
||||
throw new BadRequestError(AttributeMessage.MeterageRequiredForMeterageTheme);
|
||||
}
|
||||
} else {
|
||||
// For other themes that are neither color, size, nor meterage
|
||||
if (addVariantDto.sizeId || addVariantDto.colorId || addVariantDto.meterageId) {
|
||||
throw new BadRequestError(AttributeMessage.ThemeIsNoColorNoSizeNoMeterage);
|
||||
}
|
||||
if (addVariantDto.themeValueId) {
|
||||
const themeValue = await this.themeValueRepo.findById(addVariantDto.themeValueId);
|
||||
if (!themeValue) throw new BadRequestError(CommonMessage.NotFoundById);
|
||||
category.variants = [themeValue._id];
|
||||
}
|
||||
|
||||
return category;
|
||||
@@ -1549,9 +1512,7 @@ class ProductService {
|
||||
shop: shopId,
|
||||
warranty: addVariantDto.warrantyId,
|
||||
// shipmentMethod: addVariantDto.shipmentsId,
|
||||
color: addVariantDto.colorId,
|
||||
size: addVariantDto.sizeId,
|
||||
meterage: addVariantDto.meterageId,
|
||||
themeValue: new Types.ObjectId(addVariantDto.themeValueId),
|
||||
dimensions,
|
||||
market_status: ProductMarketStatus.Marketable,
|
||||
price: product_price,
|
||||
@@ -1611,16 +1572,6 @@ class ProductService {
|
||||
return totalCost;
|
||||
}
|
||||
|
||||
private async checkVariantCount(product: IProduct, categoryTheme: CategoryThemeEnum) {
|
||||
if (categoryTheme !== CategoryThemeEnum.No_color_No_sized) return true;
|
||||
|
||||
const variantCount = product.variants.length;
|
||||
console.log("variantCount", variantCount);
|
||||
if (!variantCount) return true;
|
||||
console.log("pro", product, categoryTheme);
|
||||
throw new BadRequestError(ProductMessage.ProductWithNoVariantCategoryTheme);
|
||||
}
|
||||
|
||||
//###############################################################
|
||||
//###################### popular product ############################
|
||||
|
||||
@@ -1744,6 +1695,16 @@ class ProductService {
|
||||
|
||||
// return searchCost;
|
||||
// }
|
||||
|
||||
// private async checkVariantCount(product: IProduct, categoryTheme: Types.ObjectId | undefined) {
|
||||
// if (categoryTheme) return true;
|
||||
|
||||
// const variantCount = product.variants.length;
|
||||
// console.log("variantCount", variantCount);
|
||||
// if (!variantCount) return true;
|
||||
// console.log("pro", product, categoryTheme);
|
||||
// throw new BadRequestError(ProductMessage.ProductWithNoVariantCategoryTheme);
|
||||
// }
|
||||
}
|
||||
|
||||
export { ProductService };
|
||||
|
||||
Reference in New Issue
Block a user