Просмотр исходного кода

fix(s8): derive module code on exception creation

YY968XX 1 месяц назад
Родитель
Сommit
11dff89a05

+ 21 - 8
server/Plugins/Admin.NET.Plugin.AiDOP/Infrastructure/S8/S8SceneCode.cs

@@ -61,16 +61,16 @@ public static class S8ModuleCode
     public const string S6 = "S6";
     public const string S7 = "S7";
 
-    /// <summary>module_code → 中文名称</summary>
+    /// <summary>module_code → 业务名称(与侧栏菜单 S{N} 看板标题对齐,统一字面)</summary>
     public static string Label(string moduleCode) => moduleCode switch
     {
-        S1 => "S1·销售评审",
-        S2 => "S2·计划排产",
-        S3 => "S3·物料套料",
-        S4 => "S4·采购执行",
-        S5 => "S5·IQC入库",
-        S6 => "S6·生产完工",
-        S7 => "S7·成品出库",
+        S1 => "S1 产销协同",
+        S2 => "S2 制造协同",
+        S3 => "S3 供应协同",
+        S4 => "S4 采购执行",
+        S5 => "S5 物料仓储",
+        S6 => "S6 生产执行",
+        S7 => "S7 成品仓储",
         _  => moduleCode
     };
 
@@ -86,4 +86,17 @@ public static class S8ModuleCode
 
     /// <summary>所有模块码有序列表</summary>
     public static readonly string[] All = { S1, S2, S3, S4, S5, S6, S7 };
+
+    /// <summary>
+    /// 场景码 → 代表模块码(取场景内 S8SceneCode.Modules 的首项)。
+    /// 用于建单时回填 module_code:scene 内含多个 module 时,取代表项作为聚合归属,
+    /// 不替代显式 module_code(caller 可在拿到此值前覆盖)。
+    /// 未识别 scene 返回 null(caller 自决:留空或兜底)。
+    /// </summary>
+    public static string? FromScene(string? sceneCode)
+    {
+        if (string.IsNullOrWhiteSpace(sceneCode)) return null;
+        var modules = S8SceneCode.Modules(sceneCode);
+        return modules.Length == 0 ? null : modules[0];
+    }
 }

+ 6 - 0
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/Rules/IS8RuleEvaluator.cs

@@ -42,4 +42,10 @@ public sealed class S8RuleHit
     public long DataSourceId { get; set; }
     public long? OccurrenceDeptId { get; set; }
     public long? ResponsibleDeptId { get; set; }
+
+    /// <summary>
+    /// 命中归属模块码(S1-S7)。evaluator 可显式提供以覆盖 scene 默认派生;
+    /// 留 null 时建单方按 scene 取代表模块(S8ModuleCode.FromScene)。
+    /// </summary>
+    public string? ModuleCode { get; set; }
 }

+ 7 - 4
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8ManualReportService.cs

@@ -170,6 +170,7 @@ public class S8ManualReportService : ITransient
             ResponsibleDeptId = dto.ResponsibleDeptId,
             ReporterId = currentUserId,
             ExceptionTypeCode = inferredType,
+            ModuleCode = S8ModuleCode.FromScene(dto.SceneCode.Trim()),
             CreatedAt = DateTime.Now,
             IsDeleted = false
         };
@@ -242,9 +243,8 @@ public class S8ManualReportService : ITransient
             IsDeleted = false,
             // G-01 首版唯一异常类型映射(seed 已确认 EQUIP_FAULT 属 S2S6_PRODUCTION 场景)。
             ExceptionTypeCode = "EQUIP_FAULT",
-            // ModuleCode:S2S6_PRODUCTION 场景对应 S2+S6 两个模块(见 S8ModuleCode.SceneOf),
-            // 无稳定“scene → 单一 module”映射;首版置空,不靠经验写死。
-            ModuleCode = null,
+            // 取场景代表模块:S2S6_PRODUCTION → S2。看板按 module_code 聚合,留空会导致模块卡空白。
+            ModuleCode = S8ModuleCode.FromScene(S8SceneCode.S2S6Production),
             ProcessNodeCode = null,
             // 追溯三件套(自动建单必填口径)。
             SourceRuleId = hit.SourceRuleId,
@@ -310,7 +310,10 @@ public class S8ManualReportService : ITransient
             CreatedAt = DateTime.Now,
             IsDeleted = false,
             ExceptionTypeCode = hit.ExceptionTypeCode,
-            ModuleCode = null,
+            // 优先使用 evaluator 显式提供的 module_code,否则按 hit.SceneCode 取代表模块。
+            ModuleCode = !string.IsNullOrWhiteSpace(hit.ModuleCode)
+                ? hit.ModuleCode
+                : S8ModuleCode.FromScene(string.IsNullOrWhiteSpace(hit.SceneCode) ? S8SceneCode.S2S6Production : hit.SceneCode),
             ProcessNodeCode = null,
             SourceRuleId = hit.SourceRuleId,
             SourceDataSourceId = hit.DataSourceId == 0 ? null : hit.DataSourceId,