12451 cf9a521b31 feat(cabinets): 柜子详情接口透出最新电表读数(meter_wh / meter_at)
协议 §5.3 的 `cabinet.meter`(柜级电表读数,Wh)已落库(`cabinets.meter_wh` / `meter_at`,
变化留痕见 `workers/meter.rs`),本提交把它透出到 `GET /api/cabinets/{id}` 的响应里。

## 做法

沿用**同一个函数里 `project_name` 的既有模式**单查一次,**不给 `CabinetBasicRow` 加字段**:
该结构体有**两个**取数点(列表 L129 / 详情 L592),且其上方注释明确写着
「字段必须与 `CabinetBasicRow` 一一对应」—— 加字段要同步两处 SELECT,耦合更大、风险更高。

- ⚠️ `null` = **从未上报过**,与「读数为 0」是两回事(前端必须区分,别渲染成 0 度);
- 查询失败降级为 `null`,不让详情接口整体失败(与 `project_name` 同口径)。

## 实测(测试环境真实 HTTPS 请求)

临时超管账号 + 自签 HS256 JWT(用测试环境 `.env` 的 `JWT_SECRET`),**用完即删**:

```
库中:cabinet_id=1 meter_wh=125600 meter_at=2026-09-19 21:54:30
接口:meter_wh=125600 meter_at='2026-09-19T21:54:30'
⇒ 逐字一致
```

## 判据自证能失败

把 `should_record` 简化成朴素写法 `prev != current`(即**会把"字段缺失"当成 0 记录**的那版)
→ `test_missing_meter_is_never_recorded` **FAILED**;还原 → 6 passed。

## 验收

- `cargo check --all-targets`:0 error / 0 warning
- `cargo test --bin pms-api`:**195 passed**
- `cd software/web && npm run typecheck`:exit 0
- `node test/device_status_parse.test.mjs`:16/16;`node test/rssi_signal.test.mjs`:9/9
- 路由数:**80**
- `python test/schema_alignment_e2e.py --env dev`:通过(exit 0)
- 已发布**测试与生产**(生产:服务 active、0 ERROR、域名 401/200、消费链探测通过)
2026-09-20 06:00:30 +08:00
..