"""inventory 仓储域模型:仓库/库存/库存流水。""" from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean, Numeric, ForeignKey, UniqueConstraint, CheckConstraint from sqlalchemy.sql import func from sqlalchemy.orm import relationship from shared.models.base import Base class Warehouse(Base): """仓库表""" __tablename__ = "warehouses" id = Column(Integer, primary_key=True, index=True) code = Column(String(50), unique=True, index=True) name = Column(String(200), nullable=False) address = Column(Text, nullable=True) manager = Column(String(100), nullable=True) phone = Column(String(50), nullable=True) is_active = Column(Boolean, default=True) is_default = Column(Boolean, default=False) created_at = Column(DateTime, default=func.now()) inventories = relationship("Inventory", back_populates="warehouse") def __repr__(self): return f"" class Inventory(Base): """库存表""" __tablename__ = "inventory" __table_args__ = ( UniqueConstraint("product_id", "warehouse_id", name="uq_inventory_product_warehouse"), CheckConstraint("quantity >= 0 AND locked_quantity >= 0 AND locked_quantity <= quantity", name="ck_inventory_qty_nonnegative"), ) id = Column(Integer, primary_key=True, index=True) product_id = Column(Integer, ForeignKey("products.id"), nullable=False, index=True) warehouse_id = Column(Integer, ForeignKey("warehouses.id"), nullable=False, index=True) quantity = Column(Numeric(12, 4), default=0) locked_quantity = Column(Numeric(12, 4), default=0) batch_number = Column(String(50), nullable=True) location = Column(String(100), nullable=True) updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) product = relationship("Product", back_populates="inventory") warehouse = relationship("Warehouse", back_populates="inventories") def __repr__(self): return f"" @property def available_quantity(self): return self.quantity - self.locked_quantity class StockMovement(Base): """库存变动记录表""" __tablename__ = "stock_movements" id = Column(Integer, primary_key=True, index=True) product_id = Column(Integer, ForeignKey("products.id"), nullable=False, index=True) warehouse_id = Column(Integer, ForeignKey("warehouses.id"), nullable=False) movement_type = Column(String(20), nullable=False) quantity = Column(Numeric(12, 4), nullable=False) before_quantity = Column(Numeric(12, 4), default=0) after_quantity = Column(Numeric(12, 4), default=0) reference_type = Column(String(50), nullable=True) reference_id = Column(Integer, nullable=True) reference_no = Column(String(50), nullable=True) unit_price = Column(Numeric(12, 2), nullable=True) total_amount = Column(Numeric(12, 2), nullable=True) remark = Column(Text, nullable=True) operator_id = Column(Integer, ForeignKey("users.id"), nullable=True) created_at = Column(DateTime, default=func.now(), index=True) product = relationship("Product", back_populates="stock_movements") def __repr__(self): return f""