---
schema: "hl-changelog/v2"
ticket: "5612"
title: "change 逐日调整只有起始日通过范围校验——中途日期误报605028（全程行服务期内任意日期可改派）"
consumer: "admin"
change_type: "修改接口"
author: "wx"
backend_status: "deployed"
gateway_status: "verified"
frontend_status: "not_required"
frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "后端完成：PR #5616 合并 dev-v3（e26cb0283cdc5773a220f975b440fc0d8cd80164）并部署 TEST（17:24 滚动 DONE）；网关实测中途生效日 08-29 change 成功（修复前 605028），原行 canceled、替换行 assigned 全程形态，随后恢复原车成功。前端无需配合。"
updated_at: "2026-08-06"
base: "dev-v3"
generated: "2026-08-06T17:35:00+08:00"
---

# change 逐日调整中途日期误报 605028 修复（全程行服务期内任意日期可改派）

> **服务**: hl-fleet-service
> **PR**: [#5616](https://git.1814.love:8443/wx/HL/pulls/5616)
> **Issue**: [#5612](https://git.1814.love:8443/wx/HL/issues/5612)
> **日期**: 2026-08-06
> **影响**: 🟢 **缺陷修复**，无契约变更（`POST /admin/fleet/assignments/assignmentId/change` 行为修复）。全程行（#5562 全程槽模型，`service_date` 为 NULL、`start_date~end_date` 覆盖整个服务期）此前仅起始日 `effectiveDate` 能通过范围校验，服务期内中途日期（如服务期 08-28~31 的 08-29/30/31）全部误报 **605028「生效日期不在派单服务日期范围内」**，逐日换车/司机走不通；本次修复后 `effectiveDate` 在 `[start_date, end_date]` 内都算在范围内。前端无需改代码。

## 背景

#5612（P1）协调台 E2E 实测：assignment `2085033560443408385`（服务期 2026-08-28~08-31，全程行）：

| effectiveDate | 结果（修复前） | 结果（修复后） |
|---|---|---|
| 2026-08-28（起始日） | ✅ 通过范围校验（走到冲突校验） | ✅ 不变 |
| 2026-08-29 | ❌ 605028 | ✅ 成功 |
| 2026-08-30 | ❌ 605028 | ✅ 成功（同逻辑） |
| 2026-08-31 | ❌ 605028 | ✅ 成功（同逻辑） |

**根因**：`AssignmentService#changeTargetRows` 用 `serviceDateOf(row)`（全程行回退 `startDate`）做 `>= effectiveDate` 过滤——中途日期大于 `startDate` 时全程行被过滤掉，目标行集合为空 → 抛 605028。逐日切片行（`service_date = start_date = end_date`）不受影响。

## 变更说明

`hl-fleet-service` 的 `AssignmentService`（3 处，无 API/DTO/枚举/错误码变化）：

1. **`changeTargetRows`**：全程行改用 `coversServiceDate(row, effectiveDate)` 过滤——`effectiveDate` 在 `[start_date, end_date]` 内都算在范围内；逐日切片行保持原「生效日及之后」过滤
2. **`assertContinuousChangeRange`**：单全程行豁免「生效日必须等于目标首行日期」校验（`serviceDateOf` 回退 `startDate` 无法表达中途生效日），仍按 #5595 整槽替换语义保持全程形态
3. **`retainedRows`**：排除全程行——中途生效日时前缀日仍属于被整槽取消替换的同一行，不得再作为保留行参与车辆费用快照与占用刷新

## 变更接口

| 方法 | 路径 | 来源 | 变更 |
|---|---|---|---|
| `POST` | `/admin/fleet/assignments/<assignmentId>/change` | `AssignmentController`（fleet） | 行为修复：全程行（service_date NULL、start/end 覆盖整个服务期）的 `effectiveDate` 范围校验从「仅起始日」放宽为「服务期内任意日期”——中途日期不再误报 605028，逐日换车/司机可用；参数、返回结构、错误码均不变 |

> 注：逐日切片行行为不变（生效日及之后切片替换、日期连续性校验）。全程行仍按 #5595 整槽替换语义（旧行取消保留历史、替换行保持全程形态）。

`POST /admin/fleet/assignments/assignmentId/change`（参数不变）：

- `effectiveDate` 合法范围：全程行 `[start_date, end_date]` 内任意日期；逐日切片行仍为「生效日 ≤ 末切片日」且目标日期连续
- 全程行 change 仍按 #5595「整槽替换」语义：旧行取消保留历史、替换行保持全程形态（`service_date` NULL、`start/end` 覆盖整个服务期）、冲突检查/日志范围覆盖整个服务期
- 错误码不变：服务期外日期仍 605028；车辆/司机档期冲突仍 605001

## 验证证据

- 定向测试 6/6（新增 2）：`change_fullTripRow_midwayEffectiveDate_succeeds`（中途生效日整槽替换成功）、`change_fullTripRow_midwayEffectiveDate_reachesConflictCheck`（中途日期走到 605001 冲突校验而非 605028）；`AssignmentServiceTest` 全量 378/378 通过；`spotless:check` 通过
- fleet `-pl hl-fleet-service -am verify`：除 3 个 MySQL Testcontainers 集成测试因 3306 端口被并行会话占用失败（环境并发，错峰后重跑通过）外全绿
- 网关验证（TEST，经 api.test.1814.love:9443，VEHICLE_MANAGER）：
  - `change`（effectiveDate=2026-08-29，换车 蒙A-E2E01 + 司机 斯琴）→ **200 成功**（修复前 605028），affectedDays=1、status=assigned
  - DB 对账：原行 2085033560443408385 → canceled（保留历史）；替换行 assigned、`service_date` NULL、start=08-28、end=08-31 全程形态、新车辆/司机
  - 验证后 change 恢复原车成功，测试数据复原

## 前端/调用方动作

**无**。契约参数、错误码不变，仅中途日期从误报 605028 变为正常可用。
