forked from ScoDoc/ScoDoc
EDT: gestion de plusieurs enseignants par évènement
This commit is contained in:
parent
96aaca9746
commit
6423baa34b
@ -192,15 +192,16 @@ class ConfigAssiduitesForm(FlaskForm):
|
|||||||
validators=[Optional(), check_ics_regexp],
|
validators=[Optional(), check_ics_regexp],
|
||||||
)
|
)
|
||||||
edt_ics_uid_field = StringField(
|
edt_ics_uid_field = StringField(
|
||||||
label="Champ contenant l'enseignant",
|
label="Champ contenant les enseignants",
|
||||||
description="""champ de l'évènement calendrier: DESCRIPTION, SUMMARY, ...""",
|
description="""champ de l'évènement calendrier: DESCRIPTION, SUMMARY, ...""",
|
||||||
validators=[Optional(), check_ics_field],
|
validators=[Optional(), check_ics_field],
|
||||||
)
|
)
|
||||||
edt_ics_uid_regexp = StringField(
|
edt_ics_uid_regexp = StringField(
|
||||||
label="Extraction de l'enseignant",
|
label="Extraction des enseignants",
|
||||||
description=r"""expression régulière python dont le premier groupe doit
|
description=r"""expression régulière python permettant d'extraire les
|
||||||
correspondre à l'identifiant (edt_id) de l'enseignant associé à l'évènement.
|
identifiants des enseignants associés à l'évènement.
|
||||||
Exemple: <tt>Enseignant : ([0-9]+)</tt>
|
(contrairement aux autres champs, il peut y avoir plusieurs enseignants par évènement.)
|
||||||
|
Exemple: <tt>[0-9]+</tt>
|
||||||
""",
|
""",
|
||||||
validators=[Optional(), check_ics_regexp],
|
validators=[Optional(), check_ics_regexp],
|
||||||
)
|
)
|
||||||
|
@ -132,7 +132,8 @@ def load_calendar(
|
|||||||
) from exc
|
) from exc
|
||||||
except FileNotFoundError as exc:
|
except FileNotFoundError as exc:
|
||||||
log(
|
log(
|
||||||
f"formsemestre_load_calendar: ics not found for {formsemestre or ''}\npath='{ics_filename}'"
|
f"""formsemestre_load_calendar: ics not found for {
|
||||||
|
formsemestre or ''}\npath='{ics_filename}'"""
|
||||||
)
|
)
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
f"Fichier ics introuvable (filename={ics_filename})"
|
f"Fichier ics introuvable (filename={ics_filename})"
|
||||||
@ -229,7 +230,8 @@ def formsemestre_edt_dict(
|
|||||||
scu.EMO_WARNING} {event['edt_module']}</span>"""
|
scu.EMO_WARNING} {event['edt_module']}</span>"""
|
||||||
bubble = "code module non trouvé dans ScoDoc. Vérifier configuration."
|
bubble = "code module non trouvé dans ScoDoc. Vérifier configuration."
|
||||||
case _: # module EDT bien retrouvé dans ScoDoc
|
case _: # module EDT bien retrouvé dans ScoDoc
|
||||||
bubble = f"{modimpl.module.abbrev or modimpl.module.titre or ''} ({event['edt_module']})"
|
bubble = f"""{modimpl.module.abbrev or modimpl.module.titre or ''
|
||||||
|
} ({event['edt_module']})"""
|
||||||
mod_disp = (
|
mod_disp = (
|
||||||
f"""<span class="mod-name mod-code">{modimpl.module.code}</span>"""
|
f"""<span class="mod-name mod-code">{modimpl.module.code}</span>"""
|
||||||
)
|
)
|
||||||
@ -249,20 +251,24 @@ def formsemestre_edt_dict(
|
|||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
ens_user_name = event["ens"].user_name if event["ens"] else None
|
ens_nomprenoms = (
|
||||||
ens_nomprenom = event["ens"].get_nomprenom() if event["ens"] else None
|
"(" + ", ".join([u.get_nomprenom() for u in event["users"]]) + ")"
|
||||||
|
if event["users"]
|
||||||
|
else ""
|
||||||
|
)
|
||||||
|
ens_user_names = (
|
||||||
|
",".join([u.user_name for u in event["users"]]) if event["users"] else ""
|
||||||
|
)
|
||||||
d = {
|
d = {
|
||||||
# Champs utilisés par tui.calendar
|
# Champs utilisés par tui.calendar
|
||||||
"calendarId": "cal1",
|
"calendarId": "cal1",
|
||||||
"title": f"""{title} {group_disp} {
|
"title": f"""{title} {group_disp} {ens_nomprenoms} {link_abs}""",
|
||||||
'('+ens_nomprenom+')' if ens_nomprenom else ''
|
|
||||||
} {link_abs}""",
|
|
||||||
"start": event["start"],
|
"start": event["start"],
|
||||||
"end": event["end"],
|
"end": event["end"],
|
||||||
"backgroundColor": event["group_bg_color"],
|
"backgroundColor": event["group_bg_color"],
|
||||||
# Infos brutes pour usage API éventuel
|
# Infos brutes pour usage API éventuel
|
||||||
"ens_edt": event["edt_ens"],
|
"edt_ens_ids": event["edt_ens_ids"],
|
||||||
"ens_user_name": ens_user_name,
|
"ens_user_names": ens_user_names,
|
||||||
"group_id": group.id if group else None,
|
"group_id": group.id if group else None,
|
||||||
"group_edt_id": event["edt_group"],
|
"group_edt_id": event["edt_group"],
|
||||||
"moduleimpl_id": modimpl.id if modimpl else None,
|
"moduleimpl_id": modimpl.id if modimpl else None,
|
||||||
@ -354,7 +360,7 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
if "DESCRIPTION" in event:
|
if "DESCRIPTION" in event:
|
||||||
# --- Titre de l'évènement
|
# --- Titre de l'évènement
|
||||||
title_edt = (
|
title_edt = (
|
||||||
extract_event_data(event, edt_ics_title_field, edt_ics_title_pattern)
|
extract_event_edt_id(event, edt_ics_title_field, edt_ics_title_pattern)
|
||||||
if edt_ics_title_pattern
|
if edt_ics_title_pattern
|
||||||
else "non configuré"
|
else "non configuré"
|
||||||
)
|
)
|
||||||
@ -362,7 +368,7 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
title = title_edt
|
title = title_edt
|
||||||
# --- Group
|
# --- Group
|
||||||
if edt_ics_group_pattern:
|
if edt_ics_group_pattern:
|
||||||
edt_group = extract_event_data(
|
edt_group = extract_event_edt_id(
|
||||||
event, edt_ics_group_field, edt_ics_group_pattern
|
event, edt_ics_group_field, edt_ics_group_pattern
|
||||||
)
|
)
|
||||||
edt_groups_ids.add(edt_group)
|
edt_groups_ids.add(edt_group)
|
||||||
@ -385,7 +391,7 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
|
|
||||||
# --- ModuleImpl
|
# --- ModuleImpl
|
||||||
if edt_ics_mod_pattern:
|
if edt_ics_mod_pattern:
|
||||||
edt_module = extract_event_data(
|
edt_module = extract_event_edt_id(
|
||||||
event, edt_ics_mod_field, edt_ics_mod_pattern
|
event, edt_ics_mod_field, edt_ics_mod_pattern
|
||||||
)
|
)
|
||||||
modimpl: ModuleImpl = edt2modimpl.get(edt_module, None)
|
modimpl: ModuleImpl = edt2modimpl.get(edt_module, None)
|
||||||
@ -394,19 +400,22 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
else:
|
else:
|
||||||
modimpl = False
|
modimpl = False
|
||||||
edt_module = ""
|
edt_module = ""
|
||||||
# --- Enseignant
|
# --- Enseignants
|
||||||
|
users: list[User] = []
|
||||||
if edt_ics_uid_pattern:
|
if edt_ics_uid_pattern:
|
||||||
edt_ens = extract_event_data(
|
ens_edt_ids = extract_event_edt_ids(
|
||||||
event, edt_ics_uid_field, edt_ics_uid_pattern
|
event, edt_ics_uid_field, edt_ics_uid_pattern
|
||||||
)
|
)
|
||||||
if edt_ens in edt2user:
|
for ens_edt_id in ens_edt_ids:
|
||||||
ens = edt2user[edt_ens]
|
if ens_edt_id in edt2user:
|
||||||
|
ens = edt2user[ens_edt_id]
|
||||||
else:
|
else:
|
||||||
ens = User.query.filter_by(edt_id=edt_ens).first()
|
ens = User.query.filter_by(edt_id=ens_edt_id).first()
|
||||||
edt2user[edt_ens] = ens
|
edt2user[ens_edt_id] = ens
|
||||||
|
if ens:
|
||||||
|
users.append(ens)
|
||||||
else:
|
else:
|
||||||
ens = None
|
ens_edt_ids = []
|
||||||
edt_ens = ""
|
|
||||||
#
|
#
|
||||||
events_sco.append(
|
events_sco.append(
|
||||||
{
|
{
|
||||||
@ -418,8 +427,8 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
"modimpl": modimpl, # False si extracteur non configuré
|
"modimpl": modimpl, # False si extracteur non configuré
|
||||||
"edt_module": edt_module, # id module edt non traduit
|
"edt_module": edt_module, # id module edt non traduit
|
||||||
# Enseignant
|
# Enseignant
|
||||||
"edt_ens": edt_ens, # id ens edt, non traduit
|
"edt_ens_ids": ens_edt_ids, # ids ens edt, normalisés mais non traduits
|
||||||
"ens": ens,
|
"users": users,
|
||||||
# heures pour saisie abs: en heure LOCALE DU SERVEUR
|
# heures pour saisie abs: en heure LOCALE DU SERVEUR
|
||||||
"heure_deb": event.decoded("dtstart")
|
"heure_deb": event.decoded("dtstart")
|
||||||
.replace(tzinfo=timezone.utc)
|
.replace(tzinfo=timezone.utc)
|
||||||
@ -437,14 +446,14 @@ def load_and_convert_ics(formsemestre: FormSemestre) -> tuple[list[dict], list[s
|
|||||||
return events_sco, sorted(edt_groups_ids)
|
return events_sco, sorted(edt_groups_ids)
|
||||||
|
|
||||||
|
|
||||||
def extract_event_data(
|
def extract_event_edt_id(
|
||||||
event: icalendar.cal.Event,
|
event: icalendar.cal.Event,
|
||||||
ics_field: str,
|
ics_field: str,
|
||||||
pattern: re.Pattern,
|
pattern: re.Pattern,
|
||||||
none_if_no_match=False,
|
none_if_no_match=False,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Extrait la chaine (id) de l'évènement et la normalise.
|
"""Extrait la chaine (id) de l'évènement et la normalise.
|
||||||
Si l'event n'a pas le champs: "-"
|
Si l'event n'a pas le champ: "-"
|
||||||
Si pas de match: None
|
Si pas de match: None
|
||||||
"""
|
"""
|
||||||
if not event.has_key(ics_field):
|
if not event.has_key(ics_field):
|
||||||
@ -457,6 +466,25 @@ def extract_event_data(
|
|||||||
return None if none_if_no_match else data
|
return None if none_if_no_match else data
|
||||||
|
|
||||||
|
|
||||||
|
def extract_event_edt_ids(
|
||||||
|
event: icalendar.cal.Event,
|
||||||
|
ics_field: str,
|
||||||
|
pattern: re.Pattern,
|
||||||
|
) -> list[str] | None:
|
||||||
|
"""Extrait les edt_id de l'évènement et les normalise.
|
||||||
|
Si l'event n'a pas le champ: None
|
||||||
|
Si pas de match: liste vide
|
||||||
|
Utilisé pour les enseignants uniquement.
|
||||||
|
"""
|
||||||
|
if not event.has_key(ics_field):
|
||||||
|
return
|
||||||
|
data = event.decoded(ics_field).decode("utf-8") # assume ics in utf8
|
||||||
|
matches = pattern.findall(data)
|
||||||
|
# nota: pattern may have zero or one group, so the result
|
||||||
|
# is a list of strings, not a list of matches
|
||||||
|
return [scu.normalize_edt_id(m) for m in matches if m]
|
||||||
|
|
||||||
|
|
||||||
def formsemestre_retreive_modimpls_from_edt_id(
|
def formsemestre_retreive_modimpls_from_edt_id(
|
||||||
formsemestre: FormSemestre,
|
formsemestre: FormSemestre,
|
||||||
) -> dict[str, ModuleImpl]:
|
) -> dict[str, ModuleImpl]:
|
||||||
|
@ -86,17 +86,23 @@ def generate_ens_calendars():
|
|||||||
nb_events += len(events)
|
nb_events += len(events)
|
||||||
ens: User | None = None
|
ens: User | None = None
|
||||||
for event in events:
|
for event in events:
|
||||||
edt_ens = sco_edt_cal.extract_event_data(
|
ens_edt_ids = sco_edt_cal.extract_event_edt_ids(
|
||||||
event, edt_ics_uid_field, edt_ics_uid_pattern, none_if_no_match=True
|
event, edt_ics_uid_field, edt_ics_uid_pattern
|
||||||
)
|
)
|
||||||
if edt_ens in edt2user:
|
users = []
|
||||||
ens = edt2user[edt_ens]
|
for ens_edt_id in ens_edt_ids:
|
||||||
|
if ens_edt_id in edt2user:
|
||||||
|
ens = edt2user[ens_edt_id]
|
||||||
else:
|
else:
|
||||||
ens = User.query.filter_by(edt_id=edt_ens).first()
|
ens = User.query.filter_by(edt_id=ens_edt_id).first()
|
||||||
edt2user[edt_ens] = ens
|
edt2user[ens_edt_id] = ens
|
||||||
if ens: # si l'utilisateur est reconnu
|
if ens:
|
||||||
event.add("X-ScoDoc-user", ens.user_name)
|
users.append(ens)
|
||||||
edt_by_uid[edt_ens].add_component(event)
|
edt_by_uid[ens_edt_id].add_component(event)
|
||||||
|
|
||||||
|
if users: # si un utilisateur est reconnu dans l'event
|
||||||
|
event.add("X-ScoDoc-users", ",".join([u.user_name for u in users]))
|
||||||
|
|
||||||
_write_user_calendars(edt_by_uid)
|
_write_user_calendars(edt_by_uid)
|
||||||
log(
|
log(
|
||||||
f"""generate_ens_calendars: done in {(time.time()-t0):g}s, processed {
|
f"""generate_ens_calendars: done in {(time.time()-t0):g}s, processed {
|
||||||
|
Loading…
Reference in New Issue
Block a user