import { Entity, Index, ManyToOne, OneToMany, Property, Collection, Cascade, Enum, PrimaryKey, BeforeCreate, type EventArgs, } 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'; @Entity({ tableName: 'orders' }) @Index({ properties: ['user', 'status'] }) @Index({ properties: ['status'] }) export class Order extends BaseEntity { @PrimaryKey({ type: 'string', columnType: 'char(26)' }) id: string = ulid() //TODO : need a new field for confirmation .confirmedAt // also need another for @ManyToOne(() => User) user!: User; @OneToMany(() => Payment, payment => payment.order, { cascade: [Cascade.ALL], orphanRemoval: true, }) payments = new Collection(this); @OneToMany(() => OrderItem, item => item.order, { cascade: [Cascade.ALL], orphanRemoval: true, }) items = new Collection(this); @ManyToOne(() => Admin, { nullable: true }) creator?: Admin @ManyToOne(() => Admin, { nullable: true }) designer?: Admin @Property({ type: 'int', nullable: true }) orderNumber?: number; @Property({ type: 'decimal', precision: 10, scale: 0, default: 0 }) discount: number = 0; @Property({ type: 'decimal', precision: 10, scale: 0 }) subTotal!: number; @Property({ type: 'decimal', precision: 10, scale: 0 }) taxAmount: number; @Property({ type: 'decimal', precision: 10, scale: 0 }) total!: number; @Property({ type: 'decimal', precision: 10, scale: 0 }) paidAmount!: number; // private _balance!: number; @Property({ type: 'decimal', precision: 10, scale: 0 }) balance!: number; @Property({ type: 'decimal', precision: 10, scale: 0, nullable: true }) dueDate?: number; // number of days to be done // get balance(): number { // return this._balance // } // set balance(value) { // this._balance = this.total - this.paidAmount // } // @Property({ type: 'text', nullable: true }) // description?: string; @Enum(() => OrderStatusEnum) status!: OrderStatusEnum; @Property({ type: 'json', nullable: true }) attachments?: string[] @Property({ type: 'json', nullable: true }) printIds?: string[] // id of field options @Property({ type: 'string', nullable: true }) paymentMethod?: string; @BeforeCreate() async generateOrderNumber(args: EventArgs) { const em = args.em; const order = args.entity; const maxOrder = await em.findOne( Order, {}, { orderBy: { orderNumber: 'DESC' }, fields: ['orderNumber'], }, ); // Set the next order number (1 if no orders exist, otherwise max + 1) order.orderNumber = maxOrder?.orderNumber ? maxOrder.orderNumber + 1 : 1; } }