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

refactor(s8): switch runtime paths to s1-s7 scenes

YY968XX 4 недель назад
Родитель
Сommit
a50fa48e5d

+ 35 - 18
server/Plugins/Admin.NET.Plugin.AiDOP/SeedData/S8ExceptionTypeSeedData.cs

@@ -1,9 +1,18 @@
+using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
+
 namespace Admin.NET.Plugin.AiDOP;
 
 /// <summary>
 /// S8 异常类型基线种子(灌入 ado_s8_exception_type)。
-/// 13 类异常类型全局基线配置:tenant_id=0 / factory_id=0
+/// 20 类异常类型全局基线(tenant_id=0 / factory_id=0);scene_code 使用 S1–S7 单模块场景
 /// 依赖 S8RolePermissionSeedData(owner_role_code 引用 ROLE_* 编码)。
+///
+/// 历史轨迹:
+///   - 初版:13 条,scene_code 用旧复合(S1S7_DELIVERY / S2S6_PRODUCTION / S3S5_SUPPLY)。
+///   - S8-SCENE-MIGRATE-CONFIG-S1S7-1(DB 阶段):DB 中现有 15 条迁 S1–S7 + 新增 5 条 = 20。
+///   - 本轮 S8-SCENE-MIGRATE-RUNTIME-CODE-S1S7-1:SeedData 重写为 S1–S7 baseline。
+///
+/// 字段约定:Id 与 DB 现有 1:1 对齐;type_code 全保留;sort_no 与 DB 一致;enabled=true。
 /// </summary>
 [IncreSeed]
 public class S8ExceptionTypeSeedData : ISqlSugarEntitySeedData<Entity.S8.AdoS8ExceptionType>
