AidopTenantInitService.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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. private static readonly (string Code, string Name, int OrderNo)[] S8BusinessRoles =
  17. {
  18. ("ROLE_ORDER_PLANNER", "订单计划员", 800),
  19. ("ROLE_PRODUCTION_PLANNER", "生产计划员", 801),
  20. ("ROLE_PURCHASER", "采购员", 802),
  21. ("ROLE_WH_INBOUND", "仓库收货员", 803),
  22. ("ROLE_WH_OUTBOUND", "仓库发货员", 804),
  23. ("ROLE_QC", "质检员", 805),
  24. ("ROLE_EQUIP_MAINT", "设备维修员", 806),
  25. };
  26. private readonly ISqlSugarClient _db;
  27. public AidopTenantInitService(ISqlSugarClient db) => _db = db;
  28. /// <summary>幂等种入目标租户的 S8 业务角色、KPI 主数据/布局与 calc config;允许重复调用。</summary>
  29. public async Task InitTenantBaselineAsync(long tenantId)
  30. {
  31. if (tenantId <= 0) return;
  32. await SeedS8BusinessRolesAsync(tenantId);
  33. AidopImprovementApprovalSeed.EnsureBaselineRoles(_db, tenantId);
  34. await SeedS8ScenesFromTemplateAsync(tenantId);
  35. AidopKpiMasterSeed.EnsureSeed(_db, tenantId, includeDemoValues: false);
  36. await SeedKpiCalcConfigFromTemplateAsync(tenantId);
  37. }
  38. private async Task SeedS8ScenesFromTemplateAsync(long tenantId)
  39. {
  40. if (tenantId == S8SceneTemplateTenantId) return;
  41. var factoryId = await _db.Queryable<SysTenant>()
  42. .ClearFilter<ITenantIdFilter>()
  43. .Where(x => x.Id == tenantId)
  44. .Select(x => x.OrgId)
  45. .FirstAsync();
  46. if (factoryId <= 0) return;
  47. var templates = await _db.Queryable<AdoS8SceneConfig>()
  48. .ClearFilter<ITenantIdFilter>()
  49. .Where(x => x.TenantId == S8SceneTemplateTenantId && x.Enabled)
  50. .OrderBy(x => x.SortNo)
  51. .ToListAsync();
  52. var now = DateTime.Now;
  53. foreach (var template in templates)
  54. {
  55. var exists = await _db.Queryable<AdoS8SceneConfig>()
  56. .ClearFilter<ITenantIdFilter>()
  57. .AnyAsync(x => x.TenantId == tenantId
  58. && x.FactoryId == factoryId
  59. && x.SceneCode == template.SceneCode);
  60. if (exists) continue;
  61. await _db.Insertable(new AdoS8SceneConfig
  62. {
  63. TenantId = tenantId,
  64. FactoryId = factoryId,
  65. SceneCode = template.SceneCode,
  66. SceneName = template.SceneName,
  67. Enabled = true,
  68. SortNo = template.SortNo,
  69. CreatedAt = now,
  70. }).ExecuteCommandAsync();
  71. }
  72. }
  73. private async Task SeedS8BusinessRolesAsync(long tenantId)
  74. {
  75. var ct = DateTime.Now;
  76. foreach (var (code, name, orderNo) in S8BusinessRoles)
  77. {
  78. var exists = await _db.Queryable<SysRole>()
  79. .ClearFilter<ITenantIdFilter>()
  80. .AnyAsync(r => r.TenantId == tenantId && r.Code == code);
  81. if (exists) continue;
  82. await _db.Insertable(new SysRole
  83. {
  84. Id = YitIdHelper.NextId(),
  85. TenantId = tenantId,
  86. Name = name,
  87. Code = code,
  88. OrderNo = orderNo,
  89. DataScope = DataScopeEnum.Self,
  90. Status = StatusEnum.Enable,
  91. Remark = "S8 业务角色(异常协同承接)",
  92. CreateTime = ct,
  93. }).ExecuteCommandAsync();
  94. }
  95. }
  96. private async Task SeedKpiCalcConfigFromTemplateAsync(long tenantId)
  97. {
  98. if (tenantId == KpiTemplateTenantId) return;
  99. var templates = await _db.Queryable<AdoSmartOpsKpiCalcConfig>()
  100. .ClearFilter<ITenantIdFilter>()
  101. .Where(c => c.TenantId == KpiTemplateTenantId)
  102. .ToListAsync();
  103. if (templates.Count == 0) return;
  104. var now = DateTime.Now;
  105. foreach (var tpl in templates)
  106. {
  107. var exists = await _db.Queryable<AdoSmartOpsKpiCalcConfig>()
  108. .ClearFilter<ITenantIdFilter>()
  109. .AnyAsync(c => c.TenantId == tenantId && c.MetricCode == tpl.MetricCode && c.VersionNo == tpl.VersionNo);
  110. if (exists) continue;
  111. await _db.Insertable(new AdoSmartOpsKpiCalcConfig
  112. {
  113. TenantId = tenantId,
  114. MetricCode = tpl.MetricCode,
  115. ModuleCode = tpl.ModuleCode,
  116. VersionNo = tpl.VersionNo,
  117. CalcEngineType = tpl.CalcEngineType,
  118. DataSourceCode = tpl.DataSourceCode,
  119. SqlScript = tpl.SqlScript,
  120. SqlParametersJson = tpl.SqlParametersJson,
  121. TimeoutSeconds = tpl.TimeoutSeconds,
  122. PublishStatus = tpl.PublishStatus,
  123. IsCurrent = tpl.IsCurrent,
  124. Remark = tpl.Remark,
  125. CreatedBy = "AidopTenantInit",
  126. CreatedAt = now,
  127. }).ExecuteCommandAsync();
  128. }
  129. }
  130. }