From 5d4154d135ed903a5a3e1540ae7d7539f2de26ee Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Fri, 20 Feb 2026 11:13:06 +0330 Subject: [PATCH] order --- .../order/controllers/order.controller.ts | 27 ++++--- src/modules/order/dto/create-order.dto.ts | 9 ++- src/modules/order/dto/update-order.dto.ts | 21 ++--- src/modules/order/providers/order.service.ts | 80 ++++++++++++++++++- 4 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src/modules/order/controllers/order.controller.ts b/src/modules/order/controllers/order.controller.ts index 797f316..791d782 100644 --- a/src/modules/order/controllers/order.controller.ts +++ b/src/modules/order/controllers/order.controller.ts @@ -7,6 +7,7 @@ import { FindOrdersDto } from '../dto/find-orders.dto'; import { CreateOrderAsAdminDto, } from '../dto/create-order.dto'; +import { UpdateOrderAsAdminDto } from '../dto/update-order.dto'; import { AdminId } from 'src/common/decorators/admin-id.decorator'; import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard'; import { Permissions } from 'src/common/decorators/permissions.decorator'; @@ -46,20 +47,20 @@ export class OrderController { } - // @Get('admin/orders/:id') - // @UseGuards(AdminAuthGuard) - // @ApiOperation({ summary: 'order detail' }) - // orderDetailAsAdmin(@Param('id') orderId: string) { - // return this.orderService.findOrderOrFail(orderId); - // } + @Get('admin/orders/:id') + @UseGuards(AdminAuthGuard) + @ApiOperation({ summary: 'order detail' }) + orderDetailAsAdmin(@Param('id') orderId: string) { + return this.orderService.findOrderOrFail(orderId); + } - // @Patch('admin/orders/:id') - // @UseGuards(AdminAuthGuard) - // @Permissions(PermissionEnum.UPDATE_ORDER) - // @ApiOperation({ summary: 'Update Order ' }) - // updateOrder(@Param('id') id: string, @Body() dto: UpdateOrderAsAdminDto) { - // return this.orderService.updateOrderAsAdmin(id, dto); - // } + @Patch('admin/orders/:id') + @UseGuards(AdminAuthGuard) + @Permissions(PermissionEnum.UPDATE_ORDER) + @ApiOperation({ summary: 'Update Order ' }) + updateOrder(@Param('id') id: string, @Body() dto: UpdateOrderAsAdminDto) { + return this.orderService.updateOrderAsAdmin(id, dto); + } // @Delete('admin/orders/:orderId') // @UseGuards(AdminAuthGuard) diff --git a/src/modules/order/dto/create-order.dto.ts b/src/modules/order/dto/create-order.dto.ts index 3165edf..5d67a5d 100644 --- a/src/modules/order/dto/create-order.dto.ts +++ b/src/modules/order/dto/create-order.dto.ts @@ -8,10 +8,15 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; export class CreateOrderAsAdminDto { - @ApiProperty({ example: '' }) + @ApiPropertyOptional({ example: '' }) @IsString() @IsNotEmpty() - userId: string; + userId?: string; + + @ApiPropertyOptional({ example: '' }) + @IsString() + @IsNotEmpty() + invoiceItemId?: string; @ApiProperty() @IsString() diff --git a/src/modules/order/dto/update-order.dto.ts b/src/modules/order/dto/update-order.dto.ts index 879235d..5f6fe87 100644 --- a/src/modules/order/dto/update-order.dto.ts +++ b/src/modules/order/dto/update-order.dto.ts @@ -1,14 +1,15 @@ -import { ApiProperty, OmitType, PartialType } from '@nestjs/swagger'; +import { ApiProperty, ApiPropertyOptional, PartialType } from '@nestjs/swagger'; import { CreateOrderAsAdminDto, CreateOrderItemDtoAsAdmin } from './create-order.dto'; -import { IsNumber } from 'class-validator'; - -export class UpdateOrderAsAdminDto extends PartialType(OmitType(CreateOrderAsAdminDto, 'items' as any)) { - @ApiProperty() - items: UpdateOrCreateOrderItem[] -} +import { IsOptional, IsString } from 'class-validator'; export class UpdateOrCreateOrderItem extends CreateOrderItemDtoAsAdmin { - @ApiProperty() - @IsNumber() - id: string + @ApiProperty() + @IsString() + id: string; +} + +export class UpdateOrderAsAdminDto extends PartialType(CreateOrderAsAdminDto) { + @ApiPropertyOptional({ type: [UpdateOrCreateOrderItem] }) + @IsOptional() + items?: UpdateOrCreateOrderItem[]; } \ No newline at end of file diff --git a/src/modules/order/providers/order.service.ts b/src/modules/order/providers/order.service.ts index 55d4ee6..6af83fa 100644 --- a/src/modules/order/providers/order.service.ts +++ b/src/modules/order/providers/order.service.ts @@ -24,6 +24,7 @@ import { PermissionEnum } from 'src/common/enums/permission.enum'; import { User } from 'src/modules/user/entities/user.entity'; import { OrderType } from '../entities/order-type.entity'; import { Product } from 'src/modules/product/entities/product.entity'; +import { InvoiceItem } from 'src/modules/invoice/entities/invoice-item.entity'; @Injectable() export class OrderService { @@ -45,11 +46,34 @@ export class OrderService { ) { } async createOrderAsAdmin(adminId: string, dto: CreateOrderAsAdminDto): Promise { - const user = await this.userService.findById(dto.userId); - if (!user) { - throw new NotFoundException(`User with ID ${dto.userId} not found.`); + let invoiceItem: null | InvoiceItem = null + let user: User | null = null + + if (dto.invoiceItemId) { + invoiceItem = await this.em.findOne(InvoiceItem, { id: dto.invoiceItemId },{populate:['invoice','invoice.user']}); + if (!invoiceItem) { + throw new NotFoundException(`Invoice item with ID ${dto.invoiceItemId} not found.`); + } + + user=invoiceItem.invoice.user + } + if (!invoiceItem) { + + if (!dto.userId) { + throw new NotFoundException(`UserId is mandatory`); + } + + const user = await this.userService.findById(dto.userId); + + if (!user) { + throw new NotFoundException(`User with ID ${dto.userId} not found.`); + } } + if(!user){ + throw new NotFoundException(`User not found`); + } + const creator = await this.adminService.findOrFail(adminId); const type = await this.em.findOne(OrderType, { id: dto.typeId }); @@ -66,16 +90,64 @@ export class OrderService { } const order = this.em.create(Order, { - user: user as User, + user, creator, type, product: product ?? null, title: dto.title, status: OrderStatusEnum.CREATED, estimatedDays: dto.estimatedDays, + invoiceItem }); await this.em.persistAndFlush(order); return order; } + + async findOrderOrFail(id: string): Promise { + const order = await this.em.findOne(Order, { id }, { populate: ['user', 'type', 'product', 'creator'] }); + if (!order) { + throw new NotFoundException(`Order with ID ${id} not found.`); + } + return order; + } + // user should not be change able + async updateOrderAsAdmin(id: string, dto: UpdateOrderAsAdminDto): Promise { + const order = await this.findOrderOrFail(id); + + if (dto.userId !== undefined) { + const user = await this.userService.findById(dto.userId); + if (!user) { + throw new NotFoundException(`User with ID ${dto.userId} not found.`); + } + order.user = user as User; + } + if (dto.typeId !== undefined) { + const type = await this.em.findOne(OrderType, { id: dto.typeId }); + if (!type) { + throw new NotFoundException(`Order type with ID ${dto.typeId} not found.`); + } + order.type = type; + } + if (dto.estimatedDays !== undefined) { + order.estimatedDays = dto.estimatedDays; + } + if (dto.title !== undefined) { + order.title = dto.title; + } + if (dto.productId !== undefined) { + if (dto.productId == null || dto.productId === '') { + order.product = null; + } else { + const product = await this.em.findOne(Product, { id: dto.productId }); + if (!product) { + throw new NotFoundException(`Product with ID ${dto.productId} not found.`); + } + order.product = product; + } + } + + await this.em.flush(); + return order; + } }