forked from ScoDoc/ScoDoc
Update opolka/ScoDoc from ScoDoc/ScoDoc #2
87
app/but/bulletin_but_court.py
Normal file
87
app/but/bulletin_but_court.py
Normal file
@ -0,0 +1,87 @@
|
||||
##############################################################################
|
||||
# ScoDoc
|
||||
# Copyright (c) 1999 - 2023 Emmanuel Viennet. All rights reserved.
|
||||
# See LICENSE
|
||||
##############################################################################
|
||||
|
||||
"""Génération bulletin BUT synthétique en une page
|
||||
|
||||
On génère du HTML. Il sera si possible traduit en PDF par weasyprint.
|
||||
|
||||
Le HTML est lui même généré à partir d'un template Jinja.
|
||||
|
||||
## Données
|
||||
|
||||
Ces données sont des objets passés au template.
|
||||
|
||||
- `etud: Identite` : l'étudiant
|
||||
- `formsemestre: FormSemestre` : le formsemestre d'où est émis ce bulletin
|
||||
- `bulletins_sem: BulletinBUT` les données bulletins pour tous les étudiants
|
||||
- `bul: dict` : le bulletin (dict, même structure que le json publié)
|
||||
- `cursus: EtudCursusBUT`: infos sur le cursus BUT (niveaux validés etc)
|
||||
- `decision_ues: dict`: `{ acronyme_ue : { 'code' : 'ADM' }}` accès aux décisions
|
||||
de jury d'UE
|
||||
- `ects_total` : nombre d'ECTS validées dans ce cursus
|
||||
- `ue_validation_by_niveau : dict` : les validations d'UE de chaque niveau du cursus
|
||||
"""
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from flask import render_template, url_for
|
||||
from flask import g, request
|
||||
|
||||
from app.but.bulletin_but import BulletinBUT
|
||||
from app.but import cursus_but, validations_view
|
||||
from app.decorators import (
|
||||
scodoc,
|
||||
permission_required,
|
||||
)
|
||||
from app.models import FormSemestre, FormSemestreInscription, Identite
|
||||
from app.scodoc.sco_exceptions import ScoNoReferentielCompetences
|
||||
from app.scodoc.sco_logos import find_logo
|
||||
from app.scodoc.sco_permissions import Permission
|
||||
from app.views import notes_bp as bp
|
||||
from app.views import ScoData
|
||||
|
||||
|
||||
@bp.route("/bulletin_but/<int:formsemestre_id>/<int:etudid>")
|
||||
@scodoc
|
||||
@permission_required(Permission.ScoView)
|
||||
def bulletin_but(formsemestre_id: int, etudid: int = None):
|
||||
"""Page HTML affichant le bulletin BUT simplifié"""
|
||||
etud: Identite = Identite.query.get_or_404(etudid)
|
||||
formsemestre: FormSemestre = (
|
||||
FormSemestre.query.filter_by(id=formsemestre_id)
|
||||
.join(FormSemestreInscription)
|
||||
.filter_by(etudid=etudid)
|
||||
.first_or_404()
|
||||
)
|
||||
bulletins_sem = BulletinBUT(formsemestre)
|
||||
bul = bulletins_sem.bulletin_etud(etud, formsemestre) # dict
|
||||
decision_ues = {x["acronyme"]: x for x in bul["semestre"]["decision_ue"]}
|
||||
cursus = cursus_but.EtudCursusBUT(etud, formsemestre.formation)
|
||||
refcomp = formsemestre.formation.referentiel_competence
|
||||
if refcomp is None:
|
||||
raise ScoNoReferentielCompetences(formation=formsemestre.formation)
|
||||
ue_validation_by_niveau = validations_view.get_ue_validation_by_niveau(
|
||||
refcomp, etud
|
||||
)
|
||||
ects_total = sum((v.ects() for v in ue_validation_by_niveau.values()))
|
||||
|
||||
logo = find_logo(logoname="header", dept_id=g.scodoc_dept_id)
|
||||
|
||||
return render_template(
|
||||
"but/bulletin_court_page.j2",
|
||||
bul=bul,
|
||||
bulletins_sem=bulletins_sem,
|
||||
cursus=cursus,
|
||||
datetime=datetime,
|
||||
decision_ues=decision_ues,
|
||||
ects_total=ects_total,
|
||||
etud=etud,
|
||||
formsemestre=formsemestre,
|
||||
logo=logo,
|
||||
sco=ScoData(formsemestre=formsemestre, etud=etud),
|
||||
time=time,
|
||||
ue_validation_by_niveau=ue_validation_by_niveau,
|
||||
)
|
@ -426,6 +426,7 @@ def dict_decision_jury(
|
||||
etud: Identite, formsemestre: FormSemestre, with_decisions: bool = False
|
||||
) -> dict:
|
||||
"""dict avec decision pour bulletins json
|
||||
- autorisation_inscription
|
||||
- decision : décision semestre
|
||||
- decision_ue : list des décisions UE
|
||||
- situation
|
||||
@ -511,7 +512,10 @@ def dict_decision_jury(
|
||||
d["autorisation_inscription"] = []
|
||||
for aut in decision["autorisations"]:
|
||||
d["autorisation_inscription"].append(
|
||||
dict(semestre_id=aut["semestre_id"])
|
||||
dict(
|
||||
semestre_id=aut["semestre_id"],
|
||||
date=aut["date"].isoformat() if aut["date"] else None,
|
||||
)
|
||||
)
|
||||
else:
|
||||
d["decision"] = dict(code="", etat="DEM")
|
||||
|
118
app/static/css/bulletin_court.css
Normal file
118
app/static/css/bulletin_court.css
Normal file
@ -0,0 +1,118 @@
|
||||
|
||||
div.but_bul_court {
|
||||
width: 17cm;
|
||||
display: grid;
|
||||
grid-template-columns: 6cm 11cm;
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
#infos_etudiant {
|
||||
grid-column: 1;
|
||||
grid-row: 1;
|
||||
border-radius: 3mm;
|
||||
border: 1px solid black;
|
||||
background-color: white;
|
||||
padding: 5mm;
|
||||
}
|
||||
.nom {
|
||||
font-weight: bold;
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
|
||||
#logo {
|
||||
grid-column: 2;
|
||||
grid-row: 1;
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
#logo img {
|
||||
text-align: right;
|
||||
height: 3cm;
|
||||
}
|
||||
|
||||
div.but_bul_court table {
|
||||
border-collapse: collapse;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
div.but_bul_court table th,
|
||||
div.but_bul_court table td {
|
||||
background-color: white;
|
||||
border: 1px solid black; /* Thin black border between cells */
|
||||
padding: 2px 4px 2px 4px; /* Padding inside the cells */
|
||||
}
|
||||
|
||||
table td.col_ue {
|
||||
width: 18mm;
|
||||
}
|
||||
|
||||
#ues {
|
||||
grid-row: 2;
|
||||
grid-column: 1/3;
|
||||
justify-self: end;
|
||||
margin-top: 5mm;
|
||||
margin-bottom: 5mm;
|
||||
}
|
||||
|
||||
#ues tr.titre_table th {
|
||||
background-color: rgb(183,235,255);
|
||||
padding: 2mm;
|
||||
}
|
||||
|
||||
tr.titres_ues td, tr.jury td {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
table.resultats_modules {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#ressources {
|
||||
grid-row: 3;
|
||||
grid-column: 1/3;
|
||||
margin-bottom: 5mm;
|
||||
width: 100%;
|
||||
}
|
||||
#ressources tr.titres_ues td:first-child {
|
||||
background-color: rgb(255, 192, 0);
|
||||
}
|
||||
#saes {
|
||||
grid-row: 4;
|
||||
grid-column: 1/3;
|
||||
margin-bottom: 5mm;
|
||||
width: 100%;
|
||||
}
|
||||
#saes tr.titres_ues td:first-child {
|
||||
background-color: rgb(176, 255, 99);
|
||||
}
|
||||
|
||||
#row_situation {
|
||||
grid-row: 5;
|
||||
grid-column: 1/3;
|
||||
display: grid;
|
||||
grid-template-columns: auto auto;
|
||||
}
|
||||
#cursus_etud, #situation {
|
||||
grid-row: 1;
|
||||
}
|
||||
#situation {
|
||||
background-color: white;
|
||||
justify-self: end;
|
||||
margin-left: 1cm;
|
||||
border-radius: 3mm;
|
||||
border: 1px solid black;
|
||||
padding: 5mm;
|
||||
}
|
||||
|
||||
#footer {
|
||||
grid-row: 6;
|
||||
grid-column: 1/3;
|
||||
margin-top: 5mm;
|
||||
font-size: 9pt;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.but_bul_court .cursus_but {
|
||||
margin-left: 0px;
|
||||
}
|
162
app/templates/but/bulletin_court_page.j2
Normal file
162
app/templates/but/bulletin_court_page.j2
Normal file
@ -0,0 +1,162 @@
|
||||
{% extends "sco_page.j2" %}
|
||||
|
||||
{% block styles %}
|
||||
{{super()}}
|
||||
<link href="{{scu.STATIC_DIR}}/css/jury_but.css" rel="stylesheet" type="text/css" />
|
||||
<link href="{{scu.STATIC_DIR}}/css/cursus_but.css" rel="stylesheet" type="text/css" />
|
||||
<link href="{{scu.STATIC_DIR}}/css/bulletin_court.css" rel="stylesheet" type="text/css" />
|
||||
{% endblock %}
|
||||
|
||||
{% macro table_modules(mod_type, title) -%}
|
||||
<table class="resultats_modules">
|
||||
<thead>
|
||||
<tr class="titre_table">
|
||||
<th colspan="2"></th>
|
||||
<th colspan="{{ bul.ues|length }}">Unités d'enseignement</th>
|
||||
</tr>
|
||||
<tr class="titres_ues">
|
||||
<td colspan="2">{{title}}</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{ue}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for mod in bul[mod_type] %}
|
||||
<tr>
|
||||
<td>{{mod}}</td>
|
||||
<td>{{bul[mod_type][mod].titre}}</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td>{{
|
||||
bul.ues[ue][mod_type][mod].moyenne
|
||||
if mod in bul.ues[ue][mod_type] else ""
|
||||
}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{%- endmacro %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
<div class="but_bul_court">
|
||||
<div id="infos_etudiant">
|
||||
<div class="nom">{{etud.nomprenom}}</div>
|
||||
<div class="formation">BUT {{formsemestre.formation.referentiel_competence.specialite}}</div>
|
||||
{% if formsemestre.etuds_inscriptions[etud.id].parcour %}
|
||||
<div class="parcours">Parcours {{formsemestre.etuds_inscriptions[etud.id].parcour.code}}</div>
|
||||
{% endif %}
|
||||
<div class="annee_scolaire">Année {{formsemestre.annee_scolaire_str()}}</div>
|
||||
<div class="semestre">Semestre {{formsemestre.semestre_id}}</div>
|
||||
</div>
|
||||
|
||||
<div id="logo">
|
||||
{% if logo %}
|
||||
{{logo.html()|safe}}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div id="ues">
|
||||
<table>
|
||||
<thead>
|
||||
<tr class="titre_table">
|
||||
<th colspan="{{ 1 + bul.ues|length }}">Unités d'enseignement du semestre {{formsemestre.semestre_id}}</th>
|
||||
</tr>
|
||||
<tr class="titres_ues">
|
||||
<td></td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{ue}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Moyenne</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].moyenne.value}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Bonus</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].bonus if bul.ues[ue].bonus != "00.00" else ""}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Malus</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].malus if bul.ues[ue].malus != "00.00" else ""}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rang</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].moyenne.rang}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Effectif</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].moyenne.total}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ECTS</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{bul.ues[ue].moyenne.ects}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
<tr class="jury">
|
||||
<td>Jury</td>
|
||||
{% for ue in bul.ues %}
|
||||
<td class="col_ue">{{decision_ues[ue].code}}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="ressources">
|
||||
{{ table_modules("ressources", "Ressources") }}
|
||||
</div>
|
||||
|
||||
<div id="saes">
|
||||
{{ table_modules("saes", "Situations d'Apprentissage et d'Évaluation (SAÉ)") }}
|
||||
</div>
|
||||
|
||||
<div id="row_situation">
|
||||
<div id="cursus_etud">
|
||||
{% include "but/cursus_etud.j2" %}
|
||||
</div>
|
||||
|
||||
<div id="situation">
|
||||
<div>ECTS acquis : {{ects_total}}</div>
|
||||
<div class="descr_jury">
|
||||
{% if bul.semestre.decision_annee %}
|
||||
Jury tenu le {{
|
||||
datetime.datetime.fromisoformat(bul.semestre.decision_annee.date).strftime("%d/%m/%Y à %H:%M")
|
||||
}},
|
||||
année BUT {{bul.semestre.decision_annee.code}}.
|
||||
{% endif %}
|
||||
{% set virg = joiner(", ") %}
|
||||
{% for aut in bul.semestre.autorisation_inscription -%}
|
||||
{% if loop.first %}
|
||||
Autorisé à s'inscrire en
|
||||
{% endif %}
|
||||
{{- virg() }}S{{aut.semestre_id -}}
|
||||
{%- if loop.last -%}
|
||||
.
|
||||
{%- endif -%}
|
||||
{%- endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer">
|
||||
Bulletin généré par ScoDoc le {{time.strftime("%d/%m/%Y à %Hh%M")}}. Explication des codes sur
|
||||
<a href="https://scodoc.org/CodesJuryBUT">https://scodoc.org/CodesJuryBUT</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -35,7 +35,7 @@ from operator import itemgetter
|
||||
import time
|
||||
|
||||
import flask
|
||||
from flask import abort, flash, redirect, render_template, url_for
|
||||
from flask import flash, redirect, render_template, url_for
|
||||
from flask import g, request
|
||||
from flask_login import current_user
|
||||
|
||||
@ -44,6 +44,7 @@ from app import models
|
||||
from app.auth.models import User
|
||||
from app.but import (
|
||||
apc_edit_ue,
|
||||
bulletin_but_court,
|
||||
cursus_but,
|
||||
jury_edit_manual,
|
||||
jury_but,
|
||||
@ -58,7 +59,6 @@ from app.comp import jury, res_sem
|
||||
from app.comp.res_compat import NotesTableCompat
|
||||
from app.models import (
|
||||
Formation,
|
||||
ScolarFormSemestreValidation,
|
||||
ScolarAutorisationInscription,
|
||||
ScolarNews,
|
||||
Scolog,
|
||||
|
@ -3,5 +3,5 @@ Version: x.y.z
|
||||
Architecture: amd64
|
||||
Maintainer: Emmanuel Viennet <emmanuel@viennet.net>
|
||||
Description: ScoDoc 9
|
||||
Un logiciel pour le suivi de la scolarité universitaire.
|
||||
Depends: adduser, curl, gcc, graphviz, graphviz-dev, libpq-dev, postfix|exim4, cracklib-runtime, libcrack2-dev, python3-dev, python3-venv, python3-pip, python3-wheel, nginx, postgresql, libpq-dev, redis, ufw
|
||||
Un logiciel pour le suivi de la scolarité universitaire.
|
||||
Depends: adduser, curl, gcc, graphviz, graphviz-dev, libpq-dev, postfix|exim4, cracklib-runtime, libcrack2-dev, libpango-1.0-0, pango1.0-tools, python3-dev, python3-venv, python3-pip, python3-wheel, nginx, postgresql, libpq-dev, redis, ufw
|
||||
|
Loading…
Reference in New Issue
Block a user