'use strict'; const db = require('../src/infra/db'); const sync = require('../src/sync/sync'); const audit = require('../src/audit/audit'); const dashboardSummary = require('../src/precompute/dashboard-summary'); const precompute = require('../src/precompute'); const precomputeService = require('../src/precompute/service'); async function main() { precompute.registerAll(); const legacy = await db.query( `SELECT id, employee_id, exam_year, exam_month, submit_time, details, extras FROM online_exams WHERE COALESCE(JSON_UNQUOTE(JSON_EXTRACT(details, '$.isMissingExam')), 'false') = 'true'`, ); const periods = new Set(); await db.transaction(async (conn) => { for (const row of legacy) { const month = `${row.exam_year}-${String(row.exam_month).padStart(2, '0')}`; const details = typeof row.details === 'string' ? JSON.parse(row.details) : (row.details || {}); const extras = typeof row.extras === 'string' ? JSON.parse(row.extras) : row.extras; const [existing] = await conn.execute( 'SELECT id FROM missing_exams WHERE employee_id = ? AND missing_month = ? LIMIT 1', [row.employee_id, month], ); if (existing.length === 0) { await conn.execute( `INSERT INTO missing_exams (employee_id, missing_month, reason, import_time, details, extras, version) VALUES (?, ?, ?, ?, ?, ?, 0)`, [ row.employee_id, month, details.reason || '缺考', row.submit_time || new Date(), JSON.stringify({ ...details, legacyOnlineExamId: row.id }), extras == null ? null : JSON.stringify(extras), ], ); } await conn.execute('DELETE FROM online_exams WHERE id = ?', [row.id]); periods.add(`${row.exam_year}-${row.exam_month}`); } }); if (legacy.length > 0) { await sync.bumpVersions(['online_exams', 'missing_exams']); for (const period of periods) { const [year, month] = period.split('-').map(Number); await precomputeService.onUploadComplete('online_exams', year, month); } await dashboardSummary.recompute(); await audit.log({ clientType: 'system', action: 'migrate_missing_exams', module: 'missing_exams', payload: { migratedCount: legacy.length, periods: [...periods] }, }); } console.log(JSON.stringify({ migratedCount: legacy.length, periods: [...periods] })); } main() .catch((error) => { console.error(error); process.exitCode = 1; }) .finally(() => db.close());