@@ -11,28 +20,36 @@ public class S8ExceptionTypeSeedData : ISqlSugarEntitySeedData<Entity.S8.AdoS8Ex
     public IEnumerable<Entity.S8.AdoS8ExceptionType> HasData()
     {
         var ct = DateTime.Parse("2026-04-18 00:00:00");
-        long seq = 1329908100001L;
+        const long baseId = 1329908100000L;
 
         return new[]
         {
-            // ── DELIVERY 域(S1+S7) ──
-            T(seq++, "ORDER_CHANGE",        "订单变更",               "DELIVERY",   "S1S7_DELIVERY",   60,  "ROLE_ORDER_PLANNER",      "MEDIUM", 100, ct),
-            T(seq++, "DELIVERY_DELAY",      "交期延迟",               "DELIVERY",   "S1S7_DELIVERY",   120, "ROLE_ORDER_PLANNER",      "HIGH",   101, ct),
-            T(seq++, "PENDING_SHIPMENT",    "入库待发",               "DELIVERY",   "S1S7_DELIVERY",   240, "ROLE_WH_OUTBOUND",        "MEDIUM", 102, ct),
+            // ── DELIVERY 域:S1 产销协同 + S7 成品仓储 ──
+            T(baseId + 1,  "ORDER_CHANGE",             "订单变更",           "DELIVERY",   S8SceneCode.S1, 60,  "ROLE_ORDER_PLANNER",      "MEDIUM", 100, ct),
+            T(baseId + 2,  "DELIVERY_DELAY",           "交期延迟",           "DELIVERY",   S8SceneCode.S7, 120, "ROLE_ORDER_PLANNER",      "HIGH",   101, ct),
+            T(baseId + 3,  "PENDING_SHIPMENT",         "入库待发",           "DELIVERY",   S8SceneCode.S7, 240, "ROLE_WH_OUTBOUND",        "MEDIUM", 102, ct),
+            T(baseId + 16, "ORDER_REVIEW_DELAY",       "订单评审延迟",       "DELIVERY",   S8SceneCode.S1, 120, "ROLE_ORDER_PLANNER",      "MEDIUM", 400, ct),
 
-            // ── PRODUCTION 域(S2+S6) ──
-            T(seq++, "EQUIP_FAULT",         "设备异常",               "PRODUCTION", "S2S6_PRODUCTION", 30,  "ROLE_EQUIP_MAINT",        "HIGH",   200, ct),
-            T(seq++, "MATERIAL_SHORTAGE",   "物料异常",               "PRODUCTION", "S2S6_PRODUCTION", 60,  "ROLE_PRODUCTION_PLANNER", "HIGH",   201, ct),
-            T(seq++, "QUALITY_DEFECT",      "质量异常",               "PRODUCTION", "S2S6_PRODUCTION", 60,  "ROLE_QC",                 "HIGH",   202, ct),
+            // ── PRODUCTION 域:S2 制造协同 + S6 生产执行 ──
+            // 注:MATERIAL_SHORTAGE 跨 domain 迁到 S5(CONFIG 阶段决策),domain_code 仍 PRODUCTION 与 DB 一致。
+            T(baseId + 4,  "EQUIP_FAULT",              "设备异常",           "PRODUCTION", S8SceneCode.S2, 30,  "ROLE_EQUIP_MAINT",        "HIGH",   200, ct),
+            T(baseId + 14, "DIMENSION_DEVIATION",      "尺寸超差",           "PRODUCTION", S8SceneCode.S2, 60,  "ROLE_QC",                 "HIGH",   200, ct),
+            T(baseId + 5,  "MATERIAL_SHORTAGE",        "物料异常",           "PRODUCTION", S8SceneCode.S5, 60,  "ROLE_PRODUCTION_PLANNER", "HIGH",   201, ct),
+            T(baseId + 6,  "QUALITY_DEFECT",           "质量异常",           "PRODUCTION", S8SceneCode.S2, 60,  "ROLE_QC",                 "HIGH",   202, ct),
+            T(baseId + 15, "YIELD_DEFICIT",            "良率不足",           "PRODUCTION", S8SceneCode.S6, 60,  "ROLE_QC",                 "HIGH",   300, ct),
+            T(baseId + 19, "WORK_ORDER_DELAY",         "工单延期",           "PRODUCTION", S8SceneCode.S6, 60,  "ROLE_PRODUCTION_PLANNER", "HIGH",   403, ct),
 
-            // ── SUPPLY 域(S3-S5) ──
-            T(seq++, "SUPPLIER_ETA_ISSUE",  "供应商回复交期异常",     "SUPPLY",     "S3S5_SUPPLY",     240, "ROLE_PURCHASER",          "MEDIUM", 300, ct),
-            T(seq++, "SUPPLIER_SHIP_ISSUE", "供应商发货异常",         "SUPPLY",     "S3S5_SUPPLY",     240, "ROLE_PURCHASER",          "MEDIUM", 301, ct),
-            T(seq++, "WH_INBOUND_ISSUE",    "仓库收货异常",           "SUPPLY",     "S3S5_SUPPLY",     120, "ROLE_WH_INBOUND",         "MEDIUM", 302, ct),
-            T(seq++, "IQC_ISSUE",           "IQC 检验异常",           "SUPPLY",     "S3S5_SUPPLY",     120, "ROLE_QC",                 "MEDIUM", 303, ct),
-            T(seq++, "WH_PUTAWAY_ISSUE",    "仓库上架入库异常",       "SUPPLY",     "S3S5_SUPPLY",     120, "ROLE_WH_INBOUND",         "LOW",    304, ct),
-            T(seq++, "WH_KIT_ISSUE",        "仓库工单备料异常",       "SUPPLY",     "S3S5_SUPPLY",     60,  "ROLE_WH_OUTBOUND",        "MEDIUM", 305, ct),
-            T(seq++, "WH_ISSUE_OUT_ISSUE",  "仓库工单发料异常",       "SUPPLY",     "S3S5_SUPPLY",     60,  "ROLE_WH_OUTBOUND",        "MEDIUM", 306, ct),
+            // ── SUPPLY 域:S3 供应协同 + S4 采购执行 + S5 物料仓储 ──
+            T(baseId + 7,  "SUPPLIER_ETA_ISSUE",       "供应商回复交期异常", "SUPPLY",     S8SceneCode.S3, 240, "ROLE_PURCHASER",          "MEDIUM", 300, ct),
+            T(baseId + 8,  "SUPPLIER_SHIP_ISSUE",      "供应商发货异常",     "SUPPLY",     S8SceneCode.S3, 240, "ROLE_PURCHASER",          "MEDIUM", 301, ct),
+            T(baseId + 9,  "WH_INBOUND_ISSUE",         "仓库收货异常",       "SUPPLY",     S8SceneCode.S5, 120, "ROLE_WH_INBOUND",         "MEDIUM", 302, ct),
+            T(baseId + 10, "IQC_ISSUE",                "IQC 检验异常",       "SUPPLY",     S8SceneCode.S3, 120, "ROLE_QC",                 "MEDIUM", 303, ct),
+            T(baseId + 11, "WH_PUTAWAY_ISSUE",         "仓库上架入库异常",   "SUPPLY",     S8SceneCode.S5, 120, "ROLE_WH_INBOUND",         "LOW",    304, ct),
+            T(baseId + 12, "WH_KIT_ISSUE",             "仓库工单备料异常",   "SUPPLY",     S8SceneCode.S5, 60,  "ROLE_WH_OUTBOUND",        "MEDIUM", 305, ct),
+            T(baseId + 13, "WH_ISSUE_OUT_ISSUE",       "仓库工单发料异常",   "SUPPLY",     S8SceneCode.S7, 60,  "ROLE_WH_OUTBOUND",        "MEDIUM", 306, ct),
+            T(baseId + 17, "PURCHASE_EXECUTION_DELAY", "采购执行延迟",       "SUPPLY",     S8SceneCode.S4, 120, "ROLE_PURCHASER",          "MEDIUM", 401, ct),
+            T(baseId + 18, "PURCHASE_QUALITY_ABNORMAL","采购质量异常",       "SUPPLY",     S8SceneCode.S4, 60,  "ROLE_QC",                 "MEDIUM", 402, ct),
+            T(baseId + 20, "MATERIAL_STOCK_ABNORMAL",  "库存异常",           "SUPPLY",     S8SceneCode.S5, 120, "ROLE_WH_INBOUND",         "MEDIUM", 404, ct),
         };
     }
 

