feat(eodswapposition): 新增框架合约新口径展示功能
- 在EodPnlCalculator中添加CalculateEodSwapRiskNewFields方法,实现新口径计算逻辑 - 创建EodSwapRiskNewFields和EodSwapRiskNewResponse模型类,支持新的展示字段 - 实现SearchEodSwapNewList查询方法,复用旧查询权限控制并计算新字段 - 添加index=3的新框架合约Tab页面,使用独立查询接口和列配置 - 前端JavaScript中实现colModelGridEodSwapNew列模型,替换旧字段并新增9个字段 - 完善导出功能支持新Tab的标准格式导出,保持与旧口径分离 - 更新测试用例验证新框架合约前端接线正确性
This commit is contained in:
@@ -3370,6 +3370,91 @@ namespace YLErp.Modules.SwapModule
|
||||
return retListResult;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询 EQD-7084 新“框架合约”字段。
|
||||
/// 旧查询负责筛选、排序、分页及旧字段计算;新字段只基于当前页对应的日终腿补充计算,
|
||||
/// 避免改变旧接口的返回口径。
|
||||
/// </summary>
|
||||
public SearchListResult<EodSwapRiskNewResponse> SearchEodSwapNewList(EodSwapQueryRequest req)
|
||||
{
|
||||
// 新 Tab 与旧 Tab 共享同一套权限、筛选、排序和分页边界;先复用旧查询,
|
||||
// 再只替换需求明确调整的展示字段,避免新接口悄然改变旧口径或查询范围。
|
||||
var oldResult = SearchEodSwapList(req);
|
||||
var oldRows = oldResult.rows?.ToList() ?? new List<EodSwapResponse>();
|
||||
var tradeIds = oldRows.Select(x => x.position.SwapTradeId).Distinct().ToList();
|
||||
var valueDates = oldRows.Select(x => x.position.ValueDate).Distinct().ToList();
|
||||
|
||||
if (tradeIds.Count == 0)
|
||||
{
|
||||
return new SearchListResult<EodSwapRiskNewResponse>(oldResult,
|
||||
Enumerable.Empty<EodSwapRiskNewResponse>());
|
||||
}
|
||||
|
||||
// 当前页的交易、日终明细和扩展信息各批量读取一次,随后在内存按“交易 + 日终日”配对。
|
||||
// 不在 rows.Select 内查询数据库,避免分页结果产生 N+1 查询。
|
||||
var trades = DbContext.trade
|
||||
.Where(x => tradeIds.Contains(x.id))
|
||||
.Select(x => new { x.id, x.StartDate, x.ExerciseDate })
|
||||
.ToDictionary(x => x.id);
|
||||
var eodPositionDetails = DbContext.eod_swap_position
|
||||
.Where(x => tradeIds.Contains(x.SwapTradeId)
|
||||
&& valueDates.Contains(x.ValueDate)
|
||||
&& !x.Invalid)
|
||||
.ToList();
|
||||
var tradeExtends = DbContext.trade_extend
|
||||
.Where(x => tradeIds.Contains(x.TradeId))
|
||||
.ToList();
|
||||
|
||||
var rows = oldRows.Select(item =>
|
||||
{
|
||||
// 同一交易可出现在多个日终日;必须同时匹配 ValueDate,不能把其他日期的腿混入本行。
|
||||
var details = eodPositionDetails
|
||||
.Where(x => x.SwapTradeId == item.position.SwapTradeId
|
||||
&& x.ValueDate == item.position.ValueDate)
|
||||
.ToList();
|
||||
var floatingLegs = details.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
|
||||
var interestLegs = details.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList();
|
||||
var tradeExtend = tradeExtends.FirstOrDefault(x => x.TradeId == item.position.SwapTradeId);
|
||||
// 缺少扩展信息时按“期间支付”处理,和旧接口的默认值保持一致。
|
||||
var dividendPayDate = tradeExtend?.ExtendObj?.DividendPayDate ?? 1;
|
||||
trades.TryGetValue(item.position.SwapTradeId, out var tradeInfo);
|
||||
|
||||
return new EodSwapRiskNewResponse
|
||||
{
|
||||
position = item.position,
|
||||
TradeDate = item.TradeDate,
|
||||
SwapTradeNo = item.SwapTradeNo,
|
||||
ClientName = item.ClientName,
|
||||
StructureType = item.StructureType,
|
||||
AssetBookName = item.AssetBookName,
|
||||
ClientId = item.ClientId,
|
||||
SwapTradeTypeStr = item.SwapTradeTypeStr,
|
||||
UnderlyingType = item.UnderlyingType,
|
||||
PeriodAmount = item.PeriodAmount,
|
||||
FloatingUnrealizedPnl = item.FloatingUnrealizedPnl,
|
||||
InterestPaymentMethod = item.InterestPaymentMethod,
|
||||
MaturityNettingValuation = item.MaturityNettingValuation,
|
||||
PeriodPaymentValuation = item.PeriodPaymentValuation,
|
||||
MarginInterestGain = item.MarginInterestGain,
|
||||
MarginInterestLoss = item.MarginInterestLoss,
|
||||
// 所有 EQD-7084 差异集中在 NewFields;上方复制的旧字段用于保留原报表的
|
||||
// 基本信息、DV、期间金额及已实现收益,前端再将六个差异列绑定到 NewFields。
|
||||
NewFields = CalculateEodSwapRiskNewFields(
|
||||
floatingLegs,
|
||||
interestLegs,
|
||||
item.StructureType,
|
||||
item.position.NotionalValue,
|
||||
tradeInfo?.StartDate,
|
||||
tradeInfo?.ExerciseDate,
|
||||
item.PeriodAmount,
|
||||
dividendPayDate)
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
return new SearchListResult<EodSwapRiskNewResponse>(oldResult, rows);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取互换交易日终持仓数据
|
||||
/// </summary>
|
||||
@@ -3448,6 +3533,29 @@ namespace YLErp.Modules.SwapModule
|
||||
return retListResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计算 EQD-7084 新“框架合约”Tab 的字段口径。
|
||||
/// 纯函数只依赖日终浮动腿、利息腿和交易级展示参数,供查询接口及无库单测共用。
|
||||
/// </summary>
|
||||
public static EodSwapRiskNewFields CalculateEodSwapRiskNewFields(
|
||||
IEnumerable<eod_swap_position> floatingLegs,
|
||||
IEnumerable<eod_swap_position> interestLegs,
|
||||
string structureType,
|
||||
decimal notionalValue,
|
||||
DateTime? startDate,
|
||||
DateTime? ExerciseDate,
|
||||
decimal periodAmount,
|
||||
int dividendPayDate)
|
||||
=> EodPnlCalculator.CalculateEodSwapRiskNewFields(
|
||||
floatingLegs,
|
||||
interestLegs,
|
||||
structureType,
|
||||
notionalValue,
|
||||
startDate,
|
||||
ExerciseDate,
|
||||
periodAmount,
|
||||
dividendPayDate);
|
||||
|
||||
/// <summary>
|
||||
/// 互换持仓明细查询
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user