From d435f3b8354ac1834b8c0591a8c12d79f6879329 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Thu, 2 Dec 2021 17:36:32 +0100 Subject: [PATCH] export ref. comp. en json --- app/models/but_refcomp.py | 63 +++++++++++++++++---- app/views/__init__.py | 2 +- app/views/refcomp.py | 30 ++++++++++ migrations/versions/eed6d50fd9cb_refcomp.py | 44 ++++++++++++++ 4 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 app/views/refcomp.py create mode 100644 migrations/versions/eed6d50fd9cb_refcomp.py diff --git a/app/models/but_refcomp.py b/app/models/but_refcomp.py index dea35173..65eba115 100644 --- a/app/models/but_refcomp.py +++ b/app/models/but_refcomp.py @@ -51,6 +51,14 @@ class ApcReferentielCompetences(db.Model, XMLModel): """Représentation complète du ref. de comp. comme un dict. """ + return { + "dept_id": self.dept_id, + "specialite": self.specialite, + "specialite_long": self.specialite_long, + "type_titre": self.type_titre, + "competences": {x.titre: x.to_dict() for x in self.competences}, + "parcours": {x.code: x.to_dict() for x in self.parcours}, + } class ApcCompetence(db.Model, XMLModel): @@ -62,7 +70,6 @@ class ApcCompetence(db.Model, XMLModel): titre_long = db.Column(db.Text()) couleur = db.Column(db.Text()) numero = db.Column(db.Integer) # ordre de présentation - couleur = db.Column(db.Text()) _xml_attribs = { # xml_attrib : attribute "name": "titre", "libelle_long": "titre_long", @@ -86,6 +93,19 @@ class ApcCompetence(db.Model, XMLModel): cascade="all, delete-orphan", ) + def to_dict(self): + return { + "titre": self.titre, + "titre_long": self.titre_long, + "couleur": self.couleur, + "numero": self.numero, + "situations": [x.to_dict() for x in self.situations], + "composantes_essentielles": [ + x.to_dict() for x in self.composantes_essentielles + ], + "niveaux": {x.annee: x.to_dict() for x in self.niveaux}, + } + class ApcSituationPro(db.Model, XMLModel): id = db.Column(db.Integer, primary_key=True) @@ -94,6 +114,8 @@ class ApcSituationPro(db.Model, XMLModel): ) libelle = db.Column(db.Text(), nullable=False) # aucun attribut (le text devient le libellé) + def to_dict(self): + return {"libelle": self.libelle} class ApcComposanteEssentielle(db.Model, XMLModel): @@ -103,6 +125,9 @@ class ApcComposanteEssentielle(db.Model, XMLModel): ) libelle = db.Column(db.Text(), nullable=False) + def to_dict(self): + return {"libelle": self.libelle} + class ApcNiveau(db.Model, XMLModel): id = db.Column(db.Integer, primary_key=True) @@ -120,6 +145,14 @@ class ApcNiveau(db.Model, XMLModel): cascade="all, delete-orphan", ) + def to_dict(self): + return { + "libelle": self.libelle, + "annee": self.annee, + "ordre": self.ordre, + "app_critiques": {x.code: x.to_dict() for x in self.app_critiques}, + } + class ApcAppCritique(db.Model, XMLModel): "Apprentissage Critique BUT" @@ -136,9 +169,7 @@ class ApcAppCritique(db.Model, XMLModel): ) def to_dict(self): - result = dict(self.__dict__) - result.pop("_sa_instance_state", None) - return result + return {"code": self.code, "libelle": self.libelle} def get_label(self): return self.code + " - " + self.titre @@ -173,18 +204,30 @@ class ApcParcours(db.Model, XMLModel): cascade="all, delete-orphan", ) + def to_dict(self): + return { + "code": self.code, + "numero": self.numero, + "libelle": self.libelle, + "annees": {x.ordre: x.to_dict() for x in self.annees}, + } + class ApcAnneeParcours(db.Model, XMLModel): id = db.Column(db.Integer, primary_key=True) parcours_id = db.Column( db.Integer, db.ForeignKey("apc_parcours.id"), nullable=False ) - numero = db.Column(db.Integer) # ordre de présentation + ordre = db.Column(db.Integer) - # L'attribut s'appelle "ordre" dans le XML Orébut - _xml_attribs = { # xml_attrib : attribute - "ordre": "numero", - } + def to_dict(self): + return { + "ordre": self.ordre, + "competences": { + x.competence.titre: {"niveau": x.niveau, "titre": x.competence.titre} + for x in self.niveaux_competences + }, + } class ApcParcoursNiveauCompetence(db.Model): @@ -215,7 +258,7 @@ class ApcParcoursNiveauCompetence(db.Model): annee_parcours = db.relationship( ApcAnneeParcours, backref=db.backref( - "competences", + "niveaux_competences", passive_deletes=True, cascade="save-update, merge, delete, delete-orphan", ), diff --git a/app/views/__init__.py b/app/views/__init__.py index d902de6c..49855d2d 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -16,7 +16,7 @@ notes_bp = Blueprint("notes", __name__) users_bp = Blueprint("users", __name__) absences_bp = Blueprint("absences", __name__) -from app.views import scodoc, notes, scolar, absences, users, pn_modules +from app.views import scodoc, notes, scolar, absences, users, pn_modules, refcomp # Cette fonction est bien appelée avant toutes les requêtes diff --git a/app/views/refcomp.py b/app/views/refcomp.py new file mode 100644 index 00000000..d2d22482 --- /dev/null +++ b/app/views/refcomp.py @@ -0,0 +1,30 @@ +""" +PN / Référentiel de compétences + +Emmanuel Viennet, 2021 +""" + +from flask import url_for +from flask import jsonify +from flask import current_app, g, request +from flask.templating import render_template +from flask_login import current_user +from werkzeug.utils import redirect + +from config import Config + +from app import db +from app import models + +from app.decorators import scodoc, permission_required +from app.models.but_refcomp import ApcReferentielCompetences +from app.scodoc.sco_permissions import Permission +from app.views import notes_bp as bp + + +@bp.route("/pn/comp/") +@scodoc +@permission_required(Permission.ScoView) +def refcomp(refcomp_id): + ref = ApcReferentielCompetences.query.get_or_404(refcomp_id) + return jsonify(ref.to_dict()) diff --git a/migrations/versions/eed6d50fd9cb_refcomp.py b/migrations/versions/eed6d50fd9cb_refcomp.py new file mode 100644 index 00000000..095454d6 --- /dev/null +++ b/migrations/versions/eed6d50fd9cb_refcomp.py @@ -0,0 +1,44 @@ +"""refcomp + +Revision ID: eed6d50fd9cb +Revises: 00ad500fb118 +Create Date: 2021-12-02 17:34:10.999132 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'eed6d50fd9cb' +down_revision = '00ad500fb118' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('app_crit') + op.drop_table('modules_acs') + op.add_column('apc_annee_parcours', sa.Column('ordre', sa.Integer(), nullable=True)) + op.drop_column('apc_annee_parcours', 'numero') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('apc_annee_parcours', sa.Column('numero', sa.INTEGER(), autoincrement=False, nullable=True)) + op.drop_column('apc_annee_parcours', 'ordre') + op.create_table('modules_acs', + sa.Column('module_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('ac_id', sa.INTEGER(), autoincrement=False, nullable=True), + sa.ForeignKeyConstraint(['ac_id'], ['app_crit.id'], name='modules_acs_ac_id_fkey'), + sa.ForeignKeyConstraint(['module_id'], ['notes_modules.id'], name='modules_acs_module_id_fkey') + ) + op.create_table('app_crit', + sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False), + sa.Column('code', sa.TEXT(), autoincrement=False, nullable=False), + sa.Column('titre', sa.TEXT(), autoincrement=False, nullable=True), + sa.PrimaryKeyConstraint('id', name='app_crit_pkey') + ) + # ### end Alembic commands ###