forked from ScoDoc/DocScoDoc
Migration ScoDOc 7 à 9: gestion des clés manquantes et tronque certains champs
This commit is contained in:
parent
7689731038
commit
8de0cd1029
@ -6,7 +6,7 @@ XXX version préliminaire ScoDoc8 #sco8 sans département
|
||||
|
||||
CODE_STR_LEN = 16 # chaine pour les codes
|
||||
SHORT_STR_LEN = 32 # courtes chaine, eg acronymes
|
||||
APO_CODE_STR_LEN = 16 # nb de car max d'un code Apogée
|
||||
APO_CODE_STR_LEN = 24 # nb de car max d'un code Apogée
|
||||
GROUPNAME_STR_LEN = 64
|
||||
|
||||
from app.models.raw_sql_init import create_database_functions
|
||||
|
@ -31,6 +31,7 @@
|
||||
from flask import g
|
||||
from flask_login import current_user
|
||||
|
||||
import app
|
||||
import app.scodoc.sco_utils as scu
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
@ -280,7 +281,6 @@ def _style_sems(sems):
|
||||
def delete_dept(dept_id: int):
|
||||
"""Suppression irréversible d'un département et de tous les objets rattachés"""
|
||||
assert isinstance(dept_id, int)
|
||||
from app import clear_scodoc_cache
|
||||
|
||||
# Un peu complexe, merci JMP :)
|
||||
cnx = ndb.GetDBConnexion()
|
||||
|
@ -173,9 +173,11 @@ def _get_formsemestre_infos_from_news(n):
|
||||
formsemestre_id = n["object"]
|
||||
elif n["type"] == NEWS_NOTE:
|
||||
moduleimpl_id = n["object"]
|
||||
if n["object"]:
|
||||
mods = sco_moduleimpl.do_moduleimpl_list(moduleimpl_id=moduleimpl_id)
|
||||
if not mods:
|
||||
return {} # module does not exists anymore
|
||||
return {} # pas d'indication du module
|
||||
mod = mods[0]
|
||||
formsemestre_id = mod["formsemestre_id"]
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 9.9 KiB |
@ -2,7 +2,7 @@
|
||||
{% import 'bootstrap/wtf.html' as wtf %}
|
||||
|
||||
{% block app_content %}
|
||||
<h2>ScoDoc: gestion scolarité (version développement)</h2>
|
||||
<h2>ScoDoc: gestion scolarité (version béta)</h2>
|
||||
|
||||
{% if not current_user.is_anonymous %}
|
||||
<p>Bonjour <font color="red"><b>{{current_user.get_nomcomplet()}}</b>
|
||||
@ -25,7 +25,7 @@
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<font color="red">Ceci est une version pour développeurs,
|
||||
<font color="red">Ceci est une version de test,
|
||||
ne pas utiliser en production !</font>
|
||||
</p>
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
"""Augmente taille codes Apogee
|
||||
|
||||
Revision ID: f6e7d2e01be1
|
||||
Revises: d3d92b2d0092
|
||||
Create Date: 2021-09-04 11:20:38.699489
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'f6e7d2e01be1'
|
||||
down_revision = 'd3d92b2d0092'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('notes_formsemestre_etapes', 'etape_apo',
|
||||
existing_type=sa.VARCHAR(length=16),
|
||||
type_=sa.String(length=24),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_formsemestre_inscription', 'etape',
|
||||
existing_type=sa.VARCHAR(length=16),
|
||||
type_=sa.String(length=24),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_modules', 'code_apogee',
|
||||
existing_type=sa.VARCHAR(length=16),
|
||||
type_=sa.String(length=24),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_ue', 'code_apogee',
|
||||
existing_type=sa.VARCHAR(length=16),
|
||||
type_=sa.String(length=24),
|
||||
existing_nullable=True)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.alter_column('notes_ue', 'code_apogee',
|
||||
existing_type=sa.String(length=24),
|
||||
type_=sa.VARCHAR(length=16),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_modules', 'code_apogee',
|
||||
existing_type=sa.String(length=24),
|
||||
type_=sa.VARCHAR(length=16),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_formsemestre_inscription', 'etape',
|
||||
existing_type=sa.String(length=24),
|
||||
type_=sa.VARCHAR(length=16),
|
||||
existing_nullable=True)
|
||||
op.alter_column('notes_formsemestre_etapes', 'etape_apo',
|
||||
existing_type=sa.String(length=24),
|
||||
type_=sa.VARCHAR(length=16),
|
||||
existing_nullable=True)
|
||||
# ### end Alembic commands ###
|
@ -169,7 +169,7 @@ def delete_dept(dept): # delete-dept
|
||||
ndb.open_db_connection()
|
||||
d = models.Departement.query.filter_by(acronym=dept).first()
|
||||
if d is None:
|
||||
sys.stderr.write(f"Erreur: le departement {dept} n'existe pas !")
|
||||
sys.stderr.write(f"Erreur: le departement {dept} n'existe pas !\n")
|
||||
return 2
|
||||
sco_dept.delete_dept(d.id)
|
||||
db.session.commit()
|
||||
|
@ -16,9 +16,26 @@ from app.auth.models import User, get_super_admin
|
||||
import app
|
||||
from app import clear_scodoc_cache
|
||||
from app import models
|
||||
from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN, GROUPNAME_STR_LEN
|
||||
from app.scodoc import notesdb as ndb
|
||||
|
||||
# Attributs modifiés entre les bases ScoDoc 7 et 8+:
|
||||
|
||||
def truncate_field(table_name, field, max_len):
|
||||
"renvoie une fonction de troncation"
|
||||
|
||||
def troncator(value):
|
||||
"Si la chaine est trop longue pour la nouvelle base, émet un warning et tronque"
|
||||
if value and len(value) > max_len:
|
||||
logging.warning(
|
||||
"Chaine trop longue tronquée: %s.%s=%s", table_name, field, value
|
||||
)
|
||||
return value[:max_len]
|
||||
return value
|
||||
|
||||
return troncator
|
||||
|
||||
|
||||
# Attributs dont le nom change entre les bases ScoDoc 7 et 9:
|
||||
# (None indique que l'attribut est supprimé, "nouveau_nom" qu'il change de nom)
|
||||
ATTRIBUTES_MAPPING = {
|
||||
"admissions": {
|
||||
@ -64,6 +81,58 @@ ATTRIBUTES_MAPPING = {
|
||||
},
|
||||
}
|
||||
|
||||
# Attributs à transformer pour passer de ScoDoc 7 à 9
|
||||
# la fonction est appliquée au nouvel attribut
|
||||
ATTRIBUTES_TRANSFORM = {
|
||||
"notes_formsemestre": {
|
||||
# la modalité CP est devenue CPRO
|
||||
"modalite": lambda x: x if x != "CP" else "CPRO",
|
||||
"bul_bgcolor": truncate_field(
|
||||
"notes_formsemestre", "bul_bgcolor", SHORT_STR_LEN
|
||||
),
|
||||
},
|
||||
# tronque les codes trop longs pour être honnêtes...
|
||||
"notes_formations": {
|
||||
"formation_code": truncate_field(
|
||||
"notes_formations", "formation_code", SHORT_STR_LEN
|
||||
),
|
||||
"code_specialite": truncate_field(
|
||||
"notes_formations", "code_specialite", SHORT_STR_LEN
|
||||
),
|
||||
},
|
||||
"notes_ue": {
|
||||
"ue_code": truncate_field("notes_ue", "ue_code", SHORT_STR_LEN),
|
||||
"code_apogee": truncate_field("notes_ue", "code_apogee", APO_CODE_STR_LEN),
|
||||
},
|
||||
"notes_modules": {
|
||||
"code_apogee": truncate_field("notes_modules", "code_apogee", APO_CODE_STR_LEN),
|
||||
},
|
||||
"notes_formsemestre_etapes": {
|
||||
"etape_apo": truncate_field(
|
||||
"notes_formsemestre_etapes", "etape_apo", APO_CODE_STR_LEN
|
||||
),
|
||||
},
|
||||
"notes_form_modalites": {
|
||||
"modalite": truncate_field("notes_form_modalites", "modalite", SHORT_STR_LEN),
|
||||
},
|
||||
"notes_formsemestre_inscription": {
|
||||
"etape": truncate_field(
|
||||
"notes_formsemestre_inscription", "etape", APO_CODE_STR_LEN
|
||||
),
|
||||
},
|
||||
"partition": {
|
||||
"partition_name": truncate_field("partition", "partition_name", SHORT_STR_LEN),
|
||||
},
|
||||
"group_descr": {
|
||||
"group_name": truncate_field("group_descr", "group_name", GROUPNAME_STR_LEN),
|
||||
},
|
||||
"scolar_autorisation_inscription": {
|
||||
"formation_code": truncate_field(
|
||||
"scolar_autorisation_inscription", "formation_code", SHORT_STR_LEN
|
||||
),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def setup_log(dept_acronym: str):
|
||||
"""log to console (stderr) and /opt/scodoc-data/log/migration79.log"""
|
||||
@ -280,6 +349,9 @@ def convert_object(
|
||||
if v is not None:
|
||||
obj[v] = obj[k]
|
||||
del obj[k]
|
||||
# transforme les valeurs: obj[k] = transform(obj[k])
|
||||
for k in ATTRIBUTES_TRANSFORM.get(table_name, {}):
|
||||
obj[k] = ATTRIBUTES_TRANSFORM[table_name][k](obj[k])
|
||||
# map les ids (foreign keys)
|
||||
for k in obj:
|
||||
if (k.endswith("id") or k == "object") and k not in USER_REFS | {
|
||||
@ -307,10 +379,18 @@ def convert_object(
|
||||
"scolar_news",
|
||||
"absences",
|
||||
"absences_notifications",
|
||||
"itemsuivi", # etudid n'était pas une clé
|
||||
}:
|
||||
# tables avec "fausses" clés
|
||||
# (l'object référencé a pu disparaitre)
|
||||
new_ref = None
|
||||
elif is_table and table_name in {
|
||||
"notes_semset_formsemestre",
|
||||
}:
|
||||
# pour anciennes installs où des relations n'avait pas été déclarées clés étrangères
|
||||
# eg: notes_semset_formsemestre.semset_id n'était pas une clé
|
||||
# Dans ce cas, mieux vaut supprimer la relation si l'un des objets n'existe pas
|
||||
return
|
||||
else:
|
||||
raise ValueError(f"no new id for {table_name}.{k}='{obj[k]}' !")
|
||||
obj[k] = new_ref
|
||||
@ -321,8 +401,9 @@ def convert_object(
|
||||
uid = login2id.get(login_scodoc7)
|
||||
if not uid:
|
||||
uid = default_user.id
|
||||
logging.warning(
|
||||
f"non existent user: {login_scodoc7}: giving {table_name}({old_id}) to admin"
|
||||
warning_user_dont_exist(
|
||||
login_scodoc7,
|
||||
f"non existent user: {login_scodoc7}: giving {table_name}({old_id}) to admin",
|
||||
)
|
||||
# raise ValueError(f"non existent user: {login_scodoc7}")
|
||||
obj[k] = uid
|
||||
@ -354,6 +435,16 @@ def convert_object(
|
||||
id_from_scodoc7[old_id] = new_id
|
||||
|
||||
|
||||
MISSING_USERS = set() # login ScoDoc7 référencés mais non existants...
|
||||
|
||||
|
||||
def warning_user_dont_exist(login_scodoc7, msg):
|
||||
if login_scodoc7 not in MISSING_USERS:
|
||||
return
|
||||
MISSING_USERS.add(login_scodoc7)
|
||||
logging.warning(msg)
|
||||
|
||||
|
||||
def insert_object(cnx, table_name: str, vals: dict) -> str:
|
||||
"""insert tuple in db
|
||||
version manuelle => ne semble pas plus rapide
|
||||
|
@ -54,7 +54,7 @@ then
|
||||
fi
|
||||
if [ "$1" == "-m" ]
|
||||
then
|
||||
echo "migration en place"
|
||||
echo "Migration en place"
|
||||
INPLACE=1
|
||||
SCODOC7_HOME=/opt/scodoc7
|
||||
# vérifie que ScoDoc7 est bien arrêté:
|
||||
@ -79,7 +79,7 @@ migrate_database_ownership() {
|
||||
else
|
||||
for base in $SCO7_BASES
|
||||
do
|
||||
echo modifying $base owner
|
||||
echo "modifying $base owner"
|
||||
su -c "psql -c 'REASSIGN OWNED BY \"www-data\" TO scodoc;' $base" "$POSTGRES_SUPERUSER"
|
||||
done
|
||||
su -c "psql -c 'REASSIGN OWNED BY \"www-data\" TO scodoc;'" "$POSTGRES_SUPERUSER"
|
||||
@ -87,7 +87,7 @@ migrate_database_ownership() {
|
||||
}
|
||||
|
||||
# --- 3. Fichiers locaux: /opt/scodoc7/var => /opt/scodoc-data
|
||||
# note mémo: $SCODOC_DIR ets /opt/scodoc, et $SCODOC_VAR_DIR /opt/scodoc-data
|
||||
# note mémo: $SCODOC_DIR est /opt/scodoc, et $SCODOC_VAR_DIR /opt/scodoc-data
|
||||
#
|
||||
# Migration en place: /opt/scodoc7/var == SCODOC7_HOME/var => /opt/scodoc-data
|
||||
# Migration via archive: SCODOC7_HOME/var => /opt/scodoc-data
|
||||
@ -105,9 +105,15 @@ migrate_local_files() {
|
||||
mv "$SCODOC_VAR_DIR" "$SCODOC_VAR_DIR_BACKUP"
|
||||
fi
|
||||
mkdir "$SCODOC_VAR_DIR" || die "erreur creation repertoire"
|
||||
echo " déplace ${SCODOC7_HOME}/var/scodoc/ dans $SCODOC_VAR_DIR..."
|
||||
mv "${SCODOC7_HOME}"/var/scodoc/* "$SCODOC_VAR_DIR" || die "migrate_local_files failed"
|
||||
# mais récupère notre .env !
|
||||
# Récupère le .env: normalement ./opt/scodoc/.env est un lien vers
|
||||
# /opt/scodoc-data/.env
|
||||
# sauf si installation non standard (developeurs) avec .env réelement dans /opt/scodoc
|
||||
if [ -L "$SCODOC_DIR"/.env ]
|
||||
then
|
||||
cp -p "$SCODOC_VAR_DIR_BACKUP"/.env "$SCODOC_VAR_DIR" || die "fichier .env manquant dans l'ancien $SCODOC_VAR_DIR !"
|
||||
fi
|
||||
# et les certificats
|
||||
if [ -d "$SCODOC_VAR_DIR_BACKUP"/certs ]
|
||||
then
|
||||
@ -156,7 +162,7 @@ echo "(les utilisateurs ScoDoc 9 existants seront laissés inchangés)"
|
||||
echo "-------------------------------------------------------------"
|
||||
echo
|
||||
|
||||
su -c "(cd $SCODOC_DIR && source venv/bin/activate && flask import-scodoc7-users)" "$SCODOC_USER"
|
||||
su -c "(cd $SCODOC_DIR && source venv/bin/activate && flask import-scodoc7-users)" "$SCODOC_USER" || die "Erreur de l'importation des utilisateurs ScoDoc7"
|
||||
|
||||
|
||||
# ----- Migration bases départements
|
||||
@ -170,7 +176,7 @@ do
|
||||
echo "----------------------------------------------"
|
||||
echo "| MIGRATION DU DEPARTEMENT $dept"
|
||||
echo "----------------------------------------------"
|
||||
su -c "(cd $SCODOC_DIR && source venv/bin/activate && flask import-scodoc7-dept $dept $db_name)" "$SCODOC_USER"
|
||||
su -c "(cd $SCODOC_DIR && source venv/bin/activate && flask import-scodoc7-dept $dept $db_name)" "$SCODOC_USER" || die "Erreur au cours de la migration de $dept."
|
||||
echo "restarting postgresql server..."
|
||||
systemctl restart postgresql
|
||||
done
|
||||
|
@ -46,7 +46,7 @@ echo "Ce script recharge les donnees de votre installation ScoDoc 7"
|
||||
echo "sur ce serveur pour migration vers ScoDoc 9."
|
||||
echo "Ce fichier doit avoir ete cree par le script save_scodoc_data.sh, sur une machine ScoDoc 7."
|
||||
echo
|
||||
echo -n "Voulez vous poursuivre cette operation ? (y/n) [n]"
|
||||
echo -n "Voulez-vous poursuivre cette operation ? (y/n) [n]"
|
||||
read -r ans
|
||||
if [ ! "$(norm_ans "$ans")" = 'Y' ]
|
||||
then
|
||||
@ -83,6 +83,7 @@ fi
|
||||
|
||||
echo "Source is $SRC"
|
||||
|
||||
echo "L'opération peut durer plusieurs minutes, suivant la taille de vos bases."
|
||||
echo "Vous allez probablement voir s'afficher de nombreux messages : "
|
||||
echo "pg_restore: attention : la restauration des tables avec WITH OIDS n'est plus supportée"
|
||||
echo
|
||||
@ -109,4 +110,6 @@ done
|
||||
echo
|
||||
echo "Terminé. (vous pouvez ignorer les éventuels avertissements de pg_restore ci-dessus !)"
|
||||
echo
|
||||
echo "Vous pouvez passer à l'étape 4 de la migration (migrate_from_scodoc7.sh), voir la doc."
|
||||
echo
|
||||
#
|
Loading…
Reference in New Issue
Block a user