diff --git a/backend/app/models/product.py b/backend/app/models/product.py index 6c9b79d..2e1ba1f 100644 --- a/backend/app/models/product.py +++ b/backend/app/models/product.py @@ -33,6 +33,11 @@ class Product(Base): UUID(as_uuid=True), ForeignKey("products.id"), nullable=True, comment="父产品ID", ) + # ---- 当前位置追踪(逻辑外键→用户ID 或 'virtual_warehouse') ---- + current_location_id: Mapped[str | None] = mapped_column( + String(64), nullable=True, comment="当前持有者ID 或 'virtual_warehouse'(仓库)", + ) + status: Mapped[str] = mapped_column( String(50), nullable=False, default="pending", comment="产品状态", ) diff --git a/backend/app/models/task.py b/backend/app/models/task.py index dc18988..b6df1bd 100644 --- a/backend/app/models/task.py +++ b/backend/app/models/task.py @@ -1,4 +1,4 @@ -"""任务模型 — 支持无限嵌套""" +"""任务模型 — 支持无限嵌套、任务裂变分支、返工闭环""" import uuid from datetime import datetime, timezone from sqlalchemy import String, DateTime, Boolean, ForeignKey @@ -7,6 +7,13 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from app.models.base import Base +# 任务状态常量 +TASK_STATUS_PENDING = "PENDING" # 待接收 +TASK_STATUS_WIP = "WIP" # 进行中 +TASK_STATUS_COMPLETED = "COMPLETED" # 已完成 +TASK_STATUS_REJECTED = "REJECTED" # 已驳回 +TASK_STATUS_ARCHIVED = "ARCHIVED" # 已入库 + class Task(Base): __tablename__ = "tasks" @@ -20,9 +27,9 @@ class Task(Base): UUID(as_uuid=True), ForeignKey("products.id"), nullable=False, comment="所属产品ID", ) - # ---- 物理外键(自引用:无限嵌套父子任务) ---- + # ---- 物理外键(自引用:无限嵌套父子任务 / 裂变分支) ---- parent_task_id: Mapped[uuid.UUID | None] = mapped_column( - UUID(as_uuid=True), ForeignKey("tasks.id"), nullable=True, index=True, comment="父任务ID", + UUID(as_uuid=True), ForeignKey("tasks.id"), nullable=True, index=True, comment="父任务ID(用于任务裂变树)", ) task_name: Mapped[str] = mapped_column( @@ -35,16 +42,32 @@ class Task(Base): ) status: Mapped[str] = mapped_column( - String(50), nullable=False, default="pending", comment="任务状态", + String(50), nullable=False, default=TASK_STATUS_PENDING, + comment="任务状态: PENDING(待接收) | WIP(进行中) | COMPLETED(已完成) | REJECTED(已驳回) | ARCHIVED(已入库)", ) notify_parent_on_complete: Mapped[bool] = mapped_column( Boolean, default=False, comment="完成后是否通知父任务", ) + # ---- 时间追踪 ---- created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), comment="创建时间", ) + received_at: Mapped[datetime | None] = mapped_column( + DateTime(timezone=True), nullable=True, comment="操作员确认接收时间", + ) + completed_at: Mapped[datetime | None] = mapped_column( + DateTime(timezone=True), nullable=True, comment="任务完工转交时间", + ) + + # ---- 驳回/返工 ---- + reject_reason: Mapped[str | None] = mapped_column( + String(500), nullable=True, comment="驳回原因", + ) + is_rework: Mapped[bool] = mapped_column( + Boolean, default=False, comment="是否为返工任务", + ) # ---- 关系 ---- product: Mapped["Product"] = relationship("Product", lazy="selectin")