import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, ManyToOne, JoinColumn, Index, } from 'typeorm'; import { EcommerceOrder } from './ecommerce-order.entity'; export enum OrderLineStatus { PENDING = 'pending', RESERVED = 'reserved', FULFILLED = 'fulfilled', SHIPPED = 'shipped', DELIVERED = 'delivered', CANCELLED = 'cancelled', RETURNED = 'returned', REFUNDED = 'refunded', } @Entity('ecommerce_order_lines', { schema: 'retail' }) @Index(['tenantId', 'orderId']) @Index(['tenantId', 'productId']) export class EcommerceOrderLine { @PrimaryGeneratedColumn('uuid') id: string; @Column({ name: 'tenant_id', type: 'uuid' }) @Index() tenantId: string; @Column({ name: 'order_id', type: 'uuid' }) orderId: string; @Column({ name: 'line_number', type: 'int' }) lineNumber: number; @Column({ type: 'enum', enum: OrderLineStatus, default: OrderLineStatus.PENDING, }) status: OrderLineStatus; // Product (from erp-core) @Column({ name: 'product_id', type: 'uuid' }) productId: string; @Column({ name: 'product_code', length: 50 }) productCode: string; @Column({ name: 'product_name', length: 200 }) productName: string; @Column({ name: 'product_slug', length: 255, nullable: true }) productSlug: string; @Column({ name: 'product_image', length: 255, nullable: true }) productImage: string; // Variant @Column({ name: 'variant_id', type: 'uuid', nullable: true }) variantId: string; @Column({ name: 'variant_name', length: 200, nullable: true }) variantName: string; @Column({ name: 'variant_sku', length: 50, nullable: true }) variantSku: string; @Column({ name: 'variant_options', type: 'jsonb', nullable: true }) variantOptions: { name: string; value: string; }[]; // Quantity @Column({ type: 'decimal', precision: 15, scale: 4, default: 1 }) quantity: number; @Column({ name: 'quantity_fulfilled', type: 'decimal', precision: 15, scale: 4, default: 0 }) quantityFulfilled: number; @Column({ name: 'quantity_refunded', type: 'decimal', precision: 15, scale: 4, default: 0 }) quantityRefunded: number; // UOM @Column({ name: 'uom_id', type: 'uuid', nullable: true }) uomId: string; @Column({ name: 'uom_name', length: 20, default: 'PZA' }) uomName: string; // Pricing @Column({ name: 'unit_price', type: 'decimal', precision: 15, scale: 4 }) unitPrice: number; @Column({ name: 'original_price', type: 'decimal', precision: 15, scale: 4 }) originalPrice: number; // Discounts @Column({ name: 'discount_percent', type: 'decimal', precision: 5, scale: 2, default: 0 }) discountPercent: number; @Column({ name: 'discount_amount', type: 'decimal', precision: 15, scale: 2, default: 0 }) discountAmount: number; @Column({ name: 'promotion_id', type: 'uuid', nullable: true }) promotionId: string; @Column({ name: 'promotion_name', length: 100, nullable: true }) promotionName: string; // Tax @Column({ name: 'tax_id', type: 'uuid', nullable: true }) taxId: string; @Column({ name: 'tax_rate', type: 'decimal', precision: 5, scale: 4, default: 0 }) taxRate: number; @Column({ name: 'tax_amount', type: 'decimal', precision: 15, scale: 2, default: 0 }) taxAmount: number; @Column({ name: 'tax_included', type: 'boolean', default: true }) taxIncluded: boolean; // Totals @Column({ type: 'decimal', precision: 15, scale: 2, default: 0 }) subtotal: number; @Column({ type: 'decimal', precision: 15, scale: 2, default: 0 }) total: number; // Cost @Column({ name: 'unit_cost', type: 'decimal', precision: 15, scale: 4, nullable: true }) unitCost: number; // Weight (for shipping calculation) @Column({ type: 'decimal', precision: 10, scale: 4, nullable: true }) weight: number; @Column({ name: 'weight_unit', length: 5, default: 'kg' }) weightUnit: string; // Warehouse @Column({ name: 'warehouse_id', type: 'uuid', nullable: true }) warehouseId: string; // Lot/Serial @Column({ name: 'lot_number', length: 50, nullable: true }) lotNumber: string; @Column({ name: 'serial_number', length: 50, nullable: true }) serialNumber: string; // Custom options @Column({ name: 'custom_options', type: 'jsonb', nullable: true }) customOptions: { name: string; value: string; price?: number; }[]; // Gift @Column({ name: 'is_gift', type: 'boolean', default: false }) isGift: boolean; @Column({ name: 'gift_message', type: 'text', nullable: true }) giftMessage: string; // Refund @Column({ name: 'refunded_at', type: 'timestamp with time zone', nullable: true }) refundedAt: Date; @Column({ name: 'refund_amount', type: 'decimal', precision: 15, scale: 2, default: 0 }) refundAmount: number; @Column({ name: 'refund_reason', length: 255, nullable: true }) refundReason: string; // Notes @Column({ type: 'text', nullable: true }) notes: string; // Metadata @Column({ type: 'jsonb', nullable: true }) metadata: Record; @CreateDateColumn({ name: 'created_at' }) createdAt: Date; // Relations @ManyToOne(() => EcommerceOrder, (order) => order.lines) @JoinColumn({ name: 'order_id' }) order: EcommerceOrder; }