Files
chis_osi/mapping/health_record_test.go
T
ilaandClaude Opus 4.8 f95a779daa feat(osi): 实现 JKDA 档案 Create/Update 与创建请求契约(T-206)
- contract/jkda.go 补创建请求结构体(healthRecord + manageInfo + 既往史节点)
- osi/jkda.go 新增 CreateHealthRecord/UpdateHealthRecord
- osi/codes.go 登记 JKDA00001 create / JKDA00003 update serviceId 与路径
- mapping 映射创建路径(真实字典快照反查主数据)
- 代码与单测完成;真实 create 待安全测试档案与写入授权(见 tasks.md T-206 BLOCKED)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:11:17 +08:00

171 lines
5.9 KiB
Go

package mapping
import "testing"
func TestBuildHealthRecordCreateUsesMappedFieldsAndCheckID(t *testing.T) {
mapped, errs := MapHealthRecord(validPHISHealthRecord(), MapContext{Dicts: DefaultDictSnapshot()})
if len(errs) != 0 {
t.Fatalf("errors = %#v", errs)
}
create := BuildHealthRecordCreate(mapped)
if create.HealthRecord.CheckID != mapped.CheckID {
t.Fatalf("checkId = %q, want %q", create.HealthRecord.CheckID, mapped.CheckID)
}
if create.HealthRecord.IDCard != mapped.IDCard || create.HealthRecord.PersonName != mapped.PersonName {
t.Fatalf("healthRecord demographics = %#v", create.HealthRecord)
}
if create.HealthRecord.RegionCode != mapped.RegionCode || create.HealthRecord.ManaDoctorID != mapped.ManaDoctorID || create.HealthRecord.ManaUnitID != mapped.ManaUnitID || create.HealthRecord.CreateUser != mapped.ManaDoctorID || create.HealthRecord.CreateUnit != mapped.ManaUnitID {
t.Fatalf("management fields = %#v", create.HealthRecord)
}
if create.BaseInfo.IDCard != mapped.IDCard || create.BaseInfo.PersonName != mapped.PersonName {
t.Fatalf("baseInfo = %#v", create.BaseInfo)
}
}
func TestMapHealthRecordMapsDirectFieldsDictsAndCheckID(t *testing.T) {
src := validPHISHealthRecord()
got, errs := MapHealthRecord(src, MapContext{Dicts: DefaultDictSnapshot()})
if len(errs) != 0 {
t.Fatalf("errors = %#v", errs)
}
if got.IDCard != src.IDCard || got.PersonName != src.PersonName || got.Birthday != src.Birthday || got.MobileNumber != src.MobileNumber {
t.Fatalf("direct fields not mapped: %#v", got)
}
if got.SexCode != "1" || got.NationCode != "01" || got.EducationCode != "31" || got.WorkCode != "Y" {
t.Fatalf("dict fields not mapped: %#v", got)
}
if got.MaritalStatusCode != "20" || got.BloodTypeCode != "4" || got.RhBloodCode != "1" || got.InsuranceCode != "01" {
t.Fatalf("dict fields not mapped: %#v", got)
}
if got.RegionCode != src.RegionCode || got.ManaDoctorID != src.ManaDoctorID || got.ManaUnitID != src.ManaUnitID {
t.Fatalf("management fields not mapped: %#v", got)
}
if got.CheckID == "" || len(got.CheckID) != 20 {
t.Fatalf("checkId = %q", got.CheckID)
}
}
func TestMapHealthRecordReportsRequiredFieldErrors(t *testing.T) {
src := validPHISHealthRecord()
src.IDCard = ""
src.PersonName = ""
src.ManaUnitID = ""
_, errs := MapHealthRecord(src, MapContext{Dicts: DefaultDictSnapshot()})
if len(errs) != 3 {
t.Fatalf("errors = %#v", errs)
}
assertValidationField(t, errs, "idCard", "required")
assertValidationField(t, errs, "personName", "required")
assertValidationField(t, errs, "manaUnitId", "required")
}
func TestMapHealthRecordReportsDictValidationErrors(t *testing.T) {
src := validPHISHealthRecord()
src.SexCode = "bad"
_, errs := MapHealthRecord(src, MapContext{Dicts: DefaultDictSnapshot()})
if len(errs) != 1 {
t.Fatalf("errors = %#v", errs)
}
if errs[0].Field != "sexCode" || errs[0].Code != "bad" || errs[0].Direction != DirectionPHISToOSI {
t.Fatalf("error = %#v", errs[0])
}
}
func TestMapHealthRecordUsesInjectedDictSnapshot(t *testing.T) {
src := validPHISHealthRecord()
src.SexCode = "M"
dicts := DefaultDictSnapshot()
dicts.Sex = Dict{Name: "sex", Field: "sexCode", Entries: []Entry{{PHIS: "M", OSI: "1", Name: "男"}}}
got, errs := MapHealthRecord(src, MapContext{Dicts: dicts})
if len(errs) != 0 {
t.Fatalf("errors = %#v", errs)
}
if got.SexCode != "1" {
t.Fatalf("SexCode = %q", got.SexCode)
}
}
func TestMapHealthRecordUsesMasterDataLookupWhenCodesMissing(t *testing.T) {
src := validPHISHealthRecord()
src.RegionCode = ""
src.ManaDoctorID = ""
src.ManaUnitID = ""
src.RegionName = "测试网格"
src.ManaDoctorName = "测试医生"
src.ManaUnitName = "测试机构"
got, errs := MapHealthRecord(src, MapContext{
Dicts: DefaultDictSnapshot(),
MasterData: fakeMasterDataLookup{},
})
if len(errs) != 0 {
t.Fatalf("errors = %#v", errs)
}
if got.RegionCode != "441625000000" || got.ManaDoctorID != "doc-001" || got.ManaUnitID != "123456789" {
t.Fatalf("master data not resolved: %#v", got)
}
}
func TestGenerateCheckIDIsDeterministicAndVersionSensitive(t *testing.T) {
first := GenerateCheckID("PHIS", "JKDA", "record-001", "20260707010101")
second := GenerateCheckID("PHIS", "JKDA", "record-001", "20260707010101")
third := GenerateCheckID("PHIS", "JKDA", "record-001", "20260708010101")
if first != second {
t.Fatalf("checkId not deterministic: %q != %q", first, second)
}
if len(first) != 20 {
t.Fatalf("checkId length = %d, want 20", len(first))
}
if first == third {
t.Fatalf("version change did not affect checkId: %q", first)
}
}
type fakeMasterDataLookup struct{}
func (fakeMasterDataLookup) RegionCodeByName(name string) (string, bool) {
return map[string]string{"测试网格": "441625000000"}[name], name == "测试网格"
}
func (fakeMasterDataLookup) DoctorIDByName(name string) (string, bool) {
return map[string]string{"测试医生": "doc-001"}[name], name == "测试医生"
}
func (fakeMasterDataLookup) ManaUnitIDByName(name string) (string, bool) {
return map[string]string{"测试机构": "123456789"}[name], name == "测试机构"
}
func validPHISHealthRecord() PHISHealthRecord {
return PHISHealthRecord{
SourceSystem: "PHIS",
SourceRecordID: "record-001",
UpdatedAt: "20260707010101",
IDCard: "440000********1234",
PersonName: "测试人员",
SexCode: "1",
Birthday: "1970-01-01",
MobileNumber: "13900000000",
RegionCode: "441625000000",
ManaDoctorID: "D001",
ManaUnitID: "123456789",
NationCode: "01",
EducationCode: "31",
WorkCode: "Y",
MaritalStatusCode: "20",
BloodTypeCode: "4",
RhBloodCode: "1",
InsuranceCode: "01",
}
}
func assertValidationField(t *testing.T, errs []ValidationError, field string, reason string) {
t.Helper()
for _, err := range errs {
if err.Field == field && err.Reason == reason {
return
}
}
t.Fatalf("missing validation error field=%s reason=%s in %#v", field, reason, errs)
}