""" Traite les données importées dans PDA pour peupler les tables de la base AGRHum usage: agrhum_traitement [-c ] [-m ] [-a ] [--auto] Options: -c Code de l'agent à traiter -m Mois -a Annee --auto Pas d'interaction utilisateur -h, --help Affiche l'aide @author: emmanuel.pheulpin et olivier.massot, juill 2018 """ from datetime import datetime import logging from docopt import docopt from path import Path # @UnusedImport from core import logconf from core.model import Sql from core.pde import AgrhumDb , FraisDeplacement, HeureSupp logger = logging.getLogger("agrhum_traitement") logconf.start("agrhum_traitement", logging.DEBUG) # # POUR TESTER, décommenter les lignes suivantes ##----------------------------------------------- # AgrhumDb._path = Path(r"\\h2o\local\4-transversal\BDD\mdb_test\BDD_ParcRH.mdb") # logger.handlers = [h for h in logger.handlers if (type(h) == logging.StreamHandler)] # logger.warning("<<<<<<<<<<<<<< Mode TEST >>>>>>>>>>>>>>>>>") ##----------------------------------------------- agrhum_db = AgrhumDb(autocommit=False) # Vérification dans la table tbl_suiviRH si la ligne agent mois annnée existe # Vérification si état != de Importé ou si valide = True : demande confirmation pour retraitement # Si retraitement on supprime des tables cibles tbl_formHS et tbl_formDep # Parcours de tbl_importRH transfo donnée et écriture dans tbl_formdep # Parcours de tbl_importRH transfo donnée et écriture dans tbl_formHS def main(CodeAgent, MoisRH, AnneeRH, auto=False): logger.error("> Traitement des données de l'agent %s pour le mois %s/%s", CodeAgent, MoisRH, AnneeRH) suivi = agrhum_db.first(Sql.format("SELECT * FROM tbl_SuiviRH WHERE CodeAgent ={:text} AND MoisRH = {} AND AnneeRH = {}", CodeAgent, MoisRH, AnneeRH)) if not suivi: logger.error("Les données de l'agent %s pour le mois %s/%s n'ont pas été importées dans la base PDA. Opération annulée.", CodeAgent, MoisRH, AnneeRH) return if suivi.Etat == "Validé": logger.error("Impossible de traiter des données qui ont déjà été validées. Opération annulée.") return if agrhum_db.exists(Sql.format("SELECT * FROM tbl_FormDep WHERE CodeAgent ={:text} AND MoisRH = {} AND AnneeRH = {}", CodeAgent, MoisRH, AnneeRH)): logger.warning("Les données de l'agent %s pour le mois %s/%s ont déjà été traitées. Les anciennes données vont être remplacées.", CodeAgent, MoisRH, AnneeRH) logger.info(">> Effacement des anciennes données") agrhum_db.execute(Sql.format("DELETE * FROM tbl_FormDep WHERE CodeAgent ={:text} AND MoisRH = {} AND AnneeRH = {}", CodeAgent, MoisRH, AnneeRH)) agrhum_db.execute(Sql.format("DELETE * FROM tbl_FormHS WHERE CodeAgent ={:text} AND MoisRH = {} AND AnneeRH = {}", CodeAgent, MoisRH, AnneeRH)) # Chargement des baremes en memoire sql = Sql.format("""SELECT tbl_baremes.NomBareme, tbl_baremes.BorneInf, tbl_baremes.BorneSup, tbl_baremes.Valeur, tbl_PeriodeBareme.DateInf, tbl_PeriodeBareme.DateSup FROM tbl_baremes INNER JOIN tbl_PeriodeBareme ON (tbl_baremes.PeriodeValidite = tbl_PeriodeBareme.CodePeriode) AND (tbl_baremes.NomBareme = tbl_PeriodeBareme.NomBareme) WHERE tbl_baremes.NomBareme = 'Heures de route' or tbl_baremes.NomBareme = 'Heures de route (nuit)' AND tbl_PeriodeBareme.DateInf <= {:date} AND (tbl_PeriodeBareme.DateSup is null or tbl_PeriodeBareme.DateSup > {:date}) """, datetime(AnneeRH, MoisRH, 1), datetime(AnneeRH, MoisRH, 1)) baremes = agrhum_db.read_all(sql) logger.info("Parcours des données") data = agrhum_db.read_all(Sql.format("""SELECT * FROM tbl_ImportRh WHERE codeagent ={:text} AND Month([daterh]) = {} AND Year([daterh]) = {} ORDER BY DateRH""", CodeAgent, MoisRH, AnneeRH)) logger.info("Mise à jour de frais de déplacement") # Parcours des données de la requête index_dep = {} for el in data : # Génération des objets FraisDeplacement if not el.DateRH.day in index_dep : fraisdep = FraisDeplacement() fraisdep.IDSuivi = suivi.IDSuivi fraisdep.AnneeRH = AnneeRH fraisdep.CodeAgent = CodeAgent fraisdep.MoisRH = MoisRH fraisdep.JourRH = el.DateRH.day fraisdep.Depart = el.Depart # mettre a jour le codedepart fraisdep.Itineraire = " - ".join([loc for loc in (fraisdep.Depart, el.Localisation) if loc]) fraisdep.Distance1_perso = int(el.DistanceTranche1) if el.VehiculePersoTranche1 else 0 fraisdep.Distance2_perso = int(el.DistanceTranche2) if el.VehiculePersoTranche2 else 0 fraisdep.Distance2_service = int(el.DistanceTranche2) if not el.VehiculePersoTranche2 else 0 fraisdep.Repas = int(el.Repas) fraisdep.Valide = True # Indexation des objets par jour index_dep[el.DateRH.day] = fraisdep else : # Mise à jour d'un objet existant index_dep[el.DateRH.day].Itineraire += " - {}".format(el.Localisation) index_dep[el.DateRH.day].Distance1_perso += int(el.DistanceTranche1) if el.VehiculePersoTranche1 else 0 index_dep[el.DateRH.day].Distance2_perso += int(el.DistanceTranche2) if el.VehiculePersoTranche2 else 0 index_dep[el.DateRH.day].Distance2_service += int(el.DistanceTranche2) if not el.VehiculePersoTranche2 else 0 index_dep[el.DateRH.day].Repas += int(el.Repas) # Insertion des données en base for fraisdep in index_dep.values() : distance2 = (fraisdep.Distance2_perso + fraisdep.Distance2_service) fraisdep.HeuresDep = next((bareme.Valeur for bareme in baremes if bareme.NomBareme == 'Heures de route' and bareme.BorneInf <= distance2 and bareme.BorneSup >= distance2)) fraisdep.HeuresDepNuit = next((bareme.Valeur for bareme in baremes if bareme.NomBareme == 'Heures de route (nuit)' and bareme.BorneInf <= distance2 and bareme.BorneSup >= distance2)) sql = Sql.format("""INSERT INTO tbl_FormDep ( IDSuivi, CodeAgent, JourRH, MoisRH, AnneeRH, Depart, Itineraire, Distance2_perso, Distance2_service, Distance1_perso, HeuresDep, HeuresDepNuit, Repas, Remarque, Valide, CreePar, CreeLe ) VALUES ({fraisdep.IDSuivi}, {fraisdep.CodeAgent:text}, {fraisdep.JourRH}, {fraisdep.MoisRH}, {fraisdep.AnneeRH}, {fraisdep.Depart:text}, {fraisdep.Itineraire:text}, {fraisdep.Distance2_perso}, {fraisdep.Distance2_service}, {fraisdep.Distance1_perso}, {fraisdep.HeuresDep}, {fraisdep.HeuresDepNuit}, {fraisdep.Repas}, {fraisdep.Remarque:text}, {fraisdep.Valide}, {fraisdep.CreePar:text}, {fraisdep.CreeLe:date})""", fraisdep=fraisdep) agrhum_db.execute(sql) # on re-parcourt des données de la requête logger.info("Mise à jour des heures supplémentaires") index_hs = {} for el in data : if not el.DateRH.day in index_hs : hs = HeureSupp() hs.IDSuivi = suivi.IDSuivi hs.AnneeRH = AnneeRH hs.CodeAgent = CodeAgent hs.MoisRH = MoisRH hs.JourRH = el.DateRH.day hs.HeureSup1 = el.HeureSup1 hs.HeuresDep = index_dep[el.DateRH.day].HeuresDep hs.HeuresDepNuit = index_dep[el.DateRH.day].HeuresDepNuit hs.HeureSupNuit = float(el.HeureSup2) + hs.HeuresDepNuit hs.HeureSupDim = el.HeureSupDimanche hs.HS_VHCanal = float(el.HeureSup1) + float(el.HeureSup2) + float(el.HeureSupDimanche) if el.strCategorieInterventionId == "07" else 0.0 hs.HS_Chantier = float(el.HeureSup1) + float(el.HeureSup2) + float(el.HeureSupDimanche) if el.strCategorieInterventionId != "07" else 0.0 hs.Valide = True index_hs[el.DateRH.day] = hs else : index_hs[el.DateRH.day].HeureSup1 += float(el.HeureSup1) index_hs[el.DateRH.day].HeureSupNuit += float(el.HeureSup2) index_hs[el.DateRH.day].HeureSupDim += float(el.HeureSupDimanche) index_hs[el.DateRH.day].HS_VHCanal += float(el.HeureSup1) + float(el.HeureSup2) + float(el.HeureSupDimanche) if el.strCategorieInterventionId == "07" else 0.0 index_hs[el.DateRH.day].HS_Chantier += float(el.HeureSup1) + float(el.HeureSup2) + float(el.HeureSupDimanche) if el.strCategorieInterventionId != "07" else 0.0 # Calcul des dépassements du seuil des 14h # NB: On mesure le depassement uniquement pour les heures de jour, # mais on tient compte des autres heures pour le cumul cumulmois = 0.0 for hs in sorted(index_hs.values(), key=lambda x: x.JourRH) : hsjour = hs.HeureSup1 + hs.HeuresDep if cumulmois > 14: hs.HeureSup1_inf_14 = 0.0 hs.HeureSup1_sup_14 = hsjour elif cumulmois + hsjour > 14: hs.HeureSup1_inf_14 = 14.0 - cumulmois hs.HeureSup1_sup_14 = (cumulmois + hsjour) - 14.0 else: hs.HeureSup1_inf_14 = hsjour hs.HeureSup1_sup_14 = 0.0 cumulmois += (hsjour + hs.HeureSupNuit + hs.HeureSupDim) # Insertion en base for hs in index_hs.values() : sql = Sql.format("""INSERT INTO tbl_FormHS ( IDSuivi, CodeAgent, JourRH, MoisRH, AnneeRH, HeureSup1, HeuresDep, HeuresDepNuit, [HeureSup1<=14], [HeureSup1>14], HeureSupNuit, HeureSupDim, HS_VHCanal, HS_Chantier, Valide, CreePar, CreeLe ) VALUES ({hs.IDSuivi}, {hs.CodeAgent:text}, {hs.JourRH}, {hs.MoisRH}, {hs.AnneeRH}, {hs.HeureSup1}, {hs.HeuresDep}, {hs.HeuresDepNuit}, {hs.HeureSup1_inf_14}, {hs.HeureSup1_sup_14}, {hs.HeureSupNuit}, {hs.HeureSupDim}, {hs.HS_VHCanal}, {hs.HS_Chantier}, {hs.Valide}, {hs.CreePar:text}, {hs.CreeLe:date}) """, hs=hs) agrhum_db.execute(sql) # Commit des données logger.info("Commit des modifications") agrhum_db.commit() if __name__ == "__main__": # Parse les arguments args = docopt(__doc__, help=False) CodeAgent = args["-c"] if args["-c"] else None MoisRH = args["-m"] if args["-m"] else None AnneeRH = args["-a"] if args["-a"] else None if not CodeAgent: CodeAgent = input("Veuillez saisir le code de l'agent à traiter (ex: T9): ") if not MoisRH: MoisRH = input("Veuillez saisir le mois (ex: 3): ") if not AnneeRH: AnneeRH = input("Veuillez saisir l'année (ex: 2018): ") main(CodeAgent, int(MoisRH), int(AnneeRH), args["--auto"]) logger.info("-- Fin --")