diff --git a/README.md b/README.md
index 5827703c756306b49be8b5f6c79b3f43af0cdc88..209a2a01766d82a2e9a501ecd01bacecd420c90d 100644
--- a/README.md
+++ b/README.md
@@ -18,12 +18,12 @@ Flask, SQLAlchemy, au lien de Python2/Zope dans les versions précédentes).
 
 
 
-### État actuel (4 dec 21)
+### État actuel (26 jan 22)
 
- - 9.0 (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf: 
-    - ancien module "Entreprises" (obsolète)
+ - 9.1 (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf: 
+    - ancien module "Entreprises" (obsolète) et ajoute la gestion du BUT.
 
- - 9.1 (branche "PNBUT") est la version de développement.
+ - 9.2 (branche refactor_nt) est la version de développement.
 
  
 ### Lignes de commandes
diff --git a/app/comp/bonus_spo.py b/app/comp/bonus_spo.py
index 7427089d005958a6430b9b82a888c5947070ddd7..0e63adaff20fbb298ea811604e925f76a5461aff 100644
--- a/app/comp/bonus_spo.py
+++ b/app/comp/bonus_spo.py
@@ -338,7 +338,7 @@ def bonus_iut1grenoble_2017(notes_sport, coefs, infos=None):
     Calcul ici du bonus sur moyenne générale
     """
     # les coefs sont ignorés
-    # notes de 0 à 5
+    # notes de 0 à 5/20
     points = sum([x for x in notes_sport])
     factor = (points / 4.0) / 100.0
     bonus = infos["moy"] * factor
@@ -347,7 +347,9 @@ def bonus_iut1grenoble_2017(notes_sport, coefs, infos=None):
 
 
 class BonusGrenobleIUT1(BonusSport):
-    """
+    """Bonus IUT1 de Grenoble
+
+    À compter de sept. 2021:
     La note de sport est sur 20, et on calcule une bonification (en %)
     qui va s'appliquer à la moyenne de chaque UE du semestre en appliquant
     la formule : bonification (en %) = (note-10)*0,5.
@@ -356,11 +358,16 @@ class BonusGrenobleIUT1(BonusSport):
 
     (Une note de 10 donne donc 0% de bonif ; note de 20 : 5% de bonif)
 
+    Avant sept. 2021, la note de sport allait de 0 à 5 points (sur 20).
+    Chaque point correspondait à 0.25% d'augmentation de la moyenne
+    générale.
+    Par exemple : note de sport 2/5 : la moyenne générale était augmentée de 0.5%.
     """
 
-    name = "bonus_grenoble_iut1_2020"
+    name = "bonus_iut1grenoble_2017"
     # C'est un bonus "multiplicatif": on l'exprime en additif,
     # sur chaque moyenne d'UE m_0
+    # Augmenter de 5% correspond à multiplier par a=1.05
     # m_1 = a . m_0
     # m_1 = m_0 + bonus
     # bonus = m_0 (a - 1)
@@ -371,16 +378,21 @@ class BonusGrenobleIUT1(BonusSport):
             sem_modimpl_moys_inscrits * modimpl_coefs_etuds_no_nan, axis=1
         ) / np.sum(modimpl_coefs_etuds_no_nan, axis=1)
         notes = np.nan_to_num(notes, copy=False)
-        a = (notes - 10.0) * 0.005
-        a[a <= 0] = 1.0  # note < 10, pas de bonus
-        if self.formsemestre.formation.is_apc():
-            # ne s'applique qu'aux moyennes d'UE
-            b = self.etud_moy_ue * (a - 1)
-            self.bonus_ues = b  # DataFrame
-        else:
-            # ne s'applique qu'à la moyenne générale
-            b = self.etud_moy_gen * (a - 1)
-            self.bonus_moy_gen = b
+
+        if self.formsemestre.date_debut > datetime.date(2021, 7, 15):
+            factor = (notes - 10.0) * 0.005  # 5% si note=20
+            factor[factor <= 0] = 0.0  # note < 10, pas de bonus
+        else:  # anciens semestres
+            factor = notes / 400.0
+            factor[factor <= 0] = 0.0  # facteur 1 si bonus nul
+
+        # S'applique qu'aux moyennes d'UE
+        bonus = self.etud_moy_ue * factor
+        self.bonus_ues = bonus  # DataFrame
+
+        if not self.formsemestre.formation.is_apc():
+            # s'applique à la moyenne générale
+            self.bonus_moy_gen = bonus
 
 
 class BonusVilleAvray(BonusSport):
diff --git a/app/models/config.py b/app/models/config.py
index c69b5ae600a83a777e5318a892c69755a9cc093e..da98998c4c6bf01dc068653812fa0f854ce52b68 100644
--- a/app/models/config.py
+++ b/app/models/config.py
@@ -3,6 +3,7 @@
 """Model : site config  WORK IN PROGRESS #WIP
 """
 
+from flask import flash
 from app import db, log
 from app.comp import bonus_spo
 from app.scodoc.sco_exceptions import ScoValueError
@@ -120,7 +121,8 @@ class ScoDocSiteConfig(db.Model):
         """returns bonus class with specified name.
         If name not specified, return the configured function.
         None if no bonus function configured.
-        Raises ScoValueError if class_name not found in module bonus_sport.
+        If class_name not found in module bonus_sport, returns None
+        and flash a warning.
         """
         if class_name is None:
             c = ScoDocSiteConfig.query.filter_by(name=cls.BONUS_SPORT).first()
@@ -131,9 +133,9 @@ class ScoDocSiteConfig(db.Model):
             return None
         klass = bonus_spo.get_bonus_class_dict().get(class_name)
         if klass is None:
-            raise ScoValueError(
+            flash(
                 f"""Fonction de calcul bonus sport inexistante: {class_name}. 
-                (contacter votre administrateur local)."""
+                Changez là ou contactez votre administrateur local."""
             )
         return klass