10 Commits

Author SHA1 Message Date
Fatimac2804
d28bf85556 Affichage de la liste des departements pour la modification de l'employer
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main This commit looks good
SGL/sirh/pipeline/head This commit looks good
2026-09-02 14:33:51 +02:00
Fatimac2804
3b587d2a1a Affichage des detait de la reservation de salle
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-09-02 13:46:07 +02:00
Fatimac2804
e3f0befff6 Correction sur l'afficha de la liste de departement pour la modification des informations de l'employer
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-09-02 12:48:35 +02:00
Soriba SYLLA
55e5a2819c Ajout du contexte processor
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-08-31 09:48:21 +00:00
Soriba SYLLA
7e28b25497 Merge branch 'staging' 2026-08-23 15:14:24 +00:00
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
48 changed files with 128 additions and 80 deletions

View File

@@ -27,7 +27,7 @@ SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=True, cast=bool)
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[]).split(',')
CSRF_TRUSTED_ORIGINS = config("CSRF_TRUSTED_ORIGINS", default=[]).split(",")
#CSRF_TRUSTED_ORIGINS = config("CSRF_TRUSTED_ORIGINS", default=[]).split(",")
# Application definition
@@ -66,6 +66,7 @@ TEMPLATES = [
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'contexte_universel.contexte_universel',
],
},
},
@@ -144,9 +145,9 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# LOGIN_URL = '/client/'
LOGIN_URL = 'simple-sso-login'
SSO_PRIVATE_KEY = 'D2brFY3LnNDLQBBnvYPXAn185Wi9EpPvnHsUosjEZ9vZMyEtXqkcVfFWkVbN0xpG'
SSO_PUBLIC_KEY = 'm9JDP3uGPmGG9ULqPw2BY3ryBNMTGRsuukgIOhk7lIN9lT0wlr2zhoRZiNZ28UCM'
SSO_SERVER = 'http://test-authentification.cerfig.org:89/server/'
SSO_PRIVATE_KEY = config('SSO_PRIVATE_KEY')
SSO_PUBLIC_KEY = config('SSO_PUBLIC_KEY')
SSO_SERVER = config('SSO_SERVER')
#SSO_LOGOUT_URL = 'http://test-authentification.cerfig.org:89/deconnexion'
# Configuration de l'email

View File

@@ -10,19 +10,25 @@ class SIRHClient(Client):
def build_user(self, user_data):
"""Crée le User et son Profile avec les infos reçues du serveur."""
user_data_copy = user_data.copy()
user_data.pop("departement")
user_data.pop("chef_departement")
user_data.pop("groups")
print("Un petit test", user_data_copy)
user_data.pop("departement", None)
user_data.pop("chef_departement", None)
user_data.pop("groups", None)
user = super().build_user(user_data)
departement = Departement.objects.get_or_create(
nom=user_data_copy.get("departement", ""))[0]
departement = None
if "departement" in user_data_copy:
departement = Departement.objects.get_or_create(
nom=user_data_copy.get("departement", ""))[0]
Employe.objects.update_or_create(
user = user,
defaults = {
"departement": departement,
"chef": user_data_copy.get("chef_departement", ""),
"chef": user_data_copy.get("chef_departement", None),
}
)
@@ -30,4 +36,4 @@ class SIRHClient(Client):
group, _ = Group.objects.get_or_create(name=group_name)
user.groups.add(group)
return user
return user

View File

@@ -1,8 +1,8 @@
<div class="col-1 bg-danger border d-flex flex-column vh-100 pt-5 sticky-top">
<a href="http://test-sirh.cerfig.org:89/" class="text-white text-center fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{{ SIRH_LIEN }}" class="text-white text-center fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<i class="bi bi-people-fill fs-1 d-block"></i>SIRH
</a>
<a href="http://test-sgl.cerfig.org:89/" class="text-white text-center fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{{ SGL_LIEN }}" class="text-white text-center fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<i class="bi bi-building-gear fs-1 d-block"></i> SGL
</a>
</div>

View File

@@ -42,7 +42,7 @@
<i class="bi bi-calendar-check"></i> Réservation
</a>
{% comment %} {% url 'deconnexion' %} {% endcomment %}
<a href="http://test-authentification.cerfig.org:89/deconnexion" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<a href="{% url 'deconnexion' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-box-arrow-right"></i> Déconnexion
</a>
</div>

View File

