# -*- coding: utf8 -*- from pyramid.response import Response from pyramid.view import ( view_config, ) from pyramid_mailer import get_mailer from pyramid_mailer.message import Message, Attachment from time import sleep from datetime import * from dateutil.relativedelta import * from ..models.utils import * @view_config(route_name='batch_nuit') def batch_nuit(request): """ Traitement est lancé chaque nuit, sur le serveur du site web, par un cron job : - Execute cron job as : root - Command : wget http://localhost:9180/batch_nuit/JonSn0w - When to execute : 02:00 each day Par sécurité, ce view ne peut être appelé qu'avec un paramètre secret 'JonSn0w' """ # contrôle : paramètre correct ? non, terminer par = request.matchdict['param'] if par != 'JonSn0w': return Response('Erreur : paramètre incorrect') # ----- effacer le log truncate_log(request) # ----- PURGE des données obsolètes insert_log(request, 'PURGE','- Début PURGE DES DONNEES OBSOLETES') TODAY = date.today() # purger tous les 1er du mois if TODAY.day() == 1 : until_date = date(TODAY.year, TODAY.month, 1).strftime('%Y-%m-%d') purge_mensuelle(request, until_date) purge_clients(request) delete_orphan_attached_files(request) # ----- MAJ STATS DELAIS de traitements des dossiers sur 1 an insert_log(request, 'STATS', '- Début MAJ STATS DES PERFORMANCES') societes = ['PL', 'ME', 'PE'] datejour = TODAY groupes = ['MAIF', 'AXA', 'X'] for i in range(12): for societe in societes: for groupe in groupes: update_stats_delais(request, societe, datejour.strftime('%Y-%m-%d'), groupe) # recule d'un mois datejour = datejour + relativedelta(months=-1) # ----- RAPPELS DES RENDEZ-VOUS update_rappels(request) # attendre 5 secondes sleep(5) # ----- envoyer les rappels notifier_rappels(request) # ----- ENVOI RAPPORTS di traitement email_rapport(request) return Response('Batch nuit terminé OK') def notifier_rappels(request): # log : Début ENVOI emails insert_log(request, 'RAPPELS','- Début ENVOI emails') # lire les rappels non encore envoyés rappels = get_email_rappels(request) nbLus = 0 nbEnvoyes = 0 for item in rappels: nbLus += 1 error = 0 if len(item.c_email) == 0 : insert_log(request, 'RAPPELS', '--> email vide : %s-%s - %s %s' % (item.societe, item.nochantier, item.c_qualite, item.c_nom)) else: # RDV ayant une heure date_heure = item.rdv_date.strftime('%d/%m/%Y - %H:%M') szBody = """

Bonjour %s %s,

L’entreprise %s vous rappelle votre prochain rendez-vous, pris d'un commun accord

le %s
%s
%s
%s

En cas d'empêchement, veuillez nous contacter au %s

Veuillez agréer nos sincères salutations.

L'entreprise %s

