update order

This commit is contained in:
2026-01-26 15:37:11 +03:30
parent bae7f470cc
commit d53bb75fae
9 changed files with 200 additions and 232 deletions
@@ -4,11 +4,14 @@ import { OrderService } from '../providers/order.service';
import { AuthGuard } from '../../auth/guards/auth.guard';
import { UserId } from '../../../common/decorators/user-id.decorator';
import { FindOrdersDto } from '../dto/find-orders.dto';
import { CreateOrderDto, CreateOrderItemAsUserDto, CreateOrderItemDtoAsAdmin } from '../dto/create-order.dto';
import {
CreateOrderDto, CreateOrderItemAsUserDto,
CreateOrderItemDtoAsAdmin, CreateOrderAsAdminDto
} from '../dto/create-order.dto';
import { AdminId } from 'src/common/decorators/admin-id.decorator';
import { CreateOrderAsAdminDto } from '../dto/create-order-as-admin.dto';
import { AssignDesignerDto } from '../dto/assign-designer.dto';
import { UpdateOrderItemDtoAsAdmin, UpdateOrderItemDtoAsUser } from '../dto/update-order-item.dto';
import { UpdateOrderDtoAsAdmin } from '../dto/update-order.dto';
@ApiTags('orders')
@ApiBearerAuth()
@@ -18,14 +21,14 @@ export class OrderController {
@Post('public/order')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'create order as user' })
@ApiOperation({ summary: 'create order ' })
createOrder(@UserId() userId: string, @Body() body: CreateOrderDto) {
return this.orderService.createOrderAsUser(userId, body);
}
@Delete('public/order/:id')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Delete order as user' })
@ApiOperation({ summary: 'Delete order ' })
deleteOrder(@Param('id') orderId: string) {
return this.orderService.removeOrderAsUser(orderId);
}
@@ -41,7 +44,7 @@ export class OrderController {
@Patch('public/order/:id/item')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'add item to order as user' })
@ApiOperation({ summary: 'add item to order ' })
addOrderItem(@Param('id') orderId: string, @UserId() userId: string, @Body() body: CreateOrderItemAsUserDto) {
return this.orderService.addOrderItemAsUser(userId, orderId, body);
}
@@ -49,16 +52,15 @@ export class OrderController {
@Patch('public/order/:id/item/:itemId')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Update order item as user' })
updateOrder(@Param('id') orderId: string, @UserId() userId: string, @Param(':itemId') itemId: string, @Body() body: UpdateOrderItemDtoAsUser) {
@ApiOperation({ summary: 'Update order item ' })
updateOrderItem(@Param('id') orderId: string, @UserId() userId: string, @Param(':itemId') itemId: string, @Body() body: UpdateOrderItemDtoAsUser) {
return this.orderService.updateOrderItemAsUser(userId, orderId, itemId, body);
}
@Post('public/orders/:orderId/items/:orderItemId/confirm')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Confirm Invoice Item By User' })
@ApiOperation({ summary: 'Confirm Invoice Item ' })
confirmOrderItem(
@Param('orderId') orderId: string,
@Param('orderItemId') orderItemId: string,
@@ -69,7 +71,7 @@ export class OrderController {
@Delete('public/orders/:orderId/items/:orderItemId')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Remove order Item By User' })
@ApiOperation({ summary: 'Remove order Item ' })
removeOrderItem(
@Param('orderId') orderId: string,
@Param('orderItemId') orderItemId: string,
@@ -82,11 +84,18 @@ export class OrderController {
@Post('admin/order')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'create order as admin' })
@ApiOperation({ summary: 'create order ' })
createOrderAsAdmin(@AdminId() adminId: string, @Body() body: CreateOrderAsAdminDto) {
return this.orderService.createOrderAsAdmin(adminId, body);
}
@Patch('admin/orders/:orderId')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Update Order ' })
updateOrder(@Param('orderId') orderId: string, @Body() dto: UpdateOrderDtoAsAdmin) {
return this.orderService.updateOrder(orderId, dto);
}
@Delete('admin/orders/:orderId')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Hard Delete Order ' })
@@ -112,7 +121,7 @@ export class OrderController {
@Delete('admin/orders/:orderId/items/:orderItemId')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Remove order Item By Admin' })
@ApiOperation({ summary: 'Remove order Item ' })
removeOrderItemAdAdmin(
@Param('orderId') orderId: string,
@Param('orderItemId') orderItemId: string,
@@ -122,7 +131,7 @@ export class OrderController {
@Patch('admin/order/:id/item')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'add item to order By Admin' })
@ApiOperation({ summary: 'add item to order ' })
addOrderItemAsAdmin(@Param('id') orderId: string, @Body() body: CreateOrderItemDtoAsAdmin) {
return this.orderService.addOrderItemAsAdmin(orderId, body);
}
@@ -1,47 +0,0 @@
import {
IsArray, IsNumber,
IsNotEmpty,
ArrayMinSize
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
export class InvoiceItemDto {
@IsNumber()
@ApiProperty()
productId: number;
@ApiProperty()
@IsArray()
attributesValues: string[]
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
}
export class AddOrderItemDto {
@IsArray()
@ApiProperty({
isArray: true, type: [InvoiceItemDto], example: [
{
orderItemId: 1,
unitPrice: 100,
}
]
})
@IsNotEmpty()
@ArrayMinSize(1, { message: 'At least one product is required' })
@Type(() => InvoiceItemDto)
items: InvoiceItemDto[];
}
@@ -1,97 +0,0 @@
import {
IsString,
IsInt, IsArray, IsNumber,
IsNotEmpty,
ArrayMinSize,
IsMobilePhone,
IsOptional,
IsBoolean,
IsEnum
} from 'class-validator';
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { OrderStatusEnum } from '../interface/order.interface';
export class CreateOrderItemDto {
@IsInt()
@ApiProperty()
productId: bigint;
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsArray()
attributesValues: string[]
@ApiProperty()
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
@ApiPropertyOptional({ example: 'توضیحات' })
@IsString()
description: string
@ApiPropertyOptional({ example: [] })
@IsArray()
@IsString({ each: true })
attachments: { url: string, type: string }[]
}
export class CreateOrderAsAdminDto {
@ApiProperty({ example: '' })
@IsString()
@IsNotEmpty()
userId: string
@IsArray()
@ApiProperty({
isArray: true, type: [CreateOrderItemDto], example: [
{
productId: 1,
quantity: 100,
attributesValues: []
}
]
})
@IsNotEmpty()
@ArrayMinSize(1, { message: 'At least one product is required' })
@Type(() => CreateOrderItemDto)
items: CreateOrderItemDto[];
@ApiProperty({ example: '' })
@IsString()
@IsNotEmpty()
designerId: string
@ApiProperty({ example: '' })
@IsArray()
@IsString({ each: true })
@IsNotEmpty()
attachments: string[]
@ApiProperty({})
@IsString()
@IsOptional()
paymentMethod: string
@ApiProperty({})
@IsBoolean()
enableTax: Boolean
@ApiProperty({})
@IsInt()
estimatedDays: number
@ApiProperty({ enum: OrderStatusEnum })
@IsEnum(OrderStatusEnum)
status: OrderStatusEnum
}
+95 -4
View File
@@ -2,10 +2,14 @@ import {
IsString,
IsInt, IsArray, IsNumber,
IsNotEmpty,
ArrayMinSize
ArrayMinSize,
IsOptional,
IsBoolean,
IsEnum
} from 'class-validator';
import { ApiPropertyOptional, ApiProperty, OmitType } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IAttribute, OrderStatusEnum } from '../interface/order.interface';
export class CreateOrderItemDtoAsAdmin {
@@ -16,10 +20,10 @@ export class CreateOrderItemDtoAsAdmin {
@ApiProperty()
@IsNumber()
quantity: number
// TODO : find a way to save attribute and value
@ApiProperty()
@IsArray()
attributesValues: string[]
attributes: IAttribute[]
@ApiPropertyOptional({ example: 'توضیحات' })
@IsString()
@@ -49,7 +53,12 @@ export class CreateOrderDto {
{
productId: 1,
quantity: 100,
attributesValues: [],
attributes: [
{
attributeId:1,
value:'string | boolean| number'
}
],
attachments: [
{ url: '', type: '' }
],
@@ -63,3 +72,85 @@ export class CreateOrderDto {
items: CreateOrderItemAsUserDto[];
}
export class CreateOrderItemDto {
@IsInt()
@ApiProperty()
productId: bigint;
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsArray()
attributes: IAttribute[]
@ApiProperty()
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
@ApiPropertyOptional({ example: 'توضیحات' })
@IsString()
description: string
@ApiPropertyOptional({ example: [] })
@IsArray()
@IsString({ each: true })
attachments: { url: string, type: string }[]
}
export class CreateOrderAsAdminDto {
@ApiProperty({ example: '' })
@IsString()
@IsNotEmpty()
userId: string
@IsArray()
@ApiProperty({
isArray: true, type: [CreateOrderItemDto], example: [
{
productId: 1,
quantity: 100,
attributesValues: []
}
]
})
@IsNotEmpty()
@ArrayMinSize(1, { message: 'At least one product is required' })
@Type(() => CreateOrderItemDto)
items: CreateOrderItemDto[];
@ApiProperty({ example: '' })
@IsString()
@IsNotEmpty()
designerId: string
@ApiProperty({ example: '' })
@IsArray()
@IsString({ each: true })
@IsNotEmpty()
attachments: string[]
@ApiProperty({})
@IsString()
@IsOptional()
paymentMethod: string
@ApiProperty({})
@IsBoolean()
enableTax: Boolean
@ApiProperty({})
@IsInt()
estimatedDays: number
@ApiProperty({ enum: OrderStatusEnum })
@IsEnum(OrderStatusEnum)
status: OrderStatusEnum
}
@@ -1,59 +0,0 @@
import {
IsArray, IsNumber,
IsNotEmpty,
ArrayMinSize,
IsBoolean,
IsString
} from 'class-validator';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
export class ItemDto {
@IsNumber()
@ApiProperty()
orderItemId: number;
@ApiProperty()
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
@ApiProperty()
@IsNumber()
quantity: number
}
export class UpdateOrderDtoAsUser {
@IsArray()
@ApiProperty({
isArray: true, type: [ItemDto], example: [
{
orderItemId: 1,
unitPrice: 100,
}
]
})
@IsNotEmpty()
@ArrayMinSize(1, { message: 'At least one product is required' })
@Type(() => ItemDto)
items: ItemDto[];
@ApiProperty()
@IsBoolean()
enableTax: boolean
@ApiPropertyOptional({ example: [] })
@IsArray()
@IsString({ each: true })
attachments: string[]
}
@@ -0,0 +1,5 @@
import { OmitType, PartialType } from '@nestjs/swagger';
import { CreateOrderAsAdminDto, CreateOrderDto } from './create-order.dto';
export class UpdateOrderDtoAsAdmin extends PartialType(OmitType(CreateOrderAsAdminDto, 'items' as any)) { }
@@ -2,6 +2,7 @@ import { Entity, Index, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core'
import { BaseEntity } from '../../../common/entities/base.entity';
import { Order } from './order.entity';
import { Product } from 'src/modules/product/entities/product.entity';
import { IAttribute } from '../interface/order.interface';
// import { OrderItemStatus } from '../interface/order.interface';
@Entity({ tableName: 'order_items' })
@@ -17,7 +18,7 @@ export class OrderItem extends BaseEntity {
product!: Product;
@Property({ type: 'json' })
attributesValues: string[]
attributes: IAttribute[]
@Property({ type: 'int' })
quantity!: number;
@@ -29,7 +29,7 @@ export enum OrderStatusEnum {
export interface IAddOrderItem {
productId: bigint;
quantity: number
attributesValues: string[]
attributes: IAttribute[]
description: string
attachments: { url: string, type: string }[]
unitPrice?: number
@@ -50,3 +50,7 @@ export interface ICreateOrder {
estimatedDays?: number
designerId?: string
}
export type IUpdateOrder = Partial<Omit<ICreateOrder, 'items'>>
export interface IAttribute { attributeId: number, value: string | number | boolean }
+70 -9
View File
@@ -4,20 +4,21 @@ import { OrderItem } from '../entities/order-item.entity';
import { OrderRepository } from '../repositories/order.repository';
import { FindOrdersDto } from '../dto/find-orders.dto';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { CreateOrderDto, CreateOrderItemAsUserDto, CreateOrderItemDtoAsAdmin } from '../dto/create-order.dto';
import {
CreateOrderDto, CreateOrderItemAsUserDto,
CreateOrderItemDtoAsAdmin, CreateOrderAsAdminDto
} from '../dto/create-order.dto';
import { UserService } from 'src/modules/user/providers/user.service';
import { IAddOrderItem, ICreateOrder, OrderStatusEnum, IUpdateOrderItem } from '../interface/order.interface';
import { IAddOrderItem, ICreateOrder, OrderStatusEnum, IUpdateOrderItem, IUpdateOrder } from '../interface/order.interface';
import { OrderItemRepository } from '../repositories/order-item.repository';
import { ProductService } from 'src/modules/product/providers/product.service';
import { ProductRepository } from 'src/modules/product/repositories/product.repository';
import { TicketService } from 'src/modules/ticket/providers/tickets.service';
import { TicketRepository } from 'src/modules/ticket/repositories/tickets.repository';
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
import { CreateOrderAsAdminDto } from '../dto/create-order-as-admin.dto';
import { Order } from '../entities/order.entity';
import { PaymentRepository } from 'src/modules/payment/repositories/payment.repository';
import { UpdateOrderItemDtoAsAdmin, UpdateOrderItemDtoAsUser } from '../dto/update-order-item.dto';
import { UpdateOrderDtoAsUser } from '../dto/update-order-as-user.dto';
import { Admin } from 'src/modules/admin/entities/admin.entity';
@@ -117,6 +118,66 @@ export class OrderService {
}
async updateOrder(orderId: string, dto: IUpdateOrder) {
const { attachments, adminId, designerId, enableTax, estimatedDays, paymentMethod, status, userId } = dto
const order = await this.findOneOrFail(orderId)
if (userId) {
const user = await this.userService.findById(userId)
if (!user) {
throw new BadRequestException("User not found!")
}
order.user = user
}
if (adminId) {
const admin = await this.adminRepository.findOne({ id: adminId })
if (!admin) {
throw new BadRequestException("Admin not found")
}
order.creator = admin
}
if (designerId) {
const designer = await this.adminRepository.findOne({ id: designerId })
if (!designer) {
throw new BadRequestException("designer not found")
}
order.designer = designer
}
if (attachments) {
order.attachments = attachments
}
if (typeof enableTax !== 'undefined') {
order.enableTax = enableTax
}
if (estimatedDays) {
order.estimatedDays = estimatedDays
}
if (paymentMethod) {
order.paymentMethod = paymentMethod
}
if (status) {
order.status = status
}
this.em.persist(order)
await this.calculateOrder(order)
await this.em.flush()
return order
}
async addOrderItemAsUser(userId: string, orderId: string, dto: CreateOrderItemAsUserDto) {
const order = await this.findOneOrFail(orderId)
@@ -152,7 +213,7 @@ export class OrderService {
}
private async persistOrderItem(order: Order, dto: IAddOrderItem) {
const { attributesValues, description, productId, quantity, attachments, discount, unitPrice } = dto
const { attributes, description, productId, quantity, attachments, discount, unitPrice } = dto
const found = order.items.find(it => it.product.id == productId)
if (found) {
@@ -165,7 +226,7 @@ export class OrderService {
}
const orderItem = this.orderItemRepository.create({
order,
attributesValues,
attributes,
description,
quantity,
attachments,
@@ -212,7 +273,7 @@ export class OrderService {
}
async updateOrderItem(itemId: string, dto: IUpdateOrderItem) {
const { attributesValues, description, productId, quantity, attachments, discount, unitPrice } = dto
const { attributes, description, productId, quantity, attachments, discount, unitPrice } = dto
const orderItem = await this.orderItemRepository.findOne({
id: itemId
@@ -233,8 +294,8 @@ export class OrderService {
orderItem.product = product
}
if (attributesValues) {
orderItem.attributesValues = attributesValues
if (attributes) {
orderItem.attributes = attributes
}
if (description) {
orderItem.description = description