273 lines
7.5 KiB
PL/PgSQL
273 lines
7.5 KiB
PL/PgSQL
CREATE OR REPLACE FUNCTION mv_reports_ucepsa_demo.oee_kpis(
|
|
p_from timestamptz,
|
|
p_to timestamptz,
|
|
p_machine_id text DEFAULT 'CORT-01',
|
|
p_asset text DEFAULT 'revpi_oee_node_01'
|
|
)
|
|
RETURNS TABLE (
|
|
oee_pct numeric,
|
|
availability_pct numeric,
|
|
performance_pct numeric,
|
|
quality_pct numeric
|
|
)
|
|
LANGUAGE sql
|
|
STABLE
|
|
AS $$
|
|
WITH dashboard_bounds AS (
|
|
SELECT
|
|
p_from AS dashboard_from,
|
|
LEAST(p_to, now()) AS dashboard_to
|
|
),
|
|
telemetry_span AS (
|
|
SELECT
|
|
MIN(ingest_ts) AS first_ts,
|
|
MAX(ingest_ts) AS last_ts
|
|
FROM mv_hot.edge_oee_live_telemetry
|
|
WHERE asset = p_asset
|
|
AND ingest_ts >= (SELECT dashboard_from FROM dashboard_bounds)
|
|
AND ingest_ts <= (SELECT dashboard_to FROM dashboard_bounds)
|
|
),
|
|
bounds AS (
|
|
SELECT
|
|
CASE
|
|
WHEN first_ts IS NULL THEN dashboard_from
|
|
ELSE GREATEST(dashboard_from, first_ts)
|
|
END AS t_from,
|
|
CASE
|
|
WHEN last_ts IS NULL THEN dashboard_to
|
|
ELSE LEAST(dashboard_to, last_ts)
|
|
END AS t_to
|
|
FROM dashboard_bounds
|
|
CROSS JOIN telemetry_span
|
|
),
|
|
target AS (
|
|
SELECT
|
|
COALESCE((
|
|
SELECT mt.target_cycle_rate_ppm
|
|
FROM mv_hot.edge_oee_machine_targets mt
|
|
WHERE mt.machine_id = p_machine_id
|
|
LIMIT 1
|
|
), 10.00)::numeric AS target_cycle_rate_ppm,
|
|
|
|
COALESCE((
|
|
SELECT mt.quality_pct_default
|
|
FROM mv_hot.edge_oee_machine_targets mt
|
|
WHERE mt.machine_id = p_machine_id
|
|
LIMIT 1
|
|
), 100.00)::numeric AS quality_pct_default
|
|
),
|
|
planned AS (
|
|
SELECT
|
|
GREATEST(EXTRACT(EPOCH FROM (t_to - t_from))::numeric, 0) AS planned_s
|
|
FROM bounds
|
|
),
|
|
stops AS (
|
|
SELECT
|
|
COALESCE(
|
|
SUM(
|
|
GREATEST(
|
|
EXTRACT(EPOCH FROM (
|
|
LEAST(COALESCE(s.ended_at, b.t_to), b.t_to)
|
|
-
|
|
GREATEST(
|
|
CASE
|
|
WHEN s.started_at > s.created_at + interval '5 seconds'
|
|
THEN s.created_at
|
|
ELSE s.started_at
|
|
END,
|
|
b.t_from
|
|
)
|
|
))::numeric,
|
|
0
|
|
)
|
|
) FILTER (
|
|
WHERE s.started_at < b.t_to
|
|
AND COALESCE(s.ended_at, now()) > b.t_from
|
|
),
|
|
0
|
|
)::numeric AS stop_s
|
|
FROM mv_hot.edge_oee_machine_stops s
|
|
CROSS JOIN bounds b
|
|
WHERE s.machine_id = p_machine_id
|
|
),
|
|
cycles AS (
|
|
SELECT
|
|
COALESCE(
|
|
GREATEST(
|
|
MAX(cycle_pulse_count) - MIN(cycle_pulse_count),
|
|
0
|
|
),
|
|
0
|
|
)::numeric AS actual_cycles
|
|
FROM mv_hot.edge_oee_live_telemetry l
|
|
CROSS JOIN bounds b
|
|
WHERE l.asset = p_asset
|
|
AND l.ingest_ts >= b.t_from
|
|
AND l.ingest_ts <= b.t_to
|
|
AND l.cycle_pulse_count IS NOT NULL
|
|
),
|
|
calc AS (
|
|
SELECT
|
|
p.planned_s,
|
|
st.stop_s,
|
|
GREATEST(p.planned_s - st.stop_s, 0)::numeric AS running_s,
|
|
c.actual_cycles,
|
|
t.target_cycle_rate_ppm,
|
|
t.quality_pct_default,
|
|
|
|
CASE
|
|
WHEN p.planned_s > 0
|
|
THEN ROUND(((GREATEST(p.planned_s - st.stop_s, 0) / p.planned_s) * 100)::numeric, 2)
|
|
ELSE 0
|
|
END AS availability_pct,
|
|
|
|
CASE
|
|
WHEN GREATEST(p.planned_s - st.stop_s, 0) > 0
|
|
AND t.target_cycle_rate_ppm > 0
|
|
THEN ROUND(
|
|
LEAST(
|
|
100::numeric,
|
|
(
|
|
c.actual_cycles
|
|
/
|
|
NULLIF(
|
|
t.target_cycle_rate_ppm * (GREATEST(p.planned_s - st.stop_s, 0) / 60.0),
|
|
0
|
|
)
|
|
) * 100
|
|
)::numeric,
|
|
2
|
|
)
|
|
ELSE 0
|
|
END AS performance_pct,
|
|
|
|
t.quality_pct_default AS quality_pct
|
|
FROM planned p
|
|
CROSS JOIN stops st
|
|
CROSS JOIN cycles c
|
|
CROSS JOIN target t
|
|
)
|
|
SELECT
|
|
ROUND(((calc.availability_pct * calc.performance_pct * calc.quality_pct) / 10000.0)::numeric, 2) AS oee_pct,
|
|
calc.availability_pct,
|
|
calc.performance_pct,
|
|
calc.quality_pct
|
|
FROM calc;
|
|
$$;
|
|
|
|
|
|
CREATE OR REPLACE FUNCTION mv_reports_ucepsa_demo.oee_operational_data(
|
|
p_from timestamptz,
|
|
p_to timestamptz,
|
|
p_machine_id text DEFAULT 'CORT-01',
|
|
p_asset text DEFAULT 'revpi_oee_node_01'
|
|
)
|
|
RETURNS TABLE (
|
|
running_min numeric,
|
|
stop_min numeric,
|
|
actual_cycles numeric
|
|
)
|
|
LANGUAGE sql
|
|
STABLE
|
|
AS $$
|
|
WITH dashboard_bounds AS (
|
|
SELECT
|
|
p_from AS dashboard_from,
|
|
LEAST(p_to, now()) AS dashboard_to
|
|
),
|
|
telemetry_span AS (
|
|
SELECT
|
|
MIN(ingest_ts) AS first_ts,
|
|
MAX(ingest_ts) AS last_ts
|
|
FROM mv_hot.edge_oee_live_telemetry
|
|
WHERE asset = p_asset
|
|
AND ingest_ts >= (SELECT dashboard_from FROM dashboard_bounds)
|
|
AND ingest_ts <= (SELECT dashboard_to FROM dashboard_bounds)
|
|
),
|
|
bounds AS (
|
|
SELECT
|
|
CASE
|
|
WHEN first_ts IS NULL THEN dashboard_from
|
|
ELSE GREATEST(dashboard_from, first_ts)
|
|
END AS t_from,
|
|
CASE
|
|
WHEN last_ts IS NULL THEN dashboard_to
|
|
ELSE LEAST(dashboard_to, last_ts)
|
|
END AS t_to
|
|
FROM dashboard_bounds
|
|
CROSS JOIN telemetry_span
|
|
),
|
|
planned AS (
|
|
SELECT
|
|
GREATEST(EXTRACT(EPOCH FROM (t_to - t_from))::numeric, 0) AS planned_s
|
|
FROM bounds
|
|
),
|
|
stops AS (
|
|
SELECT
|
|
COALESCE(
|
|
SUM(
|
|
GREATEST(
|
|
EXTRACT(EPOCH FROM (
|
|
LEAST(COALESCE(s.ended_at, b.t_to), b.t_to)
|
|
-
|
|
GREATEST(
|
|
CASE
|
|
WHEN s.started_at > s.created_at + interval '5 seconds'
|
|
THEN s.created_at
|
|
ELSE s.started_at
|
|
END,
|
|
b.t_from
|
|
)
|
|
))::numeric,
|
|
0
|
|
)
|
|
) FILTER (
|
|
WHERE s.started_at < b.t_to
|
|
AND COALESCE(s.ended_at, now()) > b.t_from
|
|
),
|
|
0
|
|
)::numeric AS stop_s
|
|
FROM mv_hot.edge_oee_machine_stops s
|
|
CROSS JOIN bounds b
|
|
WHERE s.machine_id = p_machine_id
|
|
),
|
|
cycles AS (
|
|
SELECT
|
|
COALESCE(
|
|
GREATEST(
|
|
MAX(cycle_pulse_count) - MIN(cycle_pulse_count),
|
|
0
|
|
),
|
|
0
|
|
)::numeric AS actual_cycles
|
|
FROM mv_hot.edge_oee_live_telemetry l
|
|
CROSS JOIN bounds b
|
|
WHERE l.asset = p_asset
|
|
AND l.ingest_ts >= b.t_from
|
|
AND l.ingest_ts <= b.t_to
|
|
AND l.cycle_pulse_count IS NOT NULL
|
|
),
|
|
calc AS (
|
|
SELECT
|
|
p.planned_s,
|
|
st.stop_s,
|
|
GREATEST(p.planned_s - st.stop_s, 0)::numeric AS running_s,
|
|
c.actual_cycles
|
|
FROM planned p
|
|
CROSS JOIN stops st
|
|
CROSS JOIN cycles c
|
|
)
|
|
SELECT
|
|
ROUND((running_s / 60.0)::numeric, 2) AS running_min,
|
|
ROUND((stop_s / 60.0)::numeric, 2) AS stop_min,
|
|
actual_cycles
|
|
FROM calc;
|
|
$$;
|
|
|
|
|
|
GRANT EXECUTE ON FUNCTION mv_reports_ucepsa_demo.oee_kpis(timestamptz, timestamptz, text, text)
|
|
TO grafana_ucepsa_ro;
|
|
|
|
GRANT EXECUTE ON FUNCTION mv_reports_ucepsa_demo.oee_operational_data(timestamptz, timestamptz, text, text)
|
|
TO grafana_ucepsa_ro;
|