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);
|
||||
}
|
||||
}
|
||||
@@ -7,24 +7,25 @@ import {
|
||||
Collection,
|
||||
Cascade,
|
||||
Enum,
|
||||
PrimaryKey,
|
||||
} from '@mikro-orm/core';
|
||||
|
||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||
import { User } from "../../user/entities/user.entity";
|
||||
import { TicketStatus } from "../enums/ticket-status.enum";
|
||||
import { Product } from 'src/modules/product/entities/product.entity';
|
||||
// import { Product } from 'src/modules/product/entities/product.entity';
|
||||
import { Admin } from 'src/modules/admin/entities/admin.entity';
|
||||
|
||||
@Entity()
|
||||
export class Ticket extends BaseEntity {
|
||||
@Property({ type: "bigint", primary: true })
|
||||
id: number;
|
||||
@PrimaryKey({ type: "bigint", autoincrement: true })
|
||||
id: bigint;
|
||||
|
||||
@Enum(() => TicketStatus)
|
||||
status: TicketStatus;
|
||||
// TODO : create relation
|
||||
@Property({ type: 'json' })
|
||||
products: Product | null;
|
||||
|
||||
@Property({ type: 'text' })
|
||||
content: string;
|
||||
|
||||
@ManyToOne(() => Admin)
|
||||
admin: Admin | null;
|
||||
@@ -35,6 +36,9 @@ export class Ticket extends BaseEntity {
|
||||
@ManyToOne(() => Ticket)
|
||||
parent: Ticket | null;
|
||||
|
||||
@OneToMany(()=>Ticket,(ticket)=>ticket.id)
|
||||
children=new Collection<Ticket>(this)
|
||||
|
||||
@Property({ type: 'json' })
|
||||
attachments: string[]
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ import dayjs from "dayjs";
|
||||
// import { TicketsRepository } from "../repositories/tickets.repository";
|
||||
|
||||
@Injectable()
|
||||
export class TicketsService {
|
||||
private readonly logger = new Logger(TicketsService.name);
|
||||
export class TicketService {
|
||||
private readonly logger = new Logger(TicketService.name);
|
||||
|
||||
// constructor(
|
||||
// @InjectQueue(TICKET.QUEUE_NAME) private readonly ticketQueue: Queue,
|
||||
|
||||
@@ -4,9 +4,9 @@ import { ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||
import { CreateTicketCategoryDto } from "./DTO/create-ticket-category.dto";
|
||||
import { CreateTicketMessageDto } from "./DTO/create-ticket-message.dto";
|
||||
import { CreateTicketByAdminDto, CreateTicketDto } from "./DTO/create-ticket.dto";
|
||||
import { SearchTicketCategoryDto } from "./DTO/search-ticket-category.dto";
|
||||
import { SearchTicketCategoryDto } from "./DTO/search-ticket-category.dto";
|
||||
import { SearchTicketQueryDto } from "./DTO/search-ticket-query.dto";
|
||||
import { TicketsService } from "./providers/tickets.service";
|
||||
import { TicketService } from "./providers/tickets.service";
|
||||
|
||||
|
||||
import { ParamDto } from "../../common/DTO/param.dto";
|
||||
@@ -15,7 +15,7 @@ import { ParamDto } from "../../common/DTO/param.dto";
|
||||
@ApiTags("Tickets")
|
||||
|
||||
export class TicketsController {
|
||||
constructor(private readonly ticketsService: TicketsService) {}
|
||||
constructor(private readonly ticketsService: TicketService) { }
|
||||
|
||||
//----------------- ticket categories -------------------
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Module } from "@nestjs/common";
|
||||
import { TICKET } from "./constant";
|
||||
import { Ticket } from "./entities/ticket.entity";
|
||||
|
||||
import { TicketsService } from "./providers/tickets.service";
|
||||
import { TicketService } from "./providers/tickets.service";
|
||||
|
||||
import { TicketRepository } from "./repositories/tickets.repository";
|
||||
import { TicketRepository } from "./repositories/tickets.repository";
|
||||
import { TicketsController } from "./tickets.controller";
|
||||
import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||
|
||||
@@ -17,8 +17,8 @@ import { MikroOrmModule } from "@mikro-orm/nestjs";
|
||||
MikroOrmModule.forFeature([Ticket]),
|
||||
BullModule.registerQueue({ name: TICKET.QUEUE_NAME }),
|
||||
],
|
||||
providers: [TicketsService, TicketRepository],
|
||||
providers: [TicketService, TicketRepository],
|
||||
controllers: [TicketsController],
|
||||
exports: [TicketsService],
|
||||
exports: [TicketService],
|
||||
})
|
||||
export class TicketsModule { }
|
||||
|
||||
Reference in New Issue
Block a user