using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing; using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse; using Admin.NET.Plugin.AiDOP.Infrastructure; using Admin.NET.Plugin.AiDOP.Infrastructure.S8; namespace Admin.NET.Plugin.AiDOP.Service.S8; /// /// S8 主数据下拉:优先复用 S0 已落库主数据语义(部门等),无则返回空列表,不把「下拉查询」误建成独立业务表。 /// /// S8-P0-3-MASTERDATA-TRUSTED-SCOPE-1 作用域合同:三个入口的工厂边界 /// **一律由 从认证身份解析**, /// 客户端传入的 factoryRefId 只被视为筛选意图,**当前实现直接忽略、不承担授权作用**。 /// /// S8-SYSUSER-ONLY-1GetEmployeesAsync 已退役,由 /// 取代 —— S8 的"人"只有系统账号一种。 /// public class S8MasterDataAdapter : ITransient { private readonly SqlSugarRepository _deptRep; private readonly SqlSugarRepository _lineRep; private readonly SqlSugarRepository _sysUserRep; private readonly IS8UserScopeValidator _userScope; public S8MasterDataAdapter( SqlSugarRepository deptRep, SqlSugarRepository lineRep, SqlSugarRepository sysUserRep, IS8UserScopeValidator userScope) { _deptRep = deptRep; _lineRep = lineRep; _sysUserRep = sysUserRep; _userScope = userScope; } /// /// S8-TENANT-ONLY-BATCH6:主数据下拉的边界由 factory_ref_id 改为 tenant_id。 /// /// 这不是等价改写,是修一个真实越权。真库取证(aidopdev,只读): /// factory_ref_id = 1000 同时属于租户 824585161322565797403760988229—— /// 按工厂过滤会把另一租户的 613 名员工 / 210 个部门直接列进本租户的下拉框。 /// 工厂号从来就不是隔离维度,之前只是没人对着数据看过。 /// /// 可用性同样已验证:三张表 tenant_id 100% 非空 /// (EmployeeMaster 1105 行 / DepartmentMaster 239 行 / LineMaster 169 行,NULL 均为 0), /// 每个租户都有非空主数据,改判据不会把下拉打空。 /// public async Task GetDepartmentsAsync(S8TrustedScope scope) => await _deptRep.AsQueryable() .Where(x => x.TenantId == scope.TenantId) .Take(500) .Select(x => new { id = x.Id, code = x.Department, name = x.Descr ?? x.Department }) .ToListAsync(); /// /// S8 人员选择器的唯一数据源:当前租户的启用系统账号。 /// /// S8-SYSUSER-ONLY-1:替代原 GetEmployeesAsync。原实现列的是 /// EmployeeMaster,每行还挂一个 bindStatus: BOUND/UNBOUND —— 也就是说, /// 下拉框里绝大多数选项选了也没用:真库 1105 名员工只有 8 个绑了账号, /// 选中未绑定的员工后通知发不出去、审批流转办静默跳过,而页面上没有任何提示。 /// 现在列的就是账号本身,不存在"选了但用不了"的选项 /// /// 边界只有租户,与 同因: /// factory_ref_id = 1000 横跨两个租户,工厂从来不是隔离维度。 /// public async Task GetOperatorUsersAsync(S8TrustedScope scope) { var users = await _userScope.ValidateUsersAsync( scope.TenantId, await _sysUserRep.AsQueryable().ClearFilter() .Where(u => u.TenantId == scope.TenantId) .Take(S8UserScopeValidator.MaxHydrationKeys) .Select(u => u.Id) .ToListAsync()); return users .OrderBy(u => u.DisplayName, StringComparer.Ordinal) .Select(u => new { id = u.UserId, name = u.DisplayName, account = u.Account }) .ToList(); } /// 产线下拉,边界同 public async Task GetLinesAsync(S8TrustedScope scope) => await _lineRep.AsQueryable() .Where(x => x.TenantId == scope.TenantId) .Take(500) .Select(x => new { id = x.Id, code = x.Line, name = x.Describe ?? x.Line }) .ToListAsync(); }