29 KiB
schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
| schema | ticket | title | consumer | author | change_type | backend_status | gateway_status | frontend_status | frontend_owner | frontend_ref | target_release | verified_at | status_note | updated_at | base |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| hl-changelog/v2 | 8195 | 团期「查看需求」页五处缺口: 户级团号 teamNo / 未提交户进列表 / 接送机批量确认新端点 / 车型字典校验 / 团期 endDate | admin | wx(GIT) | 修改接口 | deployed | not_required | verified | mmg | 7df2926240c51d48c31fa3c13962dd0f42b9c9ca | v2.1 | 2026-09-23 | backend_status=deployed: hl-order-service-v3 已滚动到测试服,deploy-status.sh 读数 dev-v3 / 62449e550 / DEPLOYED_AT 2026-09-22 22:22:58 / STATE=ok,62449e550 即本单合并提交本身;九条验收项全部在测试服网关上取到活体读数,原始报文逐条落盘。gateway_status=not_required: 新端点路径落在 hl-gateway 既有 /v3/admin/** 通配上,零新增路由——判据不是推断而是实测:该路径返 400「请至少选择一个要确认的子订单」(业务校验),而故意写错的同前缀路径返 404「接口不存在」,两种报文形态不同 ⇒ 路由确实存在。frontend_status=pending: 本条新增 4 个响应字段、1 个端点,且改了 householdCount 的口径,hl-ui 需要改;hl-ui(origin/v2.1) 里 src/api/orderV2GroupBatch.js 两处 JSDoc 描述的是改前契约,改后已不准确,逐行列在第六.6 节。⚠️ 契约边界:本接口上「从未提交需求的户」与「提交后被打回的户」完全同形(两者都是 requirements:[] + status:null),不可区分,依据 GroupVehicleHouseholdsRespVO.java:169-171。 mmg 2026-09-23 交付: hl-ui@7df29262 feat(order-v2) 五处缺口全落地——户卡 teamNo/统计行 endDate/未提交户空卡(中性文案)/批量确认(failedCount 判成败+reason 明细)/车型字典下拉(存量非字典值 rule 前置拦);checkpoint 全量绿,相关 106 例测试全过。 | 2026-09-22 | dev-v3 |
团期「查看需求」页五处缺口: 户级团号 teamNo / 未提交户进列表 / 接送机批量确认新端点 / 车型字典校验 / 团期 endDate
存放目录: 二期(order-v3)→
changelogs-v2/2026-09/
⚠️ 关键变化
三条,改前改后行为不同,按这个顺序看:
orderNo从来就不是团号。 改前两个 households 接口的 Swagger 把orderNo标成「子订单团号」、example 写GT-26-0081,照着当团号渲染出来的其实是订单号HL20260922210334521。本次新增teamNo字段承载真团号,orderNo字段保留不删(前端v-for :key在用),但注解已订正为「子订单编号(非团号)」。团号请改读teamNo。vehicleRowCount不再恒 ≥householdCount。 改前「没提交过用车需求的户」根本不出现在车侧响应里;改后它们进列表(requirements: []、status: null),householdCount随之变成「应报车的户数 =households长度」。原先「行数 ≥ 户数」这个不变量作废,别再拿它写断言。实测基线读数householdCount=5 / countedHouseholdCount=0 / vehicleRowCount=2。- 接送机批量确认允许部分成功,且部分失败时 HTTP 仍是
code:200/success:true。 失败的户在data.failed[]里逐条给orderId + errorCode + reason。不要用success判断「是不是全成了」,要看failedCount。
一、背景
工单 #8195,wx 在团期「查看需求」页上点出的五处缺口,合并为一个 PR(#8204,squash 62449e550)。五处分别对应:缺陷 1 团号、缺陷 2 未提交户不可见、缺陷 3 接送机无批量确认、缺陷 4 车型无字典校验、缺陷 5 缺团期结束日。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 批量确认接送机需求 | POST | /v3/admin/order/group-batch/{groupBatchId}/requirement/transfer/batch-confirm |
新增 | 允许部分成功;幂等窗口 120s |
| 2 | 团期子订单用车需求记录 | GET | /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households |
修改 | +endDate +teamNo +户级status/statusName;未提交户进列表 |
| 3 | 团期子订单订房记录 | GET | /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households |
修改 | +endDate +teamNo;orderNo 注解订正 |
| 4 | 保存团期正式用车需求 | PUT | /v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement |
修改 | 车型必须命中字典,否则 809119 |
三、接口详情
1. 批量确认接送机需求 POST /v3/admin/order/group-batch/{groupBatchId}/requirement/transfer/batch-confirm
VO: TransferBatchConfirmReqVO → Result<TransferBatchConfirmRespVO>
使用场景
「查看需求」页「用车」板块,团期管理员勾选若干户的接送机需求,一次性确认并转交车务。等价于逐户调 POST /v3/admin/order/{id}/vehicle-requirement/dispatch?kind=TRANSFER,区别是允许部分成功:整批里只要有一户能确认,接口就按业务成功返回,失败户单独列出而不回滚成功户。权限码与整团确认、按户打回同为 group-batch:demand:confirm——同一个 Tab 里同一批人的同一类动作,分码会出现「能逐户放行却不能批量放行」这种前端无法向运营解释的组合。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
groupBatchId |
path | String | 是 | 雪花 ID | 团期 ID,字符串透传,禁 Number() |
orderIds |
body | Long[] | 是 | @NotEmpty、@Size(max=200) |
待确认的子订单 ID,1~200 户,服务端去重 |
dispatchRemark |
body | String | 否 | @Size(max=500) |
确认备注,整批共用,提供给车队 |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
groupBatchId |
String | 团期 ID(ToStringSerializer) |
requestedCount |
int | 去重后的待确认户数,恒等于 successCount + failedCount,可用于对账 |
successCount |
int | 确认成功的户数 |
failedCount |
int | 确认失败的户数;> 0 时请展示 failed 明细,不要只提示「部分成功」 |
succeededOrderIds |
String[] | 成功的子订单 ID,按请求顺序,字符串形态防 JS 精度丢失 |
failed |
FailedItem[] | 失败明细,按请求顺序;全部成功时是空数组,不是 null |
failed[].orderId |
String | 子订单 ID |
failed[].errorCode |
Integer | 业务错误码;非业务异常(系统故障)时为 null |
failed[].reason |
String | 已渲染的中文报文,可直接展示 |
请求示例
POST /v3/admin/order/group-batch/2102383303678189570/requirement/transfer/batch-confirm
Content-Type: application/json
{"orderIds":[2102383417822003201,2102383458422841346],"dispatchRemark":"11/20 首都机场接"}
响应示例
全部成功(测试服实测原文,ac/06-batch-confirm-1.json):
{"code":200,"message":"成功","data":{"groupBatchId":"2102383303678189570","requestedCount":2,"successCount":2,"failedCount":0,"succeededOrderIds":["2102383417822003201","2102383458422841346"],"failed":[]},"traceId":null,"success":true}
部分成功(测试服实测原文,ac/07-partial-fail.json)。注意 code 是 200、success 是 true,但有一户没确认成功:
{"code":200,"message":"成功","data":{"groupBatchId":"2102383303678189570","requestedCount":2,"successCount":1,"failedCount":1,"succeededOrderIds":["2102405916668440577"],"failed":[{"orderId":"2102383417822003201","errorCode":582083,"reason":"需求状态不允许此操作,请检查当前状态"}]},"traceId":null,"success":true}
空数据 / 降级响应
orderIds 传空数组或不传时不进业务逻辑,直接被参数校验拦下,不产生任何写操作。succeededOrderIds 与 failed 在任何成功响应里都是数组,不会是 null——全成功时 failed 是 [],全失败时 succeededOrderIds 是 [],前端可以无条件 .map() 而不必先判空。
错误响应
整批被拒的两种形态(幂等拦截为测试服实测原文 ac/08-batch-confirm-retry.json):
{"code":400,"message":"请至少选择一个要确认的子订单"}
{"code":100502,"message":"接送机需求确认处理中,请勿重复提交","data":null,"traceId":null,"success":false}
单户被拒不走错误响应,而是进上面 data.failed[],典型 errorCode 为 582083「需求状态不允许此操作,请检查当前状态」(例如该户已经是 PENDING)。
业务边界
- 幂等窗口 120 秒:
@Idempotent的 key 由groupBatchId+orderIds共同决定 ⇒ 换一批orderIds不受上一次影响,同一批在 120s 内第二次必被100502拒。 - 部分成功是设计,不是异常:失败户不会被静默跳过,也不会把整批回滚。
- 确认只改需求状态,不产生派车记录:本阶段只把
order_vehicle_requirement.status与order_main.vehicle_control_status从PENDING_REVIEW置为PENDING;实测两次调用前后fleet_assignment按order_id过滤COUNT(*)均为 0。真正的派车分单是车队侧后续独立动作。 - 重复的
orderIds服务端去重:requestedCount是去重后的数,前端拿它对账不会因为自己传重而对不上。 - 响应体里不含刷新后的行:确认成功后需要重新拉一次
vehicle-households才能看到新状态。
2. 团期子订单用车需求记录 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/vehicle-households
VO: Result<GroupVehicleHouseholdsRespVO>
使用场景
「查看需求」页「用车」板块下半块的逐户列表。本次把它从「已提交需求的户的列表」改成「应报车的户的列表」——运营需要看见「谁还没交」,而改前那些户根本不出现在响应里,页面上无从催办。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
groupBatchId |
path | String | 是 | 雪花 ID | 团期 ID,字符串透传,禁 Number() |
kind |
query | String | 否 | TRAVEL / TRANSFER |
不传 = 两类都返(与提交侧「不传按 TRAVEL」的缺省相反,此处未改) |
出参
新增 4 个字段、2 个既有字段口径变化,其余未动:
| 字段 | 类型 | 说明 |
|---|---|---|
endDate |
String | 新增。团期结束日期 yyyy-MM-dd;团期未定结束日时为 null(与团期详情 endDate 同源) |
households[].teamNo |
String | 新增。子订单团号,取 order_main.team_no;未付订金尚未分配时原样返 null,后端不兜底成 orderNo、不回退空串 |
households[].status |
String | 新增(户级)。null = 该户一份用车需求都没提交;非 null 时取展示序首条(TRAVEL 优先)的状态 |
households[].statusName |
String | 新增(户级)。与 status 同一条需求行的中文名;status 为 null 时本字段也为 null |
householdCount |
int | 口径变更。改前 = 有活跃需求行的户数;改后 = 应报车的户数,恒等于 households 长度,含一份都没提交的户。仍按 orderId 去重(一户同时报行程用车与接送机只算 1 户) |
vehicleRowCount |
int | 口径未变、关系变了。= Σ 各户 requirements 长度,未提交户贡献 0 行 ⇒ 可能小于 householdCount |
countedHouseholdCount |
int | 口径未变、分母变了。= 有活跃 TRAVEL 行的户数。householdCount − countedHouseholdCount 从改前的「只报了接送机的户」变成「只报了接送机的户 + 一份都没提交的户」 |
households[].orderNo |
String | 值与形态都没变("HL" + yyyyMMddHHmmssSSS,定长 19),只是 Swagger 不再谎称它是团号 |
requirements[].status |
String | 未变,早就有。逐条的权威状态在这里,不在户级 status |
请求示例
GET /v3/admin/order/group-batch/2102383303678189570/requirement/vehicle-households
响应示例
测试服实测(ac/00-vehicle-households.json)顶层为 householdCount=5、countedHouseholdCount=0、vehicleRowCount=2、endDate="2026-11-21",五户的关键字段:
[{"orderNo":"HL20260922210334521","teamNo":"26-3724","status":null,"requirements":[]},
{"orderNo":"HL20260922210348601","teamNo":null,"status":null,"requirements":[]},
{"orderNo":"HL20260922210358692","teamNo":null,"status":null,"requirements":[]},
{"orderNo":"HL20260922210401823","teamNo":"26-0847","status":"PENDING_REVIEW","requirements":["…1 条"]},
{"orderNo":"HL20260922210411494","teamNo":"26-7970","status":"PENDING_REVIEW","requirements":["…1 条"]}]
三个计数两两不等,正好演示新口径:5 户全在列表里,只有 2 户提交过,且两条都是 TRANSFER,所以计入车侧汇总的 TRAVEL 户数是 0。
空数据 / 降级响应
该户没提交任何用车需求时 requirements 是 [](空数组,不是 null)、status 与 statusName 均为 null;团期未定结束日时 endDate 为 null;未付订金时 teamNo 为 null。整团一户都没有时三个计数为 0、households 为 [],接口仍返 200。以上四种降级都不会让接口报错,前端需要各自有占位显示。
错误响应
本次未改,沿用团期段位错误码:
{"code":589500,"message":"团期不存在","data":null,"traceId":null,"success":false}
另有 589507(GROUP_BATCH_PERMISSION_DENIED,团期操作/读取被拒)由拦截器透 message,前端直接展示即可。
业务边界
- 户级
status是折叠态用的,不是权威状态:一户可能同时有 TRAVEL 与 TRANSFER 两条活跃行、状态各自独立(例如 TRAVEL 已放行PENDING、TRANSFER 还在PENDING_REVIEW),户级status只取展示序第一条。按条判断一律读requirements[].status。 - 🔴 「从未提交」与「提交后被打回」在本接口上不可区分:打回 = 原地置
REJECTED_*+is_active=0,失活行不进requirements⇒ 被打回的户同样是requirements: []+status: null,与从未提交的户完全同形。依据GroupVehicleHouseholdsRespVO.java:169-171。要把这两种人分开,本接口给不出判据。 teamNo与orders接口同源同值:取order_main.team_no,不是order_group_batch.batch_no(那是整团一个值,放在逐户列表上每行都一样,这一列就没有分辨力了)。三个读口(hotel-households / vehicle-households / orders)的teamNo实测逐字符相等。
3. 团期子订单订房记录 GET /v3/admin/order/group-batch/{groupBatchId}/requirement/hotel-households
VO: Result<GroupHotelHouseholdsRespVO>
使用场景
「查看需求」页「用房」板块下半块的逐户列表,与 requirement-summary 并列调用。本次只补两个字段并订正一处注解,列表口径没动——用房侧本来就包含未提交的户(status=null、days=[]),这次是车侧向它对齐,不是它变了。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
groupBatchId |
path | String | 是 | 雪花 ID | 团期 ID,字符串透传,禁 Number() |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
endDate |
String | 新增。团期结束日期 yyyy-MM-dd,未定时 null,与车侧同源同值 |
households[].teamNo |
String | 新增。同车侧,取 order_main.team_no,未付订金时 null |
households[].orderNo |
String | 注解订正(「子订单团号」→「子订单编号(非团号)」),值未变 |
households[].status |
String | 未变。用房侧本来就有(未提交时为 null) |
households[].statusName |
String | 未变。用房侧本来就有 |
householdCount |
int | 未变。与 countedHouseholdCount 的差值仍是「未计入汇总(打回 / 未提交)的户数」 |
请求示例
GET /v3/admin/order/group-batch/2102383303678189570/requirement/hotel-households
响应示例
测试服实测(ac/00-hotel-households.json),endDate 为 "2026-11-21",五户 teamNo 与车侧、与 GET .../orders 三方逐字符相等:
[{"orderNo":"HL20260922210334521","teamNo":"26-3724"},
{"orderNo":"HL20260922210348601","teamNo":null},
{"orderNo":"HL20260922210358692","teamNo":null},
{"orderNo":"HL20260922210401823","teamNo":"26-0847"},
{"orderNo":"HL20260922210411494","teamNo":"26-7970"}]
空数据 / 降级响应
未付订金的户 teamNo 为 null;团期未定结束日时 endDate 为 null。既有的降级行为一律未动:需订房但未提交的户仍会列出(status=null、days=[]),客户自订晚仍会列出且 hotels=[],打回户仍列出且 countedInSummary=false。
错误响应
本次未改,与车侧同段位:
{"code":589500,"message":"团期不存在","data":null,"traceId":null,"success":false}
业务边界
- 用房侧的列表口径没有跟着车侧一起改:它本来就含未提交户,本次只补
teamNo与endDate两个字段。 - 「汇总 == Σ 子订单」这条既有硬约束不受影响:汇总逐日间数仍等于本接口
countedInSummary=true各户逐日加总,差值仍是householdCount − countedHouseholdCount。 orderNo的排序契约未变:households仍按orderNo升序,新增teamNo不参与排序——不要改用teamNo排序,它可以为 null。
4. 保存团期正式用车需求 PUT /v3/admin/order/group-batch/{groupBatchId}/vehicle-requirement
VO: GroupVehicleRequirementSaveReqVO → Result<GroupVehicleRequirementRespVO>
使用场景
团期管理员新增 / 编辑整团的正式行程用车需求,一次全量替换整份(主表 + 全部分组 + 全部逐日行)。本次给分组里的车型加了字典校验:改前前端传什么就落什么,运营填错的车型要等到车队派车时才暴露;改后在保存这一步就拒。
入参
结构不变,仅新增一条约束:
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
groupBatchId |
path | String | 是 | 雪花 ID | 团期 ID,字符串透传 |
groups[].vehicleType |
body | String | 是 | 新增:必须命中车型字典 | 车型大类编码,须存在且未下线,从下拉项取 |
groups[].groupName |
body | String | 是 | — | 组名,校验失败时会被写进错误报文,便于定位是哪一组 |
出参
| 字段 | 类型 | 说明 |
|---|---|---|
groups[].vehicleType |
String | 校验通过后回显的车型编码,未变 |
groups[].vehicleTypeName |
String | 车型中文名,后端按字典下发,禁前端自映射 |
其余字段结构不变。
请求示例
{"groups":[{"groupName":"AC9-BAD","vehicleType":"minivan"}]}
vehicleType 须取自 GET /admin/fleet/vehicle-types/list 的下拉项;上例的 minivan 不在字典内,用于演示校验被触发。
响应示例
合法车型实测(ac/09-good-type-4.json 节选):
{"code":200,"message":"成功","data":{"groups":[{"vehicleType":"bus","vehicleTypeName":"大巴系列"}]},"success":true}
空数据 / 降级响应
车型字典为空时不放行(fail-closed),不会退化成「不校验」——宁可让保存失败并提示运营去维护字典,也不能把一批查不到名字的车型放进正式需求,那会在车队侧变成一堆无法派车的行。
错误响应
非法车型实测原文(ac/09-bad-type.json),报文里带组名,前端可直接定位到是哪一组填错:
{"code":809119,"message":"第 AC9-BAD 组的车型 minivan 不在车型字典内(不存在或已下线),请从下拉项中选择","data":null,"traceId":null,"success":false}
业务边界
- 车型必须从
GET /admin/fleet/vehicle-types/list的返回里选,不要在前端硬编码枚举——字典行可被下线,下线后同一个编码就会被拒。 - 本端点另有两条既有前置会先于车型校验触发(本次未改):团期阶段守卫(
RECRUITING阶段被589501「团期状态不允许当前操作」拒,需先成团)、逐日乘车分组必须覆盖全团在团户与全部行程日(否则809109「子订单 {0} 的 {1} 没有被任何乘车分组覆盖」)。 - 整份全量替换:保存即覆盖,前端提交前必须带上未改动的分组与逐日行,否则会被删掉。
四、契约约束与正确调用方式
✅ 正确 / ❌ 错误对照
| 场景 | ❌ 错误 | ✅ 正确 |
|---|---|---|
| 渲染团号列 | 读 orderNo |
读 teamNo;为 null 时显示占位符,不要回落成 orderNo |
| 表头「共 N 户」 | 用行数或自行推算 | 取 householdCount(与 households.length 恒等) |
| 判断批量确认结果 | if (res.success) { 提示全部成功 } |
if (res.data.failedCount > 0) { 展示 res.data.failed 明细 } |
| 判断某条需求的状态 | 读户级 status |
读 requirements[i].status |
| 车型下拉 | 前端写死枚举数组 | 调 GET /admin/fleet/vehicle-types/list |
| 列表排序 | 改用 teamNo 排序 |
仍按 orderNo(teamNo 可为 null) |
| 传 ID | Number(orderId) |
雪花 ID 一律字符串透传 |
状态切换后的必要动作
批量确认成功后,被确认户的 order_vehicle_requirement.status 与 order_main.vehicle_control_status 都变为 PENDING。响应体里不含刷新后的行,需要重新拉一次 vehicle-households。
五、数据库行为
批量确认端点写两张表:order_vehicle_requirement.status、order_main.vehicle_control_status,均 PENDING_REVIEW → PENDING,调用前后逐户 SELECT 核对过。不写 fleet_assignment(前后均 COUNT(*)=0)。清单里的 2、3 两个读接口不写库。
六、边界行为
| 情形 | 行为 |
|---|---|
| 未付订金的户 | teamNo 为 null(team_no 此时尚未分配),前端需要占位显示 |
| 一份用车需求都没提交的户 | 进车侧列表,requirements: []、status: null、statusName: null |
| 提交后被打回的户 | 与上一行完全同形,本接口不可区分 |
| 一户同时有 TRAVEL + TRANSFER | householdCount 只算 1 户,vehicleRowCount 算 2 行 |
| 批量确认里混入状态不对的户 | 整批仍按 code:200 返回,该户进 failed[] |
| 120s 内同批重复提交 | code:100502,整批拒 |
| 团期未定结束日 | endDate: null |
| 车型字典为空 | 保存被拒(fail-closed),不退化成不校验 |
六.5、枚举 / 数据字典
households[].status(户级用车需求状态)
PENDING_REVIEW(待审核) / PENDING / PROCESSING / DONE,以及 null = 该户一份都没提交。statusName 由后端下发,禁前端自映射。
vehicleType(车型大类编码)
运行期字典,不是固定枚举,取自 fleet_vehicle_type,通过 GET /admin/fleet/vehicle-types/list 下发。2026-09-22 测试服上存活 4 项(suv2 / mpv / sedan / bus),但这是当日快照、不是契约——字典行可被增删下线,前端不得据此硬编码。
六.6、修改前后对比
字段级对比
| 接口 | 字段 | 改前 | 改后 |
|---|---|---|---|
| hotel / vehicle-households | orderNo 的 Swagger 说明 |
「子订单团号」,example GT-26-0081 |
「子订单编号(非团号;形如 HL + yyyyMMddHHmmssSSS)」,example HL20260516143052999。字段值本身从未变过,一直是订单号 |
| hotel / vehicle-households | teamNo |
不存在 | 新增,真团号,可为 null |
| hotel / vehicle-households | endDate |
不存在 | 新增,可为 null |
| vehicle-households | 户级 status / statusName |
不存在 | 新增(用房侧本来就有;requirements[].status 也早就有,别混淆) |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 没提交用车需求的户 | 不在车侧响应里 | 在响应里,空卡 |
householdCount |
有活跃需求行的户数 | households 长度 |
vehicleRowCount vs householdCount |
恒 ≥ | 可能 < |
| 接送机确认 | 只能逐户 dispatch?kind=TRANSFER |
可批量,允许部分成功 |
| 提交非法车型 | 通过,落库 | 809119 拒 |
🔴 hl-ui 里已经不准确的 JSDoc(origin/v2.1,src/api/orderV2GroupBatch.js)
两个函数的 JSDoc 都写于改前,各有过期处。行号为 2026-09-22 在 origin/v2.1 上实读:
getGroupVehicleHouseholds(JSDoc :597-622)
:600「被打回的需求行不在列表内(失活即消失,勿按用房那套找打回户)」——这句本身仍成立,但它隐含的「列表里的户都提交过」已不成立:未提交户现在也在列表里,且和被打回户长得一模一样。:601-602「householdCount 按 orderId 去重…vehicleRowCount 数行,两者刻意不等价——表头「共 N 户」必须取 householdCount,禁取行数」——结论仍然对(表头就该取householdCount),但它没说方向,读的人会默认行数 ≥ 户数,改后可能反过来。:607-620的@returns结构体——缺endDate、teamNo、户级status、户级statusName四个新字段。注意:613已有的status/statusName是requirements[]里的,不是户级的。
getGroupHotelHouseholds(JSDoc :568-589)
:576-586的@returns结构体——缺endDate与teamNo;:579列的orderNo需要补一句「不是团号」。:571-574关于打回户、未提交户与「汇总 == Σ 子订单」的几条口径未变,不必动。
六.7、影响评估
| 面 | 评估 |
|---|---|
| 破坏性 | 无字段删除、无字段改名、无类型变更,orderNo 的值与形态都没动 ⇒ 前端不改也不会报错 |
| 但会静默出错的地方 | ①「共 N 户」若不是取 householdCount 而是别的推算,数字会和列表对不上;②「行数 ≥ 户数」的断言会在有未提交户时挂掉;③ 批量确认只看 success 会把部分失败当成全成功 |
| 需要前端动手的 | 团号列改读 teamNo、空卡的展示与催提交入口、批量确认按钮与部分失败明细、车型下拉改走字典接口、endDate 展示 |
七、不影响范围
GET /v3/admin/order/group-batch/{id}/orders:未改,teamNo本来就有,本次是让另外两个接口与它对齐。- 用房侧的列表口径与「汇总 == Σ 子订单」硬约束:未改。
- 逐户
POST /v3/admin/order/{id}/vehicle-requirement/dispatch:未改,仍可用。 - 车侧汇总
requirement-summary的既有口径:未改,仍只统计行程用车(#8151 的语义保持)。 - 小程序端、
/mp/接口:零改动。 - 网关:零新增路由。
- 结算侧
settlement/**:与本次改动零文件重叠。
八、测试环境已验证
网关 https://api.test.1814.love:9443,order-v3 读数 dev-v3 / 62449e550 / 2026-09-22 22:22:58 / STATE=ok(62449e550 即本单合并提交本身)。
| 验证项 | 结果 |
|---|---|
teamNo 三方同源 |
hotel / vehicle / orders 三个接口逐户逐字符相等;已付订金户非空、未付订金户为 null,两种情形都覆盖 |
teamNo ≠ orderNo |
逐户为不同值 |
| 未提交户进列表 | 空卡与 status="PENDING_REVIEW" 的已提交户在同一份响应里同时存在,字段有分辨力 |
| 三个计数可区分 | 基线 5 / 0 / 2,终态 6 / 0 / 3,均两两不等 |
| 批量确认 | 2 户全成功;DB 回读两户双表均 PENDING_REVIEW → PENDING |
| 部分成功 | 1 成 1 败,失败户带 orderId + errorCode(582083) + reason |
| 幂等 | 同批 120s 内第二次 code:100502;DB 回读无重复行 |
| 车型字典两个方向 | 非法 minivan → 809119 拒;合法 bus → 200 通过并回显 vehicleTypeName |
endDate |
hotel / vehicle / batch-detail 三方均 2026-11-21,逐字符相等 |
| 单测 / ArchTest | 定向 9 个类共 173 个用例逐类点名核对全绿,含 MapperBoundaryArchTest 27 与 RedLineArchTest 12 |
原始报文全部落盘(D:/work2/_scratch/8195/ac/*.json)。夹具为自建团期 2102383303678189570 + 自建产品班期 2102383185755312131(batchName 为「8195夹具-2026年11月团期」),未复用他人夹具。
九、相关历史 PR
- #8151(团期子订单用车需求记录只读接口,本次改的就是它)
- #7441(团期正式用车需求的存 / 读 / 撤回 / 免车四端点)
十、相关文档
- Gitea Issue #8195
- PR #8204(squash
62449e550) - 相邻单 #8193(团期房务三事件站内信配置,同批部署)
关联 / 联系人
链接
- 工单:
https://git.1814.love:8443/wx/HL/issues/8195 - PR:
https://git.1814.love:8443/wx/HL/pulls/8204
联系人
- 后端: wx
- 前端: mmg(hl-ui,分支
v2.1)