forked from ScoDoc/ScoDoc
BUT: association UE <-> niveau competence
This commit is contained in:
parent
0709b53bbe
commit
1a18fef3e0
app
but
models
scodoc
static
templates/pn
views
migrations/versions
68
app/but/apc_edit_ue.py
Normal file
68
app/but/apc_edit_ue.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
Edition associations UE <-> Ref. Compétence
|
||||||
|
"""
|
||||||
|
from flask import g, url_for
|
||||||
|
from app import db, log
|
||||||
|
from app.models import UniteEns
|
||||||
|
from app.models.but_refcomp import ApcNiveau
|
||||||
|
|
||||||
|
|
||||||
|
def form_ue_choix_niveau(ue: UniteEns) -> str:
|
||||||
|
"""Form. HTML pour associer une UE à un niveau de compétence"""
|
||||||
|
ref_comp = ue.formation.referentiel_competence
|
||||||
|
if ref_comp is None:
|
||||||
|
return """<div class="ue_choix_niveau">pas de référentiel de compétence</div>"""
|
||||||
|
annee = (ue.semestre_idx + 1) // 2 # 1, 2, 3
|
||||||
|
niveaux_by_parcours = ref_comp.get_niveaux_by_parcours(annee)
|
||||||
|
|
||||||
|
options = []
|
||||||
|
if niveaux_by_parcours["TC"]:
|
||||||
|
options.append("""<optgroup label="Tronc commun">""")
|
||||||
|
for n in niveaux_by_parcours["TC"]:
|
||||||
|
options.append(
|
||||||
|
f"""<option value="{n.id}" {'selected' if ue.niveau_competence == n else ''}>{n.annee} {n.competence.titre_long} niveau {n.ordre}</option>"""
|
||||||
|
)
|
||||||
|
options.append("""</optgroup>""")
|
||||||
|
for parcour in ref_comp.parcours:
|
||||||
|
if len(niveaux_by_parcours[parcour.id]):
|
||||||
|
options.append(f"""<optgroup label="Parcours {parcour.libelle}">""")
|
||||||
|
for n in niveaux_by_parcours[parcour.id]:
|
||||||
|
options.append(
|
||||||
|
f"""<option value="{n.id}" {'selected' if ue.niveau_competence == n else ''}>{n.annee} {n.competence.titre_long} niveau {n.ordre}</option>"""
|
||||||
|
)
|
||||||
|
options.append("""</optgroup>""")
|
||||||
|
options_str = "\n".join(options)
|
||||||
|
return f"""
|
||||||
|
<div id="ue_choix_niveau">
|
||||||
|
<form id="form_ue_choix_niveau">
|
||||||
|
<b>Niveau de compétence associé:</b>
|
||||||
|
<select onchange="set_ue_niveau_competence();" data-setter="{
|
||||||
|
url_for( "notes.set_ue_niveau_competence", scodoc_dept=g.scodoc_dept)
|
||||||
|
}">
|
||||||
|
<option value="" {'selected' if ue.niveau_competence is None else ''}>aucun</option>
|
||||||
|
{options_str}
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def set_ue_niveau_competence(ue_id: int, niveau_id: int):
|
||||||
|
"""Associe le niveau et l'UE"""
|
||||||
|
log(f"set_ue_niveau_competence( {ue_id}, {niveau_id} )")
|
||||||
|
ue = UniteEns.query.get_or_404(ue_id)
|
||||||
|
if niveau_id == "":
|
||||||
|
# suppression de l'association
|
||||||
|
ue.niveau_competence = None
|
||||||
|
else:
|
||||||
|
niveau = ApcNiveau.query.get_or_404(niveau_id)
|
||||||
|
ue.niveau_competence = niveau
|
||||||
|
db.session.add(ue)
|
||||||
|
db.session.commit()
|
||||||
|
return "", 204
|
@ -7,6 +7,7 @@
|
|||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import flask_sqlalchemy
|
||||||
from sqlalchemy.orm import class_mapper
|
from sqlalchemy.orm import class_mapper
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
@ -105,6 +106,52 @@ class ApcReferentielCompetences(db.Model, XMLModel):
|
|||||||
"parcours": {x.code: x.to_dict() for x in self.parcours},
|
"parcours": {x.code: x.to_dict() for x in self.parcours},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_niveaux_by_parcours(self, annee) -> dict:
|
||||||
|
"""
|
||||||
|
Construit la liste des niveaux de compétences pour chaque parcours
|
||||||
|
de ce référentiel.
|
||||||
|
Les niveaux sont groupés par parcours, en isolant les niveaux de tronc commun.
|
||||||
|
Le tronc commun n'est pas identifié comme tel dans les référentiels Orébut:
|
||||||
|
on cherche les niveaux qui sont présents dans tous les parcours et les range sous
|
||||||
|
la clé "TC" (toujours présente mais éventuellement liste vide si pas de tronc commun).
|
||||||
|
|
||||||
|
résultat:
|
||||||
|
{
|
||||||
|
"TC" : [ ApcNiveau ],
|
||||||
|
parcour.id : [ ApcNiveau ]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
parcours = self.parcours.order_by(ApcParcours.numero).all()
|
||||||
|
niveaux_by_parcours = {
|
||||||
|
parcour.id: ApcNiveau.niveaux_annee_de_parcours(parcour, annee)
|
||||||
|
for parcour in parcours
|
||||||
|
}
|
||||||
|
# Cherche tronc commun
|
||||||
|
niveaux_ids_tc = set.intersection(
|
||||||
|
*[
|
||||||
|
{n.id for n in niveaux_by_parcours[parcour_id]}
|
||||||
|
for parcour_id in niveaux_by_parcours
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# Enleve les niveaux du tronc commun
|
||||||
|
niveaux_by_parcours_no_tc = {
|
||||||
|
parcour.id: [
|
||||||
|
niveau
|
||||||
|
for niveau in niveaux_by_parcours[parcour.id]
|
||||||
|
if niveau.id not in niveaux_ids_tc
|
||||||
|
]
|
||||||
|
for parcour in parcours
|
||||||
|
}
|
||||||
|
# Niveaux du TC
|
||||||
|
niveaux_tc = []
|
||||||
|
if len(parcours):
|
||||||
|
niveaux_parcours_1 = niveaux_by_parcours[parcours[0].id]
|
||||||
|
niveaux_tc = [
|
||||||
|
niveau for niveau in niveaux_parcours_1 if niveau.id in niveaux_ids_tc
|
||||||
|
]
|
||||||
|
niveaux_by_parcours_no_tc["TC"] = niveaux_tc
|
||||||
|
return niveaux_by_parcours_no_tc
|
||||||
|
|
||||||
|
|
||||||
class ApcCompetence(db.Model, XMLModel):
|
class ApcCompetence(db.Model, XMLModel):
|
||||||
"Compétence"
|
"Compétence"
|
||||||
@ -186,13 +233,20 @@ class ApcComposanteEssentielle(db.Model, XMLModel):
|
|||||||
|
|
||||||
|
|
||||||
class ApcNiveau(db.Model, XMLModel):
|
class ApcNiveau(db.Model, XMLModel):
|
||||||
|
"""Niveau de compétence
|
||||||
|
Chaque niveau peut être associé à deux UE,
|
||||||
|
des semestres impair et pair de la même année.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "apc_niveau"
|
||||||
|
|
||||||
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"), nullable=False
|
||||||
)
|
)
|
||||||
libelle = db.Column(db.Text(), nullable=False)
|
libelle = db.Column(db.Text(), nullable=False)
|
||||||
annee = db.Column(db.Text(), nullable=False) # "BUT2"
|
annee = db.Column(db.Text(), nullable=False) # "BUT1", "BUT2", "BUT3"
|
||||||
# L'ordre est l'année d'apparition de ce niveau
|
# L'ordre est le niveau (1,2,3) ou (1,2) suivant la competence
|
||||||
ordre = db.Column(db.Integer, nullable=False) # 1, 2, 3
|
ordre = db.Column(db.Integer, nullable=False) # 1, 2, 3
|
||||||
app_critiques = db.relationship(
|
app_critiques = db.relationship(
|
||||||
"ApcAppCritique",
|
"ApcAppCritique",
|
||||||
@ -200,9 +254,10 @@ class ApcNiveau(db.Model, XMLModel):
|
|||||||
lazy="dynamic",
|
lazy="dynamic",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
)
|
)
|
||||||
|
ues = db.relationship("UniteEns", back_populates="niveau_competence")
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} ordre={self.ordre}>"
|
return f"<{self.__class__.__name__} ordre={self.ordre} annee={self.annee} {self.competence}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
@ -212,6 +267,24 @@ class ApcNiveau(db.Model, XMLModel):
|
|||||||
"app_critiques": {x.code: x.to_dict() for x in self.app_critiques},
|
"app_critiques": {x.code: x.to_dict() for x in self.app_critiques},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def niveaux_annee_de_parcours(
|
||||||
|
cls, parcour: "ApcParcours", annee: int
|
||||||
|
) -> flask_sqlalchemy.BaseQuery:
|
||||||
|
"""Les niveaux de l'année du parcours"""
|
||||||
|
if annee not in {1, 2, 3}:
|
||||||
|
raise ValueError("annee invalide pour un parcours BUT")
|
||||||
|
annee_formation = f"BUT{annee}"
|
||||||
|
return ApcNiveau.query.filter(
|
||||||
|
ApcParcoursNiveauCompetence.annee_parcours_id == ApcAnneeParcours.id,
|
||||||
|
ApcParcours.id == ApcAnneeParcours.parcours_id,
|
||||||
|
ApcParcours.referentiel == parcour.referentiel,
|
||||||
|
ApcParcoursNiveauCompetence.competence_id == ApcCompetence.id,
|
||||||
|
ApcCompetence.id == ApcNiveau.competence_id,
|
||||||
|
ApcAnneeParcours.parcours == parcour,
|
||||||
|
ApcNiveau.annee == annee_formation,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ApcAppCritique(db.Model, XMLModel):
|
class ApcAppCritique(db.Model, XMLModel):
|
||||||
"Apprentissage Critique BUT"
|
"Apprentissage Critique BUT"
|
||||||
@ -281,9 +354,10 @@ class ApcAnneeParcours(db.Model, XMLModel):
|
|||||||
db.Integer, db.ForeignKey("apc_parcours.id"), nullable=False
|
db.Integer, db.ForeignKey("apc_parcours.id"), nullable=False
|
||||||
)
|
)
|
||||||
ordre = db.Column(db.Integer)
|
ordre = db.Column(db.Integer)
|
||||||
|
"numéro de l'année: 1, 2, 3"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} ordre={self.ordre}>"
|
return f"<{self.__class__.__name__} ordre={self.ordre} parcours={self.parcours.code}>"
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
@ -321,6 +395,7 @@ class ApcParcoursNiveauCompetence(db.Model):
|
|||||||
"annee_parcours",
|
"annee_parcours",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
cascade="save-update, merge, delete, delete-orphan",
|
cascade="save-update, merge, delete, delete-orphan",
|
||||||
|
lazy="dynamic",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
annee_parcours = db.relationship(
|
annee_parcours = db.relationship(
|
||||||
@ -333,4 +408,4 @@ class ApcParcoursNiveauCompetence(db.Model):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<{self.__class__.__name__} {self.competence} {self.annee_parcours}>"
|
return f"<{self.__class__.__name__} {self.competence}<->{self.annee_parcours} niveau={self.niveau}>"
|
||||||
|
@ -42,6 +42,10 @@ class UniteEns(db.Model):
|
|||||||
|
|
||||||
color = db.Column(db.Text())
|
color = db.Column(db.Text())
|
||||||
|
|
||||||
|
# BUT
|
||||||
|
niveau_competence_id = db.Column(db.Integer, db.ForeignKey("apc_niveau.id"))
|
||||||
|
niveau_competence = db.relationship("ApcNiveau", back_populates="ues")
|
||||||
|
|
||||||
# relations
|
# relations
|
||||||
matieres = db.relationship("Matiere", lazy="dynamic", backref="ue")
|
matieres = db.relationship("Matiere", lazy="dynamic", backref="ue")
|
||||||
modules = db.relationship("Module", lazy="dynamic", backref="ue")
|
modules = db.relationship("Module", lazy="dynamic", backref="ue")
|
||||||
|
@ -35,6 +35,7 @@ from flask_login import current_user
|
|||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app import log
|
from app import log
|
||||||
|
from app.but import apc_edit_ue
|
||||||
from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN
|
from app.models import APO_CODE_STR_LEN, SHORT_STR_LEN
|
||||||
from app.models import Formation, UniteEns, ModuleImpl, Module
|
from app.models import Formation, UniteEns, ModuleImpl, Module
|
||||||
from app.models import ScolarNews
|
from app.models import ScolarNews
|
||||||
@ -283,6 +284,11 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
<p class="help">Note: sauf exception, l'UE n'a pas de coefficient associé.
|
<p class="help">Note: sauf exception, l'UE n'a pas de coefficient associé.
|
||||||
Seuls les <em>modules</em> ont des coefficients.
|
Seuls les <em>modules</em> ont des coefficients.
|
||||||
</p>""",
|
</p>""",
|
||||||
|
f"""
|
||||||
|
<h4>UE du semestre S{ue.semestre_idx}</h4>
|
||||||
|
"""
|
||||||
|
if is_apc
|
||||||
|
else "",
|
||||||
]
|
]
|
||||||
|
|
||||||
ue_types = parcours.ALLOWED_UE_TYPES
|
ue_types = parcours.ALLOWED_UE_TYPES
|
||||||
@ -416,8 +422,12 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
form_descr,
|
form_descr,
|
||||||
initvalues=initvalues,
|
initvalues=initvalues,
|
||||||
submitlabel=submitlabel,
|
submitlabel=submitlabel,
|
||||||
|
cancelbutton="Revenir à la formation",
|
||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
|
niveau_competence_div = ""
|
||||||
|
if ue and is_apc:
|
||||||
|
niveau_competence_div = apc_edit_ue.form_ue_choix_niveau(ue)
|
||||||
if ue and ue.modules.count() and ue.semestre_idx is not None:
|
if ue and ue.modules.count() and ue.semestre_idx is not None:
|
||||||
modules_div = f"""<div id="ue_list_modules">
|
modules_div = f"""<div id="ue_list_modules">
|
||||||
<div><b>{ue.modules.count()} modules sont rattachés
|
<div><b>{ue.modules.count()} modules sont rattachés
|
||||||
@ -435,6 +445,7 @@ def ue_edit(ue_id=None, create=False, formation_id=None, default_semestre_idx=No
|
|||||||
return (
|
return (
|
||||||
"\n".join(H)
|
"\n".join(H)
|
||||||
+ tf[1]
|
+ tf[1]
|
||||||
|
+ niveau_competence_div
|
||||||
+ modules_div
|
+ modules_div
|
||||||
+ bonus_div
|
+ bonus_div
|
||||||
+ ue_div
|
+ ue_div
|
||||||
@ -1004,6 +1015,9 @@ def _ue_table_ues(
|
|||||||
}">transformer en UE ordinaire</a> """
|
}">transformer en UE ordinaire</a> """
|
||||||
)
|
)
|
||||||
H.append("</span>")
|
H.append("</span>")
|
||||||
|
breakpoint()
|
||||||
|
if ue.niveau_competence is None:
|
||||||
|
H.append(" pas de compétence associée ")
|
||||||
ue_editable = editable and not ue_is_locked(ue["ue_id"])
|
ue_editable = editable and not ue_is_locked(ue["ue_id"])
|
||||||
if ue_editable:
|
if ue_editable:
|
||||||
H.append(
|
H.append(
|
||||||
|
@ -194,8 +194,8 @@ def moduleimpl_status(moduleimpl_id=None, partition_id=None):
|
|||||||
raise ScoInvalidIdType("moduleimpl_id must be an integer !")
|
raise ScoInvalidIdType("moduleimpl_id must be an integer !")
|
||||||
modimpl = ModuleImpl.query.get_or_404(moduleimpl_id)
|
modimpl = ModuleImpl.query.get_or_404(moduleimpl_id)
|
||||||
M = modimpl.to_dict()
|
M = modimpl.to_dict()
|
||||||
formsemestre_id = M["formsemestre_id"]
|
formsemestre_id = modimpl.formsemestre_id
|
||||||
Mod = sco_edit_module.module_list(args={"module_id": M["module_id"]})[0]
|
Mod = sco_edit_module.module_list(args={"module_id": modimpl.module_id})[0]
|
||||||
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
sem = sco_formsemestre.get_formsemestre(formsemestre_id)
|
||||||
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
F = sco_formations.formation_list(args={"formation_id": sem["formation_id"]})[0]
|
||||||
mod_inscrits = sco_moduleimpl.do_moduleimpl_inscription_list(
|
mod_inscrits = sco_moduleimpl.do_moduleimpl_inscription_list(
|
||||||
|
@ -2206,7 +2206,7 @@ ul.notes_module_list {
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div#ue_list_modules {
|
div#ue_choix_niveau {
|
||||||
background-color: rgb(191, 242, 255);
|
background-color: rgb(191, 242, 255);
|
||||||
border: 1px solid blue;
|
border: 1px solid blue;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@ -2215,6 +2215,15 @@ div#ue_list_modules {
|
|||||||
margin-right: 15px;
|
margin-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div#ue_list_modules {
|
||||||
|
background-color: rgb(251, 225, 165);
|
||||||
|
border: 1px solid blue;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
div#ue_list_etud_validations {
|
div#ue_list_etud_validations {
|
||||||
background-color: rgb(220, 250, 220);
|
background-color: rgb(220, 250, 220);
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
|
@ -25,10 +25,27 @@ function update_bonus_description() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function update_ue_list() {
|
function update_ue_list() {
|
||||||
var ue_id = $("#tf_ue_id")[0].value;
|
let ue_id = $("#tf_ue_id")[0].value;
|
||||||
var ue_code = $("#tf_ue_code")[0].value;
|
let ue_code = $("#tf_ue_code")[0].value;
|
||||||
var query = SCO_URL + "/Notes/ue_sharing_code?ue_code=" + ue_code + "&hide_ue_id=" + ue_id + "&ue_id=" + ue_id;
|
let query = SCO_URL + "/Notes/ue_sharing_code?ue_code=" + ue_code + "&hide_ue_id=" + ue_id + "&ue_id=" + ue_id;
|
||||||
$.get(query, '', function (data) {
|
$.get(query, '', function (data) {
|
||||||
$("#ue_list_code").html(data);
|
$("#ue_list_code").html(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function set_ue_niveau_competence() {
|
||||||
|
let ue_id = document.querySelector("#tf_ue_id").value;
|
||||||
|
let select = document.querySelector("#form_ue_choix_niveau select");
|
||||||
|
let niveau_id = select.value;
|
||||||
|
let set_ue_niveau_competence_url = select.dataset.setter;
|
||||||
|
$.post(set_ue_niveau_competence_url,
|
||||||
|
{
|
||||||
|
ue_id: ue_id,
|
||||||
|
niveau_id: niveau_id,
|
||||||
|
},
|
||||||
|
function (result) {
|
||||||
|
// obj.classList.remove("sco_wait");
|
||||||
|
// obj.classList.add("sco_modified");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
@ -40,6 +40,9 @@
|
|||||||
else '<span class="missing_ue_ects">aucun</span>'|safe}} ECTS)
|
else '<span class="missing_ue_ects">aucun</span>'|safe}} ECTS)
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
{% if ue.niveau_competence is none %}
|
||||||
|
<span class="fontred">pas de compétence associée</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if editable and not ue.is_locked() %}
|
{% if editable and not ue.is_locked() %}
|
||||||
<a class="stdlink" href="{{ url_for('notes.ue_edit',
|
<a class="stdlink" href="{{ url_for('notes.ue_edit',
|
||||||
|
@ -53,7 +53,7 @@ from app import db
|
|||||||
from app import models
|
from app import models
|
||||||
from app.models import ScolarNews
|
from app.models import ScolarNews
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
from app.but import bulletin_but
|
from app.but import apc_edit_ue, bulletin_but
|
||||||
from app.decorators import (
|
from app.decorators import (
|
||||||
scodoc,
|
scodoc,
|
||||||
scodoc7func,
|
scodoc7func,
|
||||||
@ -416,6 +416,15 @@ sco_publish(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/set_ue_niveau_competence", methods=["POST"])
|
||||||
|
@permission_required(Permission.ScoChangeFormation)
|
||||||
|
def set_ue_niveau_competence(scodoc_dept=""):
|
||||||
|
"associe UE et niveau"
|
||||||
|
ue_id = request.form.get("ue_id")
|
||||||
|
niveau_id = request.form.get("niveau_id")
|
||||||
|
return apc_edit_ue.set_ue_niveau_competence(ue_id, niveau_id)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ue_list") # backward compat
|
@bp.route("/ue_list") # backward compat
|
||||||
@bp.route("/ue_table")
|
@bp.route("/ue_table")
|
||||||
@scodoc
|
@scodoc
|
||||||
|
34
migrations/versions/6002d7d366e5_assoc_ue_niveau.py
Normal file
34
migrations/versions/6002d7d366e5_assoc_ue_niveau.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
"""assoc UE - Niveau
|
||||||
|
|
||||||
|
Revision ID: 6002d7d366e5
|
||||||
|
Revises: af77ca6a89d0
|
||||||
|
Create Date: 2022-04-26 12:58:32.929910
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = "6002d7d366e5"
|
||||||
|
down_revision = "af77ca6a89d0"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.add_column(
|
||||||
|
"notes_ue", sa.Column("niveau_competence_id", sa.Integer(), nullable=True)
|
||||||
|
)
|
||||||
|
op.create_foreign_key(
|
||||||
|
None, "notes_ue", "apc_niveau", ["niveau_competence_id"], ["id"]
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_constraint(None, "notes_ue", type_="foreignkey")
|
||||||
|
op.drop_column("notes_ue", "niveau_competence_id")
|
||||||
|
# ### end Alembic commands ###
|
Loading…
Reference in New Issue
Block a user