Bug : Affichages des conges

This commit is contained in:
2026-04-30 13:28:57 +02:00
committed by Soriba SYLLA
parent 0936d6ad02
commit 7826f517f5
251 changed files with 41879 additions and 2 deletions

View File

16
gestion_employe/admin.py Normal file
View File

@@ -0,0 +1,16 @@
from django.contrib import admin
from .models import Departement, Employe
@admin.register(Departement)
class DepartementAdmin(admin.ModelAdmin):
list_display = ("nom", )
@admin.register(Employe)
class EmployeAdmin(admin.ModelAdmin):
list_display = (
"user",
"matricule",
"fonction",
)

86
gestion_employe/forms.py Normal file
View File

@@ -0,0 +1,86 @@
from django import forms
from .models import Affectation, Contrat, Departement, Employe, Formation
class EmployeForm(forms.ModelForm):
"""Formulaire pour modifier les informations de profil d'un employé"""
class Meta:
model = Employe
fields = (
'adresse',
'telephone',
'CV',
'diplome',
'rib',
'photo',
'casier_judiciaire'
)
class AffectationForm(forms.ModelForm):
class Meta:
model = Affectation
fields = (
'projet',
'date_affectation',
'date_fin_daffectation',
'role',
'pourcentage_temps_affectation'
)
widgets = {
'projet': forms.Select(attrs={'class': 'form-select'}),
'date_affectation': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'date_fin_daffectation': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'role': forms.Select(attrs={'class': 'form-select'}),
'pourcentage_temps_affectation': forms.NumberInput(attrs={'class': 'form-control'}),
}
class ContratForm(forms.ModelForm):
class Meta:
model = Contrat
fields = [
"numero_contrat",
"type_contrat",
"date_debut",
"date_fin",
"salaire_mensuel",
"statut",
"fichier_contrat"
]
widgets = {
'numero_contrat': forms.TextInput(attrs={'class': 'form-control'}),
'type_contrat': forms.Select(attrs={'class': 'form-select'}),
'date_debut': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'date_fin': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'salaire_mensuel': forms.TextInput(attrs={'class': 'form-control'}),
'statut': forms.Select(attrs={'class': 'form-select'}),
'fichier_contrat': forms.FileInput(attrs={'class': 'form-control'}),
}
class DepartementForm(forms.ModelForm):
class Meta:
model = Departement
fields = ['nom']
class FormationForm(forms.ModelForm):
class Meta:
model = Formation
fields = [
'titre',
'organisme',
'date_obtention',
'date_fin',
'description',
'certificat'
]
widgets = {
'titre': forms.TextInput(attrs={"class": "form-control"}),
'organisme': forms.TextInput(attrs={"class": "form-control"}),
'date_obtention': forms.DateInput(attrs={"class": "form-control", "type": "date"}),
'date_fin': forms.DateInput(attrs={"class": "form-control", "type": "date"}),
'description': forms.Textarea(attrs={"class": "form-control"}),
'certificat': forms.FileInput(attrs={"class": "form-control"}),
}

View File

