docs: 收款认领推送金蝶重构设计与业务流程文档、幂等变更SQL、集成语境术语
This commit is contained in:
+82
@@ -0,0 +1,82 @@
|
||||
# TMS(运输业务中台)—— 业财集成语境
|
||||
|
||||
TMS 与集团财务系统(金蝶星瀚)、合同合规系统(HCS)集成,单据在三个系统间流转。
|
||||
本表只收录集成语境下易混淆的业务术语,不含实现细节。
|
||||
|
||||
## Language
|
||||
|
||||
**合同合规系统(HCS)**:
|
||||
集团合同合规管控系统(桂物数字合同合规),接收 TMS 推送的项目、合同、履约与付款数据并做合规审批。
|
||||
_Avoid_: 桂物系统、合同系统、数字合同系统
|
||||
|
||||
**相对方**:
|
||||
HCS 对签约主体(甲乙方)的称谓,与 TMS 的"客商"同指一个外部单位。
|
||||
_Avoid_: 在 HCS 集成语境用"客户/供应商"
|
||||
|
||||
**来源单据键**:
|
||||
TMS 单据在 HCS 侧的对账主键(接口字段 `fd_kingdee_id`,字段名沿用金蝶),统一存 TMS 业务单据主键。
|
||||
_Avoid_: 外部ID、kingdeeId(泛指金蝶单据号时易混淆)
|
||||
|
||||
**来源标识**:
|
||||
TMS 推送给 HCS 时声明自身身份的常量(接口字段 `fd_sources`,约定值 "TMS")。
|
||||
_Avoid_: XH(那是星瀚侧的来源标识)
|
||||
|
||||
**履约规则**:
|
||||
合同维度的资金计划阶段(付款/收款、款项性质、计划金额、计划日期、开票规则),由 TMS 维护并同步到 HCS。
|
||||
_Avoid_: 履约计划(旧版已废弃接口的叫法)、付款计划
|
||||
|
||||
**履约阶段**:
|
||||
履约规则表中的一行;HCS 为其生成阶段ID,后续更新/删除必须凭该ID。
|
||||
_Avoid_: 阶段项、plan 行
|
||||
|
||||
**履约记录**:
|
||||
付款/收款执行事实在 HCS 的登记(一笔付款申请一条记录,随实际付款推进更新),与履约规则是"计划 vs 执行"的关系。
|
||||
_Avoid_: 履约流水
|
||||
|
||||
**额度校验**:
|
||||
付款提交时由 HCS 判定申请金额是否超出合同/项目剩余额度的同步检查;超额不阻断提交,转入特批链路。
|
||||
_Avoid_: 余额检查
|
||||
|
||||
**特批流程**:
|
||||
额度超额(或风险不通过)时在 HCS 发起的审批流程;TMS 持有其流程ID,流程结束由 HCS 经 B103 回传结果。
|
||||
_Avoid_: 特殊审批、绿色通道
|
||||
|
||||
**特批放行**:
|
||||
特批结果为"通过"后对**本次**付款申请解除推送拦截的动作;只改特批状态,不触发推送,单次有效。
|
||||
_Avoid_: 特批通过自动付款、放行推送
|
||||
|
||||
**锁单(B901)**:
|
||||
金蝶确认接收 TMS 推送的单据后,经 B901 通知 TMS 将本地源单据置为不可编辑、不可作废、不可重推的状态;金蝶反审核及删除后经 B901 解锁。
|
||||
_Avoid_: 冻结、金蝶锁定(那是金蝶侧单据自己的状态)
|
||||
|
||||
**解锁**:
|
||||
B901 通知金蝶侧单据已反审核及删除后,TMS 解除锁单、同步状态置失败、清金蝶单号留痕;不自动重推,人工核实后重新推送。
|
||||
_Avoid_: 反审核(那是金蝶侧的动作)、自动重推
|
||||
|
||||
**合规附件ID**:
|
||||
TMS 附件先上传 HCS 附件服务换取的 fdId;同一附件以 TMS 附件元数据为键缓存映射,不重复上传。
|
||||
_Avoid_: 附件fdId(指代不明)
|
||||
|
||||
**同步状态**:
|
||||
TMS 单据对 HCS 的推送生命周期(待同步/已同步/失败),权威状态在 TMS 侧字段,HCS 不回写业务状态。
|
||||
_Avoid_: 推送标志
|
||||
|
||||
**二次认领**:
|
||||
金蝶司库完成第一轮自动认领(客户维度)后,TMS 把收款流水认领到合同/结算单维度的动作;只在 TMS 本地登记,本身不产生金蝶收款单。
|
||||
_Avoid_: 收款认领(泛指整条链路时易与金蝶第一轮自动认领混淆)
|
||||
|
||||
**公告未认领金额**:
|
||||
金蝶认领公告(A301-2)上尚未被认领的金额(字段 unclaimamount),是 TMS 二次认领的上限和"认领完成"的判定基准;以金蝶侧为准,推送前须重查最新值。
|
||||
_Avoid_: 剩余可认领金额(那是本地展示口径)、未认领金额(不指明公告侧/本地侧时指代不明)
|
||||
|
||||
**认领完成**:
|
||||
一条收款流水的累计有效认领金额等于公告未认领金额的状态;只有认领完成的流水才满足推送金蝶的条件,不认领完就不推。
|
||||
_Avoid_: 认领完毕、全部认领(未指明对照基准)
|
||||
|
||||
**认领状态**:
|
||||
收款流水本地认领进度(未认领/部分认领/认领完成),对照公告未认领金额计算;作废的认领分摊不计入累计。
|
||||
_Avoid_: 与推送状态混用
|
||||
|
||||
**推送状态**:
|
||||
收款流水对金蝶 A301-3 的推送生命周期(未推送/已推送/推送失败),权威在流水级,认领主单仅冗余展示;已推送的流水不可二次推送。
|
||||
_Avoid_: 金蝶状态(那是 A301-1 回写的单据生命周期:已推送/审核通过/已收款)
|
||||
@@ -0,0 +1,257 @@
|
||||
# 收款认领推送金蝶重构设计(认领本地化 → A301-3 定时 + 手动推送 → 按流水归集)
|
||||
|
||||
> 适用系统:TMS(blade-transport)
|
||||
> 对接系统:金蝶云·星瀚(BFI,经 iPaaS 网关直连)
|
||||
> 覆盖接口:A301-2 收款认领公告查询(不变)、A301-3 收款认领结果推送(**触发时机重构**)、A301-1 收款单查询回写(**轮询对象改造**)
|
||||
> 前置文档:`2026-09-24-收款认领金蝶全链路业务流程(A301-2公告同步-A301-3认领推送-A301-1收款单回写).md`(下称「旧文档」,描述的是重构前现状)
|
||||
> 最后更新:2026-09-28(设计稿,未实施)
|
||||
|
||||
---
|
||||
|
||||
## 1. 为什么要重构
|
||||
|
||||
旧文档描述的现状(对应代码 `ReceiptFlowServiceImpl.claim()` L353):**每次认领落库后立即在事务内推送 A301-3**。带来三个问题:
|
||||
|
||||
1. **部分认领立即推**:一笔流水分两次认领(40 万 + 60 万),金蝶侧生成两张收款单,司库对账时一笔到账裂成多单。
|
||||
2. **来源编码撞码**:`awrp_src_code` 用结算单号拼接,两次认领若关联同一批结算单,编码重复,A301-1 回写按 `sourcebillnumber` 匹配存在歧义(旧文档 §4.1 幂等说明已指出)。
|
||||
3. **金额口径混乱**:本地认领上限按 `receipt_amount`(收款金额)控制,而金蝶公告侧有第一轮自动认领后的 `unclaimed_amount`(未认领金额),两个口径互不参照,可能出现本地认领金额与金蝶侧待认领金额对不上的脏数据。
|
||||
|
||||
## 2. 新设计原则(对旧文档原则的修订)
|
||||
|
||||
| # | 旧原则(旧文档 §1) | 新原则 |
|
||||
| --- | --- | --- |
|
||||
| 1 | 公告为准(A301-2 落库流水) | **不变** |
|
||||
| 2 | 推送先于结果(认领与推送同事务,失败整体回滚) | **废弃**。改为:**认领本地先行,推送异步解耦**——认领动作只落本地库,永不直接调金蝶;推送由定时任务 + 前端手动按钮承担 |
|
||||
| 3 | 认领公告 id 必填 | **不变**,并扩展:`unclaimed_amount` 同样必填,缺失拦截 |
|
||||
| 4 | 以金蝶侧实际生成为准 | **不变**,扩展为:**推送前实时对账**——推送前重查 A301-2 拿最新 `unclaimed_amount`,校验通过才推 |
|
||||
| 5 | 异常回收人工处置(作废不推金蝶) | **不变**,并强化:**已推送流水禁止二次推送**,作废后的金蝶侧冲销一律人工处置 |
|
||||
|
||||
新增两条核心规则(本次重构的业务闸门):
|
||||
|
||||
- **认领完成 = 累计有效认领金额 == 公告未认领金额**(`unclaimed_amount`,即 A301-2 的 `unclaimamount`;作废分摊不计入累计)。只有认领完成的流水才满足推送条件——**不认领完就不推**。
|
||||
- **推送单元 = 收款流水**:一条流水只产生一张金蝶收款单,分录取该流水下全部有效分摊行(可能跨多次认领主单),`awrp_src_code` 按流水生成、重试复用。
|
||||
|
||||
## 3. 领域模型与职责划分
|
||||
|
||||
### 3.1 三张表的分工
|
||||
|
||||
```
|
||||
blade_kingdee_receipt_flow(收款流水) ← 推送的权威载体
|
||||
认领状态 claim_status / 累计认领 claimed_amount(展示缓存)
|
||||
公告侧 unclaimed_amount / bill_id / fee ...
|
||||
推送状态 push_status / 推送失败原因 push_fail_reason / 推送时间 pushed_time
|
||||
推送编码 awrp_src_code / 金蝶收款单号 kingdee_bill_no / 回写状态 kingdee_bill_status
|
||||
|
||||
blade_receipt_claim(认领主单) ← 认领动作的留痕
|
||||
认领人/部门/日期/附件/备注、claim_amount(本次认领金额)
|
||||
kingdee_bill_no / kingdee_bill_status 仅作冗余展示(由流水级联刷新)
|
||||
【去掉】awrp_src_code(移至流水表)
|
||||
|
||||
blade_receipt_claim_settlement(分摊行) ← 累计认领的权威来源
|
||||
累计认领 = Σ(status=1 行的 allocated_receipt_amount) ← 作废行 status=0,天然不计入
|
||||
```
|
||||
|
||||
**权威口径**:累计认领永远以分摊表实时聚合为准(`flowClaimedAmount()`,现有实现),流水上的 `claimed_amount` 只是展示缓存,在认领/作废/同步/推送前校验四个时机重算维护。
|
||||
|
||||
### 3.2 流水新增字段
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `push_status` | varchar(20) | 推送状态:`none` 未推送(默认)/ `pushed` 已推送 / `failed` 推送失败 |
|
||||
| `push_fail_reason` | varchar(1000) | 最近一次推送失败原因(成功后清空) |
|
||||
| `pushed_time` | datetime | 首次推送成功时间 |
|
||||
| `awrp_src_code` | varchar(64) | 推送来源编码 `SKCL+yyyyMMddHHmmss+流水id尾号6位`;**首次推送尝试时生成并落库,重试复用同一编码**(依赖金蝶候选键 `awrp_src_sys+awrp_src_code` 幂等,防重试双单) |
|
||||
|
||||
认领状态 `claim_status` **口径变更**(字段沿用,含义改):
|
||||
|
||||
```
|
||||
unclaimed 累计有效认领 = 0
|
||||
partial 0 < 累计有效认领 < unclaimed_amount
|
||||
claimed 累计有效认领 == unclaimed_amount(且 > 0) ← 「认领完成」,唯一可推送状态
|
||||
```
|
||||
|
||||
不再与 `receipt_amount` 比较。前端「剩余可认领」= `unclaimed_amount − 累计有效认领`。
|
||||
|
||||
`kingdee_bill_status`(回写生命周期)从认领主单上移到流水:`none → pushed →(A301-1 回写)approved / received / failed`;认领主单保留同名冗余字段仅作展示。
|
||||
|
||||
### 3.3 状态机
|
||||
|
||||
```
|
||||
流水推送状态:
|
||||
none ──推送成功──▶ pushed ──A301-1 回写──▶ approved ──▶ received(终态)
|
||||
│ │ └──(A/B/退单)──▶ failed(回写失败)
|
||||
└──推送失败──▶ failed ──重试(同码)──▶ pushed / 维持 failed
|
||||
※ pushed 为终态闸门:任何路径不允许二次推送(作废→重认领→再满足等式也不推)
|
||||
|
||||
流水认领状态(对照 unclaimed_amount,随认领/作废/同步刷新重算):
|
||||
unclaimed ⇄ partial ⇄ claimed
|
||||
```
|
||||
|
||||
## 4. 流程编排
|
||||
|
||||
### 4.1 认领(POST /receipt-flow/claim,纯本地化)
|
||||
|
||||
改造 `ReceiptFlowServiceImpl.claim()`:
|
||||
|
||||
1. 锁流水后校验:`bill_id` 非空(沿用)+ **`unclaimed_amount` 非空**(缺失拦截「公告未认领金额缺失,请重新同步金蝶收款流水」)。
|
||||
2. 结算单侧校验全部不变(审批通过/应收类型/未作废/同项目组织收付款方/单张结算单累计 ≤ 结算金额)。
|
||||
3. **流水维度上限改为公告口径**:`累计有效认领 + 本次分摊 ≤ unclaimed_amount`(原为 ≤ receipt_amount),报错文案「累计认领金额不能超过公告未认领金额」。
|
||||
4. 本地落库:认领主单(`kingdee_bill_status=none`)+ 分摊行 + 刷新结算单收款汇总 + 更新流水 `claimed_amount/claim_status`(按 3.2 新口径)+ 认领留痕。
|
||||
5. **删除 `pushClaimResultToKingdee(...)` 调用**(L353)——认领事务到此结束,不产生任何 BFI 调用。
|
||||
|
||||
### 4.2 推送(统一入口,定时任务与手动按钮共用)
|
||||
|
||||
新服务方法 `pushClaimToKingdee(Long flowId)`,**方法级事务,推送异常在事务内消化(不外抛),以返回值向调用方报告成败与原因**——保证失败路径的状态落库不被回滚:
|
||||
|
||||
```
|
||||
① FOR UPDATE 锁流水
|
||||
② 静态闸门(硬校验,不满足直接返回失败):
|
||||
- bill_id 非空
|
||||
- push_status != pushed ←「已推送禁止二次推送」终态闸门
|
||||
- 累计有效认领(分摊表实时聚合)> 0 且 == unclaimed_amount(compareTo==0,严格相等)
|
||||
③ 实时对账:重查 A301-2 拿最新公告
|
||||
- 手动按钮:claimusers = 当前登录用户真实姓名
|
||||
- 定时任务:按候选流水的认领人姓名(认领主单 claimer_name 去重)逐人查询,§4.3
|
||||
- 按 bill_id 匹配本流水 → 刷新 unclaimed_amount / kingdee_claim_status / claim_me
|
||||
- 公告查不到 → 失败:「金蝶公告不存在或已不在认领范围,请重新同步」
|
||||
- 重验:累计有效认领 == 最新 unclaimed_amount,不等 → 失败并提示两侧金额差额
|
||||
(不等说明金蝶侧有人认领过或金额有变,需人工核对后作废/补认领)
|
||||
④ awrp_src_code:已有则复用;无则生成并落库(SKCL+时间戳+流水id尾号6位)
|
||||
⑤ 组装 A301-3:billid=流水.bill_id,entries = 该流水全部有效分摊行
|
||||
(分摊行 join 结算单,按结算单 id 升序;金额=allocated_receipt_amount;
|
||||
结算单有 kingdee_bill_no 时携带 e_corebillno,沿用现有取数)
|
||||
⑥ 调 pushClaimResult:
|
||||
成功 → push_status=pushed、push_fail_reason 清空、pushed_time=now、
|
||||
kingdee_bill_no=响应 number、kingdee_bill_status=pushed;
|
||||
级联刷新该流水名下全部未作废认领主单的 kingdee_bill_no/kingdee_bill_status
|
||||
失败 → push_status=failed、push_fail_reason=金蝶错误文本汇总(认领数据不回滚)
|
||||
⑦ 推送动作留痕(blade_receipt_flow_record,operation=push)
|
||||
```
|
||||
|
||||
**事务边界说明**:BFI HTTP 调用在事务内,流水行锁覆盖整个推送过程——天然防「定时任务与手动按钮并发双推」(后到者会看到 `push_status=pushed` 或等锁后走静态闸门被拦)。锁粒度为单流水行锁,持锁时长为一次接口调用,可接受。
|
||||
|
||||
### 4.3 定时任务 ReceiptClaimPushTask
|
||||
|
||||
沿用 `PaymentKingdeeResultTask` 编排模式(task 类只做开关与调度,逻辑收敛在服务方法,返回 summary):
|
||||
|
||||
```java
|
||||
@Value("${thirdParty.bfi.receiptClaimPush.syncEnabled:false}") // 默认关闭,联调稳定后开启
|
||||
@Scheduled(cron = "${thirdParty.bfi.receiptClaimPush.cron:0 */10 * * * ?}")
|
||||
```
|
||||
|
||||
扫描对象:`bill_id` 非空 AND `push_status IN (none, failed)` AND `claim_status = claimed`(缓存口径预筛缩小集合)。
|
||||
|
||||
**A301-2 重查的认领人问题**:A301-2 的 `claimusers` 必填且为单个用户姓名(`BfiClaimAnnounceQueryDTO` L50-52),定时任务没有登录用户上下文。处理:
|
||||
|
||||
1. 取候选流水的有效认领主单 `claimer_name` 去重集合;
|
||||
2. 逐人调 `BfiUtil.queryAllPages(queryClaimAnnounce)`(时间窗沿用 `thirdParty.bfi.claimAnnounce.months`,默认 6 个月);
|
||||
3. 按公告 `id == 流水.bill_id` 匹配刷新,再走 §4.2 ③-⑦;
|
||||
4. 单流水推送失败 try/catch 独立消化,不影响同批其他流水。
|
||||
|
||||
> 联调确认项:`claimusers` 若支持逗号分隔多人,可合并为一次查询(见 §8)。
|
||||
|
||||
### 4.4 手动推送按钮(收款流水页)
|
||||
|
||||
- 行按钮「推送金蝶」:`POST /receipt-flow/push-kingdee`(body: flowId),按钮权限 `receipt_flow_push`。
|
||||
- 前端可用条件(展示层控制,后端硬校验为准):`claim_status=claimed` 且 `push_status != pushed` 且 `bill_id` 非空。
|
||||
- 后端走 §4.2 同一入口,用当前用户姓名重查公告;若当前用户不在公告认领范围内(查不到),提示「当前用户不在该公告认领范围内,请由认领人操作或重新同步后重试」。
|
||||
- 列表新增「推送状态」「推送失败原因」列;详情弹窗展示推送留痕。
|
||||
- 本期不做批量推送按钮(定时任务已覆盖批量场景)。
|
||||
|
||||
### 4.5 A301-1 回写改造(POST /receipt-claim-record/query-kingdee-result)
|
||||
|
||||
`ReceiptClaimRecordServiceImpl.refreshKingdeeResult()` 轮询对象由认领主单改为**流水**:
|
||||
|
||||
- 扫描:`push_status = pushed` 且 `kingdee_bill_status IN (pushed, approved)` 的流水;
|
||||
- 匹配:金蝶收款单 `sourcebillnumber == 流水.awrp_src_code`(一流水一码,无歧义);
|
||||
- 回写:`flow.kingdee_bill_no / kingdee_bill_status`(状态映射不变:A/B→pushed、C→approved、D→received、其他→failed),并级联刷新名下未作废认领主单的冗余字段;
|
||||
- 定时接入复用现有任务风格(`thirdParty.bfi.receiptClaimResult.*`,本期仍可手动触发)。
|
||||
|
||||
### 4.6 作废(不变 + 两点明确)
|
||||
|
||||
`voidClaim()` 现有逻辑保留:
|
||||
|
||||
1. **累计认领不考虑作废**:作废行 `status=0`,分摊聚合天然排除——与「累计认领不考虑作废的」要求一致,无需改代码;作废后重算流水 `claimed_amount/claim_status`(口径按 §3.2)。
|
||||
2. **作废永不触发推送**:未推送的认领作废 → 纯本地;已推送流水的认领作废 → 本地 KDCX 冲单号 + 金蝶人工处置(沿用旧文档原则 5)。作废后即使重认领使等式再次满足,`push_status=pushed` 的终态闸门也阻止二次推送。
|
||||
|
||||
### 4.7 重新同步(A301-2 sync 补一处)
|
||||
|
||||
同步 upsert 刷新 `unclaimed_amount` 后,**对值发生变化的流水重算 `claim_status`**(对照分摊聚合),保证公告漂移后认领状态不失真。
|
||||
|
||||
## 5. 边界场景与防重汇总
|
||||
|
||||
| 场景 | 行为 |
|
||||
| --- | --- |
|
||||
| 定时任务与手动按钮并发推同一流水 | 流水行锁串行化 + `push_status != pushed` 静态闸门,不会双推 |
|
||||
| 推送超时但金蝶实际已生成收款单 | 本地记 failed;重试复用同一 `awrp_src_code`,金蝶候选键幂等,不产生重复收款单 |
|
||||
| 推送成功后作废一笔认领、再补认领到等式满足 | 终态闸门拦截,不二次推送;金蝶侧冲销人工处置 |
|
||||
| 公告侧 unclaimed_amount 变小(他人在金蝶认领) | 推送前实时对账发现差额 → 拦截并提示差额,人工作废多余本地认领后重推 |
|
||||
| 公告侧 unclaimed_amount 变大 | 用户补认领到等式满足后推送(认领上限随新值放开) |
|
||||
| unclaimamount = 0 的公告 | 认领上限为 0,不可认领;累计认领 > 0 的推送前置条件天然排除空推 |
|
||||
| 手动推送者不在公告认领范围 | A301-2 按其姓名查不到公告 → 拦截提示,改由认领人操作 |
|
||||
|
||||
防重键沿用旧文档 §6.3,变更点:`awrp_src_code` 由「认领主单、结算单号拼接」改为「流水、按流水生成、重试复用」,A301-1 匹配键随之移到流水上。
|
||||
|
||||
## 6. 前端改动汇总(tms-erp-web)
|
||||
|
||||
| 页面 | 改动 |
|
||||
| --- | --- |
|
||||
| `receipt-flow.vue` | ① 认领按钮可用条件:`剩余可认领 = unclaimed_amount − 累计认领 > 0`(原按 receipt_amount);② 新增「推送金蝶」行按钮(条件 §4.4);③ 列表加「推送状态/推送失败原因」列;④ 详情展示推送留痕 |
|
||||
| `receipt-flow-form.vue` | 分摊上限与提示文案改为公告未认领金额口径 |
|
||||
| `receipt-claim-record.vue` | 不变(金蝶状态列继续展示冗余字段;「查询金蝶认领结果」按钮保留) |
|
||||
| `api/payment/receiptFlow.js` | 新增 `pushKingdee` |
|
||||
|
||||
## 7. SQL 变更
|
||||
|
||||
新增幂等脚本 `doc/sql/transport/blade_receipt_flow_push_20260928.sql`,沿用仓库惯例(`information_schema` 探测 + `PREPARE/EXECUTE` 动态 DDL),**支持重复执行**:0924 脚本执行过与否均可跑,任意顺序、任意次数,已存在的列/索引自动跳过、已不存在的列/索引自动跳过删除。
|
||||
|
||||
| # | 对象 | 变更 | 说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| 1-6 | `blade_kingdee_receipt_flow` | ADD COLUMN `push_status`(默认 none)、`push_fail_reason`、`pushed_time`、`awrp_src_code`、`kingdee_bill_no`、`kingdee_bill_status`(默认 none) | 推送域字段上收至流水 |
|
||||
| 7-8 | `blade_receipt_claim` | DROP KEY `idx_receipt_claim_src_code`、DROP COLUMN `awrp_src_code` | 推送编码上移至流水;0924 未执行过则本就无此列,探测后自动跳过 |
|
||||
| 9-10 | `blade_kingdee_receipt_flow` | ADD KEY `idx_kingdee_receipt_flow_push_scan` (tenant_id, push_status, claim_status)、`idx_kingdee_receipt_flow_src_code` (tenant_id, awrp_src_code) | 定时任务扫描 + A301-1 回写匹配 |
|
||||
| 11 | `blade_menu` | INSERT 按钮权限 `receipt_flow_push`(父级 2090000000000001260 收款流水,id 2090000000000001264,ON DUPLICATE 幂等) | 手动推送按钮 |
|
||||
|
||||
0924 脚本(`blade_receipt_flow_claim_20260924.sql`)保持原样不动,两个脚本无执行顺序依赖。上线顺序:先执行 0924(若未执行)→ 执行 0928 → 启动服务。
|
||||
|
||||
## 8. 待联调确认项
|
||||
|
||||
| # | 事项 |
|
||||
| --- | --- |
|
||||
| 1 | `claimusers` 是否支持逗号分隔多人(支持则定时任务合并为一次 A301-2 查询) |
|
||||
| 2 | A301-3 字段沿用旧文档 §7 待确认清单(recpaytype_number / paymenttype / recpayer / e_corebilltype / e_corebillno) |
|
||||
| 3 | `unclaimamount` 是否已扣手续费(fee)口径——本方案等式直接对照 `unclaimamount` 本身,无论是否含费均自洽,但需确认推送后金蝶侧 `unclaimamount` 归零的时效,用于判断重查窗口 |
|
||||
| 4 | 同一公告在金蝶侧被人工认领部分金额后,A301-2 返回的 `unclaimamount` 更新时效(影响实时对账的准确性预期) |
|
||||
|
||||
## 9. 与旧文档的差异对照
|
||||
|
||||
| 环节 | 旧(2026-09-24) | 新(本设计) |
|
||||
| --- | --- | --- |
|
||||
| 认领事务 | 落库后同事务立即推 A301-3,失败整体回滚 | 纯本地落库,不调 BFI |
|
||||
| 推送触发 | 每次认领动作 | 定时任务(`receiptClaimPush.*` 开关)+ 手动按钮,双入口同一服务方法 |
|
||||
| 推送条件 | 无(认领即推) | 累计有效认领 == 公告未认领金额(推送前重查 A301-2 实时对账) |
|
||||
| 推送粒度 | 每次认领一张金蝶收款单 | 一条流水一张金蝶收款单(分摊行归集) |
|
||||
| awrp_src_code | 认领主单上,结算单号拼接(可撞码) | 流水上,SKCL+时间戳+流水尾号,重试复用 |
|
||||
| 认领上限/认领完成口径 | receipt_amount | unclaimed_amount |
|
||||
| 推送状态/失败原因 | 无(失败即回滚无痕) | 流水上 push_status / push_fail_reason / pushed_time,失败可重试可追溯 |
|
||||
| A301-1 轮询对象 | 认领主单 | 流水(级联刷新认领主单冗余字段) |
|
||||
| 二次推送 | 可能(作废重认领再推) | 禁止(终态闸门) |
|
||||
|
||||
## 10. 代码改动索引(已实施,2026-09-28)
|
||||
|
||||
| 环节 | 位置 | 改动 |
|
||||
| --- | --- | --- |
|
||||
| 认领 | `ReceiptFlowServiceImpl.claim()` | 上限口径改公告未认领金额(缺失/为0拦截);删除同步推送调用,事务内只落本地 |
|
||||
| 推送 | `IReceiptFlowService.pushClaimToKingdee(flowId)` / `pushClaimByTask()` | 新增。共用 `pushClaimLocked`(`TransactionTemplate` 编程式事务,流水行锁覆盖闸门→对账→推送→落库,防并发双推);失败不抛异常跨事务边界,以 `ReceiptClaimPushResult` 返回 |
|
||||
| 定时任务 | `task/ReceiptClaimPushTask.java`(新增) | Nacos 开关 `thirdParty.bfi.receiptClaimPush.syncEnabled/cron`(默认关闭、每10分钟);候选=认领完成且 push_status ∈ (none, failed),按认领人姓名去重逐人重查 A301-2 |
|
||||
| 推送报文 | `buildClaimPushDTO` | billid=流水.bill_id;分录=该流水全部有效分摊行(结算单升序,seq 1起);e_corebillno=结算单金蝶应收单号;awrp_src_code 按流水生成(SKCL+时间戳+尾号6位)、重试复用 |
|
||||
| 手动接口 | `ReceiptFlowController.pushKingdee`(`POST /receipt-flow/push-kingdee`) | 成功返回金蝶收款单号,失败 R.fail(原因);按钮权限 `receipt_flow_push` |
|
||||
| 回写 | `ReceiptClaimRecordServiceImpl.refreshKingdeeResult()` | 轮询对象改流水(push_status=pushed 且回写状态 pushed/approved),按流水 awrp_src_code 匹配,级联刷新认领主单冗余字段 |
|
||||
| 作废 | `ReceiptClaimRecordServiceImpl.voidClaim()` | claim_status 重算口径改对照公告未认领金额(其余不变,作废不触发推送) |
|
||||
| 同步 | `ReceiptFlowServiceImpl.sync()` + 共享 `queryClaimAnnounces` | unclaimed_amount 刷新后按新口径重算 claim_status;公告查询方法供 sync/手动推送/定时任务共用 |
|
||||
| 常量 | `KingdeeBfiConstant` | 新增 RECEIPT_CLAIM_PUSH_NONE/PUSHED/FAILED、RECEIPT_CLAIM_BILL_NONE |
|
||||
| 实体/VO | `KingdeeReceiptFlow`(推送域6字段)、`ReceiptClaim`(删 awrpSrcCode)、`ReceiptClaimMapper.xml`(删列)、`ReceiptFlowVO/Wrapper`(pushStatusName/kingdeeBillStatusName、剩余可认领改公告口径)、`ReceiptClaimPushResult`(新增 DTO) | — |
|
||||
| 详情留痕 | `ReceiptFlowServiceImpl.detail()` | claimRecords 含 claim + push 两类动作记录 |
|
||||
| 批量化 | `FormalSettlementServiceImpl.refreshPaymentSummaries(Collection<Long>)`(新增)+ `calculatePaymentSummary` 拆纯计算重载 | 固定数次批量查询完成 N 张结算单收款汇总重算(关系/付款申请/申请状态/预收来源/认领分摊各一次 IN 查询 + updateBatchById);单笔 `refreshPaymentSummary` 与 `refreshPaymentSummariesForPreSettlement` 复用同一口径 |
|
||||
| 批量化 | `claim()` / `voidClaim()` / `settlementCandidates()` / `sync()` | ① 结算单锁行改一次 `IN ... ORDER BY id FOR UPDATE`(与逐单加锁顺序一致防死锁);② 结算单累计认领额一次聚合查询(候选单列表页原先每页最多 200 次查询);③ 作废分摊行改单条 UPDATE(实体携带 status 保留审计字段填充);④ 同步留痕改 `Db.saveBatch` 批量插入 |
|
||||
| 前端 | `receipt-flow.vue`(推送金蝶按钮+canPush、推送状态/失败原因/金蝶单号/金蝶状态列、详情推送字段)、`receipt-flow-form.vue`(剩余可认领金额字段、上限口径)、`receipt-flow-batch-form.vue`(批量口径)、`option/payment/receiptFlow.js`(新列)、`api/payment/receiptFlow.js`(pushKingdee) | — |
|
||||
@@ -0,0 +1,112 @@
|
||||
# 收款认领流程(业务版)
|
||||
|
||||
> 业务域:图06「收款查询及认领(回款认领)」的 TMS 二次认领环节
|
||||
> 核心规则:**认领只在本系统登记,不同步金蝶;一笔流水认领完成后,才推送金蝶生成收款单——不认领完就不推。**
|
||||
> 最后更新:2026-09-28
|
||||
|
||||
---
|
||||
|
||||
## 一、认领的对象:收款流水从哪来
|
||||
|
||||
金蝶司库收到银行收款流水后,先自动认领到客户维度,剩余未落到合同/结算单的部分形成**未认领金额**。业务人员在 TMS「收款流水」页面点「手动同步流水」,把这些公告同步成本系统的收款流水——每条流水带一个**公告未认领金额**,这就是后续认领的额度基准(重复同步不会产生重复流水,金额有变化会刷新)。
|
||||
|
||||
---
|
||||
|
||||
## 二、认领操作流程
|
||||
|
||||
**入口**:收款流水列表/详情的「认领」按钮——流水还有剩余可认领额度(公告未认领金额 − 累计认领)时可操作。
|
||||
|
||||
**操作步骤**:
|
||||
|
||||
| 步骤 | 操作 | 规则 |
|
||||
| --- | --- | --- |
|
||||
| 1. 选结算单 | 选择一张或多张应收正式结算单 | 须审批通过、未作废;多张须同一项目、同一组织、同一收付款方 |
|
||||
| 2. 录分摊金额 | 逐张结算单录入本次认领的收款金额 | ① 单张结算单:累计被认领金额 ≤ 其结算金额;② 整条流水:累计认领金额 ≤ 公告未认领金额(只认领金蝶侧缺口) |
|
||||
| 3. 确认 | 提交认领 | 生成一条认领记录(含分摊明细),刷新流水认领进度 |
|
||||
|
||||
**关键规则**:
|
||||
|
||||
1. 确认后认领只在本系统登记,**不与金蝶发生任何交互**。
|
||||
2. 一条流水**允许多次认领**(部分认领):今天认 40 万给 A 结算单,明天再认 60 万给 B 结算单,直到累计认领等于公告未认领金额。
|
||||
|
||||
---
|
||||
|
||||
## 三、认领状态
|
||||
|
||||
### 流水认领状态(认领进度)
|
||||
|
||||
| 状态 | 含义 |
|
||||
| --- | --- |
|
||||
| 未认领 | 还没有任何有效认领 |
|
||||
| 部分认领 | 累计认领 < 公告未认领金额 |
|
||||
| **认领完成** | 累计认领 = 公告未认领金额(正好补齐金蝶侧缺口) |
|
||||
|
||||
- 累计认领金额 = 该流水下所有**有效**认领分摊之和,**作废的认领不计入**;
|
||||
- 剩余可认领金额 = 公告未认领金额 − 累计认领金额。
|
||||
|
||||
### 认领记录状态
|
||||
|
||||
| 状态 | 含义 |
|
||||
| --- | --- |
|
||||
| 已认领 | 有效认领,金额计入流水累计 |
|
||||
| 已作废 | 不再计入累计,流水认领进度相应回退 |
|
||||
|
||||
---
|
||||
|
||||
## 四、认领完成后的推送(认领流程的出口)
|
||||
|
||||
**推送条件(闸门)**:
|
||||
|
||||
1. 流水**认领完成**——累计认领 = 公告未认领金额,**不认领完就不推**;
|
||||
2. 该流水**尚未推送过**——已推送的流水不允许二次推送。
|
||||
|
||||
**推送方式(两个入口,同一套规则)**:
|
||||
|
||||
- 定时任务自动推送:系统定期扫描满足条件的流水自动推;
|
||||
- 手动推送:流水页面「推送金蝶」按钮,条件不满足时置灰。
|
||||
|
||||
**推送前对账**:推送前先到金蝶重查该公告的**最新未认领金额**,与本地累计认领核对——一致才推;不一致(如他人在金蝶侧手工认领过)则拦截并提示差额,人工核对作废或补认领后再推。
|
||||
|
||||
**推送结果**:
|
||||
|
||||
| 结果 | 表现 |
|
||||
| --- | --- |
|
||||
| 成功 | 金蝶生成**一张收款单**(一笔流水一张单,多张结算单是该单下的多条分摊明细);流水推送状态置"已推送",回填金蝶收款单号 |
|
||||
| 失败 | 推送状态置"推送失败"并记录失败原因;**本地认领保留不回滚**;排除原因后可重新推送,重试不会在金蝶产生重复单据 |
|
||||
|
||||
### 流水推送状态
|
||||
|
||||
| 状态 | 含义 | 后续 |
|
||||
| --- | --- | --- |
|
||||
| 未推送 | 未满足推送条件或尚未轮到推送 | 继续认领 / 等待定时任务或手动推送 |
|
||||
| 已推送 | 金蝶已生成收款单 | 等待金蝶处理结果回写(审核/收款状态由回写推进);不再接受二次推送 |
|
||||
| 推送失败 | 上次推送被金蝶拒绝或异常 | 按失败原因整改后重新推送 |
|
||||
|
||||
> 认领记录页可随时手动「查询金蝶认领结果」,回写金蝶收款单号与处理状态(已推送 → 审核通过 → 已收款)。
|
||||
|
||||
---
|
||||
|
||||
## 五、作废认领
|
||||
|
||||
1. 仅认领人本人可作废自己的认领记录;作废后该笔分摊不再计入累计,流水认领状态相应回退(认领完成 → 部分认领/未认领)。
|
||||
2. **作废永远不会触发推送**。
|
||||
3. 按流水是否已推送区分:
|
||||
- **未推送**:纯本地生效,无金蝶影响;补认领到认领完成后仍可正常推送;
|
||||
- **已推送**:本地生成冲单号留痕,金蝶侧冲销/红冲由人工在金蝶处置,该流水不会被再次自动推送。
|
||||
|
||||
---
|
||||
|
||||
## 六、典型场景
|
||||
|
||||
1. **一次认领完成**:未认领金额 100 万,一次认领到 2 张结算单(60 万 + 40 万)→ 认领完成 → 推送,金蝶生成一张 100 万收款单。
|
||||
2. **分两次认领完成**:先认 40 万(部分认领,不推金蝶),再认 60 万补齐 → 认领完成 → 推送,仍是一张收款单含两笔分摊。
|
||||
3. **金额不一致被拦截**:本地累计 100 万,推送前金蝶重查最新未认领只剩 80 万 → 拦截提示差额 20 万 → 作废多余认领后再推。
|
||||
4. **推送失败重试**:因结算单尚未同步金蝶应收被拒 → 记录失败原因 → 补齐前置后重推,不产生重复收款单。
|
||||
|
||||
---
|
||||
|
||||
## 七、注意事项
|
||||
|
||||
1. **结算单前提**:认领的结算单须已完成金蝶应收侧同步(有金蝶应收单号),推送时金蝶才能按应收单核销。
|
||||
2. **认领人前提**:金蝶公告的认领人姓名须与 TMS 用户真实姓名一致,否则同步不到流水;推送前对账也要求操作者在公告认领范围内(定时任务按各认领人自动查询,不受单个人限制)。
|
||||
3. **两个口径不要混**:「公告未认领金额」是金蝶侧待认领缺口(额度与认领完成的判定基准);「累计认领金额」是本系统登记的有效认领合计。认领完成 = 两者相等。
|
||||
@@ -0,0 +1,136 @@
|
||||
-- 收款认领推送金蝶重构(认领本地化 / A301-3 定时+手动推送 / 按流水归集)
|
||||
-- 支持重复执行,兼容 20260924 脚本已执行/未执行的环境,与该脚本无执行顺序要求
|
||||
-- 变更点:
|
||||
-- 1. 收款流水表新增推送域字段(推送状态/失败原因/推送时间/推送编码/金蝶收款单号/回写状态)
|
||||
-- 2. 认领主单移除 awrp_src_code 及其索引(推送编码上移至流水:按流水生成、重试复用)
|
||||
-- 3. 收款流水表新增定时任务扫描索引与 A301-1 回写匹配索引
|
||||
|
||||
-- 1. 收款流水表:推送状态
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `push_status` varchar(20) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''none'' COMMENT ''推送状态(none未推送/pushed已推送/failed推送失败)''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'push_status'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 2. 收款流水表:最近一次推送失败原因
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `push_fail_reason` varchar(1000) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ''最近一次推送失败原因(成功后清空)''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'push_fail_reason'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 3. 收款流水表:首次推送成功时间
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `pushed_time` datetime DEFAULT NULL COMMENT ''首次推送金蝶成功时间''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'pushed_time'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 4. 收款流水表:推送来源单据编码(A301-3 awrp_src_code,A301-1 回写匹配键,重试复用)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `awrp_src_code` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ''金蝶推送来源单据编码(SKCL+时间戳+流水id尾号6位,按流水生成重试复用)''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'awrp_src_code'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 5. 收款流水表:金蝶收款单号(推送响应回填 / A301-1 回写推进)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `kingdee_bill_no` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ''金蝶收款单号''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'kingdee_bill_no'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 6. 收款流水表:金蝶回写状态(A301-1 回写生命周期)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD COLUMN `kingdee_bill_status` varchar(20) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ''none'' COMMENT ''金蝶回写状态(none未推送/pushed已推送/approved审核通过/received已收款/failed失败)''',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND COLUMN_NAME = 'kingdee_bill_status'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 7. 认领主单:删除 awrp_src_code 索引(列上移至流水表;0924 未执行过则本就无此索引)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) > 0,
|
||||
'ALTER TABLE `blade_receipt_claim` DROP KEY `idx_receipt_claim_src_code`',
|
||||
'SELECT 1')
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_receipt_claim' AND INDEX_NAME = 'idx_receipt_claim_src_code'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 8. 认领主单:删除 awrp_src_code 列(0924 未执行过则本就无此列)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) > 0,
|
||||
'ALTER TABLE `blade_receipt_claim` DROP COLUMN `awrp_src_code`',
|
||||
'SELECT 1')
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_receipt_claim' AND COLUMN_NAME = 'awrp_src_code'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 9. 收款流水表:定时任务扫描索引(push_status IN (none,failed) AND claim_status='claimed' AND bill_id 非空)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD KEY `idx_kingdee_receipt_flow_push_scan` (`tenant_id`,`push_status`,`claim_status`)',
|
||||
'SELECT 1')
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND INDEX_NAME = 'idx_kingdee_receipt_flow_push_scan'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 10. 收款流水表:A301-1 回写匹配索引(sourcebillnumber = awrp_src_code)
|
||||
SET @ddl_sql = (
|
||||
SELECT IF(COUNT(*) = 0,
|
||||
'ALTER TABLE `blade_kingdee_receipt_flow` ADD KEY `idx_kingdee_receipt_flow_src_code` (`tenant_id`,`awrp_src_code`)',
|
||||
'SELECT 1')
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'blade_kingdee_receipt_flow' AND INDEX_NAME = 'idx_kingdee_receipt_flow_src_code'
|
||||
);
|
||||
PREPARE ddl_stmt FROM @ddl_sql;
|
||||
EXECUTE ddl_stmt;
|
||||
DEALLOCATE PREPARE ddl_stmt;
|
||||
|
||||
-- 11. 按钮权限:收款流水页「推送金蝶」(父级菜单 2090000000000001260 收款流水,排序 4)
|
||||
INSERT INTO `blade_menu`
|
||||
(`id`,`parent_id`,`code`,`name`,`alias`,`path`,`source`,`sort`,`category`,`action`,`is_open`,`component`,`remark`,`is_deleted`)
|
||||
VALUES
|
||||
(2090000000000001264,2090000000000001260,'receipt_flow_push','推送金蝶','receipt_flow_push','','',4,2,0,1,NULL,'',0)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
`name`=VALUES(`name`),
|
||||
`alias`=VALUES(`alias`),
|
||||
`is_deleted`=0;
|
||||
Reference in New Issue
Block a user