From df91ab0673d744b20953f237fcfba5279045f651 Mon Sep 17 00:00:00 2001 From: huangping Date: Mon, 6 Apr 2026 21:48:55 +0800 Subject: [PATCH] docs(i4): add I4 design for M3 delivery and M4 license SN Describe REST contracts, validation, routing, and I4 sync checklist aligned with V4 schema and parallel iteration index. Made-with: Cursor --- docs/engineering/iterations/I4_DESIGN.md | 299 +++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 docs/engineering/iterations/I4_DESIGN.md diff --git a/docs/engineering/iterations/I4_DESIGN.md b/docs/engineering/iterations/I4_DESIGN.md new file mode 100644 index 0000000..23ce152 --- /dev/null +++ b/docs/engineering/iterations/I4_DESIGN.md @@ -0,0 +1,299 @@ +# 迭代 I4 设计说明 — M3 交付批次与清单、M4 许可 SN 台账 + +> **迭代定位**:与 [并行迭代索引](../PARALLEL_ITERATION_INDEX.md) 中 **I4** 一致 — 平台后端 **M3 交付** + **M4 SN 录入/绑定/状态/手工回写**;前端 **交付页 + SN 页**;本仓库(SDK 工作区)以 **OpenAPI 契约与文档口径** 与 BP-10 对齐。 +> **分支**:`develop`。 +> **已有实现锚点**(勿从零重设计,仅对齐与补全):Flyway `V4__delivery_batch_and_license_sn.sql`;`cn.craftlabs.platform.api.domain.DeliveryBatchStatus` / `LicenseSnStatus`;`web/dto` 下 `Delivery*`、`LicenseSn*`;审计常量 `AuditEntityTypes`、`AuditActions` 已含 `DELIVERY_BATCH`、`LICENSE_SN` 及对应动作。 + +--- + +## 1. I4 范围与 I3 / I5 边界 + +### 1.1 I4 **纳入**(本迭代 DoD) + +| 域 | 说明 | +|----|------| +| **M3 P0** | 交付批次(项目/可选合同、批次号、计划日、备注);交付清单行(描述、数量、可选合同行关联);批次状态 **PENDING → DELIVERED / CANCELLED** 及完成时间等侧写。对应产品:[M3-F01~F05 P0](../../chuangfei-platform-product-modules.md#4-m3-交付管理)。 | +| **M4 P0** | SN 台账:全局唯一 `sn_code`;**`project_id` 与/或 `contract_line_id` 绑定路径**;生命周期状态子集;激活备注/手工回写字段。对应产品:[M4-F01~F05 P0](../../chuangfei-platform-product-modules.md#5-m4-授权与许可运营)。 | +| **M10-F01** | 交付批次、交付行、SN 的关键变更与状态迁移写入审计(与 I3 合同审计模式一致;实体类型见 §4)。 | +| **跨轨口径** | [I4 末同步点](../PARALLEL_ITERATION_INDEX.md#3-跨轨同步点必须对齐):**SN 绑定与「孤儿 SN」规则**文档化并三轨对齐;**交付门禁(M3-F07)与「孤儿 SN」强校验(M4-F02)** 在 **M11-F20 系统参数** 中预留为 **未来可配置项**(I4 可实现默认策略 + 配置占位,**不阻塞** I4 闭环)。 | + +### 1.2 I3 **留给上游的契约**(I4 只消费,不重复建设) + +- **合同 / 合同行**:`project_id`、`contract_id`、行项主键;合同状态机已在 I3 冻结。交付行上的 `contract_line_id` 必须解析到合法合同行及其所属项目。 +- **客户 / 项目**:批次必填 `project_id`;可选 `contract_id` 须属于同一项目。 + +### 1.3 I5 **明确不纳入 I4**(避免范围蔓延) + +- **M5 Callback Inbox**、**M6 集成配置** 的持久化与页面(I5 起)。 +- Webhook **生产级** 投递、幂等落库与平台 Inbox 全链路 E2E。 +- **设备(M7)**、**比特控制台摘要链接(M4-F06)** 等可后续挂接;I4 仅保证 SN 主数据与绑定字段可关联到合同行/项目。 + +--- + +## 2. 数据模型锚点(与迁移一致) + +表与字段以 `services/delivery-platform-api/src/main/resources/db/migration/V4__delivery_batch_and_license_sn.sql` 为准: + +- **`platform_delivery_batch`**:`project_id`(必填)、`contract_id`(可选)、`batch_code`(唯一)、`planned_delivery_date`、`status`(默认 `PENDING`)、`finished_at`、`remarks`。 +- **`platform_delivery_line`**:归属 `batch_id`,`description`、`quantity`、`contract_line_id`(可选),`sort_order`。 +- **`platform_license_sn`**:`sn_code`(全局唯一)、`project_id` / `contract_line_id`(均可空于 DB 层,**业务校验见 §4**)、`status`(默认 `REGISTERED`)、`activation_remark`。 + +### 2.1 状态枚举(API JSON 使用枚举名字符串) + +**交付批次** `DeliveryBatchStatus`: + +| 值 | 说明 | +|----|------| +| `PENDING` | 未交付(默认) | +| `DELIVERED` | 已交付 | +| `CANCELLED` | 已取消 | + +**许可 SN** `LicenseSnStatus`(P0 子集,与代码枚举一致): + +| 值 | 说明 | +|----|------| +| `REGISTERED` | 已登记 | +| `ISSUED` | 已发放 | +| `ACTIVATED` | 已激活 | +| `SUSPENDED` | 已冻结 | +| `REVOKED` | 已回收 | + +非法状态迁移返回 **409**,错误码建议与合同类似:`DELIVERY_BATCH_ILLEGAL_STATUS`、`LICENSE_SN_ILLEGAL_STATUS`(具体以 OpenAPI 与实现为准)。 + +--- + +## 3. REST API 提案(前缀 `/api/v1`) + +与现有 Controller 风格一致:**`@RequestMapping("/api/v1/...")`**。下列路径为 I4 计划形态;JSON 字段名与当前 DTO **camelCase** 对齐(`projectId`、`contractId`、`batchCode` 等)。 + +### 3.1 交付批次 `delivery-batches` + +| 方法 | 路径 | 说明 | +|------|------|------| +| `GET` | `/api/v1/delivery-batches` | 分页列表;查询参数建议:`projectId`、`contractId`、`status`、`keyword`(批次号)、`page`、`size`。 | +| `POST` | `/api/v1/delivery-batches` | 创建批次(体见下);**不含**行时可后续用行接口追加。 | +| `GET` | `/api/v1/delivery-batches/{id}` | 详情;可通过 `?includeLines=true` 或默认嵌套返回 `lines`(与 `DeliveryBatchResponse` 一致)。 | +| `PUT` | `/api/v1/delivery-batches/{id}` | 更新计划交付日、备注等非状态字段(`DeliveryBatchUpdateRequest`)。 | +| `PATCH` | `/api/v1/delivery-batches/{id}/status` | **仅**变更状态:`PENDING` → `DELIVERED` 或 `CANCELLED`;服务端可在此写入 `finishedAt`(如 `DELIVERED`)。 | + +**嵌套 — 交付行 `lines`** + +| 方法 | 路径 | 说明 | +|------|------|------| +| `GET` | `/api/v1/delivery-batches/{batchId}/lines` | 清单列表。 | +| `POST` | `/api/v1/delivery-batches/{batchId}/lines` | 新增一行。 | +| `PUT` | `/api/v1/delivery-batches/{batchId}/lines/{lineId}` | 更新行。 | +| `DELETE` | `/api/v1/delivery-batches/{batchId}/lines/{lineId}` | 删除行。 | + +**创建批次请求体示例** + +```json +{ + "projectId": 1001, + "contractId": 2002, + "batchCode": "DLV-2026-0001", + "plannedDeliveryDate": "2026-04-15", + "remarks": "首批现场交付" +} +``` + +**更新批次请求体示例**(`PUT /api/v1/delivery-batches/{id}`) + +```json +{ + "plannedDeliveryDate": "2026-04-20", + "remarks": "延期一周" +} +``` + +**状态 PATCH 示例**(`PATCH /api/v1/delivery-batches/{id}/status`) + +```json +{ + "status": "DELIVERED" +} +``` + +**交付行写入示例**(`POST` / `PUT` body,`DeliveryLineRequest`) + +```json +{ + "sortOrder": 1, + "description": "AI 推理节点 × 生产环境", + "quantity": 2, + "contractLineId": 3003 +} +``` + +**详情响应片段**(`DeliveryBatchResponse`,含行) + +```json +{ + "id": 1, + "projectId": 1001, + "contractId": 2002, + "batchCode": "DLV-2026-0001", + "plannedDeliveryDate": "2026-04-15", + "status": "PENDING", + "finishedAt": null, + "remarks": "首批现场交付", + "createdAt": "2026-04-06T08:00:00Z", + "updatedAt": "2026-04-06T08:00:00Z", + "lines": [ + { + "id": 10, + "batchId": 1, + "sortOrder": 1, + "description": "AI 推理节点 × 生产环境", + "quantity": 2, + "contractLineId": 3003, + "createdAt": "2026-04-06T08:05:00Z", + "updatedAt": "2026-04-06T08:05:00Z" + } + ] +} +``` + +### 3.2 许可 SN `license-sns` + +| 方法 | 路径 | 说明 | +|------|------|------| +| `GET` | `/api/v1/license-sns` | 分页列表;建议查询:`projectId`、`contractLineId`、`status`、`snCode`(精确或前缀按产品定)。 | +| `POST` | `/api/v1/license-sns` | 创建 SN(`LicenseSnCreateRequest`);须满足 §4 绑定规则。 | +| `GET` | `/api/v1/license-sns/{id}` | 详情。 | +| `PUT` | `/api/v1/license-sns/{id}` | **全量/部分更新绑定字段**:`projectId`、`contractLineId`、`activationRemark`(`LicenseSnUpdateRequest`);用于纠正绑定或手工回写备注。 | +| `PATCH` | `/api/v1/license-sns/{id}/status` | 变更 `LicenseSnStatus`(`LicenseSnStatusPatchRequest`);须校验合法迁移。 | + +**创建 SN 请求体示例** + +```json +{ + "snCode": "SN-CRAFT-8F3A-0001", + "projectId": 1001, + "contractLineId": 3003, + "activationRemark": null +} +``` + +**更新绑定 / 备注示例**(`PUT`) + +```json +{ + "projectId": 1001, + "contractLineId": 3003, + "activationRemark": "客户现场激活成功,凭证号 xxx" +} +``` + +**状态 PATCH 示例** + +```json +{ + "status": "ACTIVATED" +} +``` + +**详情响应示例**(`LicenseSnResponse`) + +```json +{ + "id": 501, + "snCode": "SN-CRAFT-8F3A-0001", + "projectId": 1001, + "contractLineId": 3003, + "status": "ACTIVATED", + "activationRemark": "客户现场激活成功,凭证号 xxx", + "createdAt": "2026-04-06T09:00:00Z", + "updatedAt": "2026-04-06T10:00:00Z" +} +``` + +--- + +## 4. 校验规则与审计 + +### 4.1 交付批次 + +- **`projectId`**:必填;项目须存在。 +- **`contractId`**:可选;若提供,合同须存在且 **`contract.project_id == batch.project_id`**。 +- **`batchCode`**:全平台唯一(与表 `uq_platform_delivery_batch_code` 一致);冲突 **409**。 +- **状态**:仅允许自 `PENDING` 转至 `DELIVERED` 或 `CANCELLED`;`DELIVERED`/`CANCELLED` 视为终态,**禁止**再次变更(除非产品后续另定「重开」流程,不在 I4 P0)。 + +### 4.2 交付行 + +- **`contractLineId`**:可选;若提供,合同行须存在,且其所属合同的 **`project_id` 须与父批次 `project_id` 一致**(从而与批次可选 `contract_id` 兼容:若批次已指定合同,可额外校验行所属合同与批次合同一致,建议 **强一致**:行上合同行必须属于 `batch.contract_id` 当 `contract_id` 非空时)。 +- **`quantity`**:> 0(与 `DeliveryLineRequest` 中 `@DecimalMin` 一致)。 + +### 4.3 许可 SN + +- **`snCode`**:必填;**全局唯一**;冲突 **409**。 +- **绑定路径**:**至少具备 `projectId` 或 `contractLineId` 之一**(可同时具备)。 + - 若仅提供 **`contractLineId`**:服务端**派生** `project_id` = 该合同行所属合同的 `project_id`,并持久化(便于列表按项目过滤)。 + - 若同时提供两者:须校验 **`contractLine` 派生出的 `project_id` 与请求 `projectId` 一致**,否则 **400**。 +- **孤儿 SN(与 I4 末同步对齐)**: + - **产品理想态(M4-F02)**:禁止无项目且无合同行路径的「裸 SN」。 + - **M11-F20(P1)**:「孤儿 SN」**强校验**开关、**交付门禁**(M3-F07,例如仅已交付范围可发放/绑定)作为**系统参数**在架构上预留;I4 建议 **默认策略**:创建/更新时 **拒绝** 零绑定(与 P0 一致);若需「先录入后绑定」,可通过 **配置** 降级为 **警告 + 允许保存**(实现可放在应用服务层读取参数表,**表结构可 Mid 再做**,I4 先在文档与 OpenAPI `description` 中固定语义)。 +- **状态迁移**:按 §2.1 枚举定义允许边(细表可在实现中维护;**禁止**随意跳转到任意状态)。 + +### 4.4 审计(M10-F01) + +沿用 I3 模式:**实体类型 + 动作 + 旧值/新值摘要 + 操作者 + 时间**。常量已存在于: + +- `AuditEntityTypes.DELIVERY_BATCH`、`AuditEntityTypes.LICENSE_SN` +- `AuditActions`:`DELIVERY_BATCH_CREATED` / `UPDATED` / `STATUS_CHANGED`;`DELIVERY_LINE_ADDED` / `UPDATED` / `DELETED`;`LICENSE_SN_CREATED` / `UPDATED` / `STATUS_CHANGED` + +若持久化审计行需扩展子类型或 payload 结构,**保持与合同审计同一表结构**,仅扩展 `entity_type` / `action` 枚举值;**无需**为 I4 另起实体类型常量,除非后续拆分「交付行」为独立可检索实体(当前可用 `DELIVERY_LINE_*` 动作挂 `entity_id` = line id,`batch_id` 放上下文 JSON)。 + +--- + +## 5. 前端路由(Vue 3,布局子路由) + +与 [轨道 B — I4](../tracks/02-frontend-platform-ui.md) 一致,路径挂在 **AppLayout** 之下(懒加载、`meta.title` / 权限码略)。 + +| 路由 | 页面职责 | +|------|----------| +| `/deliveries` | 交付批次列表、筛选、跳转新建/详情。 | +| `/deliveries/new` | 新建批次(项目/可选合同、批次号、计划日、备注);可内嵌或分步添加行。 | +| `/deliveries/:id` | 批次详情:行清单 CRUD;**状态按钮** 调用 `PATCH .../status`(PENDING → DELIVERED/CANCELLED)。 | +| `/licenses/sn` | SN 台账列表;**孤儿 SN** 列表筛选或醒目标记(与后端配置/字段一致)。 | +| `/licenses/sn/new` | 新建 SN(录入 `snCode`、绑定项目/合同行)。 | +| `/licenses/sn/:id` | SN 详情:**PUT** 调整绑定与 `activationRemark`;**PATCH** 调整状态;展示简要时间线(可仅读审计或本地状态历史 Mid 增强)。 | + +**契约顺序提醒**([轨道 B §4](../tracks/02-frontend-platform-ui.md)):Auth → Customer/Project → Contract → **Delivery/SN** → Callback;I4 页面依赖 I2/I3 主数据与合同行选择器。 + +--- + +## 6. I4 末同步点 Checklist(后端 + 前端 + SDK 文档) + +以下为 [并行索引 I4 末](../PARALLEL_ITERATION_INDEX.md#3-跨轨同步点必须对齐) 的落地核对项。 + +### 6.1 后端(platform-api) + +- [ ] Flyway V4 表与索引已在各环境应用;DTO 与 OpenAPI 字段一致。 +- [ ] §3 路径已实现或通过兼容别名暴露;错误码与 409 语义与合同模块一致。 +- [ ] §4.1~§4.3 校验全覆盖(含合同行与项目一致性、SN 全局唯一、绑定派生)。 +- [ ] **孤儿 SN**:默认策略与(可选)M11-F20 配置占位行为**文档化并在代码注释或配置类中可定位**。 +- [ ] **交付门禁(M3-F07)**:与 SN 创建/绑定相关的规则在代码中**可插拔**或明确「I4 硬编码默认 + I5+ 读配置」的 TODO 与 Owner。 +- [ ] 审计:`DELIVERY_BATCH` / `LICENSE_SN` / 交付行动作写入 M10-F01 存储。 +- [ ] `contracts/openapi/delivery-platform-api.json` 更新并通过 `OpenApiContractSnapshotTest`。 + +### 6.2 前端(delivery-platform-ui) + +- [ ] §5 路由与菜单可达;RBAC 权限码与后端对齐。 +- [ ] 交付详情状态操作仅展示合法迁移;错误态与 409 提示一致。 +- [ ] SN 新建/编辑:合同行选择器与项目联动;**孤儿**场景 UI 与后端策略一致(禁止或警告)。 +- [ ] E2E P0:`交付 → SN 录入/绑定 → 状态/备注回写`(与轨道 B I4 DoD 一致)。 + +### 6.3 客户端 SDK 工作区(本仓库) + +- [ ] OpenAPI 快照与 [contracts/README.md](../../contracts/README.md) 说明含 Delivery/SN 标签。 +- [ ] [tracks/03-client-sdk.md](../tracks/03-client-sdk.md) 或等价文档中 **BP-10 与平台对象口径** 补充:交付批次、SN 在集成叙事中的位置(**不实现**平台 REST 客户端亦可,但**文档**须与 I4 契约一致)。 +- [ ] **M11-F20**:在 SDK/集成文档中标注为 **后续配置项**(门禁、孤儿强校验),避免集成方误假设 I4 已暴露该 HTTP API。 + +--- + +## 7. 修订记录 + +| 日期 | 说明 | +|------|------| +| 2026-04-06 | 初版:I4 范围与边界、REST 提案、校验与审计、前端路由、I4 末三轨 checklist。 |