245 lines
7.2 KiB
Python
245 lines
7.2 KiB
Python
# Script de migration des données de la base "absences" -> "assiduites"/"justificatifs"
|
|
import shutil
|
|
|
|
from app import db
|
|
|
|
from app.models import (
|
|
Assiduite,
|
|
Justificatif,
|
|
Absence,
|
|
Identite,
|
|
ModuleImpl,
|
|
Departement,
|
|
)
|
|
from app.scodoc.sco_utils import EtatAssiduite, EtatJustificatif, localize_datetime
|
|
from datetime import time, datetime, date
|
|
|
|
|
|
class glob:
|
|
DUPLICATIONS_ASSIDUITES: dict[tuple[date, bool, int], Assiduite] = {}
|
|
DUPLICATED: list[Justificatif] = []
|
|
|
|
|
|
class bcolors:
|
|
BLUE = "\033[94m"
|
|
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(
|
|
dept: str = "", morning: str = None, noon: str = None, evening: str = None
|
|
):
|
|
"""
|
|
une absence à 3 états:
|
|
|
|
|.estabs|.estjust|
|
|
|1|0| -> absence non justifiée
|
|
|1|1| -> absence justifiée
|
|
|0|1| -> justifié
|
|
|
|
dualité des temps :
|
|
|
|
.matin: bool (0:00 -> time_pref | time_pref->23:59:59)
|
|
.jour : date (jour de l'absence/justificatif)
|
|
.moduleimpl_id: relation -> moduleimpl_id
|
|
description:str -> motif abs / raision justif
|
|
|
|
.entry_date: datetime -> timestamp d'entrée de l'abs
|
|
.etudid: relation -> Identite
|
|
"""
|
|
if morning is None:
|
|
pref_time_morning = time(8, 0)
|
|
else:
|
|
morning: list[str] = morning.split("h")
|
|
pref_time_morning = time(int(morning[0]), int(morning[1]))
|
|
|
|
if noon is None:
|
|
pref_time_noon = time(12, 0)
|
|
else:
|
|
noon: list[str] = noon.split("h")
|
|
pref_time_noon = time(int(noon[0]), int(noon[1]))
|
|
|
|
if evening is None:
|
|
pref_time_evening = time(18, 0)
|
|
else:
|
|
evening: list[str] = evening.split("h")
|
|
pref_time_evening = time(int(evening[0]), int(evening[1]))
|
|
|
|
absences_query = Absence.query
|
|
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 = []
|
|
glob.DUPLICATIONS_ASSIDUITES = {}
|
|
|
|
absences_len: int = len(absences)
|
|
|
|
printProgressBar(0, absences_len, "Progression", "effectué", autosize=True)
|
|
|
|
for i, abs in enumerate(absences):
|
|
|
|
if abs.estabs:
|
|
generated = _from_abs_to_assiduite(
|
|
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
|
)
|
|
if not isinstance(generated, str):
|
|
db.session.add(generated)
|
|
|
|
if abs.estjust:
|
|
generated = _from_abs_to_justificatif(
|
|
abs, pref_time_morning, pref_time_noon, pref_time_evening
|
|
)
|
|
if not isinstance(generated, str):
|
|
db.session.add(generated)
|
|
|
|
printProgressBar(
|
|
i,
|
|
absences_len,
|
|
"Progression",
|
|
"effectué",
|
|
autosize=True,
|
|
)
|
|
|
|
dup_assi = glob.DUPLICATED
|
|
assi: Assiduite
|
|
for assi in dup_assi:
|
|
assi.moduleimpl_id = None
|
|
db.session.add(assi)
|
|
|
|
db.session.commit()
|
|
|
|
printProgressBar(
|
|
absences_len,
|
|
absences_len,
|
|
"Progression",
|
|
"effectué",
|
|
autosize=True,
|
|
finish_msg=f"{bcolors.GREEN}Les absences ont bien été migrées.{bcolors.RESET}",
|
|
)
|
|
|
|
|
|
def _from_abs_to_assiduite(
|
|
_abs: Absence, morning: time, noon: time, evening: time
|
|
) -> Assiduite:
|
|
etat = EtatAssiduite.ABSENT
|
|
date_deb: datetime = None
|
|
date_fin: datetime = None
|
|
if _abs.matin:
|
|
date_deb = datetime.combine(_abs.jour, morning)
|
|
date_fin = datetime.combine(_abs.jour, noon)
|
|
else:
|
|
date_deb = datetime.combine(_abs.jour, noon)
|
|
date_fin = datetime.combine(_abs.jour, evening)
|
|
|
|
date_deb = localize_datetime(date_deb)
|
|
date_fin = localize_datetime(date_fin)
|
|
duplicata: Assiduite = glob.DUPLICATIONS_ASSIDUITES.get(
|
|
(_abs.jour, _abs.matin, _abs.etudid)
|
|
)
|
|
if duplicata is not None:
|
|
glob.DUPLICATED.append(duplicata)
|
|
return "Duplicated"
|
|
|
|
desc: str = _abs.description
|
|
entry_date: datetime = _abs.entry_date
|
|
|
|
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
|
moduleimpl: ModuleImpl = ModuleImpl.query.filter_by(id=_abs.moduleimpl_id).first()
|
|
|
|
retour = Assiduite.create_assiduite(
|
|
etud=etud,
|
|
date_debut=date_deb,
|
|
date_fin=date_fin,
|
|
etat=etat,
|
|
moduleimpl=moduleimpl,
|
|
description=desc,
|
|
entry_date=entry_date,
|
|
)
|
|
|
|
glob.DUPLICATIONS_ASSIDUITES[(_abs.jour, _abs.matin, _abs.etudid)] = retour
|
|
|
|
return retour
|
|
|
|
|
|
def _from_abs_to_justificatif(
|
|
_abs: Absence, morning: time, noon: time, evening: time
|
|
) -> Justificatif:
|
|
etat = EtatJustificatif.VALIDE
|
|
date_deb: datetime = None
|
|
date_fin: datetime = None
|
|
if _abs.matin:
|
|
date_deb = datetime.combine(_abs.jour, morning)
|
|
date_fin = datetime.combine(_abs.jour, noon)
|
|
else:
|
|
date_deb = datetime.combine(_abs.jour, noon)
|
|
date_fin = datetime.combine(_abs.jour, evening)
|
|
|
|
date_deb = localize_datetime(date_deb)
|
|
date_fin = localize_datetime(date_fin)
|
|
|
|
desc: str = _abs.description
|
|
entry_date: datetime = _abs.entry_date
|
|
|
|
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
|
|
|
retour = Justificatif.create_justificatif(
|
|
etud=etud,
|
|
date_debut=date_deb,
|
|
date_fin=date_fin,
|
|
etat=etat,
|
|
raison=desc,
|
|
entry_date=entry_date,
|
|
)
|
|
|
|
return retour
|