+ 18 - 3
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8DashboardCellDataService.cs

@@ -1,5 +1,6 @@
 using Admin.NET.Plugin.AiDOP.Dto.S8;
 using Admin.NET.Plugin.AiDOP.Entity.S8;
+using Admin.NET.Plugin.AiDOP.Infrastructure.S8;
 
 namespace Admin.NET.Plugin.AiDOP.Service.S8;
 
@@ -120,11 +121,25 @@ public class S8DashboardCellDataService : ITransient
         };
     }
 
+    // S8-SCENE-MIGRATE-RUNTIME-CODE-S1S7-1:DOMAIN_x 改为 S1–S7 多 scene OR;
+    // 同时保留旧复合 scene 兼容(27 行历史 active exception 在 HISTORY-CLEANUP 之前仍引用)。
     private static IEnumerable<EvtRow> ApplyAggregateScope(List<EvtRow> events, string? scope) => scope switch
     {
-        "DOMAIN_DELIVERY"   => events.Where(e => e.SceneCode == "S1S7_DELIVERY"),
-        "DOMAIN_PRODUCTION" => events.Where(e => e.SceneCode == "S2S6_PRODUCTION"),
-        "DOMAIN_SUPPLY"     => events.Where(e => e.SceneCode == "S3S5_SUPPLY"),
+        "DOMAIN_DELIVERY"   => events.Where(e =>
+            e.SceneCode == S8SceneCode.S1
+            || e.SceneCode == S8SceneCode.S7
+            || e.SceneCode == S8SceneCode.S1S7Delivery),
+        "DOMAIN_PRODUCTION" => events.Where(e =>
+            e.SceneCode == S8SceneCode.S2
+            || e.SceneCode == S8SceneCode.S6
+            || e.SceneCode == S8SceneCode.S2S6Production
+            || e.SceneCode == "S2S6_QUALITY"),
+        "DOMAIN_SUPPLY"     => events.Where(e =>
+            e.SceneCode == S8SceneCode.S3
+            || e.SceneCode == S8SceneCode.S4
+            || e.SceneCode == S8SceneCode.S5
+            || e.SceneCode == S8SceneCode.S3S5Supply
+            || e.SceneCode == S8SceneCode.S4Purchase),
         "ALL"               => events,
         _                   => events,
     };

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

