import { BadRequestException, Injectable } from '@nestjs/common'; import { BaseCrudService } from '../common/base-crud.service.js'; import { PrismaService } from '../prisma/prisma.service.js'; import { getRequestContext } from '../common/context/request-context.js'; import { CreateOrgDto, UpdateOrgDto } from './dto.js'; @Injectable() export class OrgsService extends BaseCrudService { constructor(prisma: PrismaService) { super(prisma, 'org'); } /** 组织树列表:按数据权限过滤(空 orgCodes=全部可见)。 */ listOrgs() { const ctx = getRequestContext(); const where: Record = {}; if (ctx && ctx.orgCodes.length > 0) { where.code = { in: ctx.orgCodes }; } return this.list(where, { sort: 'asc' }); } async createOrg(dto: CreateOrgDto) { await this.assertValidParent(dto.parentCode); return this.create({ ...dto }); } async updateOrg(id: string, dto: UpdateOrgDto) { if (dto.parentCode !== undefined) { const current = await this.findById(id); await this.assertValidParent(dto.parentCode, current?.code); } return this.update(id, { ...dto }); } /** 批量删除组织(软删 + 回收 code),收集失败项。 */ async batchDelete(ids: string[]) { const failed: string[] = []; for (const id of ids) { try { await this.softRemove(id); } catch { failed.push(id); } } return { total: ids.length, success: ids.length - failed.length, failed }; } /** 校验父组织存在,且不会构成环(父不能是自身或自身后代)。 */ private async assertValidParent(parentCode: string | null | undefined, selfCode?: string): Promise { if (!parentCode) return; // 根节点 const parent = await this.db().findFirst({ where: { code: parentCode } }); if (!parent) throw new BadRequestException('父组织不存在'); if (!selfCode) return; let cur: string | null = parentCode; const visited = new Set(); while (cur && !visited.has(cur)) { if (cur === selfCode) throw new BadRequestException('不能将组织挂到自身或其子组织下'); visited.add(cur); const node: { parentCode: string | null } | null = await this.db().findFirst({ where: { code: cur }, select: { parentCode: true }, }); cur = node?.parentCode ?? null; } } }