def fn_ejecutar_busqueda_global(request, payload, salto_bd, limite_bd): """ Ejecuta el bloque SQL maestro paginado. """ filtros = payload.get("filtros", {}) origenes = filtros.get("origenes", []) subconsulta_dinamica = fn_obtener_subconsulta_origenes(origenes) clausula_where, params = fn_construir_where_dinamico(filtros) params["limite_bd"] = limite_bd params["salto_bd"] = salto_bd sql_conteo = f""" SELECT COUNT(*) AS total_registros FROM ( {subconsulta_dinamica} ) AS T {clausula_where} """ sql_datos = f""" SELECT T.id_origen, T.tipo, T.folio, T.cliente, T.lider, T.frente, T._fid_estatus_paso AS estatus_paso_id, -- Dynamic site resolution logic CASE WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_plataforma::text IN %(ids_sitios)s THEN T._fid_plataforma WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_embarcacion::text IN %(ids_sitios)s THEN T._fid_embarcacion WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_patio::text IN %(ids_sitios)s THEN T._fid_patio ELSE T.id_sitio_oficial END AS id_sitio, CASE WHEN %(buscar_por_frente)s = '1' THEN T.sitio_oficial WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_plataforma::text IN %(ids_sitios)s THEN T.sitio_plat_desc WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_embarcacion::text IN %(ids_sitios)s THEN T.sitio_emb_desc WHEN %(buscar_por_frente)s = '0' AND %(sw_sitio)s = 1 AND T._fid_patio::text IN %(ids_sitios)s THEN T.sitio_pat_desc ELSE CONCAT_WS(' / ', NULLIF(T.sitio_pat_desc, ''), NULLIF(T.sitio_emb_desc, ''), NULLIF(T.sitio_plat_desc, '') ) END AS sitio, T.documento, T.fecha, T.archivo FROM ( {subconsulta_dinamica} ) AS T {clausula_where} ORDER BY T._fecha_sort ASC NULLS LAST LIMIT %(limite_bd)s OFFSET %(salto_bd)s; """ resultado_conteo = ejecutar_query_sql(sql_conteo, params) total_filtrados = resultado_conteo[0]["total_registros"] if resultado_conteo else 0 resultados_paginados = ejecutar_query_sql(sql_datos, params) return resultados_paginados, total_filtrados
def fn_construir_where_dinamico(filtros): lista_lideres = filtros.get("lideres_id", []) lista_clientes = filtros.get("clientes_id", []) lista_frentes = filtros.get("frentes_id", []) lista_sitios = filtros.get("sitios_id", []) lista_documentos = filtros.get("nombres_doc", []) lista_estatus = filtros.get("estatus_proceso_id", []) lista_ots = filtros.get("ots_id", []) fecha_ini_input = filtros.get("fecha_inicio") fecha_fin_input = filtros.get("fecha_fin") texto_busqueda = filtros.get("texto_busqueda", "") check_entregados = filtros.get("check_entregados") check_pendientes = filtros.get("check_no_entregados") buscar_por_frente = filtros.get("buscar_por_frente") or "1" # Delivery status logic ninguno_marcado = not check_entregados and not check_pendientes filtro_entregado = check_entregados or ninguno_marcado filtro_pendiente = check_pendientes or ninguno_marcado condiciones = [] params = {} # OT filter if lista_ots: condiciones.append("T.folio IN %(ids_ots)s") params["ids_ots"] = tuple(lista_ots) # Leader filter if lista_lideres: condiciones.append("T._fid_lider::text IN %(ids_lideres)s") params["ids_lideres"] = tuple(lista_lideres) # Client filter if lista_clientes: condiciones.append("T._fid_cliente::text IN %(ids_clientes)s") params["ids_clientes"] = tuple(lista_clientes) # Document type filter if lista_documentos: condiciones.append("T.documento IN %(nombres_documentos)s") params["nombres_documentos"] = tuple(lista_documentos) # Status filter if lista_estatus: condiciones.append("T._fid_estatus_paso::text IN %(ids_estatus)s") params["ids_estatus"] = tuple(lista_estatus) # Text search if texto_busqueda: condiciones.append(""" ( T.documento ILIKE %(texto)s OR T.folio ILIKE %(texto)s OR T.cliente ILIKE %(texto)s OR T.lider ILIKE %(texto)s ) """) params["texto"] = f"%{texto_busqueda}%" # Complex site filter logic if lista_sitios: params["ids_sitios"] = tuple(lista_sitios) if buscar_por_frente == "1": if lista_frentes: params["ids_frentes"] = tuple(lista_frentes) condiciones.append(""" ( T._fid_frente::text IN %(ids_frentes)s AND ( (T._fid_frente = 1 AND T._fid_patio::text IN %(ids_sitios)s) OR (T._fid_frente = 2 AND T._fid_embarcacion::text IN %(ids_sitios)s) OR (T._fid_frente = 4 AND T._fid_plataforma::text IN %(ids_sitios)s) ) ) """) else: condiciones.append(""" ( (T._fid_frente = 1 AND T._fid_patio::text IN %(ids_sitios)s) OR (T._fid_frente = 2 AND T._fid_embarcacion::text IN %(ids_sitios)s) OR (T._fid_frente = 4 AND T._fid_plataforma::text IN %(ids_sitios)s) ) """) else: # Free site search (searches all site fields) condiciones.append(""" ( T._fid_patio::text IN %(ids_sitios)s OR T._fid_embarcacion::text IN %(ids_sitios)s OR T._fid_plataforma::text IN %(ids_sitios)s ) """) elif lista_frentes: condiciones.append("T._fid_frente::text IN %(ids_frentes)s") params["ids_frentes"] = tuple(lista_frentes) # File delivery filter if filtro_entregado and filtro_pendiente: pass # Show both elif filtro_entregado: condiciones.append("(T.archivo IS NOT NULL AND LENGTH(TRIM(T.archivo)) > 5)") elif filtro_pendiente: condiciones.append("(T.archivo IS NULL OR LENGTH(TRIM(T.archivo)) <= 5)") # Date range filter if fecha_ini_input and fecha_fin_input: condiciones.append("T._fecha_sort BETWEEN %(fecha_ini)s::date AND %(fecha_fin)s::date") params["fecha_ini"] = fecha_ini_input params["fecha_fin"] = fecha_fin_input # Build WHERE clause if condiciones: clausula_where = "WHERE\n " + "\n AND ".join(condiciones) else: clausula_where = "" params["buscar_por_frente"] = buscar_por_frente params["sw_sitio"] = 1 if lista_sitios else 0 params["ids_sitios"] = params.get("ids_sitios", ('-1',)) return clausula_where, params