feat:根据ai merge意见修改:dbContext取消与单例riskEngienService的绑定,反射代码修改。
支持老风控Error情况下的二次特批
This commit is contained in:
@@ -66,5 +66,8 @@ namespace YLErp.DBModels
|
||||
|
||||
[NotMapped]
|
||||
public List<string> ApprovalRuleIds { get; set; } = new List<string>();
|
||||
|
||||
[NotMapped]
|
||||
public QuotaTrialStatusEnum? OldRiskTrialStatus { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using BaseOUDAL;
|
||||
using BaseOUDAL;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using YLErp.Enums;
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace YLErp.Model
|
||||
this.AvailableForClient = obj.AvailableForClient;
|
||||
this.Remark = obj.Remark;
|
||||
this.TrialSource = obj.TrialSource;
|
||||
this.OldRiskTrialStatus = obj.OldRiskTrialStatus;
|
||||
this.OptId = obj.OptId;
|
||||
this.OptName = obj.OptName;
|
||||
this.OptDate = obj.OptDate;
|
||||
|
||||
@@ -519,7 +519,9 @@ namespace YLErp.Modules.RiskEngine
|
||||
/// </summary>
|
||||
private List<RiskRule> LoadRulesFromDb()
|
||||
{
|
||||
var rules = DbContext.glms_risk_rule
|
||||
using var dbContext = DbContextFactory.GetYLDbContext();
|
||||
|
||||
var rules = dbContext.glms_risk_rule
|
||||
.AsNoTracking()
|
||||
.OrderByDescending(r => r.UpdateDate ?? r.OptDate)
|
||||
.Select(r => new RiskRule
|
||||
@@ -736,8 +738,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
//{
|
||||
// Id = 1000014,
|
||||
// RuleName = "非债券类价格偏离(本地)",
|
||||
// RuleText = "取值字段:通过 DbContext.swap_position 按 TradeId 取 PosiGrossPrice,对应普通收益互换页面填写的期初标的交割全价%,库内为 1 左右原值;通过 DbContext.eod_stock_price / eod_commodity_future_price 按当前交易标的和交易日前日期取上一日收盘价 ClosePrice。计算逻辑:按 ABS(PosiGrossPrice×100-ClosePrice) 计算绝对价差,价差大于 5 时触发审批。",
|
||||
// RuleExpr = "Math.Abs(DbContext.swap_position.First(p => p.SwapTradeId == TradeId).PosiGrossPrice * 100m - Convert.ToDecimal((DbContext.eod_stock_price.Where(e => e.UnderlyingCode == DbContext.trade.First(t => t.id == TradeId).UnderlyingCode && e.ValueDate < DbContext.trade.First(t => t.id == TradeId).TradeDate.Value.Date).OrderByDescending(e => e.ValueDate).Select(e => (double?)e.ClosePrice).FirstOrDefault() ?? DbContext.eod_commodity_future_price.Where(e => e.UnderlyingCode == DbContext.trade.First(t => t.id == TradeId).UnderlyingCode && e.ValueDate < DbContext.trade.First(t => t.id == TradeId).TradeDate.Value.Date).OrderByDescending(e => e.ValueDate).Select(e => (double?)e.ClosePrice).FirstOrDefault()).Value)) > 5m",
|
||||
// RuleText = "取值字段:通过 DbContext.swap_position 按 TradeId 取 PosiGrossPrice,对应普通收益互换页面填写的期初标的价格,库内为 1 左右原值;通过 DbContext.eod_commodity_future_price 按当前交易标的和交易日前日期取上一日收盘价 ClosePrice。计算逻辑:按 ABS(PosiGrossPrice×100-ClosePrice) 计算绝对价差,价差大于 5 时触发审批。",
|
||||
// RuleExpr = "Math.Abs(DbContext.swap_position.First(p => p.SwapTradeId == TradeId).PosiGrossPrice * 100m - Convert.ToDecimal(DbContext.eod_commodity_future_price.Where(e => e.UnderlyingCode == DbContext.trade.First(t => t.id == TradeId).UnderlyingCode && e.ValueDate < DbContext.trade.First(t => t.id == TradeId).TradeDate.Value.Date).OrderByDescending(e => e.ValueDate).First().ClosePrice)) > 5m",
|
||||
// Version = 1,
|
||||
// Status = RiskRuleStatus.Active,
|
||||
// OptId = 0,
|
||||
@@ -752,8 +754,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
//{
|
||||
// Id = 1000015,
|
||||
// RuleName = "单一交易对手累计标的数量超阈值(本地)",
|
||||
// RuleText = "取值字段:通过 DbContext.trade 按 TradeId 取当前交易对手 ClientId,再查询同一交易对手存续/审批中交易的去重标的数量。计算逻辑:同一交易对手累计标的数量超过 10 个时触发审批。",
|
||||
// RuleExpr = "DbContext.trade.Where(t => t.ValidState != \"InValid\" && t.ClientId == DbContext.trade.First(x => x.id == TradeId).ClientId && t.ParentTradeId == 0 && (ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus) || t.TradeStatus == \"审批中\")).Select(t => t.UnderlyingId).Distinct().Count() > 10",
|
||||
// RuleText = "取值字段:通过 DbContext.trade 按 TradeId 取当前交易对手 ClientId,再查询同一交易对手存续/审批中交易对应的 swap_position.UnderlyingCode 去重数量。计算逻辑:同一交易对手累计标的数量超过 10 个时触发审批。",
|
||||
// RuleExpr= DbContext.swap_position.Where(p => !string.IsNullOrEmpty(p.UnderlyingCode) && p.IsInitial && !p.Invalid && DbContext.trade.Any(t => t.id == p.SwapTradeId && t.ValidState != "InValid" && t.ClientId == DbContext.trade.First(x => x.id == TradeId).ClientId && t.ParentTradeId == 0 && (ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus) || t.TradeStatus == "审批中"))).Select(p => p.UnderlyingCode).Distinct().Count() > 10
|
||||
// Version = 1,
|
||||
// Status = RiskRuleStatus.Active,
|
||||
// OptId = 0,
|
||||
@@ -768,8 +770,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
//{
|
||||
// Id = 1000016,
|
||||
// RuleName = "多头支付固定端利率偏离(本地)",
|
||||
// RuleText = "取值字段:通过 DbContext.trade 按 TradeId 取当前交易的 FixedRate,并结合 BuySell 判断多头方向。计算逻辑:当 BuySell 表示多头且 FixedRate 有值时,先以 2.5% 作为本地测试基准,若 ABS(FixedRate-0.025)/0.025×100% 大于 5%,则触发审批。",
|
||||
// RuleExpr = "DbContext.trade.First(t => t.id == TradeId).BuySell == \"Buy\" && DbContext.trade.First(t => t.id == TradeId).FixedRate.HasValue && Math.Abs((DbContext.trade.First(t => t.id == TradeId).FixedRate.Value - 0.025d) / 0.025d) * 100d > 5d",
|
||||
// RuleText = "取值字段:通过 DbContext.swap_position 按 TradeId 取利息端支付方向记录的 InterestRateDefault,对应互换交易-利息端-利率文本框数值;通过 DbContext.eod_commodity_future_price 按 FutureContractId=FR007(模型属性 UnderlyingCode)和交易日前日期取最近一条 ClosePrice。计算逻辑:按 ABS(InterestRateDefault-FR007) 计算利率差,差值小于 5% 时触发审批。",
|
||||
// RuleExpr = "Math.Abs(DbContext.swap_position.First(p => p.SwapTradeId == TradeId && p.InterestDirection == 2).InterestRateDefault - Convert.ToDecimal(DbContext.eod_commodity_future_price.Where(e => e.UnderlyingCode == "FR007" && e.ValueDate < DbContext.trade.First(t => t.id == TradeId).TradeDate.Value.Date).OrderByDescending(e => e.ValueDate).First().ClosePrice)) < 0.05m",
|
||||
// Version = 1,
|
||||
// Status = RiskRuleStatus.Active,
|
||||
// OptId = 0,
|
||||
@@ -851,7 +853,9 @@ namespace YLErp.Modules.RiskEngine
|
||||
|
||||
private List<RiskRuleApplication> LoadApplicationsFromDb()
|
||||
{
|
||||
var applications = DbContext.glms_risk_rule_application
|
||||
using var dbContext = DbContextFactory.GetYLDbContext();
|
||||
|
||||
var applications = dbContext.glms_risk_rule_application
|
||||
.AsNoTracking()
|
||||
.OrderByDescending(a => a.UpdateDate ?? a.OptDate)
|
||||
.Select(a => new RiskRuleApplication
|
||||
@@ -992,22 +996,18 @@ namespace YLErp.Modules.RiskEngine
|
||||
|
||||
/// <summary>
|
||||
/// 读取交易的资产簿账户ID。
|
||||
/// 当前先按 BookId 取值;如果后续真实字段不是 BookId,再统一调整这里即可。
|
||||
/// </summary>
|
||||
private object GetTradeAssetBookId(YLErp.DBModels.trade trade)
|
||||
{
|
||||
var property = trade.GetType().GetProperty("BookId");
|
||||
return property?.GetValue(trade);
|
||||
return trade.AssetId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取交易的标的类型。
|
||||
/// 当前先按 UnderlyingInstrumentType 取值;如果后续真实字段名不同,再统一调整这里即可。
|
||||
/// </summary>
|
||||
private object GetTradeUnderlyingType(YLErp.DBModels.trade trade)
|
||||
{
|
||||
var property = trade.GetType().GetProperty("UnderlyingInstrumentType");
|
||||
return property?.GetValue(trade);
|
||||
return trade.UnderlyingInstrumentType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4470,11 +4470,16 @@ namespace YLErp.Modules.RiskModule
|
||||
|
||||
public bool QuotaCheck(ref TradeOpenResult res, bool ignoreRiskWarning, IEnumerable<string> ignoreRiskRuleIds = null)
|
||||
{
|
||||
if (res == null || res.Trade == null)
|
||||
if (res == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(res));
|
||||
}
|
||||
|
||||
if (res.Trade == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(res.Trade));
|
||||
}
|
||||
|
||||
var tradeId = (res.Trade.ParentTradeId == 0 || res.Trade.IsGroup != 0) ? res.Trade.id : res.Trade.ParentTradeId;
|
||||
var tradeNumber = DbContext.trade.Where(O => O.id == tradeId).Select(O => O.TradeNumber).FirstOrDefault();
|
||||
var trialService = new QuotaMonitorService(this);
|
||||
@@ -4518,8 +4523,9 @@ namespace YLErp.Modules.RiskModule
|
||||
var isRiskApprovalWarning = quotaObj.TrialStatus == QuotaTrialStatusEnum.RiskWarning
|
||||
&& !string.IsNullOrWhiteSpace(quotaObj.RiskWarningDetails)
|
||||
&& (quotaObj.ApprovalRuleIds?.Any() ?? false);
|
||||
//当前为老风控特批,不是新风控需审批
|
||||
res.OldRiskNeedSpecialApproval = quotaObj.TrialStatus == QuotaTrialStatusEnum.Warning;
|
||||
//老风控试算不通过时,延用master逻辑进入交易特批/二次处理;新风控需审批由RiskWarning单独处理
|
||||
res.OldRiskNeedSpecialApproval = quotaObj.OldRiskTrialStatus.HasValue
|
||||
&& quotaObj.OldRiskTrialStatus.Value != QuotaTrialStatusEnum.Success;
|
||||
if (isRiskApprovalWarning)
|
||||
{
|
||||
var currentApprovalRuleIds = quotaObj.ApprovalRuleIds ?? new List<string>();
|
||||
@@ -5148,6 +5154,7 @@ namespace YLErp.Modules.RiskModule
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quotaWarningStatus && riskWarningStatus && fundStatus && quotaStatus)
|
||||
{
|
||||
result.TrialStatus = QuotaTrialStatusEnum.Success;
|
||||
@@ -5172,6 +5179,7 @@ namespace YLErp.Modules.RiskModule
|
||||
result.QuotaWarningDetails = quotaWarningMsg ?? "";
|
||||
result.AvailableForClient = availableMsg ?? "";
|
||||
result.TrialSource = trialSource;
|
||||
result.OldRiskTrialStatus = result.TrialStatus;
|
||||
_logger.Info($"[限额试算] 试算完成 - tradeId: {tradeId}, TrialStatus: {result.TrialStatus}, FundCheck: {fundStatus}, QuotaCheck: {quotaStatus}");
|
||||
|
||||
// ===== 新风控引擎接入点(设计文档 4.6.1) =====
|
||||
|
||||
@@ -2513,7 +2513,7 @@ namespace YLErp.Web.Controllers
|
||||
{
|
||||
if (result.OldRiskNeedSpecialApproval)
|
||||
{
|
||||
return JsonSuccessData(new { proccessType = "AdditionalProcessing", source = "OldRiskQuotaTrialError", type = tradeBLL.LackOfMoney, TrialDataId = result.TrialDataId, message = result.errorMsg, typecode = result.type });
|
||||
return JsonSuccessData(new { proccessType = "AdditionalProcessing", source = "OldRiskQuotaTrialError", type = PS.Config.ErpElement.Company == Configuration.CompanyEnum.天风 || config.SpecialOperateForTrade == 1 ? tradeBLL.LackOfMoney : "", TrialDataId = result.TrialDataId, message = result.errorMsg, typecode = result.type });
|
||||
}
|
||||
return JsonSuccessData(new { proccessType = "QuotaTrialError", TrialDataId = result.TrialDataId, message = result.errorMsg, typecode = result.type });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user