From 2efdfa16c63666359f21a5989cab145a3f785a0c Mon Sep 17 00:00:00 2001
From: ilona <ilona@scodoc.org>
Date: Wed, 9 Oct 2024 15:59:47 +0200
Subject: [PATCH] Ajout strip nom/prenom utilisateurs + option
 TrivialFormulator

---
 app/scodoc/TrivialFormulator.py | 27 +++++++++++++++------------
 app/scodoc/sco_utils.py         | 13 ++++++-------
 app/views/users.py              | 18 ++++++++++++------
 3 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/app/scodoc/TrivialFormulator.py b/app/scodoc/TrivialFormulator.py
index a2afc76bf..0e925ce9d 100644
--- a/app/scodoc/TrivialFormulator.py
+++ b/app/scodoc/TrivialFormulator.py
@@ -296,13 +296,18 @@ class TF(object):
             if not allow_null:
                 if val is None or (isinstance(val, str) and not val.strip()):
                     msg.append(
-                        "Le champ '%s' doit être renseigné" % descr.get("title", field)
+                        f"Le champ '{descr.get('title', field)}' doit être renseigné"
                     )
                     ok = 0
-            elif val == "" or val == None:
+            elif val in ("", None):
                 continue  # allowed empty field, skip
             # type
-            typ = descr.get("type", "string")
+            typ = descr.get("type", "text")
+            # Option pour striper les chaînes
+            if isinstance(val, str) and typ == "text" and descr.get("strip", False):
+                val = val.strip()
+                self.values[field] = val
+
             if val != "" and val is not None:
                 # check only non-null values
                 if typ[:3] == "int":
@@ -311,24 +316,22 @@ class TF(object):
                         self.values[field] = val
                     except ValueError:
                         msg.append(
-                            "La valeur du champ '%s' doit être un nombre entier" % field
+                            f"La valeur du champ '{field}' doit être un nombre entier"
                         )
                         ok = 0
-                elif typ == "float" or typ == "real":
+                elif typ in ("float", "real"):
                     self.values[field] = self.values[field].replace(",", ".")
                     try:
                         val = float(val.replace(",", "."))  # allow ,
                         self.values[field] = val
                     except ValueError:
-                        msg.append(
-                            "La valeur du champ '%s' doit être un nombre" % field
-                        )
+                        msg.append(f"La valeur du champ {field}' doit être un nombre")
                         ok = 0
                 if (
                     ok
                     and (typ[:3] == "int" or typ == "float" or typ == "real")
                     and val != ""
-                    and val != None
+                    and val is not None
                 ):
                     if "min_value" in descr and self.values[field] < descr["min_value"]:
                         msg.append(
@@ -343,12 +346,12 @@ class TF(object):
                         )
                         ok = 0
                     if typ[:3] == "int":
-                        if not (scu.DB_MIN_INT <= self.values[field] <= scu.DB_MAX_INT):
+                        if not scu.DB_MIN_INT <= self.values[field] <= scu.DB_MAX_INT:
                             msg.append(
                                 f"Le champ '{field}' est a une valeur hors limite"
                             )
                             ok = 0
-                    elif typ == "float" or typ == "real":
+                    elif typ in ("float", "real"):
                         if not (
                             scu.DB_MIN_FLOAT <= self.values[field] <= scu.DB_MAX_FLOAT
                         ):
@@ -356,7 +359,7 @@ class TF(object):
                                 f"Le champ '{field}' est a une valeur hors limite"
                             )
                             ok = 0
-                if ok and (typ[:3] == "str") and "max_length" in descr:
+                if ok and "max_length" in descr and isinstance(self.values[field], str):
                     if len(self.values[field]) > descr["max_length"]:
                         msg.append(
                             "Le champ '%s' est trop long (max %d caractères)"
diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py
index e9cbb4149..a437b3dad 100644
--- a/app/scodoc/sco_utils.py
+++ b/app/scodoc/sco_utils.py
@@ -1319,19 +1319,18 @@ def format_nomprenom(etud, reverse=False):
     return " ".join([x for x in fs if x])
 
 
-def format_nom(s, uppercase=True):
+def format_nom(s: str, uppercase=True) -> str:
     "Formatte le nom"
     if not s:
         return ""
     if uppercase:
-        return s.upper()
-    else:
-        return format_prenom(s)
+        return (s.upper()).strip()
+    return format_prenom(s)
 
 
-def format_prenom(s):
+def format_prenom(s: str) -> str:
     """Formatte prenom etudiant pour affichage
-    DEPRECATED: utiliser Identite.prenom_str
+    Pour les étudiants, utiliser Identite.prenom_str
     """
     if not s:
         return ""
@@ -1340,7 +1339,7 @@ def format_prenom(s):
     for frag in frags:
         fs = frag.split("-")
         r.append("-".join([x.lower().capitalize() for x in fs]))
-    return " ".join(r)
+    return (" ".join(r)).strip()
 
 
 def format_telephone(n: str | None) -> str:
diff --git a/app/views/users.py b/app/views/users.py
index 3c147a6d6..df8368de4 100644
--- a/app/views/users.py
+++ b/app/views/users.py
@@ -307,6 +307,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
                 "size": 20,
                 "allow_null": False,
                 "readonly": edit_only_roles,
+                "strip": True,
             },
         ),
         (
@@ -316,6 +317,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
                 "size": 20,
                 "allow_null": False,
                 "readonly": edit_only_roles,
+                "strip": True,
             },
         ),
     ]
@@ -395,6 +397,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
                 "size": 36,
                 "allow_null": False,
                 "readonly": edit_only_roles,
+                "strip": True,
             },
         ),
         (
@@ -455,6 +458,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
                     else ""
                 ),
                 "size": 36,
+                "strip": True,
                 "allow_null": not require_email_institutionnel,
                 "readonly": edit_only_roles,
             },
@@ -809,11 +813,13 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
         db.session.add(the_user)
         db.session.commit()
         # envoi éventuel d'un message
-        if mode == Mode.WELCOME_AND_CHANGE_PASSWORD or mode == Mode.WELCOME_ONLY:
-            if mode == Mode.WELCOME_AND_CHANGE_PASSWORD:
-                token = the_user.get_reset_password_token()
-            else:
-                token = None
+        if mode in (Mode.WELCOME_AND_CHANGE_PASSWORD, Mode.WELCOME_ONLY):
+            token = (
+                the_user.get_reset_password_token()
+                if mode == Mode.WELCOME_AND_CHANGE_PASSWORD
+                else None
+            )
+
             cas_force = ScoDocSiteConfig.get("cas_force")
             # Le from doit utiliser la préférence du département de l'utilisateur
             email.send_email(
@@ -1008,7 +1014,7 @@ def get_user_list_xml(dept=None, start="", limit=25):
     userlist = [
         user
         for user in userlist
-        if scu.suppress_accents((user.nom or "").lower()).startswith(start)
+        if scu.suppress_accents((user.nom or "").strip().lower()).startswith(start)
     ]
     doc = ElementTree.Element("results")
     for user in userlist[:limit]: