clean: remove pycache from tracking
This commit is contained in:
485
gestion_projet/views.py
Normal file
485
gestion_projet/views.py
Normal file
@@ -0,0 +1,485 @@
|
||||
from datetime import date
|
||||
from decimal import Decimal, InvalidOperation
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.utils import timezone
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Sum
|
||||
from django.forms.models import model_to_dict
|
||||
from gestion_employe.forms import AffectationForm
|
||||
from gestion_employe.models import Affectation, Employe
|
||||
from gestion_projet.forms import ProjetForm
|
||||
from gestion_projet.models import Projet
|
||||
from .models import (
|
||||
DocumentProjet,
|
||||
Bailleur,
|
||||
FinancementProjet,
|
||||
ActiviteProjet,
|
||||
LivrablesLivres,
|
||||
)
|
||||
from .forms import (
|
||||
ActiviteProjetForm,
|
||||
DocumentProjetForm,
|
||||
FinancementProjetFrom,
|
||||
BailleurForm,
|
||||
LivrablesLivresForm
|
||||
)
|
||||
|
||||
def liste_projet(request):
|
||||
""" Vue pour retourner la liste de tous les projet """
|
||||
projets = Projet.objects.all().order_by('-created_at')
|
||||
|
||||
data = []
|
||||
for p in projets:
|
||||
financement = FinancementProjet.objects.filter(projet=p).select_related('bailleur')
|
||||
data.append({
|
||||
"id_projet": p.id_projet,
|
||||
"nom_projet": p.nom_projet,
|
||||
"date_debut": p.date_debut,
|
||||
"date_fin": p.date_fin,
|
||||
"numero_convention": p.numero_convention,
|
||||
"description": p.description,
|
||||
"type_projet": p.type_projet,
|
||||
"budget": p.budget,
|
||||
"budget_RH": p.budget_RH,
|
||||
"created_at": p.created_at,
|
||||
"statut": p.statut,
|
||||
"avancement": p.avancement,
|
||||
"domaine_recherche": [d.nom for d in p.domaine_recherche.all()],
|
||||
"source_financement": [f.bailleur.nom_organisme for f in financement],
|
||||
})
|
||||
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
def liste_employes_affectes(request, projet_id):
|
||||
""" Vue pour retourner la liste des employés affectés à un projet spécifique """
|
||||
employes = Employe.objects.filter(affectation__projet_id=projet_id).distinct()
|
||||
data = []
|
||||
for employe in employes:
|
||||
data.append({
|
||||
"employe": f"{employe.user.first_name} {employe.user.last_name}",
|
||||
"pourcentage_affectation": Affectation.objects.get(employe=employe, projet__id_projet=projet_id).pourcentage_temps_affectation
|
||||
})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
def liste_bailleurs(request, projet_id):
|
||||
""" Vue pour retourner la liste des bailleurs associés à un projet spécifique """
|
||||
bailleurs = FinancementProjet.objects.filter(projet_id=projet_id).select_related('bailleur')
|
||||
data = []
|
||||
for b in bailleurs:
|
||||
data.append({
|
||||
"bailleur": b.bailleur.nom_organisme,
|
||||
"pourcentage_financement": b.pourcentage
|
||||
})
|
||||
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
@login_required
|
||||
def index(request):
|
||||
projets = Projet.objects.all().order_by('-created_at')
|
||||
nombre_personnel = Affectation.objects.values('employe_id').distinct().count()
|
||||
budget_total = sum([projet.budget for projet in projets if projet.budget or 0])
|
||||
context = {
|
||||
'form': AffectationForm(),
|
||||
'form_ajout_financement': FinancementProjetFrom(),
|
||||
'form_ajout_bailleur': BailleurForm(),
|
||||
'bailleurs': Bailleur.objects.all(),
|
||||
'nombre_personnel': nombre_personnel,
|
||||
'budget_total': budget_total,
|
||||
'formulaire_creation_projet': ProjetForm(),
|
||||
'projet_en_cours': Projet.objects.filter(date_fin__gte=date.today()).count(),
|
||||
}
|
||||
|
||||
return render(request, 'gestion_projet/index.html', context)
|
||||
|
||||
@login_required
|
||||
def creation_projet(request):
|
||||
"""Vue pour créer un nouveau projet via un formulaire"""
|
||||
formulaire_creation_projet = ProjetForm()
|
||||
if request.method == "POST":
|
||||
form = ProjetForm(request.POST)
|
||||
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, "Projet créé avec succès.")
|
||||
else:
|
||||
messages.error(request, "Le formulaire transmis est invalide.")
|
||||
else:
|
||||
form = ProjetForm()
|
||||
return render(
|
||||
request,
|
||||
"gestion_projet/creation_projet.html",
|
||||
{
|
||||
"formulaire_creation_projet": formulaire_creation_projet
|
||||
}
|
||||
)
|
||||
|
||||
@login_required
|
||||
def mises_a_jour_projet(request):
|
||||
""" Vue de mises à jour des informations du projet """
|
||||
if request.method == "POST":
|
||||
try:
|
||||
projet = Projet.objects.get(id_projet = request.POST["id_projet"])
|
||||
except Projet.DoesNotExist:
|
||||
messages.error(request, "Ce projet n'existe pas.")
|
||||
else:
|
||||
projet_form = ProjetForm(request.POST, instance=projet)
|
||||
if projet_form.is_valid():
|
||||
projet_form.save()
|
||||
messages.success(request, f"Le projet d'identifiant {request.POST['id_projet']} a été mis à jour avec succès.")
|
||||
else:
|
||||
messages.error(request, f"Les informations de modification transmises pour la modification du projet {request.POST['id_projet']} ne sont pas valides.")
|
||||
else:
|
||||
messages.error(request, "La méthode de transmission des données n'est pas valide.")
|
||||
return redirect('gestion_projet:index')
|
||||
|
||||
@login_required
|
||||
def creation_bailleur(request):
|
||||
form = BailleurForm(request.POST)
|
||||
if request.method == 'POST':
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return JsonResponse({'success': True})
|
||||
return JsonResponse({'success': False})
|
||||
|
||||
@login_required
|
||||
def ajouter_financement_projet(request):
|
||||
"""Ajoute un financement à un projet en vérifiant que le total ne dépasse pas 100%"""
|
||||
|
||||
if request.method == 'POST':
|
||||
pourcentage_recuperer = request.POST.get('pourcentage')
|
||||
bailleur_id = request.POST.get('bailleur')
|
||||
projet_id = request.POST.get('projet')
|
||||
try:
|
||||
projet = Projet.objects.get(id_projet=projet_id)
|
||||
except Projet.DoesNotExist:
|
||||
return JsonResponse({'success': False, 'message': "Le projet spécifié n’existe pas."})
|
||||
|
||||
try:
|
||||
pourcentage_nouveau = Decimal(pourcentage_recuperer) if pourcentage_recuperer else Decimal(0)
|
||||
except (InvalidOperation, TypeError):
|
||||
return JsonResponse({'success': False, 'message': "Le pourcentage saisi n’est pas valide."})
|
||||
|
||||
financement_total_actuel = sum(financement.pourcentage for financement in FinancementProjet.objects.filter(projet=projet))
|
||||
if financement_total_actuel + pourcentage_nouveau > 100:
|
||||
return JsonResponse({'success': False, 'message': "Le total des financements dépasse 100%."})
|
||||
|
||||
if bailleur_id:
|
||||
FinancementProjet.objects.create(
|
||||
projet=projet,
|
||||
bailleur_id=bailleur_id,
|
||||
pourcentage=pourcentage_nouveau
|
||||
)
|
||||
return JsonResponse({'success': True, 'message': "Financement ajouté avec succès."})
|
||||
else:
|
||||
return JsonResponse({'success': False, 'message': "Aucun bailleur sélectionné."})
|
||||
return JsonResponse({'success': False, 'message': "Requête invalide."})
|
||||
|
||||
@login_required
|
||||
def modification_projet(request, projet_id):
|
||||
"""Vue pour éditer un projet existant via un formulaire pré-rempli"""
|
||||
try:
|
||||
projet = Projet.objects.get(id=projet_id)
|
||||
except Projet.DoesNotExist:
|
||||
messages.error(request, "Le projet spécifié n’existe pas.")
|
||||
return redirect('projet-index')
|
||||
|
||||
if request.method == "POST":
|
||||
form = ProjetForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, "Le projet a été modifié avec succès.")
|
||||
return redirect('projet-index')
|
||||
messages.error(request, "Erreur lors de la modification du projet.")
|
||||
form = ProjetForm(instance=projet)
|
||||
return render(request, 'gestion_projet/projet-edit.html', {'form': form, 'projets': projet})
|
||||
|
||||
@login_required
|
||||
def suppression_projet(request, id):
|
||||
"""Vue pour supprimer un projet spécifique après confirmation de l'utilisateur"""
|
||||
try:
|
||||
projet = Projet.objects.get(id=id)
|
||||
except Projet.DoesNotExist:
|
||||
messages.error(request, "Le projet spécifié n’existe pas.")
|
||||
return redirect('projet-index')
|
||||
|
||||
if request.method == "POST":
|
||||
projet.delete()
|
||||
messages.success(request, "Le projet a été supprimé avec succès.")
|
||||
return redirect('projet-index')
|
||||
|
||||
@login_required
|
||||
def affecter_employe_projet(request, projet_id):
|
||||
"""Vue pour affecter un employé à un projet avec vérification des contraintes d'affectation"""
|
||||
try:
|
||||
projet = Projet.objects.get(id=projet_id)
|
||||
except Projet.DoesNotExist:
|
||||
messages.error(request, "Le projet spécifié n’existe pas.")
|
||||
return redirect('projet-index')
|
||||
|
||||
if request.method == 'POST':
|
||||
form = AffectationForm(request.POST)
|
||||
if form.is_valid():
|
||||
employe = Employe.objects.get(id=form.cleaned_data['employe'].id)
|
||||
date_fin_affectation = form.cleaned_data['date_fin_daffectation']
|
||||
temps_nouveau = form.cleaned_data['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('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('projet-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('projet-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('projet-index')
|
||||
|
||||
Affectation.objects.update_or_create(
|
||||
projet=projet,
|
||||
employe=employe,
|
||||
defaults={
|
||||
'date_affectation': form.cleaned_data['date_affectation'],
|
||||
'date_fin_daffectation': date_fin_affectation,
|
||||
'role': form.cleaned_data['role'],
|
||||
'temps_affectation': temps_nouveau
|
||||
}
|
||||
)
|
||||
form = AffectationForm(initial={'projet': projet})
|
||||
messages.error(request, "Erreur : Formulaire non valide.")
|
||||
return redirect('projet-index')
|
||||
|
||||
def modifier_financement_projet(request, financement_id):
|
||||
try:
|
||||
financement = FinancementProjet.objects.get(id=financement_id)
|
||||
except FinancementProjet.DoesNotExist:
|
||||
messages.error(request, "Le financement spécifié n’existe pas.")
|
||||
return redirect('projet-index')
|
||||
projet = financement.projet
|
||||
if request.method == 'POST':
|
||||
try:
|
||||
nouveau_pourcentage = Decimal(request.POST.get('pourcentage', '0'))
|
||||
except InvalidOperation:
|
||||
messages.error(request, "Le pourcentage saisi est invalide.")
|
||||
return redirect('projet-index')
|
||||
pourcentage_total_financement = (
|
||||
FinancementProjet.objects.filter(projet=projet)
|
||||
.exclude(id=financement.id)
|
||||
.aggregate(total_financement=Sum('pourcentage'))['pourcentage_total_financement'] or 0
|
||||
)
|
||||
if pourcentage_total_financement + nouveau_pourcentage > 100:
|
||||
messages.error(request, f"Le total des financements dépasse 100% ({pourcentage_total_financement + nouveau_pourcentage}%).")
|
||||
return redirect('projet-index')
|
||||
financement.pourcentage = nouveau_pourcentage
|
||||
financement.save()
|
||||
messages.success(request, "Financement modifié avec succès.")
|
||||
return redirect('projet-index')
|
||||
|
||||
@login_required
|
||||
def activites_projet(request):
|
||||
try:
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
except Employe.DoesNotExist:
|
||||
messages.error(request, "Impossible d'accéder au menu 'Suivi des activités' car votre profil Utilisateur n'est lié à aucun profil Employe. Veuillez contacter l'administrateur.")
|
||||
return redirect("gestion_conges:conge")
|
||||
|
||||
try:
|
||||
Affectation.objects.get(employe=employe, date_fin_daffectation__gte = timezone.now().date(), role='chef_projet')
|
||||
except Affectation.DoesNotExist :
|
||||
messages.error(request, "Seuls les chefs de projet ont accès à l'onglet 'Suivi des Activités'")
|
||||
return redirect("gestion_conges:conge")
|
||||
|
||||
projet = Affectation.objects.filter(employe=employe, role='chef_projet', date_fin_daffectation__gte=timezone.now().date()).select_related('projet').first()
|
||||
if projet :
|
||||
context = {
|
||||
**model_to_dict(projet),
|
||||
"nom_projet": projet.projet.nom_projet,
|
||||
"budget_total": projet.projet.budget,
|
||||
"budget_RH": projet.projet.budget_RH,
|
||||
"form_ajout_activite": ActiviteProjetForm(),
|
||||
"form_ajout_document": DocumentProjetForm(),
|
||||
"form_ajout_livrable": LivrablesLivresForm(),
|
||||
}
|
||||
else :
|
||||
context = {
|
||||
"form_ajout_activite": ActiviteProjetForm(),
|
||||
"form_ajout_document": DocumentProjetForm(),
|
||||
"form_ajout_livrable": LivrablesLivresForm(),
|
||||
}
|
||||
return render(request, 'gestion_projet/suivi_activite.html', context)
|
||||
|
||||
@login_required
|
||||
def ajouter_activite_projet(request):
|
||||
"""Vue pour ajouter une activité à un projet spécifique via un formulaire"""
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
projet = Affectation.objects.filter(employe=employe, role='chef_projet', date_fin_daffectation__gte=timezone.now().date()).select_related('projet').first()
|
||||
|
||||
if request.method == "POST":
|
||||
form = ActiviteProjetForm(request.POST)
|
||||
if form.is_valid():
|
||||
activite = form.save(commit=False)
|
||||
activite.projet = projet.projet
|
||||
activite.budget_depense = request.POST["budget_prevu"]
|
||||
activite.save()
|
||||
messages.success(request, "Activité ajoutée avec succès !")
|
||||
else:
|
||||
messages.error(request, "Erreur : vérifiez les informations saisies.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
|
||||
@login_required
|
||||
def liste_activites_projet(request):
|
||||
"""Vue pour retourner la liste des activités d'un projet spécifique"""
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
projet = Affectation.objects.filter(employe=employe, role='chef_projet', date_fin_daffectation__gte=timezone.now().date()).select_related('projet').first()
|
||||
if projet:
|
||||
activites = ActiviteProjet.objects.filter(projet_id=projet.projet.id_projet).order_by('-date_debut')
|
||||
else:
|
||||
activites = []
|
||||
data = []
|
||||
for a in activites:
|
||||
data.append({
|
||||
"id": a.id,
|
||||
"titre": a.titre,
|
||||
"date_debut": a.date_debut,
|
||||
"date_fin": a.date_fin,
|
||||
"statut": a.statut,
|
||||
"budget_prevu": a.budget_prevu,
|
||||
"budget_depense": a.budget_depense,
|
||||
"motif_changement_budget": a.motif_changement_budget,
|
||||
"besoin_ressource_materielle": a.besoin_ressource_materielle,
|
||||
"description": a.description,
|
||||
})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
@login_required
|
||||
def liste_livrables_activite(request, activite_id):
|
||||
"""Vue pour retourner la liste des livrables attendus d'une activité spécifique"""
|
||||
livrables = LivrablesLivres.objects.filter(activite__id=activite_id)
|
||||
data = []
|
||||
for livrable in livrables:
|
||||
print(livrable.fichier.url)
|
||||
data.append({
|
||||
"titre": livrable.nom,
|
||||
"lien": livrable.fichier.url if livrable.fichier else "",
|
||||
})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
@login_required
|
||||
def mises_a_jour_depense_activite(request):
|
||||
"""Vue pour retourner la liste des activités d'un projet spécifique avec leurs dépenses mises à jour"""
|
||||
if request.method == "POST":
|
||||
activite_id = request.POST.get("id_activite")
|
||||
budget_depense = request.POST.get("budget_depense")
|
||||
motif = request.POST.get("motif", "").strip()
|
||||
try:
|
||||
activite = ActiviteProjet.objects.get(id=activite_id)
|
||||
activite.budget_depense = Decimal(budget_depense)
|
||||
if Decimal(budget_depense) != activite.budget_prevu:
|
||||
activite.motif_changement_budget = motif
|
||||
else:
|
||||
activite.motif_changement_budget = ""
|
||||
activite.save()
|
||||
messages.success(request, f"Dépenses mises à jour pour l’activité '{activite.titre}'.")
|
||||
except (ActiviteProjet.DoesNotExist, InvalidOperation):
|
||||
messages.error(request, "Erreur lors de la mise à jour des dépenses.")
|
||||
return redirect("gestion_projet:activites-projet")
|
||||
|
||||
@login_required
|
||||
def ajouter_livrables_projet(request):
|
||||
"""Vue pour ajouter un livrable à une activité de projet spécifique via un formulaire"""
|
||||
|
||||
if request.method == "POST":
|
||||
form = LivrablesLivresForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, "Livrable ajouté avec succès !")
|
||||
else:
|
||||
messages.error(request, "Erreur : vérifiez les informations saisies.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
|
||||
@login_required
|
||||
def ajouter_document_projet(request):
|
||||
"""Ajoute un document à un projet"""
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
projet = Affectation.objects.filter(employe=employe, role='chef_projet', date_fin_daffectation__gte=timezone.now().date()).select_related('projet').first()
|
||||
if request.method == "POST":
|
||||
form = DocumentProjetForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
document = form.save(commit=False)
|
||||
document.projet = projet.projet
|
||||
document.save()
|
||||
messages.success(request, "Document ajouté avec succès !")
|
||||
else:
|
||||
messages.error(request, "Erreur : le document n’a pas pu être enregistré.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
|
||||
def liste_documents_projet(request):
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
projet = Affectation.objects.filter(employe=employe, role='chef_projet', date_fin_daffectation__gte=timezone.now().date()).select_related('projet').first()
|
||||
if projet:
|
||||
documents = DocumentProjet.objects.filter(projet__id_projet=projet.projet.id_projet)
|
||||
else:
|
||||
documents = []
|
||||
data = []
|
||||
for d in documents:
|
||||
data.append({
|
||||
"nom_document": d.nom_document,
|
||||
"numero": d.numero,
|
||||
"date_validite": d.date_validite,
|
||||
"lien_document": d.fichier.url if d.fichier else "",
|
||||
})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
def modifier_activite_projet(request, id):
|
||||
"""Vue pour modifier une activité de projet spécifique via un formulaire pré-rempli"""
|
||||
try:
|
||||
activite = ActiviteProjet.objects.get(id=id)
|
||||
except ActiviteProjet.DoesNotExist:
|
||||
messages.error(request, "L'activité spécifiée n’existe pas.")
|
||||
return redirect('activites-projet')
|
||||
if request.method == 'POST':
|
||||
form = ActiviteProjetForm(request.POST, instance=activite)
|
||||
if form.is_valid():
|
||||
activite.besoin_ressource_materielle = bool(request.POST.get("besoin_ressource_materielle"))
|
||||
form.save()
|
||||
messages.success(request, f"Activité « {activite.titre} » modifiée avec succès.")
|
||||
else:
|
||||
messages.error(request, "Erreur lors de la modification de l'activité.")
|
||||
return redirect('activites-projet')
|
||||
|
||||
form = ActiviteProjetForm(instance=activite)
|
||||
return render(
|
||||
request,
|
||||
'gestion_projet/activite.html', {
|
||||
'form': form,
|
||||
'activite': activite,
|
||||
}
|
||||
)
|
||||
|
||||
def annuler_activite_projet(request):
|
||||
"""Vue pour annuler une activité de projet spécifique après confirmation de l'utilisateur"""
|
||||
print(request.POST)
|
||||
if request.method != "POST":
|
||||
messages.error(request, "Requête invalide.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
try:
|
||||
activite = ActiviteProjet.objects.get(id=request.POST.get('id_activite'))
|
||||
except ActiviteProjet.DoesNotExist:
|
||||
messages.error(request, "L'activité spécifiée n’existe pas.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
if request.method == "POST":
|
||||
activite.annuler = True
|
||||
activite.motif_annulation = request.POST.get("motif_annulation", "").strip()
|
||||
activite.save()
|
||||
messages.success(request, f"L'activité '{activite.titre}' a été annulée avec succès.")
|
||||
return redirect('gestion_projet:activites-projet')
|
||||
Reference in New Issue
Block a user