diff --git a/app/routers/patch_history.py b/app/routers/patch_history.py index 78a313c..f643d7c 100644 --- a/app/routers/patch_history.py +++ b/app/routers/patch_history.py @@ -14,6 +14,8 @@ templates = Jinja2Templates(directory="app/templates") async def patch_history_page(request: Request, db=Depends(get_db), year: int = Query(None), week: int = Query(None), hostname: str = Query(None), source: str = Query(None), + os_family: str = Query(None), zone: str = Query(None), + domain: str = Query(None), intervenant: str = Query(None), page: int = Query(1)): user = get_current_user(request) if not user: @@ -87,6 +89,25 @@ async def patch_history_page(request: Request, db=Depends(get_db), ) u GROUP BY week_num ORDER BY week_num """), {"y": year}).fetchall() + # Listes pour les filtres (selon annee courante) + filter_opts = {} + filter_opts["os"] = [r.os for r in db.execute(text(""" + SELECT DISTINCT s.os_family as os FROM servers s + WHERE s.os_family IS NOT NULL AND s.os_family <> '' + ORDER BY 1 + """)).fetchall()] + filter_opts["zones"] = [r.zone for r in db.execute(text(""" + SELECT DISTINCT z.name as zone FROM zones z ORDER BY 1 + """)).fetchall()] + filter_opts["domains"] = [r.dom for r in db.execute(text(""" + SELECT DISTINCT d.name as dom FROM domains d ORDER BY 1 + """)).fetchall()] + filter_opts["intervenants"] = [r.interv for r in db.execute(text(""" + SELECT DISTINCT intervenant_name as interv FROM patch_history + WHERE intervenant_name IS NOT NULL AND intervenant_name <> '' + ORDER BY 1 + """)).fetchall()] + where_ph = ["EXTRACT(YEAR FROM ph.date_patch)=:y"] where_qw = ["qr.year=:y", "qe.status='patched'"] params = {"y": year, "limit": per_page, "offset": offset} @@ -99,6 +120,22 @@ async def patch_history_page(request: Request, db=Depends(get_db), where_ph.append("s.hostname ILIKE :h") where_qw.append("s.hostname ILIKE :h") params["h"] = f"%{hostname}%" + if os_family: + where_ph.append("s.os_family=:os") + where_qw.append("s.os_family=:os") + params["os"] = os_family + if zone: + where_ph.append("z.name=:zn") + where_qw.append("z.name=:zn") + params["zn"] = zone + if domain: + where_ph.append("d.name=:dm") + where_qw.append("d.name=:dm") + params["dm"] = domain + if intervenant: + where_ph.append("ph.intervenant_name=:iv") + where_qw.append("1=0") # quickwin n'a pas ce champ + params["iv"] = intervenant if source == "import": where_ph.append("ph.campaign_id IS NULL") elif source == "standard": @@ -107,24 +144,29 @@ async def patch_history_page(request: Request, db=Depends(get_db), wc_ph = " AND ".join(where_ph) wc_qw = " AND ".join(where_qw) - skip_qw = source in ("import", "standard") + skip_qw = source in ("import", "standard") or bool(intervenant) skip_ph = source == "quickwin" + ph_joins = """ + JOIN servers s ON ph.server_id=s.id + LEFT JOIN zones z ON s.zone_id=z.id + LEFT JOIN domain_environments de ON s.domain_env_id=de.id + LEFT JOIN domains d ON de.domain_id=d.id + LEFT JOIN campaigns c ON ph.campaign_id=c.id + """ + qw_joins = """ + JOIN quickwin_runs qr ON qe.run_id=qr.id + JOIN servers s ON qe.server_id=s.id + LEFT JOIN zones z ON s.zone_id=z.id + LEFT JOIN domain_environments de ON s.domain_env_id=de.id + LEFT JOIN domains d ON de.domain_id=d.id + """ + count_parts = [] if not skip_ph: - count_parts.append(f""" - SELECT COUNT(*) FROM patch_history ph - JOIN servers s ON ph.server_id=s.id - LEFT JOIN campaigns c ON ph.campaign_id=c.id - WHERE {wc_ph} - """) + count_parts.append(f"SELECT COUNT(*) FROM patch_history ph {ph_joins} WHERE {wc_ph}") if not skip_qw: - count_parts.append(f""" - SELECT COUNT(*) FROM quickwin_entries qe - JOIN quickwin_runs qr ON qe.run_id=qr.id - JOIN servers s ON qe.server_id=s.id - WHERE {wc_qw} - """) + count_parts.append(f"SELECT COUNT(*) FROM quickwin_entries qe {qw_joins} WHERE {wc_qw}") count_sql = " + ".join(f"({p})" for p in count_parts) if count_parts else "0" total_filtered = db.execute(text(f"SELECT {count_sql}"), params).scalar() @@ -132,34 +174,33 @@ async def patch_history_page(request: Request, db=Depends(get_db), if not skip_ph: union_parts.append(f""" SELECT s.id as sid, s.hostname, s.os_family, s.etat, - ph.date_patch, ph.status, ph.notes, - z.name as zone, + ph.date_patch, ph.status, ph.notes, ph.intervenant_name, + z.name as zone, d.name as domain_name, CASE WHEN ph.campaign_id IS NULL THEN 'import' ELSE COALESCE(c.campaign_type, 'standard') END as source_type, c.id as campaign_id, c.label as campaign_label, NULL::int as run_id, NULL::text as run_label - FROM patch_history ph - JOIN servers s ON ph.server_id=s.id - LEFT JOIN zones z ON s.zone_id=z.id - LEFT JOIN campaigns c ON ph.campaign_id=c.id + FROM patch_history ph {ph_joins} WHERE {wc_ph} """) if not skip_qw: union_parts.append(f""" SELECT s.id as sid, s.hostname, s.os_family, s.etat, qe.patch_date as date_patch, qe.status, qe.notes, - z.name as zone, + NULL::text as intervenant_name, + z.name as zone, d.name as domain_name, 'quickwin' as source_type, NULL::int as campaign_id, NULL::text as campaign_label, qr.id as run_id, qr.label as run_label - FROM quickwin_entries qe - JOIN quickwin_runs qr ON qe.run_id=qr.id - JOIN servers s ON qe.server_id=s.id - LEFT JOIN zones z ON s.zone_id=z.id + FROM quickwin_entries qe {qw_joins} WHERE {wc_qw} """) if not union_parts: - union_parts.append("SELECT NULL::int as sid, NULL as hostname, NULL as os_family, NULL as etat, NULL::timestamptz as date_patch, NULL as status, NULL as notes, NULL as zone, NULL as source_type, NULL::int as campaign_id, NULL as campaign_label, NULL::int as run_id, NULL as run_label WHERE 1=0") + union_parts.append("""SELECT NULL::int as sid, NULL as hostname, NULL as os_family, NULL as etat, + NULL::timestamptz as date_patch, NULL as status, NULL as notes, NULL as intervenant_name, + NULL as zone, NULL as domain_name, NULL as source_type, + NULL::int as campaign_id, NULL as campaign_label, NULL::int as run_id, NULL as run_label + WHERE 1=0""") union_sql = " UNION ALL ".join(union_parts) rows = db.execute(text(f""" @@ -180,6 +221,8 @@ async def patch_history_page(request: Request, db=Depends(get_db), "request": request, "user": user, "app_name": APP_NAME, "kpis": kpis, "by_week": by_week, "by_source": by_source, "rows": rows, "year": year, "week": week, "hostname": hostname, - "source": source, "page": page, "per_page": per_page, + "source": source, "os_family": os_family, "zone": zone, + "domain": domain, "intervenant": intervenant, + "filter_opts": filter_opts, "page": page, "per_page": per_page, "total_filtered": total_filtered, "years": [y.y for y in years], }) diff --git a/app/templates/patch_history.html b/app/templates/patch_history.html index 8f0ea85..df925e9 100644 --- a/app/templates/patch_history.html +++ b/app/templates/patch_history.html @@ -78,10 +78,26 @@ - + + + + + Reset {{ total_filtered }} résultat{{ 's' if total_filtered != 1 }} @@ -95,9 +111,11 @@