import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Not, Repository } from 'typeorm'; import { uuidV7 } from '../common/uuid-v7'; import { Organization } from '../entities/organization.entity'; import { CreateOrganizationDto, UpdateOrganizationDto } from './dto/organization.dto'; const COLOR_PALETTE = [ '#ff7875', '#ffa940', '#ffc53d', '#73d13d', '#36cfc9', '#40a9ff', '#597ef7', '#9254de', '#f759ab', '#8c8c8c', ]; @Injectable() export class OrganizationsService { constructor(@InjectRepository(Organization) private repo: Repository) {} async findAll(query?: { includeArchived?: boolean; scope?: 'all' | 'host' | 'external' }) { const where: Record = {}; if (!query?.includeArchived) where.status = Not('archived'); if (query?.scope === 'host') where.isHost = true; if (query?.scope === 'external') where.isHost = false; return this.repo.find({ where, order: { isHost: 'DESC', name: 'ASC' } }); } async findOptions() { return this.repo.find({ select: ['id', 'name', 'isHost'] as const, where: { status: 'active' }, order: { isHost: 'DESC' as const, name: 'ASC' as const }, }); } async findOne(id: number) { const organization = await this.repo.findOne({ where: { id } }); if (!organization) throw new NotFoundException('机构不存在'); return organization; } async getHostOrganization() { const organization = await this.repo.findOne({ where: { isHost: true, status: 'active' } }); if (!organization) throw new NotFoundException('尚未配置本机构'); return organization; } async create(dto: CreateOrganizationDto) { if (dto.isHost) { const existingHost = await this.repo.findOne({ where: { isHost: true } }); if (existingHost) throw new BadRequestException('本机构已存在,只能配置一个本机构'); } const color = dto.color || COLOR_PALETTE[(await this.repo.count()) % COLOR_PALETTE.length]; return this.repo.save( this.repo.create({ ...dto, code: dto.code.trim().toUpperCase(), publicId: uuidV7(), color, isHost: dto.isHost ?? false, status: 'active', }), ); } async update(id: number, dto: UpdateOrganizationDto) { const organization = await this.findOne(id); if (organization.isHost && dto.status === 'archived') { throw new BadRequestException('本机构不能归档'); } await this.repo.update(id, { ...dto, ...(dto.code ? { code: dto.code.trim().toUpperCase() } : {}), }); return this.repo.findOne({ where: { id } }); } async remove(id: number) { const organization = await this.findOne(id); if (organization.isHost) throw new BadRequestException('本机构不能归档'); await this.repo.update(id, { status: 'archived' }); return { message: '已归档' }; } }