import ulid from sqlalchemy import Column, String, Numeric, DateTime, Integer, ForeignKey, Text, Index from sqlalchemy.sql import func from sqlalchemy.orm import relationship from app.core.database.db_session import Base class Order(Base): __tablename__ = "orders" order_id = Column(String(26), primary_key=True, default=lambda: str(ulid.new())) order_no = Column(String(50), unique=True, nullable=False, index=True) customer_id = Column(String(26), ForeignKey("ecom_customers.customer_id", ondelete="SET NULL"), nullable=True, index=True) total_amount = Column(Numeric(10, 2), nullable=False) discount_amount = Column(Numeric(10, 2), default=0.00) tax_amount = Column(Numeric(10, 2), default=0.00) shipping_cost = Column(Numeric(10, 2), default=0.00) final_amount = Column(Numeric(10, 2), nullable=False) status = Column(String(50), default="ORDER_CREATED", index=True) # ORDER_CREATED, PAYMENT_PENDING, ORDER_CONFIRMED, PROCESSING, PACKED, SHIPPED, DELIVERED, CANCELLED payment_status = Column(String(50), default="PAYMENT_PENDING", index=True) # PAYMENT_PENDING, PAYMENT_CAPTURED, PAYMENT_FAILED, REFUNDED fulfillment_status = Column(String(50), default="UNFULFILLED") shipping_address_json = Column(Text, nullable=True) billing_address_json = Column(Text, nullable=True) tracking_number = Column(String(100), nullable=True) courier_name = Column(String(100), nullable=True) created_at = Column(DateTime, server_default=func.now(), index=True) updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now()) __table_args__ = ( Index('idx_orders_customer_created', 'customer_id', 'created_at'), Index('idx_orders_status_created', 'status', 'created_at'), ) customer = relationship("EcomCustomer", back_populates="orders") items = relationship("OrderItem", back_populates="order", cascade="all, delete-orphan") history = relationship("OrderStatusHistory", back_populates="order", cascade="all, delete-orphan") class OrderItem(Base): __tablename__ = "order_items" item_id = Column(String(26), primary_key=True, default=lambda: str(ulid.new())) order_id = Column(String(26), ForeignKey("orders.order_id", ondelete="CASCADE"), nullable=False, index=True) product_id = Column(String(26), nullable=False) variant_id = Column(String(26), nullable=False, index=True) product_name = Column(String(255), nullable=False) sku = Column(String(100), nullable=False) unit_price = Column(Numeric(10, 2), nullable=False) quantity = Column(Integer, nullable=False) total_price = Column(Numeric(10, 2), nullable=False) order = relationship("Order", back_populates="items") class OrderStatusHistory(Base): __tablename__ = "order_status_history" history_id = Column(String(26), primary_key=True, default=lambda: str(ulid.new())) order_id = Column(String(26), ForeignKey("orders.order_id", ondelete="CASCADE"), nullable=False, index=True) previous_status = Column(String(50), nullable=True) new_status = Column(String(50), nullable=False) changed_by = Column(String(100), default="SYSTEM") reason = Column(String(255), nullable=True) created_at = Column(DateTime, server_default=func.now()) order = relationship("Order", back_populates="history")