Suppression ref. comp. et dept: cascades.

This commit is contained in:
Emmanuel Viennet 2023-02-09 11:56:20 +01:00
parent 2ce0968614
commit cd1e6aa73d
11 changed files with 508 additions and 52 deletions

View File

@ -53,7 +53,9 @@ class XMLModel:
class ApcReferentielCompetences(db.Model, XMLModel): class ApcReferentielCompetences(db.Model, XMLModel):
"Référentiel de compétence d'une spécialité" "Référentiel de compétence d'une spécialité"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
dept_id = db.Column(db.Integer, db.ForeignKey("departement.id"), index=True) dept_id = db.Column(
db.Integer, db.ForeignKey("departement.id", ondelete="CASCADE"), index=True
)
annexe = db.Column(db.Text()) # '1', '22', ... annexe = db.Column(db.Text()) # '1', '22', ...
specialite = db.Column(db.Text()) # 'CJ', 'RT', 'INFO', ... specialite = db.Column(db.Text()) # 'CJ', 'RT', 'INFO', ...
specialite_long = db.Column( specialite_long = db.Column(
@ -207,7 +209,9 @@ class ApcCompetence(db.Model, XMLModel):
"Compétence" "Compétence"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
referentiel_id = db.Column( referentiel_id = db.Column(
db.Integer, db.ForeignKey("apc_referentiel_competences.id"), nullable=False db.Integer,
db.ForeignKey("apc_referentiel_competences.id", ondelete="CASCADE"),
nullable=False,
) )
# les compétences dans Orébut sont identifiées par leur id unique # les compétences dans Orébut sont identifiées par leur id unique
# (mais id_orebut n'est pas unique car le même ref. pourra être chargé dans plusieurs depts) # (mais id_orebut n'est pas unique car le même ref. pourra être chargé dans plusieurs depts)
@ -276,7 +280,9 @@ class ApcSituationPro(db.Model, XMLModel):
"Situation professionnelle" "Situation professionnelle"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
competence_id = db.Column( competence_id = db.Column(
db.Integer, db.ForeignKey("apc_competence.id"), nullable=False db.Integer,
db.ForeignKey("apc_competence.id", ondelete="CASCADE"),
nullable=False,
) )
libelle = db.Column(db.Text(), nullable=False) libelle = db.Column(db.Text(), nullable=False)
# aucun attribut (le text devient le libellé) # aucun attribut (le text devient le libellé)
@ -288,7 +294,9 @@ class ApcComposanteEssentielle(db.Model, XMLModel):
"Composante essentielle" "Composante essentielle"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
competence_id = db.Column( competence_id = db.Column(
db.Integer, db.ForeignKey("apc_competence.id"), nullable=False db.Integer,
db.ForeignKey("apc_competence.id", ondelete="CASCADE"),
nullable=False,
) )
libelle = db.Column(db.Text(), nullable=False) libelle = db.Column(db.Text(), nullable=False)
@ -306,7 +314,9 @@ class ApcNiveau(db.Model, XMLModel):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
competence_id = db.Column( competence_id = db.Column(
db.Integer, db.ForeignKey("apc_competence.id"), nullable=False db.Integer,
db.ForeignKey("apc_competence.id", ondelete="CASCADE"),
nullable=False,
) )
libelle = db.Column(db.Text(), nullable=False) libelle = db.Column(db.Text(), nullable=False)
annee = db.Column(db.Text(), nullable=False) # "BUT1", "BUT2", "BUT3" annee = db.Column(db.Text(), nullable=False) # "BUT1", "BUT2", "BUT3"
@ -387,7 +397,7 @@ app_critiques_modules = db.Table(
), ),
db.Column( db.Column(
"app_crit_id", "app_crit_id",
db.ForeignKey("apc_app_critique.id"), db.ForeignKey("apc_app_critique.id", ondelete="CASCADE"),
primary_key=True, primary_key=True,
), ),
) )
@ -396,7 +406,9 @@ app_critiques_modules = db.Table(
class ApcAppCritique(db.Model, XMLModel): class ApcAppCritique(db.Model, XMLModel):
"Apprentissage Critique BUT" "Apprentissage Critique BUT"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
niveau_id = db.Column(db.Integer, db.ForeignKey("apc_niveau.id"), nullable=False) niveau_id = db.Column(
db.Integer, db.ForeignKey("apc_niveau.id", ondelete="CASCADE"), nullable=False
)
code = db.Column(db.Text(), nullable=False, index=True) code = db.Column(db.Text(), nullable=False, index=True)
libelle = db.Column(db.Text()) libelle = db.Column(db.Text())
@ -445,7 +457,10 @@ class ApcAppCritique(db.Model, XMLModel):
parcours_modules = db.Table( parcours_modules = db.Table(
"parcours_modules", "parcours_modules",
db.Column( db.Column(
"parcours_id", db.Integer, db.ForeignKey("apc_parcours.id"), primary_key=True "parcours_id",
db.Integer,
db.ForeignKey("apc_parcours.id", ondelete="CASCADE"),
primary_key=True,
), ),
db.Column( db.Column(
"module_id", "module_id",
@ -459,7 +474,10 @@ parcours_modules = db.Table(
parcours_formsemestre = db.Table( parcours_formsemestre = db.Table(
"parcours_formsemestre", "parcours_formsemestre",
db.Column( db.Column(
"parcours_id", db.Integer, db.ForeignKey("apc_parcours.id"), primary_key=True "parcours_id",
db.Integer,
db.ForeignKey("apc_parcours.id", ondelete="CASCADE"),
primary_key=True,
), ),
db.Column( db.Column(
"formsemestre_id", "formsemestre_id",
@ -475,7 +493,9 @@ class ApcParcours(db.Model, XMLModel):
"Un parcours BUT" "Un parcours BUT"
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
referentiel_id = db.Column( referentiel_id = db.Column(
db.Integer, db.ForeignKey("apc_referentiel_competences.id"), nullable=False db.Integer,
db.ForeignKey("apc_referentiel_competences.id", ondelete="CASCADE"),
nullable=False,
) )
numero = db.Column(db.Integer) # ordre de présentation numero = db.Column(db.Integer) # ordre de présentation
code = db.Column(db.Text(), nullable=False) code = db.Column(db.Text(), nullable=False)
@ -516,7 +536,7 @@ class ApcParcours(db.Model, XMLModel):
class ApcAnneeParcours(db.Model, XMLModel): class ApcAnneeParcours(db.Model, XMLModel):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
parcours_id = db.Column( parcours_id = db.Column(
db.Integer, db.ForeignKey("apc_parcours.id"), nullable=False db.Integer, db.ForeignKey("apc_parcours.id", ondelete="CASCADE"), nullable=False
) )
ordre = db.Column(db.Integer) ordre = db.Column(db.Integer)
"numéro de l'année: 1, 2, 3" "numéro de l'année: 1, 2, 3"

View File

@ -46,7 +46,9 @@ class ApcValidationRCUE(db.Model):
ue1_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), nullable=False) ue1_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), nullable=False)
ue2_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), nullable=False) ue2_id = db.Column(db.Integer, db.ForeignKey("notes_ue.id"), nullable=False)
# optionnel, le parcours dans lequel se trouve la compétence: # optionnel, le parcours dans lequel se trouve la compétence:
parcours_id = db.Column(db.Integer, db.ForeignKey("apc_parcours.id"), nullable=True) parcours_id = db.Column(
db.Integer, db.ForeignKey("apc_parcours.id", ondelete="set null"), nullable=True
)
date = db.Column(db.DateTime(timezone=True), server_default=db.func.now()) date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
code = db.Column(db.String(CODE_STR_LEN), nullable=False, index=True) code = db.Column(db.String(CODE_STR_LEN), nullable=False, index=True)

View File

@ -48,7 +48,7 @@ class Formation(db.Model):
# Optionnel, pour les formations type BUT # Optionnel, pour les formations type BUT
referentiel_competence_id = db.Column( referentiel_competence_id = db.Column(
db.Integer, db.ForeignKey("apc_referentiel_competences.id") db.Integer, db.ForeignKey("apc_referentiel_competences.id", ondelete="SET NULL")
) )
ues = db.relationship("UniteEns", backref="formation", lazy="dynamic") ues = db.relationship("UniteEns", backref="formation", lazy="dynamic")
formsemestres = db.relationship("FormSemestre", lazy="dynamic", backref="formation") formsemestres = db.relationship("FormSemestre", lazy="dynamic", backref="formation")

View File

@ -1037,7 +1037,9 @@ class FormSemestreInscription(db.Model):
# Etape Apogée d'inscription (ajout 2020) # Etape Apogée d'inscription (ajout 2020)
etape = db.Column(db.String(APO_CODE_STR_LEN)) etape = db.Column(db.String(APO_CODE_STR_LEN))
# Parcours (pour les BUT) # Parcours (pour les BUT)
parcour_id = db.Column(db.Integer, db.ForeignKey("apc_parcours.id"), index=True) parcour_id = db.Column(
db.Integer, db.ForeignKey("apc_parcours.id", ondelete="SET NULL"), index=True
)
parcour = db.relationship(ApcParcours) parcour = db.relationship(ApcParcours)
def __repr__(self): def __repr__(self):

View File

@ -51,11 +51,15 @@ class UniteEns(db.Model):
color = db.Column(db.Text()) color = db.Column(db.Text())
# BUT # BUT
niveau_competence_id = db.Column(db.Integer, db.ForeignKey("apc_niveau.id")) niveau_competence_id = db.Column(
db.Integer, db.ForeignKey("apc_niveau.id", ondelete="SET NULL")
)
niveau_competence = db.relationship("ApcNiveau", back_populates="ues") niveau_competence = db.relationship("ApcNiveau", back_populates="ues")
# Une ue appartient soit à tous les parcours (tronc commun), soit à un seul: # Une ue appartient soit à tous les parcours (tronc commun), soit à un seul:
parcour_id = db.Column(db.Integer, db.ForeignKey("apc_parcours.id"), index=True) parcour_id = db.Column(
db.Integer, db.ForeignKey("apc_parcours.id", ondelete="SET NULL"), index=True
)
parcour = db.relationship("ApcParcours", back_populates="ues") parcour = db.relationship("ApcParcours", back_populates="ues")
# relations # relations

View File

@ -160,11 +160,11 @@ class ScolarEvent(db.Model):
event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now()) event_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
formsemestre_id = db.Column( formsemestre_id = db.Column(
db.Integer, db.Integer,
db.ForeignKey("notes_formsemestre.id"), db.ForeignKey("notes_formsemestre.id", ondelete="SET NULL"),
) )
ue_id = db.Column( ue_id = db.Column(
db.Integer, db.Integer,
db.ForeignKey("notes_ue.id"), db.ForeignKey("notes_ue.id", ondelete="SET NULL"),
) )
# 'CREATION', 'INSCRIPTION', 'DEMISSION', # 'CREATION', 'INSCRIPTION', 'DEMISSION',
# 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM' # 'AUT_RED', 'EXCLUS', 'VALID_UE', 'VALID_SEM'

View File

@ -317,7 +317,7 @@ def _style_sems(sems):
] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_sem_apo']}" """ ] = f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_sem_apo']}" """
def delete_dept(dept_id: int): def delete_dept(dept_id: int) -> str:
"""Suppression irréversible d'un département et de tous les objets rattachés""" """Suppression irréversible d'un département et de tous les objets rattachés"""
assert isinstance(dept_id, int) assert isinstance(dept_id, int)
@ -361,6 +361,7 @@ def delete_dept(dept_id: int):
) )
reqs = [ reqs = [
"delete from apc_referentiel_competences where dept_id = %(dept_id)s",
"delete from identite where dept_id = %(dept_id)s", "delete from identite where dept_id = %(dept_id)s",
"delete from sco_prefs where dept_id = %(dept_id)s", "delete from sco_prefs where dept_id = %(dept_id)s",
"delete from notes_semset_formsemestre where formsemestre_id in (select id from formsemestres_temp)", "delete from notes_semset_formsemestre where formsemestre_id in (select id from formsemestres_temp)",
@ -392,8 +393,10 @@ def delete_dept(dept_id: int):
] ]
for r in reqs: for r in reqs:
cursor.execute(r, {"dept_id": dept_id}) cursor.execute(r, {"dept_id": dept_id})
except: except Exception as e:
cnx.rollback() cnx.rollback()
return str(e)
finally: finally:
cnx.commit() cnx.commit()
app.clear_scodoc_cache() app.clear_scodoc_cache()
return ""

