Files
aem_moniteurs/aem_gestion/views/default.py
2023-06-22 10:34:18 +02:00

800 lines
26 KiB
Python

# -*- coding: utf8 -*-
from pyramid.response import Response
from pyramid.view import (
view_config,
forbidden_view_config,
)
from pyramid.security import (
remember,
forget,
)
from pyramid.httpexceptions import (
HTTPFound,
)
from pyramid_mailer import get_mailer
from pyramid_mailer.message import Message
from datetime import date, datetime
from dateutil.relativedelta import *
from urllib.request import urlopen
from user_agents import parse
import transaction
import json
import locale
import hashlib
from ..models.default import *
from ..models.parametres import (
get_charts_data,
)
from ..models.eleves import (
get_eleves_by_code,
get_eleves_by_name,
get_eleves_by_name78,
get_eleves_not_b78_by_name,
get_eleves_ajax
)
from ..models.crm import (
get_prospects_by_name,
)
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):
if x == None:
return 0
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_decz(x):
"""Takes a float and returns a number with 2 dec"""
locale.setlocale(locale.LC_ALL, '')
if x == 0:
return ""
else:
return locale.format_string('%.2f', x, False)
def to_euroN(x):
"""Takes a float and returns a currency without decimal"""
locale.setlocale(locale.LC_ALL, '')
if x == 0:
return ""
else:
return locale.format_string('%.0f', x)
def to_percent(x):
"""Takes a float and returns a string"""
return ("%.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 to_str(s):
if s is None:
return ''
else:
return str(s)
# - - - - - - - - - - - - - - - - - - - - - - - - - -
@view_config(route_name='ajax_lookup')
def ajax_lookup(request):
recherche = request.GET['recherche']
type = recherche[:1] # 1er car.
name = recherche[1:]
if type == 'E':
# lire les élèves commencant par
items = get_eleves_not_b78_by_name(request, name, 10)
else:
# lire les propsects commencant par
items = get_prospects_by_name(request, name, False)
liste = []
for row in items:
if type == 'E':
d = "%s - %s | %s" % (row.nompren, row.permis_demande, str(row.cd_cli).zfill(6))
else:
d = "%s - %s | %s" % (row.nomprenom, row.permis_demande, str(row.cd_prospect).zfill(6))
liste.append(d)
return Response(json.dumps(liste))
@view_config(route_name='ajax_eleve')
def ajax_eleve(request):
recherche = request.GET['recherche']
items = get_eleves_ajax(request, recherche)
liste = []
for row in items:
d = "%s - %s | %s" % (row.nompren, row.permis_demande, str(row.cd_cli).zfill(6))
liste.append(d)
return Response(json.dumps(liste))
@view_config(route_name='ajax_lookupb78')
def ajax_lookupb78(request):
recherche = request.GET['recherche']
type = recherche[:1] # 1er car.
name = recherche[1:]
if type == 'E':
# lire les élèves commencant par
items = get_eleves_by_name78(request, name, 10)
else:
# lire les propsects commencant par
items = get_prospects_by_name(request, name, False)
liste = []
for row in items:
if type == 'E':
d = "%s - %s | %s" % (row.nompren, row.permis_demande, str(row.cd_cli).zfill(6))
else:
d = "%s - %s | %s" % (row.nomprenom, row.permis_demande, str(row.cd_prospect).zfill(6))
liste.append(d)
return Response(json.dumps(liste))
@view_config(route_name='ajax_moniteur')
def ajax_moniteur(request):
recherche = request.GET['recherche']
items = get_all_moniteur_active_by_name(request, recherche)
liste = []
for row in items:
code = row.CD_MON
name = row.NOM+ ' | ' + row.PLANNING
liste.append({"data": code, "value": name})
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({"value": d, "data": d})
return Response(json.dumps(liste))
@view_config(route_name='ajax_tarifs')
def ajax_tarifs(request):
recherche = request.GET['recherche']
# lire les tarifs commencant par
items = get_tarifs_byName(request, recherche)
liste = []
for row in items:
d = row.REF # + " - " + row.LIB
liste.append(d)
return Response(json.dumps(liste))
@view_config(route_name='ajax_type_devis', renderer='json')
def ajax_type_devis(request):
type_devis = request.POST['type_devis']
# lire le type de devis dans la BD
item = get_types_devis(request, type_devis)
if item:
montant = str(item.montantTTC)
montant_ht = str(item.montantHT)
nb_heures = str(item.nb_heures)
else:
montant = '0.00'
montant_ht = '0.00'
nb_heures = '0'
return {
'montant': montant,
'montant_ht': montant_ht,
'nb_heures': nb_heures,
}
@view_config(route_name='ajax_valid_formules')
def ajax_valid_formules(request):
permis = request.GET["permis"]
formules = get_all_formules(request, permis)
liste = []
for item in formules:
liste.append({"value": item.FORMULE, "data": item.FORMULE})
return Response(json.dumps(liste))
@view_config(route_name='ajax_formules')
def ajax_formules(request):
recherche = request.GET['recherche']
validite = 'EN-COURS'
# si validite a changé
if 'validite' in request.GET:
validite = request.GET["validite"]
# lire les formules
items = get_formules(request, recherche, validite)
# construire la liste
liste = []
for item in items:
liste.append({"value": item.FORMULE, "data": item.FORMULE})
# lire les codes postaux commencant par
return Response(json.dumps(liste))
@view_config(route_name='ajax_dept_nais')
def ajax_dept_nais(request):
recherche = request.GET['recherche']
items = get_dept_nais(request, recherche)
liste = []
for item in items:
liste.append({"value": item.code, "data": item.libelle})
return Response(json.dumps(liste))
@view_config(route_name='ajax_login')
def ajax_login(request):
login = request.params['login']
item = get_users_by_code(request, login)
data = {}
agences = []
if item != None:
data['find']= True
if item.mobile == True :
data['mobile']= True
list_agences = get_agences(request,0)
for agence in list_agences :
dict_agence ={
'code' : agence.CODE,
'libelle' : agence.LIBELLE
}
agences.append(dict_agence)
else:
data['mobile']= False
else:
data['find']= False
data['agence'] = agences
return Response(json.dumps(data))
@view_config(route_name='ajax_mode_regl')
def ajax_mode_regl(request):
recherche = request.GET['recherche']
items = get_mode_mode_regl(request, recherche)
# construire la liste
liste = []
for item in items:
liste.append({"value": item.LIBELLE, "data": item.CODE})
return Response(json.dumps(liste))
@view_config(route_name='ajax_libelle_regl')
def ajax_libelle_regl(request):
recherche = request.GET['recherche']
items = get_libelle_mode_regl(request, recherche)
# construire la liste
liste = []
for item in items:
liste.append({"value": item.LIBELLE, "data": item.CODE})
return Response(json.dumps(liste))
@view_config(route_name='ajax_activity')
def ajax_activity(request):
recherche = request.GET['recherche']
items = get_list_activity(request, recherche)
# construire la liste
liste = []
for item in items:
liste.append({"value": item.NOM, "data": item.CD_CLI, 'label': item.NOM})
return Response(json.dumps(liste))
def envoyerMail(request, destinataires, nom, objet, corps):
# si expediteur vide -> prendre le defaut
expediteur = request.registry.settings['aem_gestion.admin_email']
# ajouter entête et pied au corps du message
html_body = """
<p>Bonjour %s,</p>
%s
<p>
Cordialement,<br />
<b>Espace Moniteurs MARIETTON</b><br/>
<a href="https://moniteurs.marietton.com">https://moniteurs.marietton.com</a>
</p>
""" % (nom, corps)
message = Message(subject="[MARIETTON] %s" % objet,
sender=expediteur,
recipients=destinataires,
html=html_body)
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)
}
def envoyerMailEleve(request, destinataires, objet, corps):
# si expediteur vide -> prendre le defaut
expediteur = request.registry.settings['aem_gestion.admin_email']
html_body = corps
message = Message(subject="[MARIETTON] %s" % objet,
sender=expediteur,
recipients=destinataires,
html=html_body)
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='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_users_by_code(request, logged_in)
if 'form.submitted' in request.params:
old_password = request.params['old_password']
new_password = request.params['new_password1']
# On encode le password pour ne plus avoir de plantage avec les "é"
if (member.mdp_hash == to_sha1(old_password)):
update_password(request, logged_in, new_password)
request.session.flash("Votre mot de passe a été mis à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('home'))
else:
message = "L'ancien mot de passe fourni est incorrect."
return {
'page_title': "Changer mon mot de passe",
'url': url,
'member': member,
'message': message,
}
@view_config(route_name='email_password', renderer='../templates/default/email_password.pt')
def email_password(request):
url = request.route_url('email_password')
message = ''
if 'form.submitted' in request.params:
login = request.params['login']
member = get_users_by_code(request, login)
if member:
if member.actif == 0:
message = "Le compte de cet utilisateur est désactivé. Contactez votre agence."
elif member.email:
# Fabrication du corps du Message
lien = update_membre_mdp_oublie(request, login)
body = """
<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>
""" % (request.route_url('redefinir_mdp', lien=lien))
destinataires = [member.email]
envoyerMail(request, destinataires, member.nom, "Oubli de mot de passe", body)
request.session.flash("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 utilisateur n'est pas renseignée. Contactez votre agence."
else:
message = "Aucun utilisateur trouvé avec ce code. Veuillez réessayer."
return {
'page_title': "Mot de passe oublié ?",
'url': url,
'message': message,
}
@view_config(route_name='home', renderer='../templates/default/home.pt', permission='view')
def home(request):
def getChartColor(valeur):
# retourne la couleur du graphique selon la valeur
if valeur < 40:
color = 'red'
elif valeur < 50:
color = 'orange'
elif valeur < 60:
color = 'yellow'
else:
color = 'green'
return color
"""Home view"""
logged_in = request.authenticated_userid
member = get_users_by_code(request, logged_in)
now = datetime.now()
# examens = get_examen_by_agence(request,member.agence)
# récupère le nombre de messages non lus de l'utilisateur
try:
html = urlopen('https://suivi-eleve.marietton.com/MSG-nl.php?codeU=%s' % logged_in,timeout=30)
nlus = html.read()
except:
nlus = 0
barChart_annee_3 = []
mois_3 = now - relativedelta(months=+3)
mois_2 = now - relativedelta(months=+2)
mois_1 = now - relativedelta(months=+1)
mois = now - relativedelta(months=+0)
# lire les résultats exmanes mois M-2
items = get_charts_data(request, 'examens01', mois_3.strftime('%Y%m'))
# construire la liste pour barChart
barChart_annee_3 = []
barChart_annee_3.append(('Mode', '%', {'role': 'style'}, {'role': 'annotation'}, {'type': 'string','role': 'tooltip'}))
title_3 = ''
average = 0
sum_totale=0
sum_reussite=0
moyenne = 0
for item in items:
title_3 = item.group1_lib
average = round(item.moyenne)
valeur = round(item.valeur)
moyenne = item.moyenne
sum_totale = item.mar_totale
sum_reussite = item.mar_reussite
tooltip = 'Agence: '+item.group2_lib+'\nReussite: '+str(item.reussite)+'\nTotale: '+str(item.totale)+'\nTaux: '+str(round(item.valeur)) + ' %'
# construire la liste pour barChart cible
d = (item.group2_lib, valeur, getChartColor(valeur),'('+str(item.reussite)+'/'+str(item.totale)+')\xa0\xa0\xa0'+str(valeur) + ' %',tooltip)
barChart_annee_3.append(d)
# ajouter colonne MARIETTON
mar_tooltip = 'Marietton\nReussite: '+str(sum_reussite)+'\nTotale: '+str(sum_totale)+'\nTaux: '+str(round(moyenne)) + ' %'
d = ('MARIETTON', average, 'MidnightBlue','('+str(sum_reussite)+'/'+str(sum_totale)+')\xa0\xa0\xa0'+ str(average) + ' %', mar_tooltip)
barChart_annee_3.append(d)
# lire les résultats exmanes mois M-2
items = get_charts_data(request, 'examens01', mois_2.strftime('%Y%m'))
# construire la liste pour barChart
barChart_annee_2 = []
barChart_annee_2.append(('Mode', '%', {'role': 'style'}, {'role': 'annotation'}, {'type': 'string','role': 'tooltip'}))
title_2 = ''
average = 0
sum_totale=0
sum_reussite=0
moyenne = 0
for item in items:
title_2 = item.group1_lib
average = round(item.moyenne)
valeur = round(item.valeur)
moyenne = item.moyenne
sum_totale = item.mar_totale
sum_reussite = item.mar_reussite
tooltip = 'Agence: '+item.group2_lib+'\nReussite: '+str(item.reussite)+'\nTotale: '+str(item.totale)+'\nTaux: '+str(round(item.valeur)) + ' %'
# construire la liste pour barChart cible
d = (item.group2_lib, valeur, getChartColor(valeur),'('+str(item.reussite)+'/'+str(item.totale)+')\xa0\xa0\xa0'+str(valeur) + ' %',tooltip)
barChart_annee_2.append(d)
# ajouter colonne MARIETTON
mar_tooltip = 'Marietton\nReussite: '+str(sum_reussite)+'\nTotale: '+str(sum_totale)+'\nTaux: '+str(round(moyenne)) + ' %'
d = ('MARIETTON', average, 'MidnightBlue','('+str(sum_reussite)+'/'+str(sum_totale)+')\xa0\xa0\xa0'+ str(average) + ' %', mar_tooltip)
barChart_annee_2.append(d)
# lire les résultats exmanes mois M-
items = get_charts_data(request, 'examens01', mois_1.strftime('%Y%m'))
# construire la liste pour barChart
barChart_annee_1 = []
barChart_annee_1.append(('Mode', '%', {'role': 'style'}, {'role': 'annotation'}, {'type': 'string','role': 'tooltip'}))
title_1 = ''
average = 0
sum_totale = 0
sum_reussite = 0
moyenne = 0
for item in items:
title_1 = item.group1_lib
title_1h = str(round(item.moyenne))
average = round(item.moyenne)
valeur = (round(item.valeur))
totale = item.totale
reussite = item.reussite
moyenne = item.moyenne
sum_totale = item.mar_totale
sum_reussite = item.mar_reussite
tooltip = 'Agence: '+item.group2_lib+'\nReussite: ' + str(item.reussite)+'\nTotale: '+str(item.totale) + '\nTaux: '+str(round(item.valeur)) + ' %'
# construire la liste pour barChart cible
d = (item.group2_lib, valeur, getChartColor(valeur), '('+str(item.reussite)+'/'+str(item.totale)+')\xa0\xa0\xa0'+str(valeur) + ' %', tooltip)
barChart_annee_1.append(d)
mar_tooltip = 'Marietton\nReussite: '+str(sum_reussite)+'\nTotale: '+str(sum_totale)+'\nTaux: '+str(round(moyenne)) + ' %'
d = ('MARIETTON', average, 'MidnightBlue','('+str(sum_reussite)+'/'+str(sum_totale)+')\xa0\xa0\xa0'+ str(average) + ' %', mar_tooltip)
barChart_annee_1.append(d)
# lire les résultats exmanes mois M
items = get_charts_data(request, 'examens01', mois.strftime('%Y%m'))
barChart_annee = []
barChart_annee.append(('Mode', '%', {'role': 'style'}, {'role': 'annotation'}, {'type': 'string','role': 'tooltip'}))
title = ''
average = 0
sum_totale = 0
sum_reussite = 0
moyenne = 0
for item in items:
title = item.group1_lib
title_h = str(round(item.moyenne))
average = round(item.moyenne)
valeur = round(item.valeur)
totale = item.totale
reussite = item.reussite
moyenne = item.moyenne
sum_totale = item.mar_totale
sum_reussite = item.mar_reussite
tooltip = 'Agence: '+item.group2_lib+'\nReussite: ' + str(item.reussite)+'\nTotale: '+str(item.totale) + '\nTaux: '+str(round(item.valeur)) + ' %'
# construire la liste pour barChart cible
d = (item.group2_lib, valeur, getChartColor(valeur),'('+str(item.reussite)+'/'+str(item.totale)+')\xa0\xa0\xa0'+ str(valeur) + ' %', tooltip)
barChart_annee.append(d)
# ajouter colonne MARIETTON
mar_tooltip = 'Marietton\nReussite: '+str(sum_reussite)+'\nTotale: '+str(sum_totale)+'\nTaux: '+str(round(moyenne)) + ' %'
d = ('MARIETTON', average, 'MidnightBlue','('+str(sum_reussite)+'/'+str(sum_totale)+')\xa0\xa0\xa0'+ str(average) + ' %', mar_tooltip)
barChart_annee.append(d)
return {
'page_title': 'Bienvenue %s (Agence %s)' % (member.nom, member.agence),
'logged_in': logged_in,
'nlus': nlus,
'bar_annee_3': json.dumps(barChart_annee_3),
'bar_annee_2': json.dumps(barChart_annee_2),
'bar_annee_1': json.dumps(barChart_annee_1),
'bar_annee': json.dumps(barChart_annee),
'title': title,
'title_1': title_1,
'title_2': title_2,
'title_3': title_3,
'access': member.secu,
}
@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')
@view_config(route_name='login_from', renderer='../templates/default/login.pt', permission='view')
@forbidden_view_config(renderer='../templates/default/login.pt')
def login(request):
device = ''
login = ''
current_route_path = request.current_route_path()
if 'login_as' in current_route_path:
# memoriser l'identifiant du user
login = request.matchdict['login']
login_url = request.route_url('login_as', login=login)
elif 'login_from' in current_route_path:
logged_in = request.authenticated_userid
# if user is already logged in, go to home
if logged_in is not None:
return HTTPFound(location=request.route_url('home'))
# memoriser l'identifiant de la tablette
device = request.matchdict['device']
login_url = request.route_url('login_from', device=device)
else:
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'].upper()
password = request.params['password']
record = get_users_by_code(request, login)
if record:
# controler que la fiche n'est pas cloturee
if record.actif != 0:
# 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)
update_last_connection(request, login, user_agent.device.family + ' / ' + device)
# Update agence
if 'agence' in request.params:
agence = request.params['agence']
update_user_agency(request,record.cd_uti,agence)
if 'login_from' in current_route_path:
try:
urlopen(
'https://suivi-eleve.marietton.com/log_tablet.php?codeU=%s&device=%s' % (login, device),
timeout=30)
except Exception as e:
pass
# 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 utilisateur ou le mot de passe est incorrect. Identification échouée."
else:
message = "Votre code utilisateur a été désactivé. Accès refusé."
else:
message = "Le code utilisateur ou le mot de passe est incorrect. Identification échouée."
return {
'page_title': "",
'message': message,
'url': login_url,
'came_from': came_from,
'login': login,
'password': password,
'device': device,
}
@view_config(route_name='logout')
def logout(request):
headers = forget(request)
request.session.flash("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
if is_lien_mdp_oublie(request, lien) == True:
membre = get_mdp_oublie_infos(request, lien)
if 'form.submitted' in request.params:
mdp = request.params["new_password1"]
update_password(request, membre.cd_uti, mdp)
request.session.flash("Votre mot de passe a bien été mis à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('login'))
else:
return HTTPFound(location=request.route_url('login'))
return {
'page_title': "Redéfinir le mot de passe",
}
@view_config(route_name='change_agency', renderer='../templates/default/change_agency.pt', permission='view')
def change_agency(request):
cd_uti = request.authenticated_userid
url = request.route_url('change_agency')
message = ''
agences = get_agences(request, 0)
# lire la fiche de l'individu
individu = get_users_by_code(request, cd_uti)
if not individu:
request.session.flash("Utilisateur non trouvé : %s" % cd_uti, 'warning')
return HTTPFound(location=request.route_url('home'))
if 'form.submitted' in request.params:
agence = request.params["agence"]
update_user_agency(request, cd_uti, agence)
request.session.flash("L'agence a été mise à jour avec succès.", 'success')
return HTTPFound(location=request.route_url('home'))
return {
'page_title': "Changement d'agence",
'url': url,
'individu': individu,
'agences': agences,
'message': message,
}