order
This commit is contained in:
@@ -5,16 +5,10 @@ import { AuthGuard } from '../../auth/guards/auth.guard';
|
||||
import { UserId } from '../../../common/decorators/user-id.decorator';
|
||||
import { FindOrdersDto } from '../dto/find-orders.dto';
|
||||
import {
|
||||
CreateOrderAsUSerDto, CreateOrderItemAsUserDto,
|
||||
CreateOrderItemDtoAsAdmin, CreateOrderAsAdminDto
|
||||
CreateOrderAsAdminDto,
|
||||
} from '../dto/create-order.dto';
|
||||
import { AdminId } from 'src/common/decorators/admin-id.decorator';
|
||||
import { AssignDesignerDto } from '../dto/assign-designer.dto';
|
||||
import { UpdateOrderItemDtoAsAdmin, UpdateOrderItemDtoAsUser } from '../dto/update-order-item.dto';
|
||||
import { UpdateOrderAsAdminDto } from '../dto/update-order.dto';
|
||||
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
||||
import { CreatePrintFormDto } from '../dto/create-print-form.dto';
|
||||
import { FindOrderItemsDto } from '../dto/find-order-items.dto';
|
||||
import { Permissions } from 'src/common/decorators/permissions.decorator';
|
||||
import { PermissionEnum } from 'src/common/enums/permission.enum';
|
||||
|
||||
@@ -26,71 +20,20 @@ export class OrderController {
|
||||
|
||||
// ================== Public ===================
|
||||
|
||||
@Post('public/orders')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'create order ' })
|
||||
createOrder(@UserId() userId: string, @Body() body: CreateOrderAsUSerDto) {
|
||||
return this.orderService.createOrderAsUser(userId, body);
|
||||
}
|
||||
// @Get('public/orders')
|
||||
// @UseGuards(AuthGuard)
|
||||
// @ApiOperation({ summary: 'Get all orders with pagination and filters' })
|
||||
// findAll(@Query() dto: FindOrdersDto, @UserId() userId: string) {
|
||||
// return this.orderService.findOrdersAsUser(userId, dto);
|
||||
// }
|
||||
|
||||
@Delete('public/orders/:id')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Delete order ' })
|
||||
deleteOrder(@Param('id') orderId: string, @UserId() userId: string) {
|
||||
return this.orderService.removeOrderAsUser(userId, orderId);
|
||||
}
|
||||
// @Get('public/orders/:id')
|
||||
// @UseGuards(AuthGuard)
|
||||
// @ApiOperation({ summary: 'order detail' })
|
||||
// orderDetail(@Param('id') orderId: string, @UserId() userId: string) {
|
||||
// return this.orderService.getOrderAsUser(userId, orderId);
|
||||
// }
|
||||
|
||||
@Get('public/orders')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Get all orders with pagination and filters' })
|
||||
findAll(@Query() dto: FindOrdersDto, @UserId() userId: string) {
|
||||
return this.orderService.findOrdersAsUser(userId, dto);
|
||||
}
|
||||
|
||||
@Get('public/orders/:id')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'order detail' })
|
||||
orderDetail(@Param('id') orderId: string, @UserId() userId: string) {
|
||||
return this.orderService.getOrderAsUser(userId, orderId);
|
||||
}
|
||||
|
||||
@Post('public/orders/:id/item')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'add item to order ' })
|
||||
addOrderItem(@Param('id') orderId: string, @UserId() userId: string, @Body() body: CreateOrderItemAsUserDto) {
|
||||
return this.orderService.addOrderItemAsUser(userId, orderId, body);
|
||||
}
|
||||
|
||||
|
||||
@Patch('public/orders/:id/item/:itemId')
|
||||
@UseGuards(AuthGuard)
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
@Patch('public/orders/:orderId/items/:orderItemId/confirm')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Confirm Invoice Item ' })
|
||||
confirmOrderItem(
|
||||
@Param('orderId') orderId: string,
|
||||
@Param('orderItemId') orderItemId: string,
|
||||
@UserId() userId: string
|
||||
) {
|
||||
return this.orderService.confirmOrderItem(userId, orderId, orderItemId);
|
||||
}
|
||||
|
||||
@Delete('public/orders/:orderId/items/:orderItemId')
|
||||
@UseGuards(AuthGuard)
|
||||
@ApiOperation({ summary: 'Remove order Item ' })
|
||||
removeOrderItem(
|
||||
@Param('orderId') orderId: string,
|
||||
@Param('orderItemId') orderItemId: string,
|
||||
@UserId() userId: string
|
||||
) {
|
||||
return this.orderService.removeOrderItemAsUser(userId, orderId, orderItemId);
|
||||
}
|
||||
|
||||
/*========================== Admin Routes =====================*/
|
||||
|
||||
@@ -102,115 +45,71 @@ export class OrderController {
|
||||
return this.orderService.createOrderAsAdmin(adminId, body);
|
||||
}
|
||||
|
||||
@Get('admin/orders/request')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.VIEW_REQUESTS)
|
||||
@ApiOperation({ summary: 'Get all order requests with pagination and filters' })
|
||||
findOrderRequestAsAdmin(@Query() dto: FindOrdersDto) {
|
||||
return this.orderService.findOrderRequestsAsAdmin(dto);
|
||||
}
|
||||
|
||||
// this route permission is handled inside service
|
||||
@Get('admin/orders/invoiced')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiOperation({ summary: 'Get all invoiced orders with pagination and filters' })
|
||||
findInvoicedOrdersAsAdmin(@Query() dto: FindOrdersDto, @AdminId() adminId: string) {
|
||||
return this.orderService.findInvoicedOrdersAsAdmin(adminId, dto);
|
||||
}
|
||||
|
||||
@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.updateOrderAsAdmin2(id, dto);
|
||||
}
|
||||
|
||||
@Delete('admin/orders/:orderId')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.REMOVE_ORDER)
|
||||
@ApiOperation({ summary: 'Hard Delete Order ' })
|
||||
hardDelete(@Param('orderId') orderId: string) {
|
||||
return this.orderService.hardDeleteOrder(orderId);
|
||||
}
|
||||
|
||||
// =============== Order Item ================
|
||||
|
||||
@Get('admin/orders/item/print')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.VIEW_All_ORDERS)
|
||||
@ApiOperation({ summary: 'get print orders' })
|
||||
getPrintOrders(@Body() dto: FindOrderItemsDto) {
|
||||
return this.orderService.findPrintOrderItemsAsAdmin(dto);
|
||||
}
|
||||
|
||||
@Get('admin/orders/item/:id')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiOperation({ summary: 'order item detail' })
|
||||
getOrderItem(@Param('id') itemId: string) {
|
||||
return this.orderService.findOrderItemOrFailByItemId(itemId);
|
||||
}
|
||||
|
||||
|
||||
@Post('admin/orders/:orderId/item/:itemId/designer')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.ASSIGN_DESIGNER)
|
||||
@ApiOperation({ summary: 'Assign Order Designer ' })
|
||||
assignDesigner(@Param('orderId') orderId: string, @Param('itemId') itemId: string,
|
||||
@Body() body: AssignDesignerDto) {
|
||||
return this.orderService.assignDesigner(orderId, itemId, body.designerId);
|
||||
}
|
||||
|
||||
@Patch('admin/orders/:id/item/:itemId/print')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.CREATE_ORDER_PRINT)
|
||||
@ApiOperation({ summary: 'Create Print form for order item' })
|
||||
createPrintForm(@Param('id') id: string, @Param('itemId') itemId: string, @Body() dto: CreatePrintFormDto) {
|
||||
return this.orderService.createPrintForm(id, itemId, dto);
|
||||
}
|
||||
|
||||
// @Post('admin/orders/:orderId/invoice')
|
||||
// @Get('admin/orders/:id')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @ApiOperation({ summary: 'Create Order invoice ' })
|
||||
// createInvoice(@Param('orderId') orderId: string) {
|
||||
// return this.orderService.createInvoice(orderId);
|
||||
// @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);
|
||||
// }
|
||||
|
||||
// @Delete('admin/orders/:orderId')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @Permissions(PermissionEnum.REMOVE_ORDER)
|
||||
// @ApiOperation({ summary: 'Hard Delete Order ' })
|
||||
// hardDelete(@Param('orderId') orderId: string) {
|
||||
// return this.orderService.hardDeleteOrder(orderId);
|
||||
// }
|
||||
|
||||
// // =============== Order Item ================
|
||||
|
||||
|
||||
// @Post('admin/orders/:orderId/item/:itemId/designer')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @Permissions(PermissionEnum.ASSIGN_DESIGNER)
|
||||
// @ApiOperation({ summary: 'Assign Order Designer ' })
|
||||
// assignDesigner(@Param('orderId') orderId: string, @Param('itemId') itemId: string,
|
||||
// @Body() body: AssignDesignerDto) {
|
||||
// return this.orderService.assignDesigner(orderId, itemId, body.designerId);
|
||||
// }
|
||||
|
||||
|
||||
@Delete('admin/orders/:id/items/:itemId')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
@ApiOperation({ summary: 'Remove order Item ' })
|
||||
removeOrderItemAdAdmin(
|
||||
@Param('id') orderId: string,
|
||||
@Param('itemId') itemId: string,
|
||||
) {
|
||||
return this.orderService.removeOrderItemAsAdmin(orderId, itemId);
|
||||
}
|
||||
|
||||
@Post('admin/orders/:id/item')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
@ApiOperation({ summary: 'add item to order ' })
|
||||
addOrderItemAsAdmin(@Param('id') orderId: string, @Body() body: CreateOrderItemDtoAsAdmin) {
|
||||
return this.orderService.addOrderItemAsAdmin(orderId, body);
|
||||
}
|
||||
// @Delete('admin/orders/:id/items/:itemId')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
// @ApiOperation({ summary: 'Remove order Item ' })
|
||||
// removeOrderItemAdAdmin(
|
||||
// @Param('id') orderId: string,
|
||||
// @Param('itemId') itemId: string,
|
||||
// ) {
|
||||
// return this.orderService.removeOrderItemAsAdmin(orderId, itemId);
|
||||
// }
|
||||
|
||||
// @Post('admin/orders/:id/item')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
// @ApiOperation({ summary: 'add item to order ' })
|
||||
// addOrderItemAsAdmin(@Param('id') orderId: string, @Body() body: CreateOrderItemDtoAsAdmin) {
|
||||
// return this.orderService.addOrderItemAsAdmin(orderId, body);
|
||||
// }
|
||||
|
||||
|
||||
@Patch('admin/orders/:id/item/:itemId')
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
@ApiOperation({ summary: 'Update order item' })
|
||||
updateOrderItemAsAdmin(@Param('id') orderId: string, @Param('itemId') itemId: string,
|
||||
@Body() body: UpdateOrderItemDtoAsAdmin) {
|
||||
return this.orderService.updateOrderItemAsAdmin(orderId, itemId, body);
|
||||
}
|
||||
// @Patch('admin/orders/:id/item/:itemId')
|
||||
// @UseGuards(AdminAuthGuard)
|
||||
// @Permissions(PermissionEnum.UPDATE_ORDER)
|
||||
// @ApiOperation({ summary: 'Update order item' })
|
||||
// updateOrderItemAsAdmin(@Param('id') orderId: string, @Param('itemId') itemId: string,
|
||||
// @Body() body: UpdateOrderItemDtoAsAdmin) {
|
||||
// return this.orderService.updateOrderItemAsAdmin(orderId, itemId, body);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -1,146 +1,46 @@
|
||||
import {
|
||||
IsString,
|
||||
IsInt, IsArray, IsNumber,
|
||||
IsInt,
|
||||
IsNotEmpty,
|
||||
ArrayMinSize,
|
||||
IsOptional,
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsDateString
|
||||
} from 'class-validator';
|
||||
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IAttachment, IField, OrderItemStatusEnum } from '../interface/order.interface';
|
||||
|
||||
|
||||
export class CreateOrderItemAsUserDto {
|
||||
@IsString()
|
||||
@ApiProperty()
|
||||
productId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
quantity: number
|
||||
|
||||
@ApiProperty({ enum: OrderItemStatusEnum })
|
||||
@IsEnum(() => OrderItemStatusEnum)
|
||||
status: OrderItemStatusEnum
|
||||
|
||||
@ApiProperty()
|
||||
@IsArray()
|
||||
attributes: IField[]
|
||||
|
||||
@ApiPropertyOptional({ example: 'توضیحات' })
|
||||
@IsString()
|
||||
description: string
|
||||
|
||||
@ApiPropertyOptional({ example: [] })
|
||||
@IsArray()
|
||||
attachments: { url: string, type: string }[]
|
||||
|
||||
|
||||
}
|
||||
|
||||
export class CreateOrderItemDtoAsAdmin extends CreateOrderItemAsUserDto {
|
||||
// @ApiPropertyOptional({ example: [] })
|
||||
// @IsArray()
|
||||
// printAttributes?: IField[]
|
||||
|
||||
// @ApiPropertyOptional({ example: [] })
|
||||
// @IsArray()
|
||||
// printAttachments?: IAttachment[]
|
||||
|
||||
@IsInt()
|
||||
@ApiProperty()
|
||||
designerId: string;
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
unitPrice: number
|
||||
|
||||
@ApiProperty()
|
||||
@IsNumber()
|
||||
discount: number
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsString()
|
||||
adminDescription: string
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsDateString()
|
||||
confirmedAt: string
|
||||
|
||||
}
|
||||
|
||||
export class CreateOrderAsUSerDto {
|
||||
@IsArray()
|
||||
@ApiProperty({
|
||||
isArray: true, type: [CreateOrderItemAsUserDto],
|
||||
example: [
|
||||
{
|
||||
productId: 'sd4',
|
||||
quantity: 100,
|
||||
attributes: [
|
||||
{
|
||||
attributeId: 1,
|
||||
value: 'string | boolean| number'
|
||||
}
|
||||
],
|
||||
attachments: [
|
||||
{ url: '', type: '' }
|
||||
],
|
||||
description: ''
|
||||
}
|
||||
]
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@ArrayMinSize(1, { message: 'At least one item is required' })
|
||||
@Type(() => CreateOrderItemAsUserDto)
|
||||
items: CreateOrderItemAsUserDto[];
|
||||
}
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
|
||||
export class CreateOrderAsAdminDto {
|
||||
@ApiProperty({ example: '' })
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
userId: string
|
||||
userId: string;
|
||||
|
||||
@IsArray()
|
||||
@ApiProperty({
|
||||
isArray: true, type: [CreateOrderItemDtoAsAdmin], example: [
|
||||
{
|
||||
productId: 1,
|
||||
designerId: '',
|
||||
attachments: [{ url: '', type: '' }],
|
||||
quantity: 100,
|
||||
attributes: [{ fieldId: 10, value: 'blue' }],
|
||||
unitPrice: 150000,
|
||||
discount: 20000,
|
||||
adminDescription: '',
|
||||
description: 'توضیحات کاربر',
|
||||
|
||||
}
|
||||
]
|
||||
})
|
||||
@IsNotEmpty()
|
||||
@ArrayMinSize(1, { message: 'At least one product is required' })
|
||||
@Type(() => CreateOrderItemDtoAsAdmin)
|
||||
items: CreateOrderItemDtoAsAdmin[];
|
||||
|
||||
|
||||
@ApiProperty({})
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
paymentMethod: string
|
||||
@IsNotEmpty()
|
||||
typeId: string;
|
||||
|
||||
@ApiProperty({})
|
||||
@IsBoolean()
|
||||
enableTax: boolean
|
||||
|
||||
@ApiProperty({})
|
||||
@ApiProperty({ description: 'Estimated days to complete' })
|
||||
@IsInt()
|
||||
estimatedDays: number
|
||||
estimatedDays: number;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
productId?: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export class CreateOrderItemDtoAsAdmin {
|
||||
@ApiProperty()
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
productId: string;
|
||||
|
||||
@ApiPropertyOptional()
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
quantity?: number;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { IsArray, } from 'class-validator';
|
||||
import { ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { IField } from '../interface/order.interface';
|
||||
|
||||
export class CreatePrintFormDto {
|
||||
@ApiPropertyOptional({
|
||||
example: [{
|
||||
fieldId: 10, value: ''
|
||||
}]
|
||||
})
|
||||
@IsArray()
|
||||
printAttributes?: IField[]
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { PartialType } from '@nestjs/swagger';
|
||||
import { CreateOrderItemAsUserDto, CreateOrderItemDtoAsAdmin } from './create-order.dto';
|
||||
|
||||
export class UpdateOrderItemDtoAsUser extends PartialType(CreateOrderItemAsUserDto) { }
|
||||
export class UpdateOrderItemDtoAsAdmin extends PartialType(CreateOrderItemDtoAsAdmin) { }
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ import { OrderType } from './order-type.entity';
|
||||
export class Order extends BaseEntity {
|
||||
[OptionalProps]?: 'createdAt' | 'deletedAt' | 'orderNumber'
|
||||
|
||||
@ManyToOne(() => InvoiceItem)
|
||||
invoiceItem: InvoiceItem
|
||||
@ManyToOne(() => InvoiceItem,{nullable:true})
|
||||
invoiceItem?: InvoiceItem
|
||||
|
||||
@ManyToOne(() => Product)
|
||||
product: Product;
|
||||
@ManyToOne(() => Product, { nullable: true })
|
||||
product?: Product | null;
|
||||
|
||||
@PrimaryKey({ type: 'string', columnType: 'char(26)' })
|
||||
id: string = ulid()
|
||||
@@ -58,4 +58,6 @@ export class Order extends BaseEntity {
|
||||
@Enum(() => OrderStatusEnum)
|
||||
status: OrderStatusEnum = OrderStatusEnum.CREATED;
|
||||
|
||||
@Property({ type: 'int', nullable: true })
|
||||
estimatedDays?: number;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ import { MikroOrmModule } from '@mikro-orm/nestjs';
|
||||
import { OrderService } from './providers/order.service';
|
||||
import { OrderController } from './controllers/order.controller';
|
||||
import { Order } from './entities/order.entity';
|
||||
import { OrderItem } from './entities/order-item.entity';
|
||||
import { AuthModule } from '../auth/auth.module';
|
||||
import { PaymentModule } from '../payment/payments.module';
|
||||
import { JwtModule } from '@nestjs/jwt';
|
||||
@@ -16,11 +15,11 @@ import { UserModule } from '../user/user.module';
|
||||
import { UtilsModule } from '../util/utils.module';
|
||||
import { ProductModule } from '../product/product.module';
|
||||
import { TicketModule } from '../ticket/ticket.module';
|
||||
import { OrderItemRepository } from './repositories/order-item.repository';
|
||||
import { OrderType } from './entities/order-type.entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
MikroOrmModule.forFeature([Order, OrderItem]),
|
||||
MikroOrmModule.forFeature([Order, OrderType]),
|
||||
AuthModule,
|
||||
forwardRef(() => PaymentModule),
|
||||
JwtModule,
|
||||
@@ -33,7 +32,7 @@ import { OrderItemRepository } from './repositories/order-item.repository';
|
||||
],
|
||||
controllers: [OrderController],
|
||||
providers: [OrderService, OrderRepository, OrderListeners,
|
||||
OrdersCrone, OrderItemRepository],
|
||||
exports: [OrderRepository, OrderService, OrderItemRepository],
|
||||
OrdersCrone,],
|
||||
exports: [OrderRepository, OrderService],
|
||||
})
|
||||
export class OrderModule { }
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import { Injectable, BadRequestException, Logger, BadGatewayException } from '@nestjs/common';
|
||||
import { Injectable, BadRequestException, Logger, NotFoundException } from '@nestjs/common';
|
||||
import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { OrderRepository } from '../repositories/order.repository';
|
||||
import { FindOrdersDto } from '../dto/find-orders.dto';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import {
|
||||
CreateOrderAsAdminDto,
|
||||
CreateOrderAsUSerDto, CreateOrderItemAsUserDto,
|
||||
CreateOrderItemDtoAsAdmin
|
||||
CreateOrderItemDtoAsAdmin,
|
||||
} from '../dto/create-order.dto';
|
||||
import { UserService } from 'src/modules/user/providers/user.service';
|
||||
import {
|
||||
OrderItemStatusEnum,
|
||||
CreateOrderWithItems,
|
||||
CreateOrderItemPopulated,
|
||||
UpdateOrder,
|
||||
UpdateOrderItem,
|
||||
OrderStatusEnum
|
||||
} from '../interface/order.interface';
|
||||
import { OrderItemRepository } from '../repositories/order-item.repository';
|
||||
import { OrderStatusEnum } from '../interface/order.interface';
|
||||
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';
|
||||
@@ -25,16 +16,14 @@ import { TicketRepository } from 'src/modules/ticket/repositories/tickets.reposi
|
||||
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
|
||||
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 { Admin } from 'src/modules/admin/entities/admin.entity';
|
||||
import { AdminService } from 'src/modules/admin/providers/admin.service';
|
||||
import { OrderItem } from '../entities/order-item.entity';
|
||||
import { UpdateOrderAsAdminDto } from '../dto/update-order.dto';
|
||||
import { CreatePrintFormDto } from '../dto/create-print-form.dto';
|
||||
import { FindOrderItemsDto } from '../dto/find-order-items.dto';
|
||||
import { PermissionService } from 'src/modules/roles/providers/permissions.service';
|
||||
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';
|
||||
|
||||
@Injectable()
|
||||
export class OrderService {
|
||||
@@ -43,7 +32,6 @@ export class OrderService {
|
||||
constructor(
|
||||
private readonly em: EntityManager,
|
||||
private readonly orderRepository: OrderRepository,
|
||||
private readonly orderItemRepository: OrderItemRepository,
|
||||
private readonly userService: UserService,
|
||||
private readonly adminService: AdminService,
|
||||
private readonly productService: ProductService,
|
||||
@@ -56,581 +44,38 @@ export class OrderService {
|
||||
private readonly permissionService: PermissionService,
|
||||
) { }
|
||||
|
||||
async createOrderAsAdmin(adminId: string, dto: CreateOrderAsAdminDto) {
|
||||
const order = await this.createOrder({ ...dto, adminId })
|
||||
// await this.calculateOrder(order)
|
||||
// this.em.flush()
|
||||
this.logger.log("Order created as admin")
|
||||
return order
|
||||
|
||||
async createOrderAsAdmin(adminId: string, dto: CreateOrderAsAdminDto): Promise<Order> {
|
||||
const user = await this.userService.findById(dto.userId);
|
||||
if (!user) {
|
||||
throw new NotFoundException(`User with ID ${dto.userId} not found.`);
|
||||
}
|
||||
|
||||
async createOrderAsUser(userId: string, dto: CreateOrderAsUSerDto) {
|
||||
const order = await this.createOrder({ ...dto, userId })
|
||||
this.logger.log("Order created as user")
|
||||
return order
|
||||
const creator = await this.adminService.findOrFail(adminId);
|
||||
|
||||
const type = await this.em.findOne(OrderType, { id: dto.typeId });
|
||||
if (!type) {
|
||||
throw new NotFoundException(`Order type with ID ${dto.typeId} not found.`);
|
||||
}
|
||||
|
||||
async updateOrderAsAdmin(orderId: string, dto: UpdateOrderAsAdminDto) {
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
// const updateOrder = await this.updateOrder(order, dto)
|
||||
|
||||
// const updateOrder = await this.calculateOrder(order)
|
||||
|
||||
// await this.em.flush()
|
||||
|
||||
this.logger.log("Order updated as admin")
|
||||
|
||||
// return updateOrder
|
||||
}
|
||||
|
||||
|
||||
async updateOrderAsAdmin2(orderId: string, dto: UpdateOrderAsAdminDto) {
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
const { items, ...rest } = dto
|
||||
|
||||
return this.em.transactional(async (em) => {
|
||||
|
||||
em.assign(order, rest)
|
||||
|
||||
for (const item of items) {
|
||||
|
||||
if (item.id) { // update
|
||||
const currentItem = order.items.find(i => i.id == item.id)
|
||||
|
||||
if (!currentItem) {
|
||||
throw new BadGatewayException("Order Item not found")
|
||||
}
|
||||
|
||||
const { designerId, productId, ...itemRest } = item
|
||||
|
||||
let newProduct = currentItem.product
|
||||
|
||||
if (productId && productId !== currentItem.product.id) {
|
||||
|
||||
newProduct = await this.productService.findOneOrFail(productId)
|
||||
|
||||
}
|
||||
|
||||
let newDesigner: Admin | undefined
|
||||
|
||||
if (designerId && designerId !== currentItem.designer?.id) {
|
||||
|
||||
newDesigner = await this.adminService.findOrFail(designerId)
|
||||
|
||||
}
|
||||
|
||||
em.assign(currentItem, { ...itemRest, designer: newDesigner, product: newProduct })
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
if (!item.productId) {
|
||||
throw new BadRequestException(`Product id is required for item ${item.id}`)
|
||||
}
|
||||
|
||||
const product = await this.productService.findOneOrFail(item.productId)
|
||||
|
||||
const newOrderItem = em.create(OrderItem, {
|
||||
order,
|
||||
product,
|
||||
quantity: item.quantity,
|
||||
unitPrice: item.unitPrice,
|
||||
|
||||
adminDescription: item.adminDescription,
|
||||
attachments: item.attachments,
|
||||
attributes: item.attributes,
|
||||
description: item.description,
|
||||
discount: item.discount,
|
||||
confirmedAt: item.confirmedAt,
|
||||
status: OrderItemStatusEnum.CREATED
|
||||
})
|
||||
|
||||
em.persist(newOrderItem)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
await em.flush()
|
||||
|
||||
this.logger.log(`order #${order.orderNumber} was updated as Admin`)
|
||||
|
||||
return order
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
async addOrderItemAsUser(userId: string, orderId: string, dto: CreateOrderItemAsUserDto) {
|
||||
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
// if (order.status !== OrderStatusEnum.CREATED) {
|
||||
// throw new BadRequestException(`You can not update when status is ${order.status}`)
|
||||
// }
|
||||
|
||||
if (order.user.id !== userId) {
|
||||
throw new BadRequestException(`This order doest belongs to you!`)
|
||||
}
|
||||
|
||||
const product = await this.productService.findOneOrFail(dto.productId)
|
||||
|
||||
const orderItem = this.createOrderItemEntity(order, { ...dto, product })
|
||||
|
||||
await this.em.flush()
|
||||
|
||||
return orderItem
|
||||
}
|
||||
|
||||
async addOrderItemAsAdmin(orderId: string, dto: CreateOrderItemDtoAsAdmin) {
|
||||
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
const product = await this.productService.findOneOrFail(dto.productId)
|
||||
|
||||
let designer: Admin | undefined
|
||||
if (dto.designerId) {
|
||||
designer = await this.adminService.findOrFail(dto.designerId)
|
||||
}
|
||||
|
||||
const orderItem = this.createOrderItemEntity(order, { ...dto, designer, product })
|
||||
|
||||
await this.em.flush()
|
||||
|
||||
// await this.calculateOrder(undefined, orderId)
|
||||
|
||||
// await this.em.flush()
|
||||
|
||||
return orderItem
|
||||
}
|
||||
|
||||
async updateOrderItemAsUser(userId: string, orderId: string, itemId: string, dto: UpdateOrderItemDtoAsUser) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, itemId)
|
||||
|
||||
if (orderItem.order.user.id !== userId) {
|
||||
throw new BadRequestException(`This order doesnt belongs to you`)
|
||||
}
|
||||
|
||||
// if (orderItem.order.status !== OrderStatusEnum.CREATED) {
|
||||
// throw new BadRequestException(`You can not update when status is ${orderItem.order.status}`)
|
||||
// }
|
||||
|
||||
if (orderItem.confirmedAt) {
|
||||
throw new BadRequestException(`You can not update when item is confirmed`)
|
||||
}
|
||||
|
||||
const updated = await this.updateOrderItem(orderItem, dto)
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
async updateOrderItemAsAdmin(orderId: string, itemId: string, dto: UpdateOrderItemDtoAsAdmin) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, itemId)
|
||||
|
||||
const updated = await this.updateOrderItem(orderItem, dto)
|
||||
|
||||
// await this.calculateOrder(undefined, orderId)
|
||||
|
||||
// await this.em.flush()
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
async createPrintForm(orderId: string, itemId: string, dto: CreatePrintFormDto) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, itemId)
|
||||
|
||||
const updated = await this.updateOrderItem(orderItem, { ...dto, printFormCreatedAt: new Date() })
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
async removeOrderItemAsAdmin(orderId: string, itemId: string) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, itemId)
|
||||
|
||||
await this.removeOrderItem(orderItem)
|
||||
|
||||
// await this.calculateOrder(undefined, orderId)
|
||||
|
||||
// await this.em.flush()
|
||||
|
||||
return { message: 'success' }
|
||||
}
|
||||
|
||||
async removeOrderItemAsUser(userId: string, orderId: string, itemId: string) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, itemId)
|
||||
|
||||
if (orderItem.order.user.id !== userId) {
|
||||
throw new BadRequestException(`this order is not belongs to you`)
|
||||
}
|
||||
|
||||
// if (orderItem.order.status !== OrderStatusEnum.CREATED) {
|
||||
// throw new BadRequestException(`You can not delete when order status is ${orderItem.order.status}`)
|
||||
// }
|
||||
|
||||
if (orderItem.confirmedAt) {
|
||||
throw new BadRequestException(`You can not delete when item is confirmed`)
|
||||
}
|
||||
|
||||
await this.removeOrderItem(orderItem)
|
||||
|
||||
return { message: 'success' }
|
||||
}
|
||||
|
||||
|
||||
async findOrdersAsUser(userId: string, dto: FindOrdersDto) {
|
||||
const orders = await this.orderRepository.findAllPaginated({ userId, ...dto })
|
||||
return orders
|
||||
}
|
||||
|
||||
async findOrderRequestsAsAdmin(dto: FindOrdersDto) {
|
||||
const orders = await this.orderRepository.findAllPaginated({ ...dto, isInvoiced: false })
|
||||
return orders
|
||||
}
|
||||
|
||||
async findInvoicedOrdersAsAdmin(adminId: string, dto: FindOrdersDto) {
|
||||
const canSeeAll = await this.adminService.hasPermission(adminId, PermissionEnum.VIEW_All_INVOICED_ORDERS)
|
||||
|
||||
let canSeeAsigned = false
|
||||
|
||||
if (!canSeeAll) {
|
||||
canSeeAsigned = await this.adminService.hasPermission(adminId, PermissionEnum.VIEW_MY_ASSIGNED_INVOICED_REQUESTS)
|
||||
}
|
||||
|
||||
if (!canSeeAsigned && !canSeeAll) {
|
||||
throw new BadRequestException("You dont have Permission")
|
||||
}
|
||||
|
||||
let designerId = canSeeAll ? undefined : adminId
|
||||
|
||||
const orders = await this.orderRepository.findAllPaginated({ ...dto, isInvoiced: true, designerId })
|
||||
|
||||
return orders
|
||||
}
|
||||
|
||||
async findPrintOrderItemsAsAdmin(dto: FindOrderItemsDto) {
|
||||
const orderItems = await this.orderItemRepository.findAllPaginated({ ...dto, isPrintFormAdded: true, })
|
||||
return orderItems
|
||||
}
|
||||
|
||||
async findPrints(dto: FindOrdersDto) {
|
||||
const orders = await this.orderRepository.findAllPaginated({ ...dto, statuses: [] })
|
||||
return orders
|
||||
}
|
||||
|
||||
|
||||
async confirmOrderItem(userId: string, orderId: string, orderItemId: string) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, orderItemId)
|
||||
|
||||
|
||||
if (orderItem.order.user.id !== userId) {
|
||||
throw new BadRequestException("Order Item does not belong to you")
|
||||
}
|
||||
|
||||
orderItem.confirmedAt = new Date()
|
||||
|
||||
await this.em.persistAndFlush(orderItem)
|
||||
|
||||
return orderItem
|
||||
}
|
||||
|
||||
async assignDesigner(orderId: string, orderItemId: string, designerId: string) {
|
||||
|
||||
const orderItem = await this.findOrderItemOrFail(orderId, orderItemId)
|
||||
|
||||
const designer = await this.adminRepository.findOne({ id: designerId })
|
||||
|
||||
if (!designer) {
|
||||
throw new BadRequestException("designer not found")
|
||||
}
|
||||
|
||||
orderItem.designer = designer
|
||||
|
||||
await this.em.persistAndFlush(orderItem)
|
||||
|
||||
return orderItem
|
||||
|
||||
}
|
||||
|
||||
async removeOrderAsUser(userId: string, orderId: string) {
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
if (order.user.id !== userId) {
|
||||
throw new BadRequestException("this order doesnt belongs to you")
|
||||
}
|
||||
|
||||
// if (![OrderStatusEnum.CREATED].includes(order.status)) {
|
||||
// throw new BadRequestException("Order can not be deleted")
|
||||
// }
|
||||
|
||||
return this.hardDeleteOrder(orderId)
|
||||
}
|
||||
|
||||
// async updateStatus(orderId: string, newStatus: OrderStatusEnum) {
|
||||
|
||||
// const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
// // order.status = newStatus
|
||||
|
||||
// await this.em.flush()
|
||||
|
||||
// return order
|
||||
// }
|
||||
|
||||
// async createInvoice(orderId: string) {
|
||||
// const order = await this.updateStatus(orderId, OrderStatusEnum.INVOICED)
|
||||
// return order
|
||||
// }
|
||||
|
||||
async getOrderAsUser(userId: string, orderId: string) {
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
if (order.user.id !== userId) {
|
||||
throw new BadRequestException("This order is not belongs to you")
|
||||
}
|
||||
return order
|
||||
}
|
||||
|
||||
// ==================== Entity Methods ====================
|
||||
|
||||
private async createOrderItemEntity(order: Order, dto: CreateOrderItemPopulated, em?: EntityManager) {
|
||||
const { attributes, description, quantity, attachments, discount,
|
||||
unitPrice, product, designer, printAttributes, status } = dto
|
||||
|
||||
const eM = em ?? this.em
|
||||
return eM.create(
|
||||
OrderItem,
|
||||
{
|
||||
designer,
|
||||
order,
|
||||
attributes,
|
||||
description,
|
||||
quantity,
|
||||
attachments,
|
||||
discount,
|
||||
unitPrice,
|
||||
product,
|
||||
printAttributes: printAttributes,
|
||||
status
|
||||
})
|
||||
}
|
||||
|
||||
// ==================== Core Logic ====================
|
||||
|
||||
async createOrder(dto: CreateOrderWithItems) {
|
||||
const { items, userId, enableTax,
|
||||
estimatedDays, paymentMethod, adminId } = dto
|
||||
|
||||
// Validate and fetch all required entities
|
||||
const user = await this.userService.findOrFail(userId)
|
||||
const admin = adminId ? await this.adminService.findOrFail(adminId) : undefined
|
||||
const products = await this.productService.findProductsByIds(items.map(item => item.productId))
|
||||
const desiners = await this.adminService.findByIds(items.map(item => item.designerId).filter(id => id != null))
|
||||
|
||||
const productMap = new Map(
|
||||
products.map(p => [Number(p.id), p])
|
||||
);
|
||||
const designerMap = new Map(
|
||||
desiners.map(d => [d.id, d])
|
||||
)
|
||||
|
||||
return this.em.transactional(async (em) => {
|
||||
|
||||
const order = em.create(Order, {
|
||||
creator: admin,
|
||||
user,
|
||||
enableTax,
|
||||
estimatedDays,
|
||||
paymentMethod,
|
||||
status: OrderStatusEnum.REQUEST,
|
||||
})
|
||||
|
||||
em.persist(order)
|
||||
|
||||
for (const item of items) {
|
||||
const product = productMap.get(Number(item.productId))
|
||||
|
||||
let product: Product | null = null;
|
||||
if (dto.productId) {
|
||||
product = await this.em.findOne(Product, { id: dto.productId });
|
||||
if (!product) {
|
||||
throw new BadRequestException("Product not found!")
|
||||
}
|
||||
let designer: undefined | Admin = undefined
|
||||
|
||||
if (item.designerId) {
|
||||
designer = designerMap.get(item.designerId)
|
||||
if (!designer) {
|
||||
throw new BadRequestException("designer not found!")
|
||||
throw new NotFoundException(`Product with ID ${dto.productId} not found.`);
|
||||
}
|
||||
}
|
||||
|
||||
const orderItem = await this.createOrderItemEntity(order, { ...item, designer, product }, em)
|
||||
const order = this.em.create(Order, {
|
||||
user: user as User,
|
||||
creator,
|
||||
type,
|
||||
product: product ?? null,
|
||||
title: dto.title,
|
||||
status: OrderStatusEnum.CREATED,
|
||||
estimatedDays: dto.estimatedDays,
|
||||
});
|
||||
|
||||
order.items.add(orderItem)
|
||||
await this.em.persistAndFlush(order);
|
||||
return order;
|
||||
}
|
||||
|
||||
// TODO : calculation must be done after create order
|
||||
|
||||
// await this.calculateOrder(order)
|
||||
|
||||
await em.flush()
|
||||
|
||||
return order
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
async updateOrder(order: Order, param: UpdateOrder) {
|
||||
const { adminId, enableTax,
|
||||
estimatedDays, paymentMethod, userId } = param
|
||||
|
||||
|
||||
if (userId) {
|
||||
const user = await this.userService.findOrFail(userId)
|
||||
order.user = user
|
||||
}
|
||||
|
||||
|
||||
if (adminId != undefined && adminId !== null) {
|
||||
const admin = await this.adminService.findOrFail(adminId)
|
||||
order.creator = admin
|
||||
}
|
||||
|
||||
|
||||
if (enableTax != undefined) {
|
||||
order.enableTax = enableTax
|
||||
}
|
||||
|
||||
if (estimatedDays != undefined) {
|
||||
order.estimatedDays = estimatedDays
|
||||
}
|
||||
|
||||
if (paymentMethod != undefined) {
|
||||
order.paymentMethod = paymentMethod
|
||||
}
|
||||
|
||||
// if (status != undefined) {
|
||||
// order.status = status
|
||||
|
||||
// if (status === OrderStatusEnum.INVOICED && !order.invoicedAt) {
|
||||
// order.invoicedAt = new Date()
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
await this.em.persistAndFlush(order)
|
||||
|
||||
return order
|
||||
}
|
||||
|
||||
async updateOrderItem(orderItem: OrderItem, dto: UpdateOrderItem) {
|
||||
const { attributes, description, product, quantity, printFormCreatedAt,
|
||||
attachments, discount, unitPrice, designer, printAttributes, } = dto
|
||||
|
||||
if (product && orderItem.product.id !== product.id) {
|
||||
orderItem.product = product
|
||||
}
|
||||
|
||||
if (designer && orderItem.designer?.id !== designer.id) {
|
||||
orderItem.designer = designer
|
||||
}
|
||||
|
||||
if (attributes != undefined) {
|
||||
orderItem.attributes = attributes
|
||||
}
|
||||
|
||||
if (description != undefined) {
|
||||
orderItem.description = description
|
||||
}
|
||||
if (quantity != undefined) {
|
||||
orderItem.quantity = quantity
|
||||
}
|
||||
|
||||
if (attachments != undefined) {
|
||||
orderItem.attachments = attachments
|
||||
}
|
||||
if (discount != undefined) {
|
||||
orderItem.discount = discount
|
||||
}
|
||||
|
||||
if (unitPrice != undefined) {
|
||||
orderItem.unitPrice = unitPrice
|
||||
}
|
||||
|
||||
if (printFormCreatedAt != undefined) {
|
||||
orderItem.printFormCreatedAt = printFormCreatedAt
|
||||
}
|
||||
|
||||
if (printAttributes != undefined) {
|
||||
orderItem.printAttributes = printAttributes
|
||||
}
|
||||
|
||||
await this.em.flush()
|
||||
|
||||
return orderItem
|
||||
}
|
||||
|
||||
async removeOrderItem(orderItem: OrderItem) {
|
||||
|
||||
await this.em.removeAndFlush(orderItem)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async hardDeleteOrder(orderId: string) {
|
||||
const order = await this.findOrderOrFail(orderId)
|
||||
|
||||
if (order.payments.length > 0) {
|
||||
throw new BadRequestException("order with payments can not be deleted!")
|
||||
}
|
||||
|
||||
await this.em.transactional(async (em) => {
|
||||
await this.ticketRepository.nativeDelete({ orderItem: { order: { id: orderId } } })
|
||||
await this.orderRepository.nativeDelete(order)
|
||||
// order item will be deleted because cascade is true
|
||||
|
||||
// TODO : images also must be deleted
|
||||
await em.flush()
|
||||
})
|
||||
|
||||
return { message: "Order deleted successfully" }
|
||||
|
||||
}
|
||||
|
||||
// ==================== Helper Methods ====================
|
||||
|
||||
async findOrderOrFail(orderId: string) {
|
||||
const order = await this.orderRepository.findOne({ id: orderId },
|
||||
{ populate: ['items', 'items.product', 'payments', 'user', 'items.designer'] })
|
||||
if (!order) {
|
||||
throw new BadRequestException('Order not found')
|
||||
}
|
||||
return order
|
||||
}
|
||||
|
||||
async findOrderItemOrFail(orderId: string, itemId: string) {
|
||||
const orderItem = await this.orderItemRepository.findOne({ id: itemId, order: { id: orderId } },
|
||||
{ populate: ['order', 'order.user'] })
|
||||
if (!orderItem) {
|
||||
throw new BadRequestException('Order item not found')
|
||||
}
|
||||
return orderItem
|
||||
}
|
||||
|
||||
async findOrderItemOrFailByItemId(itemId: string) {
|
||||
const orderItem = await this.orderItemRepository.findOne({ id: itemId },
|
||||
{ populate: ['order', 'order.user'] })
|
||||
if (!orderItem) {
|
||||
throw new BadRequestException('Order item not found')
|
||||
}
|
||||
return orderItem
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository, FilterQuery } from '@mikro-orm/postgresql';
|
||||
import { OrderItem } from '../entities/order-item.entity';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { FindOrderItemsDto } from '../dto/find-order-items.dto';
|
||||
|
||||
class FindOrderItemsOpts extends FindOrderItemsDto {
|
||||
userId?: string;
|
||||
isPrintFormAdded?: boolean
|
||||
};
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OrderItemRepository extends EntityRepository<OrderItem> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, OrderItem);
|
||||
}
|
||||
|
||||
async findAllPaginated(opts: FindOrderItemsOpts): Promise<PaginatedResult<OrderItem>> {
|
||||
const {
|
||||
page = 1,
|
||||
limit = 10,
|
||||
search,
|
||||
orderBy = 'createdAt',
|
||||
order = 'desc',
|
||||
userId,
|
||||
isPrintFormAdded
|
||||
} = opts;
|
||||
|
||||
const offset = (page - 1) * limit;
|
||||
|
||||
const where: FilterQuery<OrderItem> = {};
|
||||
|
||||
|
||||
|
||||
if (userId) {
|
||||
where.order = { user: { id: userId } };
|
||||
}
|
||||
|
||||
if (isPrintFormAdded != undefined) {
|
||||
if (isPrintFormAdded == true) {
|
||||
where.printFormCreatedAt = { $not: null }
|
||||
} else {
|
||||
where.printFormCreatedAt = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Search by order number or user information
|
||||
if (search) {
|
||||
const searchPattern = `%${search}%`;
|
||||
const searchConditions: any[] = [
|
||||
{ user: { firstName: { $ilike: searchPattern } } },
|
||||
{ user: { lastName: { $ilike: searchPattern } } },
|
||||
{ user: { phone: { $ilike: searchPattern } } },
|
||||
];
|
||||
|
||||
// If search is numeric, also search by orderNumber
|
||||
const numericSearch = Number(search);
|
||||
if (!isNaN(numericSearch) && isFinite(numericSearch)) {
|
||||
searchConditions.push({ orderNumber: numericSearch });
|
||||
}
|
||||
|
||||
where.$or = searchConditions;
|
||||
}
|
||||
|
||||
// First, fetch orders without reviews
|
||||
const [data, total] = await this.findAndCount(where, {
|
||||
limit,
|
||||
offset,
|
||||
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
||||
populate: ['designer', 'product'],
|
||||
});
|
||||
|
||||
|
||||
const totalPages = Math.ceil(total / limit);
|
||||
|
||||
return {
|
||||
data,
|
||||
meta: {
|
||||
total,
|
||||
page,
|
||||
limit,
|
||||
totalPages,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -59,17 +59,6 @@ export class OrderRepository extends EntityRepository<Order> {
|
||||
where.user = { id: userId };
|
||||
}
|
||||
|
||||
if (isInvoiced != undefined) {
|
||||
if (isInvoiced == true) {
|
||||
where.invoicedAt = { $not: null }
|
||||
} else {
|
||||
where.invoicedAt = null
|
||||
}
|
||||
}
|
||||
|
||||
if (designerId) {
|
||||
where.items = { $some: { designer: { id: designerId } } }
|
||||
}
|
||||
// Filter by date range
|
||||
if (from || to) {
|
||||
where.createdAt = {};
|
||||
@@ -104,7 +93,7 @@ export class OrderRepository extends EntityRepository<Order> {
|
||||
limit,
|
||||
offset,
|
||||
orderBy: { [orderBy]: order.toLowerCase() as 'asc' | 'desc' },
|
||||
populate: ['items', 'items.product', 'user'],
|
||||
populate: ['user'],
|
||||
});
|
||||
|
||||
// Collect all (orderId, productId) pairs for efficient review lookup
|
||||
|
||||
Reference in New Issue
Block a user