# 互换收益结算审核后状态卡死、阻止收盘问题分析 > 本文分析到期互换"收益结算(互换)审核通过后,交易状态不流转,导致收盘到期检查一直阻止"的问题。 > 成文于 2026-07-01。 --- ## 一、问题概述 **复现场景**:一笔互换交易到期日(如 2026-06-29),用户在界面做"收益结算(互换)"并审核通过,但: - 交易状态没变成"已到期"或"已平仓",仍是"确认成交" - 不管做多少次收益结算+审核,状态依旧不变 - 收盘报错:`[检查当日到期交易]当日到期的场外交易未全部操作完成,请操作完成后再执行收盘操作:收益互换 GLMS-20260427-0001` --- ## 二、根因:审核路径 ApproveSwapTrade 漏了到期日判断 ### 代码对照(铁证) **免审核路径 `SwapIncome`(正确,基线就有)** — `SwapDealService.cs:1481-1485`: ```csharp if (td.ExerciseDate <= unwindData.ValueDate) // 判断到期 { td.Notional = 0; td.StockEqvNotional = 0; td.TradeStatus = "已到期"; // ✅ 到期 → 已到期 } ``` **审核路径 `ApproveSwapTrade`(漏了)** — `SwapDealService.cs:1525-1538`: ```csharp if (swapEvent.unwindData.CloseMethod == (int)CloseMethodEnum.全部平仓) td.TradeStatus = "已平仓"; else { td.TradeStatus = ConsTrade.确认成交; // ❌ 到期互换落到这里!没有 ExerciseDate 判断 td.HasPartialUnWind = 1; } ``` `ApproveSwapTrade` **完全没有 `ExerciseDate` 到期判断**,而互换操作的 `CloseMethod` 又是默认值 0(`InitIncome` cs:216 从不设它)→ 0 ≠ 全部平仓(1) → 走 else → 状态退回"确认成交"。 ### 为什么互换必然走 else 分支 - `CloseMethodEnum`:Unknown=0 / 全部平仓=1 / 部分平仓=2 - 互换初始化 `InitIncome`(cs:216-292)**从不给 `unwindData.CloseMethod` 赋值** → 默认 0 - 只有平仓路径(`InitUnwind`/`InitLongShortUnwind`)才设 `CloseMethod=全部平仓` - 0 ≠ 1 → 必走 else → 退回"确认成交" ### 收盘检查为什么一直阻止 `EodCheckMaturityTrade.cs:27-33`(到期检查): ```csharp var predicate = PredicateBuilder.Create(t => t.ExerciseDate >= startDate && t.ExerciseDate <= settleDate // 今日到期 && t.TradeStatus == ConsTrade.确认成交 // ★ 状态还是"确认成交" && t.SettlementFlag != 1); ``` 判断口径只看 `TradeStatus`。`TradeCompleteStatus = { 已到期, 已执行, 已平仓 }`(ConsTrade.cs:33)。审核后状态停在"确认成交"(不在完成列表里)→ 永远命中 → 永远阻止。 --- ## 三、关于"提交数量但审核时数量0" 用户还反馈"提交了数量但审核时候数量0"。经查: 1. `InitIncome`(cs:216-292)**从没给 `unwindData.CloseQty` 赋值**(对比 `InitUnwind` cs:90 有赋值)→ `CloseQty` 默认 0 2. `SaveSwapDeal`(cs:1597)的 `item.Quantity = unwindData.CloseQty` 被 `eventType == 平仓` 条件挡住 → 互换(3)不执行 但这不是核心问题——**核心是状态没流转**。互换的 Quantity 语义与平仓不同(互换是收益结清,不是按数量平仓),数量为 0 可能是设计如此。状态卡死才是阻止收盘的直接原因。 --- ## 四、引入时间(git blame) | 路径 | 提交 | 时间 | 说明 | |------|------|------|------| | `SwapIncome` 到期判断(正确)| `f9d8a256` | 2024-05-09 | 山证基线,一直有 | | `ApproveSwapTrade` 状态分支(漏判断)| `083848fb` | 2025-05-28 | 审核流程重构,漏同步 ExerciseDate 判断 | `083848fb`(2025-05-28)重构审核流程时把状态分支改成 `CloseMethod==全部平仓` 判断,但**忘了同步 `SwapIncome` 里的 `ExerciseDate` 到期判断**。 --- ## 五、涉及文件 | 文件:行号 | 问题 | |----------|------| | `SwapDealService.cs:1525-1538`(ApproveSwapTrade)| **漏 ExerciseDate 判断**,到期互换退回"确认成交" | | `SwapDealService.cs:1481-1485`(SwapIncome)| 正确对照(有到期判断)| | `SwapDealService.cs:216`(InitIncome)| 不设 CloseMethod → 默认 0,必然走 else | | `EodCheckMaturityTrade.cs:27-33` | 阻止收盘的检查(只认 TradeStatus)| | `ConsTrade.cs:33` | TradeCompleteStatus 定义(确认成交不在内)| --- ## 六、修复方向(最小改动) 在 `ApproveSwapTrade`(cs:1534-1538)的 else 分支补到期判断,与 `SwapIncome` 对齐: ```csharp else { // 补:到期互换应设为"已到期"(与 SwapIncome cs:1481 对齐) if (td.ExerciseDate <= swapEvent.unwindData.ValueDate) { td.Notional = 0; td.StockEqvNotional = 0; td.TradeStatus = "已到期"; } else { td.TradeStatus = ConsTrade.确认成交; td.HasPartialUnWind = 1; } } ``` 改后到期互换审核通过 → 状态正确变成"已到期" → 收盘检查通过。 --- ## 七、团队决策问题 1. **互换的 CloseMethod 是否应该设值**:当前 `InitIncome` 不设 CloseMethod(默认 0),是否应在互换初始化时根据是否全额结清设为"全部平仓"?这会影响 `ApproveSwapTrade` 走哪个分支。 2. **互换 Quantity=0 是否符合预期**:`InitIncome` 不设 CloseQty,导致互换 flow_event 的 Quantity=0。需业务确认这是设计意图还是遗漏。 3. **历史卡住的交易怎么处理**:GLMS-20260427-0001 等已卡住的交易,是否需要手动改 TradeStatus 为"已到期"才能继续收盘?