feat: add Bed and Locker CRUD to RoomsService

This commit is contained in:
2026-07-09 11:55:37 +08:00
parent 87a3f0c554
commit 12fa2e974f
2 changed files with 127 additions and 2 deletions

View File

@@ -3,13 +3,15 @@ import { TypeOrmModule } from '@nestjs/typeorm';
import { Room } from '../entities/room.entity';
import { Occupancy } from '../entities/occupancy.entity';
import { RoomExpense } from '../entities/room-expense.entity';
import { Bed } from '../entities/bed.entity';
import { Locker } from '../entities/locker.entity';
import { RoomsService } from './rooms.service';
import { RoomsController } from './rooms.controller';
import { OperationLogsModule } from '../operation-logs/operation-logs.module';
import { CommonModule } from '../common/common.module';
@Module({
imports: [TypeOrmModule.forFeature([Room, Occupancy, RoomExpense]), OperationLogsModule, CommonModule],
imports: [TypeOrmModule.forFeature([Room, Occupancy, RoomExpense, Bed, Locker]), OperationLogsModule, CommonModule],
controllers: [RoomsController],
providers: [RoomsService],
exports: [RoomsService],

View File

@@ -5,7 +5,11 @@ import { CampusScope } from '../common/campus-scope';
import { Room } from '../entities/room.entity';
import { Occupancy } from '../entities/occupancy.entity';
import { RoomExpense } from '../entities/room-expense.entity';
import { Bed } from '../entities/bed.entity';
import { Locker } from '../entities/locker.entity';
import { CreateRoomDto, UpdateRoomDto } from './dto/room.dto';
import { CreateBedDto, UpdateBedDto, BatchCreateBedDto } from './dto/bed.dto';
import { CreateLockerDto, UpdateLockerDto, BatchCreateLockerDto } from './dto/locker.dto';
@Injectable()
export class RoomsService {
@@ -13,7 +17,8 @@ export class RoomsService {
@InjectRepository(Room) private repo: Repository<Room>,
@InjectRepository(Occupancy) private occRepo: Repository<Occupancy>,
@InjectRepository(RoomExpense) private roomExpRepo: Repository<RoomExpense>,
private readonly scope: CampusScope,
@InjectRepository(Bed) private bedRepo: Repository<Bed>,
@InjectRepository(Locker) private lockerRepo: Repository<Locker>,
) {}
/**
@@ -320,4 +325,122 @@ export class RoomsService {
skipped,
};
}
// ── 床位管理 ──
async getRoomBeds(roomId: number): Promise<Bed[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
return this.bedRepo.find({ where: { roomId }, order: { bedNumber: 'ASC' } });
}
async getRoomAvailableBeds(roomId: number): Promise<Bed[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
return this.bedRepo.find({ where: { roomId, status: 'available' }, order: { bedNumber: 'ASC' } });
}
async createBed(roomId: number, dto: CreateBedDto): Promise<Bed> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
if (room.status === 'archived') throw new BadRequestException('已归档宿舍不能添加床位');
const existing = await this.bedRepo.findOne({ where: { roomId, bedNumber: dto.bedNumber } });
if (existing) throw new BadRequestException('该床位编号已存在');
const bed = this.bedRepo.create({ ...dto, roomId });
return this.bedRepo.save(bed);
}
async updateBed(roomId: number, id: number, dto: UpdateBedDto): Promise<Bed> {
const bed = await this.bedRepo.findOne({ where: { id, roomId } });
if (!bed) throw new NotFoundException('床位不存在');
// 不允许将 occupied 的床位改为 maintenance
if (dto.status === 'maintenance' && bed.status === 'occupied') {
throw new BadRequestException('该床位有人入住,请先退宿');
}
// 编号唯一性检查
if (dto.bedNumber && dto.bedNumber !== bed.bedNumber) {
const dup = await this.bedRepo.findOne({ where: { roomId, bedNumber: dto.bedNumber } });
if (dup) throw new BadRequestException('该床位编号已存在');
}
Object.assign(bed, dto);
return this.bedRepo.save(bed);
}
async deleteBed(roomId: number, id: number): Promise<void> {
const bed = await this.bedRepo.findOne({ where: { id, roomId } });
if (!bed) throw new NotFoundException('床位不存在');
if (bed.status === 'occupied') throw new BadRequestException('该床位有人入住,无法删除');
await this.bedRepo.remove(bed);
}
async batchCreateBeds(roomId: number, dto: BatchCreateBedDto): Promise<Bed[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
if (room.status === 'archived') throw new BadRequestException('已归档宿舍不能添加床位');
const existing = await this.bedRepo.count({ where: { roomId } });
const start = existing + 1;
const beds: Bed[] = [];
for (let i = 0; i < dto.count; i++) {
beds.push(this.bedRepo.create({ roomId, bedNumber: `${start + i}号床` }));
}
return this.bedRepo.save(beds);
}
// ── 柜子管理 ──
async getRoomLockers(roomId: number): Promise<Locker[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
return this.lockerRepo.find({ where: { roomId }, order: { lockerNumber: 'ASC' } });
}
async getRoomAvailableLockers(roomId: number): Promise<Locker[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
return this.lockerRepo.find({ where: { roomId, status: 'available' }, order: { lockerNumber: 'ASC' } });
}
async createLocker(roomId: number, dto: CreateLockerDto): Promise<Locker> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
if (room.status === 'archived') throw new BadRequestException('已归档宿舍不能添加柜子');
const existing = await this.lockerRepo.findOne({ where: { roomId, lockerNumber: dto.lockerNumber } });
if (existing) throw new BadRequestException('该柜子编号已存在');
const locker = this.lockerRepo.create({ ...dto, roomId });
return this.lockerRepo.save(locker);
}
async updateLocker(roomId: number, id: number, dto: UpdateLockerDto): Promise<Locker> {
const locker = await this.lockerRepo.findOne({ where: { id, roomId } });
if (!locker) throw new NotFoundException('柜子不存在');
if (dto.status === 'maintenance' && locker.status === 'occupied') {
throw new BadRequestException('该柜子有人占用,请先释放');
}
if (dto.lockerNumber && dto.lockerNumber !== locker.lockerNumber) {
const dup = await this.lockerRepo.findOne({ where: { roomId, lockerNumber: dto.lockerNumber } });
if (dup) throw new BadRequestException('该柜子编号已存在');
}
Object.assign(locker, dto);
return this.lockerRepo.save(locker);
}
async deleteLocker(roomId: number, id: number): Promise<void> {
const locker = await this.lockerRepo.findOne({ where: { id, roomId } });
if (!locker) throw new NotFoundException('柜子不存在');
if (locker.status === 'occupied') throw new BadRequestException('该柜子有人占用,无法删除');
await this.lockerRepo.remove(locker);
}
async batchCreateLockers(roomId: number, dto: BatchCreateLockerDto): Promise<Locker[]> {
const room = await this.repo.findOne({ where: { id: roomId } });
if (!room) throw new NotFoundException('宿舍不存在');
if (room.status === 'archived') throw new BadRequestException('已归档宿舍不能添加柜子');
const existing = await this.lockerRepo.count({ where: { roomId } });
const start = existing + 1;
const lockers: Locker[] = [];
for (let i = 0; i < dto.count; i++) {
lockers.push(this.lockerRepo.create({ roomId, lockerNumber: `${start + i}号柜` }));
}
return this.lockerRepo.save(lockers);
}
}