cleanup_referentiel: aligne envs sur canoniques iTop (Test1/Test2->Test, Developpement->Développement, Pre-production->Pré-Prod) + fusion domains avec stem (Peages->Péage). fill_emails --overwrite: force la reecriture des emails existants.
126 lines
4.6 KiB
Python
126 lines
4.6 KiB
Python
"""Complete domain_environments.responsable_email / referent_email depuis contacts.
|
|
|
|
Match sur le nom (contacts.name ≈ responsable_nom ou referent_nom).
|
|
|
|
Usage:
|
|
python tools/fill_emails_from_contacts.py [--dry-run]
|
|
"""
|
|
import os
|
|
import argparse
|
|
import unicodedata
|
|
from sqlalchemy import create_engine, text
|
|
|
|
DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \
|
|
or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo"
|
|
|
|
|
|
def normalize(s):
|
|
"""Normalise un nom: ASCII lowercase sans accent ni espaces multiples."""
|
|
if not s:
|
|
return ""
|
|
nfkd = unicodedata.normalize("NFKD", s.strip().lower())
|
|
ascii_str = "".join(c for c in nfkd if not unicodedata.combining(c))
|
|
return " ".join(ascii_str.split())
|
|
|
|
|
|
def synth_email(name):
|
|
"""Genere prenom.nom@sanef.com a partir d'un nom complet.
|
|
'Frédéric GRAFFAGNINO' -> 'frederic.graffagnino@sanef.com'
|
|
'Pierre-Louis THOUVENOT' -> 'pierre-louis.thouvenot@sanef.com'
|
|
"""
|
|
if not name:
|
|
return None
|
|
norm = normalize(name)
|
|
parts = [p for p in norm.split() if p]
|
|
if len(parts) < 2:
|
|
return None
|
|
first = parts[0]
|
|
last = parts[-1]
|
|
# Nettoie caracteres parasites (garde lettres + tiret + apostrophe)
|
|
import re
|
|
first = re.sub(r"[^a-z\-']", "", first)
|
|
last = re.sub(r"[^a-z\-']", "", last)
|
|
if not first or not last:
|
|
return None
|
|
return f"{first}.{last}@sanef.com"
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("--dry-run", action="store_true")
|
|
parser.add_argument("--overwrite", action="store_true",
|
|
help="Ecrase les emails existants (defaut: ne remplit que les vides)")
|
|
args = parser.parse_args()
|
|
|
|
engine = create_engine(DATABASE_URL)
|
|
print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}")
|
|
conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT")
|
|
|
|
# Cache contacts: normalized name -> email
|
|
contacts = conn.execute(text(
|
|
"SELECT name, email FROM contacts WHERE email IS NOT NULL AND email != ''"
|
|
)).fetchall()
|
|
name_to_email = {}
|
|
for c in contacts:
|
|
key = normalize(c.name)
|
|
if key and "no-email" not in (c.email or "").lower():
|
|
name_to_email[key] = c.email
|
|
print(f"[INFO] {len(name_to_email)} contacts avec email")
|
|
|
|
# Domain_environments: si overwrite, on prend tous ceux avec un nom renseigne
|
|
if args.overwrite:
|
|
filter_clause = "WHERE responsable_nom IS NOT NULL OR referent_nom IS NOT NULL"
|
|
else:
|
|
filter_clause = ("WHERE (responsable_email IS NULL OR responsable_email = '' "
|
|
"OR referent_email IS NULL OR referent_email = '')")
|
|
rows = conn.execute(text(f"""
|
|
SELECT id, responsable_nom, responsable_email, referent_nom, referent_email
|
|
FROM domain_environments
|
|
{filter_clause}
|
|
""")).fetchall()
|
|
print(f"[INFO] {len(rows)} (dom,env) a completer")
|
|
|
|
updated = 0
|
|
from_contacts = synth = 0
|
|
for r in rows:
|
|
updates = {}
|
|
# En mode overwrite: recalcule toujours. Sinon skip si email existe.
|
|
if r.responsable_nom and (args.overwrite or not (r.responsable_email or "").strip()):
|
|
key = normalize(r.responsable_nom)
|
|
email = name_to_email.get(key)
|
|
new_email = email or synth_email(r.responsable_nom)
|
|
if new_email and new_email != (r.responsable_email or ""):
|
|
updates["responsable_email"] = new_email
|
|
if email:
|
|
from_contacts += 1
|
|
else:
|
|
synth += 1
|
|
if r.referent_nom and (args.overwrite or not (r.referent_email or "").strip()):
|
|
key = normalize(r.referent_nom)
|
|
email = name_to_email.get(key)
|
|
new_email = email or synth_email(r.referent_nom)
|
|
if new_email and new_email != (r.referent_email or ""):
|
|
updates["referent_email"] = new_email
|
|
if email:
|
|
from_contacts += 1
|
|
else:
|
|
synth += 1
|
|
|
|
if not updates:
|
|
continue
|
|
if args.dry_run:
|
|
print(f" DRY: de_id={r.id} {updates}")
|
|
else:
|
|
sets = ", ".join(f"{k}=:{k}" for k in updates)
|
|
params = dict(updates); params["id"] = r.id
|
|
conn.execute(text(f"UPDATE domain_environments SET {sets} WHERE id=:id"), params)
|
|
updated += 1
|
|
|
|
conn.close()
|
|
print(f"\n[DONE] Maj: {updated} | depuis contacts: {from_contacts} | "
|
|
f"synthetises (prenom.nom@sanef.com): {synth}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|