feat(api): 新增核心 API 端点 + 数据库迁移
新增 3 个 API 端点:
- POST /tasks/{id}/receive: 确认接收 (PENDING→WIP)
- POST /tasks/{id}/reject: 品质驳回 + 返工闭环
- POST /tasks/{id}/transfer: 完工裂变转交 (多路分支+入库)
数据库迁移 (a1b2c3d4e5f6):
- tasks 表新增 received_at, completed_at, reject_reason, is_rework
- products 表新增 current_location_id
- 数据迁移: 已有任务状态小写→大写 (pending→PENDING 等)
This commit is contained in:
@ -0,0 +1,102 @@
|
||||
"""add task rework fields and product current_location
|
||||
|
||||
Revision ID: a1b2c3d4e5f6
|
||||
Revises: 80f8cb64544a
|
||||
Create Date: 2026-08-04 12:00:00.000000
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'a1b2c3d4e5f6'
|
||||
down_revision: Union[str, Sequence[str], None] = '80f8cb64544a'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# === 数据迁移:将已有任务状态从小写转为大写 ===
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'PENDING' WHERE lower(status) = 'pending';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'WIP' WHERE lower(status) = 'wip';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'COMPLETED' WHERE lower(status) = 'completed';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'REJECTED' WHERE lower(status) = 'rejected';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'ARCHIVED' WHERE lower(status) = 'archived';
|
||||
""")
|
||||
|
||||
# === tasks 表新增字段 ===
|
||||
op.add_column('tasks', sa.Column(
|
||||
'received_at',
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=True,
|
||||
comment='操作员确认接收时间',
|
||||
))
|
||||
op.add_column('tasks', sa.Column(
|
||||
'completed_at',
|
||||
sa.DateTime(timezone=True),
|
||||
nullable=True,
|
||||
comment='任务完工转交时间',
|
||||
))
|
||||
op.add_column('tasks', sa.Column(
|
||||
'reject_reason',
|
||||
sa.String(length=500),
|
||||
nullable=True,
|
||||
comment='驳回原因',
|
||||
))
|
||||
op.add_column('tasks', sa.Column(
|
||||
'is_rework',
|
||||
sa.Boolean(),
|
||||
nullable=False,
|
||||
server_default=sa.text('false'),
|
||||
comment='是否为返工任务',
|
||||
))
|
||||
|
||||
# === products 表新增字段 ===
|
||||
op.add_column('products', sa.Column(
|
||||
'current_location_id',
|
||||
sa.String(length=64),
|
||||
nullable=True,
|
||||
comment="当前持有者ID 或 'virtual_warehouse'(仓库)",
|
||||
))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# === products 表移除字段 ===
|
||||
op.drop_column('products', 'current_location_id')
|
||||
|
||||
# === tasks 表移除字段 ===
|
||||
op.drop_column('tasks', 'is_rework')
|
||||
op.drop_column('tasks', 'reject_reason')
|
||||
op.drop_column('tasks', 'completed_at')
|
||||
op.drop_column('tasks', 'received_at')
|
||||
|
||||
# === 数据回迁:将任务状态从大写转回小写 ===
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'pending' WHERE status = 'PENDING';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'wip' WHERE status = 'WIP';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'completed' WHERE status = 'COMPLETED';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'rejected' WHERE status = 'REJECTED';
|
||||
""")
|
||||
op.execute("""
|
||||
UPDATE tasks SET status = 'archived' WHERE status = 'ARCHIVED';
|
||||
""")
|
||||
Reference in New Issue
Block a user