fix: 修复多处边界条件问题

- rooms: parseRoomNumber 未知格式返回默认 capacity=4,防止 undefined 绕过入住容量检查
- rooms: 修复 parseInt() || undefined 导致楼层 0 被吞掉
- rooms: batchImport 中 capacity 使用 ?? 代替 ||,显式 0 不被覆盖
- occupancies: 所有 capacity 比较加 ?? 0 防守兜底,fail closed
- schedules: assertValidScheduleRange 增加 startTime > endTime 校验
- attendance: 时段重叠检查改为按 startTime 排序后再比较,消除漏检
- attendance: 移除 getScheduleOptionsForAttendance 中不可靠的 raw[index] fallback
- expenses: 个人附加费批量导入增加 assertPositiveAmount 校验
- expenses: 水电费导入增加 periodEnd >= periodStart 校验
This commit is contained in:
2026-07-20 14:45:53 +08:00
parent 990c0c16e6
commit 00e9c5e45a
6 changed files with 43 additions and 21 deletions

View File

@@ -82,7 +82,7 @@ export class OccupanciesService {
const count = await manager.count(Occupancy, {
where: { roomId: dto.roomId, checkOutDate: IsNull() },
});
if (count >= room.capacity) throw new BadRequestException('宿舍已满');
if (count >= (room.capacity ?? 0)) throw new BadRequestException('宿舍已满');
const student = await manager.findOne(Student, { where: { id: dto.studentId } });
if (!student) throw new NotFoundException('学生不存在');
@@ -124,8 +124,7 @@ export class OccupanciesService {
);
if (dto.bedId) await manager.update(Bed, dto.bedId, { status: 'occupied' });
if (dto.lockerId) await manager.update(Locker, dto.lockerId, { status: 'occupied' });
if (count + 1 >= room.capacity) await manager.update(Room, room.id, { status: 'full' });
if (count + 1 >= (room.capacity ?? 0)) await manager.update(Room, room.id, { status: 'full' });
if (dto.collectDeposit) {
let deposit = await manager.findOne(Deposit, { where: { studentId: dto.studentId } });
if (deposit) {
@@ -225,7 +224,7 @@ export class OccupanciesService {
const count = await runner.manager.count(Occupancy, {
where: { roomId: dto.newRoomId, checkOutDate: IsNull() },
});
if (count >= newRoom.capacity) throw new BadRequestException('目标宿舍已满');
if (count >= (newRoom.capacity ?? 0)) throw new BadRequestException('目标宿舍已满');
// 新床位校验
if (dto.newBedId) {
@@ -286,7 +285,7 @@ export class OccupanciesService {
await runner.manager.update(Locker, dto.newLockerId, { status: 'occupied' });
}
if (count + 1 >= newRoom.capacity) {
if (count + 1 >= (newRoom.capacity ?? 0)) {
await runner.manager.update(Room, newRoom.id, { status: 'full' });
}
@@ -556,9 +555,9 @@ export class OccupanciesService {
// 4. 检查宿舍容量
const count = await occupancyRepo.count({ where: { roomId: room.id, checkOutDate: IsNull() } });
if (!isHistoricalRecord && count >= room.capacity) {
if (!isHistoricalRecord && count >= (room.capacity ?? 0)) {
throw new ImportRowSkipped(
`${rowNum}行: 宿舍 ${row.roomNumber} 已满(${count}/${room.capacity}),跳过 ${row.name}`,
`${rowNum}行: 宿舍 ${row.roomNumber} 已满(${count}/${room.capacity ?? '?'}),跳过 ${row.name}`,
);
}
@@ -569,9 +568,9 @@ export class OccupanciesService {
bed = await bedRepo.findOne({ where: { roomId: room.id, bedNumber } });
if (!bed) {
const existingBedCount = await bedRepo.count({ where: { roomId: room.id } });
if (existingBedCount >= room.capacity) {
if (existingBedCount >= (room.capacity ?? 0)) {
throw new BadRequestException(
`宿舍 ${room.roomNumber} 已有 ${existingBedCount} 张床位,不能超过额定人数 ${room.capacity}`,
`宿舍 ${room.roomNumber} 已有 ${existingBedCount} 张床位,不能超过额定人数 ${room.capacity ?? '?'}`,
);
}
bed = await bedRepo.save(
@@ -620,7 +619,7 @@ export class OccupanciesService {
if (!isHistoricalRecord) {
if (bed) await bedRepo.update(bed.id, { status: 'occupied' });
if (locker) await lockerRepo.update(locker.id, { status: 'occupied' });
if (count + 1 >= room.capacity) {
if (count + 1 >= (room.capacity ?? 0)) {
await roomRepo.update(room.id, { status: 'full' });
}
}