Compare commits
11 Commits
643205a4bb
...
detail_res
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e81c29a586 | ||
|
|
d28bf85556 | ||
|
|
3b587d2a1a | ||
|
|
e3f0befff6 | ||
|
|
55e5a2819c | ||
|
|
7e28b25497 | ||
| f9ca539670 | |||
| 7b4778252f | |||
| 2c086187e7 | |||
| 5aff49600e | |||
| 8c6e59e15a |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -27,7 +27,7 @@ SECRET_KEY = config('SECRET_KEY')
|
|||||||
DEBUG = config('DEBUG', default=True, cast=bool)
|
DEBUG = config('DEBUG', default=True, cast=bool)
|
||||||
|
|
||||||
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[]).split(',')
|
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
|
# Application definition
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ TEMPLATES = [
|
|||||||
'django.template.context_processors.request',
|
'django.template.context_processors.request',
|
||||||
'django.contrib.auth.context_processors.auth',
|
'django.contrib.auth.context_processors.auth',
|
||||||
'django.contrib.messages.context_processors.messages',
|
'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 = '/client/'
|
||||||
LOGIN_URL = 'simple-sso-login'
|
LOGIN_URL = 'simple-sso-login'
|
||||||
|
|
||||||
SSO_PRIVATE_KEY = 'D2brFY3LnNDLQBBnvYPXAn185Wi9EpPvnHsUosjEZ9vZMyEtXqkcVfFWkVbN0xpG'
|
SSO_PRIVATE_KEY = config('SSO_PRIVATE_KEY')
|
||||||
SSO_PUBLIC_KEY = 'm9JDP3uGPmGG9ULqPw2BY3ryBNMTGRsuukgIOhk7lIN9lT0wlr2zhoRZiNZ28UCM'
|
SSO_PUBLIC_KEY = config('SSO_PUBLIC_KEY')
|
||||||
SSO_SERVER = 'http://test-authentification.cerfig.org:89/server/'
|
SSO_SERVER = config('SSO_SERVER')
|
||||||
#SSO_LOGOUT_URL = 'http://test-authentification.cerfig.org:89/deconnexion'
|
#SSO_LOGOUT_URL = 'http://test-authentification.cerfig.org:89/deconnexion'
|
||||||
|
|
||||||
# Configuration de l'email
|
# Configuration de l'email
|
||||||
|
|||||||
18
SIRH/sso.py
18
SIRH/sso.py
@@ -10,19 +10,25 @@ class SIRHClient(Client):
|
|||||||
def build_user(self, user_data):
|
def build_user(self, user_data):
|
||||||
"""Crée le User et son Profile avec les infos reçues du serveur."""
|
"""Crée le User et son Profile avec les infos reçues du serveur."""
|
||||||
user_data_copy = user_data.copy()
|
user_data_copy = user_data.copy()
|
||||||
user_data.pop("departement")
|
|
||||||
user_data.pop("chef_departement")
|
print("Un petit test", user_data_copy)
|
||||||
user_data.pop("groups")
|
|
||||||
|
user_data.pop("departement", None)
|
||||||
|
user_data.pop("chef_departement", None)
|
||||||
|
user_data.pop("groups", None)
|
||||||
|
|
||||||
user = super().build_user(user_data)
|
user = super().build_user(user_data)
|
||||||
departement = Departement.objects.get_or_create(
|
departement = None
|
||||||
nom=user_data_copy.get("departement", ""))[0]
|
|
||||||
|
if "departement" in user_data_copy:
|
||||||
|
departement = Departement.objects.get_or_create(
|
||||||
|
nom=user_data_copy.get("departement", ""))[0]
|
||||||
|
|
||||||
Employe.objects.update_or_create(
|
Employe.objects.update_or_create(
|
||||||
user = user,
|
user = user,
|
||||||
defaults = {
|
defaults = {
|
||||||
"departement": departement,
|
"departement": departement,
|
||||||
"chef": user_data_copy.get("chef_departement", ""),
|
"chef": user_data_copy.get("chef_departement", None),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<div class="col-1 bg-danger border d-flex flex-column vh-100 pt-5 sticky-top">
|
<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
|
<i class="bi bi-people-fill fs-1 d-block"></i>SIRH
|
||||||
</a>
|
</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
|
<i class="bi bi-building-gear fs-1 d-block"></i> SGL
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<i class="bi bi-calendar-check"></i> Réservation
|
<i class="bi bi-calendar-check"></i> Réservation
|
||||||
</a>
|
</a>
|
||||||
{% comment %} {% url 'deconnexion' %} {% endcomment %}
|
{% 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
|
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
20
SIRH/urls.py
20
SIRH/urls.py
@@ -18,7 +18,7 @@ from django.contrib import admin
|
|||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
# from django.conf.urls.static import static
|
# from django.conf.urls.static import static
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from . import views
|
||||||
from .sso import SIRHClient
|
from .sso import SIRHClient
|
||||||
|
|
||||||
client_sirh = SIRHClient(
|
client_sirh = SIRHClient(
|
||||||
@@ -28,15 +28,15 @@ client_sirh = SIRHClient(
|
|||||||
)
|
)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path('login/',
|
path('login/',
|
||||||
# views.login_view,
|
views.connexion,
|
||||||
# name='login'
|
name='login'
|
||||||
# ),
|
),
|
||||||
# path(
|
path(
|
||||||
# 'deconnexion/',
|
'deconnexion/',
|
||||||
# views.deconnexion_view,
|
views.deconnexion,
|
||||||
# name='deconnexion'
|
name='deconnexion'
|
||||||
# ),
|
),
|
||||||
path(
|
path(
|
||||||
'',
|
'',
|
||||||
include("gestion_employe.urls")
|
include("gestion_employe.urls")
|
||||||
|
|||||||
@@ -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
7
contexte_universel.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
from decouple import config
|
||||||
|
|
||||||
|
def contexte_universel(request):
|
||||||
|
return {
|
||||||
|
"SIRH_LIEN": config("SIRH_LIEN"),
|
||||||
|
"SGL_LIEN": config("SGL_LIEN")
|
||||||
|
}
|
||||||
Binary file not shown.
@@ -7,7 +7,11 @@ QUOTA_CONGE_ANNUEL = 30
|
|||||||
NOMBRE_PAGINATION = 8
|
NOMBRE_PAGINATION = 8
|
||||||
DEBUT_RAPPEL = 60
|
DEBUT_RAPPEL = 60
|
||||||
DUREE_FIN_CONTRAT = 90
|
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):
|
def solde_conge(employe):
|
||||||
"""Fonction de calcul du solde de congé restant l'employé"""
|
"""Fonction de calcul du solde de congé restant l'employé"""
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -18,29 +18,34 @@ const tableau_certificat = new Tabulator("#tableau-certificat", {
|
|||||||
})
|
})
|
||||||
const enregistrerProfil = $("enregistrerProfil");
|
const enregistrerProfil = $("enregistrerProfil");
|
||||||
|
|
||||||
enregistrerProfil.addEventListener("click", (e) => {
|
// enregistrerProfil.addEventListener("click", (e) => {
|
||||||
|
|
||||||
const url = $("information-personnelles").dataset.url;
|
// const url = $("information-personnelles").dataset.url;
|
||||||
const csrftoken = document.querySelector("[name='csrfmiddlewaretoken']").value;
|
// const csrftoken = document.querySelector("[name='csrfmiddlewaretoken']").value;
|
||||||
|
|
||||||
const formData = new FormData();
|
// const formData = new FormData();
|
||||||
|
|
||||||
formData.append("nom", $("nom").value);
|
// formData.append("nom", $("nom").value);
|
||||||
formData.append("prenom", $("prenom").value);
|
// formData.append("prenom", $("prenom").value);
|
||||||
formData.append("email", $("email").value);
|
// formData.append("email", $("email").value);
|
||||||
formData.append("telephone", $("telephone").value);
|
// formData.append("telephone", $("telephone").value);
|
||||||
formData.append("adresse", $("adresse").value);
|
// formData.append("adresse", $("adresse").value);
|
||||||
formData.append("sexe", $("sexe").value);
|
// formData.append("sexe", $("sexe").value);
|
||||||
formData.append("date_naissance", $("date_naissance").value);
|
// formData.append("date_naissance", $("date_naissance").value);
|
||||||
|
|
||||||
fetch(url, {
|
|
||||||
method: "POST",
|
// console.log("---------------------------------------------")
|
||||||
headers: {
|
// console.log("Données du formulaire:", url);
|
||||||
"X-CSRFToken": csrftoken
|
// console.log("Données du formulaire:", formData);
|
||||||
},
|
|
||||||
body: formData
|
// fetch(url, {
|
||||||
})
|
// method: "POST",
|
||||||
.then(response => response.json())
|
// headers: {
|
||||||
.then(data => alert(data.message))
|
// "X-CSRFToken": csrftoken
|
||||||
.catch(error => console.error("Erreur:", error));
|
// },
|
||||||
});
|
// body: formData
|
||||||
|
// })
|
||||||
|
// .then(response => response.json())
|
||||||
|
// .then(data => alert(data.message))
|
||||||
|
// .catch(error => console.error("Erreur:", error));
|
||||||
|
// });
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
<div id="collapseProfil" class="accordion-collapse" aria-labelledby="headingContrats" data-bs-parent="#accordionInformationEmploye">
|
<div id="collapseProfil" class="accordion-collapse" aria-labelledby="headingContrats" data-bs-parent="#accordionInformationEmploye">
|
||||||
<div class="accordion-body">
|
<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 %}
|
{% csrf_token %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
@@ -50,19 +50,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Matricule :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Nom :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Prénom :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Sexe :</label>
|
<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='h' {% if employe.sexe == 'h' %}selected{% endif %}>Homme</option>
|
||||||
<option value='f' {% if employe.sexe == 'f' %}selected{% endif %}>Femme</option>
|
<option value='f' {% if employe.sexe == 'f' %}selected{% endif %}>Femme</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -72,27 +72,27 @@
|
|||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Date de naissance :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Département :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Email :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Téléphone :</label>
|
<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>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Adresse :</label>
|
<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>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Binary file not shown.
@@ -20,6 +20,9 @@ from fonction_utilitaire import fonctions_utilitaire
|
|||||||
@login_required
|
@login_required
|
||||||
def index(request):
|
def index(request):
|
||||||
"""Vue d'index"""
|
"""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')
|
employes = Employe.objects.all().order_by('-user__date_joined')
|
||||||
nombre_employes = Employe.objects.count()
|
nombre_employes = Employe.objects.count()
|
||||||
nombre_cps = Contrat.objects.filter(type_contrat='contrat_prestation').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:
|
elif total_affectation + temps_nouveau > 100:
|
||||||
messages.warning(
|
messages.warning(
|
||||||
request,
|
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')
|
return redirect('gestion_employe:index')
|
||||||
|
|
||||||
@@ -191,25 +194,26 @@ def modifier_employer(request):
|
|||||||
except Employe.DoesNotExist:
|
except Employe.DoesNotExist:
|
||||||
return JsonResponse({"message": "Employé non trouvé."})
|
return JsonResponse({"message": "Employé non trouvé."})
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
data = json.loads(request.body)
|
|
||||||
user = User.objects.get(username=request.user)
|
user = User.objects.get(username=request.user)
|
||||||
user.last_name = data['nom']
|
user.last_name = request.POST['nom']
|
||||||
user.first_name = data['prenom']
|
user.first_name = request.POST['prenom']
|
||||||
user.email = data['email']
|
user.email = request.POST['email']
|
||||||
employe.telephone = data['telephone']
|
employe.telephone = request.POST['telephone']
|
||||||
employe.adresse = data['adresse']
|
employe.adresse = request.POST['adresse']
|
||||||
employe.sexe = data['sexe']
|
employe.sexe = request.POST['sexe']
|
||||||
if request.FILES.get("photo"):
|
if request.FILES.get("photo"):
|
||||||
employe.photo = request.FILES["photo"]
|
employe.photo = request.FILES["photo"]
|
||||||
if data['date_naissance']:
|
if request.POST['date_naissance']:
|
||||||
difference = relativedelta(timezone.now().date(), datetime.strptime(data['date_naissance'], "%Y-%m-%d").date())
|
difference = relativedelta(timezone.now().date(), datetime.strptime(request.POST['date_naissance'], "%Y-%m-%d").date())
|
||||||
if difference.years >= 18:
|
if difference.years >= 18:
|
||||||
employe.date_naissance = data['date_naissance']
|
employe.date_naissance = request.POST['date_naissance']
|
||||||
else:
|
else:
|
||||||
return JsonResponse({"message": "Veuillez entrez une date de naissance correcte."})
|
messages.error(request, "Veuillez entrez une date de naissance correcte.")
|
||||||
employe.save()
|
employe.save()
|
||||||
user.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):
|
def enregistrement_document(request):
|
||||||
"""Vue pour permettre à un utilisateur de télécharger et enregistrer des documents liés à son profil"""
|
"""Vue pour permettre à un utilisateur de télécharger et enregistrer des documents liés à son profil"""
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user