524 lines
18 KiB
PL/PgSQL
524 lines
18 KiB
PL/PgSQL
BEGIN;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_stop_candidates_v1 AS
|
|
WITH stop_base AS (
|
|
SELECT
|
|
s.*,
|
|
COALESCE(
|
|
s.duration_s,
|
|
EXTRACT(EPOCH FROM (COALESCE(s.ended_at, now()) - s.started_at))::numeric
|
|
) AS effective_duration_s,
|
|
COALESCE(
|
|
s.cost_eur,
|
|
ROUND((
|
|
EXTRACT(EPOCH FROM (COALESCE(s.ended_at, now()) - s.started_at))
|
|
/ 3600.0 * s.value_hour_eur
|
|
)::numeric, 2)
|
|
) AS effective_capacity_cost_eur
|
|
FROM mv_hot.edge_oee_machine_stops s
|
|
WHERE s.tenant = 'ucepsa'
|
|
AND s.site = 'ucepsa_onpremise'
|
|
), enriched AS (
|
|
SELECT
|
|
s.*,
|
|
d.id AS deployment_id,
|
|
d.scope_code,
|
|
d.mode AS deployment_mode,
|
|
d.planned_go_live_date,
|
|
d.actual_go_live_at,
|
|
p.noise_below_s,
|
|
p.aggregate_below_s,
|
|
p.operator_individual_from_s,
|
|
p.aggregation_window_min,
|
|
p.require_valid_order,
|
|
p.require_closed_event,
|
|
o.id AS order_state_event_id,
|
|
o.effective_from AS order_context_from,
|
|
o.effective_to AS order_context_to,
|
|
o.odoo_state,
|
|
o.order_present,
|
|
o.order_coherent,
|
|
o.workorder_id AS odoo_workorder_id,
|
|
o.workorder_name,
|
|
o.workorder_state,
|
|
o.production_id AS odoo_production_id,
|
|
o.production_order AS order_ref,
|
|
o.product_id,
|
|
o.product AS product_name,
|
|
o.qty_production,
|
|
o.date_start AS odoo_date_start,
|
|
o.date_finished AS odoo_date_finished,
|
|
pc.units_per_cycle,
|
|
pc.target_cycle_rate_ppm,
|
|
ep.parameter_value AS configured_capacity_eur_h,
|
|
ep.confidence AS capacity_cost_confidence
|
|
FROM stop_base s
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_loss_intelligence.deployment_config x
|
|
WHERE x.tenant = s.tenant
|
|
AND x.site = s.site
|
|
AND x.scope_code = 'CUTTERS'
|
|
ORDER BY x.id DESC
|
|
LIMIT 1
|
|
) d ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_loss_intelligence.loss_policies x
|
|
WHERE x.tenant = s.tenant
|
|
AND x.site = s.site
|
|
AND x.policy_code = 'CUTTER_STOPS_V1'
|
|
AND x.is_active = true
|
|
ORDER BY x.id DESC
|
|
LIMIT 1
|
|
) p ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_reports_ucepsa_prod.li_order_state_intervals_v1 x
|
|
WHERE x.tenant = s.tenant
|
|
AND x.site = s.site
|
|
AND x.machine_id = s.machine_id
|
|
AND s.started_at >= x.effective_from
|
|
AND (x.effective_to IS NULL OR s.started_at < x.effective_to)
|
|
ORDER BY x.effective_from DESC, x.id DESC
|
|
LIMIT 1
|
|
) o ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_loss_intelligence.product_cycle_parameters x
|
|
WHERE x.tenant = s.tenant
|
|
AND x.site = s.site
|
|
AND x.is_active = true
|
|
AND x.product_id = o.product_id
|
|
AND (x.machine_id IS NULL OR x.machine_id = s.machine_id)
|
|
AND s.started_at >= x.valid_from
|
|
AND (x.valid_to IS NULL OR s.started_at < x.valid_to)
|
|
ORDER BY (x.machine_id IS NOT NULL) DESC, x.valid_from DESC, x.id DESC
|
|
LIMIT 1
|
|
) pc ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_loss_intelligence.economic_parameters x
|
|
WHERE x.tenant = s.tenant
|
|
AND x.site = s.site
|
|
AND x.parameter_code = 'CAPACITY_HOUR_EUR'
|
|
AND x.is_active = true
|
|
AND (x.machine_id IS NULL OR x.machine_id = s.machine_id)
|
|
AND s.started_at >= x.valid_from
|
|
AND (x.valid_to IS NULL OR s.started_at < x.valid_to)
|
|
ORDER BY (x.machine_id IS NOT NULL) DESC, x.valid_from DESC, x.id DESC
|
|
LIMIT 1
|
|
) ep ON true
|
|
)
|
|
SELECT
|
|
e.id AS source_stop_id,
|
|
e.tenant,
|
|
e.site,
|
|
e.deployment_id,
|
|
e.scope_code,
|
|
e.deployment_mode,
|
|
e.planned_go_live_date,
|
|
e.actual_go_live_at,
|
|
CASE
|
|
WHEN e.deployment_mode = 'ACTIVE'
|
|
AND e.actual_go_live_at IS NOT NULL
|
|
AND e.started_at >= e.actual_go_live_at
|
|
THEN 'ACTIVE'
|
|
ELSE 'SHADOW'
|
|
END AS ledger_phase,
|
|
e.machine_id,
|
|
e.asset,
|
|
e.started_at,
|
|
e.ended_at,
|
|
e.status AS source_status,
|
|
e.classification_status,
|
|
e.cause_code,
|
|
c.cause_name,
|
|
c.is_planned,
|
|
e.operator_note,
|
|
e.start_event_name,
|
|
e.end_event_name,
|
|
e.effective_duration_s,
|
|
ROUND((e.effective_duration_s / 60.0)::numeric, 2) AS effective_duration_min,
|
|
e.value_hour_eur AS source_value_hour_eur,
|
|
e.configured_capacity_eur_h,
|
|
COALESCE(e.configured_capacity_eur_h, e.value_hour_eur) AS applied_capacity_eur_h,
|
|
ROUND((
|
|
e.effective_duration_s / 3600.0
|
|
* COALESCE(e.configured_capacity_eur_h, e.value_hour_eur)
|
|
)::numeric, 2) AS effective_capacity_cost_eur,
|
|
e.capacity_cost_confidence,
|
|
e.order_state_event_id,
|
|
e.order_context_from,
|
|
e.order_context_to,
|
|
e.odoo_state,
|
|
e.order_present,
|
|
e.order_coherent,
|
|
e.odoo_workorder_id,
|
|
e.workorder_name,
|
|
e.workorder_state,
|
|
e.odoo_production_id,
|
|
e.order_ref,
|
|
e.product_id,
|
|
e.product_name,
|
|
e.qty_production,
|
|
e.odoo_date_start,
|
|
e.odoo_date_finished,
|
|
e.units_per_cycle,
|
|
e.target_cycle_rate_ppm,
|
|
CASE
|
|
WHEN e.deployment_id IS NULL THEN 'CONFIG_MISSING'
|
|
WHEN e.noise_below_s IS NULL THEN 'POLICY_MISSING'
|
|
WHEN e.status = 'OPEN' THEN 'OPEN_MONITORING'
|
|
WHEN e.require_closed_event AND e.status <> 'CLOSED' THEN 'EXCLUDED_NOT_CLOSED'
|
|
WHEN e.order_state_event_id IS NULL THEN 'EXCLUDED_NO_ORDER_CONTEXT'
|
|
WHEN e.require_valid_order AND COALESCE(e.order_present, false) = false THEN 'EXCLUDED_NO_VALID_ORDER'
|
|
WHEN e.require_valid_order AND COALESCE(e.order_coherent, false) = false THEN 'EXCLUDED_ORDER_INCOHERENT'
|
|
WHEN e.effective_duration_s < e.noise_below_s THEN 'EXCLUDED_NOISE'
|
|
WHEN e.effective_duration_s < e.operator_individual_from_s THEN 'CANDIDATE_GROUP'
|
|
ELSE 'CANDIDATE_INDIVIDUAL'
|
|
END AS eligibility_status,
|
|
CASE
|
|
WHEN e.status = 'CLOSED'
|
|
AND e.order_state_event_id IS NOT NULL
|
|
AND (NOT e.require_valid_order OR (e.order_present = true AND e.order_coherent = true))
|
|
AND e.effective_duration_s >= e.noise_below_s
|
|
THEN true
|
|
ELSE false
|
|
END AS technically_eligible,
|
|
CASE
|
|
WHEN e.deployment_mode = 'ACTIVE'
|
|
AND e.actual_go_live_at IS NOT NULL
|
|
AND e.started_at >= e.actual_go_live_at
|
|
AND e.status = 'CLOSED'
|
|
AND e.order_state_event_id IS NOT NULL
|
|
AND (NOT e.require_valid_order OR (e.order_present = true AND e.order_coherent = true))
|
|
AND e.effective_duration_s >= e.noise_below_s
|
|
THEN true
|
|
ELSE false
|
|
END AS official_ledger_eligible,
|
|
jsonb_build_object(
|
|
'source_stop_id', e.id,
|
|
'source_start_payload', e.start_payload_json,
|
|
'source_end_payload', e.end_payload_json,
|
|
'order_state_event_id', e.order_state_event_id,
|
|
'deployment_mode', e.deployment_mode,
|
|
'policy', jsonb_build_object(
|
|
'noise_below_s', e.noise_below_s,
|
|
'aggregate_below_s', e.aggregate_below_s,
|
|
'operator_individual_from_s', e.operator_individual_from_s,
|
|
'aggregation_window_min', e.aggregation_window_min
|
|
)
|
|
) AS evidence_json
|
|
FROM enriched e
|
|
LEFT JOIN mv_hot.edge_oee_stop_causes c
|
|
ON c.cause_code = e.cause_code;
|
|
|
|
COMMENT ON VIEW mv_reports_ucepsa_prod.li_stop_candidates_v1 IS
|
|
'Clasifica cada paro raw como excluido, agrupable, individual u abierto. Mantiene separados el modo SHADOW y la elegibilidad oficial.';
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_stop_groups_v1 AS
|
|
WITH candidates AS (
|
|
SELECT
|
|
c.*,
|
|
COALESCE((c.evidence_json #>> '{policy,aggregation_window_min}')::int, 15) AS aggregation_window_min
|
|
FROM mv_reports_ucepsa_prod.li_stop_candidates_v1 c
|
|
WHERE c.eligibility_status IN ('CANDIDATE_GROUP', 'CANDIDATE_INDIVIDUAL')
|
|
), bucketed AS (
|
|
SELECT
|
|
c.*,
|
|
date_bin(
|
|
make_interval(mins => c.aggregation_window_min),
|
|
c.started_at,
|
|
TIMESTAMPTZ '2000-01-01 00:00:00+00'
|
|
) AS bucket_start
|
|
FROM candidates c
|
|
), grouped_micro AS (
|
|
SELECT
|
|
tenant,
|
|
site,
|
|
deployment_id,
|
|
ledger_phase,
|
|
machine_id,
|
|
asset,
|
|
order_ref,
|
|
odoo_production_id,
|
|
NULLIF(odoo_workorder_id, '')::bigint AS odoo_workorder_id,
|
|
product_id,
|
|
product_name,
|
|
units_per_cycle,
|
|
target_cycle_rate_ppm,
|
|
COALESCE(cause_code, 'PENDING') AS cause_code,
|
|
COALESCE(cause_name, 'Pendiente de clasificar') AS cause_name,
|
|
classification_status,
|
|
bucket_start AS group_window_start,
|
|
COUNT(*)::int AS event_count,
|
|
MIN(started_at) AS started_at,
|
|
MAX(ended_at) AS ended_at,
|
|
SUM(effective_duration_s)::numeric AS duration_s,
|
|
ROUND(SUM(effective_capacity_cost_eur)::numeric, 2) AS capacity_loss_eur,
|
|
array_agg(source_stop_id ORDER BY started_at) AS source_stop_ids,
|
|
bool_and(official_ledger_eligible) AS official_ledger_eligible
|
|
FROM bucketed
|
|
WHERE eligibility_status = 'CANDIDATE_GROUP'
|
|
GROUP BY
|
|
tenant, site, deployment_id, ledger_phase, machine_id, asset,
|
|
order_ref, odoo_production_id, odoo_workorder_id, product_id,
|
|
product_name, units_per_cycle, target_cycle_rate_ppm,
|
|
COALESCE(cause_code, 'PENDING'),
|
|
COALESCE(cause_name, 'Pendiente de clasificar'),
|
|
classification_status, bucket_start
|
|
), individual AS (
|
|
SELECT
|
|
tenant,
|
|
site,
|
|
deployment_id,
|
|
ledger_phase,
|
|
machine_id,
|
|
asset,
|
|
order_ref,
|
|
odoo_production_id,
|
|
NULLIF(odoo_workorder_id, '')::bigint AS odoo_workorder_id,
|
|
product_id,
|
|
product_name,
|
|
units_per_cycle,
|
|
target_cycle_rate_ppm,
|
|
COALESCE(cause_code, 'PENDING') AS cause_code,
|
|
COALESCE(cause_name, 'Pendiente de clasificar') AS cause_name,
|
|
classification_status,
|
|
started_at AS group_window_start,
|
|
1::int AS event_count,
|
|
started_at,
|
|
ended_at,
|
|
effective_duration_s::numeric AS duration_s,
|
|
effective_capacity_cost_eur::numeric AS capacity_loss_eur,
|
|
ARRAY[source_stop_id]::bigint[] AS source_stop_ids,
|
|
official_ledger_eligible
|
|
FROM bucketed
|
|
WHERE eligibility_status = 'CANDIDATE_INDIVIDUAL'
|
|
), combined AS (
|
|
SELECT * FROM grouped_micro
|
|
UNION ALL
|
|
SELECT * FROM individual
|
|
)
|
|
SELECT
|
|
CASE
|
|
WHEN event_count = 1 THEN 'STOP:' || source_stop_ids[1]::text
|
|
ELSE 'STOPGROUP:' || machine_id || ':'
|
|
|| COALESCE(odoo_production_id::text, COALESCE(order_ref, 'NO_ORDER')) || ':'
|
|
|| to_char(group_window_start AT TIME ZONE 'Europe/Madrid', 'YYYYMMDDHH24MI') || ':'
|
|
|| cause_code
|
|
END AS source_key,
|
|
*,
|
|
ROUND((duration_s / 60.0)::numeric, 2) AS duration_min,
|
|
CASE
|
|
WHEN duration_s >= 900 THEN 'HIGH'
|
|
WHEN duration_s >= 300 THEN 'MEDIUM'
|
|
ELSE 'LOW'
|
|
END AS preliminary_priority
|
|
FROM combined;
|
|
|
|
COMMENT ON VIEW mv_reports_ucepsa_prod.li_stop_groups_v1 IS
|
|
'Agrupa microparos por máquina, orden, ventana y causa. Los paros largos permanecen individuales.';
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_shadow_review_queue_v1 AS
|
|
SELECT
|
|
row_number() OVER (
|
|
ORDER BY capacity_loss_eur DESC, duration_s DESC, started_at DESC
|
|
) AS shadow_rank,
|
|
source_key,
|
|
machine_id,
|
|
order_ref,
|
|
product_name,
|
|
cause_code,
|
|
cause_name,
|
|
event_count,
|
|
started_at,
|
|
ended_at,
|
|
duration_min,
|
|
capacity_loss_eur,
|
|
preliminary_priority,
|
|
'SHADOW_ONLY_NOT_OFFICIAL'::text AS queue_status,
|
|
official_ledger_eligible,
|
|
source_stop_ids
|
|
FROM mv_reports_ucepsa_prod.li_stop_groups_v1
|
|
WHERE ledger_phase = 'SHADOW'
|
|
ORDER BY shadow_rank;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_operator_stop_queue_v1 AS
|
|
SELECT
|
|
source_key,
|
|
machine_id,
|
|
order_ref,
|
|
product_name,
|
|
cause_code,
|
|
cause_name,
|
|
classification_status,
|
|
event_count,
|
|
started_at,
|
|
ended_at,
|
|
duration_min,
|
|
capacity_loss_eur,
|
|
source_stop_ids
|
|
FROM mv_reports_ucepsa_prod.li_stop_groups_v1
|
|
WHERE ledger_phase = 'ACTIVE'
|
|
AND official_ledger_eligible = true
|
|
AND classification_status = 'PENDING'
|
|
ORDER BY capacity_loss_eur DESC, duration_s DESC, started_at DESC;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_daily_review_queue_v1 AS
|
|
SELECT
|
|
row_number() OVER (
|
|
ORDER BY
|
|
COALESCE(l.priority_score, 0) DESC,
|
|
l.review_due_at NULLS LAST,
|
|
l.detected_at
|
|
) AS review_rank,
|
|
l.loss_id,
|
|
l.machine_id,
|
|
l.order_ref,
|
|
l.product_name,
|
|
l.loss_type,
|
|
l.cause_code,
|
|
ROUND((l.duration_s / 60.0)::numeric, 2) AS duration_min,
|
|
l.capacity_loss_eur,
|
|
l.energy_waste_eur,
|
|
l.priority_level,
|
|
l.action_candidate,
|
|
l.action_final,
|
|
l.review_owner,
|
|
l.review_due_at,
|
|
l.status,
|
|
t.trial_id,
|
|
t.trial_code,
|
|
t.result AS trial_result,
|
|
t.decision AS trial_decision
|
|
FROM mv_loss_intelligence.loss_ledger l
|
|
LEFT JOIN LATERAL (
|
|
SELECT x.*
|
|
FROM mv_loss_intelligence.action_trials x
|
|
WHERE x.loss_id = l.loss_id
|
|
ORDER BY x.created_at DESC, x.trial_id DESC
|
|
LIMIT 1
|
|
) t ON true
|
|
WHERE l.tenant = 'ucepsa'
|
|
AND l.site = 'ucepsa_onpremise'
|
|
AND l.ledger_phase = 'ACTIVE'
|
|
AND l.status NOT IN ('CLOSED', 'DISCARDED')
|
|
ORDER BY review_rank
|
|
LIMIT 5;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_shadow_summary_v1 AS
|
|
SELECT
|
|
ledger_phase,
|
|
eligibility_status,
|
|
machine_id,
|
|
COUNT(*) AS stop_count,
|
|
ROUND(SUM(effective_duration_s / 60.0)::numeric, 2) AS total_minutes,
|
|
ROUND(SUM(effective_capacity_cost_eur)::numeric, 2) AS capacity_cost_eur
|
|
FROM mv_reports_ucepsa_prod.li_stop_candidates_v1
|
|
GROUP BY ledger_phase, eligibility_status, machine_id;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_product_cycle_coverage_v1 AS
|
|
SELECT
|
|
c.machine_id,
|
|
c.odoo_production_id,
|
|
c.order_ref,
|
|
c.product_id,
|
|
c.product_name,
|
|
c.qty_production,
|
|
c.units_per_cycle,
|
|
c.target_cycle_rate_ppm,
|
|
CASE
|
|
WHEN c.product_id IS NULL THEN 'MISSING_PRODUCT_ID'
|
|
WHEN c.units_per_cycle IS NULL THEN 'MISSING_UNITS_PER_CYCLE'
|
|
WHEN c.target_cycle_rate_ppm IS NULL THEN 'MISSING_TARGET_CYCLE_RATE'
|
|
ELSE 'READY'
|
|
END AS cycle_parameter_status,
|
|
MAX(c.started_at) AS latest_stop_started_at,
|
|
COUNT(*) AS related_stop_count
|
|
FROM mv_reports_ucepsa_prod.li_stop_candidates_v1 c
|
|
WHERE c.order_present = true
|
|
AND c.order_coherent = true
|
|
GROUP BY
|
|
c.machine_id, c.odoo_production_id, c.order_ref, c.product_id,
|
|
c.product_name, c.qty_production, c.units_per_cycle, c.target_cycle_rate_ppm;
|
|
|
|
CREATE OR REPLACE VIEW mv_reports_ucepsa_prod.li_data_quality_v1 AS
|
|
WITH deployment AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_loss_intelligence.deployment_config
|
|
WHERE tenant = 'ucepsa' AND site = 'ucepsa_onpremise' AND scope_code = 'CUTTERS'
|
|
), capacity_cost AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_loss_intelligence.economic_parameters
|
|
WHERE tenant = 'ucepsa' AND site = 'ucepsa_onpremise'
|
|
AND parameter_code = 'CAPACITY_HOUR_EUR' AND is_active = true
|
|
), energy_cost AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_loss_intelligence.economic_parameters
|
|
WHERE tenant = 'ucepsa' AND site = 'ucepsa_onpremise'
|
|
AND parameter_code = 'ENERGY_VARIABLE_EUR_KWH' AND is_active = true
|
|
), current_loaded AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_hot.odoo_order_state_current
|
|
WHERE tenant = 'ucepsa' AND site = 'ucepsa_onpremise'
|
|
AND order_present = true AND order_coherent = true
|
|
), cycle_missing AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_hot.odoo_order_state_current o
|
|
WHERE o.tenant = 'ucepsa' AND o.site = 'ucepsa_onpremise'
|
|
AND o.order_present = true AND o.order_coherent = true
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM mv_loss_intelligence.product_cycle_parameters p
|
|
WHERE p.tenant = o.tenant
|
|
AND p.site = o.site
|
|
AND p.product_id = o.product_id
|
|
AND p.is_active = true
|
|
AND (p.machine_id IS NULL OR p.machine_id = o.machine_id)
|
|
)
|
|
), stale_open AS (
|
|
SELECT COUNT(*) AS n
|
|
FROM mv_hot.edge_oee_machine_stops
|
|
WHERE tenant = 'ucepsa' AND site = 'ucepsa_onpremise'
|
|
AND status = 'OPEN'
|
|
AND started_at < now() - interval '12 hours'
|
|
)
|
|
SELECT 'DEPLOYMENT_CONFIG'::text AS check_code,
|
|
CASE WHEN n = 1 THEN 'OK' ELSE 'BLOCKER' END AS status,
|
|
n AS affected_count,
|
|
'Debe existir una única configuración CUTTERS.'::text AS description
|
|
FROM deployment
|
|
UNION ALL
|
|
SELECT 'CAPACITY_COST', CASE WHEN n >= 1 THEN 'OK' ELSE 'BLOCKER' END, n,
|
|
'Debe existir coste de capacidad €/h activo.' FROM capacity_cost
|
|
UNION ALL
|
|
SELECT 'ENERGY_COST', CASE WHEN n >= 1 THEN 'OK' ELSE 'BLOCKER' END, n,
|
|
'Debe existir coste eléctrico variable €/kWh activo.' FROM energy_cost
|
|
UNION ALL
|
|
SELECT 'CURRENT_VALID_ORDERS', CASE WHEN n >= 1 THEN 'OK' ELSE 'INFO' END, n,
|
|
'Órdenes actualmente cargadas y coherentes.' FROM current_loaded
|
|
UNION ALL
|
|
SELECT 'MISSING_CYCLE_PARAMETERS', CASE WHEN n = 0 THEN 'OK' ELSE 'WARNING' END, n,
|
|
'Productos activos sin bolsas por golpe o cadencia configurada.' FROM cycle_missing
|
|
UNION ALL
|
|
SELECT 'STALE_OPEN_STOPS', CASE WHEN n = 0 THEN 'OK' ELSE 'WARNING' END, n,
|
|
'Paros abiertos desde hace más de 12 horas; no equivalen automáticamente a pérdida.' FROM stale_open;
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ucepsa_ro') THEN
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_stop_candidates_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_stop_groups_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_shadow_review_queue_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_operator_stop_queue_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_daily_review_queue_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_shadow_summary_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_product_cycle_coverage_v1 TO grafana_ucepsa_ro;
|
|
GRANT SELECT ON mv_reports_ucepsa_prod.li_data_quality_v1 TO grafana_ucepsa_ro;
|
|
END IF;
|
|
END $$;
|
|
|
|
COMMIT;
|