diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 7bd8621d..b9145466 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -497,6 +497,48 @@ namespace YLErp.Modules.SwapModule #endregion + /// + /// 根据指定日期刷新浮动腿基线(处理公司行为除权) + /// 用于前端修改平仓日期后重新获取除权后的持仓数量和价格 + /// + /// 交易ID + /// 平仓日期 + /// 返回浮动腿的最新基线数据 + public virtual (decimal PositionQty, decimal PosiNotionalValue, decimal PosiGrossPrice, decimal PosiNetPrice, bool IsRestored) RefreshFloatLegBaseline(int tradeId, DateTime valueDate) + { + var td = DbContext.trade.Find(tradeId); + if (td == null) + { + throw new ServiceException("未找到交易信息"); + } + + var positions = DbContext.swap_position.ActiveByTrade(tradeId); + var position = positions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode) && !x.IsInitial).FirstOrDefault(); + + if (position == null) + { + // 无浮动腿,返回trade表的原始值 + return ( + Convert.ToDecimal(td.TradeAmount), + Convert.ToDecimal(td.StockEqvNotional), + 0m, + 0m, + false + ); + } + + // 尝试恢复除权后的 EOD 基线 + var restoredCorporateActionBaseline = TryRestorePositionFromEod(position, valueDate); + + return ( + position.PosiQuantity, + position.PosiNotionalValue, + position.PosiGrossPrice, + position.PosiNetPrice, + restoredCorporateActionBaseline + ); + } + /// /// 平仓初始化 /// diff --git a/YLErpWeb/Controllers/SwapTrade2Controller.cs b/YLErpWeb/Controllers/SwapTrade2Controller.cs index 33c82881..421b5cc3 100644 --- a/YLErpWeb/Controllers/SwapTrade2Controller.cs +++ b/YLErpWeb/Controllers/SwapTrade2Controller.cs @@ -393,6 +393,32 @@ namespace YLErp.Web.Controllers new SwapTradeService(CurUser).TradeBack(model.TradeId, model.TradeDate); return JsonSuccess("回退成功"); } + /// + /// 根据平仓日期刷新持仓基线(处理公司行为除权) + /// + /// 交易ID + /// 事件日期/平仓日期 + /// 返回最新的持仓数量、价格等基线数据 + public JsonResult RefreshUnwindBaseline(int tradeId, DateTime valueDate) + { + var (positionQty, posiNotionalValue, posiGrossPrice, posiNetPrice, isRestored) = + new SwapDealService(CurUser).RefreshFloatLegBaseline(tradeId, valueDate); + + var result = new + { + PositionQty = positionQty, + PosiNotionalValue = posiNotionalValue, + PosiGrossPrice = posiGrossPrice, + PosiNetPrice = posiNetPrice, + IsRestored = isRestored, + // 全平时,平仓数量等于持仓数量 + CloseQty = positionQty, + CloseNotionalValue = posiNotionalValue + }; + + return JsonSuccess("", result); + } + /// /// 平仓利息腿信息 /// diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js index 1f70d833..ab2e3c05 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js @@ -175,6 +175,8 @@ const vue = new Vue({ this.floatPosition.UnwindDate = e; } if (!isUseApproval) { + // 新增:刷新持仓基线(处理公司行为除权) + this.refreshUnwindBaseline(); this.getInterestList(); //this.refreshUnderlyingPrice(); } else { @@ -365,6 +367,57 @@ const vue = new Vue({ thisObj.deal.SwapMarginRebatePnl = formatSwapAmount(thisObj.deal.SwapMarginRebatePnl); thisObj.deal.SwapMarginAmount = formatSwapAmount(thisObj.deal.SwapMarginAmount); }, + refreshUnwindBaseline() {//刷新持仓基线(处理公司行为除权) + var thisObj = this; + var postData = { + tradeId: thisObj.deal.SwapTradeId, + valueDate: thisObj.deal.ValueDate + }; + main.post("/swaptrade2/RefreshUnwindBaseline", postData, { async: true }).done(function (resp) { + if (resp.success) { + var data = resp.obj; + // 更新持仓数量和名义本金 + thisObj.deal.PositionQty = data.PositionQty; + thisObj.deal.PositionQty2 = data.PositionQty; // 新增:同时更新 PositionQty2(界面显示用) + thisObj.deal.PosiNotionalValue = data.PosiNotionalValue; + + // 如果是全平,更新平仓数量和名义本金 + if (thisObj.deal.CloseMethod == 1) { // 全部平仓 + thisObj.deal.CloseQty = data.CloseQty; + thisObj.deal.CloseNotionalValue = data.CloseNotionalValue; + } + + // 更新浮动腿的期初价格和数量 + if (thisObj.floatPosition) { + thisObj.floatPosition.PosiGrossPrice = data.PosiGrossPrice; + thisObj.floatPosition.PosiNetPrice = data.PosiNetPrice; + thisObj.initPosiNetPrice = data.PosiGrossPrice; + // 更新浮动腿的持仓数量(底部表格显示用) + thisObj.floatPosition.PositionQty = data.PositionQty; + } + + // 重新计算最多可平比例 + thisObj.oriClosePercent = (thisObj.deal.NotionalValue && thisObj.deal.PosiNotionalValue) + ? thisObj.deal.PosiNotionalValue / thisObj.deal.NotionalValue : 1; + + // 如果是全平,更新平仓比例 + if (thisObj.deal.CloseMethod == 1) { + thisObj.deal.ClosePercent = thisObj.oriClosePercent; + } + + // 强制 Vue 更新界面 + thisObj.$forceUpdate(); + + // 可选:显示提示信息 + if (data.IsRestored && window.otcDebug) { + console.log('[公司行为] 已根据除权后的EOD基线刷新持仓数据', { + PositionQty: data.PositionQty, + PosiGrossPrice: data.PosiGrossPrice + }); + } + } + }); + }, getInterestList() {//根据平仓日期获取利息腿信息 var thisObj = this; // closePercent 按"占期初(original)"语义(A)传给后端,由 GetUnwindInterestList 转为"占剩余(B)"计算