refactor(swap): SwapPositionCompose补5个seam+事务重构为ExecuteInTransaction

SwapEodPositionService 新增5个 protected virtual seam(SwapPositionCompose路径):
- FindActiveSwapTrades(DateTime, IEnumerable<int>): 查活跃互换交易
- FindAllSwapPositions(List<int>): 查所有持仓(含初始+实际)
- FindTradeExtends(List<int>): 批量查交易扩展
- FindEodSwapsByDate(DateTime): 查指定日期日终汇总
- FindFlowEvents(int, DateTime): 查交易指定日期的完成流水事件

SwapPositionCompose 方法体重构:
- 5处内联DbContext查询替换为seam调用
- 事务(BeginTransaction/Commit/Rollback)重构为ExecuteInTransaction lambda
- SaveChanges替换为SaveAllChanges seam
- 复用已有FindEodSwapPositions seam(替代内联eod_swap_position查询)

为零行为变更(seam生产实现=原代码,ExecuteInTransaction=原事务逻辑)。
SwapModule 173测试全绿,无回归。为SwapPositionComposeScenarioTest铺路。
This commit is contained in:
hjhan
2026-07-03 18:31:01 +08:00
parent 9016ea480f
commit cbb5c88aa8
@@ -167,6 +167,51 @@ namespace YLErp.Modules.SwapModule
return new BondPaymentService(UserInfo).CalcPayment(underlyingCode, fromDate, toDate, qty, shortRatio, directionRatio);
}
// ---- SwapPositionCompose 路径专用 seam(借鉴 testable 分支)----
/// <summary>查找收盘所需的活跃互换交易(生产: DbContext.trade.Where;测试: 内存列表)</summary>
protected virtual List<trade> FindActiveSwapTrades(DateTime settleDate, IEnumerable<int> clientIds)
{
var tradePredicate = PredicateBuilder.Create<trade>(n => n.ValidState != ConsGlobal.InValid
&& n.TradeType == "收益互换"
&& n.TradeDate <= settleDate
&& n.ExerciseDate >= settleDate
&& (n.TradeStatus == ConsTrade. || n.UnWindDate >= settleDate)
);
if (clientIds != null && clientIds.Any())
{
tradePredicate = tradePredicate.And(x => clientIds.Contains(x.ClientId));
}
return DbContext.trade.Where(tradePredicate).ToList();
}
/// <summary>查找交易的所有持仓(含初始+实际,生产: DbContext.swap_position;测试: 内存列表)</summary>
protected virtual List<swap_position> FindAllSwapPositions(List<int> tradeIds)
{
return DbContext.swap_position.Where(t => tradeIds.Contains(t.SwapTradeId) && !t.Invalid).ToList();
}
/// <summary>批量查找交易扩展(生产: DbContext.trade_extend;测试: 内存列表)</summary>
protected virtual List<trade_extend> FindTradeExtends(List<int> tradeIds)
{
return DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
}
/// <summary>查找指定日期的日终汇总(生产: DbContext.eod_swap;测试: 内存列表)</summary>
protected virtual List<eod_swap> FindEodSwapsByDate(DateTime valueDate)
{
return DbContext.eod_swap.Where(x => x.ValueDate == valueDate).ToList();
}
/// <summary>查找交易在指定日期的完成流水事件(生产: DbContext.swap_flow_event;测试: 内存列表)</summary>
protected virtual List<swap_flow_event> FindFlowEvents(int swapTradeId, DateTime settleDate)
{
Expression<Func<swap_flow_event, bool>> eventExpression = x => x.SwapTradeId == swapTradeId
&& x.DataState == (int)SwapFlowDateStateEnum.
&& x.EventDate == settleDate;
return DbContext.swap_flow_event.Where(eventExpression).ToList();
}
#endregion
/// <summary>
@@ -205,28 +250,17 @@ namespace YLErp.Modules.SwapModule
{
var dateStr = settleDate.ToString("yyyy-MM-dd");
Log.Info("SwapPositionCompose:" + "settleDate:" + settleDate + " preSettleDate:" + preSettleDate + " ClientIds:" + JsonHelper.Serialize(ClientIds));
var tradePredicate = PredicateBuilder.Create<trade>(n => n.ValidState != ConsGlobal.InValid
&& n.TradeType == "收益互换"
&& n.TradeDate <= settleDate
&& n.ExerciseDate >= settleDate
&& (n.TradeStatus == ConsTrade. || n.UnWindDate >= settleDate)
);
if (ClientIds != null && ClientIds.Any())
{
tradePredicate = tradePredicate.And(x => ClientIds.Contains(x.ClientId));
}
var tradeQueryList = DbContext.trade.Where(tradePredicate).ToList();
var tradeQueryList = FindActiveSwapTrades(settleDate, ClientIds);
var tradeIds = tradeQueryList.Select(s => s.id).ToList();
var allTradePositionList = DbContext.swap_position.Where(t => tradeIds.Contains(t.SwapTradeId) && !t.Invalid).ToList();
var allTradePositionList = FindAllSwapPositions(tradeIds);
var tradePositionList = allTradePositionList.Where(t => t.IsInitial).ToList();
var tradeRealPositionList = allTradePositionList.Where(t => !t.IsInitial).ToList();
var tradeExtendList = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
var eodSwapList = DbContext.eod_swap.Where(x => x.ValueDate == preSettleDate).ToList();
var tradeExtendList = FindTradeExtends(tradeIds);
var eodSwapList = FindEodSwapsByDate(preSettleDate);
List<int> eventTyps = new List<int>() { (int)SwapEventTypeEnum., (int)SwapEventTypeEnum., (int)SwapEventTypeEnum. };
foreach (var td in tradeQueryList)
{
var trans = DbContext.Database.BeginTransaction();
try
ExecuteInTransaction(() =>
{
List<int> removeEventTyps = new List<int>() { (int)SwapEventTypeEnum. };
bool longShort = td.StructureType == ClientMarginTypeEnum..ToString();
@@ -243,7 +277,7 @@ namespace YLErp.Modules.SwapModule
{
throw new Exception($"交易{td.TradeNumber}在上一交易日【{preSettleDate:yyyy-MM-dd}】未收盘");
}
var allEodPositions = DbContext.eod_swap_position.Where(x => x.ValueDate >= preSettleDate && x.SwapTradeId == td.id && !x.Invalid);
var allEodPositions = FindEodSwapPositions(td.id, preSettleDate);
var eodPositions = allEodPositions.Where(x => x.ValueDate == preSettleDate).ToList();//上一日终持仓信息
@@ -256,18 +290,7 @@ namespace YLErp.Modules.SwapModule
{
throw new Exception($"交易【{td.TradeNumber}】到期扔有持仓信息");
}
var flowEvents = new List<swap_flow_event>();
Expression<Func<swap_flow_event, bool>> eventExpression = x => x.SwapTradeId == td.id && x.DataState == (int)SwapFlowDateStateEnum.;
eventExpression = eventExpression.And(x => x.EventDate == settleDate);
//if (settleDate == td.TradeDate)
//{
// eventExpression = eventExpression.And(x => x.EventDate == settleDate);
//}
//else
//{
// eventExpression = eventExpression.And(x => x.UnwindDate == settleDate);
//}
flowEvents = DbContext.swap_flow_event.Where(eventExpression).ToList();
var flowEvents = FindFlowEvents(td.id, settleDate);
var preDealDate = GetPreDealDate(td.id, settleDate, eventTyps);//上一次平仓/互换/自动互换处理日期
List<swap_flow_event> autoInterests = new List<swap_flow_event>();//自动互换利息腿信息
//处理浮动腿
@@ -296,18 +319,8 @@ namespace YLErp.Modules.SwapModule
td.TradeStatus = "已到期";
td.UnWindDate = settleDate;
}
DbContext.SaveChanges();
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
throw new Exception(ex.Message, ex);
}
finally
{
trans.Dispose();
}
SaveAllChanges();
});
}
}