Files
chis_osi/docs/04-字段与接口映射.md

443 lines
27 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 04 · 字段与接口映射
本文是 `mapping/` 与 `contract/` 两层的落地指引:接口能力映射、PHIS→OSI 字段映射策略、码表清单、checkId 幂等键设计。
---
## 1. 接口能力 → 内部方法映射
| OSI serviceId | 路径 | 内部方法(`osi` 包) | dataType(pipeline 分流) |
| --- | --- | --- | --- |
| JKDA00001 | `/jkda/create` | `CreateHealthRecord` | `health_record` |
| JKDA00003 | `/jkda/update` | `UpdateHealthRecord` | `health_record` |
| JKDA00002 | `/auto/jkda/find` | `FindHealthRecord` | (查询) |
| JKDA00005 | `/auto/jkda/findrqbj` | `FindRqbj` | (查询) |
| JKTJ00001 | `/jktj/create` | `CreateHealthCheck` | `health_check` |
| JKTJ00003 | `/jktj/update` | `UpdateHealthCheck` | `health_check` |
| JKTJ00002 | `/auto/jktj/query` | `QueryHealthCheck` | (查询) |
| JKTJLIST00002 | `/auto/jktjlist/query` | `ListHealthCheckPeople` | (查询) |
| JKTJLSJL00002 | `/auto/jktjlscx/query` | `LastHealthCheck` | (查询) |
| LNRZLPG00001 | `/lnrzlpg/create` | `CreateElderlySelfCare` | `elderly_self_care` |
| LNRZLPG00002 | `/auto/lnr/query` | `QueryElderlySelfCare` | (查询,代码完成,待联调确认) |
| LNRZLPG00003 | `/lnrzlpg/update` | `UpdateElderlySelfCare` | `elderly_self_care` |
| LNRZYTZ00001 | `/lnrzyygl/create` | `CreateTCMConstitution` | `tcm` |
| LNRZYTZ00003 | `/lnrzyygl/update` | `UpdateTCMConstitution` | `tcm` |
| (待确认) | `/auto/zyjkzd/create` | `SaveTCMGuidance` | `tcm_guidance` |
| (待确认) | `/auto/zyjkzd/update` | `UpdateTCMGuidance` | `tcm_guidance` |
| WGDZ00001 | `/auto/wgdzcx/query` | `QueryGridAddress` | (字典) |
| ZRYS00001 | `/auto/zryscx/query` | `QueryDoctors` | (字典) |
| YPML00001 | `/auto/ypmlcx/query` | `QueryDrugs` | (字典) |
| CXJG00002 | `/auto/cxjg/query` | `QueryOrgs` | (字典) |
> ⚠ "(待确认)"项以 01 文档第 7 节为准,联调回填后更新 `osi/codes.go` 的 serviceId 常量与 `pathOf` 路由表。
---
## 2. 字段映射策略
### 2.1 三类字段,三种处理
1. **直传字段**:PHIS 与 OSI 同义且同形(如姓名、出生日期 `yyyy-MM-dd`)。直接拷贝,做必填/长度校验。
2. **码表字段**:枚举值需经字典转换(性别、民族、血型、职业…)。统一走 `dict.go` 双向查表,未命中报 `ValidationError`,**绝不静默置空**。
3. **结构/多选字段**:嵌套节点(既往史/家族史/手术/外伤/输血/生活环境)、逗号拼接多选。集中在各业务域映射函数里组装。
### 2.2 映射函数约定
```go
// 返回结构化校验错误,pipeline 在投递前据此拦截,避免把脏数据打到平台。
func MapHealthRecord(src phis.HealthRecord, ctx MapContext) (contract.HealthRecordCreate, []ValidationError)
```
- `MapContext` 携带机构级常量:`orgCode/userName/operateUser/regionCode` 默认值与字典快照。
- 校验项:必填(idCard/personName/sexCode/birthday/mobileNumber/regionCode/manaDoctorId/manaUnitId…)、长度上限、码表合法性、日期格式。
- 映射是**纯函数**,便于用 01 文档样例 + 联调真实样本做单测(对齐旧项目"可测试改动补最小必要测试")。
---
## 3. 码表清单(`dict.go` 初始内容)
> 取值来自 docx 字段说明,建模时全部落为常量表,并加注释标"来源:OSI 文档 §字段名"。
| 维度 | 取值(节选) |
| --- | --- |
| 性别 sexCode | 0 未知 / 1 男 / 2 女 / 9 未说明 |
| 户籍 registeredPermanent | 1 户籍 / 2 非户籍 |
| 血型 bloodTypeCode | 1 A / 2 B / 3 O / 4 AB / 5 不详 |
| RH rhBloodCode | 1 阳性 / 2 阴性 / 3 不详 |
| 文化程度 educationCode | 10 研究生 / 20 本科 / 31 大专 / 41 中专 / 47 技校 / 60 高中 / 70 初中 / 80 小学 / 90 文盲 / 91 不详 |
| 职业 workCode | 0 负责人 / 1·2 专技 / 3 办事 / 4 商业服务 / 5 农林牧渔 / 9-9 生产运输 / X 军人 / Y 其他 / 8 无职业 |
| 婚姻 maritalStatusCode | 10 未婚 / 20 已婚 / 30 丧偶 / 40 离婚 / 90 未说明 |
| 医保 insuranceCode(多选) | 01 城镇职工 / 02 城乡居民 / 04 贫困救助 / 05 商业 / 06 全公费 / 07 全自费 / 99 其他 |
| 民族 nationCode | 01 汉 … 56 基诺 / 99 其他(56 项全表) |
| 人群标记 personSign | PU 普通 / GRQY 已签约 / LAO 老年 / GAO 高血压 / TANG 糖尿病 / FU 孕产妇 / ER 儿童 / FEI 肺结核 / JING 精神 / CAN 残疾 |
| 药物过敏 ywgms(多选) | 0101 无 / 0102 青霉素 / 0103 磺胺 / 0104 链霉素 / 0109 其他 |
| 既往疾病 jwsjbcode | 0201 无 / 0202 高血压 / 0203 糖尿病 / … / 0299 其他 |
| 残疾 cjqk(多选) | 1101 无 / 1102 视力 / 1103 听力 / 1104 言语 / 1105 肢体 / 1106 智力 / 1107 精神 / 1108 孤独症 / 1109 脑瘫 / 1199 其他 |
| 厨房排风 cookAirTool | 1 无 / 2 油烟机 / 3 换气扇 / 4 烟囱 / 9 其他 |
| 燃料 fuelType | 1 液化气 / 2 煤 / 3 天然气 / 4 沼气 / 5 柴火 / 9 其他 |
| 饮水 waterSourceCode | 1 自来水 / 2 净化水 / 3 井水 / 4 河湖水 / 5 塘水 / 9 其他 |
| 厕所 washroom | 1 卫生厕所 / 2 粪池式 / 3 马桶 / 4 露天粪坑 / 5 简易棚厕 / 6 其他 |
| 机构类型 organizType | A 医院 / B 社区中心(站) / C 卫生院 / D 门诊诊所村室 / D6 村卫生室 / R 市卫生局 |
> 多选字段统一用英文逗号拼接(文档示例如 `"0102,0103"`)。注意 docx 个别返回样例用了中文逗号,解析时两者都要兼容。
---
## 4. 主数据依赖:字典服务先行
创建类接口的若干必填字段依赖公共服务查询结果,建议在投递前用字典缓存解析:
```
regionCode ← QueryGridAddress(parentCode) // 网格地址
manaDoctorId/operateUser ← QueryDoctors(manaUnitId) // 责任医生
manaUnitId/organizCode ← QueryOrgs(...) // 机构
```
策略:启动或定时拉取这些字典,缓存到 `cache.DictionarySnapshot`(内存为必选,持久化接口可接 Redis)。映射时通过 `MapContext.MasterData` 按 PHIS 的地址/医生/机构名称反查 OSI 码:`RegionCodeByName`、`DoctorIDByName`、`ManaUnitIDByName`。命中失败仍表现为必填校验错误,不投递;Redis/持久化失败不阻断内存快照刷新。
---
## 5. checkId 与幂等键设计
`checkId`(第三方业务唯一识别码,长度 20)是新项目幂等的核心。
### 5.1 生成规则(`mapping/checkid.go`)
要求**确定性**:同一源记录无论重试多少次,都得到同一 checkId。
```
checkId = 截断20位( 编码( 源系统标识 | dataType | 源记录主键 [ | 版本/更新时间] ) )
```
- 同一条源记录的"创建"应使用稳定 checkId → 平台据此识别为同一档案,避免重复建档。
- "更新"沿用原 checkId(走 update 接口)。
- 若源记录内容变更需视为新版本上送,可把"更新时间/版本号"纳入 checkId 计算——**取决于平台是否以 checkId 去重**(见 03 文档开放问题 5)。
### 5.2 幂等存储
- 键:`checkId`(替代旧项目 `account|idCard|dataType|sha1(saveBody)`)。
- 值:`{status: success|failed, phrId, lastTs, attempts}`。
- 命中 `success`:跳过,不重复投递。
- `failed`:允许后续重试。
- 存储:redis 优先、本地 JSON 降级(沿用旧项目 `idempotency_store` 思路)。
> 用 checkId 做幂等键的好处:与平台对账口径一致(平台也认 checkId),且不受报文字段微调影响。
---
## 6. 校验与错误分类(与 pipeline 配合)
> 成功码以 docs/01 §1 为准:实测为字符串 `"01"`(非 `"1"`),判定按去前导零后 == `"1"`。
| 错误来源 | 分类 | 处理 |
| --- | --- | --- |
| 映射缺必填/码表未命中/格式非法 | 不可重试(数据错) | 直接 failed,回写 PHIS,附 ValidationError 明细 |
| 网络错误 / SOCKS / EOF / 超时 | 可重试 | 退避重试,计熔断 |
| OSI `code == "405"`(服务超时) | 可重试 | 退避重试 |
| OSI `code` 非成功码非 405(业务/权限拒绝) | 不可重试 | failed,记 message 供排查 |
| HTTP 5xx / 429 | 可重试 | 退避重试 |
---
## 7. 待补字段表
以下接口的完整字段表 docx 未充分给出或存在坑点,建模时以联调样本为准并在此登记:
- [ ] 体检 `jktj/create` 全量字段(hcData/lsData/exaData/aeData,体量最大)
- [x] 老年人自理评估 `lnrzlpg` **查询**字段 —— 厂家查询文档已给出,待真实联调确认,见 §13
- [ ] 老年人自理评估 `lnrzlpg` 创建/更新字段
- [ ] 中医体质辨识 `lnrzyygl` 字段
- [ ] 中医健康指导 `zyjkzd` 字段 + serviceId
- [x] 个人档案查询 JKDA00002 的请求信封与返回结构 —— 已联调实测,见 §8
- [ ] 其余列表/查询接口的分页与返回数组结构(体检/老年人/中医指导)
---
## 8. JKDA00002 个人档案查询 · 联调实测契约
> 来源:2026-07 沙箱一次成功查询(`code="01"` 操作成功)。**下方均为脱敏结构**,真实身份证/姓名/联系方式等 PII 只在本地样本,不入库。
> 这是 `contract/` 里 `FindHealthRecord` 请求/响应结构体与 `osi.FindHealthRecord` 的事实基线。
### 8.1 请求(POST `/osi/api/auto/jkda/find`)
```json
{
"serviceId": "JKDA00002",
"uploadinfo": {
"baseInfo": { "idCard": "<idCard>" },
"manageInfo": { "DSFMC": "<userName>", "operateUser": "<operateUser>", "operateUnit": "<orgCode-18位>" }
}
}
```
- `baseInfo` 三选一:`idCard` / `phrid` / `personName`。
- `manageInfo` 三字段来自机构级常量(见 docs/01 §3 三种机构码区分)。
- 请求头另带 `orgCode`(=operateUnit) / `deviceSN`(查询可空) / `ts` / `userName`(=DSFMC) / `password`,签名规则见 docs/01 §2。
### 8.2 响应(`code="01"`,`data` 为**数组**,每元素 = 一份档案聚合)
| 节点 | 类型 | 说明 |
| --- | --- | --- |
| `healthRecord` | object | 档案主体(人口学 + 管理字段),见 8.3 |
| `pastHistory` | object | 既往史**标志位**:`ywgms`(药物过敏)/`jwsjb`标志/`bls`/`ycbs`(遗传病)/`cjqk`(残疾)/`jzsfqn`/`jzsmq`/`jzszn`/`jzsxdjm`(家族史·父/母/子女/兄弟姐妹) 等 code |
| `jwsjb` | array | 既往疾病:`{ jwsjbcode, jwsjbmc, jwsjbqzsj(确诊时间) }` |
| `jwsss` | array | 既往手术:`{ jwssscode, jwsssmc, jwsssqzsj }` |
| `jwsws` | array | 既往外伤:`{ jwswscode, jwswsmc }` |
| `jwssx` | array | 既往输血:`{ jwssxcode, jwssxyy(原因) }` |
| `familyMiddle` | object | 生活环境:`waterSourceCode`/`fuelType`/`cookAirTool`/`washroom`/`livestockColumn`/`isFillShhj` |
> `pastHistory`/`familyMiddle` 实测是 **object**(非 docx 查询侧标的 list);多选标志仍以码值出现。
### 8.3 `healthRecord` 关键字段(实测字段名,注意坑点拼写)
| 字段 | 语义 | 备注 |
| --- | --- | --- |
| `idCard` `personName` `sexCode` `birthday` | 人口学主键四要素 | 直传+校验 |
| `phrId` | 健康档案号 | 注意驼峰 `phrId`(查询入参用小写 `phrid`) |
| `empiId` | EMPI 主索引 | 32 位十六进制串 |
| `checkId` | 第三方业务唯一码 | 本样本为 `null`(存量档案无 checkId)→ 佐证幂等键需我方生成,见 §5 |
| `manaUnitId` `createUnit` | 管辖/建档机构 | **9 位机构码**,≠ 请求头 orgCode(18位) |
| `manaDoctorId` `createUser` | 责任医生/建档人 | 机构内人员 ID |
| `regionCode` `addressCode` `homePlaceCode` | 行政区划/网格码 | 12 位 |
| `address` `adressNumber` | 现住址/门牌号 | ⚠门牌号字段名少一个 d:`adressNumber` |
| `homePlace` `homePlaceNumber` | 户籍地/门牌 | |
| `nationCode` `educationCode` `workCode` `maritalStatusCode` `bloodTypeCode` `rhBloodCode` `insuranceCode` | 码表字段 | 走 dict.go 双向查表(§3) |
| `personGroup` `otherPersonGroup` | 人群标记 | 与 JKDA00005 `personSign` 联动 |
| `isFillShhj` | 是否填生活环境 | `y`/`n` |
| `contact` `contactPhone` `mobileNumber` `phoneNumber` | 联系人/电话 | PII |
| `status` `createDate` | 档案状态/建档日期 | |
> 建模提示:`data` 用数组承接(可能多档案/多版本);`insuranceType`、`otherPersonGroup`、`checkId` 等实测可为 `null`,结构体用指针或 `omitempty`,映射层不得因 null 报错。
---
## 9. 公共字典查询 · 联调实测契约
> 来源:2026-07-07 沙箱验证。使用本地未入库凭据和一条已存在档案反查主数据后验证;下方只记录脱敏事实,不记录真实身份证、机构码、医生姓名或密钥。
### 9.1 请求信封
四个公共查询接口与 JKDA 查询一致,仍走统一信封:
```json
{
"serviceId": "<公共查询serviceId>",
"uploadinfo": {
"baseInfo": { "...": "..." },
"manageInfo": { "DSFMC": "<userName>", "operateUser": "<operateUser>", "operateUnit": "<orgCode-18位>" }
}
}
```
### 9.2 已验证结果
| 接口 | serviceId | 真实验证结论 | 备注 |
| --- | --- | --- | --- |
| 网格地址查询 | `WGDZ00001` | `code="01"` 且返回数组非空 | 用已存在档案的区划/网格码派生 `parentCode` 候选值验证 |
| 责任医生查询 | `ZRYS00001` | `code="01"` 且返回数组非空 | 入参 `manaUnitId` 使用档案返回的 9 位机构码 |
| 机构查询 | `CXJG00002` | `code="01"` 且返回数组非空 | `baseInfo` 必须含 `organizCode` 和 `parentId` 两个 key(值可为空);响应 `regionCode` 可为 null |
| 药品目录查询 | `YPML00001` | 未做真实联调 | T-101 已完成客户端封装与单测;后续有药品关键字/拼音码时补样本 |
> T-103 字典缓存可以先依赖网格、责任医生、机构三类真实验证结果。药品目录与健康档案创建闭环无直接依赖,不阻塞 T-103/T-206。
机构查询的 `OrgQuery` 不可为两个字段添加 `omitempty`:平台要求 `organizCode`、`parentId` 同时存在,即便查询只按其中一个条件过滤,另一个也应显式上送空字符串。机构响应的 `regionCode` 为所在网格码,平台可返回 null,Go 查询结构按空字符串承接。
---
## 10. JKDA 创建/更新请求契约(T-206 本地基线)
T-206 已完成本地契约与客户端方法并通过单测;真实写入验收拆为 T-215,当前等待明确写入授权与安全测试档案。
- `JKDA00001`:`/osi/api/jkda/create` → `osi.CreateHealthRecord`
- `JKDA00003`:`/osi/api/jkda/update` → `osi.UpdateHealthRecord`
- 请求仍走统一 `uploadinfo`,但创建/更新节点不是查询式裸 `baseInfo`,而是:`baseInfo`、`manageInfo`、`healthRecord`、`pastHistory`、`jwsjb`、`jwsss`、`jwsws`、`jwssx`、`familyMiddle` 同级。
- 创建请求侧门牌号字段使用 `addressNumber`;查询响应侧仍以实测错拼 `adressNumber` 建模,二者不能混用。
- `mapping.BuildHealthRecordCreate` 负责把 `MappedHealthRecord` 组装成 `contract.HealthRecordCreate`,保留确定性 `checkId`,并由 `manaDoctorId/manaUnitId` 派生 `createUser/createUnit`。
T-215 真实 create/update 联调完成后,需要在本节补回平台返回样本、`phrId` 字段确认、同一 `checkId` 重复提交的幂等语义、更新目标标识、`addressNumber` 落库结果及逐档案 `operateUser` 规则。
---
## 11. JKTJ 健康体检查询 · 联调实测契约(T-301)
> 来源:2026-07 沙箱"最近一次体检"一次成功查询(`code="01"`)。**脱敏结构**,真实值只在本地样本、不入库。
> 这是体检查询的事实基线,也是将来体检 **create 映射**的字段清单来源。
### 11.1 接口与状态
| 业务 | serviceId | 路径 | 返回 | 状态 |
| --- | --- | --- | --- | --- |
| 最近一次体检 | `JKTJLSJL00002` | `/auto/jktjlscx/query` | 单对象(最近一次完整体检) | ✅ 实测可用(`osi.LastHealthCheck`) |
| 某人全部体检 | `JKTJ00002` | `/auto/jktj/query` | **数组**(该人全部体检,每条完整) | ✅ 实测可用(`osi.QueryHealthChecks`;早期曾报"没有url配置",现已部署)|
| 已检/待检名单 | `JKTJLIST00002` | `/auto/jktjlist/query` | 数组(人员名单+状态,非体检明细) | ✅ 实测可用(`osi.ListHealthCheckPeople`,见 §11.4) |
- 请求信封同档案(`serviceId` + `uploadinfo{baseInfo, manageInfo}`);查询按 `phrid`/`idCard` 之一(docx baseInfo 只列这俩)。
- **身份证字段大小写三接口不一致(务必分开建模)**:最近一次 `JKTJLSJL00002` 用**小写 `idcard`**;`JKTJ00002` 与 `JKTJLIST00002` 用**驼峰 `idCard``**。档案 find 也是 `idCard`。
- 最近一次的 `data` 是**单个对象**(`JKTJ00002` 与档案 find 是数组)。
- **JKTJ00002 返回形态(实测)**:`data` 为**数组**=该人全部体检历史(本样本 8 条,2013–2026);每个元素是一份**完整体检**,结构同"最近一次"(38 顶层标量 + `healthAssessment`/`examination`/`lifestySituation`/`accessoryExamination` + 3 数组节点,见 §11.3)。
- ⚠ **`checkId` 仅近年记录有值,历史记录为 `null`**(本样本仅最近 2 条有体检编号,更早 6 条 `checkId=null`)——第三方流水码是接入后才有的。
- 因此"按体检编号取历史某次"只对**有 checkId 的近期记录**成立;更早的体检**没有 checkId**,只能按 **`checkDate`** 定位。
- docx 无"按 `checkId` 直接查单条"的接口——查历史须用本接口取该人全部体检,再本地按 `checkId`/`checkDate` 过滤。
### 11.2 记录结构与主键
- 体检记录主键 = **`checkId`**(体检自身流水,**注意**与档案 §5 我方生成的幂等 `checkId` 同名不同义)。
- 各子节点用 **`healthCheck`** 外键指向主键(值 = checkId);子节点各有自己的 id:`healthAssessment.assessmentId`、`accessoryExamination.recordId`、`inhospitalSituations[].situationId`。
### 11.3 字段清单(实测约 260 项,供体检 create 建模用)
> 查询侧只强类型化定位字段(`contract.HealthCheckSummary`:checkId/healthCheck/idcard/personName/checkDate),完整内容由 `osi.Result.Raw` 保留。
> 全量字段的强类型建模留到体检 create 任务——写入映射才需要逐字段建模,届时以本清单 + 联调 create 样本为准,不照 docx 猜类型(本样本大量字段为 null,类型不可判)。
| 节点 | 类型 | 字段数 | 说明 |
| --- | --- | --- | --- |
| (顶层标量) | - | 39 | 体征与主诉:身高体重 `height/weight/bmi`(float)、血压 `constriction/diastolic(_l)`、`temperature/pulse/breathe/waistline`、`symptom/healthstatus/selfcare/cognitive/emotion` 及各类疾病标志 |
| `healthAssessment` | object | 24 | 健康评价:`abnormality1..8`、`riskfactorsControl`、`assessmentId` + create/lastModify 审计字段 |
| `examination` | object | 52 | 一般查体:皮肤/淋巴结/心肺/腹部/肝脾/乳腺/妇科等 `*` + `*Desc` 描述对 |
| `lifestySituation` | object | 43 | 生活方式:吸烟 `wehtherSmoke/beginSmokeTime`、饮酒 `drinkingFrequency`、运动、职业暴露 `occupational/dust/ray/chemicals` |
| `accessoryExamination` | object | 84 | 辅助检查(最大):血常规 `wbc/hgb/platelet`、生化 `alt/ast/glu/fbs/hba1c/tc/tg/hdl/ldl/cr/bun/tbil`、尿常规、心电 `ecg`、胸片 `x`、视力听力 `recordId` |
| `inhospitalSituations` | array | 19/项 | 住院/家庭病床:`type`、`inhospitalDate/outhospitalDate`、`situationId`,多含 `*_text` 中文回显 |
| `nonimmuneInoculations` | array | - | 非免疫规划预防接种(本样本空,结构待样本) |
| `medicineSituations` | array | - | 用药情况(本样本空,结构待样本) |
> 命名坑点:`constriction`=收缩压、`diastolic`=舒张压(`_l` 疑为左侧);辅助检查用大量医学缩写。建 create 映射时逐字段加中文注释。
### 11.4 已检/待检人员名单查询 JKTJLIST00002(docx 契约,沙箱部署待验证)
> **不是体检数据源**,是机构级"某年度已检/未检人员名单/进度":返回**人员一行 + 体检状态**,不含体检明细。
> 来源:docx + 2026-07 沙箱实测(`code="01"`,返回分页人员名单)。**端点已部署可用**(T-305)。
- serviceId `JKTJLIST00002`,`POST /osi/api/auto/jktjlist/query`,信封同查询式(`uploadinfo{baseInfo, manageInfo}`)。
- **请求 `baseInfo`**(page/rows 也在 baseInfo 内):
| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `checkYear` | ✅ | 检查年度(如 `2025`)——无"默认所有年度" |
| `page` `rows` | ✅ | 分页,rows 默认 10 |
| `idCard` | 否 | 过滤到某人某年度状态 |
| `checkType` | 否 | `0`已检 / `1`未检 / `2`全部 |
| `personName` `sex` `age` `personGroup` `gridAddress` `beginDate` `endDate` | 否 | 各类筛选。⚠ docx 参数表与样例字段名不一致(表 `ageBegin/ageEnd`/`sexCode`/`regionCode` vs 样例 `age`/`sex`/`gridAddress`)——以联调实测为准 |
- **响应 `data`(list,每人一行)· 实测字段名**(⚠ 与 docx 多处不符,以实测为准):
`idCard`/`personName`/`age`/**`birthday`**(docx 误写 birthDay)/`sexCode`/`regionCode`/`regionCodeText`/`manaUnitId`/`manaUnitText`/**`manaDoctorId`**(docx 误写 manadoctorId)/**`manaDocterName`**(拼写 Docter)/**`phrId`**(docx 误写 phrid,此处驼峰)/**`empiId`**/`signFlag`(y/n 签约)/`address`/`mobileNumber`/`contact`/`contactPhone`/**`checkType`(0已检/1未检)**/`rqbj`(人群标志,同 personSign 码表)。
---
## 12. JKDA00005 人群分类查询 · 联调实测契约(T-209)
> 来源:2026-07-09 本地探针 `scripts/query_crow_with_idcard.py` 与返回样本 `scripts/query_crow_with_idcard.json`。样本含真实身份证和档案号,只本地留存、不入库;本文只记录脱敏结构。
### 12.1 请求
```json
{
"serviceId": "JKDA00005",
"uploadinfo": {
"baseInfo": { "idCard": "<idCard>" },
"manageInfo": { "DSFMC": "<userName>", "operateUser": "<operateUser>", "operateUnit": "<orgCode-18位>" }
}
}
```
- 路径:`/osi/api/auto/jkda/findrqbj`。
- `baseInfo` 支持 `idCard` / `phrid` 二选一;实测样本使用 `idCard`。
- 注意:早期代码/文档登记为 `/jkda/findrqbj`,本次实测脚本使用 `auto/jkda/findrqbj` 返回 `code="01"`,T-209 需同步修正 `osi/codes.go`。
### 12.2 响应
```json
{
"code": "01",
"message": "操作成功",
"data": {
"personSign": "LAO",
"idCard": "<idCard>",
"phrId": "<phrId>"
}
}
```
字段说明:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `personSign` | string | 人群分类码,可能为逗号分隔多值;码表见 §3 `personSign` |
| `idCard` | string | 身份证号,PII |
| `phrId` | string | 健康档案号,响应为驼峰 `phrId` |
Go 侧契约应从只承接 `personSign` 优化为完整承接 `personSign/idCard/phrId`,server 端点原样回写平台 JSON,避免裁掉后续可能新增字段。
---
## 13. 老年人生活自理能力评估查询 · 厂家文档契约(待联调确认)
> 来源:2026-07 新增《老年人生活自理能力评估查询服务.docx》。文档中 `serviceId` 参数表与请求样例冲突;以下以参数表的 `LNRZLPG00002` 为实现候选,真实请求成功后才能升级为实测契约。
### 13.1 请求
- `POST /osi/api/auto/lnr/query`
- `serviceId`: `LNRZLPG00002`
- 信封沿用实测查询格式:`{"serviceId", "uploadinfo": {"baseInfo", "manageInfo"}}`。docx 样例遗漏了 `uploadinfo/manageInfo`,不可照搬。
`baseInfo` 字段:
| 字段 | 必填 | 说明 |
| --- | --- | --- |
| `idCard` | ✅ | 身份证件号 |
| `phrId` | 否 | 健康档案编号 |
| `checkId` | 否 | 第三方检查主键 |
### 13.2 响应
`data` 为评估记录数组。每条记录包含:
| 维度 | 原始值 | 等级 | 评分 |
| --- | --- | --- | --- |
| 进餐 | `jc` | `jcdj` | `jcpf` |
| 梳洗 | `sx` | `sxdj` | `sxpf` |
| 穿衣 | `cy` | `cydj` | `cypf` |
| 如厕 | `rc` | `rcdj` | `rcpf` |
| 活动 | `hd` | `hddj` | `hdpf` |
| 总评 | `zp` | `zpdj` | `zpfs` |
- 等级统一为:`1` 可自理、`2` 轻度依赖、`3` 中度依赖、`4` 不能自理。
- 定位和审计字段:`phrId`、`checkId`、`createUnit`、`createUser`、`createDate`、`inputDate`、`inputUser`、`inputUnit`。
- docx 仍误写成功码为 `"1"`;项目统一按现有 `IsSuccessCode` 兼容处理,实测成功基线仍为 `"01"`。
- docx 请求样例错误写为 `"serviceId":" LNR00004"`,不能用作实现依据。
---
## 14. PHIS 健康档案 → JKDA 写入映射(T-212)
输入契约来自本地 PHIS 待上报响应的脱敏结构;真实样本含居民信息和医生凭据,不入库。`source.HealthRecordTask` 只承接业务字段,解码时忽略 `doctor.sxtAccount/sxtPassword`。
PHIS `record.createDate` 映射到 CHIS 写入 `healthRecord.createDate`;该字段已在 JKDA00002 查询响应中实测存在,但写入端是否接受仍需 T-215 创建后回查确认。空的 `pastHistory` 不上送,`isFillShhj` 在校验与输出前统一去除空白并转为小写。
### 14.1 标识与管理字段
| PHIS | CHIS | 规则 |
| --- | --- | --- |
| `archId` | `healthRecord.checkId` | 稳定源档案键;生成规则见 ADR 001,缺失即拒绝 |
| `businessId` | trace/PHIS 回写 | 不进入 OSI 请求,不参与 checkId |
| `record.manaDoctorId` | `healthRecord.manaDoctorId/createUser`、`manageInfo.operateUser` | 必须命中 CHIS 责任医生字典 |
| `record.manaUnitId` | `healthRecord.manaUnitId/createUnit` | 必须命中 CHIS 机构字典 |
| 配置 `userName/orgCode` | `manageInfo.DSFMC/operateUnit` | 由 OSI 客户端强制覆盖,不能由 PHIS 注入 |
### 14.2 主体与嵌套节点
| PHIS | JKDA 写入字段 |
| --- | --- |
| `idCard/personName/sexCode/birthday/workPlace/mobileNumber/contact/contactPhone/registeredPermanent/regionCode/address/homePlace/homePlaceNumber/cardType` | `healthRecord` 同名字段 |
| `adressNumber` | `healthRecord.addressNumber`(写入拼写;T-215 真实回查校准) |
| `nationCode/bloodTypeCode/rhBloodCode/educationCode/workCode/maritalStatusCode/insuranceCode` | 码表校验后写入 `healthRecord` |
| `diseasetext_check_gm/check_bl/check_fq/CheckMQ/CheckXDJM/CheckZN/RedioYCBS/CheckCJ` | `pastHistory.ywgms/bls/jzsfqn/jzsmq/jzsxdjm/jzszn/ycbs/cjqk` |
| `diseasetext_radio_jb/ss/ws/sx` | `jwsjb/jwsss/jwsws/jwssx` 数组;非空代码(含“无”代码)各生成一项 |
| `shhjCheckCFPFSS/RLLX/YS/CS/QCL` | `familyMiddle.cookAirTool/fuelType/waterSourceCode/washroom/livestockColumn` |
多选兼容英文逗号、中文逗号、顿号和分号,输出统一为英文逗号。`isFillShhj=n` 时省略 `familyMiddle`;为 `y` 时才校验生活环境单选码。PHIS 未提供的名称、确诊日期和可选地址编码不伪造。
### 14.3 投递前校验
- CHIS 必填字段、身份证 18 位、网格码 12 位、生日 `yyyy-MM-dd`、docx 长度上限。
- 主体码表、既往史多选码和生活环境单选码必须合法;未知码返回结构化 `ValidationError`。
- `data.doctor.doctorId` 与 `record.manaDoctorId` 必须一致;医生和机构 ID 必须命中字典快照。
- T-215 真实写入后仍需确认“无”代码数组、`addressNumber`、更新目标标识和逐档案 `operateUser` 的平台最终规则。