feat: improve occupancy import template

This commit is contained in:
2026-07-14 11:20:27 +08:00
parent 811e7ce826
commit 5cf6aede1e
8 changed files with 415 additions and 110 deletions

View File

@@ -341,7 +341,12 @@ export class OccupanciesService {
roomNumber: string;
building?: string;
checkInDate: string;
billingStartDate?: string;
checkOutDate?: string;
bedNumber?: string;
lockerNumber?: string;
stayType?: string;
notes?: string;
}[],
options?: { autoDeposit?: boolean; depositAmount?: number },
) {
@@ -450,14 +455,54 @@ export class OccupanciesService {
continue;
}
// 5. 匹配或创建床位、柜子,并校验是否可用
const isHistoricalRecord = Boolean(row.checkOutDate?.trim());
let bed: Bed | null = null;
if (row.bedNumber?.trim()) {
const bedNumber = row.bedNumber.trim();
bed = await this.bedRepo.findOne({ where: { roomId: room.id, bedNumber } });
if (!bed) {
const existingBedCount = await this.bedRepo.count({ where: { roomId: room.id } });
if (existingBedCount >= room.capacity) {
throw new BadRequestException(
`宿舍 ${room.roomNumber} 已有 ${existingBedCount} 张床位,不能超过额定人数 ${room.capacity}`,
);
}
bed = await this.bedRepo.save(
this.bedRepo.create({ roomId: room.id, bedNumber, status: 'available' }),
);
}
if (!isHistoricalRecord && bed.status !== 'available') {
throw new BadRequestException(`床位 ${bedNumber} 已被占用或维修中`);
}
}
let locker: Locker | null = null;
if (row.lockerNumber?.trim()) {
const lockerNumber = row.lockerNumber.trim();
locker = await this.lockerRepo.findOne({ where: { roomId: room.id, lockerNumber } });
if (!locker) {
locker = await this.lockerRepo.save(
this.lockerRepo.create({ roomId: room.id, lockerNumber, status: 'available' }),
);
}
if (!isHistoricalRecord && locker.status !== 'available') {
throw new BadRequestException(`柜子 ${lockerNumber} 已被占用或维修中`);
}
}
// 6. 创建入住记录
const checkInDate = row.checkInDate?.trim() || new Date().toISOString().split('T')[0];
const occData: any = {
studentId: student.id,
roomId: room.id,
checkInDate,
billingStartDate: checkInDate,
billingStartDate: row.billingStartDate?.trim() || checkInDate,
stayType: row.stayType || undefined,
responsibleOrganizationId: student.organizationId || organization.id,
notes: row.notes || undefined,
bedId: bed?.id,
lockerId: locker?.id,
};
// 如果有退宿日期,直接记录
if (row.checkOutDate?.trim()) {
@@ -466,9 +511,13 @@ export class OccupanciesService {
}
await this.repo.save(this.repo.create(occData));
// 8. 更新宿舍状态
if (!row.checkOutDate?.trim() && count + 1 >= room.capacity) {
await this.roomRepo.update(room.id, { status: 'full' });
// 7. 更新床位、柜子和宿舍状态
if (!isHistoricalRecord) {
if (bed) await this.bedRepo.update(bed.id, { status: 'occupied' });
if (locker) await this.lockerRepo.update(locker.id, { status: 'occupied' });
if (count + 1 >= room.capacity) {
await this.roomRepo.update(room.id, { status: 'full' });
}
}
// 9. 自动收取押金(仅对新入住且非历史记录的学生)