# -*- mode: python -*- # -*- coding: utf-8 -*- ############################################################################## # # Gestion scolarite IUT # # Copyright (c) 1999 - 2021 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 # ############################################################################## """Form. pour inscription rapide des etudiants d'un semestre dans un autre Utilise les autorisations d'inscription délivrées en jury. """ import datetime import notesdb as ndb import sco_utils as scu from notes_log import log from gen_tables import GenTable import sco_codes_parcours import sco_pvjury import sco_formsemestre import sco_formsemestre_inscriptions import sco_formsemestre import sco_groups import scolars from sco_exceptions import ScoValueError def list_authorized_etuds_by_sem(context, sem, delai=274): """Liste des etudiants autorisés à s'inscrire dans sem. delai = nb de jours max entre la date de l'autorisation et celle de debut du semestre cible. """ src_sems = list_source_sems(context, sem, delai=delai) inscrits = list_inscrits(context, sem["formsemestre_id"]) r = {} candidats = {} # etudid : etud (tous les etudiants candidats) nb = 0 # debug for src in src_sems: liste = list_etuds_from_sem(context, src, sem) liste_filtree = [] for e in liste: # Filtre ceux qui se sont déjà inscrit dans un semestre APRES le semestre src auth_used = False # autorisation deja utilisée ? etud = scolars.get_etud_info(etudid=e["etudid"], filled=True)[0] for isem in etud["sems"]: if ndb.DateDMYtoISO(isem["date_debut"]) >= ndb.DateDMYtoISO( src["date_fin"] ): auth_used = True if not auth_used: candidats[e["etudid"]] = etud liste_filtree.append(e) nb += 1 r[src["formsemestre_id"]] = { "etuds": liste_filtree, "infos": { "id": src["formsemestre_id"], "title": src["titreannee"], "title_target": "formsemestre_status?formsemestre_id=%s" % src["formsemestre_id"], }, } # ajoute attribut inscrit qui indique si l'étudiant est déjà inscrit dans le semestre dest. for e in r[src["formsemestre_id"]]["etuds"]: e["inscrit"] = inscrits.has_key(e["etudid"]) # Ajoute liste des etudiants actuellement inscrits for e in inscrits.values(): e["inscrit"] = True r[sem["formsemestre_id"]] = { "etuds": inscrits.values(), "infos": { "id": sem["formsemestre_id"], "title": "Semestre cible: " + sem["titreannee"], "title_target": "formsemestre_status?formsemestre_id=%s" % sem["formsemestre_id"], "comment": " actuellement inscrits dans ce semestre", "help": "Ces étudiants sont actuellement inscrits dans ce semestre. Si vous les décochez, il seront désinscrits.", }, } return r, inscrits, candidats def list_inscrits(context, formsemestre_id, with_dems=False): """Etudiants déjà inscrits à ce semestre { etudid : etud } """ if not with_dems: ins = context.Notes.do_formsemestre_inscription_listinscrits( formsemestre_id ) # optimized else: args = {"formsemestre_id": formsemestre_id} ins = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(context, args=args) inscr = {} for i in ins: etudid = i["etudid"] inscr[etudid] = scolars.get_etud_info(etudid=etudid, filled=True)[0] return inscr def list_etuds_from_sem(context, src, dst): """Liste des etudiants du semestre src qui sont autorisés à passer dans le semestre dst.""" target = dst["semestre_id"] dpv = sco_pvjury.dict_pvjury(context, src["formsemestre_id"]) if not dpv: return [] etuds = [ x["identite"] for x in dpv["decisions"] if target in [a["semestre_id"] for a in x["autorisations"]] ] return etuds def list_inscrits_date(context, sem): """Liste les etudiants inscrits dans n'importe quel semestre SAUF sem à la date de début de sem. """ cnx = ndb.GetDBConnexion() cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) sem["date_debut_iso"] = ndb.DateDMYtoISO(sem["date_debut"]) cursor.execute( """select I.etudid from notes_formsemestre_inscription I, notes_formsemestre S where I.formsemestre_id = S.formsemestre_id and I.formsemestre_id != %(formsemestre_id)s and S.date_debut <= %(date_debut_iso)s and S.date_fin >= %(date_debut_iso)s""", sem, ) return [x[0] for x in cursor.fetchall()] def do_inscrit(context, sem, etudids, REQUEST=None, inscrit_groupes=False): """Inscrit ces etudiants dans ce semestre (la liste doit avoir été vérifiée au préalable) En option: inscrit aux mêmes groupes que dans le semestre origine """ log("do_inscrit (inscrit_groupes=%s): %s" % (inscrit_groupes, etudids)) for etudid in etudids: sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( context, sem["formsemestre_id"], etudid, etat="I", REQUEST=REQUEST, method="formsemestre_inscr_passage", ) if inscrit_groupes: # Inscription dans les mêmes groupes que ceux du semestre d'origine, # s'ils existent. # (mise en correspondance à partir du nom du groupe, sans tenir compte # du nom de la partition: évidemment, cela ne marche pas si on a les # même noms de groupes dans des partitions différentes) etud = scolars.get_etud_info(etudid=etudid, filled=True)[0] log("cherche groupes de %(nom)s" % etud) # recherche le semestre origine (il serait plus propre de l'avoir conservé!) if len(etud["sems"]) < 2: continue prev_formsemestre = etud["sems"][1] sco_groups.etud_add_group_infos(context, etud, prev_formsemestre) cursem_groups_by_name = dict( [ (g["group_name"], g) for g in sco_groups.get_sem_groups(context, sem["formsemestre_id"]) if g["group_name"] ] ) # forme la liste des groupes présents dans les deux semestres: partition_groups = [] # [ partition+group ] (ds nouveau sem.) for partition_id in etud["partitions"]: prev_group_name = etud["partitions"][partition_id]["group_name"] if prev_group_name in cursem_groups_by_name: new_group = cursem_groups_by_name[prev_group_name] partition_groups.append(new_group) # inscrit aux groupes for partition_group in partition_groups: sco_groups.change_etud_group_in_partition( context, etudid, partition_group["group_id"], partition_group, REQUEST=REQUEST, ) def do_desinscrit(context, sem, etudids, REQUEST): log("do_desinscrit: %s" % etudids) for etudid in etudids: context.do_formsemestre_desinscription( etudid, sem["formsemestre_id"], REQUEST=REQUEST ) def list_source_sems(context, sem, delai=None): """Liste des semestres sources sem est le semestre destination """ # liste des semestres débutant a moins # de delai (en jours) de la date de fin du semestre d'origine. sems = sco_formsemestre.do_formsemestre_list(context) othersems = [] d, m, y = [int(x) for x in sem["date_debut"].split("/")] date_debut_dst = datetime.date(y, m, d) delais = datetime.timedelta(delai) for s in sems: if s["formsemestre_id"] == sem["formsemestre_id"]: continue # saute le semestre destination if s["date_fin"]: d, m, y = [int(x) for x in s["date_fin"].split("/")] date_fin = datetime.date(y, m, d) if date_debut_dst - date_fin > delais: continue # semestre trop ancien if date_fin > date_debut_dst: continue # semestre trop récent # Elimine les semestres de formations speciales (sans parcours) if s["semestre_id"] == sco_codes_parcours.NO_SEMESTRE_ID: continue # F = context.formation_list(args={"formation_id": s["formation_id"]})[0] parcours = sco_codes_parcours.get_parcours_from_code(F["type_parcours"]) if not parcours.ALLOW_SEM_SKIP: if s["semestre_id"] < (sem["semestre_id"] - 1): continue othersems.append(s) return othersems def formsemestre_inscr_passage( context, formsemestre_id, etuds=[], inscrit_groupes=False, submitted=False, dialog_confirmed=False, REQUEST=None, ): """Form. pour inscription des etudiants d'un semestre dans un autre (donné par formsemestre_id). Permet de selectionner parmi les etudiants autorisés à s'inscrire. Principe: - trouver liste d'etud, par semestre - afficher chaque semestre "boites" avec cases à cocher - si l'étudiant est déjà inscrit, le signaler (gras, nom de groupes): il peut être désinscrit - on peut choisir les groupes TD, TP, TA - seuls les etudiants non inscrits changent (de groupe) - les etudiants inscrit qui se trouvent décochés sont désinscrits - Confirmation: indiquer les étudiants inscrits et ceux désinscrits, le total courant. """ inscrit_groupes = int(inscrit_groupes) sem = sco_formsemestre.get_formsemestre(context, formsemestre_id) # -- check lock if sem["etat"] != "1": raise ScoValueError("opération impossible: semestre verrouille") header = html_sco_header.sco_header( context, REQUEST, page_title="Passage des étudiants" ) footer = html_sco_header.sco_footer(context, REQUEST) H = [header] if type(etuds) == type(""): etuds = etuds.split(",") # vient du form de confirmation auth_etuds_by_sem, inscrits, candidats = list_authorized_etuds_by_sem(context, sem) etuds_set = set(etuds) candidats_set = set(candidats) inscrits_set = set(inscrits) candidats_non_inscrits = candidats_set - inscrits_set inscrits_ailleurs = set(list_inscrits_date(context, sem)) def set_to_sorted_etud_list(etudset): etuds = [candidats[etudid] for etudid in etudset] etuds.sort(lambda x, y: cmp(x["nom"], y["nom"])) return etuds if submitted: a_inscrire = etuds_set.intersection(candidats_set) - inscrits_set a_desinscrire = inscrits_set - etuds_set else: a_inscrire = a_desinscrire = [] # log('formsemestre_inscr_passage: a_inscrire=%s' % str(a_inscrire) ) # log('formsemestre_inscr_passage: a_desinscrire=%s' % str(a_desinscrire) ) if not submitted: H += build_page( context, REQUEST, sem, auth_etuds_by_sem, inscrits, candidats_non_inscrits, inscrits_ailleurs, inscrit_groupes=inscrit_groupes, ) else: if not dialog_confirmed: # Confirmation if a_inscrire: H.append("
Cette page permet d'inscrire des étudiants dans le semestre destination %(titreannee)s, et d'en désincrire si besoin.
Les étudiants sont groupés par semestres d'origines. Ceux qui sont en caractères gras sont déjà inscrits dans le semestre destination. Ceux qui sont en gras et en rouge sont inscrits dans un autre semestre.
Au départ, les étudiants déjà inscrits sont sélectionnés; vous pouvez ajouter d'autres étudiants à inscrire dans le semestre destination.
Si vous dé-selectionnez un étudiant déjà inscrit (en gras), il sera désinscrit.
Aucune action ne sera effectuée si vous n'appuyez pas sur le bouton "Appliquer les modifications" !