90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
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<Organization>) {}
|
|
|
|
async findAll(query?: { includeArchived?: boolean; scope?: 'all' | 'host' | 'external' }) {
|
|
const where: Record<string, unknown> = {};
|
|
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: '已归档' };
|
|
}
|
|
}
|