S8ReportTemplateService.cs 3.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Admin.NET.Plugin.AiDOP.Dto.S8;
  2. using Admin.NET.Plugin.AiDOP.Entity.S8;
  3. using Admin.NET.Plugin.AiDOP.Infrastructure;
  4. namespace Admin.NET.Plugin.AiDOP.Service.S8;
  5. /// <summary>
  6. /// S8-RULE-GOVERNANCE-BATCH4:主动提报模板的**只读**查询。
  7. ///
  8. /// <para><b>为什么会有这个服务</b>:Batch 3 退役配置向导时,审计结论是
  9. /// 「草稿 Controller 整体只服务 Wizard」—— 这条判断不完整。
  10. /// <c>ado_s8_config_draft</c> 上还骑着第二个消费方:主动提报页把
  11. /// <c>mechanism = MANUAL_REPORT</c> 的草稿当作**提报模板**使用
  12. /// (TASK-022-MANUAL-REPORT-TEMPLATE-1)。删掉整个 Controller 之后该功能已经死了,
  13. /// 而且是**静默**死的 —— 前端 list 走 catch 把模板列表置空,用户只会觉得"模板怎么没了"。</para>
  14. ///
  15. /// <para>本服务把那一半补回来,且只补只读的一半:</para>
  16. /// <list type="bullet">
  17. /// <item>只有 GET;没有 Create / Update / Delete;</item>
  18. /// <item>没有 <c>GenerateRule</c> —— 生成规则那条路已经永久关闭;</item>
  19. /// <item>只返回 <c>mechanism = MANUAL_REPORT</c> 的行,其余(历史规则向导草稿)一律不可见。</item>
  20. /// </list>
  21. ///
  22. /// <para><b>命名刻意不叫 draft / wizard</b>:正是那个名字让 Batch 3 把两个不同的功能
  23. /// 当成了同一个。路由与类型都改叫 report-template,让下一个读代码的人一眼看出它服务谁。</para>
  24. ///
  25. /// <para>实体与表仍按既有口径 KEEP_TEMPORARILY,后续 schema 清理时再决定是否拆表。</para>
  26. /// </summary>
  27. public class S8ReportTemplateService : ITransient
  28. {
  29. /// <summary>主动提报模板的机制标识。只有该值的草稿行才被视为模板。</summary>
  30. public const string ManualReportMechanism = "MANUAL_REPORT";
  31. private readonly SqlSugarRepository<AdoS8ConfigDraft> _rep;
  32. public S8ReportTemplateService(SqlSugarRepository<AdoS8ConfigDraft> rep) => _rep = rep;
  33. /// <summary>按可信作用域列出本租户 / 工厂的主动提报模板。</summary>
  34. public async Task<List<S8ReportTemplateRowDto>> ListAsync(S8TrustedScope scope)
  35. {
  36. var rows = await ScopedQuery(scope)
  37. .OrderBy(x => x.Id)
  38. .ToListAsync();
  39. return rows.Select(x => new S8ReportTemplateRowDto
  40. {
  41. Id = x.Id,
  42. TemplateCode = x.DraftCode,
  43. TemplateName = x.DraftName,
  44. Mechanism = x.Mechanism,
  45. StageCode = x.StageCode,
  46. OrderFlowCode = x.OrderFlowCode,
  47. ExceptionTypeCode = x.ExceptionTypeCode
  48. }).ToList();
  49. }
  50. /// <summary>
  51. /// 取模板详情(含 <c>wizardJson</c> 原文,由前端解析后填表)。
  52. /// 越权 / 非 MANUAL_REPORT 的 id 一律按「不存在」处理,不泄露它是否存在。
  53. /// </summary>
  54. public async Task<S8ReportTemplateDetailDto> GetAsync(long id, S8TrustedScope scope)
  55. {
  56. var row = await ScopedQuery(scope).Where(x => x.Id == id).FirstAsync()
  57. ?? throw new S8NotFoundException();
  58. return new S8ReportTemplateDetailDto
  59. {
  60. Id = row.Id,
  61. TemplateCode = row.DraftCode,
  62. TemplateName = row.DraftName,
  63. Mechanism = row.Mechanism,
  64. StageCode = row.StageCode,
  65. OrderFlowCode = row.OrderFlowCode,
  66. ExceptionTypeCode = row.ExceptionTypeCode,
  67. TemplateJson = row.WizardJson
  68. };
  69. }
  70. /// <summary>
  71. /// 作用域 + 机制双重过滤。
  72. /// 机制过滤不是可选项:库里还躺着历史的规则向导草稿,
  73. /// 放它们出来等于给已退役的建规则流程留了一个只读展示面。
  74. /// </summary>
  75. private ISugarQueryable<AdoS8ConfigDraft> ScopedQuery(S8TrustedScope scope) =>
  76. _rep.AsQueryable()
  77. .Where(x => x.TenantId == scope.TenantId)
  78. .Where(x => x.Mechanism == ManualReportMechanism);
  79. }