clean: remove pycache from tracking

This commit is contained in:
2026-04-30 13:28:53 +02:00
committed by Soriba SYLLA
parent d12b014b20
commit 7ee14e7b3f
525 changed files with 0 additions and 45689 deletions

View File

@@ -1,14 +0,0 @@
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",
)

View File

@@ -1,84 +0,0 @@
from django import forms
from .models import Contrat, Departement, Employe,Affectation,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,88 +0,0 @@
# Generated by Django 5.2.13 on 2026-04-17 12:03
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('gestion_projet', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Departement',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nom', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Employe',
fields=[
('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)),
('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)),
('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)),
('sexe', models.CharField(blank=True, choices=[('m', 'Masculin'), ('f', 'Féminin')], max_length=1, null=True)),
('date_naissance', models.DateField(blank=True, null=True)),
('CV', models.FileField(blank=True, null=True, upload_to='cv/')),
('diplome', models.FileField(blank=True, null=True, upload_to='diplomes/')),
('rib', models.FileField(blank=True, null=True, upload_to='rib/')),
('photo', models.ImageField(blank=True, null=True, upload_to='photos/')),
('casier_judiciaire', models.FileField(blank=True, null=True, upload_to='casier/')),
('chef', models.BooleanField(default=False, verbose_name='Cet utilisateur est-il chef de ce département ?')),
('departement', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='gestion_employe.departement')),
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Contrat',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('numero_contrat', models.CharField(max_length=100, unique=True)),
('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)),
('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)),
('statut', models.CharField(choices=[('actif', 'Actif'), ('termine', 'Terminé'), ('suspendu', 'Suspendu'), ('rupture_contrat', 'Rupture de Contrat')], max_length=50)),
('fichier_contrat', models.FileField(blank=True, null=True, upload_to='contrats/')),
('employe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_employe.employe')),
],
),
migrations.CreateModel(
name='Formation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('titre', models.CharField(max_length=255, verbose_name='Nom du certificat')),
('organisme', models.CharField(max_length=255, verbose_name="Nom de l'organisme")),
('description', models.TextField(blank=True, null=True, verbose_name='Description de la formation')),
('date_obtention', models.DateField(blank=True, null=True, verbose_name="Date d'obtention")),
('date_fin', models.DateField(blank=True, null=True, verbose_name='Date de fin de validité')),
('certificat', models.FileField(blank=True, null=True, upload_to='documents/formations/', verbose_name='Certificat (PDF/Image)')),
('employe', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='employe_formation', to='gestion_employe.employe')),
],
),
migrations.CreateModel(
name='Affectation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_affectation', models.DateField()),
('date_fin_daffectation', models.DateField(blank=True, null=True)),
('role', models.CharField(choices=[('chef_projet', 'Chef de projet'), ('doctorant', 'Doctorant'), ('mastorant', 'Mastorant'), ('consultant', 'Consultant'), ('stagiaire', 'Stagiaire'), ('laborantin', 'Laborantin'), ('medecin', 'Médecin'), ('autre', 'Autre')], default='Membre', max_length=20)),
('pourcentage_temps_affectation', models.DecimalField(decimal_places=2, max_digits=5)),
('projet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_projet.projet')),
('employe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_employe.employe')),
],
options={
'unique_together': {('projet', 'employe')},
},
),
]

View File

@@ -1,18 +0,0 @@
# 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

