-- =====================================================
-- 工单执行进度与异常节点SQL
-- 数据库: PostgreSQL
-- 实时拉取工单数据，动态映射订单各环节状态
-- =====================================================

-- =====================================================
-- 1. 工单执行进度主视图
-- =====================================================
WITH work_order_base AS (
    SELECT 
        wo.work_order_id,
        wo.work_order_number,
        wo.product_id,
        wo.status,
        wo.planned_qty,
        wo.completed_qty,
        wo.event_time_utc::timestamp AS start_time,
        wo.last_updated_utc::timestamp AS last_update,
        wo.source_system
    FROM fact_work_order wo
),

product_info AS (
    SELECT 
        product_id,
        product_name,
        product_category
    FROM dim_product
    WHERE is_current = 't'
),

labor_summary AS (
    SELECT 
        work_order_number,
        COUNT(DISTINCT worker_name) AS worker_count,
        SUM(report_qty) AS total_report_qty,
        SUM(duration_minutes) AS total_minutes,
        MAX(event_time_utc::timestamp) AS last_report_time
    FROM fact_labor_report
    GROUP BY work_order_number
),

quality_summary AS (
    SELECT 
        work_order_number,
        SUM(pass_qty) AS pass_qty,
        SUM(fail_qty) AS fail_qty
    FROM fact_quality_inspection
    GROUP BY work_order_number
),

-- =====================================================
-- 2. 工单进度计算与状态映射
-- =====================================================
work_order_progress AS (
    SELECT 
        wb.work_order_id,
        wb.work_order_number,
        p.product_name,
        p.product_category,
        wb.status AS raw_status,
        
        -- 状态映射
        CASE wb.status
            WHEN 'OPEN' THEN '待生产'
            WHEN 'STARTED' THEN '生产中'
            WHEN 'CLOSED' THEN '已完成'
            ELSE '未知'
        END AS status_name,
        
        wb.planned_qty,
        wb.completed_qty,
        
        -- 完成进度
        CASE WHEN wb.planned_qty > 0 
             THEN ROUND(wb.completed_qty * 100.0 / wb.planned_qty, 1)
             ELSE 0 END AS completion_rate,
        
        -- 剩余数量
        GREATEST(wb.planned_qty - wb.completed_qty, 0) AS remaining_qty,
        
        wb.start_time,
        wb.last_update,
        
        -- 已用时间(小时)
        ROUND(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - wb.start_time)) / 3600, 1) AS elapsed_hours,
        
        -- 报工信息
        COALESCE(ls.worker_count, 0) AS worker_count,
        COALESCE(ls.total_report_qty, 0) AS total_report_qty,
        COALESCE(ls.total_minutes, 0) AS total_work_minutes,
        ls.last_report_time,
        
        -- 质检信息
        COALESCE(qs.pass_qty, 0) AS qc_pass_qty,
        COALESCE(qs.fail_qty, 0) AS qc_fail_qty
        
    FROM work_order_base wb
    LEFT JOIN product_info p ON wb.product_id = p.product_id
    LEFT JOIN labor_summary ls ON wb.work_order_number = ls.work_order_number
    LEFT JOIN quality_summary qs ON wb.work_order_number = qs.work_order_number
),

-- =====================================================
-- 3. 异常节点检测
-- =====================================================
anomaly_detection AS (
    SELECT 
        *,
        
        -- 进度异常：进行中但完成率过低
        CASE 
            WHEN raw_status = 'STARTED' AND elapsed_hours > 48 AND completion_rate < 20 THEN '进度严重滞后'
            WHEN raw_status = 'STARTED' AND elapsed_hours > 24 AND completion_rate < 30 THEN '进度滞后'
            ELSE NULL
        END AS progress_anomaly,
        
        -- 质量异常：废品率过高
        CASE 
            WHEN qc_pass_qty + qc_fail_qty > 0 
                 AND qc_fail_qty * 100.0 / (qc_pass_qty + qc_fail_qty) > 10 THEN '质量异常'
            ELSE NULL
        END AS quality_anomaly,
        
        -- 报工异常：长时间无报工
        CASE 
            WHEN raw_status = 'STARTED' 
                 AND last_report_time IS NOT NULL
                 AND EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - last_report_time)) / 3600 > 24 THEN '报工停滞'
            WHEN raw_status = 'STARTED' 
                 AND last_report_time IS NULL 
                 AND elapsed_hours > 24 THEN '无报工记录'
            ELSE NULL
        END AS labor_anomaly,
        
        -- 效率异常：人效过低
        CASE 
            WHEN total_work_minutes > 0 
                 AND total_report_qty / (total_work_minutes / 60.0) < 5 THEN '效率偏低'
            ELSE NULL
        END AS efficiency_anomaly
        
    FROM work_order_progress
)

