AidopTenantInitService.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using Admin.NET.Plugin.AiDOP.Entity;
  2. using Admin.NET.Plugin.AiDOP.Entity.S8;
  3. using Admin.NET.Plugin.AiDOP.Service.S8.OrderFlow;
  4. using Yitter.IdGenerator;
  5. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  6. /// <summary>
  7. /// Ai-DOP 每租户必备基线:S8 七个业务角色 + KPI calc config(从 AIDOP 模板租户复制)。
  8. /// 形态为「每租户复制」,便于各租户独立调整 KPI 公式与角色配置。
  9. /// </summary>
  10. public sealed class AidopTenantInitService : ITransient
  11. {
  12. /// <summary>AIDOP 运行租户:KPI calc config 模板来源。</summary>
  13. public const long KpiTemplateTenantId = 797403760988229L;
  14. /// <summary>AIDOPDemo:S8 七模块场景模板来源,不含规则、数据源或凭据。</summary>
  15. public const long S8SceneTemplateTenantId = 797403760988230L;
  16. // S8-CFG-NOTIFY-NONDEFAULT-ROLE-OPTIONS-FIX-1:改引用 canonical 单一来源。
  17. // 原先此处与 S8SysRoleSeedData 各存一份逐字相同的字面量,靠人工同步;
  18. // role-options 若再复制第三份必然分叉,故统一收口到 S8CanonicalRole。内容未变。
  19. private static (string Code, string Name, int OrderNo)[] S8BusinessRoles
  20. => Admin.NET.Plugin.AiDOP.Infrastructure.S8.S8CanonicalRole.BusinessRoles;
  21. private readonly ISqlSugarClient _db;
  22. public AidopTenantInitService(ISqlSugarClient db) => _db = db;
  23. /// <summary>幂等种入目标租户的 S8 业务角色、KPI 主数据/布局与 calc config;允许重复调用。</summary>
  24. public async Task InitTenantBaselineAsync(long tenantId)
  25. {
  26. if (tenantId <= 0) return;
  27. await SeedS8BusinessRolesAsync(tenantId);
  28. AidopImprovementApprovalSeed.EnsureBaselineRoles(_db, tenantId);
  29. await SeedS8ScenesFromTemplateAsync(tenantId);
  30. AidopKpiMasterSeed.EnsureSeed(_db, tenantId, includeDemoValues: false);
  31. await SeedKpiCalcConfigFromTemplateAsync(tenantId);
  32. }
  33. private async Task SeedS8ScenesFromTemplateAsync(long tenantId)
  34. {
  35. if (tenantId == S8SceneTemplateTenantId) return;
  36. var factoryId = await _db.Queryable<SysTenant>()
  37. .ClearFilter<ITenantIdFilter>()
  38. .Where(x => x.Id == tenantId)
  39. .Select(x => x.OrgId)
  40. .FirstAsync();
  41. if (factoryId <= 0) return;
  42. var templates = await _db.Queryable<AdoS8SceneConfig>()
  43. .ClearFilter<ITenantIdFilter>()
  44. .Where(x => x.TenantId == S8SceneTemplateTenantId && x.Enabled)
  45. .OrderBy(x => x.SortNo)
  46. .ToListAsync();
  47. var now = DateTime.Now;
  48. foreach (var template in templates)
  49. {
  50. var exists = await _db.Queryable<AdoS8SceneConfig>()
  51. .ClearFilter<ITenantIdFilter>()
  52. .AnyAsync(x => x.TenantId == tenantId
  53. && x.FactoryId == factoryId
  54. && x.SceneCode == template.SceneCode);
  55. if (exists) continue;
  56. await _db.Insertable(new AdoS8SceneConfig
  57. {
  58. TenantId = tenantId,
  59. FactoryId = factoryId,
  60. SceneCode = template.SceneCode,
  61. SceneName = template.SceneName,
  62. Enabled = true,
  63. SortNo = template.SortNo,
  64. CreatedAt = now,
  65. }).ExecuteCommandAsync();
  66. }
  67. }
  68. private async Task SeedS8BusinessRolesAsync(long tenantId)
  69. {
  70. var ct = DateTime.Now;
  71. foreach (var (code, name, orderNo) in S8BusinessRoles)
  72. {
  73. var exists = await _db.Queryable<SysRole>()
  74. .ClearFilter<ITenantIdFilter>()
  75. .AnyAsync(r => r.TenantId == tenantId && r.Code == code);
  76. if (exists) continue;
  77. await _db.Insertable(new SysRole
  78. {
  79. Id = YitIdHelper.NextId(),
  80. TenantId = tenantId,
  81. Name = name,
  82. Code = code,
  83. OrderNo = orderNo,
  84. DataScope = DataScopeEnum.Self,
  85. Status = StatusEnum.Enable,
  86. Remark = "S8 业务角色(异常协同承接)",
  87. CreateTime = ct,
  88. }).ExecuteCommandAsync();
  89. }
  90. }
  91. private async Task SeedKpiCalcConfigFromTemplateAsync(long tenantId)
  92. {
  93. if (tenantId == KpiTemplateTenantId) return;
  94. var templates = await _db.Queryable<AdoSmartOpsKpiCalcConfig>()
  95. .ClearFilter<ITenantIdFilter>()
  96. .Where(c => c.TenantId == KpiTemplateTenantId)
  97. .ToListAsync();
  98. if (templates.Count == 0) return;
  99. var now = DateTime.Now;
  100. foreach (var tpl in templates)
  101. {
  102. var exists = await _db.Queryable<AdoSmartOpsKpiCalcConfig>()
  103. .ClearFilter<ITenantIdFilter>()
  104. .AnyAsync(c => c.TenantId == tenantId && c.MetricCode == tpl.MetricCode && c.VersionNo == tpl.VersionNo);
  105. if (exists) continue;
  106. await _db.Insertable(new AdoSmartOpsKpiCalcConfig
  107. {
  108. TenantId = tenantId,
  109. MetricCode = tpl.MetricCode,
  110. ModuleCode = tpl.ModuleCode,
  111. VersionNo = tpl.VersionNo,
  112. CalcEngineType = tpl.CalcEngineType,
  113. DataSourceCode = tpl.DataSourceCode,
  114. SqlScript = tpl.SqlScript,
  115. SqlParametersJson = tpl.SqlParametersJson,
  116. TimeoutSeconds = tpl.TimeoutSeconds,
  117. PublishStatus = tpl.PublishStatus,
  118. IsCurrent = tpl.IsCurrent,
  119. Remark = tpl.Remark,
  120. CreatedBy = "AidopTenantInit",
  121. CreatedAt = now,
  122. }).ExecuteCommandAsync();
  123. }
  124. }
  125. }