@@ -1,263 +0,0 @@
const $ = (element) => document.getElementById(element);
const url_liste_employe = $("tableau_liste_employe").dataset.url;
const tableau_liste_employe = new Tabulator("#tableau_liste_employe", {
columns: [
{"title": "Matricule", "field": "matricule"},
{"title": "Nom & Prénom", "field": "employe"},
{"title": "Fonction", "field": "fonction"},
{"title": "Projet", "field": "projet"},
{"title": "Téléphone", "field": "telephone"},
],
// ajaxURL: url_liste_employe,
pagination: true,
paginationSize: 10,
})
fetch(url_liste_employe)
.then(response => response.json())
.then(data => {
if (data.success){
console.log(data.data)
tableau_liste_employe.setData(data.data);
}else{
alert(data.message);
}
}
)
tableau_liste_employe.on("rowClick", function (row, rowData) {
const data = rowData.getData();
document.getElementById('detail-id').value = data.id;
document.getElementById('detail-matricule').value = data.matricule;
document.getElementById('detail-employe').value = data.employe;
document.getElementById('detail-fonction').value = data.fonction;
document.getElementById('detail-departement').value = data.departement;
document.getElementById('detail-sexe').value = "";
document.getElementById('detail-dateNaissance').value = "";
document.getElementById('detail-email').value = data.email;
document.getElementById('detail-telephone').value = data.telephone;
document.getElementById('detail-adresse').value = data.adresse;
document.getElementById('detail-dateEmbauche').value = data.date_embauche;
document.getElementById('detail-dateNaissance').value = data.date_naissance;
document.getElementById('detail-sexe').value = data.sexe;
document.getElementById('document-diplome').href = data.diplome;
document.getElementById('document-diplome').textContent = data.diplome || "Aucun diplôme";
document.getElementById('document-cv').href = data.CV;
document.getElementById('document-cv').textContent = data.CV || "Aucun CV";
document.getElementById('document-rib').href = data.rib;
document.getElementById('document-rib').textContent = data.rib || "Aucun RIB";
document.getElementById('document-casier-judiciaire').href = data.casier_judiciaire;
document.getElementById('document-casier-judiciaire').textContent = data.casier_judiciaire || "Aucun casier judiciaire";
document.getElementById("document-employe").innerHTML = data.employe || "Employé inconnu";
document.getElementById("formations-list").innerHTML = "";
for (const formation of data.formations) {
document.getElementById("formations-list").innerHTML += `
<div class="col-6">
<div class="form-group mb-2">
<label>Titre :</label>
<input type="text" class="form-control" value="${formation.titre}">
</div>
<div class="form-group mb-2">
<label>Organisme :</label>
<input type="text" class="form-control" value="${formation.organisme}">
</div>
<div class="form-group mb-2">
<label>Date d'Optention :</label>
<input type="text" class="form-control" value="${formation.date_obtention}">
</div>
<div class="form-group mb-2">
<label>Date de validitée :</label>
<input type="text" class="form-control" value="${formation.date_fin}">
</div>
</div>
`
}
document.getElementById("contrat-employe").innerHTML = data.employe || "Employé inconnu";
document.getElementById("employeIdInput").value = data.id;
document.getElementById("contrats-list").innerHTML = "";
for (const contrat of data.contrats) {
document.getElementById("contrats-list").innerHTML += `
<div class="col-6">
<div class="form-group mb-2">
<label>Numéro de contrat :</label>
<input type="text" class="form-control" value="${contrat.numero_contrat}">
</div>
<div class="form-group mb-2">
<label>Type de contrat :</label>
<select class="form-select">
<option value="">Sélectionnez un projet</option>
<option value="contrat_duree_determinee" ${contrat.type_contrat == 'contrat_duree_determinee' ? 'selected' : ''}>Contrat à Durée Déterminée</option>
<option value="contrat_duree_indeterminee" ${contrat.type_contrat == 'contrat_duree_indeterminee' ? 'selected' : ''}>Contrat à Durée Indéterminée</option>
<option value="contrat_prestation" ${contrat.type_contrat == 'contrat_prestation' ? 'selected' : ''}>Contrat de Prestation de Service</option>
<option value="contrat_stage" ${contrat.type_contrat == 'contrat_stage' ? 'selected' : ''}>Contrat de Stage</option>
</select>
</div>
<div class="form-group mb-2">
<label>Date de début :</label>
<input type="text" class="form-control" value="${contrat.date_debut}">
</div>
<div class="form-group mb-2">
<label>Date de fin :</label>
<input type="text" class="form-control" value="${contrat.date_fin}">
</div>
<div class="form-group mb-2">
<label>Salaire mensuel :</label>
<input type="text" class="form-control" value="${contrat.salaire_mensuel}">
</div>
<div class="form-group mb-2">
<label>Statut :</label>
<input type="text" class="form-control" value="${contrat.statut}">
</div>
<div class="form-group mb-2">
<label>Fichier de contrat :</label>
<a href="${contrat.fichier_contrat}" target="_blank">Voir le document</a>
</div>
<button class='d-block m-auto btn btn-danger btn-supprimer-contrat' data-contratid="${contrat.numero_contrat}">
<i class='bi bi-trash'></i> Supprimer le contrat
</button>
</div>
`
};
const supprimerButtons = document.getElementsByClassName("btn-supprimer-contrat");
Array.from(supprimerButtons).forEach(button => {
button.addEventListener("click", function() {
const contratId = this.dataset.contratid;
fetch(`contrat/supprimer/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
"id": contratId
})
})
.then(response => response.json())
.then(data => {
alert(data.message);
location.reload();
})
});
})
document.getElementById("affectation-nom-employe").textContent = data.employe || "Employé inconnu";
document.getElementById("affecter_employe_id").value = data.id;
document.getElementById("affectations-list").innerHTML = "";
for (const affectation of data.affectations) {
document.getElementById("affectations-list").innerHTML += `
<div class="col-6">
<div class="form-group mb-2">
<label>Nom du projet :</label>
<input type="text" class="form-control" value="${affectation.projet}">
</div>
<div class="form-group mb-2">
<label>Rôle :</label>
<input type="text" class="form-control" value="${affectation.role}">
</div>
<div class="form-group mb-2">
<label>Pourcentation d'affectation :</label>
<input type="text" class="form-control" value="${affectation.pourcentage_temps_affectation}">
</div>
<div class="form-group mb-2">
<label>Date d'affectation :</label>
<input type="date" class="form-control" value="${affectation.date_affectation}">
</div>
<div class="form-group mb-2">
<label>Date de fin d'affectation :</label>
<input type="date" class="form-control" value="${affectation.date_fin_daffectation}">
</div>
<button class='d-block m-auto btn btn-danger btn-supprimer-affectation' data-contratid="${affectation.id}">
<i class='bi bi-trash'></i> Supprimer l'affectation
</button>
</div>
`
}
Array.from(document.getElementsByClassName("btn-supprimer-affectation")).forEach(button => {
button.addEventListener("click", function() {
const affectationId = this.dataset.contratid;
fetch(`affectation/supprimer/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
"id": affectationId
})
})
.then(response => response.json())
.then(data => {
alert(data.message);
location.reload();
})
});
})
const modal = new bootstrap.Modal($("modalDetailEmploye"));
modal.show();
})
$("enregistrerDetail").addEventListener("click", function() {
const id_ = document.getElementById('detail-id').value;
const fonction = document.getElementById('detail-fonction').value;
const dateEmbauche = document.getElementById('detail-dateEmbauche').value;
const matricule = document.getElementById('detail-matricule').value;
const url_enregistrer_detail = $("modalDetailEmployeBody").dataset.url;
fetch(url_enregistrer_detail, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRFToken": document.querySelector('[name=csrfmiddlewaretoken]').value
},
body: JSON.stringify({
"id": id_,
"fonction": fonction,
"date_embauche": dateEmbauche,
"matricule": matricule
})
})
.then(response => response.json())
.then(data => {
alert(data.message);
location.reload();
})
});
$("input-recherche").addEventListener("input", function() {
const recherche = this.value;
if (recherche){
tableau_liste_employe.setFilter("employe", "like", recherche);
}else{
tableau_liste_employe.clearFilter();
}
})
const listeContratExpirant = new Tabulator("#listeContratExpirant", {
columns: [
{"title": "Employé", "field": "employe"},
{"title": "Type de contrat", "field": "type_contrat"},
{"title": "Date de début", "field": "date_debut", formatter: 'datetime', formatterParams:{
inputFormat:"yyyy-MM-dd",
outputFormat:"dd/MM/yy",
}},
{"title": "Date de fin", "field": "date_fin", formatter: 'datetime', formatterParams:{
inputFormat:"yyyy-MM-dd",
outputFormat:"dd/MM/yy",
}},
{"title": "Statut", "field": "statut"},
{"title": "Lien du fichier", "field": "fichier_contrat", formatter:"link", formatterParams:{
target:"_blank",
}
},
],
ajaxURL: $("boutonContratExpirants").dataset.urlexpirants,
})

