diff --git a/Framework/YLErp.Core/DBModels/QuotaTrial.cs b/Framework/YLErp.Core/DBModels/QuotaTrial.cs index c4e95df1..650af814 100644 --- a/Framework/YLErp.Core/DBModels/QuotaTrial.cs +++ b/Framework/YLErp.Core/DBModels/QuotaTrial.cs @@ -66,5 +66,8 @@ namespace YLErp.DBModels [NotMapped] public List ApprovalRuleIds { get; set; } = new List(); + + [NotMapped] + public QuotaTrialStatusEnum? OldRiskTrialStatus { get; set; } } } diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_appconfig.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_appconfig.sql new file mode 100644 index 00000000..a20a1ea1 --- /dev/null +++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_appconfig.sql @@ -0,0 +1,28 @@ +-- 新风控二次审批确认有效期配置 +-- 幂等:已存在则不重复插入 +INSERT INTO appconfig +( + PGroup, + PName, + PValue, + PType, + Remark, + CreateTime, + OptDate +) +SELECT + 'ProjectConfig', + 'Trade.RiskWarningConfirmExpireSeconds', + '300', + 'int', + '新风控二次审批确认有效期(秒),超过后需重新校验', + NOW(), + NOW() +FROM DUAL +WHERE NOT EXISTS +( + SELECT 1 + FROM appconfig + WHERE PGroup = 'ProjectConfig' + AND PName = 'Trade.RiskWarningConfirmExpireSeconds' +); diff --git a/YLErpDAL/Model/QuotaTrial.cs b/YLErpDAL/Model/QuotaTrial.cs index 04d16d2b..60d8e7dd 100644 --- a/YLErpDAL/Model/QuotaTrial.cs +++ b/YLErpDAL/Model/QuotaTrial.cs @@ -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; diff --git a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs index efd8b91d..45d4432d 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs @@ -519,7 +519,9 @@ namespace YLErp.Modules.RiskEngine /// private List 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 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 /// /// 读取交易的资产簿账户ID。 - /// 当前先按 BookId 取值;如果后续真实字段不是 BookId,再统一调整这里即可。 /// private object GetTradeAssetBookId(YLErp.DBModels.trade trade) { - var property = trade.GetType().GetProperty("BookId"); - return property?.GetValue(trade); + return trade.AssetId; } /// /// 读取交易的标的类型。 - /// 当前先按 UnderlyingInstrumentType 取值;如果后续真实字段名不同,再统一调整这里即可。 /// private object GetTradeUnderlyingType(YLErp.DBModels.trade trade) { - var property = trade.GetType().GetProperty("UnderlyingInstrumentType"); - return property?.GetValue(trade); + return trade.UnderlyingAssetClass; } } } diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs index 68219350..a7a186d9 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs @@ -37,7 +37,7 @@ namespace YLErp.Modules.RiskEngine /// /// 应用状态。 /// 约定: - /// 1 = Active(已生效) + /// 1 = Active(已启用) /// 2 = Disabled(已停用) /// 3 = Deleted(已删除) /// 在实际执行时,通常只加载 Active 状态的应用配置。 diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs index 783a6bbc..be59ce93 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs @@ -1,6 +1,8 @@ using BaseOUDAL; using Newtonsoft.Json; +using System.Linq; using System.Linq.Expressions; +using System.Text.RegularExpressions; using YLErp.BLL; using YLErp.DBModels; using YLErp.Modules.RiskEngine.Dto; @@ -113,7 +115,7 @@ using YLErp.Modules.RiskEngine.Dto; ValidateTriggerPoints(triggerPoints) 触发时点校验(5 个合法时点) ValidateScopeFields(req) Scope 字段校验(全局互斥 + ID 格式校验) ValidateIdList(idList, fieldName) ID 列表格式校验 - TryRefreshCache() 安全调用 RefreshCache(失败仅记日志) + RefreshOneRuleCache(ruleId) 单条规则缓存刷新(规则变更后调用) GetRuleOrThrow / GetApplicationOrThrow / GetVariableOrThrow 实体获取快捷方法 【关键设计决策】 @@ -124,7 +126,7 @@ using YLErp.Modules.RiskEngine.Dto; 5. ConditionJson 校验:变量存在性(按 VariableId)+ 操作符合法性(按 DataType 映射)+ 类型匹配 + 阈值变量引用 6. RuleExpr:自由文本模式下前端直接编辑,后端做基础语法校验(括号匹配 + 变量引用校验) 7. Scope 字段:逗号分隔字符串存储,全局适用时不允许指定其他维度 - 8. 缓存刷新:写操作后调用 TryRefreshCache(),失败仅记日志不影响操作结果 + 8. 缓存刷新:规则变更后调用 RefreshOneRuleCache(ruleId),应用变更后调用 RefreshApplication() 9. 批量操作:单事务批量,全部成功或全部失败 10. 变量缓存:5 分钟本地 HashSet 缓存,CRUD 后 InvalidateVariableCache() 11. 审计日志:16 种操作类型,CRUD + 审计日志同一事务,SnapshotData 存储版本快照 @@ -172,7 +174,7 @@ using YLErp.Modules.RiskEngine.Dto; 【注意事项】 1. RiskEngineService 由另一个团队开发实现,本服务通过 GetInstance() 获取单例引用 - 2. 所有写操作后必须调用 TryRefreshCache(),确保引擎缓存与数据库一致 + 2. 规则变更后调用 RefreshOneRuleCache(ruleId),应用变更后调用 RefreshApplication(),变量变更不触发引擎缓存刷新 3. 变量删除为硬删除(物理删除),规则/应用删除为软删除(Status=Deleted) 4. ExportAuditLogs 当前为占位实现,Excel 导出功能待后续迭代 5. VariableExpr 当前仅做基础长度校验(≤10000),完整编译校验待引入 Roslyn 库 @@ -539,23 +541,44 @@ namespace YLErp.Modules.RiskEngine } /// - /// 校验规则 ID 列表是否全部 Active + /// 校验规则状态可用性并确保编译缓存就绪。 + /// 返回不可用规则信息列表,列表为空表示全部通过。 + /// 规则不可用的情况:已删除、已停用、编译缓存缺失且刷新失败。 /// - private void ValidateRuleIdsActive(string ruleIds) + private List ValidateAndEnsureRuleCache(string ruleIds) { + var errors = new List(); var ids = ParseRuleIds(ruleIds); var rules = DbContext.glms_risk_rule .Where(r => ids.Contains(r.id) && r.Status != RiskRuleStatus.Deleted) .ToList(); if (rules.Count != ids.Count) - throw new ServiceException("部分关联规则不存在或已删除"); + { + var missingIds = ids.Except(rules.Select(r => (long)r.id)).ToList(); + foreach (var id in missingIds) + errors.Add($"规则ID {id} 不存在或已删除"); + return errors; + } foreach (var rule in rules) { if (rule.Status == RiskRuleStatus.Disabled) - throw new ServiceException($"关联规则 '{rule.RuleName}' 已停用,无法创建/启用应用配置"); + { + errors.Add($"规则 '{rule.RuleName}' 已停用"); + continue; + } + + // 检查编译缓存,未命中则刷新 + if (!RuleCompiledCache.TryGet(rule.id.ToString(), out _)) + { + var result = RiskEngineService.GetInstance().RefreshOneRuleCache(rule.id); + if (!result.Success) + errors.Add($"规则 '{rule.RuleName}' 编译失败:{result.ErrorMessage}"); + } } + + return errors; } /// @@ -850,7 +873,7 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("RULE_DELETE", "RULE", ruleId, rule.RuleName, "删除规则"); DbContext.SaveChanges(); - TryRefreshCache(); + RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId); } /// @@ -862,6 +885,10 @@ namespace YLErp.Modules.RiskEngine if (rule == null) throw new ServiceException("仅已停用的规则可以启用"); + var compileResult = RuleCompiler.ValidateAndCompileFormula(ruleId, rule.RuleExpr); + if (!compileResult.Success) + throw new ServiceException($"规则表达式编译失败:{compileResult.ErrorMessage}"); + rule.Status = RiskRuleStatus.Active; rule.UpdateOptId = UserId; rule.UpdateOptName = UserName; @@ -870,7 +897,7 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("RULE_ENABLE", "RULE", ruleId, rule.RuleName, "启用规则"); DbContext.SaveChanges(); - TryRefreshCache(); + RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId); } /// @@ -880,7 +907,7 @@ namespace YLErp.Modules.RiskEngine { var rule = DbContext.glms_risk_rule.FirstOrDefault(r => r.id == ruleId && r.Status == RiskRuleStatus.Active); if (rule == null) - throw new ServiceException("仅已生效的规则可以停用"); + throw new ServiceException("仅已启用的规则可以停用"); rule.Status = RiskRuleStatus.Disabled; rule.UpdateOptId = UserId; @@ -890,7 +917,7 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("RULE_DISABLE", "RULE", ruleId, rule.RuleName, "停用规则"); DbContext.SaveChanges(); - TryRefreshCache(); + RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId); } /// @@ -966,7 +993,10 @@ namespace YLErp.Modules.RiskEngine } DbContext.SaveChanges(); - TryRefreshCache(); + foreach (var ruleId in ruleIds) + { + RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId); + } return new BatchOperationResult { @@ -1140,7 +1170,9 @@ namespace YLErp.Modules.RiskEngine /// public RiskApplicationDetail CreateApplication(CreateRiskApplicationReq req) { - ValidateRuleIdsActive(req.RuleIds); + var errors = ValidateAndEnsureRuleCache(req.RuleIds); + if (errors.Any()) + throw new ServiceException($"以下关联规则不可用:{string.Join(";", errors)}"); ValidateTriggerPoints(req.TriggerPoints); ValidateScopeFields(req); @@ -1201,7 +1233,11 @@ namespace YLErp.Modules.RiskEngine throw new ServiceException("应用配置已被其他用户修改,请重新加载后再编辑"); if (!string.IsNullOrWhiteSpace(req.RuleIds)) - ValidateRuleIdsActive(req.RuleIds); + { + var errors = ValidateAndEnsureRuleCache(req.RuleIds); + if (errors.Any()) + throw new ServiceException($"以下关联规则不可用:{string.Join(";", errors)}"); + } ValidateTriggerPoints(req.TriggerPoints); var scopeReq = new CreateRiskApplicationReq @@ -1266,7 +1302,9 @@ namespace YLErp.Modules.RiskEngine if (app == null) throw new ServiceException("仅已停用的应用配置可以启用"); - ValidateRuleIdsActive(app.RuleIds); + var errors = ValidateAndEnsureRuleCache(app.RuleIds); + if (errors.Any()) + throw new ServiceException($"以下关联规则不可用:{string.Join(";", errors)}"); app.Status = RiskRuleStatus.Active; app.UpdateOptId = UserId; @@ -1286,7 +1324,7 @@ namespace YLErp.Modules.RiskEngine { var app = DbContext.glms_risk_rule_application.FirstOrDefault(a => a.id == applicationId && a.Status == RiskRuleStatus.Active); if (app == null) - throw new ServiceException("仅已生效的应用配置可以停用"); + throw new ServiceException("仅已启用的应用配置可以停用"); app.Status = RiskRuleStatus.Disabled; app.UpdateOptId = UserId; @@ -1304,20 +1342,41 @@ namespace YLErp.Modules.RiskEngine /// public BatchOperationResult BatchEnableApplications(List applicationIds) { + _logger.Info($"[批量启用] 开始 - 传入应用数: {applicationIds?.Count ?? 0}, IDs: {string.Join(",", applicationIds ?? new List())}"); + var apps = DbContext.glms_risk_rule_application .Where(a => applicationIds.Contains(a.id) && a.Status == RiskRuleStatus.Disabled) .ToList(); + _logger.Info($"[批量启用] DB查询完成 - 匹配到 {apps.Count} 条已停用应用"); + if (apps.Count != applicationIds.Count) throw new ServiceException("部分应用配置不存在或当前状态不允许启用"); + var allErrors = new List(); foreach (var app in apps) { - ValidateRuleIdsActive(app.RuleIds); + _logger.Info($"[批量启用] 校验规则 - 应用ID: {app.id}, RuleIds: {app.RuleIds}"); + var errors = ValidateAndEnsureRuleCache(app.RuleIds); + _logger.Info($"[批量启用] 规则校验结果 - 应用ID: {app.id}, Errors: {(errors.Any() ? string.Join(";", errors) : "无")}"); + if (errors.Any()) + allErrors.Add($"应用 '{app.Description}':{string.Join(";", errors)}"); + } + + if (allErrors.Any()) + { + return new BatchOperationResult + { + Success = false, + TotalCount = applicationIds.Count, + SuccessCount = 0, + ErrorMessage = string.Join(";", allErrors) + }; } foreach (var app in apps) { + _logger.Info($"[批量启用] 写入状态 - 应用ID: {app.id}"); app.Status = RiskRuleStatus.Active; app.UpdateOptId = UserId; app.UpdateOptName = UserName; @@ -1326,8 +1385,11 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("APP_BATCH_ENABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量启用应用配置"); } + _logger.Info("[批量启用] 保存数据库..."); DbContext.SaveChanges(); + _logger.Info("[批量启用] 刷新应用缓存..."); RiskEngineService.GetInstance().RefreshApplication(); + _logger.Info("[批量启用] 完成"); return new BatchOperationResult { @@ -1342,15 +1404,20 @@ namespace YLErp.Modules.RiskEngine /// public BatchOperationResult BatchDisableApplications(List applicationIds) { + _logger.Info($"[批量停用] 开始 - 传入应用数: {applicationIds?.Count ?? 0}, IDs: {string.Join(",", applicationIds ?? new List())}"); + var apps = DbContext.glms_risk_rule_application .Where(a => applicationIds.Contains(a.id) && a.Status == RiskRuleStatus.Active) .ToList(); + _logger.Info($"[批量停用] DB查询完成 - 匹配到 {apps.Count} 条已启用应用"); + if (apps.Count != applicationIds.Count) throw new ServiceException("部分应用配置不存在或当前状态不允许停用"); foreach (var app in apps) { + _logger.Info($"[批量停用] 写入状态 - 应用ID: {app.id}"); app.Status = RiskRuleStatus.Disabled; app.UpdateOptId = UserId; app.UpdateOptName = UserName; @@ -1359,8 +1426,11 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("APP_BATCH_DISABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量停用应用配置"); } + _logger.Info("[批量停用] 保存数据库..."); DbContext.SaveChanges(); + _logger.Info("[批量停用] 刷新应用缓存..."); RiskEngineService.GetInstance().RefreshApplication(); + _logger.Info("[批量停用] 完成"); return new BatchOperationResult { @@ -1372,6 +1442,27 @@ namespace YLErp.Modules.RiskEngine #endregion + /// + /// 查询 ConditionJson 中引用了指定变量 ID 的规则(仅结构化模式) + /// 精确匹配 "VariableId":{id} 或 "ThresholdVariableId":{id},\b 防止 id=1 误匹配 id=10 + /// + private List GetRulesByVariableId(long variableId) + { + var allRules = DbContext.glms_risk_rule + .Where(r => r.Status != RiskRuleStatus.Deleted && r.ConditionJson != null) + .ToList(); + + if (allRules.Count == 0) return allRules; + + var idPattern = $@"""VariableId""\s*:\s*{variableId}\b"; + var thresholdPattern = $@"""ThresholdVariableId""\s*:\s*{variableId}\b"; + + return allRules.Where(r => + Regex.IsMatch(r.ConditionJson, idPattern) || + Regex.IsMatch(r.ConditionJson, thresholdPattern) + ).ToList(); + } + #region Variable Management /// @@ -1498,7 +1589,6 @@ namespace YLErp.Modules.RiskEngine } InvalidateVariableCache(); - TryRefreshCache(); return GetVariableDetail(entity.id); } @@ -1520,11 +1610,8 @@ namespace YLErp.Modules.RiskEngine if (req.DataType != variable.DataType) { - var varExpr = variable.VariableExpr; - var activeRefCount = DbContext.glms_risk_rule - .Count(r => r.Status == RiskRuleStatus.Active && - ((r.ConditionJson != null && r.ConditionJson.Contains(variable.id.ToString())) || - (r.RuleExpr != null && varExpr != null && r.RuleExpr.Contains(varExpr)))); + var activeRefCount = GetRulesByVariableId(variableId) + .Count(r => r.Status == RiskRuleStatus.Active); if (activeRefCount > 0) throw new ServiceException($"该变量被 {activeRefCount} 个生效中的规则引用,无法修改数据类型"); } @@ -1548,9 +1635,9 @@ namespace YLErp.Modules.RiskEngine if (variableExprChanged) { - // 编译校验:变量表达式变更后,需验证所有级联更新的规则表达式可编译 - var affectedRules = DbContext.glms_risk_rule - .Where(r => r.RuleExpr != null && r.RuleExpr.Contains(oldVariableExpr)) + // 结构化模式:通过 ConditionJson 中的 VariableId 找到受影响的规则 + var affectedRules = GetRulesByVariableId(variableId) + .Where(r => r.RuleExpr != null) .ToList(); var compileTasks = affectedRules.Select(r => @@ -1579,11 +1666,9 @@ namespace YLErp.Modules.RiskEngine WriteAuditLog("VAR_UPDATE", "VARIABLE", variableId, req.VariableName, $"修改变量:{variable.VariableName}"); - foreach (var rule in affectedRules) - { - WriteAuditLog("VAR_UPDATE_CASCADE", "RULE", rule.id, rule.RuleName, - $"变量 [{variable.VariableName}] VariableExpr 变更,级联更新规则 RuleExpr"); - } + var cascadedRuleIds = affectedRules.Select(r => r.id.ToString()).ToList(); + WriteAuditLog("VAR_UPDATE_CASCADE", "VARIABLE", variableId, req.VariableName, + $"变量 [{variable.VariableName}] VariableExpr 变更,级联更新规则 {string.Join("、", cascadedRuleIds)}"); DbContext.SaveChanges(); transaction.Commit(); @@ -1618,11 +1703,8 @@ namespace YLErp.Modules.RiskEngine { var variable = GetVariableOrThrow(variableId); - var varExpr = variable.VariableExpr; - var activeRefCount = DbContext.glms_risk_rule - .Count(r => r.Status == RiskRuleStatus.Active && - ((r.ConditionJson != null && r.ConditionJson.Contains(variable.id.ToString())) || - (r.RuleExpr != null && varExpr != null && r.RuleExpr.Contains(varExpr)))); + var activeRefCount = GetRulesByVariableId(variableId) + .Count(r => r.Status == RiskRuleStatus.Active); if (activeRefCount > 0) throw new ServiceException($"该变量被 {activeRefCount} 个生效中的规则引用,无法删除"); @@ -1632,7 +1714,6 @@ namespace YLErp.Modules.RiskEngine DbContext.SaveChanges(); InvalidateVariableCache(); - TryRefreshCache(); } /// diff --git a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs index a0817047..f2449805 100644 --- a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs +++ b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs @@ -4470,11 +4470,16 @@ namespace YLErp.Modules.RiskModule public bool QuotaCheck(ref TradeOpenResult res, bool ignoreRiskWarning, IEnumerable 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(); @@ -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) ===== diff --git a/YLErpWeb/Controllers/RiskRuleController.cs b/YLErpWeb/Controllers/RiskRuleController.cs index 28fbfeec..b30a905d 100644 --- a/YLErpWeb/Controllers/RiskRuleController.cs +++ b/YLErpWeb/Controllers/RiskRuleController.cs @@ -1,4 +1,5 @@ using Qdp.Foundation.Utilities; +using System.Threading.Tasks; using YLErp.DBModels; using YLErp.Modules.RiskEngine; using YLErp.Modules.RiskEngine.Dto; @@ -11,17 +12,19 @@ namespace YLErp.Web.Controllers { private readonly IYcLogger _logger = LogFactory.GetLogger("RiskRuleController"); + private RiskRuleService GetRiskRuleService() => new RiskRuleService(CurUser); + #region Rule Management [HttpGet("risk-rules")] [MyAuthorize("风险控制-风控规则查看")] /// 查询风控规则列表(分页) - public JsonResult QueryRiskRules(QueryRiskRuleReq req) + public async Task QueryRiskRules(QueryRiskRuleReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.QueryRuleList(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.QueryRuleList(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -38,12 +41,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-rules/{id}")] [MyAuthorize("风险控制-风控规则查看")] /// 获取风控规则详情 - public JsonResult GetRiskRule(long id) + public async Task GetRiskRule(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetRuleDetail(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetRuleDetail(id)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -60,12 +63,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-rules/{id}/versions")] [MyAuthorize("风险控制-风控规则查看")] /// 获取风控规则版本历史 - public JsonResult GetRiskRuleVersions(long id) + public async Task GetRiskRuleVersions(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetRuleVersions(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetRuleVersions(id)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -82,12 +85,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-rules")] [MyAuthorize("风险控制-风控规则新增")] /// 创建风控规则 - public JsonResult CreateRiskRule([FromBody] CreateRiskRuleReq req) + public async Task CreateRiskRule([FromBody] CreateRiskRuleReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.CreateRule(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.CreateRule(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -104,12 +107,12 @@ namespace YLErp.Web.Controllers [HttpPut("risk-rules/{id}")] [MyAuthorize("风险控制-风控规则编辑")] /// 更新风控规则 - public JsonResult UpdateRiskRule(long id, [FromBody] UpdateRiskRuleReq req) + public async Task UpdateRiskRule(long id, [FromBody] UpdateRiskRuleReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.UpdateRule(id, req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.UpdateRule(id, req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -126,12 +129,12 @@ namespace YLErp.Web.Controllers [HttpDelete("risk-rules/{id}")] [MyAuthorize("风险控制-风控规则删除")] /// 删除风控规则(软删除) - public JsonResult DeleteRiskRule(long id) + public async Task DeleteRiskRule(long id) { try { - var service = new RiskRuleService(CurUser); - service.DeleteRule(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.DeleteRule(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -148,12 +151,12 @@ namespace YLErp.Web.Controllers [HttpDelete("risk-rules/batch")] [MyAuthorize("风险控制-风控规则删除")] /// 批量删除风控规则 - public JsonResult BatchDeleteRiskRules([FromBody] List ids) + public async Task BatchDeleteRiskRules([FromBody] List ids) { try { - var service = new RiskRuleService(CurUser); - var result = service.BatchDeleteRules(ids); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.BatchDeleteRules(ids)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -170,12 +173,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-rules/{id}/enable")] [MyAuthorize("风险控制-风控规则启停")] /// 启用风控规则 - public JsonResult EnableRiskRule(long id) + public async Task EnableRiskRule(long id) { try { - var service = new RiskRuleService(CurUser); - service.EnableRule(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.EnableRule(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -192,12 +195,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-rules/{id}/disable")] [MyAuthorize("风险控制-风控规则启停")] /// 停用风控规则 - public JsonResult DisableRiskRule(long id) + public async Task DisableRiskRule(long id) { try { - var service = new RiskRuleService(CurUser); - service.DisableRule(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.DisableRule(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -214,12 +217,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-rules/{id}/applications")] [MyAuthorize("风险控制-风控规则查看")] /// 获取规则关联的应用配置列表 - public JsonResult GetRuleApplications(long id) + public async Task GetRuleApplications(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetRuleApplications(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetRuleApplications(id)); return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } }); } catch (ServiceException ex) @@ -236,12 +239,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-rules/list")] [MyAuthorize("风险控制-风控规则查看")] /// 获取所有启用规则列表(供下拉选择) - public JsonResult GetAllRiskRules() + public async Task GetAllRiskRules() { try { - var service = new RiskRuleService(CurUser); - var result = service.GetAllRuleList(); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetAllRuleList()); return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } }); } catch (ServiceException ex) @@ -262,12 +265,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-applications")] [MyAuthorize("风险控制-风控应用查看")] /// 查询应用配置列表(分页) - public JsonResult QueryRiskApplications(QueryRiskApplicationReq req) + public async Task QueryRiskApplications(QueryRiskApplicationReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.QueryApplicationList(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.QueryApplicationList(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -284,12 +287,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-applications/{id}")] [MyAuthorize("风险控制-风控应用查看")] /// 获取应用配置详情 - public JsonResult GetRiskApplication(long id) + public async Task GetRiskApplication(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetApplicationDetail(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetApplicationDetail(id)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -306,12 +309,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-applications")] [MyAuthorize("风险控制-风控应用新增")] /// 创建应用配置 - public JsonResult CreateRiskApplication([FromBody] CreateRiskApplicationReq req) + public async Task CreateRiskApplication([FromBody] CreateRiskApplicationReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.CreateApplication(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.CreateApplication(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -328,12 +331,12 @@ namespace YLErp.Web.Controllers [HttpPut("risk-applications/{id}")] [MyAuthorize("风险控制-风控应用编辑")] /// 更新应用配置 - public JsonResult UpdateRiskApplication(long id, [FromBody] UpdateRiskApplicationReq req) + public async Task UpdateRiskApplication(long id, [FromBody] UpdateRiskApplicationReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.UpdateApplication(id, req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.UpdateApplication(id, req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -350,12 +353,12 @@ namespace YLErp.Web.Controllers [HttpDelete("risk-applications/{id}")] [MyAuthorize("风险控制-风控应用删除")] /// 删除应用配置(软删除) - public JsonResult DeleteRiskApplication(long id) + public async Task DeleteRiskApplication(long id) { try { - var service = new RiskRuleService(CurUser); - service.DeleteApplication(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.DeleteApplication(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -372,12 +375,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-applications/{id}/enable")] [MyAuthorize("风险控制-风控应用启停")] /// 启用应用配置 - public JsonResult EnableRiskApplication(long id) + public async Task EnableRiskApplication(long id) { try { - var service = new RiskRuleService(CurUser); - service.EnableApplication(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.EnableApplication(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -394,12 +397,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-applications/{id}/disable")] [MyAuthorize("风险控制-风控应用启停")] /// 停用应用配置 - public JsonResult DisableRiskApplication(long id) + public async Task DisableRiskApplication(long id) { try { - var service = new RiskRuleService(CurUser); - service.DisableApplication(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.DisableApplication(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -416,12 +419,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-applications/batch-enable")] [MyAuthorize("风险控制-风控应用启停")] /// 批量启用应用配置 - public JsonResult BatchEnableRiskApplications([FromBody] List ids) + public async Task BatchEnableRiskApplications([FromBody] List ids) { try { - var service = new RiskRuleService(CurUser); - var result = service.BatchEnableApplications(ids); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.BatchEnableApplications(ids)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -438,12 +441,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-applications/batch-disable")] [MyAuthorize("风险控制-风控应用启停")] /// 批量停用应用配置 - public JsonResult BatchDisableRiskApplications([FromBody] List ids) + public async Task BatchDisableRiskApplications([FromBody] List ids) { try { - var service = new RiskRuleService(CurUser); - var result = service.BatchDisableApplications(ids); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.BatchDisableApplications(ids)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -464,12 +467,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-variables")] [MyAuthorize("风险控制-风控变量查看")] /// 查询变量列表 - public JsonResult QueryRiskVariables(QueryRiskVariableReq req) + public async Task QueryRiskVariables(QueryRiskVariableReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.QueryVariableList(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.QueryVariableList(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -486,12 +489,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-variables/{id}")] [MyAuthorize("风险控制-风控变量查看")] /// 获取变量详情 - public JsonResult GetRiskVariable(long id) + public async Task GetRiskVariable(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetVariableDetail(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetVariableDetail(id)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -508,12 +511,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-variables/list")] [MyAuthorize("风险控制-风控变量查看")] /// 获取所有变量列表(供下拉选择) - public JsonResult GetAllRiskVariables() + public async Task GetAllRiskVariables() { try { - var service = new RiskRuleService(CurUser); - var result = service.GetAllVariableList(); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetAllVariableList()); return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } }); } catch (ServiceException ex) @@ -530,12 +533,12 @@ namespace YLErp.Web.Controllers [HttpPost("risk-variables")] [MyAuthorize("风险控制-风控变量新增")] /// 创建变量 - public JsonResult CreateRiskVariable([FromBody] CreateRiskVariableReq req) + public async Task CreateRiskVariable([FromBody] CreateRiskVariableReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.CreateVariable(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.CreateVariable(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -552,12 +555,12 @@ namespace YLErp.Web.Controllers [HttpPut("risk-variables/{id}")] [MyAuthorize("风险控制-风控变量编辑")] /// 更新变量(含级联更新引用规则的 RuleExpr) - public JsonResult UpdateRiskVariable(long id, [FromBody] UpdateRiskVariableReq req) + public async Task UpdateRiskVariable(long id, [FromBody] UpdateRiskVariableReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.UpdateVariable(id, req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.UpdateVariable(id, req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -574,12 +577,12 @@ namespace YLErp.Web.Controllers [HttpDelete("risk-variables/{id}")] [MyAuthorize("风险控制-风控变量删除")] /// 删除变量 - public JsonResult DeleteRiskVariable(long id) + public async Task DeleteRiskVariable(long id) { try { - var service = new RiskRuleService(CurUser); - service.DeleteVariable(id); + var service = GetRiskRuleService(); + await Task.Run(() => service.DeleteVariable(id)); return Json(new { success = true }); } catch (ServiceException ex) @@ -599,7 +602,7 @@ namespace YLErp.Web.Controllers [HttpGet("trade-types")] [MyAuthorize("风险控制-风控应用查看")] - /// 获取合约类型列表 + /// 获取合约类型列表(纯内存操作,无需异步) public JsonResult GetTradeTypes() { try @@ -630,12 +633,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-audit-logs")] [MyAuthorize("风险控制-风控日志查看")] /// 查询风控操作日志列表(分页) - public JsonResult QueryRiskAuditLogs(QueryRiskAuditLogReq req) + public async Task QueryRiskAuditLogs(QueryRiskAuditLogReq req) { try { - var service = new RiskRuleService(CurUser); - var result = service.QueryAuditLogs(req); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.QueryAuditLogs(req)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -652,12 +655,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-audit-logs/{id}")] [MyAuthorize("风险控制-风控日志查看")] /// 获取风控操作日志详情 - public JsonResult GetRiskAuditLogDetail(long id) + public async Task GetRiskAuditLogDetail(long id) { try { - var service = new RiskRuleService(CurUser); - var result = service.GetAuditLogDetail(id); + var service = GetRiskRuleService(); + var result = await Task.Run(() => service.GetAuditLogDetail(id)); return Json(new { success = true, data = result }); } catch (ServiceException ex) @@ -674,12 +677,12 @@ namespace YLErp.Web.Controllers [HttpGet("risk-audit-logs/export")] [MyAuthorize("风险控制-风控日志导出")] /// 导出风控操作日志为 Excel - public IActionResult ExportRiskAuditLogs(QueryRiskAuditLogReq req) + public async Task ExportRiskAuditLogs(QueryRiskAuditLogReq req) { try { - var service = new RiskRuleService(CurUser); - var bytes = service.ExportAuditLogs(req); + var service = GetRiskRuleService(); + var bytes = await Task.Run(() => service.ExportAuditLogs(req)); return File(bytes, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "风控操作日志.xlsx"); } catch (ServiceException ex) @@ -695,4 +698,4 @@ namespace YLErp.Web.Controllers #endregion } -} +} \ No newline at end of file diff --git a/YLErpWeb/Controllers/tradeController.cs b/YLErpWeb/Controllers/tradeController.cs index 3cead1b9..70ac9488 100644 --- a/YLErpWeb/Controllers/tradeController.cs +++ b/YLErpWeb/Controllers/tradeController.cs @@ -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 }); }