@@ -1,5 +1,6 @@
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
# Generated by Django 5.2.13 on 2026-06-16 11:06
=======
# Generated by Django 5.2.13 on 2026-04-17 12:03
@@ -7,6 +8,9 @@
=======
# Generated by Django 5.2.13 on 2026-04-17 12:03
>>>>>>> f6b90e7 (Verification du statut avant la creation d'un contrat)
=======
# Generated by Django 5.2.13 on 2026-04-17 12:03
>>>>>>> 6026af5 (Bug : Affichages des conges)
import django.db.models.deletion
from django.conf import settings
@@ -36,6 +40,7 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('matricule', models.CharField(blank=True, max_length=10, null=True, unique=True)),
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
('fonction', models.CharField(blank=True, choices=[('directeur', 'Directeur'), ('assistant_direction', 'Assistante de direction'), ('assistant_technique_recherche', 'Assistant technique de recherche'), ('comptable', 'Comptable'), ('raf', 'RAF'), ('data_manager', 'Data Manager'), ('logisticien', 'Logisticien'), ('post_doctorant', 'Post-Doctorant'), ('qualiticien', 'Qualiticien'), ('technicien_surface', 'Technicien de surface'), ('chauffeur', 'Chauffeur')], max_length=50, null=True)),
=======
@@ -44,6 +49,9 @@ class Migration(migrations.Migration):
=======
('fonction', models.CharField(blank=True, choices=[('directeur', 'Directeur'), ('assistant_direction', 'Assistante de direction'), ('comptable', 'Comptable'), ('raf', 'RAF'), ('data_manager', 'Data Manager'), ('logisticien', 'Logisticien'), ('post_doctorant', 'Post-Doctorant'), ('qualiticien', 'Qualiticien'), ('technicien_surface', 'Technicien de surface'), ('chauffeur', 'Chauffeur')], max_length=50, null=True)),
>>>>>>> f6b90e7 (Verification du statut avant la creation d'un contrat)
=======
('fonction', models.CharField(blank=True, choices=[('directeur', 'Directeur'), ('assistant_direction', 'Assistante de direction'), ('comptable', 'Comptable'), ('raf', 'RAF'), ('data_manager', 'Data Manager'), ('logisticien', 'Logisticien'), ('post_doctorant', 'Post-Doctorant'), ('qualiticien', 'Qualiticien'), ('technicien_surface', 'Technicien de surface'), ('chauffeur', 'Chauffeur')], max_length=50, null=True)),
>>>>>>> 6026af5 (Bug : Affichages des conges)
('date_embauche', models.DateField(blank=True, null=True)),
('adresse', models.CharField(blank=True, max_length=100, null=True)),
('telephone', models.CharField(blank=True, max_length=15, null=True)),
@@ -65,6 +73,7 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('numero_contrat', models.CharField(max_length=100, unique=True)),
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
('type_contrat', models.CharField(choices=[('contrat_duree_determinee', 'Contrat à Durée Déterminée'), ('contrat_duree_indeterminee', 'Contrat à Durée Indéterminée'), ('contrat_prestation', 'Contrat de Prestation de Service'), ('contrat_stage', 'Contrat de Stage'), ('convention_bourse_entretien', "Convention de bourse d'entretien")], max_length=50)),
=======
@@ -73,6 +82,9 @@ class Migration(migrations.Migration):
=======
('type_contrat', models.CharField(choices=[('contrat_duree_determinee', 'Contrat à Durée Déterminée'), ('contrat_duree_indeterminee', 'Contrat à Durée Indéterminée'), ('contrat_prestation', 'Contrat de Prestation de Service'), ('contrat_stage', 'Contrat de Stage')], max_length=50)),
>>>>>>> f6b90e7 (Verification du statut avant la creation d'un contrat)
=======
('type_contrat', models.CharField(choices=[('contrat_duree_determinee', 'Contrat à Durée Déterminée'), ('contrat_duree_indeterminee', 'Contrat à Durée Indéterminée'), ('contrat_prestation', 'Contrat de Prestation de Service'), ('contrat_stage', 'Contrat de Stage')], max_length=50)),
>>>>>>> 6026af5 (Bug : Affichages des conges)
('date_debut', models.DateField()),
('date_fin', models.DateField(blank=True, null=True)),
('salaire_mensuel', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),

View File

@@ -0,0 +1,18 @@
# Generated by Django 6.0.4 on 2026-04-29 10:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gestion_employe', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='contrat',
name='type_contrat',
field=models.CharField(choices=[('contrat_duree_determinee', 'Contrat à Durée Déterminée'), ('contrat_duree_indeterminee', 'Contrat à Durée Indéterminée'), ('contrat_prestation', 'Contrat de Prestation de Service'), ('contrat_stage', 'Contrat de Stage'), ('convention_bourse_entretien', "Convention de bourse d'entretien")], max_length=50),
),
]

View File

View File

@@ -1,6 +1,7 @@
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone
from gestion_projet.models import Projet

View File

@@ -330,4 +330,4 @@ document.getElementById("modalContratsEmploye")
.catch(error => {
console.error("Erreur :", error);
});
});
});

