Files
gongxue-base/apps/server/src/attendance/lesson-attendance-sync.service.ts
wangziqi 90cc321221
All checks were successful
CI / check (pull_request) Successful in 1m33s
fix: UI improvements and DingTalk attendance refresh for completed sessions
- DatePicker editors open immediately on double-click
- Student archive drawer hides empty studentNo parentheses
- Student add/edit form uses 2-column grid layout
- Table horizontal scrollbars show only on hover/focus
- Remove fake 近7日趋势 stats from attendance student detail
- Allow DingTalk refresh to update completed attendance sessions
  (late-arriving punches can now change absent → present)
- Switch dev command from concurrently to turbo run dev
- Remove concurrently/wait-on dependencies
2026-07-22 17:50:59 +08:00

54 lines
1.7 KiB
TypeScript

import { BadRequestException, Injectable } from '@nestjs/common';
import { AttendanceImportService } from './attendance-import.service';
import { AttendanceService } from './attendance.service';
export type LessonAttendanceSyncMode = 'refresh' | 'finalize';
export interface LessonAttendanceSyncOptions {
scheduleId: number;
lessonDate: string;
actorId: number;
canManageAll: boolean;
mode: LessonAttendanceSyncMode;
}
@Injectable()
export class LessonAttendanceSyncService {
constructor(
private readonly attendanceService: AttendanceService,
private readonly importService: AttendanceImportService,
) {}
async syncLesson(options: LessonAttendanceSyncOptions) {
const { scheduleId, lessonDate, actorId, canManageAll, mode } = options;
const { schedule } = await this.attendanceService.getLessonAttendance(scheduleId, lessonDate);
const userIds = await this.attendanceService.getTeacherClassDingUserIds(
actorId,
schedule.classId!,
canManageAll,
lessonDate,
);
const dateRange = this.attendanceService.getLessonAttendanceImportDateRange(
schedule,
lessonDate,
);
const imported = await this.importService.importFromDingTalk({
...dateRange,
userIds,
autoMatch: true,
userId: actorId,
});
if (!imported.success || imported.errors.length > 0) {
throw new BadRequestException(imported.errors.join('; ') || '钉钉考勤拉取失败');
}
const attendance = await this.attendanceService.createLessonAttendanceFromDingTalk(
scheduleId,
lessonDate,
actorId,
mode === 'finalize',
);
return { attendance, imported: imported.imported, matched: imported.matched };
}
}