feat(swaptrade): 添加收益结算日期验证和限制功能

- 新增 MaxIncomeValueDate 属性用于限制收益结算日期上限
- 实现 parseLocalDate 函数用于解析本地日期格式
- 在前端添加日期选择器的最大日期限制和验证逻辑
- 添加 isAfterMaxIncomeValueDate 和 validateIncomeValueDate 方法进行日期验证
- 在后端添加 GetMaxIncomeValueDate 方法计算最大收益结算日期
- 实现 ValidateIncomeValueDate 对收益结算日期进行服务器端验证
- 添加 NormalizeIncomeUnwindDate 方法统一处理平仓日期
- 在模型中新增 MaxIncomeValueDate 非映射属性用于前端显示
- 更新日期格式化函数确保日期字符串的一致性处理
This commit is contained in:
张名锐
2026-07-06 15:20:21 +08:00
parent 86825cb2a1
commit 6835a593b0
4 changed files with 96 additions and 7 deletions
+35 -2
View File
@@ -113,6 +113,11 @@ namespace YLErp.Modules.SwapModule
new TradeUnwindService(this).CloseReCheck_SetTrade(swapTradeId, isSwap, needCheck);
}
protected virtual DateTime GetMaxIncomeValueDate(trade td)
{
return QdpCalendarHelper.GetNonHolidayDefore(td.ExerciseDate.Value.AddDays(-1));
}
#endregion
public SwapDealService(OptUserInfo optUser) : base(optUser)
@@ -394,7 +399,8 @@ namespace YLErp.Modules.SwapModule
var positions = DbContext.swap_position.Where(x => x.SwapTradeId == tradeId && !x.Invalid);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode);
List<int> eventTypes = new List<int>() { (int)SwapFlowEventTypeEnum., (int)SwapFlowEventTypeEnum. };
var dealDate = valuedateBLL.ValueDate < td.ExerciseDate.Value ? valuedateBLL.ValueDate : td.ExerciseDate.Value;
var maxIncomeValueDate = GetMaxIncomeValueDate(td);
var dealDate = valuedateBLL.ValueDate.Date > maxIncomeValueDate.Date ? maxIncomeValueDate : valuedateBLL.ValueDate;
// 收益结算不检查收盘限制
var tradeExtend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == tradeId);
td.trade_extend = tradeExtend;
@@ -425,7 +431,7 @@ namespace YLErp.Modules.SwapModule
unwindData.UnwindDate = dealDate;
floatEvent.UnwindDate = unwindData.UnwindDate;
floatEvent.EventDate = dealDate;
unwindData.PayDate = QdpCalendarHelper.GetNonHoliday(unwindData.UnwindDate.Value.AddDays(td.trade_extend.ExtendObj.SettlementRules));
unwindData.PayDate = valuedateBLL.ValueDate;
floatEvent.PayDate = unwindData.PayDate;
floatEvent.SwapTradeId = tradeId;
floatEvent.SwapTradeNo = td.TradeNumber;
@@ -464,6 +470,7 @@ namespace YLErp.Modules.SwapModule
}
unwindData.FlowEvents.Add(floatEvent);
}
unwindData.MaxIncomeValueDate = maxIncomeValueDate;
return unwindData;
}
/// <summary>
@@ -1645,6 +1652,8 @@ namespace YLErp.Modules.SwapModule
{
throw new ServiceException("未找到交易信息");
}
NormalizeIncomeUnwindDate(unwindData);
ValidateIncomeValueDate(unwindData, td);
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
ValidateFrontendPnL(unwindData, isIncome: true); // 只读校验告警,不阻断交易
ExecuteInTransaction(() =>
@@ -1683,6 +1692,11 @@ namespace YLErp.Modules.SwapModule
throw new Exception("该笔交易状态为平仓待复核,未找到相关记录,请检查该笔交易是否有效");
}
swapEvent.unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
if (eventType == (int)SwapEventTypeEnum.)
{
NormalizeIncomeUnwindDate(swapEvent.unwindData);
ValidateIncomeValueDate(swapEvent.unwindData, td);
}
var flowList = FindFlowEventsByEventId(swapEvent.id);
string action = eventType == (int)SwapEventTypeEnum. ? ClientCashInCashOut._互换 : ClientCashInCashOut._平仓费;
int clientCashId = AddClientCash(td, Convert.ToDouble(-swapEvent.unwindData.SwapRealizedPnL), action, swapEvent.unwindData.ValueDate);
@@ -1726,6 +1740,11 @@ namespace YLErp.Modules.SwapModule
{
throw new ServiceException("未找到交易信息");
}
if (eventType == (int)SwapEventTypeEnum.)
{
NormalizeIncomeUnwindDate(unwindData);
ValidateIncomeValueDate(unwindData, td);
}
unwindData.SwapRealizedPnL = unwindData.SwapCloseAmount;
string action = eventType == (int)SwapEventTypeEnum. ? ClientCashInCashOut._互换 : ClientCashInCashOut._平仓费;
ExecuteInTransaction(() =>
@@ -1735,6 +1754,20 @@ namespace YLErp.Modules.SwapModule
SaveAllChanges();
});
}
private void ValidateIncomeValueDate(UnwindData unwindData, trade td)
{
var maxIncomeValueDate = GetMaxIncomeValueDate(td).Date;
if (unwindData.ValueDate.Date > maxIncomeValueDate)
{
throw new ServiceException($"手动互换结算日期不能晚于当前交易结束日期T-1{maxIncomeValueDate:yyyy-MM-dd}");
}
}
private void NormalizeIncomeUnwindDate(UnwindData unwindData)
{
unwindData.UnwindDate = unwindData.ValueDate;
}
/// <summary>
/// 保存平仓/互换事件
/// </summary>