diff --git a/changelogs-v2/2026-07/25_4756_车务菜单全接口验收与前端契约收口-管理后台.md b/changelogs-v2/2026-07/25_4756_车务菜单全接口验收与前端契约收口-管理后台.md index cf03a5c..b125733 100644 --- a/changelogs-v2/2026-07/25_4756_车务菜单全接口验收与前端契约收口-管理后台.md +++ b/changelogs-v2/2026-07/25_4756_车务菜单全接口验收与前端契约收口-管理后台.md @@ -2,6 +2,7 @@ > **Issue**: [wx/HL#4756](https://git.1814.love:8443/wx/HL/issues/4756) > **PR**: [wx/HL#4757](https://git.1814.love:8443/wx/HL/pulls/4757), [wx/HL#4758](https://git.1814.love:8443/wx/HL/pulls/4758), [wx/HL#4759](https://git.1814.love:8443/wx/HL/pulls/4759) +> **追加验证**: 2026-07-06 独立账号 `fleet_mgr_4760/VEHICLE_MANAGER`、`designer_4760/CUSTOMIZER` > **服务**: hl-fleet-service + hl-order-service-v3 > **日期**: 2026-07-05 > **影响范围**: 管理后台车务管理全菜单 @@ -11,6 +12,7 @@ ## 1. 结论 - 测试服已完成真实 API 回归:车务菜单级 `23/23` 通过,覆盖后台端点 `76` 个。 +- 2026-07-06 追加独立账号回归:读接口/只读场景 `32/32` 通过;写接口探针 `22/22` 通过,覆盖派单预检、创建、确认、取消、司机险任务、车队对账实付保存/清空、模板渲染/错误分支。 - 补充全链路回归 `31/31` 通过,多订单并发回归 `10/10` 通过。 - 已修复派单重复确认返回 `100000` 的问题,现在返回业务码 `605020 当前派单状态不允许此操作`。 - `/admin/fleet/**` 已按当前登录角色拦截:车务角色可访问,定制师角色会返回 `403`。 @@ -21,9 +23,9 @@ | 场景 | 前端处理 | |------|----------| -| 当前角色 | 车务菜单只能由 `VEHICLE_MANAGER` 或 `SUPER_ADMIN` 访问;`wx/CUSTOMIZER` 访问 `/admin/fleet/**` 返回 `403`,提示切换车务角色。 | +| 当前角色 | 车务菜单只能由 `VEHICLE_MANAGER` 或 `SUPER_ADMIN` 访问;`CUSTOMIZER` 访问 `/admin/fleet/**` 返回 `403`,提示切换车务角色。测试服使用独立账号 `fleet_mgr_4760` / `designer_4760` 验证,不再用 `admin` / `wx` 当业务账号。 | | 车务工作台 | `GET /admin/profile/dashboard?period=today` 在 `VEHICLE_MANAGER` 角色下由 user-service 代理 fleet 真实看板数据;不要再读旧订单统计或本地 mock。 | -| 司机结算方式 | 司机新增/编辑/导入使用字典 `driver_settlement_mode`:`direct`=直接结算,`captain`=车队长结算。 | +| 司机结算方式 | 司机新增/编辑/导入使用字典 `driver_settlement_mode`:`direct`=直接结算,`fleet_leader`=车队长结算。不要再传旧值 `captain`。 | | 待审核详情 ID | `GET /admin/fleet/drivers/pending/{pendingId}` 响应主键字段是 `id`,不是 `pendingId`;路径变量仍叫 `pendingId`。 | | 派单重复确认 | `POST /admin/fleet/assignments/{assignmentId}/confirm` 只允许 `holding -> assigned`;非 `holding` 返回 `605020`。 | | 取消重复操作 | 终态派单再次取消也返回 `605020`。 | @@ -68,8 +70,8 @@ Content-Type: application/json 角色边界: -- `admin/VEHICLE_MANAGER`:允许访问 `/admin/fleet/**`。 -- `wx/CUSTOMIZER`:访问 `/admin/fleet/**` 返回 `403`,前端应提示切换车务角色。 +- `fleet_mgr_4760/VEHICLE_MANAGER`:允许访问 `/admin/fleet/**`。 +- `designer_4760/CUSTOMIZER`:访问 `/admin/fleet/**` 返回 `403`,前端应提示切换车务角色。 - `/app/h5/**`:公开 H5 入口,不走车务角色 guard,但需要 `token` 参数。 ### 4.2 成功响应包 @@ -813,7 +815,7 @@ PUT /admin/fleet/drivers/{driverId} "preferredTypeKey": "suv", "preferredModel": "SUV", "vehicleSource": "company", - "settlementMode": "captain", + "settlementMode": "fleet_leader", "license": { "no": "L6966520260705", "type": "C1", @@ -838,7 +840,7 @@ PUT /admin/fleet/drivers/{driverId} "phone": "199****9999", "driverStatus": "idle", "season": "active", - "settlementMode": "captain", + "settlementMode": "fleet_leader", "license": { "no": "L6966520260705", "type": "C1", "expire": "2035-12-31" }, "insurance": { "type": "none" }, "tags": ["API_TEST_FLEET_FULL"] @@ -851,7 +853,9 @@ PUT /admin/fleet/drivers/{driverId} | 值 | 展示 | |----|------| | `direct` | 直接结算 | -| `captain` | 车队长结算 | +| `fleet_leader` | 车队长结算 | + +> 当前字典库真实值是 `fleet_leader`。`captain` 是旧草稿值,后端不会按该值入库,前端新增/编辑/导入都不要再传。 非法值响应: @@ -1850,6 +1854,341 @@ DELETE /admin/fleet/message-templates/{templateId} --- +## 14.5 2026-07-06 独立账号写接口实测样本 + +本节是测试服真实返回,用于前端逐字段对齐。账号:`fleet_mgr_4760/VEHICLE_MANAGER`。测试派单已取消回滚,产生的司机险待处理任务已标记 `IGNORED`,不会污染待处理列表。 + +### 14.5.1 派单预检、创建、确认、取消 + +预检请求: + +```json +{ + "orderId": "2070756230887890945", + "vehicleId": "2067084363580760065", + "driverId": "2065272150960357378", + "startDate": "2026-07-06", + "endDate": "2026-07-08", + "pickupAt": "hailar", + "dropoffAt": "hailar", + "headcount": 2 +} +``` + +预检响应: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "conflict": false, + "conflicts": [], + "warnings": [] + } +} +``` + +创建 holding 请求: + +```json +{ + "orderId": "2070756230887890945", + "vehicleId": "2067084363580760065", + "driverId": "2065272150960357378", + "startDate": "2026-07-06", + "endDate": "2026-07-08", + "headcount": 2, + "holdMode": 1, + "fromEntry": "api-test-4760", + "strictSeats": false, + "skipCityJunctionException": false, + "requestId": "api-test-4760-9ap9s565" +} +``` + +创建响应: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "id": "2070756257240694786", + "assignmentStatus": "holding", + "holdSentAt": "2026-07-06T...", + "confirmedAt": null, + "sideEffects": null + } +} +``` + +确认请求: + +```json +{ + "driverReplyNote": "API测试4760:司机已确认,确认后立即取消回滚" +} +``` + +确认响应: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "assignmentStatus": "assigned", + "confirmedAt": "2026-07-06T...", + "itineraryUrl": "https://web.test.1814.love:9443/fleet/itinerary/...", + "sideEffects": { + "vehicleStatusUpdated": "busy", + "driverStatusUpdated": "busy", + "reconPrepRowsCreated": 0, + "reconPrepMarkedCanceled": null + } + } +} +``` + +取消请求: + +```json +{ + "cancelReason": "API测试4760:确认写接口后立即取消释放,不作为真实用车", + "driverNotified": true, + "notifyNote": "API自动化回滚,未实际通知司机", + "cutoffDate": "2026-07-06" +} +``` + +取消响应: + +```json +{ + "code": 200, + "message": "成功", + "data": { + "assignmentStatus": "canceled", + "sideEffects": { + "vehicleStatusUpdated": "idle", + "driverStatusUpdated": "idle", + "reconPrepRowsCreated": null, + "reconPrepMarkedCanceled": 0 + } + } +} +``` + +取消后订单详情: + +```json +{ + "code": 200, + "data": { + "id": "2070756230887890945", + "currentAssignment": null, + "transport": { + "arrive": null, + "depart": null, + "batches": [] + } + } +} +``` + +前端注意:无大交通时 `transport` 仍返回稳定结构,不要因为 `batches=[]` 就认为接口缺字段;有大交通的真实样本会返回 `arrive/depart/batches`。 + +### 14.5.2 司机险任务动作 + +确认派单后,司机为 `perTrip`,自动生成 3 条投保任务: + +```http +GET /admin/fleet/insurance/tasks?page=1&pageSize=20&assignmentId=2070756257240694786 +``` + +响应摘要: + +```json +{ + "code": 200, + "data": { + "page": 1, + "pageSize": 20, + "total": 3, + "records": [ + { + "taskType": "PURCHASE", + "taskStatus": "PENDING", + "source": "BAOYOU", + "errorCode": "540005", + "errorMessage": "保险计划不存在", + "suggestedAction": "请核对司机档案、保险计划和保司返回信息后重试;线下处理必须填写真实保费、保单号和凭证", + "serviceDate": "2026-07-06", + "retryCount": 0 + } + ] + } +} +``` + +线下完成缺凭证请求: + +```json +{ + "policyNo": "API-TEST-NO-PROOF", + "premiumAmount": "1.00", + "proofUrls": [], + "remark": "API测试缺凭证校验" +} +``` + +响应: + +```json +{ + "code": 400, + "message": "线下凭证不能为空", + "success": false +} +``` + +忽略测试任务请求: + +```json +{ + "remark": "API测试4760回滚派单产生,非真实用车任务,已确认忽略" +} +``` + +响应: + +```json +{ + "code": 200, + "data": { + "taskStatus": "IGNORED", + "taskStatusLabel": "已忽略" + } +} +``` + +清理后待处理确认: + +```http +GET /admin/fleet/insurance/tasks?page=1&pageSize=20&assignmentId=2070756257240694786&pendingOnly=true +``` + +```json +{ + "code": 200, + "data": { + "page": 1, + "pageSize": 20, + "total": 0, + "records": [] + } +} +``` + +### 14.5.3 车队对账实际金额保存与清空 + +录入请求: + +```json +{ + "periodStart": "2026-07-01", + "periodEnd": "2026-07-31", + "fleet": "own", + "actualAmount": "1.23", + "note": "API测试4760:写接口探针,随后清空" +} +``` + +录入响应: + +```json +{ + "code": 200, + "data": { + "id": "2073981751427821569", + "diff": "-12878.67", + "payableEstimated": "12879.90", + "estimated": "12879.90" + } +} +``` + +清空请求: + +```json +{ + "periodStart": "2026-07-01", + "periodEnd": "2026-07-31", + "fleet": "own", + "actualAmount": null, + "note": "API测试4760:清空写接口探针" +} +``` + +清空响应: + +```json +{ + "code": 200, + "data": { + "id": "2073981751427821569", + "diff": null, + "payableEstimated": "12879.90", + "estimated": "12879.90" + } +} +``` + +负数错误: + +```json +{ + "code": 605608, + "message": "实际金额必须大于等于0", + "success": false +} +``` + +### 14.5.4 模板渲染 + +渲染请求: + +```json +{ + "orderId": "2070756230887890945", + "vehicleId": "2067084363580760065", + "driverId": "2065272150960357378" +} +``` + +响应字段: + +```json +{ + "code": 200, + "data": { + "renderedBody": "渲染后的正文", + "variablesUsed": [ + "order.no", + "order.startDate", + "order.endDate", + "order.customer", + "order.headcount", + "vehicle.plate", + "vehicle.model" + ] + } +} +``` + +--- + ## 15. 前端错误码与按钮状态处理 | code | 场景 | 前端处理 | @@ -1879,6 +2218,11 @@ DELETE /admin/fleet/message-templates/{templateId} - 菜单级真实 API:`23/23` 通过,订单 `HL20260705204251138`,覆盖 76 个后台端点。 - 全链路真实 API:`31/31` 通过,订单 `HL20260705204312543`。 - 多订单并发:`10/10` 通过,真实创建 3 个订单 `HL20260705204330462`、`HL20260705204332693`、`HL20260705204334918`,仅 1 单派单成功,其余按 `605001` 冲突返回。 +- 2026-07-06 独立账号读接口回归:`32/32` 通过,报告 `HL-v3/.tmp/4760_independent_api_report.md`。覆盖工作台、角色 403、派单看板、矩阵、车辆/车型、司机、价格日历、车管模板、车队对账、保险任务、真实大交通样本。 +- 2026-07-06 独立账号写接口探针:`22/22` 通过,报告 `HL-v3/.tmp/4760_write_api_report.md`。覆盖 `precheck/create/confirm/cancel`、司机险任务生成和忽略、`offline-done` 缺凭证校验、对账实付保存/清空、模板渲染和非法变量。 - 本地后端验证: - `mvn -pl hl-fleet-service -am "-Dtest=AssignmentServiceTest,FleetAdminRoleGuardInterceptorTest" -DfailIfNoTests=false test` 通过,69 tests。 + - `mvn -pl hl-fleet-service -am "-Dtest=DriverSettlementModeDictResolverTest,DriverControllerTest,DriverImportServiceTest,DriverServiceTest,DriverCrudIntegrationTest,FleetInsuranceTaskServiceTest,AssignmentControllerTest" -DfailIfNoTests=false test` 通过,221 tests。 + - `mvn -pl hl-fleet-service -am -DskipTests compile` 通过。 + - `git diff --check` 通过,无空白错误。 - `mvn -pl hl-fleet-service spotless:check` 通过。 diff --git a/changelogs-v2/2026-07/26_4760_车务司机险自动投退保闭环与保险菜单契约-管理后台.md b/changelogs-v2/2026-07/26_4760_车务司机险自动投退保闭环与保险菜单契约-管理后台.md index 4375193..529164f 100644 --- a/changelogs-v2/2026-07/26_4760_车务司机险自动投退保闭环与保险菜单契约-管理后台.md +++ b/changelogs-v2/2026-07/26_4760_车务司机险自动投退保闭环与保险菜单契约-管理后台.md @@ -23,8 +23,8 @@ | 角色 | 行为 | |------|------| -| `admin` / 车务角色 | 可访问 `/admin/fleet/insurance/**`,可查看任务、重试、标记线下完成、忽略 | -| `wx` / 定制师 | 不应展示车务保险菜单;若访问 `/admin/fleet/**` 按角色守卫返回 `403` | +| `VEHICLE_MANAGER` / 车务角色 | 可访问 `/admin/fleet/insurance/**`,可查看任务、重试、标记线下完成、忽略。测试服独立账号:`fleet_mgr_4760` | +| `CUSTOMIZER` / 定制师 | 不应展示车务保险菜单;若访问 `/admin/fleet/**` 按角色守卫返回 `403`。测试服独立账号:`designer_4760` | 前端不要复用订单保险页面的数据源。车务保险菜单只调本文件接口。 @@ -236,7 +236,7 @@ POST /admin/fleet/insurance/tasks/{taskId}/offline-done - `policyNo` 为空:参数校验失败。 - `premiumAmount` 为空或负数:参数校验失败。 -- `proofUrls` 为空数组或不传:返回 `100001` / 参数校验失败。 +- `proofUrls` 为空数组或不传:返回 `code=400`,`message=线下凭证不能为空`。 ---