forked from ScoDoc/ScoDoc
optimisation migration abs to assiduites (WIP)
This commit is contained in:
parent
e18990d804
commit
53c9658ce1
@ -81,13 +81,11 @@ class Assiduite(db.Model):
|
|||||||
) -> object or int:
|
) -> object or int:
|
||||||
"""Créer une nouvelle assiduité pour l'étudiant"""
|
"""Créer une nouvelle assiduité pour l'étudiant"""
|
||||||
# Vérification de non duplication des périodes
|
# Vérification de non duplication des périodes
|
||||||
assiduites: list[Assiduite] = etud.assiduites.all()
|
assiduites: list[Assiduite] = etud.assiduites
|
||||||
|
if is_period_conflicting(date_debut, date_fin, assiduites, Assiduite):
|
||||||
if is_period_conflicting(date_debut, date_fin, assiduites):
|
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
|
"Duplication des assiduités (la période rentrée rentre en conflit avec une assiduité enregistrée)"
|
||||||
)
|
)
|
||||||
|
|
||||||
if moduleimpl is not None:
|
if moduleimpl is not None:
|
||||||
# Vérification de l'existence du module pour l'étudiant
|
# Vérification de l'existence du module pour l'étudiant
|
||||||
if moduleimpl.est_inscrit(etud):
|
if moduleimpl.est_inscrit(etud):
|
||||||
@ -114,6 +112,32 @@ class Assiduite(db.Model):
|
|||||||
|
|
||||||
return nouv_assiduite
|
return nouv_assiduite
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fast_create_assiduite(
|
||||||
|
cls,
|
||||||
|
etudid: int,
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
etat: EtatAssiduite,
|
||||||
|
moduleimpl_id: int = None,
|
||||||
|
description: str = None,
|
||||||
|
entry_date: datetime = None,
|
||||||
|
) -> object or int:
|
||||||
|
"""Créer une nouvelle assiduité pour l'étudiant"""
|
||||||
|
# Vérification de non duplication des périodes
|
||||||
|
|
||||||
|
nouv_assiduite = Assiduite(
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
etat=etat,
|
||||||
|
etudid=etudid,
|
||||||
|
moduleimpl_id=moduleimpl_id,
|
||||||
|
desc=description,
|
||||||
|
entry_date=entry_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nouv_assiduite
|
||||||
|
|
||||||
|
|
||||||
class Justificatif(db.Model):
|
class Justificatif(db.Model):
|
||||||
"""
|
"""
|
||||||
@ -185,8 +209,8 @@ class Justificatif(db.Model):
|
|||||||
) -> object or int:
|
) -> object or int:
|
||||||
"""Créer un nouveau justificatif pour l'étudiant"""
|
"""Créer un nouveau justificatif pour l'étudiant"""
|
||||||
# Vérification de non duplication des périodes
|
# Vérification de non duplication des périodes
|
||||||
justificatifs: list[Justificatif] = etud.justificatifs.all()
|
justificatifs: list[Justificatif] = etud.justificatifs
|
||||||
if is_period_conflicting(date_debut, date_fin, justificatifs):
|
if is_period_conflicting(date_debut, date_fin, justificatifs, Justificatif):
|
||||||
raise ScoValueError(
|
raise ScoValueError(
|
||||||
"Duplication des justificatifs (la période rentrée rentre en conflit avec un justificatif enregistré)"
|
"Duplication des justificatifs (la période rentrée rentre en conflit avec un justificatif enregistré)"
|
||||||
)
|
)
|
||||||
@ -202,11 +226,35 @@ class Justificatif(db.Model):
|
|||||||
|
|
||||||
return nouv_justificatif
|
return nouv_justificatif
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fast_create_justificatif(
|
||||||
|
cls,
|
||||||
|
etudid: int,
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
etat: EtatJustificatif,
|
||||||
|
raison: str = None,
|
||||||
|
entry_date: datetime = None,
|
||||||
|
) -> object or int:
|
||||||
|
"""Créer un nouveau justificatif pour l'étudiant"""
|
||||||
|
|
||||||
|
nouv_justificatif = Justificatif(
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
etat=etat,
|
||||||
|
etudid=etudid,
|
||||||
|
raison=raison,
|
||||||
|
entry_date=entry_date,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nouv_justificatif
|
||||||
|
|
||||||
|
|
||||||
def is_period_conflicting(
|
def is_period_conflicting(
|
||||||
date_debut: datetime,
|
date_debut: datetime,
|
||||||
date_fin: datetime,
|
date_fin: datetime,
|
||||||
collection: list[Assiduite or Justificatif],
|
collection: list[Assiduite or Justificatif],
|
||||||
|
collection_cls: Assiduite or Justificatif,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Vérifie si une date n'entre pas en collision
|
Vérifie si une date n'entre pas en collision
|
||||||
@ -215,12 +263,15 @@ def is_period_conflicting(
|
|||||||
|
|
||||||
date_debut = localize_datetime(date_debut)
|
date_debut = localize_datetime(date_debut)
|
||||||
date_fin = localize_datetime(date_fin)
|
date_fin = localize_datetime(date_fin)
|
||||||
unified = [
|
|
||||||
uni
|
|
||||||
for uni in collection
|
|
||||||
if is_period_overlapping(
|
|
||||||
(date_debut, date_fin), (uni.date_debut, uni.date_fin), bornes=False
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
return len(unified) != 0
|
if (
|
||||||
|
collection.filter_by(date_debut=date_debut, date_fin=date_fin).first()
|
||||||
|
is not None
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
|
||||||
|
count: int = collection.filter(
|
||||||
|
collection_cls.date_debut < date_fin, collection_cls.date_fin > date_debut
|
||||||
|
).count()
|
||||||
|
|
||||||
|
return count > 0
|
||||||
|
43
app/profiler.py
Normal file
43
app/profiler.py
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
from time import time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Profiler:
|
||||||
|
OUTPUT: str = "/tmp/scodoc.profiler.csv"
|
||||||
|
|
||||||
|
def __init__(self, tag: str) -> None:
|
||||||
|
self.tag: str = tag
|
||||||
|
self.start_time: time = None
|
||||||
|
self.stop_time: time = None
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.start_time = time()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.stop_time = time()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def elapsed(self) -> float:
|
||||||
|
return self.stop_time - self.start_time
|
||||||
|
|
||||||
|
def dates(self) -> tuple[datetime, datetime]:
|
||||||
|
return datetime.fromtimestamp(self.start_time), datetime.fromtimestamp(
|
||||||
|
self.stop_time
|
||||||
|
)
|
||||||
|
|
||||||
|
def write(self):
|
||||||
|
with open(Profiler.OUTPUT, "a") as file:
|
||||||
|
dates: tuple = self.dates()
|
||||||
|
date_str = (dates[0].isoformat(), dates[1].isoformat())
|
||||||
|
file.write(f"\n{self.tag},{self.elapsed() : .2}")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def write_in(cls, msg: str):
|
||||||
|
with open(cls.OUTPUT, "a") as file:
|
||||||
|
file.write(f"\n# {msg}")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def clear(cls):
|
||||||
|
with open(cls.OUTPUT, "w") as file:
|
||||||
|
file.write("")
|
@ -39,6 +39,7 @@ from hashlib import md5
|
|||||||
import numbers
|
import numbers
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
from shutil import get_terminal_size
|
||||||
import _thread
|
import _thread
|
||||||
import time
|
import time
|
||||||
import unicodedata
|
import unicodedata
|
||||||
@ -88,6 +89,60 @@ ETATS_INSCRIPTION = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def printProgressBar(
|
||||||
|
iteration,
|
||||||
|
total,
|
||||||
|
prefix="",
|
||||||
|
suffix="",
|
||||||
|
finish_msg="",
|
||||||
|
decimals=1,
|
||||||
|
length=100,
|
||||||
|
fill="█",
|
||||||
|
autosize=False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Affiche une progress bar à un point donné (mettre dans une boucle pour rendre dynamique)
|
||||||
|
@params:
|
||||||
|
iteration - Required : index du point donné (Int)
|
||||||
|
total - Required : nombre total avant complétion (eg: len(List))
|
||||||
|
prefix - Optional : Préfix -> écrit à gauche de la barre (Str)
|
||||||
|
suffix - Optional : Suffix -> écrit à droite de la barre (Str)
|
||||||
|
decimals - Optional : nombres de chiffres après la virgule (Int)
|
||||||
|
length - Optional : taille de la barre en nombre de caractères (Int)
|
||||||
|
fill - Optional : charactère de remplissange de la barre (Str)
|
||||||
|
autosize - Optional : Choisir automatiquement la taille de la barre en fonction du terminal (Bool)
|
||||||
|
"""
|
||||||
|
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
|
||||||
|
color = ProgressBarColors.RED
|
||||||
|
if 50 >= float(percent) > 25:
|
||||||
|
color = ProgressBarColors.MAGENTA
|
||||||
|
if 75 >= float(percent) > 50:
|
||||||
|
color = ProgressBarColors.BLUE
|
||||||
|
if 90 >= float(percent) > 75:
|
||||||
|
color = ProgressBarColors.CYAN
|
||||||
|
if 100 >= float(percent) > 90:
|
||||||
|
color = ProgressBarColors.GREEN
|
||||||
|
styling = f"{prefix} |{fill}| {percent}% {suffix}"
|
||||||
|
if autosize:
|
||||||
|
cols, _ = get_terminal_size(fallback=(length, 1))
|
||||||
|
length = cols - len(styling)
|
||||||
|
filledLength = int(length * iteration // total)
|
||||||
|
bar = fill * filledLength + "-" * (length - filledLength)
|
||||||
|
print(f"\r{color}{styling.replace(fill, bar)}{ProgressBarColors.RESET}", end="\r")
|
||||||
|
# Affiche une nouvelle ligne vide
|
||||||
|
if iteration == total:
|
||||||
|
print(f"\n{finish_msg}")
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressBarColors:
|
||||||
|
BLUE = "\033[94m"
|
||||||
|
CYAN = "\033[96m"
|
||||||
|
GREEN = "\033[92m"
|
||||||
|
MAGENTA = "\033[95m"
|
||||||
|
RED = "\033[91m"
|
||||||
|
RESET = "\033[0m"
|
||||||
|
|
||||||
|
|
||||||
class BiDirectionalEnum(Enum):
|
class BiDirectionalEnum(Enum):
|
||||||
"""Permet la recherche inverse d'un enum
|
"""Permet la recherche inverse d'un enum
|
||||||
Condition : les clés et les valeurs doivent être uniques
|
Condition : les clés et les valeurs doivent être uniques
|
||||||
|
@ -1,77 +1,33 @@
|
|||||||
# Script de migration des données de la base "absences" -> "assiduites"/"justificatifs"
|
# Script de migration des données de la base "absences" -> "assiduites"/"justificatifs"
|
||||||
import shutil
|
|
||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
|
from app.profiler import Profiler
|
||||||
from app.models import (
|
from app.models import (
|
||||||
Assiduite,
|
Assiduite,
|
||||||
Justificatif,
|
Justificatif,
|
||||||
Absence,
|
Absence,
|
||||||
Identite,
|
Identite,
|
||||||
ModuleImpl,
|
ModuleImplInscription,
|
||||||
Departement,
|
Departement,
|
||||||
)
|
)
|
||||||
from app.scodoc.sco_utils import EtatAssiduite, EtatJustificatif, localize_datetime
|
from app.scodoc.sco_utils import (
|
||||||
|
EtatAssiduite,
|
||||||
|
EtatJustificatif,
|
||||||
|
localize_datetime,
|
||||||
|
ProgressBarColors,
|
||||||
|
printProgressBar,
|
||||||
|
)
|
||||||
from datetime import time, datetime, date
|
from datetime import time, datetime, date
|
||||||
|
from json import dump
|
||||||
|
|
||||||
|
|
||||||
class glob:
|
class _glob:
|
||||||
DUPLICATIONS_ASSIDUITES: dict[tuple[date, bool, int], Assiduite] = {}
|
DUPLICATIONS_ASSIDUITES: dict[tuple[date, bool, int], Assiduite] = {}
|
||||||
|
DUPLICATIONS_JUSTIFICATIFS: dict[tuple[date, bool, int], Justificatif] = {}
|
||||||
DUPLICATED: list[Justificatif] = []
|
DUPLICATED: list[Justificatif] = []
|
||||||
|
PROBLEMS: dict[int, list[str]] = {}
|
||||||
|
CURRENT_ETU: list = []
|
||||||
class bcolors:
|
MODULES: list[tuple[int, int]] = []
|
||||||
BLUE = "\033[94m"
|
COMPTE: list[int, int] = []
|
||||||
CYAN = "\033[96m"
|
|
||||||
GREEN = "\033[92m"
|
|
||||||
MAGENTA = "\033[95m"
|
|
||||||
RED = "\033[91m"
|
|
||||||
RESET = "\033[0m"
|
|
||||||
|
|
||||||
|
|
||||||
def printProgressBar(
|
|
||||||
iteration,
|
|
||||||
total,
|
|
||||||
prefix="",
|
|
||||||
suffix="",
|
|
||||||
finish_msg="",
|
|
||||||
decimals=1,
|
|
||||||
length=100,
|
|
||||||
fill="█",
|
|
||||||
autosize=False,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Affiche une progress bar à un point donné (mettre dans une boucle pour rendre dynamique)
|
|
||||||
@params:
|
|
||||||
iteration - Required : index du point donné (Int)
|
|
||||||
total - Required : nombre total avant complétion (eg: len(List))
|
|
||||||
prefix - Optional : Préfix -> écrit à gauche de la barre (Str)
|
|
||||||
suffix - Optional : Suffix -> écrit à droite de la barre (Str)
|
|
||||||
decimals - Optional : nombres de chiffres après la virgule (Int)
|
|
||||||
length - Optional : taille de la barre en nombre de caractères (Int)
|
|
||||||
fill - Optional : charactère de remplissange de la barre (Str)
|
|
||||||
autosize - Optional : Choisir automatiquement la taille de la barre en fonction du terminal (Bool)
|
|
||||||
"""
|
|
||||||
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
|
|
||||||
color = bcolors.RED
|
|
||||||
if 50 > float(percent) > 25:
|
|
||||||
color = bcolors.MAGENTA
|
|
||||||
if 75 > float(percent) > 50:
|
|
||||||
color = bcolors.BLUE
|
|
||||||
if 90 > float(percent) > 75:
|
|
||||||
color = bcolors.CYAN
|
|
||||||
if 100 >= float(percent) > 90:
|
|
||||||
color = bcolors.GREEN
|
|
||||||
styling = f"{prefix} |{fill}| {percent}% {suffix}"
|
|
||||||
if autosize:
|
|
||||||
cols, _ = shutil.get_terminal_size(fallback=(length, 1))
|
|
||||||
length = cols - len(styling)
|
|
||||||
filledLength = int(length * iteration // total)
|
|
||||||
bar = fill * filledLength + "-" * (length - filledLength)
|
|
||||||
print(f"\r{color}{styling.replace(fill, bar)}{bcolors.RESET}", end="\r")
|
|
||||||
# Affiche une nouvelle ligne vide
|
|
||||||
if iteration == total:
|
|
||||||
print(f"\n{finish_msg}")
|
|
||||||
|
|
||||||
|
|
||||||
def migrate_abs_to_assiduites(
|
def migrate_abs_to_assiduites(
|
||||||
@ -95,6 +51,11 @@ def migrate_abs_to_assiduites(
|
|||||||
.entry_date: datetime -> timestamp d'entrée de l'abs
|
.entry_date: datetime -> timestamp d'entrée de l'abs
|
||||||
.etudid: relation -> Identite
|
.etudid: relation -> Identite
|
||||||
"""
|
"""
|
||||||
|
Profiler.clear()
|
||||||
|
|
||||||
|
time_elapsed: Profiler = Profiler("migration")
|
||||||
|
time_elapsed.start()
|
||||||
|
|
||||||
if morning is None:
|
if morning is None:
|
||||||
pref_time_morning = time(8, 0)
|
pref_time_morning = time(8, 0)
|
||||||
else:
|
else:
|
||||||
@ -115,42 +76,77 @@ def migrate_abs_to_assiduites(
|
|||||||
|
|
||||||
absences_query = Absence.query
|
absences_query = Absence.query
|
||||||
if dept is not None:
|
if dept is not None:
|
||||||
depts_id = [dep.id for dep in Departement.query.filter_by(acronym=dept).all()]
|
|
||||||
absences_query = absences_query.filter(Absence.etudid.in_(depts_id))
|
|
||||||
absences: list[Absence] = absences_query.order_by(Absence.jour).all()
|
|
||||||
|
|
||||||
glob.DUPLICATED = []
|
dept: Departement = Departement.query.filter_by(acronym=dept).first()
|
||||||
glob.DUPLICATIONS_ASSIDUITES = {}
|
if dept is not None:
|
||||||
|
etuds_id: list[int] = [etud.id for etud in dept.etudiants]
|
||||||
|
absences_query = absences_query.filter(Absence.etudid.in_(etuds_id))
|
||||||
|
absences: Absence = absences_query.order_by(Absence.etudid)
|
||||||
|
|
||||||
absences_len: int = len(absences)
|
_glob.DUPLICATED = []
|
||||||
|
_glob.DUPLICATIONS_ASSIDUITES = {}
|
||||||
|
_glob.DUPLICATIONS_JUSTIFICATIFS = {}
|
||||||
|
_glob.PROBLEMS = {}
|
||||||
|
_glob.CURRENT_ETU = []
|
||||||
|
_glob.MODULES = []
|
||||||
|
_glob.COMPTE = [0, 0]
|
||||||
|
|
||||||
|
absences_len: int = absences.count()
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"{ProgressBarColors.BLUE}{absences_len} absences vont être migrées{ProgressBarColors.RESET}"
|
||||||
|
)
|
||||||
|
|
||||||
printProgressBar(0, absences_len, "Progression", "effectué", autosize=True)
|
printProgressBar(0, absences_len, "Progression", "effectué", autosize=True)
|
||||||
|
|
||||||
for i, abs in enumerate(absences):
|
for i, abs in enumerate(absences):
|
||||||
|
try:
|
||||||
if abs.estabs:
|
if abs.estabs:
|
||||||
generated = _from_abs_to_assiduite(
|
generated = _from_abs_to_assiduite(
|
||||||
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
||||||
)
|
)
|
||||||
if not isinstance(generated, str):
|
if not isinstance(generated, str):
|
||||||
db.session.add(generated)
|
db.session.add(generated)
|
||||||
|
_glob.COMPTE[0] += 1
|
||||||
|
except Exception as e:
|
||||||
|
if abs.id not in _glob.PROBLEMS:
|
||||||
|
_glob.PROBLEMS[abs.id] = []
|
||||||
|
_glob.PROBLEMS[abs.id].append(e.args[0])
|
||||||
|
|
||||||
if abs.estjust:
|
try:
|
||||||
generated = _from_abs_to_justificatif(
|
if abs.estjust:
|
||||||
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
generated = _from_abs_to_justificatif(
|
||||||
|
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
||||||
|
)
|
||||||
|
if not isinstance(generated, str):
|
||||||
|
db.session.add(generated)
|
||||||
|
_glob.COMPTE[1] += 1
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
if abs.id not in _glob.PROBLEMS:
|
||||||
|
_glob.PROBLEMS[abs.id] = []
|
||||||
|
_glob.PROBLEMS[abs.id].append(e.args[0])
|
||||||
|
|
||||||
|
if i % 10 == 0:
|
||||||
|
printProgressBar(
|
||||||
|
i,
|
||||||
|
absences_len,
|
||||||
|
"Progression",
|
||||||
|
"effectué",
|
||||||
|
autosize=True,
|
||||||
)
|
)
|
||||||
if not isinstance(generated, str):
|
|
||||||
db.session.add(generated)
|
|
||||||
|
|
||||||
printProgressBar(
|
if i % 1000 == 0:
|
||||||
i,
|
printProgressBar(
|
||||||
absences_len,
|
i,
|
||||||
"Progression",
|
absences_len,
|
||||||
"effectué",
|
"Progression",
|
||||||
autosize=True,
|
"effectué",
|
||||||
)
|
autosize=True,
|
||||||
|
)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
dup_assi = glob.DUPLICATED
|
dup_assi = _glob.DUPLICATED
|
||||||
assi: Assiduite
|
assi: Assiduite
|
||||||
for assi in dup_assi:
|
for assi in dup_assi:
|
||||||
assi.moduleimpl_id = None
|
assi.moduleimpl_id = None
|
||||||
@ -164,9 +160,28 @@ def migrate_abs_to_assiduites(
|
|||||||
"Progression",
|
"Progression",
|
||||||
"effectué",
|
"effectué",
|
||||||
autosize=True,
|
autosize=True,
|
||||||
finish_msg=f"{bcolors.GREEN}Les absences ont bien été migrées.{bcolors.RESET}",
|
finish_msg=f"{ProgressBarColors.GREEN}Les absences ont bien été migrées.{ProgressBarColors.RESET}",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
time_elapsed.stop()
|
||||||
|
print(
|
||||||
|
f"{ProgressBarColors.GREEN}La migration a pris {time_elapsed.elapsed():.2f} secondes {ProgressBarColors.RESET}"
|
||||||
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"{ProgressBarColors.RED}Il y a eu {len(_glob.PROBLEMS)} absences qui n'ont pas pu être migrée."
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"Vous retrouverez un fichier json {ProgressBarColors.GREEN}/tmp/scodoc_migration_abs.json{ProgressBarColors.RED} contenant les ids des absences ainsi que les erreurs liées."
|
||||||
|
)
|
||||||
|
with open("/tmp/scodoc_migration_abs.json", "w", encoding="utf-8") as file:
|
||||||
|
dump(_glob.PROBLEMS, file)
|
||||||
|
|
||||||
|
print(
|
||||||
|
f"{ProgressBarColors.CYAN}{_glob.COMPTE[0]} assiduités et {_glob.COMPTE[1]} justificatifs ont été générés.{ProgressBarColors.RESET}"
|
||||||
|
)
|
||||||
|
# afficher nombre justificatifs généré par rapport au nombre de justificatifs
|
||||||
|
|
||||||
|
|
||||||
def _from_abs_to_assiduite(
|
def _from_abs_to_assiduite(
|
||||||
_abs: Absence, morning: time, noon: time, evening: time
|
_abs: Absence, morning: time, noon: time, evening: time
|
||||||
@ -174,6 +189,7 @@ def _from_abs_to_assiduite(
|
|||||||
etat = EtatAssiduite.ABSENT
|
etat = EtatAssiduite.ABSENT
|
||||||
date_deb: datetime = None
|
date_deb: datetime = None
|
||||||
date_fin: datetime = None
|
date_fin: datetime = None
|
||||||
|
|
||||||
if _abs.matin:
|
if _abs.matin:
|
||||||
date_deb = datetime.combine(_abs.jour, morning)
|
date_deb = datetime.combine(_abs.jour, morning)
|
||||||
date_fin = datetime.combine(_abs.jour, noon)
|
date_fin = datetime.combine(_abs.jour, noon)
|
||||||
@ -183,37 +199,54 @@ def _from_abs_to_assiduite(
|
|||||||
|
|
||||||
date_deb = localize_datetime(date_deb)
|
date_deb = localize_datetime(date_deb)
|
||||||
date_fin = localize_datetime(date_fin)
|
date_fin = localize_datetime(date_fin)
|
||||||
duplicata: Assiduite = glob.DUPLICATIONS_ASSIDUITES.get(
|
|
||||||
|
duplicata: Assiduite = _glob.DUPLICATIONS_ASSIDUITES.get(
|
||||||
(_abs.jour, _abs.matin, _abs.etudid)
|
(_abs.jour, _abs.matin, _abs.etudid)
|
||||||
)
|
)
|
||||||
if duplicata is not None:
|
if duplicata is not None:
|
||||||
glob.DUPLICATED.append(duplicata)
|
_glob.DUPLICATED.append(duplicata)
|
||||||
return "Duplicated"
|
return "Duplicated"
|
||||||
|
|
||||||
desc: str = _abs.description
|
desc: str = _abs.description
|
||||||
entry_date: datetime = _abs.entry_date
|
entry_date: datetime = _abs.entry_date
|
||||||
|
|
||||||
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
if _abs.etudid not in _glob.CURRENT_ETU:
|
||||||
moduleimpl: ModuleImpl = ModuleImpl.query.filter_by(id=_abs.moduleimpl_id).first()
|
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
||||||
|
if etud is None:
|
||||||
|
return "No Etud"
|
||||||
|
_glob.CURRENT_ETU.append(_abs.etudid)
|
||||||
|
|
||||||
retour = Assiduite.create_assiduite(
|
moduleimpl_id: int = _abs.moduleimpl_id
|
||||||
etud=etud,
|
|
||||||
|
if (
|
||||||
|
moduleimpl_id is not None
|
||||||
|
and (_abs.etudid, _abs.moduleimpl_id) not in _glob.MODULES
|
||||||
|
):
|
||||||
|
moduleimpl_inscription: ModuleImplInscription = (
|
||||||
|
ModuleImplInscription.query.filter_by(
|
||||||
|
moduleimpl_id=_abs.moduleimpl_id, etudid=_abs.etudid
|
||||||
|
).first()
|
||||||
|
)
|
||||||
|
if moduleimpl_inscription is None:
|
||||||
|
raise Exception("Moduleimpl_id incorrect ou étudiant non inscrit")
|
||||||
|
|
||||||
|
retour = Assiduite.fast_create_assiduite(
|
||||||
|
etudid=_abs.etudid,
|
||||||
date_debut=date_deb,
|
date_debut=date_deb,
|
||||||
date_fin=date_fin,
|
date_fin=date_fin,
|
||||||
etat=etat,
|
etat=etat,
|
||||||
moduleimpl=moduleimpl,
|
moduleimpl_id=moduleimpl_id,
|
||||||
description=desc,
|
description=desc,
|
||||||
entry_date=entry_date,
|
entry_date=entry_date,
|
||||||
)
|
)
|
||||||
|
_glob.DUPLICATIONS_ASSIDUITES[(_abs.jour, _abs.matin, _abs.etudid)] = retour
|
||||||
glob.DUPLICATIONS_ASSIDUITES[(_abs.jour, _abs.matin, _abs.etudid)] = retour
|
|
||||||
|
|
||||||
return retour
|
return retour
|
||||||
|
|
||||||
|
|
||||||
def _from_abs_to_justificatif(
|
def _from_abs_to_justificatif(
|
||||||
_abs: Absence, morning: time, noon: time, evening: time
|
_abs: Absence, morning: time, noon: time, evening: time
|
||||||
) -> Justificatif:
|
) -> Justificatif:
|
||||||
|
|
||||||
etat = EtatJustificatif.VALIDE
|
etat = EtatJustificatif.VALIDE
|
||||||
date_deb: datetime = None
|
date_deb: datetime = None
|
||||||
date_fin: datetime = None
|
date_fin: datetime = None
|
||||||
@ -227,13 +260,23 @@ def _from_abs_to_justificatif(
|
|||||||
date_deb = localize_datetime(date_deb)
|
date_deb = localize_datetime(date_deb)
|
||||||
date_fin = localize_datetime(date_fin)
|
date_fin = localize_datetime(date_fin)
|
||||||
|
|
||||||
|
duplicata: Justificatif = _glob.DUPLICATIONS_JUSTIFICATIFS.get(
|
||||||
|
(_abs.jour, _abs.matin, _abs.etudid)
|
||||||
|
)
|
||||||
|
if duplicata is not None:
|
||||||
|
return "Duplicated"
|
||||||
|
|
||||||
desc: str = _abs.description
|
desc: str = _abs.description
|
||||||
entry_date: datetime = _abs.entry_date
|
entry_date: datetime = _abs.entry_date
|
||||||
|
|
||||||
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
if _abs.etudid not in _glob.CURRENT_ETU:
|
||||||
|
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
||||||
|
if etud is None:
|
||||||
|
return "No Etud"
|
||||||
|
_glob.CURRENT_ETU.append(_abs.etudid)
|
||||||
|
|
||||||
retour = Justificatif.create_justificatif(
|
retour = Justificatif.fast_create_justificatif(
|
||||||
etud=etud,
|
etudid=_abs.etudid,
|
||||||
date_debut=date_deb,
|
date_debut=date_deb,
|
||||||
date_fin=date_fin,
|
date_fin=date_fin,
|
||||||
etat=etat,
|
etat=etat,
|
||||||
@ -241,4 +284,5 @@ def _from_abs_to_justificatif(
|
|||||||
entry_date=entry_date,
|
entry_date=entry_date,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_glob.DUPLICATIONS_JUSTIFICATIFS[(_abs.jour, _abs.matin, _abs.etudid)] = retour
|
||||||
return retour
|
return retour
|
||||||
|
Loading…
Reference in New Issue
Block a user