互换重收盘误删手动互换资金记录: 分析文档+TDD红灯测试
问题:重新收盘后用户手动互换产生的资金记录(ClientCashInCashOut, Action=系统操作-互换)被误删。根因 ClearSwapPositions:400 按 Action 字符串模糊删除,而该 Action 手动/自动共用,表无来源字段区分。 引入点 commit 44e89726(2026-05-14)。 - 新增决策文档(根因/引入时间/三种修复方案/自测方法) - 新增 SwapReEodDeleteManualCashRecordTest 4个测试(探查/诊断/录制红灯/离线校验) - 录制 golden 坐实 bug: trade 1903 手动互换资金记录 id=13032 会被误删
This commit is contained in:
+313
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"SwapTradeId": 1903,
|
||||
"SwapTradeNo": "GLMS-20260624-0005",
|
||||
"RecordedAt": "2026-07-01T08:33:12",
|
||||
"SourceDb": "test",
|
||||
"Purpose": "重收盘误删手动互换资金记录 - TDD红灯证据",
|
||||
"InputEvents": [
|
||||
{
|
||||
"ValueDate": "2026-06-24T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 9,
|
||||
"EventTypeName": "确认交易",
|
||||
"EventReason": "确认交易",
|
||||
"EventData": "",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 0,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20625,
|
||||
"EncryptId": "l4jIqgrZepVZBJ8gLfbu_w",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T17:38:40"
|
||||
},
|
||||
{
|
||||
"ValueDate": "2026-06-24T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 5,
|
||||
"EventTypeName": "回退",
|
||||
"EventReason": "交易回退至2026年06月24日",
|
||||
"EventData": "",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 0,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20631,
|
||||
"EncryptId": "lNwpsaP9qzZyFuecPppR4Q",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T17:58:12"
|
||||
},
|
||||
{
|
||||
"ValueDate": "2026-06-29T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 4,
|
||||
"EventTypeName": "自动互换",
|
||||
"EventReason": "系统操作-自动互换",
|
||||
"EventData": "{\"SwapTradeId\":1903,\"CloseType\":0,\"CloseQty\":0.0,\"ClosePercent\":0.0,\"CloseNotionalValue\":0.0,\"StartDate\":\"2026-06-25T00:00:00\",\"ValueDate\":\"2026-06-29T00:00:00\",\"UnwindDate\":null,\"NotionalValue\":19990.0,\"NotionalQty\":0.0,\"PosiNotionalValue\":19990.000000,\"PositionQty\":0.0,\"AnnualDays\":0,\"CloseMethod\":0,\"SwapRealizedPnL\":1.86160315679,\"SwapMarginRebatePnl\":-1.36986460274,\"SwapMarginAmount\":0.0,\"SwapCloseAmount\":1.86160315679,\"SwapDividendPnl\":0.0,\"FlowEvents\":[],\"StructureType\":null,\"PayDate\":\"2026-06-29T00:00:00\",\"TradeStartDate\":null}",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 13031,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20659,
|
||||
"EncryptId": "xgIja4GsGIq0qiL3Q-IdbQ",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T18:08:51"
|
||||
},
|
||||
{
|
||||
"ValueDate": "2026-06-30T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 3,
|
||||
"EventTypeName": "互换",
|
||||
"EventReason": "系统操作-互换",
|
||||
"EventData": "{\"SwapTradeId\":1903,\"CloseType\":0,\"CloseQty\":0.0,\"ClosePercent\":1.0,\"CloseNotionalValue\":19990.0,\"StartDate\":\"2026-06-24T00:00:00\",\"ValueDate\":\"2026-06-30T00:00:00\",\"UnwindDate\":\"2026-06-30T00:00:00\",\"NotionalValue\":19990.00,\"NotionalQty\":1000.00,\"PosiNotionalValue\":19990.00,\"PositionQty\":1000.0,\"AnnualDays\":365,\"CloseMethod\":0,\"SwapRealizedPnL\":3.23,\"SwapMarginRebatePnl\":0.00,\"SwapMarginAmount\":0.0,\"SwapCloseAmount\":3.23,\"SwapDividendPnl\":0.0,\"FlowEvents\":[],\"StructureType\":\"普通债券类收益互换\",\"PayDate\":\"2026-06-30T00:00:00\",\"TradeStartDate\":\"2026-06-25T00:00:00\"}",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 12996,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20632,
|
||||
"EncryptId": "GLfe6-0kN1kS1j8fwI35Jw",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T18:00:12"
|
||||
},
|
||||
{
|
||||
"ValueDate": "2026-06-30T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 3,
|
||||
"EventTypeName": "互换",
|
||||
"EventReason": "系统操作-互换",
|
||||
"EventData": "{\"SwapTradeId\":1903,\"CloseType\":0,\"CloseQty\":0.0,\"ClosePercent\":1.0,\"CloseNotionalValue\":19990.0,\"StartDate\":\"2026-06-30T00:00:00\",\"ValueDate\":\"2026-06-30T00:00:00\",\"UnwindDate\":\"2026-06-30T00:00:00\",\"NotionalValue\":19990.00,\"NotionalQty\":1000.00,\"PosiNotionalValue\":19990.00,\"PositionQty\":1000.0,\"AnnualDays\":365,\"CloseMethod\":0,\"SwapRealizedPnL\":5.00,\"SwapMarginRebatePnl\":0.00,\"SwapMarginAmount\":0.0,\"SwapCloseAmount\":5.00,\"SwapDividendPnl\":0.0,\"FlowEvents\":[],\"StructureType\":\"普通债券类收益互换\",\"PayDate\":\"2026-06-30T00:00:00\",\"TradeStartDate\":\"2026-06-25T00:00:00\"}",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 13029,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20658,
|
||||
"EncryptId": "CGvRD9lBlpTNg44rkLnzvA",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T18:08:07"
|
||||
},
|
||||
{
|
||||
"ValueDate": "2026-06-30T00:00:00",
|
||||
"SwapTradeId": 1903,
|
||||
"EventType": 3,
|
||||
"EventTypeName": "互换",
|
||||
"EventReason": "系统操作-互换",
|
||||
"EventData": "{\"SwapTradeId\":1903,\"CloseType\":0,\"CloseQty\":0.0,\"ClosePercent\":1.0,\"CloseNotionalValue\":19990.0,\"StartDate\":\"2026-06-30T00:00:00\",\"ValueDate\":\"2026-06-30T00:00:00\",\"UnwindDate\":\"2026-06-30T00:00:00\",\"NotionalValue\":19990.00,\"NotionalQty\":1000.00,\"PosiNotionalValue\":19990.00,\"PositionQty\":1000.0,\"AnnualDays\":365,\"CloseMethod\":0,\"SwapRealizedPnL\":5.00,\"SwapMarginRebatePnl\":0.00,\"SwapMarginAmount\":0.0,\"SwapCloseAmount\":5.00,\"SwapDividendPnl\":0.0,\"ClientCashIds\":[],\"FlowEvents\":[],\"StructureType\":\"普通债券类收益互换\",\"PayDate\":\"2026-06-30T00:00:00\",\"TradeStartDate\":\"2026-06-25T00:00:00\"}",
|
||||
"Invalid": false,
|
||||
"ClientCashId": 13032,
|
||||
"BackId": 0,
|
||||
"extenstionData": null,
|
||||
"SwapTradeNumber": null,
|
||||
"unwindData": null,
|
||||
"id": 20660,
|
||||
"EncryptId": "Q5Dzi9hzcXG6b8gXbawLHw",
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptTime": "2026-06-30T18:10:29"
|
||||
}
|
||||
],
|
||||
"InputCashRecords": [
|
||||
{
|
||||
"DirectionType": "互换支出",
|
||||
"TradeDirectionType": "互换收入",
|
||||
"CanGenerateExit": false,
|
||||
"Explain": null,
|
||||
"ValidState": "Valid",
|
||||
"TradeId": 1903,
|
||||
"Action": "系统操作-互换",
|
||||
"Direction": "应收",
|
||||
"Number": "20260630180850883",
|
||||
"ClientId": 38,
|
||||
"ClientNumber": "26033ZMRCS",
|
||||
"ClientName": "张名锐测试",
|
||||
"Money": -3.23,
|
||||
"HappenDate": "2026-06-29T00:00:00",
|
||||
"State": "已结算",
|
||||
"OpenBank": null,
|
||||
"OpenBankId": null,
|
||||
"OpenBankComments": null,
|
||||
"OpenBankCard": "",
|
||||
"MoneyStr": "-3.23",
|
||||
"SerialNumber": null,
|
||||
"BankFlowId": null,
|
||||
"AccountBalance": null,
|
||||
"Uses": null,
|
||||
"SettleDate": "2026-06-29T00:00:00",
|
||||
"Comments": null,
|
||||
"TradeNumber": "GLMS-20260624-0005",
|
||||
"TradeType": null,
|
||||
"CashFlag": 0,
|
||||
"TradeCashId": 0,
|
||||
"IsGroup": 0,
|
||||
"CurrencyCode": "",
|
||||
"ParentTradeNumber": null,
|
||||
"Deal": 0,
|
||||
"ApprovalProcess": 0,
|
||||
"CreatorId": 1,
|
||||
"CreatorName": "初始用户",
|
||||
"CreateDate": "2026-06-30T18:08:51",
|
||||
"ApprovalDate": null,
|
||||
"cash_type": null,
|
||||
"TransferOutAccount": null,
|
||||
"TransferInAccount": null,
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptDate": "2026-06-30T18:08:51",
|
||||
"id": 13030,
|
||||
"EncryptId": "PmbbhBl-gOhCtjzjFAL3MQ"
|
||||
},
|
||||
{
|
||||
"DirectionType": "预付金返息收入",
|
||||
"TradeDirectionType": "预付金返息支出",
|
||||
"CanGenerateExit": false,
|
||||
"Explain": null,
|
||||
"ValidState": "Valid",
|
||||
"TradeId": 1903,
|
||||
"Action": "系统操作-预付金返息",
|
||||
"Direction": "应收",
|
||||
"Number": "20260630180850888",
|
||||
"ClientId": 38,
|
||||
"ClientNumber": "26033ZMRCS",
|
||||
"ClientName": "张名锐测试",
|
||||
"Money": 1.37,
|
||||
"HappenDate": "2026-06-29T00:00:00",
|
||||
"State": "已结算",
|
||||
"OpenBank": null,
|
||||
"OpenBankId": null,
|
||||
"OpenBankComments": null,
|
||||
"OpenBankCard": "",
|
||||
"MoneyStr": "1.37",
|
||||
"SerialNumber": null,
|
||||
"BankFlowId": null,
|
||||
"AccountBalance": null,
|
||||
"Uses": null,
|
||||
"SettleDate": "2026-06-29T00:00:00",
|
||||
"Comments": null,
|
||||
"TradeNumber": "GLMS-20260624-0005",
|
||||
"TradeType": null,
|
||||
"CashFlag": 0,
|
||||
"TradeCashId": 0,
|
||||
"IsGroup": 0,
|
||||
"CurrencyCode": "",
|
||||
"ParentTradeNumber": null,
|
||||
"Deal": 0,
|
||||
"ApprovalProcess": 0,
|
||||
"CreatorId": 1,
|
||||
"CreatorName": "初始用户",
|
||||
"CreateDate": "2026-06-30T18:08:51",
|
||||
"ApprovalDate": null,
|
||||
"cash_type": null,
|
||||
"TransferOutAccount": null,
|
||||
"TransferInAccount": null,
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptDate": "2026-06-30T18:08:51",
|
||||
"id": 13031,
|
||||
"EncryptId": "cR8xg27rKifLQECWC61RFg"
|
||||
},
|
||||
{
|
||||
"DirectionType": "互换支出",
|
||||
"TradeDirectionType": "互换收入",
|
||||
"CanGenerateExit": false,
|
||||
"Explain": null,
|
||||
"ValidState": "Valid",
|
||||
"TradeId": 1903,
|
||||
"Action": "系统操作-互换",
|
||||
"Direction": "应收",
|
||||
"Number": "20260630181033576",
|
||||
"ClientId": 38,
|
||||
"ClientNumber": "26033ZMRCS",
|
||||
"ClientName": "张名锐测试",
|
||||
"Money": -5.0,
|
||||
"HappenDate": "2026-06-30T00:00:00",
|
||||
"State": "已结算",
|
||||
"OpenBank": null,
|
||||
"OpenBankId": null,
|
||||
"OpenBankComments": null,
|
||||
"OpenBankCard": "",
|
||||
"MoneyStr": "-5.00",
|
||||
"SerialNumber": null,
|
||||
"BankFlowId": null,
|
||||
"AccountBalance": null,
|
||||
"Uses": null,
|
||||
"SettleDate": "2026-06-30T00:00:00",
|
||||
"Comments": null,
|
||||
"TradeNumber": "GLMS-20260624-0005",
|
||||
"TradeType": null,
|
||||
"CashFlag": 0,
|
||||
"TradeCashId": 0,
|
||||
"IsGroup": 0,
|
||||
"CurrencyCode": "",
|
||||
"ParentTradeNumber": null,
|
||||
"Deal": 0,
|
||||
"ApprovalProcess": 0,
|
||||
"CreatorId": 1,
|
||||
"CreatorName": "初始用户",
|
||||
"CreateDate": "2026-06-30T18:10:34",
|
||||
"ApprovalDate": null,
|
||||
"cash_type": null,
|
||||
"TransferOutAccount": null,
|
||||
"TransferInAccount": null,
|
||||
"OptId": 1,
|
||||
"OptName": "初始用户",
|
||||
"OptDate": "2026-06-30T18:10:34",
|
||||
"id": 13032,
|
||||
"EncryptId": "NSMb8Sa0Q0Xx-5oOCr_UAw"
|
||||
}
|
||||
],
|
||||
"Diagnosis": {
|
||||
"SwapTradeId": 1903,
|
||||
"自动互换事件数": 1,
|
||||
"删除起点ValueDate": "2026-06-29T00:00:00",
|
||||
"删除命中总数": 3,
|
||||
"手动互换误删记录数": 1,
|
||||
"自动互换命中记录数": 1,
|
||||
"孤儿命中记录数": 1,
|
||||
"手动互换误删CashIds": [
|
||||
13032
|
||||
],
|
||||
"命中明细": [
|
||||
{
|
||||
"CashId": 13030,
|
||||
"Action": "系统操作-互换",
|
||||
"Money": -3.23,
|
||||
"HappenDate": "2026-06-29T00:00:00",
|
||||
"来源": "未知(孤儿)",
|
||||
"会被误删": false
|
||||
},
|
||||
{
|
||||
"CashId": 13031,
|
||||
"Action": "系统操作-预付金返息",
|
||||
"Money": 1.37,
|
||||
"HappenDate": "2026-06-29T00:00:00",
|
||||
"来源": "自动互换",
|
||||
"会被误删": false
|
||||
},
|
||||
{
|
||||
"CashId": 13032,
|
||||
"Action": "系统操作-互换",
|
||||
"Money": -5.0,
|
||||
"HappenDate": "2026-06-30T00:00:00",
|
||||
"来源": "手动互换",
|
||||
"会被误删": true
|
||||
}
|
||||
],
|
||||
"BUG成立": true,
|
||||
"结论": "坐实BUG:误删 1 条手动互换资金记录",
|
||||
"Summary": "--- 重收盘误删诊断 SwapTradeId=1903 ---\n\n[swap_event] 手动互换 vs 自动互换:\n event id=20659 EventType=自动互换 ValueDate=2026-06-29 ClientCashId=13031\n event id=20632 EventType=互换 ValueDate=2026-06-30 ClientCashId=12996\n event id=20658 EventType=互换 ValueDate=2026-06-30 ClientCashId=13029\n event id=20660 EventType=互换 ValueDate=2026-06-30 ClientCashId=13032\n\n[删除条件模拟] valueDate=2026-06-29 Action IN (系统操作-互换, 系统操作-预付金返息)\n id Action MoneyHappenDate 来源 误删? \n 13030 系统操作-互换 -3.232026-06-29 未知(孤儿) \n 13031 系统操作-预付金返息 1.372026-06-29 自动互换 \n 13032 系统操作-互换 -5.002026-06-30 手动互换 ✓BUG \n\n[结论]\n 删除命中 3 条 = 手动互换 1 + 自动互换 1 + 孤儿 1\n ⚠⚠⚠ 坐实 BUG:重收盘会误删 1 条手动互换资金记录 (ids=[13032])\n 根因:ClearSwapPositions:400 按 Action=系统操作-互换 删除,该 Action 手动/自动共用,无来源字段区分。"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user