"""组织树查询与祖先保留。""" from __future__ import annotations from sqlalchemy import select from dms.common.enums import EnabledStatus from dms.common.errors import InvalidArgumentError from dms.common.response import serialize_id from dms.extensions import db from dms.models import Organization def organization_tree( *, keyword: str | None, status: str | None ) -> list[dict[str, object]]: organizations = db.session.scalars( select(Organization) .where(Organization.is_deleted.is_(False)) .order_by(Organization.sort_no.asc(), Organization.id.asc()) ).all() by_id = {item.id: item for item in organizations} if status: try: normalized_status = EnabledStatus(status).value except ValueError as exc: raise InvalidArgumentError("status必须是ENABLED或DISABLED") from exc else: normalized_status = EnabledStatus.ENABLED.value base_ids = {item.id for item in organizations if item.status == normalized_status} if keyword and keyword.strip(): needle = keyword.strip().casefold() base_ids = { item.id for item in organizations if item.id in base_ids and (needle in item.org_name.casefold() or needle in item.org_code.casefold()) } included_ids = set(base_ids) for item_id in tuple(base_ids): parent_id = by_id[item_id].parent_id while parent_id is not None and parent_id in by_id: included_ids.add(parent_id) parent_id = by_id[parent_id].parent_id nodes = { item.id: { "id": serialize_id(item.id), "parentId": serialize_id(item.parent_id), "orgCode": item.org_code, "orgName": item.org_name, "orgPath": item.org_path, "sortNo": item.sort_no, "status": item.status, "children": [], } for item in organizations if item.id in included_ids } roots: list[dict[str, object]] = [] for item in organizations: if item.id not in nodes: continue node = nodes[item.id] if item.parent_id in nodes: nodes[item.parent_id]["children"].append(node) else: roots.append(node) return roots