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

This commit is contained in:
Pierre & Lumière 2026-05-05 15:29:34 +02:00
parent 1b82440813
commit e8f369817e
3 changed files with 90 additions and 28 deletions

View File

@ -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
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
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}")
@ -273,24 +278,29 @@ async def servers_bulk(request: Request, db=Depends(get_db),
"""), {"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
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
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})")

View File

@ -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
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})")

View File

@ -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,'');