51 lines
2.3 KiB
Python
51 lines
2.3 KiB
Python
"""Закрепление оборудования за отделами: кто какое оборудование видит.
|
|
|
|
Администратор и модератор видят всё. Сотрудник без отдела — тоже всё. Сотрудник отдела видит оборудование своего отдела
|
|
и вложенных в него отделов, а также оборудование, не закреплённое ни за каким отделом. Так крановый электрик
|
|
не получает списков, карты и уведомлений по станкам, если станки закреплены за другим отделом."""
|
|
from sqlalchemy import or_, select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from . import settings_store as ss
|
|
from .models import Department, Equipment, User
|
|
|
|
|
|
def dept_tree(db: Session, root: int) -> set[int]:
|
|
"""Отдел и все вложенные в него отделы."""
|
|
children: dict[int | None, list[int]] = {}
|
|
for i, p in db.execute(select(Department.id, Department.parent_id)):
|
|
children.setdefault(p, []).append(i)
|
|
out, stack = set(), [root]
|
|
while stack:
|
|
x = stack.pop()
|
|
if x in out:
|
|
continue
|
|
out.add(x)
|
|
stack.extend(children.get(x, []))
|
|
return out
|
|
|
|
|
|
def sees_all(u: User) -> bool:
|
|
return bool(u.is_admin or u.is_moderator or not u.department_id)
|
|
|
|
|
|
def equipment_filter(db: Session, u: User):
|
|
"""Условие SQL для выборки оборудования пользователя или None — без ограничений."""
|
|
if sees_all(u):
|
|
return None
|
|
return or_(Equipment.department_id.is_(None), Equipment.department_id.in_(dept_tree(db, u.department_id)))
|
|
|
|
|
|
def equipment_ids(db: Session, u: User) -> set[int] | None:
|
|
"""id видимого оборудования или None — видит всё."""
|
|
cond = equipment_filter(db, u)
|
|
return None if cond is None else set(db.scalars(select(Equipment.id).where(cond)))
|
|
|
|
|
|
def user_sees(db: Session, u: User, eq: Equipment) -> bool:
|
|
return sees_all(u) or eq.department_id is None or eq.department_id in dept_tree(db, u.department_id)
|
|
|
|
|
|
def crane_map_enabled(db: Session) -> bool:
|
|
return ss.get(db, "crane_map") == "1"
|