Implement application updates and refinements
This commit is contained in:
+53
-15
@@ -219,6 +219,7 @@ const sqliteSchema = `
|
||||
building TEXT NOT NULL,
|
||||
floor TEXT,
|
||||
capacity INTEGER NOT NULL CHECK (capacity > 0),
|
||||
seat_plan TEXT,
|
||||
seat_start INTEGER NOT NULL DEFAULT 1 CHECK (seat_start > 0),
|
||||
seat_end INTEGER NOT NULL CHECK (seat_end >= seat_start),
|
||||
room_type TEXT NOT NULL CHECK (room_type IN ('standard', 'computer', 'accessible', 'spare')),
|
||||
@@ -259,6 +260,7 @@ const sqliteSchema = `
|
||||
building TEXT NOT NULL,
|
||||
floor TEXT,
|
||||
capacity INTEGER NOT NULL CHECK (capacity > 0),
|
||||
seat_plan TEXT,
|
||||
seat_start INTEGER NOT NULL DEFAULT 1,
|
||||
seat_end INTEGER NOT NULL,
|
||||
room_type TEXT NOT NULL CHECK (room_type IN ('standard', 'computer', 'accessible', 'spare')),
|
||||
@@ -597,6 +599,7 @@ const mysqlSchema = [
|
||||
building VARCHAR(120) NOT NULL,
|
||||
floor VARCHAR(40) NULL,
|
||||
capacity INT UNSIGNED NOT NULL,
|
||||
seat_plan VARCHAR(500) NULL,
|
||||
seat_start INT UNSIGNED NOT NULL DEFAULT 1,
|
||||
seat_end INT UNSIGNED NOT NULL,
|
||||
room_type ENUM('standard', 'computer', 'accessible', 'spare') NOT NULL,
|
||||
@@ -643,6 +646,7 @@ const mysqlSchema = [
|
||||
building VARCHAR(120) NOT NULL,
|
||||
floor VARCHAR(40) NULL,
|
||||
capacity INT UNSIGNED NOT NULL,
|
||||
seat_plan VARCHAR(500) NULL,
|
||||
seat_start INT UNSIGNED NOT NULL DEFAULT 1,
|
||||
seat_end INT UNSIGNED NOT NULL,
|
||||
room_type ENUM('standard', 'computer', 'accessible', 'spare') NOT NULL,
|
||||
@@ -788,7 +792,7 @@ function buildSeedOperations(state) {
|
||||
const nullable = value => value == null || value === '' ? null : value;
|
||||
|
||||
add(
|
||||
'UPDATE schema_metadata SET schema_version = 5, app_version = ?, self_registration_enabled = ?, created_at = ? WHERE id = 1',
|
||||
'UPDATE schema_metadata SET schema_version = 6, app_version = ?, self_registration_enabled = ?, created_at = ? WHERE id = 1',
|
||||
Number(state.meta?.version || 1), state.settings?.selfRegistrationEnabled ? 1 : 0,
|
||||
state.meta?.createdAt || new Date().toISOString()
|
||||
);
|
||||
@@ -918,10 +922,10 @@ function buildSeedOperations(state) {
|
||||
for (const room of state.testRooms) {
|
||||
add(
|
||||
`INSERT INTO test_rooms (
|
||||
id, center_id, code, name, building, floor, capacity, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
id, center_id, code, name, building, floor, capacity, seat_plan, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
room.id, room.centerId, room.code, room.name, room.building, nullable(room.floor), Number(room.capacity),
|
||||
Number(room.seatStart || 1), Number(room.seatEnd), room.roomType, room.status || 'active', nullable(room.notes)
|
||||
nullable(room.seatPlan), Number(room.seatStart || 1), Number(room.seatEnd || room.capacity), room.roomType, room.status || 'active', nullable(room.notes)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -943,10 +947,10 @@ function buildSeedOperations(state) {
|
||||
for (const room of state.centerChangeRooms) {
|
||||
add(
|
||||
`INSERT INTO center_change_rooms (
|
||||
id, request_id, room_id, code, name, building, floor, capacity, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
id, request_id, room_id, code, name, building, floor, capacity, seat_plan, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
room.id, room.requestId, nullable(room.roomId), room.code, room.name, room.building, nullable(room.floor),
|
||||
Number(room.capacity), Number(room.seatStart || 1), Number(room.seatEnd), room.roomType,
|
||||
Number(room.capacity), nullable(room.seatPlan), Number(room.seatStart || 1), Number(room.seatEnd || room.capacity), room.roomType,
|
||||
room.status || 'active', nullable(room.notes)
|
||||
);
|
||||
}
|
||||
@@ -1225,6 +1229,7 @@ function stateFromRows(rows) {
|
||||
building: row.building,
|
||||
floor: row.floor || '',
|
||||
capacity: Number(row.capacity),
|
||||
seatPlan: row.seat_plan || '',
|
||||
seatStart: Number(row.seat_start),
|
||||
seatEnd: Number(row.seat_end),
|
||||
roomType: row.room_type,
|
||||
@@ -1262,6 +1267,7 @@ function stateFromRows(rows) {
|
||||
building: row.building,
|
||||
floor: row.floor || '',
|
||||
capacity: Number(row.capacity),
|
||||
seatPlan: row.seat_plan || '',
|
||||
seatStart: Number(row.seat_start),
|
||||
seatEnd: Number(row.seat_end),
|
||||
roomType: row.room_type,
|
||||
@@ -1717,6 +1723,27 @@ function createRepository({ client, location, read, transaction, close }) {
|
||||
auditOperation(log)
|
||||
]);
|
||||
},
|
||||
async saveSchoolClass(schoolClass, isNew, log) {
|
||||
const change = isNew
|
||||
? operation(
|
||||
'INSERT INTO school_classes (id, school_id, name, grade, active) VALUES (?, ?, ?, ?, ?)',
|
||||
schoolClass.id, schoolClass.schoolId, schoolClass.name, schoolClass.grade, schoolClass.active ? 1 : 0
|
||||
)
|
||||
: operation(
|
||||
'UPDATE school_classes SET name = ?, grade = ?, active = ? WHERE id = ?',
|
||||
schoolClass.name, schoolClass.grade, schoolClass.active ? 1 : 0, schoolClass.id
|
||||
);
|
||||
await transaction([change, auditOperation(log)]);
|
||||
},
|
||||
async updateAdmin(user, passwordChanged, log) {
|
||||
const sql = passwordChanged
|
||||
? 'UPDATE users SET display_name = ?, class_id = ?, active = ?, password_hash = ? WHERE id = ?'
|
||||
: 'UPDATE users SET display_name = ?, class_id = ?, active = ? WHERE id = ?';
|
||||
const params = passwordChanged
|
||||
? [user.displayName, optional(user.classId), user.active ? 1 : 0, user.passwordHash, user.id]
|
||||
: [user.displayName, optional(user.classId), user.active ? 1 : 0, user.id];
|
||||
await transaction([operation(sql, ...params), auditOperation(log)]);
|
||||
},
|
||||
async saveTestCenter(center, isNew, log) {
|
||||
const centerOperation = isNew
|
||||
? operation(
|
||||
@@ -1750,10 +1777,10 @@ function createRepository({ client, location, read, transaction, close }) {
|
||||
];
|
||||
for (const room of rooms) operations.push(operation(
|
||||
`INSERT INTO center_change_rooms (
|
||||
id, request_id, room_id, code, name, building, floor, capacity, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
id, request_id, room_id, code, name, building, floor, capacity, seat_plan, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
room.id, request.id, optional(room.roomId), room.code, room.name, room.building, optional(room.floor),
|
||||
Number(room.capacity), Number(room.seatStart), Number(room.seatEnd), room.roomType, room.status,
|
||||
Number(room.capacity), optional(room.seatPlan), 1, Number(room.capacity), room.roomType, room.status,
|
||||
optional(room.notes)
|
||||
));
|
||||
operations.push(auditOperation(log));
|
||||
@@ -1798,10 +1825,10 @@ function createRepository({ client, location, read, transaction, close }) {
|
||||
operations.push(operation('DELETE FROM test_rooms WHERE center_id = ?', center.id));
|
||||
for (const room of rooms) operations.push(operation(
|
||||
`INSERT INTO test_rooms (
|
||||
id, center_id, code, name, building, floor, capacity, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
id, center_id, code, name, building, floor, capacity, seat_plan, seat_start, seat_end, room_type, status, notes
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
room.id, center.id, room.code, room.name, room.building, optional(room.floor), Number(room.capacity),
|
||||
Number(room.seatStart), Number(room.seatEnd), room.roomType, room.status, optional(room.notes)
|
||||
optional(room.seatPlan), 1, Number(room.capacity), room.roomType, room.status, optional(room.notes)
|
||||
));
|
||||
}
|
||||
operations.push(auditOperation(log));
|
||||
@@ -1933,6 +1960,8 @@ async function createSqliteStore({ path, seed }) {
|
||||
['code', 'TEXT'], ['manager_name', 'TEXT'], ['manager_phone', 'TEXT'], ['emergency_phone', 'TEXT'],
|
||||
['gate_open_time', 'TEXT'], ['transport', 'TEXT'], ['status', "TEXT NOT NULL DEFAULT 'active'"], ['notes', 'TEXT']
|
||||
]);
|
||||
ensureColumns('test_rooms', [['seat_plan', 'TEXT']]);
|
||||
ensureColumns('center_change_rooms', [['seat_plan', 'TEXT']]);
|
||||
if (tableExists('workflow_definitions')) {
|
||||
const definitionSql = connection.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'workflow_definitions'").get()?.sql || '';
|
||||
if (!definitionSql.includes('candidate_account_batch')) {
|
||||
@@ -2134,13 +2163,17 @@ async function createSqliteStore({ path, seed }) {
|
||||
}
|
||||
}
|
||||
|
||||
if (existingSystem && Number(existingSystem.app_version || 1) < 6) {
|
||||
connection.prepare('UPDATE schema_metadata SET schema_version = 6, app_version = 6 WHERE id = 1').run();
|
||||
}
|
||||
|
||||
if (!connection.prepare('SELECT id FROM schema_metadata WHERE id = 1').get()) {
|
||||
const initialState = seed();
|
||||
connection.exec('BEGIN IMMEDIATE');
|
||||
try {
|
||||
connection.prepare(`
|
||||
INSERT INTO schema_metadata (id, schema_version, app_version, self_registration_enabled, created_at)
|
||||
VALUES (1, 5, ?, ?, ?)
|
||||
VALUES (1, 6, ?, ?, ?)
|
||||
`).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');
|
||||
@@ -2222,6 +2255,8 @@ async function createMysqlStore({ seed }) {
|
||||
'ALTER TABLE test_centers ADD COLUMN IF NOT EXISTS transport VARCHAR(500) NULL',
|
||||
"ALTER TABLE test_centers ADD COLUMN IF NOT EXISTS status ENUM('active', 'inactive') NOT NULL DEFAULT 'active'",
|
||||
'ALTER TABLE test_centers ADD COLUMN IF NOT EXISTS notes VARCHAR(1000) NULL',
|
||||
'ALTER TABLE test_rooms ADD COLUMN IF NOT EXISTS seat_plan VARCHAR(500) NULL',
|
||||
'ALTER TABLE center_change_rooms ADD COLUMN IF NOT EXISTS seat_plan VARCHAR(500) NULL',
|
||||
"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);
|
||||
@@ -2395,6 +2430,9 @@ async function createMysqlStore({ seed }) {
|
||||
connection.release();
|
||||
}
|
||||
}
|
||||
if (Number(metadataRows[0]?.app_version || 1) < 6) {
|
||||
await pool.execute('UPDATE schema_metadata SET schema_version = 6, app_version = 6 WHERE id = 1');
|
||||
}
|
||||
}
|
||||
if (!existing.length) {
|
||||
const initialState = seed();
|
||||
@@ -2403,7 +2441,7 @@ async function createMysqlStore({ seed }) {
|
||||
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, 5, ?, ?, ?)
|
||||
VALUES (1, 6, ?, ?, ?)
|
||||
`, [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