forked from ScoDoc/ScoDoc
migration abs : fusion + cmd downgrade
This commit is contained in:
parent
21f57aab8f
commit
aa956f4530
|
@ -1,7 +1,8 @@
|
|||
from app.scodoc.sco_archives import BaseArchiver
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
from app.models import Identite, Departement
|
||||
from flask import g
|
||||
|
||||
from shutil import rmtree
|
||||
import os
|
||||
|
||||
|
||||
|
@ -106,3 +107,12 @@ class JustificatifArchiver(BaseArchiver):
|
|||
"""
|
||||
etud: Identite = Identite.query.filter_by(id=etudid).first()
|
||||
self.set_dept_id(etud.dept_id)
|
||||
|
||||
def remove_dept_archive(self, dept_id: int = None):
|
||||
self.set_dept_id(1)
|
||||
self.initialize()
|
||||
|
||||
if dept_id is None:
|
||||
rmtree(self.root, ignore_errors=True)
|
||||
else:
|
||||
rmtree(os.path.join(self.root, str(dept_id)), ignore_errors=True)
|
||||
|
|
24
scodoc.py
24
scodoc.py
|
@ -503,6 +503,30 @@ def migrate_abs_to_assiduites(
|
|||
tools.migrate_abs_to_assiduites(dept, morning, noon, evening)
|
||||
|
||||
|
||||
@app.cli.command()
|
||||
@click.option(
|
||||
"-d", "--dept", help="Restreint la suppression au dept sélectionné (ACRONYME)"
|
||||
)
|
||||
@click.option(
|
||||
"-a",
|
||||
"--assiduites",
|
||||
is_flag=True,
|
||||
help="Supprime les assiduités de scodoc",
|
||||
)
|
||||
@click.option(
|
||||
"-j",
|
||||
"--justificatifs",
|
||||
is_flag=True,
|
||||
help="Supprime les justificatifs de scodoc",
|
||||
)
|
||||
@with_appcontext
|
||||
def downgrade_assiduites_module(
|
||||
dept: str = None, assiduites: bool = False, justificatifs: bool = False
|
||||
):
|
||||
"""Supprime les assiduites et/ou les justificatifs de tous les départements ou du département sélectionné"""
|
||||
tools.downgrade_module(dept, assiduites, justificatifs)
|
||||
|
||||
|
||||
@app.cli.command()
|
||||
@click.argument("dept", default="")
|
||||
@with_appcontext
|
||||
|
|
|
@ -9,3 +9,4 @@ from tools.import_scodoc7_dept import import_scodoc7_dept
|
|||
from tools.migrate_scodoc7_archives import migrate_scodoc7_dept_archives
|
||||
from tools.migrate_scodoc7_logos import migrate_scodoc7_dept_logos
|
||||
from tools.migrate_abs_to_assiduites import migrate_abs_to_assiduites
|
||||
from tools.downgrade_assiduites import downgrade_module
|
||||
|
|
50
tools/downgrade_assiduites.py
Normal file
50
tools/downgrade_assiduites.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
from app import db
|
||||
from app.models import Justificatif, Assiduite, Departement
|
||||
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
||||
from app.scodoc.sco_utils import ProgressBarColors
|
||||
|
||||
|
||||
def downgrade_module(
|
||||
dept: str = None, assiduites: bool = False, justificatifs: bool = False
|
||||
):
|
||||
dept_etudid: list[int] = None
|
||||
dept_id: int = None
|
||||
|
||||
if dept is not None:
|
||||
departement: Departement = Departement.query.filter_by(acronym=dept).first()
|
||||
|
||||
assert departement is not None, "Le département n'existe pas."
|
||||
|
||||
dept_etudid = [etud.id for etud in departement.etudiants]
|
||||
dept_id = departement.id
|
||||
|
||||
if assiduites:
|
||||
_remove_assiduites(dept_etudid)
|
||||
|
||||
if justificatifs:
|
||||
_remove_justificatifs(dept_etudid)
|
||||
_remove_justificatifs_archive(dept_id)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
print(
|
||||
f"{ProgressBarColors.GREEN}Le module assiduité a bien été remis à zero.{ProgressBarColors.RESET}"
|
||||
)
|
||||
|
||||
|
||||
def _remove_assiduites(dept_etudid: str = None):
|
||||
if dept_etudid is None:
|
||||
Assiduite.query.delete()
|
||||
else:
|
||||
Assiduite.query.filter(Assiduite.etudid.in_(dept_etudid)).delete()
|
||||
|
||||
|
||||
def _remove_justificatifs(dept_etudid: str = None):
|
||||
if dept_etudid is None:
|
||||
Justificatif.query.delete()
|
||||
else:
|
||||
Justificatif.query.filter(Justificatif.etudid.in_(dept_etudid)).delete()
|
||||
|
||||
|
||||
def _remove_justificatifs_archive(dept_id: int = None):
|
||||
JustificatifArchiver().remove_dept_archive(dept_id)
|
|
@ -16,19 +16,113 @@ from app.scodoc.sco_utils import (
|
|||
ProgressBarColors,
|
||||
printProgressBar,
|
||||
)
|
||||
from datetime import time, datetime, date
|
||||
from datetime import time, datetime, date, timedelta
|
||||
from json import dump, dumps
|
||||
|
||||
from sqlalchemy import not_
|
||||
|
||||
|
||||
class _Merger:
|
||||
""""""
|
||||
|
||||
|
||||
class _glob:
|
||||
DUPLICATIONS_ASSIDUITES: dict[tuple[date, bool, int], Assiduite] = {}
|
||||
DUPLICATIONS_JUSTIFICATIFS: dict[tuple[date, bool, int], Justificatif] = {}
|
||||
DUPLICATED: list[Justificatif] = []
|
||||
PROBLEMS: dict[int, list[str]] = {}
|
||||
CURRENT_ETU: list = []
|
||||
MODULES: list[tuple[int, int]] = []
|
||||
COMPTE: list[int, int] = []
|
||||
ERR_ETU: list[int] = []
|
||||
MERGER: _Merger = None
|
||||
|
||||
MORNING: time = None
|
||||
NOON: time = None
|
||||
EVENING: time = None
|
||||
|
||||
|
||||
class _Merger:
|
||||
def __init__(self, abs: Absence) -> None:
|
||||
self.deb = (abs.jour, abs.matin)
|
||||
self.fin = (abs.jour, abs.matin)
|
||||
self.moduleimpl = abs.moduleimpl_id
|
||||
self.etudid = abs.etudid
|
||||
self.est_abs = abs.estabs
|
||||
self.est_just = abs.estjust
|
||||
self.raison = abs.description
|
||||
|
||||
def merge(self, abs: Absence) -> bool:
|
||||
|
||||
if self.etudid != abs.etudid:
|
||||
return False
|
||||
|
||||
# Cas d'une même absence enregistrée plusieurs fois
|
||||
if self.fin == (abs.jour, abs.matin):
|
||||
self.est_abs |= abs.estabs
|
||||
self.est_just |= abs.estjust
|
||||
self.moduleimpl = None
|
||||
else:
|
||||
if self.est_abs != abs.estabs or self.est_just != abs.estjust:
|
||||
return False
|
||||
|
||||
if self.fin[1]:
|
||||
if abs.jour != self.fin[0]:
|
||||
return False
|
||||
else:
|
||||
if abs.jour - timedelta(days=1) != self.fin[0]:
|
||||
return False
|
||||
|
||||
self.fin = (abs.jour, abs.matin)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _tuple_to_date(tuple, end=False):
|
||||
if tuple[1]:
|
||||
time_ = _glob.NOON if end else _glob.MORNING
|
||||
date_ = datetime.combine(tuple[0], time_)
|
||||
else:
|
||||
time_ = _glob.EVENING if end else _glob.NOON
|
||||
date_ = datetime.combine(tuple[0], time_)
|
||||
d = localize_datetime(date_)
|
||||
return d
|
||||
|
||||
def _to_justif(self):
|
||||
date_deb = _Merger._tuple_to_date(self.deb)
|
||||
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
||||
|
||||
retour = Justificatif.fast_create_justificatif(
|
||||
etudid=self.etudid,
|
||||
date_debut=date_deb,
|
||||
date_fin=date_fin,
|
||||
etat=EtatJustificatif.VALIDE,
|
||||
raison=self.raison,
|
||||
)
|
||||
return retour
|
||||
|
||||
def _to_assi(self):
|
||||
date_deb = _Merger._tuple_to_date(self.deb)
|
||||
date_fin = _Merger._tuple_to_date(self.fin, end=True)
|
||||
|
||||
retour = Assiduite.fast_create_assiduite(
|
||||
etudid=self.etudid,
|
||||
date_debut=date_deb,
|
||||
date_fin=date_fin,
|
||||
etat=EtatAssiduite.ABSENT,
|
||||
moduleimpl_id=self.moduleimpl,
|
||||
description=self.raison,
|
||||
)
|
||||
return retour
|
||||
|
||||
def export(self):
|
||||
objects = []
|
||||
if self.est_abs:
|
||||
_glob.COMPTE[0] += 1
|
||||
objects.append(self._to_assi())
|
||||
if self.est_just:
|
||||
_glob.COMPTE[1] += 1
|
||||
objects.append(self._to_justif())
|
||||
|
||||
db.session.add_all(objects)
|
||||
|
||||
|
||||
class _Statistics:
|
||||
|
@ -116,22 +210,22 @@ def migrate_abs_to_assiduites(
|
|||
time_elapsed.start()
|
||||
|
||||
if morning is None:
|
||||
pref_time_morning = time(8, 0)
|
||||
_glob.MORNING = time(8, 0)
|
||||
else:
|
||||
morning: list[str] = morning.split("h")
|
||||
pref_time_morning = time(int(morning[0]), int(morning[1]))
|
||||
_glob.MORNING = time(int(morning[0]), int(morning[1]))
|
||||
|
||||
if noon is None:
|
||||
pref_time_noon = time(12, 0)
|
||||
_glob.NOON = time(12, 0)
|
||||
else:
|
||||
noon: list[str] = noon.split("h")
|
||||
pref_time_noon = time(int(noon[0]), int(noon[1]))
|
||||
_glob.NOON = time(int(noon[0]), int(noon[1]))
|
||||
|
||||
if evening is None:
|
||||
pref_time_evening = time(18, 0)
|
||||
_glob.EVENING = time(18, 0)
|
||||
else:
|
||||
evening: list[str] = evening.split("h")
|
||||
pref_time_evening = time(int(evening[0]), int(evening[1]))
|
||||
_glob.EVENING = time(int(evening[0]), int(evening[1]))
|
||||
|
||||
absences_query = Absence.query
|
||||
if dept is not None:
|
||||
|
@ -140,7 +234,9 @@ def migrate_abs_to_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: Absence = absences_query.order_by(
|
||||
Absence.etudid, Absence.jour, not_(Absence.matin)
|
||||
)
|
||||
|
||||
_glob.DUPLICATED = []
|
||||
_glob.DUPLICATIONS_ASSIDUITES = {}
|
||||
|
@ -160,25 +256,7 @@ def migrate_abs_to_assiduites(
|
|||
|
||||
for i, abs in enumerate(absences):
|
||||
try:
|
||||
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)
|
||||
_glob.COMPTE[0] += 1
|
||||
except Exception as e:
|
||||
stats.add_problem(abs, e.args[0])
|
||||
|
||||
try:
|
||||
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)
|
||||
_glob.COMPTE[1] += 1
|
||||
|
||||
_from_abs_to_assiduite_justificatif(abs)
|
||||
except Exception as e:
|
||||
stats.add_problem(abs, e.args[0])
|
||||
|
||||
|
@ -225,12 +303,14 @@ def migrate_abs_to_assiduites(
|
|||
)
|
||||
|
||||
print(
|
||||
f"{ProgressBarColors.RED}{statistiques['total']} absences qui n'ont pas pu être migrée."
|
||||
f"{ProgressBarColors.RED}{statistiques['total']} absences qui n'ont pas pu être migrées."
|
||||
)
|
||||
print(
|
||||
f"Vous retrouverez un fichier json {ProgressBarColors.GREEN}/tmp/scodoc_migration_abs.json{ProgressBarColors.RED} contenant les problèmes de migrations"
|
||||
f"Vous retrouverez un fichier json {ProgressBarColors.GREEN}/opt/scodoc-data/log/scodoc_migration_abs.json{ProgressBarColors.RED} contenant les problèmes de migrations"
|
||||
)
|
||||
with open("/tmp/scodoc_migration_abs.json", "w", encoding="utf-8") as file:
|
||||
with open(
|
||||
"/opt/scodoc-data/log/scodoc_migration_abs.json", "w", encoding="utf-8"
|
||||
) as file:
|
||||
stats.export(file)
|
||||
|
||||
print(
|
||||
|
@ -240,32 +320,7 @@ def migrate_abs_to_assiduites(
|
|||
print(dumps(statistiques, indent=2))
|
||||
|
||||
|
||||
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 "Duplicata"
|
||||
|
||||
desc: str = _abs.description
|
||||
entry_date: datetime = _abs.entry_date
|
||||
def _from_abs_to_assiduite_justificatif(_abs: Absence):
|
||||
|
||||
if _abs.etudid not in _glob.CURRENT_ETU:
|
||||
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
||||
|
@ -273,73 +328,24 @@ def _from_abs_to_assiduite(
|
|||
raise Exception("Etudiant inexistant")
|
||||
_glob.CURRENT_ETU.append(_abs.etudid)
|
||||
|
||||
moduleimpl_id: int = _abs.moduleimpl_id
|
||||
if _abs.estabs:
|
||||
moduleimpl_id: int = _abs.moduleimpl_id
|
||||
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")
|
||||
|
||||
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_fin=date_fin,
|
||||
etat=etat,
|
||||
moduleimpl_id=moduleimpl_id,
|
||||
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)
|
||||
if _glob.MERGER is None:
|
||||
_glob.MERGER = _Merger(_abs)
|
||||
elif _glob.MERGER.merge(_abs):
|
||||
return True
|
||||
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: Justificatif = _glob.DUPLICATIONS_JUSTIFICATIFS.get(
|
||||
(_abs.jour, _abs.matin, _abs.etudid)
|
||||
)
|
||||
if duplicata is not None:
|
||||
return "Duplicated"
|
||||
|
||||
desc: str = _abs.description
|
||||
entry_date: datetime = _abs.entry_date
|
||||
|
||||
if _abs.etudid not in _glob.CURRENT_ETU:
|
||||
etud: Identite = Identite.query.filter_by(id=_abs.etudid).first()
|
||||
if etud is None:
|
||||
raise Exception("Etudiant inexistant")
|
||||
_glob.CURRENT_ETU.append(_abs.etudid)
|
||||
|
||||
retour = Justificatif.fast_create_justificatif(
|
||||
etudid=_abs.etudid,
|
||||
date_debut=date_deb,
|
||||
date_fin=date_fin,
|
||||
etat=etat,
|
||||
raison=desc,
|
||||
entry_date=entry_date,
|
||||
)
|
||||
|
||||
_glob.DUPLICATIONS_JUSTIFICATIFS[(_abs.jour, _abs.matin, _abs.etudid)] = retour
|
||||
return retour
|
||||
_glob.MERGER.export()
|
||||
_glob.MERGER = _Merger(_abs)
|
||||
|
|
Loading…
Reference in New Issue
Block a user