feat(osi): 实现老年人自理能力查询(T-303)
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
package contract
|
||||||
|
|
||||||
|
// ElderlySelfCareAssessment 是老年人生活自理能力评估查询的一条记录。
|
||||||
|
// 查询侧只建模厂家文档明确列出的稳定字段,完整响应仍由 osi.Result.Raw 保留。
|
||||||
|
type ElderlySelfCareAssessment struct {
|
||||||
|
PHRID string `json:"phrId"`
|
||||||
|
CheckID string `json:"checkId"`
|
||||||
|
|
||||||
|
Meal string `json:"jc"`
|
||||||
|
MealLevel string `json:"jcdj"`
|
||||||
|
MealScore string `json:"jcpf"`
|
||||||
|
Grooming string `json:"sx"`
|
||||||
|
GroomLevel string `json:"sxdj"`
|
||||||
|
GroomScore string `json:"sxpf"`
|
||||||
|
Dressing string `json:"cy"`
|
||||||
|
DressLevel string `json:"cydj"`
|
||||||
|
DressScore string `json:"cypf"`
|
||||||
|
Toilet string `json:"rc"`
|
||||||
|
ToiletLevel string `json:"rcdj"`
|
||||||
|
ToiletScore string `json:"rcpf"`
|
||||||
|
Activity string `json:"hd"`
|
||||||
|
ActivityLevel string `json:"hddj"`
|
||||||
|
ActivityScore string `json:"hdpf"`
|
||||||
|
Overall string `json:"zp"`
|
||||||
|
OverallLevel string `json:"zpdj"`
|
||||||
|
TotalScore string `json:"zpfs"`
|
||||||
|
|
||||||
|
CreateUnit string `json:"createUnit"`
|
||||||
|
CreateUser string `json:"createUser"`
|
||||||
|
CreateDate string `json:"createDate"`
|
||||||
|
InputDate string `json:"inputDate"`
|
||||||
|
InputUser string `json:"inputUser"`
|
||||||
|
InputUnit string `json:"inputUnit"`
|
||||||
|
}
|
||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
| JKTJLIST00002 | `/auto/jktjlist/query` | `ListHealthCheckPeople` | (查询) |
|
| JKTJLIST00002 | `/auto/jktjlist/query` | `ListHealthCheckPeople` | (查询) |
|
||||||
| JKTJLSJL00002 | `/auto/jktjlscx/query` | `LastHealthCheck` | (查询) |
|
| JKTJLSJL00002 | `/auto/jktjlscx/query` | `LastHealthCheck` | (查询) |
|
||||||
| LNRZLPG00001 | `/lnrzlpg/create` | `CreateElderlySelfCare` | `elderly_self_care` |
|
| LNRZLPG00001 | `/lnrzlpg/create` | `CreateElderlySelfCare` | `elderly_self_care` |
|
||||||
| LNRZLPG00002 | `/auto/lnr/query` | `QueryElderlySelfCare` | (查询,待联调确认) |
|
| LNRZLPG00002 | `/auto/lnr/query` | `QueryElderlySelfCare` | (查询,代码完成,待联调确认) |
|
||||||
| LNRZLPG00003 | `/lnrzlpg/update` | `UpdateElderlySelfCare` | `elderly_self_care` |
|
| LNRZLPG00003 | `/lnrzlpg/update` | `UpdateElderlySelfCare` | `elderly_self_care` |
|
||||||
| LNRZYTZ00001 | `/lnrzyygl/create` | `CreateTCMConstitution` | `tcm` |
|
| LNRZYTZ00001 | `/lnrzyygl/create` | `CreateTCMConstitution` | `tcm` |
|
||||||
| LNRZYTZ00003 | `/lnrzyygl/update` | `UpdateTCMConstitution` | `tcm` |
|
| LNRZYTZ00003 | `/lnrzyygl/update` | `UpdateTCMConstitution` | `tcm` |
|
||||||
|
|||||||
+17
-1
@@ -167,6 +167,21 @@ GET /api/dictionaries/orgs
|
|||||||
|
|
||||||
- 上游:`CXJG00002` `/auto/cxjg/query`
|
- 上游:`CXJG00002` `/auto/cxjg/query`
|
||||||
- 返回:`data` 为**数组**(机构主数据,含 `organizCode`、`organizName`、`organizType`、`parentId` 等)
|
- 返回:`data` 为**数组**(机构主数据,含 `organizCode`、`organizName`、`organizType`、`parentId` 等)
|
||||||
|
|
||||||
|
### 10. 查询老年人生活自理能力评估
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /api/elderly/self-care
|
||||||
|
```
|
||||||
|
|
||||||
|
| 参数 | 必填 | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `idCard` | **是** | 身份证件号 |
|
||||||
|
| `phrId` | 否 | 健康档案编号(注意驼峰 `phrId`) |
|
||||||
|
| `checkId` | 否 | 第三方检查主键 |
|
||||||
|
|
||||||
|
- 上游:`LNRZLPG00002` `/auto/lnr/query`(厂家文档契约,待真实联调确认)
|
||||||
|
- 返回:`data` 为**数组**,每条含进餐/梳洗/穿衣/如厕/活动及总评的原始值、等级和评分;完整字段原样回写
|
||||||
---
|
---
|
||||||
|
|
||||||
## 调用示例
|
## 调用示例
|
||||||
@@ -181,6 +196,7 @@ curl "http://127.0.0.1:8080/api/dictionaries/grid-addresses?parentCode=<区划
|
|||||||
curl "http://127.0.0.1:8080/api/dictionaries/doctors?manaUnitId=<机构码>"
|
curl "http://127.0.0.1:8080/api/dictionaries/doctors?manaUnitId=<机构码>"
|
||||||
curl "http://127.0.0.1:8080/api/dictionaries/drugs?pageNo=1&pageSize=10&ypmc=<药品名>" # pageNo 必填
|
curl "http://127.0.0.1:8080/api/dictionaries/drugs?pageNo=1&pageSize=10&ypmc=<药品名>" # pageNo 必填
|
||||||
curl "http://127.0.0.1:8080/api/dictionaries/orgs?parentId=<上级机构ID>"
|
curl "http://127.0.0.1:8080/api/dictionaries/orgs?parentId=<上级机构ID>"
|
||||||
|
curl "http://127.0.0.1:8080/api/elderly/self-care?idCard=<身份证>"
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -188,5 +204,5 @@ curl "http://127.0.0.1:8080/api/dictionaries/orgs?parentId=<上级机构ID>"
|
|||||||
## 尚未提供(后续)
|
## 尚未提供(后续)
|
||||||
|
|
||||||
- 写入类端点(档案/体检 create/update):`handler` 侧 `/api/health-record/save` 等待 T-204/T-206 及厂家写入授权。
|
- 写入类端点(档案/体检 create/update):`handler` 侧 `/api/health-record/save` 等待 T-204/T-206 及厂家写入授权。
|
||||||
- 老年人自理/体质、中医指导查询端点:待对应 OSI serviceId 联调(docs/06 B4)。
|
- 老年人中医体质辨识、中医指导查询端点:待对应 OSI serviceId/字段契约(docs/06 B4)。
|
||||||
- 鉴权、访问日志、限流:当前是本机联调工具形态,对外前必须补齐。
|
- 鉴权、访问日志、限流:当前是本机联调工具形态,对外前必须补齐。
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
## 当前快照
|
## 当前快照
|
||||||
|
|
||||||
- 日期:2026-07-09
|
- 日期:2026-07-09
|
||||||
- 阶段:**Phase D 创建/更新代码基线完成,真实写入验收受阻;T-303 老年人生活自理能力评估查询待实现**;T-001~T-006、T-201、T-203、T-102、T-202、T-205、T-101、T-103、T-209、T-210 已验收;T-206 已完成本地契约/客户端/映射组装代码,但未执行真实 `JKDA00001` create
|
- 阶段:**Phase D 创建/更新代码基线完成,真实写入验收受阻;T-303 老年人生活自理能力评估查询代码完成、真实联调受阻**;T-001~T-006、T-201、T-203、T-102、T-202、T-205、T-101、T-103、T-209、T-210 已验收;T-206 已完成本地契约/客户端/映射组装代码,但未执行真实 `JKDA00001` create
|
||||||
- 技术栈:Go 1.24 单二进制;`main.go -mode server|deliver`;配置读取使用 viper,支持环境变量覆盖;OSI 客户端已具备签名、信封、传输、基础判码、JKDA00002 Find、JKDA00005 FindRqbj(人群分类,已按实测 auto 路径校准)、JKDA00001 Create、JKDA00003 Update,以及 WGDZ/ZRYS/YPML/CXJG 四个公开查询薄封装
|
- 技术栈:Go 1.24 单二进制;`main.go -mode server|deliver`;配置读取使用 viper,支持环境变量覆盖;OSI 客户端已具备签名、信封、传输、基础判码、JKDA00002 Find、JKDA00005 FindRqbj(人群分类,已按实测 auto 路径校准)、JKDA00001 Create、JKDA00003 Update、LNRZLPG00002 老年人生活自理能力查询(待真实联调),以及 WGDZ/ZRYS/YPML/CXJG 四个公开查询薄封装
|
||||||
- 生产代码:已有 `main.go`、`config/`、`contract/envelope.go`、`contract/jkda.go`、`osi/` 薄客户端、`cache/dictionary.go`、`verify_jkda.go`、`go.mod`/`go.sum`;`mapping/dict.go`、`mapping/health_record.go`、`mapping/checkid.go` 已建立映射纯函数、码表基线、主数据反查接入点和创建请求组装;`handler/health_record.go`+`handler/public.go`+`server.go` 提供 server 模式档案查询、人群分类查询、网格地址、责任医生、药品目录、机构查询端点;`pipeline/` 等业务模块仍待后续任务建立
|
- 生产代码:已有 `main.go`、`config/`、`contract/envelope.go`、`contract/jkda.go`、`contract/lnr.go`、`osi/` 薄客户端、`cache/dictionary.go`、`verify_jkda.go`、`go.mod`/`go.sum`;`mapping/dict.go`、`mapping/health_record.go`、`mapping/checkid.go` 已建立映射纯函数、码表基线、主数据反查接入点和创建请求组装;`handler/health_record.go`+`handler/elderly.go`+`handler/public.go`+`server.go` 提供 server 模式档案查询、人群分类查询、老年人自理能力查询、网格地址、责任医生、药品目录、机构查询端点;`pipeline/` 等业务模块仍待后续任务建立
|
||||||
- 联调现实:**JKDA00002 个人档案查询已用 Go 侧真实请求打通**,返回 `code="01" message="操作成功" data_count=1`;**公开查询 WGDZ00001/ZRYS00001/CXJG00002 已用真实档案主数据验证通过**,均返回 `code="01"` 且数组非空;药品目录 YPML00001 已完成客户端封装和单测,尚未做真实药品关键字样本验证;**JKDA00001 create 未跑真实请求**,避免在没有安全测试居民/写入授权时污染平台档案
|
- 联调现实:**JKDA00002 个人档案查询已用 Go 侧真实请求打通**,返回 `code="01" message="操作成功" data_count=1`;**公开查询 WGDZ00001/ZRYS00001/CXJG00002 已用真实档案主数据验证通过**,均返回 `code="01"` 且数组非空;药品目录 YPML00001 已完成客户端封装和单测,尚未做真实药品关键字样本验证;**JKDA00001 create 未跑真实请求**,避免在没有安全测试居民/写入授权时污染平台档案
|
||||||
- 测试:`go test ./...` 通过;当前测试覆盖 mode 解析、配置加载与环境变量覆盖、MD5 签名、请求头组装、JSON POST 传输、头名大小写保留、identity 响应编码声明、超时配置、SOCKS5 代理地址校验、信封结构、serviceId 路由、成功/重试判码、Client.Call 请求与响应解析、JKDA00002 查询响应契约、JKDA00001/00003 创建更新请求契约与客户端方法、JKDA00002 Find、JKDA00005 FindRqbj(personSign/idCard/phrId)、公开查询四接口、公开查询 HTTP API、字典缓存快照与持久化失败不阻断、映射码表双向查找、民族 01~56 完整性、健康档案映射必填/码表校验、主数据名称反查、创建请求组装、checkId 确定性、docx/联调风格映射样本基线、JKDA00002 验证入口
|
- 测试:`go test ./...` 通过;当前测试覆盖 mode 解析、配置加载与环境变量覆盖、MD5 签名、请求头组装、JSON POST 传输、头名大小写保留、identity 响应编码声明、超时配置、SOCKS5 代理地址校验、信封结构、serviceId 路由、成功/重试判码、Client.Call 请求与响应解析、JKDA00002 查询响应契约、JKDA00001/00003 创建更新请求契约与客户端方法、JKDA00002 Find、JKDA00005 FindRqbj(personSign/idCard/phrId)、公开查询四接口、公开查询 HTTP API、字典缓存快照与持久化失败不阻断、映射码表双向查找、民族 01~56 完整性、健康档案映射必填/码表校验、主数据名称反查、创建请求组装、checkId 确定性、docx/联调风格映射样本基线、JKDA00002 验证入口
|
||||||
- 标准启动路径:`./init.sh` 已配置三步:依赖下载、`go test ./...`、`go run . -mode server -config config.yaml.example`
|
- 标准启动路径:`./init.sh` 已配置三步:依赖下载、`go test ./...`、`go run . -mode server -config config.yaml.example`
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
| `mapping/health_record_baseline_test.go` | 已有 | docx 风格、联调风格、脏数据映射回归样本 |
|
| `mapping/health_record_baseline_test.go` | 已有 | docx 风格、联调风格、脏数据映射回归样本 |
|
||||||
| `handler/health_record.go` | 已有 | `GET /api/health-record/find` 档案查询、`GET /api/health-record/crowd` 人群分类查询,均回写平台完整响应 |
|
| `handler/health_record.go` | 已有 | `GET /api/health-record/find` 档案查询、`GET /api/health-record/crowd` 人群分类查询,均回写平台完整响应 |
|
||||||
| `handler/health_check.go` | 已有 | 体检端点 `GET /api/health-check/last`(最近一次)+ `/all`(全部体检)+ `/list`(年度名单)|
|
| `handler/health_check.go` | 已有 | 体检端点 `GET /api/health-check/last`(最近一次)+ `/all`(全部体检)+ `/list`(年度名单)|
|
||||||
|
| `handler/elderly.go` | 已有 | `GET /api/elderly/self-care` 老年人生活自理能力评估查询(待真实联调) |
|
||||||
| `handler/public.go` | 已有 | 公开查询端点 `GET /api/dictionaries/grid-addresses`、`/doctors`、`/drugs`、`/orgs` |
|
| `handler/public.go` | 已有 | 公开查询端点 `GET /api/dictionaries/grid-addresses`、`/doctors`、`/drugs`、`/orgs` |
|
||||||
| `server.go` `osi_client.go` | 已有 | server 模式起 HTTP 服务、注册路由;`buildOSIClient` 共用构造(verify 与 server 复用) |
|
| `server.go` `osi_client.go` | 已有 | server 模式起 HTTP 服务、注册路由;`buildOSIClient` 共用构造(verify 与 server 复用) |
|
||||||
| `pipeline/` 等 | 待建 | 后续任务 |
|
| `pipeline/` 等 | 待建 | 后续任务 |
|
||||||
@@ -85,6 +86,7 @@ curl "http://127.0.0.1:8080/api/health-record/crowd?idCard=<idCard>" #
|
|||||||
curl "http://127.0.0.1:8080/api/health-check/last?idCard=<idCard>" # 最近一次体检
|
curl "http://127.0.0.1:8080/api/health-check/last?idCard=<idCard>" # 最近一次体检
|
||||||
curl "http://127.0.0.1:8080/api/health-check/all?idCard=<idCard>" # 某人全部体检(数组)
|
curl "http://127.0.0.1:8080/api/health-check/all?idCard=<idCard>" # 某人全部体检(数组)
|
||||||
curl "http://127.0.0.1:8080/api/health-check/list?checkYear=2025&idCard=<idCard>" # 年度已检/未检名单
|
curl "http://127.0.0.1:8080/api/health-check/list?checkYear=2025&idCard=<idCard>" # 年度已检/未检名单
|
||||||
|
curl "http://127.0.0.1:8080/api/elderly/self-care?idCard=<idCard>" # 老年人生活自理能力评估(待真实联调)
|
||||||
curl "http://127.0.0.1:8080/api/dictionaries/grid-addresses?parentCode=<区划码>" # 网格地址
|
curl "http://127.0.0.1:8080/api/dictionaries/grid-addresses?parentCode=<区划码>" # 网格地址
|
||||||
curl "http://127.0.0.1:8080/api/dictionaries/doctors?manaUnitId=<机构码>" # 责任医生
|
curl "http://127.0.0.1:8080/api/dictionaries/doctors?manaUnitId=<机构码>" # 责任医生
|
||||||
curl "http://127.0.0.1:8080/api/dictionaries/drugs?pageNo=1&ypmc=<药品名>" # 药品目录(pageNo 必填)
|
curl "http://127.0.0.1:8080/api/dictionaries/drugs?pageNo=1&ypmc=<药品名>" # 药品目录(pageNo 必填)
|
||||||
@@ -99,7 +101,7 @@ python3 scripts/query_health_record.py
|
|||||||
> 读先行调整(2026-07-08):写入(T-206/T-204)被厂家授权锁死,先推其余业务线查询。
|
> 读先行调整(2026-07-08):写入(T-206/T-204)被厂家授权锁死,先推其余业务线查询。
|
||||||
|
|
||||||
1. ✅ T-301/T-305 体检查询(最近一次 + 名单)、T-302 体检 HTTP 端点 —— 均已完成。
|
1. ✅ T-301/T-305 体检查询(最近一次 + 名单)、T-302 体检 HTTP 端点 —— 均已完成。
|
||||||
2. **T-303 老年人生活自理能力评估查询**:厂家文档已给出 `LNRZLPG00002` 与 `/auto/lnr/query`,先实现客户端、HTTP 端点与测试,再用真实请求确认契约。
|
2. **T-303 真实联调**:提供安全测试身份证后,确认 `LNRZLPG00002`、`/auto/lnr/query` 与响应字段;当前代码/单测已完成。
|
||||||
3. T-307 老年人中医体质辨识查询仍待厂家补查询文档(docs/06 B4)。
|
3. T-307 老年人中医体质辨识查询仍待厂家补查询文档(docs/06 B4)。
|
||||||
4. 并行催厂家(docs/06 ★ 优先催办):写入授权+测试档案、缺失单查/老年人体质 serviceId、checkId/完整度规则。
|
4. 并行催厂家(docs/06 ★ 优先催办):写入授权+测试档案、缺失单查/老年人体质 serviceId、checkId/完整度规则。
|
||||||
4. 授权到位后回到 T-206 真实 create 验收 → T-204。
|
4. 授权到位后回到 T-206 真实 create 验收 → T-204。
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ tags:
|
|||||||
description: 健康体检查询
|
description: 健康体检查询
|
||||||
- name: dictionaries
|
- name: dictionaries
|
||||||
description: 公开主数据查询
|
description: 公开主数据查询
|
||||||
|
- name: elderly
|
||||||
|
description: 老年人业务查询
|
||||||
paths:
|
paths:
|
||||||
/api/health-record/find:
|
/api/health-record/find:
|
||||||
get:
|
get:
|
||||||
@@ -230,6 +232,59 @@ paths:
|
|||||||
$ref: '#/components/responses/MethodNotAllowed'
|
$ref: '#/components/responses/MethodNotAllowed'
|
||||||
'502':
|
'502':
|
||||||
$ref: '#/components/responses/BadGateway'
|
$ref: '#/components/responses/BadGateway'
|
||||||
|
/api/elderly/self-care:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- elderly
|
||||||
|
summary: 查询老年人生活自理能力评估
|
||||||
|
description: 厂家文档给出的 LNRZLPG00002 查询契约,待真实联调确认。原样返回上游 `/auto/lnr/query` 响应。
|
||||||
|
operationId: queryElderlySelfCare
|
||||||
|
parameters:
|
||||||
|
- name: idCard
|
||||||
|
in: query
|
||||||
|
required: true
|
||||||
|
description: 身份证件号。
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: phrId
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: 健康档案编号。注意参数名为驼峰 phrId。
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
- name: checkId
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
description: 第三方检查主键。
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: 平台完整响应,成功和平台业务错误均原样透传。
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/ElderlySelfCareResponse'
|
||||||
|
examples:
|
||||||
|
success:
|
||||||
|
value:
|
||||||
|
code: '01'
|
||||||
|
message: 操作成功
|
||||||
|
data:
|
||||||
|
- phrId: PHRID_PLACEHOLDER
|
||||||
|
checkId: LNR_CHECK_ID_PLACEHOLDER
|
||||||
|
jc: '1'
|
||||||
|
jcdj: '1'
|
||||||
|
jcpf: '10'
|
||||||
|
zp: '1'
|
||||||
|
zpdj: '1'
|
||||||
|
zpfs: '100'
|
||||||
|
'400':
|
||||||
|
$ref: '#/components/responses/BadRequest'
|
||||||
|
'405':
|
||||||
|
$ref: '#/components/responses/MethodNotAllowed'
|
||||||
|
'502':
|
||||||
|
$ref: '#/components/responses/BadGateway'
|
||||||
/api/dictionaries/grid-addresses:
|
/api/dictionaries/grid-addresses:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
@@ -647,3 +702,52 @@ components:
|
|||||||
items:
|
items:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
|
ElderlySelfCareResponse:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/OSIBaseResponse'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
data:
|
||||||
|
type: array
|
||||||
|
description: 老年人生活自理能力评估记录数组。
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/ElderlySelfCareAssessment'
|
||||||
|
ElderlySelfCareAssessment:
|
||||||
|
type: object
|
||||||
|
description: 厂家查询文档列出的评估字段;完整原始字段由服务透传。
|
||||||
|
properties:
|
||||||
|
phrId:
|
||||||
|
type: string
|
||||||
|
checkId:
|
||||||
|
type: string
|
||||||
|
jc:
|
||||||
|
type: string
|
||||||
|
description: 进餐原始值。
|
||||||
|
jcdj:
|
||||||
|
type: string
|
||||||
|
description: 进餐等级。
|
||||||
|
jcpf:
|
||||||
|
type: string
|
||||||
|
description: 进餐评分。
|
||||||
|
sx:
|
||||||
|
type: string
|
||||||
|
description: 梳洗原始值。
|
||||||
|
cy:
|
||||||
|
type: string
|
||||||
|
description: 穿衣原始值。
|
||||||
|
rc:
|
||||||
|
type: string
|
||||||
|
description: 如厕原始值。
|
||||||
|
hd:
|
||||||
|
type: string
|
||||||
|
description: 活动原始值。
|
||||||
|
zp:
|
||||||
|
type: string
|
||||||
|
description: 总评。
|
||||||
|
zpdj:
|
||||||
|
type: string
|
||||||
|
description: 总评等级。
|
||||||
|
zpfs:
|
||||||
|
type: string
|
||||||
|
description: 总评分数。
|
||||||
|
additionalProperties: true
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"chis_osi/osi"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ElderlyHandler 暴露老年人业务查询 HTTP 入口。
|
||||||
|
type ElderlyHandler struct {
|
||||||
|
client *osi.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewElderlyHandler(client *osi.Client) *ElderlyHandler {
|
||||||
|
return &ElderlyHandler{client: client}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SelfCare 处理 GET /api/elderly/self-care?idCard=..&phrId=..&checkId=..
|
||||||
|
func (h *ElderlyHandler) SelfCare(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
writeJSONError(w, http.StatusMethodNotAllowed, "only GET is supported")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
q := r.URL.Query()
|
||||||
|
if q.Get("idCard") == "" {
|
||||||
|
writeJSONError(w, http.StatusBadRequest, "idCard is required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, result, err := h.client.QueryElderlySelfCare(r.Context(), osi.ElderlySelfCareQuery{
|
||||||
|
IDCard: q.Get("idCard"),
|
||||||
|
PHRID: q.Get("phrId"),
|
||||||
|
CheckID: q.Get("checkId"),
|
||||||
|
})
|
||||||
|
writeRawOrError(w, result, err)
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestElderlySelfCareReturnsRawResponse(t *testing.T) {
|
||||||
|
client, seenPath := newTestClient(t, `{"code":"01","message":"操作成功","data":[{"checkId":"LNR-1","jc":"1","zpfs":"100"}]}`)
|
||||||
|
h := NewElderlyHandler(client)
|
||||||
|
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/elderly/self-care?idCard=TEST-ID&phrId=PHR-1", nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
h.SelfCare(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("status = %d", rec.Code)
|
||||||
|
}
|
||||||
|
if *seenPath != "/osi/api/auto/lnr/query" {
|
||||||
|
t.Fatalf("osi path = %q", *seenPath)
|
||||||
|
}
|
||||||
|
body, _ := io.ReadAll(rec.Body)
|
||||||
|
if !strings.Contains(string(body), `"zpfs":"100"`) {
|
||||||
|
t.Fatalf("body missing assessment content: %s", body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestElderlySelfCareRequiresIDCard(t *testing.T) {
|
||||||
|
h := NewElderlyHandler(nil)
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/elderly/self-care?phrId=PHR-1", nil)
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
h.SelfCare(rec, req)
|
||||||
|
|
||||||
|
if rec.Code != http.StatusBadRequest {
|
||||||
|
t.Fatalf("status = %d, want 400", rec.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ const (
|
|||||||
ServiceIDJKTJLast = "JKTJLSJL00002" // 最近一次体检(实测可用)
|
ServiceIDJKTJLast = "JKTJLSJL00002" // 最近一次体检(实测可用)
|
||||||
ServiceIDJKTJQuery = "JKTJ00002" // 某人全部体检(实测可用,返回数组)
|
ServiceIDJKTJQuery = "JKTJ00002" // 某人全部体检(实测可用,返回数组)
|
||||||
ServiceIDJKTJList = "JKTJLIST00002" // 已检/待检人员名单(实测可用)
|
ServiceIDJKTJList = "JKTJLIST00002" // 已检/待检人员名单(实测可用)
|
||||||
|
ServiceIDLNRSelfCareQuery = "LNRZLPG00002" // 老年人生活自理能力评估查询(待联调确认)
|
||||||
)
|
)
|
||||||
|
|
||||||
const codeRetryableTimeout = "405"
|
const codeRetryableTimeout = "405"
|
||||||
@@ -34,6 +35,7 @@ var servicePaths = map[string]string{
|
|||||||
ServiceIDJKTJLast: "/auto/jktjlscx/query",
|
ServiceIDJKTJLast: "/auto/jktjlscx/query",
|
||||||
ServiceIDJKTJQuery: "/auto/jktj/query",
|
ServiceIDJKTJQuery: "/auto/jktj/query",
|
||||||
ServiceIDJKTJList: "/auto/jktjlist/query",
|
ServiceIDJKTJList: "/auto/jktjlist/query",
|
||||||
|
ServiceIDLNRSelfCareQuery: "/auto/lnr/query",
|
||||||
}
|
}
|
||||||
|
|
||||||
func PathOf(serviceID string) (string, error) {
|
func PathOf(serviceID string) (string, error) {
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package osi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"chis_osi/contract"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ElderlySelfCareQuery 是 LNRZLPG00002 的查询条件。
|
||||||
|
// 厂家文档要求 idCard,phrId 和 checkId 为可选定位条件。
|
||||||
|
type ElderlySelfCareQuery struct {
|
||||||
|
IDCard string
|
||||||
|
PHRID string
|
||||||
|
CheckID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryElderlySelfCare 查询老年人生活自理能力评估记录。
|
||||||
|
func (c *Client) QueryElderlySelfCare(ctx context.Context, query ElderlySelfCareQuery) ([]contract.ElderlySelfCareAssessment, Result, error) {
|
||||||
|
baseInfo, err := query.baseInfo()
|
||||||
|
if err != nil {
|
||||||
|
return nil, Result{}, err
|
||||||
|
}
|
||||||
|
var rows []contract.ElderlySelfCareAssessment
|
||||||
|
result, err := c.Call(ctx, ServiceIDLNRSelfCareQuery, baseInfo, &rows)
|
||||||
|
return rows, result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q ElderlySelfCareQuery) baseInfo() (map[string]string, error) {
|
||||||
|
if q.IDCard == "" {
|
||||||
|
return nil, fmt.Errorf("query elderly self care requires idCard")
|
||||||
|
}
|
||||||
|
baseInfo := map[string]string{"idCard": q.IDCard}
|
||||||
|
if q.PHRID != "" {
|
||||||
|
baseInfo["phrId"] = q.PHRID
|
||||||
|
}
|
||||||
|
if q.CheckID != "" {
|
||||||
|
baseInfo["checkId"] = q.CheckID
|
||||||
|
}
|
||||||
|
return baseInfo, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package osi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestQueryElderlySelfCareUsesDocumentedContract(t *testing.T) {
|
||||||
|
var seenPath string
|
||||||
|
var seenBody 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(&seenBody); err != nil {
|
||||||
|
t.Fatalf("decode request: %v", err)
|
||||||
|
}
|
||||||
|
_, _ = w.Write([]byte(`{"code":"01","message":"操作成功","data":[{"phrId":"PHR-1","checkId":"LNR-1","jc":"1","jcdj":"1","jcpf":"10","zp":"1","zpdj":"1","zpfs":"100","createDate":"2026-01-01"}]}`))
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client := newTestJKDAClient(t, server.URL)
|
||||||
|
rows, result, err := client.QueryElderlySelfCare(context.Background(), ElderlySelfCareQuery{
|
||||||
|
IDCard: "TEST-ID",
|
||||||
|
PHRID: "PHR-1",
|
||||||
|
CheckID: "LNR-1",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("QueryElderlySelfCare: %v", err)
|
||||||
|
}
|
||||||
|
if seenPath != "/osi/api/auto/lnr/query" {
|
||||||
|
t.Fatalf("path = %q", seenPath)
|
||||||
|
}
|
||||||
|
if seenBody["serviceId"] != ServiceIDLNRSelfCareQuery {
|
||||||
|
t.Fatalf("serviceId = %v", seenBody["serviceId"])
|
||||||
|
}
|
||||||
|
baseInfo := seenBody["uploadinfo"].(map[string]any)["baseInfo"].(map[string]any)
|
||||||
|
if baseInfo["idCard"] != "TEST-ID" || baseInfo["phrId"] != "PHR-1" || baseInfo["checkId"] != "LNR-1" {
|
||||||
|
t.Fatalf("baseInfo = %#v", baseInfo)
|
||||||
|
}
|
||||||
|
if !result.Success || len(rows) != 1 {
|
||||||
|
t.Fatalf("rows=%d result=%#v", len(rows), result)
|
||||||
|
}
|
||||||
|
if rows[0].Meal != "1" || rows[0].TotalScore != "100" || rows[0].CheckID != "LNR-1" {
|
||||||
|
t.Fatalf("row = %#v", rows[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestElderlySelfCareQueryRequiresIDCard(t *testing.T) {
|
||||||
|
if _, err := (ElderlySelfCareQuery{PHRID: "PHR-1"}).baseInfo(); err == nil {
|
||||||
|
t.Fatal("missing idCard should error")
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
@@ -292,6 +292,17 @@
|
|||||||
- 风险:docx 请求样例错误写 `LNR00004` 且缺 `uploadinfo/manageInfo`,仅能以参数表和既有查询信封实施;服务路径、serviceId、字段仍须真实请求验收后确认。
|
- 风险:docx 请求样例错误写 `LNR00004` 且缺 `uploadinfo/manageInfo`,仅能以参数表和既有查询信封实施;服务路径、serviceId、字段仍须真实请求验收后确认。
|
||||||
- 下一步:领取 T-303,先做 `contract/lnr.go`、`osi/lnr.go`、HTTP handler 与回归测试,再以安全测试居民探针联调。
|
- 下一步:领取 T-303,先做 `contract/lnr.go`、`osi/lnr.go`、HTTP handler 与回归测试,再以安全测试居民探针联调。
|
||||||
|
|
||||||
|
## 2026-07-13 T-303 老年人生活自理能力评估查询
|
||||||
|
|
||||||
|
- 状态:BLOCKED(代码、测试、HTTP 文档完成;真实联调缺安全测试身份证)
|
||||||
|
- 变更:新增 `contract/lnr.go`(评估响应字段)、`osi/lnr.go`(`QueryElderlySelfCare`)、`osi/lnr_test.go`;在 `osi/codes.go` 登记 `LNRZLPG00002 -> /auto/lnr/query`。
|
||||||
|
- 变更:新增 `handler/elderly.go`、`handler/elderly_test.go`,提供 `GET /api/elderly/self-care?idCard=...&phrId=...&checkId=...`,查询响应继续原样回写;`server.go` 注册路由;同步 docs/07、OpenAPI 与当前快照。
|
||||||
|
- RED:`go test ./osi ./handler -run "Test(QueryElderlySelfCare|ElderlySelfCare)" -count=1` 初次失败,缺少查询方法、查询类型、serviceId 与 handler。
|
||||||
|
- GREEN:补最小实现后上述目标测试通过。
|
||||||
|
- 验证:`go test ./...`、`go build ./...`、OpenAPI YAML 解析与 `git diff --check` 通过。
|
||||||
|
- 阻塞:本机存在 `config.yaml`,但没有 `OSI_VERIFY_ID_CARD`,未提供可用于该接口的安全测试身份证;不可把厂家 docx 契约当作真实平台已确认。
|
||||||
|
- 下一步:提供安全测试身份证后,以 Go 客户端做只读查询,记录脱敏后的 `code/message/data_count`,据结果确认或修正 serviceId、路径与字段。
|
||||||
|
|
||||||
## 2026-07-09 T-211 药品目录分页契约修正(登记)
|
## 2026-07-09 T-211 药品目录分页契约修正(登记)
|
||||||
|
|
||||||
- 状态:DOING
|
- 状态:DOING
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ func runServer(cfg config.Config, addr string) error {
|
|||||||
|
|
||||||
hr := handler.NewHealthRecordHandler(client)
|
hr := handler.NewHealthRecordHandler(client)
|
||||||
hc := handler.NewHealthCheckHandler(client)
|
hc := handler.NewHealthCheckHandler(client)
|
||||||
|
elderly := handler.NewElderlyHandler(client)
|
||||||
pub := handler.NewPublicHandler(client)
|
pub := handler.NewPublicHandler(client)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
mux.HandleFunc("/api/health-record/find", hr.Find)
|
mux.HandleFunc("/api/health-record/find", hr.Find)
|
||||||
@@ -24,6 +25,7 @@ func runServer(cfg config.Config, addr string) error {
|
|||||||
mux.HandleFunc("/api/health-check/last", hc.Last)
|
mux.HandleFunc("/api/health-check/last", hc.Last)
|
||||||
mux.HandleFunc("/api/health-check/all", hc.All)
|
mux.HandleFunc("/api/health-check/all", hc.All)
|
||||||
mux.HandleFunc("/api/health-check/list", hc.List)
|
mux.HandleFunc("/api/health-check/list", hc.List)
|
||||||
|
mux.HandleFunc("/api/elderly/self-care", elderly.SelfCare)
|
||||||
mux.HandleFunc("/api/dictionaries/grid-addresses", pub.GridAddresses)
|
mux.HandleFunc("/api/dictionaries/grid-addresses", pub.GridAddresses)
|
||||||
mux.HandleFunc("/api/dictionaries/doctors", pub.Doctors)
|
mux.HandleFunc("/api/dictionaries/doctors", pub.Doctors)
|
||||||
mux.HandleFunc("/api/dictionaries/drugs", pub.Drugs)
|
mux.HandleFunc("/api/dictionaries/drugs", pub.Drugs)
|
||||||
@@ -35,6 +37,7 @@ func runServer(cfg config.Config, addr string) error {
|
|||||||
fmt.Printf(" GET http://%s/api/health-check/last?idCard=<身份证>\n", addr)
|
fmt.Printf(" GET http://%s/api/health-check/last?idCard=<身份证>\n", addr)
|
||||||
fmt.Printf(" GET http://%s/api/health-check/all?idCard=<身份证>\n", addr)
|
fmt.Printf(" GET http://%s/api/health-check/all?idCard=<身份证>\n", addr)
|
||||||
fmt.Printf(" GET http://%s/api/health-check/list?checkYear=<年度>&idCard=<身份证>\n", addr)
|
fmt.Printf(" GET http://%s/api/health-check/list?checkYear=<年度>&idCard=<身份证>\n", addr)
|
||||||
|
fmt.Printf(" GET http://%s/api/elderly/self-care?idCard=<身份证>\n", addr)
|
||||||
fmt.Printf(" GET http://%s/api/dictionaries/grid-addresses?parentCode=<区划码>\n", addr)
|
fmt.Printf(" GET http://%s/api/dictionaries/grid-addresses?parentCode=<区划码>\n", addr)
|
||||||
fmt.Printf(" GET http://%s/api/dictionaries/doctors?manaUnitId=<机构码>\n", addr)
|
fmt.Printf(" GET http://%s/api/dictionaries/doctors?manaUnitId=<机构码>\n", addr)
|
||||||
fmt.Printf(" GET http://%s/api/dictionaries/drugs?ypmc=<药品名>\n", addr)
|
fmt.Printf(" GET http://%s/api/dictionaries/drugs?ypmc=<药品名>\n", addr)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
| T-301 | 体检查询打通:`contract/jktj.go` + `osi/jktj.go`(最近一次 JKTJLSJL00002) | T-004 | 真实请求拿到 `code="01"` 与体检数据;响应字段(~260 项/7 节点)记入 docs/04 §11 | DONE(单条 JKTJ00002 平台未部署,见 §11) |
|
| T-301 | 体检查询打通:`contract/jktj.go` + `osi/jktj.go`(最近一次 JKTJLSJL00002) | T-004 | 真实请求拿到 `code="01"` 与体检数据;响应字段(~260 项/7 节点)记入 docs/04 §11 | DONE(单条 JKTJ00002 平台未部署,见 §11) |
|
||||||
| T-302 | 体检 HTTP 查询端点(复用 T-208 handler 模式) | T-301 | server 模式 `GET /api/health-check/last`+`/all`+`/list` curl 返回完整 JSON;默认仅绑本机 | DONE |
|
| T-302 | 体检 HTTP 查询端点(复用 T-208 handler 模式) | T-301 | server 模式 `GET /api/health-check/last`+`/all`+`/list` curl 返回完整 JSON;默认仅绑本机 | DONE |
|
||||||
| T-306 | 某人全部体检查询 JKTJ00002(`osi.QueryHealthChecks` + `/api/health-check/all`)| T-004 | 实测已部署,按 idCard 返回全部体检数组;驼峰 idCard、历史记录 checkId 可空,契约见 docs/04 §11.1 | DONE |
|
| T-306 | 某人全部体检查询 JKTJ00002(`osi.QueryHealthChecks` + `/api/health-check/all`)| T-004 | 实测已部署,按 idCard 返回全部体检数组;驼峰 idCard、历史记录 checkId 可空,契约见 docs/04 §11.1 | DONE |
|
||||||
| T-303 | 老年人生活自理能力评估查询(LNRZLPG00002) | T-004 | 按厂家查询文档实现 `/auto/lnr/query`;按 idCard 查询返回评估数组;真实请求确认 serviceId/路径/字段 | TODO(文档契约已取得,待联调确认) |
|
| T-303 | 老年人生活自理能力评估查询(LNRZLPG00002) | T-004 | 按厂家查询文档实现 `/auto/lnr/query`;按 idCard 查询返回评估数组;真实请求确认 serviceId/路径/字段 | BLOCKED(代码/单测/HTTP 文档完成;缺安全测试身份证做真实联调) |
|
||||||
| T-307 | 老年人中医体质辨识查询(LNRZYTZ00002) | T-004 | 取得厂家查询契约后实现并真实请求打通 | BLOCKED(待 docs/06 B4 补体质查询文档) |
|
| T-307 | 老年人中医体质辨识查询(LNRZYTZ00002) | T-004 | 取得厂家查询契约后实现并真实请求打通 | BLOCKED(待 docs/06 B4 补体质查询文档) |
|
||||||
| T-305 | 体检已检/未检名单查询 JKTJLIST00002(`osi` 方法 + 契约)| T-004 | `auto/jktjlist/query` 探针实测已部署(code=01 返回名单);`osi.ListHealthCheckPeople` 按 checkYear+idCard 返回名单(含 checkType 状态),契约见 docs/04 §11.4 | DONE |
|
| T-305 | 体检已检/未检名单查询 JKTJLIST00002(`osi` 方法 + 契约)| T-004 | `auto/jktjlist/query` 探针实测已部署(code=01 返回名单);`osi.ListHealthCheckPeople` 按 checkYear+idCard 返回名单(含 checkType 状态),契约见 docs/04 §11.4 | DONE |
|
||||||
| T-304 | 列表类查询(**档案 / 老年人自理·体质 / 中医指导** 列表,serviceId docx 缺漏)| T-004 | 各列表路径+serviceId 到位后返回分页数组 | BLOCKED(待 docs/06 B1/B2 厂家回填)|
|
| T-304 | 列表类查询(**档案 / 老年人自理·体质 / 中医指导** 列表,serviceId docx 缺漏)| T-004 | 各列表路径+serviceId 到位后返回分页数组 | BLOCKED(待 docs/06 B1/B2 厂家回填)|
|
||||||
|
|||||||
Reference in New Issue
Block a user