add item to invoice

This commit is contained in:
2026-01-24 11:47:44 +03:30
parent 49390ce62e
commit bdc76689a5
4 changed files with 122 additions and 43 deletions
@@ -63,12 +63,12 @@ export class OrderController {
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/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)
+48 -2
View File
@@ -2,9 +2,10 @@ import {
IsInt, IsArray, IsNumber,
IsNotEmpty,
ArrayMinSize,
IsBoolean
IsBoolean,
IsString
} from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Type } from 'class-transformer';
export class InvoiceItemDto {
@@ -20,6 +21,33 @@ export class InvoiceItemDto {
@IsNumber()
discount: number
@ApiProperty()
@IsNumber()
quantity: number
}
export class InvoiceNewItemDto {
@IsNumber()
@ApiProperty()
productId: number;
@ApiProperty()
@IsArray()
attributesValues: string[]
@ApiProperty()
@IsNumber()
quantity: number
@ApiProperty()
@IsNumber()
unitPrice: number
@ApiProperty()
@IsNumber()
discount: number
}
export class CreateInvoiceDto {
@@ -37,9 +65,27 @@ export class CreateInvoiceDto {
@Type(() => InvoiceItemDto)
items: InvoiceItemDto[];
@IsArray()
@ApiProperty({
isArray: true, type: [InvoiceItemDto], example: [
{
orderItemId: 1,
unitPrice: 100,
}
]
})
@Type(() => InvoiceNewItemDto)
newItems: InvoiceNewItemDto[];
@ApiProperty()
@IsBoolean()
enableTax: boolean
@ApiPropertyOptional({ example: [] })
@IsArray()
@IsString({ each: true })
attachments: string[]
}
@@ -100,6 +100,9 @@ export class Order extends BaseEntity {
@Property({ type: 'json', nullable: true })
attachments?: string[]
@Property({ type: 'string', nullable: true })
paymentMethod?: string;
@BeforeCreate()
async generateOrderNumber(args: EventArgs<Order>) {
const em = args.em;
+65 -35
View File
@@ -54,7 +54,7 @@ export class OrderService {
paidAmount: 0,
balance: 0,
status: OrderStatusEnum.DRAFT,
taxAmount: 0
taxAmount: 0,
})
em.persist(order)
@@ -202,14 +202,14 @@ export class OrderService {
}
async createInvoice(orderId: string, dto: CreateInvoiceDto) {
const { items, enableTax } = dto
const { items, enableTax, attachments, newItems } = dto
const targetOrder = await this.findOneOrFail(orderId)
if (items.length !== targetOrder.items.length) {
throw new BadRequestException("One or more order items price is not set")
}
//TODO : calc is not correct
const order = await this.em.transactional(async (em) => {
@@ -234,6 +234,33 @@ export class OrderService {
}
newItems.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
})
subTotal += item.unitPrice
this.em.persist(newOrderItem)
})
// calculate order financials
targetOrder.subTotal = subTotal
targetOrder.discount = totalDiscount
@@ -249,6 +276,9 @@ export class OrderService {
targetOrder.total = total + tax
targetOrder.balance = total + tax
if (attachments.length) {
order.attachments = attachments
}
// change status
targetOrder.status = OrderStatusEnum.INVOICED
@@ -325,40 +355,40 @@ export class OrderService {
}
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
// 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))
// 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
})
// 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()
// this.em.persist(newOrderItem)
// })
// // need calculate order finacial
// await this.em.flush()
return order
}
// return order
// }
}