From 880489e2dcd7a7da4604127b9bfadc5d029f56c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=94=A6=E9=BA=9F=20=E7=8E=8B?= Date: Thu, 27 Aug 2026 18:50:30 +0800 Subject: [PATCH] =?UTF-8?q?BugFix=20=E8=B5=84=E9=87=91=E7=8A=B6=E5=86=B5?= =?UTF-8?q?=E7=9A=84=E5=88=9D=E5=A7=8B=E4=BF=9D=E8=AF=81=E9=87=91=E5=92=8C?= =?UTF-8?q?=E6=8E=88=E4=BF=A1=E9=A2=9D=E5=BA=A6=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YLErp.Core/Models/ClientSettleBalance.cs | 8 +++++- .../BLL/EodSettlement/ClientBalanceUtility.cs | 12 +++++++++ .../Margin/SwapSpanBalanceQueryService.cs | 25 +++++++++++++++++-- .../Scripts/app/client/tradeMarketReport.js | 7 +++--- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Framework/YLErp.Core/Models/ClientSettleBalance.cs b/Framework/YLErp.Core/Models/ClientSettleBalance.cs index 087ea1c1..e9d9dc6d 100644 --- a/Framework/YLErp.Core/Models/ClientSettleBalance.cs +++ b/Framework/YLErp.Core/Models/ClientSettleBalance.cs @@ -1,4 +1,4 @@ -using Qdp.Foundation.Utilities; +using Qdp.Foundation.Utilities; using System.ComponentModel.DataAnnotations.Schema; using YLErp.DBModels; @@ -253,6 +253,12 @@ namespace YLErp.Models /// public double TotalCredit { get; set; } + /// + /// 原始授信额度(展示用:credit 表 Σ(OriginalCredit ?? Credit),未经 MaxCreditUseRatio 折算; + /// TotalCredit 仍是折算后值,供可用资金/追保公式使用) + /// + public double OriginalTotalCredit { get; set; } + /// /// 用户可用的名义本金规模 /// diff --git a/YLErpDAL/BLL/EodSettlement/ClientBalanceUtility.cs b/YLErpDAL/BLL/EodSettlement/ClientBalanceUtility.cs index d4158fbe..a65ba73f 100644 --- a/YLErpDAL/BLL/EodSettlement/ClientBalanceUtility.cs +++ b/YLErpDAL/BLL/EodSettlement/ClientBalanceUtility.cs @@ -303,6 +303,16 @@ namespace YLErp.BLL.EodSettlement var usedCreditDic = ClientCreditInoutService.GetUsedCreditByClients(clientIdS, db); var swapInitMarginDic = SwapSpanBalanceQueryService.GetSwapInitMarginByClients(clientIdS, lastDate, db); var swapAdditionalDic = SwapSpanBalanceQueryService.GetTradeAdditionalMarginByClients(clientIdS, lastDate, db); + //原始授信额度(展示用):与 EOD 写入 clientbalancedaily.Credit 同批过滤条件(EodClientBalanceCalc :68), + //取 Σ(OriginalCredit ?? Credit) 不经比例折算;TotalCredit 仍为折算后值供公式使用 + var originalCreditDic = db.credit.AsNoTracking() + .Where(t => t.ClientId != null && clientIdS.Contains(t.ClientId.Value) + && t.ProcessStatus == "已审批" + && (!t.CreditDeadLine.HasValue || t.CreditDeadLine >= lastDate) + && (!t.CreditStartDate.HasValue || t.CreditStartDate <= lastDate)) + .GroupBy(t => t.ClientId.Value) + .Select(g => new { ClientId = g.Key, Sum = g.Sum(t => (t.OriginalCredit ?? t.Credit) ?? 0d) }) + .ToDictionary(x => x.ClientId, x => x.Sum); foreach (var data in endDatas) { @@ -319,6 +329,7 @@ namespace YLErp.BLL.EodSettlement balance.TotalCredit = data.TotalCredit; + balance.OriginalTotalCredit = originalCreditDic.TryGetValue(data.ClientId, out var originalCredit) ? originalCredit : 0; balance.PayableMargin = data.PayableMargin; balance.GuaranteesTotalAmount = data.GuaranteesTotalAmount; balance.FrozenMarginMoney = data.FrozenMarginMoney; @@ -671,6 +682,7 @@ namespace YLErp.BLL.EodSettlement DicTotal.AvailableAmount += dc.Value.AvailableAmount; DicTotal.TotalMarginTotal += dc.Value.TotalMargin; DicTotal.TotalCredit += dc.Value.TotalCredit; + DicTotal.OriginalTotalCredit += dc.Value.OriginalTotalCredit; DicTotal.WinLoss += dc.Value.WinLoss; DicTotal.TdWinLoss += dc.Value.TdWinLoss; DicTotal.PositionPremiumNetCash += dc.Value.PositionPremiumNetCash; diff --git a/YLErpDAL/Modules/SwapModule/Margin/SwapSpanBalanceQueryService.cs b/YLErpDAL/Modules/SwapModule/Margin/SwapSpanBalanceQueryService.cs index 0aecb695..ec26f6cf 100644 --- a/YLErpDAL/Modules/SwapModule/Margin/SwapSpanBalanceQueryService.cs +++ b/YLErpDAL/Modules/SwapModule/Margin/SwapSpanBalanceQueryService.cs @@ -8,7 +8,8 @@ namespace YLErp.Modules.SwapModule.Margin /// /// R2 阶段三 §3.2 估值报告/可用资金查询输入(静态查询,供 ClientBalanceUtility 与 RealTimeClientBanlanceService 共用,保证三处口径一致)。 /// 口径: - /// - 互换初始保证金(净收取为正)= 客户 应付预付金 流水收付净额取反(客户应付入金记负、平仓返还为正,取负号后净收取为正); + /// - 互换初始保证金(净收取为正)= 客户 应付预付金 流水收付净额取反 + 初始预付金授信占用净额 + /// (授信垫付的初始预付金无资金流水,2026-08-27 补入口径,否则授信垫付客户初始保证金展示为 0); /// - 交易维度追加保证金(合约维度)= Σ(维持保证金 − 累计保证金): /// 维持保证金取当日 trade_span.Spv(区间追保结构引擎产出,我方净收取为正); /// 累计保证金 = 该交易 应付预付金+追加保证金 流水收付净额 + 追加保证金授信占用净额(§0 口径,阶段四 §4.1 起) @@ -19,6 +20,8 @@ namespace YLErp.Modules.SwapModule.Margin { /// /// 客户维度输入:互换初始保证金(净收取为正,按客户汇总)。 + /// 初始保证金 = 应付预付金流水收付净额 + 初始预付金授信占用净额(非"追加保证金"前缀、关联交易)—— + /// 授信垫付的初始预付金不产生资金流水,只算流水会把授信垫付部分漏掉(展示为 0)。 /// public static Dictionary GetSwapInitMarginByClients(List clientIds, DateTime valueDate, YLContext db) { @@ -37,8 +40,26 @@ namespace YLErp.Modules.SwapModule.Margin .Select(x => new { ClientId = x.ClientId ?? 0, Money = x.Money ?? 0d }) .ToList(); - return flows.GroupBy(x => x.ClientId) + var result = flows.GroupBy(x => x.ClientId) .ToDictionary(g => g.Key, g => -g.Sum(x => x.Money)); + + //初始预付金的授信占用净额(占用记正/释放记负,Σ(amount) 即净已缴;trade_id != null 排除人工调整类记录, + //"追加保证金"前缀为 EOD 追保占用,不计入初始保证金) + var initCredit = db.client_credit_inout.AsNoTracking() + .Where(x => clientIds.Contains(x.client_id) + && x.trade_id != null + && x.happen_date <= valueDate + && (x.remark == null || !x.remark.StartsWith(ClientCreditInoutService.AdditionalMarginRemark))) + .GroupBy(x => x.client_id) + .Select(g => new { ClientId = g.Key, Sum = g.Sum(x => x.amount) }) + .ToList(); + + foreach (var item in initCredit) + { + result[item.ClientId] = (result.TryGetValue(item.ClientId, out var cash) ? cash : 0d) + item.Sum; + } + + return result; } /// diff --git a/YLErpWeb/wwwroot/Scripts/app/client/tradeMarketReport.js b/YLErpWeb/wwwroot/Scripts/app/client/tradeMarketReport.js index 7e3f4cc2..74969fe8 100644 --- a/YLErpWeb/wwwroot/Scripts/app/client/tradeMarketReport.js +++ b/YLErpWeb/wwwroot/Scripts/app/client/tradeMarketReport.js @@ -1,4 +1,4 @@ -var g_grid = {}; +var g_grid = {}; $(function () { var PostData = {}; var calcDate = page.ValueDate; @@ -291,7 +291,8 @@ function SearchClientBalance() { main.post("/trade_span/GetClientLatestBalance", { clientId: $("#ClientId").val(), ValueDateFrom: param.ValueDateStart, ValueDateTo: param.ValueDateEnd, IsClientBalanceGap: param.IsClientBalanceGap, IsGetOuterMarginGap: param.IsGetOuterMarginGap, ParentFlag: param.ParentFlag }).done(function (data) { $("#LastDayRemainFund").text(numFormart(data.LastDayRemainFund)); //R2 阶段三 §3.2 口径(BUG-07 修正,与邮件/Excel 报告 SettlementReportService 同源): - //初始保证金=SwapInitMargin(应付预付金净额)、维持保证金=−MySideMargin(client_span 维持保证金反号聚合) + //初始保证金=SwapInitMargin(应付预付金净额+初始预付金授信占用净额)、维持保证金=−MySideMargin(client_span 维持保证金反号聚合)、 + //授信额度=OriginalTotalCredit(原始授信值,未经最大可用比例折算;公式计算仍用折算后 TotalCredit) $("#SwapInitMargin").text(numFormart(data.SwapInitMargin)); $("#WinLoss").text(numFormart(data.WinLoss)); $("#CashInCashOutChange").text(numFormart(data.NetFundAll)); @@ -305,7 +306,7 @@ function SearchClientBalance() { $("#MarginByPayableMargin").text(numFormart(data.MarginByPayableMarginTotal)); $("#ToDayRemainFund").text(numFormart(data.AmountFund)); $("#DesirableFund").text(numFormart(data.DesirableFundTotal)); - $("#TotalCredit").text(numFormart(data.TotalCredit)); + $("#TotalCredit").text(numFormart(data.OriginalTotalCredit)); $("#UsedCredit").text(numFormart(data.UsedCredit)); });