7 Commits

Author SHA1 Message Date
f9ca539670 Supprimer gestion_salle/migrations/0001_initial.py
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-07-14 09:17:13 +00:00
7b4778252f Supprimer gestion_projet/migrations/0001_initial.py
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-07-14 09:17:02 +00:00
2c086187e7 Supprimer gestion_employe/migrations/0001_initial.py
Some checks are pending
Organisation/sirh/pipeline/head Build queued...
2026-07-14 09:16:51 +00:00
5aff49600e Supprimer gestion_conge/migrations/0001_initial.py
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-07-14 09:16:28 +00:00
8c6e59e15a Correction enregistrement profil
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-07-14 09:03:28 +00:00
415860f233 Filtrage des reservations par salle
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-15 17:13:02 +00:00
8503689aa4 Bug: Correction du refus des reservations et d'envoi de mail
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-15 16:31:11 +00:00
49 changed files with 88 additions and 349 deletions

1
Jenkinsfile vendored
View File

@@ -39,6 +39,7 @@ pipeline
python manage.py makemigrations
python manage.py migrate
echo $SUDO_PASSWORD | sudo -S rm -r staticfiles
python manage.py collectstatic --noinput
echo $SUDO_PASSWORD | sudo -S chown -R www-data:www-data /var/www/sirh

View File

@@ -41,7 +41,7 @@ urlpatterns = [
name='deconnexion'
),
path(
'employé/',
'gestion-employe/',
include("gestion_employe.urls")
),
path(

View File

@@ -7,7 +7,10 @@ QUOTA_CONGE_ANNUEL = 30
NOMBRE_PAGINATION = 8
DEBUT_RAPPEL = 60
DUREE_FIN_CONTRAT = 90
try:
EMAIL_ASSISTANTE_DE_DIRECTION = list(Employe.objects.filter(fonction="assistant_direction").values_list('user__email', flat=True))
except:
pass
def solde_conge(employe):
"""Fonction de calcul du solde de congé restant l'employé"""

View File

@@ -1,30 +0,0 @@
# Generated by Django 5.2.13 on 2026-04-17 12:03
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('gestion_employe', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Conge',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_debut', models.DateField(verbose_name='Date de Début')),
('date_fin', models.DateField(verbose_name='Date de Fin')),
('type', models.CharField(choices=[('conge_annuel', 'Conge Annuel')], max_length=100, verbose_name='Type de Congé')),
('date_demande', models.DateField(auto_now_add=True, verbose_name='Date de Demande')),
('validation_hierarchique', models.BooleanField(default=None, null=True)),
('validation_direction', models.BooleanField(default=None, null=True)),
('motif_refus', models.TextField(blank=True, null=True)),
('employe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='employe', to='gestion_employe.employe')),
],
),
]

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

@@ -18,29 +18,34 @@ const tableau_certificat = new Tabulator("#tableau-certificat", {
})
const enregistrerProfil = $("enregistrerProfil");
enregistrerProfil.addEventListener("click", (e) => {
// enregistrerProfil.addEventListener("click", (e) => {
const url = $("information-personnelles").dataset.url;
const csrftoken = document.querySelector("[name='csrfmiddlewaretoken']").value;
// const url = $("information-personnelles").dataset.url;
// const csrftoken = document.querySelector("[name='csrfmiddlewaretoken']").value;
const formData = new FormData();
// 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);
// 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));
});
// console.log("---------------------------------------------")
// console.log("Données du formulaire:", url);
// console.log("Données du formulaire:", formData);
// 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

