|
|
@@ -6,11 +6,14 @@ import secrets
|
|
|
from datetime import date, datetime
|
|
|
from typing import Any, Dict, List, Optional, Sequence
|
|
|
|
|
|
+from sqlalchemy import and_
|
|
|
from sqlalchemy.orm import Session
|
|
|
|
|
|
from app.core.config import settings
|
|
|
from app.core.utils import generate_id
|
|
|
from app.models.duty_models import (
|
|
|
+ DUTY_STAFF_ROLE_ID,
|
|
|
+ DUTY_STAFF_ROLE_NAME,
|
|
|
LINK_CLOSED,
|
|
|
LINK_OPEN,
|
|
|
SHIFT_LABELS,
|
|
|
@@ -20,7 +23,7 @@ from app.models.duty_models import (
|
|
|
DutyDay,
|
|
|
DutySlot,
|
|
|
)
|
|
|
-from app.models.models import SysUser
|
|
|
+from app.models.models import SysRole, SysUser, SysUserRole
|
|
|
from app.schemas.duty import DutyDaySaveBody, DutySlotSaveIn
|
|
|
|
|
|
PERSON_NAME_MAX_LEN = 20
|
|
|
@@ -348,6 +351,8 @@ def save_day(
|
|
|
# 若只有 userId,允许 personName 已由上层填好
|
|
|
if not person_name:
|
|
|
raise DutyBizError("指定员工姓名不能为空")
|
|
|
+ if item.source == SOURCE_ASSIGN and uid:
|
|
|
+ assert_user_is_duty_staff(db, tenant_no, uid)
|
|
|
db.add(
|
|
|
DutyAssignment(
|
|
|
id=generate_id(),
|
|
|
@@ -375,9 +380,48 @@ def save_day(
|
|
|
return _serialize_day(db, day)
|
|
|
|
|
|
|
|
|
-def _list_public_users(db: Session, tenant_no: str) -> List[Dict[str, str]]:
|
|
|
+def resolve_duty_staff_role_id(db: Session, tenant_no: str) -> Optional[str]:
|
|
|
+ """按固定 id 查找「值班人员」角色;找不到再按角色名兜底。"""
|
|
|
+ role = (
|
|
|
+ db.query(SysRole)
|
|
|
+ .filter(
|
|
|
+ SysRole.id == DUTY_STAFF_ROLE_ID,
|
|
|
+ SysRole.tenant_no == tenant_no,
|
|
|
+ SysRole.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if role:
|
|
|
+ return role.id
|
|
|
+ role = (
|
|
|
+ db.query(SysRole)
|
|
|
+ .filter(
|
|
|
+ SysRole.role_name == DUTY_STAFF_ROLE_NAME,
|
|
|
+ SysRole.tenant_no == tenant_no,
|
|
|
+ SysRole.del_flag == 0,
|
|
|
+ SysRole.status == "1",
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ return role.id if role else None
|
|
|
+
|
|
|
+
|
|
|
+def list_duty_staff_users(db: Session, tenant_no: str) -> List[Dict[str, str]]:
|
|
|
+ """本租户启用且绑定「值班人员」角色的用户(公开页 users / 管理端 options)。"""
|
|
|
+ role_id = resolve_duty_staff_role_id(db, tenant_no)
|
|
|
+ if not role_id:
|
|
|
+ return []
|
|
|
rows = (
|
|
|
db.query(SysUser)
|
|
|
+ .join(
|
|
|
+ SysUserRole,
|
|
|
+ and_(
|
|
|
+ SysUserRole.user_id == SysUser.id,
|
|
|
+ SysUserRole.role_id == role_id,
|
|
|
+ SysUserRole.del_flag == 0,
|
|
|
+ SysUserRole.tenant_no == tenant_no,
|
|
|
+ ),
|
|
|
+ )
|
|
|
.filter(
|
|
|
SysUser.tenant_no == tenant_no,
|
|
|
SysUser.del_flag == 0,
|
|
|
@@ -387,7 +431,11 @@ def _list_public_users(db: Session, tenant_no: str) -> List[Dict[str, str]]:
|
|
|
.all()
|
|
|
)
|
|
|
out: List[Dict[str, str]] = []
|
|
|
+ seen = set()
|
|
|
for r in rows:
|
|
|
+ if r.id in seen:
|
|
|
+ continue
|
|
|
+ seen.add(r.id)
|
|
|
label = (r.nick_name or "").strip() or (r.user_no or "").strip()
|
|
|
if not label:
|
|
|
continue
|
|
|
@@ -395,6 +443,28 @@ def _list_public_users(db: Session, tenant_no: str) -> List[Dict[str, str]]:
|
|
|
return out
|
|
|
|
|
|
|
|
|
+def assert_user_is_duty_staff(db: Session, tenant_no: str, user_id: str) -> None:
|
|
|
+ role_id = resolve_duty_staff_role_id(db, tenant_no)
|
|
|
+ if not role_id:
|
|
|
+ raise DutyBizError("未配置「值班人员」角色,请联系管理员")
|
|
|
+ link = (
|
|
|
+ db.query(SysUserRole)
|
|
|
+ .filter(
|
|
|
+ SysUserRole.user_id == user_id,
|
|
|
+ SysUserRole.role_id == role_id,
|
|
|
+ SysUserRole.tenant_no == tenant_no,
|
|
|
+ SysUserRole.del_flag == 0,
|
|
|
+ )
|
|
|
+ .first()
|
|
|
+ )
|
|
|
+ if not link:
|
|
|
+ raise DutyBizError("仅可选择「值班人员」角色的用户")
|
|
|
+
|
|
|
+
|
|
|
+def _list_public_users(db: Session, tenant_no: str) -> List[Dict[str, str]]:
|
|
|
+ return list_duty_staff_users(db, tenant_no)
|
|
|
+
|
|
|
+
|
|
|
def _resolve_grab_user(db: Session, tenant_no: str, user_id: str) -> SysUser:
|
|
|
uid = (user_id or "").strip()
|
|
|
if not uid:
|
|
|
@@ -411,6 +481,7 @@ def _resolve_grab_user(db: Session, tenant_no: str, user_id: str) -> SysUser:
|
|
|
)
|
|
|
if not user:
|
|
|
raise DutyBizError("用户无效或不存在")
|
|
|
+ assert_user_is_duty_staff(db, tenant_no, user.id)
|
|
|
return user
|
|
|
|
|
|
|
|
|
@@ -525,4 +596,7 @@ __all__ = [
|
|
|
"soft_delete_assignment",
|
|
|
"get_public_page",
|
|
|
"grab",
|
|
|
+ "resolve_duty_staff_role_id",
|
|
|
+ "list_duty_staff_users",
|
|
|
+ "assert_user_is_duty_staff",
|
|
|
]
|