from sqlalchemy import DateTime, ForeignKey, Numeric, String, Text from sqlalchemy.orm import Mapped, mapped_column from backend.app.db import Base from backend.app.models.base import AuditMixin, TimestampMixin class Customer(TimestampMixin, AuditMixin, Base): __tablename__ = "customer" id: Mapped[int] = mapped_column(primary_key=True) customer_name: Mapped[str] = mapped_column(String(64), index=True) mobile: Mapped[str] = mapped_column(String(32), index=True) address: Mapped[str | None] = mapped_column(String(255), nullable=True) settlement_type: Mapped[str | None] = mapped_column(String(32), nullable=True) settlement_days: Mapped[int] = mapped_column(default=0) customer_type: Mapped[str | None] = mapped_column(String(32), nullable=True) salesman_id: Mapped[int | None] = mapped_column(nullable=True) credit_limit: Mapped[float] = mapped_column(Numeric(18, 2), default=0) remark: Mapped[str | None] = mapped_column(String(255), nullable=True) class ProductCategory(TimestampMixin, AuditMixin, Base): __tablename__ = "product_category" id: Mapped[int] = mapped_column(primary_key=True) category_name: Mapped[str] = mapped_column(String(64)) category_code: Mapped[str] = mapped_column(String(64), unique=True, index=True) sort_no: Mapped[int] = mapped_column(default=0) status: Mapped[int] = mapped_column(default=1) remark: Mapped[str | None] = mapped_column(String(255), nullable=True) class Product(TimestampMixin, AuditMixin, Base): __tablename__ = "product" id: Mapped[int] = mapped_column(primary_key=True) product_name: Mapped[str] = mapped_column(String(64), index=True) specification: Mapped[str] = mapped_column(String(64), default="") unit: Mapped[str] = mapped_column(String(32), default="") category: Mapped[str | None] = mapped_column(String(64), nullable=True) category_id: Mapped[int | None] = mapped_column(ForeignKey("product_category.id"), nullable=True) cost_price: Mapped[float] = mapped_column(Numeric(18, 2), default=0) sale_price: Mapped[float] = mapped_column(Numeric(18, 2), default=0) status: Mapped[int] = mapped_column(default=1) remark: Mapped[str | None] = mapped_column(String(255), nullable=True) class Supplier(TimestampMixin, AuditMixin, Base): __tablename__ = "supplier" id: Mapped[int] = mapped_column(primary_key=True) supplier_name: Mapped[str] = mapped_column(String(64), index=True) supplier_type: Mapped[str] = mapped_column(String(32), default="factory") contact_name: Mapped[str | None] = mapped_column(String(64), nullable=True) contact_mobile: Mapped[str | None] = mapped_column(String(32), nullable=True) address: Mapped[str | None] = mapped_column(String(255), nullable=True) template_type: Mapped[str | None] = mapped_column(String(64), nullable=True) status: Mapped[int] = mapped_column(default=1) remark: Mapped[str | None] = mapped_column(String(255), nullable=True) class SalesOrder(TimestampMixin, AuditMixin, Base): __tablename__ = "sales_order" id: Mapped[int] = mapped_column(primary_key=True) order_no: Mapped[str] = mapped_column(String(64), unique=True, index=True) customer_id: Mapped[int | None] = mapped_column(ForeignKey("customer.id"), nullable=True) customer_name: Mapped[str] = mapped_column(String(64)) customer_mobile: Mapped[str] = mapped_column(String(32)) customer_address: Mapped[str | None] = mapped_column(String(255), nullable=True) salesman_id: Mapped[int | None] = mapped_column(nullable=True) order_status: Mapped[str] = mapped_column(String(32), index=True, default="draft") order_source: Mapped[str | None] = mapped_column(String(64), nullable=True) delivery_type: Mapped[str | None] = mapped_column(String(64), nullable=True) factory_id: Mapped[int | None] = mapped_column(ForeignKey("supplier.id"), nullable=True) sale_price_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) cost_price_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) rebate_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) freight_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) tax_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) other_fee_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) profit_total: Mapped[float] = mapped_column(Numeric(18, 2), default=0) profit_rate: Mapped[float] = mapped_column(Numeric(18, 2), default=0) commission_amount: Mapped[float] = mapped_column(Numeric(18, 2), default=0) cancel_requested_by: Mapped[int | None] = mapped_column(nullable=True) cancel_requested_at: Mapped[DateTime | None] = mapped_column(DateTime, nullable=True) cancel_reason: Mapped[str | None] = mapped_column(String(255), nullable=True) cancel_opinion: Mapped[str | None] = mapped_column(Text, nullable=True) cancel_previous_status: Mapped[str | None] = mapped_column(String(32), nullable=True) supplier_text_confirmed_at: Mapped[DateTime | None] = mapped_column(DateTime, nullable=True) supplier_text_confirmed_by: Mapped[int | None] = mapped_column(nullable=True) remark: Mapped[str | None] = mapped_column(Text, nullable=True) class SalesOrderItem(TimestampMixin, AuditMixin, Base): __tablename__ = "sales_order_item" id: Mapped[int] = mapped_column(primary_key=True) order_id: Mapped[int] = mapped_column(ForeignKey("sales_order.id"), index=True) product_id: Mapped[int | None] = mapped_column(nullable=True) product_name: Mapped[str] = mapped_column(String(64)) specification: Mapped[str] = mapped_column(String(64), default="") unit: Mapped[str] = mapped_column(String(32), default="") quantity: Mapped[float] = mapped_column(Numeric(18, 4), default=0) sale_price: Mapped[float] = mapped_column(Numeric(18, 2), default=0) cost_price: Mapped[float] = mapped_column(Numeric(18, 2), default=0) rebate_amount: Mapped[float] = mapped_column(Numeric(18, 2), default=0) freight_amount: Mapped[float] = mapped_column(Numeric(18, 2), default=0) tax_amount: Mapped[float] = mapped_column(Numeric(18, 2), default=0) other_fee_amount: Mapped[float] = mapped_column(Numeric(18, 2), default=0) remark: Mapped[str | None] = mapped_column(String(255), nullable=True) class LogisticsTask(TimestampMixin, AuditMixin, Base): __tablename__ = "logistics_task" id: Mapped[int] = mapped_column(primary_key=True) order_id: Mapped[int] = mapped_column(ForeignKey("sales_order.id"), index=True) driver_id: Mapped[int] = mapped_column(index=True) factory_id: Mapped[int | None] = mapped_column(ForeignKey("supplier.id"), nullable=True) pickup_address: Mapped[str] = mapped_column(String(255)) delivery_address: Mapped[str] = mapped_column(String(255)) pickup_content: Mapped[str] = mapped_column(String(255)) quantity: Mapped[float] = mapped_column(Numeric(18, 4), default=0) status: Mapped[str] = mapped_column(String(32), default="pending") created_by: Mapped[int | None] = mapped_column(nullable=True) canceled_by: Mapped[int | None] = mapped_column(nullable=True) cancel_reason: Mapped[str | None] = mapped_column(String(255), nullable=True) remark: Mapped[str | None] = mapped_column(String(255), nullable=True)