refactor(swap): 阶段1b SwapEodPositionService加虚方法接缝(testable迁移)

加3个protected virtual虚方法(Seams接缝),不改变生产行为:
- PersistEodSwapPosition: 持久化eod持仓(原DbContext.Add+UpdateDbOption)
- SaveAllChanges: 保存变更(原DbContext.SaveChanges)
- GetCurrencyRate: 获取汇率(原new EodCurrencyRateService)

将4个利息归档分支方法里的直接DB调用替换为调虚方法:
- SaveEodInterestPosition(互换分支)
- SaveAutoEodInterestPosition(自动互换分支)
- SaveAutoEodWithCloseInterestPosition(平仓分支)
- SaveEodInterestPositionCopy(普通计息分支)

测试子类override这些虚方法即可在内存中运行收盘逻辑,
不连数据库。生产代码行为完全不变(虚方法默认实现=原逻辑)。

验证: GetInterestsUnitTest_T0/T1 89个测试全通过,无回归。
This commit is contained in:
hjhan
2026-07-01 17:21:56 +08:00
parent b548709371
commit dc3a6e9f77
@@ -30,6 +30,36 @@ namespace YLErp.Modules.SwapModule
{
}
#region Seamsoverride DB/
/// <summary>持久化 eod 持仓记录(生产: DbContext.Add;测试: 收集到列表)</summary>
protected virtual void PersistEodSwapPosition(eod_swap_position position)
{
if (position.id == 0)
{
DbContext.eod_swap_position.Add(position);
}
else
{
UpdateDbOption(position);
}
}
/// <summary>保存所有变更(生产: DbContext.SaveChanges;测试: 计数)</summary>
protected virtual void SaveAllChanges()
{
DbContext.SaveChanges();
}
/// <summary>获取汇率(生产: EodCurrencyRateService;测试: 返回固定值)</summary>
protected virtual double GetCurrencyRate(string quoteCurrency, string settlementCurrency, DateTime valueDate, bool seekPreday, CurrencyRateType currencyRateType)
{
return new EodCurrencyRateService(UserInfo).GetCurrencyRate(quoteCurrency, settlementCurrency, valueDate, seekPreday, currencyRateType);
}
#endregion
/// <summary>
/// 多空组合 互换流水合成持仓
/// </summary>
@@ -845,13 +875,10 @@ namespace YLErp.Modules.SwapModule
//累计已实现
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate
, seekPreday: true, currencyRateType: position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
if (newEodPayPosition.id == 0)
{
DbContext.eod_swap_position.Add(newEodPayPosition);
}
PersistEodSwapPosition(newEodPayPosition);
}
/// <summary>
/// 自动互换用,当日无互换,当日无平仓
@@ -982,13 +1009,10 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate
, seekPreday: true, currencyRateType: position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
if (newEodPayPosition.id == 0)
{
DbContext.eod_swap_position.Add(newEodPayPosition);
}
PersistEodSwapPosition(newEodPayPosition);
Log.Info($"the last newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}");
return interests;
}
@@ -1120,14 +1144,11 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee; ;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate
, seekPreday: true, currencyRateType: position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
position.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
Log.Info($"即将插入数据库的 newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}");
if (newEodPayPosition.id == 0)
{
DbContext.eod_swap_position.Add(newEodPayPosition);
}
PersistEodSwapPosition(newEodPayPosition);
return interests;
}
@@ -1245,14 +1266,11 @@ namespace YLErp.Modules.SwapModule
newEodPayPosition.RealizedInterest = eodPayPosition.RealizedInterest + newEodPayPosition.TdCloseInterest * ratio;
newEodPayPosition.RealizedInterestFee = eodPayPosition.RealizedInterestFee + newEodPayPosition.TdCloseInterestFee;
newEodPayPosition.RealizedPnl = newEodPayPosition.RealizedInterest + newEodPayPosition.RealizedInterestFee;
var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate
, seekPreday: true, currencyRateType: eodPayPosition.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
var currencyRate = GetCurrencyRate(td.QuoteCurrency, td.SettlementCurrency, valueDate, true,
eodPayPosition.InterestDirection == (int)SwapDirectionEnum. ? CurrencyRateType.Buy : CurrencyRateType.Sell);
newEodPayPosition.TdCurrency = Convert.ToDecimal(currencyRate);
Log.Info($"the last newEodPayPosition is {JsonHelper.Serialize(newEodPayPosition, false)}");
if (newEodPayPosition.id == 0)
{
DbContext.eod_swap_position.Add(newEodPayPosition);
}
PersistEodSwapPosition(newEodPayPosition);
}
/// <summary>