From d7f4209a5a9d0a0bc63052f93d06eef20d5248df Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Fri, 1 Nov 2024 11:58:58 +0100
Subject: [PATCH] Comptes utilisateur: option pour forcer modif mot de passe.
---
app/auth/cas.py | 2 +-
app/auth/logic.py | 12 +-
app/auth/models.py | 12 +-
app/auth/routes.py | 21 +-
app/but/bulletin_but.py | 4 +-
app/models/but_refcomp.py | 2 +-
app/models/formsemestre.py | 12 +-
app/models/moduleimpls.py | 10 +
app/scodoc/sco_archives_etud.py | 6 +-
app/scodoc/sco_bulletins.py | 2 +
app/scodoc/sco_formsemestre_edit.py | 9 -
app/scodoc/sco_permissions_check.py | 6 +-
app/scodoc/sco_users.py | 4 +
app/templates/auth/msg_change_password.j2 | 38 ++
app/templates/auth/user_info_page.j2 | 3 +
app/templates/babase.j2 | 3 +
app/templates/base.j2 | 5 +-
app/views/__init__.py | 2 +-
app/views/users.py | 10 +
.../bcd959a23aea_passwd_must_be_changed.py | 34 ++
.../results/formsemestre_resultat.json | 480 +++++++++---------
21 files changed, 408 insertions(+), 269 deletions(-)
create mode 100644 app/templates/auth/msg_change_password.j2
create mode 100644 migrations/versions/bcd959a23aea_passwd_must_be_changed.py
diff --git a/app/auth/cas.py b/app/auth/cas.py
index 268611469..c96e9689e 100644
--- a/app/auth/cas.py
+++ b/app/auth/cas.py
@@ -38,7 +38,7 @@ def after_cas_login():
flask.session["scodoc_cas_login_date"] = (
datetime.datetime.now().isoformat()
)
- user.cas_last_login = datetime.datetime.utcnow()
+ user.cas_last_login = datetime.datetime.now()
if flask.session.get("CAS_EDT_ID"):
# essaie de récupérer l'edt_id s'il est présent
# cet ID peut être renvoyé par le CAS et extrait par ScoDoc
diff --git a/app/auth/logic.py b/app/auth/logic.py
index 496aea1d6..51f1d68df 100644
--- a/app/auth/logic.py
+++ b/app/auth/logic.py
@@ -9,8 +9,8 @@ from flask import current_app, g, redirect, request, url_for
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
import flask_login
-from app import db, login
-from app.auth.models import User
+from app import db, log, login
+from app.auth.models import User, Role
from app.models.config import ScoDocSiteConfig
from app.scodoc.sco_utils import json_error
@@ -19,7 +19,7 @@ token_auth = HTTPTokenAuth()
@basic_auth.verify_password
-def verify_password(username, password):
+def verify_password(username, password) -> User | None:
"""Verify password for this user
Appelé lors d'une demande de jeton (normalement via la route /tokens)
"""
@@ -28,6 +28,7 @@ def verify_password(username, password):
g.current_user = user
# note: est aussi basic_auth.current_user()
return user
+ return None
@basic_auth.error_handler
@@ -61,7 +62,8 @@ def token_auth_error(status):
@token_auth.get_user_roles
-def get_user_roles(user):
+def get_user_roles(user) -> list[Role]:
+ "list roles"
return user.roles
@@ -82,7 +84,7 @@ def load_user_from_request(req: flask.Request) -> User:
@login.unauthorized_handler
def unauthorized():
"flask-login: si pas autorisé, redirige vers page login, sauf si API"
- if request.blueprint == "api" or request.blueprint == "apiweb":
+ if request.blueprint in ("api", "apiweb"):
return json_error(http.HTTPStatus.UNAUTHORIZED, "Non autorise (logic)")
return redirect(url_for("auth.login"))
diff --git a/app/auth/models.py b/app/auth/models.py
index 0354e9288..b73190459 100644
--- a/app/auth/models.py
+++ b/app/auth/models.py
@@ -105,6 +105,9 @@ class User(UserMixin, ScoDocModel):
date_modif_passwd = db.Column(db.DateTime, default=datetime.now)
date_created = db.Column(db.DateTime, default=datetime.now)
date_expiration = db.Column(db.DateTime, default=None)
+ passwd_must_be_changed = db.Column(
+ db.Boolean, nullable=False, server_default="false", default=False
+ )
passwd_temp = db.Column(db.Boolean, default=False)
"""champ obsolete. Si connexion alors que passwd_temp est vrai,
efface mot de passe et redirige vers accueil."""
@@ -185,6 +188,8 @@ class User(UserMixin, ScoDocModel):
# La création d'un mot de passe efface l'éventuel mot de passe historique
self.password_scodoc7 = None
self.passwd_temp = False
+ # Retire le flag
+ self.passwd_must_be_changed = False
def check_password(self, password: str) -> bool:
"""Check given password vs current one.
@@ -282,6 +287,7 @@ class User(UserMixin, ScoDocModel):
if self.date_modif_passwd
else None
),
+ "passwd_must_be_changed": self.passwd_must_be_changed,
"date_created": (
self.date_created.isoformat() + "Z" if self.date_created else None
),
@@ -385,7 +391,7 @@ class User(UserMixin, ScoDocModel):
def get_token(self, expires_in=3600):
"Un jeton pour cet user. Stocké en base, non commité."
- now = datetime.utcnow()
+ now = datetime.now()
if self.token and self.token_expiration > now + timedelta(seconds=60):
return self.token
self.token = base64.b64encode(os.urandom(24)).decode("utf-8")
@@ -395,7 +401,7 @@ class User(UserMixin, ScoDocModel):
def revoke_token(self):
"Révoque le jeton de cet utilisateur"
- self.token_expiration = datetime.utcnow() - timedelta(seconds=1)
+ self.token_expiration = datetime.now() - timedelta(seconds=1)
@staticmethod
def check_token(token):
@@ -403,7 +409,7 @@ class User(UserMixin, ScoDocModel):
and returns the user object.
"""
user = User.query.filter_by(token=token).first()
- if user is None or user.token_expiration < datetime.utcnow():
+ if user is None or user.token_expiration < datetime.now():
return None
return user
diff --git a/app/auth/routes.py b/app/auth/routes.py
index 778cf8e5e..e8283c1a4 100644
--- a/app/auth/routes.py
+++ b/app/auth/routes.py
@@ -4,7 +4,7 @@ auth.routes.py
"""
import flask
-from flask import current_app, flash, render_template
+from flask import current_app, flash, g, render_template
from flask import redirect, url_for, request
from flask_login import login_user, current_user
from sqlalchemy import func
@@ -23,6 +23,7 @@ from app.auth.email import send_password_reset_email
from app.decorators import admin_required
from app.forms.generic import SimpleConfirmationForm
from app.models.config import ScoDocSiteConfig
+from app.models.departements import Departement
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
from app.scodoc import sco_utils as scu
@@ -49,6 +50,24 @@ def _login_form():
login_user(user, remember=form.remember_me.data)
current_app.logger.info("login: success (%s)", form.user_name.data)
+
+ if user.passwd_must_be_changed:
+ # Mot de passe à changer à la première connexion
+ dept = user.dept or getattr(g, "scodoc_dept", None)
+ if not dept:
+ departement = db.session.query(Departement).first()
+ dept = departement.acronym
+ if dept:
+ # Redirect to the password change page
+ flash("Votre mot de passe doit être changé")
+ return redirect(
+ url_for(
+ "users.form_change_password",
+ scodoc_dept=dept,
+ user_name=user.user_name,
+ )
+ )
+
return form.redirect("scodoc.index")
return render_template(
diff --git a/app/but/bulletin_but.py b/app/but/bulletin_but.py
index 4a6908ec3..cf706008b 100644
--- a/app/but/bulletin_but.py
+++ b/app/but/bulletin_but.py
@@ -407,7 +407,9 @@ class BulletinBUT:
d = {
"version": "0",
"type": "BUT",
- "date": datetime.datetime.utcnow().isoformat() + "Z",
+ "date": datetime.datetime.now(datetime.timezone.utc)
+ .astimezone()
+ .isoformat(),
"publie": not formsemestre.bul_hide_xml,
"etat_inscription": etud.inscription_etat(formsemestre.id),
"etudiant": etud.to_dict_bul(),
diff --git a/app/models/but_refcomp.py b/app/models/but_refcomp.py
index d89e19dab..69c3e0fc5 100644
--- a/app/models/but_refcomp.py
+++ b/app/models/but_refcomp.py
@@ -76,7 +76,7 @@ class ApcReferentielCompetences(models.ScoDocModel, XMLModel):
"version": "version_orebut",
}
# ScoDoc specific fields:
- scodoc_date_loaded = db.Column(db.DateTime, default=datetime.utcnow)
+ scodoc_date_loaded = db.Column(db.DateTime, default=datetime.now)
scodoc_orig_filename = db.Column(db.Text())
# Relations:
competences = db.relationship(
diff --git a/app/models/formsemestre.py b/app/models/formsemestre.py
index 863b5d8ce..dc08a847b 100644
--- a/app/models/formsemestre.py
+++ b/app/models/formsemestre.py
@@ -646,9 +646,11 @@ class FormSemestre(models.ScoDocModel):
)
return [db.session.get(ModuleImpl, modimpl_id) for modimpl_id in cursor]
- def can_be_edited_by(self, user):
+ def can_be_edited_by(self, user: User):
"""Vrai si user peut modifier ce semestre (est chef ou l'un des responsables)"""
- if not user.has_permission(Permission.EditFormSemestre): # pas chef
+ if user.passwd_must_be_changed or not user.has_permission(
+ Permission.EditFormSemestre
+ ): # pas chef
if not self.resp_can_edit or user.id not in [
resp.id for resp in self.responsables
]:
@@ -897,6 +899,8 @@ class FormSemestre(models.ScoDocModel):
if not self.etat:
return False # semestre verrouillé
user = user or current_user
+ if user.passwd_must_be_changed:
+ return False
if user.has_permission(Permission.EtudChangeGroups):
return True # typiquement admin, chef dept
return self.est_responsable(user)
@@ -906,11 +910,15 @@ class FormSemestre(models.ScoDocModel):
dans ce semestre: vérifie permission et verrouillage.
"""
user = user or current_user
+ if user.passwd_must_be_changed:
+ return False
return self.etat and self.est_chef_or_diretud(user)
def can_edit_pv(self, user: User = None):
"Vrai si utilisateur (par def. current) peut editer un PV de jury de ce semestre"
user = user or current_user
+ if user.passwd_must_be_changed:
+ return False
# Autorise les secrétariats, repérés via la permission EtudChangeAdr
return self.est_chef_or_diretud(user) or user.has_permission(
Permission.EtudChangeAdr
diff --git a/app/models/moduleimpls.py b/app/models/moduleimpls.py
index c3a3c2698..a3ce27a72 100644
--- a/app/models/moduleimpls.py
+++ b/app/models/moduleimpls.py
@@ -199,6 +199,8 @@ class ModuleImpl(ScoDocModel):
"""True if this user can create, delete or edit and evaluation in this modimpl
(nb: n'implique pas le droit de saisir ou modifier des notes)
"""
+ if user.passwd_must_be_changed:
+ return False
# acces pour resp. moduleimpl et resp. form semestre (dir etud)
if (
user.has_permission(Permission.EditAllEvals)
@@ -222,6 +224,8 @@ class ModuleImpl(ScoDocModel):
# was sco_permissions_check.can_edit_notes
from app.scodoc import sco_cursus_dut
+ if user.passwd_must_be_changed:
+ return False
if not self.formsemestre.etat:
return False # semestre verrouillé
is_dir_etud = user.id in (u.id for u in self.formsemestre.responsables)
@@ -247,6 +251,8 @@ class ModuleImpl(ScoDocModel):
if raise_exc:
raise ScoLockedSemError("Modification impossible: semestre verrouille")
return False
+ if user.passwd_must_be_changed:
+ return False
# -- check access
# admin ou resp. semestre avec flag resp_can_change_resp
if user.has_permission(Permission.EditFormSemestre):
@@ -264,6 +270,8 @@ class ModuleImpl(ScoDocModel):
if user is None, current user.
"""
user = current_user if user is None else user
+ if user.passwd_must_be_changed:
+ return False
if not self.formsemestre.etat:
if raise_exc:
raise ScoLockedSemError("Modification impossible: semestre verrouille")
@@ -285,6 +293,8 @@ class ModuleImpl(ScoDocModel):
Autorise ScoEtudInscrit ou responsables semestre.
"""
user = current_user if user is None else user
+ if user.passwd_must_be_changed:
+ return False
if not self.formsemestre.etat:
if raise_exc:
raise ScoLockedSemError("Modification impossible: semestre verrouille")
diff --git a/app/scodoc/sco_archives_etud.py b/app/scodoc/sco_archives_etud.py
index 0067be0af..be0b70523 100644
--- a/app/scodoc/sco_archives_etud.py
+++ b/app/scodoc/sco_archives_etud.py
@@ -54,9 +54,11 @@ class EtudsArchiver(sco_archives.BaseArchiver):
ETUDS_ARCHIVER = EtudsArchiver()
-def can_edit_etud_archive(authuser):
+def can_edit_etud_archive(user):
"""True si l'utilisateur peut modifier les archives etudiantes"""
- return authuser.has_permission(Permission.EtudAddAnnotations)
+ if user.passwd_must_be_changed:
+ return False
+ return user.has_permission(Permission.EtudAddAnnotations)
def etud_list_archives_html(etud: Identite):
diff --git a/app/scodoc/sco_bulletins.py b/app/scodoc/sco_bulletins.py
index e59249926..5279ab98b 100644
--- a/app/scodoc/sco_bulletins.py
+++ b/app/scodoc/sco_bulletins.py
@@ -1001,6 +1001,8 @@ def formsemestre_bulletinetud(
def can_send_bulletin_by_mail(formsemestre_id):
"""True if current user is allowed to send a bulletin (pdf) by mail"""
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
+ if current_user.passwd_must_be_changed:
+ return False
return (
sco_preferences.get_preference("bul_mail_allowed_for_all", formsemestre_id)
or current_user.has_permission(Permission.EditFormSemestre)
diff --git a/app/scodoc/sco_formsemestre_edit.py b/app/scodoc/sco_formsemestre_edit.py
index 74f1d7481..ee7a133a3 100644
--- a/app/scodoc/sco_formsemestre_edit.py
+++ b/app/scodoc/sco_formsemestre_edit.py
@@ -134,15 +134,6 @@ def formsemestre_editwithmodules(formsemestre_id: int):
)
-def can_edit_sem(formsemestre_id: int = None, sem=None):
- """Return sem if user can edit it, False otherwise"""
- sem = sem or sco_formsemestre.get_formsemestre(formsemestre_id)
- if not current_user.has_permission(Permission.EditFormSemestre): # pas chef
- if not sem["resp_can_edit"] or current_user.id not in sem["responsables"]:
- return False
- return sem
-
-
RESP_FIELDS = [
"responsable_id",
"responsable_id2",
diff --git a/app/scodoc/sco_permissions_check.py b/app/scodoc/sco_permissions_check.py
index 6f98aafd2..4145b7e06 100644
--- a/app/scodoc/sco_permissions_check.py
+++ b/app/scodoc/sco_permissions_check.py
@@ -17,6 +17,8 @@ def can_suppress_annotation(annotation_id):
Seuls l'auteur de l'annotation et le chef de dept peuvent supprimer
une annotation.
"""
+ if current_user.passwd_must_be_changed:
+ return False
annotation = (
EtudAnnotation.query.filter_by(id=annotation_id)
.join(Identite)
@@ -30,8 +32,10 @@ def can_suppress_annotation(annotation_id):
)
-def can_edit_suivi():
+def can_edit_suivi() -> bool:
"""Vrai si l'utilisateur peut modifier les informations de suivi sur la page etud" """
+ if current_user.passwd_must_be_changed:
+ return False
return current_user.has_permission(Permission.EtudChangeAdr)
diff --git a/app/scodoc/sco_users.py b/app/scodoc/sco_users.py
index d31c08380..db27e0c76 100644
--- a/app/scodoc/sco_users.py
+++ b/app/scodoc/sco_users.py
@@ -184,9 +184,11 @@ def list_users(
if not current_user.is_administrator():
# si non super-admin, ne donne pas la date exacte de derniere connexion
d["last_seen"] = _approximate_date(u.last_seen)
+ d["passwd_must_be_changed"] = "OUI" if d["passwd_must_be_changed"] else ""
else:
d["date_modif_passwd"] = "(non visible)"
d["non_migre"] = ""
+ d["passwd_must_be_changed"] = ""
if detail_roles:
d["roles_set"] = {
f"{r.role.name or ''}_{r.dept or ''}" for r in u.user_roles
@@ -209,6 +211,7 @@ def list_users(
"roles_string",
"date_expiration",
"date_modif_passwd",
+ "passwd_must_be_changed",
"non_migre",
"status_txt",
]
@@ -240,6 +243,7 @@ def list_users(
"roles_string": "Rôles",
"date_expiration": "Expiration",
"date_modif_passwd": "Modif. mot de passe",
+ "passwd_must_be_changed": "À changer",
"last_seen": "Dernière cnx.",
"non_migre": "Non migré (!)",
"status_txt": "Etat",
diff --git a/app/templates/auth/msg_change_password.j2 b/app/templates/auth/msg_change_password.j2
new file mode 100644
index 000000000..ed572907b
--- /dev/null
+++ b/app/templates/auth/msg_change_password.j2
@@ -0,0 +1,38 @@
+<style>
+div.msg-change-passwd {
+ border: 3px solid white;
+ border-radius: 8px;
+ padding: 16px;
+ width: fit-content;
+ margin-left: auto;
+ margin-right: auto;
+ margin-top: 28px;
+ margin-bottom: 28px;
+}
+div.msg-change-passwd, div.msg-change-passwd a {
+ font-size: 36px;
+ font-weight: bold;
+ background-color: red;
+ color: white;
+}
+div.msg-change-passwd a, div.msg-change-passwd a:visited {
+ text-decoration: underline;
+}
+</style>
+<div class="msg-change-passwd">
+Vous devez
+ {% if current_user.dept %}
+ <a class="nav-link" href="{{
+ url_for(
+ 'users.form_change_password',
+ scodoc_dept=current_user.dept,
+ user_name=current_user.user_name
+ )
+ }}">
+ {% endif %}
+ changer votre mot de passe
+ {% if current_user.dept %}
+ </a>
+ {% endif %}
+ !
+</div>
diff --git a/app/templates/auth/user_info_page.j2 b/app/templates/auth/user_info_page.j2
index b3957202a..6b36704a5 100644
--- a/app/templates/auth/user_info_page.j2
+++ b/app/templates/auth/user_info_page.j2
@@ -18,6 +18,9 @@
<br>
<b>Nom :</b> {{user.nom or ""}}<br>
<b>Prénom :</b> {{user.prenom or ""}}<br>
+ {% if user.passwd_must_be_changed %}
+ <div style="color:white; background-color: red; padding:8px; margin-top: 4px; width: fit-content;">mot de passe à changer</div>
+ {% endif %}
<b>Mail :</b> {{user.email}}<br>
<b>Mail institutionnel:</b> {{user.email_institutionnel or ""}}<br>
<b>Identifiant EDT:</b> {{user.edt_id or ""}}<br>
diff --git a/app/templates/babase.j2 b/app/templates/babase.j2
index b48669535..ef538ca1a 100644
--- a/app/templates/babase.j2
+++ b/app/templates/babase.j2
@@ -25,6 +25,9 @@
{% block navbar %}
{%- endblock navbar %}
<div id="sco_msg" class="head_message"></div>
+ {% if current_user and current_user.passwd_must_be_changed %}
+ {% include "auth/msg_change_password.j2" %}
+ {% endif %}
{% block content -%}
{%- endblock content %}
diff --git a/app/templates/base.j2 b/app/templates/base.j2
index ed1ff28eb..dcde83581 100644
--- a/app/templates/base.j2
+++ b/app/templates/base.j2
@@ -46,7 +46,8 @@
{% if current_user.is_anonymous %}
<li class="nav-item"><a class="nav-link" href="{{ url_for('auth.login') }}">connexion</a></li>
{% else %}
- <li class="nav-item">{% if current_user.dept %}
+ <li class="nav-item">
+ {% if current_user.dept %}
<a class="nav-link" href="{{ url_for('users.user_info_page', scodoc_dept=current_user.dept, user_name=current_user.user_name )
}}">{{current_user.user_name}} ({{current_user.dept}})</a>
{% else %}
@@ -89,7 +90,7 @@
<script>
const SCO_URL = "{% if g.scodoc_dept %}{{
url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)}}{% endif %}";
-
+
document.querySelector('.navbar-toggler').addEventListener('click', function() {
document.querySelector('.navbar-collapse').classList.toggle('show');
});
diff --git a/app/views/__init__.py b/app/views/__init__.py
index 65d2b9e11..7193d7f5e 100644
--- a/app/views/__init__.py
+++ b/app/views/__init__.py
@@ -37,7 +37,7 @@ def start_scodoc_request():
# current_app.logger.info(f"start_scodoc_request")
ndb.open_db_connection()
if current_user and current_user.is_authenticated:
- current_user.last_seen = datetime.datetime.utcnow()
+ current_user.last_seen = datetime.datetime.now()
db.session.commit()
# caches locaux (durée de vie=la requête en cours)
g.stored_get_formsemestre = {}
diff --git a/app/views/users.py b/app/views/users.py
index df8368de4..3ffe57938 100644
--- a/app/views/users.py
+++ b/app/views/users.py
@@ -334,6 +334,16 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
},
)
)
+ descr.append(
+ (
+ "passwd_must_be_changed",
+ {
+ "title": "Force à changer le mot de passe",
+ "input_type": "boolcheckbox",
+ "explanation": """ à la première connexion.""",
+ },
+ )
+ )
if not edit:
descr += [
(
diff --git a/migrations/versions/bcd959a23aea_passwd_must_be_changed.py b/migrations/versions/bcd959a23aea_passwd_must_be_changed.py
new file mode 100644
index 000000000..6eedcdf0b
--- /dev/null
+++ b/migrations/versions/bcd959a23aea_passwd_must_be_changed.py
@@ -0,0 +1,34 @@
+"""passwd_must_be_changed
+
+Revision ID: bcd959a23aea
+Revises: 2640b7686de6
+Create Date: 2024-11-01 09:51:01.299407
+
+"""
+
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = "bcd959a23aea"
+down_revision = "2640b7686de6"
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ with op.batch_alter_table("user", schema=None) as batch_op:
+ batch_op.add_column(
+ sa.Column(
+ "passwd_must_be_changed",
+ sa.Boolean(),
+ server_default="false",
+ nullable=False,
+ )
+ )
+
+
+def downgrade():
+ with op.batch_alter_table("user", schema=None) as batch_op:
+ batch_op.drop_column("passwd_must_be_changed")
diff --git a/tests/ressources/results/formsemestre_resultat.json b/tests/ressources/results/formsemestre_resultat.json
index d6187aebc..f3438baf2 100644
--- a/tests/ressources/results/formsemestre_resultat.json
+++ b/tests/ressources/results/formsemestre_resultat.json
@@ -5,27 +5,13 @@
"rang": "1",
"civilite_str": "Mme",
"nom_disp": "BONHOMME",
- "prenom": "MADELEINE",
+ "prenom": "Madeleine",
"nom_short": "BONHOMME Ma.",
"partitions": {
"1": 1
},
"sort_key": "bonhomme;madeleine",
"moy_gen": "14.36",
- "moy_ue_1": "14.94",
- "moy_res_1_1": "~",
- "moy_res_3_1": "11.97",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "15.71",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "10.66",
- "moy_res_12_1": "12.50",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "18.72",
- "moy_sae_7_1": "14.69",
"moy_ue_2": "11.17",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -49,6 +35,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "17.83",
"moy_sae_15_3": "~",
+ "moy_ue_1": "14.94",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "11.97",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "15.71",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "10.66",
+ "moy_res_12_1": "12.50",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "18.72",
+ "moy_sae_7_1": "14.69",
"ues_validables": "3/3",
"nbabs": 1,
"nbabsjust": 0,
@@ -65,27 +65,13 @@
"rang": "2",
"civilite_str": "M.",
"nom_disp": "JAMES",
- "prenom": "JACQUES",
+ "prenom": "Jacques",
"nom_short": "JAMES Ja.",
"partitions": {
"1": 1
},
"sort_key": "james;jacques",
"moy_gen": "12.67",
- "moy_ue_1": "13.51",
- "moy_res_1_1": "~",
- "moy_res_3_1": "03.27",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "13.05",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "04.35",
- "moy_res_12_1": "18.85",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "~",
- "moy_sae_7_1": "17.07",
"moy_ue_2": "14.24",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -109,6 +95,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "10.74",
"moy_sae_15_3": "~",
+ "moy_ue_1": "13.51",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "03.27",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "13.05",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "04.35",
+ "moy_res_12_1": "18.85",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "~",
+ "moy_sae_7_1": "17.07",
"ues_validables": "3/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -125,27 +125,13 @@
"rang": "3",
"civilite_str": "",
"nom_disp": "THIBAUD",
- "prenom": "MAXIME",
+ "prenom": "Maxime",
"nom_short": "THIBAUD Ma.",
"partitions": {
"1": 1
},
"sort_key": "thibaud;maxime",
"moy_gen": "12.02",
- "moy_ue_1": "14.34",
- "moy_res_1_1": "~",
- "moy_res_3_1": "17.68",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "18.31",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "18.97",
- "moy_res_12_1": "05.46",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "13.02",
- "moy_sae_7_1": "14.11",
"moy_ue_2": "09.89",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -169,6 +155,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "05.70",
"moy_sae_15_3": "~",
+ "moy_ue_1": "14.34",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "17.68",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "18.31",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "18.97",
+ "moy_res_12_1": "05.46",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "13.02",
+ "moy_sae_7_1": "14.11",
"ues_validables": "2/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -185,27 +185,13 @@
"rang": "4",
"civilite_str": "",
"nom_disp": "ROYER",
- "prenom": "CAMILLE",
+ "prenom": "Camille",
"nom_short": "ROYER Ca.",
"partitions": {
"1": 1
},
"sort_key": "royer;camille",
"moy_gen": "11.88",
- "moy_ue_1": "07.09",
- "moy_res_1_1": "~",
- "moy_res_3_1": "04.07",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "17.62",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "16.57",
- "moy_res_12_1": "18.61",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "14.13",
- "moy_sae_7_1": "00.53",
"moy_ue_2": "17.35",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -229,6 +215,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "10.52",
"moy_sae_15_3": "~",
+ "moy_ue_1": "07.09",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "04.07",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "17.62",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "16.57",
+ "moy_res_12_1": "18.61",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "14.13",
+ "moy_sae_7_1": "00.53",
"ues_validables": "2/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -245,27 +245,13 @@
"rang": "5",
"civilite_str": "M.",
"nom_disp": "GODIN",
- "prenom": "CLAUDE",
+ "prenom": "Claude",
"nom_short": "GODIN Cl.",
"partitions": {
"1": 1
},
"sort_key": "godin;claude",
"moy_gen": "10.52",
- "moy_ue_1": "08.93",
- "moy_res_1_1": "~",
- "moy_res_3_1": "07.77",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "00.48",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "08.95",
- "moy_res_12_1": "18.10",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "14.29",
- "moy_sae_7_1": "06.89",
"moy_ue_2": "16.04",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -289,6 +275,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "11.09",
"moy_sae_15_3": "~",
+ "moy_ue_1": "08.93",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "07.77",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "00.48",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "08.95",
+ "moy_res_12_1": "18.10",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "14.29",
+ "moy_sae_7_1": "06.89",
"ues_validables": "1/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -305,27 +305,13 @@
"rang": "6",
"civilite_str": "M.",
"nom_disp": "CONSTANT",
- "prenom": "PATRICK",
+ "prenom": "Patrick",
"nom_short": "CONSTANT Pa.",
"partitions": {
"1": 1
},
"sort_key": "constant;patrick",
"moy_gen": "10.04",
- "moy_ue_1": "13.06",
- "moy_res_1_1": "~",
- "moy_res_3_1": "05.84",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "11.44",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "14.04",
- "moy_res_12_1": "13.28",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "09.82",
- "moy_sae_7_1": "17.46",
"moy_ue_2": "10.62",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -349,6 +335,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "01.55",
"moy_sae_15_3": "~",
+ "moy_ue_1": "13.06",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "05.84",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "11.44",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "14.04",
+ "moy_res_12_1": "13.28",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "09.82",
+ "moy_sae_7_1": "17.46",
"ues_validables": "2/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -365,27 +365,13 @@
"rang": "7",
"civilite_str": "",
"nom_disp": "TOUSSAINT",
- "prenom": "ALIX",
+ "prenom": "Alix",
"nom_short": "TOUSSAINT Al.",
"partitions": {
"1": 1
},
"sort_key": "toussaint;alix",
"moy_gen": "08.59",
- "moy_ue_1": "07.24",
- "moy_res_1_1": "~",
- "moy_res_3_1": "11.90",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "00.47",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "18.66",
- "moy_res_12_1": "18.02",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "~",
- "moy_sae_7_1": "04.46",
"moy_ue_2": "13.93",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -409,6 +395,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "05.17",
"moy_sae_15_3": "~",
+ "moy_ue_1": "07.24",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "11.90",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "00.47",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "18.66",
+ "moy_res_12_1": "18.02",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "~",
+ "moy_sae_7_1": "04.46",
"ues_validables": "1/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -425,27 +425,13 @@
"rang": "8",
"civilite_str": "",
"nom_disp": "DENIS",
- "prenom": "MAXIME",
+ "prenom": "Maxime",
"nom_short": "DENIS Ma.",
"partitions": {
"1": 1
},
"sort_key": "denis;maxime",
"moy_gen": "07.21",
- "moy_ue_1": "06.86",
- "moy_res_1_1": "~",
- "moy_res_3_1": "~",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "10.06",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "11.75",
- "moy_res_12_1": "01.88",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "14.55",
- "moy_sae_7_1": "03.02",
"moy_ue_2": "08.84",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -469,6 +455,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "03.32",
"moy_sae_15_3": "~",
+ "moy_ue_1": "06.86",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "~",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "10.06",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "11.75",
+ "moy_res_12_1": "01.88",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "14.55",
+ "moy_sae_7_1": "03.02",
"ues_validables": "0/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -485,27 +485,13 @@
"rang": "9",
"civilite_str": "Mme",
"nom_disp": "WALTER",
- "prenom": "SIMONE",
+ "prenom": "Simone",
"nom_short": "WALTER Si.",
"partitions": {
"1": 1
},
"sort_key": "walter;simone",
"moy_gen": "07.02",
- "moy_ue_1": "06.82",
- "moy_res_1_1": "~",
- "moy_res_3_1": "16.91",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "12.84",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "13.08",
- "moy_res_12_1": "10.63",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "06.28",
- "moy_sae_7_1": "01.36",
"moy_ue_2": "07.96",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -529,6 +515,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "02.10",
"moy_sae_15_3": "~",
+ "moy_ue_1": "06.82",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "16.91",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "12.84",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "13.08",
+ "moy_res_12_1": "10.63",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "06.28",
+ "moy_sae_7_1": "01.36",
"ues_validables": "0/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -545,27 +545,13 @@
"rang": "10",
"civilite_str": "",
"nom_disp": "GROSS",
- "prenom": "SACHA",
+ "prenom": "Sacha",
"nom_short": "GROSS Sa.",
"partitions": {
"1": 1
},
"sort_key": "gross;sacha",
"moy_gen": "05.31",
- "moy_ue_1": "03.73",
- "moy_res_1_1": "~",
- "moy_res_3_1": "~",
- "moy_res_4_1": "~",
- "moy_res_5_1": "~",
- "moy_res_6_1": "~",
- "moy_res_18_1": "03.04",
- "moy_res_10_1": "~",
- "moy_res_11_1": "~",
- "moy_res_20_1": "04.89",
- "moy_res_12_1": "09.88",
- "moy_res_13_1": "~",
- "moy_sae_2_1": "~",
- "moy_sae_7_1": "02.85",
"moy_ue_2": "07.13",
"moy_res_1_2": "~",
"moy_res_4_2": "~",
@@ -589,6 +575,20 @@
"moy_res_21_3": "~",
"moy_sae_14_3": "07.17",
"moy_sae_15_3": "~",
+ "moy_ue_1": "03.73",
+ "moy_res_1_1": "~",
+ "moy_res_3_1": "~",
+ "moy_res_4_1": "~",
+ "moy_res_5_1": "~",
+ "moy_res_6_1": "~",
+ "moy_res_18_1": "03.04",
+ "moy_res_10_1": "~",
+ "moy_res_11_1": "~",
+ "moy_res_20_1": "04.89",
+ "moy_res_12_1": "09.88",
+ "moy_res_13_1": "~",
+ "moy_sae_2_1": "~",
+ "moy_sae_7_1": "02.85",
"ues_validables": "0/3",
"nbabs": 0,
"nbabsjust": 0,
@@ -605,27 +605,13 @@
"rang": "11 ex",
"civilite_str": "M.",
"nom_disp": "BARTHELEMY",
- "prenom": "G\u00c9RARD",
+ "prenom": "G\u00e9rard",
"nom_short": "BARTHELEMY G\u00e9.",
"partitions": {
"1": 1
},
"sort_key": "barthelemy;gerard",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -649,6 +635,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 2,
"nbabsjust": 0,
@@ -665,27 +665,13 @@
"rang": "11 ex",
"civilite_str": "Mme",
"nom_disp": "MILLOT",
- "prenom": "FRAN\u00c7OISE",
+ "prenom": "Fran\u00e7oise",
"nom_short": "MILLOT Fr.",
"partitions": {
"1": 1
},
"sort_key": "millot;francoise",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -709,6 +695,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 0,
"nbabsjust": 0,
@@ -725,27 +725,13 @@
"rang": "11 ex",
"civilite_str": "M.",
"nom_disp": "BENOIT",
- "prenom": "EMMANUEL",
+ "prenom": "Emmanuel",
"nom_short": "BENOIT Em.",
"partitions": {
"1": 1
},
"sort_key": "benoit;emmanuel",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -769,6 +755,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 2,
"nbabsjust": 0,
@@ -785,27 +785,13 @@
"rang": "11 ex",
"civilite_str": "Mme",
"nom_disp": "LECOCQ",
- "prenom": "MARGUERITE",
+ "prenom": "Marguerite",
"nom_short": "LECOCQ Ma.",
"partitions": {
"1": 1
},
"sort_key": "lecocq;marguerite",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -829,6 +815,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 0,
"nbabsjust": 0,
@@ -845,27 +845,13 @@
"rang": "11 ex",
"civilite_str": "M.",
"nom_disp": "ROUSSET",
- "prenom": "DERC'HEN",
+ "prenom": "Derc'hen",
"nom_short": "ROUSSET De.",
"partitions": {
"1": 1
},
"sort_key": "rousset;derchen",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -889,6 +875,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 0,
"nbabsjust": 0,
@@ -905,27 +905,13 @@
"rang": "11 ex",
"civilite_str": "",
"nom_disp": "MORAND",
- "prenom": "CAMILLE",
+ "prenom": "Camille",
"nom_short": "MORAND Ca.",
"partitions": {
"1": 1
},
"sort_key": "morand;camille",
"moy_gen": "",
- "moy_ue_1": "",
- "moy_res_1_1": "",
- "moy_res_3_1": "",
- "moy_res_4_1": "",
- "moy_res_5_1": "",
- "moy_res_6_1": "",
- "moy_res_18_1": "",
- "moy_res_10_1": "",
- "moy_res_11_1": "",
- "moy_res_20_1": "",
- "moy_res_12_1": "",
- "moy_res_13_1": "",
- "moy_sae_2_1": "",
- "moy_sae_7_1": "",
"moy_ue_2": "",
"moy_res_1_2": "",
"moy_res_4_2": "",
@@ -949,6 +935,20 @@
"moy_res_21_3": "",
"moy_sae_14_3": "",
"moy_sae_15_3": "",
+ "moy_ue_1": "",
+ "moy_res_1_1": "",
+ "moy_res_3_1": "",
+ "moy_res_4_1": "",
+ "moy_res_5_1": "",
+ "moy_res_6_1": "",
+ "moy_res_18_1": "",
+ "moy_res_10_1": "",
+ "moy_res_11_1": "",
+ "moy_res_20_1": "",
+ "moy_res_12_1": "",
+ "moy_res_13_1": "",
+ "moy_sae_2_1": "",
+ "moy_sae_7_1": "",
"ues_validables": "",
"nbabs": 1,
"nbabsjust": 0,
--
GitLab