准考证编排
This commit is contained in:
+139
-24
@@ -16,7 +16,10 @@ export const relationalTables = [
|
||||
'exam_subjects',
|
||||
'registrations',
|
||||
'registration_subjects',
|
||||
'admission_number_rules',
|
||||
'exam_arrangement_plans',
|
||||
'admit_cards',
|
||||
'admit_card_subjects',
|
||||
'results',
|
||||
'test_centers',
|
||||
'test_rooms',
|
||||
@@ -37,6 +40,7 @@ function validateState(state, source = '数据库') {
|
||||
const collections = [
|
||||
'schools', 'classes', 'users', 'candidateProfiles', 'notices', 'exams', 'registrations', 'results',
|
||||
'testCenters', 'testRooms', 'centerChangeRequests', 'centerChangeRooms',
|
||||
'admissionNumberRules', 'arrangementPlans',
|
||||
'numberRules', 'candidateAccountBatches', 'candidateAccountBatchItems',
|
||||
'workflows', 'workflowInstances', 'workflowActions', 'auditLogs'
|
||||
];
|
||||
@@ -53,7 +57,7 @@ function buildSeedOperations(state) {
|
||||
const nullable = value => value == null || value === '' ? null : value;
|
||||
|
||||
add(
|
||||
'UPDATE schema_metadata SET schema_version = 8, app_version = ?, self_registration_enabled = ?, created_at = ? WHERE id = 1',
|
||||
'UPDATE schema_metadata SET schema_version = 9, 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()
|
||||
);
|
||||
@@ -150,15 +154,6 @@ function buildSeedOperations(state) {
|
||||
for (const subjectId of registration.subjectIds) {
|
||||
add('INSERT INTO registration_subjects (registration_id, subject_id) VALUES (?, ?)', registration.id, subjectId);
|
||||
}
|
||||
if (registration.admitCard) {
|
||||
add(
|
||||
`INSERT INTO admit_cards (
|
||||
registration_id, card_number, test_center, room, seat, generated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
registration.id, registration.admitCard.number, registration.admitCard.testCenter,
|
||||
registration.admitCard.room, registration.admitCard.seat, registration.admitCard.generatedAt
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (const result of state.results) {
|
||||
@@ -197,6 +192,46 @@ function buildSeedOperations(state) {
|
||||
);
|
||||
}
|
||||
|
||||
for (const rule of state.admissionNumberRules) {
|
||||
add(
|
||||
`INSERT INTO admission_number_rules (
|
||||
id, code, name, description, separator, segments_json, example, active, created_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
rule.id, rule.code, rule.name, rule.description, rule.separator || '', JSON.stringify(rule.segments || []),
|
||||
rule.example || '', rule.active === false ? 0 : 1, rule.createdAt
|
||||
);
|
||||
}
|
||||
|
||||
for (const plan of state.arrangementPlans) {
|
||||
add(
|
||||
`INSERT INTO exam_arrangement_plans (
|
||||
id, exam_id, number_rule_id, mixing_scope, random_seed, candidate_count, center_count,
|
||||
subject_assignment_count, subject_combination_count, same_school_center_rate, warnings_json, generated_by, generated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
plan.id, plan.examId, plan.numberRuleId, plan.mixingScope, plan.randomSeed,
|
||||
Number(plan.candidateCount || 0), Number(plan.centerCount || 0), Number(plan.subjectAssignmentCount || 0),
|
||||
Number(plan.subjectCombinationCount || 0), Number(plan.sameSchoolCenterRate || 0), JSON.stringify(plan.warnings || []),
|
||||
nullable(plan.generatedBy), plan.generatedAt
|
||||
);
|
||||
}
|
||||
|
||||
for (const registration of state.registrations.filter(item => item.admitCard)) {
|
||||
const card = registration.admitCard;
|
||||
add(
|
||||
`INSERT INTO admit_cards (
|
||||
registration_id, plan_id, card_number, center_id, test_center, generated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
registration.id, card.planId, card.number, nullable(card.centerId), card.testCenter, card.generatedAt
|
||||
);
|
||||
for (const assignment of card.assignments || []) add(
|
||||
`INSERT INTO admit_card_subjects (
|
||||
registration_id, subject_id, room_id, room, room_code, exam_room_code, seat, subject_signature
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
registration.id, assignment.subjectId, nullable(assignment.roomId), assignment.roomName || assignment.room,
|
||||
assignment.roomCode, assignment.examRoomCode, assignment.seat, assignment.subjectSignature || ''
|
||||
);
|
||||
}
|
||||
|
||||
for (const request of state.centerChangeRequests) {
|
||||
add(
|
||||
`INSERT INTO center_change_requests (
|
||||
@@ -328,13 +363,39 @@ function stateFromRows(rows) {
|
||||
subjectIds.push(row.subject_id);
|
||||
registrationSubjects.set(row.registration_id, subjectIds);
|
||||
}
|
||||
const admitCards = new Map(rows.admitCards.map(row => [row.registration_id, {
|
||||
number: row.card_number,
|
||||
testCenter: row.test_center,
|
||||
room: row.room,
|
||||
seat: row.seat,
|
||||
generatedAt: row.generated_at
|
||||
}]));
|
||||
const subjectPositions = new Map(rows.subjects.map(row => [row.id, Number(row.position)]));
|
||||
const admitAssignments = new Map();
|
||||
for (const row of rows.admitCardSubjects) {
|
||||
const assignments = admitAssignments.get(row.registration_id) || [];
|
||||
assignments.push({
|
||||
subjectId: row.subject_id,
|
||||
roomId: row.room_id,
|
||||
roomName: row.room,
|
||||
room: row.room,
|
||||
roomCode: row.room_code,
|
||||
examRoomCode: row.exam_room_code,
|
||||
seat: row.seat,
|
||||
subjectSignature: row.subject_signature || ''
|
||||
});
|
||||
admitAssignments.set(row.registration_id, assignments);
|
||||
}
|
||||
for (const assignments of admitAssignments.values()) assignments.sort((left, right) =>
|
||||
(subjectPositions.get(left.subjectId) || 0) - (subjectPositions.get(right.subjectId) || 0)
|
||||
);
|
||||
const admitCards = new Map(rows.admitCards.map(row => {
|
||||
const assignments = admitAssignments.get(row.registration_id) || [];
|
||||
const primary = assignments[0] || {};
|
||||
return [row.registration_id, {
|
||||
planId: row.plan_id,
|
||||
number: row.card_number,
|
||||
centerId: row.center_id,
|
||||
testCenter: row.test_center,
|
||||
room: primary.roomName || '',
|
||||
seat: primary.seat || '',
|
||||
assignments,
|
||||
generatedAt: row.generated_at
|
||||
}];
|
||||
}));
|
||||
const ruleSegments = new Map();
|
||||
for (const row of rows.numberRuleSegments) {
|
||||
const segments = ruleSegments.get(row.rule_id) || [];
|
||||
@@ -567,6 +628,32 @@ function stateFromRows(rows) {
|
||||
status: row.status,
|
||||
notes: row.notes || ''
|
||||
})),
|
||||
admissionNumberRules: rows.admissionNumberRules.map(row => ({
|
||||
id: row.id,
|
||||
code: row.code,
|
||||
name: row.name,
|
||||
description: row.description,
|
||||
separator: row.separator || '',
|
||||
segments: Array.isArray(row.segments_json) ? row.segments_json : JSON.parse(row.segments_json || '[]'),
|
||||
example: row.example || '',
|
||||
active: Boolean(row.active),
|
||||
createdAt: row.created_at
|
||||
})),
|
||||
arrangementPlans: rows.arrangementPlans.map(row => ({
|
||||
id: row.id,
|
||||
examId: row.exam_id,
|
||||
numberRuleId: row.number_rule_id,
|
||||
mixingScope: row.mixing_scope,
|
||||
randomSeed: row.random_seed,
|
||||
candidateCount: Number(row.candidate_count),
|
||||
centerCount: Number(row.center_count),
|
||||
subjectAssignmentCount: Number(row.subject_assignment_count),
|
||||
subjectCombinationCount: Number(row.subject_combination_count),
|
||||
sameSchoolCenterRate: Number(row.same_school_center_rate),
|
||||
warnings: Array.isArray(row.warnings_json) ? row.warnings_json : JSON.parse(row.warnings_json || '[]'),
|
||||
generatedBy: row.generated_by,
|
||||
generatedAt: row.generated_at
|
||||
})),
|
||||
numberRules: rows.numberRules.map(row => ({
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
@@ -649,7 +736,10 @@ function readSqliteRows(connection) {
|
||||
subjects: connection.prepare('SELECT * FROM exam_subjects ORDER BY exam_id, position, id').all(),
|
||||
registrations: connection.prepare('SELECT * FROM registrations ORDER BY created_at, id').all(),
|
||||
registrationSubjects: connection.prepare('SELECT * FROM registration_subjects ORDER BY registration_id, subject_id').all(),
|
||||
admissionNumberRules: connection.prepare('SELECT * FROM admission_number_rules ORDER BY created_at, id').all(),
|
||||
arrangementPlans: connection.prepare('SELECT * FROM exam_arrangement_plans ORDER BY generated_at DESC, id').all(),
|
||||
admitCards: connection.prepare('SELECT * FROM admit_cards ORDER BY registration_id').all(),
|
||||
admitCardSubjects: connection.prepare('SELECT * FROM admit_card_subjects ORDER BY registration_id, subject_id').all(),
|
||||
results: connection.prepare('SELECT * FROM results ORDER BY id').all(),
|
||||
testCenters: connection.prepare('SELECT * FROM test_centers ORDER BY school_id, name, id').all(),
|
||||
testRooms: connection.prepare('SELECT * FROM test_rooms ORDER BY center_id, code, id').all(),
|
||||
@@ -682,7 +772,10 @@ async function readMysqlRows(connection) {
|
||||
subjects: await query('SELECT * FROM exam_subjects ORDER BY exam_id, position, id'),
|
||||
registrations: await query('SELECT * FROM registrations ORDER BY created_at, id'),
|
||||
registrationSubjects: await query('SELECT * FROM registration_subjects ORDER BY registration_id, subject_id'),
|
||||
admissionNumberRules: await query('SELECT * FROM admission_number_rules ORDER BY created_at, id'),
|
||||
arrangementPlans: await query('SELECT * FROM exam_arrangement_plans ORDER BY generated_at DESC, id'),
|
||||
admitCards: await query('SELECT * FROM admit_cards ORDER BY registration_id'),
|
||||
admitCardSubjects: await query('SELECT * FROM admit_card_subjects ORDER BY registration_id, subject_id'),
|
||||
results: await query('SELECT * FROM results ORDER BY id'),
|
||||
testCenters: await query('SELECT * FROM test_centers ORDER BY school_id, name, id'),
|
||||
testRooms: await query('SELECT * FROM test_rooms ORDER BY center_id, code, id'),
|
||||
@@ -1154,16 +1247,38 @@ function createRepository({ client, location, read, transaction, close }) {
|
||||
operations.push(auditOperation(log));
|
||||
await transaction(operations);
|
||||
},
|
||||
async createAdmitCard(registrationId, admitCard, log) {
|
||||
await transaction([
|
||||
async saveAdmissionArrangement(plan, cards, log) {
|
||||
const operations = [
|
||||
operation('DELETE FROM exam_arrangement_plans WHERE exam_id = ?', plan.examId),
|
||||
operation(
|
||||
`INSERT INTO exam_arrangement_plans (
|
||||
id, exam_id, number_rule_id, mixing_scope, random_seed, candidate_count, center_count,
|
||||
subject_assignment_count, subject_combination_count, same_school_center_rate,
|
||||
warnings_json, generated_by, generated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
plan.id, plan.examId, plan.numberRuleId, plan.mixingScope, plan.randomSeed,
|
||||
Number(plan.candidateCount), Number(plan.centerCount), Number(plan.subjectAssignmentCount),
|
||||
Number(plan.subjectCombinationCount), Number(plan.sameSchoolCenterRate), JSON.stringify(plan.warnings || []),
|
||||
optional(plan.generatedBy), plan.generatedAt
|
||||
)
|
||||
];
|
||||
for (const card of cards) {
|
||||
operations.push(operation(
|
||||
`INSERT INTO admit_cards (
|
||||
registration_id, card_number, test_center, room, seat, generated_at
|
||||
registration_id, plan_id, card_number, center_id, test_center, generated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
registrationId, admitCard.number, admitCard.testCenter, admitCard.room, admitCard.seat, admitCard.generatedAt
|
||||
),
|
||||
auditOperation(log)
|
||||
]);
|
||||
card.registrationId, plan.id, card.number, optional(card.centerId), card.testCenter, card.generatedAt
|
||||
));
|
||||
for (const assignment of card.assignments) operations.push(operation(
|
||||
`INSERT INTO admit_card_subjects (
|
||||
registration_id, subject_id, room_id, room, room_code, exam_room_code, seat, subject_signature
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
card.registrationId, assignment.subjectId, optional(assignment.roomId), assignment.roomName,
|
||||
assignment.roomCode, assignment.examRoomCode, assignment.seat, assignment.subjectSignature
|
||||
));
|
||||
}
|
||||
operations.push(auditOperation(log));
|
||||
await transaction(operations);
|
||||
},
|
||||
async createExam(exam, log) {
|
||||
const operations = [operation(
|
||||
|
||||
Reference in New Issue
Block a user