From ddaba6866a2e20536130e4ad95098467ce9e81a1 Mon Sep 17 00:00:00 2001 From: markosbenitez Date: Fri, 26 Jun 2026 22:38:17 -0300 Subject: [PATCH] fix(rpc): filtrar elementos individuales en carrera_congelada [BUG-001] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mover el filtro 'Ninguna de las anteriores' del WHERE sobre a.value al WHERE del subquery expandido, donde opt es ya un elemento individual resultado de jsonb_array_elements_text. El operador #>> '{}' aplicado sobre un array jsonb no filtraba elementos sino la representación textual del array completo. Co-Authored-By: Claude Sonnet 4.6 --- ...626000002_fix_rpc_me_carrera_congelada.sql | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 supabase/migrations/20260626000002_fix_rpc_me_carrera_congelada.sql diff --git a/supabase/migrations/20260626000002_fix_rpc_me_carrera_congelada.sql b/supabase/migrations/20260626000002_fix_rpc_me_carrera_congelada.sql new file mode 100644 index 0000000..e42c713 --- /dev/null +++ b/supabase/migrations/20260626000002_fix_rpc_me_carrera_congelada.sql @@ -0,0 +1,73 @@ +-- BUG-001 — Fix filtro "Ninguna de las anteriores" en rpc_me_carrera_congelada +-- +-- PROBLEMA: la migración anterior (20260626000001) dejó en el subquery interno: +-- AND a.value #>> '{}' != 'Ninguna de las anteriores' +-- El operador `#>> '{}'` aplicado sobre un ARRAY jsonb no extrae elementos; +-- convierte todo el array a su representación textual (ej. '["opcion","Ninguna..."]'), +-- por lo que la comparación nunca descarta el elemento deseado. +-- +-- SOLUCIÓN: mover el filtro al WHERE del subquery expandido, donde `opt` ya existe +-- como elemento individual resultado de jsonb_array_elements_text. + +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 opt, count(DISTINCT response_id) AS cnt + FROM ( + SELECT jsonb_array_elements_text(a.value) AS opt, + dr.response_id + 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' + ) expanded + WHERE opt != 'Ninguna de las anteriores' + GROUP BY opt + ) 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; +$$;