准考证编排
This commit is contained in:
+36
-4
@@ -286,7 +286,11 @@ try {
|
||||
registrationStart: new Date(now - hour).toISOString(), registrationEnd: new Date(now + 24 * hour).toISOString(),
|
||||
examStart: new Date(now + 48 * hour).toISOString(), examEnd: new Date(now + 60 * hour).toISOString(),
|
||||
admitDownloadStart: new Date(now - hour).toISOString(), admitDownloadEnd: new Date(now + 47 * hour).toISOString(),
|
||||
location: '测试考点', status: 'published', subjects: ['语文', '数学', '外语']
|
||||
location: '测试考点', status: 'published', subjects: [
|
||||
{ name: '语文', date: new Date(now + 48 * hour).toISOString().slice(0, 10), start: '09:00', end: '11:00', fee: 0, fullScore: 150, passScore: 90 },
|
||||
{ name: '数学', date: new Date(now + 48 * hour).toISOString().slice(0, 10), start: '13:00', end: '15:00', fee: 0, fullScore: 150, passScore: 90 },
|
||||
{ name: '外语', date: new Date(now + 48 * hour).toISOString().slice(0, 10), start: '15:30', end: '17:00', fee: 0, fullScore: 150, passScore: 90 }
|
||||
]
|
||||
}
|
||||
});
|
||||
assert.equal(createExam.response.status, 201);
|
||||
@@ -379,8 +383,32 @@ try {
|
||||
assert.equal(approveRegistration.data.registration.status, 'approved');
|
||||
assert.equal(approveRegistration.data.registration.registrationNumber, candidateNumber, '考试报名必须复用考生账户的固定报名号');
|
||||
|
||||
const generateAdmit = await admin.request(`/api/admin/registrations/${registrationId}/admit-card`, { method: 'POST', body: { testCenter: '海州市测试中学' } });
|
||||
assert.ok(generateAdmit.data.admitCard.number, '管理员应能生成准考证号');
|
||||
const arrangementContext = await admin.request('/api/admin/admission-arrangements');
|
||||
assert.equal(arrangementContext.data.rules.length, 4, '系统应预置四种准考证号规则');
|
||||
assert.deepEqual(arrangementContext.data.mixingScopes.map(item => item.code), ['class', 'school', 'district', 'city', 'province'], '应支持班、校、县区、市、省五级混编');
|
||||
for (const scope of arrangementContext.data.mixingScopes) {
|
||||
const preview = await admin.request(`/api/admin/exams/${exam.id}/admission-arrangement/preview`, { method: 'POST', body: {
|
||||
mixingScope: scope.code, numberRuleId: arrangementContext.data.rules[0].id, seed: `scope-${scope.code}`
|
||||
} });
|
||||
assert.equal(preview.response.status, 200, `${scope.name}应通过容量与同考点约束预检`);
|
||||
}
|
||||
for (const rule of arrangementContext.data.rules) {
|
||||
const preview = await admin.request(`/api/admin/exams/${exam.id}/admission-arrangement/preview`, { method: 'POST', body: {
|
||||
mixingScope: 'school', numberRuleId: rule.id, seed: `rule-${rule.code}`
|
||||
} });
|
||||
assert.equal(preview.response.status, 200, `${rule.name}应能生成有效号码`);
|
||||
assert.equal(new Set(preview.data.samples.map(item => item.number)).size, preview.data.samples.length, `${rule.name}生成的样例号码不得重复`);
|
||||
}
|
||||
const arrangementBody = { mixingScope: 'school', numberRuleId: 'admit_rule_district_room_seat', seed: 'system-test-stable' };
|
||||
const arrangementPreview = await admin.request(`/api/admin/exams/${exam.id}/admission-arrangement/preview`, { method: 'POST', body: arrangementBody });
|
||||
assert.equal(arrangementPreview.response.status, 200, '正式写入前应可预检整场编排');
|
||||
assert.ok(arrangementPreview.data.summary.subjectAssignmentCount >= arrangementPreview.data.summary.candidateCount, '预检应统计全部科次座位');
|
||||
const generateAdmit = await admin.request(`/api/admin/exams/${exam.id}/admission-arrangement`, { method: 'POST', body: arrangementBody });
|
||||
const generatedCard = generateAdmit.data.cards.find(item => item.registrationId === registrationId);
|
||||
assert.ok(generatedCard.number, '管理员应能按整场考试批量生成准考证号');
|
||||
assert.equal(new Set(generatedCard.assignments.map(item => item.centerId)).size, 1, '同一考生所有科目必须固定在同一考点');
|
||||
assert.equal(generatedCard.assignments.length, submitRegistration.data.registration.subjectIds.length, '每个报考科目都必须有独立考场座位');
|
||||
assert.equal((await admin.request(`/api/admin/registrations/${registrationId}/admit-card`, { method: 'POST', body: {} })).response.status, 410, '旧单人生成入口应明确停用');
|
||||
|
||||
const candidateRegistrations = await candidate.request('/api/candidate/registrations');
|
||||
const candidateRegistration = candidateRegistrations.data.registrations.find(item => item.id === registrationId);
|
||||
@@ -409,7 +437,10 @@ try {
|
||||
await futureSchoolClient.request(`/api/admin/registrations/${futureRegistrationId}`, { method: 'PATCH', body: { status: 'approved', reviewNote: '学校通过' } });
|
||||
const approvedFutureRegistration = await admin.request(`/api/admin/registrations/${futureRegistrationId}`, { method: 'PATCH', body: { status: 'approved', reviewNote: '通过' } });
|
||||
assert.equal(approvedFutureRegistration.data.registration.registrationNumber, candidateNumber, '同一考生参加不同考试必须保持相同报名号');
|
||||
await admin.request(`/api/admin/registrations/${futureRegistrationId}/admit-card`, { method: 'POST', body: { testCenter: '海州市测试中学' } });
|
||||
const futureArrangement = await admin.request(`/api/admin/exams/${futureExam.id}/admission-arrangement`, { method: 'POST', body: {
|
||||
mixingScope: 'district', numberRuleId: 'admit_rule_candidate_school_room_seat', seed: 'future-window-test'
|
||||
} });
|
||||
assert.equal(futureArrangement.response.status, 200, '不同考试应分别保存独立编排方案');
|
||||
const earlyDownload = await candidate.request(`/api/candidate/registrations/${futureRegistrationId}/admit-card`);
|
||||
assert.equal(earlyDownload.response.status, 403, '准考证下载窗口开放前必须拒绝下载');
|
||||
|
||||
@@ -479,6 +510,7 @@ try {
|
||||
console.log('✓ 超级、校级、班级管理员的数据范围与权限隔离');
|
||||
console.log('✓ 固定报名号账户、首次强制改密、完整资料与注册开关');
|
||||
console.log('✓ 多科目考试创建与考生自主选科报名');
|
||||
console.log('✓ 五级混编、四种号码规则、多科目同考点与逐科座位');
|
||||
console.log('✓ 审批流程设计、同级转交与超级管理员监督退回');
|
||||
console.log('✓ 校级按班级批量申领、终审原子建号与结果返回');
|
||||
console.log('✓ 结构化考点考场档案、变更审批与班级只读边界');
|
||||
|
||||
Reference in New Issue
Block a user