View File

@ -28,8 +28,8 @@
"""Dump base de données pour debug et support technique """Dump base de données pour debug et support technique
Le principe est le suivant: Le principe est le suivant:
1- S'il existe une base en cours d'anonymisation, s'arrête et affiche un msg d'erreur l'utilisateur, 1- S'il existe une base en cours d'anonymisation, s'arrête et affiche un msg
qui peut décider de la supprimer. d'erreur à l'utilisateur, qui peut décider de la supprimer.
2- ScoDoc lance un script qui duplique la base (la copie de SCORT devient ANORT) 2- ScoDoc lance un script qui duplique la base (la copie de SCORT devient ANORT)
- (si elle existe deja, s'arrête) - (si elle existe deja, s'arrête)
@ -49,9 +49,9 @@ pg_dump SCORT | psql ANORT
import base64 import base64
import fcntl import fcntl
import os import os
import requests
import subprocess import subprocess
import traceback
import requests
from flask import g, request from flask import g, request
from flask_login import current_user from flask_login import current_user
@ -59,9 +59,8 @@ from flask_login import current_user
import app.scodoc.notesdb as ndb import app.scodoc.notesdb as ndb
import app.scodoc.sco_utils as scu import app.scodoc.sco_utils as scu
from app import log from app import log
from app.scodoc import sco_users
import sco_version
from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_exceptions import ScoValueError
import sco_version
SCO_DUMP_LOCK = "/tmp/scodump.lock" SCO_DUMP_LOCK = "/tmp/scodump.lock"
@ -81,12 +80,10 @@ def sco_dump_and_send_db(
try: try:
x = open(SCO_DUMP_LOCK, "w+") x = open(SCO_DUMP_LOCK, "w+")
fcntl.flock(x, fcntl.LOCK_EX | fcntl.LOCK_NB) fcntl.flock(x, fcntl.LOCK_EX | fcntl.LOCK_NB)
except (IOError, OSError): except (IOError, OSError) as e:
raise ScoValueError( raise ScoValueError(
"Un envoi de la base " "Un envoi de la base {db_name} est déjà en cours, re-essayer plus tard"
+ db_name ) from e
+ " est déjà en cours, re-essayer plus tard"
)
try: try:
# Drop if exists # Drop if exists
@ -96,7 +93,7 @@ def sco_dump_and_send_db(
_duplicate_db(db_name, ano_db_name) _duplicate_db(db_name, ano_db_name)
# Anonymisation # Anonymisation
_anonymize_db(ano_db_name) anonymize_db(ano_db_name)
# Send # Send
r = _send_db(ano_db_name, message, request_url, traceback_str=traceback_str) r = _send_db(ano_db_name, message, request_url, traceback_str=traceback_str)
@ -116,44 +113,44 @@ def sco_dump_and_send_db(
def _duplicate_db(db_name, ano_db_name): def _duplicate_db(db_name, ano_db_name):
"""Create new database, and copy old one into""" """Create new database, and copy old one into"""
cmd = ["createdb", "-E", "UTF-8", ano_db_name] cmd = ["createdb", "-E", "UTF-8", ano_db_name]
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd)) log(f"sco_dump_and_send_db/_duplicate_db: {cmd}")
try: try:
_ = subprocess.check_output(cmd) _ = subprocess.check_output(cmd)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
log("sco_dump_and_send_db: exception createdb {}".format(e)) log(f"sco_dump_and_send_db: exception createdb {e}")
raise ScoValueError( raise ScoValueError(
"erreur lors de la creation de la base {}".format(ano_db_name) f"erreur lors de la creation de la base {ano_db_name}"
) ) from e
cmd = "pg_dump {} | psql {}".format(db_name, ano_db_name) cmd = f"pg_dump {db_name} | psql {ano_db_name}"
log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd)) log("sco_dump_and_send_db/_duplicate_db: {}".format(cmd))
try: try:
_ = subprocess.check_output(cmd, shell=1) _ = subprocess.check_output(cmd, shell=1)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
log("sco_dump_and_send_db: exception {}".format(e)) log("sco_dump_and_send_db: exception {}".format(e))
raise ScoValueError( raise ScoValueError(
"erreur lors de la duplication de la base {} vers {}".format( f"erreur lors de la duplication de la base {db_name} vers {ano_db_name}"
db_name, ano_db_name ) from e
)
)
def _anonymize_db(ano_db_name): def anonymize_db(ano_db_name):
"""Anonymize a departement database""" """Anonymize a ScoDoc database"""
cmd = os.path.join(scu.SCO_TOOLS_DIR, "anonymize_db.py") cmd = os.path.join(scu.SCO_TOOLS_DIR, "anonymize_db.py")
log("_anonymize_db: {}".format(cmd)) log(f"anonymize_db: {cmd}")
try: try:
_ = subprocess.check_output([cmd, ano_db_name]) _ = subprocess.check_output([cmd, ano_db_name])
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
log("sco_dump_and_send_db: exception in anonymisation: {}".format(e)) log(f"sco_dump_and_send_db: exception in anonymisation: {e}")
raise ScoValueError( raise ScoValueError(
"erreur lors de l'anonymisation de la base {}".format(ano_db_name) f"erreur lors de l'anonymisation de la base {ano_db_name}"
) ) from e
def _get_scodoc_serial(): def _get_scodoc_serial():
try: try:
with open(os.path.join(scu.SCODOC_VERSION_DIR, "scodoc.sn")) as f: with open(
os.path.join(scu.SCODOC_VERSION_DIR, "scodoc.sn"), encoding=scu.SCO_ENCODING
) as f:
return int(f.read()) return int(f.read())
except: except:
return 0 return 0

