Files
loom/backend/app/services/org_service.py
T
2026-04-24 17:46:03 +08:00

77 lines
2.5 KiB
Python

"""组织架构:CRUD + 树构建。"""
from __future__ import annotations
from fastapi import status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.exceptions import AppError
from app.models import Organization
from app.schemas.organization import OrgCreate, OrgTreeNode, OrgUpdate
async def list_all(db: AsyncSession) -> list[Organization]:
res = await db.execute(select(Organization).order_by(Organization.sort, Organization.id))
return list(res.scalars().all())
async def get(db: AsyncSession, oid: int) -> Organization:
org = await db.get(Organization, oid)
if org is None:
raise AppError("组织不存在", code=404, http_status=status.HTTP_404_NOT_FOUND)
return org
async def create(db: AsyncSession, data: OrgCreate) -> Organization:
exists = await db.execute(select(Organization).where(Organization.code == data.code))
if exists.scalar_one_or_none():
raise AppError("code 已存在", code=409, http_status=status.HTTP_409_CONFLICT)
org = Organization(**data.model_dump())
db.add(org)
await db.commit()
await db.refresh(org)
return org
async def update(db: AsyncSession, oid: int, data: OrgUpdate) -> Organization:
org = await get(db, oid)
for k, v in data.model_dump(exclude_unset=True).items():
setattr(org, k, v)
await db.commit()
await db.refresh(org)
return org
async def delete(db: AsyncSession, oid: int) -> None:
org = await get(db, oid)
# 不允许删除有子节点的组织
res = await db.execute(select(Organization.id).where(Organization.parent_id == oid))
if res.first():
raise AppError("存在子组织,无法删除", code=409, http_status=status.HTTP_409_CONFLICT)
await db.delete(org)
await db.commit()
def build_tree(items: list[Organization]) -> list[OrgTreeNode]:
nodes: dict[int, OrgTreeNode] = {}
for o in items:
nodes[o.id] = OrgTreeNode(
id=o.id, parent_id=o.parent_id, name=o.name, code=o.code,
type=o.type, sort=o.sort, description=o.description,
)
roots: list[OrgTreeNode] = []
for o in items:
n = nodes[o.id]
if o.parent_id and o.parent_id in nodes:
nodes[o.parent_id].children.append(n)
else:
roots.append(n)
def _sort(lst: list[OrgTreeNode]) -> None:
lst.sort(key=lambda x: (x.sort, x.id))
for it in lst:
_sort(it.children)
_sort(roots)
return roots