1149 lines
41 KiB
Python
1149 lines
41 KiB
Python
# -*- coding: utf8 -*-
|
||
import re
|
||
from pyramid.response import Response,FileResponse
|
||
from pyramid.renderers import render, get_renderer
|
||
from pyramid.view import (
|
||
view_config,
|
||
forbidden_view_config,
|
||
)
|
||
from pyramid.security import (
|
||
remember,
|
||
forget,
|
||
)
|
||
from pyramid.httpexceptions import (
|
||
HTTPFound,
|
||
)
|
||
from ..security import groupfinder
|
||
from pyramid_mailer import get_mailer
|
||
from pyramid_mailer.message import Message, Attachment
|
||
|
||
from datetime import *
|
||
from dateutil.relativedelta import relativedelta
|
||
from email.utils import formataddr
|
||
from docutils.core import publish_parts
|
||
from time import strftime
|
||
from user_agents import parse
|
||
from markdown2 import Markdown
|
||
|
||
import math
|
||
import os.path
|
||
import subprocess
|
||
import pkg_resources
|
||
import tempfile
|
||
import transaction
|
||
import hashlib
|
||
import hmac
|
||
import json
|
||
from PIL import Image
|
||
import shutil
|
||
import locale
|
||
from datetime import datetime
|
||
import magic
|
||
from ..models.default import *
|
||
from ..models.reservation import *
|
||
|
||
|
||
def to_age(dob, type):
|
||
today = date.today()
|
||
age = relativedelta(today, dob)
|
||
if type == '>':
|
||
if age.years >= 0:
|
||
a = '%s ans %s mois' % (age.years, age.months)
|
||
else:
|
||
a = '???'
|
||
else:
|
||
if age.years < 0 or age.years < 0:
|
||
if age.years <= -1:
|
||
a = '%sa %sm' % (age.years, age.months)
|
||
else:
|
||
a = '%sm' % (age.months)
|
||
else:
|
||
a = ''
|
||
|
||
return a.replace('-', '')
|
||
|
||
|
||
def to_decimal(x):
|
||
import decimal
|
||
return decimal.Decimal(str(x))
|
||
|
||
|
||
def to_sha1(message):
|
||
return hashlib.sha1(message.encode('utf-8')).hexdigest()
|
||
|
||
|
||
def to_int(x):
|
||
try:
|
||
number = int(x.replace(',', '.'))
|
||
return number
|
||
except ValueError:
|
||
return 0
|
||
|
||
|
||
def to_euro(x):
|
||
"""Takes a float and returns 12 345,67 €"""
|
||
locale.setlocale(locale.LC_ALL, '')
|
||
return locale.currency(x, True, True)
|
||
|
||
|
||
def to_euroz(x):
|
||
"""Takes a float and returns 12 345,67 € if non zero"""
|
||
if x == 0:
|
||
return ""
|
||
else:
|
||
return to_euro(x)
|
||
|
||
|
||
def to_percent(x):
|
||
"""Takes a float and returns a string"""
|
||
return (u"%.2f " % x).replace('.', ',') + "%"
|
||
|
||
|
||
def to_date(date_text):
|
||
try:
|
||
madate = datetime.strptime(date_text, '%d/%m/%Y')
|
||
if madate.year >= 1900:
|
||
return madate
|
||
else:
|
||
return False
|
||
|
||
except ValueError:
|
||
return False
|
||
|
||
|
||
def to_time(date_text):
|
||
try:
|
||
madate = datetime.strptime(date_text, '%H:%M')
|
||
return madate
|
||
except ValueError:
|
||
return False
|
||
|
||
|
||
def isMinor(dob):
|
||
today = date.today()
|
||
age = relativedelta(today, dob)
|
||
if age.years < 18:
|
||
minor = True
|
||
else:
|
||
minor = False
|
||
return minor
|
||
|
||
|
||
def toSemaine(strDate):
|
||
chaine = strDate.replace(' Feb', ' Fév')
|
||
chaine = chaine.replace(' Mar', ' Mars')
|
||
chaine = chaine.replace(' Apr', ' Avr')
|
||
chaine = chaine.replace(' May', ' Mai')
|
||
chaine = chaine.replace(' Jun', ' Juin')
|
||
chaine = chaine.replace(' Jul', ' Juil')
|
||
chaine = chaine.replace(' Aug', ' Août')
|
||
chaine = chaine.replace(' Dec', ' Déc')
|
||
|
||
chaine = chaine.replace('Mon', 'Lun')
|
||
chaine = chaine.replace('Tue', 'Mar')
|
||
chaine = chaine.replace('Wed', 'Mer')
|
||
chaine = chaine.replace('Thu', 'Jeu')
|
||
chaine = chaine.replace('Fri', 'Ven')
|
||
chaine = chaine.replace('Sat', 'Sam')
|
||
chaine = chaine.replace('Sun', 'Dim')
|
||
|
||
return chaine
|
||
|
||
|
||
# - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
|
||
def envoyerMail(request, destinataires, objet, corps):
|
||
# lire l'adresse email de l'agence
|
||
logged_in = request.authenticated_userid
|
||
if logged_in is None:
|
||
# user anonyme
|
||
agence_email = request.registry.settings['monaem.admin_email']
|
||
else:
|
||
# user connecté, lire son numéro d'agence
|
||
agence = get_eleve_agence(request, logged_in)
|
||
agence_email = agence.email if agence else request.registry.settings['monaem.admin_email']
|
||
message = Message(subject=u"[MARIETTON] %s" % objet,
|
||
sender=agence_email,
|
||
recipients=destinataires,
|
||
html=corps)
|
||
|
||
mailer = get_mailer(request)
|
||
mailer.send_immediately(message, fail_silently=True)
|
||
|
||
|
||
@view_config(route_name='affiche_message', renderer='../templates/default/affiche_message.pt')
|
||
def affiche_message(request):
|
||
login = request.matchdict['login']
|
||
messages = request.session.pop_flash()
|
||
|
||
return {
|
||
'page_title': "Demande effectuée",
|
||
'login': login,
|
||
'messages': messages,
|
||
'url_identification': request.route_url('login_as', login=login)
|
||
}
|
||
|
||
|
||
@view_config(route_name='agence', renderer='../templates/default/agence.pt', permission='view')
|
||
def agence(request):
|
||
"""Mon agence"""
|
||
logged_in = request.authenticated_userid
|
||
# get agence
|
||
item = get_eleve_agence(request, logged_in)
|
||
|
||
return {
|
||
'page_title': "Mon agence MARIETTON",
|
||
'item': item,
|
||
}
|
||
|
||
|
||
@view_config(route_name='change_details', renderer='../templates/default/change_details.pt', permission='view')
|
||
def change_details(request):
|
||
url = request.route_url('change_details')
|
||
logged_in = request.authenticated_userid
|
||
|
||
member = get_eleves_by_code(request, logged_in)
|
||
|
||
if 'form.submitted' in request.params:
|
||
new_values = {}
|
||
for param, db_value in member.items():
|
||
if param in request.params and request.params[param] != db_value:
|
||
new_values[param] = request.params[param]
|
||
|
||
if new_values:
|
||
update_details(request, logged_in, new_values)
|
||
request.session.flash(u"Vos coordonnées ont été mises à jour avec succès.", 'success')
|
||
|
||
# si élève appartient à une agence
|
||
if member.AGENCE > 0:
|
||
# envoyer un message à la secrétaire
|
||
body = getMessageText(request, 'changeCoord', member.NOMPREN, logged_in, '', '', '')
|
||
|
||
agence_email = get_eleve_agence(request, logged_in).email
|
||
destinataires = [agence_email]
|
||
envoyerMail(request, destinataires, "Changement de coordonnées", body)
|
||
|
||
return HTTPFound(location=request.route_url('home'))
|
||
|
||
return {
|
||
'page_title': "Changer mes coordonnées",
|
||
'url': url,
|
||
'member': member,
|
||
}
|
||
|
||
|
||
@view_config(route_name='change_password', renderer='../templates/default/change_password.pt', permission='view')
|
||
def change_password(request):
|
||
url = request.route_url('change_password')
|
||
logged_in = request.authenticated_userid
|
||
message = ''
|
||
|
||
member = get_eleves_by_code(request, logged_in)
|
||
|
||
if 'form.submitted' in request.params:
|
||
old_password = request.params['old_password']
|
||
new_password = request.params['new_password1']
|
||
new_password2 = request.params['new_password2']
|
||
if len(new_password) >= 8 and len(new_password) <= 20:
|
||
if re.match(r'^(?=.*\d)(?=.*[!@#$%^&*\_\-\.\+,;\:\\/§à\]\[\?\{\}])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z!@#$%^&*\_\-\.\+,;\:\\/§à\]\[\?\{\}]{8,}$',new_password):
|
||
if new_password == new_password2 :
|
||
if member.mdp_hash == to_sha1(old_password):
|
||
update_password(request, logged_in, new_password)
|
||
request.session.flash(u"Votre mot de passe a été mis à jour avec succès.", 'success')
|
||
return HTTPFound(location=request.route_url('home'))
|
||
else:
|
||
message = "Le mot de passe fourni est incorrect."
|
||
else:
|
||
message = "Le mot de passe et sa confirmation ne sont pas identiques."
|
||
else:
|
||
message = "Le mot de passe doit contenir au minimum une lettre, un nombre,un majuscule, un minuscle, et un caractère speciaux."
|
||
else:
|
||
message = "La longueur du mot de passe n'est pas respectée, minimum 8, maximum 20."
|
||
return {
|
||
'page_title': "Changer mon mot de passe",
|
||
'url': url,
|
||
'member': member,
|
||
'message': message,
|
||
}
|
||
|
||
|
||
@view_config(route_name='date_examen', renderer='../templates/default/date_examen.pt', permission='view')
|
||
def date_examen(request):
|
||
""" Date examen view """
|
||
logged_in = request.authenticated_userid
|
||
item = get_date_examen(request, logged_in)
|
||
|
||
return {
|
||
'page_title': "Prochaine date d'examen",
|
||
'item': item,
|
||
}
|
||
|
||
|
||
@view_config(route_name='email_password', renderer='../templates/default/email_password.pt')
|
||
def email_password(request):
|
||
url = request.route_url('email_password')
|
||
message = ''
|
||
login = ''
|
||
date_naissance = ''
|
||
|
||
if 'form.submitted' in request.params:
|
||
login = request.params['login']
|
||
date_naissance = request.params['date_naissance']
|
||
member = get_eleves_by_date_nais(request, login, date_naissance)
|
||
if member:
|
||
if member.email:
|
||
lien = update_membre_mdp_oublie(request, login)
|
||
# Fabrication du corps du Message
|
||
body = getMessageText(request, 'emailPassword', member.NOMPREN, lien, '', '', '')
|
||
|
||
destinataires = [member.email]
|
||
envoyerMail(request, destinataires, "Oubli de mot de passe", body)
|
||
request.session.flash(
|
||
u"Le lien permettant de redéfinir votre mot de passe vous a été envoyé à l'adresse : %s." % member.email,
|
||
'success')
|
||
return HTTPFound(location=request.route_url('affiche_message', login=login))
|
||
else:
|
||
message = "L'adresse e-mail de cet élève n'est pas renseignée. Contactez votre agence."
|
||
else:
|
||
message = "Aucun élève trouvé avec ce code et cette date de naissance. Veuillez réessayer."
|
||
|
||
return {
|
||
'page_title': "Mot de passe oublié ?",
|
||
'url': url,
|
||
'message': message,
|
||
'login': login,
|
||
'date_naissance': date_naissance,
|
||
}
|
||
|
||
|
||
@view_config(route_name='email_code', renderer='../templates/default/email_code.pt')
|
||
def email_code(request):
|
||
url = request.route_url('email_code')
|
||
message = ''
|
||
|
||
if 'form.submitted' in request.params:
|
||
name = request.params['name']
|
||
forname = request.params['forname']
|
||
birthday = request.params['birthday']
|
||
member = get_eleves_by_name_date_nais(request, name, forname, birthday)
|
||
if not member:
|
||
message = "Aucun utilisateur trouvé avec ce nom, prenom et cette date de naissance. Veuillez réessayer."
|
||
else:
|
||
# a member has been found
|
||
if member.email:
|
||
# Fabrication du corps du Message
|
||
body = getMessageText(request, 'emailCode', member.NOMPREN, member.CD_CLI, '', '', '')
|
||
|
||
destinataires = [member.email]
|
||
envoyerMail(request, destinataires, "Oubli de code élève", body)
|
||
request.session.flash(u"Votre code élève vous a été envoyé à l'adresse : %s." % member.email)
|
||
return HTTPFound(location=request.route_url('affiche_message', login=member.CD_CLI))
|
||
else:
|
||
message = "L'adresse e-mail de ce compte n'est pas renseignée. Veuillez contacter votre agence."
|
||
|
||
return {
|
||
'page_title': "Code élève oublié ?",
|
||
'url': url,
|
||
'message': message,
|
||
}
|
||
@view_config(route_name='stages_reservation', renderer='../templates/default/stages_reservation.pt', permission='view')
|
||
def stages_reservation(request):
|
||
|
||
std = {
|
||
'POINT' : {
|
||
'title' : "RECUPERATION DE POINTS",
|
||
'link' : 2763
|
||
},
|
||
'PEM125' : {
|
||
'title' : "PRISE EN MAIN 125",
|
||
'link' : 2765
|
||
},
|
||
'PASSERELLE' : {
|
||
'title' : 'PASSERELLE A2 à A',
|
||
'link' : 2766
|
||
},
|
||
'B96' : {
|
||
'title':'B96',
|
||
'link' : 2786
|
||
}
|
||
}
|
||
logged_in = request.authenticated_userid
|
||
url = request.route_url('stages_reservation')
|
||
|
||
eleve = get_eleves_by_code(request, logged_in)
|
||
permis = eleve.PERMIS_DEMANDE
|
||
stages = get_stages_by_type(request, eleve.FORMULE,None,15)
|
||
|
||
if 'form.submitted' in request.params:
|
||
params = dict(request.params)
|
||
cd_cli = logged_in
|
||
new_stage = get_stage_by_id(request, params['stage_id'])
|
||
if new_stage.dispo <= 0:
|
||
request.session.flash(u"Ce stage n’est plus disponible", 'danger')
|
||
return HTTPFound(location=request.route_url('stages_reserves'))
|
||
else:
|
||
debut_stage = ins_stage_eleve(request, eleve.FORMULE, new_stage.stage_id, cd_cli, eleve.NOM, eleve.PRENOM)
|
||
if debut_stage != None:
|
||
# si déjà inscrit, retourne aux dispo
|
||
request.session.flash(u"Vous êtes déjà inscrit(e) au stage du %s." % debut_stage.strftime("%d-%m-%Y"), 'danger')
|
||
else:
|
||
nompren = "%s %s %s" % (eleve.CIVILITE, eleve.NOM, eleve.PRENOM)
|
||
body = getConfirmText(request, eleve.FORMULE, nompren, cd_cli,
|
||
'%s au %s à %s' % (new_stage.debut.strftime("%d-%m-%Y"), new_stage.fin.strftime("%d-%m-%Y"), new_stage.debut.strftime("%Hh%M")),
|
||
new_stage.lieu1, new_stage.lieu2)
|
||
|
||
# envoyer un message à l'élève et la secrétaire
|
||
agence_email = get_eleve_agence(request, cd_cli).email
|
||
destinataires = [eleve.email, agence_email,]
|
||
envoyerMail(request, destinataires, "Votre réservation pour le stage de %s" %std[eleve.FORMULE]['title'], body)
|
||
|
||
request.session.flash(u"Vous avez réservé votre date de stage le %s à %s " % (new_stage.debut.date().strftime("%d-%m-%Y"), new_stage.fin.strftime("%d-%m-%Y")), 'success')
|
||
|
||
return HTTPFound(location=request.route_url('home'))
|
||
return {
|
||
'eleve': eleve,
|
||
'message': "",
|
||
'link': std[eleve.FORMULE]['link'],
|
||
'stages': stages,
|
||
'url': url,
|
||
'page_title': "Mon espace",
|
||
}
|
||
|
||
|
||
@view_config(route_name='stages_dates', renderer='../templates/default/stages_dates.pt', permission='view')
|
||
def stages_dates(request):
|
||
logged_in = request.authenticated_userid
|
||
url = request.route_url('stages_dates')
|
||
|
||
eleve = get_eleves_by_code(request, logged_in)
|
||
|
||
items = get_eleve_stage(request, logged_in)
|
||
|
||
permis = eleve.PERMIS_DEMANDE
|
||
|
||
std = {
|
||
'POINT' : {
|
||
'title' : "RECUPERATION DE POINTS",
|
||
'link' : 2763
|
||
},
|
||
'PEM125' : {
|
||
'title' : "PRISE EN MAIN 125",
|
||
'link' : 2765
|
||
},
|
||
'PASSERELLE' : {
|
||
'title' : 'PASSERELLE A2 à A',
|
||
'link' : 2766
|
||
},
|
||
'B96' : {
|
||
'title':'B96',
|
||
'link' : 2786
|
||
}
|
||
}
|
||
diff = False
|
||
|
||
nbdaysbefore_stage = 15
|
||
stages = []
|
||
if items:
|
||
stage = items[0]
|
||
debut_en_clair = 'Il commence le %s.' % stage.debut_en_clair
|
||
lieu_stage = 'VAUGNERAY'
|
||
if permis[:1] == 'A': # and stage.date_debut < datetime(2016,11,20):
|
||
debut_en_clair = ''
|
||
if eleve.FORMULE == 'POINT':
|
||
if stage.groupe == 'A':
|
||
lieu_stage = 'CHARPENNES'
|
||
|
||
stage_startdate = datetime.strptime(str(stage.stage_debut), '%d-%m-%Y').date()
|
||
datenow = datetime.now().date()
|
||
nbdaysbefore_stage = stage_startdate - datenow
|
||
if stage.debut_en_clair:
|
||
diff = nbdaysbefore_stage.days > 1 and eleve.FORMULE in ['B96', 'PEM125', 'PASSERELLE', 'POINT']
|
||
|
||
else:
|
||
stage = items
|
||
debut_en_clair = ''
|
||
lieu_stage = ''
|
||
|
||
stages = get_stages_by_type(request, eleve.FORMULE,stage_startdate.strftime('%Y-%m-%d'),nbdaysbefore_stage.days)
|
||
|
||
if 'form.submitted' in request.params:
|
||
params = dict(request.params)
|
||
cd_cli = logged_in
|
||
new_stage = get_stage_by_id(request, params['stage_id'])
|
||
if items:
|
||
stage = items[0]
|
||
else:
|
||
stage = items
|
||
diffdate = new_stage.debut.date() - datetime.strptime(str(stage.stage_debut), '%d-%m-%Y').date()
|
||
if diffdate.days == 0:
|
||
request.session.flash(u"Vous êtes déjà inscrit(e) au stage du %s." % stage.stage_debut, 'danger')
|
||
return HTTPFound(location=request.route_url('stages_dates'))
|
||
else:
|
||
stage_ligne = dict(get_stage_ligne_by_cd_cli(request, cd_cli, stage.groupe))
|
||
# Delete stage_ligne
|
||
query = """ CALL spDel_PLA_STAGE_LIGNES(:type,:semaine,:groupe,:cd_cli)"""
|
||
request.dbsession.execute(query, {'type': stage_ligne['TYPE'], 'semaine': stage_ligne['SEMAINE'], 'groupe': stage_ligne['GROUPE'], "cd_cli": stage_ligne['CD_CLI']})
|
||
debut_stage = ins_stage_eleve(request, eleve.FORMULE, new_stage.stage_id, cd_cli, eleve.NOM, eleve.PRENOM)
|
||
if debut_stage != None:
|
||
# si déjà inscrit, retourne aux dispo
|
||
request.session.flash(u"Vous êtes déjà inscrit(e) au stage du %s." % debut_stage.strftime("%d-%m-%Y"), 'danger')
|
||
else:
|
||
nompren = "%s %s %s" % (eleve.CIVILITE, eleve.NOM, eleve.PRENOM)
|
||
body = getConfirmText(request, eleve.FORMULE, nompren, cd_cli,
|
||
'%s au %s à %s' % (new_stage.debut.strftime("%d-%m-%Y"), new_stage.fin.strftime("%d-%m-%Y"), new_stage.debut.strftime("%Hh%M")),
|
||
new_stage.lieu1, new_stage.lieu2)
|
||
|
||
# envoyer un message à l'élève et la secrétaire
|
||
agence_email = get_eleve_agence(request, cd_cli).email
|
||
destinataires = [eleve.email, agence_email,]
|
||
envoyerMail(request, destinataires, "Votre réservation pour le stage de %s" %std[eleve.FORMULE]['title'], body)
|
||
request.session.flash(u"Vous avez modifié votre date de stage le %s à %s " % (new_stage.debut.date().strftime("%d-%m-%Y"), new_stage.fin.strftime("%d-%m-%Y")), 'success')
|
||
|
||
return HTTPFound(location=request.route_url('home'))
|
||
|
||
return {
|
||
'eleve': eleve,
|
||
'message': "",
|
||
'debut_en_clair': debut_en_clair,
|
||
'stage': stage,
|
||
'lieu_stage': lieu_stage,
|
||
'link': std[eleve.FORMULE]['link'],
|
||
'stages': stages,
|
||
'url': url,
|
||
'diff': diff,
|
||
'page_title': "Mon espace",
|
||
}
|
||
|
||
|
||
@view_config(route_name='home', renderer='../templates/default/home.pt', permission='view')
|
||
def home(request):
|
||
"""Home view"""
|
||
logged_in = request.authenticated_userid
|
||
url = request.route_url('home')
|
||
|
||
eleve = get_eleves_by_code(request, logged_in)
|
||
permis = eleve.PERMIS_DEMANDE
|
||
suivi_list = ['B', 'B78', 'A1', 'A2', 'POINT', 'AL', 'A','AM']
|
||
if permis in suivi_list:
|
||
hasSuivi = True
|
||
else:
|
||
hasSuivi = False
|
||
|
||
# lire le carnet de rendez-vous
|
||
nb_rdv = len(get_rdv_by_code(request, logged_in))
|
||
# lire les justifs
|
||
justifs = get_eleve_docs(request, logged_in, 'JUST')
|
||
docs = get_eleve_docs(request, logged_in, 'DOC')
|
||
diff = False
|
||
items = get_eleve_stage(request, logged_in)
|
||
if items:
|
||
stage = items[0]
|
||
debut_en_clair = 'Il commence le %s.' % stage.debut_en_clair
|
||
|
||
lieu_stage = 'VAUGNERAY'
|
||
if permis[:1] == 'A': # and stage.date_debut < datetime(2016,11,20):
|
||
debut_en_clair = ''
|
||
if eleve.FORMULE == 'POINT':
|
||
if stage.groupe == 'A':
|
||
lieu_stage = 'CHARPENNES'
|
||
if stage['type'] == 'B':
|
||
if stage['groupe'] == 'J':
|
||
lieu_stage = 'VAISE'
|
||
elif stage['groupe'] == 'K' :
|
||
lieu_stage = 'CHARPENNES'
|
||
elif stage['groupe'] == 'L' :
|
||
lieu_stage = "PRESQU’ILE"
|
||
|
||
|
||
if stage.debut_en_clair:
|
||
startedDateStage = datetime.strptime(str(stage.stage_debut), '%d-%m-%Y').date()
|
||
dateNow = datetime.now().date()
|
||
diffDate = startedDateStage - dateNow
|
||
diff = diffDate.days > 1 and eleve.FORMULE in ['B96', 'PEM125', 'PASSERELLE', 'POINT']
|
||
|
||
else:
|
||
stage = items
|
||
debut_en_clair = ''
|
||
lieu_stage = ''
|
||
|
||
examen = get_date_examen(request, logged_in)
|
||
|
||
# lire le compte
|
||
items = get_eleve_cpt_extrait(request, logged_in)
|
||
# calculer le solde de l'élève
|
||
sum_to_pay = 0
|
||
sum_paid = 0
|
||
for item in items:
|
||
sum_to_pay += float(item.DEBIT)
|
||
sum_paid += float(item.CREDIT)
|
||
solde = sum_to_pay - eleve.encours_societe - sum_paid
|
||
|
||
# get date de fin code
|
||
dates = get_dates_fin_validite(request, logged_in)
|
||
if dates:
|
||
date_fin_code = dates[0].date_fin_code
|
||
date_fin_vm = dates[0].date_fin_vm
|
||
else:
|
||
date_fin_code = None
|
||
date_fin_vm = None
|
||
|
||
# Lire toutes les FAQS sauf les 'INTERNE'
|
||
faqs = get_faqs(request, -1)
|
||
|
||
# calcul des clés élève
|
||
d = date.today()
|
||
# calculer le jour de l'année d'auj
|
||
yearday = (d - date(d.year, 1, 1)).days + 1
|
||
keyE = int(yearday * d.year / d.day * eleve.CD_CLI)
|
||
param_suivi = 'codeE=%s&key=%s&En=%s&MnR=%s&filiere=%s&agence=%s&permis=%s&formule=%s' % (
|
||
str(eleve.CD_CLI), keyE, eleve.NOMPREN, eleve.CD_MON, eleve.filiere, eleve.AGENCE, eleve.PERMIS_DEMANDE,
|
||
eleve.FORMULE)
|
||
|
||
suivi_pedago_list = ['CE', 'C', 'D', 'DE', 'BE', 'BEPCA', 'C1', 'D1', 'GL', 'B96']
|
||
if permis in suivi_pedago_list:
|
||
hasOutilPedago = True
|
||
else:
|
||
hasOutilPedago = False
|
||
|
||
return {
|
||
'page_title': "Mon espace",
|
||
'nb_rdv': nb_rdv,
|
||
'stage': stage,
|
||
'examen': examen,
|
||
'faqs': faqs,
|
||
'eleve': eleve,
|
||
'reservation' : eleve.FORMULE in ['B96', 'PEM125', 'PASSERELLE', 'POINT'],
|
||
'today': strftime("%d/%m/%Y"),
|
||
'solde': solde,
|
||
'remain_to_pay': to_euro(solde * -1),
|
||
'date_fin_code': date_fin_code,
|
||
'date_fin_vm': date_fin_vm,
|
||
'has_email': bool(eleve.email),
|
||
'debut_en_clair': debut_en_clair,
|
||
'lieu_stage': lieu_stage,
|
||
'hasSuivi': hasSuivi,
|
||
'justifs': justifs,
|
||
'docs': docs,
|
||
'param_suivi': param_suivi,
|
||
'hasOutilPedago': hasOutilPedago,
|
||
'diff': diff,
|
||
'logged_in': str(logged_in)
|
||
}
|
||
|
||
|
||
@view_config(route_name='fiche_inscription', renderer='../templates/default/fiche_inscription.pt', permission='view')
|
||
def fiche_inscription(request):
|
||
""" Fiche inscription view """
|
||
logged_in = request.authenticated_userid
|
||
eleve = get_eleves_by_code(request, logged_in)
|
||
return {
|
||
'page_title': "Fiche d'inscription",
|
||
'item': eleve,
|
||
}
|
||
|
||
|
||
@view_config(route_name='login', renderer='../templates/default/login.pt', permission='view')
|
||
@view_config(route_name='login_as', renderer='../templates/default/login.pt', permission='view')
|
||
@forbidden_view_config(renderer='../templates/default/login.pt')
|
||
def login(request):
|
||
current_route_path = request.current_route_path()
|
||
if 'login_as' in current_route_path:
|
||
login = request.matchdict['login']
|
||
login_url = request.route_url('login_as', login=login)
|
||
else:
|
||
login = ''
|
||
login_url = request.route_url('login')
|
||
|
||
referrer = request.url
|
||
if referrer == login_url:
|
||
referrer = '/' # never use the login form itself as came_from
|
||
|
||
came_from = request.params.get('came_from', referrer)
|
||
|
||
message = ''
|
||
password = ''
|
||
|
||
if 'form.submitted' in request.params:
|
||
login = request.params['login']
|
||
password = request.params['password']
|
||
record = get_eleves_by_code(request, login)
|
||
if record:
|
||
# controler que la fiche n'est pas cloturee
|
||
if record.STATUT < 10:
|
||
# On encode le password pour ne plus avoir de plantage avec les "é"
|
||
if (record.mdp_hash == to_sha1(password)):
|
||
# get user agent string from request
|
||
ua_string = request.user_agent
|
||
user_agent = parse(ua_string)
|
||
|
||
device = str(user_agent).split('/')
|
||
update_last_connection(request, login, device[0])
|
||
|
||
# force le commit car il ne se fait pas automatiquement après l'update
|
||
transaction.commit()
|
||
|
||
headers = remember(request, login)
|
||
return HTTPFound(location=came_from, headers=headers)
|
||
else:
|
||
message = "Le code élève ou le mot de passe est incorrect. Identification échouée."
|
||
else:
|
||
message = "Votre espace client a été clôturé. Accès refusé."
|
||
else:
|
||
message = "Le code élève ou le mot de passe est incorrect. Identification échouée."
|
||
|
||
return {
|
||
'page_title': "Se connecter",
|
||
'message': message,
|
||
'url': login_url,
|
||
'came_from': came_from,
|
||
'login': login,
|
||
'password': password,
|
||
}
|
||
|
||
|
||
@view_config(route_name='logout')
|
||
def logout(request):
|
||
headers = forget(request)
|
||
request.session.flash(u"Vous avez bien été déconnecté.", 'success')
|
||
return HTTPFound(location=request.route_url('login', login=''),
|
||
headers=headers)
|
||
|
||
|
||
@view_config(route_name='connecter_a', permission='manage')
|
||
def connecter_a(request):
|
||
# paramètre fourni ?
|
||
login = request.matchdict["login"]
|
||
if len(login) > 0:
|
||
request.session.invalidate()
|
||
headers = forget(request)
|
||
headers = remember(request, login)
|
||
return HTTPFound(location="/", headers=headers)
|
||
else:
|
||
return HTTPFound(location="/")
|
||
|
||
|
||
@view_config(route_name='redefinir_mdp', renderer='..//templates/default/redefinir_mdp.pt')
|
||
def redefinir_mdp(request):
|
||
lien = request.matchdict["lien"]
|
||
# tester si le champ "motdepasse_oublie" est encore valide
|
||
message = ''
|
||
if is_lien_mdp_oublie(request, lien) == True:
|
||
membre = get_mdp_oublie_infos(request, lien)
|
||
if 'form.submitted' in request.params:
|
||
new_password = request.params['new_password1']
|
||
if len(new_password) >= 8 and len(new_password) <= 20:
|
||
if re.match(r'^(?=.*\d)(?=.*[!@#$%^&*\_\-\.\+,;\:\\/§à\]\[\?\{\}])(?=.*[a-z])(?=.*[A-Z])[0-9a-zA-Z!@#$%^&*\_\-\.\+,;\:\\/§à\]\[\?\{\}]{8,}$',new_password):
|
||
new_password2 = request.params['new_password2']
|
||
if new_password == new_password2 :
|
||
update_password(request, membre.CD_CLI, new_password)
|
||
request.session.flash(u"Votre mot de passe a été mis à jour avec succès.", 'success')
|
||
return HTTPFound(location=request.route_url('login'))
|
||
else:
|
||
message = "Le mot de passe et sa confirmation ne sont pas identiques."
|
||
else:
|
||
message = "Le mot de passe doit contenir au minimum une lettre, un nombre,un majuscule, un minuscle, et un caractère speciaux."
|
||
else:
|
||
message = "La longueur du mot de passe n'est pas respectée, minimum 8, maximum 20."
|
||
else:
|
||
return HTTPFound(location=request.route_url('login'))
|
||
return {
|
||
'page_title': "Redéfinir le mot de passe",
|
||
'message': message,
|
||
}
|
||
|
||
|
||
@view_config(route_name='show_iframe', renderer='../templates/default/show_iframe.pt', permission='view')
|
||
def show_iframe(request):
|
||
param = request.matchdict['param']
|
||
logged_in = request.authenticated_userid
|
||
eleve = get_eleves_by_code(request, logged_in)
|
||
|
||
if param == 'suivi':
|
||
# calcul des clés élève
|
||
d = date.today()
|
||
# calculer le jour de l'année d'auj
|
||
yearday = (d - date(d.year, 1, 1)).days + 1
|
||
keyE = int(yearday * d.year / d.day * eleve.CD_CLI)
|
||
param = 'codeE=%s&key=%s&En=%s&MnR=%s&filiere=%s&agence=%s&permis=%s&formule=%s' % (
|
||
str(eleve.CD_CLI), keyE, eleve.NOMPREN, eleve.CD_MON, eleve.filiere, eleve.AGENCE, eleve.PERMIS_DEMANDE,
|
||
eleve.FORMULE)
|
||
iframe_src = "https://www.suivi-eleve.marietton.com/suivi.php?%s" % param
|
||
else:
|
||
# videos pédagogiques
|
||
param = 'codeE=%s&filiere=%s&agence=%s' % (str(eleve.CD_CLI), eleve.filiere, eleve.AGENCE)
|
||
iframe_src = "https://suivi-eleve.marietton.com/contenu-pedago/index.php?%s" % param
|
||
|
||
return {
|
||
'page_title': "",
|
||
'iframe_src': iframe_src,
|
||
}
|
||
|
||
|
||
@view_config(route_name='faq_view', renderer='../templates/default/faq_view.pt')
|
||
def faq_view(request):
|
||
faq_id = request.matchdict['faq_id']
|
||
|
||
faq = get_faqs(request, faq_id)
|
||
intitule = faq.intitule
|
||
# insèrer le path de static/img
|
||
img_path = 'image:: %s/static/img/' % request.application_url
|
||
|
||
texte = faq.texte.replace('image:: static/img/', img_path)
|
||
# convertir reST en HTML
|
||
texte = publish_parts(texte, writer_name='html')['html_body']
|
||
return {
|
||
'page_title': intitule,
|
||
'texte': texte,
|
||
'faq_id': faq_id,
|
||
}
|
||
|
||
|
||
@view_config(route_name='member_search', renderer='../templates/default/member_search.pt', permission='manage')
|
||
def member_search(request):
|
||
url = request.route_url('member_search')
|
||
message = ''
|
||
members = []
|
||
name = ''
|
||
if 'form.submitted' in request.params:
|
||
name = request.params['name']
|
||
members = get_eleves_by_name(request, name)
|
||
if len(members) == 0:
|
||
message = "Elève non trouvé : %s" % name
|
||
|
||
return {
|
||
'page_title': "Rechercher un élève",
|
||
'url': url,
|
||
'message': message,
|
||
'members': members,
|
||
'name': name,
|
||
}
|
||
|
||
|
||
@view_config(route_name='ajax_dept_nais')
|
||
def ajax_dept_nais(request):
|
||
recherche = request.GET['recherche']
|
||
|
||
# lire les departements commencant par
|
||
items = get_departements(request, recherche)
|
||
|
||
liste = []
|
||
for row in items:
|
||
d = row.libelle + " | " + row.code
|
||
liste.append(d)
|
||
|
||
return Response(json.dumps(liste))
|
||
|
||
|
||
@view_config(route_name='ajax_codepostal')
|
||
def ajax_codepostal(request):
|
||
recherche = request.GET['recherche']
|
||
|
||
# lire les codes postaux commencant par
|
||
items = get_codespostaux(request, recherche)
|
||
|
||
liste = []
|
||
for row in items:
|
||
d = row.code_postal + " - " + row.libelle
|
||
liste.append(d)
|
||
|
||
return Response(json.dumps(liste))
|
||
|
||
|
||
def getMessageText(request, ref, nomEleve, codeEleve, dateRDV, Lieu1RDV, Lieu2RDV):
|
||
if ref == 'emailPassword':
|
||
body = """
|
||
<p>Bonjour %s,</p>
|
||
<p>Vous avez oublié votre mot de passe. Par mesure de sécurité, nous vous demandons de bien vouloir le réinitialiser en cliquant sur ce lien :</p>
|
||
<p>%s</p>
|
||
<p>Ce lien ne sera valable que pendant 48 heures.</p>
|
||
|
||
""" % (nomEleve, request.route_url('redefinir_mdp', lien=codeEleve))
|
||
|
||
elif ref == 'emailCode':
|
||
body = """
|
||
<p>Bonjour %s,</p>
|
||
<p>Pour faire suite à votre demande, voici le code élève de votre compte MARIETTON : %s</p>
|
||
<p>Merci de bien vouloir le mémoriser pour une connexion ultérieure.</p>
|
||
|
||
""" % (nomEleve, codeEleve)
|
||
|
||
elif ref == 'annuleRDV':
|
||
body = """
|
||
<p>Bonjour,</p>
|
||
<p>L'élève : %s (%s), </p>
|
||
<p>vient d'<b>annuler son rendez-vous %s du planning %s</b>.</p>
|
||
<p>%s</p>
|
||
""" % (nomEleve, codeEleve, dateRDV, Lieu1RDV, Lieu2RDV)
|
||
|
||
elif ref == 'envoiPassRousseau':
|
||
body = """
|
||
<p>Bonjour %s,</p>
|
||
<p>L’équipe Marietton vous remercie pour votre inscription.</p>
|
||
<p>Vos identifiants de connexion au site [https://www.marietton.com/salle-de-code-acces.php](https://www.marietton.com/salle-de-code-acces.php) sont les suivants :</p>
|
||
<p>votre identifiant : %s</p>
|
||
<p>votre mot de passe : %s</p>
|
||
|
||
<p>Nous vous souhaitons à présent une agréable formation.</p>""" % (nomEleve, codeEleve, Lieu1RDV, Lieu2RDV)
|
||
|
||
elif ref == 'dispoPassRousseau':
|
||
body = """
|
||
<p>Bonjour %s,</p>
|
||
<p>L’équipe Marietton vous remercie pour votre inscription.</p>
|
||
<p>Nous vous invitons à contacter communication@marietton.com sur la disponibilité des PASS Rousseau.</p>""" % (
|
||
nomEleve)
|
||
|
||
else:
|
||
# message changeCoord
|
||
body = """
|
||
<p>Bonjour,</p>
|
||
<p>L'élève : %s (%s), </p>
|
||
<p>vient de changer ses coordonnées via son espace élève.</p>""" % (nomEleve, codeEleve)
|
||
|
||
# ajouter salutation
|
||
corps = """
|
||
%s
|
||
<p>Cordialement,<br>
|
||
<a href="https://monespace.marietton.com">Espace Client MARIETTON</a>
|
||
<p>
|
||
<p></p>""" % body
|
||
|
||
return corps
|
||
|
||
|
||
def getConfirmText(request, ref, nomEleve, codeEleve, dateRDV, lieu1RDV, lieu2RDV):
|
||
# lire le message selon la référence du tarif
|
||
body = get_messageConformation(request, ref)
|
||
|
||
# convertir confirmation de mardown en HTML
|
||
if body:
|
||
markdowner = Markdown()
|
||
body = markdowner.convert(body)
|
||
# remplacer les mots clés
|
||
body = body.replace("!civNomPrenom!", nomEleve)
|
||
body = body.replace("!codeClient!", str(codeEleve))
|
||
body = body.replace("!dateRDV!", dateRDV)
|
||
body = body.replace("!lieu1RDV!", lieu1RDV)
|
||
body = body.replace("!lieu2RDV!", lieu2RDV)
|
||
else:
|
||
body = 'Texte de confirmation non trouvé pour %s' % ref
|
||
|
||
return body
|
||
|
||
|
||
@view_config(route_name='justifs_list', renderer='../templates/default/justifs_list.pt', permission='view')
|
||
def justifs_list(request):
|
||
logged_in = request.authenticated_userid
|
||
|
||
# initialiser la liste des justifs à télécharger
|
||
init_eleve_justifs(request, logged_in)
|
||
|
||
justifs = get_eleve_docs(request, logged_in, 'JUST')
|
||
justifs_manquant = get_eleve_justifs_manquant(request, logged_in)
|
||
|
||
return {
|
||
'page_title': "Justificatifs à télécharger",
|
||
'justifs': justifs,
|
||
'justifs_manquant': justifs_manquant,
|
||
'code_add': '',
|
||
'cd_cli' : logged_in
|
||
}
|
||
|
||
|
||
def downloadFile2Temp(input_file, input_name, ext_allowed):
|
||
# récupère son extension
|
||
input_extension = input_name.split('.')[-1]
|
||
mime = magic.from_buffer(input_file.read(), mime=True)
|
||
# extensions autorisées ?
|
||
if mime not in ext_allowed:
|
||
return "ERREUR: Le format du fichier n'est pas valide. Téléchargement impossible."
|
||
|
||
# Finally write the data to a temporary file
|
||
temp_file_path = os.path.join('/tmp/', input_name)
|
||
# supprimer le fichier s'il existe déjà
|
||
if os.path.exists(temp_file_path):
|
||
os.remove(temp_file_path)
|
||
|
||
input_file.seek(0)
|
||
with open(temp_file_path, 'wb') as output_file:
|
||
shutil.copyfileobj(input_file, output_file)
|
||
|
||
# controler la taille du fichier < 4 Mo
|
||
filesize = round(os.path.getsize(temp_file_path) / 1024)
|
||
if filesize > 4096:
|
||
os.remove(temp_file_path)
|
||
return "ERREUR: La taille du fichier dépasse la limite autorisée. Téléchargement impossible."
|
||
|
||
if input_extension in ['jpeg', 'jpg', 'png']:
|
||
# using the Python Image Library (PIL) to resize an image
|
||
resize_photos(temp_file_path)
|
||
|
||
return temp_file_path
|
||
|
||
|
||
def tempFile2Dossier(request, no_ligne, cd_cli, temp_file, filename, logged_in):
|
||
# créer le répertoire du chantier
|
||
path = '%s/%s' % (request.registry.settings['monaem.justifs_dir'], cd_cli)
|
||
os.makedirs(path, exist_ok=True)
|
||
|
||
filepath = os.path.join('%s/%s' % (path, filename))
|
||
# supprimer le fichier s'il existe déjà
|
||
if os.path.exists(filepath):
|
||
os.remove(filepath)
|
||
|
||
# Finally move the temporary file to folder
|
||
shutil.move(temp_file, filepath)
|
||
|
||
filesize = round(os.path.getsize(filepath) / 1024)
|
||
new_values = {}
|
||
new_values['nom_fic'] = filename
|
||
new_values['taille_fic'] = filesize
|
||
new_values['cd_uti'] = 'WEB'
|
||
update_eleve_justif(request, no_ligne, new_values)
|
||
|
||
|
||
def resize_photos(image_file):
|
||
# using the Python Image Library (PIL) to resize an image
|
||
img_org = Image.open(image_file)
|
||
# get the size of the original image
|
||
width_org, height_org = img_org.size
|
||
# set the resizing factor so the aspect ratio can be retained
|
||
# factor > 1.0 increases size
|
||
# factor < 1.0 decreases size
|
||
factor = 0.75
|
||
width = int(width_org * factor)
|
||
height = int(height_org * factor)
|
||
# best down-sizing filter
|
||
img_anti = img_org.resize((width, height), Image.ANTIALIAS)
|
||
# split image filename into name and extension
|
||
name, ext = os.path.splitext(image_file)
|
||
# create a new file name for saving the result
|
||
img_anti.save(image_file)
|
||
|
||
return
|
||
|
||
|
||
@view_config(route_name='doc_upload', renderer='../templates/default/doc_upload.pt', permission='view')
|
||
def doc_upload(request):
|
||
logged_in = request.authenticated_userid.upper()
|
||
no_ligne = request.matchdict['no_ligne']
|
||
cd_cli = request.matchdict['cd_cli']
|
||
|
||
url = request.route_url("doc_upload", no_ligne=no_ligne, cd_cli=cd_cli)
|
||
message = ""
|
||
|
||
# lire le document à uploader
|
||
justif = get_eleve_justifs_byligne(request, no_ligne)
|
||
if justif is None:
|
||
request.session.flash(u"Le justif %s est introuvable" % (noligne), 'danger')
|
||
return HTTPFound(location=request.route_url("home", cd_cli=cd_cli))
|
||
|
||
url_retour = request.route_url('justifs_list')
|
||
|
||
if 'form.submitted' in request.params:
|
||
libelle_fic = None
|
||
if 'libelle_fic' in request.params:
|
||
new_values = {}
|
||
new_values['libelle_fic'] = request.params['libelle_fic']
|
||
new_values['cd_uti'] = 'WEB'
|
||
if 'nom_fic' in request.params:
|
||
new_values['nom_fic'] = request.params['nom_fic']
|
||
update_eleve_justif(request, no_ligne, new_values)
|
||
request.session.flash('Le e-photo est enregistré avec succès.', 'success')
|
||
|
||
if request.POST['uploadfile'] != b'':
|
||
# récupère le fichier download dans le dossier /tmp
|
||
input_file = request.POST['uploadfile'].file
|
||
input_name = request.POST['uploadfile'].filename
|
||
input_parts = input_name.split('.')
|
||
input_ext = input_parts[len(input_parts) - 1]
|
||
ext_allowed = ['image/jpeg', 'image/jpg', 'image/png', 'application/pdf']
|
||
temp_file = downloadFile2Temp(input_file, input_name, ext_allowed)
|
||
if temp_file[:8] == 'ERREUR: ':
|
||
request.session.flash(temp_file, 'danger')
|
||
return HTTPFound(location=url)
|
||
|
||
# fabriquer le nom du document
|
||
TODAY = date.today().strftime('%Y-%m-%d')
|
||
filename = '%s_%s_%s_%s.%s' % (cd_cli, justif.type, justif.code, TODAY, input_ext)
|
||
tempFile2Dossier(request, no_ligne, cd_cli, temp_file, filename, logged_in)
|
||
request.session.flash('%s : Ce fichier est téléchargé avec succès.' % input_name, 'success')
|
||
|
||
return HTTPFound(location=url_retour)
|
||
|
||
return {
|
||
'page_title': "Télécharger un document",
|
||
'url': url,
|
||
'url_retour': url_retour,
|
||
'justif': justif,
|
||
}
|
||
|
||
|
||
@view_config(route_name='doc_edit', renderer='../templates/default/doc_edit.pt', permission='view')
|
||
def doc_edit(request):
|
||
logged_in = request.authenticated_userid.upper()
|
||
no_ligne = request.matchdict['no_ligne']
|
||
cd_cli = request.matchdict['cd_cli']
|
||
|
||
url = request.route_url("doc_edit", no_ligne=no_ligne, cd_cli=cd_cli)
|
||
message = ""
|
||
|
||
# lire le document à uploader
|
||
justif = get_eleve_justifs_byligne(request, no_ligne)
|
||
if justif is None:
|
||
request.session.flash(u"Le justif %s est introuvable" % (no_ligne), 'danger')
|
||
return HTTPFound(location=request.route_url("fiche_eleve", cd_cli=cd_cli))
|
||
|
||
url_retour = request.route_url('justifs_list')
|
||
|
||
if 'form.submitted' in request.params:
|
||
new_values = {}
|
||
new_values['cd_uti'] = 'WEB'
|
||
if 'libelle_fic' in request.params:
|
||
new_values['libelle_fic'] = request.params['libelle_fic']
|
||
update_eleve_justif(request, no_ligne, new_values)
|
||
request.session.flash('Le fichier est validé avec succès.', 'success')
|
||
return HTTPFound(location=url_retour)
|
||
|
||
if 'form.erased' in request.params:
|
||
new_values = {}
|
||
new_values['cd_uti'] = 'WEB'
|
||
new_values['nom_fic'] = ''
|
||
new_values['libelle_fic'] = ''
|
||
new_values['taille_fic'] = 0
|
||
# supprimer le fichier de la pièce
|
||
file_path = '%s/%s/%s' % (request.registry.settings['monaem.justifs_dir'], cd_cli, justif.nom_fic)
|
||
if os.path.exists(file_path):
|
||
os.remove(file_path)
|
||
update_eleve_justif(request, no_ligne, new_values)
|
||
request.session.flash('Le fichier est effacé avec succès.', 'success')
|
||
return HTTPFound(location=url_retour)
|
||
|
||
if 'form.deleted' in request.params:
|
||
# supprimer le fichier de la pièce
|
||
file_path = '%s/%s/%s' % (request.registry.settings['monaem.justifs_dir'], cd_cli, justif.nom_fic)
|
||
if os.path.exists(file_path):
|
||
os.remove(file_path)
|
||
delete_eleve_justif(request, no_ligne)
|
||
request.session.flash('Le fichier est supprimé avec succès.', 'success')
|
||
return HTTPFound(location=url_retour)
|
||
|
||
return {
|
||
'page_title': "Modifier un document",
|
||
'url': url,
|
||
'url_retour': url_retour,
|
||
'justif': justif,
|
||
}
|
||
|
||
@view_config(route_name='download', renderer='', permission='view')
|
||
def download(request):
|
||
filename = request.matchdict['filename']
|
||
cd_cli = request.matchdict['cd_cli']
|
||
logged_in = request.authenticated_userid
|
||
file_path = '%s/%s/%s' % (request.registry.settings['monaem.justifs_dir'], cd_cli, filename)
|
||
if str(logged_in) != str(cd_cli) or not os.path.exists(file_path):
|
||
return Response(status=404)
|
||
else: #there is no overwrite
|
||
response = FileResponse(file_path)
|
||
response.headers['Content-Disposition'] = ("inline; filename=%s"%(filename))
|
||
return response
|