Merge branch 'modif' of https://scodoc.org/git/iziram/ScoDoc into iziram-rev
This commit is contained in:
commit
43849007fb
@ -26,6 +26,7 @@ from flask_mail import Mail
|
|||||||
from flask_bootstrap import Bootstrap
|
from flask_bootstrap import Bootstrap
|
||||||
from flask_moment import Moment
|
from flask_moment import Moment
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
|
from jinja2 import select_autoescape
|
||||||
import sqlalchemy
|
import sqlalchemy
|
||||||
|
|
||||||
from app.scodoc.sco_exceptions import (
|
from app.scodoc.sco_exceptions import (
|
||||||
@ -61,11 +62,11 @@ cache = Cache(
|
|||||||
|
|
||||||
|
|
||||||
def handle_sco_value_error(exc):
|
def handle_sco_value_error(exc):
|
||||||
return render_template("sco_value_error.html", exc=exc), 404
|
return render_template("sco_value_error.j2", exc=exc), 404
|
||||||
|
|
||||||
|
|
||||||
def handle_access_denied(exc):
|
def handle_access_denied(exc):
|
||||||
return render_template("error_access_denied.html", exc=exc), 403
|
return render_template("error_access_denied.j2", exc=exc), 403
|
||||||
|
|
||||||
|
|
||||||
def internal_server_error(exc):
|
def internal_server_error(exc):
|
||||||
@ -75,7 +76,7 @@ def internal_server_error(exc):
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
render_template(
|
render_template(
|
||||||
"error_500.html",
|
"error_500.j2",
|
||||||
SCOVERSION=sco_version.SCOVERSION,
|
SCOVERSION=sco_version.SCOVERSION,
|
||||||
date=datetime.datetime.now().isoformat(),
|
date=datetime.datetime.now().isoformat(),
|
||||||
exc=exc,
|
exc=exc,
|
||||||
@ -146,7 +147,7 @@ def render_raw_html(template_filename: str, **args) -> str:
|
|||||||
|
|
||||||
def postgresql_server_error(e):
|
def postgresql_server_error(e):
|
||||||
"""Erreur de connection au serveur postgresql (voir notesdb.open_db_connection)"""
|
"""Erreur de connection au serveur postgresql (voir notesdb.open_db_connection)"""
|
||||||
return render_raw_html("error_503.html", SCOVERSION=sco_version.SCOVERSION), 503
|
return render_raw_html("error_503.j2", SCOVERSION=sco_version.SCOVERSION), 503
|
||||||
|
|
||||||
|
|
||||||
class LogRequestFormatter(logging.Formatter):
|
class LogRequestFormatter(logging.Formatter):
|
||||||
@ -275,6 +276,9 @@ def create_app(config_class=DevConfig):
|
|||||||
from app.api import api_bp
|
from app.api import api_bp
|
||||||
from app.api import api_web_bp
|
from app.api import api_web_bp
|
||||||
|
|
||||||
|
# Enable autoescaping of all templates, including .j2
|
||||||
|
app.jinja_env.autoescape = select_autoescape(default_for_string=True, default=True)
|
||||||
|
|
||||||
# https://scodoc.fr/ScoDoc
|
# https://scodoc.fr/ScoDoc
|
||||||
app.register_blueprint(scodoc_bp)
|
app.register_blueprint(scodoc_bp)
|
||||||
# https://scodoc.fr/ScoDoc/RT/Scolarite/...
|
# https://scodoc.fr/ScoDoc/RT/Scolarite/...
|
||||||
|
@ -42,6 +42,7 @@ from app.api import (
|
|||||||
formations,
|
formations,
|
||||||
formsemestres,
|
formsemestres,
|
||||||
jury,
|
jury,
|
||||||
|
justificatif,
|
||||||
logos,
|
logos,
|
||||||
partitions,
|
partitions,
|
||||||
users,
|
users,
|
||||||
|
@ -6,23 +6,19 @@
|
|||||||
"""ScoDoc 9 API : Assiduités
|
"""ScoDoc 9 API : Assiduités
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from typing import List
|
|
||||||
from flask import g, jsonify, request
|
from flask import g, jsonify, request
|
||||||
|
|
||||||
from app import db
|
|
||||||
|
|
||||||
from app.api import api_bp as bp, api_web_bp
|
|
||||||
from app.scodoc.sco_utils import json_error
|
|
||||||
from app.decorators import scodoc, permission_required
|
|
||||||
from app.scodoc.sco_permissions import Permission
|
|
||||||
from flask_login import login_required
|
from flask_login import login_required
|
||||||
|
|
||||||
|
|
||||||
from app.models import Identite, Assiduite, FormSemestre, ModuleImpl
|
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
import app.scodoc.sco_utils as scu
|
|
||||||
import app.scodoc.sco_assiduites as scass
|
import app.scodoc.sco_assiduites as scass
|
||||||
|
import app.scodoc.sco_utils as scu
|
||||||
|
from app import db
|
||||||
|
from app.api import api_bp as bp
|
||||||
|
from app.api import api_web_bp
|
||||||
|
from app.decorators import permission_required, scodoc
|
||||||
|
from app.models import Assiduite, FormSemestre, Identite, ModuleImpl
|
||||||
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from app.scodoc.sco_utils import json_error
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/assiduite/<int:assiduite_id>")
|
@bp.route("/assiduite/<int:assiduite_id>")
|
||||||
@ -47,12 +43,11 @@ def assiduite(assiduite_id: int = None):
|
|||||||
query = Assiduite.query.filter_by(id=assiduite_id)
|
query = Assiduite.query.filter_by(id=assiduite_id)
|
||||||
# if g.scodoc_dept:
|
# if g.scodoc_dept:
|
||||||
# query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
# query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
assiduite_query = query.first_or_404()
|
||||||
|
|
||||||
assiduite = query.first_or_404()
|
data = assiduite_query.to_dict()
|
||||||
|
|
||||||
data = assiduite.to_dict()
|
return jsonify(_change_etat(data))
|
||||||
|
|
||||||
return jsonify(change_etat(data))
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/assiduites/<int:etudid>/count", defaults={"with_query": False})
|
@bp.route("/assiduites/<int:etudid>/count", defaults={"with_query": False})
|
||||||
@ -104,15 +99,15 @@ def count_assiduites(etudid: int = None, with_query: bool = False):
|
|||||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
etud: Identite = query.first_or_404(etudid)
|
etud: Identite = query.first_or_404(etudid)
|
||||||
filter: dict[str, object] = {}
|
filtered: dict[str, object] = {}
|
||||||
metric: str = "all"
|
metric: str = "all"
|
||||||
|
|
||||||
if with_query:
|
if with_query:
|
||||||
metric, filter = count_manager(request)
|
metric, filtered = _count_manager(request)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
scass.get_assiduites_stats(
|
scass.get_assiduites_stats(
|
||||||
assiduites=etud.assiduites, metric=metric, filter=filter
|
assiduites=etud.assiduites, metric=metric, filtered=filtered
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,15 +157,15 @@ def assiduites(etudid: int = None, with_query: bool = False):
|
|||||||
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
etud: Identite = query.first_or_404(etudid)
|
etud: Identite = query.first_or_404(etudid)
|
||||||
assiduites = etud.assiduites
|
assiduites_query = etud.assiduites
|
||||||
|
|
||||||
if with_query:
|
if with_query:
|
||||||
assiduites = filter_manager(request, assiduites)
|
assiduites_query = _filter_manager(request, assiduites_query)
|
||||||
|
|
||||||
data_set: List[dict] = []
|
data_set: list[dict] = []
|
||||||
for ass in assiduites.all():
|
for ass in assiduites_query.all():
|
||||||
data = ass.to_dict()
|
data = ass.to_dict()
|
||||||
data_set.append(change_etat(data))
|
data_set.append(_change_etat(data))
|
||||||
|
|
||||||
return jsonify(data_set)
|
return jsonify(data_set)
|
||||||
|
|
||||||
@ -200,19 +195,15 @@ def assiduites_formsemestre(formsemestre_id: int, with_query: bool = False):
|
|||||||
if formsemestre is None:
|
if formsemestre is None:
|
||||||
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
|
return json_error(404, "le paramètre 'formsemestre_id' n'existe pas")
|
||||||
|
|
||||||
etuds = formsemestre.etuds.all()
|
assiduites_query = scass.filter_by_formsemestre(Assiduite.query, formsemestre)
|
||||||
etuds_id = [etud.id for etud in etuds]
|
|
||||||
|
|
||||||
assiduites = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
|
|
||||||
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
|
|
||||||
|
|
||||||
if with_query:
|
if with_query:
|
||||||
assiduites = filter_manager(request, assiduites)
|
assiduites_query = _filter_manager(request, assiduites_query)
|
||||||
|
|
||||||
data_set: List[dict] = []
|
data_set: list[dict] = []
|
||||||
for ass in assiduites.all():
|
for ass in assiduites_query.all():
|
||||||
data = ass.to_dict()
|
data = ass.to_dict()
|
||||||
data_set.append(change_etat(data))
|
data_set.append(_change_etat(data))
|
||||||
|
|
||||||
return jsonify(data_set)
|
return jsonify(data_set)
|
||||||
|
|
||||||
@ -249,14 +240,14 @@ def count_assiduites_formsemestre(
|
|||||||
etuds = formsemestre.etuds.all()
|
etuds = formsemestre.etuds.all()
|
||||||
etuds_id = [etud.id for etud in etuds]
|
etuds_id = [etud.id for etud in etuds]
|
||||||
|
|
||||||
assiduites = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
|
assiduites_query = Assiduite.query.filter(Assiduite.etudid.in_(etuds_id))
|
||||||
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
|
assiduites_query = scass.filter_by_formsemestre(assiduites_query, formsemestre)
|
||||||
metric: str = "all"
|
metric: str = "all"
|
||||||
filter: dict = {}
|
filtered: dict = {}
|
||||||
if with_query:
|
if with_query:
|
||||||
metric, filter = count_manager(request)
|
metric, filtered = _count_manager(request)
|
||||||
|
|
||||||
return jsonify(scass.get_assiduites_stats(assiduites, metric, filter))
|
return jsonify(scass.get_assiduites_stats(assiduites_query, metric, filtered))
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/assiduite/<int:etudid>/create", methods=["POST"])
|
@bp.route("/assiduite/<int:etudid>/create", methods=["POST"])
|
||||||
@ -265,31 +256,38 @@ def count_assiduites_formsemestre(
|
|||||||
@login_required
|
@login_required
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
# @permission_required(Permission.ScoAssiduiteChange)
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
def create(etudid: int = None):
|
def assiduite_create(etudid: int = None):
|
||||||
"""
|
"""
|
||||||
Création d'une assiduité pour l'étudiant (etudid)
|
Création d'une assiduité pour l'étudiant (etudid)
|
||||||
La requête doit avoir un content type "application/json":
|
La requête doit avoir un content type "application/json":
|
||||||
|
[
|
||||||
{
|
{
|
||||||
"date_debut": str,
|
"date_debut": str,
|
||||||
"date_fin": str,
|
"date_fin": str,
|
||||||
"etat": str,
|
"etat": str,
|
||||||
}
|
},
|
||||||
ou
|
|
||||||
{
|
{
|
||||||
"date_debut": str,
|
"date_debut": str,
|
||||||
"date_fin": str,
|
"date_fin": str,
|
||||||
"etat": str,
|
"etat": str,
|
||||||
"moduleimpl_id": int,
|
"moduleimpl_id": int,
|
||||||
|
"desc":str,
|
||||||
}
|
}
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
etud: Identite = Identite.query.filter_by(id=etudid).first_or_404()
|
etud: Identite = Identite.query.filter_by(id=etudid).first_or_404()
|
||||||
|
|
||||||
|
create_list: list[object] = request.get_json(force=True)
|
||||||
|
|
||||||
|
if not isinstance(create_list, list):
|
||||||
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
||||||
|
|
||||||
errors: dict[int, str] = {}
|
errors: dict[int, str] = {}
|
||||||
success: dict[int, object] = {}
|
success: dict[int, object] = {}
|
||||||
for i, data in enumerate(request.get_json(force=True)):
|
for i, data in enumerate(create_list):
|
||||||
code, obj = create_singular(data, etud)
|
code, obj = _create_singular(data, etud)
|
||||||
if code == 404:
|
if code == 404:
|
||||||
errors[i] = obj
|
errors[i] = obj
|
||||||
else:
|
else:
|
||||||
@ -298,21 +296,21 @@ def create(etudid: int = None):
|
|||||||
return jsonify({"errors": errors, "success": success})
|
return jsonify({"errors": errors, "success": success})
|
||||||
|
|
||||||
|
|
||||||
def create_singular(
|
def _create_singular(
|
||||||
data: dict,
|
data: dict,
|
||||||
etud: Identite,
|
etud: Identite,
|
||||||
) -> tuple[int, object]:
|
) -> tuple[int, object]:
|
||||||
errors: List[str] = []
|
errors: list[str] = []
|
||||||
|
|
||||||
# -- vérifications de l'objet json --
|
# -- vérifications de l'objet json --
|
||||||
# cas 1 : ETAT
|
# cas 1 : ETAT
|
||||||
etat = data.get("etat", None)
|
etat = data.get("etat", None)
|
||||||
if etat is None:
|
if etat is None:
|
||||||
errors.append("param 'etat': manquant")
|
errors.append("param 'etat': manquant")
|
||||||
elif etat not in scu.ETATS_ASSIDUITE.keys():
|
elif etat not in scu.ETATS_ASSIDUITE:
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
|
|
||||||
data = change_etat(data, False)
|
data = _change_etat(data, False)
|
||||||
etat = data.get("etat", None)
|
etat = data.get("etat", None)
|
||||||
|
|
||||||
# cas 2 : date_debut
|
# cas 2 : date_debut
|
||||||
@ -329,7 +327,7 @@ def create_singular(
|
|||||||
errors.append("param 'date_fin': manquant")
|
errors.append("param 'date_fin': manquant")
|
||||||
fin = scu.is_iso_formated(date_fin, convert=True)
|
fin = scu.is_iso_formated(date_fin, convert=True)
|
||||||
if fin is None:
|
if fin is None:
|
||||||
errors.append(f"param 'date_fin': format invalide")
|
errors.append("param 'date_fin': format invalide")
|
||||||
|
|
||||||
# cas 4 : moduleimpl_id
|
# cas 4 : moduleimpl_id
|
||||||
|
|
||||||
@ -345,7 +343,7 @@ def create_singular(
|
|||||||
|
|
||||||
desc: str = data.get("desc", None)
|
desc: str = data.get("desc", None)
|
||||||
|
|
||||||
if errors != []:
|
if errors:
|
||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
return (404, err)
|
return (404, err)
|
||||||
|
|
||||||
@ -358,6 +356,7 @@ def create_singular(
|
|||||||
etat=etat,
|
etat=etat,
|
||||||
etud=etud,
|
etud=etud,
|
||||||
moduleimpl=moduleimpl,
|
moduleimpl=moduleimpl,
|
||||||
|
description=desc,
|
||||||
)
|
)
|
||||||
|
|
||||||
db.session.add(nouv_assiduite)
|
db.session.add(nouv_assiduite)
|
||||||
@ -376,15 +375,27 @@ def create_singular(
|
|||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
# @permission_required(Permission.ScoAssiduiteChange)
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
def delete():
|
def assiduite_cdelete():
|
||||||
"""
|
"""
|
||||||
Suppression d'une assiduité à partir de son id
|
Suppression d'une assiduité à partir de son id
|
||||||
|
|
||||||
|
Forme des données envoyées :
|
||||||
|
|
||||||
|
[
|
||||||
|
<assiduite_id:int>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
assiduites: list[int] = request.get_json(force=True)
|
assiduites_list: list[int] = request.get_json(force=True)
|
||||||
|
if not isinstance(assiduites_list, list):
|
||||||
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
||||||
|
|
||||||
output = {"errors": {}, "success": {}}
|
output = {"errors": {}, "success": {}}
|
||||||
|
|
||||||
for i, ass in enumerate(assiduites):
|
for i, ass in enumerate(assiduites_list):
|
||||||
code, msg = delete_singular(ass, db)
|
code, msg = _delete_singular(ass, db)
|
||||||
if code == 404:
|
if code == 404:
|
||||||
output["errors"][f"{i}"] = msg
|
output["errors"][f"{i}"] = msg
|
||||||
else:
|
else:
|
||||||
@ -393,11 +404,11 @@ def delete():
|
|||||||
return jsonify(output)
|
return jsonify(output)
|
||||||
|
|
||||||
|
|
||||||
def delete_singular(assiduite_id: int, db):
|
def _delete_singular(assiduite_id: int, database):
|
||||||
assiduite: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
|
assiduite_unique: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first()
|
||||||
if assiduite is None:
|
if assiduite_unique is None:
|
||||||
return (404, "Assiduite non existante")
|
return (404, "Assiduite non existante")
|
||||||
db.session.delete(assiduite)
|
database.session.delete(assiduite_unique)
|
||||||
return (200, "OK")
|
return (200, "OK")
|
||||||
|
|
||||||
|
|
||||||
@ -407,28 +418,31 @@ def delete_singular(assiduite_id: int, db):
|
|||||||
@scodoc
|
@scodoc
|
||||||
@permission_required(Permission.ScoView)
|
@permission_required(Permission.ScoView)
|
||||||
# @permission_required(Permission.ScoAssiduiteChange)
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
def edit(assiduite_id: int):
|
def assiduite_cedit(assiduite_id: int):
|
||||||
"""
|
"""
|
||||||
Edition d'une assiduité à partir de son id
|
Edition d'une assiduité à partir de son id
|
||||||
La requête doit avoir un content type "application/json":
|
La requête doit avoir un content type "application/json":
|
||||||
{
|
{
|
||||||
"etat": str,
|
"etat"?: str,
|
||||||
"moduleimpl_id": int
|
"moduleimpl_id"?: int
|
||||||
|
"desc"?: str
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
assiduite: Assiduite = Assiduite.query.filter_by(id=assiduite_id).first_or_404()
|
assiduite_unique: Assiduite = Assiduite.query.filter_by(
|
||||||
errors: List[str] = []
|
id=assiduite_id
|
||||||
|
).first_or_404()
|
||||||
|
errors: list[str] = []
|
||||||
data = request.get_json(force=True)
|
data = request.get_json(force=True)
|
||||||
|
|
||||||
# Vérifications de data
|
# Vérifications de data
|
||||||
|
|
||||||
# Cas 1 : Etat
|
# Cas 1 : Etat
|
||||||
if data.get("etat") is not None:
|
if data.get("etat") is not None:
|
||||||
data = change_etat(data, False)
|
data = _change_etat(data, False)
|
||||||
if data.get("etat") is None:
|
if data.get("etat") is None:
|
||||||
errors.append("param 'etat': invalide")
|
errors.append("param 'etat': invalide")
|
||||||
else:
|
else:
|
||||||
assiduite.etat = data.get("etat")
|
assiduite_unique.etat = data.get("etat")
|
||||||
|
|
||||||
# Cas 2 : Moduleimpl_id
|
# Cas 2 : Moduleimpl_id
|
||||||
moduleimpl_id = data.get("moduleimpl_id", False)
|
moduleimpl_id = data.get("moduleimpl_id", False)
|
||||||
@ -441,24 +455,30 @@ def edit(assiduite_id: int):
|
|||||||
errors.append("param 'moduleimpl_id': invalide")
|
errors.append("param 'moduleimpl_id': invalide")
|
||||||
else:
|
else:
|
||||||
if not moduleimpl.est_inscrit(
|
if not moduleimpl.est_inscrit(
|
||||||
Identite.query.filter_by(id=assiduite.etudid).first()
|
Identite.query.filter_by(id=assiduite_unique.etudid).first()
|
||||||
):
|
):
|
||||||
errors.append("param 'moduleimpl_id': etud non inscrit")
|
errors.append("param 'moduleimpl_id': etud non inscrit")
|
||||||
else:
|
else:
|
||||||
assiduite.moduleimpl_id = moduleimpl_id
|
assiduite_unique.moduleimpl_id = moduleimpl_id
|
||||||
else:
|
else:
|
||||||
assiduite.moduleimpl_id = moduleimpl_id
|
assiduite_unique.moduleimpl_id = moduleimpl_id
|
||||||
if errors != []:
|
|
||||||
|
# Cas 3 : desc
|
||||||
|
desc = data.get("desc", False)
|
||||||
|
if desc is not False:
|
||||||
|
assiduite_unique.desc = desc
|
||||||
|
|
||||||
|
if errors:
|
||||||
err: str = ", ".join(errors)
|
err: str = ", ".join(errors)
|
||||||
return json_error(404, err)
|
return json_error(404, err)
|
||||||
|
|
||||||
db.session.add(assiduite)
|
db.session.add(assiduite_unique)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return jsonify({"OK": True})
|
return jsonify({"OK": True})
|
||||||
|
|
||||||
|
|
||||||
# -- Utils --
|
# -- Utils --
|
||||||
def change_etat(data: dict, from_int: bool = True):
|
def _change_etat(data: dict, from_int: bool = True):
|
||||||
"""change dans un json la valeur du champs état"""
|
"""change dans un json la valeur du champs état"""
|
||||||
if from_int:
|
if from_int:
|
||||||
data["etat"] = scu.ETAT_ASSIDUITE_NAME.get(data["etat"])
|
data["etat"] = scu.ETAT_ASSIDUITE_NAME.get(data["etat"])
|
||||||
@ -467,104 +487,108 @@ def change_etat(data: dict, from_int: bool = True):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def count_manager(request) -> tuple[str, dict]:
|
def _count_manager(requested) -> tuple[str, dict]:
|
||||||
"""
|
"""
|
||||||
Retourne la/les métriques à utiliser ainsi que le filtre donnés en query de la requête
|
Retourne la/les métriques à utiliser ainsi que le filtre donnés en query de la requête
|
||||||
"""
|
"""
|
||||||
filter: dict = {}
|
filtered: dict = {}
|
||||||
# cas 1 : etat assiduite
|
# cas 1 : etat assiduite
|
||||||
etat = request.args.get("etat")
|
etat = requested.args.get("etat")
|
||||||
if etat is not None:
|
if etat is not None:
|
||||||
filter["etat"] = etat
|
filtered["etat"] = etat
|
||||||
|
|
||||||
# cas 2 : date de début
|
# cas 2 : date de début
|
||||||
deb = request.args.get("date_debut")
|
deb = requested.args.get("date_debut")
|
||||||
deb: datetime = scu.is_iso_formated(deb, True)
|
deb: datetime = scu.is_iso_formated(deb, True)
|
||||||
if deb is not None:
|
if deb is not None:
|
||||||
filter["date_debut"] = deb
|
filtered["date_debut"] = deb
|
||||||
|
|
||||||
# cas 3 : date de fin
|
# cas 3 : date de fin
|
||||||
fin = request.args.get("date_fin")
|
fin = requested.args.get("date_fin")
|
||||||
fin = scu.is_iso_formated(fin, True)
|
fin = scu.is_iso_formated(fin, True)
|
||||||
|
|
||||||
if fin is not None:
|
if fin is not None:
|
||||||
filter["date_fin"] = fin
|
filtered["date_fin"] = fin
|
||||||
|
|
||||||
# cas 4 : moduleimpl_id
|
# cas 4 : moduleimpl_id
|
||||||
module = request.args.get("moduleimpl_id", False)
|
module = requested.args.get("moduleimpl_id", False)
|
||||||
try:
|
try:
|
||||||
if module is False:
|
if module is False:
|
||||||
raise Exception
|
raise ValueError
|
||||||
if module != "":
|
if module != "":
|
||||||
module = int(module)
|
module = int(module)
|
||||||
else:
|
else:
|
||||||
module = None
|
module = None
|
||||||
except Exception:
|
except ValueError:
|
||||||
module = False
|
module = False
|
||||||
|
|
||||||
if module is not False:
|
if module is not False:
|
||||||
filter["moduleimpl_id"] = module
|
filtered["moduleimpl_id"] = module
|
||||||
|
|
||||||
# cas 5 : formsemestre_id
|
# cas 5 : formsemestre_id
|
||||||
formsemestre_id = request.args.get("formsemestre_id")
|
formsemestre_id = requested.args.get("formsemestre_id")
|
||||||
|
|
||||||
if formsemestre_id is not None:
|
if formsemestre_id is not None:
|
||||||
formsemestre: FormSemestre = None
|
formsemestre: FormSemestre = None
|
||||||
formsemestre_id = int(formsemestre_id)
|
formsemestre_id = int(formsemestre_id)
|
||||||
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
||||||
filter["formsemestre"] = formsemestre
|
filtered["formsemestre"] = formsemestre
|
||||||
|
|
||||||
# cas 6 : type
|
# cas 6 : type
|
||||||
metric = request.args.get("metric", "all")
|
metric = requested.args.get("metric", "all")
|
||||||
|
|
||||||
return (metric, filter)
|
return (metric, filtered)
|
||||||
|
|
||||||
|
|
||||||
def filter_manager(request, assiduites):
|
def _filter_manager(requested, assiduites_query):
|
||||||
"""
|
"""
|
||||||
Retourne les assiduites entrées filtrées en fonction de la request
|
Retourne les assiduites entrées filtrées en fonction de la request
|
||||||
"""
|
"""
|
||||||
# cas 1 : etat assiduite
|
# cas 1 : etat assiduite
|
||||||
etat = request.args.get("etat")
|
etat = requested.args.get("etat")
|
||||||
if etat is not None:
|
if etat is not None:
|
||||||
assiduites = scass.filter_by_etat(assiduites, etat)
|
assiduites_query = scass.filter_assiduites_by_etat(assiduites_query, etat)
|
||||||
|
|
||||||
# cas 2 : date de début
|
# cas 2 : date de début
|
||||||
deb = request.args.get("date_debut")
|
deb = requested.args.get("date_debut")
|
||||||
deb: datetime = scu.is_iso_formated(deb, True)
|
deb: datetime = scu.is_iso_formated(deb, True)
|
||||||
if deb is not None:
|
if deb is not None:
|
||||||
|
|
||||||
assiduites = scass.filter_by_date(assiduites, deb, sup=True)
|
assiduites_query = scass.filter_assiduites_by_date(
|
||||||
|
assiduites_query, deb, sup=True
|
||||||
|
)
|
||||||
|
|
||||||
# cas 3 : date de fin
|
# cas 3 : date de fin
|
||||||
fin = request.args.get("date_fin")
|
fin = requested.args.get("date_fin")
|
||||||
fin = scu.is_iso_formated(fin, True)
|
fin = scu.is_iso_formated(fin, True)
|
||||||
|
|
||||||
if fin is not None:
|
if fin is not None:
|
||||||
assiduites = scass.filter_by_date(assiduites, fin, sup=False)
|
assiduites_query = scass.filter_assiduites_by_date(
|
||||||
|
assiduites_query, fin, sup=False
|
||||||
|
)
|
||||||
|
|
||||||
# cas 4 : moduleimpl_id
|
# cas 4 : moduleimpl_id
|
||||||
module = request.args.get("moduleimpl_id", False)
|
module = requested.args.get("moduleimpl_id", False)
|
||||||
try:
|
try:
|
||||||
if module is False:
|
if module is False:
|
||||||
raise Exception
|
raise ValueError
|
||||||
if module != "":
|
if module != "":
|
||||||
module = int(module)
|
module = int(module)
|
||||||
else:
|
else:
|
||||||
module = None
|
module = None
|
||||||
except Exception:
|
except ValueError:
|
||||||
module = False
|
module = False
|
||||||
|
|
||||||
if module is not False:
|
if module is not False:
|
||||||
assiduites = scass.filter_by_module_impl(assiduites, module)
|
assiduites_query = scass.filter_by_module_impl(assiduites_query, module)
|
||||||
|
|
||||||
# cas 5 : formsemestre_id
|
# cas 5 : formsemestre_id
|
||||||
formsemestre_id = request.args.get("formsemestre_id")
|
formsemestre_id = requested.args.get("formsemestre_id")
|
||||||
|
|
||||||
if formsemestre_id is not None:
|
if formsemestre_id is not None:
|
||||||
formsemestre: FormSemestre = None
|
formsemestre: FormSemestre = None
|
||||||
formsemestre_id = int(formsemestre_id)
|
formsemestre_id = int(formsemestre_id)
|
||||||
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first()
|
||||||
assiduites = scass.filter_by_formsemstre(assiduites, formsemestre)
|
assiduites_query = scass.filter_by_formsemestre(assiduites_query, formsemestre)
|
||||||
|
|
||||||
return assiduites
|
return assiduites_query
|
||||||
|
536
app/api/justificatif.py
Normal file
536
app/api/justificatif.py
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
##############################################################################
|
||||||
|
# ScoDoc
|
||||||
|
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
|
||||||
|
# See LICENSE
|
||||||
|
##############################################################################
|
||||||
|
"""ScoDoc 9 API : Assiduités
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import app.scodoc.sco_assiduites as scass
|
||||||
|
import app.scodoc.sco_utils as scu
|
||||||
|
from app import db
|
||||||
|
|
||||||
|
from app.api import api_bp as bp
|
||||||
|
from app.api import api_web_bp
|
||||||
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
from app.decorators import permission_required, scodoc
|
||||||
|
from app.models import Identite, Justificatif
|
||||||
|
from app.scodoc.sco_archives_justificatifs import JustificatifArchiver
|
||||||
|
from app.scodoc.sco_permissions import Permission
|
||||||
|
from flask import g, jsonify, request
|
||||||
|
from flask_login import login_required
|
||||||
|
from app.scodoc.sco_utils import json_error
|
||||||
|
|
||||||
|
|
||||||
|
# @bp.route("/justificatif/remove")
|
||||||
|
# @api_web_bp.route("/justificatif/remove")
|
||||||
|
# @scodoc
|
||||||
|
# def justremove():
|
||||||
|
# """ """
|
||||||
|
# archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
|
||||||
|
# archiver.delete_justificatif(etudid=1, archive_id="2023-02-01-10-29-20")
|
||||||
|
# return jsonify("done")
|
||||||
|
|
||||||
|
# Partie Modèle
|
||||||
|
# TODO: justificatif
|
||||||
|
@bp.route("/justificatif/<int:justif_id>")
|
||||||
|
@api_web_bp.route("/assiduite/<int:justif_id>")
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def justificatif(justif_id: int = None):
|
||||||
|
"""Retourne un objet justificatif à partir de son id
|
||||||
|
|
||||||
|
Exemple de résultat:
|
||||||
|
{
|
||||||
|
"justif_id": 1,
|
||||||
|
"etudid": 2,
|
||||||
|
"date_debut": "2022-10-31T08:00+01:00",
|
||||||
|
"date_fin": "2022-10-31T10:00+01:00",
|
||||||
|
"etat": "valide",
|
||||||
|
"fichier": "archive_id",
|
||||||
|
"raison": "une raison",
|
||||||
|
"entry_date": "2022-10-31T08:00+01:00",
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
justificatif_unique = query.first_or_404()
|
||||||
|
|
||||||
|
data = justificatif_unique.to_dict()
|
||||||
|
|
||||||
|
return jsonify(_change_etat(data))
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatifs[-query]
|
||||||
|
@bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
||||||
|
@bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
||||||
|
@api_web_bp.route("/justificatifs/<int:etudid>", defaults={"with_query": False})
|
||||||
|
@api_web_bp.route("/justificatifs/<int:etudid>/query", defaults={"with_query": True})
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
def justificatifs(etudid: int = None, with_query: bool = False):
|
||||||
|
"""
|
||||||
|
Retourne toutes les assiduités d'un étudiant
|
||||||
|
chemin : /justificatifs/<int:etudid>
|
||||||
|
|
||||||
|
Un filtrage peut être donné avec une query
|
||||||
|
chemin : /justificatifs/<int:etudid>/query?
|
||||||
|
|
||||||
|
Les différents filtres :
|
||||||
|
Etat (etat du justificatif -> validé, non validé, modifé, en attente):
|
||||||
|
query?etat=[- liste des états séparé par une virgule -]
|
||||||
|
ex: .../query?etat=validé,modifié
|
||||||
|
Date debut
|
||||||
|
(date de début du justificatif, sont affichés les justificatifs
|
||||||
|
dont la date de début est supérieur ou égale à la valeur donnée):
|
||||||
|
query?date_debut=[- date au format iso -]
|
||||||
|
ex: query?date_debut=2022-11-03T08:00+01:00
|
||||||
|
Date fin
|
||||||
|
(date de fin du justificatif, sont affichés les justificatifs
|
||||||
|
dont la date de fin est inférieure ou égale à la valeur donnée):
|
||||||
|
query?date_fin=[- date au format iso -]
|
||||||
|
ex: query?date_fin=2022-11-03T10:00+01:00
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = Identite.query.filter_by(id=etudid)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
etud: Identite = query.first_or_404(etudid)
|
||||||
|
justificatifs_query = etud.justificatifs
|
||||||
|
|
||||||
|
if with_query:
|
||||||
|
justificatifs_query = _filter_manager(request, justificatifs_query)
|
||||||
|
|
||||||
|
data_set: list[dict] = []
|
||||||
|
for just in justificatifs_query.all():
|
||||||
|
data = just.to_dict()
|
||||||
|
data_set.append(_change_etat(data))
|
||||||
|
|
||||||
|
return jsonify(data_set)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-create
|
||||||
|
@bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
|
@api_web_bp.route("/justificatif/<int:etudid>/create", methods=["POST"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_create(etudid: int = None):
|
||||||
|
"""
|
||||||
|
Création d'un justificatif pour l'étudiant (etudid)
|
||||||
|
La requête doit avoir un content type "application/json":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"date_debut": str,
|
||||||
|
"date_fin": str,
|
||||||
|
"etat": str,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"date_debut": str,
|
||||||
|
"date_fin": str,
|
||||||
|
"etat": str,
|
||||||
|
"raison":str,
|
||||||
|
}
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
"""
|
||||||
|
etud: Identite = Identite.query.filter_by(id=etudid).first_or_404()
|
||||||
|
|
||||||
|
create_list: list[object] = request.get_json(force=True)
|
||||||
|
|
||||||
|
if not isinstance(create_list, list):
|
||||||
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
||||||
|
|
||||||
|
errors: dict[int, str] = {}
|
||||||
|
success: dict[int, object] = {}
|
||||||
|
for i, data in enumerate(create_list):
|
||||||
|
code, obj = _create_singular(data, etud)
|
||||||
|
if code == 404:
|
||||||
|
errors[i] = obj
|
||||||
|
else:
|
||||||
|
success[i] = obj
|
||||||
|
|
||||||
|
return jsonify({"errors": errors, "success": success})
|
||||||
|
|
||||||
|
|
||||||
|
def _create_singular(
|
||||||
|
data: dict,
|
||||||
|
etud: Identite,
|
||||||
|
) -> tuple[int, object]:
|
||||||
|
errors: list[str] = []
|
||||||
|
|
||||||
|
# -- vérifications de l'objet json --
|
||||||
|
# cas 1 : ETAT
|
||||||
|
etat = data.get("etat", None)
|
||||||
|
if etat is None:
|
||||||
|
errors.append("param 'etat': manquant")
|
||||||
|
elif etat not in scu.ETATS_JUSTIFICATIF:
|
||||||
|
errors.append("param 'etat': invalide")
|
||||||
|
|
||||||
|
data = _change_etat(data, False)
|
||||||
|
etat = data.get("etat", None)
|
||||||
|
|
||||||
|
# cas 2 : date_debut
|
||||||
|
date_debut = data.get("date_debut", None)
|
||||||
|
if date_debut is None:
|
||||||
|
errors.append("param 'date_debut': manquant")
|
||||||
|
deb = scu.is_iso_formated(date_debut, convert=True)
|
||||||
|
if deb is None:
|
||||||
|
errors.append("param 'date_debut': format invalide")
|
||||||
|
|
||||||
|
# cas 3 : date_fin
|
||||||
|
date_fin = data.get("date_fin", None)
|
||||||
|
if date_fin is None:
|
||||||
|
errors.append("param 'date_fin': manquant")
|
||||||
|
fin = scu.is_iso_formated(date_fin, convert=True)
|
||||||
|
if fin is None:
|
||||||
|
errors.append("param 'date_fin': format invalide")
|
||||||
|
|
||||||
|
# cas 4 : raison
|
||||||
|
|
||||||
|
raison: str = data.get("raison", None)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
err: str = ", ".join(errors)
|
||||||
|
return (404, err)
|
||||||
|
|
||||||
|
# TOUT EST OK
|
||||||
|
|
||||||
|
try:
|
||||||
|
nouv_justificatif: Justificatif = Justificatif.create_justificatif(
|
||||||
|
date_debut=deb,
|
||||||
|
date_fin=fin,
|
||||||
|
etat=etat,
|
||||||
|
etud=etud,
|
||||||
|
raison=raison,
|
||||||
|
)
|
||||||
|
|
||||||
|
db.session.add(nouv_justificatif)
|
||||||
|
db.session.commit()
|
||||||
|
return (200, {"justif_id": nouv_justificatif.id})
|
||||||
|
except ScoValueError as excp:
|
||||||
|
return (
|
||||||
|
404,
|
||||||
|
excp.args[0],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-edit
|
||||||
|
@bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
||||||
|
@api_web_bp.route("/justificatif/<int:justif_id>/edit", methods=["POST"])
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_edit(justif_id: int):
|
||||||
|
"""
|
||||||
|
Edition d'un justificatif à partir de son id
|
||||||
|
La requête doit avoir un content type "application/json":
|
||||||
|
{
|
||||||
|
"etat"?: str,
|
||||||
|
"raison"?: str
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
justificatif_unique: Justificatif = Justificatif.query.filter_by(
|
||||||
|
id=justif_id
|
||||||
|
).first_or_404()
|
||||||
|
errors: list[str] = []
|
||||||
|
data = request.get_json(force=True)
|
||||||
|
|
||||||
|
# Vérifications de data
|
||||||
|
|
||||||
|
# Cas 1 : Etat
|
||||||
|
if data.get("etat") is not None:
|
||||||
|
data = _change_etat(data, False)
|
||||||
|
if data.get("etat") is None:
|
||||||
|
errors.append("param 'etat': invalide")
|
||||||
|
else:
|
||||||
|
justificatif_unique.etat = data.get("etat")
|
||||||
|
|
||||||
|
# Cas 2 : raison
|
||||||
|
raison = data.get("raison", False)
|
||||||
|
if raison is not False:
|
||||||
|
justificatif_unique.raison = raison
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
err: str = ", ".join(errors)
|
||||||
|
return json_error(404, err)
|
||||||
|
|
||||||
|
db.session.add(justificatif_unique)
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify({"OK": True})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-delete
|
||||||
|
@bp.route("/justificatif/delete", methods=["POST"])
|
||||||
|
@api_web_bp.route("/justificatif/delete", methods=["POST"])
|
||||||
|
@login_required
|
||||||
|
@scodoc
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_delete():
|
||||||
|
"""
|
||||||
|
Suppression d'un justificatif à partir de son id
|
||||||
|
|
||||||
|
Forme des données envoyées :
|
||||||
|
|
||||||
|
[
|
||||||
|
<justif_id:int>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
justificatifs_list: list[int] = request.get_json(force=True)
|
||||||
|
if not isinstance(justificatifs_list, list):
|
||||||
|
return json_error(404, "Le contenu envoyé n'est pas une liste")
|
||||||
|
|
||||||
|
output = {"errors": {}, "success": {}}
|
||||||
|
|
||||||
|
for i, ass in enumerate(justificatifs_list):
|
||||||
|
code, msg = _delete_singular(ass, db)
|
||||||
|
if code == 404:
|
||||||
|
output["errors"][f"{i}"] = msg
|
||||||
|
else:
|
||||||
|
output["success"][f"{i}"] = {"OK": True}
|
||||||
|
db.session.commit()
|
||||||
|
return jsonify(output)
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_singular(justif_id: int, database):
|
||||||
|
justificatif_unique: Justificatif = Justificatif.query.filter_by(
|
||||||
|
id=justif_id
|
||||||
|
).first()
|
||||||
|
if justificatif_unique is None:
|
||||||
|
return (404, "Justificatif non existant")
|
||||||
|
database.session.delete(justificatif_unique)
|
||||||
|
return (200, "OK")
|
||||||
|
|
||||||
|
|
||||||
|
# Partie archivage
|
||||||
|
# TODO: justificatif-import
|
||||||
|
@bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
||||||
|
@api_web_bp.route("/justificatif/import/<int:justif_id>", methods=["POST"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_import(justif_id: int = None):
|
||||||
|
"""
|
||||||
|
Importation d'un fichier (création d'archive)
|
||||||
|
"""
|
||||||
|
if len(request.files) == 0:
|
||||||
|
return json_error(404, "Il n'y a pas de fichier joint")
|
||||||
|
|
||||||
|
file = list(request.files.values())[0]
|
||||||
|
if file.filename == "":
|
||||||
|
return json_error(404, "Il n'y a pas de fichier joint")
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
justificatif_unique: Justificatif = query.first_or_404()
|
||||||
|
|
||||||
|
archive_name: str = justificatif_unique.fichier
|
||||||
|
|
||||||
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
try:
|
||||||
|
archive_name: str = archiver.save_justificatif(
|
||||||
|
etudid=justificatif_unique.etudid,
|
||||||
|
filename=file.filename,
|
||||||
|
data=file.stream.read(),
|
||||||
|
archive_name=archive_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
justificatif_unique.fichier = archive_name
|
||||||
|
|
||||||
|
db.session.add(justificatif_unique)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
return jsonify({"response": "imported"})
|
||||||
|
except ScoValueError as err:
|
||||||
|
return json_error(404, err.args[1])
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-export
|
||||||
|
@bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
||||||
|
@api_web_bp.route("/justificatif/export/<int:justif_id>/<filename>", methods=["GET"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_export(justif_id: int = None, filename: str = None):
|
||||||
|
"""
|
||||||
|
Retourne un fichier d'une archive d'un justificatif
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
justificatif_unique: Justificatif = query.first_or_404()
|
||||||
|
|
||||||
|
archive_name: str = justificatif_unique.fichier
|
||||||
|
if archive_name is None:
|
||||||
|
return json_error(404, "le justificatif ne possède pas de fichier")
|
||||||
|
|
||||||
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
|
||||||
|
try:
|
||||||
|
return archiver.get_justificatif_file(
|
||||||
|
archive_name, justificatif_unique.etudid, filename
|
||||||
|
)
|
||||||
|
except ScoValueError as err:
|
||||||
|
return json_error(404, err.args[1])
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-remove
|
||||||
|
@bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
||||||
|
@api_web_bp.route("/justificatif/remove/<int:justif_id>", methods=["POST"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_remove(justif_id: int = None):
|
||||||
|
"""
|
||||||
|
Supression d'un fichier ou d'une archive
|
||||||
|
|
||||||
|
{
|
||||||
|
"remove": <"all"/"list">
|
||||||
|
|
||||||
|
"filenames"?: [
|
||||||
|
<filename:str>,
|
||||||
|
...
|
||||||
|
]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
data: dict = request.get_json(force=True)
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
justificatif_unique: Justificatif = query.first_or_404()
|
||||||
|
|
||||||
|
archive_name: str = justificatif_unique.fichier
|
||||||
|
if archive_name is None:
|
||||||
|
return json_error(404, "le justificatif ne possède pas de fichier")
|
||||||
|
|
||||||
|
remove: str = data.get("remove")
|
||||||
|
if remove is None or remove not in ("all", "list"):
|
||||||
|
return json_error(404, "param 'remove': Valeur invalide")
|
||||||
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
etudid: int = justificatif_unique.etudid
|
||||||
|
try:
|
||||||
|
if remove == "all":
|
||||||
|
archiver.delete_justificatif(etudid=etudid, archive_name=archive_name)
|
||||||
|
justificatif_unique.fichier = None
|
||||||
|
db.session.add(justificatif_unique)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
else:
|
||||||
|
for fname in data.get("filenames", []):
|
||||||
|
archiver.delete_justificatif(
|
||||||
|
etudid=etudid,
|
||||||
|
archive_name=archive_name,
|
||||||
|
filename=fname,
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(archiver.list_justificatifs(archive_name, etudid)) == 0:
|
||||||
|
archiver.delete_justificatif(etudid, archive_name)
|
||||||
|
justificatif_unique.fichier = None
|
||||||
|
db.session.add(justificatif_unique)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
except ScoValueError as err:
|
||||||
|
return json_error(404, err.args[1])
|
||||||
|
|
||||||
|
return jsonify({"response": "removed"})
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: justificatif-list
|
||||||
|
@bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
||||||
|
@api_web_bp.route("/justificatif/list/<int:justif_id>", methods=["GET"])
|
||||||
|
@scodoc
|
||||||
|
@login_required
|
||||||
|
@permission_required(Permission.ScoView)
|
||||||
|
# @permission_required(Permission.ScoAssiduiteChange)
|
||||||
|
def justif_list(justif_id: int = None):
|
||||||
|
"""
|
||||||
|
Liste les fichiers du justificatif
|
||||||
|
"""
|
||||||
|
|
||||||
|
query = Justificatif.query.filter_by(id=justif_id)
|
||||||
|
if g.scodoc_dept:
|
||||||
|
query = query.join(Identite).filter_by(dept_id=g.scodoc_dept_id)
|
||||||
|
|
||||||
|
justificatif_unique: Justificatif = query.first_or_404()
|
||||||
|
|
||||||
|
archive_name: str = justificatif_unique.fichier
|
||||||
|
|
||||||
|
filenames: list[str] = []
|
||||||
|
|
||||||
|
archiver: JustificatifArchiver = JustificatifArchiver()
|
||||||
|
if archive_name is not None:
|
||||||
|
filenames = archiver.list_justificatifs(
|
||||||
|
archive_name, justificatif_unique.etudid
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify(filenames)
|
||||||
|
|
||||||
|
|
||||||
|
# Partie justification
|
||||||
|
# TODO: justificatif-justified
|
||||||
|
|
||||||
|
|
||||||
|
# -- Utils --
|
||||||
|
def _change_etat(data: dict, from_int: bool = True):
|
||||||
|
"""change dans un json la valeur du champs état"""
|
||||||
|
if from_int:
|
||||||
|
data["etat"] = scu.ETAT_JUSTIFICATIF_NAME.get(data["etat"])
|
||||||
|
else:
|
||||||
|
data["etat"] = scu.ETATS_JUSTIFICATIF.get(data["etat"])
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def _filter_manager(requested, justificatifs_query):
|
||||||
|
"""
|
||||||
|
Retourne les justificatifs entrés filtrés en fonction de la request
|
||||||
|
"""
|
||||||
|
# cas 1 : etat justificatif
|
||||||
|
etat = requested.args.get("etat")
|
||||||
|
if etat is not None:
|
||||||
|
justificatifs_query = scass.filter_justificatifs_by_etat(
|
||||||
|
justificatifs_query, etat
|
||||||
|
)
|
||||||
|
|
||||||
|
# cas 2 : date de début
|
||||||
|
deb = requested.args.get("date_debut")
|
||||||
|
deb: datetime = scu.is_iso_formated(deb, True)
|
||||||
|
if deb is not None:
|
||||||
|
|
||||||
|
justificatifs_query = scass.filter_justificatifs_by_date(
|
||||||
|
justificatifs_query, deb, sup=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# cas 3 : date de fin
|
||||||
|
fin = requested.args.get("date_fin")
|
||||||
|
fin = scu.is_iso_formated(fin, True)
|
||||||
|
|
||||||
|
if fin is not None:
|
||||||
|
justificatifs_query = scass.filter_justificatifs_by_date(
|
||||||
|
justificatifs_query, fin, sup=False
|
||||||
|
)
|
||||||
|
|
||||||
|
return justificatifs_query
|
@ -11,5 +11,5 @@ def send_password_reset_email(user):
|
|||||||
sender=current_app.config["SCODOC_MAIL_FROM"],
|
sender=current_app.config["SCODOC_MAIL_FROM"],
|
||||||
recipients=[user.email],
|
recipients=[user.email],
|
||||||
text_body=render_template("email/reset_password.txt", user=user, token=token),
|
text_body=render_template("email/reset_password.txt", user=user, token=token),
|
||||||
html_body=render_template("email/reset_password.html", user=user, token=token),
|
html_body=render_template("email/reset_password.j2", user=user, token=token),
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,7 @@ def login():
|
|||||||
return form.redirect("scodoc.index")
|
return form.redirect("scodoc.index")
|
||||||
message = request.args.get("message", "")
|
message = request.args.get("message", "")
|
||||||
return render_template(
|
return render_template(
|
||||||
"auth/login.html", title=_("Sign In"), form=form, message=message
|
"auth/login.j2", title=_("Sign In"), form=form, message=message
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -65,9 +65,7 @@ def create_user():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash(f"Utilisateur {user.user_name} créé")
|
flash(f"Utilisateur {user.user_name} créé")
|
||||||
return redirect(url_for("scodoc.index"))
|
return redirect(url_for("scodoc.index"))
|
||||||
return render_template(
|
return render_template("auth/register.j2", title="Création utilisateur", form=form)
|
||||||
"auth/register.html", title="Création utilisateur", form=form
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/reset_password_request", methods=["GET", "POST"])
|
@bp.route("/reset_password_request", methods=["GET", "POST"])
|
||||||
@ -98,7 +96,7 @@ def reset_password_request():
|
|||||||
)
|
)
|
||||||
return redirect(url_for("auth.login"))
|
return redirect(url_for("auth.login"))
|
||||||
return render_template(
|
return render_template(
|
||||||
"auth/reset_password_request.html", title=_("Reset Password"), form=form
|
"auth/reset_password_request.j2", title=_("Reset Password"), form=form
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -116,7 +114,7 @@ def reset_password(token):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash(_("Votre mot de passe a été changé."))
|
flash(_("Votre mot de passe a été changé."))
|
||||||
return redirect(url_for("auth.login"))
|
return redirect(url_for("auth.login"))
|
||||||
return render_template("auth/reset_password.html", form=form, user=user)
|
return render_template("auth/reset_password.j2", form=form, user=user)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/reset_standard_roles_permissions", methods=["GET", "POST"])
|
@bp.route("/reset_standard_roles_permissions", methods=["GET", "POST"])
|
||||||
|
@ -841,6 +841,7 @@ class DecisionsProposeesAnnee(DecisionsProposees):
|
|||||||
et autorisations d'inscription émises.
|
et autorisations d'inscription émises.
|
||||||
Efface même si étudiant DEM ou DEF.
|
Efface même si étudiant DEM ou DEF.
|
||||||
Si à cheval, n'efface que pour le semestre d'origine du deca.
|
Si à cheval, n'efface que pour le semestre d'origine du deca.
|
||||||
|
(commite la session.)
|
||||||
"""
|
"""
|
||||||
if only_one_sem or self.a_cheval:
|
if only_one_sem or self.a_cheval:
|
||||||
# N'efface que les autorisations venant de ce semestre,
|
# N'efface que les autorisations venant de ce semestre,
|
||||||
|
@ -500,7 +500,7 @@ def jury_but_semestriel(
|
|||||||
H.append("</div>")
|
H.append("</div>")
|
||||||
H.append(
|
H.append(
|
||||||
render_template(
|
render_template(
|
||||||
"but/documentation_codes_jury.html",
|
"but/documentation_codes_jury.j2",
|
||||||
nom_univ=f"""Export {sco_preferences.get_preference("InstituteName")
|
nom_univ=f"""Export {sco_preferences.get_preference("InstituteName")
|
||||||
or sco_preferences.get_preference("UnivName")
|
or sco_preferences.get_preference("UnivName")
|
||||||
or "Apogée"}""",
|
or "Apogée"}""",
|
||||||
|
@ -1358,6 +1358,44 @@ class BonusIUTvannes(BonusSportAdditif):
|
|||||||
classic_use_bonus_ues = False # seulement sur moy gen.
|
classic_use_bonus_ues = False # seulement sur moy gen.
|
||||||
|
|
||||||
|
|
||||||
|
class BonusValenciennes(BonusDirect):
|
||||||
|
"""Article 7 des RCC de l’IUT de Valenciennes
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Une bonification maximale de 0.25 point (1/4 de point) peut être ajoutée
|
||||||
|
à la moyenne de chaque Unité d’Enseignement pour :
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>l'engagement citoyen ;</li>
|
||||||
|
<li>la participation à un module de sport.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Une bonification accordée par la commission des sports de l’UPHF peut être attribuée
|
||||||
|
aux sportifs de haut niveau. Cette bonification est appliquée à l’ensemble des
|
||||||
|
Unités d’Enseignement. Ce bonus est :
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li> 0.5 pour la catégorie <em>or</em> (sportif inscrit sur liste ministérielle
|
||||||
|
jeunesse et sport) ;
|
||||||
|
</li>
|
||||||
|
<li> 0.45 pour la catégorie <em>argent</em> (sportif en club professionnel) ;
|
||||||
|
</li>
|
||||||
|
<li> 0.40 pour le <em>bronze</em> (sportif de niveau départemental, régional ou national).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>Le cumul de bonifications est possible mais ne peut excéder 0.5 point (un demi-point).
|
||||||
|
</p>
|
||||||
|
<p><em>Dans ScoDoc, saisir directement la valeur désirée du bonus
|
||||||
|
dans une évaluation notée sur 20.</em>
|
||||||
|
</p>
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = "bonus_valenciennes"
|
||||||
|
displayed_name = "IUT de Valenciennes"
|
||||||
|
bonus_max = 0.5
|
||||||
|
|
||||||
|
|
||||||
class BonusVilleAvray(BonusSportAdditif):
|
class BonusVilleAvray(BonusSportAdditif):
|
||||||
"""Bonus modules optionnels (sport, culture), règle IUT Ville d'Avray.
|
"""Bonus modules optionnels (sport, culture), règle IUT Ville d'Avray.
|
||||||
|
|
||||||
|
@ -33,7 +33,10 @@ import pandas as pd
|
|||||||
from app import db
|
from app import db
|
||||||
from app import models
|
from app import models
|
||||||
from app.models import (
|
from app.models import (
|
||||||
|
DispenseUE,
|
||||||
FormSemestre,
|
FormSemestre,
|
||||||
|
FormSemestreInscription,
|
||||||
|
Identite,
|
||||||
Module,
|
Module,
|
||||||
ModuleImpl,
|
ModuleImpl,
|
||||||
ModuleUECoef,
|
ModuleUECoef,
|
||||||
@ -215,6 +218,31 @@ def notes_sem_load_cube(formsemestre: FormSemestre) -> tuple:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def load_dispense_ues(
|
||||||
|
formsemestre: FormSemestre, etudids: pd.Index, ues: list[UniteEns]
|
||||||
|
) -> set[tuple[int, int]]:
|
||||||
|
"""Construit l'ensemble des
|
||||||
|
etudids = modimpl_inscr_df.index, # les etudids
|
||||||
|
ue_ids : modimpl_coefs_df.index, # les UE du formsemestre sans les UE bonus sport
|
||||||
|
|
||||||
|
Résultat: set de (etudid, ue_id).
|
||||||
|
"""
|
||||||
|
dispense_ues = set()
|
||||||
|
ue_sem_by_code = {ue.ue_code: ue for ue in ues}
|
||||||
|
# Prend toutes les dispenses obtenues par des étudiants de ce formsemestre,
|
||||||
|
# puis filtre sur inscrits et code d'UE UE
|
||||||
|
for dispense_ue in DispenseUE.query.join(
|
||||||
|
Identite, FormSemestreInscription
|
||||||
|
).filter_by(formsemestre_id=formsemestre.id):
|
||||||
|
if dispense_ue.etudid in etudids:
|
||||||
|
# UE dans le semestre avec même code ?
|
||||||
|
ue = ue_sem_by_code.get(dispense_ue.ue.ue_code)
|
||||||
|
if ue is not None:
|
||||||
|
dispense_ues.add((dispense_ue.etudid, ue.id))
|
||||||
|
|
||||||
|
return dispense_ues
|
||||||
|
|
||||||
|
|
||||||
def compute_ue_moys_apc(
|
def compute_ue_moys_apc(
|
||||||
sem_cube: np.array,
|
sem_cube: np.array,
|
||||||
etuds: list,
|
etuds: list,
|
||||||
|
@ -72,7 +72,7 @@ class ResultatsSemestreBUT(NotesTableCompat):
|
|||||||
modimpl.module.ue.type != UE_SPORT
|
modimpl.module.ue.type != UE_SPORT
|
||||||
for modimpl in self.formsemestre.modimpls_sorted
|
for modimpl in self.formsemestre.modimpls_sorted
|
||||||
]
|
]
|
||||||
self.dispense_ues = DispenseUE.load_formsemestre_dispense_ues_set(
|
self.dispense_ues = moy_ue.load_dispense_ues(
|
||||||
self.formsemestre, self.modimpl_inscr_df.index, self.ues
|
self.formsemestre, self.modimpl_inscr_df.index, self.ues
|
||||||
)
|
)
|
||||||
self.etud_moy_ue = moy_ue.compute_ue_moys_apc(
|
self.etud_moy_ue = moy_ue.compute_ue_moys_apc(
|
||||||
|
@ -89,7 +89,7 @@ def index():
|
|||||||
visible=True, association=True, siret_provisoire=True
|
visible=True, association=True, siret_provisoire=True
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/entreprises.html",
|
"entreprises/entreprises.j2",
|
||||||
title="Entreprises",
|
title="Entreprises",
|
||||||
entreprises=entreprises,
|
entreprises=entreprises,
|
||||||
logs=logs,
|
logs=logs,
|
||||||
@ -109,7 +109,7 @@ def logs():
|
|||||||
EntrepriseHistorique.date.desc()
|
EntrepriseHistorique.date.desc()
|
||||||
).paginate(page=page, per_page=20)
|
).paginate(page=page, per_page=20)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/logs.html",
|
"entreprises/logs.j2",
|
||||||
title="Logs",
|
title="Logs",
|
||||||
logs=logs,
|
logs=logs,
|
||||||
)
|
)
|
||||||
@ -134,7 +134,7 @@ def correspondants():
|
|||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/correspondants.html",
|
"entreprises/correspondants.j2",
|
||||||
title="Correspondants",
|
title="Correspondants",
|
||||||
correspondants=correspondants,
|
correspondants=correspondants,
|
||||||
logs=logs,
|
logs=logs,
|
||||||
@ -149,7 +149,7 @@ def validation():
|
|||||||
"""
|
"""
|
||||||
entreprises = Entreprise.query.filter_by(visible=False).all()
|
entreprises = Entreprise.query.filter_by(visible=False).all()
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/entreprises_validation.html",
|
"entreprises/entreprises_validation.j2",
|
||||||
title="Validation entreprises",
|
title="Validation entreprises",
|
||||||
entreprises=entreprises,
|
entreprises=entreprises,
|
||||||
)
|
)
|
||||||
@ -167,7 +167,7 @@ def fiche_entreprise_validation(entreprise_id):
|
|||||||
description=f"fiche entreprise (validation) {entreprise_id} inconnue"
|
description=f"fiche entreprise (validation) {entreprise_id} inconnue"
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/fiche_entreprise_validation.html",
|
"entreprises/fiche_entreprise_validation.j2",
|
||||||
title="Validation fiche entreprise",
|
title="Validation fiche entreprise",
|
||||||
entreprise=entreprise,
|
entreprise=entreprise,
|
||||||
)
|
)
|
||||||
@ -205,7 +205,7 @@ def validate_entreprise(entreprise_id):
|
|||||||
flash("L'entreprise a été validé et ajouté à la liste.")
|
flash("L'entreprise a été validé et ajouté à la liste.")
|
||||||
return redirect(url_for("entreprises.validation"))
|
return redirect(url_for("entreprises.validation"))
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_validate_confirmation.html",
|
"entreprises/form_validate_confirmation.j2",
|
||||||
title="Validation entreprise",
|
title="Validation entreprise",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -242,7 +242,7 @@ def delete_validation_entreprise(entreprise_id):
|
|||||||
flash("L'entreprise a été supprimé de la liste des entreprise à valider.")
|
flash("L'entreprise a été supprimé de la liste des entreprise à valider.")
|
||||||
return redirect(url_for("entreprises.validation"))
|
return redirect(url_for("entreprises.validation"))
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supression entreprise",
|
title="Supression entreprise",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -282,7 +282,7 @@ def offres_recues():
|
|||||||
files.append(file)
|
files.append(file)
|
||||||
offres_recues_with_files.append([envoi_offre, offre, files, correspondant])
|
offres_recues_with_files.append([envoi_offre, offre, files, correspondant])
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/offres_recues.html",
|
"entreprises/offres_recues.j2",
|
||||||
title="Offres reçues",
|
title="Offres reçues",
|
||||||
offres_recues=offres_recues_with_files,
|
offres_recues=offres_recues_with_files,
|
||||||
)
|
)
|
||||||
@ -321,7 +321,7 @@ def preferences():
|
|||||||
form.mail_entreprise.data = EntreprisePreferences.get_email_notifications()
|
form.mail_entreprise.data = EntreprisePreferences.get_email_notifications()
|
||||||
form.check_siret.data = int(EntreprisePreferences.get_check_siret())
|
form.check_siret.data = int(EntreprisePreferences.get_check_siret())
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/preferences.html",
|
"entreprises/preferences.j2",
|
||||||
title="Préférences",
|
title="Préférences",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -357,7 +357,7 @@ def add_entreprise():
|
|||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
flash("Une erreur est survenue veuillez réessayer.")
|
flash("Une erreur est survenue veuillez réessayer.")
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_ajout_entreprise.html",
|
"entreprises/form_ajout_entreprise.j2",
|
||||||
title="Ajout entreprise avec correspondant",
|
title="Ajout entreprise avec correspondant",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -408,7 +408,7 @@ def add_entreprise():
|
|||||||
flash("L'entreprise a été ajouté à la liste pour la validation.")
|
flash("L'entreprise a été ajouté à la liste pour la validation.")
|
||||||
return redirect(url_for("entreprises.index"))
|
return redirect(url_for("entreprises.index"))
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_ajout_entreprise.html",
|
"entreprises/form_ajout_entreprise.j2",
|
||||||
title="Ajout entreprise avec correspondant",
|
title="Ajout entreprise avec correspondant",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -446,7 +446,7 @@ def fiche_entreprise(entreprise_id):
|
|||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/fiche_entreprise.html",
|
"entreprises/fiche_entreprise.j2",
|
||||||
title="Fiche entreprise",
|
title="Fiche entreprise",
|
||||||
entreprise=entreprise,
|
entreprise=entreprise,
|
||||||
offres=offres_with_files,
|
offres=offres_with_files,
|
||||||
@ -472,7 +472,7 @@ def logs_entreprise(entreprise_id):
|
|||||||
.paginate(page=page, per_page=20)
|
.paginate(page=page, per_page=20)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/logs_entreprise.html",
|
"entreprises/logs_entreprise.j2",
|
||||||
title="Logs",
|
title="Logs",
|
||||||
logs=logs,
|
logs=logs,
|
||||||
entreprise=entreprise,
|
entreprise=entreprise,
|
||||||
@ -490,7 +490,7 @@ def offres_expirees(entreprise_id):
|
|||||||
).first_or_404(description=f"fiche entreprise {entreprise_id} inconnue")
|
).first_or_404(description=f"fiche entreprise {entreprise_id} inconnue")
|
||||||
offres_with_files = are.get_offres_expirees_with_files(entreprise.offres)
|
offres_with_files = are.get_offres_expirees_with_files(entreprise.offres)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/offres_expirees.html",
|
"entreprises/offres_expirees.j2",
|
||||||
title="Offres expirées",
|
title="Offres expirées",
|
||||||
entreprise=entreprise,
|
entreprise=entreprise,
|
||||||
offres_expirees=offres_with_files,
|
offres_expirees=offres_with_files,
|
||||||
@ -574,7 +574,7 @@ def edit_entreprise(entreprise_id):
|
|||||||
form.pays.data = entreprise.pays
|
form.pays.data = entreprise.pays
|
||||||
form.association.data = entreprise.association
|
form.association.data = entreprise.association
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_modification_entreprise.html",
|
"entreprises/form_modification_entreprise.j2",
|
||||||
title="Modification entreprise",
|
title="Modification entreprise",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -610,7 +610,7 @@ def fiche_entreprise_desactiver(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Désactiver entreprise",
|
title="Désactiver entreprise",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Modifier pour confirmer la désactivation",
|
info_message="Cliquez sur le bouton Modifier pour confirmer la désactivation",
|
||||||
@ -646,7 +646,7 @@ def fiche_entreprise_activer(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Activer entreprise",
|
title="Activer entreprise",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Modifier pour confirmer l'activaction",
|
info_message="Cliquez sur le bouton Modifier pour confirmer l'activaction",
|
||||||
@ -692,7 +692,7 @@ def add_taxe_apprentissage(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Ajout taxe apprentissage",
|
title="Ajout taxe apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -735,7 +735,7 @@ def edit_taxe_apprentissage(entreprise_id, taxe_id):
|
|||||||
form.montant.data = taxe.montant
|
form.montant.data = taxe.montant
|
||||||
form.notes.data = taxe.notes
|
form.notes.data = taxe.notes
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Modification taxe apprentissage",
|
title="Modification taxe apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -775,7 +775,7 @@ def delete_taxe_apprentissage(entreprise_id, taxe_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=taxe.entreprise_id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=taxe.entreprise_id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supprimer taxe apprentissage",
|
title="Supprimer taxe apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -845,7 +845,7 @@ def add_offre(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Ajout offre",
|
title="Ajout offre",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -921,7 +921,7 @@ def edit_offre(entreprise_id, offre_id):
|
|||||||
form.expiration_date.data = offre.expiration_date
|
form.expiration_date.data = offre.expiration_date
|
||||||
form.depts.data = offre_depts_list
|
form.depts.data = offre_depts_list
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Modification offre",
|
title="Modification offre",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -971,7 +971,7 @@ def delete_offre(entreprise_id, offre_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supression offre",
|
title="Supression offre",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -1047,7 +1047,7 @@ def add_site(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Ajout site",
|
title="Ajout site",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1098,7 +1098,7 @@ def edit_site(entreprise_id, site_id):
|
|||||||
form.ville.data = site.ville
|
form.ville.data = site.ville
|
||||||
form.pays.data = site.pays
|
form.pays.data = site.pays
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Modification site",
|
title="Modification site",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1154,7 +1154,7 @@ def add_correspondant(entreprise_id, site_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=site.entreprise_id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=site.entreprise_id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_ajout_correspondants.html",
|
"entreprises/form_ajout_correspondants.j2",
|
||||||
title="Ajout correspondant",
|
title="Ajout correspondant",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1234,7 +1234,7 @@ def edit_correspondant(entreprise_id, site_id, correspondant_id):
|
|||||||
form.origine.data = correspondant.origine
|
form.origine.data = correspondant.origine
|
||||||
form.notes.data = correspondant.notes
|
form.notes.data = correspondant.notes
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Modification correspondant",
|
title="Modification correspondant",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1290,7 +1290,7 @@ def delete_correspondant(entreprise_id, site_id, correspondant_id):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supression correspondant",
|
title="Supression correspondant",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -1308,7 +1308,7 @@ def contacts(entreprise_id):
|
|||||||
).first_or_404(description=f"entreprise {entreprise_id} inconnue")
|
).first_or_404(description=f"entreprise {entreprise_id} inconnue")
|
||||||
contacts = EntrepriseContact.query.filter_by(entreprise=entreprise.id).all()
|
contacts = EntrepriseContact.query.filter_by(entreprise=entreprise.id).all()
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/contacts.html",
|
"entreprises/contacts.j2",
|
||||||
title="Liste des contacts",
|
title="Liste des contacts",
|
||||||
contacts=contacts,
|
contacts=contacts,
|
||||||
entreprise=entreprise,
|
entreprise=entreprise,
|
||||||
@ -1365,7 +1365,7 @@ def add_contact(entreprise_id):
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect(url_for("entreprises.contacts", entreprise_id=entreprise.id))
|
return redirect(url_for("entreprises.contacts", entreprise_id=entreprise.id))
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Ajout contact",
|
title="Ajout contact",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1421,7 +1421,7 @@ def edit_contact(entreprise_id, contact_id):
|
|||||||
)
|
)
|
||||||
form.notes.data = contact.notes
|
form.notes.data = contact.notes
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Modification contact",
|
title="Modification contact",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1459,7 +1459,7 @@ def delete_contact(entreprise_id, contact_id):
|
|||||||
url_for("entreprises.contacts", entreprise_id=contact.entreprise)
|
url_for("entreprises.contacts", entreprise_id=contact.entreprise)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supression contact",
|
title="Supression contact",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -1525,7 +1525,7 @@ def add_stage_apprentissage(entreprise_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=entreprise.id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_ajout_stage_apprentissage.html",
|
"entreprises/form_ajout_stage_apprentissage.j2",
|
||||||
title="Ajout stage / apprentissage",
|
title="Ajout stage / apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1599,7 +1599,7 @@ def edit_stage_apprentissage(entreprise_id, stage_apprentissage_id):
|
|||||||
form.date_fin.data = stage_apprentissage.date_fin
|
form.date_fin.data = stage_apprentissage.date_fin
|
||||||
form.notes.data = stage_apprentissage.notes
|
form.notes.data = stage_apprentissage.notes
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_ajout_stage_apprentissage.html",
|
"entreprises/form_ajout_stage_apprentissage.j2",
|
||||||
title="Modification stage / apprentissage",
|
title="Modification stage / apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1640,7 +1640,7 @@ def delete_stage_apprentissage(entreprise_id, stage_apprentissage_id):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Supression stage/apprentissage",
|
title="Supression stage/apprentissage",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -1690,7 +1690,7 @@ def envoyer_offre(entreprise_id, offre_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_envoi_offre.html",
|
"entreprises/form_envoi_offre.j2",
|
||||||
title="Envoyer une offre",
|
title="Envoyer une offre",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1816,7 +1816,7 @@ def import_donnees():
|
|||||||
db.session.rollback()
|
db.session.rollback()
|
||||||
flash("Une erreur est survenue veuillez réessayer.")
|
flash("Une erreur est survenue veuillez réessayer.")
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/import_donnees.html",
|
"entreprises/import_donnees.j2",
|
||||||
title="Importation données",
|
title="Importation données",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1845,7 +1845,7 @@ def import_donnees():
|
|||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash(f"Importation réussie")
|
flash(f"Importation réussie")
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/import_donnees.html",
|
"entreprises/import_donnees.j2",
|
||||||
title="Importation données",
|
title="Importation données",
|
||||||
form=form,
|
form=form,
|
||||||
entreprises_import=entreprises_import,
|
entreprises_import=entreprises_import,
|
||||||
@ -1853,7 +1853,7 @@ def import_donnees():
|
|||||||
correspondants_import=correspondants,
|
correspondants_import=correspondants,
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/import_donnees.html", title="Importation données", form=form
|
"entreprises/import_donnees.j2", title="Importation données", form=form
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -1927,7 +1927,7 @@ def add_offre_file(entreprise_id, offre_id):
|
|||||||
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
url_for("entreprises.fiche_entreprise", entreprise_id=offre.entreprise_id)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form.html",
|
"entreprises/form.j2",
|
||||||
title="Ajout fichier à une offre",
|
title="Ajout fichier à une offre",
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
@ -1969,7 +1969,7 @@ def delete_offre_file(entreprise_id, offre_id, filedir):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"entreprises/form_confirmation.html",
|
"entreprises/form_confirmation.j2",
|
||||||
title="Suppression fichier d'une offre",
|
title="Suppression fichier d'une offre",
|
||||||
form=form,
|
form=form,
|
||||||
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
info_message="Cliquez sur le bouton Supprimer pour confirmer votre supression",
|
||||||
@ -1981,4 +1981,4 @@ def not_found_error_handler(e):
|
|||||||
"""
|
"""
|
||||||
Renvoie une page d'erreur pour l'erreur 404
|
Renvoie une page d'erreur pour l'erreur 404
|
||||||
"""
|
"""
|
||||||
return render_template("entreprises/error.html", title="Erreur", e=e)
|
return render_template("entreprises/error.j2", title="Erreur", e=e)
|
||||||
|
@ -171,7 +171,7 @@ class AddLogoForm(FlaskForm):
|
|||||||
|
|
||||||
|
|
||||||
class LogoForm(FlaskForm):
|
class LogoForm(FlaskForm):
|
||||||
"""Embed both presentation of a logo (cf. template file configuration.html)
|
"""Embed both presentation of a logo (cf. template file configuration.j2)
|
||||||
and all its data and UI action (change, delete)"""
|
and all its data and UI action (change, delete)"""
|
||||||
|
|
||||||
dept_key = HiddenField()
|
dept_key = HiddenField()
|
||||||
@ -434,7 +434,7 @@ def config_logos():
|
|||||||
scu.flash_errors(form)
|
scu.flash_errors(form)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"config_logos.html",
|
"config_logos.j2",
|
||||||
scodoc_dept=None,
|
scodoc_dept=None,
|
||||||
title="Configuration ScoDoc",
|
title="Configuration ScoDoc",
|
||||||
form=form,
|
form=form,
|
||||||
|
@ -133,7 +133,7 @@ def configuration():
|
|||||||
return redirect(url_for("scodoc.index"))
|
return redirect(url_for("scodoc.index"))
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
"configuration.html",
|
"configuration.j2",
|
||||||
form_bonus=form_bonus,
|
form_bonus=form_bonus,
|
||||||
form_scodoc=form_scodoc,
|
form_scodoc=form_scodoc,
|
||||||
scu=scu,
|
scu=scu,
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
# -*- coding: UTF-8 -*
|
# -*- coding: UTF-8 -*
|
||||||
"""Gestion de l'assiduité (assiduités + justificatifs)
|
"""Gestion de l'assiduité (assiduités + justificatifs)
|
||||||
"""
|
"""
|
||||||
from app import db
|
|
||||||
from app.models import ModuleImpl, ModuleImplInscription
|
|
||||||
from app.models.etudiants import Identite
|
|
||||||
from app.scodoc.sco_utils import EtatAssiduite, localize_datetime, is_period_overlapping
|
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from app import db
|
||||||
|
from app.models import ModuleImpl
|
||||||
|
from app.models.etudiants import Identite
|
||||||
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
from app.scodoc.sco_utils import (
|
||||||
|
EtatAssiduite,
|
||||||
|
EtatJustificatif,
|
||||||
|
is_period_overlapping,
|
||||||
|
localize_datetime,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Assiduite(db.Model):
|
class Assiduite(db.Model):
|
||||||
"""
|
"""
|
||||||
@ -43,6 +49,8 @@ class Assiduite(db.Model):
|
|||||||
|
|
||||||
desc = db.Column(db.Text)
|
desc = db.Column(db.Text)
|
||||||
|
|
||||||
|
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
data = {
|
data = {
|
||||||
"assiduite_id": self.assiduite_id,
|
"assiduite_id": self.assiduite_id,
|
||||||
@ -52,6 +60,7 @@ class Assiduite(db.Model):
|
|||||||
"date_fin": self.date_fin,
|
"date_fin": self.date_fin,
|
||||||
"etat": self.etat,
|
"etat": self.etat,
|
||||||
"desc": self.desc,
|
"desc": self.desc,
|
||||||
|
"entry_date": self.entry_date,
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -119,7 +128,8 @@ class Justificatif(db.Model):
|
|||||||
|
|
||||||
__tablename__ = "justificatifs"
|
__tablename__ = "justificatifs"
|
||||||
|
|
||||||
justif_id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
justif_id = db.synonym("id")
|
||||||
|
|
||||||
date_debut = db.Column(
|
date_debut = db.Column(
|
||||||
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
|
db.DateTime(timezone=True), server_default=db.func.now(), nullable=False
|
||||||
@ -136,26 +146,63 @@ class Justificatif(db.Model):
|
|||||||
)
|
)
|
||||||
etat = db.Column(
|
etat = db.Column(
|
||||||
db.Integer,
|
db.Integer,
|
||||||
|
nullable=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
entry_date = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
|
||||||
|
|
||||||
raison = db.Column(db.Text())
|
raison = db.Column(db.Text())
|
||||||
|
|
||||||
"""
|
# Archive_id -> sco_archives_justificatifs.py
|
||||||
Les justificatifs sont enregistrés dans
|
|
||||||
<archivedir>/justificatifs/<dept_id>/<etudid>/<nom_fichier.extension>
|
|
||||||
|
|
||||||
d'après sco_archives.py#JustificatifArchiver
|
|
||||||
"""
|
|
||||||
fichier = db.Column(db.Text())
|
fichier = db.Column(db.Text())
|
||||||
|
|
||||||
def to_dict(self) -> dict:
|
def to_dict(self) -> dict:
|
||||||
data = {
|
data = {
|
||||||
"justif_id": self.assiduite_id,
|
"justif_id": self.justif_id,
|
||||||
"etudid": self.etudid,
|
"etudid": self.etudid,
|
||||||
"date_debut": self.date_debut,
|
"date_debut": self.date_debut,
|
||||||
"date_fin": self.date_fin,
|
"date_fin": self.date_fin,
|
||||||
"etat": self.etat,
|
"etat": self.etat,
|
||||||
"raison": self.raison,
|
"raison": self.raison,
|
||||||
"fichier": self.fichier,
|
"fichier": self.fichier,
|
||||||
|
"entry_date": self.entry_date,
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_justificatif(
|
||||||
|
cls,
|
||||||
|
etud: Identite,
|
||||||
|
date_debut: datetime,
|
||||||
|
date_fin: datetime,
|
||||||
|
etat: EtatJustificatif,
|
||||||
|
raison: str = None,
|
||||||
|
) -> object or int:
|
||||||
|
"""Créer un nouveau justificatif pour l'étudiant"""
|
||||||
|
# Vérification de non duplication des périodes
|
||||||
|
justificatifs: list[Justificatif] = etud.justificatifs.all()
|
||||||
|
|
||||||
|
date_debut = localize_datetime(date_debut)
|
||||||
|
date_fin = localize_datetime(date_fin)
|
||||||
|
justificatifs = [
|
||||||
|
just
|
||||||
|
for just in justificatifs
|
||||||
|
if is_period_overlapping(
|
||||||
|
(date_debut, date_fin),
|
||||||
|
(just.date_debut, just.date_fin),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
if len(justificatifs) != 0:
|
||||||
|
raise ScoValueError(
|
||||||
|
"Duplication des justificatifs (la période rentrée rentre en conflit avec un justificatif enregistré)"
|
||||||
|
)
|
||||||
|
|
||||||
|
nouv_assiduite = Justificatif(
|
||||||
|
date_debut=date_debut,
|
||||||
|
date_fin=date_fin,
|
||||||
|
etat=etat,
|
||||||
|
etudiant=etud,
|
||||||
|
raison=raison,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nouv_assiduite
|
||||||
|
@ -36,6 +36,7 @@ class Formation(db.Model):
|
|||||||
titre = db.Column(db.Text(), nullable=False)
|
titre = db.Column(db.Text(), nullable=False)
|
||||||
titre_officiel = db.Column(db.Text(), nullable=False)
|
titre_officiel = db.Column(db.Text(), nullable=False)
|
||||||
version = db.Column(db.Integer, default=1, server_default="1")
|
version = db.Column(db.Integer, default=1, server_default="1")
|
||||||
|
commentaire = db.Column(db.Text())
|
||||||
formation_code = db.Column(
|
formation_code = db.Column(
|
||||||
db.String(SHORT_STR_LEN),
|
db.String(SHORT_STR_LEN),
|
||||||
server_default=db.text("notes_newid_fcod()"),
|
server_default=db.text("notes_newid_fcod()"),
|
||||||
@ -63,7 +64,7 @@ class Formation(db.Model):
|
|||||||
return f"""Formation {self.titre} ({self.acronyme}) [version {self.version}] code {self.formation_code}"""
|
return f"""Formation {self.titre} ({self.acronyme}) [version {self.version}] code {self.formation_code}"""
|
||||||
|
|
||||||
def to_dict(self, with_refcomp_attrs=False):
|
def to_dict(self, with_refcomp_attrs=False):
|
||||||
""" "as a dict.
|
"""As a dict.
|
||||||
Si with_refcomp_attrs, ajoute attributs permettant de retrouver le ref. de comp.
|
Si with_refcomp_attrs, ajoute attributs permettant de retrouver le ref. de comp.
|
||||||
"""
|
"""
|
||||||
e = dict(self.__dict__)
|
e = dict(self.__dict__)
|
||||||
|
@ -256,23 +256,12 @@ class UniteEns(db.Model):
|
|||||||
|
|
||||||
class DispenseUE(db.Model):
|
class DispenseUE(db.Model):
|
||||||
"""Dispense d'UE
|
"""Dispense d'UE
|
||||||
Utilisé en APC (BUT) pour indiquer les étudiants redoublants avec une UE capitalisée
|
Utilisé en PCC (BUT) pour indiquer les étudiants redoublants avec une UE capitalisée
|
||||||
qu'ils ne refont pas.
|
qu'ils ne refont pas.
|
||||||
La dispense d'UE n'est PAS une validation:
|
|
||||||
- elle n'est pas affectée par les décisions de jury (pas effacée)
|
|
||||||
- elle est associée à un formsemestre
|
|
||||||
- elle ne permet pas la délivrance d'ECTS ou du diplôme.
|
|
||||||
|
|
||||||
On utilise cette dispense et non une "inscription" par souci d'efficacité:
|
|
||||||
en général, la grande majorité des étudiants suivront toutes les UEs de leur parcours,
|
|
||||||
la dispense étant une exception.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__table_args__ = (db.UniqueConstraint("formsemestre_id", "ue_id", "etudid"),)
|
__table_args__ = (db.UniqueConstraint("ue_id", "etudid"),)
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
formsemestre_id = formsemestre_id = db.Column(
|
|
||||||
db.Integer, db.ForeignKey("notes_formsemestre.id"), index=True, nullable=True
|
|
||||||
)
|
|
||||||
ue_id = db.Column(
|
ue_id = db.Column(
|
||||||
db.Integer,
|
db.Integer,
|
||||||
db.ForeignKey(UniteEns.id, ondelete="CASCADE"),
|
db.ForeignKey(UniteEns.id, ondelete="CASCADE"),
|
||||||
@ -291,25 +280,3 @@ class DispenseUE(db.Model):
|
|||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
return f"""<{self.__class__.__name__} {self.id} etud={
|
return f"""<{self.__class__.__name__} {self.id} etud={
|
||||||
repr(self.etud)} ue={repr(self.ue)}>"""
|
repr(self.etud)} ue={repr(self.ue)}>"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def load_formsemestre_dispense_ues_set(
|
|
||||||
cls, formsemestre: "FormSemestre", etudids: pd.Index, ues: list[UniteEns]
|
|
||||||
) -> set[tuple[int, int]]:
|
|
||||||
"""Construit l'ensemble des
|
|
||||||
etudids = modimpl_inscr_df.index, # les etudids
|
|
||||||
ue_ids : modimpl_coefs_df.index, # les UE du formsemestre sans les UE bonus sport
|
|
||||||
|
|
||||||
Résultat: set de (etudid, ue_id).
|
|
||||||
"""
|
|
||||||
# Prend toutes les dispenses obtenues par des étudiants de ce formsemestre,
|
|
||||||
# puis filtre sur inscrits et ues
|
|
||||||
ue_ids = {ue.id for ue in ues}
|
|
||||||
dispense_ues = {
|
|
||||||
(dispense_ue.etudid, dispense_ue.ue_id)
|
|
||||||
for dispense_ue in DispenseUE.query.filter_by(
|
|
||||||
formsemestre_id=formsemestre.id
|
|
||||||
)
|
|
||||||
if dispense_ue.etudid in etudids and dispense_ue.ue_id in ue_ids
|
|
||||||
}
|
|
||||||
return dispense_ues
|
|
||||||
|
@ -274,7 +274,7 @@ def sco_header(
|
|||||||
H.append("""<div id="gtrcontent">""")
|
H.append("""<div id="gtrcontent">""")
|
||||||
# En attendant le replacement complet de cette fonction,
|
# En attendant le replacement complet de cette fonction,
|
||||||
# inclusion ici des messages flask
|
# inclusion ici des messages flask
|
||||||
H.append(render_template("flashed_messages.html"))
|
H.append(render_template("flashed_messages.j2"))
|
||||||
#
|
#
|
||||||
# Barre menu semestre:
|
# Barre menu semestre:
|
||||||
H.append(formsemestre_page_title(formsemestre_id))
|
H.append(formsemestre_page_title(formsemestre_id))
|
||||||
|
@ -166,6 +166,6 @@ def sidebar(etudid: int = None):
|
|||||||
def sidebar_dept():
|
def sidebar_dept():
|
||||||
"""Partie supérieure de la marge de gauche"""
|
"""Partie supérieure de la marge de gauche"""
|
||||||
return render_template(
|
return render_template(
|
||||||
"sidebar_dept.html",
|
"sidebar_dept.j2",
|
||||||
prefs=sco_preferences.SemPreferences(),
|
prefs=sco_preferences.SemPreferences(),
|
||||||
)
|
)
|
||||||
|
@ -43,6 +43,7 @@ Pour chaque étudiant commun:
|
|||||||
comparer les résultats
|
comparer les résultats
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
from flask import g, url_for
|
||||||
|
|
||||||
from app import log
|
from app import log
|
||||||
from app.scodoc import sco_apogee_csv
|
from app.scodoc import sco_apogee_csv
|
||||||
@ -72,11 +73,11 @@ def apo_compare_csv_form():
|
|||||||
"""
|
"""
|
||||||
<div class="apo_compare_csv_form_but">
|
<div class="apo_compare_csv_form_but">
|
||||||
Fichier Apogée A:
|
Fichier Apogée A:
|
||||||
<input type="file" size="30" name="A_file"/>
|
<input type="file" size="30" name="file_a"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="apo_compare_csv_form_but">
|
<div class="apo_compare_csv_form_but">
|
||||||
Fichier Apogée B:
|
Fichier Apogée B:
|
||||||
<input type="file" size="30" name="B_file"/>
|
<input type="file" size="30" name="file_b"/>
|
||||||
</div>
|
</div>
|
||||||
<input type="checkbox" name="autodetect" checked/>autodétecter encodage</input>
|
<input type="checkbox" name="autodetect" checked/>autodétecter encodage</input>
|
||||||
<div class="apo_compare_csv_form_submit">
|
<div class="apo_compare_csv_form_submit">
|
||||||
@ -88,17 +89,36 @@ def apo_compare_csv_form():
|
|||||||
return "\n".join(H)
|
return "\n".join(H)
|
||||||
|
|
||||||
|
|
||||||
def apo_compare_csv(A_file, B_file, autodetect=True):
|
def apo_compare_csv(file_a, file_b, autodetect=True):
|
||||||
"""Page comparing 2 Apogee CSV files"""
|
"""Page comparing 2 Apogee CSV files"""
|
||||||
A = _load_apo_data(A_file, autodetect=autodetect)
|
try:
|
||||||
B = _load_apo_data(B_file, autodetect=autodetect)
|
apo_data_a = _load_apo_data(file_a, autodetect=autodetect)
|
||||||
|
apo_data_b = _load_apo_data(file_b, autodetect=autodetect)
|
||||||
|
except (UnicodeDecodeError, UnicodeEncodeError) as exc:
|
||||||
|
dest_url = url_for("notes.semset_page", scodoc_dept=g.scodoc_dept)
|
||||||
|
if autodetect:
|
||||||
|
raise ScoValueError(
|
||||||
|
"""
|
||||||
|
Erreur: l'encodage de l'un des fichiers est mal détecté.
|
||||||
|
Essayez sans auto-détection, ou vérifiez le codage et le contenu
|
||||||
|
des fichiers.
|
||||||
|
""",
|
||||||
|
dest_url=dest_url,
|
||||||
|
) from exc
|
||||||
|
else:
|
||||||
|
raise ScoValueError(
|
||||||
|
f"""
|
||||||
|
Erreur: l'encodage de l'un des fichiers est incorrect.
|
||||||
|
Vérifiez qu'il est bien en {sco_apogee_csv.APO_INPUT_ENCODING}
|
||||||
|
""",
|
||||||
|
dest_url=dest_url,
|
||||||
|
) from exc
|
||||||
H = [
|
H = [
|
||||||
html_sco_header.sco_header(page_title="Comparaison de fichiers Apogée"),
|
html_sco_header.sco_header(page_title="Comparaison de fichiers Apogée"),
|
||||||
"<h2>Comparaison de fichiers Apogée</h2>",
|
"<h2>Comparaison de fichiers Apogée</h2>",
|
||||||
_help_txt,
|
_help_txt,
|
||||||
'<div class="apo_compare_csv">',
|
'<div class="apo_compare_csv">',
|
||||||
_apo_compare_csv(A, B),
|
_apo_compare_csv(apo_data_a, apo_data_b),
|
||||||
"</div>",
|
"</div>",
|
||||||
"""<p><a href="apo_compare_csv_form" class="stdlink">Autre comparaison</a></p>""",
|
"""<p><a href="apo_compare_csv_form" class="stdlink">Autre comparaison</a></p>""",
|
||||||
html_sco_header.sco_footer(),
|
html_sco_header.sco_footer(),
|
||||||
@ -112,9 +132,9 @@ def _load_apo_data(csvfile, autodetect=True):
|
|||||||
if autodetect:
|
if autodetect:
|
||||||
data_b, message = sco_apogee_csv.fix_data_encoding(data_b)
|
data_b, message = sco_apogee_csv.fix_data_encoding(data_b)
|
||||||
if message:
|
if message:
|
||||||
log("apo_compare_csv: %s" % message)
|
log(f"apo_compare_csv: {message}")
|
||||||
if not data_b:
|
if not data_b:
|
||||||
raise ScoValueError("apo_compare_csv: no data")
|
raise ScoValueError("fichier vide ? (apo_compare_csv: no data)")
|
||||||
data = data_b.decode(sco_apogee_csv.APO_INPUT_ENCODING)
|
data = data_b.decode(sco_apogee_csv.APO_INPUT_ENCODING)
|
||||||
apo_data = sco_apogee_csv.ApoData(data, orig_filename=csvfile.filename)
|
apo_data = sco_apogee_csv.ApoData(data, orig_filename=csvfile.filename)
|
||||||
return apo_data
|
return apo_data
|
||||||
|
@ -155,28 +155,25 @@ def fix_data_encoding(
|
|||||||
text: bytes,
|
text: bytes,
|
||||||
default_source_encoding=APO_INPUT_ENCODING,
|
default_source_encoding=APO_INPUT_ENCODING,
|
||||||
dest_encoding=APO_INPUT_ENCODING,
|
dest_encoding=APO_INPUT_ENCODING,
|
||||||
) -> bytes:
|
) -> tuple[bytes, str]:
|
||||||
"""Try to ensure that text is using dest_encoding
|
"""Try to ensure that text is using dest_encoding
|
||||||
returns converted text, and a message describing the conversion.
|
returns converted text, and a message describing the conversion.
|
||||||
|
|
||||||
|
Raises UnicodeEncodeError en cas de problème, en général liée à
|
||||||
|
une auto-détection errornée.
|
||||||
"""
|
"""
|
||||||
message = ""
|
message = ""
|
||||||
detected_encoding = guess_data_encoding(text)
|
detected_encoding = guess_data_encoding(text)
|
||||||
if not detected_encoding:
|
if not detected_encoding:
|
||||||
if default_source_encoding != dest_encoding:
|
if default_source_encoding != dest_encoding:
|
||||||
message = "converting from %s to %s" % (
|
message = f"converting from {default_source_encoding} to {dest_encoding}"
|
||||||
default_source_encoding,
|
text = text.decode(default_source_encoding).encode(dest_encoding)
|
||||||
dest_encoding,
|
|
||||||
)
|
|
||||||
text = text.decode(default_source_encoding).encode(
|
|
||||||
dest_encoding
|
|
||||||
) # XXX #py3 #sco8 à tester
|
|
||||||
else:
|
else:
|
||||||
if detected_encoding != dest_encoding:
|
if detected_encoding != dest_encoding:
|
||||||
message = "converting from detected %s to %s" % (
|
message = (
|
||||||
detected_encoding,
|
f"converting from detected {default_source_encoding} to {dest_encoding}"
|
||||||
dest_encoding,
|
|
||||||
)
|
)
|
||||||
text = text.decode(detected_encoding).encode(dest_encoding) # XXX
|
text = text.decode(detected_encoding).encode(dest_encoding)
|
||||||
return text, message
|
return text, message
|
||||||
|
|
||||||
|
|
||||||
|
@ -373,7 +373,7 @@ def etudarchive_import_files(
|
|||||||
filename_title="fichier_a_charger",
|
filename_title="fichier_a_charger",
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"scolar/photos_import_files.html",
|
"scolar/photos_import_files.j2",
|
||||||
page_title="Téléchargement de fichiers associés aux étudiants",
|
page_title="Téléchargement de fichiers associés aux étudiants",
|
||||||
ignored_zipfiles=ignored_zipfiles,
|
ignored_zipfiles=ignored_zipfiles,
|
||||||
unmatched_files=unmatched_files,
|
unmatched_files=unmatched_files,
|
||||||
|
112
app/scodoc/sco_archives_justificatifs.py
Normal file
112
app/scodoc/sco_archives_justificatifs.py
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
from app.scodoc.sco_archives import BaseArchiver
|
||||||
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
|
from app.models import Identite, Departement
|
||||||
|
from flask import g
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class JustificatifArchiver(BaseArchiver):
|
||||||
|
"""
|
||||||
|
|
||||||
|
TOTALK:
|
||||||
|
- oid -> etudid
|
||||||
|
- archive_id -> date de création de l'archive (une archive par dépot de document)
|
||||||
|
|
||||||
|
justificatif
|
||||||
|
└── <dept_id>
|
||||||
|
└── <etudid/oid>
|
||||||
|
└── <archive_id>
|
||||||
|
├── [_description.txt]
|
||||||
|
└── [<filename.ext>]
|
||||||
|
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
- Faire fonction suppression fichier unique dans archive
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
BaseArchiver.__init__(self, archive_type="justificatifs")
|
||||||
|
|
||||||
|
def save_justificatif(
|
||||||
|
self,
|
||||||
|
etudid: int,
|
||||||
|
filename: str,
|
||||||
|
data: bytes or str,
|
||||||
|
archive_name: str = None,
|
||||||
|
description: str = "",
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Ajoute un fichier dans une archive "justificatif" pour l'etudid donné
|
||||||
|
Retourne l'archive_name utilisé
|
||||||
|
"""
|
||||||
|
self._set_dept(etudid)
|
||||||
|
if archive_name is None:
|
||||||
|
archive_id: str = self.create_obj_archive(
|
||||||
|
oid=etudid, description=description
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
archive_id: str = self.get_id_from_name(etudid, archive_name)
|
||||||
|
|
||||||
|
self.store(archive_id, filename, data)
|
||||||
|
|
||||||
|
return self.get_archive_name(archive_id)
|
||||||
|
|
||||||
|
def delete_justificatif(self, etudid: int, archive_name: str, filename: str = None):
|
||||||
|
"""
|
||||||
|
Supprime une archive ou un fichier particulier de l'archivage de l'étudiant donné
|
||||||
|
"""
|
||||||
|
self._set_dept(etudid)
|
||||||
|
if str(etudid) not in self.list_oids():
|
||||||
|
raise ValueError(f"Aucune archive pour etudid[{etudid}]")
|
||||||
|
|
||||||
|
archive_id = self.get_id_from_name(etudid, archive_name)
|
||||||
|
|
||||||
|
if filename is not None:
|
||||||
|
if filename not in self.list_archive(archive_id):
|
||||||
|
raise ValueError(
|
||||||
|
f"filename {filename} inconnu dans l'archive archive_id[{archive_id}] -> etudid[{etudid}]"
|
||||||
|
)
|
||||||
|
|
||||||
|
path: str = os.path.join(self.get_obj_dir(etudid), archive_id, filename)
|
||||||
|
|
||||||
|
if os.path.isfile(path):
|
||||||
|
os.remove(path)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.delete_archive(
|
||||||
|
os.path.join(
|
||||||
|
self.get_obj_dir(etudid),
|
||||||
|
archive_id,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def list_justificatifs(self, archive_name: str, etudid: int) -> list[str]:
|
||||||
|
"""
|
||||||
|
Retourne la liste des noms de fichiers dans l'archive donnée
|
||||||
|
"""
|
||||||
|
self._set_dept(etudid)
|
||||||
|
filenames: list[str] = []
|
||||||
|
archive_id = self.get_id_from_name(etudid, archive_name)
|
||||||
|
|
||||||
|
filenames = self.list_archive(archive_id)
|
||||||
|
return filenames
|
||||||
|
|
||||||
|
def get_justificatif_file(self, archive_name: str, etudid: int, filename: str):
|
||||||
|
"""
|
||||||
|
Retourne une réponse de téléchargement de fichier si le fichier existe
|
||||||
|
"""
|
||||||
|
self._set_dept(etudid)
|
||||||
|
archive_id: str = self.get_id_from_name(etudid, archive_name)
|
||||||
|
if filename in self.list_archive(archive_id):
|
||||||
|
return self.get_archived_file(etudid, archive_name, filename)
|
||||||
|
raise ScoValueError(
|
||||||
|
f"Fichier {filename} introuvable dans l'archive {archive_name}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _set_dept(self, etudid: int):
|
||||||
|
if g.scodoc_dept is None or g.scodoc_dept_id is None:
|
||||||
|
etud: Identite = Identite.query.filter_by(id=etudid).first()
|
||||||
|
dept: Departement = Departement.query.filter_by(id=etud.dept_id).first()
|
||||||
|
|
||||||
|
g.scodoc_dept = dept.acronym
|
||||||
|
g.scodoc_dept_id = dept.id
|
@ -1,27 +1,33 @@
|
|||||||
from app.models.etudiants import Identite
|
from datetime import date, datetime, time, timedelta
|
||||||
from app.models.formsemestre import FormSemestre
|
|
||||||
from app.models.assiduites import Assiduite
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from datetime import datetime, date, time, timedelta
|
from app.models.assiduites import Assiduite, Justificatif
|
||||||
|
from app.models.etudiants import Identite
|
||||||
|
from app.models.formsemestre import FormSemestre, FormSemestreInscription
|
||||||
|
|
||||||
# TOTALK: Réfléchir sur le fractionnement d'une assiduite prolongée
|
# TOTALK: Réfléchir sur le fractionnement d'une assiduite prolongée
|
||||||
|
|
||||||
|
|
||||||
def get_assiduites_stats(
|
def get_assiduites_stats(
|
||||||
assiduites: Assiduite, metric: str = "all", filter: dict[str, object] = {}
|
assiduites: Assiduite, metric: str = "all", filtered: dict[str, object] = None
|
||||||
) -> Assiduite:
|
) -> Assiduite:
|
||||||
if filter != {}:
|
|
||||||
for key in filter:
|
if filtered is not None:
|
||||||
|
for key in filtered:
|
||||||
if key == "etat":
|
if key == "etat":
|
||||||
assiduites = filter_by_etat(assiduites, filter[key])
|
assiduites = filter_assiduites_by_etat(assiduites, filtered[key])
|
||||||
elif key == "date_fin":
|
elif key == "date_fin":
|
||||||
assiduites = filter_by_date(assiduites, filter[key], sup=False)
|
assiduites = filter_assiduites_by_date(
|
||||||
|
assiduites, filtered[key], sup=False
|
||||||
|
)
|
||||||
elif key == "date_debut":
|
elif key == "date_debut":
|
||||||
assiduites = filter_by_date(assiduites, filter[key], sup=True)
|
assiduites = filter_assiduites_by_date(
|
||||||
|
assiduites, filtered[key], sup=True
|
||||||
|
)
|
||||||
elif key == "moduleimpl_id":
|
elif key == "moduleimpl_id":
|
||||||
assiduites = filter_by_module_impl(assiduites, filter[key])
|
assiduites = filter_by_module_impl(assiduites, filtered[key])
|
||||||
elif key == "formsemestre":
|
elif key == "formsemestre":
|
||||||
assiduites = filter_by_formsemstre(assiduites, filter[key])
|
assiduites = filter_by_formsemestre(assiduites, filtered[key])
|
||||||
|
|
||||||
count: dict = get_count(assiduites)
|
count: dict = get_count(assiduites)
|
||||||
|
|
||||||
@ -29,10 +35,10 @@ def get_assiduites_stats(
|
|||||||
|
|
||||||
output: dict = {}
|
output: dict = {}
|
||||||
|
|
||||||
for key in count:
|
for key, val in count.items():
|
||||||
if key in metrics:
|
if key in metrics:
|
||||||
output[key] = count[key]
|
output[key] = val
|
||||||
return output if output != {} else count
|
return output if output else count
|
||||||
|
|
||||||
|
|
||||||
def get_count(assiduites: Assiduite) -> dict[str, int or float]:
|
def get_count(assiduites: Assiduite) -> dict[str, int or float]:
|
||||||
@ -48,9 +54,11 @@ def get_count(assiduites: Assiduite) -> dict[str, int or float]:
|
|||||||
current_day: date = None
|
current_day: date = None
|
||||||
current_time: str = None
|
current_time: str = None
|
||||||
|
|
||||||
MIDNIGHT: time = time(hour=0)
|
midnight: time = time(hour=0)
|
||||||
NOON: time = time(hour=12)
|
noon: time = time(hour=12)
|
||||||
time_check = lambda d: (MIDNIGHT <= d.time() <= NOON)
|
|
||||||
|
def time_check(dtime):
|
||||||
|
return midnight <= dtime.time() <= noon
|
||||||
|
|
||||||
for ass in all_assiduites:
|
for ass in all_assiduites:
|
||||||
delta: timedelta = ass.date_fin - ass.date_debut
|
delta: timedelta = ass.date_fin - ass.date_debut
|
||||||
@ -72,7 +80,7 @@ def get_count(assiduites: Assiduite) -> dict[str, int or float]:
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def filter_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
|
def filter_assiduites_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
|
||||||
"""
|
"""
|
||||||
Filtrage d'une collection d'assiduites en fonction de leur état
|
Filtrage d'une collection d'assiduites en fonction de leur état
|
||||||
"""
|
"""
|
||||||
@ -81,8 +89,8 @@ def filter_by_etat(assiduites: Assiduite, etat: str) -> Assiduite:
|
|||||||
return assiduites.filter(Assiduite.etat.in_(etats))
|
return assiduites.filter(Assiduite.etat.in_(etats))
|
||||||
|
|
||||||
|
|
||||||
def filter_by_date(
|
def filter_assiduites_by_date(
|
||||||
assiduites: Assiduite, date: datetime, sup: bool = True
|
assiduites: Assiduite, date_: datetime, sup: bool = True
|
||||||
) -> Assiduite:
|
) -> Assiduite:
|
||||||
"""
|
"""
|
||||||
Filtrage d'une collection d'assiduites en fonction d'une date
|
Filtrage d'une collection d'assiduites en fonction d'une date
|
||||||
@ -91,15 +99,47 @@ def filter_by_date(
|
|||||||
Sup == False -> les assiduites doivent finir avant 'date'
|
Sup == False -> les assiduites doivent finir avant 'date'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if date.tzinfo is None:
|
if date_.tzinfo is None:
|
||||||
first_assiduite: Assiduite = assiduites.first()
|
first_assiduite: Assiduite = assiduites.first()
|
||||||
if first_assiduite is not None:
|
if first_assiduite is not None:
|
||||||
date: datetime = date.replace(tzinfo=first_assiduite.date_debut.tzinfo)
|
date_: datetime = date_.replace(tzinfo=first_assiduite.date_debut.tzinfo)
|
||||||
|
|
||||||
if sup:
|
if sup:
|
||||||
return assiduites.filter(Assiduite.date_debut >= date)
|
return assiduites.filter(Assiduite.date_debut >= date_)
|
||||||
else:
|
|
||||||
return assiduites.filter(Assiduite.date_fin <= date)
|
return assiduites.filter(Assiduite.date_fin <= date_)
|
||||||
|
|
||||||
|
|
||||||
|
def filter_justificatifs_by_etat(
|
||||||
|
justificatifs: Justificatif, etat: str
|
||||||
|
) -> Justificatif:
|
||||||
|
"""
|
||||||
|
Filtrage d'une collection de justificatifs en fonction de leur état
|
||||||
|
"""
|
||||||
|
etats: list[str] = list(etat.split(","))
|
||||||
|
etats = [scu.ETATS_JUSTIFICATIF.get(e, -1) for e in etats]
|
||||||
|
return justificatifs.filter(Justificatif.etat.in_(etats))
|
||||||
|
|
||||||
|
|
||||||
|
def filter_justificatifs_by_date(
|
||||||
|
justificatifs: Justificatif, date_: datetime, sup: bool = True
|
||||||
|
) -> Assiduite:
|
||||||
|
"""
|
||||||
|
Filtrage d'une collection d'assiduites en fonction d'une date
|
||||||
|
|
||||||
|
Sup == True -> les assiduites doivent débuter après 'date'\n
|
||||||
|
Sup == False -> les assiduites doivent finir avant 'date'
|
||||||
|
"""
|
||||||
|
|
||||||
|
if date_.tzinfo is None:
|
||||||
|
first_justificatif: Justificatif = justificatifs.first()
|
||||||
|
if first_justificatif is not None:
|
||||||
|
date_: datetime = date_.replace(tzinfo=first_justificatif.date_debut.tzinfo)
|
||||||
|
|
||||||
|
if sup:
|
||||||
|
return justificatifs.filter(Justificatif.date_debut >= date_)
|
||||||
|
|
||||||
|
return justificatifs.filter(Justificatif.date_fin <= date_)
|
||||||
|
|
||||||
|
|
||||||
def filter_by_module_impl(
|
def filter_by_module_impl(
|
||||||
@ -111,18 +151,24 @@ def filter_by_module_impl(
|
|||||||
return assiduites.filter(Assiduite.moduleimpl_id == module_impl_id)
|
return assiduites.filter(Assiduite.moduleimpl_id == module_impl_id)
|
||||||
|
|
||||||
|
|
||||||
def filter_by_formsemstre(assiduites: Assiduite, formsemestre: FormSemestre):
|
def filter_by_formsemestre(assiduites_query: Assiduite, formsemestre: FormSemestre):
|
||||||
"""
|
"""
|
||||||
Filtrage d'une collection d'assiduites en fonction d'un formsemestre
|
Filtrage d'une collection d'assiduites en fonction d'un formsemestre
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if formsemestre is None:
|
if formsemestre is None:
|
||||||
return assiduites.filter(False)
|
return assiduites_query.filter(False)
|
||||||
|
|
||||||
assiduites = assiduites.filter(
|
assiduites_query = (
|
||||||
Identite.query.filter_by(id=Assiduite.etudid).first()
|
assiduites_query.join(Identite, Assiduite.etudid == Identite.id)
|
||||||
in formsemestre.etuds.all()
|
.join(
|
||||||
|
FormSemestreInscription,
|
||||||
|
Identite.id == FormSemestreInscription.etudid,
|
||||||
|
)
|
||||||
|
.filter(FormSemestreInscription.formsemestre_id == formsemestre.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
assiduites = assiduites.filter(Assiduite.date_debut >= formsemestre.date_debut)
|
assiduites_query = assiduites_query.filter(
|
||||||
return assiduites.filter(Assiduite.date_fin <= formsemestre.date_fin)
|
Assiduite.date_debut >= formsemestre.date_debut
|
||||||
|
)
|
||||||
|
return assiduites_query.filter(Assiduite.date_fin <= formsemestre.date_fin)
|
||||||
|
@ -926,7 +926,7 @@ def formsemestre_bulletinetud(
|
|||||||
_formsemestre_bulletinetud_header_html(etud, formsemestre, format, version),
|
_formsemestre_bulletinetud_header_html(etud, formsemestre, format, version),
|
||||||
bulletin,
|
bulletin,
|
||||||
render_template(
|
render_template(
|
||||||
"bul_foot.html",
|
"bul_foot.j2",
|
||||||
appreciations=None, # déjà affichées
|
appreciations=None, # déjà affichées
|
||||||
css_class="bul_classic_foot",
|
css_class="bul_classic_foot",
|
||||||
etud=etud,
|
etud=etud,
|
||||||
@ -1259,7 +1259,7 @@ def _formsemestre_bulletinetud_header_html(
|
|||||||
cssstyles=["css/radar_bulletin.css"],
|
cssstyles=["css/radar_bulletin.css"],
|
||||||
),
|
),
|
||||||
render_template(
|
render_template(
|
||||||
"bul_head.html",
|
"bul_head.j2",
|
||||||
etud=etud,
|
etud=etud,
|
||||||
format=format,
|
format=format,
|
||||||
formsemestre=formsemestre,
|
formsemestre=formsemestre,
|
||||||
|
@ -234,6 +234,16 @@ def formation_edit(formation_id=None, create=False):
|
|||||||
"explanation": "optionel: code utilisé pour échanger avec d'autres logiciels et identifiant la filière ou spécialité (exemple: ASUR). N'est utilisé que s'il n'y a pas de numéro de semestre.",
|
"explanation": "optionel: code utilisé pour échanger avec d'autres logiciels et identifiant la filière ou spécialité (exemple: ASUR). N'est utilisé que s'il n'y a pas de numéro de semestre.",
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"commentaire",
|
||||||
|
{
|
||||||
|
"input_type": "textarea",
|
||||||
|
"rows": 3,
|
||||||
|
"cols": 77,
|
||||||
|
"title": "Commentaire",
|
||||||
|
"explanation": "commentaire libre.",
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
initvalues=initvalues,
|
initvalues=initvalues,
|
||||||
submitlabel=submitlabel,
|
submitlabel=submitlabel,
|
||||||
|
@ -385,7 +385,7 @@ def module_edit(
|
|||||||
),
|
),
|
||||||
f"""<h2>{title}</h2>""",
|
f"""<h2>{title}</h2>""",
|
||||||
render_template(
|
render_template(
|
||||||
"scodoc/help/modules.html",
|
"scodoc/help/modules.j2",
|
||||||
is_apc=is_apc,
|
is_apc=is_apc,
|
||||||
semestre_id=semestre_id,
|
semestre_id=semestre_id,
|
||||||
formsemestres=FormSemestre.query.filter(
|
formsemestres=FormSemestre.query.filter(
|
||||||
@ -396,6 +396,7 @@ def module_edit(
|
|||||||
.all()
|
.all()
|
||||||
if not create
|
if not create
|
||||||
else None,
|
else None,
|
||||||
|
create=create,
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
if not unlocked:
|
if not unlocked:
|
||||||
@ -655,7 +656,8 @@ def module_edit(
|
|||||||
(
|
(
|
||||||
"numero",
|
"numero",
|
||||||
{
|
{
|
||||||
"size": 2,
|
"title": "Numéro",
|
||||||
|
"size": 4,
|
||||||
"explanation": "numéro (1, 2, 3, 4, ...) pour ordre d'affichage",
|
"explanation": "numéro (1, 2, 3, 4, ...) pour ordre d'affichage",
|
||||||
"type": "int",
|
"type": "int",
|
||||||
"default": default_num,
|
"default": default_num,
|
||||||
|
@ -591,19 +591,45 @@ def view_apo_csv_store(semset_id="", csvfile=None, data: bytes = "", autodetect=
|
|||||||
if not semset_id:
|
if not semset_id:
|
||||||
raise ValueError("invalid null semset_id")
|
raise ValueError("invalid null semset_id")
|
||||||
semset = sco_semset.SemSet(semset_id=semset_id)
|
semset = sco_semset.SemSet(semset_id=semset_id)
|
||||||
|
try:
|
||||||
if csvfile:
|
if csvfile:
|
||||||
data = csvfile.read() # bytes
|
data = csvfile.read() # bytes
|
||||||
if autodetect:
|
if autodetect:
|
||||||
# check encoding (although documentation states that users SHOULD upload LATIN1)
|
# check encoding (although documentation states that users SHOULD upload LATIN1)
|
||||||
|
|
||||||
data, message = sco_apogee_csv.fix_data_encoding(data)
|
data, message = sco_apogee_csv.fix_data_encoding(data)
|
||||||
if message:
|
if message:
|
||||||
log("view_apo_csv_store: %s" % message)
|
log(f"view_apo_csv_store: {message}")
|
||||||
else:
|
else:
|
||||||
log("view_apo_csv_store: autodetection of encoding disabled by user")
|
log("view_apo_csv_store: autodetection of encoding disabled by user")
|
||||||
if not data:
|
if not data:
|
||||||
raise ScoValueError("view_apo_csv_store: no data")
|
raise ScoValueError("view_apo_csv_store: no data")
|
||||||
# data est du bytes, encodé en APO_INPUT_ENCODING
|
# data est du bytes, encodé en APO_INPUT_ENCODING
|
||||||
data_str = data.decode(APO_INPUT_ENCODING)
|
data_str = data.decode(APO_INPUT_ENCODING)
|
||||||
|
except (UnicodeDecodeError, UnicodeEncodeError) as exc:
|
||||||
|
dest_url = url_for(
|
||||||
|
"notes.apo_semset_maq_status",
|
||||||
|
scodoc_dept=g.scodoc_dept,
|
||||||
|
semset_id=semset_id,
|
||||||
|
)
|
||||||
|
if autodetect:
|
||||||
|
raise ScoValueError(
|
||||||
|
f"""
|
||||||
|
Erreur: l'encodage du fichier est mal détecté.
|
||||||
|
Essayez sans auto-détection, ou vérifiez le codage et le contenu
|
||||||
|
du fichier (qui doit être en {sco_apogee_csv.APO_INPUT_ENCODING}).
|
||||||
|
""",
|
||||||
|
dest_url=dest_url,
|
||||||
|
) from exc
|
||||||
|
else:
|
||||||
|
raise ScoValueError(
|
||||||
|
f"""
|
||||||
|
Erreur: l'encodage du fichier est incorrect.
|
||||||
|
Vérifiez qu'il est bien en {sco_apogee_csv.APO_INPUT_ENCODING}
|
||||||
|
""",
|
||||||
|
dest_url=dest_url,
|
||||||
|
) from exc
|
||||||
|
|
||||||
# check si etape maquette appartient bien au semset
|
# check si etape maquette appartient bien au semset
|
||||||
apo_data = sco_apogee_csv.ApoData(
|
apo_data = sco_apogee_csv.ApoData(
|
||||||
data_str, periode=semset["sem_id"]
|
data_str, periode=semset["sem_id"]
|
||||||
|
@ -36,7 +36,7 @@ from flask_login import current_user
|
|||||||
|
|
||||||
from app import db, log
|
from app import db, log
|
||||||
|
|
||||||
from app.models import Evaluation, ModuleImpl, ScolarNews
|
from app.models import ModuleImpl, ScolarNews
|
||||||
from app.models.evaluations import evaluation_enrich_dict, check_evaluation_args
|
from app.models.evaluations import evaluation_enrich_dict, check_evaluation_args
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
|
@ -345,7 +345,7 @@ def evaluation_create_form(
|
|||||||
+ "\n".join(H)
|
+ "\n".join(H)
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ tf[1]
|
+ tf[1]
|
||||||
+ render_template("scodoc/help/evaluations.html", is_apc=is_apc)
|
+ render_template("scodoc/help/evaluations.j2", is_apc=is_apc)
|
||||||
+ html_sco_header.sco_footer()
|
+ html_sco_header.sco_footer()
|
||||||
)
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
|
@ -75,6 +75,7 @@ _formationEditor = ndb.EditableTable(
|
|||||||
"type_parcours",
|
"type_parcours",
|
||||||
"code_specialite",
|
"code_specialite",
|
||||||
"referentiel_competence_id",
|
"referentiel_competence_id",
|
||||||
|
"commentaire",
|
||||||
),
|
),
|
||||||
filter_dept=True,
|
filter_dept=True,
|
||||||
sortkey="acronyme",
|
sortkey="acronyme",
|
||||||
@ -118,6 +119,7 @@ def formation_export(
|
|||||||
formation: Formation = Formation.query.get_or_404(formation_id)
|
formation: Formation = Formation.query.get_or_404(formation_id)
|
||||||
f_dict = formation.to_dict(with_refcomp_attrs=True)
|
f_dict = formation.to_dict(with_refcomp_attrs=True)
|
||||||
if not export_ids:
|
if not export_ids:
|
||||||
|
del f_dict["id"]
|
||||||
del f_dict["formation_id"]
|
del f_dict["formation_id"]
|
||||||
del f_dict["dept_id"]
|
del f_dict["dept_id"]
|
||||||
ues = formation.ues
|
ues = formation.ues
|
||||||
|
@ -541,7 +541,7 @@ def formsemestre_page_title(formsemestre_id=None):
|
|||||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||||
|
|
||||||
h = render_template(
|
h = render_template(
|
||||||
"formsemestre_page_title.html",
|
"formsemestre_page_title.j2",
|
||||||
formsemestre=formsemestre,
|
formsemestre=formsemestre,
|
||||||
scu=scu,
|
scu=scu,
|
||||||
sem_menu_bar=formsemestre_status_menubar(formsemestre),
|
sem_menu_bar=formsemestre_status_menubar(formsemestre),
|
||||||
|
@ -46,7 +46,7 @@ def affect_groups(partition_id):
|
|||||||
raise AccessDenied("vous n'avez pas la permission de modifier les groupes")
|
raise AccessDenied("vous n'avez pas la permission de modifier les groupes")
|
||||||
partition.formsemestre.setup_parcours_groups()
|
partition.formsemestre.setup_parcours_groups()
|
||||||
return render_template(
|
return render_template(
|
||||||
"scolar/affect_groups.html",
|
"scolar/affect_groups.j2",
|
||||||
sco_header=html_sco_header.sco_header(
|
sco_header=html_sco_header.sco_header(
|
||||||
page_title="Affectation aux groupes",
|
page_title="Affectation aux groupes",
|
||||||
javascripts=["js/groupmgr.js"],
|
javascripts=["js/groupmgr.js"],
|
||||||
|
@ -400,9 +400,7 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
|||||||
# Etudiants "dispensés" d'une UE (capitalisée)
|
# Etudiants "dispensés" d'une UE (capitalisée)
|
||||||
ues_cap_info = get_etuds_with_capitalized_ue(formsemestre_id)
|
ues_cap_info = get_etuds_with_capitalized_ue(formsemestre_id)
|
||||||
if ues_cap_info:
|
if ues_cap_info:
|
||||||
H.append(
|
H.append('<h3>Étudiants avec UEs capitalisées:</h3><ul class="ue_inscr_list">')
|
||||||
'<h3>Étudiants avec UEs capitalisées (ADM):</h3><ul class="ue_inscr_list">'
|
|
||||||
)
|
|
||||||
ues = [
|
ues = [
|
||||||
sco_edit_ue.ue_list({"ue_id": ue_id})[0] for ue_id in ues_cap_info.keys()
|
sco_edit_ue.ue_list({"ue_id": ue_id})[0] for ue_id in ues_cap_info.keys()
|
||||||
]
|
]
|
||||||
@ -470,8 +468,7 @@ def moduleimpl_inscriptions_stats(formsemestre_id):
|
|||||||
if can_change:
|
if can_change:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<div><a class="stdlink" href="{
|
f"""<div><a class="stdlink" href="{
|
||||||
url_for("notes.etud_inscrit_ue",
|
url_for("notes.etud_inscrit_ue", scodoc_dept=g.scodoc_dept, etudid=etud["etudid"],
|
||||||
scodoc_dept=g.scodoc_dept, etudid=etud["etudid"],
|
|
||||||
formsemestre_id=formsemestre_id, ue_id=ue["ue_id"])
|
formsemestre_id=formsemestre_id, ue_id=ue["ue_id"])
|
||||||
}">inscrire à {"" if is_apc else "tous les modules de"} cette UE</a></div>
|
}">inscrire à {"" if is_apc else "tous les modules de"} cette UE</a></div>
|
||||||
"""
|
"""
|
||||||
|
@ -215,7 +215,7 @@ def placement_eval_selectetuds(evaluation_id):
|
|||||||
html_sco_header.sco_header(),
|
html_sco_header.sco_header(),
|
||||||
sco_evaluations.evaluation_describe(evaluation_id=evaluation_id),
|
sco_evaluations.evaluation_describe(evaluation_id=evaluation_id),
|
||||||
"<h3>Placement et émargement des étudiants</h3>",
|
"<h3>Placement et émargement des étudiants</h3>",
|
||||||
render_template("scodoc/forms/placement.html", form=form),
|
render_template("scodoc/forms/placement.j2", form=form),
|
||||||
]
|
]
|
||||||
footer = html_sco_header.sco_footer()
|
footer = html_sco_header.sco_footer()
|
||||||
return "\n".join(htmls) + "<p>" + footer
|
return "\n".join(htmls) + "<p>" + footer
|
||||||
|
@ -166,9 +166,15 @@ def formsemestre_recapcomplet(
|
|||||||
H.append("<p>")
|
H.append("<p>")
|
||||||
if mode_jury:
|
if mode_jury:
|
||||||
H.append(
|
H.append(
|
||||||
f"""<a class="stdlink" href="{url_for('notes.formsemestre_validation_auto',
|
f"""<p><a class="stdlink" href="{url_for('notes.formsemestre_validation_auto',
|
||||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id)
|
||||||
}">Calcul automatique des décisions du jury</a></p>"""
|
}">Calcul automatique des décisions du jury</a>
|
||||||
|
</p><a class="stdlink" href="{url_for('notes.formsemestre_jury_but_erase',
|
||||||
|
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre_id, only_one_sem=1)
|
||||||
|
}">Effacer <em>toutes</em> les décisions de jury du semestre</a>
|
||||||
|
<p>
|
||||||
|
</p>
|
||||||
|
"""
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
H.append(
|
H.append(
|
||||||
|
@ -554,7 +554,7 @@ def photos_import_files_form(group_ids=()):
|
|||||||
back_url=back_url,
|
back_url=back_url,
|
||||||
)
|
)
|
||||||
return render_template(
|
return render_template(
|
||||||
"scolar/photos_import_files.html",
|
"scolar/photos_import_files.j2",
|
||||||
page_title="Téléchargement des photos des étudiants",
|
page_title="Téléchargement des photos des étudiants",
|
||||||
ignored_zipfiles=ignored_zipfiles,
|
ignored_zipfiles=ignored_zipfiles,
|
||||||
unmatched_files=unmatched_files,
|
unmatched_files=unmatched_files,
|
||||||
|
@ -128,6 +128,13 @@ ETAT_JUSTIFICATIF_NAME = {
|
|||||||
EtatJustificatif.MODIFIE: "modifié",
|
EtatJustificatif.MODIFIE: "modifié",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ETATS_JUSTIFICATIF = {
|
||||||
|
"validé": EtatJustificatif.VALIDE,
|
||||||
|
"non vaidé": EtatJustificatif.NON_VALIDE,
|
||||||
|
"en attente": EtatJustificatif.ATTENTE,
|
||||||
|
"modifié": EtatJustificatif.MODIFIE,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or None:
|
def is_iso_formated(date: str, convert=False) -> bool or datetime.datetime or None:
|
||||||
"""
|
"""
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
:root {
|
:root {
|
||||||
--sco-content-min-width: 600px;
|
--sco-content-min-width: 600px;
|
||||||
--sco-content-max-width: 1024px;
|
--sco-content-max-width: 1024px;
|
||||||
|
--sco-color-explication: rgb(10, 58, 140);
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
@ -325,9 +326,9 @@ div.logo-logo img {
|
|||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
/* -10px */
|
/* -10px */
|
||||||
width: 80px;
|
width: 130px;
|
||||||
/* adapter suivant image */
|
/* adapter suivant image */
|
||||||
padding-right: 5px;
|
/* padding-right: 5px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
div.sidebar-bottom {
|
div.sidebar-bottom {
|
||||||
@ -2115,6 +2116,11 @@ div.formation_descr span.fd_n {
|
|||||||
margin-left: 6em;
|
margin-left: 6em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span.explication {
|
||||||
|
font-style: italic;
|
||||||
|
color: var(--sco-color-explication);
|
||||||
|
}
|
||||||
|
|
||||||
div.formation_ue_list {
|
div.formation_ue_list {
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 69 KiB |
@ -14,6 +14,8 @@ $(function () {
|
|||||||
const url = new URL(document.URL);
|
const url = new URL(document.URL);
|
||||||
const formsemestre_id = url.searchParams.get("formsemestre_id");
|
const formsemestre_id = url.searchParams.get("formsemestre_id");
|
||||||
const order_info_key = JSON.stringify([url.pathname, formsemestre_id]);
|
const order_info_key = JSON.stringify([url.pathname, formsemestre_id]);
|
||||||
|
const etudids_key = JSON.stringify(["etudids", url.origin, formsemestre_id]);
|
||||||
|
const noms_key = JSON.stringify(["noms", url.origin, formsemestre_id]);
|
||||||
let order_info;
|
let order_info;
|
||||||
if (formsemestre_id) {
|
if (formsemestre_id) {
|
||||||
const x = localStorage.getItem(order_info_key);
|
const x = localStorage.getItem(order_info_key);
|
||||||
@ -157,6 +159,7 @@ $(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
let table = $('table.table_recap').DataTable(
|
let table = $('table.table_recap').DataTable(
|
||||||
{
|
{
|
||||||
paging: false,
|
paging: false,
|
||||||
@ -226,14 +229,19 @@ $(function () {
|
|||||||
document.querySelectorAll("td.identite_court").forEach(e => {
|
document.querySelectorAll("td.identite_court").forEach(e => {
|
||||||
noms.push(e.dataset.nomprenom);
|
noms.push(e.dataset.nomprenom);
|
||||||
});
|
});
|
||||||
const etudids_key = JSON.stringify(["etudids", url.origin, formsemestre_id]);
|
|
||||||
localStorage.setItem(etudids_key, JSON.stringify(etudids));
|
localStorage.setItem(etudids_key, JSON.stringify(etudids));
|
||||||
const noms_key = JSON.stringify(["noms", url.origin, formsemestre_id]);
|
|
||||||
localStorage.setItem(noms_key, JSON.stringify(noms));
|
localStorage.setItem(noms_key, JSON.stringify(noms));
|
||||||
},
|
},
|
||||||
"order": order_info,
|
"order": order_info,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
// l'erreur peut etre causee par un ancien storage:
|
||||||
|
localStorage.removeItem(etudids_key);
|
||||||
|
localStorage.removeItem(noms_key);
|
||||||
|
localStorage.removeItem(order_info_key);
|
||||||
|
location.reload();
|
||||||
|
}
|
||||||
update_buttons_labels(table);
|
update_buttons_labels(table);
|
||||||
});
|
});
|
||||||
$('table.table_recap tbody').on('click', 'tr', function () {
|
$('table.table_recap tbody').on('click', 'tr', function () {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.j2' %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
|
|
||||||
<h2>Système de gestion scolarité</h2>
|
<h2>Système de gestion scolarité</h2>
|
||||||
|
|
||||||
<p>© Emmanuel Viennet 2021</p>
|
<p>© Emmanuel Viennet 2023</p>
|
||||||
|
|
||||||
<p>Version {{ version }}</p>
|
<p>Version {{ version }}</p>
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% macro render_field(field, auth_name=None) %}
|
{% macro render_field(field, auth_name=None) %}
|
||||||
@ -29,7 +29,8 @@
|
|||||||
<form method=post>
|
<form method=post>
|
||||||
{{ form.user_name }}
|
{{ form.user_name }}
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
<table class="tf"><tbody>
|
<table class="tf">
|
||||||
|
<tbody>
|
||||||
{{ render_field(form.old_password, size=14, auth_name=auth_username,
|
{{ render_field(form.old_password, size=14, auth_name=auth_username,
|
||||||
style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
|
style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
|
||||||
<tr>
|
<tr>
|
||||||
@ -44,7 +45,8 @@
|
|||||||
style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
|
style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
|
||||||
{{ render_field(form.email, size=40,
|
{{ render_field(form.email, size=40,
|
||||||
style="padding:1px; margin-top: 12px;margin-bottom: 16px; margin-left: 1em;") }}
|
style="padding:1px; margin-top: 12px;margin-bottom: 16px; margin-left: 1em;") }}
|
||||||
</tbody></table>
|
</tbody>
|
||||||
|
</table>
|
||||||
<input type="submit" value="Valider">
|
<input type="submit" value="Valider">
|
||||||
<input type="submit" name="cancel" value="Annuler" style="margin-left: 1em;>
|
<input type="submit" name="cancel" value="Annuler" style="margin-left: 1em;>
|
||||||
</form>
|
</form>
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.j2' %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -36,7 +36,9 @@
|
|||||||
url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)
|
url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)
|
||||||
}}">Dept. {{ g.scodoc_dept }}</a></li>
|
}}">Dept. {{ g.scodoc_dept }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if not current_user.is_anonymous and current_user.has_permission(current_user.Permission.RelationsEntreprisesView, None) and scu and scu.is_entreprises_enabled() %}
|
{% if not current_user.is_anonymous and
|
||||||
|
current_user.has_permission(current_user.Permission.RelationsEntreprisesView, None) and scu and
|
||||||
|
scu.is_entreprises_enabled() %}
|
||||||
<li><a href="{{ url_for('entreprises.index') }}">Entreprises</a></li>
|
<li><a href="{{ url_for('entreprises.index') }}">Entreprises</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.html" %}
|
{% extends "sco_page.j2" %}
|
||||||
|
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
@ -7,12 +7,12 @@
|
|||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
|
|
||||||
{% include 'bul_head.html' %}
|
{% include 'bul_head.j2' %}
|
||||||
|
|
||||||
<releve-but></releve-but>
|
<releve-but></releve-but>
|
||||||
<script src="{{sco.scu.STATIC_DIR}}/js/releve-but.js"></script>
|
<script src="{{sco.scu.STATIC_DIR}}/js/releve-but.js"></script>
|
||||||
|
|
||||||
{% include 'bul_foot.html' %}
|
{% include 'bul_foot.j2' %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
let dataSrc = "{{bul_url|safe}}";
|
let dataSrc = "{{bul_url|safe}}";
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.html" %}
|
{% extends "sco_page.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block styles %}
|
{% block styles %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,30 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends "base.html" %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>Charger un référentiel de compétences</h1>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-5">
|
|
||||||
{{ wtf.quick_form(form) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-5">
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept, ) }}">
|
|
||||||
Liste des référentiels de compétences chargés</a>
|
|
||||||
</li>
|
|
||||||
{% if formation is not none %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('notes.refcomp_assoc_formation', scodoc_dept=g.scodoc_dept, formation_id=formation.id) }}">
|
|
||||||
Association à la formation {{ formation.acronyme }}</a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
31
app/templates/but/refcomp_load.j2
Normal file
31
app/templates/but/refcomp_load.j2
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends "base.j2" %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>Charger un référentiel de compétences</h1>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
{{ wtf.quick_form(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-5">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="{{ url_for('notes.refcomp_table', scodoc_dept=g.scodoc_dept, ) }}">
|
||||||
|
Liste des référentiels de compétences chargés</a>
|
||||||
|
</li>
|
||||||
|
{% if formation is not none %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ url_for('notes.refcomp_assoc_formation', scodoc_dept=g.scodoc_dept, formation_id=formation.id) }}">
|
||||||
|
Association à la formation {{ formation.acronyme }}</a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.html" %}
|
{% extends "sco_page.j2" %}
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
{{super()}}
|
{{super()}}
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "sco_page.html" %}
|
{% extends "sco_page.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,4 +1,4 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,132 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% macro render_field(field, with_label=True) %}
|
|
||||||
<div>
|
|
||||||
{% if with_label %}
|
|
||||||
<span class="wtf-field">{{ field.label }} :</span>
|
|
||||||
{% endif %}
|
|
||||||
<span class="wtf-field">{{ field(**kwargs)|safe }}
|
|
||||||
{% if field.errors %}
|
|
||||||
<ul class=errors>
|
|
||||||
{% for error in field.errors %}
|
|
||||||
<li>{{ error }}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_add_logo(add_logo_form) %}
|
|
||||||
<details {{ add_logo_form.opened() }}>
|
|
||||||
<summary>
|
|
||||||
<h3>Ajouter un logo</h3>
|
|
||||||
</summary>
|
|
||||||
<div>
|
|
||||||
{{ render_field(add_logo_form.name) }}
|
|
||||||
{{ render_field(add_logo_form.upload) }}
|
|
||||||
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_logo(dept_form, logo_form) %}
|
|
||||||
<details {{ logo_form.opened() }}>
|
|
||||||
{{ logo_form.hidden_tag() }}
|
|
||||||
<summary>
|
|
||||||
{% if logo_form.titre %}
|
|
||||||
<h3 class="titre_logo">{{ logo_form.titre }}</h3>
|
|
||||||
{% if logo_form.description %}
|
|
||||||
<div class="sco_help">{{ logo_form.description }}</div>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
<h3 class="titre_logo">Logo personalisé: {{ logo_form.logo_id.data }}</h3>
|
|
||||||
{% if logo_form.description %}
|
|
||||||
<div class="sco_help">{{ logo_form.description }}</div>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
</summary>
|
|
||||||
<div class="content">
|
|
||||||
<div class="image_logo">
|
|
||||||
<img src="{{ logo_form.logo.get_url_small() }}" alt="pas de logo chargé" />
|
|
||||||
</div>
|
|
||||||
<div class="infos_logo">
|
|
||||||
<h4>{{ logo_form.logo.logoname }} (Format: {{ logo_form.logo.suffix }})</h4>
|
|
||||||
Taille: {{ logo_form.logo.size }} px
|
|
||||||
{% if logo_form.logo.mm %} / {{ logo_form.logo.mm }} mm {% endif %}<br />
|
|
||||||
Aspect ratio: {{ logo_form.logo.aspect_ratio }}<br />
|
|
||||||
Usage: <span style="font-family: system-ui">{{ logo_form.logo.get_usage() }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="actions_logo">
|
|
||||||
<div class="action_label">Modifier l'image</div>
|
|
||||||
<div class="action_button">
|
|
||||||
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
|
|
||||||
</div>
|
|
||||||
{% if logo_form.can_delete %}
|
|
||||||
<div class="action_label">Renommer</div>
|
|
||||||
<div class="action_button">
|
|
||||||
{{ render_field(logo_form.new_name, False) }}
|
|
||||||
{{ render_field(logo_form.do_rename, False, onSubmit="submit_form()") }}
|
|
||||||
</div>
|
|
||||||
<div class="action_label">Supprimer l'image</div>
|
|
||||||
<div class="action_button">
|
|
||||||
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% macro render_logos(dept_form) %}
|
|
||||||
{% for logo_entry in dept_form.logos.entries %}
|
|
||||||
{% set logo_form = logo_entry.form %}
|
|
||||||
{{ render_logo(dept_form, logo_form) }}
|
|
||||||
{% else %}
|
|
||||||
<p class="logo-titre_logo">
|
|
||||||
<h3 class="titre_logo">Aucun logo défini en propre à ce département</h3>
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
{% endmacro %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery.js"></script>
|
|
||||||
<script src="/ScoDoc/static/js/config_logos.js"></script>
|
|
||||||
|
|
||||||
<form id="config_logos_form" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
|
|
||||||
<div class="configuration_logo">
|
|
||||||
<h1>Bibliothèque de logos</h1>
|
|
||||||
{% for dept_entry in form.depts.entries %}
|
|
||||||
{% set dept_form = dept_entry.form %}
|
|
||||||
{{ dept_entry.form.hidden_tag() }}
|
|
||||||
<details {{ dept_form.opened() }}>
|
|
||||||
<summary>
|
|
||||||
<span class="entete_dept">
|
|
||||||
{% if dept_entry.form.is_local() %}
|
|
||||||
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
|
||||||
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
|
||||||
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br />
|
|
||||||
Les logos du département se substituent aux logos de même nom définis globalement:</div>
|
|
||||||
{% else %}
|
|
||||||
<h2>Logos généraux</h2>
|
|
||||||
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
|
||||||
<div class="sco_help">Les images de cette section sont utilisé pour tous les départements,
|
|
||||||
mais peuvent être redéfinies localement au niveau de chaque département
|
|
||||||
(il suffit de définir un logo local de même nom)</div>
|
|
||||||
{% endif %}
|
|
||||||
</span>
|
|
||||||
</summary>
|
|
||||||
<div>
|
|
||||||
{{ render_logos(dept_form) }}
|
|
||||||
{{ render_add_logo(dept_form.add_logo.form) }}
|
|
||||||
</div>
|
|
||||||
</details>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
132
app/templates/config_logos.j2
Normal file
132
app/templates/config_logos.j2
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% macro render_field(field, with_label=True) %}
|
||||||
|
<div>
|
||||||
|
{% if with_label %}
|
||||||
|
<span class="wtf-field">{{ field.label }} :</span>
|
||||||
|
{% endif %}
|
||||||
|
<span class="wtf-field">{{ field(**kwargs)|safe }}
|
||||||
|
{% if field.errors %}
|
||||||
|
<ul class=errors>
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_add_logo(add_logo_form) %}
|
||||||
|
<details {{ add_logo_form.opened() }}>
|
||||||
|
<summary>
|
||||||
|
<h3>Ajouter un logo</h3>
|
||||||
|
</summary>
|
||||||
|
<div>
|
||||||
|
{{ render_field(add_logo_form.name) }}
|
||||||
|
{{ render_field(add_logo_form.upload) }}
|
||||||
|
{{ render_field(add_logo_form.do_insert, False, onSubmit="submit_form") }}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_logo(dept_form, logo_form) %}
|
||||||
|
<details {{ logo_form.opened() }}>
|
||||||
|
{{ logo_form.hidden_tag() }}
|
||||||
|
<summary>
|
||||||
|
{% if logo_form.titre %}
|
||||||
|
<h3 class="titre_logo">{{ logo_form.titre }}</h3>
|
||||||
|
{% if logo_form.description %}
|
||||||
|
<div class="sco_help">{{ logo_form.description }}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<h3 class="titre_logo">Logo personalisé: {{ logo_form.logo_id.data }}</h3>
|
||||||
|
{% if logo_form.description %}
|
||||||
|
<div class="sco_help">{{ logo_form.description }}</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
</summary>
|
||||||
|
<div class="content">
|
||||||
|
<div class="image_logo">
|
||||||
|
<img src="{{ logo_form.logo.get_url_small() }}" alt="pas de logo chargé" />
|
||||||
|
</div>
|
||||||
|
<div class="infos_logo">
|
||||||
|
<h4>{{ logo_form.logo.logoname }} (Format: {{ logo_form.logo.suffix }})</h4>
|
||||||
|
Taille: {{ logo_form.logo.size }} px
|
||||||
|
{% if logo_form.logo.mm %} / {{ logo_form.logo.mm }} mm {% endif %}<br />
|
||||||
|
Aspect ratio: {{ logo_form.logo.aspect_ratio }}<br />
|
||||||
|
Usage: <span style="font-family: system-ui">{{ logo_form.logo.get_usage() }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="actions_logo">
|
||||||
|
<div class="action_label">Modifier l'image</div>
|
||||||
|
<div class="action_button">
|
||||||
|
<span class="wtf-field">{{ render_field(logo_form.upload, False, onchange="submit_form()") }}</span>
|
||||||
|
</div>
|
||||||
|
{% if logo_form.can_delete %}
|
||||||
|
<div class="action_label">Renommer</div>
|
||||||
|
<div class="action_button">
|
||||||
|
{{ render_field(logo_form.new_name, False) }}
|
||||||
|
{{ render_field(logo_form.do_rename, False, onSubmit="submit_form()") }}
|
||||||
|
</div>
|
||||||
|
<div class="action_label">Supprimer l'image</div>
|
||||||
|
<div class="action_button">
|
||||||
|
{{ render_field(logo_form.do_delete, False, onSubmit="submit_form()") }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_logos(dept_form) %}
|
||||||
|
{% for logo_entry in dept_form.logos.entries %}
|
||||||
|
{% set logo_form = logo_entry.form %}
|
||||||
|
{{ render_logo(dept_form, logo_form) }}
|
||||||
|
{% else %}
|
||||||
|
<p class="logo-titre_logo">
|
||||||
|
<h3 class="titre_logo">Aucun logo défini en propre à ce département</h3>
|
||||||
|
</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery.js"></script>
|
||||||
|
<script src="/ScoDoc/static/js/config_logos.js"></script>
|
||||||
|
|
||||||
|
<form id="config_logos_form" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
|
||||||
|
<div class="configuration_logo">
|
||||||
|
<h1>Bibliothèque de logos</h1>
|
||||||
|
{% for dept_entry in form.depts.entries %}
|
||||||
|
{% set dept_form = dept_entry.form %}
|
||||||
|
{{ dept_entry.form.hidden_tag() }}
|
||||||
|
<details {{ dept_form.opened() }}>
|
||||||
|
<summary>
|
||||||
|
<span class="entete_dept">
|
||||||
|
{% if dept_entry.form.is_local() %}
|
||||||
|
<h2>Département {{ dept_form.dept_name.data }}</h2>
|
||||||
|
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
||||||
|
<div class="sco_help">Les paramètres donnés sont spécifiques à ce département.<br />
|
||||||
|
Les logos du département se substituent aux logos de même nom définis globalement:</div>
|
||||||
|
{% else %}
|
||||||
|
<h2>Logos généraux</h2>
|
||||||
|
<h3 class="effectifs">{{ dept_form.count() }}</h3>
|
||||||
|
<div class="sco_help">Les images de cette section sont utilisé pour tous les départements,
|
||||||
|
mais peuvent être redéfinies localement au niveau de chaque département
|
||||||
|
(il suffit de définir un logo local de même nom)</div>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<div>
|
||||||
|
{{ render_logos(dept_form) }}
|
||||||
|
{{ render_add_logo(dept_form.add_logo.form) }}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.j2' %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% macro render_field(field, with_label=True) %}
|
{% macro render_field(field, with_label=True) %}
|
||||||
@ -49,7 +49,8 @@
|
|||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h2>Exports Apogée</h2>
|
<h2>Exports Apogée</h2>
|
||||||
<p><a class="stdlink" href="{{url_for('scodoc.config_codes_decisions')}}">configuration des codes de décision</a></p>
|
<p><a class="stdlink" href="{{url_for('scodoc.config_codes_decisions')}}">configuration des codes de décision</a>
|
||||||
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<h2>Utilisateurs</h2>
|
<h2>Utilisateurs</h2>
|
||||||
@ -82,8 +83,7 @@ function update_bonus_description() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function()
|
$(function () {
|
||||||
{
|
|
||||||
$("#configuration_form select").change(function () {
|
$("#configuration_form select").change(function () {
|
||||||
update_bonus_description();
|
update_bonus_description();
|
||||||
});
|
});
|
@ -1,5 +1,4 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{% extends 'base.j2' %}
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
||||||
@ -7,7 +6,7 @@
|
|||||||
<h2>{{ title }}</h2>
|
<h2>{{ title }}</h2>
|
||||||
|
|
||||||
<div style="margin-top: 16px;">
|
<div style="margin-top: 16px;">
|
||||||
{{ explanation }}
|
{{ explanation|safe }}
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 16px;">
|
<div style="margin-top: 16px;">
|
||||||
<form method="post">
|
<form method="post">
|
@ -1,5 +1,5 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
{# -*- mode: jinja-html -*- #}
|
||||||
{% extends "base.html" %}
|
{% extends "base.j2" %}
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
{% block app_content %}
|
{% block app_content %}
|
@ -1,47 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends "sco_page.html" %}
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h2>Opérations dans le département {{g.scodoc_dept}}</h2>
|
|
||||||
|
|
||||||
<table id="dept_news" class="table table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Date</th>
|
|
||||||
<th>Type</th>
|
|
||||||
<th>Auteur</th>
|
|
||||||
<th>Détail</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block scripts %}
|
|
||||||
{{super()}}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
$('#dept_news').DataTable({
|
|
||||||
ajax: '{{url_for("scolar.dept_news_json", scodoc_dept=g.scodoc_dept)}}',
|
|
||||||
serverSide: true,
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
data: {
|
|
||||||
_: "date.display",
|
|
||||||
sort: "date.timestamp"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{data: 'type', searchable: false},
|
|
||||||
{data: 'authenticated_user', orderable: false, searchable: true},
|
|
||||||
{data: 'text', orderable: false, searchable: true}
|
|
||||||
],
|
|
||||||
"order": [[ 0, "desc" ]]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
47
app/templates/dept_news.j2
Normal file
47
app/templates/dept_news.j2
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends "sco_page.j2" %}
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h2>Opérations dans le département {{g.scodoc_dept}}</h2>
|
||||||
|
|
||||||
|
<table id="dept_news" class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Auteur</th>
|
||||||
|
<th>Détail</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{{super()}}
|
||||||
|
<script>
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#dept_news').DataTable({
|
||||||
|
ajax: '{{url_for("scolar.dept_news_json", scodoc_dept=g.scodoc_dept)}}',
|
||||||
|
serverSide: true,
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
data: {
|
||||||
|
_: "date.display",
|
||||||
|
sort: "date.timestamp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ data: 'type', searchable: false },
|
||||||
|
{ data: 'authenticated_user', orderable: false, searchable: true },
|
||||||
|
{ data: 'text', orderable: false, searchable: true }
|
||||||
|
],
|
||||||
|
"order": [[0, "desc"]]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,104 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
|
||||||
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<div class="container">
|
|
||||||
<ul class="breadcrumbs">
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=entreprise.id) }}" class="breadcrumbs_link">Fiche entreprise</a>
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Contacts</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container" style="margin-bottom: 10px;">
|
|
||||||
<h1>Liste des contacts</h1>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<a class="btn btn-primary" style="margin-bottom:10px;" href="{{ url_for('entreprises.add_contact', entreprise_id=entreprise.id) }}">Ajouter contact</a>
|
|
||||||
{% endif %}
|
|
||||||
<table id="table-contacts">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td data-priority="">Date</td>
|
|
||||||
<td data-priority="">Utilisateur</td>
|
|
||||||
<td data-priority="">Notes</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td data-priority="">Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for contact in contacts %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ contact.date.strftime('%d/%m/%Y %Hh%M') }}</td>
|
|
||||||
<td>{{ contact.user|get_nomcomplet_by_id }}</td>
|
|
||||||
<td>{{ contact.notes }}</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
|
||||||
<span class="caret"></span>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu pull-left">
|
|
||||||
<li><a href="{{ url_for('entreprises.edit_contact', entreprise_id=entreprise.id, contact_id=contact.id) }}">Modifier</a></li>
|
|
||||||
<li><a href="{{ url_for('entreprises.delete_contact', entreprise_id=entreprise.id, contact_id=contact.id) }}" style="color:red">Supprimer</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>Date</td>
|
|
||||||
<td>Utilisateur</td>
|
|
||||||
<td>Notes</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
let table = new DataTable('#table-contacts',
|
|
||||||
{
|
|
||||||
"autoWidth": false,
|
|
||||||
"responsive": {
|
|
||||||
"details": true
|
|
||||||
},
|
|
||||||
"pageLength": 10,
|
|
||||||
"language": {
|
|
||||||
"emptyTable": "Aucune donnée disponible dans le tableau",
|
|
||||||
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
|
||||||
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
|
||||||
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
|
||||||
"lengthMenu": "Afficher _MENU_ entrées",
|
|
||||||
"loadingRecords": "Chargement...",
|
|
||||||
"processing": "Traitement...",
|
|
||||||
"search": "Rechercher:",
|
|
||||||
"zeroRecords": "Aucune entrée correspondante trouvée",
|
|
||||||
"paginate": {
|
|
||||||
"next": "Suivante",
|
|
||||||
"previous": "Précédente"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
109
app/templates/entreprises/contacts.j2
Normal file
109
app/templates/entreprises/contacts.j2
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
||||||
|
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="container">
|
||||||
|
<ul class="breadcrumbs">
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=entreprise.id) }}"
|
||||||
|
class="breadcrumbs_link">Fiche entreprise</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Contacts</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" style="margin-bottom: 10px;">
|
||||||
|
<h1>Liste des contacts</h1>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<a class="btn btn-primary" style="margin-bottom:10px;"
|
||||||
|
href="{{ url_for('entreprises.add_contact', entreprise_id=entreprise.id) }}">Ajouter contact</a>
|
||||||
|
{% endif %}
|
||||||
|
<table id="table-contacts">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td data-priority="">Date</td>
|
||||||
|
<td data-priority="">Utilisateur</td>
|
||||||
|
<td data-priority="">Notes</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td data-priority="">Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for contact in contacts %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ contact.date.strftime('%d/%m/%Y %Hh%M') }}</td>
|
||||||
|
<td>{{ contact.user|get_nomcomplet_by_id }}</td>
|
||||||
|
<td>{{ contact.notes }}</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu pull-left">
|
||||||
|
<li><a
|
||||||
|
href="{{ url_for('entreprises.edit_contact', entreprise_id=entreprise.id, contact_id=contact.id) }}">Modifier</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="{{ url_for('entreprises.delete_contact', entreprise_id=entreprise.id, contact_id=contact.id) }}"
|
||||||
|
style="color:red">Supprimer</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>Date</td>
|
||||||
|
<td>Utilisateur</td>
|
||||||
|
<td>Notes</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let table = new DataTable('#table-contacts',
|
||||||
|
{
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": {
|
||||||
|
"details": true
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "Aucune donnée disponible dans le tableau",
|
||||||
|
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
||||||
|
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
||||||
|
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
||||||
|
"lengthMenu": "Afficher _MENU_ entrées",
|
||||||
|
"loadingRecords": "Chargement...",
|
||||||
|
"processing": "Traitement...",
|
||||||
|
"search": "Rechercher:",
|
||||||
|
"zeroRecords": "Aucune entrée correspondante trouvée",
|
||||||
|
"paginate": {
|
||||||
|
"next": "Suivante",
|
||||||
|
"previous": "Précédente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,93 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
|
||||||
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
{% include 'entreprises/nav.html' %}
|
|
||||||
|
|
||||||
{% if logs %}
|
|
||||||
<div class="container">
|
|
||||||
<h3>Dernières opérations <a href="{{ url_for('entreprises.logs') }}">Voir tout</a></h3>
|
|
||||||
<ul>
|
|
||||||
{% for log in logs %}
|
|
||||||
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="container" style="margin-bottom: 10px;">
|
|
||||||
<h1>Liste des correspondants</h1>
|
|
||||||
<table id="table-correspondants">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td data-priority="1">Nom</td>
|
|
||||||
<td data-priority="3">Prenom</td>
|
|
||||||
<td data-priority="4">Téléphone</td>
|
|
||||||
<td data-priority="5">Mail</td>
|
|
||||||
<td data-priority="6">Poste</td>
|
|
||||||
<td data-priority="7">Service</td>
|
|
||||||
<td data-priority="2">Entreprise</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for correspondant, site in correspondants %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ correspondant.nom }}</td>
|
|
||||||
<td>{{ correspondant.prenom }}</td>
|
|
||||||
<td>{{ correspondant.telephone }}</td>
|
|
||||||
<td>{{ correspondant.mail }}</td>
|
|
||||||
<td>{{ correspondant.poste}}</td>
|
|
||||||
<td>{{ correspondant.service}}</td>
|
|
||||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=site.entreprise.id) }}">{{ site.nom }}</a></td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>Nom</td>
|
|
||||||
<td>Prenom</td>
|
|
||||||
<td>Téléphone</td>
|
|
||||||
<td>Mail</td>
|
|
||||||
<td>Poste</td>
|
|
||||||
<td>Service</td>
|
|
||||||
<td>Entreprise</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
let table = new DataTable('#table-correspondants',
|
|
||||||
{
|
|
||||||
"autoWidth": false,
|
|
||||||
"responsive": {
|
|
||||||
"details": true
|
|
||||||
},
|
|
||||||
"pageLength": 10,
|
|
||||||
"language": {
|
|
||||||
"emptyTable": "Aucune donnée disponible dans le tableau",
|
|
||||||
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
|
||||||
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
|
||||||
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
|
||||||
"lengthMenu": "Afficher _MENU_ entrées",
|
|
||||||
"loadingRecords": "Chargement...",
|
|
||||||
"processing": "Traitement...",
|
|
||||||
"search": "Rechercher:",
|
|
||||||
"zeroRecords": "Aucune entrée correspondante trouvée",
|
|
||||||
"paginate": {
|
|
||||||
"next": "Suivante",
|
|
||||||
"previous": "Précédente"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
95
app/templates/entreprises/correspondants.j2
Normal file
95
app/templates/entreprises/correspondants.j2
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
||||||
|
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
{% include 'entreprises/nav.html' %}
|
||||||
|
|
||||||
|
{% if logs %}
|
||||||
|
<div class="container">
|
||||||
|
<h3>Dernières opérations <a href="{{ url_for('entreprises.logs') }}">Voir tout</a></h3>
|
||||||
|
<ul>
|
||||||
|
{% for log in logs %}
|
||||||
|
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par
|
||||||
|
{{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="container" style="margin-bottom: 10px;">
|
||||||
|
<h1>Liste des correspondants</h1>
|
||||||
|
<table id="table-correspondants">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td data-priority="1">Nom</td>
|
||||||
|
<td data-priority="3">Prenom</td>
|
||||||
|
<td data-priority="4">Téléphone</td>
|
||||||
|
<td data-priority="5">Mail</td>
|
||||||
|
<td data-priority="6">Poste</td>
|
||||||
|
<td data-priority="7">Service</td>
|
||||||
|
<td data-priority="2">Entreprise</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for correspondant, site in correspondants %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ correspondant.nom }}</td>
|
||||||
|
<td>{{ correspondant.prenom }}</td>
|
||||||
|
<td>{{ correspondant.telephone }}</td>
|
||||||
|
<td>{{ correspondant.mail }}</td>
|
||||||
|
<td>{{ correspondant.poste}}</td>
|
||||||
|
<td>{{ correspondant.service}}</td>
|
||||||
|
<td><a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=site.entreprise.id) }}">{{
|
||||||
|
site.nom }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>Nom</td>
|
||||||
|
<td>Prenom</td>
|
||||||
|
<td>Téléphone</td>
|
||||||
|
<td>Mail</td>
|
||||||
|
<td>Poste</td>
|
||||||
|
<td>Service</td>
|
||||||
|
<td>Entreprise</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let table = new DataTable('#table-correspondants',
|
||||||
|
{
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": {
|
||||||
|
"details": true
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "Aucune donnée disponible dans le tableau",
|
||||||
|
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
||||||
|
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
||||||
|
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
||||||
|
"lengthMenu": "Afficher _MENU_ entrées",
|
||||||
|
"loadingRecords": "Chargement...",
|
||||||
|
"processing": "Traitement...",
|
||||||
|
"search": "Rechercher:",
|
||||||
|
"zeroRecords": "Aucune entrée correspondante trouvée",
|
||||||
|
"paginate": {
|
||||||
|
"next": "Suivante",
|
||||||
|
"previous": "Précédente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,133 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
|
||||||
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
{% include 'entreprises/nav.html' %}
|
|
||||||
|
|
||||||
{% if logs %}
|
|
||||||
<div class="container">
|
|
||||||
<h3>Dernières opérations <a href="{{ url_for('entreprises.logs') }}">Voir tout</a></h3>
|
|
||||||
<ul>
|
|
||||||
{% for log in logs %}
|
|
||||||
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="container boutons">
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a>
|
|
||||||
{% endif %}
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %}
|
|
||||||
<a class="btn btn-default" href="{{ url_for('entreprises.import_donnees') }}">Importer des données</a>
|
|
||||||
{% endif %}
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and entreprises %}
|
|
||||||
<a class="btn btn-default" href="{{ url_for('entreprises.export_donnees') }}">Exporter des données</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container" style="margin-bottom: 10px;">
|
|
||||||
<h1>Liste des entreprises</h1>
|
|
||||||
{% if form %}
|
|
||||||
<form id="form-entreprise-filter" method="POST" action="">
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
<div><input id="active" name="active" type="checkbox" onChange="form.submit()" {% if checked[0] %} checked {% endif %}> {{ form.active.label }}</div>
|
|
||||||
<div><input id="association" name="association" type="checkbox" onChange="form.submit()" {% if checked[1] %} checked {% endif %}> {{ form.association.label }}</div>
|
|
||||||
<div><input id="siret_provisoire" name="siret_provisoire" type="checkbox" onChange="form.submit()" {% if checked[2] %} checked {% endif %}> {{ form.siret_provisoire.label }}</div>
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
<table id="table-entreprises">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td data-priority="2">SIRET</td>
|
|
||||||
<td data-priority="1">Nom</td>
|
|
||||||
<td data-priority="4">Adresse</td>
|
|
||||||
<td data-priority="6">Code postal</td>
|
|
||||||
<td data-priority="5">Ville</td>
|
|
||||||
<td data-priority="7">Pays</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td data-priority="3">Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for entreprise in entreprises %}
|
|
||||||
<tr>
|
|
||||||
<td><a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=entreprise.id) }}" style="{% if not entreprise.active %}color:red;{% endif %}{% if entreprise.siret_provisoire %}font-weight:bold;{% endif %}" >{{ entreprise.siret }}</a></td>
|
|
||||||
<td>{{ entreprise.nom }}</td>
|
|
||||||
<td>{{ entreprise.adresse }}</td>
|
|
||||||
<td>{{ entreprise.codepostal }}</td>
|
|
||||||
<td>{{ entreprise.ville }}</td>
|
|
||||||
<td>{{ entreprise.pays }}</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
|
||||||
<span class="caret"></span>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu pull-left">
|
|
||||||
<li><a href="{{ url_for('entreprises.edit_entreprise', entreprise_id=entreprise.id) }}">Modifier</a></li>
|
|
||||||
{% if entreprise.active %}
|
|
||||||
<li><a href="{{ url_for('entreprises.fiche_entreprise_desactiver', entreprise_id=entreprise.id)}}" style="color:red">Désactiver</a></li>
|
|
||||||
{% else %}
|
|
||||||
<li><a href="{{ url_for('entreprises.fiche_entreprise_activer', entreprise_id=entreprise.id)}}" style="color:lightgreen">Activer</a></li>
|
|
||||||
{% endif %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>SIRET</td>
|
|
||||||
<td>Nom</td>
|
|
||||||
<td>Adresse</td>
|
|
||||||
<td>Code postal</td>
|
|
||||||
<td>Ville</td>
|
|
||||||
<td>Pays</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
let table = new DataTable('#table-entreprises',
|
|
||||||
{
|
|
||||||
"autoWidth": false,
|
|
||||||
"responsive": {
|
|
||||||
"details": true
|
|
||||||
},
|
|
||||||
"pageLength": 10,
|
|
||||||
"language": {
|
|
||||||
"emptyTable": "Aucune donnée disponible dans le tableau",
|
|
||||||
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
|
||||||
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
|
||||||
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
|
||||||
"lengthMenu": "Afficher _MENU_ entrées",
|
|
||||||
"loadingRecords": "Chargement...",
|
|
||||||
"processing": "Traitement...",
|
|
||||||
"search": "Rechercher:",
|
|
||||||
"zeroRecords": "Aucune entrée correspondante trouvée",
|
|
||||||
"paginate": {
|
|
||||||
"next": "Suivante",
|
|
||||||
"previous": "Précédente"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
143
app/templates/entreprises/entreprises.j2
Normal file
143
app/templates/entreprises/entreprises.j2
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
||||||
|
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
{% include 'entreprises/nav.html' %}
|
||||||
|
|
||||||
|
{% if logs %}
|
||||||
|
<div class="container">
|
||||||
|
<h3>Dernières opérations <a href="{{ url_for('entreprises.logs') }}">Voir tout</a></h3>
|
||||||
|
<ul>
|
||||||
|
{% for log in logs %}
|
||||||
|
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par
|
||||||
|
{{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="container boutons">
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<a class="btn btn-default" href="{{ url_for('entreprises.add_entreprise') }}">Ajouter une entreprise</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) %}
|
||||||
|
<a class="btn btn-default" href="{{ url_for('entreprises.import_donnees') }}">Importer des données</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesExport, None) and entreprises %}
|
||||||
|
<a class="btn btn-default" href="{{ url_for('entreprises.export_donnees') }}">Exporter des données</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container" style="margin-bottom: 10px;">
|
||||||
|
<h1>Liste des entreprises</h1>
|
||||||
|
{% if form %}
|
||||||
|
<form id="form-entreprise-filter" method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<div><input id="active" name="active" type="checkbox" onChange="form.submit()" {% if checked[0] %} checked {%
|
||||||
|
endif %}> {{ form.active.label }}</div>
|
||||||
|
<div><input id="association" name="association" type="checkbox" onChange="form.submit()" {% if checked[1] %}
|
||||||
|
checked {% endif %}> {{ form.association.label }}</div>
|
||||||
|
<div><input id="siret_provisoire" name="siret_provisoire" type="checkbox" onChange="form.submit()" {% if
|
||||||
|
checked[2] %} checked {% endif %}> {{ form.siret_provisoire.label }}</div>
|
||||||
|
</form>
|
||||||
|
{% endif %}
|
||||||
|
<table id="table-entreprises">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td data-priority="2">SIRET</td>
|
||||||
|
<td data-priority="1">Nom</td>
|
||||||
|
<td data-priority="4">Adresse</td>
|
||||||
|
<td data-priority="6">Code postal</td>
|
||||||
|
<td data-priority="5">Ville</td>
|
||||||
|
<td data-priority="7">Pays</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td data-priority="3">Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for entreprise in entreprises %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{ url_for('entreprises.fiche_entreprise', entreprise_id=entreprise.id) }}"
|
||||||
|
style="{% if not entreprise.active %}color:red;{% endif %}{% if entreprise.siret_provisoire %}font-weight:bold;{% endif %}">{{
|
||||||
|
entreprise.siret }}</a></td>
|
||||||
|
<td>{{ entreprise.nom }}</td>
|
||||||
|
<td>{{ entreprise.adresse }}</td>
|
||||||
|
<td>{{ entreprise.codepostal }}</td>
|
||||||
|
<td>{{ entreprise.ville }}</td>
|
||||||
|
<td>{{ entreprise.pays }}</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu pull-left">
|
||||||
|
<li><a
|
||||||
|
href="{{ url_for('entreprises.edit_entreprise', entreprise_id=entreprise.id) }}">Modifier</a>
|
||||||
|
</li>
|
||||||
|
{% if entreprise.active %}
|
||||||
|
<li><a href="{{ url_for('entreprises.fiche_entreprise_desactiver', entreprise_id=entreprise.id)}}"
|
||||||
|
style="color:red">Désactiver</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li><a href="{{ url_for('entreprises.fiche_entreprise_activer', entreprise_id=entreprise.id)}}"
|
||||||
|
style="color:lightgreen">Activer</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>SIRET</td>
|
||||||
|
<td>Nom</td>
|
||||||
|
<td>Adresse</td>
|
||||||
|
<td>Code postal</td>
|
||||||
|
<td>Ville</td>
|
||||||
|
<td>Pays</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let table = new DataTable('#table-entreprises',
|
||||||
|
{
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": {
|
||||||
|
"details": true
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "Aucune donnée disponible dans le tableau",
|
||||||
|
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
||||||
|
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
||||||
|
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
||||||
|
"lengthMenu": "Afficher _MENU_ entrées",
|
||||||
|
"loadingRecords": "Chargement...",
|
||||||
|
"processing": "Traitement...",
|
||||||
|
"search": "Rechercher:",
|
||||||
|
"zeroRecords": "Aucune entrée correspondante trouvée",
|
||||||
|
"paginate": {
|
||||||
|
"next": "Suivante",
|
||||||
|
"previous": "Précédente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,95 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
|
||||||
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
{% include 'entreprises/nav.html' %}
|
|
||||||
|
|
||||||
{% if logs %}
|
|
||||||
<div class="container">
|
|
||||||
<h3>Dernières opérations</h3>
|
|
||||||
<ul>
|
|
||||||
{% for log in logs %}
|
|
||||||
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="container" style="margin-bottom: 10px;">
|
|
||||||
<h1>Liste des entreprises à valider</h1>
|
|
||||||
<table id="table-entreprises-validation">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td data-priority="3">SIRET</td>
|
|
||||||
<td data-priority="1">Nom</td>
|
|
||||||
<td data-priority="4">Adresse</td>
|
|
||||||
<td data-priority="5">Code postal</td>
|
|
||||||
<td data-priority="6">Ville</td>
|
|
||||||
<td data-priority="7">Pays</td>
|
|
||||||
<td data-priority="2">Action</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for entreprise in entreprises %}
|
|
||||||
<tr class="table-row active">
|
|
||||||
<th><a href="{{ url_for('entreprises.fiche_entreprise_validation', entreprise_id=entreprise.id) }}">{{ entreprise.siret }}</a></th>
|
|
||||||
<th>{{ entreprise.nom }}</th>
|
|
||||||
<th>{{ entreprise.adresse }}</th>
|
|
||||||
<th>{{ entreprise.codepostal }}</th>
|
|
||||||
<th>{{ entreprise.ville }}</th>
|
|
||||||
<th>{{ entreprise.pays }}</th>
|
|
||||||
<th>
|
|
||||||
<a class="btn btn-default" href="{{ url_for('entreprises.fiche_entreprise_validation', entreprise_id=entreprise.id) }}">Voir</a>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>SIRET</td>
|
|
||||||
<td>Nom</td>
|
|
||||||
<td>Adresse</td>
|
|
||||||
<td>Code postal</td>
|
|
||||||
<td>Ville</td>
|
|
||||||
<td>Pays</td>
|
|
||||||
<td>Action</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
let table = new DataTable('#table-entreprises-validation',
|
|
||||||
{
|
|
||||||
"autoWidth": false,
|
|
||||||
"responsive": {
|
|
||||||
"details": true
|
|
||||||
},
|
|
||||||
"pageLength": 10,
|
|
||||||
"language": {
|
|
||||||
"emptyTable": "Aucune donnée disponible dans le tableau",
|
|
||||||
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
|
||||||
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
|
||||||
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
|
||||||
"lengthMenu": "Afficher _MENU_ entrées",
|
|
||||||
"loadingRecords": "Chargement...",
|
|
||||||
"processing": "Traitement...",
|
|
||||||
"search": "Rechercher:",
|
|
||||||
"zeroRecords": "Aucune entrée correspondante trouvée",
|
|
||||||
"paginate": {
|
|
||||||
"next": "Suivante",
|
|
||||||
"previous": "Précédente"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
98
app/templates/entreprises/entreprises_validation.j2
Normal file
98
app/templates/entreprises/entreprises_validation.j2
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
||||||
|
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
{% include 'entreprises/nav.html' %}
|
||||||
|
|
||||||
|
{% if logs %}
|
||||||
|
<div class="container">
|
||||||
|
<h3>Dernières opérations</h3>
|
||||||
|
<ul>
|
||||||
|
{% for log in logs %}
|
||||||
|
<li><span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span><span>{{ log.text|safe }} par
|
||||||
|
{{ log.authenticated_user|get_nomcomplet_by_username }}</span></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="container" style="margin-bottom: 10px;">
|
||||||
|
<h1>Liste des entreprises à valider</h1>
|
||||||
|
<table id="table-entreprises-validation">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td data-priority="3">SIRET</td>
|
||||||
|
<td data-priority="1">Nom</td>
|
||||||
|
<td data-priority="4">Adresse</td>
|
||||||
|
<td data-priority="5">Code postal</td>
|
||||||
|
<td data-priority="6">Ville</td>
|
||||||
|
<td data-priority="7">Pays</td>
|
||||||
|
<td data-priority="2">Action</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for entreprise in entreprises %}
|
||||||
|
<tr class="table-row active">
|
||||||
|
<th><a href="{{ url_for('entreprises.fiche_entreprise_validation', entreprise_id=entreprise.id) }}">{{
|
||||||
|
entreprise.siret }}</a></th>
|
||||||
|
<th>{{ entreprise.nom }}</th>
|
||||||
|
<th>{{ entreprise.adresse }}</th>
|
||||||
|
<th>{{ entreprise.codepostal }}</th>
|
||||||
|
<th>{{ entreprise.ville }}</th>
|
||||||
|
<th>{{ entreprise.pays }}</th>
|
||||||
|
<th>
|
||||||
|
<a class="btn btn-default"
|
||||||
|
href="{{ url_for('entreprises.fiche_entreprise_validation', entreprise_id=entreprise.id) }}">Voir</a>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>SIRET</td>
|
||||||
|
<td>Nom</td>
|
||||||
|
<td>Adresse</td>
|
||||||
|
<td>Code postal</td>
|
||||||
|
<td>Ville</td>
|
||||||
|
<td>Pays</td>
|
||||||
|
<td>Action</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let table = new DataTable('#table-entreprises-validation',
|
||||||
|
{
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": {
|
||||||
|
"details": true
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "Aucune donnée disponible dans le tableau",
|
||||||
|
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
||||||
|
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
||||||
|
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
||||||
|
"lengthMenu": "Afficher _MENU_ entrées",
|
||||||
|
"loadingRecords": "Chargement...",
|
||||||
|
"processing": "Traitement...",
|
||||||
|
"search": "Rechercher:",
|
||||||
|
"zeroRecords": "Aucune entrée correspondante trouvée",
|
||||||
|
"paginate": {
|
||||||
|
"next": "Suivante",
|
||||||
|
"previous": "Précédente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,14 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
|
|
||||||
<h2>Erreur !</h2>
|
|
||||||
|
|
||||||
{{ e }}
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<a href="{{ url_for('entreprises.index') }}">Retour</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
14
app/templates/entreprises/error.j2
Normal file
14
app/templates/entreprises/error.j2
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
|
||||||
|
<h2>Erreur !</h2>
|
||||||
|
|
||||||
|
{{ e }}
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="{{ url_for('entreprises.index') }}">Retour</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -1,227 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
|
||||||
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<div class="container">
|
|
||||||
<ul class="breadcrumbs">
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Fiche entreprise</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if logs %}
|
|
||||||
<div class="container">
|
|
||||||
<h3>Dernières opérations sur cette fiche <a href="{{ url_for('entreprises.logs_entreprise', entreprise_id=entreprise.id) }}">Voir tout</a></h3>
|
|
||||||
<ul>
|
|
||||||
{% for log in logs %}
|
|
||||||
<li>
|
|
||||||
<span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span>
|
|
||||||
<span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet_by_username }}</span>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="container fiche-entreprise">
|
|
||||||
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
|
|
||||||
|
|
||||||
{% if not entreprise.active %}
|
|
||||||
<div class="info-active">
|
|
||||||
La fiche entreprise est désactivée<br>
|
|
||||||
{% if entreprise.notes_active != "" %}
|
|
||||||
Notes : {{ entreprise.notes_active }}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<div class="entreprise">
|
|
||||||
<div>
|
|
||||||
SIRET {% if entreprise.siret_provisoire %}provisoire{% endif %} : {{ entreprise.siret }}<br>
|
|
||||||
Nom : {{ entreprise.nom }}<br>
|
|
||||||
Adresse : {{ entreprise.adresse }}<br>
|
|
||||||
Code postal : {{ entreprise.codepostal }}<br>
|
|
||||||
Ville : {{ entreprise.ville }}<br>
|
|
||||||
Pays : {{ entreprise.pays }}<br>
|
|
||||||
{% if entreprise.association %}
|
|
||||||
Association
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<div>
|
|
||||||
Taxe d'apprentissage<br>
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.add_taxe_apprentissage', entreprise_id=entreprise.id) }}">Ajouter taxe apprentissage</a>
|
|
||||||
<div class="taxe-apprentissage">
|
|
||||||
<ul id="liste-taxes-apprentissages">
|
|
||||||
{% if not taxes|check_taxe_now %}
|
|
||||||
<li>année actuelle : non versée</li>
|
|
||||||
{% endif %}
|
|
||||||
{% for taxe in taxes %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ url_for('entreprises.delete_taxe_apprentissage', entreprise_id=entreprise.id, taxe_id=taxe.id) }}"><img title="Supprimer taxe d'apprentissage" alt="supprimer" width="10" height="9" border="0" src="/ScoDoc/static/icons/delete_small_img.png" /></a>
|
|
||||||
<a href="{{ url_for('entreprises.edit_taxe_apprentissage', entreprise_id=entreprise.id, taxe_id=taxe.id) }}">{{ taxe.annee }}</a> : {{ taxe.montant }} euros {% if taxe.notes %}- {{ taxe.notes}} {% endif %}
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_entreprise', entreprise_id=entreprise.id) }}">Modifier</a>
|
|
||||||
{% if entreprise.active %}
|
|
||||||
<a class="btn btn-danger" href="{{ url_for('entreprises.fiche_entreprise_desactiver', entreprise_id=entreprise.id) }}">Désactiver</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="btn btn-success" href="{{ url_for('entreprises.fiche_entreprise_activer', entreprise_id=entreprise.id) }}">Activer</a>
|
|
||||||
{% endif %}
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.add_site', entreprise_id=entreprise.id) }}">Ajouter site</a>
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.add_offre', entreprise_id=entreprise.id) }}">Ajouter offre</a>
|
|
||||||
{% endif %}
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.contacts', entreprise_id=entreprise.id) }}">Liste contacts</a>
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.offres_expirees', entreprise_id=entreprise.id) }}">Voir les offres expirées</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="sites-et-offres">
|
|
||||||
{% if entreprise.sites %}
|
|
||||||
<div>
|
|
||||||
<h3>Sites</h3>
|
|
||||||
{% for site in entreprise.sites %}
|
|
||||||
<div class="site">
|
|
||||||
Nom : {{ site.nom }}<br>
|
|
||||||
Adresse : {{ site.adresse }}<br>
|
|
||||||
Code postal : {{ site.codepostal }}<br>
|
|
||||||
Ville : {{ site.ville }}<br>
|
|
||||||
Pays : {{ site.pays }}
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<div>
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.edit_site', entreprise_id=entreprise.id, site_id=site.id) }}">Modifier</a>
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.add_correspondant', entreprise_id=entreprise.id, site_id=site.id) }}">Ajouter correspondant</a>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
|
||||||
{% for correspondant in site.correspondants %}
|
|
||||||
{% include 'entreprises/_correspondant.html' %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% if offres %}
|
|
||||||
<div>
|
|
||||||
<h3>Offres - <a href="{{ url_for('entreprises.offres_expirees', entreprise_id=entreprise.id) }}">Voir les offres expirées</a></h3>
|
|
||||||
{% for offre, files, offre_depts, correspondant in offres %}
|
|
||||||
{% include 'entreprises/_offre.html' %}
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="margin-bottom: 10px;">
|
|
||||||
<h3>Liste des stages et apprentissages réalisés au sein de l'entreprise</h3>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<a class="btn btn-primary" href="{{ url_for('entreprises.add_stage_apprentissage', entreprise_id=entreprise.id) }}" style="margin-bottom:10px;">Ajouter stage ou apprentissage</a>
|
|
||||||
{% endif %}
|
|
||||||
<table id="table-stages-apprentissages">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td data-priority="3">Date début</td>
|
|
||||||
<td data-priority="4">Date fin</td>
|
|
||||||
<td data-priority="5">Durée</td>
|
|
||||||
<td data-priority="2">Type</td>
|
|
||||||
<td data-priority="1">Étudiant</td>
|
|
||||||
<td data-priority="6">Formation</td>
|
|
||||||
<td data-priority="7">Notes</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td data-priority="3">Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for stage_apprentissage, etudiant in stages_apprentissages %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ stage_apprentissage.date_debut.strftime('%d/%m/%Y') }}</td>
|
|
||||||
<td>{{ stage_apprentissage.date_fin.strftime('%d/%m/%Y') }}</td>
|
|
||||||
<td>{{ (stage_apprentissage.date_fin-stage_apprentissage.date_debut).days//7 }} semaines</td>
|
|
||||||
<td>{{ stage_apprentissage.type_offre }}</td>
|
|
||||||
<td><a href="{{ url_for('scolar.ficheEtud', scodoc_dept=etudiant.dept_id|get_dept_acronym, etudid=stage_apprentissage.etudid) }}">{{ etudiant.nom|format_nom }} {{ etudiant.prenom|format_prenom }}</a></td>
|
|
||||||
<td>{% if stage_apprentissage.formation_text %}{{ stage_apprentissage.formation_text }}{% endif %}</td>
|
|
||||||
<td>{{ stage_apprentissage.notes }}</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>
|
|
||||||
<div class="btn-group">
|
|
||||||
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
|
||||||
<span class="caret"></span>
|
|
||||||
</a>
|
|
||||||
<ul class="dropdown-menu pull-left">
|
|
||||||
<li><a href="{{ url_for('entreprises.edit_stage_apprentissage', entreprise_id=entreprise.id, stage_apprentissage_id=stage_apprentissage.id) }}">Modifier</a></li>
|
|
||||||
<li><a href="{{ url_for('entreprises.delete_stage_apprentissage', entreprise_id=entreprise.id, stage_apprentissage_id=stage_apprentissage.id) }}" style="color:red">Supprimer</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>Date début</td>
|
|
||||||
<td>Date fin</td>
|
|
||||||
<td>Durée</td>
|
|
||||||
<td>Type</td>
|
|
||||||
<td>Étudiant</td>
|
|
||||||
<td>Formation</td>
|
|
||||||
<td>Notes</td>
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
|
||||||
<td>Action</td>
|
|
||||||
{% endif %}
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
|
||||||
let table = new DataTable('#table-stages-apprentissages',
|
|
||||||
{
|
|
||||||
"autoWidth": false,
|
|
||||||
"responsive": {
|
|
||||||
"details": true
|
|
||||||
},
|
|
||||||
"pageLength": 10,
|
|
||||||
"language": {
|
|
||||||
"emptyTable": "Aucune donnée disponible dans le tableau",
|
|
||||||
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
|
||||||
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
|
||||||
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
|
||||||
"lengthMenu": "Afficher _MENU_ entrées",
|
|
||||||
"loadingRecords": "Chargement...",
|
|
||||||
"processing": "Traitement...",
|
|
||||||
"search": "Rechercher:",
|
|
||||||
"zeroRecords": "Aucune entrée correspondante trouvée",
|
|
||||||
"paginate": {
|
|
||||||
"next": "Suivante",
|
|
||||||
"previous": "Précédente"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
253
app/templates/entreprises/fiche_entreprise.j2
Normal file
253
app/templates/entreprises/fiche_entreprise.j2
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<script src="/ScoDoc/static/jQuery/jquery-1.12.4.min.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/ScoDoc/static/DataTables/datatables.min.css">
|
||||||
|
<script type="text/javascript" charset="utf8" src="/ScoDoc/static/DataTables/datatables.min.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="container">
|
||||||
|
<ul class="breadcrumbs">
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="{{ url_for('entreprises.index') }}" class="breadcrumbs_link">Entreprises</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Fiche entreprise</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if logs %}
|
||||||
|
<div class="container">
|
||||||
|
<h3>Dernières opérations sur cette fiche <a
|
||||||
|
href="{{ url_for('entreprises.logs_entreprise', entreprise_id=entreprise.id) }}">Voir tout</a></h3>
|
||||||
|
<ul>
|
||||||
|
{% for log in logs %}
|
||||||
|
<li>
|
||||||
|
<span style="margin-right: 10px;">{{ log.date.strftime('%d %b %Hh%M') }}</span>
|
||||||
|
<span>{{ log.text|safe }} par {{ log.authenticated_user|get_nomcomplet_by_username }}</span>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="container fiche-entreprise">
|
||||||
|
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
|
||||||
|
|
||||||
|
{% if not entreprise.active %}
|
||||||
|
<div class="info-active">
|
||||||
|
La fiche entreprise est désactivée<br>
|
||||||
|
{% if entreprise.notes_active != "" %}
|
||||||
|
Notes : {{ entreprise.notes_active }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="entreprise">
|
||||||
|
<div>
|
||||||
|
SIRET {% if entreprise.siret_provisoire %}provisoire{% endif %} : {{ entreprise.siret }}<br>
|
||||||
|
Nom : {{ entreprise.nom }}<br>
|
||||||
|
Adresse : {{ entreprise.adresse }}<br>
|
||||||
|
Code postal : {{ entreprise.codepostal }}<br>
|
||||||
|
Ville : {{ entreprise.ville }}<br>
|
||||||
|
Pays : {{ entreprise.pays }}<br>
|
||||||
|
{% if entreprise.association %}
|
||||||
|
Association
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<div>
|
||||||
|
Taxe d'apprentissage<br>
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('entreprises.add_taxe_apprentissage', entreprise_id=entreprise.id) }}">Ajouter taxe
|
||||||
|
apprentissage</a>
|
||||||
|
<div class="taxe-apprentissage">
|
||||||
|
<ul id="liste-taxes-apprentissages">
|
||||||
|
{% if not taxes|check_taxe_now %}
|
||||||
|
<li>année actuelle : non versée</li>
|
||||||
|
{% endif %}
|
||||||
|
{% for taxe in taxes %}
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="{{ url_for('entreprises.delete_taxe_apprentissage', entreprise_id=entreprise.id, taxe_id=taxe.id) }}"><img
|
||||||
|
title="Supprimer taxe d'apprentissage" alt="supprimer" width="10" height="9" border="0"
|
||||||
|
src="/ScoDoc/static/icons/delete_small_img.png" /></a>
|
||||||
|
<a
|
||||||
|
href="{{ url_for('entreprises.edit_taxe_apprentissage', entreprise_id=entreprise.id, taxe_id=taxe.id) }}">{{
|
||||||
|
taxe.annee }}</a> : {{ taxe.montant }} euros {% if taxe.notes %}- {{ taxe.notes}} {% endif
|
||||||
|
%}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('entreprises.edit_entreprise', entreprise_id=entreprise.id) }}">Modifier</a>
|
||||||
|
{% if entreprise.active %}
|
||||||
|
<a class="btn btn-danger"
|
||||||
|
href="{{ url_for('entreprises.fiche_entreprise_desactiver', entreprise_id=entreprise.id) }}">Désactiver</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="btn btn-success"
|
||||||
|
href="{{ url_for('entreprises.fiche_entreprise_activer', entreprise_id=entreprise.id) }}">Activer</a>
|
||||||
|
{% endif %}
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('entreprises.add_site', entreprise_id=entreprise.id) }}">Ajouter
|
||||||
|
site</a>
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('entreprises.add_offre', entreprise_id=entreprise.id) }}">Ajouter
|
||||||
|
offre</a>
|
||||||
|
{% endif %}
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('entreprises.contacts', entreprise_id=entreprise.id) }}">Liste
|
||||||
|
contacts</a>
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('entreprises.offres_expirees', entreprise_id=entreprise.id) }}">Voir
|
||||||
|
les offres expirées</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="sites-et-offres">
|
||||||
|
{% if entreprise.sites %}
|
||||||
|
<div>
|
||||||
|
<h3>Sites</h3>
|
||||||
|
{% for site in entreprise.sites %}
|
||||||
|
<div class="site">
|
||||||
|
Nom : {{ site.nom }}<br>
|
||||||
|
Adresse : {{ site.adresse }}<br>
|
||||||
|
Code postal : {{ site.codepostal }}<br>
|
||||||
|
Ville : {{ site.ville }}<br>
|
||||||
|
Pays : {{ site.pays }}
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('entreprises.edit_site', entreprise_id=entreprise.id, site_id=site.id) }}">Modifier</a>
|
||||||
|
<a class="btn btn-primary"
|
||||||
|
href="{{ url_for('entreprises.add_correspondant', entreprise_id=entreprise.id, site_id=site.id) }}">Ajouter
|
||||||
|
correspondant</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
||||||
|
{% for correspondant in site.correspondants %}
|
||||||
|
{% include 'entreprises/_correspondant.html' %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if offres %}
|
||||||
|
<div>
|
||||||
|
<h3>Offres - <a href="{{ url_for('entreprises.offres_expirees', entreprise_id=entreprise.id) }}">Voir les
|
||||||
|
offres expirées</a></h3>
|
||||||
|
{% for offre, files, offre_depts, correspondant in offres %}
|
||||||
|
{% include 'entreprises/_offre.html' %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<h3>Liste des stages et apprentissages réalisés au sein de l'entreprise</h3>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<a class="btn btn-primary" href="{{ url_for('entreprises.add_stage_apprentissage', entreprise_id=entreprise.id) }}"
|
||||||
|
style="margin-bottom:10px;">Ajouter stage ou apprentissage</a>
|
||||||
|
{% endif %}
|
||||||
|
<table id="table-stages-apprentissages">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td data-priority="3">Date début</td>
|
||||||
|
<td data-priority="4">Date fin</td>
|
||||||
|
<td data-priority="5">Durée</td>
|
||||||
|
<td data-priority="2">Type</td>
|
||||||
|
<td data-priority="1">Étudiant</td>
|
||||||
|
<td data-priority="6">Formation</td>
|
||||||
|
<td data-priority="7">Notes</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td data-priority="3">Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for stage_apprentissage, etudiant in stages_apprentissages %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ stage_apprentissage.date_debut.strftime('%d/%m/%Y') }}</td>
|
||||||
|
<td>{{ stage_apprentissage.date_fin.strftime('%d/%m/%Y') }}</td>
|
||||||
|
<td>{{ (stage_apprentissage.date_fin-stage_apprentissage.date_debut).days//7 }} semaines</td>
|
||||||
|
<td>{{ stage_apprentissage.type_offre }}</td>
|
||||||
|
<td><a
|
||||||
|
href="{{ url_for('scolar.ficheEtud', scodoc_dept=etudiant.dept_id|get_dept_acronym, etudid=stage_apprentissage.etudid) }}">{{
|
||||||
|
etudiant.nom|format_nom }} {{ etudiant.prenom|format_prenom }}</a></td>
|
||||||
|
<td>{% if stage_apprentissage.formation_text %}{{ stage_apprentissage.formation_text }}{% endif %}</td>
|
||||||
|
<td>{{ stage_apprentissage.notes }}</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-default dropdown-toggle" data-toggle="dropdown" href="#">Action
|
||||||
|
<span class="caret"></span>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu pull-left">
|
||||||
|
<li><a
|
||||||
|
href="{{ url_for('entreprises.edit_stage_apprentissage', entreprise_id=entreprise.id, stage_apprentissage_id=stage_apprentissage.id) }}">Modifier</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="{{ url_for('entreprises.delete_stage_apprentissage', entreprise_id=entreprise.id, stage_apprentissage_id=stage_apprentissage.id) }}"
|
||||||
|
style="color:red">Supprimer</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td>Date début</td>
|
||||||
|
<td>Date fin</td>
|
||||||
|
<td>Durée</td>
|
||||||
|
<td>Type</td>
|
||||||
|
<td>Étudiant</td>
|
||||||
|
<td>Formation</td>
|
||||||
|
<td>Notes</td>
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesChange, None) %}
|
||||||
|
<td>Action</td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
let table = new DataTable('#table-stages-apprentissages',
|
||||||
|
{
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": {
|
||||||
|
"details": true
|
||||||
|
},
|
||||||
|
"pageLength": 10,
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "Aucune donnée disponible dans le tableau",
|
||||||
|
"info": "Affichage de _START_ à _END_ sur _TOTAL_ entrées",
|
||||||
|
"infoEmpty": "Affichage de 0 à 0 sur 0 entrées",
|
||||||
|
"infoFiltered": "(filtrées depuis un total de _MAX_ entrées)",
|
||||||
|
"lengthMenu": "Afficher _MENU_ entrées",
|
||||||
|
"loadingRecords": "Chargement...",
|
||||||
|
"processing": "Traitement...",
|
||||||
|
"search": "Rechercher:",
|
||||||
|
"zeroRecords": "Aucune entrée correspondante trouvée",
|
||||||
|
"paginate": {
|
||||||
|
"next": "Suivante",
|
||||||
|
"previous": "Précédente"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,84 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<div class="container">
|
|
||||||
<ul class="breadcrumbs">
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="{{ url_for('entreprises.validation') }}" class="breadcrumbs_link">Entreprises</a>
|
|
||||||
</li>
|
|
||||||
<li class="breadcrumbs_item">
|
|
||||||
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Fiche entreprise</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
|
|
||||||
|
|
||||||
<div class="entreprise">
|
|
||||||
<div>
|
|
||||||
SIRET {% if entreprise.siret_provisoire %}provisoire{% endif %} : {{ entreprise.siret }}<br>
|
|
||||||
Nom : {{ entreprise.nom }}<br>
|
|
||||||
Adresse : {{ entreprise.adresse }}<br>
|
|
||||||
Code postal : {{ entreprise.codepostal }}<br>
|
|
||||||
Ville : {{ entreprise.ville }}<br>
|
|
||||||
Pays : {{ entreprise.pays }}<br>
|
|
||||||
{% if entreprise.association %}
|
|
||||||
Association
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sites-et-offres">
|
|
||||||
{% if entreprise.sites %}
|
|
||||||
<div>
|
|
||||||
<h3>Sites</h3>
|
|
||||||
{% for site in entreprise.sites %}
|
|
||||||
<div class="site">
|
|
||||||
Nom : {{ site.nom }}<br>
|
|
||||||
Adresse : {{ site.adresse }}<br>
|
|
||||||
Code postal : {{ site.codepostal }}<br>
|
|
||||||
Ville : {{ site.ville }}<br>
|
|
||||||
Pays : {{ site.pays }}
|
|
||||||
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
|
||||||
{% for correspondant in site.correspondants %}
|
|
||||||
<div class="correspondant">
|
|
||||||
<div>
|
|
||||||
Civilité : {{ correspondant.civilite|get_civilité }}<br>
|
|
||||||
Nom : {{ correspondant.nom }}<br>
|
|
||||||
Prénom : {{ correspondant.prenom }}<br>
|
|
||||||
{% if correspondant.telephone %}
|
|
||||||
Téléphone : {{ correspondant.telephone }}<br>
|
|
||||||
{% endif %}
|
|
||||||
{% if correspondant.mail %}
|
|
||||||
Mail : {{ correspondant.mail }}<br>
|
|
||||||
{% endif %}
|
|
||||||
{% if correspondant.poste %}
|
|
||||||
Poste : {{ correspondant.poste }}<br>
|
|
||||||
{% endif %}
|
|
||||||
{% if correspondant.service %}
|
|
||||||
Service : {{ correspondant.service }}<br>
|
|
||||||
{% endif %}
|
|
||||||
{% if correspondant.origine %}
|
|
||||||
Origine : {{ correspondant.origine }}<br>
|
|
||||||
{% endif %}
|
|
||||||
{% if correspondant.notes %}
|
|
||||||
Notes : {{ correspondant.notes }}<br>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<a class="btn btn-success" href="{{ url_for('entreprises.validate_entreprise', entreprise_id=entreprise.id) }}">Valider</a>
|
|
||||||
<a class="btn btn-danger" href="{{ url_for('entreprises.delete_validation_entreprise', entreprise_id=entreprise.id) }}">Supprimer</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
86
app/templates/entreprises/fiche_entreprise_validation.j2
Normal file
86
app/templates/entreprises/fiche_entreprise_validation.j2
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="container">
|
||||||
|
<ul class="breadcrumbs">
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="{{ url_for('entreprises.validation') }}" class="breadcrumbs_link">Entreprises</a>
|
||||||
|
</li>
|
||||||
|
<li class="breadcrumbs_item">
|
||||||
|
<a href="" class="breadcrumbs_link breadcrumbs_link-active">Fiche entreprise</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h2>Fiche entreprise - {{ entreprise.nom }} ({{ entreprise.siret }})</h2>
|
||||||
|
|
||||||
|
<div class="entreprise">
|
||||||
|
<div>
|
||||||
|
SIRET {% if entreprise.siret_provisoire %}provisoire{% endif %} : {{ entreprise.siret }}<br>
|
||||||
|
Nom : {{ entreprise.nom }}<br>
|
||||||
|
Adresse : {{ entreprise.adresse }}<br>
|
||||||
|
Code postal : {{ entreprise.codepostal }}<br>
|
||||||
|
Ville : {{ entreprise.ville }}<br>
|
||||||
|
Pays : {{ entreprise.pays }}<br>
|
||||||
|
{% if entreprise.association %}
|
||||||
|
Association
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sites-et-offres">
|
||||||
|
{% if entreprise.sites %}
|
||||||
|
<div>
|
||||||
|
<h3>Sites</h3>
|
||||||
|
{% for site in entreprise.sites %}
|
||||||
|
<div class="site">
|
||||||
|
Nom : {{ site.nom }}<br>
|
||||||
|
Adresse : {{ site.adresse }}<br>
|
||||||
|
Code postal : {{ site.codepostal }}<br>
|
||||||
|
Ville : {{ site.ville }}<br>
|
||||||
|
Pays : {{ site.pays }}
|
||||||
|
{% if current_user.has_permission(current_user.Permission.RelationsEntreprisesCorrespondants, None) %}
|
||||||
|
{% for correspondant in site.correspondants %}
|
||||||
|
<div class="correspondant">
|
||||||
|
<div>
|
||||||
|
Civilité : {{ correspondant.civilite|get_civilité }}<br>
|
||||||
|
Nom : {{ correspondant.nom }}<br>
|
||||||
|
Prénom : {{ correspondant.prenom }}<br>
|
||||||
|
{% if correspondant.telephone %}
|
||||||
|
Téléphone : {{ correspondant.telephone }}<br>
|
||||||
|
{% endif %}
|
||||||
|
{% if correspondant.mail %}
|
||||||
|
Mail : {{ correspondant.mail }}<br>
|
||||||
|
{% endif %}
|
||||||
|
{% if correspondant.poste %}
|
||||||
|
Poste : {{ correspondant.poste }}<br>
|
||||||
|
{% endif %}
|
||||||
|
{% if correspondant.service %}
|
||||||
|
Service : {{ correspondant.service }}<br>
|
||||||
|
{% endif %}
|
||||||
|
{% if correspondant.origine %}
|
||||||
|
Origine : {{ correspondant.origine }}<br>
|
||||||
|
{% endif %}
|
||||||
|
{% if correspondant.notes %}
|
||||||
|
Notes : {{ correspondant.notes }}<br>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-success"
|
||||||
|
href="{{ url_for('entreprises.validate_entreprise', entreprise_id=entreprise.id) }}">Valider</a>
|
||||||
|
<a class="btn btn-danger"
|
||||||
|
href="{{ url_for('entreprises.delete_validation_entreprise', entreprise_id=entreprise.id) }}">Supprimer</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -1,62 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
|
||||||
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
{{ wtf.quick_form(form, novalidate=True) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
{# pour les formulaires offre #}
|
|
||||||
var champ_depts = document.getElementById("depts")
|
|
||||||
if (champ_depts) {
|
|
||||||
var closest_form_control = champ_depts.closest(".form-control")
|
|
||||||
closest_form_control.classList.remove("form-control")
|
|
||||||
}
|
|
||||||
|
|
||||||
if(document.getElementById("expiration_date") && document.getElementById("expiration_date").value === "")
|
|
||||||
expiration()
|
|
||||||
|
|
||||||
if(document.getElementById("type_offre"))
|
|
||||||
document.getElementById("type_offre").addEventListener("change", expiration);
|
|
||||||
|
|
||||||
function expiration() {
|
|
||||||
var date = new Date()
|
|
||||||
var expiration = document.getElementById("expiration_date")
|
|
||||||
var type_offre = document.getElementById("type_offre").value
|
|
||||||
if (type_offre === "Alternance") {
|
|
||||||
expiration.value = `${date.getFullYear() + 1}-01-01`
|
|
||||||
} else {
|
|
||||||
if(date.getMonth() + 1 < 8)
|
|
||||||
expiration.value = `${date.getFullYear()}-08-01`
|
|
||||||
else
|
|
||||||
expiration.value = `${date.getFullYear() + 1}-08-01`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var responsables_options = {
|
|
||||||
script: "/ScoDoc/entreprises/responsables?",
|
|
||||||
varname: "term",
|
|
||||||
json: true,
|
|
||||||
noresults: "Valeur invalide !",
|
|
||||||
minchars: 2,
|
|
||||||
timeout: 60000
|
|
||||||
};
|
|
||||||
|
|
||||||
var as_utilisateurs = new bsn.AutoSuggest('utilisateur', responsables_options);
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
62
app/templates/entreprises/form.j2
Normal file
62
app/templates/entreprises/form.j2
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
||||||
|
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<p>
|
||||||
|
(*) champs requis
|
||||||
|
</p>
|
||||||
|
{{ wtf.quick_form(form, novalidate=True) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
{# pour les formulaires offre # }
|
||||||
|
var champ_depts = document.getElementById("depts")
|
||||||
|
if (champ_depts) {
|
||||||
|
var closest_form_control = champ_depts.closest(".form-control")
|
||||||
|
closest_form_control.classList.remove("form-control")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById("expiration_date") && document.getElementById("expiration_date").value === "")
|
||||||
|
expiration()
|
||||||
|
|
||||||
|
if (document.getElementById("type_offre"))
|
||||||
|
document.getElementById("type_offre").addEventListener("change", expiration);
|
||||||
|
|
||||||
|
function expiration() {
|
||||||
|
var date = new Date()
|
||||||
|
var expiration = document.getElementById("expiration_date")
|
||||||
|
var type_offre = document.getElementById("type_offre").value
|
||||||
|
if (type_offre === "Alternance") {
|
||||||
|
expiration.value = `${date.getFullYear() + 1}-01-01`
|
||||||
|
} else {
|
||||||
|
if (date.getMonth() + 1 < 8)
|
||||||
|
expiration.value = `${date.getFullYear()}-08-01`
|
||||||
|
else
|
||||||
|
expiration.value = `${date.getFullYear() + 1}-08-01`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var responsables_options = {
|
||||||
|
script: "/ScoDoc/entreprises/responsables?",
|
||||||
|
varname: "term",
|
||||||
|
json: true,
|
||||||
|
noresults: "Valeur invalide !",
|
||||||
|
minchars: 2,
|
||||||
|
timeout: 60000
|
||||||
|
};
|
||||||
|
|
||||||
|
var as_utilisateurs = new bsn.AutoSuggest('utilisateur', responsables_options);
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,91 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
<form method="POST" action="" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
{{ form.correspondants.label }}
|
|
||||||
{% for subfield in form.correspondants %}
|
|
||||||
{% if subfield.errors %}
|
|
||||||
<p class="title-form-error">Formulaire {{ subfield.label.text }}</p>
|
|
||||||
{% endif %}
|
|
||||||
{% for subsubfield in subfield %}
|
|
||||||
{% if subsubfield.errors %}
|
|
||||||
{% for error in subsubfield.errors %}
|
|
||||||
<p class="help-block form-error">{{ error }}</p>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ form.correspondants }}
|
|
||||||
<div style="margin-bottom: 10px;">
|
|
||||||
<button class="btn btn-default" id="add-correspondant-field">Ajouter un correspondant</button>
|
|
||||||
{{ form.submit(class_="btn btn-default") }}
|
|
||||||
{{ form.cancel(class_="btn btn-default") }}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let allCorrepondantsFieldWrapper = document.getElementById('correspondants');
|
|
||||||
let allCorrepondantsForm = allCorrepondantsFieldWrapper.getElementsByTagName('li');
|
|
||||||
for(let i = 0; i < allCorrepondantsForm.length; i++) {
|
|
||||||
let form_id = allCorrepondantsForm[i].getElementsByTagName('table')[0].id
|
|
||||||
if(form_id.split('-')[1] != 0)
|
|
||||||
allCorrepondantsForm[i].insertAdjacentHTML('beforeend', `<div class="btn btn-default btn-remove" onclick="deleteForm('${form_id}')">Retirer ce correspondant</div>`)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function(e) {
|
|
||||||
let addCorrespondantFieldBtn = document.getElementById('add-correspondant-field');
|
|
||||||
addCorrespondantFieldBtn.addEventListener('click', function(e){
|
|
||||||
e.preventDefault();
|
|
||||||
let allCorrepondantsFieldWrapper = document.getElementById('correspondants');
|
|
||||||
let allCorrepondantsField = allCorrepondantsFieldWrapper.getElementsByTagName('input');
|
|
||||||
let correspondantInputIds = []
|
|
||||||
let csrf_token = document.getElementById('csrf_token').value;
|
|
||||||
for(let i = 0; i < allCorrepondantsField.length; i++) {
|
|
||||||
correspondantInputIds.push(parseInt(allCorrepondantsField[i].name.split('-')[1]));
|
|
||||||
}
|
|
||||||
let newFieldName = `correspondants-${Math.max(...correspondantInputIds) + 1}`;
|
|
||||||
allCorrepondantsFieldWrapper.insertAdjacentHTML('beforeend',`
|
|
||||||
<li>
|
|
||||||
<label for="${newFieldName}">Correspondants-${Math.max(...correspondantInputIds) + 1}</label>
|
|
||||||
<table id="${newFieldName}">
|
|
||||||
<tr><th><label for="${newFieldName}-civilite">Civilité (*)</label></th><td><select class="form-control" id="${newFieldName}-civilite" name="${newFieldName}-civilite" required><option value="H">Monsieur</option><option value="F">Madame</option></select></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-nom">Nom (*)</label></th><td><input class="form-control" id="${newFieldName}-nom" name="${newFieldName}-nom" required type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-prenom">Prénom (*)</label></th><td><input class="form-control" id="${newFieldName}-prenom" name="${newFieldName}-prenom" required type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-telephone">Téléphone (*)</label></th><td><input class="form-control" id="${newFieldName}-telephone" name="${newFieldName}-telephone" type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-mail">Mail (*)</label></th><td><input class="form-control" id="${newFieldName}-mail" name="${newFieldName}-mail" type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-poste">Poste</label></th><td><input class="form-control" id="${newFieldName}-poste" name="${newFieldName}-poste" type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-service">Service</label></th><td><input class="form-control" id="${newFieldName}-service" name="${newFieldName}-service" type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-origine">Origine</label></th><td><input class="form-control" id="${newFieldName}-origine" name="${newFieldName}-origine" type="text" value=""></td></tr>
|
|
||||||
<tr><th><label for="${newFieldName}-notes">Notes</label></th><td><input class="form-control" id="${newFieldName}-notes" name="${newFieldName}-notes" type="text" value=""></td></tr>
|
|
||||||
</table>
|
|
||||||
<input id="${newFieldName}-csrf_token" name="${newFieldName}-csrf_token" type="hidden" value=${csrf_token}>
|
|
||||||
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer ce correspondant</div>
|
|
||||||
</li>
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteForm(x) {
|
|
||||||
var li_form = document.querySelector(`label[for=${x}]`).closest('li');
|
|
||||||
if (li_form) {
|
|
||||||
li_form.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
91
app/templates/entreprises/form_ajout_correspondants.j2
Normal file
91
app/templates/entreprises/form_ajout_correspondants.j2
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<p>
|
||||||
|
(*) champs requis
|
||||||
|
</p>
|
||||||
|
<form method="POST" action="" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{{ form.correspondants.label }}
|
||||||
|
{% for subfield in form.correspondants %}
|
||||||
|
{% if subfield.errors %}
|
||||||
|
<p class="title-form-error">Formulaire {{ subfield.label.text }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% for subsubfield in subfield %}
|
||||||
|
{% if subsubfield.errors %}
|
||||||
|
{% for error in subsubfield.errors %}
|
||||||
|
<p class="help-block form-error">{{ error }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{{ form.correspondants }}
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<button class="btn btn-default" id="add-correspondant-field">Ajouter un correspondant</button>
|
||||||
|
{{ form.submit(class_="btn btn-default") }}
|
||||||
|
{{ form.cancel(class_="btn btn-default") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let allCorrepondantsFieldWrapper = document.getElementById('correspondants');
|
||||||
|
let allCorrepondantsForm = allCorrepondantsFieldWrapper.getElementsByTagName('li');
|
||||||
|
for (let i = 0; i < allCorrepondantsForm.length; i++) {
|
||||||
|
let form_id = allCorrepondantsForm[i].getElementsByTagName('table')[0].id
|
||||||
|
if (form_id.split('-')[1] != 0)
|
||||||
|
allCorrepondantsForm[i].insertAdjacentHTML('beforeend', `<div class="btn btn-default btn-remove" onclick="deleteForm('${form_id}')">Retirer ce correspondant</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function (e) {
|
||||||
|
let addCorrespondantFieldBtn = document.getElementById('add-correspondant-field');
|
||||||
|
addCorrespondantFieldBtn.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let allCorrepondantsFieldWrapper = document.getElementById('correspondants');
|
||||||
|
let allCorrepondantsField = allCorrepondantsFieldWrapper.getElementsByTagName('input');
|
||||||
|
let correspondantInputIds = []
|
||||||
|
let csrf_token = document.getElementById('csrf_token').value;
|
||||||
|
for (let i = 0; i < allCorrepondantsField.length; i++) {
|
||||||
|
correspondantInputIds.push(parseInt(allCorrepondantsField[i].name.split('-')[1]));
|
||||||
|
}
|
||||||
|
let newFieldName = `correspondants-${Math.max(...correspondantInputIds) + 1}`;
|
||||||
|
allCorrepondantsFieldWrapper.insertAdjacentHTML('beforeend', `
|
||||||
|
<li>
|
||||||
|
<label for="${newFieldName}">Correspondants-${Math.max(...correspondantInputIds) + 1}</label>
|
||||||
|
<table id="${newFieldName}">
|
||||||
|
<tr><th><label for="${newFieldName}-civilite">Civilité (*)</label></th><td><select class="form-control" id="${newFieldName}-civilite" name="${newFieldName}-civilite" required><option value="H">Monsieur</option><option value="F">Madame</option></select></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-nom">Nom (*)</label></th><td><input class="form-control" id="${newFieldName}-nom" name="${newFieldName}-nom" required type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-prenom">Prénom (*)</label></th><td><input class="form-control" id="${newFieldName}-prenom" name="${newFieldName}-prenom" required type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-telephone">Téléphone (*)</label></th><td><input class="form-control" id="${newFieldName}-telephone" name="${newFieldName}-telephone" type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-mail">Mail (*)</label></th><td><input class="form-control" id="${newFieldName}-mail" name="${newFieldName}-mail" type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-poste">Poste</label></th><td><input class="form-control" id="${newFieldName}-poste" name="${newFieldName}-poste" type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-service">Service</label></th><td><input class="form-control" id="${newFieldName}-service" name="${newFieldName}-service" type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-origine">Origine</label></th><td><input class="form-control" id="${newFieldName}-origine" name="${newFieldName}-origine" type="text" value=""></td></tr>
|
||||||
|
<tr><th><label for="${newFieldName}-notes">Notes</label></th><td><input class="form-control" id="${newFieldName}-notes" name="${newFieldName}-notes" type="text" value=""></td></tr>
|
||||||
|
</table>
|
||||||
|
<input id="${newFieldName}-csrf_token" name="${newFieldName}-csrf_token" type="hidden" value=${csrf_token}>
|
||||||
|
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer ce correspondant</div>
|
||||||
|
</li>
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteForm(x) {
|
||||||
|
var li_form = document.querySelector(`label[for=${x}]`).closest('li');
|
||||||
|
if (li_form) {
|
||||||
|
li_form.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,58 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>Ajout entreprise</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
Les champs s'auto complète selon le SIRET<br>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
{{ wtf.quick_form(form, novalidate=True) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
{# ajout margin-bottom sur le champ pays #}
|
|
||||||
var champ_pays = document.getElementById("pays")
|
|
||||||
if (champ_pays !== null) {
|
|
||||||
var closest_form_group = champ_pays.closest(".form-group")
|
|
||||||
closest_form_group.style.marginBottom = "50px"
|
|
||||||
}
|
|
||||||
|
|
||||||
document.getElementById("siret").addEventListener("keyup", autocomplete);
|
|
||||||
|
|
||||||
function autocomplete() {
|
|
||||||
var input = document.getElementById("siret").value.replaceAll(" ", "")
|
|
||||||
if(input.length >= 14) {
|
|
||||||
fetch("https://entreprise.data.gouv.fr/api/sirene/v1/siret/" + input)
|
|
||||||
.then(response => {
|
|
||||||
if(response.ok)
|
|
||||||
return response.json()
|
|
||||||
else {
|
|
||||||
emptyForm()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(response => fillForm(response))
|
|
||||||
.catch(err => err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fillForm(response) {
|
|
||||||
document.getElementById("nom_entreprise").value = response.etablissement.l1_normalisee
|
|
||||||
document.getElementById("adresse").value = response.etablissement.l4_normalisee
|
|
||||||
document.getElementById("codepostal").value = response.etablissement.code_postal
|
|
||||||
document.getElementById("ville").value = response.etablissement.libelle_commune
|
|
||||||
}
|
|
||||||
|
|
||||||
function emptyForm() {
|
|
||||||
document.getElementById("nom_entreprise").value = ''
|
|
||||||
document.getElementById("adresse").value = ''
|
|
||||||
document.getElementById("codepostal").value = ''
|
|
||||||
document.getElementById("ville").value = ''
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
58
app/templates/entreprises/form_ajout_entreprise.j2
Normal file
58
app/templates/entreprises/form_ajout_entreprise.j2
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>Ajout entreprise</h1>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<p>
|
||||||
|
Les champs s'auto complète selon le SIRET<br>
|
||||||
|
(*) champs requis
|
||||||
|
</p>
|
||||||
|
{{ wtf.quick_form(form, novalidate=True) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
{# ajout margin - bottom sur le champ pays # }
|
||||||
|
var champ_pays = document.getElementById("pays")
|
||||||
|
if (champ_pays !== null) {
|
||||||
|
var closest_form_group = champ_pays.closest(".form-group")
|
||||||
|
closest_form_group.style.marginBottom = "50px"
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("siret").addEventListener("keyup", autocomplete);
|
||||||
|
|
||||||
|
function autocomplete() {
|
||||||
|
var input = document.getElementById("siret").value.replaceAll(" ", "")
|
||||||
|
if (input.length >= 14) {
|
||||||
|
fetch("https://entreprise.data.gouv.fr/api/sirene/v1/siret/" + input)
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok)
|
||||||
|
return response.json()
|
||||||
|
else {
|
||||||
|
emptyForm()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => fillForm(response))
|
||||||
|
.catch(err => err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillForm(response) {
|
||||||
|
document.getElementById("nom_entreprise").value = response.etablissement.l1_normalisee
|
||||||
|
document.getElementById("adresse").value = response.etablissement.l4_normalisee
|
||||||
|
document.getElementById("codepostal").value = response.etablissement.code_postal
|
||||||
|
document.getElementById("ville").value = response.etablissement.libelle_commune
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyForm() {
|
||||||
|
document.getElementById("nom_entreprise").value = ''
|
||||||
|
document.getElementById("adresse").value = ''
|
||||||
|
document.getElementById("codepostal").value = ''
|
||||||
|
document.getElementById("ville").value = ''
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,36 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
|
||||||
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
{{ wtf.quick_form(form, novalidate=True) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
window.onload = function(e) {
|
|
||||||
var etudiants_options = {
|
|
||||||
script: "/ScoDoc/entreprises/etudiants?",
|
|
||||||
varname: "term",
|
|
||||||
json: true,
|
|
||||||
noresults: "Valeur invalide !",
|
|
||||||
minchars: 2,
|
|
||||||
timeout: 60000
|
|
||||||
};
|
|
||||||
var as_etudiants = new bsn.AutoSuggest('etudiant', etudiants_options);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
36
app/templates/entreprises/form_ajout_stage_apprentissage.j2
Normal file
36
app/templates/entreprises/form_ajout_stage_apprentissage.j2
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
||||||
|
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<p>
|
||||||
|
(*) champs requis
|
||||||
|
</p>
|
||||||
|
{{ wtf.quick_form(form, novalidate=True) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.onload = function (e) {
|
||||||
|
var etudiants_options = {
|
||||||
|
script: "/ScoDoc/entreprises/etudiants?",
|
||||||
|
varname: "term",
|
||||||
|
json: true,
|
||||||
|
noresults: "Valeur invalide !",
|
||||||
|
minchars: 2,
|
||||||
|
timeout: 60000
|
||||||
|
};
|
||||||
|
var as_etudiants = new bsn.AutoSuggest('etudiant', etudiants_options);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,15 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
<br>
|
|
||||||
<div>{{ info_message }}</div>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
{{ wtf.quick_form(form) }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
15
app/templates/entreprises/form_confirmation.j2
Normal file
15
app/templates/entreprises/form_confirmation.j2
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>{{ title }}</h1>
|
||||||
|
<br>
|
||||||
|
<div>{{ info_message }}</div>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
{{ wtf.quick_form(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -1,88 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
|
||||||
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>Envoyer une offre</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
<form method="POST" action="" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
{{ form.responsables.label }}
|
|
||||||
{% for error in form.responsables.errors %}
|
|
||||||
<p class="help-block form-error">{{ error }}</p>
|
|
||||||
{% endfor %}
|
|
||||||
{{ form.responsables }}
|
|
||||||
<div style="margin-bottom: 10px;">
|
|
||||||
<button class="btn btn-default" id="add-responsable-field">Ajouter un responsable</button>
|
|
||||||
{{ form.submit(class_="btn btn-default") }}
|
|
||||||
{{ form.cancel(class_="btn btn-default") }}
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
|
||||||
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('li');
|
|
||||||
for(let i = 0; i < allResponsablesField.length; i++) {
|
|
||||||
let form_id = allResponsablesField[i].getElementsByTagName('input')[0].id
|
|
||||||
if(form_id.split('-')[1] != 0)
|
|
||||||
allResponsablesField[i].insertAdjacentHTML('beforeend', `<div class="btn btn-default btn-remove" onclick="deleteForm('${form_id}')">Retirer</div>`)
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = function(e) {
|
|
||||||
var responsables_options = {
|
|
||||||
script: "/ScoDoc/entreprises/responsables?",
|
|
||||||
varname: "term",
|
|
||||||
json: true,
|
|
||||||
noresults: "Valeur invalide !",
|
|
||||||
minchars: 2,
|
|
||||||
timeout: 60000
|
|
||||||
};
|
|
||||||
|
|
||||||
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
|
||||||
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('input');
|
|
||||||
for(let i = 0; i < allResponsablesField.length; i++) {
|
|
||||||
new bsn.AutoSuggest(allResponsablesField[i].id, responsables_options);
|
|
||||||
}
|
|
||||||
|
|
||||||
let addResponsableFieldBtn = document.getElementById('add-responsable-field');
|
|
||||||
addResponsableFieldBtn.addEventListener('click', function(e){
|
|
||||||
e.preventDefault();
|
|
||||||
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
|
||||||
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('input');
|
|
||||||
let responsableInputIds = []
|
|
||||||
for(let i = 0; i < allResponsablesField.length; i++) {
|
|
||||||
responsableInputIds.push(parseInt(allResponsablesField[i].name.split('-')[1]));
|
|
||||||
}
|
|
||||||
let newFieldName = `responsables-${Math.max(...responsableInputIds) + 1}`;
|
|
||||||
allResponsablesFieldWrapper.insertAdjacentHTML('beforeend',`
|
|
||||||
<li>
|
|
||||||
<label for="${newFieldName}">Responsable (*)</label>
|
|
||||||
<input class="form-control" id="${newFieldName}" name="${newFieldName}" type="text" value="" placeholder="Tapez le nom du responsable de formation">
|
|
||||||
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer</div>
|
|
||||||
</li>
|
|
||||||
`);
|
|
||||||
var as_r = new bsn.AutoSuggest(newFieldName, responsables_options);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteForm(x) {
|
|
||||||
var li_form = document.querySelector(`label[for=${x}]`).closest('li');
|
|
||||||
if (li_form) {
|
|
||||||
li_form.remove()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
88
app/templates/entreprises/form_envoi_offre.j2
Normal file
88
app/templates/entreprises/form_envoi_offre.j2
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{# -*- mode: jinja-html -*- #}
|
||||||
|
{% extends 'base.j2' %}
|
||||||
|
{% import 'bootstrap/wtf.html' as wtf %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
{{super()}}
|
||||||
|
<link type="text/css" rel="stylesheet" href="/ScoDoc/static/css/autosuggest_inquisitor.css" />
|
||||||
|
<script src="/ScoDoc/static/libjs/AutoSuggest.js"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<h1>Envoyer une offre</h1>
|
||||||
|
<br>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<p>
|
||||||
|
(*) champs requis
|
||||||
|
</p>
|
||||||
|
<form method="POST" action="" novalidate>
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
{{ form.responsables.label }}
|
||||||
|
{% for error in form.responsables.errors %}
|
||||||
|
<p class="help-block form-error">{{ error }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
{{ form.responsables }}
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<button class="btn btn-default" id="add-responsable-field">Ajouter un responsable</button>
|
||||||
|
{{ form.submit(class_="btn btn-default") }}
|
||||||
|
{{ form.cancel(class_="btn btn-default") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
||||||
|
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('li');
|
||||||
|
for (let i = 0; i < allResponsablesField.length; i++) {
|
||||||
|
let form_id = allResponsablesField[i].getElementsByTagName('input')[0].id
|
||||||
|
if (form_id.split('-')[1] != 0)
|
||||||
|
allResponsablesField[i].insertAdjacentHTML('beforeend', `<div class="btn btn-default btn-remove" onclick="deleteForm('${form_id}')">Retirer</div>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function (e) {
|
||||||
|
var responsables_options = {
|
||||||
|
script: "/ScoDoc/entreprises/responsables?",
|
||||||
|
varname: "term",
|
||||||
|
json: true,
|
||||||
|
noresults: "Valeur invalide !",
|
||||||
|
minchars: 2,
|
||||||
|
timeout: 60000
|
||||||
|
};
|
||||||
|
|
||||||
|
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
||||||
|
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('input');
|
||||||
|
for (let i = 0; i < allResponsablesField.length; i++) {
|
||||||
|
new bsn.AutoSuggest(allResponsablesField[i].id, responsables_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
let addResponsableFieldBtn = document.getElementById('add-responsable-field');
|
||||||
|
addResponsableFieldBtn.addEventListener('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let allResponsablesFieldWrapper = document.getElementById('responsables');
|
||||||
|
let allResponsablesField = allResponsablesFieldWrapper.getElementsByTagName('input');
|
||||||
|
let responsableInputIds = []
|
||||||
|
for (let i = 0; i < allResponsablesField.length; i++) {
|
||||||
|
responsableInputIds.push(parseInt(allResponsablesField[i].name.split('-')[1]));
|
||||||
|
}
|
||||||
|
let newFieldName = `responsables-${Math.max(...responsableInputIds) + 1}`;
|
||||||
|
allResponsablesFieldWrapper.insertAdjacentHTML('beforeend', `
|
||||||
|
<li>
|
||||||
|
<label for="${newFieldName}">Responsable (*)</label>
|
||||||
|
<input class="form-control" id="${newFieldName}" name="${newFieldName}" type="text" value="" placeholder="Tapez le nom du responsable de formation">
|
||||||
|
<div class="btn btn-default btn-remove" onclick="deleteForm('${newFieldName}')">Retirer</div>
|
||||||
|
</li>
|
||||||
|
`);
|
||||||
|
var as_r = new bsn.AutoSuggest(newFieldName, responsables_options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteForm(x) {
|
||||||
|
var li_form = document.querySelector(`label[for=${x}]`).closest('li');
|
||||||
|
if (li_form) {
|
||||||
|
li_form.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
@ -1,68 +0,0 @@
|
|||||||
{# -*- mode: jinja-html -*- #}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
{% import 'bootstrap/wtf.html' as wtf %}
|
|
||||||
|
|
||||||
{% block styles %}
|
|
||||||
{{super()}}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block app_content %}
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
<br>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-4">
|
|
||||||
<p>
|
|
||||||
(*) champs requis
|
|
||||||
</p>
|
|
||||||
{{ wtf.quick_form(form, novalidate=True) }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="sirene-data" class="col-md-5">
|
|
||||||
<b>Informations de la base SIRENE</b>
|
|
||||||
<div id="nom_entreprise_base"></div>
|
|
||||||
<div id="adresse_base"></div>
|
|
||||||
<div id="codepostal_base"></div>
|
|
||||||
<div id="ville_base"></div>
|
|
||||||
<a class="btn btn-primary" onclick="getData()">Copier</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var value = document.getElementById("siret").value;
|
|
||||||
fetch("https://entreprise.data.gouv.fr/api/sirene/v1/siret/" + value)
|
|
||||||
.then(response => {
|
|
||||||
if(response.ok)
|
|
||||||
return response.json()
|
|
||||||
})
|
|
||||||
.then(response => showSireneData(response))
|
|
||||||
.catch(err => {
|
|
||||||
document.getElementById("sirene-data").style.display = "none"
|
|
||||||
return err
|
|
||||||
})
|
|
||||||
|
|
||||||
function showSireneData(response) {
|
|
||||||
document.getElementById("nom_entreprise_base").innerHTML = "Nom de l'entreprise: " + response.etablissement.l1_normalisee
|
|
||||||
document.getElementById("adresse_base").innerHTML = "Adresse: " + response.etablissement.l4_normalisee
|
|
||||||
document.getElementById("codepostal_base").innerHTML = "Code postal: " + response.etablissement.code_postal
|
|
||||||
document.getElementById("ville_base").innerHTML = "Ville: " + response.etablissement.libelle_commune
|
|
||||||
}
|
|
||||||
|
|
||||||
function getData() {
|
|
||||||
var value = document.getElementById("siret").value;
|
|
||||||
fetch("https://entreprise.data.gouv.fr/api/sirene/v1/siret/" + value)
|
|
||||||
.then(response => {
|
|
||||||
if(response.ok)
|
|
||||||
return response.json()
|
|
||||||
})
|
|
||||||
.then(response => fillForm(response))
|
|
||||||
.catch(err => err)
|
|
||||||
}
|
|
||||||
|
|
||||||
function fillForm(response) {
|
|
||||||
document.getElementById("nom").value = response.etablissement.l1_normalisee
|
|
||||||
document.getElementById("adresse").value = response.etablissement.l4_normalisee
|
|
||||||
document.getElementById("codepostal").value = response.etablissement.code_postal
|
|
||||||
document.getElementById("ville").value = response.etablissement.libelle_commune
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user