# -*- 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 = """
Bonjour %s,
%s
Cordialement,
Espace Moniteurs MARIETTON
https://moniteurs.marietton.com
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 :
%s
Ce lien ne sera valable que pendant 48 heures.
""" % (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, }