feat(swap): 实现互换交易价格精度控制功能 init

- 添加 swapPricePrecisionHelper.js 工具类处理价格精度格式化
- 新增 swappriceprecision.js 配置文件定义各类金融产品的精度规则
- 在 EodPositionRisks.cshtml 和 SwapIncome.cshtml 中引入新的价格格式化脚本
- 替换原有的价格格式化函数为基于产品类型的动态精度控制
- 移除旧的价格验证和标准化逻辑,改用新的精度控制机制
- 添加 vue-swap-price-input 组件用于精确的价格输入控制
- 更新 Controller 中的价格处理逻辑以支持新精度格式化方式
This commit is contained in:
张名锐
2026-07-29 09:44:04 +08:00
parent ac00548009
commit fd2a054764
18 changed files with 548 additions and 136 deletions
@@ -37,7 +37,6 @@ namespace YLErp.Modules.SwapModule
protected virtual long SaveSwapDeal(UnwindData unwindData, int eventType, int clientCashId, string eventResason = "", bool approve = false)
{
NormalizeNotionalValues(unwindData);
NormalizeDeliveryPrices(unwindData.FlowEvents);
return SaveSwapDealInternal(unwindData, eventType, clientCashId, eventResason, approve);
}
@@ -48,49 +47,6 @@ namespace YLErp.Modules.SwapModule
unwindData.CloseNotionalValue = Math.Round(unwindData.CloseNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
}
private static int GetStorageDeliveryPriceRound(swap_flow_event flowEvent)
{
if (ConsGlobal.InstrumentType.IsBond(flowEvent?.UnderlyingInstrumentType))
{
return ConsGlobal.PriceRound;
}
if (string.IsNullOrEmpty(flowEvent?.UnderlyingCode))
{
return ConsGlobal.SwapDeliveryPriceRound;
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(flowEvent?.UnderlyingCode);
return underlying?.IsBond() == true ? ConsGlobal.PriceRound : ConsGlobal.SwapDeliveryPriceRound;
}
private static void ValidateDeliveryPrices(UnwindData unwindData)
{
if (unwindData.FlowEvents == null)
{
return;
}
foreach (var item in unwindData.FlowEvents.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)))
{
var roundedPrice = Math.Round(item.TradingAmountAvg, GetStorageDeliveryPriceRound(item), MidpointRounding.AwayFromZero);
if (item.TradingAmountAvg != roundedPrice)
{
throw new ServiceException($"期末交割价最多保留{ConsGlobal.SwapDeliveryPriceRound}位小数");
}
item.TradingAmountAvg = roundedPrice;
}
}
private static void NormalizeDeliveryPrices(IEnumerable<swap_flow_event> flowEvents)
{
if (flowEvents == null)
{
return;
}
foreach (var item in flowEvents.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)))
{
item.TradingAmountAvg = Math.Round(item.TradingAmountAvg, GetStorageDeliveryPriceRound(item), MidpointRounding.AwayFromZero);
}
}
/// <summary>保存所有变更(生产: DbContext.SaveChanges;测试: 空操作)</summary>
protected virtual void SaveAllChanges()
{
@@ -1291,7 +1247,6 @@ namespace YLErp.Modules.SwapModule
{
throw new ServiceException("未找到交易信息");
}
ValidateDeliveryPrices(unwindData);
NormalizeNotionalValues(unwindData);
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
ValidateFrontendPnL(unwindData, isIncome: false); // 只读校验告警,不阻断交易
@@ -1776,7 +1731,6 @@ namespace YLErp.Modules.SwapModule
{
throw new ServiceException("未找到交易信息");
}
ValidateDeliveryPrices(unwindData);
NormalizeIncomeUnwindDate(unwindData);
ValidateIncomeValueDate(unwindData, td);
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
@@ -1817,14 +1771,12 @@ namespace YLErp.Modules.SwapModule
throw new Exception("该笔交易状态为平仓待复核,未找到相关记录,请检查该笔交易是否有效");
}
swapEvent.unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
NormalizeDeliveryPrices(swapEvent.unwindData.FlowEvents);
if (eventType == (int)SwapEventTypeEnum.)
{
NormalizeIncomeUnwindDate(swapEvent.unwindData);
ValidateIncomeValueDate(swapEvent.unwindData, td);
}
var flowList = FindFlowEventsByEventId(swapEvent.id);
NormalizeDeliveryPrices(flowList);
string action = eventType == (int)SwapEventTypeEnum. ? ClientCashInCashOut._互换 : ClientCashInCashOut._平仓费;
int clientCashId = AddClientCash(td, Convert.ToDouble(-swapEvent.unwindData.SwapRealizedPnL), action, swapEvent.unwindData.ValueDate);
if (swapEvent.unwindData.SwapMarginAmount != 0)
@@ -1867,7 +1819,6 @@ namespace YLErp.Modules.SwapModule
{
throw new ServiceException("未找到交易信息");
}
ValidateDeliveryPrices(unwindData);
if (eventType == (int)SwapEventTypeEnum.)
{
NormalizeIncomeUnwindDate(unwindData);