-- =====================================================
-- 输出：工单执行进度明细
-- =====================================================
SELECT 
    work_order_number AS "工单号",
    product_name AS "产品名称",
    product_category AS "产品类别",
    status_name AS "状态",
    planned_qty AS "计划数量",
    completed_qty AS "完成数量",
    remaining_qty AS "剩余数量",
    completion_rate AS "完成率(%)",
    worker_count AS "参与人数",
    ROUND(total_work_minutes / 60.0, 1) AS "累计工时(小时)",
    elapsed_hours AS "已用时间(小时)",
    
    -- 异常标记
    COALESCE(progress_anomaly, '') || 
    CASE WHEN progress_anomaly IS NOT NULL AND quality_anomaly IS NOT NULL THEN ',' ELSE '' END ||
    COALESCE(quality_anomaly, '') ||
    CASE WHEN (progress_anomaly IS NOT NULL OR quality_anomaly IS NOT NULL) AND labor_anomaly IS NOT NULL THEN ',' ELSE '' END ||
    COALESCE(labor_anomaly, '') ||
    CASE WHEN (progress_anomaly IS NOT NULL OR quality_anomaly IS NOT NULL OR labor_anomaly IS NOT NULL) AND efficiency_anomaly IS NOT NULL THEN ',' ELSE '' END ||
    COALESCE(efficiency_anomaly, '') AS "异常标记",
    
    -- 风险等级
    CASE 
        WHEN progress_anomaly = '进度严重滞后' OR quality_anomaly IS NOT NULL THEN '高'
        WHEN progress_anomaly = '进度滞后' OR labor_anomaly IS NOT NULL THEN '中'
        WHEN efficiency_anomaly IS NOT NULL THEN '低'
        ELSE '-'
    END AS "风险等级"
    
FROM anomaly_detection
ORDER BY 
    CASE raw_status WHEN 'STARTED' THEN 1 WHEN 'OPEN' THEN 2 ELSE 3 END,
    CASE WHEN progress_anomaly IS NOT NULL THEN 0 ELSE 1 END,
    completion_rate ASC;


-- =====================================================
-- 补充查询1：工单状态分布汇总
-- =====================================================
WITH status_summary AS (
    SELECT 
        CASE status
            WHEN 'OPEN' THEN '待生产'
            WHEN 'STARTED' THEN '生产中'
            WHEN 'CLOSED' THEN '已完成'
            ELSE '未知'
        END AS status_name,
        status AS raw_status,
        COUNT(*) AS order_count,
        SUM(planned_qty) AS total_planned,
        SUM(completed_qty) AS total_completed
    FROM fact_work_order
    GROUP BY status
)
SELECT 
    status_name AS "状态",
    order_count AS "工单数",
    ROUND(order_count * 100.0 / SUM(order_count) OVER (), 1) AS "占比(%)",
    ROUND(total_planned, 0) AS "计划总量",
    ROUND(total_completed, 0) AS "完成总量",
    CASE WHEN total_planned > 0 
         THEN ROUND(total_completed * 100.0 / total_planned, 1)
         ELSE 0 END AS "完成率(%)"
FROM status_summary
ORDER BY 
    CASE raw_status WHEN 'STARTED' THEN 1 WHEN 'OPEN' THEN 2 ELSE 3 END;


