Compare commits

...

2 Commits

12 changed files with 219 additions and 29 deletions

View File

@ -603,8 +603,19 @@ class Role(db.Model):
"""Create default roles if missing, then, if reset_permissions,
reset their permissions to default values.
"""
Role.reset_roles_permissions(
SCO_ROLES_DEFAULTS, reset_permissions=reset_permissions
)
@staticmethod
def reset_roles_permissions(roles_perms: dict[str, tuple], reset_permissions=True):
"""Ajoute les permissions aux roles
roles_perms : { "role_name" : (permission, ...) }
reset_permissions : si vrai efface permissions déja existantes
Si le role n'existe pas, il est (re) créé.
"""
default_role = "Observateur"
for role_name, permissions in SCO_ROLES_DEFAULTS.items():
for role_name, permissions in roles_perms.items():
role = Role.query.filter_by(name=role_name).first()
if role is None:
role = Role(name=role_name)

View File

@ -59,3 +59,4 @@ def check_taxe_now(taxes):
from app.entreprises import routes
from app.entreprises.activate import activate_module

View File

@ -0,0 +1,31 @@
##############################################################################
# ScoDoc
# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved.
# See LICENSE
##############################################################################
"""Activation du module entreprises
L'affichage du module est contrôlé par la config ScoDocConfig.enable_entreprises
Au moment de l'activation, il est en général utile de proposer de configurer les
permissions de rôles standards: AdminEntreprise UtilisateurEntreprise ObservateurEntreprise
Voir associations dans sco_roles_default
"""
from app.auth.models import Role
from app.models import ScoDocSiteConfig
from app.scodoc.sco_roles_default import SCO_ROLES_ENTREPRISES_DEFAULT
def activate_module(
enable: bool = True, set_default_roles_permission: bool = False
) -> bool:
"""Active le module et en option donne les permissions aux rôles standards.
True si l'état d'activation a changé.
"""
change = ScoDocSiteConfig.enable_entreprises(enable)
if enable and set_default_roles_permission:
Role.reset_roles_permissions(SCO_ROLES_ENTREPRISES_DEFAULT)
return change

View File

@ -0,0 +1,17 @@
"""
Formulaire activation module entreprises
"""
from flask_wtf import FlaskForm
from wtforms.fields.simple import BooleanField, SubmitField
from app.models import ScoDocSiteConfig
class ActivateEntreprisesForm(FlaskForm):
"Formulaire activation module entreprises"
set_default_roles_permission = BooleanField(
"(re)mettre les rôles 'Entreprise' à leurs valeurs par défaut"
)
submit = SubmitField("Valider")
cancel = SubmitField("Annuler", render_kw={"formnovalidate": True})

View File

@ -54,7 +54,6 @@ class BonusConfigurationForm(FlaskForm):
class ScoDocConfigurationForm(FlaskForm):
"Panneau de configuration avancée"
enable_entreprises = BooleanField("activer le module <em>entreprises</em>")
disable_passerelle = BooleanField( # disable car par défaut activée
"""cacher les fonctions liées à une passerelle de publication des résultats vers les étudiants ("œil"). N'affecte pas l'API, juste la présentation."""
)
@ -127,13 +126,6 @@ def configuration():
flash("Fonction bonus inchangée.")
return redirect(url_for("scodoc.index"))
elif form_scodoc.submit_scodoc.data and form_scodoc.validate():
if ScoDocSiteConfig.enable_entreprises(
enabled=form_scodoc.data["enable_entreprises"]
):
flash(
"Module entreprise "
+ ("activé" if form_scodoc.data["enable_entreprises"] else "désactivé")
)
if ScoDocSiteConfig.disable_passerelle(
disabled=form_scodoc.data["disable_passerelle"]
):
@ -182,6 +174,7 @@ def configuration():
return render_template(
"configuration.j2",
is_entreprises_enabled=ScoDocSiteConfig.is_entreprises_enabled(),
form_bonus=form_bonus,
form_scodoc=form_scodoc,
scu=scu,

View File

@ -51,7 +51,24 @@ SCO_ROLES_DEFAULTS = {
p.UsersView,
p.ViewEtudData,
),
# Rôles pour l'application relations entreprises
# LecteurAPI peut utiliser l'API en lecture
"LecteurAPI": (p.ScoView,),
"Observateur": (p.Observateur,),
# RespPE est le responsable poursuites d'études
# il peut ajouter des tags sur les formations:
# (doit avoir un rôle Ens en plus !)
"RespPe": (p.EditFormationTags,),
# Super Admin est un root: création/suppression de départements
# _tous_ les droits
# Afin d'avoir tous les droits, il ne doit pas être asscoié à un département
"SuperAdmin": p.ALL_PERMISSIONS,
}
# Rôles pour l'application relations entreprises
# séparés pour pouvoir les réinitialiser lors de l'activation du module Entreprises
# Note: Admin (chef de dept n'a par défaut aucun rôle lié à ce module)
SCO_ROLES_ENTREPRISES_DEFAULT = {
# ObservateurEntreprise est un observateur de l'application entreprise
"ObservateurEntreprise": (p.RelationsEntrepView,),
# UtilisateurEntreprise est un utilisateur de l'application entreprise (droit de modification)
@ -70,19 +87,10 @@ SCO_ROLES_DEFAULTS = {
p.RelationsEntrepValidate,
p.RelationsEntrepViewCorrs,
),
# LecteurAPI peut utiliser l'API en lecture
"LecteurAPI": (p.ScoView,),
"Observateur": (p.Observateur,),
# RespPE est le responsable poursuites d'études
# il peut ajouter des tags sur les formations:
# (doit avoir un rôle Ens en plus !)
"RespPe": (p.EditFormationTags,),
# Super Admin est un root: création/suppression de départements
# _tous_ les droits
# Afin d'avoir tous les droits, il ne doit pas être asscoié à un département
"SuperAdmin": p.ALL_PERMISSIONS,
}
SCO_ROLES_DEFAULTS.update(SCO_ROLES_ENTREPRISES_DEFAULT)
# Les rôles accessibles via la page d'admin utilisateurs
# - associés à un département:
ROLES_ATTRIBUABLES_DEPT = ("Ens", "Secr", "Admin", "RespPe")