@@ -209,7 +209,7 @@ public class S8ManualReportService : ITransient
     ///  - SourceType 标识为自动监控来源
     ///  - 填入 SourceRuleId / SourceDataSourceId / SourcePayload / RelatedObjectCode 追溯
     ///  - ExceptionTypeCode 固定 EQUIP_FAULT(G-01 首版唯一映射)
-    ///  - SceneCode 固定 S2S6_PRODUCTION(G-01 首版唯一场景
+    ///  - SceneCode 固定 S2(G-01 首版唯一场景,迁移后从 S2S6_PRODUCTION 切到单模块 S2
     /// 不做补偿、重试、对账;失败由调用方接住。
     /// </summary>
     public async Task<AdoS8Exception> CreateFromWatchAsync(S8WatchHitResult hit)
@@ -227,7 +227,7 @@ public class S8ManualReportService : ITransient
             ExceptionCode = code,
             Title = title,
             Description = null,
-            SceneCode = S8SceneCode.S2S6Production,
+            SceneCode = S8SceneCode.S2,
             // 首版自动监控建单来源标识(字符串值,先不抽常量类)。
             SourceType = "AUTO_WATCH",
             Status = "NEW",
@@ -241,10 +241,10 @@ public class S8ManualReportService : ITransient
             ReporterId = null,
             CreatedAt = DateTime.Now,
             IsDeleted = false,
-            // G-01 首版唯一异常类型映射(seed 已确认 EQUIP_FAULT 属 S2S6_PRODUCTION 场景)。
+            // G-01 首版唯一异常类型映射(baseline 已迁后 EQUIP_FAULT 属 S2 制造协同场景)。
             ExceptionTypeCode = "EQUIP_FAULT",
-            // 取场景代表模块:S2S6_PRODUCTION → S2。看板按 module_code 聚合,留空会导致模块卡空白。
-            ModuleCode = S8ModuleCode.FromScene(S8SceneCode.S2S6Production),
+            // S2 自映射 → S2。看板按 module_code 聚合,留空会导致模块卡空白。
+            ModuleCode = S8ModuleCode.FromScene(S8SceneCode.S2),
             ProcessNodeCode = null,
             // 追溯三件套(自动建单必填口径)。
             SourceRuleId = hit.SourceRuleId,
@@ -298,7 +298,7 @@ public class S8ManualReportService : ITransient
                 ? $"[自动] {hit.SourceObjectType} {hit.SourceObjectId}"
                 : hit.Title,
             Description = null,
-            SceneCode = string.IsNullOrWhiteSpace(hit.SceneCode) ? S8SceneCode.S2S6Production : hit.SceneCode,
+            SceneCode = string.IsNullOrWhiteSpace(hit.SceneCode) ? S8SceneCode.S2 : hit.SceneCode,
             SourceType = "AUTO_WATCH",
             Status = "NEW",
             Severity = string.IsNullOrWhiteSpace(hit.Severity) ? "MEDIUM" : hit.Severity,