@@ -38,7 +38,7 @@
</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' %}">
<form class="row" action = "{% url 'gestion_employe:modifier-employe' %}" method = "POST" enctype = "multipart/form-data" id="information-personnelles" data-url="{% url 'gestion_employe:modifier-employe' %}">
{% csrf_token %}
<div class="col">
<div class="form-group mb-2">
@@ -50,19 +50,19 @@
</div>
<div class="form-group mb-2">
<label>Matricule :</label>
<input type="text" class="form-control" id="matricule" value="{{ employe.matricule|default:'' }}" readonly>
<input type="text" class="form-control" id="matricule" name = '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 }}">
<input type="text" class="form-control" id="nom" name = '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 }}">
<input type="text" class="form-control" id="prenom" name = 'prenom' value="{{ employe.user.first_name }}">
</div>
<div class="form-group mb-2">
<label>Sexe :</label>
<select id='sexe' class="form-select">
<select id='sexe' name = '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>
@@ -72,27 +72,27 @@
<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' }}">
<input type="date" class="form-control" id="date_naissance" name = '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>
<input type="text" class="form-control" id="departement" name = '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:'' }}">
<input type="email" class="form-control" id="email" name = '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:'' }}">
<input type="text" class="form-control" id="telephone" name = '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>
<input type="text" class="form-control" id="adresse" name = 'adresse' value="{{ employe.adresse|default:'' }}">
</div>
</div>
<button type="submit" class="btn btn-success d-block m-auto" id="enregistrerProfil">Enregistrer</button>
</form>
</div>
</div>
</div>

View File

@@ -191,25 +191,26 @@ def modifier_employer(request):
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']
user.last_name = request.POST['nom']
user.first_name = request.POST['prenom']
user.email = request.POST['email']
employe.telephone = request.POST['telephone']
employe.adresse = request.POST['adresse']
employe.sexe = request.POST['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 request.POST['date_naissance']:
difference = relativedelta(timezone.now().date(), datetime.strptime(request.POST['date_naissance'], "%Y-%m-%d").date())
if difference.years >= 18:
employe.date_naissance = data['date_naissance']
employe.date_naissance = request.POST['date_naissance']
else:
return JsonResponse({"message": "Veuillez entrez une date de naissance correcte."})
messages.error(request, "Veuillez entrez une date de naissance correcte.")
employe.save()
user.save()
return JsonResponse({"message": "Profil mis à jour avec succès."})
messages.success(request, "Profil mis à jour avec succès.")
return redirect("gestion_employe:mon-profil")
def enregistrement_document(request):
"""Vue pour permettre à un utilisateur de télécharger et enregistrer des documents liés à son profil"""

View File

@@ -1,107 +0,0 @@
# Generated by Django 5.2.13 on 2026-04-17 12:03
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='ActiviteProjet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('titre', models.CharField(max_length=200, verbose_name="Titre de l'activité")),
('description', models.TextField(blank=True, null=True, verbose_name="Description de l'activité")),
('date_debut', models.DateField(verbose_name='Date de début')),
('date_fin', models.DateField(verbose_name='Date de fin')),
('annuler', models.BooleanField(default=False, verbose_name="Annuler l'activité")),
('motif_annulation', models.TextField(blank=True, null=True, verbose_name="Motif d'annulation")),
('motif_changement_budget', models.TextField(blank=True, null=True, verbose_name='Motif de changement de budget')),
('budget_prevu', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Budget prévu')),
('budget_depense', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Budget dépensé')),
('besoin_ressource_materielle', models.TextField(verbose_name='Besoin de ressources matérielles')),
],
),
migrations.CreateModel(
name='Bailleur',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nom_organisme', models.CharField(max_length=200, unique=True)),
('contact', models.CharField(blank=True, max_length=100, null=True)),
('email', models.EmailField(blank=True, max_length=254, null=True)),
('pays', models.CharField(blank=True, max_length=100, null=True)),
],
),
migrations.CreateModel(
name='DomaineDeRecherche',
fields=[
('nom', models.CharField(choices=[('sciences_sociales', 'Sciences sociales'), ('naturelles', 'Naturelles'), ('humaines', 'Humaines'), ('veterinaires', 'Vétérinaires')], max_length=100, primary_key=True, serialize=False, verbose_name='Domaine de recherche')),
],
options={
'verbose_name': 'Domaine de recherche',
'verbose_name_plural': 'Domaines de recherche',
},
),
migrations.CreateModel(
name='LivrablesLivres',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nom', models.CharField(max_length=255, verbose_name='Nom du livrable')),
('fichier', models.FileField(blank=True, null=True, upload_to='fichier_livrables/')),
('activite', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_projet.activiteprojet')),
],
),
migrations.CreateModel(
name='Projet',
fields=[
('id_projet', models.CharField(blank=True, max_length=100, primary_key=True, serialize=False, unique=True, verbose_name='ID du projet')),
('nom_projet', models.CharField(max_length=200, verbose_name='Nom du projet')),
('date_debut', models.DateField(verbose_name='Date de début')),
('date_fin', models.DateField(verbose_name='Date de fin')),
('numero_convention', models.CharField(max_length=100, verbose_name='Numéro de convention')),
('description', models.TextField(verbose_name='Description')),
('type_projet', models.CharField(choices=[('laboratoire', 'Laboratoire'), ('épidémiologie', 'Épidémiologie'), ('sciences sociales', 'Sciences sociales'), ('cliniques', 'Cliniques'), ('autre', 'Autre')], default='épidémiologie', max_length=100, verbose_name='Type de projet')),
('budget', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Budget')),
('budget_RH', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Budget RH')),
('created_at', models.DateTimeField(auto_now_add=True)),
('bailleur', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='gestion_projet.bailleur', verbose_name='Bailleur de fonds')),
('domaine_recherche', models.ManyToManyField(to='gestion_projet.domainederecherche')),
],
),
migrations.CreateModel(
name='DocumentProjet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date_ajout', models.DateTimeField(auto_now_add=True, verbose_name="Date d'ajout")),
('nom_document', models.CharField(choices=[('protocole', 'Protocole d’étude'), ('ethique', "Approbation du comité d'éthique"), ('autorisation', 'Autorisation (DNLP)'), ('rapport_technique', 'Rapport technique'), ('rapport_financier', 'Rapport financier'), ('rapport_avancement', "Rapport d'avancement"), ('convention', 'Convention'), ('rapport_final', 'Rapport final'), ('autre', 'Autre')], max_length=100, verbose_name='Type de document')),
('description', models.TextField(blank=True, verbose_name='Description')),
('numero', models.CharField(blank=True, max_length=100, null=True, verbose_name='Numéro du document')),
('date_validite', models.DateField(blank=True, null=True, verbose_name='Date de validité')),
('fichier', models.FileField(upload_to='documents_projets/', verbose_name='Fichier à télécharger')),
('projet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='documents', to='gestion_projet.projet', verbose_name='Projet')),
],
),
migrations.AddField(
model_name='activiteprojet',
name='projet',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_projet.projet', verbose_name='Projet'),
),
migrations.CreateModel(
name='FinancementProjet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('pourcentage', models.DecimalField(decimal_places=2, max_digits=5)),
('bailleur', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_projet.bailleur')),
('projet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_projet.projet')),
],
options={
'unique_together': {('projet', 'bailleur')},
},
),
]

