Files
dumas_gestion/mondumas/views/utils.py
2023-10-14 18:06:39 +02:00

377 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- 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
import smtplib
import ssl
from email.message import EmailMessage
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 = """
<!DOCTYPE html>
<html><body>
<p>Bonjour %s %s,</p>
<p>Lentreprise %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):
# import pdb;pdb.set_trace()
# Create a secure SSL context
context = ssl.create_default_context()
smtp_server = "smtp.office365.com"
smtp_port = 587 # For TLS
# lire la societe
soc = get_societes(request, societe)
if soc:
smtp_user = soc.email_from
smtp_pass = soc.email_cci
else:
smtp_user = request.registry.settings['mail.username']
smtp_pass = request.registry.settings['mail.password']
# construire le message
msg = EmailMessage()
msg['Subject'] = "[Ent. Dumas] " + objet
msg['From'] = smtp_user
msg['To'] = destinataire
# msg['Bcc'] = "phuoc@caotek.fr"
msg.set_content(corps, subtype='html')
# Try to log in to server and send email
err = ''
try:
server = smtplib.SMTP(smtp_server,smtp_port)
server.starttls(context=context) # Secure the connection
server.login(smtp_user, smtp_pass)
# envoyer l'email
server.send_message(msg)
print("sendmail -> OK")
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...
err = repr(e)[0:400]
insert_log(request, 'MAILER', "- ERROR : %s, TO : %s" % (err, destinataire))
finally:
server.quit()
return len(err)
def email_rapport(request):
NOW = datetime.now()
corps = "<!DOCTYPE html><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-dumas@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_html = Attachment(data=corps, transfer_encoding="base64", disposition='inline')
message = Message(subject=objet,
sender=expediteur,
recipients=destinataires,
html=body_html)
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...
msg = repr(e)[0:400]
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)
"""
# 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)
# 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 le chantier le + récent
chantier = get_last_chantier_client(request, client.societe, client.CD_CLI)
if chantier:
dern_operation = chantier.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 proforma le + récent
proforma = get_last_proforma_client(request, client.societe, client.CD_CLI)
if proforma:
dern_operation = proforma.DATE
else:
# lire la facture la + récente
facture = get_last_facture_client(request, client.societe, client.CD_CLI)
if facture:
dern_operation = facture.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