diff --git a/ucepsa/edge-oee-demo/sql/versions/101_fix_open_production_context_tail_v3.sql b/ucepsa/edge-oee-demo/sql/versions/101_fix_open_production_context_tail_v3.sql new file mode 100644 index 0000000..984d387 --- /dev/null +++ b/ucepsa/edge-oee-demo/sql/versions/101_fix_open_production_context_tail_v3.sql @@ -0,0 +1,124 @@ +BEGIN; + +CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_production_context_intervals_v1 AS +WITH explicit_contexts AS ( + SELECT + s.tenant, + s.site, + s.machine_id, + 'SESSION:' || s.context_session_id::text AS context_key, + s.context_session_id, + s.source_type AS context_source, + CASE s.source_type + WHEN 'ODOO_SHOPFLOOR' THEN 5 + WHEN 'LEGACY_ERP' THEN 20 + WHEN 'MANUAL_AUTHORIZED' THEN 30 + WHEN 'MAINTENANCE' THEN 40 + WHEN 'TEST_SETUP' THEN 50 + ELSE 90 + END AS context_priority, + s.started_at AS context_from, + COALESCE( + s.ended_at, + 'infinity'::timestamptz + ) AS context_to, + s.external_order_ref AS order_ref, + s.odoo_production_id, + s.odoo_workorder_id, + s.product_id, + s.product_default_code, + s.product_name, + s.operator_employee_id, + s.operator_name, + s.confidence, + true AS context_confirmed, + s.official_eligible AS official_loss_eligible, + s.authorization_status, + s.status, + s.notes, + s.evidence_json + FROM mv_loss_intelligence.production_context_sessions s + WHERE s.tenant = 'ucepsa' + AND s.site = 'ucepsa_onpremise' + AND s.status IN ('OPEN', 'CLOSED') + AND s.authorization_status IN ( + 'AUTHORIZED', + 'AUTO_CONFIRMED' + ) + AND ( + s.ended_at IS NULL + OR s.ended_at > s.started_at + ) +), +odoo_contexts AS ( + SELECT + o.tenant, + o.site, + o.machine_id, + 'ODOO:' || o.machine_id || ':' || o.id::text + AS context_key, + NULL::bigint AS context_session_id, + 'ODOO_ORDER_CONTEXT'::text AS context_source, + 10 AS context_priority, + o.effective_from AS context_from, + COALESCE( + o.effective_to, + 'infinity'::timestamptz + ) AS context_to, + o.production_order AS order_ref, + o.production_id AS odoo_production_id, + NULLIF(o.workorder_id, '')::bigint + AS odoo_workorder_id, + o.product_id, + NULL::text AS product_default_code, + o.product AS product_name, + NULL::bigint AS operator_employee_id, + NULL::text AS operator_name, + 'HIGH'::text AS confidence, + true AS context_confirmed, + false AS official_loss_eligible, + 'AUTO_CONFIRMED'::text AS authorization_status, + CASE + WHEN o.effective_to IS NULL THEN 'OPEN' + ELSE 'CLOSED' + END AS status, + 'Contexto de orden Odoo válido. Aún no equivale a sesión oficial de operaria.'::text + AS notes, + jsonb_build_object( + 'order_state_event_id', o.id, + 'odoo_state', o.odoo_state, + 'workorder_state', o.workorder_state, + 'qty_production', o.qty_production + ) AS evidence_json + FROM mv_reports_ucepsa_prod.li_order_state_intervals_v1 o + WHERE o.tenant = 'ucepsa' + AND o.site = 'ucepsa_onpremise' + AND o.order_present = true + AND o.order_coherent = true + AND ( + o.effective_to IS NULL + OR o.effective_to > o.effective_from + ) +) +SELECT * FROM explicit_contexts +UNION ALL +SELECT * FROM odoo_contexts; + +COMMENT ON VIEW +mv_reports_ucepsa_prod.li_production_context_intervals_v1 IS +'Contextos productivos Odoo, legacy, manuales, mantenimiento y pruebas. Los contextos abiertos permanecen vigentes hasta su cierre explícito, incluyendo la cola temporal de actividad.'; + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 + FROM pg_roles + WHERE rolname = 'grafana_ucepsa_ro' + ) THEN + GRANT SELECT + ON mv_reports_ucepsa_prod.li_production_context_intervals_v1 + TO grafana_ucepsa_ro; + END IF; +END $$; + +COMMIT;