View File

@@ -2,7 +2,6 @@ from datetime import date
from decimal import Decimal, InvalidOperation
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils import timezone
from django.contrib import messages
from django.contrib.auth.decorators import login_required

View File

@@ -1,34 +0,0 @@
# Generated by Django 5.2.13 on 2026-04-17 12:03
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('gestion_employe', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Reservation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('salle', models.CharField(choices=[('formation', 'Salle de formation'), ('reunion', 'Salle de réunion'), ('lien_zoom', 'Lien Zoom')], max_length=100)),
('date_demande', models.DateTimeField(auto_now_add=True)),
('date_debut', models.DateField()),
('date_fin', models.DateField(blank=True, null=True)),
('heure_debut', models.TimeField()),
('heure_fin', models.TimeField()),
('besoin_zoom', models.BooleanField(default=False, verbose_name="Besoin d'un lien Zoom ?")),
('besoin_ordi', models.BooleanField(default=False, verbose_name="Besoin d'un ordinateur ?")),
('lien_zoom', models.URLField(blank=True, null=True, verbose_name='Lien Zoom')),
('motif_reservation', models.TextField()),
('statut', models.CharField(choices=[('en_attente', 'En attente'), ('validee', 'Validée'), ('refusee', 'Refusée'), ('annulee', 'Annulée')], default='en_attente', max_length=25)),
('employe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_employe.employe')),
],
),
]

View File

