CREATE SCHEMA IF NOT EXISTS mv_hot; CREATE TABLE IF NOT EXISTS mv_hot.edge_oee_node_events ( id BIGSERIAL PRIMARY KEY, received_at TIMESTAMPTZ NOT NULL DEFAULT now(), event_ts TIMESTAMPTZ NOT NULL, topic TEXT NOT NULL, tenant TEXT NOT NULL, site TEXT NOT NULL, vertical TEXT NOT NULL, asset TEXT NOT NULL, machine_id TEXT, order_id TEXT, event_type TEXT NOT NULL, event_name TEXT NOT NULL, previous_auto_signal BOOLEAN, new_auto_signal BOOLEAN, machine_running BOOLEAN, reason_pending BOOLEAN, cycle_pulse_count BIGINT, cycle_rate_ppm NUMERIC(10,2), last_cycle_age_s NUMERIC(10,2), payload_json JSONB NOT NULL DEFAULT '{}'::jsonb ); CREATE INDEX IF NOT EXISTS idx_edge_oee_node_events_received_at ON mv_hot.edge_oee_node_events(received_at DESC); CREATE INDEX IF NOT EXISTS idx_edge_oee_node_events_event_ts ON mv_hot.edge_oee_node_events(event_ts DESC); CREATE INDEX IF NOT EXISTS idx_edge_oee_node_events_asset_ts ON mv_hot.edge_oee_node_events(asset, event_ts DESC); CREATE INDEX IF NOT EXISTS idx_edge_oee_node_events_machine_ts ON mv_hot.edge_oee_node_events(machine_id, event_ts DESC); CREATE OR REPLACE VIEW mv_hot.edge_oee_node_events_recent AS SELECT received_at, EXTRACT(EPOCH FROM (now() - received_at))::int AS age_s, event_ts, tenant, site, vertical, asset, machine_id, order_id, event_type, event_name, previous_auto_signal, new_auto_signal, machine_running, reason_pending, cycle_pulse_count, cycle_rate_ppm, last_cycle_age_s, topic, payload_json FROM mv_hot.edge_oee_node_events ORDER BY event_ts DESC; CREATE OR REPLACE VIEW mv_hot.edge_oee_machine_state_latest AS SELECT DISTINCT ON (asset) received_at, EXTRACT(EPOCH FROM (now() - received_at))::int AS age_s, event_ts, tenant, site, vertical, asset, machine_id, event_name, previous_auto_signal, new_auto_signal, machine_running, reason_pending, cycle_pulse_count, cycle_rate_ppm, last_cycle_age_s FROM mv_hot.edge_oee_node_events WHERE event_type = 'machine_state_changed' ORDER BY asset, event_ts DESC;