实现考试归档并永久锁定成绩流程
This commit is contained in:
@@ -66,6 +66,8 @@ export function createMysqlAdapter(context) {
|
||||
'ALTER TABLE registrations ADD COLUMN IF NOT EXISTS number_rule_id VARCHAR(64) NULL',
|
||||
"ALTER TABLE exams ADD COLUMN IF NOT EXISTS pass_policy ENUM('fixed_score', 'score_ratio', 'rank_percent', 'subject_scores', 'none') NOT NULL DEFAULT 'rank_percent'",
|
||||
'ALTER TABLE exams ADD COLUMN IF NOT EXISTS pass_value DOUBLE NOT NULL DEFAULT 60',
|
||||
'ALTER TABLE exams ADD COLUMN IF NOT EXISTS archived_at VARCHAR(35) NULL',
|
||||
'ALTER TABLE exams ADD COLUMN IF NOT EXISTS archived_by VARCHAR(64) NULL',
|
||||
'ALTER TABLE exam_subjects ADD COLUMN IF NOT EXISTS full_score DOUBLE NOT NULL DEFAULT 150',
|
||||
'ALTER TABLE exam_subjects ADD COLUMN IF NOT EXISTS pass_score DOUBLE NOT NULL DEFAULT 90',
|
||||
"ALTER TABLE exam_subjects ADD COLUMN IF NOT EXISTS pass_rule ENUM('fixed_score', 'score_ratio', 'none') NOT NULL DEFAULT 'fixed_score'",
|
||||
@@ -99,6 +101,37 @@ export function createMysqlAdapter(context) {
|
||||
"ALTER TABLE workflow_definitions MODIFY COLUMN business_type ENUM('profile_change', 'registration_review', 'center_change', 'candidate_account_batch') NOT NULL"
|
||||
];
|
||||
for (const statement of mysqlColumnMigrations) await pool.execute(statement);
|
||||
const [resultLockTriggers] = await pool.execute(`
|
||||
SELECT TRIGGER_NAME FROM information_schema.TRIGGERS
|
||||
WHERE TRIGGER_SCHEMA = DATABASE() AND TRIGGER_NAME LIKE 'trg_results_lock_archived_%'
|
||||
`);
|
||||
const existingResultLockTriggers = new Set(resultLockTriggers.map(item => item.TRIGGER_NAME));
|
||||
const mysqlResultLockTriggers = {
|
||||
trg_results_lock_archived_insert: `CREATE TRIGGER trg_results_lock_archived_insert BEFORE INSERT ON results FOR EACH ROW
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM registrations registration JOIN exams exam ON exam.id = registration.exam_id
|
||||
WHERE registration.id = NEW.registration_id AND exam.archived_at IS NOT NULL) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '归档考试成绩已永久锁定';
|
||||
END IF;
|
||||
END`,
|
||||
trg_results_lock_archived_update: `CREATE TRIGGER trg_results_lock_archived_update BEFORE UPDATE ON results FOR EACH ROW
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM registrations registration JOIN exams exam ON exam.id = registration.exam_id
|
||||
WHERE registration.id IN (OLD.registration_id, NEW.registration_id) AND exam.archived_at IS NOT NULL) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '归档考试成绩已永久锁定';
|
||||
END IF;
|
||||
END`,
|
||||
trg_results_lock_archived_delete: `CREATE TRIGGER trg_results_lock_archived_delete BEFORE DELETE ON results FOR EACH ROW
|
||||
BEGIN
|
||||
IF EXISTS (SELECT 1 FROM registrations registration JOIN exams exam ON exam.id = registration.exam_id
|
||||
WHERE registration.id = OLD.registration_id AND exam.archived_at IS NOT NULL) THEN
|
||||
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '归档考试成绩已永久锁定';
|
||||
END IF;
|
||||
END`
|
||||
};
|
||||
for (const [name, statement] of Object.entries(mysqlResultLockTriggers)) {
|
||||
if (!existingResultLockTriggers.has(name)) await pool.execute(statement);
|
||||
}
|
||||
const [legacyRegistrationNumberIndexes] = await pool.execute("SHOW INDEX FROM registrations WHERE Key_name = 'uq_registrations_number'");
|
||||
if (legacyRegistrationNumberIndexes.length) await pool.execute('ALTER TABLE registrations DROP INDEX uq_registrations_number');
|
||||
const [existing] = await pool.execute('SELECT id FROM schema_metadata WHERE id = 1');
|
||||
@@ -155,6 +188,11 @@ export function createMysqlAdapter(context) {
|
||||
metadataRows[0].schema_version = 13;
|
||||
metadataRows[0].app_version = 13;
|
||||
}
|
||||
if (Number(metadataRows[0]?.schema_version || 1) < 14) {
|
||||
await pool.execute('UPDATE schema_metadata SET schema_version = 14, app_version = 14 WHERE id = 1');
|
||||
metadataRows[0].schema_version = 14;
|
||||
metadataRows[0].app_version = 14;
|
||||
}
|
||||
if (Number(metadataRows[0]?.app_version || 1) < 2) {
|
||||
const extension = seed();
|
||||
const connection = await pool.getConnection();
|
||||
@@ -326,8 +364,8 @@ export function createMysqlAdapter(context) {
|
||||
if (Number(metadataRows[0]?.app_version || 1) < 7) {
|
||||
await pool.execute('UPDATE schema_metadata SET schema_version = 7, app_version = 7 WHERE id = 1');
|
||||
}
|
||||
if (Number(metadataRows[0]?.schema_version || 1) < 13) {
|
||||
await pool.execute('UPDATE schema_metadata SET schema_version = 13, app_version = 13 WHERE id = 1');
|
||||
if (Number(metadataRows[0]?.schema_version || 1) < 14) {
|
||||
await pool.execute('UPDATE schema_metadata SET schema_version = 14, app_version = 14 WHERE id = 1');
|
||||
}
|
||||
}
|
||||
if (!existing.length) {
|
||||
@@ -337,7 +375,7 @@ export function createMysqlAdapter(context) {
|
||||
await connection.beginTransaction();
|
||||
const [insert] = await connection.execute(`
|
||||
INSERT IGNORE INTO schema_metadata (id, schema_version, app_version, self_registration_enabled, created_at)
|
||||
VALUES (1, 13, ?, ?, ?)
|
||||
VALUES (1, 14, ?, ?, ?)
|
||||
`, [Number(initialState.meta?.version || 1), initialState.settings?.selfRegistrationEnabled ? 1 : 0, initialState.meta?.createdAt || new Date().toISOString()]);
|
||||
if (insert.affectedRows === 1) {
|
||||
for (const item of buildSeedOperations(initialState)) await connection.execute(item.sql, item.params);
|
||||
|
||||
Reference in New Issue
Block a user