| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess;
- /// <summary>
- /// 数据集能力声明,分两层:
- ///
- /// <b>A. 机制能力</b>(SupportsXxx):该数据集打算支撑哪几类规则判定。
- /// <b>B. 字段能力</b>(HasXxx):该数据集实际能提供哪些 canonical 字段。
- ///
- /// 分两层的理由:单一布尔位不可信。声明 SupportsTimeout=true 却拿不出 due_at 是一种
- /// 自相矛盾的配置,运行期只会表现为"永不命中"的静默失效。两层交叉校验才能在启用前发现。
- ///
- /// 字段能力回答的是"这个数据集有没有这个字段",与"某一行该字段值为 NULL"是两件事:
- /// 前者是能力问题(规则不能启用),后者由 evaluator 按原规则跳过该行。
- /// </summary>
- public sealed class S8DatasetCapabilities
- {
- // ---------- A. 机制能力 ----------
- /// <summary>可支撑 TIMEOUT。</summary>
- public bool SupportsTimeout { get; init; }
- /// <summary>可支撑 SHORTAGE。</summary>
- public bool SupportsShortage { get; init; }
- /// <summary>可支撑 OUT_OF_RANGE。</summary>
- public bool SupportsOutOfRange { get; init; }
- // ---------- B. 字段能力 ----------
- /// <summary>能提供 source_object_id(对象身份 + DedupKey 输入)。</summary>
- public bool HasSourceObjectId { get; init; }
- /// <summary>能提供 related_object_code。</summary>
- public bool HasRelatedObjectCode { get; init; }
- /// <summary>能提供 due_at。</summary>
- public bool HasDueAt { get; init; }
- /// <summary>能提供 status。</summary>
- public bool HasStatus { get; init; }
- /// <summary>能提供 measured_value。</summary>
- public bool HasMeasuredValue { get; init; }
- /// <summary>能提供 target_qty。</summary>
- public bool HasTargetQty { get; init; }
- /// <summary>能提供 actual_qty。</summary>
- public bool HasActualQty { get; init; }
- /// <summary>该数据集是否声明支持给定规则类型(仅机制层,未校验字段是否齐备)。</summary>
- public bool Supports(string? ruleType)
- {
- if (string.IsNullOrWhiteSpace(ruleType)) return false;
- return ruleType.Trim().ToUpperInvariant() switch
- {
- "TIMEOUT" => SupportsTimeout,
- "SHORTAGE" => SupportsShortage,
- "OUT_OF_RANGE" => SupportsOutOfRange,
- _ => false
- };
- }
- /// <summary>该数据集是否能提供给定 canonical 字段。</summary>
- public bool HasField(string? canonicalColumn)
- {
- if (string.IsNullOrWhiteSpace(canonicalColumn)) return false;
- return canonicalColumn.Trim().ToLowerInvariant() switch
- {
- S8CanonicalColumns.SourceObjectId => HasSourceObjectId,
- S8CanonicalColumns.RelatedObjectCode => HasRelatedObjectCode,
- S8CanonicalColumns.DueAt => HasDueAt,
- S8CanonicalColumns.Status => HasStatus,
- S8CanonicalColumns.MeasuredValue => HasMeasuredValue,
- S8CanonicalColumns.TargetQty => HasTargetQty,
- S8CanonicalColumns.ActualQty => HasActualQty,
- _ => false
- };
- }
- /// <summary>
- /// 返回该规则类型缺少的 canonical 字段。空集合表示字段能力齐备。
- /// 未知规则类型返回 null(由调用方按 unknown_rule_type 处理,与"字段缺失"区分)。
- /// </summary>
- public IReadOnlyList<string>? MissingFieldsFor(string? ruleType)
- {
- var required = S8RuleTypeFieldRequirements.For(ruleType);
- if (required == null) return null;
- return required.Where(field => !HasField(field)).ToList();
- }
- /// <summary>机制能力与字段能力是否都满足该规则类型。</summary>
- public bool CanServe(string? ruleType)
- {
- if (!Supports(ruleType)) return false;
- var missing = MissingFieldsFor(ruleType);
- return missing != null && missing.Count == 0;
- }
- }
|