Compare commits
8 Commits
99434a21e0
...
messege_et
| Author | SHA1 | Date | |
|---|---|---|---|
| c1dc44d223 | |||
| cea67c7057 | |||
| 741519c341 | |||
| 48f069506a | |||
| 3693ef29f9 | |||
| c28b14fb98 | |||
| 29a93e9bfe | |||
| a97c233ddb |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -1,6 +1,10 @@
|
|||||||
|
# db.sqlite3
|
||||||
|
# venv/*
|
||||||
|
# media/*
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
venv/
|
venv/
|
||||||
media/
|
.env
|
||||||
staticfiles/
|
|
||||||
.env
|
|
||||||
migrations/
|
|
||||||
50
Jenkinsfile
vendored
50
Jenkinsfile
vendored
@@ -1,50 +0,0 @@
|
|||||||
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 chown -R www-data:www-data /var/www/sirh
|
|
||||||
echo "Deploiement reussi"
|
|
||||||
echo $SUDO_PASSWORD | sudo -S supervisorctl restart sirh
|
|
||||||
'''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -12,21 +12,21 @@ https://docs.djangoproject.com/en/5.2/ref/settings/
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from decouple import config
|
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = config('SECRET_KEY')
|
SECRET_KEY = 'django-insecure--wdb9t(77rvyac$_q!n5gw86&0r(0&&j171v9h!-_$jahsza*5'
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = config('DEBUG', default=False, cast=bool)
|
DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default=[]).split(',')
|
ALLOWED_HOSTS = ["https://support.cerfig.org", "support.cerfig.org"]
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
@@ -79,25 +79,24 @@ WSGI_APPLICATION = 'SIRH.wsgi.application'
|
|||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
|
||||||
|
|
||||||
|
# DATABASES = {
|
||||||
|
# 'default': {
|
||||||
|
# 'ENGINE': 'django.db.backends.mysql',
|
||||||
|
# 'NAME': 'sirh',
|
||||||
|
# 'USER': 'sirh',
|
||||||
|
# 'PASSWORD': 'sirh-cerfig',
|
||||||
|
# 'HOST': 'localhost',
|
||||||
|
# 'PORT': '3306',
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
if config('ENVIRONMENT') == 'local':
|
DATABASES = {
|
||||||
DATABASES = {
|
'default': {
|
||||||
'default': {
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
DATABASES = {
|
|
||||||
'default': {
|
|
||||||
'ENGINE': 'django.db.backends.mysql',
|
|
||||||
'NAME': config('DATABASE_NAME'),
|
|
||||||
'USER': config('DATABASE_USER'),
|
|
||||||
'PASSWORD': config('DATABASE_PASSWORD'),
|
|
||||||
'HOST': config('DATABASE_HOST'),
|
|
||||||
'PORT': config('DATABASE_PORT'),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
|
||||||
|
|||||||
@@ -6,13 +6,13 @@
|
|||||||
{% if user.employe.photo %}
|
{% if user.employe.photo %}
|
||||||
<img src="{{ user.employe.photo.url }}"
|
<img src="{{ user.employe.photo.url }}"
|
||||||
class="rounded-circle"
|
class="rounded-circle"
|
||||||
width="100"
|
width="80"
|
||||||
height="100"
|
height="80"
|
||||||
style="object-fit:cover;">
|
style="object-fit:cover;">
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="bi bi-person-circle text-white" style="font-size:60px;"></i>
|
<i class="bi bi-person-circle text-white" style="font-size:60px;"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="text-white mt-2 fw-bold fs-5">
|
<div class="text-white mt-2">
|
||||||
{{ user.username }}
|
{{ user.username }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,6 +41,15 @@
|
|||||||
<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.4em">
|
||||||
<i class="bi bi-calendar-check"></i> Réservation
|
<i class="bi bi-calendar-check"></i> Réservation
|
||||||
</a>
|
</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">
|
<a href="{% url 'deconnexion' %}" class="text-white fw-bold text-decoration-none mb-4" style="font-size:1.4em">
|
||||||
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
<i class="bi bi-box-arrow-right"></i> Déconnexion
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
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.
@@ -129,66 +129,69 @@ def demander_conge(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def liste_demande_conges(request):
|
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:
|
try:
|
||||||
employe = Employe.objects.get(user__username = request.user)
|
employe = Employe.objects.get(user=request.user)
|
||||||
except Employe.DoesNotExist:
|
except Employe.DoesNotExist:
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"success": False,
|
"success": False,
|
||||||
"message": "Votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'administrateur."
|
"message": "Profil employé introuvable"
|
||||||
})
|
})
|
||||||
|
|
||||||
try:
|
affectation = Affectation.objects.filter(
|
||||||
affectation = Affectation.objects.get(
|
employe=employe,
|
||||||
employe=employe,
|
date_fin_daffectation__gte=timezone.now().date()
|
||||||
date_fin_daffectation__gte=timezone.now().date()
|
).first()
|
||||||
)
|
|
||||||
except Affectation.DoesNotExist:
|
is_direction = employe.user.groups.filter(name='direction').exists()
|
||||||
affectation = None
|
|
||||||
|
|
||||||
if employe.chef:
|
if employe.chef:
|
||||||
print("chef")
|
|
||||||
conges_en_attente = Conge.objects.filter(
|
conges = Conge.objects.filter(
|
||||||
employe__departement = employe.departement,
|
Q(employe__departement=employe.departement) |
|
||||||
validation_hierarchique = None
|
Q(employe=employe)
|
||||||
).order_by('-date_demande')
|
).order_by('-date_demande')
|
||||||
|
|
||||||
elif affectation and affectation.role == "chef_projet":
|
elif affectation and affectation.role == "chef_projet":
|
||||||
|
|
||||||
employes_du_projet = Affectation.objects.filter(
|
employes_du_projet = Affectation.objects.filter(
|
||||||
projet = affectation.projet,
|
projet=affectation.projet,
|
||||||
date_fin_daffectation__gte = timezone.now().date()
|
date_fin_daffectation__gte=timezone.now().date()
|
||||||
).values('employe')
|
).values_list('employe', flat=True)
|
||||||
|
|
||||||
conges_en_attente = Conge.objects.filter(
|
conges = Conge.objects.filter(
|
||||||
employe__in = employes_du_projet,
|
Q(employe__in=employes_du_projet) |
|
||||||
validation_hierarchique = None
|
Q(employe=employe)
|
||||||
).order_by('-date_demande')
|
).order_by('-date_demande')
|
||||||
|
|
||||||
elif 'direction' in employe.user.groups.values_list('name', flat=True):
|
|
||||||
conges_en_attente = Conge.objects.filter(
|
elif is_direction:
|
||||||
validation_hierarchique = True,
|
|
||||||
validation_direction = None
|
conges = Conge.objects.filter(
|
||||||
).order_by('-date_demande')
|
Q(validation_hierarchique=True) |
|
||||||
|
Q(employe__user__groups__name='direction')
|
||||||
|
).distinct().order_by('-date_demande')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
conges_en_attente = Conge.objects.filter(
|
|
||||||
employe__user__username = request.user
|
conges = Conge.objects.filter(
|
||||||
|
employe=employe
|
||||||
).order_by('-date_demande')
|
).order_by('-date_demande')
|
||||||
|
|
||||||
return JsonResponse({
|
return JsonResponse({
|
||||||
"success": True,
|
"success": True,
|
||||||
"data":[
|
"data": [
|
||||||
{
|
{
|
||||||
**model_to_dict(conge),
|
**model_to_dict(conge),
|
||||||
"prenom_nom": f"{conge.employe.user.first_name} {conge.employe.user.last_name}",
|
"prenom_nom": f"{conge.employe.user.first_name} {conge.employe.user.last_name}",
|
||||||
"date_demande": conge.date_demande,
|
"date_demande": conge.date_demande,
|
||||||
"nombre_jours": conge.nombre_jours,
|
"nombre_jours": conge.nombre_jours,
|
||||||
"type": dict(conge.TYPE_CHOICES).get(conge.type),
|
"type": dict(conge.TYPE_CHOICES).get(conge.type),
|
||||||
"solde_conge": fonctions_utilitaire.solde_conge(conge.employe)["quota_annuel"]
|
"solde_conge": fonctions_utilitaire.solde_conge(conge.employe)["quota_annuel"]
|
||||||
}
|
}
|
||||||
for conge in conges_en_attente]},
|
for conge in conges
|
||||||
safe=False
|
]
|
||||||
)
|
})
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def validation_de_conge(request):
|
def validation_de_conge(request):
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -15,7 +15,6 @@ class Employe(models.Model):
|
|||||||
FONCTION_LISTE = [
|
FONCTION_LISTE = [
|
||||||
('directeur', 'Directeur'),
|
('directeur', 'Directeur'),
|
||||||
('assistant_direction', 'Assistante de direction'),
|
('assistant_direction', 'Assistante de direction'),
|
||||||
('assistant_technique_recherche', 'Assistant technique de recherche'),
|
|
||||||
('comptable', 'Comptable'),
|
('comptable', 'Comptable'),
|
||||||
('raf', 'RAF'),
|
('raf', 'RAF'),
|
||||||
('data_manager', 'Data Manager'),
|
('data_manager', 'Data Manager'),
|
||||||
|
|||||||
@@ -19,12 +19,13 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if not expiration_contrat %}
|
{% if not has_contrat %}
|
||||||
<div class="alert alert-danger fade show alert-dismissible mt-2">
|
<div class="alert alert-danger mt-2">
|
||||||
<strong>Important :</strong> Les informations sur votre contrat n'ont pas été renseignées, veuillez contacter les ressources humaines.
|
<strong>Important :</strong> Les informations sur votre contrat n'ont pas été renseignées, veuillez contacter les ressources humaines.
|
||||||
</div>
|
</div>
|
||||||
{% elif contrat_nb_jours_restant %}
|
|
||||||
<div class="alert alert-danger fade show alert-dismissible mt-2">
|
{% elif expiration_contrat %}
|
||||||
|
<div class="alert alert-warning mt-2">
|
||||||
<strong>Important :</strong> Votre contrat de travail expire dans {{ contrat_nb_jours_restant }} jours, veuillez contacter les ressources humaines.
|
<strong>Important :</strong> Votre contrat de travail expire dans {{ contrat_nb_jours_restant }} jours, veuillez contacter les ressources humaines.
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -42,7 +43,7 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Photo</label>
|
<label>photo</label>
|
||||||
{% if employe.photo %}
|
{% if employe.photo %}
|
||||||
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
|
<span>Fichier actuel : <a href="{{ employe.photo.url }}">{{employe.photo}}</a></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
Binary file not shown.
@@ -79,6 +79,21 @@ urlpatterns = [
|
|||||||
views.modifier_mot_passe,
|
views.modifier_mot_passe,
|
||||||
name='modifier-mot-passe'
|
name='modifier-mot-passe'
|
||||||
),
|
),
|
||||||
|
# path(
|
||||||
|
# 'creation-departement/',
|
||||||
|
# views.creation_departement,
|
||||||
|
# name='creation-departement'
|
||||||
|
# ),
|
||||||
|
# path(
|
||||||
|
# 'modifier-departement/',
|
||||||
|
# views.modifier_departement,
|
||||||
|
# name='modifier-departement'
|
||||||
|
# ),
|
||||||
|
# path(
|
||||||
|
# 'suppression-departement/',
|
||||||
|
# views.supprimer_departement,
|
||||||
|
# name='suppression-departement/'
|
||||||
|
# ),
|
||||||
path(
|
path(
|
||||||
"liste-contrat-expirants",
|
"liste-contrat-expirants",
|
||||||
views.liste_contrat_expirants,
|
views.liste_contrat_expirants,
|
||||||
|
|||||||
@@ -122,26 +122,41 @@ def mon_profil(request):
|
|||||||
try:
|
try:
|
||||||
employe = Employe.objects.get(user__username=request.user)
|
employe = Employe.objects.get(user__username=request.user)
|
||||||
except Employe.DoesNotExist:
|
except Employe.DoesNotExist:
|
||||||
messages.error(request, "Impossible d'acceder au menu 'Mon profil' car votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'Administrateur.")
|
messages.error(
|
||||||
|
request,
|
||||||
|
"Impossible d'acceder au menu 'Mon profil' car votre profil Utilisateur n'est lié à aucun profil Employé. Veuillez contacter l'Administrateur."
|
||||||
|
)
|
||||||
return redirect("gestion_conges:conge")
|
return redirect("gestion_conges:conge")
|
||||||
|
|
||||||
contrats = Contrat.objects.filter(employe=employe, statut='actif').first()
|
contrats = Contrat.objects.filter(employe=employe, statut='actif').first()
|
||||||
|
|
||||||
projets = Affectation.objects.filter(
|
projets = Affectation.objects.filter(
|
||||||
employe = employe,
|
employe=employe,
|
||||||
date_fin_daffectation__gte = timezone.now().date()
|
date_fin_daffectation__gte=timezone.now().date()
|
||||||
).select_related('projet')
|
).select_related('projet')
|
||||||
|
|
||||||
|
has_contrat = contrats is not None
|
||||||
|
expiration_contrat = False
|
||||||
|
contrat_nb_jours_restant = None
|
||||||
|
|
||||||
|
if contrats:
|
||||||
|
nb_jours = contrats.nombre_jours_restant
|
||||||
|
contrat_nb_jours_restant = nb_jours
|
||||||
|
expiration_contrat = nb_jours <= fonctions_utilitaire.DUREE_FIN_CONTRAT
|
||||||
|
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
'gestion_employe/monprofil.html',
|
'gestion_employe/monprofil.html',
|
||||||
{
|
{
|
||||||
'employe': employe,
|
'employe': employe,
|
||||||
|
|
||||||
'contrats': [{
|
'contrats': [{
|
||||||
**model_to_dict(contrats),
|
**model_to_dict(contrats),
|
||||||
"type_contrat": dict(Contrat.TYPE_CONTRAT).get(contrats.type_contrat),
|
"type_contrat": dict(Contrat.TYPE_CONTRAT).get(contrats.type_contrat),
|
||||||
"statut": dict(Contrat.STATUT_CONTRAT).get(contrats.statut),
|
"statut": dict(Contrat.STATUT_CONTRAT).get(contrats.statut),
|
||||||
"fichier_contrat": contrats.fichier_contrat.url if contrats.fichier_contrat else "",
|
"fichier_contrat": contrats.fichier_contrat.url if contrats.fichier_contrat else "",
|
||||||
} if contrats else []],
|
}] if contrats else [],
|
||||||
|
|
||||||
'projets': [
|
'projets': [
|
||||||
{
|
{
|
||||||
**model_to_dict(a.projet),
|
**model_to_dict(a.projet),
|
||||||
@@ -151,12 +166,13 @@ def mon_profil(request):
|
|||||||
"pourcentage_temps_affectation": a.pourcentage_temps_affectation
|
"pourcentage_temps_affectation": a.pourcentage_temps_affectation
|
||||||
} for a in projets
|
} for a in projets
|
||||||
],
|
],
|
||||||
|
|
||||||
"formation_form": FormationForm(),
|
"formation_form": FormationForm(),
|
||||||
"expiration_contrat": contrats.nombre_jours_restant <= fonctions_utilitaire.DUREE_FIN_CONTRAT if contrats else False,
|
"has_contrat": has_contrat,
|
||||||
"contrat_nb_jours_restant": contrats.nombre_jours_restant if contrats else None
|
"expiration_contrat": expiration_contrat,
|
||||||
|
"contrat_nb_jours_restant": contrat_nb_jours_restant
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def modifier_mot_passe(request):
|
def modifier_mot_passe(request):
|
||||||
"""Vue pour permettre à un utilisateur de modifier son mot de passe et ses informations de profil"""
|
"""Vue pour permettre à un utilisateur de modifier son mot de passe et ses informations de profil"""
|
||||||
@@ -176,7 +192,6 @@ def modifier_mot_passe(request):
|
|||||||
messages.success(request, "Mot de passe modifié avec succès.")
|
messages.success(request, "Mot de passe modifié avec succès.")
|
||||||
|
|
||||||
return redirect("gestion_employe:mon-profil")
|
return redirect("gestion_employe:mon-profil")
|
||||||
|
|
||||||
def modifier_employer(request):
|
def modifier_employer(request):
|
||||||
"""Vue pour permettre à un utilisateur de modifier les informations d'un employé"""
|
"""Vue pour permettre à un utilisateur de modifier les informations d'un employé"""
|
||||||
try:
|
try:
|
||||||
@@ -205,19 +220,13 @@ def modifier_employer(request):
|
|||||||
return JsonResponse({"message": "Profil mis à jour avec succès."})
|
return JsonResponse({"message": "Profil mis à jour avec succès."})
|
||||||
|
|
||||||
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"""
|
|
||||||
employe = Employe.objects.get(user=request.user)
|
employe = Employe.objects.get(user=request.user)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if request.FILES.get("photo"):
|
if request.FILES.get("photo"):employe.photo = request.FILES["photo"]
|
||||||
employe.photo = request.FILES["photo"]
|
if "cv" in request.FILES:employe.CV = request.FILES["cv"]
|
||||||
if "cv" in request.FILES:
|
if "diplome" in request.FILES: employe.diplome = request.FILES["diplome"]
|
||||||
employe.CV = request.FILES["cv"]
|
if "rib" in request.FILES: employe.rib = request.FILES["rib"]
|
||||||
if "diplome" in request.FILES:
|
if "casier_judiciaire" in request.FILES:employe.casier_judiciaire = request.FILES["casier_judiciaire"]
|
||||||
employe.diplome = request.FILES["diplome"]
|
|
||||||
if "rib" in request.FILES:
|
|
||||||
employe.rib = request.FILES["rib"]
|
|
||||||
if "casier_judiciaire" in request.FILES:
|
|
||||||
employe.casier_judiciaire = request.FILES["casier_judiciaire"]
|
|
||||||
employe.save()
|
employe.save()
|
||||||
messages.success(request, "Documents enregistrés avec succès.")
|
messages.success(request, "Documents enregistrés avec succès.")
|
||||||
|
|
||||||
@@ -429,3 +438,41 @@ def supprimer_formation(request, id_formation):
|
|||||||
formation.delete()
|
formation.delete()
|
||||||
messages.success(request, "Formation supprimée ")
|
messages.success(request, "Formation supprimée ")
|
||||||
return redirect("mes_formations")
|
return redirect("mes_formations")
|
||||||
|
|
||||||
|
# @login_required
|
||||||
|
# def creation_departement(request):
|
||||||
|
# """Gère la création d'un nouveau département via un formulaire."""
|
||||||
|
# if request.method == 'POST':
|
||||||
|
# form_departement = DepartementForm(request.POST)
|
||||||
|
# if form_departement.is_valid():
|
||||||
|
# form_departement.save()
|
||||||
|
# messages.success(request, "Département ajouté avec succès.")
|
||||||
|
# else:
|
||||||
|
# messages.error(request, "Erreur lors de l'ajout du département.")
|
||||||
|
# return redirect('parametres-rh')
|
||||||
|
|
||||||
|
# @login_required
|
||||||
|
# def modifier_departement(request, id):
|
||||||
|
# """Gère la modification d'un département existant via un formulaire pré-rempli."""
|
||||||
|
# departement = Departement.objects.get(id=id)
|
||||||
|
# form = DepartementForm(instance=departement)
|
||||||
|
# if request.method == 'POST':
|
||||||
|
# nouveau_nom_departement = request.POST.get('nom')
|
||||||
|
# if nouveau_nom_departement:
|
||||||
|
# departement.nom = nouveau_nom_departement
|
||||||
|
# departement.save()
|
||||||
|
# messages.success(request, "Département modifié avec succès.")
|
||||||
|
# return redirect('parametres-rh')
|
||||||
|
# return render(request, 'gestion_employe/edit_departement.html', {
|
||||||
|
# 'form': form,
|
||||||
|
# 'departement': departement
|
||||||
|
# })
|
||||||
|
|
||||||
|
# @login_required
|
||||||
|
# def supprimer_departement(request, id):
|
||||||
|
# """Gère la suppression d'un département existant."""
|
||||||
|
# if request.method == "POST":
|
||||||
|
# departement = Departement.objects.get(id=id)
|
||||||
|
# departement.delete()
|
||||||
|
# messages.success(request, "Département supprimé avec succès !")
|
||||||
|
# return redirect('parametres-rh')
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
const btnEnregistrerBailleur = document.getElementById('btnEnregistrerBailleur');
|
const btnEnregistrerBailleur = document.getElementById('btnEnregistrerBailleur');
|
||||||
|
let table;
|
||||||
|
|
||||||
btnEnregistrerBailleur.addEventListener('click', function() {
|
btnEnregistrerBailleur.addEventListener('click', function() {
|
||||||
const form = document.getElementById('formBailleur');
|
const form = document.getElementById('formBailleur');
|
||||||
@@ -20,4 +21,31 @@ btnEnregistrerBailleur.addEventListener('click', function() {
|
|||||||
alert('Ce bailleur existe déjà dans la base de données.');
|
alert('Ce bailleur existe déjà dans la base de données.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
|
||||||
|
table = new Tabulator("#table-bailleurs", {
|
||||||
|
ajaxURL: "/gestion-projet/bailleurs/",
|
||||||
|
layout: "fitColumns",
|
||||||
|
pagination: "local",
|
||||||
|
paginationSize: 5,
|
||||||
|
|
||||||
|
columns: [
|
||||||
|
{title: "#", formatter: "rownum", width: 60},
|
||||||
|
{title: "Organisme", field: "nom_organisme"},
|
||||||
|
{title: "Contact", field: "contact"},
|
||||||
|
{title: "Email", field: "email"},
|
||||||
|
{title: "Pays", field: "pays"},
|
||||||
|
],
|
||||||
|
rowDblClick: function(e, row) {
|
||||||
|
const data = row.getData();
|
||||||
|
|
||||||
|
if (confirm(`Voulez-vous vraiment supprimer ${data.nom_organisme} ?`)) {
|
||||||
|
supprimerBailleur(data.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,51 @@
|
|||||||
<div class="modal fade" id="modalBailleur" tabindex="-1" aria-labelledby="modalBailleurLabel" aria-hidden="true">
|
<div class="modal fade" id="modalBailleur" tabindex="-1" aria-labelledby="modalBailleurLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog ">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="modalBailleurLabel">Ajouter un Bailleur</h5>
|
<h5 class="modal-title" id="modalBailleurLabel">Gestion des Bailleurs</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-4">
|
<ul class="nav nav-tabs px-3 pt-2" id="bailleurTab" role="tablist">
|
||||||
<form id="formBailleur" method="POST" action="{% url 'gestion_projet:creation-bailleur' %}">
|
<li class="nav-item" role="presentation">
|
||||||
{% csrf_token %}
|
<button class="nav-link active" id="ajouter-tab" data-bs-toggle="tab"
|
||||||
{{ form_ajout_bailleur.as_p }}
|
data-bs-target="#ajouter" type="button" role="tab">
|
||||||
</form>
|
Ajouter
|
||||||
</div>
|
</button>
|
||||||
<div class="modal-footer">
|
</li>
|
||||||
<button type="submit" id="btnEnregistrerBailleur" class="btn btn-success"><i class="bi bi-save me-1"></i> Enregistrer</button>
|
<li class="nav-item" role="presentation">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
<button class="nav-link" id="liste-tab" data-bs-toggle="tab"
|
||||||
|
data-bs-target="#liste" type="button" role="tab">
|
||||||
|
Liste
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="tab-content pt-3">
|
||||||
|
<div class="tab-pane fade show active" id="ajouter" role="tabpanel">
|
||||||
|
<form id="formBailleur" method="POST" action="{% url 'gestion_projet:creation-bailleur' %}">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ form_ajout_bailleur.as_p }}
|
||||||
|
<button type="submit" class="btn btn-success mt-3" id="btnEnregistrerBailleur">
|
||||||
|
<i class="bi bi-save me-1"></i> Enregistrer
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="liste" role="tabpanel">
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h6 class="mb-0">Liste des bailleurs</h6>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div id="table-bailleurs"
|
||||||
|
data-url="{% url 'gestion_projet:liste-bailleurs' %}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ urlpatterns = [
|
|||||||
views.creation_projet,
|
views.creation_projet,
|
||||||
name='creation-projet'
|
name='creation-projet'
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
'bailleurs/',
|
||||||
|
views.liste_bailleur,
|
||||||
|
name='liste-bailleurs'
|
||||||
|
),
|
||||||
|
|
||||||
path(
|
path(
|
||||||
'projet/modifier/<int:projet_id>/',
|
'projet/modifier/<int:projet_id>/',
|
||||||
views.modification_projet,
|
views.modification_projet,
|
||||||
@@ -84,6 +90,7 @@ urlpatterns = [
|
|||||||
views.liste_activites_projet,
|
views.liste_activites_projet,
|
||||||
name='liste-activites-projet'
|
name='liste-activites-projet'
|
||||||
),
|
),
|
||||||
|
|
||||||
# path(
|
# path(
|
||||||
# 'projet/ajout-de-document/',
|
# 'projet/ajout-de-document/',
|
||||||
# views.ajouter_document_projet,
|
# views.ajouter_document_projet,
|
||||||
@@ -119,4 +126,6 @@ urlpatterns = [
|
|||||||
views.mises_a_jour_projet,
|
views.mises_a_jour_projet,
|
||||||
name='mises-a-jour-projet'
|
name='mises-a-jour-projet'
|
||||||
)
|
)
|
||||||
]
|
|
||||||
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from datetime import date
|
|||||||
from decimal import Decimal, InvalidOperation
|
from decimal import Decimal, InvalidOperation
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.shortcuts import redirect, render
|
from django.shortcuts import redirect, render
|
||||||
|
from django.urls import reverse
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
@@ -143,6 +144,22 @@ def creation_bailleur(request):
|
|||||||
return JsonResponse({'success': True})
|
return JsonResponse({'success': True})
|
||||||
return JsonResponse({'success': False})
|
return JsonResponse({'success': False})
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def liste_bailleur(request):
|
||||||
|
""" Vue pour retourner la liste de tous les bailleurs """
|
||||||
|
bailleurs = Bailleur.objects.all().order_by('-id')
|
||||||
|
data = []
|
||||||
|
for b in bailleurs:
|
||||||
|
data.append({
|
||||||
|
"id": b.id,
|
||||||
|
"nom_organisme": b.nom_organisme,
|
||||||
|
"contact": b.contact,
|
||||||
|
"email": b.email,
|
||||||
|
"pays": b.pays,
|
||||||
|
})
|
||||||
|
return JsonResponse(data, safe=False)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def ajouter_financement_projet(request):
|
def ajouter_financement_projet(request):
|
||||||
"""Ajoute un financement à un projet en vérifiant que le total ne dépasse pas 100%"""
|
"""Ajoute un financement à un projet en vérifiant que le total ne dépasse pas 100%"""
|
||||||
@@ -318,6 +335,7 @@ def activites_projet(request):
|
|||||||
}
|
}
|
||||||
return render(request, 'gestion_projet/suivi_activite.html', context)
|
return render(request, 'gestion_projet/suivi_activite.html', context)
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def ajouter_activite_projet(request):
|
def ajouter_activite_projet(request):
|
||||||
"""Vue pour ajouter une activité à un projet spécifique via un formulaire"""
|
"""Vue pour ajouter une activité à un projet spécifique via un formulaire"""
|
||||||
|
|||||||
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.
@@ -167,9 +167,9 @@ tableau_reservation_attente.on("rowClick", (row, rowData) => {
|
|||||||
$("lien_zoom_container").className = 'd-none';
|
$("lien_zoom_container").className = 'd-none';
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.statut !== "refusee"){
|
// if(data.statut !== "refusee"){
|
||||||
$("motif_refus_container").className = 'd-none';
|
// $("motif_refus_container").className = 'd-none';
|
||||||
}
|
// }
|
||||||
|
|
||||||
$("id_reservation_detail").value = data.id;
|
$("id_reservation_detail").value = data.id;
|
||||||
$("id_reservation_refus").value = data.id;
|
$("id_reservation_refus").value = data.id;
|
||||||
@@ -178,14 +178,15 @@ tableau_reservation_attente.on("rowClick", (row, rowData) => {
|
|||||||
$("employe").value=data.employe;
|
$("employe").value=data.employe;
|
||||||
$("salle").value=data.salle;
|
$("salle").value=data.salle;
|
||||||
$("statut-reservation").innerHTML=data.statut;
|
$("statut-reservation").innerHTML=data.statut;
|
||||||
$("date_evenement").value=data.date_debut;
|
$("date_debut").value = data.date_debut;
|
||||||
|
$("date_fin").value = data.date_fin;
|
||||||
$("heure_debut").value=data.heure_debut;
|
$("heure_debut").value=data.heure_debut;
|
||||||
$("heure_fin").value=data.heure_fin;
|
$("heure_fin").value=data.heure_fin;
|
||||||
$("motif_reservation").value=data.motif_reservation;
|
$("motif_reservation").value=data.motif_reservation;
|
||||||
$("besoin_zoom").checked=data.besoin_zoom;
|
$("besoin_zoom").checked=data.besoin_zoom;
|
||||||
$("besoin_ordinateur").checked=data.besoin_ordi;
|
$("besoin_ordinateur").checked=data.besoin_ordi;
|
||||||
$("lien_zoom").value=data.lien_zoom;
|
$("lien_zoom").value=data.lien_zoom;
|
||||||
$("motif_refus").value=data.motif_refus;
|
// $("motif_refus").value=data.motif_refus;
|
||||||
|
|
||||||
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
||||||
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
||||||
|
|||||||
@@ -21,8 +21,12 @@
|
|||||||
<input class="form-control" id="salle" readonly>
|
<input class="form-control" id="salle" readonly>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Date de l'évènement :</label>
|
<label>Date de debut :</label>
|
||||||
<input type='date' class="form-control" id="date_evenement" readonly >
|
<input type='date' class="form-control" id="date_debut" readonly >
|
||||||
|
</div>
|
||||||
|
<div class="form-group mb-2">
|
||||||
|
<label>Date de fin :</label>
|
||||||
|
<input type='date' class="form-control" id="date_fin" readonly >
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-2">
|
<div class="form-group mb-2">
|
||||||
<label>Heure de début :</label>
|
<label>Heure de début :</label>
|
||||||
@@ -48,24 +52,19 @@
|
|||||||
<label label="form-check-label">Besoin d'un ordinateur</label>
|
<label label="form-check-label">Besoin d'un ordinateur</label>
|
||||||
<input type="checkbox" class="form-check-input" id="besoin_ordinateur" readonly >
|
<input type="checkbox" class="form-check-input" id="besoin_ordinateur" readonly >
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mb-2" id='motif_refus_container'>
|
|
||||||
<label>Motif de refus de la reservation :</label>
|
|
||||||
<textarea class="form-control" id="motif_refus" readonly></textarea>
|
|
||||||
</div>
|
|
||||||
<div class='d-flex justify-content-around mt-2'>
|
<div class='d-flex justify-content-around mt-2'>
|
||||||
{% if appartient_au_departement_informatique %}
|
{% if appartient_au_departement_informatique %}
|
||||||
<button class="btn btn-primary" id="ajoutZoom">Ajout du lien zoom</button>
|
<button class="btn btn-primary" id="ajoutZoom">Ajout du lien zoom</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if appartient_direction and reservation.statut == "en_attente" %}
|
{% if appartient_direction and reservation.statut == "en_attente" %}
|
||||||
<button class="btn btn-danger" id="refuserReservation" data-lienrefus="{% url 'gestion_salle:refuser-reservation' %}">Refuser</button>
|
<button class="btn btn-danger" id="refuserReservation" data-lienrefus="{% url 'gestion_salle:refuser-reservation' %}">Refuser</button>
|
||||||
{% endif %}
|
|
||||||
<button class="btn btn-danger" id="bouton-annuler">Annuler</button>
|
|
||||||
{% if appartient_direction %}
|
|
||||||
<button class="btn btn-success" id="bouton-valider">Valider</button>
|
<button class="btn btn-success" id="bouton-valider">Valider</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<span id="current-user-id" data-user-id="{{ request.user.id }}"></span>
|
||||||
|
<button class="btn btn-danger" id="bouton-annuler">Annuler</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -8,63 +8,93 @@ from django.forms import model_to_dict
|
|||||||
from gestion_employe.models import Employe
|
from gestion_employe.models import Employe
|
||||||
from gestion_salle.forms import ReservationForm
|
from gestion_salle.forms import ReservationForm
|
||||||
from .models import Reservation
|
from .models import Reservation
|
||||||
|
from datetime import timedelta
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def index(request:HttpRequest):
|
def index(request: HttpRequest):
|
||||||
"""Vue de gestion de la reservation de la salle"""
|
|
||||||
try:
|
try:
|
||||||
employe = Employe.objects.get(user=request.user)
|
employe = Employe.objects.get(user=request.user)
|
||||||
except Employe.DoesNotExist:
|
except Employe.DoesNotExist:
|
||||||
messages.error(request, "Impossible d'accéder au menu 'Reservation de salle' car votre profil Utilisateur n'est lié à aucun profil Employe. Veuillez contacter l'administrateur.")
|
messages.error(request, "Profil employé introuvable.")
|
||||||
return redirect('gestion_conges:conge')
|
return redirect('gestion_conges:conge')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
form = ReservationForm(request.POST)
|
form = ReservationForm(request.POST)
|
||||||
if form.is_valid():
|
|
||||||
date_debut = form.cleaned_data.get('date_debut')
|
|
||||||
date_fin = form.cleaned_data.get('date_fin')
|
|
||||||
salle = form.cleaned_data.get('salle')
|
|
||||||
heure_debut = form.cleaned_data.get('heure_debut')
|
|
||||||
heure_fin = form.cleaned_data.get('heure_fin')
|
|
||||||
motif_reservation = form.cleaned_data.get('motif_reservation')
|
|
||||||
besoin_zoom = form.cleaned_data.get('besoin_zoom')
|
|
||||||
besoin_ordi = form.cleaned_data.get('besoin_ordi')
|
|
||||||
|
|
||||||
while date_debut <= date_fin :
|
|
||||||
reservation = Reservation(
|
|
||||||
employe = employe,
|
|
||||||
date_debut = date_debut,
|
|
||||||
date_fin = date_debut,
|
|
||||||
salle = salle,
|
|
||||||
heure_debut = heure_debut,
|
|
||||||
heure_fin = heure_fin,
|
|
||||||
besoin_zoom = besoin_zoom,
|
|
||||||
besoin_ordi = besoin_ordi,
|
|
||||||
motif_reservation=motif_reservation,
|
|
||||||
)
|
|
||||||
reservation.save()
|
|
||||||
date_debut = date_debut + timedelta(days=1)
|
|
||||||
|
|
||||||
messages.success(request, "Réservation(s) créées avec succès.")
|
if form.is_valid():
|
||||||
|
|
||||||
|
date_debut = form.cleaned_data['date_debut']
|
||||||
|
date_fin = form.cleaned_data['date_fin']
|
||||||
|
salle = form.cleaned_data['salle']
|
||||||
|
heure_debut = form.cleaned_data['heure_debut']
|
||||||
|
heure_fin = form.cleaned_data['heure_fin']
|
||||||
|
motif = form.cleaned_data['motif_reservation']
|
||||||
|
besoin_zoom = form.cleaned_data['besoin_zoom']
|
||||||
|
besoin_ordi = form.cleaned_data['besoin_ordi']
|
||||||
|
|
||||||
|
if date_fin < date_debut:
|
||||||
|
messages.error(request, "Date fin invalide.")
|
||||||
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
|
if heure_fin <= heure_debut:
|
||||||
|
messages.error(request, "Heure invalide.")
|
||||||
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
|
if not request.user.first_name.strip() or not request.user.last_name.strip():
|
||||||
|
messages.error(
|
||||||
|
request,
|
||||||
|
"Veuillez renseigner votre nom et prénom pour pouvoir faire une réservation."
|
||||||
|
)
|
||||||
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
|
created = []
|
||||||
|
current_date = date_debut
|
||||||
|
|
||||||
|
while current_date <= date_fin:
|
||||||
|
|
||||||
|
reservation = Reservation.objects.create(
|
||||||
|
employe=employe,
|
||||||
|
date_debut=current_date,
|
||||||
|
date_fin=current_date,
|
||||||
|
salle=salle,
|
||||||
|
heure_debut=heure_debut,
|
||||||
|
heure_fin=heure_fin,
|
||||||
|
besoin_zoom=besoin_zoom,
|
||||||
|
besoin_ordi=besoin_ordi,
|
||||||
|
motif_reservation=motif,
|
||||||
|
statut="en_attente"
|
||||||
|
)
|
||||||
|
|
||||||
|
created.append(reservation)
|
||||||
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
|
messages.success(request, "Réservation(s) créée(s) avec succès.")
|
||||||
return redirect('gestion_salle:reservation-salle')
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
formulaire_reservation = ReservationForm()
|
formulaire_reservation = ReservationForm()
|
||||||
departement = Employe.objects.get(user__username=request.user).departement
|
departement = employe.departement
|
||||||
appartient_direction = 'direction' in request.user.groups.values_list('name', flat=True)
|
|
||||||
liste_demande_reservation = [
|
appartient_direction = request.user.groups.filter(name='direction').exists()
|
||||||
reservation.id for reservation in
|
|
||||||
Reservation.objects.filter(employe=employe, statut='en_attente')
|
liste_demande_reservation = Reservation.objects.filter(
|
||||||
]
|
employe=employe,
|
||||||
|
statut='en_attente'
|
||||||
|
).values_list('id', flat=True)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'formulaire_reservation': formulaire_reservation,
|
'formulaire_reservation': formulaire_reservation,
|
||||||
'nb_reservation_attente': Reservation.objects.filter(statut='en_attente').count(),
|
'nb_reservation_attente': Reservation.objects.filter(statut='en_attente').count(),
|
||||||
'appartient_au_departement_informatique': 'Informatique' == departement.nom if departement else False,
|
'appartient_au_departement_informatique': departement and departement.nom == "Systeme informatique",
|
||||||
'appartient_direction': appartient_direction,
|
'appartient_direction': appartient_direction,
|
||||||
'liste_demande_reservation': liste_demande_reservation
|
'liste_demande_reservation': list(liste_demande_reservation),
|
||||||
}
|
}
|
||||||
return render(request, "gestion_salle/index.html", context)
|
|
||||||
|
|
||||||
|
return render(request, "gestion_salle/index.html", context)
|
||||||
def liste_reservation(request:HttpRequest):
|
def liste_reservation(request:HttpRequest):
|
||||||
"""Vue d'affichage des creneaux disponibles"""
|
"""Vue d'affichage des creneaux disponibles"""
|
||||||
reservations = Reservation.objects.filter(statut = "validee")
|
reservations = Reservation.objects.filter(statut = "validee")
|
||||||
@@ -86,7 +116,6 @@ def liste_reservation(request:HttpRequest):
|
|||||||
"end": reservation.heure_fin,
|
"end": reservation.heure_fin,
|
||||||
"color": color,
|
"color": color,
|
||||||
})
|
})
|
||||||
|
|
||||||
return JsonResponse(liste_reservation, safe=False)
|
return JsonResponse(liste_reservation, safe=False)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -103,23 +132,25 @@ def liste_reservation_attente(request):
|
|||||||
return JsonResponse(liste_reservation, safe=False)
|
return JsonResponse(liste_reservation, safe=False)
|
||||||
|
|
||||||
def detail_reservation(request:HttpRequest, reservation_id:int):
|
def detail_reservation(request:HttpRequest, reservation_id:int):
|
||||||
|
|
||||||
reservation = Reservation.objects.get(id=reservation_id)
|
reservation = Reservation.objects.get(id=reservation_id)
|
||||||
employe = reservation.employe.user
|
employe = reservation.employe.user
|
||||||
|
|
||||||
reservation_json = {
|
reservation_json = {
|
||||||
|
|
||||||
'id_reservation': reservation_id,
|
'id_reservation': reservation_id,
|
||||||
'employe': f"{employe.first_name} {employe.last_name}",
|
'employe': f"{employe.first_name} {employe.last_name}",
|
||||||
'salle': reservation.salle,
|
'salle': reservation.salle,
|
||||||
'statut': reservation.statut,
|
'statut': reservation.statut,
|
||||||
'date_evenement': reservation.date_debut.strftime('%Y-%m-%d'),
|
'date_debut': reservation.date_debut.strftime('%Y-%m-%d'),
|
||||||
|
'date_fin': reservation.date_fin.strftime('%Y-%m-%d'),
|
||||||
'heure_debut': reservation.heure_debut.strftime('%H:%M'),
|
'heure_debut': reservation.heure_debut.strftime('%H:%M'),
|
||||||
'heure_fin': reservation.heure_fin.strftime('%H:%M'),
|
'heure_fin': reservation.heure_fin.strftime('%H:%M'),
|
||||||
'motif_reservation': reservation.motif_reservation,
|
'motif_reservation': reservation.motif_reservation,
|
||||||
'besoin_zoom': reservation.besoin_zoom,
|
'besoin_zoom': reservation.besoin_zoom,
|
||||||
'besoin_ordinateur': reservation.besoin_ordi,
|
'besoin_ordinateur': reservation.besoin_ordi,
|
||||||
'lien_zoom': reservation.lien_zoom or '',
|
'lien_zoom': reservation.lien_zoom or '',
|
||||||
'motif_refus': reservation.motif_refus or '',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonResponse(reservation_json, safe=True)
|
return JsonResponse(reservation_json, safe=True)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -165,31 +196,35 @@ def annuler_reservation(request:HttpRequest):
|
|||||||
return redirect('gestion_salle:reservation-salle')
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def valider_reservation(request:HttpRequest):
|
def valider_reservation(request: HttpRequest):
|
||||||
"""Vue de gestion de l'annulation de la reservation"""
|
"""Validation d'une réservation"""
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
reservation_id= request.POST['id_reservation']
|
reservation_id = request.POST.get('id_reservation')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
reservation = Reservation.objects.get(id=reservation_id)
|
reservation = Reservation.objects.get(id=reservation_id)
|
||||||
except reservation.DoesNotExist:
|
except Reservation.DoesNotExist:
|
||||||
messages.error(request, "La resevertion selectionné n'existe pas.")
|
messages.error(request, "La réservation sélectionnée n'existe pas.")
|
||||||
return redirect("salle")
|
return redirect("salle")
|
||||||
|
|
||||||
reservation.statut = 'validee'
|
reservation.statut = 'validee'
|
||||||
reservation.save()
|
reservation.save()
|
||||||
messages.success(request, f"Réservation de {reservation.employe.get_full_name()} validée avec succès.")
|
|
||||||
return redirect('gestion_salle:reservation-salle')
|
return redirect('gestion_salle:reservation-salle')
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def refuser_reservation(request:HttpRequest):
|
def refuser_reservation(request: HttpRequest):
|
||||||
"""Vue de gestion de refus de la reservation"""
|
"""Refuser une réservation"""
|
||||||
data = json.loads(request.body)
|
if request.method == 'POST':
|
||||||
reservation_id = data.get("id_reservation")
|
reservation_id = request.POST.get('id_reservation')
|
||||||
try:
|
|
||||||
reservation = Reservation.objects.get(id=reservation_id)
|
try:
|
||||||
except Reservation.DoesNotExist and ValueError:
|
reservation = Reservation.objects.get(id=reservation_id)
|
||||||
return JsonResponse({"message": "La resevertion selectionné n'existe pas."})
|
except Reservation.DoesNotExist:
|
||||||
else:
|
messages.error(request, "La réservation n'existe pas.")
|
||||||
reservation.statut = "refusee"
|
return redirect("salle")
|
||||||
|
|
||||||
|
reservation.statut = 'refusee'
|
||||||
reservation.save()
|
reservation.save()
|
||||||
return JsonResponse({"message": "Réservation refusée avec succès."})
|
|
||||||
|
return redirect('gestion_salle:reservation-salle')
|
||||||
159
requirements.txt
159
requirements.txt
@@ -1,21 +1,152 @@
|
|||||||
asgiref==3.11.1
|
anyio==4.13.0
|
||||||
certifi==2026.4.22
|
argon2-cffi==25.1.0
|
||||||
|
argon2-cffi-bindings==25.1.0
|
||||||
|
arrow==1.4.0
|
||||||
|
asgiref==3.11.0
|
||||||
|
asttokens==3.0.1
|
||||||
|
async-lru==2.3.0
|
||||||
|
attrs==26.1.0
|
||||||
|
Automat==20.2.0
|
||||||
|
babel==2.18.0
|
||||||
|
bcrypt==3.2.0
|
||||||
|
beautifulsoup4==4.14.3
|
||||||
|
bleach==6.3.0
|
||||||
|
blinker==1.4
|
||||||
|
certifi==2026.2.25
|
||||||
|
cffi==2.0.0
|
||||||
|
chardet==4.0.0
|
||||||
charset-normalizer==3.4.7
|
charset-normalizer==3.4.7
|
||||||
Django==5.2.13
|
click==8.0.3
|
||||||
django-simple-sso==1.3.0
|
cloud-init==25.3
|
||||||
idna==3.13
|
colorama==0.4.4
|
||||||
itsdangerous==0.24
|
comm==0.2.3
|
||||||
mysqlclient==2.2.8
|
command-not-found==0.3
|
||||||
|
configobj==5.0.6
|
||||||
|
constantly==15.1.0
|
||||||
|
cryptography==3.4.8
|
||||||
|
dbus-python==1.2.18
|
||||||
|
debugpy==1.8.20
|
||||||
|
decorator==5.2.1
|
||||||
|
defusedxml==0.7.1
|
||||||
|
distlib==0.4.0
|
||||||
|
distro==1.7.0
|
||||||
|
distro-info==1.1+ubuntu0.2
|
||||||
|
Django==5.2.10
|
||||||
|
et_xmlfile==2.0.0
|
||||||
|
exceptiongroup==1.3.1
|
||||||
|
executing==2.2.1
|
||||||
|
fastjsonschema==2.21.2
|
||||||
|
filelock==3.20.3
|
||||||
|
fqdn==1.5.1
|
||||||
|
h11==0.16.0
|
||||||
|
httpcore==1.0.9
|
||||||
|
httplib2==0.20.2
|
||||||
|
httpx==0.28.1
|
||||||
|
hyperlink==21.0.0
|
||||||
|
idna==3.3
|
||||||
|
importlib-metadata==4.6.4
|
||||||
|
incremental==21.3.0
|
||||||
|
ipykernel==7.2.0
|
||||||
|
ipython==8.39.0
|
||||||
|
isoduration==20.11.0
|
||||||
|
jedi==0.19.2
|
||||||
|
jeepney==0.7.1
|
||||||
|
Jinja2==3.0.3
|
||||||
|
json5==0.14.0
|
||||||
|
jsonpatch==1.32
|
||||||
|
jsonpointer==2.0
|
||||||
|
jsonschema==4.26.0
|
||||||
|
jsonschema-specifications==2025.9.1
|
||||||
|
jupyter-events==0.12.0
|
||||||
|
jupyter-lsp==2.3.1
|
||||||
|
jupyter_client==8.8.0
|
||||||
|
jupyter_core==5.9.1
|
||||||
|
jupyter_server==2.17.0
|
||||||
|
jupyter_server_terminals==0.5.4
|
||||||
|
jupyterlab==4.5.6
|
||||||
|
jupyterlab_pygments==0.3.0
|
||||||
|
jupyterlab_server==2.28.0
|
||||||
|
keyring==23.5.0
|
||||||
|
lark==1.3.1
|
||||||
|
launchpadlib==1.10.16
|
||||||
|
lazr.restfulclient==0.14.4
|
||||||
|
lazr.uri==1.0.6
|
||||||
|
MarkupSafe==2.0.1
|
||||||
|
matplotlib-inline==0.2.1
|
||||||
|
mistune==3.2.0
|
||||||
|
more-itertools==8.10.0
|
||||||
|
nbclient==0.10.4
|
||||||
|
nbconvert==7.17.0
|
||||||
|
nbformat==5.10.4
|
||||||
|
nest-asyncio==1.6.0
|
||||||
|
netifaces==0.11.0
|
||||||
|
notebook_shim==0.2.4
|
||||||
numpy==2.2.6
|
numpy==2.2.6
|
||||||
|
oauthlib==3.2.0
|
||||||
|
openpyxl==3.1.5
|
||||||
|
overrides==7.7.0
|
||||||
|
packaging==26.0
|
||||||
pandas==2.3.3
|
pandas==2.3.3
|
||||||
pillow==12.2.0
|
pandocfilters==1.5.1
|
||||||
|
parso==0.8.6
|
||||||
|
pexpect==4.9.0
|
||||||
|
platformdirs==4.5.1
|
||||||
|
prometheus_client==0.24.1
|
||||||
|
prompt_toolkit==3.0.52
|
||||||
|
psutil==7.2.2
|
||||||
|
ptyprocess==0.7.0
|
||||||
|
pure_eval==0.2.3
|
||||||
|
pyasn1==0.4.8
|
||||||
|
pyasn1-modules==0.2.1
|
||||||
|
pycparser==3.0
|
||||||
|
pycurl==7.44.1
|
||||||
|
Pygments==2.20.0
|
||||||
|
PyGObject==3.42.1
|
||||||
|
PyHamcrest==2.0.2
|
||||||
|
PyJWT==2.3.0
|
||||||
|
pyOpenSSL==21.0.0
|
||||||
|
pyparsing==2.4.7
|
||||||
|
pyrsistent==0.18.1
|
||||||
|
pyserial==3.5
|
||||||
|
python-apt==2.4.0+ubuntu4.1
|
||||||
python-dateutil==2.9.0.post0
|
python-dateutil==2.9.0.post0
|
||||||
pytz==2026.1.post1
|
python-json-logger==4.1.0
|
||||||
|
pytz==2022.1
|
||||||
|
PyYAML==5.4.1
|
||||||
|
pyzmq==27.1.0
|
||||||
|
referencing==0.37.0
|
||||||
requests==2.33.1
|
requests==2.33.1
|
||||||
six==1.17.0
|
rfc3339-validator==0.1.4
|
||||||
|
rfc3986-validator==0.1.1
|
||||||
|
rfc3987-syntax==1.1.0
|
||||||
|
rpds-py==0.30.0
|
||||||
|
SecretStorage==3.3.1
|
||||||
|
Send2Trash==2.1.0
|
||||||
|
service-identity==18.1.0
|
||||||
|
six==1.16.0
|
||||||
|
soupsieve==2.8.3
|
||||||
sqlparse==0.5.5
|
sqlparse==0.5.5
|
||||||
|
ssh-import-id==5.11
|
||||||
|
stack-data==0.6.3
|
||||||
|
systemd-python==234
|
||||||
|
terminado==0.18.1
|
||||||
|
tinycss2==1.4.0
|
||||||
|
tomli==2.4.1
|
||||||
|
tornado==6.5.5
|
||||||
|
traitlets==5.14.3
|
||||||
|
Twisted==22.1.0
|
||||||
typing_extensions==4.15.0
|
typing_extensions==4.15.0
|
||||||
tzdata==2026.2
|
tzdata==2025.3
|
||||||
urllib3==2.6.3
|
ubuntu-pro-client==8001
|
||||||
python-decouple
|
ufw==0.36.1
|
||||||
gunicorn
|
unattended-upgrades==0.1
|
||||||
|
uri-template==1.3.0
|
||||||
|
urllib3==1.26.5
|
||||||
|
virtualenv==20.13.0+ds
|
||||||
|
wadllib==1.3.6
|
||||||
|
wcwidth==0.6.0
|
||||||
|
webcolors==25.10.0
|
||||||
|
webencodings==0.5.1
|
||||||
|
websocket-client==1.9.0
|
||||||
|
zipp==1.0.0
|
||||||
|
zope.interface==5.4.0
|
||||||
|
|||||||
Reference in New Issue
Block a user