View File

@@ -0,0 +1,67 @@
{% extends "BASE.html" %}
{% load static %}
{% block 'titre_page' %} Gestion des projets {% endblock %}
{% block 'css' %}
{% endblock %}
{% block 'contenu' %}
<div class="col px-2">
<h3>Gestion des employés</h3>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{% if message.tags == 'error' %}danger{% else %}success{% endif %} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
<div class="row">
<div class="col text-white bg-success d-flex flex-column justify-content-center align-items-center border rounded p-4">
<span class="fs-5">Nombre d'employés</span>
<h3>{{ nombre_employes }}</h3>
</div>
<div class="col text-white bg-info d-flex flex-column justify-content-center align-items-center border rounded p-4 mx-3">
<span class="fs-5">Nombre de prestataires</span>
<h3>{{ nombre_cps }}</h3>
</div>
<div class="col text-white bg-warning d-flex flex-column justify-content-center align-items-center border rounded p-4">
<span class="fs-5">Nombre de stagiaires</span>
<h3>{{ nombre_stage }}</h3>
</div>
</div>
<div class="row mt-4">
<div class="col d-flex justify-content-between mb-3">
<h3>
<i class="bi bi-people"></i>
La liste des employés
</h3>
<button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#modalListeDesContratExpirants" id="boutonContratExpirants" data-urlexpirants="{% url 'gestion_employe:liste-contrat-expirants' %}">
Contrats proches de la fin <span class="badge badge-light">{{ nombre_expirants }}</span>
</button>
</div>
<div class="row mb-2 d-flex justify-content-end">
<div class="col">
<div class="row">
<div class="col d-flex justify-content-center">
<input class="form-control d-block" type="search" placeholder="Recherche par nom et prénom..." id="input-recherche">
</div>
</div>
</div>
</div>
<div class="table-responsive">
<div id="tableau_liste_employe" data-url={% url 'gestion_employe:liste-employes' %}></div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block 'modal' %}
{% include "gestion_employe/parts/modalDetailEmploye.html" %}
{% include "gestion_employe/parts/modalCreationContrat.html" %}
{% include "gestion_employe/parts/modalAffectationProjet.html" %}
{% include "gestion_employe/parts/modalDocument.html" %}
{% include "gestion_employe/parts/modalListeContratExpirants.html" %}
{% endblock %}
{% block 'js' %}
<script type="text/javascript" src="{% static 'gestion_employe/js/index.js' %}"></script>
{% endblock %}

View File

