import { Injectable, NotFoundException, BadRequestException } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository, Not } from 'typeorm'; import { Classroom } from '../entities/classroom.entity'; import { ClassroomRental } from '../entities/classroom-rental.entity'; import { CreateClassroomDto, UpdateClassroomDto } from './dto/classroom.dto'; @Injectable() export class ClassroomsService { constructor( @InjectRepository(Classroom) private repo: Repository, @InjectRepository(ClassroomRental) private rentalRepo: Repository, ) {} async findAll(query?: { building?: string; roomType?: string; includeArchived?: boolean }) { const where: any = {}; if (query?.building) where.building = query.building; if (query?.roomType) where.roomType = query.roomType; if (!query?.includeArchived) where.status = Not('archived'); return this.repo.find({ where, order: { building: 'ASC', name: 'ASC' } }); } async findOne(id: number) { const cls = await this.repo.findOne({ where: { id } }); if (!cls) throw new NotFoundException('教室不存在'); return cls; } async create(dto: CreateClassroomDto) { const exists = await this.repo.findOne({ where: { name: dto.name } }); if (exists) throw new BadRequestException(`教室 ${dto.name} 已存在`); return this.repo.save(this.repo.create(dto)); } async update(id: number, dto: UpdateClassroomDto) { await this.findOne(id); await this.repo.update(id, dto); return this.repo.findOne({ where: { id } }); } async remove(id: number) { await this.findOne(id); // 若存在未结束的租赁订单,不允许归档 const active = await this.rentalRepo.count({ where: { classroomId: id, status: 'active' } }); if (active > 0) throw new BadRequestException('该教室存在进行中的租赁订单,无法归档'); await this.repo.update(id, { status: 'archived' }); return { message: '已归档' }; } async restore(id: number) { const cls = await this.findOne(id); if (cls.status !== 'archived') throw new BadRequestException('该教室未被归档'); await this.repo.update(id, { status: 'available' }); return { message: '已恢复' }; } async batchImport(rows: { name: string; building?: string; floor?: number; capacity?: number; roomType?: string; courseType?: string; supervisor?: string }[]) { let imported = 0; let skipped = 0; for (const row of rows) { if (!row.name || !row.name.trim()) { skipped++; continue; } const name = row.name.trim(); const exists = await this.repo.findOne({ where: { name } }); if (exists) { skipped++; continue; } await this.repo.save(this.repo.create({ name, building: row.building?.trim() || undefined, floor: row.floor || undefined, capacity: row.capacity || 30, roomType: row.roomType?.trim() || '大', courseType: row.courseType?.trim() || undefined, supervisor: row.supervisor?.trim() || undefined, })); imported++; } return { message: `成功导入 ${imported} 间教室,跳过 ${skipped} 条(重复或空行)`, imported, skipped }; } }