namespace Admin.NET.Plugin.AiDOP.Const.S8;
///
/// S8-RESPONSIBILITY-POOL-1:规则的三种责任类型。
///
/// 与角色严格分离:SysRole 回答「这个账号能做什么」
/// (认领 / 转派 / 审核 / 升级这类动作权限);责任池回答「这个账号负责什么」
/// (哪一条规则产生的异常归他)。最终允许 = 动作权限 ∩ 规则责任 ∩ 状态机。
///
/// 刻意不引入 Supervisor / 部门负责人 / L1-L2-L3 三层虚拟层级:
/// 系统里不存在组织主管关系(SysOrg.DirectorId 与 SysUser.ManagerUserId
/// 实测填充率均为 0),拿它当产品主模型只会配出一条永远解析为空的责任链。
/// 将来业务真需要层级升级时,另建真正的 Escalation Policy,不在这里假装。
///
public static class S8ResponsibilityType
{
/// 处理账号池:谁负责处理这条规则产生的异常。存量表 ado_s8_rule_handler_user。
public const string Handler = "HANDLER";
/// 复核账号池:谁有资格被选为这条规则的复核人。
public const string Reviewer = "REVIEWER";
/// 升级账号池:异常超时 / 触发升级时找谁。
public const string Escalation = "ESCALATION";
}
/// 责任类型的展示元信息。后端校验、配置接口、前端 UI 三方共用同一份。
/// 类型编码。
/// 业务用户看到的名字(不出现任何技术术语)。
/// 页面上的一句话说明。
/// 展示顺序。
public sealed record S8ResponsibilityDefinition(string Code, string DisplayName, string Description, int OrderNo);
/// 责任类型目录。
public static class S8ResponsibilityCatalog
{
public static readonly IReadOnlyList All = new List
{
new(S8ResponsibilityType.Handler, "处理人员", "以下账号负责处理该规则产生的异常。", 10),
new(S8ResponsibilityType.Reviewer, "复核人员", "处理人提交复核时,只能从以下账号中选择复核人。", 20),
new(S8ResponsibilityType.Escalation, "升级人员", "异常超时或触发升级时通知以下账号。", 30),
};
private static readonly HashSet TypeSet =
All.Select(x => x.Code).ToHashSet(StringComparer.OrdinalIgnoreCase);
public static bool IsKnown(string? code) => !string.IsNullOrWhiteSpace(code) && TypeSet.Contains(code!);
public static S8ResponsibilityDefinition? Find(string? code) =>
string.IsNullOrWhiteSpace(code)
? null
: All.FirstOrDefault(x => string.Equals(x.Code, code, StringComparison.OrdinalIgnoreCase));
///
/// 存储在新表 ado_s8_rule_responsibility_user 里的类型。
///
/// HANDLER 不在其中:它有稳定的存量表与生产读路径(就绪门禁 / 认领资格 /
/// 可见性收敛 / 通知解析都已依赖),为了"三张表长得一样"去迁它,收益是审美、
/// 代价是动四条已验证的链路。调用方通过统一 reader 拿到一致的 API,
/// 存储差异被收敛在一处。
///
public static bool IsStoredInResponsibilityTable(string? code) =>
string.Equals(code, S8ResponsibilityType.Reviewer, StringComparison.OrdinalIgnoreCase)
|| string.Equals(code, S8ResponsibilityType.Escalation, StringComparison.OrdinalIgnoreCase);
}