Add independent subject pass rules and atomic score imports

This commit is contained in:
2026-07-20 15:42:36 +08:00 Unverified
parent c5b18d0b15
commit 9f850fa045
17 changed files with 688 additions and 114 deletions
+43 -5
View File
@@ -40,10 +40,11 @@ export function createSqliteAdapter(context) {
]);
ensureColumns('registrations', [['registration_number', 'TEXT'], ['number_rule_id', 'TEXT']]);
ensureColumns('exams', [
['pass_policy', "TEXT NOT NULL DEFAULT 'score_ratio'"], ['pass_value', 'REAL NOT NULL DEFAULT 60']
['pass_policy', "TEXT NOT NULL DEFAULT 'rank_percent'"], ['pass_value', 'REAL NOT NULL DEFAULT 60']
]);
ensureColumns('exam_subjects', [
['full_score', 'REAL NOT NULL DEFAULT 150'], ['pass_score', 'REAL NOT NULL DEFAULT 90']
['full_score', 'REAL NOT NULL DEFAULT 150'], ['pass_score', 'REAL NOT NULL DEFAULT 90'],
['pass_rule', "TEXT NOT NULL DEFAULT 'fixed_score'"], ['pass_value', 'REAL NOT NULL DEFAULT 90']
]);
ensureColumns('test_centers', [
['code', 'TEXT'], ['manager_name', 'TEXT'], ['manager_phone', 'TEXT'], ['emergency_phone', 'TEXT'],
@@ -194,6 +195,43 @@ export function createSqliteAdapter(context) {
`).run();
connection.prepare('UPDATE schema_metadata SET schema_version = 10, app_version = 10 WHERE id = 1').run();
}
if (existingSystem && Number(existingSystem.schema_version || 1) < 11) {
connection.exec('PRAGMA foreign_keys = OFF;');
connection.exec('BEGIN IMMEDIATE');
try {
connection.prepare("UPDATE exam_subjects SET pass_rule = 'fixed_score', pass_value = pass_score").run();
connection.exec(`
CREATE TABLE results_v11 (
id TEXT PRIMARY KEY,
registration_id TEXT NOT NULL REFERENCES registrations(id) ON DELETE CASCADE,
subject_id TEXT NOT NULL REFERENCES exam_subjects(id) ON DELETE CASCADE,
score REAL NOT NULL CHECK (score >= 0),
grade TEXT NOT NULL,
published INTEGER NOT NULL DEFAULT 0 CHECK (published IN (0, 1)),
updated_at TEXT,
published_at TEXT,
UNIQUE (registration_id, subject_id)
) STRICT;
INSERT INTO results_v11 (id, registration_id, subject_id, score, grade, published, updated_at, published_at)
SELECT id, registration_id, subject_id, score, grade, published, updated_at, published_at FROM results;
DROP TABLE results;
ALTER TABLE results_v11 RENAME TO results;
CREATE INDEX IF NOT EXISTS idx_results_registration ON results(registration_id, published);
`);
connection.prepare('UPDATE schema_metadata SET schema_version = 11, app_version = 11 WHERE id = 1').run();
connection.exec('COMMIT');
} catch (error) {
connection.exec('ROLLBACK');
connection.close();
throw error;
} finally {
try { connection.exec('PRAGMA foreign_keys = ON;'); } catch {}
}
}
if (existingSystem && Number(existingSystem.schema_version || 1) < 12) {
connection.prepare("UPDATE exams SET pass_policy = 'rank_percent' WHERE pass_policy = 'score_ratio'").run();
connection.prepare('UPDATE schema_metadata SET schema_version = 12, app_version = 12 WHERE id = 1').run();
}
if (existingSystem && Number(existingSystem.app_version || 1) < 2) {
const extension = seed();
connection.exec('BEGIN IMMEDIATE');
@@ -344,8 +382,8 @@ export function createSqliteAdapter(context) {
if (existingSystem && Number(existingSystem.app_version || 1) < 7) {
connection.prepare('UPDATE schema_metadata SET schema_version = 7, app_version = 7 WHERE id = 1').run();
}
if (existingSystem && Number(existingSystem.schema_version || 1) < 10) {
connection.prepare('UPDATE schema_metadata SET schema_version = 10, app_version = 10 WHERE id = 1').run();
if (existingSystem && Number(existingSystem.schema_version || 1) < 12) {
connection.prepare('UPDATE schema_metadata SET schema_version = 12, app_version = 12 WHERE id = 1').run();
}
if (!connection.prepare('SELECT id FROM schema_metadata WHERE id = 1').get()) {
@@ -354,7 +392,7 @@ export function createSqliteAdapter(context) {
try {
connection.prepare(`
INSERT INTO schema_metadata (id, schema_version, app_version, self_registration_enabled, created_at)
VALUES (1, 10, ?, ?, ?)
VALUES (1, 12, ?, ?, ?)
`).run(Number(initialState.meta?.version || 1), initialState.settings?.selfRegistrationEnabled ? 1 : 0, initialState.meta?.createdAt || new Date().toISOString());
for (const item of buildSeedOperations(initialState)) connection.prepare(item.sql).run(...item.params);
connection.exec('COMMIT');