|
|
@@ -17,32 +17,21 @@ public class S8MonitoringService : ITransient
|
|
|
private readonly SqlSugarRepository<AdoS0DepartmentMaster> _deptRep;
|
|
|
// TASK-012-S9-QDC-RATIO-MIGRATION-2:result KPI summary 读取 RATIO 指标字典
|
|
|
private readonly SqlSugarRepository<AdoS8MonitorMetric> _metricRep;
|
|
|
- // S9-RESULT-KPI-DEMO-BASELINE-AND-ORDER-FLOW-CALC-1:ORDER_FLOW_CYCLE_RATIO 半真实计算依赖订单链路阶段表
|
|
|
- private readonly SqlSugarRepository<AdoS8OrderFlowStage> _orderFlowStageRep;
|
|
|
- // S8-STEP4-KPI-CURRENT-VALUE-CLOSURE-1:ORDER_DELIVERY_RATE / PO_DELIVERY_RATE / WO_COMPLETION_RATE
|
|
|
- // 由 DEMO_BASELINE 常量改为订单链路真实聚合,各自依赖以下三张表。
|
|
|
- private readonly SqlSugarRepository<AdoS8OrderFlowOrder> _orderFlowOrderRep;
|
|
|
- private readonly SqlSugarRepository<AdoS8OrderFlowProcurementPivot> _procurementPivotRep;
|
|
|
- private readonly SqlSugarRepository<AdoS8OrderFlowManufacturingProcess> _manufacturingProcessRep;
|
|
|
+ // S8-REAL-DATA-PRESENTATION-1:原先这里注入了 ado_s8_order_flow_order / _procurement_pivot /
|
|
|
+ // _manufacturing_process / _stage 四个 SEED 仓储,用于把种子数据算成「当前 KPI」。
|
|
|
+ // 四项 KPI 已改为如实 PENDING_REAL(见 ComputeResultKpiCurrentAsync),依赖随之移除 ——
|
|
|
+ // 本服务从此与 ado_s8_order_flow_* **无任何运行期事实依赖**。
|
|
|
|
|
|
public S8MonitoringService(
|
|
|
SqlSugarRepository<AdoS8Exception> rep,
|
|
|
SqlSugarRepository<AdoS8ExceptionType> typeRep,
|
|
|
SqlSugarRepository<AdoS0DepartmentMaster> deptRep,
|
|
|
- SqlSugarRepository<AdoS8MonitorMetric> metricRep,
|
|
|
- SqlSugarRepository<AdoS8OrderFlowStage> orderFlowStageRep,
|
|
|
- SqlSugarRepository<AdoS8OrderFlowOrder> orderFlowOrderRep,
|
|
|
- SqlSugarRepository<AdoS8OrderFlowProcurementPivot> procurementPivotRep,
|
|
|
- SqlSugarRepository<AdoS8OrderFlowManufacturingProcess> manufacturingProcessRep)
|
|
|
+ SqlSugarRepository<AdoS8MonitorMetric> metricRep)
|
|
|
{
|
|
|
_rep = rep;
|
|
|
_typeRep = typeRep;
|
|
|
_deptRep = deptRep;
|
|
|
_metricRep = metricRep;
|
|
|
- _orderFlowStageRep = orderFlowStageRep;
|
|
|
- _orderFlowOrderRep = orderFlowOrderRep;
|
|
|
- _procurementPivotRep = procurementPivotRep;
|
|
|
- _manufacturingProcessRep = manufacturingProcessRep;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -794,11 +783,18 @@ public class S8MonitoringService : ITransient
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// S9-RESULT-KPI-DEMO-BASELINE-AND-ORDER-FLOW-CALC-1:A+B 混合方案。
|
|
|
- /// 4 个 KPI(ORDER_DELIVERY_RATE/PO_DELIVERY_RATE/IQC_PASS_RATE/WO_COMPLETION_RATE)→ DEMO_BASELINE 演示基线;
|
|
|
- /// 1 个 KPI(ORDER_FLOW_CYCLE_RATIO)→ ORDER_FLOW_CALC 基于 ado_s8_order_flow_stage 半真实计算;
|
|
|
- /// 不写 DB / 不接 period / 不启用 watch_rule。
|
|
|
- /// 来源:ado_s8_monitor_metric WHERE mechanism='RATIO' AND is_result_kpi=1(保留字典顺序与 metricName)。
|
|
|
+ /// 结果 KPI 汇总。来源:ado_s8_monitor_metric WHERE mechanism='RATIO' AND is_result_kpi=1
|
|
|
+ /// (保留字典顺序与 metricName)。不写 DB / 不接 period / 不启用 watch_rule。
|
|
|
+ ///
|
|
|
+ /// <para>S8-REAL-DATA-PRESENTATION-1 当前口径:
|
|
|
+ /// <c>IQC_PASS_RATE</c> → <c>DEMO_BASELINE</c>(常量,前端「当前基线」,如实标注);
|
|
|
+ /// 其余全部 → <c>PENDING_REAL</c>(无当前值,前端「待真实接入」)。
|
|
|
+ /// 曾经的 <c>ORDER_FLOW_CALC</c> 一路已全部撤除——它算的是 seed,详见
|
|
|
+ /// <see cref="ComputeResultKpiCurrentAsync"/>。</para>
|
|
|
+ ///
|
|
|
+ /// <para>⚠️ 本段历史注释曾写「4 个 KPI → DEMO_BASELINE / 1 个 → ORDER_FLOW_CALC」,
|
|
|
+ /// 与其后的实现长期不符(实际是 4 个走 ORDER_FLOW_CALC、仅 IQC 走 DEMO_BASELINE)。
|
|
|
+ /// 已按现行实现改写,勿再据旧文案推断行为。</para>
|
|
|
/// </summary>
|
|
|
/// <summary>
|
|
|
/// S8-CONFIG-AUTHORITY-FIX-1:结果 KPI 的「覆盖解析 → 启用门禁」。
|
|
|
@@ -888,10 +884,15 @@ public class S8MonitoringService : ITransient
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // S8-REAL-DATA-PRESENTATION-1:envelope 的 provenance 必须由 items 真实构成推出。
|
|
|
+ // 旧实现无条件写死 "MIXED_BASELINE",前端渲染「当前基线 · 部分订单链路计算」——
|
|
|
+ // 在 items 为空(当前实况:字典 5 行全部 enabled=0)或全部为基线/待接入时,
|
|
|
+ // 这句话是一个没有任何计算支撑的断言,属于把「没算」说成「部分算了」。
|
|
|
+ var hasRealCalc = items.Exists(i => i.Source == "ORDER_FLOW_CALC");
|
|
|
return new AdoS8ResultKpiSummaryDto
|
|
|
{
|
|
|
Items = items,
|
|
|
- Source = "MIXED_BASELINE",
|
|
|
+ Source = hasRealCalc ? "MIXED_BASELINE" : "DICTIONARY_MOCK",
|
|
|
};
|
|
|
}
|
|
|
|
|
|
@@ -909,79 +910,42 @@ public class S8MonitoringService : ITransient
|
|
|
};
|
|
|
|
|
|
/// <summary>
|
|
|
- /// S8-STEP4-KPI-CURRENT-VALUE-CLOSURE-1:结果 KPI 当前值的真实聚合分发。
|
|
|
- /// 返回 null 表示该指标不由订单链路计算(调用方回落 DEMO_BASELINE / PENDING_REAL)。
|
|
|
- /// 统一口径:只统计 tenant/factory 内未删除、且 <c>order_code</c> 非空的**订单关联业务记录**;
|
|
|
- /// order_code 为空的 BASELINE_PPT / DEMO 演示装置行不是业务记录,一律排除。
|
|
|
- /// </summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source, string Remark)?> ComputeResultKpiCurrentAsync(
|
|
|
- string metricCode, long tenantId) => metricCode switch
|
|
|
- {
|
|
|
- "ORDER_DELIVERY_RATE" => await ComputeOrderDeliveryRateAsync(tenantId),
|
|
|
- "PO_DELIVERY_RATE" => await ComputePoDeliveryRateAsync(tenantId),
|
|
|
- "WO_COMPLETION_RATE" => await ComputeWoCompletionRateAsync(tenantId),
|
|
|
- "ORDER_FLOW_CYCLE_RATIO" => await ComputeOrderFlowCycleRatioItemAsync(tenantId),
|
|
|
- _ => null,
|
|
|
- };
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 订单交付满足率 = 已完工订单中 actual_cycle_days <= target_cycle_days 的占比。
|
|
|
- /// 分母只含 actual_cycle_days 已回填的订单(在制订单尚无实际周期,纳入会系统性低估)。
|
|
|
- /// </summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source, string Remark)> ComputeOrderDeliveryRateAsync(
|
|
|
- long tenantId)
|
|
|
- {
|
|
|
- var rows = await _orderFlowOrderRep.AsQueryable()
|
|
|
- .Where(x => !x.IsDeleted && x.TenantId == tenantId
|
|
|
- && x.ActualCycleDays != null)
|
|
|
- .Select(x => new { x.ActualCycleDays, x.TargetCycleDays })
|
|
|
- .ToListAsync();
|
|
|
- const string remark = "基于订单链路已完工订单 actual_cycle_days/target_cycle_days 计算,在制订单不纳入分母";
|
|
|
- if (rows.Count == 0) return (null, "ORDER_FLOW_CALC_EMPTY", remark);
|
|
|
- var numerator = rows.Count(x => x.ActualCycleDays!.Value <= x.TargetCycleDays);
|
|
|
- return (Math.Round(numerator * 100m / rows.Count, 1), "ORDER_FLOW_CALC", remark);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 到货达成率 = 采购透视中 status='green'(按期到货)的占比;yellow/red 均计入分母。
|
|
|
- /// </summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source, string Remark)> ComputePoDeliveryRateAsync(
|
|
|
- long tenantId)
|
|
|
- {
|
|
|
- var rows = await _procurementPivotRep.AsQueryable()
|
|
|
- .Where(x => !x.IsDeleted && x.TenantId == tenantId
|
|
|
- && x.OrderCode != null && x.OrderCode != "")
|
|
|
- .Select(x => x.Status)
|
|
|
- .ToListAsync();
|
|
|
- const string remark = "基于订单关联采购透视 status 计算:green 为按期到货,yellow/red 计入分母";
|
|
|
- if (rows.Count == 0) return (null, "ORDER_FLOW_CALC_EMPTY", remark);
|
|
|
- var numerator = rows.Count(s => s == "green");
|
|
|
- return (Math.Round(numerator * 100m / rows.Count, 1), "ORDER_FLOW_CALC", remark);
|
|
|
- }
|
|
|
-
|
|
|
- /// <summary>
|
|
|
- /// 工单完工率 = 订单关联制造工序 achievement_rate 的算术平均(存储为 0~1 比率,×100 转百分比)。
|
|
|
+ /// S8-REAL-DATA-PRESENTATION-1:结果 KPI「当前值」的真实 Authority 分发点。
|
|
|
+ /// 返回 null = 该指标当前没有真实计算,调用方回落 DEMO_BASELINE / PENDING_REAL。
|
|
|
+ ///
|
|
|
+ /// <para><b>这里为什么一个计算都没有了</b>:ORDER_DELIVERY_RATE / PO_DELIVERY_RATE /
|
|
|
+ /// WO_COMPLETION_RATE / ORDER_FLOW_CYCLE_RATIO 此前分别读
|
|
|
+ /// <c>ado_s8_order_flow_order</c> / <c>_procurement_pivot</c> / <c>_manufacturing_process</c> /
|
|
|
+ /// <c>_stage</c>,并以 <c>Source="ORDER_FLOW_CALC"</c>(前端渲染「订单链路计算」)
|
|
|
+ /// 宣称是对当前业务的实算。但这四张表**唯一的写入方是 SeedData**,实库全部行
|
|
|
+ /// <c>data_source='SEED'</c>,四个查询也从不过滤 SEED —— 数字不是业务事实,标注是错的。</para>
|
|
|
+ ///
|
|
|
+ /// <para><b>为何不改成读中台而是直接不出值</b>(逐项核对,四项均无等价 Authority):
|
|
|
+ /// <list type="bullet">
|
|
|
+ /// <item>ORDER_DELIVERY_RATE:<c>dwd_t8_order_shipment_fulfillment</c> 是「行级发运及时率 / 按 biz_date」,
|
|
|
+ /// 与「订单周期 actual <= target」不同口径,换算须自行发明时间窗并改分母粒度;</item>
|
|
|
+ /// <item>PO_DELIVERY_RATE:<c>mdp_std_purchase_order_completion</c> **既无承诺到期日、也无实际到货日**
|
|
|
+ /// (<c>observed_at</c> / <c>source_update_time</c> 在表注释中被明确标注「禁止冒充业务完成时间」),
|
|
|
+ /// 按期到货率在现有中台里根本不可算;</item>
|
|
|
+ /// <item>WO_COMPLETION_RATE:<c>dwd_t8_work_order_mfg_fulfillment</c> 粒度是
|
|
|
+ /// (biz_date, 工单, 物料) 的窗口完成率,与「工序 achievement_rate 算术平均」不同,
|
|
|
+ /// 换算须自行选定 biz_date 与再聚合规则;</item>
|
|
|
+ /// <item>ORDER_FLOW_CYCLE_RATIO:中台没有任何对象承载 S8 五阶段的 planned/actual days。</item>
|
|
|
+ /// </list>
|
|
|
+ /// 按「不得为了保住卡片而发明公式」的口径,四项一律不出当前值,落 PENDING_REAL
|
|
|
+ /// (前端「待真实接入」),与 IQC_PASS_RATE 的如实标注是同一范式。</para>
|
|
|
+ ///
|
|
|
+ /// <para>⚠️ 真实 Authority 就位后在此接回并改回具体 Source;
|
|
|
+ /// <b>不要改回读 ado_s8_order_flow_*</b> —— 那是 seed,不是业务事实。</para>
|
|
|
/// </summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source, string Remark)> ComputeWoCompletionRateAsync(
|
|
|
- long tenantId)
|
|
|
+ private static Task<(decimal? CurrentValue, string Source, string Remark)?> ComputeResultKpiCurrentAsync(
|
|
|
+ string metricCode, long tenantId)
|
|
|
{
|
|
|
- var rows = await _manufacturingProcessRep.AsQueryable()
|
|
|
- .Where(x => !x.IsDeleted && x.TenantId == tenantId
|
|
|
- && x.OrderCode != null && x.OrderCode != "" && x.AchievementRate != null)
|
|
|
- .Select(x => x.AchievementRate)
|
|
|
- .ToListAsync();
|
|
|
- const string remark = "基于订单关联制造工序 achievement_rate 平均值计算(0~1 比率换算百分比)";
|
|
|
- if (rows.Count == 0) return (null, "ORDER_FLOW_CALC_EMPTY", remark);
|
|
|
- return (Math.Round(rows.Sum(x => x!.Value) * 100m / rows.Count, 1), "ORDER_FLOW_CALC", remark);
|
|
|
+ _ = metricCode;
|
|
|
+ _ = tenantId;
|
|
|
+ return Task.FromResult<(decimal? CurrentValue, string Source, string Remark)?>(null);
|
|
|
}
|
|
|
|
|
|
- /// <summary>ORDER_FLOW_CYCLE_RATIO 适配到统一分发签名;计算逻辑保持不变。</summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source, string Remark)> ComputeOrderFlowCycleRatioItemAsync(
|
|
|
- long tenantId)
|
|
|
- {
|
|
|
- var (cv, source) = await ComputeOrderFlowCycleRatioAsync(tenantId);
|
|
|
- return (cv, source, "基于已完成订单链路阶段 actual_days/planned_days 计算,pending 阶段暂不纳入");
|
|
|
- }
|
|
|
|
|
|
/// <summary>
|
|
|
/// 生效目标值:rows 已按 (0,0) 平台默认 ‖ 本租户覆盖取回并按「租户行优先」去重,
|
|
|
@@ -990,30 +954,4 @@ public class S8MonitoringService : ITransient
|
|
|
/// </summary>
|
|
|
private static decimal? ResolveEffectiveTarget(AdoS8MonitorMetric m) => m.DefaultTargetRatio;
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// 候选 A:actual_days IS NOT NULL 的已完成阶段中 actual_days <= planned_days 的占比。
|
|
|
- /// pending 阶段不纳入 denominator;不依赖 status 字段;按 tenant 过滤(S8-TENANT-ONLY-BATCH6)。
|
|
|
- /// </summary>
|
|
|
- private async Task<(decimal? CurrentValue, string Source)> ComputeOrderFlowCycleRatioAsync(long tenantId)
|
|
|
- {
|
|
|
- try
|
|
|
- {
|
|
|
- var stages = await _orderFlowStageRep.AsQueryable()
|
|
|
- .Where(x => !x.IsDeleted && x.TenantId == tenantId
|
|
|
- && x.ActualDays != null)
|
|
|
- .Select(x => new { x.ActualDays, x.PlannedDays })
|
|
|
- .ToListAsync();
|
|
|
-
|
|
|
- var denominator = stages.Count;
|
|
|
- if (denominator == 0) return (null, "ORDER_FLOW_CALC_EMPTY");
|
|
|
-
|
|
|
- var numerator = stages.Count(s => s.ActualDays!.Value <= s.PlannedDays);
|
|
|
- var value = Math.Round(numerator * 100m / denominator, 1);
|
|
|
- return (value, "ORDER_FLOW_CALC");
|
|
|
- }
|
|
|
- catch
|
|
|
- {
|
|
|
- return (null, "ORDER_FLOW_CALC_EMPTY");
|
|
|
- }
|
|
|
- }
|
|
|
}
|