View File

@@ -1,46 +0,0 @@
const $ = (element) => document.getElementById(element);
url_certificat = $("tableau-certificat").dataset.url;
const tableau_certificat = new Tabulator("#tableau-certificat", {
columns: [
{"title": "Nom du certificat", "field": "titre"},
{"title": "Nom de l'organisme", "field": "organisme"},
{"title": "Date d'obtention", "field": "date_obtention", formatter:"datetime", formatterParams:{
inputFormat:"yyyy-MM-dd",
outputFormat:"dd/MM/yy",
}},
{"title": "Date de fin de validité", "field": "date_fin", formatter:"datetime", formatterParams:{
inputFormat:"yyyy-MM-dd",
outputFormat:"dd/MM/yy",
}},
],
ajaxURL: url_certificat,
})
const enregistrerProfil = $("enregistrerProfil");
enregistrerProfil.addEventListener("click", (e) => {
const url = $("information-personnelles").dataset.url;
const csrftoken = document.querySelector("[name='csrfmiddlewaretoken']").value;
const formData = new FormData();
formData.append("nom", $("nom").value);
formData.append("prenom", $("prenom").value);
formData.append("email", $("email").value);
formData.append("telephone", $("telephone").value);
formData.append("adresse", $("adresse").value);
formData.append("sexe", $("sexe").value);
formData.append("date_naissance", $("date_naissance").value);
fetch(url, {
method: "POST",
headers: {
"X-CSRFToken": csrftoken
},
body: formData
})
.then(response => response.json())
.then(data => alert(data.message))
.catch(error => console.error("Erreur:", error));
});

