Add hierarchical region data to candidate and center records

This commit is contained in:
2026-07-20 11:50:51 +08:00 Unverified
parent 352f471ed0
commit c5446d5241
21 changed files with 387 additions and 64 deletions
+78 -29
View File
@@ -53,7 +53,7 @@ function buildSeedOperations(state) {
const nullable = value => value == null || value === '' ? null : value;
add(
'UPDATE schema_metadata SET schema_version = 6, app_version = ?, self_registration_enabled = ?, created_at = ? WHERE id = 1',
'UPDATE schema_metadata SET schema_version = 7, 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()
);
@@ -90,13 +90,16 @@ function buildSeedOperations(state) {
for (const profile of state.candidateProfiles) {
add(
`INSERT INTO candidate_profiles (
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id, address,
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id,
province_code, province_name, city_code, city_name, district_code, district_name, address,
emergency_contact, emergency_phone, native_place, birth_date, ethnicity, postal_code, guardian_name,
guardian_phone, profile_completed, status, review_note, reviewed_at, reviewer_id, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
profile.id, profile.userId, profile.name, nullable(profile.gender), profile.idNumber, profile.phone,
nullable(profile.email), nullable(profile.school), nullable(profile.grade), nullable(profile.schoolId),
nullable(profile.classId), nullable(profile.address),
nullable(profile.classId), nullable(profile.provinceCode), nullable(profile.provinceName),
nullable(profile.cityCode), nullable(profile.cityName), nullable(profile.districtCode), nullable(profile.districtName),
nullable(profile.address),
nullable(profile.emergencyContact), nullable(profile.emergencyPhone), nullable(profile.nativePlace), nullable(profile.birthDate),
nullable(profile.ethnicity), nullable(profile.postalCode), nullable(profile.guardianName), nullable(profile.guardianPhone),
profile.profileCompleted ? 1 : 0, profile.status, nullable(profile.reviewNote),
@@ -171,10 +174,13 @@ function buildSeedOperations(state) {
for (const center of state.testCenters) {
add(
`INSERT INTO test_centers (
id, school_id, code, name, address, contact, manager_name, manager_phone, emergency_phone,
id, school_id, code, name, province_code, province_name, city_code, city_name, district_code, district_name,
address, contact, manager_name, manager_phone, emergency_phone,
gate_open_time, transport, status, notes, rooms, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.code, center.name, center.address, nullable(center.contact),
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.code, center.name,
center.provinceCode, center.provinceName, center.cityCode, center.cityName, center.districtCode, center.districtName,
center.address, nullable(center.contact),
nullable(center.managerName), nullable(center.managerPhone), nullable(center.emergencyPhone),
nullable(center.gateOpenTime), nullable(center.transport), center.status || 'active', nullable(center.notes),
center.rooms || '', center.updatedAt
@@ -194,11 +200,14 @@ function buildSeedOperations(state) {
for (const request of state.centerChangeRequests) {
add(
`INSERT INTO center_change_requests (
id, center_id, school_id, request_type, code, name, address, contact, manager_name, manager_phone,
id, center_id, school_id, request_type, code, name,
province_code, province_name, city_code, city_name, district_code, district_name,
address, contact, manager_name, manager_phone,
emergency_phone, gate_open_time, transport, center_status, notes, status, review_note,
requested_by, created_at, reviewed_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
request.id, nullable(request.centerId), request.schoolId, request.requestType, request.code, request.name,
request.provinceCode, request.provinceName, request.cityCode, request.cityName, request.districtCode, request.districtName,
request.address, nullable(request.contact), nullable(request.managerName), nullable(request.managerPhone),
nullable(request.emergencyPhone), nullable(request.gateOpenTime), nullable(request.transport),
request.centerStatus || 'active', nullable(request.notes), request.status, nullable(request.reviewNote),
@@ -400,6 +409,12 @@ function stateFromRows(rows) {
grade: row.grade || '',
schoolId: row.school_id || null,
classId: row.class_id || null,
provinceCode: row.province_code || '',
provinceName: row.province_name || '',
cityCode: row.city_code || '',
cityName: row.city_name || '',
districtCode: row.district_code || '',
districtName: row.district_name || '',
address: row.address || '',
emergencyContact: row.emergency_contact || '',
emergencyPhone: row.emergency_phone || '',
@@ -475,6 +490,12 @@ function stateFromRows(rows) {
schoolId: row.school_id,
code: row.code || '',
name: row.name,
provinceCode: row.province_code || '',
provinceName: row.province_name || '',
cityCode: row.city_code || '',
cityName: row.city_name || '',
districtCode: row.district_code || '',
districtName: row.district_name || '',
address: row.address,
contact: row.contact || '',
managerName: row.manager_name || '',
@@ -509,6 +530,12 @@ function stateFromRows(rows) {
requestType: row.request_type,
code: row.code,
name: row.name,
provinceCode: row.province_code || '',
provinceName: row.province_name || '',
cityCode: row.city_code || '',
cityName: row.city_name || '',
districtCode: row.district_code || '',
districtName: row.district_name || '',
address: row.address,
contact: row.contact || '',
managerName: row.manager_name || '',
@@ -730,13 +757,16 @@ function createRepository({ client, location, read, transaction, close }) {
),
operation(
`INSERT INTO candidate_profiles (
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id, address,
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id,
province_code, province_name, city_code, city_name, district_code, district_name, address,
emergency_contact, emergency_phone, native_place, birth_date, ethnicity, postal_code, guardian_name,
guardian_phone, profile_completed, status, review_note, reviewed_at, reviewer_id, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
profile.id, profile.userId, profile.name, optional(profile.gender), profile.idNumber, profile.phone,
optional(profile.email), optional(profile.school), optional(profile.grade), optional(profile.schoolId),
optional(profile.classId), optional(profile.address),
optional(profile.classId), optional(profile.provinceCode), optional(profile.provinceName),
optional(profile.cityCode), optional(profile.cityName), optional(profile.districtCode), optional(profile.districtName),
optional(profile.address),
optional(profile.emergencyContact), optional(profile.emergencyPhone), optional(profile.nativePlace), optional(profile.birthDate),
optional(profile.ethnicity), optional(profile.postalCode), optional(profile.guardianName), optional(profile.guardianPhone),
profile.profileCompleted ? 1 : 0, profile.status, optional(profile.reviewNote),
@@ -771,13 +801,16 @@ function createRepository({ client, location, read, transaction, close }) {
const operations = [
operation(
`UPDATE candidate_profiles SET
name = ?, gender = ?, id_number = ?, phone = ?, email = ?, school = ?, grade = ?, address = ?,
name = ?, gender = ?, id_number = ?, phone = ?, email = ?, school = ?, grade = ?,
province_code = ?, province_name = ?, city_code = ?, city_name = ?, district_code = ?, district_name = ?, address = ?,
school_id = ?, class_id = ?, emergency_contact = ?, emergency_phone = ?, status = ?, review_note = ?,
native_place = ?, birth_date = ?, ethnicity = ?, postal_code = ?, guardian_name = ?, guardian_phone = ?,
profile_completed = ?, reviewed_at = ?, reviewer_id = ?, updated_at = ?
WHERE id = ?`,
profile.name, optional(profile.gender), profile.idNumber, profile.phone, optional(profile.email),
optional(profile.school), optional(profile.grade), optional(profile.address), optional(profile.schoolId),
optional(profile.school), optional(profile.grade), optional(profile.provinceCode), optional(profile.provinceName),
optional(profile.cityCode), optional(profile.cityName), optional(profile.districtCode), optional(profile.districtName),
optional(profile.address), optional(profile.schoolId),
optional(profile.classId), optional(profile.emergencyContact), optional(profile.emergencyPhone), profile.status,
optional(profile.reviewNote), optional(profile.nativePlace), optional(profile.birthDate), optional(profile.ethnicity),
optional(profile.postalCode), optional(profile.guardianName), optional(profile.guardianPhone), profile.profileCompleted ? 1 : 0, optional(profile.reviewedAt),
@@ -909,13 +942,16 @@ function createRepository({ client, location, read, transaction, close }) {
),
operation(
`INSERT INTO candidate_profiles (
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id, address,
id, user_id, name, gender, id_number, phone, email, school, grade, school_id, class_id,
province_code, province_name, city_code, city_name, district_code, district_name, address,
emergency_contact, emergency_phone, native_place, birth_date, ethnicity, postal_code, guardian_name,
guardian_phone, profile_completed, status, review_note, reviewed_at, reviewer_id, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
profile.id, profile.userId, profile.name, optional(profile.gender), profile.idNumber, profile.phone,
optional(profile.email), profile.school, profile.grade, profile.schoolId, profile.classId,
optional(profile.address), optional(profile.emergencyContact), optional(profile.emergencyPhone),
optional(profile.provinceCode), optional(profile.provinceName), optional(profile.cityCode), optional(profile.cityName),
optional(profile.districtCode), optional(profile.districtName), optional(profile.address),
optional(profile.emergencyContact), optional(profile.emergencyPhone),
optional(profile.nativePlace), optional(profile.birthDate), optional(profile.ethnicity), optional(profile.postalCode),
optional(profile.guardianName), optional(profile.guardianPhone), 0, profile.status, optional(profile.reviewNote),
optional(profile.reviewedAt), optional(profile.reviewerId), profile.updatedAt
@@ -1014,14 +1050,19 @@ function createRepository({ client, location, read, transaction, close }) {
const centerOperation = isNew
? operation(
`INSERT INTO test_centers (
id, school_id, name, address, contact, rooms, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.name, center.address, optional(center.contact), center.rooms, center.updatedAt
id, school_id, code, name, province_code, province_name, city_code, city_name, district_code, district_name,
address, contact, rooms, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.code, center.name,
center.provinceCode, center.provinceName, center.cityCode, center.cityName, center.districtCode, center.districtName,
center.address, optional(center.contact), center.rooms, center.updatedAt
)
: operation(
`UPDATE test_centers SET
name = ?, address = ?, contact = ?, rooms = ?, updated_at = ? WHERE id = ?`,
center.name, center.address, optional(center.contact), center.rooms, center.updatedAt, center.id
code = ?, name = ?, province_code = ?, province_name = ?, city_code = ?, city_name = ?,
district_code = ?, district_name = ?, address = ?, contact = ?, rooms = ?, updated_at = ? WHERE id = ?`,
center.code, center.name, center.provinceCode, center.provinceName, center.cityCode, center.cityName,
center.districtCode, center.districtName, center.address, optional(center.contact), center.rooms, center.updatedAt, center.id
);
await transaction([centerOperation, auditOperation(log)]);
},
@@ -1029,11 +1070,14 @@ function createRepository({ client, location, read, transaction, close }) {
const operations = [
operation(
`INSERT INTO center_change_requests (
id, center_id, school_id, request_type, code, name, address, contact, manager_name, manager_phone,
id, center_id, school_id, request_type, code, name,
province_code, province_name, city_code, city_name, district_code, district_name,
address, contact, manager_name, manager_phone,
emergency_phone, gate_open_time, transport, center_status, notes, status, review_note,
requested_by, created_at, reviewed_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
request.id, optional(request.centerId), request.schoolId, request.requestType, request.code, request.name,
request.provinceCode, request.provinceName, request.cityCode, request.cityName, request.districtCode, request.districtName,
request.address, optional(request.contact), optional(request.managerName), optional(request.managerPhone),
optional(request.emergencyPhone), optional(request.gateOpenTime), optional(request.transport),
request.centerStatus, optional(request.notes), request.status, optional(request.reviewNote),
@@ -1069,10 +1113,13 @@ function createRepository({ client, location, read, transaction, close }) {
if (request.requestType === 'create') {
operations.push(operation(
`INSERT INTO test_centers (
id, school_id, code, name, address, contact, manager_name, manager_phone, emergency_phone,
id, school_id, code, name, province_code, province_name, city_code, city_name, district_code, district_name,
address, contact, manager_name, manager_phone, emergency_phone,
gate_open_time, transport, status, notes, rooms, updated_at
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.code, center.name, center.address, optional(center.contact),
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
center.id, center.schoolId, center.code, center.name,
center.provinceCode, center.provinceName, center.cityCode, center.cityName, center.districtCode, center.districtName,
center.address, optional(center.contact),
optional(center.managerName), optional(center.managerPhone), optional(center.emergencyPhone),
optional(center.gateOpenTime), optional(center.transport), center.status, optional(center.notes),
center.rooms || '', center.updatedAt
@@ -1080,10 +1127,12 @@ function createRepository({ client, location, read, transaction, close }) {
} else {
operations.push(operation(
`UPDATE test_centers SET
code = ?, name = ?, address = ?, contact = ?, manager_name = ?, manager_phone = ?,
code = ?, name = ?, province_code = ?, province_name = ?, city_code = ?, city_name = ?,
district_code = ?, district_name = ?, address = ?, contact = ?, manager_name = ?, manager_phone = ?,
emergency_phone = ?, gate_open_time = ?, transport = ?, status = ?, notes = ?, rooms = ?, updated_at = ?
WHERE id = ?`,
center.code, center.name, center.address, optional(center.contact), optional(center.managerName),
center.code, center.name, center.provinceCode, center.provinceName, center.cityCode, center.cityName,
center.districtCode, center.districtName, center.address, optional(center.contact), optional(center.managerName),
optional(center.managerPhone), optional(center.emergencyPhone), optional(center.gateOpenTime),
optional(center.transport), center.status, optional(center.notes), center.rooms || '', center.updatedAt, center.id
));