diff --git a/contract/jkda.go b/contract/jkda.go index f8ee234..a762a71 100644 --- a/contract/jkda.go +++ b/contract/jkda.go @@ -97,3 +97,49 @@ type FamilyMiddle struct { LivestockColumn string `json:"livestockColumn,omitempty"` IsFillSHHJ string `json:"isFillShhj,omitempty"` } + +type HealthRecordCreate struct { + BaseInfo HealthRecordBaseInfo `json:"baseInfo,omitempty"` + ManageInfo ManageInfo `json:"manageInfo"` + HealthRecord HealthRecordCreateInfo `json:"healthRecord"` + PastHistory *PastHistory `json:"pastHistory,omitempty"` + PastDiseases []PastDisease `json:"jwsjb,omitempty"` + PastSurgeries []PastSurgery `json:"jwsss,omitempty"` + PastTraumas []PastTrauma `json:"jwsws,omitempty"` + PastTransfusions []PastBloodTx `json:"jwssx,omitempty"` + FamilyMiddle *FamilyMiddle `json:"familyMiddle,omitempty"` +} + +type HealthRecordBaseInfo struct { + IDCard string `json:"idCard,omitempty"` + PersonName string `json:"personName,omitempty"` + PHRID string `json:"phrId,omitempty"` +} + +type HealthRecordCreateInfo struct { + CheckID string `json:"checkId,omitempty"` + IDCard string `json:"idCard,omitempty"` + PersonName string `json:"personName,omitempty"` + SexCode string `json:"sexCode,omitempty"` + Birthday string `json:"birthday,omitempty"` + PhrID string `json:"phrId,omitempty"` + MobileNumber string `json:"mobileNumber,omitempty"` + RegionCode string `json:"regionCode,omitempty"` + ManaDoctorID string `json:"manaDoctorId,omitempty"` + ManaUnitID string `json:"manaUnitId,omitempty"` + CreateUser string `json:"createUser,omitempty"` + CreateUnit string `json:"createUnit,omitempty"` + NationCode string `json:"nationCode,omitempty"` + EducationCode string `json:"educationCode,omitempty"` + WorkCode string `json:"workCode,omitempty"` + MaritalStatusCode string `json:"maritalStatusCode,omitempty"` + BloodTypeCode string `json:"bloodTypeCode,omitempty"` + RhBloodCode string `json:"rhBloodCode,omitempty"` + InsuranceCode string `json:"insuranceCode,omitempty"` + AddressNumber string `json:"addressNumber,omitempty"` +} + +type HealthRecordSaveResult struct { + PhrID string `json:"phrId"` + CreateUnit string `json:"createUnit,omitempty"` +} diff --git a/contract/jkda_test.go b/contract/jkda_test.go index 6c451f2..6f14cee 100644 --- a/contract/jkda_test.go +++ b/contract/jkda_test.go @@ -135,3 +135,47 @@ func TestFindHealthRecordResponseDeserializesDataArray(t *testing.T) { t.Fatalf("checkId = %#v, want nil", response.Data[0].HealthRecord.CheckID) } } +func TestHealthRecordCreateSerializesCreateFieldNames(t *testing.T) { + req := HealthRecordCreate{ + BaseInfo: HealthRecordBaseInfo{ + IDCard: "440000********1234", + PersonName: "测试人员", + }, + HealthRecord: HealthRecordCreateInfo{ + CheckID: "CHK2026070700000001", + IDCard: "440000********1234", + PersonName: "测试人员", + SexCode: "1", + Birthday: "1970-01-01", + MobileNumber: "13900000000", + RegionCode: "441625000000", + ManaDoctorID: "doc-001", + ManaUnitID: "123456789", + AddressNumber: "101号", + }, + PastHistory: &PastHistory{YWGMS: "0101"}, + } + + raw, err := json.Marshal(req) + if err != nil { + t.Fatalf("Marshal: %v", err) + } + var got map[string]any + if err := json.Unmarshal(raw, &got); err != nil { + t.Fatalf("Unmarshal: %v", err) + } + healthRecord := got["healthRecord"].(map[string]any) + if healthRecord["checkId"] != "CHK2026070700000001" { + t.Fatalf("healthRecord = %#v", healthRecord) + } + if healthRecord["addressNumber"] != "101号" { + t.Fatalf("addressNumber missing: %#v", healthRecord) + } + if _, ok := healthRecord["adressNumber"]; ok { + t.Fatalf("create request used response typo adressNumber: %#v", healthRecord) + } + baseInfo := got["baseInfo"].(map[string]any) + if baseInfo["idCard"] != "440000********1234" || baseInfo["personName"] != "测试人员" { + t.Fatalf("baseInfo = %#v", baseInfo) + } +} diff --git a/mapping/health_record.go b/mapping/health_record.go index 77b7344..b790028 100644 --- a/mapping/health_record.go +++ b/mapping/health_record.go @@ -1,5 +1,7 @@ package mapping +import "chis_osi/contract" + type PHISHealthRecord struct { SourceSystem string SourceRecordID string @@ -158,3 +160,31 @@ func mapCode(dict Dict, code string, errs *[]ValidationError) string { } return mapped } +func BuildHealthRecordCreate(mapped MappedHealthRecord) contract.HealthRecordCreate { + return contract.HealthRecordCreate{ + BaseInfo: contract.HealthRecordBaseInfo{ + IDCard: mapped.IDCard, + PersonName: mapped.PersonName, + }, + HealthRecord: contract.HealthRecordCreateInfo{ + CheckID: mapped.CheckID, + IDCard: mapped.IDCard, + PersonName: mapped.PersonName, + SexCode: mapped.SexCode, + Birthday: mapped.Birthday, + MobileNumber: mapped.MobileNumber, + RegionCode: mapped.RegionCode, + ManaDoctorID: mapped.ManaDoctorID, + ManaUnitID: mapped.ManaUnitID, + CreateUser: mapped.ManaDoctorID, + CreateUnit: mapped.ManaUnitID, + NationCode: mapped.NationCode, + EducationCode: mapped.EducationCode, + WorkCode: mapped.WorkCode, + MaritalStatusCode: mapped.MaritalStatusCode, + BloodTypeCode: mapped.BloodTypeCode, + RhBloodCode: mapped.RhBloodCode, + InsuranceCode: mapped.InsuranceCode, + }, + } +} diff --git a/mapping/health_record_test.go b/mapping/health_record_test.go index 3960a0f..c01ecdf 100644 --- a/mapping/health_record_test.go +++ b/mapping/health_record_test.go @@ -2,6 +2,26 @@ 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()}) diff --git a/osi/client.go b/osi/client.go index 2bff7ba..685ab4e 100644 --- a/osi/client.go +++ b/osi/client.go @@ -49,6 +49,18 @@ func NewClient(config ClientConfig) *Client { } func (c *Client) Call(ctx context.Context, serviceID string, baseInfo any, out any) (Result, error) { + uploadInfo := contract.UploadInfo{ + BaseInfo: baseInfo, + ManageInfo: contract.ManageInfo{ + DSFMC: c.config.UserName, + OperateUser: c.config.OperateUser, + OperateUnit: c.operateUnit(), + }, + } + return c.callUploadInfo(ctx, serviceID, uploadInfo, out) +} + +func (c *Client) callUploadInfo(ctx context.Context, serviceID string, uploadInfo any, out any) (Result, error) { if c.transport == nil { transport, err := NewTransport(TransportConfig{}) if err != nil { @@ -63,15 +75,8 @@ func (c *Client) Call(ctx context.Context, serviceID string, baseInfo any, out a } payload := contract.Envelope{ - ServiceID: serviceID, - UploadInfo: contract.UploadInfo{ - BaseInfo: baseInfo, - ManageInfo: contract.ManageInfo{ - DSFMC: c.config.UserName, - OperateUser: c.config.OperateUser, - OperateUnit: c.operateUnit(), - }, - }, + ServiceID: serviceID, + UploadInfo: uploadInfo, } targetURL := c.urlFor(path) diff --git a/osi/codes.go b/osi/codes.go index 8ed2553..0b5d7ec 100644 --- a/osi/codes.go +++ b/osi/codes.go @@ -6,7 +6,9 @@ import ( ) const ( + ServiceIDJKDACreate = "JKDA00001" ServiceIDJKDAFind = "JKDA00002" + ServiceIDJKDAUpdate = "JKDA00003" ServiceIDJKDAFindRqbj = "JKDA00005" ServiceIDGridAddress = "WGDZ00001" ServiceIDDoctors = "ZRYS00001" @@ -17,7 +19,9 @@ const ( const codeRetryableTimeout = "405" var servicePaths = map[string]string{ + ServiceIDJKDACreate: "/jkda/create", ServiceIDJKDAFind: "/auto/jkda/find", + ServiceIDJKDAUpdate: "/jkda/update", ServiceIDJKDAFindRqbj: "/jkda/findrqbj", ServiceIDGridAddress: "/auto/wgdzcx/query", ServiceIDDoctors: "/auto/zryscx/query", diff --git a/osi/jkda.go b/osi/jkda.go index 3c43b70..59c0a31 100644 --- a/osi/jkda.go +++ b/osi/jkda.go @@ -23,6 +23,19 @@ type PersonSignResult struct { PersonSign string `json:"personSign"` } +func (c *Client) CreateHealthRecord(ctx context.Context, req contract.HealthRecordCreate) (contract.HealthRecordSaveResult, Result, error) { + req.ManageInfo = c.manageInfo() + var out contract.HealthRecordSaveResult + result, err := c.callUploadInfo(ctx, ServiceIDJKDACreate, req, &out) + return out, result, err +} + +func (c *Client) UpdateHealthRecord(ctx context.Context, req contract.HealthRecordCreate) (contract.HealthRecordSaveResult, Result, error) { + req.ManageInfo = c.manageInfo() + var out contract.HealthRecordSaveResult + result, err := c.callUploadInfo(ctx, ServiceIDJKDAUpdate, req, &out) + return out, result, err +} func (c *Client) FindHealthRecord(ctx context.Context, query FindHealthRecordQuery) ([]contract.FindHealthRecord, Result, error) { baseInfo, err := query.baseInfo() if err != nil { @@ -43,6 +56,13 @@ func (c *Client) FindRqbj(ctx context.Context, query FindRqbjQuery) (PersonSignR return personSign, result, err } +func (c *Client) manageInfo() contract.ManageInfo { + return contract.ManageInfo{ + DSFMC: c.config.UserName, + OperateUser: c.config.OperateUser, + OperateUnit: c.operateUnit(), + } +} func (q FindHealthRecordQuery) baseInfo() (map[string]string, error) { fields := []queryField{ {name: "idCard", value: q.IDCard}, diff --git a/osi/jkda_test.go b/osi/jkda_test.go index 0b93850..b0e4073 100644 --- a/osi/jkda_test.go +++ b/osi/jkda_test.go @@ -7,8 +7,83 @@ import ( "net/http/httptest" "testing" "time" + + "chis_osi/contract" ) +func TestCreateHealthRecordCallsJKDA00001WithUploadInfo(t *testing.T) { + var seenPath string + var seenPayload map[string]any + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + seenPath = r.URL.Path + if err := json.NewDecoder(r.Body).Decode(&seenPayload); err != nil { + t.Fatalf("decode request: %v", err) + } + _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":{"phrId":"PHR001","createUnit":"123456789"}}`)) + })) + defer server.Close() + + client := newTestJKDAClient(t, server.URL) + resultData, result, err := client.CreateHealthRecord(context.Background(), contract.HealthRecordCreate{ + BaseInfo: contract.HealthRecordBaseInfo{IDCard: "440000********1234", PersonName: "测试人员"}, + HealthRecord: contract.HealthRecordCreateInfo{ + CheckID: "CHK2026070700000001", + IDCard: "440000********1234", + PersonName: "测试人员", + RegionCode: "441625000000", + ManaDoctorID: "doc-001", + ManaUnitID: "123456789", + }, + }) + if err != nil { + t.Fatalf("CreateHealthRecord: %v", err) + } + if !result.Success || result.Code != "01" { + t.Fatalf("result = %#v", result) + } + if seenPath != "/osi/api/jkda/create" { + t.Fatalf("path = %q", seenPath) + } + if seenPayload["serviceId"] != ServiceIDJKDACreate { + t.Fatalf("serviceId = %v", seenPayload["serviceId"]) + } + uploadInfo := seenPayload["uploadinfo"].(map[string]any) + healthRecord := uploadInfo["healthRecord"].(map[string]any) + if healthRecord["checkId"] != "CHK2026070700000001" || healthRecord["manaUnitId"] != "123456789" { + t.Fatalf("healthRecord = %#v", healthRecord) + } + if resultData.PhrID != "PHR001" || resultData.CreateUnit != "123456789" { + t.Fatalf("resultData = %#v", resultData) + } +} + +func TestUpdateHealthRecordCallsJKDA00003(t *testing.T) { + var seenPath string + var seenPayload map[string]any + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + seenPath = r.URL.Path + if err := json.NewDecoder(r.Body).Decode(&seenPayload); err != nil { + t.Fatalf("decode request: %v", err) + } + _, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":{"phrId":"PHR001"}}`)) + })) + defer server.Close() + + client := newTestJKDAClient(t, server.URL) + _, _, err := client.UpdateHealthRecord(context.Background(), contract.HealthRecordCreate{ + BaseInfo: contract.HealthRecordBaseInfo{IDCard: "440000********1234"}, + HealthRecord: contract.HealthRecordCreateInfo{CheckID: "CHK2026070700000001", PhrID: "PHR001"}, + }) + if err != nil { + t.Fatalf("UpdateHealthRecord: %v", err) + } + if seenPath != "/osi/api/jkda/update" { + t.Fatalf("path = %q", seenPath) + } + if seenPayload["serviceId"] != ServiceIDJKDAUpdate { + t.Fatalf("serviceId = %v", seenPayload["serviceId"]) + } +} func TestFindHealthRecordCallsJKDA00002WithBaseInfo(t *testing.T) { var seenPath string var seenPayload map[string]any