import time import pandas as pd import numpy as np from django.utils import timezone from django.db.transaction import atomic from django.http import Http404, HttpResponse 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 from ..utils_extraction import APP_NAN from ..utils.alimentation import BOCols, ReoCols from ..serializers import ExportationSerializer from ..models import Administre, Affectation, Administre_Notation, Poste, FichiersExporte from ..utils.alimentation_decorators import (data_perf_logger_factory, get_data_logger) from ..utils.decorators import execution_time, query_count class ExportationFichiersView(APIView): """ Vue pour exporter les données de la base dans des fichiers au format de ceux utilisés pour l'insertion""" permission_classes = [IsAuthenticated, IsAdminUser] serializer_class = ExportationSerializer def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.logger = get_data_logger(self) def get(self, request): resp = [] resp.append(["Formulaire d\'OGURE NG permettant d'exporter les données de la base au format des fichiers d'insertion."]) resp.append(["Selectionnez le fichier que vous souhaitez exporter puis appuyez sur le bouton 'POST' pour lancer l'exportation."]) resp = pd.DataFrame(resp) return Response(resp[0]) def export_adm_bo_df(self): self.logger.info("Lecture et traitement de la table des administrés... ") start_time_adm = time.time() Cols = Administre.Cols administres = Administre.objects.all().values_list( Cols.PK, Cols.REL_GRADE, 'a_nom', 'a_prenom', 'a_id_def', 'a_eip', 'a_eis', 'a_domaine_gestion', Cols.REL_DOMAINE, Cols.REL_FILIERE, 'a_nf', 'a_arme', 'a_rg_origine_recrutement', 'a_date_entree_service', 'a_nombre_enfants', 'a_origine_recrutement', 'a_date_naissance', 'a_fonction', 'a_diplome_hl', 'a_dernier_diplome', 'a_date_rdc', 'a_credo_fe', f'{Cols.REL_FORMATION_EMPLOI}__fe_garnison_lieu', 'a_date_arrivee_fe', 'a_date_dernier_acr', 'a_pos_statuaire', 'a_date_pos_statuaire', 'a_interruption_service', 'a_grade_date_debut', 'a_profession_conjoint', 'a_sap_conjoint', 'a_id_def_conjoint', 'a_sexe_conjoint', 'a_date_fonction1', 'a_fonction1', 'a_date_fonction2', 'a_fonction2', 'a_date_fonction3', 'a_fonction3', 'a_date_fonction4', 'a_fonction4', 'a_date_fonction5', 'a_fonction5', 'a_date_fonction6', 'a_fonction6', 'a_date_fonction7', 'a_fonction7', 'a_date_fonction8', 'a_fonction8', 'a_date_fonction9', 'a_fonction9', 'a_date_mariage', 'a_situation_fam', 'a_sexe', 'a_date_fud', 'a_fud', Cols.DATE_STATUT_CONCERTO, Cols.STATUT_CONCERTO, Cols.DATE_STATUT_CONCERTO_FUTUR, Cols.STATUT_CONCERTO_FUTUR, 'a_domaine_poste', 'a_filiere_poste', 'a_nf_poste', 'a_lien_service', 'a_marqueur_pn', 'a_pls_gb_max', 'a_enfants', ) administres_df = pd.DataFrame.from_records(administres) adm_bo_cols = BOCols.columns( BOCols.ID_SAP, # A BOCols.GRADE, # B BOCols.NOM, # C BOCols.PRENOM, # D BOCols.ID_DEF, # E BOCols.EIP, # F BOCols.EIS, # G BOCols.DOMAINE_GESTION, # H BOCols.DOMAINE, # I BOCols.FILIERE, # J BOCols.NF, # K BOCols.ARME, # L BOCols.REGROUPEMENT_ORIGINE_RECRUTEMENT, # M BOCols.DATE_ENTREE_SERVICE, # N BOCols.NOMBRE_ENFANTS, # O BOCols.ORIGINE_RECRUTEMENT, # Q BOCols.DATE_NAISSANCE, # R BOCols.FONCTION, # T BOCols.DIPLOME_PLUS_HAUT_NIVEAU, # U BOCols.DERNIER_DIPLOME, # V BOCols.DATE_RDC, # W BOCols.CREDO_FE, # X BOCols.GARNISON, # Z (utilisé dans la table des garnisons) BOCols.DATE_ARRIVEE_FE, # AA BOCols.DATE_DERNIER_ACR, # AC BOCols.POSITION_STATUTAIRE, # AE BOCols.DATE_POSITION_STATUAIRE, # AF BOCols.INTERRUPTION_SERVICE, # AG BOCols.DATE_DEBUT_GRADE, # AH BOCols.PROFESSION_CONJOINT, # AL BOCols.ID_SAP_CONJOINT, # AM BOCols.ID_DEF_CONJOINT, # AN BOCols.SEXE_CONJOINT, # AT BOCols.DATE_FONCTION_1, # BM BOCols.FONCTION_1, # BN BOCols.DATE_FONCTION_2, # BO BOCols.FONCTION_2, # BP BOCols.DATE_FONCTION_3, # BQ BOCols.FONCTION_3, # BR BOCols.DATE_FONCTION_4, # BS BOCols.FONCTION_4, # BT BOCols.DATE_FONCTION_5, # BU BOCols.FONCTION_5, # BV BOCols.DATE_FONCTION_6, # BW BOCols.FONCTION_6, # BX BOCols.DATE_FONCTION_7, # BY BOCols.FONCTION_7, # BZ BOCols.DATE_FONCTION_8, # CA BOCols.FONCTION_8, # CB BOCols.DATE_FONCTION_9, # CC BOCols.FONCTION_9, # CD BOCols.DATE_MARIAGE, # CH BOCols.SITUATION_FAMILIALE, # CI BOCols.SEXE, # CJ BOCols.DATE_FUD, # DV BOCols.FUD, # DW BOCols.DATE_STATUT_CONCERTO, # DX BOCols.STATUT_CONCERTO, # DY BOCols.DATE_STATUT_CONCERTO_FUTUR, # DZ BOCols.STATUT_CONCERTO_FUTUR, # EA BOCols.DOMAINE_POSTE, # ED (non utilisé) BOCols.FILIERE_POSTE, # EE (non utilisé) BOCols.NF_POSTE, # EF (non utilisé) BOCols.DATE_LIEN_SERVICE, # EG BOCols.MARQUEUR_PN, # EH BOCols.PLS_GB_MAX, # EI BOCols.ENFANTS, # EK ) administres_df.columns = adm_bo_cols # Changement des types des colonnes dates administres_df[BOCols.DATE_ARRIVEE_FE] = pd.to_datetime(administres_df[BOCols.DATE_ARRIVEE_FE], errors='coerce').dt.strftime('%d/%m/%Y') # AA administres_df[BOCols.DATE_DEBUT_GRADE] = pd.to_datetime(administres_df[BOCols.DATE_DEBUT_GRADE], errors='coerce').dt.strftime('%d/%m/%Y') # AH administres_df[BOCols.DATE_DERNIER_ACR] = pd.to_datetime(administres_df[BOCols.DATE_DERNIER_ACR], errors='coerce').dt.strftime('%d/%m/%Y') # AC administres_df[BOCols.DATE_ENTREE_SERVICE] = pd.to_datetime(administres_df[BOCols.DATE_ENTREE_SERVICE], errors='coerce').dt.strftime('%d/%m/%Y') # N administres_df[BOCols.DATE_FUD] = pd.to_datetime(administres_df[BOCols.DATE_FUD], errors='coerce').dt.strftime('%d/%m/%Y') # DV administres_df[BOCols.DATE_LIEN_SERVICE] = pd.to_datetime(administres_df[BOCols.DATE_LIEN_SERVICE], errors='coerce').dt.strftime('%d/%m/%Y') # EG administres_df[BOCols.DATE_NAISSANCE] = pd.to_datetime(administres_df[BOCols.DATE_NAISSANCE], errors='coerce').dt.strftime('%d/%m/%Y') # R administres_df[BOCols.DATE_POSITION_STATUAIRE] = pd.to_datetime(administres_df[BOCols.DATE_POSITION_STATUAIRE], errors='coerce').dt.strftime('%d/%m/%Y') # AF administres_df[BOCols.DATE_RDC] = pd.to_datetime(administres_df[BOCols.DATE_RDC], errors='coerce').dt.strftime('%d/%m/%Y') # W administres_df[BOCols.DATE_STATUT_CONCERTO] = pd.to_datetime(administres_df[BOCols.DATE_STATUT_CONCERTO], errors='coerce').dt.strftime('%d/%m/%Y') # DX administres_df[BOCols.DATE_STATUT_CONCERTO_FUTUR] = pd.to_datetime(administres_df[BOCols.DATE_STATUT_CONCERTO_FUTUR], errors='coerce').dt.strftime('%d/%m/%Y') # DZ administres_df[BOCols.DATE_MARIAGE] = pd.to_datetime(administres_df[BOCols.DATE_MARIAGE], errors='coerce').dt.strftime('%d/%m/%Y') # CH for i in range(1, 10): administres_df[f'Fonction -{i} DD'] = pd.to_datetime(administres_df[f'Fonction -{i} DD']).dt.strftime('%d/%m/%Y') # Changement des types des colonnes bool administres_df[[BOCols.MARQUEUR_PN]] = administres_df[[BOCols.MARQUEUR_PN]].replace([True, False], ['X', None]) # CHangement des types des colonnes int administres_df[BOCols.ID_SAP_CONJOINT] = administres_df[BOCols.ID_SAP_CONJOINT].fillna(0).astype(int).replace({0: None}) administres_df[BOCols.PLS_GB_MAX] = administres_df[BOCols.PLS_GB_MAX].fillna(0).astype(int).replace({0: None}) administres_df = (administres_df.fillna(APP_NAN) .replace({APP_NAN: None}) .replace({np.nan: None}) .replace({'nan': None})) self.logger.info("Table des administrés lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_adm, administres_df.shape[0], administres_df.shape[1]) return administres_df def export_aff_bo_df(self): self.logger.info("Lecture et traitement de la table des affectations... ") start_time_aff = time.time() aff = pd.DataFrame.from_records(Affectation.objects.all().values()).sort_values('affect_date', ascending=False) aff_grouped = aff.groupby(['administre_id']).agg( affect_libelle=('affect_libelle', ',,,'.join), affect_date=('affect_date', ',,,'.join), ) aff_date_cols = [f'Affectation -{i} DD' for i in range(1,10)] aff_libelle_cols = [f'Affectation -{i} L' for i in range(1,10)] aff_date_df = aff_grouped['affect_date'].str.split(',,,', expand=True) aff_libelle_df = aff_grouped['affect_libelle'].str.split(',,,', expand=True) nb_cols_date = aff_date_df.shape[1] nb_cols_libelle = aff_date_df.shape[1] aff_date_cols_tronc = aff_date_cols[:nb_cols_date] aff_libelle_cols_tronc = aff_libelle_cols[:nb_cols_libelle] aff_grouped[aff_date_cols_tronc] = aff_date_df aff_grouped[aff_libelle_cols_tronc] = aff_libelle_df aff_grouped = (aff_grouped.drop(['affect_libelle', 'affect_date'], axis=1) .reset_index()) # Changement des types des colonnes dates for i in range(1, 10): aff_grouped[f'Affectation -{i} DD'] = pd.to_datetime(aff_grouped[f'Affectation -{i} DD']).dt.strftime('%d/%m/%Y') aff_grouped = (aff_grouped.fillna(APP_NAN) .replace({APP_NAN: None}) .replace({np.nan: None}) .replace({'nan': None})) self.logger.info("Table des affectations lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_aff, aff_grouped.shape[0], aff_grouped.shape[1]) return aff_grouped def export_no_bo_df(self): self.logger.info("Lecture et traitement de la table des notations... ") start_time_no = time.time() no = pd.DataFrame.from_records(Administre_Notation.objects.all().values()).sort_values('no_age_annees', ascending=False) no_grouped = no.groupby(["administre_id"]).agg( no_annne_de_notation=("no_annne_de_notation", ",,,".join), no_nr_ou_iris=("no_nr_ou_iris", ",,,".join), no_rac_ou_iris_cumule=("no_rac_ou_iris_cumule", ",,,".join), no_rf_qsr=("no_rf_qsr", ",,,".join), no_aptitude_emploie_sup=("no_aptitude_emploie_sup", ",,,".join), no_potentiel_responsabilite_sup=("no_potentiel_responsabilite_sup", ",,,".join), no_age_annees=("no_age_annees", ",,,".join), ) no_age_annees_cols = ['Age en années (au 31/12)'] no_annne_de_notation_cols = ['Année notation A'] + [f'Année notation A-{i}' for i in range(1,6)] no_nr_ou_iris_cols = ['IRIS / RAC retenu A'] + [f'IRIS / RAC retenu A-{i}' for i in range(1,6)] no_rac_ou_iris_cumule_cols = ['NR/NGC cumulé A'] + [f'NR/NGC cumulé A-{i}' for i in range(1,6)] no_rf_qsr_cols = ['QSR A'] + [f'QSR A-{i}' for i in range(1,6)] no_aptitude_emploie_sup_cols = ['Apt resp / Emp sup A'] + [f'Apt resp / Emp sup A-{i}' for i in range(1,6)] no_potentiel_responsabilite_sup_cols = ['Potentiel responsabilités catégorie sup A'] + [f'Potentiel responsabilités catégorie sup A-{i}' for i in range(1,6)] no_grouped[no_age_annees_cols] = no_grouped['no_age_annees'].str.split(',,,', expand=True)[0] no_grouped[no_annne_de_notation_cols] = no_grouped['no_annne_de_notation'].str.split(',,,', expand=True) no_grouped[no_nr_ou_iris_cols] = no_grouped['no_nr_ou_iris'].str.split(',,,', expand=True) no_grouped[no_rac_ou_iris_cumule_cols] = no_grouped['no_rac_ou_iris_cumule'].str.split(',,,', expand=True) no_grouped[no_rf_qsr_cols] = no_grouped['no_rf_qsr'].str.split(',,,', expand=True) no_grouped[no_aptitude_emploie_sup_cols] = no_grouped['no_aptitude_emploie_sup'].str.split(',,,', expand=True) no_grouped[no_potentiel_responsabilite_sup_cols] = no_grouped['no_potentiel_responsabilite_sup'].str.split(',,,', expand=True) no_grouped = (no_grouped.drop(['no_annne_de_notation', 'no_nr_ou_iris', 'no_rac_ou_iris_cumule', 'no_rf_qsr', 'no_aptitude_emploie_sup', 'no_potentiel_responsabilite_sup', 'no_age_annees'], axis=1) .reset_index()) # Changement des types des colonnes int no_grouped[f'Année notation A'] = no_grouped[f'Année notation A'].astype(float).fillna(0).astype(int).replace({0: None}) no_grouped[f'IRIS / RAC retenu A'] = no_grouped[f'IRIS / RAC retenu A'].astype(float).fillna(0).astype(int).replace({0: None}) no_grouped[f'NR/NGC cumulé A'] = no_grouped[f'NR/NGC cumulé A'].astype(float).fillna(0).astype(int).replace({0: None}) for i in range(1, 6): no_grouped[f'Année notation A-{i}'] = no_grouped[f'Année notation A-{i}'].astype(float).fillna(0).astype(int).replace({0: None}) no_grouped[f'IRIS / RAC retenu A-{i}'] = no_grouped[f'IRIS / RAC retenu A-{i}'].astype(float).fillna(0).astype(int).replace({0: None}) no_grouped[f'NR/NGC cumulé A-{i}'] = no_grouped[f'NR/NGC cumulé A-{i}'].astype(float).fillna(0).astype(int).replace({0: None}) no_grouped = (no_grouped.fillna(APP_NAN) .replace({APP_NAN: None}) .replace({np.nan: None}) .replace({'nan': None})) self.logger.info("Table des notations lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_no, no_grouped.shape[0], no_grouped.shape[1]) return no_grouped def export_pos_reo_df(self): self.logger.info("Lecture et traitement de la table des postes... ") start_time_pos = time.time() Cols = Poste.Cols postes = Poste.objects.all().values_list( 'p_annee', Cols.REL_FORMATION_EMPLOI, 'p_dep', Cols.CATEGORIE, 'p_eip', Cols.REL_DOMAINE, Cols.REL_FILIERE, Cols.NIVEAU_FONCTIONNEL, Cols.PK, f'{Cols.REL_FONCTION}__fon_id', f'{Cols.REL_FONCTION}__fon_libelle', 'p_nfs', ) postes_df = pd.DataFrame.from_records(postes) pos_reo_cols = ReoCols.columns( ReoCols.ANNEE_PROJET, # B ReoCols.FORMATION_EMPLOI, # F ReoCols.CODE_POSTAL, # J ReoCols.CATEGORIE, # P ReoCols.EIP, # T ReoCols.DOMAINE, # U ReoCols.FILIERE, # V ReoCols.CODE_NF, # W ReoCols.ID_POSTE, # X ReoCols.FONCTION_ID, # Y ReoCols.FONCTION_LIBELLE, # Z ReoCols.DOMAINE_GESTION, # AA ) postes_df.columns = pos_reo_cols postes_df = (postes_df.fillna(APP_NAN) .replace({APP_NAN: None}) .replace({np.nan: None}) .replace({'nan': None})) self.logger.info("Table des postes lue et traitée en %d secondes : %s lignes et %s colonnes extraites\n", time.time()-start_time_pos, postes_df.shape[0], postes_df.shape[1]) return postes_df @atomic # @execution_time(logger_factory=data_perf_logger_factory) @query_count(logger_factory=data_perf_logger_factory) def export_bo(self, request): self.logger.info("--------- Début de l'exportation du fichier 'Données BO' --------- ") start_time_export = time.time() administres_df = self.export_adm_bo_df() affectations_df = self.export_aff_bo_df() notations_df = self.export_no_bo_df() bo_df = administres_df.merge(affectations_df, how='left', left_on=BOCols.ID_SAP, right_on='administre_id') bo_df = bo_df.drop(['administre_id'], axis=1) bo_df = bo_df.merge(notations_df, how='left', left_on=BOCols.ID_SAP, right_on='administre_id') bo_df = bo_df.drop(['administre_id'], axis=1) bo_cols = BOCols.columns( BOCols.ID_SAP, # A BOCols.GRADE, # B BOCols.NOM, # C BOCols.PRENOM, # D BOCols.ID_DEF, # E BOCols.EIP, # F BOCols.EIS, # G BOCols.DOMAINE_GESTION, # H BOCols.DOMAINE, # I BOCols.FILIERE, # J BOCols.NF, # K BOCols.ARME, # L BOCols.REGROUPEMENT_ORIGINE_RECRUTEMENT, # M BOCols.DATE_ENTREE_SERVICE, # N BOCols.NOMBRE_ENFANTS, # O BOCols.ORIGINE_RECRUTEMENT, # Q BOCols.DATE_NAISSANCE, # R BOCols.FONCTION, # T BOCols.DIPLOME_PLUS_HAUT_NIVEAU, # U BOCols.DERNIER_DIPLOME, # V BOCols.DATE_RDC, # W BOCols.CREDO_FE, # X BOCols.GARNISON, # Z (utilisé dans la table des garnisons) BOCols.DATE_ARRIVEE_FE, # AA BOCols.DATE_DERNIER_ACR, # AC BOCols.POSITION_STATUTAIRE, # AE BOCols.DATE_POSITION_STATUAIRE, # AF BOCols.INTERRUPTION_SERVICE, # AG BOCols.DATE_DEBUT_GRADE, # AH BOCols.PROFESSION_CONJOINT, # AL BOCols.ID_SAP_CONJOINT, # AM BOCols.ID_DEF_CONJOINT, # AN BOCols.SEXE_CONJOINT, # AT BOCols.DATE_AFFECTATION_1, # AU BOCols.AFFECTATION_1, # AV BOCols.DATE_AFFECTATION_2, # AW BOCols.AFFECTATION_2, # AX BOCols.DATE_AFFECTATION_3, # AY BOCols.AFFECTATION_3, # AZ BOCols.DATE_AFFECTATION_4, # BA BOCols.AFFECTATION_4, # BB BOCols.DATE_AFFECTATION_5, # BC BOCols.AFFECTATION_5, # BD BOCols.DATE_AFFECTATION_6, # BE BOCols.AFFECTATION_6, # BF BOCols.DATE_AFFECTATION_7, # BG BOCols.AFFECTATION_7, # BH BOCols.DATE_AFFECTATION_8, # BI BOCols.AFFECTATION_8, # BJ BOCols.DATE_AFFECTATION_9, # BK BOCols.AFFECTATION_9, # BL BOCols.DATE_FONCTION_1, # BM BOCols.FONCTION_1, # BN BOCols.DATE_FONCTION_2, # BO BOCols.FONCTION_2, # BP BOCols.DATE_FONCTION_3, # BQ BOCols.FONCTION_3, # BR BOCols.DATE_FONCTION_4, # BS BOCols.FONCTION_4, # BT BOCols.DATE_FONCTION_5, # BU BOCols.FONCTION_5, # BV BOCols.DATE_FONCTION_6, # BW BOCols.FONCTION_6, # BX BOCols.DATE_FONCTION_7, # BY BOCols.FONCTION_7, # BZ BOCols.DATE_FONCTION_8, # CA BOCols.FONCTION_8, # CB BOCols.DATE_FONCTION_9, # CC BOCols.FONCTION_9, # CD BOCols.AGE_ANNEES, # CG BOCols.DATE_MARIAGE, # CH BOCols.SITUATION_FAMILIALE, # CI BOCols.SEXE, # CJ BOCols.ANNEE_NOTATION, # CL BOCols.RAC_OU_IRIS_CUMULE, # CM BOCols.NR_OU_IRIS, # CN BOCols.RF_QSR, # CO BOCols.APTITUDE_EMPLOI_SUP, # CP BOCols.POTENTIEL_RESPONSABILITE_SUP, # CQ BOCols.ANNEE_NOTATION_1, # CR BOCols.RAC_OU_IRIS_CUMULE_1, # CS BOCols.NR_OU_IRIS_1, # CT BOCols.RF_QSR_1, # CU BOCols.APTITUDE_EMPLOI_SUP_1, # CV BOCols.POTENTIEL_RESPONSABILITE_SUP_1, # CW BOCols.ANNEE_NOTATION_2, # CX BOCols.RAC_OU_IRIS_CUMULE_2, # CY BOCols.NR_OU_IRIS_2, # CZ BOCols.RF_QSR_2, # DA BOCols.APTITUDE_EMPLOI_SUP_2, # DB BOCols.POTENTIEL_RESPONSABILITE_SUP_2, # DC BOCols.ANNEE_NOTATION_3, # DD BOCols.RAC_OU_IRIS_CUMULE_3, # DE BOCols.NR_OU_IRIS_3, # DF BOCols.RF_QSR_3, # DG BOCols.APTITUDE_EMPLOI_SUP_3, # DH BOCols.POTENTIEL_RESPONSABILITE_SUP_3, # DI BOCols.ANNEE_NOTATION_4, # DJ BOCols.RAC_OU_IRIS_CUMULE_4, # DK BOCols.NR_OU_IRIS_4, # DL BOCols.RF_QSR_4, # DM BOCols.APTITUDE_EMPLOI_SUP_4, # DN BOCols.POTENTIEL_RESPONSABILITE_SUP_4, # DO BOCols.ANNEE_NOTATION_5, # DP BOCols.RAC_OU_IRIS_CUMULE_5, # DQ BOCols.NR_OU_IRIS_5, # DR BOCols.RF_QSR_5, # DS BOCols.APTITUDE_EMPLOI_SUP_5, # DT BOCols.POTENTIEL_RESPONSABILITE_SUP_5, # DU BOCols.DATE_FUD, # DV BOCols.FUD, # DW BOCols.DATE_STATUT_CONCERTO, # DX BOCols.STATUT_CONCERTO, # DY BOCols.DATE_STATUT_CONCERTO_FUTUR, # DZ BOCols.STATUT_CONCERTO_FUTUR, # EA BOCols.DOMAINE_POSTE, # ED (non utilisé) BOCols.FILIERE_POSTE, # EE (non utilisé) BOCols.NF_POSTE, # EF (non utilisé) BOCols.DATE_LIEN_SERVICE, # EG BOCols.MARQUEUR_PN, # EH BOCols.PLS_GB_MAX, # EI BOCols.ENFANTS, # EK ) bo_df = bo_df.reindex(columns=bo_cols) if bo_df.empty: return Response("Aucune donnée à extraire.") else: try: self.logger.info("Exportation du fichier 'Données BO'...") start_time_export_bo = time.time() now = timezone.now().date() bo_df.to_excel(f'..\\fichiers_exportes\\{now}_donnees_BO_export.xlsx', index=False, header=True) bo_obj = FichiersExporte(nom_fichier=f'{now}_donnees_BO_export.xlsx') bo_obj.save() self.logger.info("Exportation du fichier 'Données BO' réalisée en %d secondes : %s lignes et %s colonnes exportées", time.time()-start_time_export_bo, bo_df.shape[0], bo_df.shape[1]) self.logger.info("---- Exportation totale réalisée en : %d minutes et %d secondes ----\n", (time.time()-start_time_export)//60, (time.time()-start_time_export)%60) return Response("Exportation terminée. Vous trouverez le fichier 'Données BO' exporté dans le dossier 'fichiers_exportes'.") except (Http404, APIException): raise except BaseException: message = "Imposible de réaliser l'exportation du fichier 'Données BO'. Vérifiez que les fichiers Excel d'exportation sont bien fermés." self.logger.exception(message) raise APIException(message) @atomic # @execution_time(logger_factory=data_perf_logger_factory) @query_count(logger_factory=data_perf_logger_factory) def export_reo(self, request): self.logger.info("--------- Début de l'exportation du fichier 'REO' --------- ") start_time_export = time.time() postes_df = self.export_pos_reo_df() reo_df = postes_df if reo_df.empty: return Response("Aucune donnée à extraire.") else: try: self.logger.info("Exportation du fichier 'REO'...") start_time_export_reo = time.time() now = timezone.now().date() reo_df.to_excel(f'..\\fichiers_exportes\\{now}_REO_export.xlsx', index=False, header=True) reo_obj = FichiersExporte(nom_fichier=f'{now}_REO_export.xlsx') reo_obj.save() self.logger.info("Exportation du fichier 'REO' réalisée en %d secondes : %s lignes et %s colonnes exportées", time.time()-start_time_export_reo, reo_df.shape[0], reo_df.shape[1]) self.logger.info("------- Exportation totale réalisée en : %d secondes ------\n", time.time()-start_time_export) return Response("Exportation terminée. Vous trouverez le fichier 'REO' exporté dans le dossier 'fichiers_exportes'.") except (Http404, APIException): raise except BaseException: message = "Imposible de réaliser l'exportation du fichier 'REO'. Vérifiez que les fichiers Excel d'exportation sont bien fermés." self.logger.exception(message) raise APIException(message) def post(self, request): serializer = self.serializer_class(data=request.data) serializer.is_valid(raise_exception=True) nom_fichier = serializer.validated_data.get('fichier_exporte') if nom_fichier == '1': resp = self.export_bo(request) return resp if nom_fichier == '2': resp = self.export_reo(request) return resp return Response("Imposible de réaliser l'exportation.")