63 lines
5.0 KiB
JavaScript
63 lines
5.0 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { buildVolunteerPlacements, candidateTotalScore, publicAdmissionRows, remainingPlanQuota } from '../src/services/volunteer-admission.mjs';
|
|
|
|
const now = '2026-07-21T08:00:00.000Z';
|
|
let sequence = 0;
|
|
const db = {
|
|
users: [
|
|
{ id: 'u-high', candidateNumber: '20260001', displayName: '高分考生' },
|
|
{ id: 'u-low', candidateNumber: '20260002', displayName: '次高考生' },
|
|
{ id: 'u-sport', candidateNumber: '20260003', displayName: '特长考生' }
|
|
],
|
|
candidateProfiles: [
|
|
{ userId: 'u-high', name: '高分考生', schoolId: 'source-a', idNumber: '320101200901011234', phone: '13812345678', specialtyTypes: [] },
|
|
{ userId: 'u-low', name: '次高考生', schoolId: 'source-b', idNumber: '320101200902021234', phone: '13912345678', specialtyTypes: [] },
|
|
{ userId: 'u-sport', name: '特长考生', schoolId: 'source-b', idNumber: '320101200903031234', phone: '13712345678', specialtyTypes: ['田径'] }
|
|
],
|
|
schools: [
|
|
{ id: 'source-a', name: '生源学校 A' }, { id: 'source-b', name: '生源学校 B' },
|
|
{ id: 'target-a', name: '第一中学' }, { id: 'target-b', name: '第二中学' }
|
|
],
|
|
registrations: [
|
|
{ id: 'r-high', examId: 'exam', userId: 'u-high', status: 'approved', subjectIds: ['cn', 'math'] },
|
|
{ id: 'r-low', examId: 'exam', userId: 'u-low', status: 'approved', subjectIds: ['cn', 'math'] },
|
|
{ id: 'r-sport', examId: 'exam', userId: 'u-sport', status: 'approved', subjectIds: ['cn', 'math'] }
|
|
],
|
|
results: [
|
|
{ registrationId: 'r-high', subjectId: 'cn', score: 120, published: true }, { registrationId: 'r-high', subjectId: 'math', score: 130, published: true },
|
|
{ registrationId: 'r-low', subjectId: 'cn', score: 118, published: true }, { registrationId: 'r-low', subjectId: 'math', score: 126, published: true },
|
|
{ registrationId: 'r-sport', subjectId: 'cn', score: 105, published: true }, { registrationId: 'r-sport', subjectId: 'math', score: 110, published: true }
|
|
],
|
|
admissionRecords: [
|
|
{ id: 'plan-a', kind: 'plan', examId: 'exam', schoolId: 'target-a', status: 'approved', payload: { categories: [{ code: 'general', name: '普通生', quota: 1, specialtyType: '', indicatorAllocations: [] }] } },
|
|
{ id: 'plan-b', kind: 'plan', examId: 'exam', schoolId: 'target-b', status: 'approved', payload: { categories: [
|
|
{ code: 'general', name: '普通生', quota: 1, specialtyType: '', indicatorAllocations: [] },
|
|
{ code: 'sport', name: '田径特长生', quota: 1, specialtyType: '田径', indicatorAllocations: [{ sourceSchoolId: 'source-b', quota: 1 }] }
|
|
] } },
|
|
{ id: 'pref-high', kind: 'preference', examId: 'exam', userId: 'u-high', status: 'submitted', payload: { round: 1, choices: [{ schoolId: 'target-b', categoryCode: 'general' }, { schoolId: 'target-a', categoryCode: 'general' }] } },
|
|
{ id: 'pref-low', kind: 'preference', examId: 'exam', userId: 'u-low', status: 'submitted', payload: { round: 1, choices: [{ schoolId: 'target-b', categoryCode: 'general' }, { schoolId: 'target-a', categoryCode: 'general' }] } },
|
|
{ id: 'pref-sport', kind: 'preference', examId: 'exam', userId: 'u-sport', status: 'submitted', payload: { round: 1, choices: [{ schoolId: 'target-b', categoryCode: 'sport' }] } }
|
|
]
|
|
};
|
|
|
|
const setting = { examId: 'exam', payload: { round: 1 } };
|
|
const placements = buildVolunteerPlacements(db, setting, { uid: prefix => `${prefix}-${++sequence}`, nowIso: () => now });
|
|
assert.equal(candidateTotalScore(db, 'exam', 'u-high'), 250, '投档总分应取当次全部已发布科目之和');
|
|
assert.equal(placements.length, 3, '三个符合条件且计划充足的考生都应投档');
|
|
assert.equal(placements.find(item => item.userId === 'u-high').schoolId, 'target-b', '最高分考生应优先满足第一志愿');
|
|
assert.equal(placements.find(item => item.userId === 'u-low').schoolId, 'target-a', '第一志愿已满时应继续遵循下一志愿');
|
|
assert.equal(placements.find(item => item.userId === 'u-sport').payload.quotaBucket, 'indicator:source-b', '特长生指标应使用对应生源学校指标名额');
|
|
|
|
db.admissionRecords.push(...placements.map(item => ({ ...item, status: 'final' })));
|
|
const remaining = remainingPlanQuota(db, db.admissionRecords.find(item => item.id === 'plan-b'));
|
|
assert.equal(remaining.find(item => item.code === 'general').remaining, 0, '普通生计划占用应准确统计');
|
|
assert.equal(remaining.find(item => item.code === 'sport').remaining, 0, '特长生计划占用应准确统计');
|
|
const publicRows = publicAdmissionRows(db, 'exam');
|
|
assert.equal(publicRows[0].registrationNumber, '20260001', '公示必须公开报名号');
|
|
assert.equal(publicRows[0].name, '高分考生', '公示必须公开姓名');
|
|
assert.equal(publicRows[0].totalScore, 250, '公示必须公开总成绩');
|
|
assert.equal(publicRows[0].admittedSchool, '第二中学', '公示必须公开录取学校');
|
|
assert.ok(publicRows[0].idNumberMasked.includes('*') && !publicRows[0].idNumberMasked.includes('20090101'), '重要身份信息必须脱敏');
|
|
|
|
console.log('志愿投档、指标名额与脱敏公示测试通过');
|