diff --git a/src/modules/order/entities/order.entity.ts b/src/modules/order/entities/order.entity.ts index 3270561..a69e0d2 100644 --- a/src/modules/order/entities/order.entity.ts +++ b/src/modules/order/entities/order.entity.ts @@ -10,19 +10,23 @@ import { PrimaryKey, BeforeCreate, type EventArgs, + OptionalProps } from '@mikro-orm/core'; -import { BaseEntity } from '../../../common/entities/base.entity'; import { OrderStatusEnum } from '../interface/order.interface'; import { User } from '../../user/entities/user.entity'; import { OrderItem } from './order-item.entity'; import { Payment } from 'src/modules/payment/entities/payment.entity'; import { ulid } from 'ulid'; import { Admin } from 'src/modules/admin/entities/admin.entity'; +import { PaymentStatusEnum } from 'src/modules/payment/interface/payment'; @Entity({ tableName: 'orders' }) @Index({ properties: ['user', 'status'] }) @Index({ properties: ['status'] }) -export class Order extends BaseEntity { +export class Order { + [OptionalProps]?: 'createdAt' | 'deletedAt' | 'balance' | 'paidAmount' + | 'discount' | 'subTotal' | 'total' | 'taxAmount'; + @PrimaryKey({ type: 'string', columnType: 'char(26)' }) id: string = ulid() @@ -55,33 +59,60 @@ export class Order extends BaseEntity { orderNumber?: number; - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - discount?: number; + // @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) + // discount?: number; + get discount(): number { + if (!this.items.isInitialized()) return 0; + return this.items + .getItems() + .reduce((sum, p) => sum + Number(p.discount), 0); + } - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - subTotal?: number; + // @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) + // subTotal?: number; + get subTotal(): number { + if (!this.items.isInitialized()) return 0; + return this.items + .getItems() + .reduce((sum, p) => sum + Number(p.subTotal), 0) + } - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - taxAmount?: number; + // @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) + // taxAmount?: number; + get taxAmount(): number { + return this.enableTax ? this.total * 0.1 : 0 + } - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - total?: number; + // @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) + // total?: number; + get total(): number { + return this.subTotal - this.discount + Number(this.taxAmount) + } - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - paidAmount?: number; + // @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) + // paidAmount?: number; // private _balance!: number; - // get balance(): number { - // return this._balance - // } // set balance(value) { // this._balance = this.total - this.paidAmount // } - @Property({ type: 'decimal', precision: 10, scale: 0, default: null, nullable: true }) - balance?: number; + + get paidAmount(): number { + if (!this.payments.isInitialized()) return 0; + + return this.payments + .getItems() + .filter(p => p.status == PaymentStatusEnum.Paid) + .reduce((sum, p) => sum + Number(p.amount), 0); + } + + get balance(): number { + const total = Number(this.total ?? 0); + return total - this.paidAmount; + } @Property({ type: 'int', nullable: true }) estimatedDays?: number; // number of days to be done @@ -105,6 +136,12 @@ export class Order extends BaseEntity { @Property({ type: 'boolean', default: false }) enableTax?: Boolean = false + @Property({ defaultRaw: 'now()', columnType: 'timestamptz' }) + createdAt: Date = new Date(); + + @Property({ nullable: true, columnType: 'timestamptz' }) + deletedAt?: Date; + @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 8f95f4a..04370f0 100644 --- a/src/modules/order/providers/order.service.ts +++ b/src/modules/order/providers/order.service.ts @@ -42,14 +42,16 @@ export class OrderService { async createOrderAsAdmin(adminId: string, dto: CreateOrderAsAdminDto) { const order = await this.createOrder({ ...dto, adminId }) - await this.calculateOrder(order) - this.em.flush() + // await this.calculateOrder(order) + // this.em.flush() + this.logger.log("Order created as admin") return order } async createOrderAsUser(userId: string, dto: CreateOrderDto) { const order = await this.createOrder({ ...dto, userId, status: OrderStatusEnum.CREATED }) + this.logger.log("Order created as admin") return order } @@ -101,13 +103,13 @@ export class OrderService { throw new BadRequestException("some products not found") } - items.forEach(item => { + for (const item of items) { this.persistOrderItem(order, item) - }); + } // TODO : calculation must be done after create order - await this.calculateOrder(order) + // await this.calculateOrder(order) // await em.flush() @@ -131,7 +133,7 @@ export class OrderService { } - if (adminId) { + if (adminId != undefined) { const admin = await this.adminRepository.findOne({ id: adminId }) if (!admin) { throw new BadRequestException("Admin not found") @@ -140,7 +142,7 @@ export class OrderService { } - if (designerId) { + if (designerId != undefined) { const designer = await this.adminRepository.findOne({ id: designerId }) if (!designer) { throw new BadRequestException("designer not found") @@ -148,31 +150,27 @@ export class OrderService { order.designer = designer } - if (attachments) { + if (attachments != undefined) { order.attachments = attachments } - if (typeof enableTax !== 'undefined') { + if (enableTax != undefined) { order.enableTax = enableTax } - if (estimatedDays) { + if (estimatedDays != undefined) { order.estimatedDays = estimatedDays } - if (paymentMethod) { + if (paymentMethod != undefined) { order.paymentMethod = paymentMethod } - if (status) { + if (status != undefined) { order.status = status } - this.em.persist(order) - - await this.calculateOrder(order) - - await this.em.flush() + await this.em.persistAndFlush(order) return order } @@ -180,11 +178,13 @@ export class OrderService { async updateOrderAsAdmin(orderId: string, dto: IUpdateOrder) { const order = await this.findOneOrFail(orderId) - await this.updateOrder(order, dto) + const updateOrder= await this.updateOrder(order, dto) - const updateOrder = await this.calculateOrder(order) + // const updateOrder = await this.calculateOrder(order) - await this.em.flush() + // await this.em.flush() + + this.logger.log("Order updated as admin") return updateOrder } @@ -216,9 +216,9 @@ export class OrderService { await this.em.flush() - await this.calculateOrder(undefined, orderId) + // await this.calculateOrder(undefined, orderId) - await this.em.flush() + // await this.em.flush() return orderItem } @@ -276,9 +276,9 @@ export class OrderService { const orderItem = await this.updateOrderItem(itemId, dto) - await this.calculateOrder(undefined, orderId) + // await this.calculateOrder(undefined, orderId) - await this.em.flush() + // await this.em.flush() return orderItem } @@ -337,9 +337,9 @@ export class OrderService { await this.removeOrderItem(itemId) - await this.calculateOrder(undefined, orderId) + // await this.calculateOrder(undefined, orderId) - await this.em.flush() + // await this.em.flush() return true } @@ -391,44 +391,44 @@ export class OrderService { return order } - async calculateOrder(inputOrder?: Order, orderId?: string) { - let order: undefined | Order = inputOrder + // async calculateOrder(inputOrder?: Order, orderId?: string) { + // let order: undefined | Order = inputOrder - if (!order && orderId) { - order = await this.findOneOrFail(orderId) - } + // if (!order && orderId) { + // order = await this.findOneOrFail(orderId) + // } - if (!order) { - throw new BadRequestException("Order not found") - } - // calculate order financials - let subTotal = 0 - let totalDiscount = 0 + // if (!order) { + // throw new BadRequestException("Order not found") + // } + // // calculate order financials + // const subTotal = order.items.reduce((sum, item) => { + // return sum + item.subTotal + // }, 0) - // TODO : use reduce - for (let orderItem of order.items) { - subTotal += orderItem.total - totalDiscount += Number(orderItem.discount) - } + // const totalDiscount = order.items.reduce((sum, item) => { + // return sum + Number(item.discount) + // }, 0) - const totalBeforeTax = subTotal - totalDiscount - let tax = 0 - if (order.enableTax) { - tax = 0.1 * totalBeforeTax - } + // const totalBeforeTax = subTotal - totalDiscount + // let tax = 0 - const total = totalBeforeTax + tax - const paidAmount = await this.paymentRepository.getActualPaidAmount(order.id) - // Update Order financial values - order.subTotal = subTotal - order.discount = totalDiscount - order.taxAmount = tax - order.total = total - order.balance = total - paidAmount + // if (order.enableTax) { + // tax = 0.1 * totalBeforeTax + // } - return order - } + // const total = totalBeforeTax + tax + + // // Update Order financial values + // // order.subTotal = subTotal + // // order.discount = totalDiscount + // // order.taxAmount = tax + // // order.total = total + // // order.balance = total - paidAmount + + // return order + // } async confirmOrderItem(userId: string, orderId: string, orderItemId: number) { @@ -477,7 +477,7 @@ export class OrderService { throw new BadRequestException("Order not found") } if (![OrderStatusEnum.CREATED, OrderStatusEnum.INVOICED].includes(order.status)) { - throw new BadRequestException("Order status must be of of Drfat or Invoiced") + throw new BadRequestException("Order status must be of of Draft or Invoiced") } if (order.payments.length > 0) { throw new BadRequestException("order with payments can not be deleted!") @@ -522,7 +522,7 @@ export class OrderService { async createInvoice(orderId: string) { const order = await this.findOneOrFail(orderId) await this.updateStatus(orderId, OrderStatusEnum.INVOICED) - await this.calculateOrder(order) + // await this.calculateOrder(order) await this.em.flush() } } diff --git a/src/modules/payment/services/payments.service.ts b/src/modules/payment/services/payments.service.ts index 536ea91..5a61451 100644 --- a/src/modules/payment/services/payments.service.ts +++ b/src/modules/payment/services/payments.service.ts @@ -222,8 +222,8 @@ export class PaymentService { payment.transactionId = referenceId; // TODO : use decimal js // does need persist or not - payment.order.paidAmount! += payment.amount - payment.order.balance! -= payment.amount + // payment.order.paidAmount! += payment.amount + // payment.order.balance! -= payment.amount await em.flush(); return payment; @@ -261,8 +261,8 @@ export class PaymentService { payment.failedAt = null; // TODO : use decimal js - payment.order.paidAmount! += payment.amount - payment.order.balance! -= payment.amount + // payment.order.paidAmount! += payment.amount + // payment.order.balance! -= payment.amount em.persist(payment); em.persist(payment.order); @@ -286,8 +286,8 @@ export class PaymentService { } if (payment.status == PaymentStatusEnum.Paid) { - payment.order.paidAmount! -= payment.amount - payment.order.balance! += payment.amount + // payment.order.paidAmount! -= payment.amount + // payment.order.balance! += payment.amount em.persistAndFlush(payment.order) }