@@ -18,7 +18,7 @@ from django.contrib import admin
from django.urls import include, path
# from django.conf.urls.static import static
from django.conf import settings
from . import views
from .sso import SIRHClient
client_sirh = SIRHClient(
@@ -28,15 +28,15 @@ client_sirh = SIRHClient(
)
urlpatterns = [
# path('login/',
# views.login_view,
# name='login'
# ),
# path(
# 'deconnexion/',
# views.deconnexion_view,
# name='deconnexion'
# ),
path('login/',
views.connexion,
name='login'
),
path(
'deconnexion/',
views.deconnexion,
name='deconnexion'
),
path(
'',
include("gestion_employe.urls")
@@ -59,4 +59,4 @@ urlpatterns = [
),
path("client/", include(client_sirh.get_urls())),
]
# + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -0,0 +1,16 @@
from django.contrib.auth import logout
from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.conf import settings
def connexion(request):
"""Redirige vers le serveur SSO pour l'authentification."""
return redirect(reverse_lazy("simple-sso-login"))
def deconnexion(request):
"""Gérez la déconnexion des utilisateurs."""
logout(request)
#return redirect(settings.SSO_LOGOUT_URL)
return redirect("http://authentification.cerfig.org/login")

7
contexte_universel.py Normal file
View File

@@ -0,0 +1,7 @@
from decouple import config
def contexte_universel(request):
return {
"SIRH_LIEN": config("SIRH_LIEN"),
"SGL_LIEN": config("SGL_LIEN")
}

View File

@@ -7,7 +7,11 @@ QUOTA_CONGE_ANNUEL = 30
NOMBRE_PAGINATION = 8
DEBUT_RAPPEL = 60
DUREE_FIN_CONTRAT = 90
# EMAIL_ASSISTANTE_DE_DIRECTION = list(Employe.objects.filter(fonction="assistant_direction").values_list('user__email', flat=True))
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

@@ -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:'' }}">
<input type="text" class="form-control" id="adresse" name = 'adresse' value="{{ employe.adresse|default:'' }}">
</div>
</div>
</div>
<button type="submit" class="btn btn-success d-block m-auto" id="enregistrerProfil">Enregistrer</button>
<button type="submit" class="btn btn-success d-block m-auto" id="enregistrerProfil">Enregistrer</button>
</form>
</div>
</div>
</div>

View File

@@ -20,6 +20,9 @@ from fonction_utilitaire import fonctions_utilitaire
@login_required
def index(request):
"""Vue d'index"""
if not request.user.groups.filter(name="ressource_humaine").exists():
return redirect('gestion_employe:mon-profil')
employes = Employe.objects.all().order_by('-user__date_joined')
nombre_employes = Employe.objects.count()
nombre_cps = Contrat.objects.filter(type_contrat='contrat_prestation').count()
@@ -94,7 +97,7 @@ def affecter_employe_projet(request):
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}%)."
f"Les pourcentages d'affectation de l'employé {employe.user.first_name} {employe.user.last_name} dépasse 100% sur les différents projets ({total_affectation + temps_nouveau}%)."
)
return redirect('gestion_employe:index')
@@ -191,25 +194,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

@@ -12,7 +12,12 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), {
const modal = new bootstrap.Modal($("modalDetailReservation"));
modal.show();
fetch (`/gestion-salle/revervation/details/${event.guid}`)
.then(response => response.json())
.then(response => {
if (!response.ok) {
throw new Error(`Erreur HTTP ${response.status}`);
}
return response.json();
})
.then(data => {
currentReservationId = data.id_reservation;
$("id_reservation_detail").value = data.id_reservation;
@@ -21,7 +26,7 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), {
$("employe").value=data.employe;
$("salle").value=data.salle;
$("statut-reservation").innerHTML=data.statut;
$("date_evenement").value=data.date_evenement;
$("date_debut").value=data.date_debut;
$("heure_debut").value=data.heure_debut;
$("heure_fin").value=data.heure_fin;
$("motif_reservation").value=data.motif_reservation;
@@ -34,6 +39,7 @@ const calendrier = Schedule(document.getElementById('planning-reservation'), {
}
})
.catch(error => console.error("Impossible de charger les détails de la réservation :", error));
}
});
@@ -180,7 +186,6 @@ tableau_reservation_attente.on("rowClick", (row, rowData) => {
$("salle").value=data.salle;
$("statut-reservation").innerHTML=data.statut;
$("date_debut").value = data.date_debut;
$("date_fin").value = data.date_fin;
$("heure_debut").value=data.heure_debut;
$("heure_fin").value=data.heure_fin;
$("motif_reservation").value=data.motif_reservation;

View File

@@ -55,5 +55,5 @@
{% block 'js' %}
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@calendarjs/ce/dist/index.min.js"></script>
<script src="{% static 'gestion_salle/js/index.js' %}"></script>
<script src="{% static 'gestion_salle/js/index.js' %}?v=3"></script>
{% endblock %}

View File

@@ -25,10 +25,10 @@
<label>Date de debut :</label>
<input type='date' class="form-control" id="date_debut" readonly >
</div>
<div class="form-group mb-2">
{% comment %} <div class="form-group mb-2">
<label>Date de fin :</label>
<input type='date' class="form-control" id="date_fin" readonly >
</div>
</div> {% endcomment %}
<div class="form-group mb-2">
<label>Heure de début :</label>
<input type='time' class="form-control" id="heure_debut" readonly>

View File

@@ -153,7 +153,7 @@ def detail_reservation(request:HttpRequest, reservation_id:int):
'employe': f"{employe.first_name} {employe.last_name}",
'salle': reservation.salle,
'statut': dict(Reservation.STATUT).get(reservation.statut),
'date_evenement': reservation.date_debut.strftime('%Y-%m-%d'),
'date_debut': reservation.date_debut.strftime('%Y-%m-%d'),
'heure_debut': reservation.heure_debut.strftime('%H:%M'),
'heure_fin': reservation.heure_fin.strftime('%H:%M'),
'motif_reservation': reservation.motif_reservation,