using Admin.NET.Plugin.AiDOP.Dto.S8; using Admin.NET.Plugin.AiDOP.Entity.S8; using Admin.NET.Plugin.AiDOP.Infrastructure; namespace Admin.NET.Plugin.AiDOP.Service.S8; /// /// S8-RULE-GOVERNANCE-BATCH4:主动提报模板的**只读**查询。 /// /// 为什么会有这个服务:Batch 3 退役配置向导时,审计结论是 /// 「草稿 Controller 整体只服务 Wizard」—— 这条判断不完整。 /// ado_s8_config_draft 上还骑着第二个消费方:主动提报页把 /// mechanism = MANUAL_REPORT 的草稿当作**提报模板**使用 /// (TASK-022-MANUAL-REPORT-TEMPLATE-1)。删掉整个 Controller 之后该功能已经死了, /// 而且是**静默**死的 —— 前端 list 走 catch 把模板列表置空,用户只会觉得"模板怎么没了"。 /// /// 本服务把那一半补回来,且只补只读的一半: /// /// 只有 GET;没有 Create / Update / Delete; /// 没有 GenerateRule —— 生成规则那条路已经永久关闭; /// 只返回 mechanism = MANUAL_REPORT 的行,其余(历史规则向导草稿)一律不可见。 /// /// /// 命名刻意不叫 draft / wizard:正是那个名字让 Batch 3 把两个不同的功能 /// 当成了同一个。路由与类型都改叫 report-template,让下一个读代码的人一眼看出它服务谁。 /// /// 实体与表仍按既有口径 KEEP_TEMPORARILY,后续 schema 清理时再决定是否拆表。 /// public class S8ReportTemplateService : ITransient { /// 主动提报模板的机制标识。只有该值的草稿行才被视为模板。 public const string ManualReportMechanism = "MANUAL_REPORT"; private readonly SqlSugarRepository _rep; public S8ReportTemplateService(SqlSugarRepository rep) => _rep = rep; /// 按可信作用域列出本租户 / 工厂的主动提报模板。 public async Task> ListAsync(S8TrustedScope scope) { var rows = await ScopedQuery(scope) .OrderBy(x => x.Id) .ToListAsync(); return rows.Select(x => new S8ReportTemplateRowDto { Id = x.Id, TemplateCode = x.DraftCode, TemplateName = x.DraftName, Mechanism = x.Mechanism, StageCode = x.StageCode, OrderFlowCode = x.OrderFlowCode, ExceptionTypeCode = x.ExceptionTypeCode }).ToList(); } /// /// 取模板详情(含 wizardJson 原文,由前端解析后填表)。 /// 越权 / 非 MANUAL_REPORT 的 id 一律按「不存在」处理,不泄露它是否存在。 /// public async Task GetAsync(long id, S8TrustedScope scope) { var row = await ScopedQuery(scope).Where(x => x.Id == id).FirstAsync() ?? throw new S8NotFoundException(); return new S8ReportTemplateDetailDto { Id = row.Id, TemplateCode = row.DraftCode, TemplateName = row.DraftName, Mechanism = row.Mechanism, StageCode = row.StageCode, OrderFlowCode = row.OrderFlowCode, ExceptionTypeCode = row.ExceptionTypeCode, TemplateJson = row.WizardJson }; } /// /// 作用域 + 机制双重过滤。 /// 机制过滤不是可选项:库里还躺着历史的规则向导草稿, /// 放它们出来等于给已退役的建规则流程留了一个只读展示面。 /// private ISugarQueryable ScopedQuery(S8TrustedScope scope) => _rep.AsQueryable() .Where(x => x.TenantId == scope.TenantId) .Where(x => x.Mechanism == ManualReportMechanism); }