diff --git a/supabase/migrations/20260626000001_fix_rpc_me_carrera_apoyos.sql b/supabase/migrations/20260626000001_fix_rpc_me_carrera_apoyos.sql new file mode 100644 index 0000000..7e28657 --- /dev/null +++ b/supabase/migrations/20260626000001_fix_rpc_me_carrera_apoyos.sql @@ -0,0 +1,110 @@ +-- Fix puntual: column "cnt" does not exist en jsonb_agg(row ORDER BY cnt DESC). +-- El alias cnt vive en el subquery interno; el nivel externo del jsonb_agg solo +-- ve `row`. Solución (Opción B): exponer cnt en el SELECT externo para que +-- jsonb_agg(row ORDER BY cnt DESC) pueda referenciarlo en ese nivel. +-- Solo se tocan estas dos funciones; las otras 9 rpc_me_* no se modifican. + +CREATE OR REPLACE FUNCTION public.rpc_me_apoyos_demandados( + p_survey_id uuid, + p_filters jsonb DEFAULT '{}'::jsonb +) +RETURNS jsonb +LANGUAGE plpgsql STABLE SECURITY DEFINER +SET search_path = public +AS $$ +DECLARE + v_f record; + v_total bigint; + v_rows jsonb; +BEGIN + SELECT * INTO v_f FROM public._dash_parse_filters(p_filters); + + SELECT count(*) INTO v_total + FROM public._dash_responses(p_survey_id, v_f.f_depto, v_f.f_genero, v_f.f_etario, v_f.f_modalidad); + + IF v_total < 5 THEN + RETURN jsonb_build_object('status','suppressed','min_n',5,'n',v_total); + END IF; + + SELECT jsonb_agg(row ORDER BY cnt DESC) INTO v_rows FROM ( + SELECT jsonb_build_object( + 'apoyo', opt, + 'n', cnt, + 'pct', ROUND(cnt::numeric / v_total * 100, 1) + ) AS row, + cnt + FROM ( + SELECT jsonb_array_elements_text(a.value) AS opt, + count(DISTINCT dr.response_id) AS cnt + FROM public._dash_responses(p_survey_id, v_f.f_depto, v_f.f_genero, v_f.f_etario, v_f.f_modalidad) dr + JOIN public.answers a ON a.response_id = dr.response_id + JOIN public.questions q ON q.id = a.question_id + WHERE q.code = '9.2' AND jsonb_typeof(a.value) = 'array' + GROUP BY 1 + ) sub + WHERE cnt >= 5 + ) t; + + RETURN jsonb_build_object('status','ok','n',v_total,'apoyos', COALESCE(v_rows,'[]'::jsonb)); +END; +$$; + +CREATE OR REPLACE FUNCTION public.rpc_me_carrera_congelada( + p_survey_id uuid, + p_filters jsonb DEFAULT '{}'::jsonb +) +RETURNS jsonb +LANGUAGE plpgsql STABLE SECURITY DEFINER +SET search_path = public +AS $$ +DECLARE + v_f record; + v_n bigint; + v_cong bigint; + v_rows jsonb; +BEGIN + SELECT * INTO v_f FROM public._dash_parse_filters(p_filters); + + SELECT + count(*), + count(*) FILTER ( + WHERE CASE WHEN jsonb_typeof(a.value) = 'array' + THEN jsonb_array_length(a.value - 'Ninguna de las anteriores') > 0 + ELSE false + END + ) + INTO v_n, v_cong + FROM public._dash_responses(p_survey_id, v_f.f_depto, v_f.f_genero, v_f.f_etario, v_f.f_modalidad) dr + JOIN public.answers a ON a.response_id = dr.response_id + JOIN public.questions q ON q.id = a.question_id AND q.code = '7.5' + WHERE public._dash_es_cuidador(dr.response_id); + + IF v_n < 5 THEN + RETURN jsonb_build_object('status','suppressed','min_n',5,'n',v_n); + END IF; + + SELECT jsonb_agg(row ORDER BY cnt DESC) INTO v_rows FROM ( + SELECT jsonb_build_object('opcion', opt, 'n', cnt, 'pct', ROUND(cnt::numeric / v_n * 100, 1)) AS row, + cnt + FROM ( + SELECT jsonb_array_elements_text(a.value) AS opt, + count(DISTINCT dr.response_id) AS cnt + FROM public._dash_responses(p_survey_id, v_f.f_depto, v_f.f_genero, v_f.f_etario, v_f.f_modalidad) dr + JOIN public.answers a ON a.response_id = dr.response_id + JOIN public.questions q ON q.id = a.question_id AND q.code = '7.5' + WHERE public._dash_es_cuidador(dr.response_id) + AND jsonb_typeof(a.value) = 'array' + AND a.value #>> '{}' != 'Ninguna de las anteriores' + GROUP BY 1 + ) sub + WHERE cnt >= 5 + ) t; + + RETURN jsonb_build_object( + 'status', 'ok', + 'n', v_n, + 'pct_carrera_congelada', ROUND(v_cong::numeric / v_n * 100, 1), + 'top_opciones', COALESCE(v_rows, '[]'::jsonb) + ); +END; +$$;