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 f3ecab99..be59ce93 100644 --- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs +++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs @@ -1,5 +1,6 @@ using BaseOUDAL; using Newtonsoft.Json; +using System.Linq; using System.Linq.Expressions; using System.Text.RegularExpressions; using YLErp.BLL; @@ -540,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; } /// @@ -885,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; @@ -1148,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); @@ -1209,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 @@ -1274,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; @@ -1294,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; @@ -1312,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; @@ -1334,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 { @@ -1350,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; @@ -1367,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 {