31 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 | 8375 | 房务配房列表改版:并入订单列表,新增两个读端点(户级/团期),旧池端点标废弃,菜单与通知链接改向 | admin | wx(GIT) | 新增接口 | deployed | verified | verified | mmg | beb6e18b55866f9914811362638b7d3713044d70 | v2.1 | 2026-09-27 | 订单列表新增两个读端点替代房务抢单池;五个旧读端点标 @Deprecated;三个错误码文案改动(去「抢单池」);菜单 101/102 下线;团期通知链接改为订单列表。后端三个 PR(product-v2/#8381、order-v3/#8382、user-service/#8379)已合入 dev-v3 并部署测试服,逐条实测验证通过。前端 2026-09-27 已交付并回写 verified:订单列表重写为表格模式(产品页签全部/核心/定制/团期+状态页签户级七桶/团期三桶+scope 全部/我的+「开始配房」canStartAllocation 唯一依据+?groupBatchId= 团期定位),旧抢单池两页与五个旧读端点调用已删除,写口(claim/transfer/release/takeover)不变仅改入口;house-allocation-orders spec 8 例+房务域 161 例全绿(mmg,beb6e18b,v2.1)。 | 2026-09-26 | dev-v3 |
房务订单列表改版:新读端点替代抢单池、旧端点标废弃、菜单下线、通知改向(管理后台)
服务: hl-order-service-v3(端口 8086/8186)/ hl-user-service(端口 8089/8189) PR: #8381(product-v2)/ #8382(order-v3)/ #8379(user-service) Issue: #8375 日期: 2026-09-26 影响范围: 房务管家 › 订单列表的页签切换、筛选项恢复、「开始配房」入口改向、所有房务角色的可见范围放开、旧页面与菜单下线
⚠️ 关键变化
-
新增两个读端点,替代房务抢单池两个旧页面:
GET /v3/admin/order/house-allocation/households:户级(核心/定制订单)GET /v3/admin/order/house-allocation/group-batches:团期订单
-
五个旧读端点标
@Deprecated,行为不变,但前端改调新端点:GET /v3/admin/order/grab-pool/hotel-requirementsGET /v3/admin/order/grab-pool/group-batchesGET /v3/admin/order/grab-pool/my-claims/hotelGET /v3/admin/order/grab-pool/my-claims/group-batchesGET /v3/admin/order/grab-pool/all-claims/hotel
-
权限视图放开:两个新端点都挂读门
HouseReadPermission,不限scope=all;普通房务也能看全员认领情况(旧的all-claims/hotel仍返回 808092)。 -
认领写口不变:保持现有逻辑,只是入口从池页改到列表行:
- 户级:
POST /v3/admin/order/hotel-requirements/{requirementId}/claim - 团期:
POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/claim
- 户级:
-
三个错误码文案改动,去掉"抢单池"页面名:
- 808650:改为「团期订单须整团认领后配房,不支持逐户认领 / 转单」
- 808612:改为「该团期尚未被房务整团认领」
- 808001:改为「该需求已被其他房务认领或状态已变化,请刷新后重试」
-
菜单下线:房务抢单池菜单(菜单 101 与 102)已在 user-service 侧置为 INACTIVE,部署后生效。
-
团期通知链接改向:站内链接由
/housekeeper/grab-pool-group?groupBatchId=改为/housekeeper/orders?groupBatchId=(订单列表团期页签)。
一、背景
房务原来要在"订单列表"和"房务抢单池"两个页面之间来回切,体验割裂。本次改版将待配房的单并入订单列表,整合三类订单视图:
- 待配房:所有房务都能点「开始配房」认领
- 配房中:谁在做,全员可见
- 已认领:可按「我的」或「全部」筛选
新端点按以下规则返回行:
- 户级行(order_main 表,group_batch_id 与 product_batch_id 都为空)
- 待配房:
status=PENDING且claimer_id IS NULL - 已认领:
status=PENDING且claimer_id IS NOT NULL
- 待配房:
- 团期行(order_group_batch 表,整团一行)
- 待配房:
house_claimer_id IS NULL且requirement_confirmed=1且batch_status=RESOURCE_PREPARING - 已认领:
house_claimer_id IS NOT NULL(任意阶段)
- 待配房:
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 房务配房列表·户级 | GET | /v3/admin/order/house-allocation/households |
新增接口 | 户级页签(核心/定制订单),分页返回 |
| 2 | 房务配房列表·团期 | GET | /v3/admin/order/house-allocation/group-batches |
新增接口 | 团期页签,整团一行 |
旧端点标废弃(行为不变):GET /v3/admin/order/grab-pool/hotel-requirements、/grab-pool/group-batches、/grab-pool/my-claims/hotel、/grab-pool/my-claims/group-batches、/grab-pool/all-claims/hotel 加 @Deprecated,详见第五章节。
网关无改动(均在既有 /v3/admin/order/ 前缀下);新路径已验证可达。
三、接口详情
1. 房务配房列表·户级 GET /v3/admin/order/house-allocation/households
VO: HouseAllocationHouseholdPageReqVO → HouseAllocationHouseholdPageRespVO
使用场景
房务管家 › 订单列表的核心和定制页签,以及全部页签的户级数据部分。返回户级订单(order_main),按待配房/已认领分行展示,支持 scope 筛选当前用户或全员,按多种条件排序和分页。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| scope | Query | String | 否 | all | mine,小写 |
默认 all;mine 则只返回当前用户认领的行,pendingClaim 桶恒为 0 |
| status | Query | String | 否 | pendingClaim | unfinished | claiming | pendingConfirm | confirmed | exception,或空 |
默认 unfinished;空串表示全部;返回对应 house_status 的行 |
| productType | Query | String | 否 | CORE | CUSTOM,或空 |
空或不传表示全部户级行;不接受 productType=GROUP(团期订单走团期端点) |
| keyword | Query | String | 否 | @Size(max=32) |
模糊匹配:订单号 / 团号 / 客人姓名 / 产品名(OR) |
| productName | Query | String | 否 | — | 模糊匹配产品名 |
| consultantId | Query | Long | 否 | — | 定制师 ID,精确匹配 |
| guestName | Query | String | 否 | — | 客人姓名,模糊匹配 |
| departDateFrom | Query | LocalDate | 否 | yyyy-MM-dd |
出发日期起 |
| departDateTo | Query | LocalDate | 否 | yyyy-MM-dd |
出发日期止(含) |
| claimedAtFrom | Query | LocalDateTime | 否 | yyyy-MM-dd'T'HH:mm:ss |
认领时间起;传了就等于只看已认领的行 |
| claimedAtTo | Query | LocalDateTime | 否 | yyyy-MM-dd'T'HH:mm:ss |
认领时间止 |
| page | Query | Integer | 否 | @Min(1) |
默认 1 |
| pageSize | Query | Integer | 否 | @Min(1) @Max(100) |
默认 20 |
| sortBy | Query | String | 否 | departDate,asc | createTime,desc | claimedAt,desc |
默认 departDate,asc;无论选哪个,都先按手动加急(manual_urgent DESC, manual_urgent_at DESC)排 |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| list | List<HouseAllocationHouseholdRespVO> | 分页结果行 |
| total | Long | 满足条件的总行数 |
| stats | HouseAllocationHouseholdStatsVO | 各页签的计数(与列表共用筛选条件,忽略 status) |
行字段详情(HouseAllocationHouseholdRespVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| id | String | requirementId,前端「开始配房」时用此值 |
| orderId | String | 订单 ID,进户级详情时用 |
| orderNo / teamNo | String | 订单号 / 团号 |
| guestName | String | 客人姓名 |
| personsDesc | String | 人数描述(如「2成人1儿童」) |
| productType | String | 产品类型(CORE/CUSTOM/ROUTE/…) |
| productName | String | 产品名称 |
| productNo | String | 产品编号;来自 product-v2 批量查询,取不到时为 null(见降级响应) |
| route | String | 行程描述 |
| cities | List<String> | 城市列表 |
| departDate | LocalDate | 出发日期 |
| nights | Integer | 晚数 |
| totalAmount | String | 订单金额(后端计算,已序列化为字符串) |
| consultantId | String | 定制师 ID |
| consultantName | String | 定制师姓名 |
| consultantRemark | String | 定制师备注 |
| requirementNote | String | 需求备注 |
| dispatchRemark | String | 派车备注 |
| special | String | 特殊需求 |
| requirementVersion | Integer | 需求版本号 |
| requirementStatus | String | 对外状态(PENDING/PROCESSING/DONE/…) |
| houseStatus | String | 枚举码:PENDING_CLAIM / CLAIMING / PENDING_FINALIZE / CONFIRMED / EXCEPTION;与旧 VO 的中文名不同 |
| houseStatusLabel | String | 中文显示名(「待配房」/「配房中」/「待确认」/「已确认」/「异常」) |
| claimerId | String | 当前认领人 ID;待配房行为 null |
| claimerName | String | 当前认领人名字;待配房行为 null |
| claimedAt | LocalDateTime | 认领时间;待配房行为 null |
| isMine | Boolean | 认领人是否当前用户 |
| canStartAllocation | Boolean | 前端「开始配房」按钮的唯一依据(true 时显示,false 时隐藏);条件:status=PENDING 且 claimerId IS NULL 且当前用户有写权限 |
| manualUrgent | Boolean | 手动加急标记 |
| manualUrgentAt | LocalDateTime | 加急时间 |
| urgencyLevel | String | 紧急度标签(LOW/MEDIUM/HIGH) |
| urgencyLabel | String | 紧急度中文名(「低」/「中」/「高」) |
| daysToDepart | Integer | 距出发还有几天(负数表示已出发) |
| isRework | Boolean | 是否返工 |
| reworkPrevClaimerName | String | 上次认领人名字 |
| exceptionCount | Integer | 已认领行:该户有几个未处理异常待办;待配房行为 0 |
| todoCount | Integer | 已认领行:该户有几个待办;待配房行为 0 |
| primaryAction | HousePrimaryActionVO | 只在 isMine=true 时返回;包含转单、释放等操作信息 |
| createTime | LocalDateTime | 需求创建时间 |
stats 分桶计数(HouseAllocationHouseholdStatsVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| pendingClaim | Long | 待配房行数;scope=mine 时恒为 0 |
| claiming | Long | house_status=CLAIMING 的行数 |
| pendingConfirm | Long | house_status=PENDING_FINALIZE 的行数 |
| confirmed | Long | house_status=CONFIRMED 的行数 |
| exception | Long | house_status=EXCEPTION 或订单有未处理异常待办的行数 |
| unfinished | Long | 待配房 + 配房中 + 待确认 + 异常 的行数;与 status=unfinished 的查询结果同源 |
| all | Long | 待配房 + 已认领 的总行数;与不传 status 的查询结果同源 |
请求示例
GET /v3/admin/order/house-allocation/households?scope=all&status=pendingClaim&productType=CORE&page=1&pageSize=20&sortBy=departDate,asc HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer ***
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"list": [
{
"id": "2097250563497385985",
"orderId": "770145",
"orderNo": "O20260926001",
"teamNo": null,
"guestName": "张三",
"personsDesc": "2成人1儿童",
"productType": "CORE",
"productName": "日本东京 6 日游",
"productNo": "P002301",
"route": "东京→富士山→京都",
"cities": ["东京", "富士山", "京都"],
"departDate": "2026-10-01",
"nights": 6,
"totalAmount": "8500.00",
"consultantId": "1001",
"consultantName": "李四",
"consultantRemark": "客户有特殊需求",
"requirementNote": "希望升级酒店",
"dispatchRemark": "已预留",
"special": "客户晕车,安排靠窗座位",
"requirementVersion": 1,
"requirementStatus": "PROCESSING",
"houseStatus": "PENDING_CLAIM",
"houseStatusLabel": "待配房",
"claimerId": null,
"claimerName": null,
"claimedAt": null,
"isMine": false,
"canStartAllocation": true,
"manualUrgent": true,
"manualUrgentAt": "2026-09-25T14:30:00",
"urgencyLevel": "HIGH",
"urgencyLabel": "高",
"daysToDepart": 5,
"isRework": false,
"reworkPrevClaimerName": null,
"exceptionCount": 0,
"todoCount": 0,
"primaryAction": null,
"createTime": "2026-09-20T09:00:00"
}
],
"total": 12,
"stats": {
"pendingClaim": 12,
"claiming": 5,
"pendingConfirm": 3,
"confirmed": 8,
"exception": 1,
"unfinished": 21,
"all": 28
}
}
}
空数据 / 降级响应
- 分页无结果时,
list=[],total=0,stats各字段为 0,code=200不报错:
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"list": [],
"total": 0,
"stats": { "pendingClaim": 0, "claiming": 0, "pendingConfirm": 0, "confirmed": 0, "exception": 0, "unfinished": 0, "all": 0 }
}
}
-
productNo 取不到时(product-v2 服务降级或响应缺字段),该字段为 null,其余字段正常返回,不报错。
-
参数不合法时(status、productType、sortBy 等与规则不符),HTTP 200,
code=400(全局 BindException 处理),message是具体字段的校验文案。下面是传productType=GROUP的实测原文:
{"code":400,"message":"productType 只能是 CORE 或 CUSTOM","data":null,"traceId":null,"success":false}
错误响应
- 未登录或无房务读权限(808090):
{
"code": 808090,
"message": "未登录或无该操作权限",
"success": false,
"data": null
}
业务边界
- 查询条件
claimedAtFrom/claimedAtTo同时传递时,等于隐含过滤claimerId IS NOT NULL(只看已认领的行);与status=pendingClaim同传时查询结果为空、code=200、stats.pendingClaim=0,不报错。 - 手动加急
manual_urgent=true的行在任何status页签里都会被提前排列(加急 DESC,加急时间 DESC),无论选何种 sortBy。 - 并发认领:前端的「开始配房」按钮直接调
POST /v3/admin/order/hotel-requirements/{id}/claim,若二人同时点同一行,先到者返回 200,后到者返回 808001 并附加新文案「该需求已被其他房务认领或状态已变化,请刷新后重试」,前端刷新列表即可看到当前认领人。 - 异常数据(存量):列表里个别行的
orderNo或productName可能为 null(对应主订单已软删除),前端需容忍空值、不做特殊提示,只显示已有字段。 - 转单、释放等操作只在
isMine=true的行显示(primaryAction非 null);他人认领的行为只读。 requirementStatus是订单对外状态,houseStatus是该户配房阶段(两个维度独立)。
2. 房务配房列表·团期 GET /v3/admin/order/house-allocation/group-batches
VO: HouseAllocationGroupPageReqVO → HouseAllocationGroupPageRespVO
使用场景
订单列表的团期页签,整团一行。返回团期订单(order_group_batch),按待配房/已认领分行展示。前端的通知链接 ?groupBatchId=<团ID> 也以此端点定位落地。
入参字段表
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| scope | Query | String | 否 | all | mine |
默认 all;mine 时只返回当前用户认领的团 |
| status | Query | String | 否 | pendingClaim | claimed,或空 |
空或不传表示两者都要 |
| groupBatchId | Query | Long | 否 | — | 精确定位一个团(通知链接用);传了则 1 条或 0 条结果 |
| keyword | Query | String | 否 | @Size(max=32) |
模糊匹配:团期号 / 产品名(OR) |
| productId | Query | Long | 否 | — | 产品 ID,精确匹配 |
| batchStatus | Query | String | 否 | RECRUITING | RESOURCE_PREPARING | MATERIAL_PREPARING | PENDING_DEPARTURE | TRAVELLING | TRIP_FINISHED | REVIEWING | SETTLED | CANCELLED |
团期阶段,精确匹配 |
| departDateFrom | Query | LocalDate | 否 | yyyy-MM-dd |
出发日期起 |
| departDateTo | Query | LocalDate | 否 | yyyy-MM-dd |
出发日期止 |
| claimedAtFrom | Query | LocalDateTime | 否 | yyyy-MM-dd'T'HH:mm:ss |
认领时间起 |
| claimedAtTo | Query | LocalDateTime | 否 | yyyy-MM-dd'T'HH:mm:ss |
认领时间止 |
| page | Query | Integer | 否 | @Min(1) |
默认 1 |
| pageSize | Query | Integer | 否 | @Min(1) @Max(100) |
默认 20 |
| sortBy | Query | String | 否 | departDate,asc | claimedAt,desc | createTime,desc |
默认 departDate,asc |
出参字段表
| 字段 | 类型 | 说明 |
|---|---|---|
| list | List<HouseAllocationGroupRespVO> | 分页结果行 |
| total | Long | 满足条件的总行数 |
| stats | HouseAllocationGroupStatsVO | 三个页签的计数:pendingClaim / claimed / all |
行字段详情(HouseAllocationGroupRespVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| groupBatchId | String | 团期 ID,前端「开始配房」时用此值 |
| batchNo | String | 团期号 |
| batchName | String | 团期名称 |
| batchLabel | String | 团期标签 |
| productId | String | 产品 ID |
| productName | String | 产品名称 |
| batchStatus | String | 团期阶段码(RECRUITING/RESOURCE_PREPARING/…) |
| batchStatusLabel | String | 中文显示名(「招募中」/「资源准备中」/…) |
| departDate | LocalDate | 出发日期 |
| endDate | LocalDate | 结束日期 |
| enrollDeadline | LocalDate | 报名截止日期 |
| enrolledRooms | Integer | 已报名房间数 |
| enrolledPeople | Integer | 已报名人数 |
| activeOrderCount | Integer | 活跃订单数 |
| hotelOrderCount | Integer | 需要配房的订单数 |
| hotelReady | Integer | 已配房的订单数 |
| daysToDepart | Integer | 距出发还有几天 |
| urgencyLevel | String | 紧急度标签(LOW/MEDIUM/HIGH) |
| urgencyLabel | String | 紧急度中文名 |
| requirementConfirmed | Boolean | 团期需求是否已整体确认(仅信息展示,不影响认领) |
| houseClaimerId | String | 团级认领人 ID;待配房时为 null |
| houseClaimerName | String | 团级认领人名字;待配房时为 null |
| houseClaimedAt | LocalDateTime | 认领时间;待配房时为 null |
| isMine | Boolean | 认领人是否当前用户 |
| canStartAllocation | Boolean | 前端「开始配房」按钮的唯一依据;条件:houseClaimerId IS NULL 且当前用户有写权限 |
| createTime | LocalDateTime | 创建时间 |
stats 分桶计数(HouseAllocationGroupStatsVO):
| 字段 | 类型 | 说明 |
|---|---|---|
| pendingClaim | Long | 待配房团数(houseClaimerId IS NULL 且 requirementConfirmed=1 且 batchStatus=RESOURCE_PREPARING) |
| claimed | Long | 已认领团数(houseClaimerId IS NOT NULL,任意阶段) |
| all | Long | pendingClaim + claimed 的总数 |
请求示例
GET /v3/admin/order/house-allocation/group-batches?scope=all&status=pendingClaim&page=1&pageSize=20 HTTP/1.1
Host: api.test.1814.love:9443
Authorization: Bearer ***
无请求体。
响应示例
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"list": [
{
"groupBatchId": "2097250563497385985",
"batchNo": "G20260926001",
"batchName": "日本 10 月团·东京-京都-大阪",
"batchLabel": "标准",
"productId": "5001",
"productName": "日本东京-京都-大阪 8 日游",
"batchStatus": "RESOURCE_PREPARING",
"batchStatusLabel": "资源准备中",
"departDate": "2026-10-05",
"endDate": "2026-10-12",
"enrollDeadline": "2026-09-28",
"enrolledRooms": 8,
"enrolledPeople": 16,
"activeOrderCount": 8,
"hotelOrderCount": 8,
"hotelReady": 0,
"daysToDepart": 9,
"urgencyLevel": "HIGH",
"urgencyLabel": "高",
"requirementConfirmed": false,
"houseClaimerId": null,
"houseClaimerName": null,
"houseClaimedAt": null,
"isMine": false,
"canStartAllocation": true,
"createTime": "2026-09-15T10:00:00"
}
],
"total": 5,
"stats": {
"pendingClaim": 5,
"claimed": 12,
"all": 17
}
}
}
空数据 / 降级响应
- 分页无结果:
list=[],total=0,stats各字段为 0,code=200:
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"list": [],
"total": 0,
"stats": { "pendingClaim": 0, "claimed": 0, "all": 0 }
}
}
- 参数不合法时,HTTP 200,
code=400,message是具体字段的校验文案(结构同户级端点):
{"code":400,"message":"<该字段的校验文案>","data":null,"traceId":null,"success":false}
错误响应
- 未登录或无房务读权限(808090):
{
"code": 808090,
"message": "未登录或无该操作权限",
"success": false,
"data": null
}
业务边界
- 整团一行:团期阶段任意时刻只要被认领一次,就会在列表持续出现(
claimed页签或混合页签),不会因为进入后续阶段(待出发、出行中等)而消失。 - 并发认领:前端的「开始配房」按钮直接调
POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/claim。并发场景下:- 团期 claim 端点挂了
@Idempotent(5 秒窗口)与@Lock4j两重防护 - 同时提交会被幂等或锁层拦下,返回 100502(「整团认领处理中,请勿重复提交」,幂等窗口内),前端提示并刷新列表
- 窗口过后别人已抢到会返回 808652(「该团期已被其他房务认领」)
- 团期 claim 端点挂了
- 他人认领的团不提供看板入口:前端对
isMine=false的行不显示「查看看板」入口(若用户直接访问详情页,会得到 808612 或 808613 拒绝);详情页权限不变。 - 订单列表的通知参数
?groupBatchId=<团ID>须在团期页签按此参数定位(可配合 filter 或直接查询定位)。
四、契约约束与正确调用方式
| 场景 | 调用方法 | 说明 |
|---|---|---|
| ✅ 户级「开始配房」 | POST /v3/admin/order/hotel-requirements/{id}/claim |
直接调现有写口,行为不变;canStartAllocation=true 时显示按钮 |
| ✅ 团期「开始配房」 | POST /v3/admin/order/grab-pool/group-batches/{groupBatchId}/claim |
同上;路径保留 grab-pool,因为是现有写口 |
| ✅ 查看全员认领情况 | GET /v3/admin/order/house-allocation/households?scope=all 或 /group-batches?scope=all |
普通房务首次可见;旧端点 all-claims/ 仍返回 808092 |
| ✅ 刷新列表信号 | 监听 SSE 事件 grab-pool-changed |
现有 SSE 通道保留,不新增事件 |
| ❌ 调旧端点继续写代码 | GET /v3/admin/order/grab-pool/hotel-requirements |
@Deprecated,禁用 |
| ❌ 团期已被他人认领后再点「开始配房」 | — | 返回 808652「该团期已被其他房务认领」,刷新列表即可看到认领人,不要重试 |
配套变更说明
错误码文案更新
随 PR-1 部署,三个错误码文案改动(去掉对「抢单池」页面的引用):
| 码 | 旧文案 | 新文案 | 触发场景 |
|---|---|---|---|
| 808650 | "团期订单须整团认领,不支持逐户认领。请到团期抢单池整团认领" | "团期订单须整团认领后配房,不支持逐户认领 / 转单" | 试图逐户认领 / 转单一个团期订单 |
| 808612 | "该团期尚未被房务认领,请先到团期抢单池认领" | "该团期尚未被房务整团认领" | 进入他人未认领的团期看板,或操作不满足条件的团期 |
| 808001 | "需求已被其他房务抢到" | "该需求已被其他房务认领或状态已变化,请刷新后重试" | 户级并发认领冲突,或状态变化后重复调用 |
房务抢单池菜单下线
随 PR-2 部署(Flyway V20260926_001):
- 菜单 101(「抢单池·普通」,路径
/housekeeper/grab-pool)置为 INACTIVE - 菜单 102(「抢单池·团期」,路径
/housekeeper/grab-pool-group)置为 INACTIVE
菜单对所有角色同步生效(按 ACTIVE 状态过滤)。缓存于 user-service 启动完成时自动刷新;若启动日志出现"应用启动后刷新菜单缓存失败",需手工 Redis DEL 对应 key(1 小时 TTL 后自动过期)。
团期通知链接改向
随 PR-2 部署(SQL Flyway 更新通知配置),三条团期站内链接由抢单池改指订单列表:
| 通知事件 | 原链接 | 新链接 | 内容变化 |
|---|---|---|---|
| GROUP_BATCH_HOUSE_CLAIMED | /housekeeper/grab-pool-group?groupBatchId= |
/housekeeper/orders?groupBatchId= |
链接改向;内容不再含「抢单池」词语 |
| GROUP_BATCH_HOUSE_RELEASED | /housekeeper/grab-pool-group?groupBatchId= |
/housekeeper/orders?groupBatchId= |
同上 |
| GROUP_BATCH_REQUIREMENT_CONFIRMED | /housekeeper/grab-pool-group?groupBatchId= |
/housekeeper/orders?groupBatchId= |
同上 |
旧读端点标废弃
五个旧端点的 Controller 方法加 @Deprecated 注解;Swagger 操作描述末尾补充「(已废弃,改用 /v3/admin/order/house-allocation/…)」。行为与字段完全不变,现有消费方在迁移完毕前仍可继续调用,但新代码禁止接入。
迁移完毕后(todos 与作废页签移至新端点或别处)方开工单删除。
五、数据库行为
无表结构变更,无 H2 迁移脚本改动。user-service Flyway V20260926_001 更新系统菜单与通知配置(非业务表)。
六、边界行为
- 两个新端点都挂读门
HouseReadPermission,非房务角色(或未登录)返回 808090;普通房务、组长、超管均可调(不限scope=all),这是与旧all-claims/最大的权限差异。 - 写口(认领、转单、释放)权限不变:写门只放行 ROOM_MANAGER 与 SUPER_ADMIN;房务组长(house_keeper_lead)调写口返回 808091,其他角色返回 808090。所以组长在两个新端点上所有行
canStartAllocation=false。 - SSE 广播现有四类事件 ADDED / CLAIMED / RELEASED / URGENT 保留,团期认领、释放、接管不补新事件(现状事实:旧池亦不发,属既知设计)。
- 他人认领的团期行只读:行操作(转单、释放等)只在
isMine=true时展示;若直接访问团期看板详情,会得 808612/808613 拒绝。 - 参数校验失败(如 status 值非法)走全局
BindException,HTTP 200,code=400(非 400 HTTP 状态)。
七、不影响范围
- 认领、转单、释放、接管的写逻辑:完全不变,只改入口
- 订单详情读权限:不变
- 小程序端(
/v3/mp/):无改动 - 旧池的五个读端点在存量消费方(todos、作废页签)迁移完毕前仍可继续调用
- SSE 通道与事件:保留现有四类,不新增
- 子订单状态机、配房流程:不变
- 身份权限种子与角色:不变(仅房务菜单下线,不涉及角色、权限位、权限码)
- 网关配置:无改动;新路径在现有通配规则
Path=/v3/admin/**下已生效
八、测试环境已验证
部署:hl-gateway / hl-user-service / hl-product-service-v2 / hl-order-service-v3 四个服务均为 dev-v3 12707c57c(deploy-status.sh 四行 ok,2026-09-26 15:47~16:06 滚完)。以下读数都是经网关 api.test.1814.love、用真实账号鉴权的实测结果(2026-09-26)。
| # | 场景 | 实测结果 |
|---|---|---|
| 1 | 户级「开始配房」:两个普通房务并发认领同一行 | 一个 200,另一个 808001「已被认领或状态已变化」。随后另一人在列表里看到该行:claimerName = 认领人,isMine=false,canStartAllocation=false |
| 2 | 普通房务对他人已认领的户级行调认领 / 转交 / 释放 | 分别返回 808001 / 808010 / 808020,行状态不变 |
| 3 | 普通房务调户级列表 scope=all |
code=200;旧端点 GET /grab-pool/all-claims/hotel 仍返回 808092(旧权限策略不变) |
| 4 | 团期「开始配房」:两个普通房务同时点击 | 5 秒幂等窗口内,后到者 100502;窗口外重试 808652。列表中该团 houseClaimerName = 先到者 |
| 5 | 房务主管(house_keeper_lead)调两个列表 |
均 code=200。全量翻页:户级 107 行、团期 109 行,canStartAllocation 全部为 false |
| 6 | 房务主管调「开始配房」 | 808091「房务组长为只读监督角色,无权执行该操作」 |
| 7 | 非房务角色调两个列表 | 808090「未登录或非房务角色,无权操作」 |
| 8 | 户级列表传 productType=GROUP |
HTTP 200,{"code":400,"message":"productType 只能是 CORE 或 CUSTOM"} |
| 9 | 团期订单不进户级列表 | 全量翻页户级 107 行,与团期的需求 ID、订单 ID 交集均为 0;阳性对照(已知户级行)在列 |
| 10 | 加急行排序 | 打标前第 1、2 页都没有加急行;把原在第 2 页第 10 行的样本标为加急后,它移到第 1 页第 1 行,第 2 页没有加急行(样本已还原) |
| 11 | stats 与列表同源 |
户级:不筛选 total=107,productType=CORE total=105,7 个状态分桶的 stats 与按该状态查询的 total 逐一相等。团期:不筛选 stats 为 45 / 64 / 109(pendingClaim / claimed / all),带关键字为 24 / 53 / 77,均与对应 total 相等 |
| 12 | scope=mine 与 status=pendingClaim 同传 |
code=200,空页 |
| 13 | 整团认领后的站内信 | 6 条 CLAIMED 记录的链接为 /housekeeper/orders?groupBatchId=<团期ID>,正文不含「抢单池」;用该 groupBatchId 查团期列表,total=1 |
| 14 | 5 个旧端点 | 均 code=200,响应结构不变;Swagger 中 deprecated=true |
| 15 | 菜单 | 普通房务 ×2、房务主管、超管共 4 个账号,当前菜单树里都没有菜单 101 / 102 |
| 16 | 户级列表 productNo |
抽 3 行,与库中产品编号一致 |
| 17 | 关联订单已软删的存量需求行 | 该行 orderNo / productName / productNo 为 null,列表 code=200 照常返回 |
本次未在测试服触发、只按代码契约给出的:808612 / 808613(看他人认领的团期看板);productNo 取数失败时的降级(Feign fallback 置 null)。
十、相关文档
- Issue: #8375
- PR:
- 涉及表结构: 无
- 数据库变更: user-service Flyway
V20260926_001(菜单下线 + 通知链接改向)
关联 / 联系人
链接
- Issue: #8375
- 合并提交: