PUT /api/candidate/profile

行政区划、学校班级、特长类别校验
证件号码唯一性
自动创建资料审核工作流
资料和用户显示名称原子更新

POST /api/candidate/registrations
资料审核状态、报名时间和科目校验
重复报名防护
自动选择负载最低的审批管理员
报名、科目和审批流原子写入
This commit is contained in:
2026-07-22 19:55:19 +08:00 Unverified
parent 07efa6813b
commit aecb0a04e7
16 changed files with 995 additions and 36 deletions
+103
View File
@@ -440,6 +440,108 @@ try {
throw 'Native candidate profile route was not available during onboarding'
}
$invalidSpecialtyBody = @{
name = '原生迁移注册考生'
gender = '女'
idNumber = 'SMOKE-INVALID-SPECIALTY'
phone = '13800000000'
email = 'candidate@example.test'
nativePlace = '江苏连云港'
address = '迁移测试路 1 号'
schoolId = $registrationSchool.id
classId = $registrationClass.id
provinceCode = '320000'
cityCode = '320700'
districtCode = '320706'
specialtyCategory = 'arts'
specialtyType = 'track_field'
} | ConvertTo-Json -Compress
$invalidSpecialty = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -Method Put -ContentType 'application/json' -Body $invalidSpecialtyBody -WebSession $registeredSession -SkipHttpErrorCheck
if ($invalidSpecialty.StatusCode -ne 400) {
throw 'Native candidate profile API accepted a mismatched specialty category and type'
}
$profileIdNumber = "SMOKE-NATIVE-$([guid]::NewGuid().ToString('N'))"
$profileBody = @{
name = '原生迁移注册考生'
gender = '女'
idNumber = $profileIdNumber
phone = '13800000000'
email = 'candidate@example.test'
address = '迁移测试路 1 号'
emergencyContact = '测试联系人'
emergencyPhone = '13900000000'
nativePlace = '江苏连云港'
birthDate = '2010-01-02'
ethnicity = '汉族'
postalCode = '222000'
guardianName = '测试监护人'
guardianPhone = '13700000000'
schoolId = $registrationSchool.id
classId = $registrationClass.id
provinceCode = '320000'
cityCode = '320700'
districtCode = '320706'
specialtyCategory = ''
specialtyType = ''
specialtyCertificate = ''
policyEligibility = ''
} | ConvertTo-Json -Compress
$profileUpdateResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/profile" -Method Put -ContentType 'application/json' -Body $profileBody -WebSession $registeredSession
if ($profileUpdateResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw 'Candidate profile update did not use the native ASP.NET Core endpoint'
}
$profileUpdate = $profileUpdateResponse.Content | ConvertFrom-Json
if ($profileUpdate.profile.profileCompleted -ne $true -or $profileUpdate.profile.districtName -ne '海州区' -or $profileUpdate.profile.status -ne 'pending') {
throw 'Native candidate profile update did not resolve the region or persist onboarding state'
}
$prematureRegistrationBody = @{ examId = 'not-approved-yet'; subjectIds = @('none') } | ConvertTo-Json -Compress
$prematureRegistration = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $prematureRegistrationBody -WebSession $registeredSession -SkipHttpErrorCheck
if ($prematureRegistration.StatusCode -ne 403) {
throw 'Native registration API did not require an approved candidate profile'
}
$candidateWriteSetup = Start-TestProcess -FileName $nodeExecutable -ArgumentList @(
'tests/helpers/prepare-candidate-write-smoke.mjs', $smokeDatabasePath, $registration.registrationNumber
) -Environment $nodeEnvironment
if (-not $candidateWriteSetup.WaitForExit(10000)) {
$candidateWriteSetup.Kill($true)
throw 'Timed out while preparing the native candidate write smoke test'
}
$candidateWriteSetupOutput = $candidateWriteSetup.StandardOutput.ReadToEnd().Trim()
$candidateWriteSetupError = $candidateWriteSetup.StandardError.ReadToEnd()
if ($candidateWriteSetup.ExitCode -ne 0) {
throw "Could not prepare the native candidate write smoke test`n$candidateWriteSetupError"
}
$candidateWriteSetup.Dispose()
$candidateWriteTarget = $candidateWriteSetupOutput | ConvertFrom-Json
$nativeRegistrationBody = @{
examId = $candidateWriteTarget.examId
subjectIds = @($candidateWriteTarget.subjectId)
} | ConvertTo-Json -Compress
$nativeRegistrationResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $nativeRegistrationBody -WebSession $registeredSession
if ($nativeRegistrationResponse.StatusCode -ne 201 -or $nativeRegistrationResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
throw 'Exam registration submission did not use the native ASP.NET Core endpoint'
}
$nativeRegistration = $nativeRegistrationResponse.Content | ConvertFrom-Json
if ($nativeRegistration.registration.status -ne 'pending' -or $nativeRegistration.registration.subjectIds.Count -ne 1) {
throw 'Native exam registration did not persist the selected subject and pending state'
}
$duplicateRegistration = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/registrations" -Method Post -ContentType 'application/json' -Body $nativeRegistrationBody -WebSession $registeredSession -SkipHttpErrorCheck
if ($duplicateRegistration.StatusCode -ne 409) {
throw 'Native exam registration did not reject a duplicate submission'
}
$legacyRegisteredSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
Invoke-RestMethod -Uri "$legacyBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $registeredLoginBody -WebSession $legacyRegisteredSession | Out-Null
foreach ($candidateWriteReadRoute in @('profile', 'registrations')) {
$legacyWriteRead = Invoke-WebRequest -Uri "$legacyBaseUrl/api/candidate/$candidateWriteReadRoute" -WebSession $legacyRegisteredSession
$nativeWriteRead = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/candidate/$candidateWriteReadRoute" -WebSession $registeredSession
Assert-JsonEquivalent -Expected $legacyWriteRead.Content -Actual $nativeWriteRead.Content -Label "Candidate write follow-up '$candidateWriteReadRoute'"
}
$nativeSession = [Microsoft.PowerShell.Commands.WebRequestSession]::new()
$nativeLoginResponse = Invoke-WebRequest -Uri "$nativeAuthBaseUrl/api/auth/login" -Method Post -ContentType 'application/json' -Body $loginBody -WebSession $nativeSession
if ($nativeLoginResponse.Headers['X-EIS-Implementation'] -ne 'aspnet-core') {
@@ -528,6 +630,7 @@ try {
DocumentCodes = 'passed'
NativeAuthentication = 'passed'
NativeCandidateReads = 'passed'
NativeCandidateWrites = 'passed'
} | Format-List
}
finally {