import enum from sqlalchemy import Column, DateTime, Enum, Float, ForeignKey, Integer, String, Text from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.db.session import Base class ShipmentStatus(str, enum.Enum): PENDING = "pending" PROCESSING = "processing" IN_TRANSIT = "in_transit" DELIVERED = "delivered" CANCELLED = "cancelled" class Shipment(Base): __tablename__ = "shipments" id = Column(Integer, primary_key=True, index=True) tracking_number = Column(String, unique=True, index=True, nullable=False) order_id = Column(Integer, ForeignKey("orders.id"), nullable=True) # Optional - can be internal movement origin_warehouse_id = Column(Integer, ForeignKey("warehouses.id"), nullable=False) destination_warehouse_id = Column(Integer, ForeignKey("warehouses.id"), nullable=True) # Null for direct customer delivery customer_address = Column(Text, nullable=True) # Required if destination_warehouse_id is null status = Column(Enum(ShipmentStatus), default=ShipmentStatus.PENDING) carrier = Column(String, nullable=True) estimated_delivery = Column(DateTime(timezone=True), nullable=True) actual_delivery = Column(DateTime(timezone=True), nullable=True) shipping_cost = Column(Float, default=0.0) created_by_id = Column(Integer, ForeignKey("users.id"), nullable=False) created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) # Relationships order = relationship("Order", back_populates="shipments") origin_warehouse = relationship("Warehouse", foreign_keys=[origin_warehouse_id], back_populates="shipments_from") destination_warehouse = relationship("Warehouse", foreign_keys=[destination_warehouse_id], back_populates="shipments_to") created_by = relationship("User", back_populates="shipments") items = relationship("ShipmentItem", back_populates="shipment") class ShipmentItem(Base): __tablename__ = "shipment_items" id = Column(Integer, primary_key=True, index=True) shipment_id = Column(Integer, ForeignKey("shipments.id"), nullable=False) product_id = Column(Integer, ForeignKey("products.id"), nullable=False) quantity = Column(Integer, nullable=False, default=1) # Relationships shipment = relationship("Shipment", back_populates="items") product = relationship("Product", back_populates="shipment_items")