|
|
@@ -1,7 +1,9 @@
|
|
|
namespace Admin.NET.Plugin.AiDOP.DataPlatform;
|
|
|
|
|
|
/// <summary>
|
|
|
-/// 岗位原文 → 中立岗位码。精确值优先于关键字。未命中为 UNKNOWN,不计入在职分母。
|
|
|
+/// 岗位原文 → 中立岗位码。精确值优先于关键字。
|
|
|
+/// S3/S5/S6/S7 人效分母按 PLANNER/WAREHOUSE/PRODUCTION 逐个过滤,故 OTHER 与 UNKNOWN 均不进分母;
|
|
|
+/// 两者的差别只在运维可见性:UNKNOWN 会记 POSITION_UNMAPPED 并进待映射清单,OTHER 不会。
|
|
|
/// </summary>
|
|
|
public static class EmployeePositionRules
|
|
|
{
|
|
|
@@ -11,9 +13,12 @@ public static class EmployeePositionRules
|
|
|
public const string Other = "OTHER";
|
|
|
public const string Unknown = "UNKNOWN";
|
|
|
|
|
|
- public static readonly string[] WarehouseKeywords = ["仓", "库管", "保管", "物料员", "WMS"];
|
|
|
- public static readonly string[] ProductionKeywords = ["生产", "操作", "装配", "车间", "班组", "产线", "工段"];
|
|
|
- public static readonly string[] PlannerKeywords = ["计划", "PMC", "调度"];
|
|
|
+ public static readonly string[] WarehouseKeywords = ["仓", "库管", "保管", "物料员", "WMS", "warehouse", "storekeeper"];
|
|
|
+ public static readonly string[] ProductionKeywords = ["生产", "操作", "装配", "车间", "班组", "产线", "工段", "production", "assembly", "operator", "workshop"];
|
|
|
+ public static readonly string[] PlannerKeywords = ["计划", "PMC", "调度", "planner", "planning", "scheduler"];
|
|
|
+
|
|
|
+ /// <summary>已确认不属于仓管/生产/计划的岗位,归 OTHER 后不再记 POSITION_UNMAPPED 告警。</summary>
|
|
|
+ public static readonly string[] OtherKeywords = ["quality", "质量", "QC", "QA", "数据员", "研发"];
|
|
|
|
|
|
/// <summary>T8 gw 原值精确匹配,优先于关键字。</summary>
|
|
|
public static readonly IReadOnlyDictionary<string, string> Exact = new Dictionary<string, string>(StringComparer.Ordinal)
|
|
|
@@ -30,12 +35,19 @@ public static class EmployeePositionRules
|
|
|
var text = raw.Trim();
|
|
|
if (Exact.TryGetValue(text, out var exact))
|
|
|
return exact;
|
|
|
- if (WarehouseKeywords.Any(text.Contains))
|
|
|
+ if (Matches(text, WarehouseKeywords))
|
|
|
return Warehouse;
|
|
|
- if (ProductionKeywords.Any(text.Contains))
|
|
|
+ if (Matches(text, ProductionKeywords))
|
|
|
return Production;
|
|
|
- if (PlannerKeywords.Any(text.Contains))
|
|
|
+ if (Matches(text, PlannerKeywords))
|
|
|
return Planner;
|
|
|
+ // OTHER 放在三类业务岗之后:岗位原文同时含「质量」与「仓」时仍归 WAREHOUSE。
|
|
|
+ if (Matches(text, OtherKeywords))
|
|
|
+ return Other;
|
|
|
return Unknown;
|
|
|
}
|
|
|
+
|
|
|
+ // 岗位原文的大小写不由平台控制(165 的 JobTitle 是小写英文,T8 的 gw 是中文),统一忽略大小写比对。
|
|
|
+ private static bool Matches(string text, string[] keywords)
|
|
|
+ => keywords.Any(keyword => text.Contains(keyword, StringComparison.OrdinalIgnoreCase));
|
|
|
}
|