Files
sirh/gestion_employe/views.py

463 lines
20 KiB
Python
Raw Normal View History

2026-04-30 13:28:57 +02:00
import json
2026-04-30 13:33:39 +02:00
from datetime import date, timedelta, datetime
2026-04-30 13:28:57 +02:00
from dateutil.relativedelta import relativedelta
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.forms.models import model_to_dict
from django.db.models import Sum
from .models import Employe, Contrat, Affectation, Formation
from .forms import AffectationForm, ContratForm, FormationForm
from fonction_utilitaire import fonctions_utilitaire
@login_required
def index(request):
"""Vue d'index"""
employes = Employe.objects.all().order_by('-user__date_joined')
nombre_employes = Employe.objects.count()
nombre_cps = Contrat.objects.filter(type_contrat='contrat_prestation').count()
nombre_stage = Contrat.objects.filter(type_contrat='contrat_stage').count()
date_limite = timezone.now().date() + timedelta(days=60)
nombre_expirants = Contrat.objects.filter(
date_fin__lte=date_limite,
date_fin__gte=timezone.now().date(),
statut='actif'
).count()
return render(request, 'gestion_employe/index.html', {
'employes': employes,
'nombre_employes': nombre_employes,
'nombre_cps': nombre_cps,
'nombre_stage': nombre_stage,
'nombre_expirants': nombre_expirants,
'affectation_form': AffectationForm(),
'contrat_form': ContratForm()
})
@login_required
def liste_contrat_expirants(request):
""" Liste des contrats proches """
date_limite = timezone.now().date() + timedelta(days = fonctions_utilitaire.DUREE_FIN_CONTRAT)
contats_expirants = [
{
'employe': f"{contrat.employe.user.first_name} {contrat.employe.user.last_name}",
'type_contrat': dict(Contrat.TYPE_CONTRAT).get(contrat.type_contrat),
'date_debut': contrat.date_debut,
'date_fin': contrat.date_fin,
'statut': contrat.statut,
'fichier_contrat': contrat.fichier_contrat.url if contrat.fichier_contrat else ""
}
for contrat in
Contrat.objects.filter(date_fin__lte=date_limite, date_fin__gte=timezone.now().date(), statut='actif')
]
return JsonResponse(contats_expirants, safe=False)
@login_required
def affecter_employe_projet(request):
"""Vue pour affecter un employé à un projet avec vérification des contraintes d'affectation"""
if request.method == 'POST':
employe_id = request.POST.get('affecter_employe_id')
try:
employe = Employe.objects.get(id=employe_id)
except Employe.DoesNotExist:
messages.error(request, "L'employé spécifié n'existe pas.")
return redirect('gestion_employe:index')
form = AffectationForm(request.POST)
if form.is_valid():
projet = form.cleaned_data['projet']
date_fin_affectation = form.cleaned_data['date_fin_daffectation']
temps_nouveau = form.cleaned_data['pourcentage_temps_affectation']
date_affectation = form.cleaned_data['date_affectation']
if (date_fin_affectation and date_affectation):
total_affectation = (
Affectation.objects.filter(employe=employe)
.aggregate(total_pourcentage_affectation = Sum('pourcentage_temps_affectation'))
['total_pourcentage_affectation'] or 0
)
if (date_fin_affectation < date_affectation):
messages.warning(request, "La date de fin d'affectation ne peut pas être antérieure à la date de début.")
return redirect('gestion_employe:index')
elif date_fin_affectation > projet.date_fin:
messages.warning(request, f"La date de fin de l'affectation ({date_fin_affectation}) ne peut pas dépasser la date de fin du projet ({projet.date_fin}).")
return redirect('gestion_employe:index')
elif total_affectation + temps_nouveau > 100:
messages.warning(
request,
f"Les pourcentages d'affectation de l'employé {employe.first_name} {employe.last_name} dépasse 100% sur les différents projets ({total_affectation + temps_nouveau}%)."
)
return redirect('gestion_employe:index')
Affectation.objects.update_or_create(
employe=employe,
projet=projet,
defaults={
'date_affectation': form.cleaned_data['date_affectation'],
'date_fin_daffectation': date_fin_affectation,
'role': form.cleaned_data['role'],
'pourcentage_temps_affectation': temps_nouveau,
}
)
messages.success(request, f"L'employé {employe.user.first_name} {employe.user.last_name} a été affecté au projet {projet.nom_projet}.")
return redirect('gestion_employe:index')
else:
messages.error(request, "Erreur : Formulaire non valide.")
return redirect('gestion_employe:index')
else:
return redirect('gestion_employe:index')
@login_required
def mon_profil(request):
"""Vue pour afficher et modifier le profil de l'utilisateur connecté"""
try:
employe = Employe.objects.get(user__username=request.user)
except Employe.DoesNotExist:
messages.error(request, "Impossible d'acceder au menu 'Mon profil' car votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'Administrateur.")
return redirect("gestion_conges:conge")
contrats = Contrat.objects.filter(employe=employe, statut='actif').first()
projets = Affectation.objects.filter(
employe = employe,
date_fin_daffectation__gte = timezone.now().date()
).select_related('projet')
return render(
request,
'gestion_employe/monprofil.html',
{
'employe': employe,
'contrats': [{
**model_to_dict(contrats),
"type_contrat": dict(Contrat.TYPE_CONTRAT).get(contrats.type_contrat),
"statut": dict(Contrat.STATUT_CONTRAT).get(contrats.statut),
"fichier_contrat": contrats.fichier_contrat.url if contrats.fichier_contrat else "",
} if contrats else []],
'projets': [
{
**model_to_dict(a.projet),
"date_affectation": a.date_affectation,
"date_fin_daffectation": a.date_fin_daffectation,
"role": dict(Affectation.ROLE_CHOICES).get(a.role),
"pourcentage_temps_affectation": a.pourcentage_temps_affectation
} for a in projets
],
"formation_form": FormationForm(),
"expiration_contrat": contrats.nombre_jours_restant <= fonctions_utilitaire.DUREE_FIN_CONTRAT if contrats else False,
"contrat_nb_jours_restant": contrats.nombre_jours_restant if contrats else None
}
)
@login_required
def modifier_mot_passe(request):
"""Vue pour permettre à un utilisateur de modifier son mot de passe et ses informations de profil"""
user = User.objects.get(username=request.user)
if request.method == "POST":
ancien_mdp = request.POST["ancien-mdp"]
nouveau_mdp = request.POST["nouveau-mdp"]
confirmation_mdp = request.POST["confirmation-mdp"]
if authenticate(request, username=request.user, password=ancien_mdp) is None:
messages.error(request, "Ancien mot de passe incorrect.")
elif nouveau_mdp != confirmation_mdp:
messages.error(request, "Les deux nouveaux ne correspondent pas.")
else:
user.set_password(nouveau_mdp)
user.save()
messages.success(request, "Mot de passe modifié avec succès.")
return redirect("gestion_employe:mon-profil")
def modifier_employer(request):
"""Vue pour permettre à un utilisateur de modifier les informations d'un employé"""
try:
employe = Employe.objects.get(user__username=request.user)
except Employe.DoesNotExist:
return JsonResponse({"message": "Employé non trouvé."})
if request.method == "POST":
data = json.loads(request.body)
user = User.objects.get(username=request.user)
user.last_name = data['nom']
user.first_name = data['prenom']
user.email = data['email']
employe.telephone = data['telephone']
employe.adresse = data['adresse']
employe.sexe = data['sexe']
if request.FILES.get("photo"):
employe.photo = request.FILES["photo"]
if data['date_naissance']:
difference = relativedelta(timezone.now().date(), datetime.strptime(data['date_naissance'], "%Y-%m-%d").date())
if difference.years >= 18:
employe.date_naissance = data['date_naissance']
else:
return JsonResponse({"message": "Veuillez entrez une date de naissance correcte."})
employe.save()
user.save()
return JsonResponse({"message": "Profil mis à jour avec succès."})
def enregistrement_document(request):
employe = Employe.objects.get(user=request.user)
if request.method == "POST":
if request.FILES.get("photo"):employe.photo = request.FILES["photo"]
if "cv" in request.FILES:employe.CV = request.FILES["cv"]
if "diplome" in request.FILES: employe.diplome = request.FILES["diplome"]
if "rib" in request.FILES: employe.rib = request.FILES["rib"]
if "casier_judiciaire" in request.FILES:employe.casier_judiciaire = request.FILES["casier_judiciaire"]
employe.save()
messages.success(request, "Documents enregistrés avec succès.")
return redirect("gestion_employe:mon-profil")
def suppression_contrat(request):
"""Vue pour permettre à un utilisateur de supprimer un contrat"""
id_contrat = json.loads(request.body)['id']
try:
contrat = Contrat.objects.get(numero_contrat = id_contrat)
except Contrat.DoesNotExist:
messages.error(request, "Contrat non trouvé.")
return JsonResponse({"message": "Contrat non trouvé."}, status=404)
contrat.delete()
return JsonResponse({"message": "Contrat supprimé avec succès."})
def suppression_affectation(request):
"""Vue pour permettre à un utilisateur de supprimer une affectation"""
id_affectation = json.loads(request.body)['id']
try:
affectation = Affectation.objects.get(id=id_affectation)
except Affectation.DoesNotExist:
return JsonResponse({"message": "Affectation non trouvée."}, status=404)
affectation.delete()
return JsonResponse({"message": "Affectation supprimée avec succès."})
def creation_contrat(request):
2026-04-30 13:33:39 +02:00
"""Créer un contrat pour un employé (avec contrôle d'existence de contrat actif)"""
2026-04-30 13:28:57 +02:00
try:
employe = Employe.objects.get(id=request.POST.get('employe_id'))
except Employe.DoesNotExist:
messages.error(request, "Employé non trouvé.")
return redirect('employe-index')
2026-04-30 13:33:39 +02:00
contrat_actif = Contrat.objects.filter(
employe=employe,
date_fin__gte=date.today()
).exists()
2026-04-30 13:28:57 +02:00
if request.method == "POST":
2026-04-30 13:33:39 +02:00
if contrat_actif:
messages.error(
request,
"Impossible de créer un contrat : cet employé a déjà un contrat actif."
)
return redirect('gestion_employe:index')
2026-04-30 13:28:57 +02:00
form = ContratForm(request.POST, request.FILES)
if form.is_valid():
contrat = form.save(commit=False)
contrat.employe = employe
contrat.save()
messages.success(request, "Contrat créé avec succès.")
return redirect('gestion_employe:index')
messages.error(request, "Formulaire non valide")
2026-04-30 13:33:39 +02:00
2026-04-30 13:28:57 +02:00
else:
form = ContratForm(initial={'employe': employe})
2026-04-30 13:33:39 +02:00
return render(request, 'gestion_employe/index.html', {
'contrat_form': form
})
2026-04-30 13:28:57 +02:00
@login_required
def enregistrer_detail_employe(request):
"""Vue pour permettre à un utilisateur de modifier les détails d'un employé via une requête AJAX"""
if request.method == "POST":
data = json.loads(request.body)
try:
employe = Employe.objects.get(id=data['id'])
except Employe.DoesNotExist:
return JsonResponse({"error": "Employé non trouvé."}, status=404)
employe.fonction = data['fonction']
employe.date_embauche = data['date_embauche']
employe.matricule = data['matricule']
employe.save()
return JsonResponse({"message": "Détails de l'employé mis à jour avec succès."})
else:
return JsonResponse({"message": "Méthode non autorisée."}, status=405)
@login_required
def liste_employe(request):
""" Vue pour retourner la liste de tous les employés """
employes = Employe.objects.exclude(user__first_name = '', user__last_name = '')
data = []
for employe in employes:
if employe.user.first_name != ' ' and employe.user.last_name != ' ':
projets = [
", ".join([
a.projet.nom_projet for a in Affectation.objects.filter(
employe=employe,
date_fin_daffectation__gte=timezone.now().date()
)
])
]
formations = [
{
"titre": formation.titre,
"organisme": formation.organisme,
"description": formation.description,
"date_obtention": formation.date_obtention,
"date_fin": formation.date_fin,
"certificat": formation.certificat.url if formation.certificat else "",
} for formation in Formation.objects.filter(employe=employe)
]
contrats = [
{
"numero_contrat": contrat.numero_contrat,
"type_contrat": contrat.type_contrat,
"date_debut": contrat.date_debut,
"date_fin": contrat.date_fin,
"salaire_mensuel": contrat.salaire_mensuel,
"statut": contrat.statut,
"fichier_contrat": contrat.fichier_contrat.url if contrat.fichier_contrat else "",
} for contrat in Contrat.objects.filter(employe=employe, statut='actif')
]
affectations = [
{**model_to_dict(affectation), "projet": affectation.projet.nom_projet}
for affectation in Affectation.objects.filter(
employe=employe,
date_fin_daffectation__gte=timezone.now().date()
)
]
data.append(
{
"id": employe.id,
"employe": f"{employe.user.first_name} {employe.user.last_name}",
"matricule": employe.matricule,
"email": employe.user.email,
"formations": formations,
"affectations": affectations,
"projet": projets,
"contrats": contrats,
"departement": employe.departement.nom if employe.departement else "",
"fonction": employe.fonction,
"date_embauche": employe.date_embauche,
"adresse": employe.adresse,
"telephone": employe.telephone,
"sexe": employe.sexe,
"CV": employe.CV.url if employe.CV else "",
"diplome": employe.diplome.url if employe.diplome else "",
"rib": employe.rib.url if employe.rib else "",
"photo": employe.photo.url if employe.photo else "",
"casier_judiciaire": employe.casier_judiciaire.url if employe.casier_judiciaire else "",
"date_naissance": employe.date_naissance,
}
)
return JsonResponse({'success': True, 'data': data}, safe=False)
@login_required
def ajouter_formation(request):
"""Vue pour permettre à un employé d'ajouter une formation à son profil"""
employe = Employe.objects.get(user__username=request.user)
if request.method == "POST":
formation = FormationForm(request.POST, request.FILES)
if formation.is_valid():
ma_formation = formation.save(commit=False)
ma_formation.employe = employe
ma_formation.save()
messages.success(request, "Formation ajoutée avec succès ")
return redirect("gestion_employe:mon-profil")
messages.error(request, "Formulaire non valide. Veuillez vérifier les informations saisies.")
return redirect("gestion_employe:mon-profil")
def liste_formation(request):
formations = Formation.objects.filter(employe__user__username=request.user).order_by("-date_obtention")
return JsonResponse([
{
**model_to_dict(formation),
"certificat": formation.certificat.url if formation.certificat else ""
}
for formation in formations
], safe=False)
@login_required
def modifier_formation(request, id_formation):
"""Vue pour permettre à un employé de modifier une formation de son profil"""
try:
formation = Formation.objects.get(id=id_formation, employes=request.user)
except Formation.DoesNotExist:
messages.error(request, "Formation non trouvée.")
return redirect("mes_formations")
if request.method == "POST":
formation = FormationForm(request.POST, request.FILES, instance=formation)
if formation.is_valid():
messages.success(request, "Formation mise à jour ")
formation.save()
messages.error(request, "Formulaire non valide. Veuillez vérifier les informations saisies.")
return redirect("mes_formations")
@login_required
def supprimer_formation(request, id_formation):
"""Vue pour permettre à un employé de supprimer une formation de son profil"""
try:
formation = Formation.objects.get(id=id_formation, employes=request.user)
except Formation.DoesNotExist:
messages.error(request, "Formation non trouvée.")
return redirect("mes_formations")
if request.method == "POST":
formation.delete()
messages.success(request, "Formation supprimée ")
return redirect("mes_formations")
# @login_required
# def creation_departement(request):
# """Gère la création d'un nouveau département via un formulaire."""
# if request.method == 'POST':
# form_departement = DepartementForm(request.POST)
# if form_departement.is_valid():
# form_departement.save()
# messages.success(request, "Département ajouté avec succès.")
# else:
# messages.error(request, "Erreur lors de l'ajout du département.")
# return redirect('parametres-rh')
# @login_required
# def modifier_departement(request, id):
# """Gère la modification d'un département existant via un formulaire pré-rempli."""
# departement = Departement.objects.get(id=id)
# form = DepartementForm(instance=departement)
# if request.method == 'POST':
# nouveau_nom_departement = request.POST.get('nom')
# if nouveau_nom_departement:
# departement.nom = nouveau_nom_departement
# departement.save()
# messages.success(request, "Département modifié avec succès.")
# return redirect('parametres-rh')
# return render(request, 'gestion_employe/edit_departement.html', {
# 'form': form,
# 'departement': departement
# })
# @login_required
# def supprimer_departement(request, id):
# """Gère la suppression d'un département existant."""
# if request.method == "POST":
# departement = Departement.objects.get(id=id)
# departement.delete()
# messages.success(request, "Département supprimé avec succès !")
# return redirect('parametres-rh')