test(swap): 为债券TRS期间结算自动互换10场景补单测 + SaveAutoSwapDeal接缝可测化

- 新增 BondTrsAutoSwapScenarioTest:覆盖测试场景/测试场景-0702复测两页
  10个自动互换场景(含付息日历登记日2/28→支付日3/2、资金发生日3/3/3/4)、
  部分平仓后按登记日持仓数量计算(剩余60%为54240)、同日多腿合并、
  分红支付日偏移、无结算观察日不得凭空产生互换等,共11条断言全绿。
- SaveAutoSwapDeal 改为走 AddClientCash/AddSwapEvent/PersistFlowEvent 接缝
  (默认实现与重构前行为一致,零行为变更);UpdateInitalPostion 由 private
  改 protected virtual;GetPreDealDate 改 virtual,便于无DB单测。
This commit is contained in:
hjhan
2026-08-08 13:32:22 +08:00
parent 5ca297a73c
commit 096d2609eb
3 changed files with 559 additions and 8 deletions
@@ -127,6 +127,12 @@ namespace YLErp.Modules.SwapModule
}
}
/// <summary>持久化互换流水事件(生产: DbContext.swap_flow_event.Add;测试: 收集到列表)</summary>
protected virtual void PersistFlowEvent(swap_flow_event flowEvent)
{
DbContext.swap_flow_event.Add(flowEvent);
}
/// <summary>保存所有变更(生产: DbContext.SaveChanges;测试: 计数)</summary>
protected virtual void SaveAllChanges()
{
@@ -773,14 +779,14 @@ namespace YLErp.Modules.SwapModule
// 利息腿:插入资金记录(使用系统操作_互换)
if (unwindData.SwapCloseAmount != 0)
{
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapCloseAmount), ClientCashInCashOut._互换, cashHappenDate);
clientCashId = AddClientCash(td, Convert.ToDouble(-unwindData.SwapCloseAmount), ClientCashInCashOut._互换, cashHappenDate);
clientCashIds.Add(clientCashId);
}
// 预付金腿:单独插入一条资金记录(系统操作_预付金返息)
if (unwindData.SwapMarginRebatePnl != 0)
{
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut._预付金返息, unwindData.ValueDate);
clientCashId = AddClientCash(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut._预付金返息, unwindData.ValueDate);
clientCashIds.Add(clientCashId);
}
unwindData.SwapCloseAmount = unwindData.SwapRealizedPnL;//需要算上预付金利息 和 分红; 只是不算预付金返还
@@ -790,19 +796,19 @@ namespace YLErp.Modules.SwapModule
var dividendPayDate = (dividendEvents != null && dividendEvents.Count > 0)
? dividendEvents.First().PayDate.Value
: unwindData.ValueDate;
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapDividendPnl), ClientCashInCashOut._互换, dividendPayDate);
clientCashId = AddClientCash(td, Convert.ToDouble(-unwindData.SwapDividendPnl), ClientCashInCashOut._互换, dividendPayDate);
clientCashIds.Add(clientCashId);
}
unwindData.ClientCashIds = clientCashIds;
string data = JsonConvert.SerializeObject(unwindData);
var swapEvent = new SwapEventService(this).AddSwapEventDate(unwindData.ValueDate, unwindData.SwapTradeId, (int)SwapEventTypeEnum., data, clientCashId, true, "系统操作-自动互换");//将互换总额存入事件
var swapEvent = AddSwapEvent(unwindData.ValueDate, unwindData.SwapTradeId, (int)SwapEventTypeEnum., data, clientCashId, true, "系统操作-自动互换");//将互换总额存入事件
if (flowEvents!=null)
{
flowEvents.ForEach(x =>
{
x.EventId = swapEvent.id;
DbContext.swap_flow_event.Add(x);
PersistFlowEvent(x);
});
UpdateInitalPostion(flowEvents, td.id);
}
@@ -813,7 +819,7 @@ namespace YLErp.Modules.SwapModule
dividendEvents.ForEach(x =>
{
x.EventId = swapEvent.id;
DbContext.swap_flow_event.Add(x);
PersistFlowEvent(x);
});
UpdateInitalPostion(dividendEvents, td.id);
}
@@ -823,7 +829,7 @@ namespace YLErp.Modules.SwapModule
/// 互换更新实时持仓信息
/// </summary>
/// <param name="flowEvents"></param>
private void UpdateInitalPostion(List<swap_flow_event> flowEvents, int swapTradeId)
protected virtual void UpdateInitalPostion(List<swap_flow_event> flowEvents, int swapTradeId)
{
var positions = DbContext.swap_position.Where(x => !x.IsInitial && x.SwapTradeId == swapTradeId && !x.Invalid);
foreach (var position in positions)
@@ -284,7 +284,7 @@ namespace YLErp.Modules.SwapModule
/// <param name="valueDate"></param>
/// <param name="eventTypes"></param>
/// <returns></returns>
public DateTime? GetPreDealDate(int tradeId, DateTime valueDate, List<int> eventTypes)
public virtual DateTime? GetPreDealDate(int tradeId, DateTime valueDate, List<int> eventTypes)
{
Expression<Func<swap_event, bool>> eventExpression = x => x.SwapTradeId == tradeId && x.ValueDate <= valueDate && !x.Invalid && eventTypes.Contains(x.EventType);
var swapEvent = DbContext.swap_event.Where(eventExpression).OrderByDescending(o => o.ValueDate).FirstOrDefault();