"""Ce fichier contient les utilitaires du reporting""" # import des pré requis from ast import For import json from datetime import date from logging import getLevelName import time import pandas as pd from django.utils import timezone from django.db.models import Sum from .models import Administre, Domaine, FMOB, Fonction, FormationEmploi, Garnison, Grade, Poste, Notation, \ PreferencesListe, Marque, MarquesGroupe, Filiere, Decision, SousVivier, SousVivierAssociation, \ AvisPosteChoices as AvisPoste from .utils_insertion import insert_Notation import numpy as np def reporting_taux_armement_pcp(fe_id, f_id, d_id, nf, categorie): """ Renvoie les indicateurs figurant dans la vue Taux Armement FE pour les PCP :type fe_id: list :param fe_id: codes CREDO des FE sur lesquelles on filtre :type f_id: list :param f_id: trigrammes des filières sur lesquelles on filtre :type d_id: list :param d_id: trigrammes des domaines sur lesquels on filtre :type nf: list :param nf: niveau fonctionnel sur lesquels on filtre :type categorie: list :param categorie: catégorie sur lesquelles on filtre :return: - **nb_militaires_actuel** (*int*): Nombre de militaires présents dans la/les FE selon les filtres cochés. - **nb_postes_actuel** (*int*): Nombre de postes présents dans la/les FE selon les filtres cochés. - **ecart_actuel** (*int*): Différence entre le nombre de postes et de militaires présents actuellement. - **taux_armement_actuel** (*int*): Taux d'armement de la/les FE selon les filtres cochés. - **nb_militaires_entrants** (*int*): Nombre de militaires entrants dans la FE selon les filtres cochés. - **nb_militaires_sortants** (*int*): Nombre de militaires sortants de la FE selon les filtres cochés. - **nb_militaires_projete** (*int*): Nombre de militaires attendus dans la FE après les mobilités selon les filtres cochés. - **taux_armement_projete** (*int*): Taux d'armement projete selon les filtres cochés. - **taux_armement_cible** (*int*): Taux d'armement cible pour la FE choisie selon la catégorie choisie, None si plusieurs catégories ont été sélectionnées. """ taux_armement_cible = None if len(fe_id) == 1 and len(categorie) == 1: fe = FormationEmploi.objects.get(fe_code__in=fe_id) if 'MDR' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_mdr if 'OFF' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_off if 'SOFF' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_soff nb_militaires_actuel = Administre.objects.filter(formation_emploi_id__in=fe_id, a_domaine__in=d_id, a_filiere__in=f_id, a_nf__in=nf, a_categorie__in=categorie).count() or 0 nb_militaires_sortants = Administre.objects.filter(a_domaine_id__in=d_id, a_filiere_id__in=f_id, a_nf__in=nf, a_categorie__in=categorie, formation_emploi_id__in=fe_id, a_statut_pam__in=['A_MUTER', 'NON_DISPONIBLE', 'PARTANT']).count() or 0 nb_militaires_entrants = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__formation_emploi_id__in=fe_id).count() or 0 nb_militaires_projete = nb_militaires_actuel + nb_militaires_entrants - nb_militaires_sortants nb_postes_actuel = Poste.objects.filter(formation_emploi_id__in=fe_id, p_filiere__in=f_id, p_domaine__in=d_id, p_nf__in=nf, p_categorie__in=categorie).count() or 0 if nb_postes_actuel == 0: nb_postes_actuel = 0 taux_armement_actuel = 0 taux_armement_projete = 0 else: ecart_actuel = nb_postes_actuel - nb_militaires_actuel ecart_projete = nb_postes_actuel - nb_militaires_projete taux_armement_actuel = nb_militaires_actuel / nb_postes_actuel * 100 taux_armement_projete = nb_militaires_projete / nb_postes_actuel * 100 ecart_actuel = nb_postes_actuel - nb_militaires_actuel ecart_projete = nb_postes_actuel - nb_militaires_projete return nb_militaires_actuel, nb_postes_actuel, ecart_actuel, taux_armement_actuel, nb_militaires_entrants, nb_militaires_sortants, nb_militaires_projete, taux_armement_projete, taux_armement_cible def reporting_taux_armement_gestionnaire(fe_id, f_id, d_id, nf, categorie, sv_id): """ Renvoie les indicateurs figurant dans la vue Taux Armement FE pour les gestionnaires :type fe_id: list :param fe_id: codes CREDO des FE sur lesquelles on filtre :type f_id: list :param f_id: trigrammes des filières sur lesquelles on filtre :type d_id: list :param d_id: trigrammes des domaines sur lesquels on filtre :type nf: list :param nf: niveau fonctionnel sur lesquels on filtre :type sv_id: chaine de caractères :param categorie: sous-vivier du gestionnaire :type categorie: list :param categorie: catégorie sur lesquelles on filtre :return: - **nb_militaires_actuel** (*int*): Nombre de militaires présents dans la/les FE selon les filtres cochés. - **nb_postes_actuel** (*int*): Nombre de postes présents dans la/les FE selon les filtres cochés. - **ecart_actuel** (*int*): Différence entre le nombre de postes et de militaires présents actuellement. - **taux_armement_actuel** (*int*): Taux d'armement de la/les FE selon les filtres cochés. - **nb_militaires_entrants** (*int*): Nombre de militaires entrants dans la FE selon les filtres cochés. - **nb_militaires_sortants** (*int*): Nombre de militaires sortants de la FE selon les filtres cochés. - **nb_militaires_projete** (*int*): Nombre de militaires attendus dans la FE après les mobilités selon les filtres cochés. - **taux_armement_projete** (*int*): Taux d'armement projete selon les filtres cochés. - **taux_armement_cible** (*int*): Taux d'armement cible pour la FE choisie selon la catégorie choisie, None si plusieurs catégories ont été sélectionnées. """ taux_armement_cible = None if len(fe_id) == 1 and len(categorie) == 1: fe = FormationEmploi.objects.get(fe_code__in=fe_id) if 'MDR' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_mdr if 'OFF' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_off if 'SOFF' in categorie: taux_armement_cible = fe.fe_taux_armement_cible_soff nb_militaires_actuel = Administre.objects.filter(sous_vivier_id=sv_id, formation_emploi_id__in=fe_id, a_domaine__in=d_id, a_filiere__in=f_id, a_nf__in=nf, a_categorie__in=categorie).count() or 0 nb_militaires_sortants = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_id__in=d_id, a_filiere_id__in=f_id, a_nf__in=nf, a_categorie__in=categorie, formation_emploi_id__in=fe_id, a_statut_pam__in=['A_MUTER', 'NON_DISPONIBLE', 'PARTANT']).count() or 0 nb_militaires_entrants = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__formation_emploi_id__in=fe_id).count() or 0 nb_militaires_projete = nb_militaires_actuel + nb_militaires_entrants - nb_militaires_sortants nb_postes_actuel = Poste.objects.filter(sous_viviers=sv_id, formation_emploi_id__in=fe_id, p_filiere__in=f_id, p_domaine__in=d_id, p_nf__in=nf, p_categorie__in=categorie).count() or 0 if nb_postes_actuel == 0: nb_postes_actuel = 0 taux_armement_actuel = 0 taux_armement_projete = 0 else: ecart_actuel = nb_postes_actuel - nb_militaires_actuel ecart_projete = nb_postes_actuel - nb_militaires_projete taux_armement_actuel = nb_militaires_actuel / nb_postes_actuel * 100 taux_armement_projete = nb_militaires_projete / nb_postes_actuel * 100 ecart_actuel = nb_postes_actuel - nb_militaires_actuel ecart_projete = nb_postes_actuel - nb_militaires_projete return nb_militaires_actuel, nb_postes_actuel, ecart_actuel, taux_armement_actuel, nb_militaires_entrants, nb_militaires_sortants, nb_militaires_projete, taux_armement_projete, taux_armement_cible def reporting_suivi_pam_admin(sv_id, f_id, d_id, nf, categorie): """ Renvoie les indicateurs figurant dans la vue Suivi PAM gestionnaire pour les administrés :type f_id: list :param f_id: trigrammes des filières sur lesquelles on filtre :type d_id: list :param d_id: trigrammes des domaines sur lesquels on filtre :type nf: list :param nf: niveau fonctionnel sur lesquels on filtre :type sv_id: chaine de caractères :param categorie: sous-vivier du gestionnaire :type categorie: list :param categorie: catégorie sur lesquelles on filtre :return: - **nb_a_etudier** (*int*): Nombre de militaires à étudier selon les filtres cochés. - **nb_a_muter** (*int*): Nombre de militaires à muter selon les filtres cochés. - **nb_a_maintenir** (*int*): Nombre de militaires à maintenir selon les filtres cochés. - **nb_non_etudie_administres** (*int*): Nombre de militaires non étudiés selon les filtres cochés. - **nb_a_partant** (*int*): Nombre de militaires partant selon les filtres cochés. - **nb_a_non_dispo** (*int*): Nombre de militaires non disponibles selon les filtres cochés. - **nb_prepos_administres** (*int*): Nombre de militaires prépositionnés selon les filtres cochés. - **nb_pos_administres** (*int*): Nombre de militaires positionnés selon les filtres cochés. - **nb_omi_active_administres** (*int*): Nombre de militaires avec un OMI activé selon les filtres cochés. - **nb_omi_en_cours_administres** (*int*): Nombre de militaires avec un OMI en cours selon les filtres cochés. - **reste_a_realiser_administres** (*int*): Nombre de militaires à muter ou à étudier pour lesquels aucune décision n'a été prise. - **reste_a_realiser_a_etudier** (*int*): Nombre de militaires à étudier pour lesquels aucune décision n'a été prise. - **reste_a_realiser_a_muter** (*int*): Nombre de militaires à muter pour lesquels aucune décision n'a été prise. """ nb_militaires_fe = Administre.objects.filter(a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie).count() a_etudier = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="A_ETUDIER") a_muter = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="A_MUTER") a_maintenir = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="A_MAINTENIR") non_etudie_administres = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="NON_ETUDIE") a_partant = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="PARTANT") a_non_dispo = Administre.objects.filter(sous_vivier_id=sv_id, a_domaine_futur_id__in=d_id, a_filiere_futur_id__in=f_id, a_nf_futur__in=nf, a_categorie__in=categorie, a_statut_pam="NON_DISPONIBLE") nb_a_etudier = a_etudier.count() or 0 nb_a_muter = a_muter.count() or 0 nb_a_maintenir = a_maintenir.count() or 0 nb_non_etudie_administres = non_etudie_administres.count() or 0 nb_a_partant = a_partant.count() or 0 nb_a_non_dispo = a_non_dispo.count() or 0 nb_prepos_administres = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam__in=["A_ETUDIER", "A_MUTER"], de_decision='PREPOSITIONNE').count() or 0 nb_pos_administres = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam__in=["A_ETUDIER", "A_MUTER"], de_decision='POSITIONNE').count() or 0 nb_omi_active_administres = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam__in=["A_ETUDIER", "A_MUTER"], de_decision='OMI_ACTIVE').count() or 0 nb_omi_en_cours_administres = Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam__in=["A_ETUDIER", "A_MUTER"], de_decision='OMI_EN_COURS').count() or 0 reste_a_realiser_a_etudier = nb_a_etudier - Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam="A_ETUDIER").count() or 0 reste_a_realiser_a_muter = nb_a_muter - Decision.objects.filter(administre__a_domaine_futur_id__in=d_id, administre__a_filiere_futur_id__in=f_id, administre__a_nf_futur__in=nf, administre__a_categorie__in=categorie, administre__sous_vivier_id=sv_id, administre__a_statut_pam="A_MUTER").count() or 0 reste_a_realiser_administres = (nb_a_etudier + nb_a_muter) - (nb_prepos_administres + nb_pos_administres + nb_omi_en_cours_administres + nb_omi_active_administres) return nb_a_etudier, nb_a_muter, nb_a_maintenir, nb_non_etudie_administres, nb_a_partant, nb_a_non_dispo, nb_prepos_administres, nb_pos_administres, nb_omi_active_administres, nb_omi_en_cours_administres, reste_a_realiser_administres, reste_a_realiser_a_etudier, reste_a_realiser_a_muter def reporting_suivi_pam_poste(sv_id, f_id, d_id, nf, categorie): """ Renvoie les indicateurs figurant dans la vue Suivi PAM gestionnaire pour les postes :type f_id: list :param f_id: trigrammes des filières sur lesquelles on filtre :type d_id: list :param d_id: trigrammes des domaines sur lesquels on filtre :type nf: list :param nf: niveau fonctionnel sur lesquels on filtre :type sv_id: chaine de caractères :param categorie: sous-vivier du gestionnaire :type categorie: list :param categorie: catégorie sur lesquelles on filtre :return: - **nb_p1** (*int*): Nombre de postes P1 selon les filtres cochés. - **nb_p2** (*int*): Nombre de postes P2 selon les filtres cochés. - **nb_p3** (*int*): Nombre de postes P3 selon les filtres cochés. - **nb_p4** (*int*): Nombre de postes P4 selon les filtres cochés. - **nb_gele** (*int*): Nombre de postes gelés selon les filtres cochés. - **nb_non_etudie_postes** (*int*): Nombre de postes non étudiés selon les filtres cochés. - **nb_prepos_postes** (*int*): Nombre de postes prépositionnés selon les filtres cochés. - **nb_pos_postes** (*int*): Nombre de postes positionnés selon les filtres cochés. - **nb_omi_active_postes** (*int*): Nombre de postes avec un OMI activé selon les filtres cochés. - **nb_omi_en_cours_postes** (*int*): Nombre de postes avec un OMI en cours selon les filtres cochés. - **reste_a_realiser_postes** (*int*): Nombre de postes de P1 à P4 pour lesquels aucune décision n'a été prise. - **reste_a_realiser_p1** (*int*): Nombre de postes P1 pour lesquels aucune décision n'a été prise. - **reste_a_realiser_p2** (*int*): Nombre de postes P2 pour lesquels aucune décision n'a été prise. - **reste_a_realiser_p3** (*int*): Nombre de postes P3 pour lesquels aucune décision n'a été prise. - **reste_a_realiser_p4** (*int*): Nombre de postes P4 pour lesquels aucune décision n'a été prise. """ nb_p1 = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.P1).count() or 0 nb_p2 = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.P2).count() or 0 nb_p3 = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.P3).count() or 0 nb_p4 = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.P4).count() or 0 nb_gele = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.GELE).count() or 0 nb_non_etudie_postes = Poste.objects.filter(sous_viviers=sv_id, p_domaine__in=d_id, p_filiere__in=f_id, p_nf__in=nf, p_categorie__in=categorie, p_avis=AvisPoste.NON_ETUDIE).count() or 0 nb_prepos_postes = Decision.objects.filter(poste__p_domaine__in=d_id, poste__p_filiere__in=f_id, poste__p_nf__in=nf, poste__p_categorie__in=categorie, poste__sous_viviers=sv_id, de_decision='PREPOSITIONNE').count() or 0 nb_pos_postes = Decision.objects.filter(poste__p_domaine__in=d_id, poste__p_filiere__in=f_id, poste__p_nf__in=nf, poste__p_categorie__in=categorie, poste__sous_viviers=sv_id, de_decision='POSITIONNE').count() or 0 nb_omi_active_postes = Decision.objects.filter(poste__p_domaine__in=d_id, poste__p_filiere__in=f_id, poste__p_nf__in=nf, poste__p_categorie__in=categorie, poste__sous_viviers=sv_id, de_decision='OMI_ACTIVE').count() or 0 nb_omi_en_cours_postes = Decision.objects.filter(poste__p_domaine__in=d_id, poste__p_filiere__in=f_id, poste__p_nf__in=nf, poste__p_categorie__in=categorie, poste__sous_viviers=sv_id, de_decision='OMI_EN_COURS').count() or 0 reste_a_realiser_p1 = 0 reste_a_realiser_p2 = 0 reste_a_realiser_p3 = 0 reste_a_realiser_p4 = 0 reste_a_realiser_postes = (nb_p1 + nb_p2 + nb_p3 + nb_p4) - (nb_prepos_postes + nb_pos_postes + nb_omi_active_postes + nb_omi_en_cours_postes) if reste_a_realiser_postes > nb_p4: reste_a_realiser_p4 = nb_p4 if reste_a_realiser_postes - nb_p4 > nb_p3: reste_a_realiser_p3 = nb_p3 if reste_a_realiser_postes - nb_p4 - nb_p3 > nb_p2: reste_a_realiser_p2 = nb_p2 if reste_a_realiser_postes - nb_p4 - nb_p3 - nb_p2 >= nb_p1: reste_a_realiser_p1 = nb_p1 else: reste_a_realiser_p1 = reste_a_realiser_postes - nb_p4 - nb_p3 - nb_p2 else: reste_a_realiser_p2 = reste_a_realiser_postes - nb_p4 - nb_p3 reste_a_realiser_p1 = 0 else: reste_a_realiser_p3 = reste_a_realiser_postes - nb_p4 reste_a_realiser_p2 = 0 reste_a_realiser_p1 = 0 else: reste_a_realiser_p4 = nb_p4 - reste_a_realiser_postes reste_a_realiser_p2 = 0 reste_a_realiser_p3 = 0 reste_a_realiser_p4 = 0 return nb_p1, nb_p2, nb_p3, nb_p4, nb_gele, nb_non_etudie_postes, reste_a_realiser_postes, reste_a_realiser_p1, reste_a_realiser_p2, reste_a_realiser_p3, reste_a_realiser_p4, nb_prepos_postes, nb_pos_postes, nb_omi_active_postes, nb_omi_en_cours_postes # TODO : Supprimer cette fonction car non utilisée dans le code et utilise SousvivierAssociation def poste_vacant_vivier(sv_id, fe_id): """ Renvoie le nombre de postes vacants dans un sous-vivier pour une FE sélectionnée :type sv_id: chaine de caractères :param sv_id: sous-vivier du gestionnaire :type fe_id: chaine de caractères :param fe_id: FE sur laquelle le gestionnaire a filtré :return: - **1** (*int*): Nombre de postes vacants pour la FE sélectionnée. """ sva = SousVivierAssociation.objects.filter(sous_vivier_id=sv_id).first() categorie = sva.sva_categorie fe = FormationEmploi.objects.get(fe_code=fe_id) if categorie == 'MDR': nb_poste_reevalue_fe = fe.fe_nb_poste_reevalue_mdr or 0 nb_poste_vacant_fe = fe.fe_nb_poste_vacant_mdr or 0 if categorie == 'OFF': nb_poste_reevalue_fe = fe.fe_nb_poste_reo_off or 0 nb_poste_vacant_fe = fe.fe_nb_poste_vacant_off or 0 if categorie == 'SOFF': nb_poste_reevalue_fe = fe.fe_nb_poste_reevalue_soff or 0 nb_poste_vacant_fe = fe.fe_nb_poste_vacant_soff or 0 nb_poste_vivier_dans_fe = Poste.objects.filter(formation_emploi_id=fe_id, sous_viviers=sv_id).aggregate(Sum('p_id')) or 0 if nb_poste_reevalue_fe == 0: return 0 else: proportion = nb_poste_vivier_dans_fe / nb_poste_reevalue_fe nb_poste_vacant_vivier = proportion * nb_poste_vacant_fe if nb_poste_vacant_vivier > np.floor(nb_poste_vacant_vivier) + 0.5: return np.ceil(nb_poste_vacant_vivier) else: return np.floor(nb_poste_vacant_vivier)