@@ -0,0 +1,105 @@
{% extends "BASE.html" %}
{% load static %}
{% block 'titre_page' %} Gestion des employés - Mon profil {% endblock %}
{% block 'contenu' %}
<div class="card shadow-sm border-0 w-100" style="max-width: 850px;">
<div class="card-header bg-orange-dark">
<h5 class="mb-0 fw-bold">
<i class="bi bi-pencil-square me-2"></i> Modifier mon profil
</h5>
</div>
<div class="card-body">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="accordion" id="accordionProfil">
<div class="accordion-item">
<h2 class="accordion-header" id="headingInfo">
<button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#collapseInfo" aria-expanded="false" aria-controls="collapseInfo">
<i class="bi bi-person-lines-fill me-2"></i> Informations personnelles
</button>
</h2>
<div id="collapseInfo" class="accordion-collapse collapse" aria-labelledby="headingInfo" data-bs-parent="#accordionProfil">
<div class="accordion-body">
<div class="row">
<div class="col">
<div class="form-group mb-2">
<label>Photo de profil :</label>
<input type="file" class="form-control">
</div>
<div class="form-group mb-2">
<label>Prénom :</label>
<input type="text" class="form-control">
</div>
<div class="form-group mb-2">
<label>Nom :</label>
<input type="text" class="form-control">
</div>
</div>
<div class="col">
<div class="form-group mb-2">
<label>Email :</label>
<input type="email" class="form-control">
</div>
<div class="form-group mb-2">
<label>Téléphone :</label>
<input type="text" class="form-control">
</div>
<div class="form-group mb-2">
<label>Adresse :</label>
<input type="text" class="form-control">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingDocs">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseDocs" aria-expanded="false" aria-controls="collapseDocs">
<i class="bi bi-file-earmark-text me-2"></i> Documents
</button>
</h2>
<div id="collapseDocs" class="accordion-collapse collapse" aria-labelledby="headingDocs" data-bs-parent="#accordionProfil">
<div class="accordion-body">
<div class="row">
<div class="col">
<div class="form-group mb-2">
<label>CV :</label>
<input type="file" class="form-control">
</div>
<div class="form-group mb-2">
<label>Diplome :</label>
<input type="file" class="form-control">
</div>
</div>
<div class="col">
<div class="form-group mb-2">
<label>RIB :</label>
<input type="file" class="form-control">
</div>
<div class="form-group mb-2">
<label>Casier judiciaire :</label>
<input type="file" class="form-control">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="d-flex justify-content-end mt-4 gap-2 flex-wrap">
<a href="{% url 'gestion_employe:mon-profil' %}" class="btn btn-outline-secondary">
<i class="bi bi-x-circle me-1"></i> Annuler
</a>
<button type="submit" class="btn btn-primary">
<i class="bi bi-check-circle me-1"></i> Enregistrer
</button>
</div>
</form>
</div>
</div>
{% endblock %}
{% block 'modal' %}
{% endblock %}
{% block 'js' %}
{% endblock %}

View File

