Files
test_OgureNG/backend-django/backend/reporting.py
2022-11-08 21:19:51 +01:00

328 lines
21 KiB
Python

"""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)