@@ -313,7 +313,7 @@ public class S8ManualReportService : ITransient
             // 优先使用 evaluator 显式提供的 module_code,否则按 hit.SceneCode 取代表模块。
             ModuleCode = !string.IsNullOrWhiteSpace(hit.ModuleCode)
                 ? hit.ModuleCode
-                : S8ModuleCode.FromScene(string.IsNullOrWhiteSpace(hit.SceneCode) ? S8SceneCode.S2S6Production : hit.SceneCode),
+                : S8ModuleCode.FromScene(string.IsNullOrWhiteSpace(hit.SceneCode) ? S8SceneCode.S2 : hit.SceneCode),
             ProcessNodeCode = null,
             SourceRuleId = hit.SourceRuleId,
             SourceDataSourceId = hit.DataSourceId == 0 ? null : hit.DataSourceId,

+ 5 - 5
server/Plugins/Admin.NET.Plugin.AiDOP/Service/S8/S8WatchSchedulerService.cs

@@ -87,7 +87,7 @@ public class S8WatchSchedulerService : ITransient
             .Where(x => x.TenantId == tenantId
                 && x.FactoryId == factoryId
                 && x.Enabled
-                && x.SceneCode == S8SceneCode.S2S6Production
+                && x.SceneCode == S8SceneCode.S2
                 && (x.RuleType == null || x.RuleType == ""))
             .ToListAsync();
 
@@ -112,7 +112,7 @@ public class S8WatchSchedulerService : ITransient
         var alertRules = (await _alertRuleRep.AsQueryable()
             .Where(x => x.TenantId == tenantId
                 && x.FactoryId == factoryId
-                && x.SceneCode == S8SceneCode.S2S6Production)
+                && x.SceneCode == S8SceneCode.S2)
             .ToListAsync())
             .Where(IsSupportedAlertRule)
             .ToList();
@@ -1749,7 +1749,7 @@ public sealed class S8WatchDeviceRow
 
 /// <summary>
 /// G01-05 去重结果对象。仅服务 G01-06 建单前拦截,由 CanCreate 单决策位决定是否建单。
-/// 只服务首版唯一场景 S2S6_PRODUCTION + 唯一 trigger_type VALUE_DEVIATION + 设备对象。
+/// 只服务首版唯一场景 S2(迁移后由 S2S6_PRODUCTION 切到单模块 S2)+ 唯一 trigger_type VALUE_DEVIATION + 设备对象。
 /// 不预留多 trigger_type / 平台化去重扩展结构。
 /// Reason 值域:no_pending / duplicate_pending / missing_dedup_key / query_failed。
 /// </summary>
@@ -1763,7 +1763,7 @@ public sealed class S8WatchDedupResult
 
 /// <summary>
 /// G01-06 建单结果对象。仅服务 G-01 首版主线验收,由 Created / Skipped 两位决定结局。
-/// 只服务首版唯一场景 S2S6_PRODUCTION + 唯一 trigger_type VALUE_DEVIATION + 设备对象。
+/// 只服务首版唯一场景 S2(迁移后由 S2S6_PRODUCTION 切到单模块 S2)+ 唯一 trigger_type VALUE_DEVIATION + 设备对象。
 /// 不预留多 trigger_type / 平台化工单扩展结构。
 /// Reason 值域:auto_created / create_failed / 透传自 DedupResult.Reason。
 /// </summary>
@@ -1779,7 +1779,7 @@ public sealed class S8WatchCreationResult
 
 /// <summary>
 /// G01-04 命中结果对象。承载 G01-05 去重与 G01-06 建单所需最小追溯字段,
-/// 仅服务首版唯一场景 S2S6_PRODUCTION + 唯一 trigger_type VALUE_DEVIATION + 设备对象。
+/// 仅服务首版唯一场景 S2(迁移后由 S2S6_PRODUCTION 切到单模块 S2)+ 唯一 trigger_type VALUE_DEVIATION + 设备对象。
 /// 不预留多 trigger_type / 多场景 / 平台化扩展结构。
 /// </summary>
 public sealed class S8WatchHitResult