25 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 | 8320 | 调整订单:团期子订单未录大交通时提交用车需求须显式确认「不用接送机」(新错误码 587044) | admin | wx(GIT) | 修改接口 | deployed | verified | verified | mmg | f8c389c1a1230316163bac80079675fb3c1a26ad | v2.1 | 2026-09-24 | 已合 dev-v3(PR #8326,bc197bc07)并部署测试服,deploy-status.sh 回读 hl-order-service-v3=bc197bc07、BEHIND 0/N、STATE ok。网关实测五组全过:①无大交通不带声明提交团期单车辆需求 → 587044 且整笔零写入(order_main/需求/调整记录/状态日志前后快照逐项相等)②两方向声明 true + 同一份 vehicleRequirement → 200,order_main 两列置 1,snapshot 回显 transferDeclaration=true/true、transferTransportPresent=false/false ③该方向补大交通批次后声明不生效,车务读侧仍 required=true/READY<接客信息已齐> ④同一张单同一时刻:已声明不用且无批次的方向 required=false/NOT_REQUIRED/<无需送客>,未声明且无批次的方向 required=true/MISSING/<待补接客信息>(阴性对照)⑤接机有批次、送机无批次时提交非空 transferRequirement 未声明送机 → 587044<不用送机>且零写入;散客单同 payload 不带声明 → 200 正常落库(口径 4 成立)。定向单测 14 类 386 例全绿 + ArchUnit/错误码门禁绿。 | 2026-09-24 mmg 交付:调整订单车辆安排页新增「接送机确认」卡(仅团期子订单+该方向无大交通渲染不用接机/送机必选确认,有批次不渲染),snapshot 回显声明+基线已声明无批次锁定禁撤销,前置闸报文与 587044 逐字一致本地拦,提交整份回传 transferDeclaration 自动弃快捷写口走统一提交;FunItemAdjustModal spec 46 例全绿(新增 6 例) | 2026-09-24 | dev-v3 |
调整订单:团期子订单未录大交通时提交用车需求须显式确认「不用接送机」
服务: hl-order-service-v3 PR: #8326 | Issue: #8320 | 合并提交:
bc197bc07日期: 2026-09-24 影响范围: 管理后台「订单详情 → 调整订单 → 车辆安排」。仅团期子订单受影响,散客单行为完全不变。
⚠️ 关键变化
接送机那一槽多了一条硬闸,前端不做就会撞 587044 整笔提交失败。
- 团期子订单(下单时带
productBatchId的订单)在「车辆安排」页提交时,如果某个方向一条大交通批次都没有,该方向就必须在提交体里显式确认「不用接送机」(true),否则整笔被拒,返回 587044,一个字都不落库。有批次的方向不需要确认(沿用大交通,声明对它无效)。两个方向各自判定。 - 确认之后,车务侧那一格的文案会变:该方向由「待补接客信息 / 待补送客信息」变成「无需接客 / 无需送客」。不确认则维持「待补」——这是有意的,不要把「客人还没填大交通」读成「不用接送机」。
- 要接送机的路径没有变:需要接送机就必须先把大交通录进去(接送机用车需求的服务日只能从大交通航班日派生)。本次没有新增「需要但航班未定」这种第三态。
一、背景
「车辆安排」页的接送机用车槽,服务日由服务端从大交通批次派生。客人没录大交通时:
- 订单侧算出来的接送要求是「未知」,车务侧按「需要」处理,于是看板/配车页恒显示「待补接客信息 / 待补送客信息」;
- 而车务侧的接送机状态里本来就有「无需接客 / 无需送客」这一档,订单侧却没有任何入口能把它置上。
结果是「客人还没填大交通」与「这单就是不用接送机」在数据上完全一样,接送机缺口永远关不掉。本版增加一个订单级的显式声明来承载「就是不用」这个语义,并在提交侧设闸,逼定制师傅表态。
二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|---|---|---|---|---|
| 1 | 调整订单预填快照查询 | GET | /v3/admin/order/{id}/adjustment/snapshot |
修改接口 | 出参新增 transferDeclaration 与 transferTransportPresent |
| 2 | 调整订单统一提交 | POST | /v3/admin/order/{id}/adjustment/submit |
修改接口 | updates 新增 transferDeclaration;某方向无大交通未表态时返回新码 587044 |
读侧(车务看板 / 团期配车)路径与响应结构均未变,只有接送机那一档的取值会随声明变化,见「六.6、修改前后对比」。
三、接口详情
1. 调整订单预填快照查询 GET /v3/admin/order/{id}/adjustment/snapshot
VO: AdjustmentSnapshotRespVO(入参为 path 变量 + query,无独立 ReqVO)
使用场景
管理后台打开「调整订单」弹窗时调用一次,一次性拉取各子领域当前值用于回显。本次相关的是「车辆安排」页:需要知道(a)接送机不用声明的当前值,(b)两个方向是否已有大交通批次——后者决定前端要不要渲染「不用接送机」的必选确认。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| id | Path | Long | ✅ | 订单雪花 ID(字符串传输,别转 Number) | 订单 ID |
| scope | Query | String | ❌ | 逗号分隔:BASIC/PEOPLE/SCHEDULE/ITINERARY/HOTEL_REQ/VEHICLE_REQ;任一 token 非法返 587003 |
限定返回子领域;不传返全部。传了但不含 VEHICLE_REQ 时,本次两个新字段不返回 |
出参 Result<AdjustmentSnapshotRespVO>
本次新增字段(其余字段结构与取值规则一律不变):
| 字段 | 类型 | 说明 |
|---|---|---|
transferDeclaration.pickupNotRequired |
Boolean | 新增。接机方向是否已声明「本单不用接机」。未声明返回 false(不是 null) |
transferDeclaration.dropoffNotRequired |
Boolean | 新增。送机方向是否已声明「本单不用送机」。未声明返回 false |
transferTransportPresent.pickup |
Boolean | 新增。接机方向是否已存在大交通批次。true 时该方向不需要「不用接送机」确认,且声明对它不生效 |
transferTransportPresent.dropoff |
Boolean | 新增。送机方向是否已存在大交通批次 |
其余字段(vehicleRequirement / transferRequirement / vehicleTransportSummary / basic 等)结构与取值均未变。
请求示例
GET /v3/admin/order/2101219133700952066/adjustment/snapshot?scope=VEHICLE_REQ
响应示例
{
"code": 0,
"message": "success",
"data": {
"vehicleRequirement": { "...": "结构未变,略" },
"transferRequirement": null,
"vehicleTransportSummary": {
"hasPickupTime": false,
"displayText": null,
"emptyText": "暂无接送机时间",
"arrivals": [],
"departures": []
},
"transferDeclaration": { "pickupNotRequired": false, "dropoffNotRequired": false },
"transferTransportPresent": { "pickup": false, "dropoff": false }
},
"success": true
}
空数据 / 降级响应
- 订单没有大交通批次:
vehicleTransportSummary.hasPickupTime=false、emptyText="暂无接送机时间"、arrivals/departures均为[];transferTransportPresent两个方向都是false。这是正常态,不是降级。 - 订单从未表过态:
transferDeclaration两个字段都是false(表示「未声明」,不是「声明了需要」)。 - 老订单 / 存量数据:两列默认 0,读出来与「从未表态」完全一致,不会异常。
scope不含VEHICLE_REQ:本组三个字段(含本次两个)整体不返回。
错误响应
{ "code": 587003, "message": "调整范围取值非法", "data": null, "success": false }
业务边界
- 只读接口,无副作用;不因订单状态(已出行、已结算)而拒绝。
transferTransportPresent判的是「该方向有没有大交通批次」,不看批次的pickupRequired;与提交闸、车务读侧回落同一句判据。- 订单 ID 传错/不存在 → 既有 581007「订单不存在」,本次未改。
2. 调整订单统一提交 POST /v3/admin/order/{id}/adjustment/submit
VO: AdjustmentSubmitReqVO → AdjustmentSubmitRespVO
使用场景
「调整订单」弹窗内收集齐所有子领域改动后一次性提交;「车辆安排」页保存行程用车 / 接送机用车需求、以及本次新增的接送机不用声明,都走这一个入口。单事务原子应用:任一步失败整笔回滚。
入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---|---|---|
| id | Path | Long | ✅ | 订单雪花 ID | 订单 ID |
updates |
Body | Object | ✅ | 各子领域容器,不可全 null | 未改的子领域置 null |
updates.transferDeclaration |
Body | Object | ❌ | 本次新增 | 接送机不用声明,见下 |
updates.transferDeclaration.pickupNotRequired |
Body | Boolean | ❌ | true=本单不用接机;false=需要(或撤销声明) |
接机方向表态 |
updates.transferDeclaration.dropoffNotRequired |
Body | Boolean | ❌ | true=本单不用送机 |
送机方向表态 |
updates.vehicleRequirement |
Body | Object | ❌ | 结构未变(fleet 为空数组按「未提交」处理) |
行程用车需求 |
updates.transferRequirement |
Body | Object | ❌ | 结构未变;服务日由服务端派生 | 接送机用车需求 |
其余 updates.* |
Body | Object | ❌ | 全部未变 | 出行人 / 改期 / 行程 / 房需求 |
出参 Result<AdjustmentSubmitRespVO>
| 字段 | 类型 | 说明 |
|---|---|---|
success |
Boolean | 恒 true(失败走错误码) |
结构未变。
请求示例
无大交通、只提交行程用车、不带声明(会被拒,用于说明闸的位置):
{
"updates": {
"vehicleRequirement": {
"specialTags": [],
"remark": "按原方案",
"fleet": [ { "vehicleType": "SUV系列", "seats": 5, "count": 1 } ]
}
}
}
两个方向都确认「不用」:这是无大交通时唯一能被接受的形态
{
"updates": {
"vehicleRequirement": {
"specialTags": [],
"remark": "按原方案",
"fleet": [ { "vehicleType": "SUV系列", "seats": 5, "count": 1 } ]
},
"transferDeclaration": { "pickupNotRequired": true, "dropoffNotRequired": true }
}
}
只改声明、不动其他子领域(有效提交,不会被 587033 拦):
{ "updates": { "transferDeclaration": { "pickupNotRequired": true, "dropoffNotRequired": false } } }
响应示例
{ "code": 0, "message": "success", "data": { "success": true }, "success": true }
空数据 / 降级响应
updates.transferDeclaration传空对象{}(两个字段都 null)或整体不传:按「本次没对车辆子领域表态」处理,不触发 587044。- 散客单(无
productBatchId)传了transferDeclaration:不写入、不报错,静默忽略。 - 该方向已有大交通批次时传了声明:不写入、不报错,接送要求仍按批次
pickupRequired判。
错误响应
{ "code": 587044, "message": "本单未录入大交通,请先确认「不用接机」,或先在大交通模块录入行程后再提交", "data": null, "success": false }
(方向占位符取「接机」或「送机」,两个方向各自判定,只报先撞上的那一个。)
{ "code": 587033, "message": "未检测到有效变更,无需提交", "data": null, "success": false }
业务边界
- 只对团期子订单生效:散客单行为与本次之前逐字相同。
- 只在本次提交真的带了车辆子领域有效载荷时判定:非空
fleet、或transferDeclaration任一方向非 null。改房务、改行程、加出行人、改期这些提交不会被 587044 拦。 - 整笔零写入:587044 与其它守卫一样在任何 DB 写之前抛出,不存在「声明写了、需求没写」的半截状态。
- 覆盖写 + 值级 no-op:字段为 null 表示「本次不动这个方向」;两个方向的值与现值都相同时不写库、不产调整记录项。
- 两个方向独立:可以只声明接机不用、送机照旧(送机若已补录大交通则不受影响)。
- 幂等/并发:沿用本接口既有的订单级锁与「提交期间订单被改」守卫(587043),本次未改。
四、契约约束与正确调用方式
本节只写后端接受 / 拒绝 payload 的规则。
✅ 正确 / ❌ 错误 payload 对照
前提:订单是团期子订单,且两个方向都没有大交通批次。
| 场景 | payload | 结果 |
|---|---|---|
| ✅ 只提交行程用车 + 两个方向都确认不用 | {"updates":{"vehicleRequirement":{"fleet":[{"vehicleType":"SUV系列","seats":5,"count":1}]},"transferDeclaration":{"pickupNotRequired":true,"dropoffNotRequired":true}}} |
200 |
| ✅ 只提交声明(不动车辆) | {"updates":{"transferDeclaration":{"pickupNotRequired":true,"dropoffNotRequired":true}}} |
200 |
| ❌ 只提交行程用车、不带声明 | {"updates":{"vehicleRequirement":{"fleet":[...]}}} |
587044 |
| ❌ 只声明了一个方向(另一个方向无批次) | {"updates":{"vehicleRequirement":{"fleet":[...]},"transferDeclaration":{"pickupNotRequired":true,"dropoffNotRequired":null}}} |
587044(报「送机」) |
| ✅ 改房务 / 改行程 / 改期(完全不带车辆子领域字段) | {"updates":{"hotelRequirement":{...}}} |
200(不判 587044) |
| ⚠️ 混方向:接机有批次、送机没有 | {"updates":{"transferRequirement":{"fleet":[...]}}}(未声明送机) |
587044——即便接送机需求能派生出服务日也一样拦,防「带着没表过态的方向落库」 |
| ✅ 散客单不带声明 | {"updates":{"vehicleRequirement":{"fleet":[...]}}} |
200(散客单不判) |
| ✅ 该方向已有大交通批次 | 传或不传声明 | 200,声明不生效 |
切换状态时的必要动作
transferDeclaration是逐方向覆盖写:只传想动的方向,另一个方向传null或干脆不传(不要因为「表单里没这个控件」就传false,那会被当成「本方向需要接送机」,在无批次时被 587044 拒绝)。- 未进入 / 未编辑「车辆安排」页时,整个
transferDeclaration都不要回传(连空对象也建议不传)——只要出现true/false就视为对车辆子领域表态。 - 需要接送机时不要试图用声明绕过:接送机用车需求的服务日只能来自大交通,先录大交通。
- 判据只看本次请求体,不回看库里已存的声明:某方向无大交通时,本次提交必须带上该方向的表态。前端如果只回传「变化过的字段」(例如只带
transferRequirement),即使客人此前已勾过「不用接送机」也会被 587044 挡住。正确做法:车辆安排页每次提交都把transferDeclaration按当前控件状态整份回传。
五、数据库行为
涉及写操作:order_main 新增两列,语义为「该方向已显式声明不用接送机」。
前端提交 updates.transferDeclaration |
pickup_not_required 列 |
dropoff_not_required 列 |
|---|---|---|
{"pickupNotRequired":true,"dropoffNotRequired":true} |
1 |
1 |
{"pickupNotRequired":true,"dropoffNotRequired":null} |
1 |
保持原值(不动) |
{"pickupNotRequired":false,"dropoffNotRequired":false} |
0 |
0 |
| 不传 / 空对象 | 保持原值 | 保持原值 |
- 列类型
TINYINT(1) NOT NULL DEFAULT 0;存量数据不做任何回填,全部为 0(未声明)。 - 该方向已有大交通批次时即使传了
true也不写库(声明对该方向不生效)。 - 提交成功时同时写一条调整记录项(类型为车辆需求类,文案「接送机不用声明已更新」,带方向的中文前后值)。
六、边界行为
- 未登录 / 无权限 → 网关拦截(401/403),本次未改。
- 订单不存在 → 既有 581007。
- 订单已是终态 → 既有 587002「订单已是终态,不可调整」。
- 提交期间订单被并发改动 → 既有 587043,重新拉取后重试。
- 老前端(不认识这两个新字段、也不回传
transferDeclaration):团期子订单只要提交车辆子领域就会被 587044 拦住——这是有意的硬闸,前端必须同步上线。 - 老数据兼容:存量订单两列为 0,读侧与「从未表态」一致;车务侧该方向仍显示「待补」,不会被静默读成「无需接送」。
- 大交通批次
direction为空的历史行:与订单侧既有的方向切分口径一致(该行不归入任何方向)。
六.5、枚举 / 数据字典
接送机 readiness(车务读侧)
所属字段: 车务看板 / 配车页 readiness.statusCode(本次未改路径与结构,仅取值可能变化)
| 值 | 中文 | 说明 |
|---|---|---|
NOT_REQUIRED |
无需接客 / 无需送客 | 该方向有大交通批次且批次 pickupRequired=false,或该方向无批次但订单已声明「不用接送机」 |
MISSING |
待补接客信息 / 待补送客信息 | 该方向需要接送但信息不齐;无大交通且未声明也算这一档(fail-closed) |
PARTIAL |
接客/送客信息部分缺失 | 有多条批次,部分缺时刻或站点 |
READY |
接客/送客信息已齐 | 全部批次时刻与站点齐全 |
SOURCE_UNAVAILABLE |
订单信息暂不可用 | 订单上下文取数失败(降级态) |
六.6、修改前后对比
字段级对比
| 字段 | 改前 | 改后 |
|---|---|---|
snapshot 出参 transferDeclaration |
不存在 | {pickupNotRequired:Boolean, dropoffNotRequired:Boolean},未声明为 false |
snapshot 出参 transferTransportPresent |
不存在 | {pickup:Boolean, dropoff:Boolean} |
submit 入参 updates.transferDeclaration |
不存在 | 新增,两个方向可选 |
updates 其余字段 / 出参结构 |
- | 未变 |
行为级对比
| 行为 | 改前 | 改后 |
|---|---|---|
| 团期子订单无大交通、只提交行程用车 | 200,接送机不留任何结论 | 587044,整笔零写入 |
| 团期子订单无大交通、确认两个方向不用后提交 | 无此路径 | 200,订单落两列声明 |
| 车务侧某方向(无大交通) | 恒「待补接客信息 / 待补送客信息」 | 已声明 ⇒「无需接客 / 无需送客」;未声明仍「待补」 |
| 车务侧某方向(有大交通批次) | 按批次 pickupRequired 判 |
不变 |
| 散客单 | - | 完全不变 |
| 809002 / 809009 | 接送机用车需求的服务日与开关校验 | 触发条件均未改(但无大交通且未表态时,会先撞 587044) |
六.7、影响评估
- 是否破坏向后兼容: 否(纯新增字段;但行为上对团期子订单是硬闸——老前端提交车辆子领域会撞 587044)
- 前端是否必须同步上线: 是(团期子订单的「车辆安排」页必须按
transferTransportPresent渲染必选确认并回传transferDeclaration) - 前端 workaround 清理点: 无
六.8、已知约束(实测确认,非缺陷,但前端要知道)
- 声明的撤销只在「该方向已有大交通批次」时可达。该方向一条批次都没有时,把声明清回
false会被 587044 拒绝(实测:两方向都清false→ 587044「不用接机」;只清送机、接机留true→ 587044「不用送机」)。要改回「需要接送机」,先录该方向的大交通——这也是接送机服务能落地的必经步骤。 - 团期子订单的用车需求提交后是「待审核」,不即时进车务池:需由团期管理员执行提交车务动作后才会出现在车务看板。这不是本版引入的行为,但会影响「提交完立刻看车务看板」的验收动作。
- 大交通批次新增接口有 3 秒幂等窗口,同一订单连续两次新增会返回 100502「大交通批次新增处理中」,与本次改动无关。
七、不影响范围
- 仅影响: 管理后台「订单详情 → 调整订单 → 车辆安排」的团期子订单提交路径;以及车务侧接送机 readiness 的取值。
- 零影响:
- 散客单(无
productBatchId)的一切调整行为 - 「调整订单」的其余 tab(出行人 / 改期 / 行程 / 房需求)
- 接送机用车需求(TRANSFER)的服务日派生、提交开关、809002 / 809009 的触发条件
- 大交通模块自身的读写接口
- 行程单 / H5 / 小程序
- 网关路由(无新增,均在既有
/v3/admin/**通配下) - 历史数据(存量两列为 0,不迁移)
- 散客单(无
八、测试环境已验证
被测服务 hl-order-service-v3:dev-v3 @ bc197bc07,deploy-status.sh 回读 BEHIND 0/N、STATE ok。
被测服务部署:`hl-order-service-v3` = `dev-v3 @ bc197bc07`,`BEHIND 0/N`、`STATE ok`。
网关 `hl-gateway` 本次无路由改动;`hl-fleet-service` 现网版本虽落后若干提交,但落后的提交全是 order-v3 的、
未触及 fleet 代码,其接送就绪态判据与本次工作树逐字相同,故车务读口读数有效。
实测用**自建的团期子订单测试单**(客户备注带 `HLTEST[8320]` 标记,未碰任何真实订单):
```text
① 无大交通 + 不带 transferDeclaration 提交行程用车
POST /v3/admin/order/{orderId}/adjustment/submit → HTTP 200,code=587044
"本单未录入大交通,请先确认「不用接机」,或先在大交通模块录入行程后再提交" ✓
零写入核对(提交前后同一次 SQL 快照逐项相等):
order_main 两列仍为 0 / order_vehicle_requirement 无新版本 /
order_transport_plan 无变化 / order_adjustment_record 空 / order_status_log 计数不变 ✓
② 同一 payload + transferDeclaration={pickupNotRequired:true,dropoffNotRequired:true}
POST .../adjustment/submit → {"code":200,"data":{"success":true}} ✓
GET .../adjustment/snapshot?scope=VEHICLE_REQ
"transferDeclaration":{"pickupNotRequired":true,"dropoffNotRequired":true}
"transferTransportPresent":{"pickup":false,"dropoff":false} ✓
order_main: pickup_not_required=1 dropoff_not_required=1 ✓
order_adjustment_record: label="接送机不用声明已更新"
before="接机:需要接送,送机:需要接送" after="接机:不用接送,送机:不用接送" ✓
③ 给该方向补一条 ARRIVAL 大交通批次后再提交(仍带声明 true)
snapshot "transferTransportPresent":{"pickup":true,"dropoff":false} ✓
车务读侧 pickupSummary: required=true, statusCode=READY, "接客信息已齐" ✓(声明不覆盖批次)
④ 车务读侧阳性 + 阴性对照(同一张单、同一时刻,两个方向都没有批次)
pickupSummary : 未声明(0) → required=true, statusCode=MISSING, "待补接客信息" ✓
dropoffSummary : 已声明不用(1) → required=false, statusCode=NOT_REQUIRED, "无需送客" ✓
⑤ 混方向:接机有批次、送机无批次,提交非空 transferRequirement 且不声明送机
→ code=587044 "…请先确认「不用送机」…",整笔零写入 ✓
⑥ 散客单(productBatchId=null)不带声明提交同一份用车需求
→ {"code":200,"data":{"success":true}},正常落库;snapshot transferDeclaration={false,false} ✓
(车务读侧入口:管理端 GET /admin/fleet/board/orders——fleet 管理端路径没有 /v3 前缀;
/v3/internal/** 经网关直连返 403 属设计内,未作为证据。)
---
## 九、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| #8024 | #7443 | 调整订单车辆安排页同页提交行程用车 + 接送机用车两类需求 | ✅ 有效,本版在其上加闸 |
| #7439 | #7439 | 用车需求分家(TRAVEL / TRANSFER),接送机服务日由大交通派生 | ✅ 有效 |
| #8153 | #8153 | 声明了接送机却无 TRANSFER 需求行的户在确认预检里报出 | ✅ 有效 |
| **本 PR #8326** | **#8320** | 补「不需要接送机」这一侧的显式声明 + 提交闸 | ✅ 最新 |
---
## 十、相关文档
- 关联 Issue: [wx/HL#8320](https://git.1814.love/wx/HL/issues/8320)
- 关联 PR: [wx/HL#8326](https://git.1814.love/wx/HL/pulls/8326)
- 团期车务实施单: `HL-v3/docs/group/实施单/06-团期车务.html`(接送机 readiness 口径本次补了一句)
## 关联 / 联系人
### 链接
- **Issue**: [#8320](https://git.1814.love/wx/HL/issues/8320)
- **PR**: [#8326](https://git.1814.love/wx/HL/pulls/8326)
- **Merge commit**: [bc197bc07](https://git.1814.love/wx/HL/commit/bc197bc07)
### 联系人
- **后端负责人**: @wx