| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354 |
- namespace Admin.NET.Plugin.AiDOP.Infrastructure.S8;
- /// <summary>
- /// S8-CFG-NOTIFY-NONDEFAULT-ROLE-OPTIONS-FIX-1:S8 业务角色的 **canonical 定义(唯一来源)**。
- ///
- /// <para><b>身份模型(本批锁定)</b>:
- /// <c>SysRole.Code</c> = **逻辑身份**,跨租户稳定;
- /// <c>SysRole.Id</c> = **租户本地物理身份**,同一个 Code 在每个租户都有各自不同的 Id。
- /// 因此任何「按角色找行」的逻辑都必须**按 Code 在可信租户作用域内查**,
- /// 绝不能按写死的物理 Id 去找——那等于假设所有租户共用默认租户那一份角色行。</para>
- ///
- /// <para><b>为什么需要这个文件</b>:这 7 个角色此前在仓内被**逐字复制了两份**
- /// (<c>S8SysRoleSeedData</c> 种默认租户、<c>AidopTenantInitService</c> 按租户复制),
- /// 内容恰好一致纯属人工同步。再在第三处(role-options)复制一份必然分叉,
- /// 所以本文件把两份合并为一份,两个既有定义改为引用它。</para>
- ///
- /// <para>⚠️ <b>不含 <c>sys_admin</c></b>:那是平台系统管理员角色(默认租户 `系统管理员`),
- /// 既不在上述任一 S8 角色定义里,也不被任何一条生效通知层引用
- /// (14 条 GLOBAL 层只引用下列 Code 中的 5 个)。仓内唯一出现 <c>sys_admin</c> 的通知层
- /// 属于另一个租户的 legacy demo 行,且其 scene 是已被禁止新建的非规范场景。
- /// 故它**不是** S8 业务角色,不应出现在租户的 CFG_NOTIFY 角色候选里。</para>
- /// </summary>
- public static class S8CanonicalRole
- {
- /// <summary>
- /// S8 七个业务角色(异常协同承接)。
- /// <c>OrderNo</c> 同时是**产品展示顺序**——产品顺序不得由数据库物理 Id 决定,
- /// 否则同一份配置在不同租户会呈现不同排序。
- /// </summary>
- public static readonly (string Code, string Name, int OrderNo)[] BusinessRoles =
- {
- ("ROLE_ORDER_PLANNER", "订单计划员", 800),
- ("ROLE_PRODUCTION_PLANNER", "生产计划员", 801),
- ("ROLE_PURCHASER", "采购员", 802),
- ("ROLE_WH_INBOUND", "仓库收货员", 803),
- ("ROLE_WH_OUTBOUND", "仓库发货员", 804),
- ("ROLE_QC", "质检员", 805),
- ("ROLE_EQUIP_MAINT", "设备维修员", 806),
- };
- /// <summary>canonical 业务角色 Code 白名单(候选集合的**唯一**筛选依据)。</summary>
- public static readonly string[] BusinessRoleCodes = Array.ConvertAll(BusinessRoles, x => x.Code);
- /// <summary>
- /// canonical 展示序。未知 Code 排到末尾而不是抛错——
- /// 排序不是校验入口,不该因为出现一个陌生 Code 就让整个下拉挂掉。
- /// </summary>
- public static int OrderOf(string? code)
- {
- foreach (var r in BusinessRoles)
- if (string.Equals(r.Code, code, StringComparison.Ordinal)) return r.OrderNo;
- return int.MaxValue;
- }
- }
|