# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # ScoDoc # # Copyright (c) 1999 - 2024 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 # ############################################################################## """Page accueil département (liste des semestres, etc) """ from sqlalchemy import desc from flask import g, url_for, render_template from flask_login import current_user from flask_sqlalchemy.query import Query import app from app import log from app.models import FormSemestre, ScolarNews, ScoDocSiteConfig import app.scodoc.sco_utils as scu from app.scodoc.gen_tables import GenTable from app.scodoc.sco_permissions import Permission import app.scodoc.notesdb as ndb from app.scodoc import sco_modalites from app.scodoc import sco_preferences from app.scodoc import sco_users from app.views import ScoData def index_html(showcodes=0, showsemtable=0, export_table_formsemestres=False): "Page accueil département (liste des semestres)" showcodes = int(showcodes) showsemtable = int(showsemtable) or export_table_formsemestres # Liste tous les formsemestres du dept, le plus récent d'abord current_formsemestres = ( FormSemestre.query.filter_by(dept_id=g.scodoc_dept_id, etat=True) .filter(FormSemestre.modalite != "EXT") .order_by(desc(FormSemestre.date_debut)) ) locked_formsemestres = ( FormSemestre.query.filter_by(dept_id=g.scodoc_dept_id, etat=False) .filter(FormSemestre.modalite != "EXT") .order_by(desc(FormSemestre.date_debut)) ) formsemestres = ( FormSemestre.query.filter_by(dept_id=g.scodoc_dept_id) .filter(FormSemestre.modalite != "EXT") .order_by(desc(FormSemestre.date_debut)) ) if showsemtable: # table de tous les formsemestres table = _sem_table_gt( formsemestres, showcodes=showcodes, fmt="xlsx" if export_table_formsemestres else "html", ) if export_table_formsemestres: return table # cas spécial: on renvoie juste cette table html_table_formsemestres = table.html() else: html_table_formsemestres = None current_formsemestres_by_modalite, modalites = ( sco_modalites.group_formsemestres_by_modalite(current_formsemestres) ) passerelle_disabled = ScoDocSiteConfig.is_passerelle_disabled() return render_template( "scolar/index.j2", current_user=current_user, current_formsemestres=current_formsemestres, current_formsemestres_by_modalite=current_formsemestres_by_modalite, dept_name=sco_preferences.get_preference("DeptName"), emptygroupicon=scu.icontag( "emptygroupicon_img", title="Pas d'inscrits", border="0" ), formsemestres=formsemestres, groupicon=scu.icontag("groupicon_img", title="Inscrits", border="0"), html_table_formsemestres=html_table_formsemestres, icon_hidden="" if passerelle_disabled else scu.ICON_HIDDEN, icon_published="" if passerelle_disabled else scu.ICON_PUBLISHED, locked_formsemestres=locked_formsemestres, modalites=modalites, nb_locked=locked_formsemestres.count(), nb_user_accounts=sco_users.get_users_count(dept=g.scodoc_dept), page_title=f"ScoDoc {g.scodoc_dept}", Permission=Permission, scolar_news_summary=ScolarNews.scolar_news_summary_html(), showcodes=showcodes, showsemtable=showsemtable, sco=ScoData(), ) def _convert_formsemestres_to_dicts( formsemestres: Query, showcodes: bool, fmt: str = "html" ) -> list[dict]: """ """ if fmt == "html": # icon images: groupicon = scu.icontag("groupicon_img", title="Inscrits", border="0") emptygroupicon = scu.icontag( "emptygroupicon_img", title="Pas d'inscrits", border="0" ) lockicon = scu.icontag("lock32_img", title="verrouillé", border="0") else: groupicon = "X" emptygroupicon = "" lockicon = "X" # génère liste de dict sems = [] formsemestre: FormSemestre for formsemestre in formsemestres: nb_inscrits = len(formsemestre.inscriptions) formation = formsemestre.formation sem = { "anneescolaire": formsemestre.annee_scolaire(), "anneescolaire_str": formsemestre.annee_scolaire_str(), "bul_hide_xml": formsemestre.bul_hide_xml, "dateord": formsemestre.date_debut, "elt_annee_apo": formsemestre.elt_annee_apo, "elt_sem_apo": formsemestre.elt_sem_apo, "etapes_apo_str": formsemestre.etapes_apo_str(), "formation": f"{formation.acronyme} v{formation.version}", "_formation_target": url_for( "notes.ue_table", scodoc_dept=g.scodoc_dept, formation_id=formation.id, semestre_idx=formsemestre.semestre_id, ), "formsemestre_id": formsemestre.id, "groupicon": groupicon if nb_inscrits > 0 else emptygroupicon, "lockimg": lockicon, "modalite": formsemestre.modalite, "mois_debut": formsemestre.mois_debut(), "mois_fin": formsemestre.mois_fin(), "nb_inscrits": nb_inscrits, "responsable_name": formsemestre.responsables_str(), "semestre_id": formsemestre.semestre_id, "session_id": formsemestre.session_id(), "titre_num": formsemestre.titre_num(), "tmpcode": (f"{formsemestre.id}" if showcodes else ""), } sems.append(sem) return sems def _sem_table_gt(formsemestres: Query, showcodes=False, fmt="html") -> GenTable: """Table des semestres Utilise une datatables. """ sems = _style_sems( _convert_formsemestres_to_dicts(formsemestres, showcodes, fmt=fmt), fmt=fmt ) sems.sort( key=lambda s: ( -s["anneescolaire"], s["semestre_id"] if s["semestre_id"] > 0 else -s["semestre_id"] * 1000, s["modalite"], ) ) columns_ids = ["lockimg"] if not ScoDocSiteConfig.is_passerelle_disabled(): columns_ids.append("published") columns_ids += [ "dash_mois_fin", "semestre_id_n", "modalite", "titre_resp", "nb_inscrits", "formation", "etapes_apo_str", "elt_annee_apo", "elt_sem_apo", ] if showcodes: columns_ids = ("formsemestre_id",) + columns_ids html_class = "stripe cell-border compact hover order-column table_leftalign semlist" if current_user.has_permission(Permission.EditApogee): html_class += " apo_editable" tab = GenTable( titles={ "formsemestre_id": "id", "semestre_id_n": "S#", "modalite": "" if fmt == "html" else "Modalité", "mois_debut": "Début", "dash_mois_fin": "Année", "titre_resp": "Semestre", "nb_inscrits": "N", "etapes_apo_str": "Étape Apo.", "elt_annee_apo": "Elt. année Apo.", "elt_sem_apo": "Elt. sem. Apo.", "formation": "Formation", }, columns_ids=columns_ids, rows=sems, table_id="semlist", html_class_ignore_default=True, html_class=html_class, html_sortable=True, html_table_attrs=f""" data-apo_save_url="{url_for('notes.formsemestre_set_apo_etapes', scodoc_dept=g.scodoc_dept)}" data-elt_annee_apo_save_url="{url_for('notes.formsemestre_set_elt_annee_apo', scodoc_dept=g.scodoc_dept)}" data-elt_sem_apo_save_url="{url_for('notes.formsemestre_set_elt_sem_apo', scodoc_dept=g.scodoc_dept)}" """, html_with_td_classes=True, preferences=sco_preferences.SemPreferences(), ) return tab def _style_sems(sems: list[dict], fmt="html") -> list[dict]: """ajoute quelques attributs de présentation pour la table""" is_h = fmt == "html" if is_h: icon_published = scu.ICON_PUBLISHED icon_hidden = scu.ICON_HIDDEN else: icon_published = "publié" icon_hidden = "non publié" for sem in sems: status_url = url_for( "notes.formsemestre_status", scodoc_dept=g.scodoc_dept, formsemestre_id=sem["formsemestre_id"], ) sem["_groupicon_target"] = status_url sem["_formsemestre_id_class"] = "blacktt" sem["dash_mois_fin"] = ( (f"""{sem['anneescolaire_str']}""") if is_h else sem["anneescolaire_str"] ) sem["_dash_mois_fin_class"] = "datesem" sem["titre_resp"] = ( ( f"""{sem['titre_num']} ({sem['responsable_name']})""" ) if is_h else f"""{sem['titre_num']} ({sem["responsable_name"]})""" ) sem["published"] = icon_hidden if sem["bul_hide_xml"] else icon_published sem["_css_row_class"] = "css_S%d css_M%s" % ( sem["semestre_id"], sem["modalite"], ) sem["_semestre_id_class"] = "semestre_id" sem["_modalite_class"] = "modalite" if sem["semestre_id"] == -1: sem["semestre_id_n"] = "" else: sem["semestre_id_n"] = sem["semestre_id"] # pour édition codes Apogée: sem["_etapes_apo_str_td_attrs"] = ( f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['etapes_apo_str']}" """ ) sem["_elt_annee_apo_td_attrs"] = ( f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_annee_apo']}" """ ) sem["_elt_sem_apo_td_attrs"] = ( f""" data-oid="{sem['formsemestre_id']}" data-value="{sem['elt_sem_apo']}" """ ) return sems def delete_dept(dept_id: int) -> str: """Suppression irréversible d'un département et de tous les objets rattachés""" assert isinstance(dept_id, int) # Un peu complexe, merci JMP :) cnx = ndb.GetDBConnexion() cursor = cnx.cursor() try: # 1- Create temp tables to store ids reqs = [ "create temp table etudids_temp as select id from identite where dept_id = %(dept_id)s", """create temp table formsemestres_temp as select id from notes_formsemestre where dept_id = %(dept_id)s""", """create temp table moduleimpls_temp as select id from notes_moduleimpl where formsemestre_id in (select id from formsemestres_temp)""", """create temp table formations_temp as select id from notes_formations where dept_id = %(dept_id)s""", "create temp table tags_temp as select id from notes_tags where dept_id = %(dept_id)s", ] for r in reqs: log(f"delete_dept: {r}") cursor.execute(r, {"dept_id": dept_id}) # 2- Delete student-related informations # ordered list of tables etud_tables = [ "notes_notes", "group_membership", "billet_absence", "adresse", "absences", "notes_notes_log", "notes_moduleimpl_inscription", "itemsuivi", "notes_appreciations", "scolar_autorisation_inscription", "absences_notifications", "notes_formsemestre_inscription", "scolar_formsemestre_validation", "scolar_events", ] for table in etud_tables: log(f"delete from {table}") cursor.execute( f"delete from {table} where etudid in (select id from etudids_temp)" ) reqs = [ """delete from apc_validation_annee where referentiel_competence_id in (select id from apc_referentiel_competences where dept_id = %(dept_id)s)""", "delete from apc_referentiel_competences where dept_id = %(dept_id)s", "delete from sco_prefs where dept_id = %(dept_id)s", """delete from notes_semset_formsemestre where formsemestre_id in (select id from formsemestres_temp)""", """delete from notes_evaluation where moduleimpl_id in (select id from moduleimpls_temp)""", """delete from notes_modules_enseignants where moduleimpl_id in (select id from moduleimpls_temp)""", """delete from notes_formsemestre_uecoef where formsemestre_id in (select id from formsemestres_temp)""", """delete from notes_formsemestre_ue_computation_expr where formsemestre_id in (select id from formsemestres_temp)""", """delete from notes_formsemestre_responsables where formsemestre_id in (select id from formsemestres_temp)""", """delete from notes_moduleimpl where formsemestre_id in (select id from formsemestres_temp)""", """delete from notes_modules_tags where tag_id in (select id from tags_temp)""", "delete from notes_tags where dept_id = %(dept_id)s", "delete from notes_modules where formation_id in (select id from formations_temp)", """delete from notes_matieres where ue_id in (select id from notes_ue where formation_id in (select id from formations_temp))""", """delete from notes_formsemestre_etapes where formsemestre_id in (select id from formsemestres_temp)""", """delete from group_descr where partition_id in (select id from partition where formsemestre_id in (select id from formsemestres_temp))""", "delete from partition where formsemestre_id in (select id from formsemestres_temp)", """delete from notes_formsemestre_custommenu where formsemestre_id in (select id from formsemestres_temp)""", "delete from notes_ue where formation_id in (select id from formations_temp)", "delete from notes_formsemestre where dept_id = %(dept_id)s", "delete from scolar_news where dept_id = %(dept_id)s", "delete from notes_semset where dept_id = %(dept_id)s", "delete from notes_formations where dept_id = %(dept_id)s", "delete from itemsuivi_tags where dept_id = %(dept_id)s", "delete from identite where dept_id = %(dept_id)s", "delete from departement where id = %(dept_id)s", "drop table tags_temp", "drop table formations_temp", "drop table moduleimpls_temp", "drop table etudids_temp", "drop table formsemestres_temp", ] for r in reqs: log(f"delete_dept: {r}") cursor.execute(r, {"dept_id": dept_id}) except Exception as e: cnx.rollback() return str(e) finally: cnx.commit() app.clear_scodoc_cache() return ""