View File

@@ -1,67 +0,0 @@
{% 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

@@ -1,105 +0,0 @@
{% 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

@@ -1,241 +0,0 @@
{% extends "BASE.html" %}
{% load static %}
{% block 'titre_page' %} Gestion des employés - Mon profil {% endblock %}
{% block 'contenu' %}
<div class="d-flex justify-content-between">
<h5 class="fw-bold">
<i class="bi bi-pencil-square me-2"></i> Les informations de mon profil
</h5>
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#modalModifierProfil">
<i class="bi bi-pencil-square me-1"></i> Modifier le mot de passe
</button>
</div>
{% 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 %}
{% if not expiration_contrat %}
<div class="alert alert-danger fade show alert-dismissible mt-2">
<strong>Important :</strong> Les informations sur votre contrat n'ont pas été renseignées, veuillez contacter les ressources humaines.
</div>
{% elif contrat_nb_jours_restant %}
<div class="alert alert-danger fade show alert-dismissible mt-2">
<strong>Important :</strong> Votre contrat de travail expire dans {{ contrat_nb_jours_restant }} jours, veuillez contacter les ressources humaines.
</div>
{% endif %}
<div class="accordion mt-2" id="accordionInformationEmploye">
<div class="accordion-item">
<h2 class="accordion-header" id="headingContrats">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseProfil" aria-expanded="false" aria-controls="collapseProfil">
<i class="bi bi-file-earmark-text me-2"></i> Mon identité
</button>
</h2>
<div id="collapseProfil" class="accordion-collapse" aria-labelledby="headingContrats" data-bs-parent="#accordionInformationEmploye">
<div class="accordion-body">
<div class="row" id="information-personnelles" data-url="{% url 'gestion_employe:modifier-employe' %}">
{% csrf_token %}
<div class="col">
<div class="form-group mb-2">
<label>photo</label>
{% if employe.photo %}
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
{% endif %}
<input type="file" id="photo" name="photo" class="form-control">
</div>
<div class="form-group mb-2">
<label>Matricule :</label>
<input type="text" class="form-control" id="matricule" value="{{ employe.matricule|default:'' }}" readonly>
</div>
<div class="form-group mb-2">
<label>Nom :</label>
<input type="text" class="form-control" id="nom" value="{{ employe.user.last_name }}">
</div>
<div class="form-group mb-2">
<label>Prénom :</label>
<input type="text" class="form-control" id="prenom" value="{{ employe.user.first_name }}">
</div>
<div class="form-group mb-2">
<label>Sexe :</label>
<select id='sexe' class="form-select">
<option value='h' {% if employe.sexe == 'h' %}selected{% endif %}>Homme</option>
<option value='f' {% if employe.sexe == 'f' %}selected{% endif %}>Femme</option>
</select>
</div>
</div>
<div class="col">
<div class="form-group mb-2">
<label>Date de naissance :</label>
<input type="date" class="form-control" id="date_naissance" value="{{ employe.date_naissance|date:'Y-m-d' }}">
</div>
<div class="form-group mb-2">
<label>Département :</label>
<input type="text" class="form-control" id="departement" value="{{ employe.departement.nom|default:'' }}" readonly>
</div>
<div class="form-group mb-2">
<label>Email :</label>
<input type="email" class="form-control" id="email" value="{{ employe.user.email|default:'' }}">
</div>
<div class="form-group mb-2">
<label>Téléphone :</label>
<input type="text" class="form-control" id="telephone" value="{{ employe.telephone|default:'' }}">
</div>
<div class="form-group mb-2">
<label>Adresse :</label>
<input type="text" class="form-control" id="adresse" value="{{ employe.adresse|default:'' }}">
</div>
</div>
</div>
<button type="submit" class="btn btn-success d-block m-auto" id="enregistrerProfil">Enregistrer</button>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingContrats">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseContrats" aria-expanded="false" aria-controls="collapseContrats">
<i class="bi bi-file-earmark-text me-2"></i> Contrats
</button>
</h2>
<div id="collapseContrats" class="accordion-collapse collapse" aria-labelledby="headingContrats" data-bs-parent="#accordionInformationEmploye">
<div class="accordion-body">
{% for contrat in contrats %}
<div class="mb-3 p-3 border rounded">
<div class="form-group mb-2">
<label>Numéro :</label>
<input type="text" class="form-control" value="{{ contrat.numero_contrat }}" id="numero_contrat" readonly>
</div><div class="form-group mb-2">
<label>Type de Contrat :</label>
<input type="text" class="form-control" value="{{ contrat.type_contrat }}" id="type_contrat" readonly>
</div><div class="form-group mb-2">
<label>Date début :</label>
<input type="date" class="form-control" value="{{ contrat.date_debut|date:'Y-m-d' }}" id="date_debut" readonly>
</div>
<div class="form-group mb-2">
<label>Date fin :</label>
<input type="date" class="form-control" value="{{ contrat.date_fin|date:'Y-m-d' }}" id="date_fin" readonly>
</div>
<div class="form-group mb-2">
<label>Salaire :</label>
<input type="number" class="form-control" value="{{ contrat.salaire_mensuel }}" id="salaire" readonly>
</div>
<div class="form-group mb-2">
<label>Statut :</label>
<input type="text" class="form-control" value="{{ contrat.statut }}" id="satut" readonly>
</div>
<div class="form-group mb-2">
<label>fichier :</label>
<a href="{{ contrat.fichier_contrat }}" target="_blank" class="btn btn-outline-primary">Voir le contrat</a>
</div>
</div>
{% empty %}
<p class="text-danger">Aucun contrat trouvé.</p>
{% endfor %}
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingProjets">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseProjets" aria-expanded="false" aria-controls="collapseProjets">
<i class="bi bi-briefcase me-2"></i> Projets
</button>
</h2>
<div id="collapseProjets" class="accordion-collapse collapse" aria-labelledby="headingProjets" data-bs-parent="#accordionInformationEmploye">
<div class="accordion-body">
<ul class="list-group">
{% for projet in projets %}
<li class="list-group-item d-flex justify-content-between align-items-center">
{{ projet.nom_projet }} ({{ projet.pourcentage_temps_affectation }}%) du <strong>{{ projet.date_debut|date:"d/m/Y" }}</strong> au
<strong>{{ projet.date_fin|date:"d/m/Y" }}</strong> en tant que {{ projet.role }}.
</li>
{% empty %}
<li class="list-group-item text-muted text-center">Vous n'êtes affecté à aucun projet.</li>
{% endfor %}
</ul>
</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="#accordionInformationEmploye">
<div class="accordion-body">
<form method="POST" action="{% url 'gestion_employe:enregistrement-document-rh' %}" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="col">
<div class="form-group mb-2">
<label>photo</label>
{% if employe.photo %}
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
{% endif %}
<input type="file" class="form-control" name="photo">
</div>
<div class="form-group mb-2">
<label>CV</label>
{% if employe.CV %}
<span>Fichier actuel : <a href="{{ employe.CV.url }}">{{employe.CV}}</a></span>
{% endif %}
<input type="file" class="form-control" name="cv">
</div>
<div class="form-group mb-2">
<label>Diplôme</label>
{% if employe.diplome %}
<span>Fichier actuel : <a href="{{ employe.diplome.url }}">{{employe.diplome}}</a></span>
{% endif %}
<input type="file" class="form-control" name="diplome">
</div>
</div>
<div class="col">
<div class="form-group mb-2">
<label>Casier judiciaire</label>
{% if employe.casier_judiciaire %}
<span>Fichier actuel : <a href="{{ employe.casier_judiciaire.url }}">{{employe.casier_judiciaire}}</a></span>
{% endif %}
<input type="file" class="form-control" name="casier_judiciaire">
</div>
<div class="form-group mb-2">
<label>RIB</label>
{% if employe.rib %}
<span>Fichier actuel : <a href="{{ employe.rib.url }}">{{employe.rib}}</a></span>
{% endif %}
<input type="file" class="form-control" name="rib">
</div>
</div>
</div>
<button type="submit" class="btn btn-success d-block m-auto">Enregistrer</button>
</form>
</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header" id="headingCertificat">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseCertificat" aria-expanded="false" aria-controls="collapseCertificat">
<i class="bi bi-file-earmark-text me-2"></i> Certificats
</button>
</h2>
<div id="collapseCertificat" class="accordion-collapse collapse" aria-labelledby="headingCertificat" data-bs-parent="#accordionInformationEmploye">
<div class="accordion-body">
<div id="tableau-certificat" data-url="{% url 'gestion_employe:liste-formation' %}"></div>
<button class="btn btn-success d-block m-auto" data-bs-toggle="modal" data-bs-target="#modalAjouterFormation">Ajouter un certificat</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block 'modal' %}
{% include "gestion_employe/parts/modificationMotPasse.html" %}
{% include "gestion_employe/parts/modalAjoutFormation.html" %}
{% endblock %}
{% block 'js' %}
<script src="{% static 'gestion_employe/js/mon_profil.js' %}"></script>
{% endblock %}

View File

@@ -1,28 +0,0 @@
<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

@@ -1,21 +0,0 @@
<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

@@ -1,57 +0,0 @@
<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

@@ -1,136 +0,0 @@
{% load tags_personnaliser %}
<div class="modal fade" id="modalDetailEmploye" tabindex="-1" aria-labelledby="modalDetailEmployeLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header ">
<h5 class="modal-title bi-pencil-square" id="modalDetailEmployeLabel">
Détails de l'employé <span id="detail-employe"></span>
</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body" id="modalDetailEmployeBody" data-url="{% url 'gestion_employe:enregistrer-detail-employe' %}">
<div class="row g-3">
<input type="hidden" id="detail-id">
<div class="col-md-6">
{% csrf_token %}
<div class="form-group mb-2">
<label>Matricule :</label>
<input type="text" class="form-control" id="detail-matricule">
</div>
<div class="form-group mb-2">
<label>Date d'embauche :</label>
<input type="date" class="form-control" id="detail-dateEmbauche">
</div>
<div class="form-group mb-2">
<label>Département :</label>
<input type="text" class="form-control" id="detail-departement">
</div>
<div class="form-group mb-2">
<label>Sexe :</label>
<select id="detail-sexe" class="form-select">
<option value="">-- Sélectionner --</option>
<option value="h">Masculin</option>
<option value="f">Féminin</option>
</select>
</div>
<div class="form-group mb-2">
<label>Date de naissance :</label>
<input type="date" class="form-control" id="detail-dateNaissance">
</div>
</div>
<div class="col-md-6">
<div class="form-group mb-2">
<label>Fonction :</label>
<select class="form-select" id='detail-fonction'>
<option value='chauffeur'>Chauffeur</option>
<option value='technicien_surface'>Technicien de surface</option>
<option value='qualiticien'>Qualiticien</option>
<option value='post_doctorant'>Post-Doctorant</option>
<option value='logisticien'>Logisticien</option>
<option value='data_manager'>Data Manager</option>
<option value='raf'>RAF</option>
<option value='comptable'>Comptable</option>
<option value='assistant_direction'>Assistante de direction</option>
<option value='directeur'>Directeur</option>
</select>
</div>
<div class="form-group mb-2">
<label>Email :</label>
<input type="email" class="form-control" id="detail-email">
</div>
<div class="form-group mb-2">
<label>Téléphone :</label>
<input type="text" class="form-control" id="detail-telephone">
</div>
<div class="form-group mb-2">
<label>Adresse :</label>
<input type="text" class="form-control" id="detail-adresse">
</div>
</div>
</div>
<div class="row">
{% if user|has_group:"ressource_humaine" %}
<div class="col">
<button type="button" class="btn btn-success d-block m-auto" id="enregistrerDetail">
<i class="bi bi-save"></i> Enregistrer
</button>
</div>
{% endif %}
</div>
<div class="row">
<div class="col text-end">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalDocuments">
<i class="bi bi-folder2-open"></i> Voir les documents RH
</button>
</div>
</div>
<hr class="my-4">
<div class="row">
<div class="col">
<div class="d-flex justify-content-between">
<h5>
<i class="bi bi-file-earmark-text me-2"></i> Liste des Contrats
</h5>
{% if user|has_group:"ressource_humaine" %}
<div>
<button class="btn btn-secondary" disabled>
<i class="bi bi-file-earmark-lock"></i> Contrat actif
</button>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#modalContrat{{ item.employe.id }}">
<i class="bi bi-file-earmark-text"></i> Créer contrat
</button>
</div>
{% endif %}
</div>
{% csrf_token %}
<div class="row" id="contrats-list"></div>
</div>
</div>
<hr class="my-4">
<div class="row d-flex g-3">
<div class="d-flex justify-content-between">
<h5><i class="bi bi-pin-angle me-2"></i> Affectations</h5>
{% if user|has_group:"ressource_humaine" %}
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#modalAffectation" onclick="setEmployeId()">
<i class="bi bi-file-earmark-text"></i>Affecter
</button>
{% endif %}
</div>
<div class="row">
<div id="affectations-list"></div>
</div>
</div>
<hr class="my-4">
<div class="row g-3">
<h5 class="mb-3"><i class="bi bi-award-fill me-2"></i> Formations</h5>
<div class="row" id="formations-list"></div>
</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>

View File

@@ -1,41 +0,0 @@
<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

@@ -1,17 +0,0 @@
<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

@@ -1,36 +0,0 @@
<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

@@ -1,24 +0,0 @@
"""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"

View File

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

View File

@@ -1,102 +0,0 @@
from . import views
from django.urls import path
app_name = 'gestion_employe'
urlpatterns = [
path(
'',
views.index,
name='index'
),
path(
'liste-employes/',
views.liste_employe,
name='liste-employes'
),
path(
'enregistrer-detail-employe/',
views.enregistrer_detail_employe,
name='enregistrer-detail-employe'
),
path(
'affectation/supprimer/',
views.suppression_affectation,
name='supprimer-affectation'
),
path(
'contrat/creation/',
views.creation_contrat,
name='creation-contrat'
),
path(
'contrat/supprimer/',
views.suppression_contrat,
name='supprimer-contrat'
),
path(
'Affectation/affectation/',
views.affecter_employe_projet,
name='affecter_employe_projet'
),
path(
'mon-profil/',
views.mon_profil,
name='mon-profil'
),
path(
'enregistrement-document-rh',
views.enregistrement_document,
name='enregistrement-document-rh'
),
path(
'modifier-employe',
views.modifier_employer,
name='modifier-employe'
),
path(
"mes-formations/ajouter/",
views.ajouter_formation,
name="ajouter_formation"
),
path(
"mes-formations/liste/",
views.liste_formation,
name="liste-formation"
),
path(
"mes-formations/modifier/<int:pk>/",
views.modifier_formation,
name="modifier_formation"
),
path(
"mes-formations/supprimer/<int:pk>/",
views.supprimer_formation,
name="supprimer_formation"
),
path(
'modifier-mot-passe/',
views.modifier_mot_passe,
name='modifier-mot-passe'
),
# path(
# 'creation-departement/',
# views.creation_departement,
# name='creation-departement'
# ),
# path(
# 'modifier-departement/',
# views.modifier_departement,
# name='modifier-departement'
# ),
# path(
# 'suppression-departement/',
# views.supprimer_departement,
# name='suppression-departement/'
# ),
path(
"liste-contrat-expirants",
views.liste_contrat_expirants,
name='liste-contrat-expirants'
)
]

View File

@@ -1,447 +0,0 @@
import json
from datetime import timedelta, datetime
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):
"""Vue pour permettre à un utilisateur de créer un contrat pour un employé"""
try:
employe = Employe.objects.get(id=request.POST.get('employe_id'))
except Employe.DoesNotExist:
messages.error(request, "Employé non trouvé.")
return redirect('employe-index')
if request.method == "POST":
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")
else:
form = ContratForm(initial={'employe': employe})
return render(request, 'gestion_employe/index.html', {'contrat_form': form})
@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')