using Admin.NET.Core; using Admin.NET.Plugin.AiDOP.Entity.S0.Manufacturing; using Admin.NET.Plugin.AiDOP.Entity.S0.Sales; using Admin.NET.Plugin.AiDOP.Entity.S0.Supply; using Admin.NET.Plugin.AiDOP.Entity.S0.Warehouse; using SqlSugar; using Xunit; namespace Admin.NET.Plugin.AiDOP.Tests.S0.Tenant; /// /// S0 tenant isolation contract for entities whose DB tables already contain tenant_id. /// public class S0TenantEntityContractTests { public static IEnumerable TenantScopedEntityTypes() { yield return [typeof(AdoS0BarCodeType)]; yield return [typeof(AdoS0CostCtrMaster)]; yield return [typeof(AdoS0CustMaster)]; yield return [typeof(AdoS0DepartmentMaster)]; yield return [typeof(AdoS0DevMonitor)]; yield return [typeof(AdoS0EmpSkills)]; yield return [typeof(AdoS0EmpWorkDutyMaster)]; yield return [typeof(AdoS0EmployeeMaster)]; yield return [typeof(AdoS0ImageType)]; yield return [typeof(AdoS0ItemMaster)]; yield return [typeof(AdoS0ItemOpCondition)]; yield return [typeof(AdoS0ItemPackMaster)]; yield return [typeof(AdoS0ItemSubstituteDetail)]; yield return [typeof(AdoS0LineMaster)]; yield return [typeof(AdoS0LineSkillDetail)]; yield return [typeof(AdoS0LineSkillMaster)]; yield return [typeof(AdoS0LocationMaster)]; yield return [typeof(AdoS0LocationShelfMaster)]; yield return [typeof(AdoS0NbrControl)]; yield return [typeof(AdoS0NbrTypeMaster)]; yield return [typeof(AdoS0MfgPersonSkillAssignment)]; yield return [typeof(AdoS0MfgPreprocessElement)]; yield return [typeof(AdoS0MfgPreprocessElementParam)]; yield return [typeof(AdoS0ProdLineDetail)]; yield return [typeof(AdoS0ProductStructureMaster)]; yield return [typeof(AdoS0ProductStructureOp)]; yield return [typeof(AdoS0QualitySegmentImage)]; yield return [typeof(AdoS0MfgRoutingOpDetail)]; yield return [typeof(AdoS0StdOpMaster)]; yield return [typeof(AdoS0SuppMaster)]; yield return [typeof(AdoS0WorkCtrMaster)]; yield return [typeof(AdoS0WorkOrdControl)]; yield return [typeof(IcSubstitute)]; yield return [typeof(AdoS0SrmPurchase)]; // 2026-08-25 批次:原本无 tenant_id 的 12 张 S0 列表主表,随 ITenantIdFilter 一并纳入契约。 yield return [typeof(AdoS0OrderScheduleCycle)]; yield return [typeof(AdoS0MfgWorkOrderControl)]; yield return [typeof(AdoS0MfgPersonSkill)]; yield return [typeof(AdoS0ContractReviewCycle)]; yield return [typeof(AdoS0ContractReviewCycleBreakdown)]; yield return [typeof(AdoS0ContractReviewCycleSyncFlag)]; yield return [typeof(AdoS0OrderReviewCycle)]; yield return [typeof(AdoS0PriorityCode)]; yield return [typeof(AdoS0PriorityRule)]; yield return [typeof(AdoS0ProductDesignCycle)]; yield return [typeof(AdoS0CategoryLeadTime)]; yield return [typeof(AdoS0MaterialPlanCycle)]; // 2026-08-25 同批:工序流转卡随其组织解析改造(去 ClearFilter)一并租户化,migration 1.0.390。 yield return [typeof(AdoS0ProcessFlowCard)]; } [Theory] [MemberData(nameof(TenantScopedEntityTypes))] public void TenantScopedS0Entities_ImplementTenantFilterAndMapTenantId(Type entityType) { Assert.True(typeof(ITenantIdFilter).IsAssignableFrom(entityType), $"{entityType.Name} must implement ITenantIdFilter"); var property = entityType.GetProperty(nameof(ITenantIdFilter.TenantId)); Assert.NotNull(property); Assert.Equal(typeof(long?), property!.PropertyType); var sugarColumn = property.GetCustomAttributes(typeof(SugarColumn), inherit: true) .OfType() .SingleOrDefault(); Assert.NotNull(sugarColumn); Assert.Equal("tenant_id", sugarColumn!.ColumnName); } }