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

1464 lines
70 KiB
Python

from ast import For
import time
from datetime import date
#from tkinter.tix import Form
import numpy as np
import pandas as pd
from django.db.models import Case, IntegerField, Prefetch, Sum, When
from django.db.transaction import atomic
from django.forms import model_to_dict
from django.http import Http404, JsonResponse
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status, viewsets
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 django.db.models import Q
from .. import constants
from ..filters import AdministreFilter, AdministrePAMFilter, PosteFilter, PostePAMFilter, RelatedOrderingFilter
from ..models import (FMOB, Administre, Decision, DecisionChoices, Domaine,
Filiere, FormationEmploi, Marque, MarquesGroupe,
PcpFeGroupe, Poste, PreferencesListe, SousVivier,
SousVivierAssociation, SpecifiqueChoices, Administres_Pams, StatutPamChoices as StatutPam,
Postes_Pams,PAM)
from ..paginations import HeavyDataPagination
from ..reporting import (reporting_suivi_pam_admin, reporting_suivi_pam_poste,
reporting_taux_armement_gestionnaire,
reporting_taux_armement_pcp)
from ..serializers import (CTX_KEY_DECISIONS, CTX_KEY_PROFILES,
AdministreSerializer,
AdministresPamsSerializer,
AlimentationReferentielSerializer,
DomaineSerializer, FileSVSerializer,
FiliereSerializer, FmobSerializer, MarqueSerializer,
MarquesGroupeSerializer, PcpFeGroupeSerializer,
PosteSerializer, SousVivierAssociationSerializer,
PostesPamsSerializer)
from ..utils import sous_viviers_du_cellule, without_keys, generate_sv_id, nf2categorie
from ..utils.decisions import get_available_decisions
from ..utils.decorators import class_logger
from ..utils.permissions import get_profiles_by_adm
from ..utils_extraction import (DataFrameTypes, FileTypes, open_excel,
read_files_by_type)
from .commun import (GestionnairePermission, execution_time_viewset,
query_count_viewset)
# Vue de calcul des indicateurs
# Renvoie les indicateurs pour les vues :
# - taux armement FE pour les PCP
# - taux armement FE pour les gestionnaires
# - suivi pam des gestionnaires pour les administrés
# - suivi pam des gestionnaires pour les postes
@class_logger
@execution_time_viewset
@query_count_viewset
class ReportingView(APIView):
"""
Cette classe est dédiée au vue du calcul des indicateurs
- taux armement FE pour les PCP
- taux armement FE pour les gestionnaires
- suivi pam des gestionnaires pour les administrés
- suivi pam des gestionnaires pour les postes
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
def __str__(self):
return 'ReportingView'
def get(self, request):
"""La fonction get renvoie les indicateurs
:type request: rest_framework.request.Request
:param request: Request contenant le type, sous_vivier id, niveau fonctinonel et l'id de la formation emploi.
:return: - **return** (*json*): Si le type est SUIVI_PAM_GESTIONNAIRE le json contiendra l'information sur le suivi pam des
gestionnaires pour les administrés et les postes. Si le type est TAUX_ARMEMENT_FE le json contiendra les indicateurs sur les taux d'armement.
"""
type = request.query_params["type"]
sv_id = []
if 'sv_id' in request.query_params:
sv_id = request.query_params["sv_id"]
if 'vue' in request.query_params:
vue = request.query_params["vue"]
if "nf" in request.query_params:
nf = request.query_params.getlist("nf")
else:
nf = ['1A', '1B', '1C', '2.', '3A', '3B', '3B NFS', '4.', '5A', '5B', '5C', '6A', '6B']
if 'fe_id' in request.query_params: # a voir
fe_id = request.query_params.getlist('fe_id')
else:
fe_id = list(FormationEmploi.objects.values_list('fe_code', flat=True))
# Vues pour les indicateurs sur le suivi du pam
if (type == "SUIVI_PAM_GESTIONNAIRE"):
if "d_code" in request.query_params:
d_id = request.query_params.getlist("d_code")
else:
filieres = list(SousVivierAssociation.objects.filter(sous_vivier__sv_id=sv_id).values_list('filiere_id',
flat=True).distinct())
d_id = list(Filiere.objects.filter(f_code__in=filieres).values_list('domaine_id', flat=True).distinct())
if "f_code" in request.query_params:
f_id = request.query_params.getlist("f_code")
else:
f_id = list(SousVivierAssociation.objects.filter(sous_vivier__sv_id=sv_id).values_list('filiere_id',
flat=True).distinct())
if "categorie" in request.query_params:
categorie = request.query_params.getlist("categorie")
else:
categorie = list(
SousVivierAssociation.objects.filter(sous_vivier__sv_id=sv_id).values_list('sva_categorie',
flat=True).distinct())
# résultats pour la vue suivi pam des gestionnaires pour les administrés
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 = reporting_suivi_pam_admin(
sv_id, f_id, d_id, nf, categorie)
# résultats pour la vue suivi pam des gestionnaires pour les postes
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 = reporting_suivi_pam_poste(
sv_id, f_id, d_id, nf, categorie)
return JsonResponse(
{"nb_a_etudier": nb_a_etudier, "nb_a_muter": nb_a_muter, "nb_a_maintenir": nb_a_maintenir,
"nb_a_partant": nb_a_partant, "nb_a_non_dispo": nb_a_non_dispo,
"nb_non_etudie_administres": nb_non_etudie_administres,
"nb_prepos_administres": nb_prepos_administres, "nb_pos_administres": nb_pos_administres,
"nb_omi_en_cours_administres": nb_omi_en_cours_administres,
"nb_omi_active_administres": nb_omi_active_administres,
"reste_a_realiser_administres": reste_a_realiser_administres,
"reste_a_realiser_a_etudier": reste_a_realiser_a_etudier,
"reste_a_realiser_a_muter": reste_a_realiser_a_muter,
"nb_p1": nb_p1, "nb_p2": nb_p2, "nb_p3": nb_p3, "nb_p4": nb_p4, "nb_gele": nb_gele,
"nb_non_etudie_postes": nb_non_etudie_postes, "reste_a_realiser_postes": reste_a_realiser_postes,
"reste_a_realiser_p1": reste_a_realiser_p1, "reste_a_realiser_p2": reste_a_realiser_p2,
"reste_a_realiser_p3": reste_a_realiser_p3, "reste_a_realiser_p4": reste_a_realiser_p4,
"nb_prepos_postes": nb_prepos_postes, "nb_pos_postes": nb_pos_postes,
"nb_omi_en_cours_postes": nb_omi_en_cours_postes, "nb_omi_active_postes": nb_omi_active_postes},
safe=False)
# Vues pour les indicateurs sur les taux d'armement
elif (type == 'TAUX_ARMEMENT_FE'):
if "d_code" in request.query_params:
d_id = request.query_params.getlist("d_code")
else:
d_id = list(Domaine.objects.all().values_list('d_code', flat=True))
if "f_code" in request.query_params:
f_id = request.query_params.getlist("f_code")
else:
f_id = list(Filiere.objects.all().values_list('f_code', flat=True))
if "categorie" in request.query_params:
categorie = request.query_params.getlist("categorie")
else:
categorie = ['MDR', 'SOFF', 'OFF', 'OGX']
if len(sv_id) == 0:
# résultats pour la vue taux armement FE pour les PCP
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 = reporting_taux_armement_pcp(
fe_id, f_id, d_id, nf, categorie)
else:
# résultats pour la vue taux armement FE pour les gestionnaires
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 = reporting_taux_armement_gestionnaire(
fe_id, f_id, d_id, nf, categorie, sv_id)
return JsonResponse({'nb_militaires_actuel': nb_militaires_actuel, "nb_postes_actuel": nb_postes_actuel,
'ecart_actuel': ecart_actuel, 'taux_armement_actuel': taux_armement_actuel,
'nb_militaires_entrants': nb_militaires_entrants,
'nb_militaires_sortants': nb_militaires_sortants,
'nb_militaires_projete': nb_militaires_projete,
'taux_armement_projete': taux_armement_projete,
'taux_armement_cible': taux_armement_cible}, safe=False)
else:
return JsonResponse({"autre vue": "autres indicateurs demandes"})
# TODO : Supprimer cette vue qui n'est plus utilisée
# Vue de chargement des sous-viviers :
# - Charge et traite le fichier de définition des sous-viviers
# - Attribue les sous-viviers présents aux administrés et postes correspondants
@class_logger
@execution_time_viewset
@query_count_viewset
class ChargementSVView(APIView):
"""
Cette classe est dédiée au vue de chargement des sous-viviers. Charge et traite le fichier de définition des sous-viviers et attribue les sous-viviers présents aux administrés et postes correspondants
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = FileSVSerializer
def get(self, request):
"""La fonction get renvoie une reponse contenant ok
:type request: rest_framework.request.Request
:param request: Requset
:return: - **return** (*json*): json contenant "ok".
"""
return Response({"get": "ok"})
def post(self, request):
"""La fonction post charge les sous-viviers
:type request: rest_framework.request.Request
:param request: Request contenant le fichier SV
:return: - **Response** (*Response*): Reponse contient la liste des sous-viviers créés, ignorés et où il y a eu une erreur.
"""
serializer = FileSVSerializer(data=request.data)
if not serializer.is_valid():
return Response(
data=serializer.errors,
status=status.HTTP_400_BAD_REQUEST
)
sv_file = request.data['SV']
sv_df = open_excel(sv_file, sheetname="GESTIONNAIRES", engine='openpyxl')
sv = pd.DataFrame(columns=['gestionnaire_id_sap', 'f_code', 'asso_sv_categorie', 'arme'])
for i in range(len(sv_df)):
sv.loc[i] = [sv_df.iloc[i, 0], sv_df.iloc[i, 3], sv_df.iloc[i, 4], sv_df.iloc[i, 5]]
sv.dropna(subset=['f_code'], inplace=True)
sv['arme'] = sv['arme'].replace({np.nan: None})
sv.reset_index(drop=True, inplace=True)
sv['asso_sv_categorie'].replace({"SOUS-OFFICIER": "SOFF", "OFFICIER": "OFF", "MILITAIRE DU RANG": "MDR"},
inplace=True)
sv['sv_id'] = sv.f_code + '_' + sv.asso_sv_categorie
sv.f_code = sv.f_code.apply(lambda x: x.split(','))
sv = sv.explode(column='f_code')
sv.reset_index(drop=True, inplace=True)
errors = []
created = []
ignored = []
sv.fillna(np.nan, inplace=True)
sv.replace([np.nan], [None], inplace=True)
self.logger.debug(sv.head())
for i in range(len(sv)):
try:
filiere = Filiere.objects.get(f_code=sv.at[i, "f_code"])
categorie = sv.at[i, "asso_sv_categorie"]
asso_sv = SousVivierAssociation.objects.filter(sva_categorie=categorie,
filiere__f_code=sv.at[i, "f_code"])
# Vérifier que filiere et catégorie n'ont pas déjà de sous vivier
if asso_sv.count() == 0 and categorie is not None:
# Créer le sous-vivier correspondant dans la table SousVivier
sous_vivier = SousVivier(sv_id=sv.at[i, "sv_id"],
sv_libelle=str(sv.at[i, "sv_id"]))
self.logger.debug(model_to_dict(sous_vivier))
sous_vivier.save()
self.logger.debug(sv.at[i, "sv_id"])
# Insertion du nouveau sous-vivier dans la table d'association (sans le droit arme dans un premier temps)
sva = SousVivierAssociation(sva_id=i, sous_vivier_id=sous_vivier.sv_id, filiere_id=filiere.f_code,
sva_categorie=categorie, sva_arme=sv.at[i, "arme"])
sva.save()
# Mise à jour du sous_vivier_id pour les postes et administres ayant la filiere et la categorie en cours
Administre.objects.filter(a_categorie=categorie, a_filiere_id=filiere.f_code).update(
sous_vivier_id=sous_vivier.sv_id)
# En fonction du fichier excel, changer la mise à jour du sous_vivier
Poste.objects.filter(p_categorie=categorie, p_filiere_id=filiere.f_code).sous_viviers.set([sous_vivier.sv_id])
created.append(str(sv.at[i, "asso_sv_categorie"]) + " " + str(sv.at[i, "f_code"]))
else:
ignored.append(str(sv.at[i, "asso_sv_categorie"]) + " " + str(sv.at[i, "f_code"]))
# Si l'association appartient déjà à un sous_vivier, on ne fait rien
except Filiere.DoesNotExist:
errors.append("Filiere " + sv.at[i, 'f_code'] + "non retrouvée")
return Response({"created": created, "ignored": ignored, "errors": errors})
@class_logger
@execution_time_viewset
@query_count_viewset
class AlimentationReferentielView(APIView):
""" Vue pour alimenter la base à partir de référentiels """
permission_classes = [IsAuthenticated, IsAdminUser]
serializer_class = AlimentationReferentielSerializer
def get(self, request):
return Response("Formulaire d'alimentation d'OGURE NG (référentiel)")
@atomic
def post(self, request):
"""
Charge le(s) fichier(s) et met à jour la base.
:param request: requête, contient les fichiers
:type request: class:`rest_framework.request.Request`
:raises: class:`rest_framework.exceptions.APIException`
:return: réponse
:rtype: class:`rest_framework.response.Response`
"""
try:
validator = self.serializer_class(data=request.data)
validator.is_valid(raise_exception=True)
# récupération des fichiers
referentiel_fe = validator.validated_data.get('referentiel_fe')
if referentiel_fe:
Cols = FormationEmploi.Cols
col_pk = Cols.PK
col_pk_mere = Cols.REL_MERE
col_libelle_mere = Cols.LIBELLE
col_zone_def = Cols.ZONE_DEFENSE
def process_referentiel_fe(referentiel) -> pd.DataFrame:
"""
Fonction de lecture du référentiel de FE.
:param referentiel: Fichier du référentiel FE
:type referentiel: XLSX
:return: DataFrame
:rtype: class:`pandas.DataFrame`
"""
return open_excel(referentiel, sheetname=0, engine='openpyxl')
def convertir_fe(df: pd.DataFrame) -> pd.DataFrame:
"""
Fonction de conversion du DataFrame de FE.
:param df: DataFrame du référentiel FE
:type df: class:`pandas.DataFrame`
:return: DataFrame
:rtype: class:`pandas.DataFrame`
"""
col_pk_avant = 'FE CREDO' # B
col_pk_mere_avant = 'FE mère CREDO' # D
col_libelle_mere_avant = 'FE mère LA' # E
col_zone_def_avant = 'Zone de Défense' # O
return (
df[[col_pk_avant, col_pk_mere_avant, col_libelle_mere_avant, col_zone_def_avant]]
.drop_duplicates(subset=col_pk_avant, keep='first')
.rename(columns={
col_pk_avant: col_pk,
col_pk_mere_avant: col_pk_mere,
col_libelle_mere_avant: col_libelle_mere,
col_zone_def_avant: col_zone_def
})
.astype({col_pk: 'str', col_pk_mere: 'str'})
)
def mettre_a_jour_fe(df: pd.DataFrame) -> None:
"""
Met à jour les FE base à partir du DataFrame de FE.
:param df: DataFrame du référentiel FE
:type df: class:`pandas.DataFrame`
:return: DataFrame
:rtype: class:`pandas.DataFrame`
"""
TypeModele = FormationEmploi
Cols = TypeModele.Cols
champs_maj = (Cols.REL_MERE, Cols.ZONE_DEFENSE)
modeles_en_base = {m.pk: m for m in TypeModele.objects.select_related(Cols.REL_MERE).only('pk', *champs_maj)}
taille_batch = 100
dict_update = {}
dict_mere_create = {}
error_count = 0
for idx, rec in enumerate(df.to_dict('records')):
pk = rec.get(col_pk)
try:
id_mere = rec.get(col_pk_mere)
zone_defense = rec.get(col_zone_def)
en_base = modeles_en_base.get(pk)
# TODO pas de création pour l'instant (ni de suppression) quand en_base est falsy
if en_base:
mere = None
if id_mere is not None:
mere = modeles_en_base.get(id_mere) or dict_mere_create.get(id_mere)
if not mere:
try:
# les FE mères manquantes seront créées
mere = TypeModele(pk=id_mere, fe_libelle=rec.get(col_libelle_mere))
except Exception as e:
raise RuntimeError(f'la création d\'un modèle de type "{TypeModele.__name__}" (mère) a échoué') from e
dict_mere_create.setdefault(id_mere, mere)
if mere != getattr(en_base, Cols.REL_MERE, None) or zone_defense != getattr(en_base, Cols.ZONE_DEFENSE, None):
try:
modele = TypeModele(pk=pk, mere=mere, zone_defense=zone_defense)
except Exception as e:
raise RuntimeError(f'la création d\'un modèle de type "{TypeModele.__name__}" a échoué') from e
dict_update.setdefault(pk, modele)
except Exception:
error_count = error_count + 1
self.logger.exception('%s une erreur est survenue à la ligne : %s (pk=%s)', TypeModele.__name__, idx, pk)
if error_count:
self.logger.warning("%s(s) en erreur : %s", TypeModele.__name__, error_count)
if dict_mere_create:
TypeModele.objects.bulk_create(dict_mere_create.values(), batch_size=taille_batch)
self.logger.info('%s(s) mères créée(s) : %s', TypeModele.__name__, len(dict_mere_create))
if dict_update and champs_maj:
TypeModele.objects.bulk_update(dict_update.values(), batch_size=taille_batch, fields=champs_maj)
self.logger.info('%s(s) mise(s) à jour : %s', TypeModele.__name__, len(dict_update))
df_referentiel_fe = process_referentiel_fe(referentiel_fe)
self.logger.info('Lecture du référentiel FE ------> Succès')
df_referentiel_fe = convertir_fe(df_referentiel_fe)
self.logger.info('Extraction des données du référentiel FE ------> Succès')
mettre_a_jour_fe(df_referentiel_fe)
self.logger.info('Mise à jour du référentiel FE ------> Succès')
return Response({'Insertion réussie'})
except (Http404, APIException):
raise
except BaseException:
message = "Impossible d'alimenter le(s) référentiel(s)"
self.logger.exception(message)
raise APIException(message)
# Vue API des administrés
# Pagination OK
# Ordering OK
# Search NOK
# Filtering NOK
@class_logger
@execution_time_viewset
@query_count_viewset
class AdministreView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue de l'administre.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = AdministreSerializer
filter_backends = [DjangoFilterBackend, RelatedOrderingFilter]
# filterset_fields = ['category', 'in_stock']
filterset_class = AdministreFilter
ordering_fields = Administre.Cols.PK
ordering = [Administre.Cols.PK]
pagination_class = HeavyDataPagination
# important : mettre à jour quand le serializer change
def get_queryset(self):
Cols = Administre.Cols
ColsFE = FormationEmploi.Cols
return Administre.objects.select_related(
Cols.REL_FONCTION, Cols.REL_GRADE, Cols.REL_SOUS_VIVIER
).prefetch_related(
Cols.M2M_COMPETENCES,
Prefetch(Cols.M2M_PAM, queryset=Administres_Pams.objects.select_related(Administres_Pams.Cols.O2M_FMOB)),
# Prefetch(Cols.REL_DECISION, queryset=Decision.objects.select_related(
# f'{Decision.Cols.REL_POSTE}__{Poste.Cols.REL_FORMATION_EMPLOI}__{ColsFE.REL_MERE}',
# )),
Prefetch(Cols.REL_FORMATION_EMPLOI, queryset=FormationEmploi.objects.select_related(ColsFE.REL_MERE)),
)
def get_serializer(self, *args, **kwargs):
ser = super().get_serializer(*args, **kwargs)
arg = args[0] if args else None
if arg and isinstance(arg, (list, tuple)) and self.request.method == 'GET':
# calcule directement, si besoin, les profils et les décisions disponibles pour tous les résultats
if CTX_KEY_PROFILES not in ser.context:
ser.context[CTX_KEY_PROFILES] = get_profiles_by_adm(self.request.user, *arg)
if CTX_KEY_DECISIONS not in ser.context:
ser.context[CTX_KEY_DECISIONS] = get_available_decisions(arg, profiles_by_adm=ser.context[CTX_KEY_PROFILES],
annee_pam = self.request.query_params['pam__in'])
return ser
@atomic
def put(self, request):
"""La fonction put met à jour une liste d'administres.
:type request: rest_framework.request.Request
:param request: Request contenant la liste d'administres.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour des administres .
"""
try:
req_data = request.data
is_list = isinstance(req_data, list)
validator = self.serializer_class(data=req_data, many=is_list, partial=True)
validator.is_valid(raise_exception=True)
today = date.today()
Cols = Administre.Cols
if 'annee_pam' in req_data:
annee_pam = req_data.pop('annee_pam')
else:
annee_pam = ''
def copy_data_item(input, pk):
"""Copie et complète si besoin le dictionnaire en entrée"""
result = {**input}
if pk and Cols.PK not in result:
result[Cols.PK] = pk
return result
def set_competences(administre_obj, a_comp):
"""Set competences to administre object"""
a_comp_id = [competence.comp_id for competence in a_comp]
administre_obj.a_liste_id_competences.set(a_comp_id)
return administre_obj
if is_list: # Update multiple elements
data = [copy_data_item(item, req_data[idx][Cols.PK]) for idx, item in enumerate(validator.validated_data)]
fields = [key for key in data[0].keys() if key != Cols.PK]
# Direct assignment to the forward side of a many-to-many set is prohibited. Use a_liste_id_competences.set() instead.
if Cols.STATUT_PAM in fields:
fields_to_update_pam = ['a_statut_pam_annee']
data_statut_pam = [{'id' :str(o['a_id_sap'])+str(annee_pam), 'a_statut_pam_annee' : o[Cols.STATUT_PAM]} for o in data]
objs = [Administres_Pams(**data_item) for data_item in data_statut_pam]
Administres_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'a_liste_id_competences' not in fields:
objs = [Administre(**data_item) for data_item in data]
if Cols.STATUT_PAM in fields:
list_error = []
for i in range(len(objs)):
old_administre = Administre.objects.get(a_id_sap=objs[i].a_id_sap)
administre = objs[i]
eip = administre.a_eip
fe_code = old_administre.formation_emploi_id
avis = administre.a_statut_pam
old_avis = old_administre.a_statut_pam
try:
categorie = constants.CATEGORIE_BY_NF[old_administre.a_nf.upper()]
except:
erreur = 'la catégorie de l\'administré n\'est pas reconnue dans ogure.'
raise Exception(erreur)
# liste_error = impact_decisions(old_administre, administre, old_avis, avis, eip, fe_code, categorie)
Administre.objects.bulk_update(objs, fields=fields)
else:
objs_w_comp = [set_competences(Administre(**without_keys(i, ['a_liste_id_competences'])), i['a_liste_id_competences']) for i in data]
else: # Update one element
data = copy_data_item(validator.validated_data, validator.validated_data[Cols.PK])
# c'est un bug la récupération de a_id_sap en-dessous, non ?
a_id_sap = Administre.objects.update(data)
db_instance = Administre.objects.filter(a_id_sap=a_id_sap).first()
db_instance.tag.clear()
return Response({'msg': 'updated'})
except APIException:
raise
except Exception:
message = 'échec de la mise à jour de N administrés'
self.logger.exception(message)
raise APIException(message)
def partial_update(self, request, pk=None):
""" La fonction put met à jour un administre.
:type request: rest_framework.request.Request
:param request: Request contenant l'administre.
:type pk: integer
:param pk: Primary Key de l'administre.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour de l'administre .
"""
try:
a = get_object_or_404(Administre.objects, a_id_sap=pk) # Permet de déclancher la vérification des droits au niveau de l'objet
self.check_object_permissions(self.request, a)
req_data = request.data
if 'annee_pam' in req_data:
annee_pam = req_data.pop('annee_pam')
# TODO valider les données (il faut d'abord corriger la MAJ des compétences)
# validator = self.serializer_class(data=req_data, partial=True)
# validator.is_valid(raise_exception=True)
Cols = Administre.Cols
# Copie et complète si besoin le dictionnaire en entrée
# administre = {**validator.validated_data}
administre = {**req_data}
administre[Cols.PK] = pk
fields = [key for key in administre.keys() if key != Cols.PK] # and key != 'a_liste_id_competences']
if 'a_domaine_futur' in fields:
administre['a_domaine_futur_id'] = administre['a_domaine_futur']
del administre['a_domaine_futur']
if 'a_filiere_futur' in fields:
administre['a_filiere_futur_id'] = administre['a_filiere_futur']
del administre['a_filiere_futur']
if Cols.STATUT_PAM in fields:
old_administre = Administre.objects.get(a_id_sap=pk)
eip = old_administre.a_eip
fe_code = old_administre.formation_emploi_id
avis = administre[Cols.STATUT_PAM]
old_avis = old_administre.a_statut_pam
try:
categorie = constants.CATEGORIE_BY_NF[old_administre.a_nf.upper()]
except:
erreur = 'la catégorie de l\'administré n\'est pas reconnue dans ogure.'
raise APIException(erreur)
# liste_error = impact_decisions(old_administre, Administre(**administre), old_avis, avis, eip, fe_code, categorie)
if 'a_liste_id_competences' in fields:
adm=Administre(pk=pk)
#adm=request.data['a_liste_id_competences']
if administre['a_liste_id_competences']:
adm.a_liste_id_competences.set(administre['a_liste_id_competences'].split(','))
else:
adm.a_liste_id_competences.set("")
elif Cols.STATUT_PAM in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_statut_pam_annee = administre[Cols.STATUT_PAM]
adm_pam.save()
else:
copy = { k: v for k, v in administre.items() if k != 'a_liste_id_competences'}
adm = Administre(**copy)
if fields:
Administre.objects.bulk_update([adm], fields=fields)
return Response({'msg': 'updated'})
except (Http404, APIException):
raise
except Exception:
message = "échec de la mise à jour de l'administré"
self.logger.exception(message)
raise APIException(message)
# GET /api/administres => 0 administrés
# POST /api/administres => Crée 1 nouvel administres => id=1
# GET /api/administres/1 => 1 administre précédemment créé
# POST /api/administres/1 => 1 administre précédemment créé
@class_logger
@execution_time_viewset
@query_count_viewset
class AdministrePAMView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue de l'administre.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = AdministresPamsSerializer
filter_backends = [DjangoFilterBackend, RelatedOrderingFilter]
# filterset_fields = ['category', 'in_stock']
filterset_class = AdministrePAMFilter
ordering_fields = Administres_Pams.Cols.PK
ordering = [Administres_Pams.Cols.PK]
pagination_class = HeavyDataPagination
# important : mettre à jour quand le serializer change
def get_queryset(self):
Cols = Administres_Pams.Cols
Cols_Administre = Administre.Cols
ColsFE = FormationEmploi.Cols
return Administres_Pams.objects.select_related(
Cols.REL_DECISION, Cols.REL_PAM, Cols.O2M_FMOB
).prefetch_related(
Prefetch(Cols.REL_ADMINISTRE, queryset = Administre.objects.select_related(Cols_Administre.REL_FONCTION, Cols_Administre.REL_GRADE, Cols_Administre.REL_SOUS_VIVIER
).prefetch_related(
Cols_Administre.M2M_COMPETENCES,
Prefetch(Cols_Administre.REL_FORMATION_EMPLOI, queryset=FormationEmploi.objects.select_related(ColsFE.REL_MERE)),
))
)
def get_serializer(self, *args, **kwargs):
ser = super().get_serializer(*args, **kwargs)
arg = args[0] if args else None
if arg and isinstance(arg, (list, tuple)) and self.request.method == 'GET':
# calcule directement, si besoin, les profils et les décisions disponibles pour tous les résultats
if CTX_KEY_PROFILES not in ser.context:
ser.context[CTX_KEY_PROFILES] = get_profiles_by_adm(self.request.user, *arg)
if CTX_KEY_DECISIONS not in ser.context:
ser.context[CTX_KEY_DECISIONS] = get_available_decisions(arg, profiles_by_adm=ser.context[CTX_KEY_PROFILES])
return ser
@atomic
def put(self, request):
"""La fonction put met à jour une liste d'administres.
:type request: rest_framework.request.Request
:param request: Request contenant la liste d'administres.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour des administres .
"""
try:
req_data = request.data
is_list = isinstance(req_data, list)
# validator = AdministreSerializer(data=req_data, many=is_list, partial=True)
# validator.is_valid(raise_exception=True)
today = date.today()
Cols = Administre.Cols
# Extraire l'annee
if 'pam_id' in req_data[0]:
annee_pam = req_data[0]['pam_id']
def copy_data_item(input, pk):
"""Copie et complète si besoin le dictionnaire en entrée"""
result = {**input}
if pk and Cols.PK not in result:
result[Cols.PK] = pk
return result
def set_competences(administre_obj, a_comp):
"""Set competences to administre object"""
a_comp_id = [competence.comp_id for competence in a_comp]
administre_obj.a_liste_id_competences.set(a_comp_id)
return administre_obj
if is_list:
data = [copy_data_item(item, req_data[idx][Cols.PK]) for idx, item in enumerate(req_data)]
fields = [key for key in data[0].keys() if key != Cols.PK]
# Direct assignment to the forward side of a many-to-many set is prohibited. Use a_liste_id_competences.set() instead.
# Update Administres Pams dans les if et elif et le else et elif est utilisé pour la mise a jour des Administres
if Cols.STATUT_PAM in fields:
fields_to_update_pam = ['a_statut_pam_annee']
# Creation d'une liste qui contient l'id ( a_id_sap + annee_pam) avec le statut choisi
data_statut_pam = [{'id' :str(o['a_id_sap'])+str(annee_pam), 'a_statut_pam_annee' : o[Cols.STATUT_PAM]} for o in data]
# Creation des objets Administres Pams
objs = [Administres_Pams(**data_item) for data_item in data_statut_pam]
# Mise a jour des objets Administres Pams
Administres_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'a_liste_depts_souhaites_pam' in fields:
fields_to_update_pam = ['a_liste_depts_souhaites_pam']
# Creation d'une liste qui contient l'id ( a_id_sap + annee_pam) avec le statut choisi
data_statut_pam = [{'id' :str(o['a_id_sap'])+str(annee_pam), 'a_liste_depts_souhaites_pam' : o['a_liste_depts_souhaites_pam']} for o in data]
# Creation des objets Administres Pams
objs = [Administres_Pams(**data_item) for data_item in data_statut_pam]
# Mise a jour des objets Administres Pams
Administres_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'a_liste_id_competences' in fields:
objs_w_comp = [set_competences(Administre(**without_keys(i, ['a_liste_id_competences'])), i['a_liste_id_competences']) for i in data]
elif 'a_liste_zones_geographiques_shm_pam' in fields:
fields_to_update_pam = ['a_liste_zones_geographiques_shm_pam']
data_statut_pam = [{'id' :str(o['a_id_sap'])+str(annee_pam), 'a_liste_zones_geographiques_shm_pam' : o['a_liste_zones_geographiques_shm_pam']} for o in data]
objs = [Administres_Pams(**data_item) for data_item in data_statut_pam]
# Mise a jour des objets Administres Pams
Administres_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
else:
objs = [Administre(**data_item) for data_item in data]
if Cols.STATUT_PAM in fields:
list_error = []
for i in range(len(objs)):
old_administre = Administre.objects.get(a_id_sap=objs[i].a_id_sap)
administre = objs[i]
eip = administre.a_eip
fe_code = old_administre.formation_emploi_id
avis = administre.a_statut_pam
old_avis = old_administre.a_statut_pam
try:
categorie = constants.CATEGORIE_BY_NF[old_administre.a_nf.upper()]
except:
erreur = 'la catégorie de l\'administré n\'est pas reconnue dans ogure.'
raise Exception(erreur)
# liste_error = impact_decisions(old_administre, administre, old_avis, avis, eip, fe_code, categorie)
elif 'a_domaine_futur_id' in fields or 'a_filiere_futur_id' in fields or 'a_nf_futur' in fields:
for i in range(len(objs)):
old_administre = Administre.objects.get(a_id_sap=objs[i].a_id_sap)
administre = objs[i]
dom = administre.a_domaine_futur_id if 'a_domaine_futur_id' in fields else old_administre.a_domaine_futur_id
fil = administre.a_filiere_futur_id if 'a_filiere_futur_id' in fields else old_administre.a_filiere_futur_id
nf = administre.a_nf_futur if 'a_nf_futur' in fields else old_administre.a_nf_futur
cat = nf2categorie(nf)
sv_id = generate_sv_id(dom, fil, cat)
sv = SousVivier.objects.filter(sv_id=sv_id)
try:
sv.exists()
administre.sous_vivier_id = sv_id
if 'sous_vivier_id' not in fields:
fields += ['sous_vivier_id']
except:
message = f"La mise à jour a échoué car la sous-vivier d'id : {sv_id} n'est pas en base"
self.logger.exception(message)
raise APIException(message)
Administre.objects.bulk_update(objs, fields=fields)
return Response({'msg': 'updated'})
except APIException:
raise
except Exception:
message = 'échec de la mise à jour de N administrés'
self.logger.exception(message)
raise APIException(message)
def partial_update(self, request, pk=None):
""" La fonction put met à jour un administre.
:type request: rest_framework.request.Request
:param request: Request contenant l'administre.
:type pk: integer
:param pk: Primary Key de l'administre.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour de l'administre .
"""
try:
a = get_object_or_404(Administre.objects, a_id_sap=pk) # Permet de déclancher la vérification des droits au niveau de l'objet
self.check_object_permissions(self.request, a)
req_data = request.data
if 'annee_pam' in req_data:
annee_pam = req_data.pop('annee_pam')
# TODO valider les données (il faut d'abord corriger la MAJ des compétences)
# validator = self.serializer_class(data=req_data, partial=True)
# validator.is_valid(raise_exception=True)
Cols = Administre.Cols
# Copie et complète si besoin le dictionnaire en entrée
# administre = {**validator.validated_data}
administre = {**req_data}
administre[Cols.PK] = pk
fields = [key for key in administre.keys() if key != Cols.PK] # and key != 'a_liste_id_competences']
if 'a_domaine_futur' in fields:
administre['a_domaine_futur_id'] = administre['a_domaine_futur']
del administre['a_domaine_futur']
if 'a_filiere_futur' in fields:
administre['a_filiere_futur_id'] = administre['a_filiere_futur']
del administre['a_filiere_futur']
if 'a_domaine_futur' in fields or 'a_filiere_futur' in fields or 'a_nf_futur' in fields:
old_administre = Administre.objects.get(a_id_sap=pk)
dom = administre['a_domaine_futur_id'] if 'a_domaine_futur' in fields else old_administre.a_domaine_futur_id
fil = administre['a_filiere_futur_id'] if 'a_filiere_futur' in fields else old_administre.a_filiere_futur_id
nf = administre['a_nf_futur'] if 'a_nf_futur' in fields else old_administre.a_nf_futur
cat = nf2categorie(nf)
sv_id = generate_sv_id(dom, fil, cat)
sv = SousVivier.objects.filter(sv_id=sv_id)
try:
sv.exists()
administre['sous_vivier_id'] = sv_id
fields += ['sous_vivier_id']
except:
message = f"La mise à jour a échoué car la sous-vivier d'id : {sv_id} n'est pas en base"
self.logger.exception(message)
raise APIException(message)
if Cols.STATUT_PAM in fields:
old_administre = Administre.objects.get(a_id_sap=pk)
eip = old_administre.a_eip
fe_code = old_administre.formation_emploi_id
avis = administre[Cols.STATUT_PAM]
old_avis = old_administre.a_statut_pam
try:
categorie = constants.CATEGORIE_BY_NF[old_administre.a_nf.upper()]
except:
erreur = 'la catégorie de l\'administré n\'est pas reconnue dans ogure.'
raise APIException(erreur)
if 'a_liste_id_competences' in fields:
adm=Administre(pk=pk)
if administre['a_liste_id_competences']:
adm.a_liste_id_competences.set(administre['a_liste_id_competences'].split(','))
else:
adm.a_liste_id_competences.set("")
elif Cols.STATUT_PAM in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_statut_pam_annee = administre[Cols.STATUT_PAM]
adm_pam.save()
elif 'notes_pam' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.notes_pam = administre['notes_pam']
adm_pam.save()
elif 'a_ciat_pam' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_ciat_pam = administre['a_ciat_pam']
adm_pam.save()
elif 'a_specifique_pam' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_specifique_pam = administre['a_specifique_pam']
adm_pam.save()
elif 'a_liste_depts_souhaites_pam' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_liste_depts_souhaites_pam = administre['a_liste_depts_souhaites_pam']
adm_pam.save()
elif 'a_liste_zones_geographiques_shm_pam' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_liste_zones_geographiques_shm_pam = administre['a_liste_zones_geographiques_shm_pam']
adm_pam.save()
elif 'a_situationfuture_notes_fe' in fields:
adm_pam = Administres_Pams.objects.get(id = str(pk)+str(annee_pam))
adm_pam.a_situationfuture_notes_fe = administre['a_situationfuture_notes_fe']
adm_pam.save()
else:
copy = {k: v for k, v in administre.items() if k != 'a_liste_id_competences'}
adm = Administre(**copy)
if fields:
Administre.objects.bulk_update([adm], fields=fields)
return Response({'msg': 'updated'})
except (Http404, APIException):
raise
except Exception:
message = "échec de la mise à jour de l'administré"
self.logger.exception(message)
raise APIException(message)
@execution_time_viewset
@query_count_viewset
@class_logger
class PostePAMView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des postes.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
lookup_value_regex = r"[\w.]+"
serializer_class = PostesPamsSerializer
pagination_class = HeavyDataPagination
filter_backends = [DjangoFilterBackend, RelatedOrderingFilter]
filterset_class = PostePAMFilter
# ordering_fields = '__all_related__'
ordering = ['poste_id','-p_pam']
# important : mettre à jour quand le serializer change
def get_queryset(self):
"""Cette fonction permet d'ajouter plus de logique à l'attribut queryset."""
Cols = Postes_Pams.Cols
Poste_Cols = Poste.Cols
queryset = Postes_Pams.objects.select_related(
Cols.REL_PAM
).prefetch_related(
Prefetch(Cols.O2M_DECISION, queryset=Decision.objects.select_related(f'{Decision.Cols.REL_ADMINISTRE}__{Administre.Cols.REL_GRADE}')),
Prefetch(Cols.REL_POSTE, queryset=Poste.objects.select_related(Poste_Cols.REL_FONCTION)
.prefetch_related(
Poste_Cols.M2M_COMPETENCES,
Poste_Cols.M2M_SOUS_VIVIERS,
Prefetch(Poste_Cols.REL_FORMATION_EMPLOI,
queryset=FormationEmploi.objects.select_related(FormationEmploi.Cols.REL_MERE))))
)
sous_viviers_name = self.request.query_params.get('sous_vivier')
if sous_viviers_name is not None:
queryset = queryset.filter(poste__sous_viviers__in=sous_viviers_name.split('-'))
return queryset
def put(self, request):
"""La fonction put met à jour une liste des postes.
:type request: rest_framework.request.Request
:param request: Request contenant la liste des postes.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour des postes .
"""
data = request.data
self.logger.debug('------------------------- Modification Multiple de Poste verification ---------------------')
self.logger.debug('Request data : %s', data)
if 'pam_id' in data[0]:
annee_pam = data[0]['pam_id']
# serialized = self.serializer_class(data=data, many=isinstance(data, list), partial=True)
# serialized.is_valid(raise_exception=True)
if isinstance(data, list): # Update multiple elements
try:
fields = [key for key in data[0].keys() if key != 'p_id' ]
if 'p_avis_fe' in fields:
fields_to_update_pam = ['p_avis_fe_pam', 'p_avis_pam']
# Creation d'une liste qui contient l'id ( p_id + annee_pam) avec l'avis choisi
data_statut_pam = [{'id' :str(o['p_id'])+str(annee_pam), 'p_avis_fe_pam' : o['p_avis_fe'], 'p_avis_pam' : o['p_avis_fe']} for o in data]
# Creation des objets Poste Pams
objs = [Postes_Pams(**data_item) for data_item in data_statut_pam]
# Mise a jour des objets Poste Pams
Postes_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'p_avis' in fields:
fields_to_update_pam = ['p_avis_pam']
data_statut_pam = [{'id' :str(o['p_id'])+str(annee_pam), 'p_avis_pam' : o['p_avis']} for o in data]
objs = [Postes_Pams(**data_item) for data_item in data_statut_pam]
Postes_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'p_direct_commissionne' in fields:
fields_to_update_pam = ['p_direct_commissionne_pam']
data_statut_pam = [{'id' :str(o['p_id'])+str(annee_pam), 'p_direct_commissionne_pam' : o['p_direct_commissionne']} for o in data]
objs = [Postes_Pams(**data_item) for data_item in data_statut_pam]
Postes_Pams.objects.bulk_update(objs, fields=fields_to_update_pam)
elif 'p_itd_cellule' in fields:
sous_viviers = sous_viviers_du_cellule(data[0]['p_itd_cellule'])
self.logger.debug('Modification Multiple de p_itd_cellule, les sous_viviers de la cellule sont : %s', sous_viviers)
if sous_viviers:
objs = [Poste(**data[i]) for i in range(len(data))]
Poste.objects.bulk_update(objs, fields=fields)
objs_w_comp = [Poste(**without_keys(data[i], ['p_itd_cellule'])).sous_viviers.set(sous_viviers) for i in range(len(data))]
else:
return JsonResponse({'info': f"La mise à jour n'a pas réussi : la cellule '{data[0]['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application."})
elif 'competence_id' not in fields:
if 'supression' in fields:
elem = data[0]
Postes_Pams.objects.filter(p_pam_id=elem['pam_id'],poste_id=elem['p_id']).delete()
if 'departement' and 'codeFe' and 'lieu' and 'zoneDeDefense' and 'codeFeMere' and 'etr' in fields:
elem = data[0]
#generate random id : create compteur de poste en sureff
no_sureff = str(Postes_Pams.objects.filter(p_pam_id=str(annee_pam),id__contains='_').count() + 1)
pam_actuel = PAM.objects.get(pam_statut='PAM en cours').pam_id
#on crée l'instance de formation d'emploi
fe = FormationEmploi.objects.get(fe_code=elem['codeFe'])
fe_poste_duplique = fe
fe_poste_duplique.zone_defense =elem['zoneDeDefense']
fe_poste_duplique.fe_garnison_lieu = elem['lieu']
fe_poste_duplique.save()
#créer une copie d'instance de poste qui existe déjà en base:
poste = Poste.objects.get(p_id=elem['p_id'])
poste_duplique = poste
poste_duplique.p_id = poste.p_id + '_'+ no_sureff
poste_duplique.p_dep= elem['departement']
poste_duplique.p_fonction = elem['etr']
poste_duplique.formation_emploi = fe_poste_duplique
poste_duplique.save()
if elem['pam_id'] == pam_actuel:
poste_sureffA = Postes_Pams.objects.get(id=elem['p_id'] + elem['pam_id'])
poste_sureffA.id = elem['p_id']+ '_'+ no_sureff + elem['pam_id']
poste_sureffA.poste_id = elem['p_id']+ '_'+ no_sureff
poste_sureffA.poste = poste_duplique
poste_sureffA.info_reo = f"SUREFF {str(annee_pam)}"
poste_sureffA.save()
poste_sureffA1 = Postes_Pams.objects.get(id=elem['p_id'] + str(int(elem['pam_id'])+1))
poste_sureffA1.id = elem['p_id']+ '_'+ no_sureff +str(int(elem['pam_id'])+1)
poste_sureffA1.poste_id = elem['p_id']+ '_'+ no_sureff
poste_sureffA1.poste = poste_duplique
poste_sureffA1.info_reo = f"SUREFF {str(annee_pam)}"
poste_sureffA1.save()
else:
poste_sureffA1 = Postes_Pams.objects.get(id=elem['p_id'] + elem['pam_id'])
poste_sureffA1.id = elem['p_id']+ '_'+ no_sureff + elem['pam_id']
poste_sureffA1.poste_id = elem['p_id']+ '_'+ no_sureff
poste_sureffA1.poste = poste_duplique
poste_sureffA1.info_reo = f"SUREFF {str(annee_pam)}"
poste_sureffA1.save()
else:
objs = [Poste(**data[i]) for i in range(len(data))]
Poste.objects.bulk_update(objs, fields=fields)
else:
objs_w_comp = [Poste(**without_keys(data[i],['competence_id'])).competences.set(data[i]['competence_id'].split(',')) for i in range(len(data))]
except:
raise Exception("bulk update error")
return Response({'msg': 'updated'})
def partial_update(self, request, pk=None):
""" La fonction put met à jour un poste.
:type request: rest_framework.request.Request
:param request: Request contenant le poste.
:type pk: integer
:param pk: Primary Key du poste.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour du poste .
"""
p = get_object_or_404(Poste.objects, p_id=pk) # Permet de déclancher la vérification des droits au niveau de l'objet
self.check_object_permissions(self.request, p)
poste = request.data
self.logger.debug('------------------------- Modification Unitaire de Poste verification ---------------------')
self.logger.debug('Request data : %s', poste)
if 'annee_pam' in poste:
annee_pam = poste.pop('annee_pam')
fields_not_updated = ['p_id', 'p_poids_filiere', 'p_poids_nf', 'p_poids_competences']
fields = [key for key in poste.keys() if key not in fields_not_updated]
poste['p_id'] = pk
if 'competence' in fields:
pos=Poste(pk=pk)
if poste['competence']:
pos.competences.set(poste['competence'].split(','))
else:
pos.competences.set("")
elif 'sous_vivier_id' in fields:
pos=Poste(pk=pk)
pos.sous_viviers.add(poste['sous_vivier_id'])
elif 'p_avis_fe_pam' in fields:
poste_pam = Postes_Pams.objects.get(id = str(pk)+str(annee_pam))
poste_pam.p_avis_pam = poste['p_avis_fe_pam']
poste_pam.p_avis_fe_pam = poste['p_avis_fe_pam']
poste_pam.save()
elif 'p_avis_pam' in fields:
poste_pam = Postes_Pams.objects.get(id = str(pk)+str(annee_pam))
poste_pam.p_avis_pam = poste['p_avis_pam']
poste_pam.save()
elif 'p_direct_commissionne_pam' in fields:
poste_pam = Postes_Pams.objects.get(id = str(pk)+str(annee_pam))
poste_pam.p_direct_commissionne_pam = poste['p_direct_commissionne_pam']
poste_pam.save()
elif 'p_priorisation_pcp_pam' in fields:
poste_pam = Postes_Pams.objects.get(id = str(pk)+str(annee_pam))
poste_pam.p_priorisation_pcp_pam = poste['p_priorisation_pcp_pam']
poste_pam.save()
elif 'p_notes_gestionnaire_pam' in fields:
poste_pam = Postes_Pams.objects.get(id = str(pk)+str(annee_pam))
poste_pam.p_notes_gestionnaire_pam = poste['p_notes_gestionnaire_pam']
poste_pam.save()
else:
copy = {k: v for k, v in poste.items() if k != 'competence'}
pos = Poste(**copy)
# l'orde des if est tres important
if 'p_specifique' in fields and poste['p_specifique'] == SpecifiqueChoices.ITD:
pos.p_itd_affecte = False
fields += ['p_itd_affecte']
elif 'p_itd_cellule' in fields:
sous_viviers = sous_viviers_du_cellule(poste['p_itd_cellule'])
if sous_viviers:
pos.sous_viviers.set(sous_viviers)
pos.p_itd_affecte = True
fields += ['p_itd_affecte']
else :
self.logger.debug(f"La mise à jour n'a pas réussi, La cellule '{poste['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application.")
return JsonResponse({'info': f"La mise à jour n'a pas réussi : la cellule '{poste['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application."})
if fields:
Poste.objects.bulk_update([pos], fields=fields)
return Response({'msg': 'updated'})
@execution_time_viewset
@query_count_viewset
@class_logger
class PosteView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des postes.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
lookup_value_regex = r"[\w.]+"
serializer_class = PosteSerializer
pagination_class = HeavyDataPagination
filter_backends = [DjangoFilterBackend, RelatedOrderingFilter]
filterset_class = PosteFilter
ordering_fields = '__all_related__'
ordering = ['p_id']
# important : mettre à jour quand le serializer change
def get_queryset(self):
"""Cette fonction permet d'ajouter plus de logique à l'attribut queryset."""
Cols = Poste.Cols
queryset = Poste.objects.select_related(
Cols.REL_FONCTION
).prefetch_related(
Cols.M2M_COMPETENCES,
Cols.M2M_SOUS_VIVIERS,
Prefetch(Cols.M2M_PAM, queryset=Postes_Pams.objects.select_related(Postes_Pams.Cols.O2M_DECISION)),
Prefetch(Cols.O2M_DECISION, queryset=Decision.objects.select_related(f'{Decision.Cols.REL_ADMINISTRE}__{Administre.Cols.REL_GRADE}')),
Prefetch(Cols.REL_FORMATION_EMPLOI, queryset=FormationEmploi.objects.select_related(FormationEmploi.Cols.REL_MERE)),
).annotate(
p_nb_prepositionne=Sum(
Case(When(decisions__de_decision=DecisionChoices.PREPOSITIONNE, then=1), default=0,
output_field=IntegerField())),
p_nb_positionne=Sum(Case(When(decisions__de_decision=DecisionChoices.POSITIONNE, then=1), default=0,
output_field=IntegerField())),
p_nb_omi_en_cours=Sum(Case(When(decisions__de_decision=DecisionChoices.OMI_EN_COURS, then=1), default=0,
output_field=IntegerField())),
p_nb_omi_active=Sum(Case(When(decisions__de_decision=DecisionChoices.OMI_ACTIVE, then=1), default=0,
output_field=IntegerField())),
)
sous_viviers_name = self.request.query_params.get('sous_vivier')
if sous_viviers_name is not None:
queryset = queryset.filter(sous_viviers=sous_viviers_name)
return queryset
def put(self, request):
"""La fonction put met à jour une liste des postes.
:type request: rest_framework.request.Request
:param request: Request contenant la liste des postes.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour des postes .
"""
data = request.data
self.logger.debug('------------------------- Modification Multiple de Poste verification ---------------------')
self.logger.debug('Request data : %s', data)
serialized = self.serializer_class(data=data, many=isinstance(data, list), partial=True)
serialized.is_valid(raise_exception=True)
if isinstance(data, list): # Update multiple elements
try:
fields = [key for key in data[0].keys() if key != 'p_id' ]
if 'p_itd_cellule' in fields:
sous_viviers = sous_viviers_du_cellule(data[0]['p_itd_cellule'])
self.logger.debug('Modification Multiple de p_itd_cellule, les sous_viviers de la cellule sont : %s', sous_viviers)
if sous_viviers:
objs = [Poste(**data[i]) for i in range(len(data))]
Poste.objects.bulk_update(objs, fields=fields)
objs_w_comp = [Poste(**without_keys(data[i],['p_itd_cellule'])).sous_viviers.set(sous_viviers) for i in range(len(data))]
else :
return JsonResponse({'info': f"La mise à jour n'a pas réussi, La cellule '{data[0]['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application."})
elif 'competence_id' not in fields:
objs = [Poste(**data[i]) for i in range(len(data))]
Poste.objects.bulk_update(objs, fields=fields)
else:
objs_w_comp = [Poste(**without_keys(data[i],['competence_id'])).competences.set(data[i]['competence_id'].split(',')) for i in range(len(data))]
except:
raise Exception("bulk update error")
else: # Update one element
a_id_sap = Poste.objects.update(serialized.validated_data)
db_instance = Poste.objects.filter(
a_id_sap=a_id_sap).first()
db_instance.tag.clear()
return Response({'msg': 'updated'})
def partial_update(self, request, pk=None):
""" La fonction put met à jour un poste.
:type request: rest_framework.request.Request
:param request: Request contenant le poste.
:type pk: integer
:param pk: Primary Key du poste.
:return: - **Response** (*Response*): Reponse contient un message de la réussite de met à jour du poste .
"""
p = get_object_or_404(Poste.objects, p_id=pk) # Permet de déclancher la vérification des droits au niveau de l'objet
self.check_object_permissions(self.request, p)
poste = request.data
self.logger.debug('------------------------- Modification Unitaire de Poste verification ---------------------')
self.logger.debug('Request data : %s', poste)
fields_not_updated = ['p_id', 'p_poids_filiere', 'p_poids_nf', 'p_poids_competences']
fields = [key for key in poste.keys() if key not in fields_not_updated]
poste['p_id'] = pk
if 'competence' in fields:
pos=Poste(pk=pk)
if poste['competence']:
pos.competences.set(poste['competence'].split(','))
else:
pos.competences.set("")
elif 'sous_vivier_id' in fields:
pos=Poste(pk=pk)
pos.sous_viviers.add(poste['sous_vivier_id'])
else:
copy = { k: v for k, v in poste.items() if k != 'competence'}
pos = Poste(**copy)
if 'p_avis_fe' in fields:
pos.p_avis = poste['p_avis_fe']
fields += ['p_avis']
# l'orde des if est tres important
if 'p_specifique' in fields and poste['p_specifique'] == SpecifiqueChoices.ITD:
pos.p_itd_affecte = False
fields += ['p_itd_affecte']
elif 'p_itd_cellule' in fields:
sous_viviers = sous_viviers_du_cellule(poste['p_itd_cellule'])
if sous_viviers:
pos.sous_viviers.set(sous_viviers)
pos.p_itd_affecte = True
fields += ['p_itd_affecte']
else :
self.logger.debug(f"La mise à jour n'a pas réussi, La cellule '{poste['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application.")
return JsonResponse({'info': f"La mise à jour n'a pas réussi, La cellule '{poste['p_itd_cellule']}' n'a pas de sous viviers enregistrés dans l'application."})
if fields:
Poste.objects.bulk_update([pos], fields=fields)
return Response({'msg': 'updated'})
@execution_time_viewset
@query_count_viewset
class ListesPreferencesView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des ListesPreferences.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = PreferencesListe
queryset = PreferencesListe.objects.all()
@execution_time_viewset
@query_count_viewset
class MarqueView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des marques.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = MarqueSerializer
queryset = Marque.objects.all()
@execution_time_viewset
@query_count_viewset
class MarquesGroupeView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des marquegroupes.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = MarquesGroupeSerializer
queryset = MarquesGroupe.objects.all()
@execution_time_viewset
@query_count_viewset
class FmobView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des Fmob.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = FmobSerializer
queryset = FMOB.objects.all()
@execution_time_viewset
@query_count_viewset
class FiliereView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des filieres.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = FiliereSerializer
queryset = Filiere.objects.all()
@execution_time_viewset
@query_count_viewset
class DomaineView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue des domaines.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = DomaineSerializer
queryset = Domaine.objects.all()
@execution_time_viewset
@query_count_viewset
class SousVivierAssociationView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue du SousVivierAssociation.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = SousVivierAssociationSerializer
queryset = SousVivierAssociation.objects.all()
@execution_time_viewset
@query_count_viewset
class PcpFeGroupeView(viewsets.ModelViewSet):
"""
Cette classe est dédiée au vue du PcpFeGroupe.
"""
permission_classes = [IsAuthenticated, GestionnairePermission]
serializer_class = PcpFeGroupeSerializer
queryset = PcpFeGroupe.objects.all()