""" % (item.c_qualite, item.c_nom, item.nom_societe, date_heure, item.c_adr, item.c_adr2, item.c_ville, item.tel, item.nom_societe) error = email_rappels(request, "RAPPEL : rendez-vous le " + date_heure, szBody, [item.c_email,], item.societe) nbEnvoyes += 1 # attendre 6 secondes, envoi de 10 emails par minute sleep(6) # si envoi OK, marquer le rdv comme envoyé ou traité if error == 0: update_email_rappels(request, item.no_id) if nbLus > 0: pc = str(round(nbEnvoyes * 100 / nbLus, 0)) + ' %' else: pc = '0 %' insert_log(request, 'RAPPELS', "- Fin ENVOI emails : %s rdv lus, %s rappels envoyés, soit %s envoyés." % (str(nbLus), str(nbEnvoyes), pc)) return def email_rappels(request, objet, corps, destinataire, societe): # lire la societe soc = get_societes(request, societe) if soc: expediteur = soc.email_from else: expediteur = "peinture@entreprise-dumas.com" # envoyer le rappel error = send_mail(request, expediteur, destinataire, "[Ent. Dumas] " + objet, corps) return error def email_rapport(request): NOW = datetime.now() corps = "

=============================================

" corps += "

Rapport du traitement de nuit du " + NOW.strftime('%d/%m/%Y - %H:%M') + "

" corps += "

=============================================

" # Lire le fichier log items = get_log(request) for item in items: corps += " - " + item.date.strftime('%d/%m/%Y - %H:%M') + " - " + item.proc + " : " + item.msg + "
" corps += "

=============================================

" expediteur = request.registry.settings['mondumas.admin_email'] destinataire = ["phuoc@caotek.fr","peinture@entreprise-dumas.com"] send_mail(request, expediteur, destinataire, "[DEV_NUIT] Rapport des traitements de nuit", corps) return def send_mail(request, expediteur, destinataires, objet, corps): body = """ %s """ % (corps) message = Message(subject=objet, sender=expediteur, recipients=destinataires, html=body) mailer = get_mailer(request) # import pdb;pdb.set_trace() msg = '' try: mailer.send_immediately(message) except Exception as e: # Just print(e) is cleaner and more likely what you want, # but if you insist on printing message specifically whenever possible... if hasattr(e, 'message'): msg = e.message else: msg = e # logguer l'erreur insert_log(request, 'MAILER', "- ERROR : %s, TO : %s" % (msg, destinataires)) return len(msg) @view_config(route_name='batch_test') def batch_test(request): """ Traitement est lancé pour tester des traitements batch URL = /batch_test/Sansa5tark Par sécurité, ce view ne peut être appelé qu'avec un paramètre secret 'Sansa5tark' """ # contrôle : paramètre correct ? non, terminer par = request.matchdict['param'] if par != 'Sansa5tark': return Response('Erreur : paramètre incorrect') # à revoir # update_chantiers_status(request) TODAY = date.today() until_date = date(TODAY.year - 10, TODAY.month, 1) purge_mensuelle(request, until_date) purge_clients(request) delete_orphan_attached_files(request) return Response('Batch nuit terminé OK') def delete_orphan_attached_files(request): """ Ce traitement parcourt le répertoire DOCS_ATTACHES de chacune des 5 sociétés et controle que le dossier sur le filesystem existe dans la BD. S'il n'existe plus, on supprime les fichiers du dossier """ import os import shutil societes = ['CD', 'ME', 'PE', 'PL', 'PO'] for ste in societes: # Scan the directiory of attached files # and get an iterator of os.DirEntry objets path = request.registry.settings['mondumas.devfac_dir'] + '/' + ste obj = os.scandir(path) # List all diretories in the specified path nbLus = 0 nbSupp = 0 for entry in obj : if entry.is_dir(): nbLus += 1 # le chantier existe ? if chantierExiste(request,ste, entry.name) == False : # non, supprimer les docs attaches shutil.rmtree(path+ '/' + entry.name) nbSupp += 1 if nbLus > 0: insert_log(request, 'DELETE', '%s : %d Répertoires lues, %d supprimées' % (ste, nbLus, nbSupp)) def update_chantiers_status(request): """ Ce traitement parcourt tous les chantiers de chacune des 5 sociétés pour mettre à jour son STATUS selon l'avancement du chantier. """ societes = ['PE','ME','PL','PO','CD'] for ste in societes: # lire tous les chantiers chantiers = get_all_chantiers(request, ste) for item in chantiers: # si le chantier est annulé, ne rien faire if item.STATUS != 'Annulé': status = '' # lire la dernière facture du chantier facture = get_last_facture(request, ste, item.NO_ID) if facture : # remonte le status de la facture ('','Régl part.', 'Réglée') status = facture.STATUS if status == '': status = 'Facturé' else: # lire le dernier devis du chantier ('','Commandé, 'Facturé') devis = get_last_devis(request, ste, item.NO_ID) if devis: # remonte le status de la facture status = devis.STATUS if status == '' or status == '0': status = 'Devis' else: if item.HUMIDITE != 0: status = 'Humidité' # maj le status du chantier update_chantier_status(request, ste, item.NO_ID, status) def update_chantiers_delais(request, date): """ Ce traitement calcul les delais : - delai_contact : le nombre de jours entre la réception de la DD et la création d'un 1er RDV - delai_rdv : le nombre de jours entre la réception de la DD et la date d'un 1er RDV - delai_devis : le nombre de jours entre la réception de la DD et la date d'un 1er devis - delai_facture : le nombre de jours entre la réception de la DD et la date d'une 1ere facture """ societes = ['PE','ME','PL','PO','CD'] for societe in societes: # lire tous les chantiers chantiers = get_chantiers_month(request, societe, date) for item in chantiers: dt_dossier = datetime.combine(item.DATE, datetime.min.time()) # lire les dates 1er contact, 1er rdv, 1er devis, 1er facture du chantiers date_contact, date_rdv, date_devis, date_facture = get_chantiers_dates(request, societe, item.NO_ID) # calculer le delai contact en jours if date_contact == None: delai_contact = 0 else: dt = datetime.combine(date_contact, datetime.min.time()) delai_contact = (dt - dt_dossier).days + 1 # delai négatif, ignorer if delai_contact < 0: delai_contact = 0 # calculer le delai rdv en jours if date_rdv == None: delai_rdv = 0 else: dt = datetime.combine(date_rdv, datetime.min.time()) delai_rdv = (dt - dt_dossier).days + 1 # delai négatif, ignorer if delai_rdv < 0: delai_rdv = 0 # calculer le delai contact en jours if date_devis == None: delai_devis = 0 else: dt = datetime.combine(date_devis, datetime.min.time()) delai_devis = (dt - dt_dossier).days + 1 # delai négatif, ignorer if delai_devis < 0: delai_devis = 0 # calculer le delai facture en jours if date_facture == None: delai_facture = 0 else: dt = datetime.combine(date_facture, datetime.min.time()) delai_facture = (dt - dt_dossier).days + 1 # delai négatif, ignorer if delai_facture < 0: delai_facture = 0 update_chantier_delais(request, societe, item.NO_ID, delai_contact, delai_rdv, delai_devis, delai_facture) def purge_clients(request): # lire tous les clients clients = get_all_clients(request) for client in clients: dern_operation = None # lire la facture la + récente facture = get_last_facture_client(request, client.societe, client.CD_CLI) if facture: dern_operation = facture.DATE else: # lire le réglemnet le + récent payment = get_last_payment_client(request, client.societe, client.CD_CLI) if payment: dern_operation = payment.DATE else: # lire le devis le + récent devis = get_last_devis_client(request, client.societe, client.CD_CLI) if devis: dern_operation = devis.DATE else: # lire le chantier le + récent chantier = get_last_chantier_client(request, client.societe, client.CD_CLI) if chantier: dern_operation = chantier.DATE # mémoriser dernière opération update_client_dern_operation(request, client.societe, client.CD_CLI, dern_operation) # supprimer clients ayant aucun dossier delete_client_unused(request) return