order
This commit is contained in:
@@ -9,6 +9,7 @@ import { OrderStatus } from '../interface/order.interface';
|
||||
import { UpdateOrderStatusDto } from '../dto/update-order-status.dto';
|
||||
import { Permissions } from 'src/common/decorators/permissions.decorator';
|
||||
import { Permission } from 'src/common/enums/permission.enum';
|
||||
import { CreateOrderDto } from '../dto/create-order.dto';
|
||||
|
||||
@ApiTags('orders')
|
||||
@ApiBearerAuth()
|
||||
@@ -16,13 +17,13 @@ import { Permission } from 'src/common/enums/permission.enum';
|
||||
export class OrdersController {
|
||||
constructor(private readonly ordersService: OrdersService) { }
|
||||
|
||||
@Post('public/checkout')
|
||||
// @UseGuards(AuthGuard)
|
||||
// @Post('public/checkout')
|
||||
|
||||
// @ApiOperation({ summary: 'Checkout : create order and payment record' })
|
||||
// checkout(@UserId() userId: string,) {
|
||||
// return this.ordersService.checkout(userId);
|
||||
// }
|
||||
@ApiOperation({ summary: 'Checkout : create order ' })
|
||||
@ApiBody({ type: CreateOrderDto })
|
||||
checkout(@UserId() userId: string, @Body() body: CreateOrderDto) {
|
||||
return this.ordersService.createOrder(userId, body);
|
||||
}
|
||||
|
||||
// @UseGuards(AuthGuard)
|
||||
// @Get('public/orders')
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { IsString, IsOptional, IsBoolean, IsInt, Min, IsArray, IsNumber } from 'class-validator';
|
||||
import { ApiPropertyOptional, ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
|
||||
export class CreateOrderDto {
|
||||
@IsArray()
|
||||
@ApiProperty({ isArray: true })
|
||||
items: CreateOrderItemDto[];
|
||||
|
||||
@IsString()
|
||||
content: string
|
||||
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
attachments: string[]
|
||||
}
|
||||
|
||||
export class CreateOrderItemDto {
|
||||
|
||||
@IsInt()
|
||||
@ApiProperty()
|
||||
productId: bigint;
|
||||
|
||||
@ApiProperty()
|
||||
quantity: number
|
||||
|
||||
@IsArray()
|
||||
attributesValues: string[]
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Entity, Enum, Index, ManyToOne, PrimaryKey, Property } from '@mikro-orm/core';
|
||||
import { Entity, Enum, Index, ManyToOne, OneToMany, 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';
|
||||
@@ -10,13 +10,16 @@ import { OrderItemStatus } from '../interface/order.interface';
|
||||
export class OrderItem extends BaseEntity {
|
||||
@PrimaryKey({ type: 'bigint', autoincrement: true })
|
||||
id: bigint
|
||||
|
||||
|
||||
@ManyToOne(() => Order)
|
||||
order!: Order;
|
||||
|
||||
@ManyToOne(() => Product)
|
||||
product!: Product;
|
||||
|
||||
@Property({ type: 'json' })
|
||||
attributesValues: string[]
|
||||
|
||||
@Property({ type: 'int' })
|
||||
quantity!: number;
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ import { ulid } from 'ulid';
|
||||
@Index({ properties: ['user', 'status'] })
|
||||
@Index({ properties: ['status'] })
|
||||
export class Order extends BaseEntity {
|
||||
@PrimaryKey({type:'string',columnType:'char(26)'})
|
||||
id:string=ulid()
|
||||
|
||||
@PrimaryKey({ type: 'string', columnType: 'char(26)' })
|
||||
id: string = ulid()
|
||||
|
||||
@ManyToOne(() => User)
|
||||
user!: User;
|
||||
|
||||
@@ -38,8 +38,8 @@ export class Order extends BaseEntity {
|
||||
})
|
||||
items = new Collection<OrderItem>(this);
|
||||
|
||||
@Property({ nullable: true })
|
||||
userAddress?: string | null;
|
||||
// @Property({ nullable: true })
|
||||
// userAddress?: string | null;
|
||||
|
||||
@Property({ type: 'bigint', autoincrement: true })
|
||||
orderNumber: number;
|
||||
@@ -52,8 +52,8 @@ export class Order extends BaseEntity {
|
||||
subTotal!: number;
|
||||
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 0, default: 0 })
|
||||
deliveryFee: number = 0;
|
||||
// @Property({ type: 'decimal', precision: 10, scale: 0, default: 0 })
|
||||
// deliveryFee: number = 0;
|
||||
|
||||
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||
total!: number;
|
||||
@@ -64,12 +64,11 @@ export class Order extends BaseEntity {
|
||||
@Property({ type: 'decimal', precision: 10, scale: 0 })
|
||||
balance!: number;
|
||||
|
||||
@Property({ type: 'text', nullable: true })
|
||||
description?: string;
|
||||
// @Property({ type: 'text', nullable: true })
|
||||
// description?: string;
|
||||
|
||||
|
||||
@Enum(() => OrderStatus)
|
||||
status!: OrderStatus;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ export enum OrderStatus {
|
||||
|
||||
export enum OrderItemStatus {
|
||||
PENDING = 'pending',
|
||||
VERIFIED = 'verified',
|
||||
CONFIRMED = 'confirmed',
|
||||
}
|
||||
|
||||
@@ -3,35 +3,106 @@ import { EntityManager } from '@mikro-orm/postgresql';
|
||||
import { Order } from '../entities/order.entity';
|
||||
import { OrderItem } from '../entities/order-item.entity';
|
||||
import { User } from '../../user/entities/user.entity';
|
||||
|
||||
|
||||
import { PaymentMethodEnum, PaymentStatusEnum } from '../../payment/interface/payment';
|
||||
|
||||
|
||||
import { PaymentsService } from '../../payment/services/payments.service';
|
||||
|
||||
|
||||
import { OrderRepository } from '../repositories/order.repository';
|
||||
import { FindOrdersDto } from '../dto/find-orders.dto';
|
||||
import { PaginatedResult } from 'src/common/interfaces/pagination.interface';
|
||||
import { Payment } from 'src/modules/payment/entities/payment.entity';
|
||||
|
||||
|
||||
|
||||
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { OrderCreatedEvent, OrderStatusChangedEvent } from '../events/order.events';
|
||||
import { OrderMessage } from 'src/common/enums/message.enum';
|
||||
|
||||
import { CreateOrderDto } from '../dto/create-order.dto';
|
||||
import { UserService } from 'src/modules/user/providers/user.service';
|
||||
import { OrderItemStatus, OrderStatus } 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 { TicketStatus } from 'src/modules/ticket/enums/ticket-status.enum';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OrdersService {
|
||||
private readonly logger = new Logger(OrdersService.name);
|
||||
|
||||
|
||||
|
||||
constructor(
|
||||
private readonly em: EntityManager,
|
||||
|
||||
private readonly orderRepository: OrderRepository,
|
||||
private readonly orderItemRepository: OrderItemRepository,
|
||||
private readonly paymentsService: PaymentsService,
|
||||
|
||||
private readonly userService: UserService,
|
||||
private readonly productService: ProductService,
|
||||
private readonly productRepository: ProductRepository,
|
||||
private readonly ticketRepository: TicketRepository,
|
||||
private readonly ticketService: TicketService,
|
||||
private readonly eventEmitter: EventEmitter2,
|
||||
) { }
|
||||
|
||||
async createOrder(userId: string, dto: CreateOrderDto) {
|
||||
const { attachments, content, items } = dto
|
||||
this.em.transactional(async (em) => {
|
||||
const user = await this.userService.findById(userId)
|
||||
if (!user) {
|
||||
throw new BadRequestException("user not found")
|
||||
}
|
||||
const order = this.orderRepository.create({
|
||||
user,
|
||||
discount: 0,
|
||||
subTotal: 0,
|
||||
orderNumber: 1,
|
||||
total: 0,
|
||||
paidAmount: 0,
|
||||
balance: 0,
|
||||
status: OrderStatus.NEW
|
||||
})
|
||||
|
||||
em.persist(order)
|
||||
|
||||
const productIds = items.map(item => item.productId)
|
||||
const products = await this.productRepository.find({
|
||||
id: { $in: productIds }
|
||||
})
|
||||
if (productIds.length !== products.length) {
|
||||
throw new BadRequestException("some products not found")
|
||||
}
|
||||
items.forEach(item => {
|
||||
const product = products.find(p => p.id == item.productId)
|
||||
if (!product) {
|
||||
throw new BadRequestException(`product ${product} not found`)
|
||||
}
|
||||
const orderItem = this.orderItemRepository.create({
|
||||
order,
|
||||
attributesValues: item.attributesValues,
|
||||
discount: 0,
|
||||
product,
|
||||
quantity: item.quantity,
|
||||
status: OrderItemStatus.PENDING,
|
||||
unitPrice: 0,
|
||||
totalPrice: 0,
|
||||
})
|
||||
em.persist(orderItem)
|
||||
});
|
||||
|
||||
const ticket = this.ticketRepository.create({
|
||||
content,
|
||||
user,
|
||||
attachments,
|
||||
status: TicketStatus.PENDING
|
||||
})
|
||||
em.persist(ticket)
|
||||
|
||||
em.flush()
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { EntityManager, EntityRepository } from '@mikro-orm/postgresql';
|
||||
import { OrderItem } from '../entities/order-item.entity';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class OrderItemRepository extends EntityRepository<OrderItem> {
|
||||
constructor(readonly em: EntityManager) {
|
||||
super(em, OrderItem);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user