from datetime import datetime import time import datetime from django.http import Http404 from rest_framework.exceptions import APIException from rest_framework.permissions import IsAdminUser, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView import datetime from ..models import Administre, PAM from ..models import StatutPamChoices as StatutPam from ..serializers import AlimentationSerializer from ..utils.alimentation_decorators import (data_perf_logger_factory, get_data_logger) from ..utils.decorators import execution_time, query_count from ..utils.extraction.administre import (to_table_administres_bo) from ..utils.insertion.administre import (insert_administre_bo, update_administre_fmob) from ..utils_extraction import (DataFrameTypes, FileTypes, read_files_by_type, to_table_administre_notation, to_table_affectation, to_table_diplome, to_table_domaines, to_table_fe, to_table_filieres, to_table_fmob_femp, to_table_fmob_fmob, to_table_fonctions, to_table_fud, to_table_garnisons, to_table_groupesMarques, to_table_marques, to_table_pam, to_table_postes, to_table_ref_gest, to_table_ref_org, to_table_ref_sv_fil, to_table_reo_ocv, to_table_sous_vivier, to_table_zone_geographique) from ..utils_insertion import (insert_PAM, insert_administre_notation, insert_Affectation, insert_Diplome, insert_Filiere, insert_FMOB_femp, insert_FMOB_fmob, insert_Fonction, insert_FormationEmploi, insert_Fud, insert_Garnison, insert_Grade, insert_Marque, insert_MarquesGroupe, insert_Poste, insert_RefFeMere, insert_RefGest, insert_RefOrg, insert_RefSvFil, insert_SousVivier, insert_SousVivier_instances, insert_ZoneGeographique, update_domaine, update_m2m_links_gestionnaire, update_poste_ocv, insert_delta) import pandas as pd class AlimentationView(APIView): """ Cette page est l'alimentation principale d'Ogure. Elle permet à l'administrateur de charger un ensemble de fichiers pour alimenter ou mettre à jour la base de données. """ permission_classes = [IsAuthenticated, IsAdminUser] serializer_class = AlimentationSerializer def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.logger = get_data_logger(self) def get(self, request): """La fonction get renvoie une reponse contenant Formulaire d'alimentation d'OGURE NG :type request: rest_framework.request.Request :param request: Request :return: - **return** (*json*): json contenant "Formulaire d'alimentation d'OGURE NG". """ return Response("Formulaire d'alimentation d'OGURE NG") @execution_time(logger_factory=data_perf_logger_factory) @query_count(logger_factory=data_perf_logger_factory) def post(self, request): """La fonction post charge les fichiers. :type request: rest_framework.request.Request :param request: Request contenant les fichiers :return: - **Response** (*Response*): Reponse contient les erreurs de chargement des données . """ try: # TODO: préparer une variable qui renvoie les erreurs sous 3 axes : données référentielles, administrés, postes serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) self.logger.info('---------------------Upload begining---------------------------') start_time = time.time() file_donnees_bo = serializer.validated_data.get('Donnees_BO_ADT') file_reo = serializer.validated_data.get('REO') file_reo_suivant = serializer.validated_data.get('REO_PAM_SUIVANT') file_reo_ocv = serializer.validated_data.get('REO_OCV') file_ref_gest = serializer.validated_data.get('referentiel_gestionnaire') file_ref_org = serializer.validated_data.get('referentiel_organique') file_ref_sv_fil = serializer.validated_data.get('refeferentiel_sous_vivier_filiere') file_ref_fe = serializer.validated_data.get('referentiel_fe') file_fmob = serializer.validated_data.get('FMOB') file_fmob_suivant = serializer.validated_data.get('FMOB_PAM_SUIVANT') file_filiere_domaine = serializer.validated_data.get('domaine_filiere') file_insee = serializer.validated_data.get('insee_maping') file_diplomes = serializer.validated_data.get('diplomes') file_fud = serializer.validated_data.get('FUD') file_ref_zones_geo = serializer.validated_data.get('ref_zones_geo') self.logger.info('---------------------Upload ending-----------------------------') self.logger.debug("--------------upload time -- %d seconds ------------------------", time.time() - start_time) df_by_type = read_files_by_type({ FileTypes.BO: file_donnees_bo, FileTypes.DIPLOME: file_diplomes, FileTypes.DOM_FIL: file_filiere_domaine, FileTypes.FMOB_FEMP: file_fmob, FileTypes.FMOB_FEMP_PAM_SUIVANT: file_fmob_suivant, FileTypes.FUD: file_fud, FileTypes.INSEE: file_insee, FileTypes.REF_FE: file_ref_fe, FileTypes.REF_GEO: file_ref_zones_geo, FileTypes.REF_GEST: file_ref_gest, FileTypes.REF_ORG: file_ref_org, FileTypes.REF_SV_FIL: file_ref_sv_fil, FileTypes.REO: file_reo, FileTypes.REO_PAM_SUIVANT: file_reo_suivant, FileTypes.REO_OCV: file_reo_ocv, }) DF = DataFrameTypes diplomes_df = df_by_type.get(DF.DIPLOME) donnees_bo_df = df_by_type.get(DF.BO) femp_df = df_by_type.get(DF.FEMP) filiere_domaine_df = df_by_type.get(DF.DOM_FIL) fmob_df = df_by_type.get(DF.FMOB) fud_df = df_by_type.get(DF.FUD) insee_df = df_by_type.get(DF.INSEE) ref_fe_df = df_by_type.get(DF.REF_FE) ref_gest_df = df_by_type.get(DF.REF_GEST) ref_org_df = df_by_type.get(DF.REF_ORG) ref_sv_fil_df = df_by_type.get(DF.REF_SV_FIL) ref_zones_geo_df = df_by_type.get(DF.REF_GEO) reo_df = df_by_type.get(DF.REO) reo_ocv_df = df_by_type.get(DF.REO_OCV) #dataframe pam + 1 femp_suivant_df = df_by_type.get(DF.FEMP_PAM_SUIVANT) fmob_suivant_df = df_by_type.get(DF.FMOB_PAM_SUIVANT) reo_suivant_df = df_by_type.get(DF.REO_PAM_SUIVANT) self.logger.info('-------------------- Insert beginning ---------------------') start_time_insert = time.time() text_response = [] if ref_sv_fil_df is not None: sv_cree, sv_modifie, sv_erreur, sv_supprime = insert_SousVivier(to_table_sous_vivier(ref_sv_fil_df)) text_response.append([f"Référentiel de sous-viviers/filières : {sv_cree} SousVivier créés, {sv_modifie} SousVivier mis à jour, {sv_erreur} SousVivier en erreur et {sv_supprime} SousVivier supprimés."]) self.logger.info('Sous-viviers ---------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : sous-viviers (nécessite %s)', DF.REF_SV_FIL.value[1]) if ref_org_df is not None: ref_org_cree, ref_org_modifie, ref_org_erreur, ref_org_supprime = insert_RefOrg(to_table_ref_org(ref_org_df)) text_response.append([f"Référentiel organique : {ref_org_cree} RefOrg créés, {ref_org_modifie} RefOrg mis à jour, {ref_org_erreur} RefOrg en erreur et {ref_org_supprime} RefOrg supprimés."]) self.logger.info('Référentiel organique ------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : référentiel organique') if ref_gest_df is not None: ref_gest_cree, ref_gest_modifie, ref_gest_erreur, ref_gest_supprime, user_cree, user_modifie, user_supprime, user_ignore = insert_RefGest(to_table_ref_gest(ref_gest_df)) text_response.append([f"Référentiel de gestionnaires : {ref_gest_cree} RefGest créés, {ref_gest_modifie} RefGest mis à jour, {ref_gest_erreur} RefGest en erreur et {ref_gest_supprime} RefGest supprimés."]) text_response.append([f"Référentiel de gestionnaires : {user_cree} User créés, {user_modifie} User mis à jour, {user_supprime} User supprimés et {user_ignore} User ignorés."]) self.logger.info('Référentiel gestionnaire ---------------------------> Succès') else: self.logger.info('Mise à jour ignorée : référentiel de gestionnaires') if ref_sv_fil_df is not None: ref_sv_cree, ref_sv_delete, ref_sv_erreur, ref_sv_ignore = insert_RefSvFil(to_table_ref_sv_fil(ref_sv_fil_df)) text_response.append([f"Référentiel de sous-viviers/filières : {ref_sv_cree} RefSvFil créés, {ref_sv_delete} RefSvFil supprimés, {ref_sv_erreur} RefSvFil en erreur et {ref_sv_ignore} RefSvFil ignorés."]) self.logger.info('Référentiel sous-vivier filière --------------------> Succès') else: self.logger.info('Mise à jour ignorée : référentiel de sous-viviers/filières') if ref_gest_df is not None or ref_org_df is not None or ref_sv_fil_df is not None: update_m2m_links_gestionnaire('SV') self.logger.info('Liens gestionnaires/sous-viviers -------------------> Succès') else: self.logger.info('Mise à jour ignorée : liens gestionnaires/sous-viviers (nécessite %s ou %s ou %s)', DF.REF_GEST.value[1], DF.REF_ORG.value[1], DF.REF_SV_FIL.value[1]) if filiere_domaine_df is not None: update_domaine(to_table_domaines(filiere_domaine_df)) self.logger.info('Domaine --------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : domaines (nécessite %s)', DF.DOM_FIL.value[1]) if insee_df is not None and donnees_bo_df is not None: gar_cree, gar_maj , error = insert_Garnison(to_table_garnisons(insee_df, donnees_bo_df)) text_response.append([f"INSEE et Données BO : {gar_cree} garnisons crées, {gar_maj} garnisons mises à jour, {error} garnisons en erreur."]) self.logger.info('Garnison -------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : garnisons (nécessite %s + %s)', DF.INSEE.value[1], DF.BO.value[1]) if reo_df is not None: reo_cree = insert_Fonction(to_table_fonctions(reo_df)) text_response.append([f"REO : {reo_cree} fonctions de postes créés."]) self.logger.info('Fonction -------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : fonctions (nécessite %s)', DF.REO.value[1]) if reo_suivant_df is not None: reo_suivant_cree = insert_Fonction(to_table_fonctions(reo_suivant_df)) text_response.append([f"REO : {reo_suivant_cree} fonctions de postes A+1 créés."]) self.logger.info('Fonction A+1 -------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : fonctions A + 1 (nécessite %s)', DF.REO_PAM_SUIVANT.value[1]) # TODO if .... insert_Grade() self.logger.info('Grade ----------------------------------------------> Succès') if filiere_domaine_df is not None: dom_fil_cree, dom_fil_modifie, dom_fil_erreur, dom_fil_supprime = insert_Filiere(to_table_filieres(filiere_domaine_df)) text_response.append([f"Domaines - filières : {dom_fil_cree} couples domaine/filière créés, {dom_fil_modifie} couples domaine/filière mis à jour, {dom_fil_erreur} couples domaine/filière en erreur et {dom_fil_supprime} couples domaine/filière supprimés."]) self.logger.info('Filières ------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : filières (nécessite %s)', DF.DOM_FIL.value[1]) # TODO if .... insert_MarquesGroupe(to_table_groupesMarques()) self.logger.info('MarquesGroupe -------------------------------------> Succès') # TODO if .... insert_Marque(to_table_marques()) self.logger.info('Marque --------------------------------------------> Succès') if ref_fe_df is not None: df = to_table_fe(ref_fe_df) self.logger.debug('Extraction des données du référentiel FE ----------> Succès') fe_cree, fe_maj, error_count = insert_FormationEmploi(df) text_response.append([f"Référentiel FE : {fe_cree} formation d'emplois créées, {fe_maj} formation d'emplois mises à jour, {error_count} formation d'emplois en erreur."]) self.logger.info('FormationEmplois ----------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : formations-emplois (nécessite %s)', DF.REF_FE.value[1]) if ref_fe_df is not None: insert_RefFeMere(ref_fe_df) self.logger.info('Référentiel FE mère -------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : formations-emplois mères (nécessite %s)', DF.REF_FE.value[1]) if ref_gest_df is not None or ref_org_df is not None or ref_fe_df is not None: update_m2m_links_gestionnaire('FE') self.logger.info('Liens gestionnaires/formations-emplois ------------> Succès') else: self.logger.info('Mise à jour ignorée : liens gestionnaires/formations-emplois (nécessite %s ou %s ou %s)', DF.REF_GEST.value[1], DF.REF_ORG.value[1], DF.REF_FE.value[1]) if donnees_bo_df is not None: bo_adm_cree, bo_adm_modifie, bo_adm_deja_modifie, bo_adm_erreur, bo_adm_ignore, bo_dom_ignore, bo_fil_ignore = insert_administre_bo(to_table_administres_bo(donnees_bo_df)) text_response.append([f"Données BO : {bo_adm_cree} administrés créés, {bo_adm_modifie} administrés mis à jour, {bo_adm_deja_modifie} adminsitrés déjà à jour, {bo_adm_erreur} administrés en erreur, {bo_adm_ignore} administrés ignorés, {bo_dom_ignore} domaines ignorés et {bo_fil_ignore} filières ignorées."]) self.logger.info('Administre ----------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : administrés (nécessite %s)', DF.BO.value[1]) if diplomes_df is not None: diplome_cree, diplome_maj, diplome_sup = insert_Diplome(to_table_diplome(diplomes_df)) text_response.append([f"Diplômes : {diplome_cree} diplômes créés, {diplome_maj} diplômes mis à jour, {diplome_sup} supprimés."]) self.logger.info('Diplome -------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : diplômes (nécessite %s)', DF.DIPLOME.value[1]) if donnees_bo_df is not None: donnee_bo_cree, donnee_bo_sup = insert_Affectation(to_table_affectation(donnees_bo_df)) text_response.append([f"Données BO : {donnee_bo_cree} affectation créés, {donnee_bo_sup} affectation mis à jour."]) self.logger.info('Affectations --------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : affectations (nécessite %s)', DF.BO.value[1]) if fud_df is not None: fud_cree, fud_sup = insert_Fud(to_table_fud(fud_df)) text_response.append([f"FUD : {fud_cree} FUD créés, {fud_sup} FUD supprimées."]) self.logger.info('FUD -----------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : FUD (nécessite %s)', DF.FUD.value[1]) if donnees_bo_df is not None: bo_cree, bo_maj, error_count = insert_administre_notation(to_table_administre_notation(donnees_bo_df)) text_response.append([f"Données BO : {bo_cree} notations créées, {bo_maj} notations mises à jour, {error_count} notations en erreurs."]) self.logger.info('Administre Notation -------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : administrés/notations (nécessite %s)', DF.BO.value[1]) if reo_df is not None: annee_pam = PAM.objects.get(pam_statut='PAM en cours').pam_id reo_cree, reo_suivant_cree, reo_modifie, reo_erreur, reo_ignore = insert_Poste(to_table_postes(reo_df),annee_pam) text_response.append([f"REO : {reo_cree} postes créés, {reo_modifie} postes mis à jour, {reo_erreur} postes en erreur et {reo_ignore} postes ignorés."]) self.logger.info('Poste ---------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : postes (nécessite %s)', DF.REO.value[1]) if reo_suivant_df is not None: annee_pam = PAM.objects.get(pam_statut='PAM A+1').pam_id reo_cree, reo_suivant_cree, reo_modifie, reo_erreur, reo_ignore = insert_Poste(to_table_postes(reo_suivant_df),annee_pam) #info reo text_response.append([f"REO A + 1 : {reo_suivant_cree} postes A+1 créés, {reo_erreur} postes A+1 en erreur et {reo_ignore} postes A+1 ignorés."]) self.logger.info('Poste A+1 ---------------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : postes A + 1 (nécessite %s)', DF.REO_PAM_SUIVANT.value[1]) if reo_suivant_df is not None: self.logger.info('Calcul du delta de la colonne Info REO, veuillez patienter ...') insert_delta(to_table_postes(reo_suivant_df)) text_response.append([f"Mise à jour de la colonne info REO"]) self.logger.info('Calcul du delta Info Reo ---------------------------------------------> Succès') else: self.logger.info('Mise à jour de la colonne "info reo" ignorée') # TODO if .... insert_SousVivier_instances() self.logger.info('Sous-viviers instances ---------------------------> Succès') if reo_ocv_df is not None: reo_ocv_modifie, reo_ocv_erreur, reo_ocv_ignore = update_poste_ocv(to_table_reo_ocv(reo_ocv_df)) text_response.append([f"Requêtes OCV : {reo_ocv_modifie} postes-ocv mis à jour, {reo_ocv_erreur} postes-ocv en erreur et {reo_ocv_ignore} postes-ocv ignorés."]) self.logger.info('Poste-ocv -----------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : postes/administrés (nécessite %s)', DF.REO_OCV.value[1]) if ref_zones_geo_df is not None: ref_zones_geo_df_cree, ref_zones_geo_df_sup, error_count = insert_ZoneGeographique(to_table_zone_geographique(ref_zones_geo_df)) text_response.append([f"Référentiels Zones Géographiques : {ref_zones_geo_df_cree} zones-geo créées, {ref_zones_geo_df_sup} zones-geo supprimés et {error_count} zones-geo en erreur."]) self.logger.info('Référentiel zones géographiques -------------------> Succès') else: self.logger.info('Mise à jour ignorée : zones géographiques (nécessite %s)', DF.REF_GEO.value[1]) if fmob_df is not None: fmob_cree, fmob_maj, ignore_count = insert_FMOB_fmob(to_table_fmob_fmob(fmob_df)) text_response.append([f"Formulaire de mobilité : {fmob_cree} fmob créés, {fmob_maj} fmob mis à jour et {ignore_count} fmob ignorés."]) self.logger.debug('Fichier FMOB --------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : FMOB (nécessite %s)', DF.FMOB.value[1]) if femp_df is not None: femp_cree, femp_maj, ignore_count = insert_FMOB_femp(to_table_fmob_femp(femp_df)) text_response.append([f"Formulaire de mobilité : {femp_cree} femp créés, {femp_maj} femp mis à jour et {ignore_count} femp ignorés."]) self.logger.debug('Fichier FEMP --------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : FEMP (nécessite %s)', DF.FEMP.value[1]) if fmob_suivant_df is not None: fmob_cree, fmob_maj, ignore_count = insert_FMOB_fmob(to_table_fmob_fmob(fmob_suivant_df)) text_response.append([f"Formulaire de mobilité A+1 : {fmob_cree} fmob A+1 créés, {fmob_maj} fmob A+1 mis à jour et {ignore_count} fmob A+1 ignorés."]) self.logger.debug('Fichier FMOB A+1--------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : FMOB A + 1(nécessite %s)', DF.FMOB_PAM_SUIVANT.value[1]) if femp_suivant_df is not None: femp_cree, femp_maj, ignore_count = insert_FMOB_femp(to_table_fmob_femp(femp_suivant_df)) text_response.append([f"Formulaire de mobilité A+1 : {femp_cree} femp A+1 créés, {femp_maj} femp A+1 mis à jour et {ignore_count} femp A+1 ignorés."]) self.logger.debug('Fichier FEMP A+1 --------------------------------------> Succès') else: self.logger.info('Mise à jour ignorée : FEMP A + 1(nécessite %s)', DF.FEMP_PAM_SUIVANT.value[1]) if fmob_df is not None: a_maintenir, a_traiter = update_administre_fmob(to_table_fmob_fmob(fmob_df)) text_response.append([f"Formulaire de mobilité : {a_maintenir} administrés mis à jour en 'A maintenir' car FMOB annulé, {a_traiter} administrés mis à jour en 'A muter' car ils ont un FMOB."]) self.logger.debug('Mise à jour du statut PAM si annulation FMOB et si FMOB existe------> Succès') else: self.logger.info('Mise à jour ignorée : statut PAM si annulation FMOB (nécessite %s ou %s)', DF.BO.value[1], DF.FMOB.value[1]) if fmob_suivant_df is not None: a_maintenir, a_traiter = update_administre_fmob(to_table_fmob_fmob(fmob_suivant_df)) text_response.append([f"Formulaire de mobilité A+1 : {a_maintenir} administrés A+1 mis à jour en 'A maintenir' car FMOB annulé, {a_traiter} administrés A+1 mis à jour en 'A muter' car ils ont un FMOB A+1."]) self.logger.debug('Mise à jour du statut PAM A+1 si annulation FMOB et si FMOB existe ------> Succès') else: self.logger.info('Mise à jour ignorée : statut PAM A+1 si annulation FMOB (nécessite %s ou %s)', DF.BO.value[1], DF.FMOB_PAM_SUIVANT.value[1]) self.logger.debug('Administres Pams -------------------------> Success') self.logger.debug('--------------- Insert time : %d seconds -----------------', time.time() - start_time_insert) self.logger.info('---------------------- Insert ending ----------------------') text_response_df = pd.DataFrame(text_response) if text_response_df.empty: return Response(text_response_df) else: return Response(text_response_df[0]) except (Http404, APIException): raise except BaseException: message = "Impossible d'alimenter le(s) référentiel(s)" self.logger.exception(message) raise APIException(message)