From 3572fc7a0d69a2943b6fc13e46a23277617aca90 Mon Sep 17 00:00:00 2001 From: jw Date: Mon, 14 Sep 2026 20:03:34 +0800 Subject: [PATCH] =?UTF-8?q?docs(changelog):=20#7534=20=E6=88=90=E5=9B=A2?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=8E=A5=E9=80=9A=E9=80=9A=E7=9F=A5=E4=B8=AD?= =?UTF-8?q?=E5=BF=83=20+=20=E8=A1=A5=E5=8F=91=E7=AB=AF=E7=82=B9=20GB-ADM-0?= =?UTF-8?q?04N=EF=BC=88=E6=96=B0=E5=A2=9E=E6=8E=A5=E5=8F=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增补发端点 notify-formed;成团(含自动成团)后事务外投递 GROUP_BATCH_FORMED。 backend=deployed / gateway=verified(TEST 网关三组实测:补发成功 recipientCount=4 / 冷却 589593 {0} 渲染 / 成团契约 589537 未变)。错误码 589593/594/595(589592 被 #7533 占顺延)。 --- ...知接通通知中心与补发端点-新增接口-管理后台.md | 215 ++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 changelogs-v2/2026-09/14_7534_成团通知接通通知中心与补发端点-新增接口-管理后台.md diff --git a/changelogs-v2/2026-09/14_7534_成团通知接通通知中心与补发端点-新增接口-管理后台.md b/changelogs-v2/2026-09/14_7534_成团通知接通通知中心与补发端点-新增接口-管理后台.md new file mode 100644 index 00000000..ac6b1be2 --- /dev/null +++ b/changelogs-v2/2026-09/14_7534_成团通知接通通知中心与补发端点-新增接口-管理后台.md @@ -0,0 +1,215 @@ +--- +schema: "hl-changelog/v2" +ticket: "7534" +title: "成团通知接通通知中心 + 补发端点(GB-ADM-004N)" +consumer: "admin" +author: "jw(GIT)" +change_type: "新增接口" +backend_status: "deployed" +gateway_status: "verified" +frontend_status: "pending" +frontend_owner: "mmg" +frontend_ref: "" +target_release: "" +verified_at: "2026-09-14" +status_note: "新增补发成团通知端点 notify-formed;成团端点 group 契约一字未变,但成团成功后现在会真的给全部活跃子订单客户投递 GROUP_BATCH_FORMED 事件(此前不发任何通知)。前端需:①成团弹窗「通知客户」勾选框去掉或改纯说明(后端无对应入参,勾不勾都发);②团期详情/看板加「补发成团通知」按钮接 notify-formed。通知模板与占位符全在通知中心 notification_event_config 侧配置,文案定了不需再改 order-v3。eventCode 暂定 GROUP_BATCH_FORMED,最终取值待 jw/运营在通知中心确认;配置未建时 dispatcher 走 config 未找到分支、链路照通、零渠道触发(不阻塞)。零 DDL、零网关路由改动(/v3/admin/** 既有覆盖)。" +updated_at: "2026-09-14" +base: "dev-v3" +--- + +# order-v3: 成团通知接通通知中心 + 补发端点(GB-ADM-004N) + +**服务**: hl-order-service-v3 +**PR**: #7705 +**Issue**: #7534 + +--- + +## ⚠️ 关键变化 + +🟢 **新增一个补发端点 + 一处成团行为变更(成团端点契约零改动)**: + +1. **新增** `POST .../group-batch/:groupBatchId/notify-formed`:对**已成团**团期,向全部活跃子订单客户**补发**一次 `GROUP_BATCH_FORMED` 通知。无请求体、无查询参数。300s/团 冷却(Redis SETNX),冷却期内返 589593。 +2. **行为变更(契约不变)** `POST .../group-batch/:groupBatchId/group`:请求体 / 响应 / 错误码**一字未变**,但成团成功后**现在会真的给客户发通知**了——成团(含自动成团)后在**事务外**向全部活跃子订单客户投递 `GROUP_BATCH_FORMED`;投递失败只记 `log.error`,**接口响应与错误码不受影响**。 +3. **通道**:走 `MqNotificationEventProducer` 异步投递(afterCommit + producer 可空降级 + 异常只 log.error),**不**走同步 Feign。**一户一条**消息带 C 端 `userId`,`bizType=GROUP_BATCH`、`bizId=groupBatchId`、`extras` 含团期号 / 产品名 / 出发日期 / 成团时间 / orderId 供模板占位。 + +**无 DDL、无网关路由改动、成团端点结构一字未改。** + +## 一、背景 + +团期「成团」此前**不发任何客户通知**;且成团当下通知失败(MQ 不可用 / 模板未配 / 手机号缺)后运营**无任何补发手段**——既有团期动作端点只有成团 / 取消成团 / 流团 / 调名额 / 预支 / 退单 / 转订单七个,无通知相关端点。本单第 1 步:①成团后接通通知中心;②新增补发口。第 2 步(转订单同类缺口)另开单。事件码与短信 / 公众号模板由 jw / 运营在通知中心 `notification_event_config` 侧配置,order-v3 只负责把 `extras` 业务字段塞全。 + +## 二、变更接口清单 + +| # | 接口 | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|------|----------|------| +| 1 | 补发成团通知 | POST | `/v3/admin/order/group-batch/:groupBatchId/notify-formed` | 新增 | 对已成团团期向全部活跃子订单客户补发 GROUP_BATCH_FORMED;300s/团 冷却,冷却期返 589593;无收件人 589594;MQ/Redis 不可用 589595 | +| 2 | 成团 | POST | `/v3/admin/order/group-batch/:groupBatchId/group` | 行为变更(契约不变) | 请求体/响应/错误码一字未变;成团(含自动成团)成功后事务外投递 GROUP_BATCH_FORMED,失败只记日志不影响响应 | + +## 三、接口详情 + +### 1. 补发成团通知 `POST /v3/admin/order/group-batch/:groupBatchId/notify-formed` + +**VO**: `Result`(path: groupBatchId) + +#### 使用场景 + +团期管理台「团期详情 / 团期看板」的「补发成团通知」按钮。成团当下通知失败或客户没收到时,运营对**已成团**团期主动补发一次。沿用既有鉴权(`group-batch:manage`,与成团同权限)与网关路由(`/v3/admin/**` 已覆盖)。冷却 300s/团,防连点与「没收到再点一次」。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| groupBatchId | path | string(Long) | 是 | 雪花 ID | 团期主订单 ID | + +无请求体、无查询参数(`X-Admin-Id` 由网关注入,客户端传值忽略)。 + +#### 出参字段表 + +| 字段 | 类型 | 说明 | +|---|---|---| +| groupBatchId | string(Long) | 团期主订单 ID(字符串防精度丢失) | +| eventCode | string | 本次投递的事件码,如 `GROUP_BATCH_FORMED` | +| recipientCount | int | 本次投递的收件人数(= 活跃子订单户数) | +| enqueued | boolean | 是否成功入队(false 时接口已抛 589595,本字段恒 true,保留供排查) | +| notifiedAt | string(datetime) | 本次补发时间 | +| cooldownSeconds | int | 下次可补发前的冷却秒数(固定 300) | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2096412454643802114/notify-formed +Authorization: Bearer +``` + +#### 响应示例 + +```json +{ + "code": 200, + "msg": "成功", + "data": { + "groupBatchId": "2096412454643802114", + "eventCode": "GROUP_BATCH_FORMED", + "recipientCount": 6, + "enqueued": true, + "notifiedAt": "2026-09-14T18:00:00", + "cooldownSeconds": 300 + } +} +``` + +#### 空数据 / 降级响应 + +`notification_event_config` 未建 `GROUP_BATCH_FORMED` 行时,消息仍成功入队(本端点仍返 200 + recipientCount),dispatcher 侧走「config 未找到」分支、零渠道触发;客户手机号 / userId 缺失时 dispatcher 侧走「无接收人」日志降级,order-v3 不预校验。 + +#### 错误响应 + +```json +{ "code": 589593, "msg": "成团通知补发过于频繁,请 180 秒后再试", "data": null } +``` + +冷却期内重复补发 → **589593**(`{0}` 渲染为剩余秒数);团期无活跃子订单 → **589594**(并释放冷却键);MQ producer 不可用 / 投递失败 / Redis 不可用 → **589595**(并释放冷却键);团期不存在 → 589500;仍招募中或已流团(CANCELLED)→ 589552;无 `group-batch:manage` → 589507。 + +#### 业务边界 + +- 编排顺序严格:权限 → 存在性 → 状态门(∈ RESOURCE_PREPARING 及其后续已成团态;RECRUITING / CANCELLED 拒)→ 冷却 SETNX → 收件人 → 投递。 +- 冷却键 `order:gb:notify-formed:{groupBatchId}` 必设 TTL 300s;**投递阶段失败(589594/589595)主动删冷却键**——冷却是防轰炸不是惩罚失败,让运营可立刻重试。Redis 不可用时按 589595 处理(宁可拒绝,不在防轰炸失效时放行)。 +- 收件人 = 活跃(非 COMPLETED / CANCELLED)子订单户,一户一条消息带其 `userId`;`recipientCount` 为户数。 +- 全程无事务:只读 + Redis 写 + MQ 发,不写任何业务表;发送日志由通知中心 `notification_send_log` 记录(user-service 职责)。 + +### 2. 成团 `POST /v3/admin/order/group-batch/:groupBatchId/group` + +**VO**: `Result`(path: groupBatchId;body: `GroupBatchFormReqVO`,整体选填) + +#### 使用场景 + +团期成团弹窗。**本单不改契约**——请求体 `GroupBatchFormReqVO`(`formedNote` 选填)、响应 `Result`、错误码(589500/589501/589507/589537)全部不变。改的只是行为:成团成功后现在会给客户发成团通知。 + +#### 入参字段表 + +| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | +|---|---|---|---|---|---| +| groupBatchId | path | string(Long) | 是 | 雪花 ID | 团期主订单 ID | +| formedNote | body | string | 否 | `@Size(max=256)` | 提前成团理由(本单不动此字段) | + +#### 出参字段表 + +| 字段 | 类型 | 说明 | +|---|---|---| +| data | null | `Result`,成团成功 data 恒 null(契约不变) | + +#### 请求示例 + +```http +POST /v3/admin/order/group-batch/2096412454643802114/group +Authorization: Bearer +Content-Type: application/json + +{} +``` + +#### 响应示例 + +```json +{ "code": 200, "msg": "成功", "data": null } +``` + +#### 空数据 / 降级响应 + +成团后通知投递为**事务外**动作:无活跃子订单只 log.warn、MQ producer 不可用只 log.warn、单条投递异常只 log.error——**一律不冒泡**,接口响应恒为 `{"code":200,"data":null}`。 + +#### 错误响应 + +```json +{ "code": 589500, "msg": "团期不存在", "data": null } +``` + +错误码**一字未变**(589500 团期不存在 / 589501 / 589507 无权限 / 589537)。通知失败被吞,**不产生任何新错误码**。 + +#### 业务边界 + +- 成团原子事务由 `GroupBatchFormTxService#formAtomically` 开,返回即已提交;通知调用插在 `doGroup` 末尾(该方法第 3/4 步本就在事务外),故通知天然在事务外投递。 +- **自动成团**(达门槛定时任务)与手动成团共用 `doGroup`,同获通知行为。 +- 通知内部再走 afterCommit 注册 + 无活动事务立即执行 的双路兜底,将来若有人把 doGroup 折进事务语义仍正确。 + +## 四、契约约束与正确调用方式 + +- notify-formed 无请求体;`groupBatchId` 走路径。重复补发受 300s 冷却约束,前端应对 589593 展示「请 N 秒后再试」(N 从 message 取)。 +- 成团弹窗若有「通知客户」勾选框:后端无对应入参,勾不勾都发——请去掉或改为纯说明文案。 +- 金额无涉;`groupBatchId` 字符串回传防 JS 大整数精度丢失。 + +## 五、数据库行为 + +无 DDL、无迁移、无新表新列。冷却状态只在 Redis(带 TTL,不持久化)。通知发送记录由通知中心侧 `notification_send_log` 记录(user-service 职责,本单不改 user-service 一行)。 + +## 六、边界行为 + +- 逐户容错与通知顺序:成团状态已 CAS 提交、通知已发,个别户子订单推进失败——短信内容仍为真(团确已成团),逐户失败有日志且下一轮 job 重扫。 +- 历史脏数据:2026-09-11 前已成团团不自动补发(本单不做回溯),运营需要就点补发端点。 +- 300s 冷却跨实例:Redis 共享天然一致。 + +## 七、不影响范围 + +- 成团 / 取消成团 / 流团 / 调名额 / 预支 / 退单 / 转订单等既有端点结构与错误码零改动。 +- user-service 一行未改;通知中心 publish / dispatch 端点复用不改。 +- 无网关路由新增(`/v3/admin/**` 前缀既有覆盖)。 + +## 八、测试环境已验证 + +TEST 网关(`api.test.1814.love:9443`)实测,特性分支 `feat/7534-formed-notify`(HEAD `3fc5d7d6b`)已部署两实例(8086/8186): + +1. **补发端点成功**:`POST .../group-batch/2089713737135964161/notify-formed` → `{"code":200,"data":{"groupBatchId":"2089713737135964161","eventCode":"GROUP_BATCH_FORMED","recipientCount":4,"enqueued":true,"notifiedAt":"2026-09-14 19:59:11","cooldownSeconds":300}}`(4 活跃户逐户投递,`enqueued=true` 证 TEST RocketMQ 真实入队)。 +2. **冷却期内 589593**:同团 13 秒后再次调用 → `{"code":589593,"message":"成团通知补发过于频繁,请 287 秒后再试"}`(`{0}` 已渲染为剩余秒数 287,非字面 `{0}`)。 +3. **成团端点契约未变**:`POST .../group-batch/2089713737135964161/group`(已成团团)→ `{"code":589537,"message":"团期已成团,不可重复成团"}`(既有码、`Result` 信封一字未变)。 + +**AC-8 通知配置行**:TEST `hl_user_service.notification_event_config` 查无 `GROUP_BATCH_FORMED` 行——属 jw / 运营在通知中心管理后台的配置动作(eventCode 最终取值亦待 jw 确认);未建时 dispatcher 走「config 未找到」分支、链路照通、零渠道触发(口径第 5 条不阻塞代码)。上线前须先建该行否则等于没发。 + +## 十、相关文档 + +- 工单 #7534;本单为「成团通知」链路第 1 步,转订单同类缺口第 2 步另开单。 + +## 关联 / 联系人 + +- 后端 jw;前端 mmg(成团弹窗勾选框调整 + 团期详情/看板「补发成团通知」按钮)。 +- 通知中心配置(`notification_event_config` 建 `GROUP_BATCH_FORMED` 行 + 配模板 + ≥1 渠道 enabled):jw / 运营。