erp-retail-backend/src/modules/ecommerce/entities/ecommerce-order.entity.ts

310 lines
8.3 KiB
TypeScript

import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
Index,
} from 'typeorm';
import { EcommerceOrderLine } from './ecommerce-order-line.entity';
export enum EcommerceOrderStatus {
PENDING = 'pending',
CONFIRMED = 'confirmed',
PROCESSING = 'processing',
READY_FOR_PICKUP = 'ready_for_pickup',
SHIPPED = 'shipped',
DELIVERED = 'delivered',
CANCELLED = 'cancelled',
REFUNDED = 'refunded',
}
export enum PaymentStatus {
PENDING = 'pending',
AUTHORIZED = 'authorized',
CAPTURED = 'captured',
FAILED = 'failed',
REFUNDED = 'refunded',
PARTIALLY_REFUNDED = 'partially_refunded',
}
export enum FulfillmentType {
SHIP = 'ship',
PICKUP = 'pickup',
DELIVERY = 'delivery',
}
@Entity('ecommerce_orders', { schema: 'retail' })
@Index(['tenantId', 'status', 'createdAt'])
@Index(['tenantId', 'customerId'])
@Index(['tenantId', 'number'], { unique: true })
@Index(['tenantId', 'paymentStatus'])
export class EcommerceOrder {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'tenant_id', type: 'uuid' })
@Index()
tenantId: string;
@Column({ length: 30, unique: true })
number: string;
@Column({
type: 'enum',
enum: EcommerceOrderStatus,
default: EcommerceOrderStatus.PENDING,
})
status: EcommerceOrderStatus;
@Column({
name: 'payment_status',
type: 'enum',
enum: PaymentStatus,
default: PaymentStatus.PENDING,
})
paymentStatus: PaymentStatus;
@Column({
name: 'fulfillment_type',
type: 'enum',
enum: FulfillmentType,
default: FulfillmentType.SHIP,
})
fulfillmentType: FulfillmentType;
// Customer
@Column({ name: 'customer_id', type: 'uuid', nullable: true })
customerId: string;
@Column({ name: 'customer_email', length: 100 })
customerEmail: string;
@Column({ name: 'customer_phone', length: 20, nullable: true })
customerPhone: string;
@Column({ name: 'customer_name', length: 200 })
customerName: string;
@Column({ name: 'is_guest', type: 'boolean', default: false })
isGuest: boolean;
// Currency
@Column({ name: 'currency_code', length: 3, default: 'MXN' })
currencyCode: string;
@Column({ name: 'exchange_rate', type: 'decimal', precision: 10, scale: 6, default: 1 })
exchangeRate: number;
// Amounts
@Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
subtotal: number;
@Column({ name: 'discount_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
discountAmount: number;
@Column({ name: 'tax_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
taxAmount: number;
@Column({ name: 'shipping_amount', type: 'decimal', precision: 15, scale: 2, default: 0 })
shippingAmount: number;
@Column({ name: 'shipping_tax', type: 'decimal', precision: 15, scale: 2, default: 0 })
shippingTax: number;
@Column({ type: 'decimal', precision: 15, scale: 2, default: 0 })
total: number;
@Column({ name: 'amount_paid', type: 'decimal', precision: 15, scale: 2, default: 0 })
amountPaid: number;
@Column({ name: 'amount_refunded', type: 'decimal', precision: 15, scale: 2, default: 0 })
amountRefunded: number;
// Item counts
@Column({ name: 'items_count', type: 'int', default: 0 })
itemsCount: number;
@Column({ name: 'items_quantity', type: 'decimal', precision: 15, scale: 4, default: 0 })
itemsQuantity: number;
// Coupon
@Column({ name: 'coupon_id', type: 'uuid', nullable: true })
couponId: string;
@Column({ name: 'coupon_code', length: 50, nullable: true })
couponCode: string;
@Column({ name: 'coupon_discount', type: 'decimal', precision: 15, scale: 2, default: 0 })
couponDiscount: number;
// Loyalty
@Column({ name: 'loyalty_points_used', type: 'int', default: 0 })
loyaltyPointsUsed: number;
@Column({ name: 'loyalty_points_value', type: 'decimal', precision: 15, scale: 2, default: 0 })
loyaltyPointsValue: number;
@Column({ name: 'loyalty_points_earned', type: 'int', default: 0 })
loyaltyPointsEarned: number;
// Shipping address
@Column({ name: 'shipping_address', type: 'jsonb' })
shippingAddress: {
firstName: string;
lastName: string;
company?: string;
address1: string;
address2?: string;
city: string;
state: string;
postalCode: string;
country: string;
phone: string;
instructions?: string;
};
// Billing address
@Column({ name: 'billing_address', type: 'jsonb' })
billingAddress: {
firstName: string;
lastName: string;
company?: string;
rfc?: string;
address1: string;
address2?: string;
city: string;
state: string;
postalCode: string;
country: string;
phone: string;
};
// Shipping
@Column({ name: 'shipping_method_id', type: 'uuid', nullable: true })
shippingMethodId: string;
@Column({ name: 'shipping_method_name', length: 100, nullable: true })
shippingMethodName: string;
@Column({ name: 'shipping_carrier', length: 100, nullable: true })
shippingCarrier: string;
@Column({ name: 'tracking_number', length: 100, nullable: true })
trackingNumber: string;
@Column({ name: 'tracking_url', length: 255, nullable: true })
trackingUrl: string;
@Column({ name: 'estimated_delivery', type: 'date', nullable: true })
estimatedDelivery: Date;
@Column({ name: 'shipped_at', type: 'timestamp with time zone', nullable: true })
shippedAt: Date;
@Column({ name: 'delivered_at', type: 'timestamp with time zone', nullable: true })
deliveredAt: Date;
// Pickup
@Column({ name: 'pickup_branch_id', type: 'uuid', nullable: true })
pickupBranchId: string;
@Column({ name: 'pickup_ready_at', type: 'timestamp with time zone', nullable: true })
pickupReadyAt: Date;
@Column({ name: 'picked_up_at', type: 'timestamp with time zone', nullable: true })
pickedUpAt: Date;
// Payment
@Column({ name: 'payment_method', length: 50, nullable: true })
paymentMethod: string;
@Column({ name: 'payment_gateway', length: 50, nullable: true })
paymentGateway: string;
@Column({ name: 'payment_transaction_id', length: 100, nullable: true })
paymentTransactionId: string;
@Column({ name: 'payment_details', type: 'jsonb', nullable: true })
paymentDetails: Record<string, any>;
// Invoice
@Column({ name: 'requires_invoice', type: 'boolean', default: false })
requiresInvoice: boolean;
@Column({ name: 'invoice_rfc', length: 13, nullable: true })
invoiceRfc: string;
@Column({ name: 'invoice_uso_cfdi', length: 4, nullable: true })
invoiceUsoCfdi: string;
@Column({ name: 'cfdi_id', type: 'uuid', nullable: true })
cfdiId: string;
@Column({ name: 'invoice_status', length: 20, nullable: true })
invoiceStatus: string;
// Gift
@Column({ name: 'is_gift', type: 'boolean', default: false })
isGift: boolean;
@Column({ name: 'gift_message', type: 'text', nullable: true })
giftMessage: string;
// Notes
@Column({ name: 'customer_notes', type: 'text', nullable: true })
customerNotes: string;
@Column({ name: 'internal_notes', type: 'text', nullable: true })
internalNotes: string;
// Cancellation
@Column({ name: 'cancelled_at', type: 'timestamp with time zone', nullable: true })
cancelledAt: Date;
@Column({ name: 'cancellation_reason', length: 255, nullable: true })
cancellationReason: string;
// Source cart
@Column({ name: 'cart_id', type: 'uuid', nullable: true })
cartId: string;
// Fulfillment warehouse
@Column({ name: 'warehouse_id', type: 'uuid', nullable: true })
warehouseId: string;
// Analytics
@Column({ name: 'utm_source', length: 100, nullable: true })
utmSource: string;
@Column({ name: 'utm_medium', length: 100, nullable: true })
utmMedium: string;
@Column({ name: 'utm_campaign', length: 100, nullable: true })
utmCampaign: string;
@Column({ name: 'device_type', length: 20, nullable: true })
deviceType: string;
@Column({ name: 'ip_address', length: 45, nullable: true })
ipAddress: string;
// Metadata
@Column({ type: 'jsonb', nullable: true })
metadata: Record<string, any>;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
@Column({ name: 'confirmed_at', type: 'timestamp with time zone', nullable: true })
confirmedAt: Date;
// Relations
@OneToMany(() => EcommerceOrderLine, (line) => line.order)
lines: EcommerceOrderLine[];
}