Files
zlwuandCursor b9ff9c9d67 feat(duty): make duty time range a single-select dict like work plans
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>
2026-08-20 21:58:18 +08:00

98 lines
4.8 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""值班排班模型 — 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="删除标志")