View File

@ -0,0 +1,415 @@
"""cascades ref. comp.
Revision ID: d8288b7f0a3e
Revises: 5c7b208355df
Create Date: 2023-02-09 11:25:28.879434
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = "d8288b7f0a3e"
down_revision = "5c7b208355df"
branch_labels = ""
depends_on = ""
def upgrade():
# EVENTS
op.drop_constraint(
"scolar_events_formsemestre_id_fkey", "scolar_events", type_="foreignkey"
)
op.drop_constraint("scolar_events_ue_id_fkey", "scolar_events", type_="foreignkey")
op.create_foreign_key(
"scolar_events_ue_id_fkey",
"scolar_events",
"notes_ue",
["ue_id"],
["id"],
ondelete="SET NULL",
)
op.create_foreign_key(
"scolar_events_formsemestre_id_fkey",
"scolar_events",
"notes_formsemestre",
["formsemestre_id"],
["id"],
ondelete="SET NULL",
)
# REF COMP
op.drop_constraint(
"apc_annee_parcours_parcours_id_fkey", "apc_annee_parcours", type_="foreignkey"
)
op.create_foreign_key(
"apc_annee_parcours_parcours_id_fkey",
"apc_annee_parcours",
"apc_parcours",
["parcours_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_app_critique_niveau_id_fkey", "apc_app_critique", type_="foreignkey"
)
op.create_foreign_key(
"apc_app_critique_niveau_id_fkey",
"apc_app_critique",
"apc_niveau",
["niveau_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_competence_referentiel_id_fkey", "apc_competence", type_="foreignkey"
)
op.create_foreign_key(
"apc_competence_referentiel_id_fkey",
"apc_competence",
"apc_referentiel_competences",
["referentiel_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_composante_essentielle_competence_id_fkey",
"apc_composante_essentielle",
type_="foreignkey",
)
op.create_foreign_key(
"apc_composante_essentielle_competence_id_fkey",
"apc_composante_essentielle",
"apc_competence",
["competence_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_modules_acs_app_crit_id_fkey", "apc_modules_acs", type_="foreignkey"
)
op.create_foreign_key(
"apc_modules_acs_app_crit_id_fkey",
"apc_modules_acs",
"apc_app_critique",
["app_crit_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_niveau_competence_id_fkey", "apc_niveau", type_="foreignkey"
)
op.create_foreign_key(
"apc_niveau_competence_id_fkey",
"apc_niveau",
"apc_competence",
["competence_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_parcours_referentiel_id_fkey", "apc_parcours", type_="foreignkey"
)
op.create_foreign_key(
"apc_parcours_referentiel_id_fkey",
"apc_parcours",
"apc_referentiel_competences",
["referentiel_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_referentiel_competences_dept_id_fkey",
"apc_referentiel_competences",
type_="foreignkey",
)
op.create_foreign_key(
"apc_referentiel_competences_dept_id_fkey",
"apc_referentiel_competences",
"departement",
["dept_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_situation_pro_competence_id_fkey", "apc_situation_pro", type_="foreignkey"
)
op.create_foreign_key(
"apc_situation_pro_competence_id_fkey",
"apc_situation_pro",
"apc_competence",
["competence_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"apc_validation_rcue_parcours_id_fkey",
"apc_validation_rcue",
type_="foreignkey",
)
op.create_foreign_key(
"apc_validation_rcue_parcours_id_fkey",
"apc_validation_rcue",
"apc_parcours",
["parcours_id"],
["id"],
ondelete="set null",
)
op.drop_constraint(
"notes_formations_referentiel_competence_id_fkey",
"notes_formations",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formations_referentiel_competence_id_fkey",
"notes_formations",
"apc_referentiel_competences",
["referentiel_competence_id"],
["id"],
ondelete="SET NULL",
)
op.drop_constraint(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
"apc_parcours",
["parcour_id"],
["id"],
ondelete="SET NULL",
)
op.drop_constraint(
"notes_ue_niveau_competence_id_fkey", "notes_ue", type_="foreignkey"
)
op.drop_constraint("notes_ue_parcour_id_fkey", "notes_ue", type_="foreignkey")
op.create_foreign_key(
"notes_ue_niveau_competence_id_fkey",
"notes_ue",
"apc_niveau",
["niveau_competence_id"],
["id"],
ondelete="SET NULL",
)
op.create_foreign_key(
"notes_ue_parcour_id_fkey",
"notes_ue",
"apc_parcours",
["parcour_id"],
["id"],
ondelete="SET NULL",
)
op.drop_constraint(
"parcours_formsemestre_parcours_id_fkey",
"parcours_formsemestre",
type_="foreignkey",
)
op.create_foreign_key(
"parcours_formsemestre_parcours_id_fkey",
"parcours_formsemestre",
"apc_parcours",
["parcours_id"],
["id"],
ondelete="CASCADE",
)
op.drop_constraint(
"parcours_modules_parcours_id_fkey", "parcours_modules", type_="foreignkey"
)
op.create_foreign_key(
"parcours_modules_parcours_id_fkey",
"parcours_modules",
"apc_parcours",
["parcours_id"],
["id"],
ondelete="CASCADE",
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(
"parcours_modules_parcours_id_fkey", "parcours_modules", type_="foreignkey"
)
op.create_foreign_key(
"parcours_modules_parcours_id_fkey",
"parcours_modules",
"apc_parcours",
["parcours_id"],
["id"],
)
op.drop_constraint(
"parcours_formsemestre_parcours_id_fkey",
"parcours_formsemestre",
type_="foreignkey",
)
op.create_foreign_key(
"parcours_formsemestre_parcours_id_fkey",
"parcours_formsemestre",
"apc_parcours",
["parcours_id"],
["id"],
)
op.drop_constraint("notes_ue_parcour_id_fkey", "notes_ue", type_="foreignkey")
op.drop_constraint(
"notes_ue_niveau_competence_id_fkey", "notes_ue", type_="foreignkey"
)
op.create_foreign_key(
"notes_ue_parcour_id_fkey", "notes_ue", "apc_parcours", ["parcour_id"], ["id"]
)
op.create_foreign_key(
"notes_ue_niveau_competence_id_fkey",
"notes_ue",
"apc_niveau",
["niveau_competence_id"],
["id"],
)
op.drop_constraint(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formsemestre_inscription_parcour_id_fkey",
"notes_formsemestre_inscription",
"apc_parcours",
["parcour_id"],
["id"],
)
op.drop_constraint(
"notes_formations_referentiel_competence_id_fkey",
"notes_formations",
type_="foreignkey",
)
op.create_foreign_key(
"notes_formations_referentiel_competence_id_fkey",
"notes_formations",
"apc_referentiel_competences",
["referentiel_competence_id"],
["id"],
)
op.drop_constraint(
"apc_validation_rcue_parcours_id_fkey",
"apc_validation_rcue",
type_="foreignkey",
)
op.create_foreign_key(
"apc_validation_rcue_parcours_id_fkey",
"apc_validation_rcue",
"apc_parcours",
["parcours_id"],
["id"],
)
op.drop_constraint(
"apc_situation_pro_competence_id_fkey", "apc_situation_pro", type_="foreignkey"
)
op.create_foreign_key(
"apc_situation_pro_competence_id_fkey",
"apc_situation_pro",
"apc_competence",
["competence_id"],
["id"],
)
op.drop_constraint(
"apc_referentiel_competences_dept_id_fkey",
"apc_referentiel_competences",
type_="foreignkey",
)
op.create_foreign_key(
"apc_referentiel_competences_dept_id_fkey",
"apc_referentiel_competences",
"departement",
["dept_id"],
["id"],
)
op.drop_constraint(
"apc_parcours_referentiel_id_fkey", "apc_parcours", type_="foreignkey"
)
op.create_foreign_key(
"apc_parcours_referentiel_id_fkey",
"apc_parcours",
"apc_referentiel_competences",
["referentiel_id"],
["id"],
)
op.drop_constraint(
"apc_niveau_competence_id_fkey", "apc_niveau", type_="foreignkey"
)
op.create_foreign_key(
"apc_niveau_competence_id_fkey",
"apc_niveau",
"apc_competence",
["competence_id"],
["id"],
)
op.drop_constraint(
"apc_modules_acs_app_crit_id_fkey", "apc_modules_acs", type_="foreignkey"
)
op.create_foreign_key(
"apc_modules_acs_app_crit_id_fkey",
"apc_modules_acs",
"apc_app_critique",
["app_crit_id"],
["id"],
)
op.drop_constraint(
"apc_composante_essentielle_competence_id_fkey",
"apc_composante_essentielle",
type_="foreignkey",
)
op.create_foreign_key(
"apc_composante_essentielle_competence_id_fkey",
"apc_composante_essentielle",
"apc_competence",
["competence_id"],
["id"],
)
op.drop_constraint(
"apc_competence_referentiel_id_fkey", "apc_competence", type_="foreignkey"
)
op.create_foreign_key(
"apc_competence_referentiel_id_fkey",
"apc_competence",
"apc_referentiel_competences",
["referentiel_id"],
["id"],
)
op.drop_constraint(
"apc_app_critique_niveau_id_fkey", "apc_app_critique", type_="foreignkey"
)
op.create_foreign_key(
"apc_app_critique_niveau_id_fkey",
"apc_app_critique",
"apc_niveau",
["niveau_id"],
["id"],
)
op.drop_constraint(
"apc_annee_parcours_parcours_id_fkey", "apc_annee_parcours", type_="foreignkey"
)
op.create_foreign_key(
"apc_annee_parcours_parcours_id_fkey",
"apc_annee_parcours",
"apc_parcours",
["parcours_id"],
["id"],
)
# EVENTS
op.drop_constraint("scolar_events_ue_id_fkey", "scolar_events", type_="foreignkey")
op.drop_constraint(
"scolar_events_formsemestre_id_fkey", "scolar_events", type_="foreignkey"
)
op.create_foreign_key(
"scolar_events_ue_id_fkey", "scolar_events", "notes_ue", ["ue_id"], ["id"]
)
op.create_foreign_key(
"scolar_events_formsemestre_id_fkey",
"scolar_events",
"notes_formsemestre",
["formsemestre_id"],
["id"],
)
# ### end Alembic commands ###

View File

@ -41,6 +41,7 @@ from app.models.but_refcomp import (
) )
from app.models.but_validations import ApcValidationAnnee, ApcValidationRCUE from app.models.but_validations import ApcValidationAnnee, ApcValidationRCUE
from app.models.evaluations import Evaluation from app.models.evaluations import Evaluation
from app.scodoc import sco_dump_db
from app.scodoc.sco_logos import make_logo_local from app.scodoc.sco_logos import make_logo_local
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
from app.views import notes, scolar from app.views import notes, scolar
@ -131,6 +132,18 @@ def sco_db_init(erase=False): # sco-db-init
initialize_scodoc_database(erase=erase) initialize_scodoc_database(erase=erase)
@app.cli.command()
@click.argument("database")
def anonymize_db(database): # anonymize-db
"""Anonymise la base de nom indiqué (et non pas la base courante!)"""
click.confirm(
f"L'anonymisation va affecter la base {database} et PERDRE beaucoup de données.\nContinuer ?",
abort=True,
)
sco_dump_db.anonymize_db(database)
click.echo(f"Base {database} pseudonymisée")
@app.cli.command() @app.cli.command()
def user_db_clear(): def user_db_clear():
"""Erase all users and roles from the database !""" """Erase all users and roles from the database !"""
@ -397,9 +410,11 @@ def delete_dept(dept, force=False): # delete-dept
sys.stderr.write(f"Erreur: le departement {dept} n'existe pas !\n") sys.stderr.write(f"Erreur: le departement {dept} n'existe pas !\n")
return 2 return 2
elif d: elif d:
sco_dept.delete_dept(d.id) msg = sco_dept.delete_dept(d.id)
db.session.commit() db.session.commit()
return 0 if msg:
print(f"Erreur:\n {msg}")
return 0 if not msg else 1
@app.cli.command() @app.cli.command()

View File

@ -26,8 +26,6 @@
# #
############################################################################## ##############################################################################
# TODO à tester avec ScoDoc9, devrait fonctionner sans problème majeur ?
"""Anonymize une base de données ScoDoc """Anonymize une base de données ScoDoc
Runned as user "scodoc" with scodoc and postgresql up. Runned as user "scodoc" with scodoc and postgresql up.