diff --git a/development.ini b/development.ini index 6234a0d..3640f35 100644 --- a/development.ini +++ b/development.ini @@ -23,7 +23,7 @@ sqlalchemy.url = mysql://phuoc:phuoc!@localhost/bddevfac?charset=utf8 # sqlalchemy.url = mysql://phuoc:phuoc!@192.168.0.31/bddevfac?charset=utf8 mondumas.admin_email = cao.thien-phuoc@orange.fr -mondumas.devfac_url = mondumas:static/DEVFAC/ +mondumas.devfac_url = mondumas:static/DEVFAC/DOCS_ATTACHES/ mondumas.devfac_dir = /DEVFAC14/DOCS_ATTACHES # Mailer configuration diff --git a/mondumas/models/dossier.py b/mondumas/models/dossier.py index 142b202..03dc97a 100644 --- a/mondumas/models/dossier.py +++ b/mondumas/models/dossier.py @@ -126,9 +126,9 @@ def get_docs_attaches(request, nodossier, norapport, origine, filename): nochantier = int(nodossier[3:]) if filename == '': - query = "SELECT * FROM dossier_attaches WHERE nomrep = 'DOCS_ATTACHES' AND societe = :societe AND nochantier = :nochantier AND nodossier=0 AND origine = :origine ORDER BY cree_le;" + query = "SELECT * FROM dossier_attaches WHERE societe = :societe AND nochantier = :nochantier AND nodossier=0 AND origine = :origine ORDER BY cree_le;" else: - query = """SELECT * FROM dossier_attaches WHERE nomrep = 'DOCS_ATTACHES' AND societe = :societe AND nochantier = :nochantier + query = """SELECT * FROM dossier_attaches WHERE societe = :societe AND nochantier = :nochantier AND nodossier = :norapport AND origine = :origine AND nomfichier = :filename ORDER BY cree_le;""" results = request.dbsession.execute(query, {'societe': societe, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine, 'filename': filename}).fetchall() @@ -137,7 +137,7 @@ def get_docs_attaches(request, nodossier, norapport, origine, filename): def get_photos(request, nodossier, norapport, origine): societe = nodossier[0:2] nochantier = int(nodossier[3:]) - query = """SELECT * FROM dossier_attaches WHERE nomrep = 'DOCS_ATTACHES' AND societe = :societe AND nochantier = :nochantier + query = """SELECT * FROM dossier_attaches WHERE societe = :societe AND nochantier = :nochantier AND nodossier = :norapport AND origine = :origine AND UPPER(RIGHT(nomfichier,3)) <> 'PDF' ORDER BY cree_le;""" results = request.dbsession.execute(query, {'societe': societe, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine}).fetchall() return results @@ -153,7 +153,7 @@ def delete_photos(request, nodossier, norapport, origine, nomfic): if os.path.exists(file_path): os.remove(file_path) - query = "DELETE FROM dossier_attaches WHERE nomrep='DOCS_ATTACHES' AND societe=:societe AND nochantier=:nochantier AND nodossier=:norapport AND origine=:origine AND nomfichier=:nomfic;" + query = "DELETE FROM dossier_attaches WHERE societe=:societe AND nochantier=:nochantier AND nodossier=:norapport AND origine=:origine AND nomfichier=:nomfic;" execute_query(request, query, {'societe': societe, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine, 'nomfic': nomfic}) def rename_photos(request, nodossier, norapport, origine, nomfic, new_nomfic): @@ -162,7 +162,7 @@ def rename_photos(request, nodossier, norapport, origine, nomfic, new_nomfic): query = """ UPDATE dossier_attaches SET nomfichier = :new_nomfic - WHERE nomrep='DOCS_ATTACHES' AND societe=:societe AND nochantier=:nochantier AND nodossier=:norapport AND origine=:origine AND nomfichier=:nomfic; + WHERE societe=:societe AND nochantier=:nochantier AND nodossier=:norapport AND origine=:origine AND nomfichier=:nomfic; """ execute_query(request, query, {'societe': societe, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine, 'nomfic': nomfic, 'new_nomfic': new_nomfic}) @@ -204,8 +204,8 @@ def insert_dossier_attaches(request, nodossier, norapport, origine, filename, fi if item: return # enregistrer dans la table dossier_attaches - query = """INSERT INTO dossier_attaches (nomrep, societe, nochantier, nodossier, origine, nomfichier, taillefichier, cree_le, usermaj) - VALUES('DOCS_ATTACHES',:societe,:nochantier,:norapport,:origine,:filename,:filesize,NOW(),:user);""" + query = """INSERT INTO dossier_attaches (societe, nochantier, nodossier, origine, nomfichier, taillefichier, cree_le, usermaj) + VALUES(:societe,:nochantier,:norapport,:origine,:filename,:filesize,NOW(),:user);""" execute_query(request, query, {'societe': societe, 'nochantier': nochantier, 'norapport': norapport, 'origine': origine, 'filename': filename, 'filesize': filesize, 'user': user}) diff --git a/mondumas/models/parametres.py b/mondumas/models/parametres.py index 6f30205..abed1c0 100644 --- a/mondumas/models/parametres.py +++ b/mondumas/models/parametres.py @@ -32,10 +32,17 @@ def get_rappels_rdv(request): results = request.dbsession.execute(query, {}) return results.fetchall() -def get_orphans_DE(request, societe): +def get_stats_dd(request, societe): - query = "SELECT * FROM devis WHERE societe = '%s' AND nochantier = 0 ORDER BY date desc LIMIT 50 ;" % (societe) - results = request.dbsession.execute(query).first() + query = """SELECT societe, year(date) as Annee, COUNT(*) as Total, +SUM(IF(status = '', 1, 0)) AS Created, +SUM(IF(status = 'Devis', 1, 0)) AS Devis, +SUM(IF(status = 'Commandé', 1, 0)) AS Commande, +SUM(IF(status = 'Facturé', 1, 0)) AS Facture, +SUM(IF(status = 'Régl part.', 1, 0)) AS ReglePart, +SUM(IF(status = 'Réglée', 1, 0)) AS Regle +FROM dem_devis where societe=:societe group by societe, year(date);""" + results = request.dbsession.execute(query, {'societe': societe}).fetchall() return results def get_dossiers_byChantier(request, societe, name): diff --git a/mondumas/models/utils.py b/mondumas/models/utils.py index e53e37b..353d957 100644 --- a/mondumas/models/utils.py +++ b/mondumas/models/utils.py @@ -61,3 +61,31 @@ def get_societes(request, societe): query = "SELECT * FROM p_societe WHERE societe = :societe;" results = request.dbsession.execute(query, {'societe': societe}).first() return results + +def chantierExiste(request,societe, no_id): + query = "SELECT no_id FROM dem_devis WHERE societe = :societe and no_id = :no_id;" + results = request.dbsession.execute(query, {'societe': societe, 'no_id': no_id}).first() + if results: + return len(results) > 0 + else: + return False + +def get_all_chantiers(request,societe): + query = "SELECT * FROM dem_devis WHERE societe = :societe;" + results = request.dbsession.execute(query, {'societe': societe}).fetchall() + return results + +def get_last_facture(request, societe, nochantier): + query = "SELECT * FROM facture WHERE societe = :societe AND nochantier = :nochantier order by date DESC LIMIT 1;" + results = request.dbsession.execute(query, {'societe': societe, 'nochantier': nochantier}).first() + return results + +def get_last_devis(request, societe, nochantier): + query = "SELECT * FROM devis WHERE societe = :societe AND nochantier = :nochantier order by date DESC LIMIT 1;" + results = request.dbsession.execute(query, {'societe': societe, 'nochantier': nochantier}).first() + return results + +def update_chantier_status(request, societe, no_id, status): + query = "UPDATE dem_devis SET status = :status, DATEMAJ = DATEMAJ WHERE societe = :societe AND no_id = :no_id AND status <> :status;" + execute_query(request, query, {'societe': societe, 'no_id': no_id, 'status': status}) + diff --git a/mondumas/routes.py b/mondumas/routes.py index 5e7dad8..d6f358c 100644 --- a/mondumas/routes.py +++ b/mondumas/routes.py @@ -58,7 +58,7 @@ def includeme(config): config.add_route('emails_msg', '/emails_msg/{nolig}') config.add_route('expert_edit', '/expert_edit/{code_cab}/{code_exp}') config.add_route('infrastructure', '/infrastructure') - config.add_route('orphans_de', '/orphans_de/{societe}') + config.add_route('stats_dd', '/stats_dd/{societe}') config.add_route('rappels_rdv', '/rappels_rdv') config.add_route('rdf_cause_edit', '/rdf_cause_edit/{code}') config.add_route('rdf_causes', '/rdf_causes') @@ -71,3 +71,4 @@ def includeme(config): # utils config.add_route('batch_nuit', '/batch_nuit/{param}') + config.add_route('batch_test', '/batch_test/{param}') diff --git a/mondumas/templates/dossier/dossier_lookup.pt b/mondumas/templates/dossier/dossier_lookup.pt index bcff91d..73588c2 100644 --- a/mondumas/templates/dossier/dossier_lookup.pt +++ b/mondumas/templates/dossier/dossier_lookup.pt @@ -70,7 +70,7 @@ $.fn.dataTable.moment('DD-MM-YYYY'); $('#dossiers_list').DataTable({ data: dataSet, - pageLength: 50, + pageLength: 100, bLengthChange: false, language: { url: 'https://cdn.datatables.net/plug-ins/1.10.16/i18n/French.json' @@ -89,10 +89,13 @@ if ( data[6] == "Humidité" ) { $('td', row).eq(6).css('background-color', 'Crimson').css('color', 'white'); } - if ( data[6] == "En-cours" ) { + if ( data[6] == "Devis" || data[6] == "Commandé") { $('td', row).eq(6).css('background-color', 'Orange'); } - if ( data[6] == "Terminé" ) { + if ( data[6] == "Facturé") { + $('td', row).eq(6).css('background-color', 'LightBlue'); + } + if ( data[6] == "Réglée" || data[6] == "Régl part.") { $('td', row).eq(6).css('background-color', 'LightGreen'); } }, diff --git a/mondumas/templates/dossier/dossier_view.pt b/mondumas/templates/dossier/dossier_view.pt index 1c0ae82..11cf108 100644 --- a/mondumas/templates/dossier/dossier_view.pt +++ b/mondumas/templates/dossier/dossier_view.pt @@ -238,9 +238,9 @@ - + onclick="window.open('${docs_url}${detail.societe}/${detail.nochantier}/${detail.nomfichier},'popup','width=900,height=768'); return false;"> ${detail.nomfichier} @@ -271,9 +271,9 @@ - + onclick="window.open('${docs_url}${detail.societe}/${detail.nochantier}/${detail.nomfichier},'popup','width=900,height=768'); return false;"> ${detail.nomfichier} diff --git a/mondumas/templates/dossier/rdf_view.pt b/mondumas/templates/dossier/rdf_view.pt index 98c6fe6..16b22e2 100644 --- a/mondumas/templates/dossier/rdf_view.pt +++ b/mondumas/templates/dossier/rdf_view.pt @@ -162,7 +162,7 @@

