From bdc76689a5b25d244963ff88cc90025a4f8f24e0 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sat, 24 Jan 2026 11:47:44 +0330 Subject: [PATCH] add item to invoice --- .../order/controllers/order.controller.ts | 12 +-- src/modules/order/dto/create-invoice.dto.ts | 50 ++++++++- src/modules/order/entities/order.entity.ts | 3 + src/modules/order/providers/order.service.ts | 100 ++++++++++++------ 4 files changed, 122 insertions(+), 43 deletions(-) diff --git a/src/modules/order/controllers/order.controller.ts b/src/modules/order/controllers/order.controller.ts index f8911d5..dab70ab 100644 --- a/src/modules/order/controllers/order.controller.ts +++ b/src/modules/order/controllers/order.controller.ts @@ -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) diff --git a/src/modules/order/dto/create-invoice.dto.ts b/src/modules/order/dto/create-invoice.dto.ts index a054b00..12bd328 100644 --- a/src/modules/order/dto/create-invoice.dto.ts +++ b/src/modules/order/dto/create-invoice.dto.ts @@ -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[] + } diff --git a/src/modules/order/entities/order.entity.ts b/src/modules/order/entities/order.entity.ts index 2b21853..7cfe53c 100644 --- a/src/modules/order/entities/order.entity.ts +++ b/src/modules/order/entities/order.entity.ts @@ -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) { const em = args.em; diff --git a/src/modules/order/providers/order.service.ts b/src/modules/order/providers/order.service.ts index b1bd174..4c0a08f 100644 --- a/src/modules/order/providers/order.service.ts +++ b/src/modules/order/providers/order.service.ts @@ -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 + // } }