342 lines
12 KiB
Python
342 lines
12 KiB
Python
# -*- 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 :
|
||
# données de + 10 ans
|
||
until_date = date(TODAY.year - 10, TODAY.month, 1)
|
||
# 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')
|
||
datejour = TODAY
|
||
for i in range(12):
|
||
update_chantiers_delais(request, datejour)
|
||
datejour = datejour + relativedelta(months=-1)
|
||
|
||
societes = ['PL', 'ME', 'PE']
|
||
datejour = TODAY
|
||
groupes = ['MAIF', 'AXA', 'X']
|
||
for i in range(4):
|
||
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 3 secondes
|
||
sleep(3)
|
||
|
||
# ----- envoyer les rappels
|
||
notifier_rappels(request)
|
||
|
||
# ----- ENVOI RAPPORTS di traitement
|
||
email_rapport(request)
|
||
|
||
return Response('FIN Batch nuit')
|
||
|
||
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 = """
|
||
<html><body>
|
||
<p>Bonjour %s %s,</p>
|
||
<p>L’entreprise %s vous rappelle votre prochain rendez-vous, pris d'un commun accord</p>
|
||
<p>le <b>%s</b><br />
|
||
%s<br />
|
||
%s<br />
|
||
%s<br /><p>
|
||
<p>En cas d'empêchement, veuillez nous contacter au <b>%s</b></p>
|
||
<p>Veuillez agréer nos sincères salutations.</p>
|
||
<p>L'entreprise %s</p></body></html>
|
||
""" % (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 3 secondes, envoi de 20 emails par minute
|
||
sleep(3)
|
||
|
||
# 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 len(error)
|
||
|
||
def email_rapport(request):
|
||
NOW = datetime.now()
|
||
corps = "<html><body><p>=============================================</p>"
|
||
corps += "<p>Rapport du traitement de nuit du " + NOW.strftime('%d/%m/%Y - %H:%M') + "</p>"
|
||
corps += "<p>=============================================</p><p></p><p>"
|
||
|
||
# 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 + "<br />"
|
||
|
||
corps += "</p><p></p><p>=============================================</p><p></p>"
|
||
|
||
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)
|
||
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
|
||
insert_log(request, 'MAILER', "- ERROR : %s, TO : %s" % (msg, destinataires))
|
||
|
||
return str(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')
|
||
|
||
|
||
TODAY = date.today()
|
||
|
||
# ------ UPDATE statut DEVIS COMMANDE
|
||
update_devis_statut_4(request)
|
||
|
||
"""
|
||
# ----- MAJ STATS DELAIS de traitements des dossiers sur 1 an
|
||
datejour = TODAY
|
||
for i in xrange(12):
|
||
update_chantiers_delais(request, datejour)
|
||
datejour = datejour + relativedelta(months=-1)
|
||
|
||
"""
|
||
# until_date = date(TODAY.year - 10, TODAY.month, 1)
|
||
# purge_mensuelle(request, until_date)
|
||
# purge_clients(request)
|
||
|
||
# delete_orphan_attached_files(request)
|
||
|
||
# update_chantiers_delais(request, date(TODAY.year - 1, TODAY.month, 1))
|
||
insert_log(request, 'TEST','- Fin -')
|
||
|
||
return Response('TEST 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_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 |