fix(server): 考勤自动结算支持空班级直接完成,补充自动匹配测试
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
|
||||
import { Cron } from '@nestjs/schedule';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { In, LessThan, LessThanOrEqual, MoreThanOrEqual, Repository } from 'typeorm';
|
||||
@@ -150,13 +150,91 @@ export class AttendanceSettlementService {
|
||||
true,
|
||||
);
|
||||
} catch (error: unknown) {
|
||||
if (session) await this.sessionRepo.update({ id: session.id, status: 'settling' }, { status: 'in_progress' });
|
||||
if (this.isNoActiveStudentsError(error)) {
|
||||
try {
|
||||
await this.finalizeEmptyLesson(schedule, lessonDate, session);
|
||||
this.logger.log(`课程${schedule.id} ${lessonDate}班级无在读学生,已直接完成结算`);
|
||||
} catch (finalizeError: unknown) {
|
||||
this.logger.error(
|
||||
`课程${schedule.id} ${lessonDate}空班级完成结算落库失败: ${finalizeError instanceof Error ? finalizeError.message : String(finalizeError)}`,
|
||||
);
|
||||
if (session) {
|
||||
await this.sessionRepo.update(
|
||||
{ id: session.id, status: 'settling' },
|
||||
{ status: 'in_progress' },
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (session) {
|
||||
await this.sessionRepo.update({ id: session.id, status: 'settling' }, { status: 'in_progress' });
|
||||
}
|
||||
this.logger.error(
|
||||
`课程${schedule.id} ${lessonDate}自动结算失败: ${error instanceof Error ? error.message : String(error)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private isNoActiveStudentsError(error: unknown): boolean {
|
||||
return (
|
||||
error instanceof BadRequestException &&
|
||||
error.message.includes('该班级暂无在读学生')
|
||||
);
|
||||
}
|
||||
|
||||
private async finalizeEmptyLesson(
|
||||
schedule: ClassSchedule,
|
||||
lessonDate: string,
|
||||
session?: AttendanceSession,
|
||||
): Promise<void> {
|
||||
const completedAt = new Date();
|
||||
const completedBy = schedule.teacherId;
|
||||
if (session) {
|
||||
await this.sessionRepo.update(
|
||||
{ id: session.id, status: 'settling' },
|
||||
{ status: 'completed', completedBy, completedAt },
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const existing = await this.sessionRepo.findOne({
|
||||
where: { scheduleId: schedule.id, lessonDate },
|
||||
});
|
||||
if (existing) {
|
||||
if (existing.status !== 'completed') {
|
||||
await this.sessionRepo.update(
|
||||
{ id: existing.id },
|
||||
{ status: 'completed', completedBy, completedAt },
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await this.sessionRepo.save(
|
||||
this.sessionRepo.create({
|
||||
scheduleId: schedule.id,
|
||||
classId: schedule.classId!,
|
||||
lessonDate,
|
||||
status: 'completed',
|
||||
startedBy: completedBy,
|
||||
startedAt: completedAt,
|
||||
completedBy,
|
||||
completedAt,
|
||||
}),
|
||||
);
|
||||
} catch (error: unknown) {
|
||||
const code = (error as Record<string, unknown>).code;
|
||||
const errno = (error as Record<string, unknown>).errno;
|
||||
if (code !== 'ER_DUP_ENTRY' && errno !== 1062) throw error;
|
||||
await this.sessionRepo.update(
|
||||
{ scheduleId: schedule.id, lessonDate, status: 'in_progress' },
|
||||
{ status: 'completed', completedBy, completedAt },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private getEndedOccurrenceDate(
|
||||
schedule: ClassSchedule,
|
||||
clock: { weekDay: number; minutes: number },
|
||||
|
||||
Reference in New Issue
Block a user