feat: improve attendance scheduling and API validation
This commit is contained in:
@@ -260,7 +260,11 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
||||
const runner = this.dataSource.createQueryRunner();
|
||||
await runner.connect();
|
||||
try {
|
||||
const tables = await runner.getTables(['attendance_records', 'attendance_sessions']);
|
||||
const tables = await runner.getTables([
|
||||
'class_schedule',
|
||||
'attendance_records',
|
||||
'attendance_sessions',
|
||||
]);
|
||||
const tableNames = new Set(tables.map((table) => table.name));
|
||||
const isMySQL = this.dataSource.options.type === 'mysql';
|
||||
|
||||
@@ -287,6 +291,17 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
|
||||
`);
|
||||
}
|
||||
|
||||
if (tableNames.has('class_schedule')) {
|
||||
const scheduleTable = await runner.getTable('class_schedule');
|
||||
const scheduleColumns = new Set(scheduleTable?.columns.map((column) => column.name) ?? []);
|
||||
if (!scheduleColumns.has('attendance_advance_minutes')) {
|
||||
await runner.query(
|
||||
'ALTER TABLE class_schedule ADD COLUMN attendance_advance_minutes INTEGER NOT NULL DEFAULT 30',
|
||||
);
|
||||
this.logger.log('已为排课添加课前签到分钟配置');
|
||||
}
|
||||
}
|
||||
|
||||
const attendanceTable = await runner.getTable('attendance_records');
|
||||
const columnNames = new Set(attendanceTable?.columns.map((column) => column.name) ?? []);
|
||||
if (!columnNames.has('schedule_id')) {
|
||||
|
||||
@@ -209,6 +209,28 @@ describe('DatabaseMigrationsService — course attendance schema', () => {
|
||||
expect(runner.release).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('adds the configurable attendance window to existing schedules', async () => {
|
||||
const runner = mockRunner({
|
||||
getTables: [
|
||||
{ name: 'class_schedule', columns: [{ name: 'id' }] },
|
||||
{ name: 'attendance_records', columns: [{ name: 'id' }] },
|
||||
{ name: 'attendance_sessions', columns: [{ name: 'id' }] },
|
||||
],
|
||||
});
|
||||
runner.getTable.mockImplementation(async (name: string) =>
|
||||
name === 'class_schedule'
|
||||
? { name, columns: [{ name: 'id' }] }
|
||||
: { name, columns: [{ name: 'id' }, { name: 'schedule_id' }, { name: 'attendance_session_id' }] },
|
||||
);
|
||||
await bootstrapCourseAttendance(runner);
|
||||
|
||||
await service.ensureCourseAttendanceSchema();
|
||||
|
||||
expect(runner.query).toHaveBeenCalledWith(
|
||||
expect.stringContaining('ALTER TABLE class_schedule ADD COLUMN attendance_advance_minutes'),
|
||||
);
|
||||
});
|
||||
|
||||
it('creates attendance_sessions with FK RESTRICT constraints when table is missing', async () => {
|
||||
const runner = mockRunner({
|
||||
getTables: [{ name: 'attendance_records', columns: [{ name: 'id' }] }],
|
||||
|
||||
Reference in New Issue
Block a user