-- =====================================================
-- 补充查询2：异常工单预警清单
-- =====================================================
WITH work_order_anomaly AS (
    SELECT 
        wo.work_order_number,
        p.product_name,
        wo.status,
        wo.planned_qty,
        wo.completed_qty,
        CASE WHEN wo.planned_qty > 0 
             THEN ROUND(wo.completed_qty * 100.0 / wo.planned_qty, 1)
             ELSE 0 END AS completion_rate,
        ROUND(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - wo.event_time_utc::timestamp)) / 3600, 1) AS elapsed_hours,
        (SELECT MAX(lr.event_time_utc::timestamp) 
         FROM fact_labor_report lr 
         WHERE lr.work_order_number = wo.work_order_number) AS last_report_time
    FROM fact_work_order wo
    LEFT JOIN dim_product p ON wo.product_id = p.product_id AND p.is_current = 't'
    WHERE wo.status = 'STARTED'
)
SELECT 
    work_order_number AS "工单号",
    product_name AS "产品",
    ROUND(planned_qty, 0) AS "计划数量",
    ROUND(completed_qty, 0) AS "完成数量",
    completion_rate AS "完成率(%)",
    elapsed_hours AS "已用时间(小时)",
    CASE 
        WHEN elapsed_hours > 48 AND completion_rate < 20 THEN '进度严重滞后'
        WHEN elapsed_hours > 24 AND completion_rate < 30 THEN '进度滞后'
        WHEN last_report_time IS NULL AND elapsed_hours > 24 THEN '无报工记录'
        WHEN last_report_time IS NOT NULL 
             AND EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - last_report_time)) / 3600 > 24 THEN '报工停滞'
        ELSE '正常'
    END AS "异常类型",
    CASE 
        WHEN elapsed_hours > 48 AND completion_rate < 20 THEN '立即跟进，排查生产瓶颈'
        WHEN elapsed_hours > 24 AND completion_rate < 30 THEN '关注进度，协调资源'
        WHEN last_report_time IS NULL AND elapsed_hours > 24 THEN '确认工单是否已开工'
        WHEN last_report_time IS NOT NULL 
             AND EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - last_report_time)) / 3600 > 24 THEN '跟进报工情况'
        ELSE '-'
    END AS "处理建议"
FROM work_order_anomaly
WHERE elapsed_hours > 24 AND completion_rate < 50
   OR (last_report_time IS NULL AND elapsed_hours > 24)
   OR (last_report_time IS NOT NULL 
       AND EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - last_report_time)) / 3600 > 24)
ORDER BY 
    CASE 
        WHEN elapsed_hours > 48 AND completion_rate < 20 THEN 1
        WHEN elapsed_hours > 24 AND completion_rate < 30 THEN 2
        ELSE 3
    END,
    completion_rate ASC;


-- =====================================================
-- 补充查询3：产品类别执行进度汇总
-- =====================================================
SELECT 
    p.product_category AS "产品类别",
    COUNT(*) AS "工单数",
    SUM(CASE WHEN wo.status = 'OPEN' THEN 1 ELSE 0 END) AS "待生产",
    SUM(CASE WHEN wo.status = 'STARTED' THEN 1 ELSE 0 END) AS "生产中",
    SUM(CASE WHEN wo.status = 'CLOSED' THEN 1 ELSE 0 END) AS "已完成",
    ROUND(SUM(wo.planned_qty), 0) AS "计划总量",
    ROUND(SUM(wo.completed_qty), 0) AS "完成总量",
    CASE WHEN SUM(wo.planned_qty) > 0 
         THEN ROUND(SUM(wo.completed_qty) * 100.0 / SUM(wo.planned_qty), 1)
         ELSE 0 END AS "整体完成率(%)"
FROM fact_work_order wo
LEFT JOIN dim_product p ON wo.product_id = p.product_id AND p.is_current = 't'
GROUP BY p.product_category
ORDER BY "工单数" DESC;