@@ -78,6 +78,11 @@ $("bouton-annuler").addEventListener("click", (e) => {
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
const url_annuler = $("formulaire-details").dataset.urlannuler;
console.log("URL d'annulation :");
console.log($("formulaire-details"))
e.preventDefault();
fetch(
url_annuler,
{
@@ -128,6 +133,9 @@ if($("refuserReservation")){
const url = e.currentTarget.dataset.lienrefus;
const idRes = $("id_reservation_detail").value;
console.log(idRes);
e.preventDefault();
fetch(url, {
method: "POST",
headers: {

View File

@@ -26,9 +26,9 @@
<div class="form-group col-5 me-2">
<label>Selectionner une salle :</label>
<select class = "form-select" id="liste-salle">
<option value='formation'>Salle de formation</option>
<option value='reunion'>Salle de réunion</option>
<option value='lien_zoom'>Lien Zoom</option>
<option value='Salle de formation'>Salle de formation</option>
<option value='Salle de réunion'>Salle de réunion</option>
<option value='Lien Zoom'>Lien Zoom</option>
</select>
</div>
</div>

View File

@@ -1,4 +1,5 @@
from datetime import timedelta
import json
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect, render
@@ -19,8 +20,6 @@ def index(request: HttpRequest):
messages.error(request, "Profil employé introuvable.")
return redirect('gestion_conges:conge')
if request.method == "POST":
form = ReservationForm(request.POST)
@@ -72,7 +71,6 @@ def index(request: HttpRequest):
messages.success(request, "Réservation(s) créée(s) avec succès.")
print(fonctions_utilitaire.EMAIL_ASSISTANTE_DE_DIRECTION)
if fonctions_utilitaire.EMAIL_ASSISTANTE_DE_DIRECTION:
fonctions_utilitaire.envoyer_mail(
sujet = "Reservation de salle",
@@ -107,6 +105,7 @@ def liste_reservation(request:HttpRequest):
"""Vue d'affichage des creneaux disponibles"""
reservations = Reservation.objects.filter(statut = "validee")
liste_reservation = []
for reservation in reservations:
color = None
if reservation.statut == "en_attente":
@@ -116,6 +115,8 @@ def liste_reservation(request:HttpRequest):
else:
color = "#dc3545"
print(dict(Reservation.TYPE_CHOICES).get(reservation.salle))
liste_reservation.append({
"guid": reservation.pk,
"title": dict(Reservation.TYPE_CHOICES).get(reservation.salle),
@@ -220,32 +221,30 @@ def valider_reservation(request: HttpRequest):
reservation.statut = 'validee'
reservation.save()
if fonctions_utilitaire.EMAIL_ASSISTANTE_DE_DIRECTION:
fonctions_utilitaire.envoyer_mail(
sujet = "Reservation de salle",
message = f"""Bonjour {request.user.first_name} {request.user.last_name}, votre reservation de la salle {dict(Reservation.TYPE_CHOICES).get(reservation.salle)} du {reservation.date_debut.strftime('%d/%m/%Y')} au {reservation.date_fin.strftime('%d/%m/%Y')} pour motif "{reservation.motif_reservation}" a été validée. Veuillez vous connecter à la plateforme pour plus de détails.""",
destinataires = [reservation.employe.user.email]
)
messages.success(request, f"Réservation de {reservation.employe.get_full_name()} validée avec succès.")
messages.success(request, f"La réservation de {request.user.first_name} {request.user.last_name} validée avec succès.")
return redirect('gestion_salle:reservation-salle')
@login_required
def refuser_reservation(request: HttpRequest):
"""Refuser une réservation"""
if request.method == 'POST':
reservation_id = request.POST.get('id_reservation')
reservation_id = json.loads(request.body).get('id_reservation')
try:
reservation = Reservation.objects.get(id=reservation_id)
except Reservation.DoesNotExist:
messages.error(request, "La réservation n'existe pas.")
return redirect("salle")
return JsonResponse({"message": "Une erreur s'est produite lors de l'annulation de la reservation."})
reservation.statut = 'refusee'
reservation.save()
if fonctions_utilitaire.EMAIL_ASSISTANTE_DE_DIRECTION:
fonctions_utilitaire.envoyer_mail(
sujet = "Reservation de salle",
message = f"""Bonjour {request.user.first_name} {request.user.last_name}, votre reservation de la salle {dict(Reservation.TYPE_CHOICES).get(reservation.salle)} du {reservation.date_debut.strftime('%d/%m/%Y')} au {reservation.date_fin.strftime('%d/%m/%Y')} pour motif "{reservation.motif_reservation}" a été refusée. Veuillez vous connecter à l'Assistante de Direction pour plus de détails.""",