View File

@ -265,6 +265,8 @@ class Table(Element):
title: str = None,
classes: list[str] = None,
raw_title: str = None,
no_excel: bool = False,
only_excel: bool = False,
) -> tuple["Cell", "Cell"]:
"""Record this title,
and create cells for footer and header if they don't already exist.
@ -282,6 +284,8 @@ class Table(Element):
classes=classes,
group=self.column_group.get(col_id),
raw_content=raw_title or title,
no_excel=no_excel,
only_excel=only_excel,
)
if self.foot_title_row:
self.foot_title_row.cells[col_id] = self.foot_title_row.add_cell(
@ -370,6 +374,7 @@ class Row(Element):
target_attrs: dict = None,
target: str = None,
column_classes: set[str] = None,
only_excel: bool = False,
no_excel: bool = False,
) -> "Cell":
"""Create cell and add it to the row.
@ -397,6 +402,7 @@ class Row(Element):
column_group=group,
title=title,
raw_title=raw_title,
only_excel=only_excel,
no_excel=no_excel,
)
@ -406,6 +412,7 @@ class Row(Element):
cell: "Cell",
column_group: str | None = None,
title: str | None = None,
only_excel: bool = False,
no_excel: bool = False,
raw_title: str | None = None,
) -> "Cell":
@ -414,10 +421,10 @@ class Row(Element):
"""
cell.data["group"] = column_group or ""
self.cells[col_id] = cell
if col_id not in self.table.column_ids:
if not only_excel and col_id not in self.table.column_ids:
self.table.column_ids.append(col_id)
if not no_excel:
self.table.raw_column_ids.append(col_id)
if not no_excel and col_id not in self.table.raw_column_ids:
self.table.raw_column_ids.append(col_id)
self.table.insert_group(column_group)
if column_group is not None:
@ -425,7 +432,12 @@ class Row(Element):
if title is not None:
self.table.add_title(
col_id, title, classes=cell.classes, raw_title=raw_title
col_id,
title,
classes=cell.classes,
raw_title=raw_title,
no_excel=no_excel,
only_excel=only_excel,
)
return cell

View File

@ -6,14 +6,15 @@
"""Liste simple d'étudiants
"""
import datetime
from flask import g, url_for
from app import log
from app.models import FormSemestre, Identite, Justificatif
from app.tables import table_builder as tb
import app.scodoc.sco_assiduites as scass
from app.scodoc import sco_preferences
from app.scodoc import sco_utils as scu
import app.scodoc.sco_assiduites as scass
from app.scodoc.sco_exceptions import ScoValueError
class TableAssi(tb.Table):
@ -39,7 +40,13 @@ class TableAssi(tb.Table):
):
self.rows: list["RowAssi"] = [] # juste pour que VSCode nous aide sur .rows
classes = ["gt_table"]
self.dates = [str(dates[0]) + "T00:00", str(dates[1]) + "T23:59"]
try:
self.dates = [
datetime.datetime.fromisoformat(str(dates[0]) + "T00:00"),
datetime.datetime.fromisoformat(str(dates[1]) + "T00:00"),
]
except ValueError as exc:
raise ScoValueError("invalid dates") from exc
self.formsemestre = formsemestre
self.formsemestre_modimpls = formsemestre_modimpls
if convert_values:
@ -97,6 +104,20 @@ class RowAssi(tb.Row):
bilan_etud = url_for(
"assiduites.bilan_etud", scodoc_dept=g.scodoc_dept, etudid=etud.id
)
self.add_cell(
"etudid",
"etudid",
etud.etudid,
"etudinfo",
only_excel=True,
)
self.add_cell(
"code_nip",
"code_nip",
etud.code_nip,
"etudinfo",
only_excel=True,
)
self.add_cell(
"nom_disp",
"Nom",

View File

@ -0,0 +1,51 @@
{% extends "base.j2" %}
{% import 'wtf.j2' as wtf %}
{% block app_content %}
<h1>{{title}}</h1>
<div class="help">
<p>
</p>
<p>
</p>
</div>
<div class="row">
<div class="col-md-8">
<form class="form form-horizontal spacediv" method="post" enctype="multipart/form-data" role="form">
{{ form.hidden_tag() }}
{{ wtf.form_errors(form, hiddens="only") }}
{% if is_enabled %}
<p>Le module <em>relations entreprises</em> est actuellement activé.</p>
<p>Il peut être activé ou désactivé à tout moment sans aucune perte de
données (la désactivation le fait simplement disparaitre des pages
utilisateurs).
<p>
{% else %}
<p>Le module <em>relations entreprises</em> est actuellement désactivé.
</p>
<p>Il peut être activé ou désactivé à tout moment sans aucune perte de
données (la désactivation le fait simplement disparaitre des pages
utilisateurs).
<p>
<p>
Lors de son activation, vous pouvez (re)positionner les rôles qu'il utilise
à leurs valeurs par défaut en cochant la case ci-dessous.
</p>
{{ wtf.form_field(form.set_default_roles_permission) }}
{% endif %}
<div class="form-group spacediv">
{{ wtf.form_field(form.submit) }}
{{ wtf.form_field(form.cancel) }}
</div>
</div>
</div>
<style>
.spacediv {
margin-top: 16px;
}
</style>
{% endblock %}

View File

@ -39,6 +39,18 @@ Heure: <b><tt>{{ time.strftime("%d/%m/%Y %H:%M") }}</tt></b>
<div class="scobox">
<div class="scobox-title">ScoDoc : paramètres généraux</div>
<div style="margin-top: 16px;">
Le module <em>Relations Entreprises</em>
{% if is_entreprises_enabled %}
est <b>activé</b>
{% else %}
n'est pas activé
{% endif %}
: <a class="stdlink" href="{{url_for('scodoc.activate_entreprises')
}}">{% if is_entreprises_enabled %}le désactiver{%else%}l'activer{%endif%}</a>
</div>
<form id="configuration_form_scodoc" class="sco-form" action="" method="post" enctype="multipart/form-data" novalidate>
{{ form_scodoc.hidden_tag() }}
<div class="row">

View File

@ -1440,7 +1440,6 @@ def visu_assi_group():
formsemestre_modimpls=formsemestre_modimpls,
convert_values=(fmt == "html"),
)
# Export en XLS
if fmt.startswith("xls"):
return scu.send_file(

View File

@ -53,6 +53,7 @@ from werkzeug.exceptions import BadRequest, NotFound
from app import db, log
from app import entreprises
from app.auth.models import User, Role
from app.auth.cas import set_cas_configuration
from app.decorators import (
@ -62,6 +63,7 @@ from app.decorators import (
)
from app.forms.generic import SimpleConfirmationForm
from app.forms.main import config_logos, config_main
from app.forms.main.activate_entreprises import ActivateEntreprisesForm
from app.forms.main.config_assiduites import ConfigAssiduitesForm
from app.forms.main.config_apo import CodesDecisionsForm
from app.forms.main.config_cas import ConfigCASForm
@ -484,6 +486,38 @@ def config_personalized_links():
)
@bp.route("/ScoDoc/activate_entreprises", methods=["GET", "POST"])
@admin_required
def activate_entreprises():
"""Form activation module entreprises"""
is_enabled = ScoDocSiteConfig.is_entreprises_enabled()
form = ActivateEntreprisesForm(
data={
"set_default_roles_permission": True,
}
)
if request.method == "POST" and form.cancel.data: # cancel button
return redirect(url_for("scodoc.configuration"))
if form.validate_on_submit():
if entreprises.activate_module(
enable=not is_enabled,
set_default_roles_permission=form.data["set_default_roles_permission"],
):
flash("Module entreprise " + ("activé" if not is_enabled else "désactivé"))
return redirect(url_for("scodoc.configuration"))
if is_enabled:
form.submit.label.text = "Désactiver le module relations entreprises"
else:
form.submit.label.text = "Activer le module relations entreprises"
return render_template(
"activate_entreprises.j2",
form=form,
is_enabled=is_enabled,
title="Activation module Relations Entreprises",
)
@bp.route("/ScoDoc/table_etud_in_accessible_depts", methods=["POST"])
@login_required
def table_etud_in_accessible_depts():