|
@@ -48,17 +48,17 @@ D/X 同步引擎(`HealthSyncServiceImpl` / `XiaomiHealthServiceImpl`)已实
|
|
|
| `dimension` | `dimension_codes`(逗号分隔) | 切分后逐码 `body.X` → `X`;须 ∈ {growth,sleep,vision,immunity,nutrition,gut,exercise},未知码丢弃 | 一条 source 记录可产出多行(如 body_weight → nutrition+growth 两行) |
|
|
| `dimension` | `dimension_codes`(逗号分隔) | 切分后逐码 `body.X` → `X`;须 ∈ {growth,sleep,vision,immunity,nutrition,gut,exercise},未知码丢弃 | 一条 source 记录可产出多行(如 body_weight → nutrition+growth 两行) |
|
|
|
| `score` | `parsed_result.normalized.score` | 直取(0-100 带归一化分,BAND_SCORE 已产出) | 多源同日冲突:**读最新覆盖**(与原 §3c 语义一致:`getLatest` created_at DESC LIMIT 1) |
|
|
| `score` | `parsed_result.normalized.score` | 直取(0-100 带归一化分,BAND_SCORE 已产出) | 多源同日冲突:**读最新覆盖**(与原 §3c 语义一致:`getLatest` created_at DESC LIMIT 1) |
|
|
|
| `percentile` | `parsed_result.normalized.percentile` | 直取(可空) | |
|
|
| `percentile` | `parsed_result.normalized.percentile` | 直取(可空) | |
|
|
|
-| `data_source` | `parsed_result.sourceType` | `huawei_health` / `xiaomi_health` 映射为 `REPORT` 语义(设备采集 Auto)→ 建议新增 `DEVICE`;未拍板前暂用 `REPORT` | **待拍板项 ①** |
|
|
|
|
|
-| `tier` | — | D/X 设备自动采集 = 可信度 2(AI 分析级),随 data_source 裁决 | **待拍板项 ②** |
|
|
|
|
|
|
|
+| `data_source` | `parsed_result.sourceType` | `huawei_health` / `xiaomi_health` 映射为 `DEVICE`(设备采集 Auto;已拍板 §6 ①) | 已拍板:DEVICE |
|
|
|
|
|
+| `tier` | — | D/X 设备自动采集 = 可信度 2(AI 分析级;已拍板 §6 ②) | 已拍板:tier=2 |
|
|
|
| `raw_data` | `parsed_result`(整条 JSON) | 直存,含 dataType/单位/原始指标 | |
|
|
| `raw_data` | `parsed_result`(整条 JSON) | 直存,含 dataType/单位/原始指标 | |
|
|
|
| `assess_date` | `created_at` 对应采集日 | 取指标采集点日期(HuaweiHealthDataPoint 携带时间戳) | 过期语义沿用 `expire_date` 规则 |
|
|
| `assess_date` | `created_at` 对应采集日 | 取指标采集点日期(HuaweiHealthDataPoint 携带时间戳) | 过期语义沿用 `expire_date` 规则 |
|
|
|
|
|
|
|
|
-**写入语义**:幂等 upsert(member_id+dimension+assess_date 冲突 → 覆盖),**不得**与报告/手动填分产生的 `health_dimension_scores` 行互相覆盖消灭——按 `tier`/`data_source` 分层保留(报告 tier=1 最高优先级)。**防负向回归**:桥接不得降低既有 REPORT/MANUAL 得分行的有效性(非覆盖语义待拍板)。
|
|
|
|
|
|
|
+**写入语义**:幂等 upsert(member_id+dimension+assess_date 冲突 → 覆盖),**不得**与报告/手动填分产生的 `health_dimension_scores` 行互相覆盖消灭——按 `tier`/`data_source` 分层保留(报告 tier=1 最高优先级)。**防负向回归**:桥接不得降低既有 REPORT/MANUAL 得分行的有效性(非覆盖语义已拍板:按 tier/data_source 分层保留,报告 tier=1 最高优先级)。
|
|
|
|
|
|
|
|
### 3.2 消费侧接线契约
|
|
### 3.2 消费侧接线契约
|
|
|
|
|
|
|
|
1. **`DimensionScoreServiceImpl` 死注入解除**:注入的 `dataSourceRecordService` 必须产生真实调用——新增桥接步骤(建议独立 `HealthDataSourceBridgeService`):同步成功后把本批 `health_data_sources` 行按 §3.1 写入/更新 `health_dimension_scores`;`/api/dimension/overview`、`/api/dimension-registry/*` 由此自然读到 D/X 得分。
|
|
1. **`DimensionScoreServiceImpl` 死注入解除**:注入的 `dataSourceRecordService` 必须产生真实调用——新增桥接步骤(建议独立 `HealthDataSourceBridgeService`):同步成功后把本批 `health_data_sources` 行按 §3.1 写入/更新 `health_dimension_scores`;`/api/dimension/overview`、`/api/dimension-registry/*` 由此自然读到 D/X 得分。
|
|
|
-2. **写入触发点(二选一,待拍板项 ③)**:
|
|
|
|
|
|
|
+2. **写入触发点(已拍板:A 同步内事务桥接,见 §6 ③)**:
|
|
|
- A:同步链路内(`saveRecord` 后同事务桥接)——实现简单、实时;
|
|
- A:同步链路内(`saveRecord` 后同事务桥接)——实现简单、实时;
|
|
|
- B:`health_data_sources` 新行侧车(读时桥接)——无写扩散但多一跳。
|
|
- B:`health_data_sources` 新行侧车(读时桥接)——无写扩散但多一跳。
|
|
|
3. **档案展示**:`POST /api/health/indicators/current`(读 `member_indicator_current`)与 `POST /api/health/body/detail`(读 `health_indicator`)**提供 D/X 来源展示**——新增读取源或合并视图,字段口径:`body.*` 得分可溯源 `source=huawei_health/xiaomi_health` + 采集时间 + 原始值(步数/心率/睡眠 h/体重 kg)。
|
|
3. **档案展示**:`POST /api/health/indicators/current`(读 `member_indicator_current`)与 `POST /api/health/body/detail`(读 `health_indicator`)**提供 D/X 来源展示**——新增读取源或合并视图,字段口径:`body.*` 得分可溯源 `source=huawei_health/xiaomi_health` + 采集时间 + 原始值(步数/心率/睡眠 h/体重 kg)。
|
|
@@ -82,8 +82,8 @@ D/X 同步引擎(`HealthSyncServiceImpl` / `XiaomiHealthServiceImpl`)已实
|
|
|
|
|
|
|
|
- **无新表**(复用 `health_data_sources` 读 + `health_dimension_scores` 写)。
|
|
- **无新表**(复用 `health_data_sources` 读 + `health_dimension_scores` 写)。
|
|
|
- 唯一迁移变更(若拍板):
|
|
- 唯一迁移变更(若拍板):
|
|
|
- 1. `health_dimension_scores.data_source` 注释与取值枚举扩展 `DEVICE`(可选,待拍板项 ①);
|
|
|
|
|
- 2. 如需幂等 upsert:`health_dimension_scores` 加唯一索引(member_id, dimension, assess_date)——**⚠ 影响存储**:该表已被报告/手动链路共用,加唯一索引需先查重清理,**列为待拍板项 ④,默认不加**(沿用读最新覆盖)。
|
|
|
|
|
|
|
+ 1. `health_dimension_scores.data_source` 注释与取值枚举扩展 `DEVICE`(已拍板:扩展,见 §6 ①);
|
|
|
|
|
+ 2. 如需幂等 upsert:`health_dimension_scores` 加唯一索引(member_id, dimension, assess_date)——**⚠ 影响存储**:该表已被报告/手动链路共用,加唯一索引需先查重清理,**已拍板:不加唯一索引(见 §6 ④)**(沿用读最新覆盖)。
|
|
|
|
|
|
|
|
## 5. 测试侧证据要求(契约合入后转 TR 补证,防伪证)
|
|
## 5. 测试侧证据要求(契约合入后转 TR 补证,防伪证)
|
|
|
|
|
|
|
@@ -99,12 +99,12 @@ D/X 同步引擎(`HealthSyncServiceImpl` / `XiaomiHealthServiceImpl`)已实
|
|
|
|
|
|
|
|
| 项 | 内容 | 建议 |
|
|
| 项 | 内容 | 建议 |
|
|
|
|---|---|---|
|
|
|---|---|---|
|
|
|
-| ① | `data_source` 取值:新增 `DEVICE` 还是沿用 `REPORT` | 新增 `DEVICE`(语义清晰,成本=枚举+注释) |
|
|
|
|
|
-| ② | `tier` 可信度:D/X 设备采集 = 2 还是 3 | 2(设备自动采集 ≈ AI 分析级,非手动) |
|
|
|
|
|
-| ③ | 桥接触发点:同步内事务桥接(A)vs 读时桥接(B) | A(实时、简单) |
|
|
|
|
|
-| ④ | `health_dimension_scores` 是否加唯一索引做幂等 upsert | 不加(默认读最新覆盖,避免动共享表) |
|
|
|
|
|
|
|
+| ① | `data_source` 取值:新增 `DEVICE` 还是沿用 `REPORT` | **已拍板:新增 DEVICE(语义清晰,成本=枚举+注释)**(主理人裁决 2026-11-08) |
|
|
|
|
|
+| ② | `tier` 可信度:D/X 设备采集 = 2 还是 3 | **已拍板:tier=2(设备自动采集 ≈ AI 分析级,非手动)**(主理人裁决 2026-11-08) |
|
|
|
|
|
+| ③ | 桥接触发点:同步内事务桥接(A)vs 读时桥接(B) | **已拍板:A(同步内事务桥接,实时、简单)**(主理人裁决 2026-11-08) |
|
|
|
|
|
+| ④ | `health_dimension_scores` 是否加唯一索引做幂等 upsert | **已拍板:不加唯一索引(默认读最新覆盖,避免动共享表)**(主理人裁决 2026-11-08) |
|
|
|
|
|
|
|
|
-> 以上默认建议为研发负责人先行意见,随本契约提交主理人/产品侧拍板;未拍板项按「保守不改」原则执行。
|
|
|
|
|
|
|
+> 以上已由主理人裁决生效(2026-11-08):① DEVICE / ② tier=2 / ③ 触发点 A(同步内事务桥接)/ ④ 不加唯一索引。契约已登记至 O-17,桥接实现(P1)待入 TDD 池派发(O-14「不纳入 241 基线」口径不变)。
|
|
|
|
|
|
|
|
## 7. 状态与后续
|
|
## 7. 状态与后续
|
|
|
|
|
|