From 8a0659312b2230a2c95294290e5b90f86897be8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=94=A6=E9=BA=9F=20=E7=8E=8B?= Date: Mon, 24 Aug 2026 17:21:21 +0800 Subject: [PATCH] =?UTF-8?q?BugFix=20=E7=89=B9=E6=89=B9=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E6=B2=A1=E6=B3=95=E8=B5=B0=E9=80=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/SwapModule/SwapTradeService.cs | 12 ++++-- .../SwapModule/TradeLackOfMoneyException.cs | 17 ++++++++ YLErpWeb/Controllers/SwapTrade2Controller.cs | 20 +++++++++- .../Scripts/app/swaptrade/swapTradeEdit.js | 39 ++++++++++++++++--- 4 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 YLErpDAL/Modules/SwapModule/TradeLackOfMoneyException.cs diff --git a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs index 7daf7770..7ff6a46c 100644 --- a/YLErpDAL/Modules/SwapModule/SwapTradeService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapTradeService.cs @@ -80,10 +80,13 @@ namespace YLErp.Modules.SwapModule } /// /// 互换交易保存 + /// ignoreMoneyCheck=true:资金不足特批放行(additionalProcessing=LackOfMoney,controller 按 系统参数"允许交易特批" + /// 判定后传入,与确认/审批环节 ignoreMoneyCheck 同口径);确认成交时资金校验独立再跑,特批链路在那边仍有兜底。 /// /// + /// /// - public trade SaveTrade(trade req) + public trade SaveTrade(trade req, bool ignoreMoneyCheck = false) { var um = checkUnderlying(req); trade dbTrade = new trade(); @@ -91,11 +94,12 @@ namespace YLErp.Modules.SwapModule //资金校验须在其后取值,否则互换表单不填平铺 InitialMargin 时校验会按 0 放行) var tradeNumberGenerated = PrepareTrade(req, TradeSourceEnum.系统交易, um); // R4 簿记资金校验:可用资金(现金结存+授信−已使用授信,口径见 RealtimePnlCalc.TradeCanBeConfirm) - // 需覆盖 应付预付金+成交金额,不足拦截抛错;特批放行发生在确认成交环节(ignoreMoneyCheck)。 + // 需覆盖 应付预付金+成交金额;不足时抛 TradeLackOfMoneyException——controller 依"允许交易特批"开关 + // 走 AdditionalProcessing/LackOfMoney 特批协议(与确认/审批环节一致)或按保存失败拦截。 // ExerciseDate 为空(异常数据)时跳过该校验,避免 TradeCanBeConfirm 内部解引用抛错。 - if (req.ExerciseDate.HasValue && !RealtimePnlCalc.TradeCanBeConfirm(req.ClientId, req, out var fundErrorMsg)) + if (!ignoreMoneyCheck && req.ExerciseDate.HasValue && !RealtimePnlCalc.TradeCanBeConfirm(req.ClientId, req, out var fundErrorMsg)) { - throw new ServiceException(fundErrorMsg); + throw new TradeLackOfMoneyException(fundErrorMsg); } var trans = DbContext.Database.BeginTransaction(); diff --git a/YLErpDAL/Modules/SwapModule/TradeLackOfMoneyException.cs b/YLErpDAL/Modules/SwapModule/TradeLackOfMoneyException.cs new file mode 100644 index 00000000..dd8ecf3a --- /dev/null +++ b/YLErpDAL/Modules/SwapModule/TradeLackOfMoneyException.cs @@ -0,0 +1,17 @@ +using BaseOUDAL; + +namespace YLErp.Modules.SwapModule +{ + /// + /// R4 簿记资金校验:保存交易时资金不足(走现金部分超现金结存)的标记异常。 + /// controller 识别本类型后按确认/审批环节同一协议处理——系统参数 允许交易特批(SpecialOperateForTrade) 开启时 + /// 返回 AdditionalProcessing/LackOfMoney 结构化响应(UI 弹"交易特批",带 additionalProcessing=LackOfMoney 重提放行), + /// 开关关闭时按普通保存失败拦截。此前保存环节直接抛 ServiceException 无特批出口,资金不足的交易无法落库走到确认环节。 + /// + public class TradeLackOfMoneyException : ServiceException + { + public TradeLackOfMoneyException(string message) : base(message) + { + } + } +} diff --git a/YLErpWeb/Controllers/SwapTrade2Controller.cs b/YLErpWeb/Controllers/SwapTrade2Controller.cs index 6378b5f7..7dbb0d69 100644 --- a/YLErpWeb/Controllers/SwapTrade2Controller.cs +++ b/YLErpWeb/Controllers/SwapTrade2Controller.cs @@ -477,9 +477,10 @@ namespace YLErp.Web.Controllers /// 框架合约保存 /// /// + /// 特批重提标记:LackOfMoney=资金不足交易特批放行(须系统参数"允许交易特批"开启) /// [HttpPost] - public JsonResult tradeEditJson(trade req) + public JsonResult tradeEditJson(trade req, string additionalProcessing = null) { if (req == null) { @@ -490,16 +491,31 @@ namespace YLErp.Web.Controllers { req.id = DecryptInt(req.EncryptId); } + //特批放行判定与确认/审批环节同口径(processtradelogController/ApprovalService): + //系统参数 允许交易特批(SpecialOperateForTrade) 开启 且 显式带 LackOfMoney 标记重提 + var ignoreMoneyCheck = valuedateBLL.SystemDate.SpecialOperateForTrade == 1 && additionalProcessing == tradeBLL.LackOfMoney; try { bool edit = req.id != 0; - var r= swapTradeService.SaveTrade(req); + var r= swapTradeService.SaveTrade(req, ignoreMoneyCheck); Task.Run(() => { RealtimePnlCalc.RealtimeSwapPosition(new OptUserInfo(0, "互换实时持仓服务", OptUserFrom.Service)); }); return JsonSuccess("更新成功", r); } + catch (TradeLackOfMoneyException e) + { + //保存环节资金不足:开关开启时按确认/审批同一协议返回 AdditionalProcessing/LackOfMoney, + //UI 弹"交易特批"确认后带 additionalProcessing=LackOfMoney 重提放行;开关关闭时按保存失败拦截 + if (valuedateBLL.SystemDate.SpecialOperateForTrade == 1) + { + LogFactory.GetLogger("交易保存").Info("保存资金不足待特批:" + e.Message); + return JsonSuccessData(new { proccessType = "AdditionalProcessing", type = tradeBLL.LackOfMoney, message = e.Message }); + } + LogFactory.GetLogger("交易保存").Error(e); + return JsonError("保存失败:" + e.Message); + } catch (Exception e) { LogFactory.GetLogger("交易保存").Error(e); diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js index 38e6045e..70d0d69e 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapTradeEdit.js @@ -817,12 +817,41 @@ const vue = new Vue({ "补充协议编号": $("#SupProtocolCode").val() }; this.trade.trade_extend.ExtendJson = JSON.stringify(this.trade.trade_extend.ExtendObj); - main.post("/swaptrade2/tradeEditJson", this.trade).done(function (resp) { - window.location.href = "/swaptrade2/tradeview?enid=" + resp.obj.EncryptId; - if (window.parent && window.parent.reloadtrade) { - window.parent.reloadtrade(); + //R4 保存环节资金校验:资金不足且系统开启"允许交易特批"时,服务端按确认/审批同一协议返回 + //AdditionalProcessing/LackOfMoney——弹"交易特批"确认,带 additionalProcessing=LackOfMoney 重提放行 + var thisObj = this; + var doSave = function (additionalProcessing) { + var url = "/swaptrade2/tradeEditJson"; + if (!main.isEmpty(additionalProcessing)) { + url += "?additionalProcessing=" + additionalProcessing; } - }); + main.post(url, thisObj.trade).done(function (resp) { + if (resp.obj && resp.obj.proccessType == "AdditionalProcessing") { + if (resp.obj.type == "LackOfMoney") { + var htmlContent = '
' + resp.obj.message + '
'; + var lackMoneyConfirmLayer = main.open2("提示", + htmlContent, + { + area: ["430px", "175px"], + btn: ['交易特批', '取消'], + yes: function (index, layero) { + var layerIndex = lackMoneyConfirmLayer; + main.confirm("客户资金或授信不足,强制保存会导致本机构产生风险!要继续特批保存?", function () { + layer.close(layerIndex); + doSave("LackOfMoney"); + }); + } + }); + } + return; + } + window.location.href = "/swaptrade2/tradeview?enid=" + resp.obj.EncryptId; + if (window.parent && window.parent.reloadtrade) { + window.parent.reloadtrade(); + } + }); + }; + doSave(); }, changeMainProtocolCode() { this.getSupProtocolCode();