add order item

This commit is contained in:
2026-01-22 11:24:11 +03:30
parent f2d30af119
commit e53c574931
5 changed files with 119 additions and 18 deletions
@@ -11,6 +11,7 @@ import { CreateInvoiceDto } from '../dto/create-invoice.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 { AddOrderItemDto } from '../dto/add-order-item.dto';
@ApiTags('orders')
@ApiBearerAuth()
@@ -61,7 +62,14 @@ export class OrderController {
hardDelete(@Param('orderId') orderId: string) {
return this.orderService.hardDeleteOrder(orderId);
}
@Post('admin/orders/:orderId/add-item')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'add item to Order ' })
addItem(@Param('orderId') orderId: string, @Body() body: AddOrderItemDto) {
return this.orderService.addOrderItem(orderId, body);
}
@Post('admin/orders/:orderId/create-invoice')
@UseGuards(AuthGuard)
@ApiOperation({ summary: 'Create invoice for new order' })
@@ -0,0 +1,47 @@
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[];
}
+5 -3
View File
@@ -15,6 +15,10 @@ export class InvoiceItemDto {
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
}
export class CreateInvoiceDto {
@@ -32,8 +36,6 @@ export class CreateInvoiceDto {
@Type(() => InvoiceItemDto)
items: InvoiceItemDto[];
@ApiProperty()
@IsNumber()
discount: number
}
@@ -26,9 +26,14 @@ export class OrderItem extends BaseEntity {
@Property({ type: 'decimal', precision: 10, scale: 0 })
unitPrice!: number;
@Property({ type: 'decimal', precision: 10, scale: 0 })
subTotal!: number;
@Property({ type: 'decimal', precision: 10, scale: 0, default: 0 })
discount: number = 0;
@Property({ type: 'decimal', precision: 10, scale: 0 })
totalPrice!: number;
total!: number;
@Property({ nullable: true })
description?: string;
+52 -13
View File
@@ -1,14 +1,9 @@
import { Injectable, NotFoundException, BadRequestException, Logger } from '@nestjs/common';
import { EntityManager } from '@mikro-orm/postgresql';
import { OrderItem } from '../entities/order-item.entity';
import { PaymentService } 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, OrderStatusEnum } from '../interface/order.interface';
@@ -20,6 +15,7 @@ import { TicketRepository } from 'src/modules/ticket/repositories/tickets.reposi
import { CreateInvoiceDto } from '../dto/create-invoice.dto';
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
import { CreateOrderAsAdminDto } from '../dto/create-order-as-admin.dto';
import { AddOrderItemDto } from '../dto/add-order-item.dto';
@Injectable()
@@ -81,7 +77,9 @@ export class OrderService {
quantity: item.quantity,
status: OrderItemStatus.PENDING,
unitPrice: 0,
totalPrice: 0,
total: 0,
subTotal: 0,
discount: 0
})
em.persist(orderItem)
});
@@ -159,7 +157,9 @@ export class OrderService {
quantity: item.quantity,
status: OrderItemStatus.CONFIRMED,
unitPrice: item.unitPrice,
totalPrice: item.unitPrice * item.quantity,
total: item.unitPrice * item.quantity,
discount: 0,
subTotal: 0
})
em.persist(orderItem)
@@ -200,7 +200,7 @@ export class OrderService {
}
async createInvoice(orderId: string, dto: CreateInvoiceDto) {
const { items, discount } = dto
const { items } = dto
const targetOrder = await this.findOneOrFail(orderId)
@@ -212,6 +212,7 @@ export class OrderService {
const order = await this.em.transactional(async (em) => {
let subTotal = 0
let totalDiscount = 0
// Calculate order item finnicials
for (let orderItem of targetOrder.items) {
@@ -222,9 +223,10 @@ export class OrderService {
}
// TODO use Deciaml js to calculation
orderItem.unitPrice = found.unitPrice
orderItem.totalPrice = (found.unitPrice) * orderItem.quantity
orderItem.subTotal = (found.unitPrice) * orderItem.quantity
subTotal += orderItem.totalPrice
subTotal += orderItem.subTotal
em.persist(orderItem)
@@ -232,10 +234,10 @@ export class OrderService {
// calculate order financials
targetOrder.subTotal = subTotal
targetOrder.discount = discount
targetOrder.discount = totalDiscount
targetOrder.total = subTotal - discount
targetOrder.balance = subTotal - discount
targetOrder.total = subTotal - totalDiscount
targetOrder.balance = subTotal - totalDiscount
// change status
targetOrder.status = OrderStatusEnum.INVOICED
@@ -311,4 +313,41 @@ export class OrderService {
return { message: "Order deleted successfully" }
}
async addOrderItem(orderId: string, dto: AddOrderItemDto) {
const order = await this.orderRepository.findOne({ id: orderId })
if (!order) {
throw new BadRequestException("Order not Found!")
}
const { items } = dto
items.forEach(async item => {
const found = order.items.find((it => Number(it.product.id) === item.productId))
if (found) {
throw new BadRequestException("Product already exist!")
}
const product = await this.productRepository.findOne({ id: item.productId })
if (!product) {
throw new BadRequestException("Product not found!")
}
const newOrderItem = this.orderItemRepository.create({
discount: item.discount,
product,
unitPrice: item.unitPrice,
total: (item.unitPrice - item.discount) * item.quantity,
subTotal: item.unitPrice * item.quantity,
quantity: item.quantity,
status: OrderItemStatus.CONFIRMED,
attributesValues: item.attributesValues,
order
})
this.em.persist(newOrderItem)
})
// need calculate order finacial
await this.em.flush()
return order
}
}