@@ -0,0 +1,28 @@
<div class="modal fade" id="modalAffectation" tabindex="-1" aria-labelledby="modalAffectationLabel" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content">
<div class="modal-header bg-orange-dark">
<h5 class="modal-title" id="modalAffectationLabel" >
Affectation de projet (<span id="affectation-nom-employe"></span>)
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal">
</button>
</div>
<div class="modal-body">
<form action="{% url 'gestion_employe:affecter_employe_projet' %}" method="POST">
{% csrf_token %}
<input type="hidden" name="affecter_employe_id" id="affecter_employe_id">
{{ affectation_form.as_p }}
<div class="modal-footer bg-light">
<button type="submit" class="btn btn-success">
<i class="bi bi-check-circle"></i> affecter
</button>
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
<i class="bi bi-x-circle me-1"></i> Annuler
</button>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,21 @@
<div class="modal fade" id="modalAjouterFormation" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-orange-dark">
<h5 class="modal-title">Ajouter un certificat</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form method="post" action="{% url 'gestion_employe:ajouter_formation' %}" enctype="multipart/form-data">
{% csrf_token %}
{{ formation_form.as_p }}
<div class="modal-footer">
<button type="submit" class="btn btn-success">Enregistrer</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,57 @@
<div class="modal fade" id="modalContrat" tabindex="-1" aria-labelledby="modalContratLabel" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content bg-white">
<div class="modal-header ">
<h5 class="modal-title" id="modalContratLabel">
<i class="bi bi-file-earmark-text me-2"></i>
Contrat de <span id="contrat-employe"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form action="{% url 'gestion_employe:creation-contrat' %}" method="POST" id="contrat_form" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="employe_id" value="" id="employeIdInput">
{{ contrat_form.as_p }}
<div class="modal-footer bg-light">
<button type="submit" class="btn btn-success">
<i class="bi bi-check-circle me-1"></i> Enregistrer
</button>
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
<i class="bi bi-x-circle me-1"></i> Annuler
</button>
</div>
</form>
{% comment %} <fieldset class="border p-3 mb-4">
<legend class="fw-bold mb-3 text-muted">Informations du contrat</legend>
<div class="form-group mb-2">
<label>Numero de contrat :</label>
<input type="text" class="form-control">
</div>
<div class="form-group mb-2">
<label>Type contrat :</label>
<input type="text" class="form-control">
</div>
<div class="form-group mb-2">
<label>date de début :</label>
<input type="date" class="form-control">
</div>
<div class="form-group mb-2">
<label>date de fin :</label>
<input type="date" class="form-control">
</div>
<div class="form-group mb-2">
<label>Salaire mensuel :</label>
<input type="text" class="form-control">
</div>
<div class="form-group mb-2">
<label>Fichier du contrat :</label>
<input type="file" class="form-control">
</div>
</div>
</fieldset> {% endcomment %}
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,41 @@
<div class="modal fade" id="modalDocuments" tabindex="-1" aria-labelledby="modalDocumentsLabel" aria-hidden="true">
<div class="modal-dialog ">
<div class="modal-content border-0 shadow-lg">
<div class="modal-header ">
<h5 class="modal-title" id="modalDocumentsLabel">
<i class="bi bi-folder2-open me-2"></i> Documents RH de <span id="document-employe"></span>
</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="row g-3">
<div class="col">
<ul class="list-group">
<li class="list-group-item">
<strong>Diplôme :</strong>
<a id="document-diplome" target="_blank"></a>
</li>
<li class="list-group-item">
<strong>CV :</strong>
<a id="document-cv" target="_blank"></a>
</li>
<li class="list-group-item">
<strong>RIB :</strong>
<a id="document-rib" target="_blank"></a>
</li>
<li class="list-group-item">
<strong>Casier judiciaire :</strong>
<a id="document-casier-judiciaire" target="_blank"></a>
</li>
</ul>
</div>
</div>
<div class="modal-footer bg-light">
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
<i class="bi bi-x-circle"></i> Fermer
</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,17 @@
<div class="modal fade" id="modalListeDesContratExpirants" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Contrats expirants dans un maximum de 60 jours</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div id='listeContratExpirant'></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
</div>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,36 @@
<div class="modal fade" id="modalModifierProfil" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"><i class="bi bi-person-lines-fill me-2"></i> Modifier le mot de passe</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form method="POST" action="{% url 'gestion_employe:modifier-mot-passe' %}">
{% csrf_token %}
<div class="form-group mb-2">
<label>Votre mot de passe actuel :</label>
<input class="form-control" type="password" name="ancien-mdp">
</div>
<div class="form-group mb-2">
<label>Votre nouveau mot de passe :</label>
<input class="form-control" type="password" name="nouveau-mdp">
</div>
<div class="form-group mb-2">
<label>Confirmez votre nouveau mot de passe :</label>
<input class="form-control" type="password" name="confirmation-mdp">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Fermer
</button>
<button type="submit" class="btn btn-success">
<i class="bi bi-check-circle me-1"></i> Enregistrer
</button>
</div>
</form>
</div>
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
"""Tags personnalisés pour les templates d'authentification.
Ce fichier contient des tags personnalisés pour les templates du projet lié à
la gestion de l'accès des utilisateurs aux différentes pages.
"""
from django import template
from django.utils import timezone
from gestion_employe.models import Affectation
register = template.Library()
@register.filter
def has_group(user, group_name):
"""Vérifiez si un utilisateur appartient à un groupe spécifique."""
return user.groups.filter(name=group_name).exists()
@register.filter
def is_chef_projet(user):
try:
affectation = Affectation.objects.get(employe__user__username = user, date_fin_daffectation__gte = timezone.now().date())
except Affectation.DoesNotExist:
return False
return affectation.role == "chef_projet"

3
gestion_employe/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.