-- =====================================================
-- 补充查询4：工单执行时间线
-- =====================================================
WITH timeline AS (
    SELECT 
        wo.work_order_number,
        p.product_name,
        wo.status,
        wo.event_time_utc::timestamp AS start_time,
        wo.last_updated_utc::timestamp AS last_update,
        CASE WHEN wo.status = 'CLOSED' 
             THEN ROUND(EXTRACT(EPOCH FROM (wo.last_updated_utc::timestamp - wo.event_time_utc::timestamp)) / 3600, 1)
             ELSE ROUND(EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - wo.event_time_utc::timestamp)) / 3600, 1)
        END AS duration_hours,
        wo.planned_qty,
        wo.completed_qty
    FROM fact_work_order wo
    LEFT JOIN dim_product p ON wo.product_id = p.product_id AND p.is_current = 't'
)
SELECT 
    work_order_number AS "工单号",
    product_name AS "产品",
    CASE status
        WHEN 'OPEN' THEN '待生产'
        WHEN 'STARTED' THEN '生产中'
        WHEN 'CLOSED' THEN '已完成'
    END AS "状态",
    TO_CHAR(start_time, 'YYYY-MM-DD HH24:MI') AS "开始时间",
    TO_CHAR(last_update, 'YYYY-MM-DD HH24:MI') AS "最后更新",
    duration_hours AS "持续时间(小时)",
    ROUND(planned_qty, 0) AS "计划数量",
    ROUND(completed_qty, 0) AS "完成数量",
    CASE WHEN planned_qty > 0 
         THEN ROUND(completed_qty * 100.0 / planned_qty, 1)
         ELSE 0 END AS "完成率(%)"
FROM timeline
ORDER BY start_time DESC
LIMIT 50;


-- =====================================================
-- 补充查询5：实时生产看板汇总
-- =====================================================
WITH current_stats AS (
    SELECT 
        COUNT(*) AS total_orders,
        SUM(CASE WHEN status = 'OPEN' THEN 1 ELSE 0 END) AS open_orders,
        SUM(CASE WHEN status = 'STARTED' THEN 1 ELSE 0 END) AS started_orders,
        SUM(CASE WHEN status = 'CLOSED' THEN 1 ELSE 0 END) AS closed_orders,
        SUM(planned_qty) AS total_planned,
        SUM(completed_qty) AS total_completed
    FROM fact_work_order
),
anomaly_stats AS (
    SELECT 
        COUNT(*) AS anomaly_count
    FROM fact_work_order wo
    WHERE wo.status = 'STARTED'
      AND EXTRACT(EPOCH FROM (CURRENT_TIMESTAMP - wo.event_time_utc::timestamp)) / 3600 > 24
      AND wo.completed_qty * 100.0 / NULLIF(wo.planned_qty, 0) < 30
),
today_stats AS (
    SELECT 
        COUNT(*) AS today_completed
    FROM fact_work_order
    WHERE status = 'CLOSED'
      AND last_updated_utc::date = CURRENT_DATE
)
SELECT 
    '总工单数' AS "指标",
    cs.total_orders::text AS "数值",
    '-' AS "状态"
FROM current_stats cs
UNION ALL
SELECT 
    '待生产',
    cs.open_orders::text,
    CASE WHEN cs.open_orders > 20 THEN '积压' ELSE '正常' END
FROM current_stats cs
UNION ALL
SELECT 
    '生产中',
    cs.started_orders::text,
    '进行中'
FROM current_stats cs
UNION ALL
SELECT 
    '已完成',
    cs.closed_orders::text,
    '正常'
FROM current_stats cs
UNION ALL
SELECT 
    '整体完成率',
    ROUND(cs.total_completed * 100.0 / NULLIF(cs.total_planned, 0), 1)::text || '%',
    CASE 
        WHEN cs.total_completed * 100.0 / NULLIF(cs.total_planned, 0) >= 80 THEN '良好'
        WHEN cs.total_completed * 100.0 / NULLIF(cs.total_planned, 0) >= 50 THEN '正常'
        ELSE '偏低'
    END
FROM current_stats cs
UNION ALL
SELECT 
    '异常工单数',
    ans.anomaly_count::text,
    CASE WHEN ans.anomaly_count > 5 THEN '需关注' ELSE '正常' END
FROM anomaly_stats ans
UNION ALL
SELECT 
    '今日完成',
    ts.today_completed::text,
    '-'
FROM today_stats ts;
