Add duty_time_range dictionary with day/night presets, parse typed ranges on ensure, and replace time pickers with allow-create select in the schedule dialog. Co-authored-by: Cursor <cursoragent@cursor.com>
98 lines
4.8 KiB
Python
98 lines
4.8 KiB
Python
"""值班排班模型 — docs/superpowers/specs/2026-08-14-duty-schedule-design.md"""
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import Column, Date, DateTime, Integer, SmallInteger, String, Time
|
||
|
||
from app.core.database import Base
|
||
|
||
SHIFT_MORNING = "morning"
|
||
SHIFT_EVENING = "evening"
|
||
SHIFT_DUTY = "duty"
|
||
SHIFT_LABELS = {
|
||
SHIFT_MORNING: "早班",
|
||
SHIFT_EVENING: "晚班",
|
||
SHIFT_DUTY: "值班",
|
||
}
|
||
DICT_SHIFT_TYPE = "duty_shift_type"
|
||
DICT_WORK_PLAN = "duty_work_plan"
|
||
DICT_TIME_RANGE = "duty_time_range"
|
||
DEFAULT_SHIFT_TIMES = {
|
||
SHIFT_MORNING: ("08:00", "18:00", 0),
|
||
SHIFT_EVENING: ("18:00", "07:00", 1),
|
||
}
|
||
# 预置时段 dict_value:start|end|cross_day
|
||
TIME_RANGE_DAY = "08:00|18:00|0"
|
||
TIME_RANGE_NIGHT = "18:00|07:00|1"
|
||
LINK_OPEN = "open"
|
||
LINK_CLOSED = "closed"
|
||
SOURCE_ASSIGN = "assign"
|
||
SOURCE_GRAB = "grab"
|
||
# 可排班名单角色(sys_role 固定 id;无菜单,仅标签)
|
||
DUTY_STAFF_ROLE_ID = "R65CAAE057914CCCAE2A81BE627A5101"
|
||
DUTY_STAFF_ROLE_NAME = "值班人员"
|
||
|
||
|
||
class DutyDay(Base):
|
||
__tablename__ = "duty_day"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
|
||
duty_date = Column(Date, nullable=False, comment="值班日期")
|
||
access_token = Column(String(64), nullable=False, comment="公开访问令牌")
|
||
link_status = Column(String(16), nullable=False, default=LINK_OPEN, comment="open/closed")
|
||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||
remark = Column(String(500), nullable=True, comment="备注")
|
||
create_by = Column(String(64), nullable=True, comment="创建者")
|
||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
|
||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||
update_by = Column(String(64), nullable=True, comment="更新者")
|
||
update_time = Column(
|
||
DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间"
|
||
)
|
||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标志")
|
||
|
||
|
||
class DutySlot(Base):
|
||
__tablename__ = "duty_slot"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
|
||
duty_day_id = Column(String(64), nullable=False, comment="值班日ID")
|
||
shift_type = Column(String(32), nullable=False, comment="morning/evening/duty")
|
||
capacity = Column(Integer, nullable=False, default=1, comment="名额")
|
||
work_plans = Column(String(500), nullable=True, comment="工作安排dict_value逗号分隔")
|
||
start_time = Column(Time, nullable=True, comment="值班开始时间")
|
||
end_time = Column(Time, nullable=True, comment="值班结束时间")
|
||
cross_day = Column(SmallInteger, nullable=False, default=0, comment="结束是否次日")
|
||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||
remark = Column(String(500), nullable=True, comment="备注")
|
||
create_by = Column(String(64), nullable=True, comment="创建者")
|
||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
|
||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||
update_by = Column(String(64), nullable=True, comment="更新者")
|
||
update_time = Column(
|
||
DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间"
|
||
)
|
||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标志")
|
||
|
||
|
||
class DutyAssignment(Base):
|
||
__tablename__ = "duty_assignment"
|
||
|
||
id = Column(String(64), primary_key=True, comment="主键ID(UUID)")
|
||
duty_slot_id = Column(String(64), nullable=False, comment="班次名额ID")
|
||
source = Column(String(16), nullable=False, comment="assign/grab")
|
||
user_id = Column(String(64), nullable=True, comment="系统用户ID(指定时)")
|
||
person_name = Column(String(64), nullable=False, comment="展示姓名")
|
||
tenant_no = Column(String(64), nullable=False, default="shanxia2.0", comment="租户编号")
|
||
order_num = Column(Integer, nullable=True, comment="排序号")
|
||
remark = Column(String(500), nullable=True, comment="备注")
|
||
create_by = Column(String(64), nullable=True, comment="创建者")
|
||
create_dept_id = Column(String(64), nullable=False, default="", comment="创建部门")
|
||
create_time = Column(DateTime, nullable=False, default=datetime.now, comment="创建时间")
|
||
update_by = Column(String(64), nullable=True, comment="更新者")
|
||
update_time = Column(
|
||
DateTime, nullable=False, default=datetime.now, onupdate=datetime.now, comment="更新时间"
|
||
)
|
||
del_flag = Column(SmallInteger, nullable=False, default=0, comment="删除标志")
|