-

@@ -300,7 +300,7 @@

-


diff --git a/mondumas/templates/dossier/upload_doc.pt b/mondumas/templates/dossier/upload_doc.pt index 774227d..5f24094 100644 --- a/mondumas/templates/dossier/upload_doc.pt +++ b/mondumas/templates/dossier/upload_doc.pt @@ -31,9 +31,9 @@
  • - + onclick="window.open('${docs_url}${detail.societe}/${detail.nochantier}/${detail.nomfichier},'popup','width=900,height=768'); return false;"> ${detail.nomfichier}  - crée le ${detail.cree_le.strftime('%d-%m-%Y')} par ${detail.usermaj} diff --git a/mondumas/templates/dossier/upload_img.pt b/mondumas/templates/dossier/upload_img.pt index aff3d89..c2356ea 100644 --- a/mondumas/templates/dossier/upload_img.pt +++ b/mondumas/templates/dossier/upload_img.pt @@ -48,9 +48,9 @@ + src="${docs_url}${detail.societe}/${nochantier}/${detail.nomfichier}" /> + src="${docs_url}${detail.societe}/${nochantier}/${norapport}/${detail.nomfichier}" />

    diff --git a/mondumas/templates/parametres/orphans_de.pt b/mondumas/templates/parametres/orphans_de.pt deleted file mode 100644 index b20b3c3..0000000 --- a/mondumas/templates/parametres/orphans_de.pt +++ /dev/null @@ -1,156 +0,0 @@ - -

    - -
    - -
    -
    - -
    - -
    -
    -
    - - - -
    - -
    - - - - - - - - - -

    CHANTIER

    -

    ${devis.C_QUALITE} ${devis.C_NOM}

    - ${devis.C_ADR}
    - ${devis.C_ADR2}
    - ${devis.C_CP} ${devis.C_VILLE}
    -
    - Police
    - Sinistre
    -
    - ${devis.NOPOL}
    - ${devis.NOSIN}
    -
    -
    -
    - - - - - -
    -

    CLIENT

    - NO DEVIS
    - DATE
    -
    -

    ${devis.NOMCLI}

    - ${devis.NO_ID}
    - ${devis.DATE.strftime('%d-%m-%Y')} -
    -
    -
    - -
    -
    - -
    - -
    -
    - -   (Veuillez cocher un ou plusieurs dossiers pour mettre à jour leur no de chantier) -
    -
    -
    - -
    - - - - - - - - - - - - - -
    NuméroDateClientChantierMontantSinistreCh.
    -
    -
    -
    - - - -
    - diff --git a/mondumas/templates/parametres/parametres.pt b/mondumas/templates/parametres/parametres.pt index f0cc6c3..125755c 100644 --- a/mondumas/templates/parametres/parametres.pt +++ b/mondumas/templates/parametres/parametres.pt @@ -41,10 +41,12 @@

    CONNEXIONS

    -
    - -

    DEVIS ORPHELINS

    +
    + +

    STATS GLOBALES

    +
    +

    INFRASTRUCTURE

    diff --git a/mondumas/templates/parametres/stats_dd.pt b/mondumas/templates/parametres/stats_dd.pt new file mode 100644 index 0000000..2d35793 --- /dev/null +++ b/mondumas/templates/parametres/stats_dd.pt @@ -0,0 +1,74 @@ + +
    + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    + + + + + + + + + + + + + +
    AnnéeA traiterDevisCommandéFacturéRégl part.RégléeTotal
    +
    +
    +
    + + + +
    + diff --git a/mondumas/views/parametres.py b/mondumas/views/parametres.py index 54d498c..9d34648 100644 --- a/mondumas/views/parametres.py +++ b/mondumas/views/parametres.py @@ -27,7 +27,7 @@ from ..views.default import * @view_config(route_name='parametres', renderer='../templates/parametres/parametres.pt', permission='manage') def parametres(request): - logged_in = request.authenticated_userid.lower() + logged_in = request.authenticated_userid.upper() return { 'page_title': "Paramètres", @@ -168,7 +168,7 @@ def user_edit(request): @view_config(route_name='dashboard', renderer='../templates/parametres/dashboard.pt', permission='manage') def dashboard(request): - + # lire le log de nuit log_nuit = get_log_nuit(request) @@ -216,60 +216,36 @@ def rappels_rdv(request): 'nbRappels': nbRappels, } -@view_config(route_name='orphans_de', renderer='../templates/parametres/orphans_de.pt', permission='manage') -def orphans_de(request): +@view_config(route_name='stats_dd', renderer='../templates/parametres/stats_dd.pt', permission='view') +def stats_dd(request): societe = request.matchdict['societe'] - url = request.route_url('orphans_de', societe=societe) + url = request.route_url('stats_dd', societe=societe) message = '' societes = ['PE','ME','PL','PO','CD'] - nochantier = '0' # prendre en compte les paramètres de saisie if 'societe' in request.params: societe = request.params["societe"] - url = request.route_url('orphans_de', societe=societe) + url = request.route_url('stats_dd', societe=societe) - if 'form.nochantier' in request.params: - message = '' - nochantier = request.params['nochantier'] - - # oui, NestedMultiDict([('form.submitted', ''), ('id0', '271246'), ('id1', '370929')]) - for param in request.params: - if param[:2] == 'id': - update_nochantier(request, societe, request.params[param], int(nochantier)) - message = "Le numéro de chantier est mis à jour avec succès" + # lire les stats globales des demandes de devis + stats_dd = get_stats_dd(request, societe) - # lire le premier devis orphelin - devis = get_orphans_DE(request, societe) - - # lire tous les dossiers de ce chantier - dossiers = get_dossiers_byChantier(request, societe, '%s;%s;%s' % (devis.C_NOM, devis.C_ADR, devis.C_VILLE)) liste=[] - nochantiers=[] # construire la liste - for item in dossiers: - dossier_id = '%s-%s' % (item.TYPE, item.numero) - if item.nochantier != 0: - nochantiers.append(item.nochantier) - nochantier = item.nochantier - d = (dossier_id, dossier_id, item.date.strftime('%d-%m-%Y'), item.nomcli, item.chantier, to_euro(item.montant), - item.nosin, item.nochantier) + for item in stats_dd: + d = (str(item.Annee), str(item.Created), str(item.Devis), str(item.Commande), str(item.Facture), str(item.ReglePart), + str(item.Regle), str(item.Total)) liste.append(d) - - if len(nochantiers) == 0: - nochantiers.append(1) - + return { - 'page_title': "DEVIS orphelins", + 'page_title': "Stats : Demandes de devis", 'url': url, 'message': message, - 'devis': devis, 'dt_data': json.dumps(liste), 'societes': societes, 'societe': societe, - 'nochantiers': nochantiers, - 'nochantier': nochantier, } @view_config(route_name='rdf_causes', renderer='../templates/parametres/rdf_causes.pt', permission='manage') diff --git a/mondumas/views/utils.py b/mondumas/views/utils.py index 9cd914b..9888e10 100644 --- a/mondumas/views/utils.py +++ b/mondumas/views/utils.py @@ -31,8 +31,9 @@ def batch_nuit(request): # ----- effacer le log truncate_log(request) - # ----- PURGE des dosiers obsolètes - # todo + # ----- PURGE des données obsolètes + delete_orphan_attached_files(request) + # ----- RAPPELS DES RENDEZ-VOUS update_rappels(request) # attendre 5 secondes @@ -55,14 +56,12 @@ def notifier_rappels(request): rappels = get_email_rappels(request) nbLus = 0 - nbEmailVide = 0 nbEnvoyes = 0 for item in rappels: nbLus += 1 error = 0 if len(item.c_email) == 0 : - nbEmailVide += 1 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 @@ -153,6 +152,95 @@ def send_mail(request, expediteur, destinataires, objet, corps): else: msg = e # logguer l'erreur - insert_log(request, 'RAPPELS', "- MAILER ERROR : %s TO %s - %s" % (expediteur, destinataires, msg)) + insert_log(request, 'RAPPELS', "- MAILER ERROR : %s, TO : %s" % (msg, destinataires)) - return len(msg) \ No newline at end of file + 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') + + update_chantiers_status(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) + + +