67 Commits

Author SHA1 Message Date
643205a4bb Premiere implementation de sso
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-08-04 09:34:31 +00:00
4934b42ed9 Implementation de sso 2026-07-29 10:26:22 +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
b03a4214c0 Bug: Validation des conges
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-11 15:33:04 +00:00
d4f4b7d954 Bug: Validation des conges
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-05-11 15:27:50 +00:00
489eeb439f Correction Bug : Validation 2026-05-11 14:46:59 +00:00
5277b7f355 Bug: Validation de reservation
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-11 13:20:13 +00:00
9d9e6c6549 Bug: Affichage de la lite des conges en fonction des profil
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-07 15:32:22 +00:00
784822478e feature: Affichage de la liste des bailleur 2026-05-07 15:28:52 +00:00
ab87baaa3a Bug: Affichage des details de la reservation 2026-05-07 15:28:42 +00:00
6026af5498 Bug : Affichages des conges 2026-05-07 15:23:47 +00:00
91bdd791f1 Bug : Affichage des demandes de conges 2026-05-07 15:11:25 +00:00
671072864d Bug: Details des reservations
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-07 14:44:16 +00:00
bb93a853db Gestion de l'envoie des mails
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-07 11:25:11 +00:00
99434a21e0 Fonctionnalite: verifier qu'aucun contrat n'est actif avant la creation d'un nouveau pour un employe
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-06 16:01:37 +00:00
f6b90e7dd0 Verification du statut avant la creation d'un contrat 2026-05-06 15:53:02 +00:00
fcfac71026 clean: remove pycache from tracking 2026-05-06 15:44:16 +00:00
34a261a4af Prise en charge de la photo de profil
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
2026-05-06 12:25:38 +00:00
f0e8b025a4 Prise en charge de la photo de profil
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-05-06 11:51:55 +00:00
62b2938c71 Prise en charge de la photo de profil
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-05-06 11:43:54 +00:00
06125b0900 Prise en charge de la photo de profil
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
2026-05-06 11:31:49 +00:00
0047b1f91c Ajout de la prise en charge des photos de profil 2026-05-06 08:50:49 +00:00
7ee14e7b3f clean: remove pycache from tracking 2026-05-06 08:42:28 +00:00
d12b014b20 feature: ajout photo de profil 2026-05-05 15:57:35 +00:00
d9b45ac364 Merge pull request 'Finalisation du Jenkinsfile' (#37) from finalisation into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #37
2026-05-04 13:45:46 +00:00
44faeac222 Finalisation du Jenkinsfile
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-05-04 13:44:41 +00:00
e1436e8f4e Merge pull request 'Deploiement automatique' (#36) from env2 into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #36
2026-05-04 13:16:38 +00:00
4ee7dd9fc7 Deploiement automatique
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-05-04 13:15:38 +00:00
a9e708c778 Merge pull request 'Ajout de dependance' (#35) from env2 into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #35
2026-05-04 13:04:03 +00:00
e427561cc1 Ajout de dependance
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-05-04 13:01:17 +00:00
78fafebc4d Merge pull request 'env1' (#34) from env1 into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #34
2026-05-04 12:39:23 +00:00
ecdaa9f9f9 Config des environnement
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-05-04 12:38:33 +00:00
9951719b26 Config env 2026-05-04 12:22:15 +00:00
1391a5ea3b Derniere modification du Jenkinsfile
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main This commit looks good
2026-05-04 09:58:34 +00:00
357b50dfa4 Merge pull request 'utilisation des credentials' (#32) from pipeline10 into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #32
2026-05-04 09:52:26 +00:00
bda80fae85 utilisation des credentials
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-05-04 09:51:25 +00:00
9c1eb543ff Merge pull request 'pipeline9' (#31) from pipeline9 into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #31
2026-04-30 16:07:01 +00:00
f55b1a6f2d pipeline9
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head This commit looks good
2026-04-30 16:06:21 +00:00
a6412341cf Merge pull request 'pipeline 8' (#30) from pipeline8 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #30
2026-04-30 15:59:17 +00:00
ab2d8b479c pipeline 8
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main This commit looks good
2026-04-30 15:57:54 +00:00
8f412cb031 Merge pull request 'pipeline 7' (#29) from pipeline7 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #29
2026-04-30 15:44:04 +00:00
69764b74a2 pipeline 7
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head Build started...
2026-04-30 15:43:00 +00:00
e1dc510af1 Merge pull request 'pipeline 6' (#28) from pipeline6 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #28
2026-04-30 15:28:19 +00:00
fa21850c6b pipeline 6
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-04-30 15:27:29 +00:00
4a8cbf02b9 Merge pull request 'pipeline 5' (#27) from pipeline5 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #27
2026-04-30 15:21:29 +00:00
798784a163 pipeline 5
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head This commit looks good
2026-04-30 15:21:02 +00:00
86ad99de76 Merge pull request 'pipeline 4' (#25) from pipeline4 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #25
2026-04-30 15:09:54 +00:00
5680677865 pipeline 4
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head Build started...
2026-04-30 15:09:22 +00:00
886c3246af Merge pull request 'pipeline3' (#24) from pipeline3 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #24
2026-04-30 15:03:16 +00:00
7b66250832 pipeline3
Some checks are pending
Organisation/sirh/pipeline/head This commit looks good
Organisation/sirh/pipeline/pr-main Build queued...
2026-04-30 15:01:54 +00:00
80b3573674 Merge pull request 'pipeline 2' (#23) from pipeline2 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #23
2026-04-30 14:56:41 +00:00
efadd66483 pipeline 2
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head Build started...
2026-04-30 14:56:06 +00:00
c9431063de Merge pull request 'Pipeline 1' (#22) from pipeline1 into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #22
2026-04-30 14:51:42 +00:00
15c33efc14 Pipeline 1
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Organisation/sirh/pipeline/pr-main Build queued...
2026-04-30 14:50:58 +00:00
5257901e75 Merge pull request 'Test pipeline' (#21) from jenkins_agent_exemple into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #21
2026-04-30 14:47:05 +00:00
b3294a823e Test pipeline
Some checks failed
Organisation/sirh/pipeline/pr-main There was a failure building this commit
2026-04-30 14:45:35 +00:00
2a182830a6 Merge pull request 'Ajout de l'agent' (#20) from jenkins_agent into main
All checks were successful
Organisation/sirh/pipeline/head This commit looks good
Reviewed-on: #20
2026-04-30 13:18:30 +00:00
14631c3744 Ajout de l'agent
Some checks are pending
Organisation/sirh/pipeline/pr-main Build queued...
Organisation/sirh/pipeline/head This commit looks good
2026-04-30 13:17:43 +00:00
f0894bb66f Merge pull request 'jenkins test 3' (#18) from jenkins into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #18
2026-04-30 13:12:06 +00:00
75285a140a jenkins test 3
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Organisation/sirh/pipeline/pr-main There was a failure building this commit
2026-04-30 13:11:14 +00:00
3cc8e292b3 Merge pull request 'renommage jenkinsfile' (#16) from test_jenkins into main
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Reviewed-on: #16
2026-04-30 13:02:50 +00:00
34d1464391 renommage jenkinsfile
Some checks failed
Organisation/sirh/pipeline/head There was a failure building this commit
Organisation/sirh/pipeline/pr-main There was a failure building this commit
2026-04-30 13:00:26 +00:00
6c12131fab Merge pull request 'Test jenkins 1' (#15) from test_jenkins into main
Reviewed-on: #15
2026-04-30 12:48:13 +00:00
19e4675f32 Test jenkins 1 2026-04-30 12:47:18 +00:00
b9f9de19f5 Merge pull request 'Ajout de type de contrat' (#6) from type_contrat into main
Reviewed-on: #6
Reviewed-by: Soriba Sylla <soribasyllakamsar@gmail.com>
2026-04-29 10:53:41 +00:00
6b977d5809 Ajout de type de contrat 2026-04-29 12:44:26 +02:00
252 changed files with 691 additions and 525 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
db.sqlite3
venv/
media/
staticfiles/
.env
migrations/
*.pyc

52
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,52 @@
pipeline
{
agent any
options {
// This is required if you want to clean before build
skipDefaultCheckout(true)
}
environment
{
SUDO_PASSWORD = credentials('sudo-password')
}
stages
{
stage ( 'checkout' )
{
steps
{
sh 'echo "Debut du pipeline"'
cleanWs()
checkout scm
}
}
stage ( 'Deploiement' )
{
when { branch 'main' }
steps {
sh '''
cd /var/www/sirh
echo $SUDO_PASSWORD | sudo -S chown -R jenkins:jenkins /var/www/sirh
git fetch origin main
git reset --hard origin/main
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
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
echo "Deploiement reussi"
echo $SUDO_PASSWORD | sudo -S supervisorctl restart sirh
'''
}
}
}
}

View File

@@ -12,21 +12,22 @@ https://docs.djangoproject.com/en/5.2/ref/settings/
import os
from pathlib import Path
from decouple import config
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure--wdb9t(77rvyac$_q!n5gw86&0r(0&&j171v9h!-_$jahsza*5'
SECRET_KEY = config('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
DEBUG = config('DEBUG', default=True, cast=bool)
ALLOWED_HOSTS = ["https://support.cerfig.org", "support.cerfig.org"]
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[]).split(',')
CSRF_TRUSTED_ORIGINS = config("CSRF_TRUSTED_ORIGINS", default=[]).split(",")
# Application definition
@@ -40,12 +41,9 @@ INSTALLED_APPS = [
'gestion_employe',
'gestion_conge',
'gestion_projet',
'gestion_salle',
'simple_sso.sso_server'
'gestion_salle'
]
LOGIN_URL = 'login'
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
@@ -79,18 +77,18 @@ WSGI_APPLICATION = 'SIRH.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = {
'default': {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'sirh',
'USER': 'sirh',
'PASSWORD': 'sirh-cerfig',
'HOST': 'localhost', # Or the server IP
'PORT': '3306', # Default MySQL port
'NAME': config("DB_NAME"),
'USER': config("DB_USER"),
'PASSWORD': config("DB_PASSWORD"),
'HOST': config("DB_HOST"),
'PORT': config("DB_PORT", cast=int),
}
}
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
@@ -142,11 +140,21 @@ MEDIA_ROOT = BASE_DIR / "media"
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
# Connexion sso
# 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_LOGOUT_URL = 'http://test-authentification.cerfig.org:89/deconnexion'
# Configuration de l'email
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'ssl0.ovh.net'
EMAIL_PORT = 465
EMAIL_USE_SSL = True
EMAIL_USE_TLS = False
EMAIL_HOST_USER = 'support.it@cerfig.org'
EMAIL_HOST_PASSWORD = 'Cerfig2025'
EMAIL_HOST_USER = config("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = config("EMAIL_HOST_PASSWORD")
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

33
SIRH/sso.py Normal file
View File

@@ -0,0 +1,33 @@
# SGL/sso.py
from gestion_employe.models import Employe, Departement
from simple_sso.sso_client.client import Client
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
User = get_user_model()
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")
user = super().build_user(user_data)
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", ""),
}
)
for group_name in user_data_copy.get("groups", []):
group, _ = Group.objects.get_or_create(name=group_name)
user.groups.add(group)
return user

View File

@@ -15,8 +15,9 @@
<body>
<div class="container-fluid">
<div class="row flex-nowrap">
{% include 'parts/menu_application.html' %}
{% include 'parts/menu_principal.html' %}
<div class="col-9 p-4">
<div class="col p-4">
{% block 'contenu' %} {% endblock %}
</div>
</div>

View File

@@ -24,15 +24,16 @@
{% endfor %}
{% endif %}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">
<div class="mb-3">
<label for="mail">Votre adresse email :</label>
<input type="text" name="mail" class="form-control" placeholder="Entrez votre e-mail" required>
<label for="mail">Votre adresse email :</label>
<input type="text" name="mail" class="form-control" placeholder="Entrez votre e-mail" required>
</div>
<div class="mb-3">
<label for="mot_de_passe">Mot de passe</label>
<input type="password" name="mot_de_passe" class="form-control" placeholder="Entrez votre mot de passe" required>
<i class="bi bi-eye toggle-password" onclick="togglePassword()"
style="position:absolute; right:10px; top:38px; cursor:pointer;"></i>
<label for="mot_de_passe">Mot de passe</label>
<input type="password" name="mot_de_passe" class="form-control" placeholder="Entrez votre mot de passe" required>
<i class="bi bi-eye toggle-password" onclick="togglePassword()"
style="position:absolute; right:10px; top:38px; cursor:pointer;"></i>
</div>
<button type="submit" class="btn btn-primary w-100">Se connecter</button>
</form>

View File

@@ -0,0 +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">
<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">
<i class="bi bi-building-gear fs-1 d-block"></i> SGL
</a>
</div>

View File

@@ -2,40 +2,47 @@
{% load tags_personnaliser %}
<div class="col-3 bg-danger d-flex flex-column vh-100 pt-5 sticky-top">
<a href="{% url 'gestion_employe:mon-profil' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<div class="text-center mb-4">
{% if user.employe.photo %}
<img src="{{ user.employe.photo.url }}"
class="rounded-circle"
width="100"
height="100"
style="object-fit:cover;">
{% else %}
<i class="bi bi-person-circle text-white" style="font-size:60px;"></i>
{% endif %}
<div class="text-white mt-2 fw-bold fs-5">
{{ user.first_name }} {{ user.last_name }}
</div>
</div>
<a href="{% url 'gestion_employe:mon-profil' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-person-circle"></i> Mon profil
</a>
{% if user|has_group:"ressource_humaine" or user|has_group:"direction" %}
<a href="{% url 'gestion_employe:index' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{% url 'gestion_employe:index' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-speedometer2"></i> Tableau de bord
</a>
{% endif %}
{% if user|has_group:"ressource_humaine" or user|has_group:"direction" %}
<a href="{% url 'gestion_projet:index' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{% url 'gestion_projet:index' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-folder"></i> Gestion des Projets
</a>
{% endif %}
<a href="{% url 'gestion_conges:conge' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{% url 'gestion_conges:conge' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-airplane"></i> Gestion des congés
</a>
{% if user|is_chef_projet %}
<a href="{% url 'gestion_projet:activites-projet' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{% url 'gestion_projet:activites-projet' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-list-task"></i> Suivi des Activités
</a>
{% endif %}
<a href="{% url 'gestion_salle:reservation-salle' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
<a href="{% url 'gestion_salle:reservation-salle' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size: 1.2em;">
<i class="bi bi-calendar-check"></i> Réservation
</a>
{% comment %} <a href="{% url 'rapport-rh' %}" class="text-white fw-bold text-decoration-none mb-2" style="font-size:1.2em">
<i class="bi bi-graph-up"></i> Rapports et Statistiques
</a> {% endcomment %}
{% comment %} <a href="" class="text-white fw-bold text-decoration-none mb-2" style="font-size:1.2em">
<i class="bi bi-person-gear"></i> Gestion des Utilisateurs
</a> {% endcomment %}
{% comment %} <a href="{% url 'gestion_employe:departement' %}" class="text-white fw-bold text-decoration-none mb-2" style="font-size:1.2em">
<i class="bi bi-gear"></i> Paramètres
</a> {% endcomment %}
<a href="{% url 'deconnexion' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
{% 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;">
<i class="bi bi-box-arrow-right"></i> Déconnexion
</a>
</div>
</div>

View File

@@ -16,32 +16,29 @@ Including another URLconf
"""
from django.contrib import admin
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 simple_sso.sso_server.server import Server
from . import views
from .sso import SIRHClient
# server_sso = Server()
client_sirh = SIRHClient(
settings.SSO_SERVER,
settings.SSO_PUBLIC_KEY,
settings.SSO_PRIVATE_KEY
)
urlpatterns = [
urlpatterns = [
# path('login/',
# views.login_view,
# name='login'
# ),
# path(
# 'deconnexion/',
# views.deconnexion_view,
# name='deconnexion'
# ),
path(
'',
views.login_view,
name='index'
),
path('login/',
views.login_view,
name='login'
),
path(
'deconnexion/',
views.deconnexion_view,
name='deconnexion'
),
path(
'employé/',
include("gestion_employe.urls")
),
path(
@@ -59,9 +56,7 @@ urlpatterns = [
path(
'admin/',
admin.site.urls
),
# path(
# 'sso',
# include(server_sso.get_urls())
# )
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
),
path("client/", include(client_sirh.get_urls())),
]
# + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -1,37 +0,0 @@
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect
from django.contrib import messages
def login_view(request):
"""
Gère la connexion des utilisateurs avec redirection selon le rôle et
vérification de l'acceptation de la politique d'utilisation.
"""
if request.method == 'POST':
email = request.POST.get('mail')
password = request.POST.get('mot_de_passe')
if not (email and password):
messages.error(request, "Veuillez remplir tous les champs.")
return render(request, 'login.html')
user = authenticate(request, username=email, password=password)
if user is None:
messages.error(request, "Nom dutilisateur ou mot de passe incorrect.")
return render(request, 'login.html')
if not user.is_active:
messages.error(request, "Compte inactif. Contactez l'administrateur.")
return render(request, 'login.html')
login(request, user)
return redirect("gestion_conges:conge")
return render(request, 'login.html')
def deconnexion_view(request):
"""Gère la déconnexion de l'utilisateur."""
logout(request)
return redirect('login')

View File

@@ -1,5 +1,5 @@
from django.utils import timezone
from gestion_employe.models import Contrat
from gestion_employe.models import Contrat, Employe
from gestion_conge.models import Conge
@@ -7,6 +7,7 @@ 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))
def solde_conge(employe):
"""Fonction de calcul du solde de congé restant l'employé"""
@@ -31,4 +32,26 @@ def solde_conge(employe):
"success": True,
"quota_annuel": QUOTA_CONGE_ANNUEL - jours_conges_valider,
"nombre_jours_valide": jours_conges_valider
}
}
def envoyer_mail(sujet, message, destinataires):
"""Fonction d'envoi de mail"""
from django.core.mail import send_mail
from django.conf import settings
send_mail(
sujet,
message,
settings.EMAIL_HOST_USER,
destinataires,
fail_silently=False,
)
def destinataire_mail_demande_conges(employe):
"""Fonction de récupération des destinataires pour les mails de demande de congés"""
if employe.chef:
return EMAIL_ASSISTANTE_DE_DIRECTION
else:
if employe.departement:
chefs_departement = Employe.objects.filter(departement=employe.departement, chef=True)
return list(chefs_departement.values_list('user__email', flat=True))

View File

@@ -1,4 +1,4 @@
# Generated by Django 5.2.13 on 2026-04-17 12:03
# Generated by Django 5.2.13 on 2026-06-16 11:06
import django.db.models.deletion
from django.db import migrations, models

View File

@@ -3,7 +3,7 @@ const $ = (element) => document.getElementById(element);
const url_liste_conge_attente = $("liste-demande-conges").dataset.url
const tableau_liste_demande_conge = new Tabulator("#liste-demande-conges", {
layout : "fitColumns",
// layout : "fitColumns",
columns: [
{"title": "Nom et Prénom", "field": "prenom_nom"},
{"title": "Date de début", "field": "date_debut", formatter:"datetime", formatterParams:{
@@ -15,7 +15,7 @@ const tableau_liste_demande_conge = new Tabulator("#liste-demande-conges", {
outputFormat:"dd/MM/yy",
}},
{"title": "Type de congé", "field": "type"},
{"title": "Date de la demande", "field": "date_demande"},
{"title": "Date de la demande", "field": "date_demande", responsive: 1},
{"title": "Validation par supérieur hiérarchique", "field": "validation_hierarchique", formatter:"tickCross", formatterParams :{
allowEmpty : true ,
}},
@@ -24,7 +24,7 @@ const tableau_liste_demande_conge = new Tabulator("#liste-demande-conges", {
}},
],
pagination: true,
paginationSize: 5
paginationSize: 5,
})
const bouton_demande_conges = $("bouton-demande-conge");

View File

@@ -7,6 +7,7 @@
<div class="alert alert-{% if message.tags == 'error' %}danger{% else %}success{% endif %}">{{message}}</div>
{% endfor %}
{% endif %}
<div class="row d-flex justify-content-center mb-4">
<div class="col text-white bg-danger d-flex flex-column justify-content-center align-items-center border rounded p-4">
<div class="card-header fw-bold">
@@ -32,11 +33,17 @@
<h5 class="fw-bold">{{ nombre_conges_valide }}</h5>
</div>
</div>
<div class="d-flex justify-content-between my-4">
</div>
<div class="row mb-3">
<div class="col d-flex justify-content-between align-items-center">
<h3><i class="bi bi-list-ul"></i> Liste des demandes de congé</h3>
<button class='btn btn-primary' id="bouton-demande-conge">Demande de congé</button>
</div>
<div class="table-responsive">
</div>
<div class="row">
<div class="col">
<div id="liste-demande-conges" data-url="{% url 'gestion_conges:liste-des-conges' %}"></div>
</div>
</div>

View File

@@ -83,7 +83,6 @@ def index(request):
Q(validation_hierarchique = True) | Q(validation_hierarchique = False)
).order_by('-date_demande')
return render(request, 'gestion_conge/index.html', {
"nombre_conges_valide": nombre_conges_valide,
"nombre_conges_refuse": nombre_conges_refuse,
@@ -123,72 +122,82 @@ def demander_conge(request):
conge_obj.save()
messages.success(request, "Votre demande de congé a été enregistrée.")
fonctions_utilitaire.envoyer_mail(
sujet = "Demande de congé",
message = f"""Bonjour {employe.user.first_name} {employe.user.last_name}, votre demande de congé a été enregistrée. Veuillez consulter votre profil pour plus de détails.""",
destinataires = fonctions_utilitaire.destinataire_mail_demande_conges() + [employe.user.email]
)
return redirect("gestion_conges:conge")
return redirect("gestion_conges:conge")
@login_required
def liste_demande_conges(request):
"""Vue de liste des demandes de congés en attente de validation selon le statut de l'utilisateur actuel"""
try:
employe = Employe.objects.get(user__username = request.user)
employe = Employe.objects.get(user=request.user)
except Employe.DoesNotExist:
return JsonResponse({
"success": False,
"message": "Votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'administrateur."
"message": "Profil employé introuvable"
})
try:
affectation = Affectation.objects.get(
employe=employe,
date_fin_daffectation__gte=timezone.now().date()
)
except Affectation.DoesNotExist:
affectation = None
affectation = Affectation.objects.filter(
employe=employe,
date_fin_daffectation__gte=timezone.now().date()
).first()
is_direction = employe.user.groups.filter(name='direction').exists()
if employe.chef:
print("chef")
conges_en_attente = Conge.objects.filter(
employe__departement = employe.departement,
validation_hierarchique = None
conges = Conge.objects.filter(
Q(employe__departement=employe.departement) |
Q(employe=employe)
).order_by('-date_demande')
elif affectation and affectation.role == "chef_projet":
employes_du_projet = Affectation.objects.filter(
projet = affectation.projet,
date_fin_daffectation__gte = timezone.now().date()
).values('employe')
projet=affectation.projet,
date_fin_daffectation__gte=timezone.now().date()
).values_list('employe', flat=True)
conges_en_attente = Conge.objects.filter(
employe__in = employes_du_projet,
validation_hierarchique = None
conges = Conge.objects.filter(
Q(employe__in=employes_du_projet) |
Q(employe=employe)
).order_by('-date_demande')
elif 'direction' in employe.user.groups.values_list('name', flat=True):
conges_en_attente = Conge.objects.filter(
validation_hierarchique = True,
validation_direction = None
).order_by('-date_demande')
elif is_direction:
conges = Conge.objects.filter(
Q(validation_hierarchique=True) |
Q(employe__user__groups__name='direction')
).distinct().order_by('-date_demande')
else:
conges_en_attente = Conge.objects.filter(
employe__user__username = request.user
conges = Conge.objects.filter(
employe=employe
).order_by('-date_demande')
return JsonResponse({
"success": True,
"data":[
{
**model_to_dict(conge),
"prenom_nom": f"{conge.employe.user.first_name} {conge.employe.user.last_name}",
"date_demande": conge.date_demande,
"nombre_jours": conge.nombre_jours,
"type": dict(conge.TYPE_CHOICES).get(conge.type),
"solde_conge": fonctions_utilitaire.solde_conge(conge.employe)["quota_annuel"]
}
for conge in conges_en_attente]},
safe=False
)
"data": [
{
**model_to_dict(conge),
"prenom_nom": f"{conge.employe.user.first_name} {conge.employe.user.last_name}",
"date_demande": conge.date_demande,
"nombre_jours": conge.nombre_jours,
"type": dict(conge.TYPE_CHOICES).get(conge.type),
"solde_conge": fonctions_utilitaire.solde_conge(conge.employe)["quota_annuel"]
}
for conge in conges
]
})
@login_required
def validation_de_conge(request):

Some files were not shown because too many files have changed in this diff Show More