refactor: resolve remaining field audit issues

This commit is contained in:
2026-07-13 15:12:36 +08:00
parent 0533c30ece
commit aa1ed7db56
34 changed files with 953 additions and 263 deletions

View File

@@ -17,6 +17,7 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
await this.removeUnusedClassroomColumns();
await this.cleanupDepositRefundColumns();
await this.removeUnusedClassStudentColumns();
await this.normalizeClassroomStatuses();
}
private async removeUnusedClassroomColumns(): Promise<void> {
@@ -92,6 +93,22 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
}
}
private async normalizeClassroomStatuses(): Promise<void> {
const runner = this.dataSource.createQueryRunner();
await runner.connect();
try {
const tables = await runner.getTables(['classrooms']);
if (tables.length === 0) return;
await runner.query(`
UPDATE classrooms
SET status = 'available'
WHERE status IS NULL OR status NOT IN ('available', 'maintenance', 'archived')
`);
} finally {
await runner.release();
}
}
private async ensureAiConfigTable(): Promise<void> {
const runner = this.dataSource.createQueryRunner();
await runner.connect();
@@ -410,14 +427,17 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
// Drop any existing FK constraint on schedule_id or class_id
const fkColumns = ['schedule_id', 'class_id'];
for (const col of fkColumns) {
const fkRows: { CONSTRAINT_NAME: string }[] = await runner.query(`
const fkRows: { CONSTRAINT_NAME: string }[] = await runner.query(
`
SELECT CONSTRAINT_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'attendance_sessions'
AND COLUMN_NAME = ?
AND REFERENCED_TABLE_NAME IS NOT NULL
`, [col]);
`,
[col],
);
for (const row of fkRows) {
try {
@@ -437,13 +457,16 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
];
for (const c of constraints) {
// Only skip if RESTRICT constraint is already confirmed via information_schema
const existing: Array<{ DELETE_RULE: string }> = await runner.query(`
const existing: Array<{ DELETE_RULE: string }> = await runner.query(
`
SELECT DELETE_RULE
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE()
AND TABLE_NAME = 'attendance_sessions'
AND CONSTRAINT_NAME = ?
`, [c.name]);
`,
[c.name],
);
if (existing.length > 0 && existing[0].DELETE_RULE === 'RESTRICT') {
this.logger.log(`考勤场次删除保护约束已存在: ${c.name}`);
@@ -505,17 +528,13 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
FROM attendance_sessions
`);
await runner.query('DROP TABLE attendance_sessions');
await runner.query(
'ALTER TABLE attendance_sessions_new RENAME TO attendance_sessions',
);
await runner.query('ALTER TABLE attendance_sessions_new RENAME TO attendance_sessions');
await runner.query(
'CREATE UNIQUE INDEX IF NOT EXISTS uq_attendance_session_schedule_date ON attendance_sessions(schedule_id, lesson_date)',
);
// Rebuild attendance_records to add/protect FK on attendance_session_id
const recordsFk = await runner.query(
"PRAGMA foreign_key_list('attendance_records')",
);
const recordsFk = await runner.query("PRAGMA foreign_key_list('attendance_records')");
const hasSessionFk = recordsFk.some(
(r: { from: string }) => r.from === 'attendance_session_id',
);
@@ -548,9 +567,7 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
FROM attendance_records
`);
await runner.query('DROP TABLE attendance_records');
await runner.query(
'ALTER TABLE attendance_records_new RENAME TO attendance_records',
);
await runner.query('ALTER TABLE attendance_records_new RENAME TO attendance_records');
await runner.query(
'CREATE UNIQUE INDEX IF NOT EXISTS uq_attendance_session_student ON attendance_records(attendance_session_id, student_id)',
);
@@ -560,9 +577,7 @@ export class DatabaseMigrationsService implements OnApplicationBootstrap {
// If violations exist, the transaction rolls back and old tables are preserved.
const checkRows = await runner.query('PRAGMA foreign_key_check');
if (checkRows.length > 0) {
throw new Error(
`外键一致性检查失败: ${checkRows.length} 行违反外键约束`,
);
throw new Error(`外键一致性检查失败: ${checkRows.length} 行违反外键约束`);
}
await runner.query('COMMIT');