From e8f369817e280214816fbc1ce300ae490c21de1d Mon Sep 17 00:00:00 2001 From: Admin MPCZ Date: Tue, 5 May 2026 15:29:34 +0200 Subject: [PATCH] fix(servers): bulk + edit synchronisent aussi les colonnes text legacy s.environnement et s.domaine (sinon liste affiche valeur obsolete) + script SQL re-sync des serveurs deja desyncs --- app/routers/servers.py | 52 ++++++++++++++++++++-------------- app/services/server_service.py | 20 ++++++++----- resync_servers_text_fields.sql | 46 ++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 28 deletions(-) create mode 100644 resync_servers_text_fields.sql diff --git a/app/routers/servers.py b/app/routers/servers.py index fff6723..dfc70d6 100644 --- a/app/routers/servers.py +++ b/app/routers/servers.py @@ -248,16 +248,21 @@ async def servers_bulk(request: Request, db=Depends(get_db), n_updated = res.rowcount or 0 elif bulk_field == "domain_code": # Tous les serveurs prennent le 1er domain_env de ce domaine - # (priorité Production > autres via display_order) row = db.execute(sqlt(""" - SELECT de.id FROM domain_environments de - JOIN domains d ON de.domain_id = d.id - JOIN environments e ON de.environment_id = e.id - WHERE LOWER(d.code) = LOWER(:dc) ORDER BY e.display_order LIMIT 1 + SELECT de.id, d.name AS domaine_name + FROM domain_environments de + JOIN domains d ON de.domain_id = d.id + JOIN environments e ON de.environment_id = e.id + WHERE LOWER(d.code) = LOWER(:dc) + ORDER BY e.display_order LIMIT 1 """), {"dc": bulk_value_clean}).fetchone() if row: - res = db.execute(sqlt("UPDATE servers SET domain_env_id = :deid WHERE id = ANY(:ids)"), - {"deid": row.id, "ids": ids}) + # On sync aussi la colonne text legacy s.domaine + res = db.execute(sqlt(""" + UPDATE servers SET domain_env_id = :deid, domaine = :dn, + updated_at = NOW() + WHERE id = ANY(:ids) + """), {"deid": row.id, "dn": row.domaine_name, "ids": ids}) n_updated = res.rowcount or 0 else: logger.warning(f"servers_bulk domain_code: aucun domain_environments pour {bulk_value_clean!r}") @@ -267,30 +272,35 @@ async def servers_bulk(request: Request, db=Depends(get_db), for sid in ids: srv = db.execute(sqlt(""" SELECT s.id, s.domain_env_id, de.domain_id AS did - FROM servers s - LEFT JOIN domain_environments de ON s.domain_env_id = de.id - WHERE s.id = :sid + FROM servers s + LEFT JOIN domain_environments de ON s.domain_env_id = de.id + WHERE s.id = :sid """), {"sid": sid}).fetchone() if not srv: continue - did = srv.did # peut être None si serveur sans domaine + did = srv.did if did: de = db.execute(sqlt(""" - SELECT de.id FROM domain_environments de - JOIN environments e ON de.environment_id = e.id - WHERE de.domain_id = :did AND LOWER(e.code) = LOWER(:ec) + SELECT de.id, e.name AS env_name + FROM domain_environments de + JOIN environments e ON de.environment_id = e.id + WHERE de.domain_id = :did AND LOWER(e.code) = LOWER(:ec) """), {"did": did, "ec": bulk_value_clean}).fetchone() else: - # Fallback : on prend n'importe quel domain_env avec cet env de = db.execute(sqlt(""" - SELECT de.id FROM domain_environments de - JOIN environments e ON de.environment_id = e.id - WHERE LOWER(e.code) = LOWER(:ec) - ORDER BY de.id LIMIT 1 + SELECT de.id, e.name AS env_name + FROM domain_environments de + JOIN environments e ON de.environment_id = e.id + WHERE LOWER(e.code) = LOWER(:ec) + ORDER BY de.id LIMIT 1 """), {"ec": bulk_value_clean}).fetchone() if de: - db.execute(sqlt("UPDATE servers SET domain_env_id = :deid WHERE id = :sid"), - {"deid": de.id, "sid": sid}) + # On sync aussi la colonne text legacy s.environnement + db.execute(sqlt(""" + UPDATE servers SET domain_env_id = :deid, environnement = :en, + updated_at = NOW() + WHERE id = :sid + """), {"deid": de.id, "en": de.env_name, "sid": sid}) n_updated += 1 else: logger.warning(f"servers_bulk env_code: pas de domain_env pour env {bulk_value_clean!r} (sid={sid}, did={did})") diff --git a/app/services/server_service.py b/app/services/server_service.py index c002845..2b0c99f 100644 --- a/app/services/server_service.py +++ b/app/services/server_service.py @@ -214,19 +214,25 @@ def update_server(db, server_id, data, username): import logging log = logging.getLogger("patchcenter.server") - # Domain + Env -> domain_env_id + # Domain + Env -> domain_env_id (+ sync colonnes text legacy s.domaine / s.environnement) dc = (data.get("domain_code") or "").strip() ec = (data.get("env_code") or "").strip() if dc and ec: row = db.execute(text(""" - SELECT de.id FROM domain_environments de - JOIN domains d ON de.domain_id = d.id - JOIN environments e ON de.environment_id = e.id - WHERE LOWER(d.code) = LOWER(:dc) AND LOWER(e.code) = LOWER(:ec) + SELECT de.id, d.name AS domaine_name, e.name AS env_name + FROM domain_environments de + JOIN domains d ON de.domain_id = d.id + JOIN environments e ON de.environment_id = e.id + WHERE LOWER(d.code) = LOWER(:dc) AND LOWER(e.code) = LOWER(:ec) """), {"dc": dc, "ec": ec}).fetchone() if row: - db.execute(text("UPDATE servers SET domain_env_id = :deid WHERE id = :id"), - {"deid": row.id, "id": server_id}) + db.execute(text(""" + UPDATE servers + SET domain_env_id = :deid, + domaine = :dn, + environnement = :en + WHERE id = :id + """), {"deid": row.id, "dn": row.domaine_name, "en": row.env_name, "id": server_id}) else: log.warning(f"update_server({server_id}): pas de domain_environments pour ({dc!r}, {ec!r})") diff --git a/resync_servers_text_fields.sql b/resync_servers_text_fields.sql new file mode 100644 index 0000000..c81c79a --- /dev/null +++ b/resync_servers_text_fields.sql @@ -0,0 +1,46 @@ +-- Re-sync des colonnes text legacy s.environnement et s.domaine avec +-- les valeurs résolues via domain_env_id → domain_environments → domains/environments. +-- Corrige les serveurs où les colonnes text étaient désynchronisées par +-- des updates précédents qui ne touchaient que domain_env_id. +-- Idempotent. + +\echo '═══ AVANT (lignes désynchronisées) ═══' + +SELECT 'desync_env' AS scope, COUNT(*) + FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN environments e ON de.environment_id = e.id + WHERE COALESCE(s.environnement,'') <> COALESCE(e.name,'') +UNION ALL +SELECT 'desync_dom' AS scope, COUNT(*) + FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN domains d ON de.domain_id = d.id + WHERE COALESCE(s.domaine,'') <> COALESCE(d.name,''); + +\echo '═══ RE-SYNC ═══' + +UPDATE servers s + SET environnement = e.name, + domaine = d.name, + updated_at = NOW() + FROM domain_environments de + JOIN environments e ON de.environment_id = e.id + JOIN domains d ON de.domain_id = d.id + WHERE s.domain_env_id = de.id + AND ( COALESCE(s.environnement,'') <> COALESCE(e.name,'') + OR COALESCE(s.domaine,'') <> COALESCE(d.name,'') ); + +\echo '═══ APRÈS (résiduel doit être 0) ═══' + +SELECT 'desync_env_residuel' AS scope, COUNT(*) + FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN environments e ON de.environment_id = e.id + WHERE COALESCE(s.environnement,'') <> COALESCE(e.name,'') +UNION ALL +SELECT 'desync_dom_residuel' AS scope, COUNT(*) + FROM servers s + JOIN domain_environments de ON s.domain_env_id = de.id + JOIN domains d ON de.domain_id = d.id + WHERE COALESCE(s.domaine,'') <> COALESCE(d.name,'');