Compare commits

...

12 Commits

157 changed files with 1752 additions and 209 deletions

322
README.md
View File

@ -1,189 +1,139 @@
# ScoDoc - Gestion de la scolarité - Version ScoDoc 9
# Reapplication des modifs locales suite à upgrade serveur
Voila les opérations que j ai faite en direct pour mettre a jour notre scodoc local apres un upgrade de scodoc
l'exemple ici fait suite à l upgrade 9.1.55 -> 9.1.56
le no de version (9.1.56) devrait être un parametre d'un éventuel script
Note preliminaire:
- j ai installé git sur iut-scodoc
- on travaille avec les réperoires:
- /opt/scodoc répértoire de production
- /opt/scodoc-local les fichiers différentes entre la version lillooise et la version officielle
- /opt/ScoDoc-git le working-dir de git
Tous ces répertoires doivent être la propriété de l'user `scodoc
Je pars d'un situation où le working dir est sur la branche `local`, que le depot distant git contient la dernière version et que /opt/scodoc a déjà été mis à jour
Mise en place
```bash
cd /opt/ScoDoc-git/
su scodoc
```
première vérification que l on est bien sur la branche `local` et à jour (sinon faire `git checkout local`)
```bash
git status
Sur la branche local
rien à valider, la copie de travail est propre
git log -1
commit 322090276326c36e8d5525372e3e0804569b70ac (HEAD -> local)
Merge: 574fede 514a09e
Author: jean-marie Place (as scodoc) <jean-marie.place@univ-lille.fr>
Date: Mon Feb 14 16:49:36 2022 +0100
Merge tag '9.1.55' into local
9.1 220213
```
Recpie en local de l'historique officiel (contient la nouvelle version (ici 9.1.56) en tant que tag)
```bash
git fetch
remote: Enumerating objects: 32, done.
remote: Counting objects: 100% (32/32), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 17 (delta 15), reused 0 (delta 0), pack-reused 0
Dépaquetage des objets: 100% (17/17), 2.64 Kio | 246.00 Kio/s, fait.
Depuis https://scodoc.org/git/ScoDoc/ScoDoc
0196d41..60a77b8 dev92 -> origin/dev92
* [nouvelle étiquette] 9.1.56 -> 9.1.56
```
Intégration des dernières midif officielles dans la branche locale
Il est possible que la fusion déclenche une erreur à ce niveai si la mise à jour officielle concerne un des fichiers modifiés localalement
Dans ce cas, pas d'autre solution que de verifier la fusion à la main
si procedure automatisée, prévoir un arrêt éventuel à ce niveau (basé sur la valeur de retour gu git merge ?)
```bash
git merge origin 9.1.56
Fusion automatique de app/views/notes.py
Fusion automatique de app/scodoc/sco_formsemestre_status.py
Merge made by the 'recursive' strategy.
app/but/bulletin_but.py | 2 +-
app/but/bulletin_but_xml_compat.py | 26 ++++++++++++++++----------
app/comp/res_common.py | 11 +++++++++++
app/models/moduleimpls.py | 2 +-
......
......
app/templates/pn/form_ues.html | 5 +++++
app/templates/pn/ue_infos.html | 2 +-
app/views/absences.py | 4 +++-
app/views/notes.py | 2 +-
sco_version.py | 2 +-
35 files changed, 149 insertions(+), 90 deletions(-)
```
Si tout s est bien passé, vérification
```bash
git status
Sur la branche local
rien à valider, la copie de travail est propre
```
Enumération des fichiers modifiés localement
```bash
git diff --name-only 9.1.56
app/scodoc/sco_excel.py
app/scodoc/sco_excel_add.py
app/scodoc/sco_formsemestre_status.py
app/scodoc/sco_prepajury_formats.py
app/scodoc/sco_prepajury_iuta.py
app/views/notes.py
app/views/scolar.py
```
et recopie des diffs dans `/opt/scodoc-local/`
(pour l instant 2 sous répertoires /app/scodoc et /app/views)
TODO adapter la commande pour créer d'autres sous-répertoires si besoin (actuellement -> erreur bash)
```bash
for f in $(git diff --name-only 9.1.56); do cp -p $f /opt/scodoc-local/$f ; done
```
Si tout s'est bien passé jusque là recopie des fichiers diffs en production
```bash
for f in $(git diff --name-only 9.1.56); do cp -p $f /opt/scodoc/$f ; done
```
Effacement du cache REDIS (préservé même en cas de redémarrage serveur)
Et relance du serveur
```bash
cd /opt/scodoc
source venv/bin/activate
flask clear-cache
exit
systemctl restart scodoc9
```
# Ajout d'autres adaptations locales
Ajouter les nouvelles modifs à la branche `local`du git
Et compléter ci-dessous.
## Adaptations actuelles
- Ajout mention adaptation local à l'écran principal
- api: formsemestre_partition_list
- Ajout dans le menu de `Générer feuille préparation Jury (DUT)`
- TODO: poursuite d'études
- TODO: Affichage des étiquettes étudiant
(c) Emmanuel Viennet 1999 - 2022 (voir LICENCE.txt)
Installation: voir instructions à jour sur <https://scodoc.org/GuideInstallDebian11>
Documentation utilisateur: <https://scodoc.org>
## Version ScoDoc 9
La version ScoDoc 9 est basée sur Flask (au lieu de Zope) et sur
**python 3.9+**.
La version 9.0 s'efforce de reproduire presque à l'identique le fonctionnement
de ScoDoc7, avec des composants logiciels différents (Debian 11, Python 3,
Flask, SQLAlchemy, au lien de Python2/Zope dans les versions précédentes).
### État actuel (26 jan 22)
- 9.1 (master) reproduit l'ensemble des fonctions de ScoDoc 7 (donc pas de BUT), sauf:
- ancien module "Entreprises" (obsolète) et ajoute la gestion du BUT.
- 9.2 (branche refactor_nt) est la version de développement.
### Lignes de commandes
Voir [https://scodoc.org/GuideConfig](le guide de configuration).
## Organisation des fichiers
L'installation comporte les fichiers de l'application, sous `/opt/scodoc/`, et
les fichiers locaux (archives, photos, configurations, logs) sous
`/opt/scodoc-data`. Par ailleurs, il y a évidemment les bases de données
postgresql et la configuration du système Linux.
### Fichiers locaux
Sous `/opt/scodoc-data`, fichiers et répertoires appartenant à l'utilisateur `scodoc`.
Ils ne doivent pas être modifiés à la main, sauf certains fichiers de configuration sous
`/opt/scodoc-data/config`.
Le répertoire `/opt/scodoc-data` doit être régulièrement sauvegardé.
Principaux contenus:
/opt/scodoc-data
/opt/scodoc-data/log # Fichiers de log ScoDoc
/opt/scodoc-data/config # Fichiers de configuration
.../config/logos # Logos de l'établissement
.../config/depts # un fichier par département
/opt/scodoc-data/photos # Photos des étudiants
/opt/scodoc-data/archives # Archives: PV de jury, maquettes Apogée, fichiers étudiants
## Pour les développeurs
### Installation du code
Installer ScoDoc 9 normalement ([voir la doc](https://scodoc.org/GuideInstallDebian11)).
Puis remplacer `/opt/scodoc` par un clone du git.
sudo su
mv /opt/scodoc /opt/off-scodoc # ou ce que vous voulez
apt-get install git # si besoin
cd /opt
git clone https://scodoc.org/git/viennet/ScoDoc.git
# (ou bien utiliser votre clone gitea si vous l'avez déjà créé !)
mv ScoDoc scodoc # important !
Il faut ensuite installer l'environnement et le fichier de configuration:
# Le plus simple est de piquer le virtualenv configuré par l'installeur:
mv /opt/off-scodoc/venv /opt/scodoc
Et la config:
ln -s /opt/scodoc-data/.env /opt/scodoc
Cette dernière commande utilise le `.env` crée lors de l'install, ce qui
n'est pas toujours le plus judicieux: vous pouvez modifier son contenu, par
exemple pour travailler en mode "développement" avec `FLASK_ENV=development`.
### Tests unitaires
Les tests unitaires utilisent normalement la base postgresql `SCODOC_TEST`.
Avant le premier lancement, créer cette base ainsi:
./tools/create_database.sh SCODOC_TEST
export FLASK_ENV=test
flask db upgrade
Cette commande n'est nécessaire que la première fois (le contenu de la base
est effacé au début de chaque test, mais son schéma reste) et aussi si des
migrations (changements de schéma) ont eu lieu dans le code.
Certains tests ont besoin d'un département déjà créé, qui n'est pas créé par les
scripts de tests:
Lancer au préalable:
flask delete-dept TEST00 && flask create-dept TEST00
Puis dérouler les tests unitaires:
pytest tests/unit
Ou avec couverture (`pip install pytest-cov`)
pytest --cov=app --cov-report=term-missing --cov-branch tests/unit/*
#### Utilisation des tests unitaires pour initialiser la base de dev
On peut aussi utiliser les tests unitaires pour mettre la base
de données de développement dans un état connu, par exemple pour éviter de
recréer à la main étudiants et semestres quand on développe.
Il suffit de positionner une variable d'environnement indiquant la BD
utilisée par les tests:
export SCODOC_TEST_DATABASE_URI=postgresql:///SCODOC_DEV
(si elle n'existe pas, voir plus loin pour la créer) puis de les lancer
normalement, par exemple:
pytest tests/unit/test_sco_basic.py
Il est en général nécessaire d'affecter ensuite un mot de passe à (au moins)
un utilisateur:
flask user-password admin
**Attention:** les tests unitaires **effacent** complètement le contenu de la
base de données (tous les départements, et les utilisateurs) avant de commencer !
#### Modification du schéma de la base
On utilise SQLAlchemy avec Alembic et Flask-Migrate.
flask db migrate -m "message explicatif....."
flask db upgrade
Ne pas oublier de d'ajouter le script de migration à git (`git add migrations/...`).
**Mémo**: séquence re-création d'une base (vérifiez votre `.env`
ou variables d'environnement pour interroger la bonne base !).
dropdb SCODOC_DEV
tools/create_database.sh SCODOC_DEV # créé base SQL
flask db upgrade # créé les tables à partir des migrations
flask sco-db-init # ajoute au besoin les constantes (fait en migration 0)
# puis imports:
flask import-scodoc7-users
flask import-scodoc7-dept STID SCOSTID
Si la base utilisée pour les dev n'est plus en phase avec les scripts de
migration, utiliser les commandes `flask db history`et `flask db stamp`pour se
positionner à la bonne étape.
### Profiling
Sur une machine de DEV, lancer
flask profile --host 0.0.0.0 --length 32 --profile-dir /opt/scodoc-data
le fichier `.prof` sera alors écrit dans `/opt/scodoc-data` (on peut aussi utiliser `/tmp`).
Pour la visualisation, [snakeviz](https://jiffyclub.github.io/snakeviz/) est bien:
pip install snakeviz
puis
snakeviz -s --hostname 0.0.0.0 -p 5555 /opt/scodoc-data/GET.ScoDoc......prof
# Paquet Debian 11
Les scripts associés au paquet Debian (.deb) sont dans `tools/debian`. Le plus
important est `postinst`qui se charge de configurer le système (install ou
upgrade de scodoc9).
La préparation d'une release se fait à l'aide du script
`tools/build_release.sh`.

View File

@ -219,6 +219,14 @@ class ScoExcelSheet:
self.column_dimensions = {}
self.row_dimensions = {}
# def merge_cells(self, start_row, start_column, end_row, end_column):
# self.ws.merge_cells(
# start_row=start_row,
# start_column=start_column,
# end_row=end_row,
# end_column=end_column,
# )
def excel_make_composite_style(
self,
alignment=None,
@ -247,7 +255,7 @@ class ScoExcelSheet:
if idx < 26: # one letter key
return chr(idx + 65)
else: # two letters AA..ZZ
first = (idx // 26) + 66
first = (idx // 26) + 64
second = (idx % 26) + 65
return "" + chr(first) + chr(second)
@ -260,11 +268,25 @@ class ScoExcelSheet:
for i, val in enumerate(value):
self.ws.column_dimensions[self.i2col(i)].width = val
# No keys: value is a list of widths
elif type(cle) == str: # accepts set_column_with("D", ...)
elif isinstance(cle, str): # accepts set_column_with("D", ...)
self.ws.column_dimensions[cle].width = value
else:
self.ws.column_dimensions[self.i2col(cle)].width = value
def set_column_dimension_hidden(self, cle=None, value=21):
"""Détermine la largeur d'une colonne. cle -- identifie la colonne ("A" "B", ... ou 0, 1, 2, ...) si None,
value donne la liste des largeurs de colonnes depuis A, B, C, ... value -- la dimension (unité : 7 pixels
comme affiché dans Excel)
"""
if cle is None:
for i, val in enumerate(value):
self.ws.column_dimensions[self.i2col(i)].width = val
# No keys: value is a list of widths
elif isinstance(cle, str): # accepts set_column_with("D", ...)
self.ws.column_dimensions[cle].hidden = value
else:
self.ws.column_dimensions[self.i2col(cle)].hidden = value
def set_row_dimension_height(self, cle=None, value=21):
"""Détermine la hauteur d'une ligne. cle -- identifie la ligne (1, 2, ...) si None,
value donne la liste des hauteurs de colonnes depuis 1, 2, 3, ... value -- la dimension
@ -276,6 +298,11 @@ class ScoExcelSheet:
else:
self.ws.row_dimensions[cle].height = value
def merge(self, start_row, end_row, start_column, end_column):
self.ws.merged_cells.ranges.append(
f"{self.i2col(start_column)}{start_row}:{self.i2col(end_column)}{end_row}"
)
def set_row_dimension_hidden(self, cle, value):
"""Masque ou affiche une ligne.
cle -- identifie la colonne (1...)
@ -338,12 +365,14 @@ class ScoExcelSheet:
return cell
def make_row(self, values: list, style=None, comments=None):
# TODO make possible differents styles in a row
# styles: a list of style(s) instead of a unique style (in a row)
if comments is None:
comments = [None] * len(values)
if not isinstance(style, list):
style = [style] * len(values)
return [
self.make_cell(value, style, comment)
for value, comment in zip(values, comments)
self.make_cell(value, a_style, comment)
for value, a_style, comment in zip(values, style, comments)
]
def append_single_cell_row(self, value: any, style=None):

221
app/scodoc/sco_excel_add.py Normal file
View File

@ -0,0 +1,221 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2019 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
""" Excel file handling
"""
# from sco_utils import *
# from sco_excel import *
import time, datetime
from openpyxl.styles import Font, Alignment, PatternFill, Side, Border
from app.scodoc.sco_excel import COLORS
def make_font(
bold=False,
italic=False,
font_name=None,
font_size=None,
color=COLORS.BLACK.value,
style=None,
uline=False,
):
font = None
if bold or italic or font_name or font_size:
font = Font()
if bold:
font.bold = bold
if uline:
font.underline = Font.UNDERLINE_SINGLE
if italic:
font.italic = italic
font.name = font_name if font_name else "Arial"
if font_size:
font.height = 20 * font_size
if color:
font.color = color
if font and style:
style["font"] = font
return font
def make_alignment(halign=None, valign=None, orientation=None, style=None):
alignment = None
if halign or valign or orientation:
alignment = Alignment()
if halign:
alignment.horz = halign
if valign:
alignment.vert = valign
if orientation:
alignment.rota = orientation
if alignment and style:
breakpoint()
style["alignment"] = alignment
return alignment
def make_numfmt(fmt, style=None):
if fmt and style:
style["num_format_str"] = fmt
def make_pattern(bgcolor, style=None):
pattern = PatternFill(fill_type="solid", fgColor=bgcolor)
if pattern and style:
style["fill"] = pattern
return pattern
Sides = {
"none": Side(border_style=None),
"thin": Side(border_style="thin"),
"medium": Side(border_style="medium"),
"thick": Side(border_style="thick"),
"filet": Side(border_style="hair"),
}
def make_borders(left=None, top=None, bottom=None, right=None, style=None):
border = None
if left or right or top or bottom:
border = Border()
if left:
border.left = Sides[left]
if right:
border.right = Sides[right]
if top:
border.top = Sides[top]
if bottom:
border.bottom = Sides[bottom]
if border and style:
style["border"] = border
return border
#
#
# def Excel_MakeStyle(
# bold=False,
# italic=False,
# color="black",
# bgcolor=None,
# halign=None,
# valign=None,
# orientation=None,
# font_name=None,
# font_size=None,
# ):
# style = XFStyle()
# make_font(bold, italic, font_name, font_size, color, style=style)
# make_alignment(halign, valign, orientation, style=style)
# make_pattern(bgcolor, style=style)
# return style
#
#
# class ScoExcelSheetExt(ScoExcelSheet):
# def __init__(self, sheet_name="feuille", default_style=None):
# ScoExcelSheet.__init__(self, sheet_name, default_style)
# self.cols_width = {}
# self.row_height = {}
# self.merged = []
# self.panes_frozen = False
# self.horz_split_pos = 0
# self.vert_split_pos = 0
#
# def set_panes(self, panes_frozen=True, horz_split_pos=0, vert_split_pos=0):
# self.panes_frozen = panes_frozen
# self.horz_split_pos = horz_split_pos
# self.vert_split_pos = vert_split_pos
#
# def set_cols_width(self, cols_width):
# self.cols_width = cols_width
#
# def set_row_height(self, row_height):
# self.row_height = row_height
#
# def add_merged(self, first_row, last_row, first_col, last_col, value, style):
# self.merged.append((first_row, last_row, first_col, last_col, value, style))
#
# def gen_workbook(self, wb=None):
# """Generates and returns a workbook from stored data.
# If wb, add a sheet (tab) to the existing workbook (in this case, returns None).
# """
# if wb == None:
# wb = Workbook() # Création du fichier
# sauvegarde = True
# else:
# sauvegarde = False
# ws0 = wb.add_sheet(self.sheet_name.decode(SCO_ENCODING))
# li = 0
# for l in self.cells:
# co = 0
# for c in l:
# # safety net: allow only str, int and float
# if type(c) == LongType:
# c = int(c) # assume all ScoDoc longs fits in int !
# elif type(c) not in (IntType, FloatType):
# c = str(c).decode(SCO_ENCODING)
#
# ws0.write(li, co, c, self.get_cell_style(li, co))
# co += 1
# li += 1
# for first_row, last_row, first_col, last_col, value, style in self.merged:
# ws0.write_merge(
# first_row,
# last_row,
# first_col,
# last_col,
# str(value).decode(SCO_ENCODING),
# style,
# )
# for col_no in range(len(self.cols_width)):
# width = self.cols_width[col_no]
# ws0.col(col_no).width = abs(width) * 110 / 3
# if width < 0:
# ws0.col(col_no).hidden = True
# row_styles = {}
# for row_no in range(len(self.row_height)):
# height = self.row_height[row_no]
# if height not in row_styles:
# fnt = Font()
# fnt.height = height * 12
# row_styles[height] = XFStyle()
# row_styles[height].font = fnt
# ws0.row(row_no).set_style(row_styles[height]) # Excel way
# ws0.row(row_no).height = height * 19 / 2 # Libre-Office compatibilité
# if self.panes_frozen:
# ws0.panes_frozen = self.panes_frozen
# ws0.horz_split_pos = self.vert_split_pos
# ws0.vert_split_pos = self.horz_split_pos
# if sauvegarde:
# return wb.savetostr()
# else:
# return None

View File

@ -107,10 +107,10 @@ def _build_menu_stats(formsemestre_id):
"enabled": True,
},
{
"title": "Documents Avis Poursuite Etudes (xp)",
"title": "Documents Avis Poursuite Etudes",
"endpoint": "notes.pe_view_sem_recap",
"args": {"formsemestre_id": formsemestre_id},
"enabled": True, # current_app.config["TESTING"] or current_app.config["DEBUG"],
"enabled": current_app.config["TESTING"] or current_app.config["DEBUG"],
},
{
"title": 'Table "débouchés"',
@ -398,6 +398,11 @@ def formsemestre_status_menubar(sem):
"endpoint": "notes.feuille_preparation_jury",
"args": {"formsemestre_id": formsemestre_id},
},
{
"title": "Générer feuille préparation Jury DUT",
"endpoint": "notes.feuille_preparation_jury_dut",
"args": {"formsemestre_id": formsemestre_id},
},
{
"title": "Saisie des décisions du jury",
"endpoint": "notes.formsemestre_recapcomplet",

0
app/scodoc/sco_pdf.py Executable file → Normal file
View File

View File

@ -0,0 +1,173 @@
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2019 Emmanuel Viennet. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
""" Excel file formatting
"""
# from sco_excel_add import *
import copy
from enum import IntFlag, Enum
from app.scodoc.sco_excel import excel_make_style
from app.scodoc.sco_excel_add import make_font, make_pattern, make_numfmt, make_borders
class CellBorder(IntFlag):
TOP = 1 << 0
BOTTOM = 1 << 1
LEFT = 1 << 2
RIGHT = 1 << 3
# Liste des modificateurs de format
class CellFormat(IntFlag):
# Mise en Forme usuelle
FMT_CAP_UE = 1 << 4 # UE capitalisée
FMT_MOY = 1 << 5 # Moyenne de semestre
FMT_UE = 1 << 6 # Acquisition d'UE sans validation semestre
# Mise en Forme sur le contenu
EMPHASE_PREC = 1 << 7 # Cause échec de semestre
EMPHASE_ATB = 1 << 8 # Cause échec de semestre
EMPHASE_UEACQ = 1 << 9 # Cause échec de semestre
EMPHASE_ATT = 1 << 10 # Cause échec de semestre
EMPHASE_ABS = 1 << 11 # Absences
EMPHASE_COMP = 1 << 12 # Cause échec de semestre
# Mise en forme numérique
PRECISE = 1 << 20 # Précision de l'affichage
GRAYED = 1 << 22 # Grisé horizontal
# Color palette at : https://groups.google.com/g/python-excel/c/cePI-ojUJfc/m/dH72A-rm6_gJ
class CellColor(Enum):
COLOR_PREC = "FAA76C" # TAN
COLOR_ATB = "CCCCFF" # LIGHT CORNFLOWER BLUE
COLOR_ATT = "FE8DB1" # LIGHT ORANGE
COLOR_COMP = "CCFFCC" # LIGHT GREEN
COLOR_UEACQ = "CCFFCC" # LIGHT GREEN
COLOR_ABS = "FFFF99" # LIGHT YELLOW
def format_note(valeur, warning, seuil, mini=True):
if seuil is not None:
if isinstance(valeur, (int, float)):
if mini:
diff = valeur - seuil
else:
diff = seuil - valeur
if -0.20 < diff < 0:
warning += CellFormat.PRECISE
return warning
class Formatter:
def __init__(self):
self.style_table = {}
self.last_rank = None
self.left_borders = []
self.right_borders = []
self.default_top = "none"
self.default_bottom = "none"
self.default_left = "none"
self.default_right = "none"
self.default_format = None
# def add_category(self, left, right):
# self.left_borders.append(left)
# self.right_borders.append(right)
def set_borders_default(self, left="none", top="none", bottom="none", right="none"):
self.default_bottom = bottom
self.default_left = left
self.default_right = right
self.default_top = top
def borders(self, li, co):
index = 0
index |= CellBorder.TOP if li == 0 else 0
index |= CellBorder.BOTTOM if self.last_rank and li == self.last_rank else 0
index |= CellBorder.LEFT if co in self.left_borders else 0
index |= CellBorder.RIGHT if co in self.right_borders else 0
return index
def get_style(self, index=0):
if index not in self.style_table:
border_enable = "filet"
if self.default_format:
style = copy.copy(self.default_format)
else:
style = excel_make_style()
make_font(
style=style,
font_name="Calibri",
font_size=9,
bold=(CellFormat.FMT_MOY & index),
uline=(CellFormat.FMT_CAP_UE & index),
)
make_borders(
style=style, left="none", right="none", top="filet", bottom="filet"
)
if index & CellFormat.EMPHASE_ATB:
make_pattern(style=style, bgcolor=CellColor.COLOR_ATB.value)
elif index & CellFormat.EMPHASE_ATT:
make_pattern(style=style, bgcolor=CellColor.COLOR_ATT.value)
elif index & CellFormat.EMPHASE_PREC:
make_pattern(style=style, bgcolor=CellColor.COLOR_PREC.value)
elif index & CellFormat.EMPHASE_COMP:
make_pattern(style=style, bgcolor=CellColor.COLOR_COMP.value)
elif index & CellFormat.EMPHASE_UEACQ:
make_pattern(style=style, bgcolor=CellColor.COLOR_UEACQ.value)
elif index & CellFormat.EMPHASE_ABS:
make_pattern(style=style, bgcolor=CellColor.COLOR_ABS.value)
# elif not index & GRAYED:
# make_pattern(style=style, bgcolor=0x43)
if index & (CellFormat.FMT_CAP_UE | CellFormat.FMT_UE | CellFormat.FMT_MOY):
if index & CellFormat.PRECISE:
make_numfmt("#0.00", style)
else:
make_numfmt("#0.0", style)
top = border_enable if index & CellBorder.TOP else self.default_top
bottom = border_enable if index & CellBorder.BOTTOM else self.default_bottom
left = border_enable if index & CellBorder.LEFT else self.default_left
right = border_enable if index & CellBorder.RIGHT else self.default_right
make_borders(style=style, top=top, left=left, right=right, bottom=bottom)
self.style_table[index] = style
return self.style_table[index]
def set_categories(self, categories, categories_desc):
col_no = 0
for c in categories:
self.left_borders.append(col_no)
col_no += len(categories_desc[c]["items"])
self.right_borders.append(col_no - 1)
def set_default_format(self, default_format):
self.default_format = default_format

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

0
app/static/libjs/bootstrap-3.1.1-dist/._css Executable file → Normal file
View File

0
app/static/libjs/bootstrap-3.1.1-dist/._fonts Executable file → Normal file
View File

0
app/static/libjs/bootstrap-3.1.1-dist/._js Executable file → Normal file
View File

0
app/templates/scolar/photos_import_files.txt Executable file → Normal file
View File

View File

@ -121,6 +121,7 @@ from app.scodoc import sco_placement
from app.scodoc import sco_poursuite_dut
from app.scodoc import sco_preferences
from app.scodoc import sco_prepajury
from app.scodoc import sco_prepajury_iuta
from app.scodoc import sco_pvjury
from app.scodoc import sco_pvpdf
from app.scodoc import sco_recapcomplet
@ -293,17 +294,13 @@ def formsemestre_bulletinetud(
if etudid:
etud = models.Identite.query.get_or_404(etudid)
elif code_nip:
etud = (
models.Identite.query.filter_by(code_nip=str(code_nip))
.filter_by(dept_id=formsemestre.dept_id)
.first_or_404()
)
etud = models.Identite.query.filter_by(
code_nip=str(code_nip)
).first_or_404()
elif code_ine:
etud = (
models.Identite.query.filter_by(code_ine=str(code_ine))
.filter_by(dept_id=formsemestre.dept_id)
.first_or_404()
)
etud = models.Identite.query.filter_by(
code_ine=str(code_ine)
).first_or_404()
else:
raise ScoValueError(
"Paramètre manquant: spécifier code_nip ou etudid ou code_ine"
@ -323,7 +320,6 @@ def formsemestre_bulletinetud(
formsemestre_id=formsemestre_id,
etudid=etudid,
format="json",
force_publishing=1, # pour ScoDoc lui même
),
sco=ScoData(),
)
@ -2312,6 +2308,11 @@ sco_publish(
sco_prepajury.feuille_preparation_jury,
Permission.ScoView,
)
sco_publish(
"/feuille_preparation_jury_dut",
sco_prepajury_iuta.feuille_preparation_jury_dut,
Permission.ScoView,
)
sco_publish(
"/formsemestre_archive",
sco_archives.formsemestre_archive,

View File

@ -753,9 +753,9 @@ sco_publish(
)
sco_publish(
"/formsemestre_partition_list",
sco_groups.formsemestre_partition_list,
Permission.ScoView,
"/formsemestre_partition_list",
sco_groups.formsemestre_partition_list,
Permission.ScoView,
)
sco_publish("/setGroups", sco_groups.setGroups, Permission.ScoView)

0
config.py Executable file → Normal file
View File

0
migrations/README Executable file → Normal file
View File

0
migrations/env.py Executable file → Normal file
View File

0
migrations/script.py.mako Executable file → Normal file
View File

0
misc/ArreteDUT2005.txt Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

0
misc/PublicationBulletins/Portail-LeHavre/fpdf.php Executable file → Normal file
View File

View File

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 214 B

After

Width:  |  Height:  |  Size: 214 B

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 219 B

After

Width:  |  Height:  |  Size: 219 B

0
misc/PublicationBulletins/Portail-LeHavre/index.php Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

0
misc/PublicationBulletins/Portail-LeHavre/jQuery/jquery.js vendored Executable file → Normal file
View File

View File

View File

View File

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 180 B

View File

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 178 B

View File

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 120 B

View File

Before

Width:  |  Height:  |  Size: 105 B

After

Width:  |  Height:  |  Size: 105 B

View File

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

View File

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

Before

Width:  |  Height:  |  Size: 101 B

After

Width:  |  Height:  |  Size: 101 B

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 180 B

After

Width:  |  Height:  |  Size: 180 B

View File

Before

Width:  |  Height:  |  Size: 178 B

After

Width:  |  Height:  |  Size: 178 B

View File

Before

Width:  |  Height:  |  Size: 120 B

After

Width:  |  Height:  |  Size: 120 B

View File

Before

Width:  |  Height:  |  Size: 105 B

After

Width:  |  Height:  |  Size: 105 B

View File

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

View File

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 110 B

View File

Before

Width:  |  Height:  |  Size: 119 B

After

Width:  |  Height:  |  Size: 119 B

View File

Before

Width:  |  Height:  |  Size: 101 B

After

Width:  |  Height:  |  Size: 101 B

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Some files were not shown because too many files have changed in this diff Show More