add new field to product
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import { Entity, Index, ManyToOne, Property } from '@mikro-orm/core';
|
import { Entity, Enum, ManyToOne, Property } from '@mikro-orm/core';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
import { Order } from './order.entity';
|
import { Order } from './order.entity';
|
||||||
import { Variant } from '../../products/entities/variant.entity';
|
import { Variant } from '../../products/entities/variant.entity';
|
||||||
|
import { OrderItemStatus } from '../enum/order-item.enum';
|
||||||
|
|
||||||
@Entity({ tableName: 'order_items' })
|
@Entity({ tableName: 'order_items' })
|
||||||
export class OrderItem extends BaseEntity {
|
export class OrderItem extends BaseEntity {
|
||||||
@@ -22,4 +23,7 @@ export class OrderItem extends BaseEntity {
|
|||||||
|
|
||||||
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||||
totalPrice!: number;
|
totalPrice!: number;
|
||||||
|
|
||||||
|
@Enum(() => OrderItemStatus)
|
||||||
|
status: OrderItemStatus = OrderItemStatus.normal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
export enum OrderItemStatus {
|
||||||
|
normal = 'normal',
|
||||||
|
needConfirmation = 'needConfirmation',
|
||||||
|
confirmed = 'confirmed'
|
||||||
|
}
|
||||||
@@ -20,6 +20,8 @@ export enum OrderStatus {
|
|||||||
SHIPPED = 'shipped',
|
SHIPPED = 'shipped',
|
||||||
COMPLETED = 'completed',
|
COMPLETED = 'completed',
|
||||||
CANCELED = 'canceled',
|
CANCELED = 'canceled',
|
||||||
|
NEED_CONFIRMATION = 'needConfirmation',
|
||||||
|
CONFIRMED = 'confirmed',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OrderCouponDetail {
|
export interface OrderCouponDetail {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { UserService } from 'src/modules/users/providers/user.service';
|
|||||||
import { ShopService } from 'src/modules/shops/providers/shops.service';
|
import { ShopService } from 'src/modules/shops/providers/shops.service';
|
||||||
import { DeliveryService } from 'src/modules/delivery/providers/delivery.service';
|
import { DeliveryService } from 'src/modules/delivery/providers/delivery.service';
|
||||||
import { PaymentMethodService } from 'src/modules/payments/services/payment-method.service';
|
import { PaymentMethodService } from 'src/modules/payments/services/payment-method.service';
|
||||||
|
import { OrderItemStatus } from '../enum/order-item.enum';
|
||||||
|
|
||||||
type OrderItemData = { variant: Variant; quantity: number; unitPrice: number; discount: number };
|
type OrderItemData = { variant: Variant; quantity: number; unitPrice: number; discount: number };
|
||||||
|
|
||||||
@@ -102,6 +103,7 @@ export class OrdersService {
|
|||||||
unitPrice,
|
unitPrice,
|
||||||
discount,
|
discount,
|
||||||
totalPrice,
|
totalPrice,
|
||||||
|
status: OrderItemStatus.normal,
|
||||||
});
|
});
|
||||||
|
|
||||||
em.persist(orderItem);
|
em.persist(orderItem);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import {
|
|||||||
ValidateNested,
|
ValidateNested,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
import { PricingType } from '../enum/pricing.enum';
|
||||||
|
import { PurchaseUnit } from '../enum/unit.enum';
|
||||||
|
|
||||||
export class CreateVariantDto {
|
export class CreateVariantDto {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@@ -78,13 +80,6 @@ export class CreateProductDto {
|
|||||||
desc?: string;
|
desc?: string;
|
||||||
|
|
||||||
|
|
||||||
@IsOptional()
|
|
||||||
@IsNumber()
|
|
||||||
@Min(0)
|
|
||||||
@Type(() => Number)
|
|
||||||
@ApiPropertyOptional({ example: 120000 })
|
|
||||||
price?: number;
|
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsBoolean()
|
@IsBoolean()
|
||||||
@ApiPropertyOptional({ example: true })
|
@ApiPropertyOptional({ example: true })
|
||||||
@@ -111,6 +106,11 @@ export class CreateProductDto {
|
|||||||
@Type(() => Boolean)
|
@Type(() => Boolean)
|
||||||
isSpecialOffer?: boolean;
|
isSpecialOffer?: boolean;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
@ApiProperty({ example: false })
|
||||||
|
@Type(() => Boolean)
|
||||||
|
needAdminAcceptance: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@Min(0)
|
@Min(0)
|
||||||
@@ -124,4 +124,28 @@ export class CreateProductDto {
|
|||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@ApiPropertyOptional({ description: 'Maximum quantity per order; omit or null for unlimited', example: 5 })
|
@ApiPropertyOptional({ description: 'Maximum quantity per order; omit or null for unlimited', example: 5 })
|
||||||
maxPurchaseQuantity?: number | null;
|
maxPurchaseQuantity?: number | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsString()
|
||||||
|
@ApiPropertyOptional({ example: '1000' })
|
||||||
|
@Type(() => String)
|
||||||
|
purchasePitch?: string | null;
|
||||||
|
|
||||||
|
@IsNotEmpty()
|
||||||
|
@IsEnum(PricingType)
|
||||||
|
@ApiProperty({ example: PricingType.FIXED })
|
||||||
|
pricingType: PricingType;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsEnum(PurchaseUnit)
|
||||||
|
@ApiPropertyOptional({ example: PurchaseUnit.NUMBER })
|
||||||
|
purchaseUnit?: PurchaseUnit;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsInt()
|
||||||
|
@Min(1)
|
||||||
|
@Type(() => Number)
|
||||||
|
@ApiPropertyOptional({ description: 'Minimum quantity per order; omit or null for unlimited', example: 1 })
|
||||||
|
minPurchaseQuantity?: number | null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
import { Cascade, Collection, Entity, Index, ManyToOne, OneToMany, Property } from '@mikro-orm/core';
|
import { Cascade, Collection, Entity, Enum, Index, ManyToOne, OneToMany, Property } from '@mikro-orm/core';
|
||||||
import { Category } from './category.entity';
|
import { Category } from './category.entity';
|
||||||
import { BaseEntity } from '../../../common/entities/base.entity';
|
import { BaseEntity } from '../../../common/entities/base.entity';
|
||||||
import { Shop } from '../../../modules/shops/entities/shop.entity';
|
import { Shop } from '../../../modules/shops/entities/shop.entity';
|
||||||
import { Review } from 'src/modules/review/entities/review.entity';
|
import { Review } from 'src/modules/review/entities/review.entity';
|
||||||
import { Favorite } from './favorite.entity';
|
import { Favorite } from './favorite.entity';
|
||||||
import { Variant } from './variant.entity';
|
import { Variant } from './variant.entity';
|
||||||
|
import { PricingType } from '../enum/pricing.enum';
|
||||||
|
import { PurchaseUnit } from '../enum/unit.enum';
|
||||||
|
|
||||||
@Entity({ tableName: 'products' })
|
@Entity({ tableName: 'products' })
|
||||||
@Index({ properties: ['shop', 'isActive'] })
|
@Index({ properties: ['shop', 'isActive'] })
|
||||||
@@ -54,10 +56,33 @@ export class Product extends BaseEntity {
|
|||||||
@Property({ type: 'boolean', default: false })
|
@Property({ type: 'boolean', default: false })
|
||||||
isSpecialOffer: boolean = false;
|
isSpecialOffer: boolean = false;
|
||||||
|
|
||||||
@Property({ type: 'decimal', precision: 10, scale: 0, nullable: true })
|
|
||||||
price?: number;
|
|
||||||
|
|
||||||
/** Maximum quantity per order; null means unlimited */
|
/** Maximum quantity per order; null means unlimited */
|
||||||
@Property({ type: 'int', nullable: true, default: null })
|
@Property({ type: 'int', nullable: true, default: null })
|
||||||
maxPurchaseQuantity: number | null = null;
|
maxPurchaseQuantity: number | null = null;
|
||||||
|
|
||||||
|
@Property({ type: 'int', nullable: true, default: null })
|
||||||
|
minPurchaseQuantity: number | null = null;
|
||||||
|
|
||||||
|
// برای کالا هایی مثل گوشت متغیر میشه
|
||||||
|
@Enum(() => PricingType)
|
||||||
|
pricingType: PricingType = PricingType.FIXED;
|
||||||
|
|
||||||
|
@Enum(() => PurchaseUnit)
|
||||||
|
purchaseUnit: PurchaseUnit = PurchaseUnit.NUMBER;
|
||||||
|
|
||||||
|
// گام جلو رفتن برای برای کالا های مقداری
|
||||||
|
@Property({
|
||||||
|
type: 'decimal',
|
||||||
|
precision: 10,
|
||||||
|
scale: 3,
|
||||||
|
nullable: true,
|
||||||
|
default: null,
|
||||||
|
})
|
||||||
|
purchasePitch?: string | null = null;
|
||||||
|
|
||||||
|
//
|
||||||
|
@Property({ type: 'boolean', default: false })
|
||||||
|
needAdminAcceptance: boolean = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
export enum PricingType {
|
||||||
|
FIXED = 'fixed',
|
||||||
|
VARIABLE = 'variable',
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export enum PurchaseUnit {
|
||||||
|
NUMBER = 'number',
|
||||||
|
KILOGRAM = 'kilogram',
|
||||||
|
GRAM = 'gram',
|
||||||
|
CENTIMETER = 'centimeter',
|
||||||
|
METER = 'meter',
|
||||||
|
MILLILITER = 'milliliter',
|
||||||
|
LITER = 'liter',
|
||||||
|
}
|
||||||
@@ -13,6 +13,8 @@ import { ShopService } from 'src/modules/shops/providers/shops.service';
|
|||||||
import { CategoryService } from './category.service';
|
import { CategoryService } from './category.service';
|
||||||
import { User } from 'src/modules/users/entities/user.entity';
|
import { User } from 'src/modules/users/entities/user.entity';
|
||||||
import { FavoriteRepository } from '../repositories/favorite.repository';
|
import { FavoriteRepository } from '../repositories/favorite.repository';
|
||||||
|
import { PurchaseUnit } from '../enum/unit.enum';
|
||||||
|
import { PricingType } from '../enum/pricing.enum';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ProductService {
|
export class ProductService {
|
||||||
@@ -46,10 +48,14 @@ export class ProductService {
|
|||||||
// map single-title/content DTO to localized fields
|
// map single-title/content DTO to localized fields
|
||||||
title: rest.title,
|
title: rest.title,
|
||||||
attribute: rest.attribute,
|
attribute: rest.attribute,
|
||||||
|
needAdminAcceptance: rest.needAdminAcceptance ,
|
||||||
images: rest.images ?? undefined,
|
images: rest.images ?? undefined,
|
||||||
shop: shop,
|
shop: shop,
|
||||||
category: category,
|
category: category,
|
||||||
|
pricingType: rest.pricingType ,
|
||||||
|
purchaseUnit: rest.purchaseUnit ?? PurchaseUnit.NUMBER,
|
||||||
|
minPurchaseQuantity: rest.minPurchaseQuantity ?? null,
|
||||||
|
purchasePitch: rest.purchasePitch ?? null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const product = em.create(Product, data);
|
const product = em.create(Product, data);
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import type { Shop } from '../modules/shops/entities/shop.entity';
|
|||||||
import type { Category } from '../modules/products/entities/category.entity';
|
import type { Category } from '../modules/products/entities/category.entity';
|
||||||
import { productsData } from './data/products.data';
|
import { productsData } from './data/products.data';
|
||||||
import { Variant } from 'src/modules/products/entities/variant.entity';
|
import { Variant } from 'src/modules/products/entities/variant.entity';
|
||||||
|
import { PurchaseUnit } from 'src/modules/products/enum/unit.enum';
|
||||||
|
import { PricingType } from 'src/modules/products/enum/pricing.enum';
|
||||||
|
|
||||||
export class ProductsSeeder {
|
export class ProductsSeeder {
|
||||||
async run(
|
async run(
|
||||||
@@ -55,6 +57,9 @@ export class ProductsSeeder {
|
|||||||
score: productData.score ?? 0,
|
score: productData.score ?? 0,
|
||||||
images: productData.images,
|
images: productData.images,
|
||||||
isSpecialOffer: productData.isSpecialOffer ?? false,
|
isSpecialOffer: productData.isSpecialOffer ?? false,
|
||||||
|
pricingType: PricingType.FIXED,
|
||||||
|
purchaseUnit: PurchaseUnit.NUMBER,
|
||||||
|
needAdminAcceptance: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
productData.varrinats.forEach(variant => {
|
productData.varrinats.forEach(variant => {
|
||||||
|
|||||||
Reference in New Issue
Block a user