clean: remove pycache from tracking
This commit is contained in:
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.
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.
@@ -1,3 +0,0 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
@@ -1,5 +0,0 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class GestionSalleConfig(AppConfig):
|
||||
name = 'gestion_salle'
|
||||
@@ -1,32 +0,0 @@
|
||||
from django import forms
|
||||
from .models import Reservation
|
||||
|
||||
class ReservationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Reservation
|
||||
fields = ['salle', 'date_debut', 'date_fin', 'heure_debut', 'heure_fin', 'motif_reservation', 'besoin_zoom', 'besoin_ordi']
|
||||
widgets = {
|
||||
'date_debut': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
||||
'date_fin': forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
||||
'heure_debut': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
||||
'heure_fin': forms.TimeInput(attrs={'type': 'time', 'class': 'form-control'}),
|
||||
'motif_reservation': forms.Textarea(attrs={'rows': 3, 'cols': 40, 'style':'resize:none;', 'class': 'form-control'}),
|
||||
'salle': forms.Select(attrs={'class': 'form-select'}),
|
||||
}
|
||||
besoin_zoom = forms.BooleanField(
|
||||
required=False,
|
||||
label="Besoin d'un lien Zoom ?",
|
||||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'id_besoin_zoom'})
|
||||
)
|
||||
besoin_ordi = forms.BooleanField(
|
||||
required=False,
|
||||
label="Besoin d'ordinateur ?",
|
||||
widget=forms.CheckboxInput(attrs={'class': 'form-check-input', 'id': 'id_besoin_ordi'})
|
||||
)
|
||||
|
||||
class RefusReservationForm(forms.Form):
|
||||
motif_refus = forms.CharField(
|
||||
label= "Motif du refus",
|
||||
widget=forms.Textarea(attrs={'rows': 3, 'cols': 40, 'style': 'resize:none;'}),
|
||||
required=True
|
||||
)
|
||||
@@ -1,34 +0,0 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-17 12:03
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('gestion_employe', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Reservation',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('salle', models.CharField(choices=[('formation', 'Salle de formation'), ('reunion', 'Salle de réunion'), ('lien_zoom', 'Lien Zoom')], max_length=100)),
|
||||
('date_demande', models.DateTimeField(auto_now_add=True)),
|
||||
('date_debut', models.DateField()),
|
||||
('date_fin', models.DateField(blank=True, null=True)),
|
||||
('heure_debut', models.TimeField()),
|
||||
('heure_fin', models.TimeField()),
|
||||
('besoin_zoom', models.BooleanField(default=False, verbose_name="Besoin d'un lien Zoom ?")),
|
||||
('besoin_ordi', models.BooleanField(default=False, verbose_name="Besoin d'un ordinateur ?")),
|
||||
('lien_zoom', models.URLField(blank=True, null=True, verbose_name='Lien Zoom')),
|
||||
('motif_reservation', models.TextField()),
|
||||
('statut', models.CharField(choices=[('en_attente', 'En attente'), ('validee', 'Validée'), ('refusee', 'Refusée'), ('annulee', 'Annulée')], default='en_attente', max_length=25)),
|
||||
('employe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='gestion_employe.employe')),
|
||||
],
|
||||
),
|
||||
]
|
||||
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.
@@ -1,33 +0,0 @@
|
||||
from django.db import models
|
||||
from gestion_employe.models import Employe
|
||||
|
||||
|
||||
class Reservation(models.Model):
|
||||
"""Modèle de création des réservations"""
|
||||
TYPE_CHOICES = [
|
||||
('formation', 'Salle de formation'),
|
||||
('reunion', 'Salle de réunion'),
|
||||
('lien_zoom', 'Lien Zoom'),
|
||||
]
|
||||
STATUT = [
|
||||
('en_attente', 'En attente'),
|
||||
('validee', 'Validée'),
|
||||
('refusee', 'Refusée'),
|
||||
('annulee', 'Annulée'),
|
||||
]
|
||||
|
||||
employe = models.ForeignKey(Employe, on_delete=models.CASCADE)
|
||||
salle = models.CharField(max_length=100, choices=TYPE_CHOICES)
|
||||
date_demande = models.DateTimeField(auto_now_add=True)
|
||||
date_debut = models.DateField()
|
||||
date_fin = models.DateField(blank=True,null=True)
|
||||
heure_debut = models.TimeField()
|
||||
heure_fin = models.TimeField()
|
||||
besoin_zoom = models.BooleanField(default=False, verbose_name="Besoin d'un lien Zoom ?")
|
||||
besoin_ordi = models.BooleanField(default=False, verbose_name="Besoin d'un ordinateur ?")
|
||||
lien_zoom = models.URLField(blank=True, null=True, verbose_name="Lien Zoom")
|
||||
motif_reservation = models.TextField()
|
||||
statut = models.CharField(choices=STATUT, default='en_attente', max_length=25)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.salle} - {self.employe.user.first_name} {self.employe.user.last_name} le {self.date_reservation}"
|
||||
@@ -1,193 +0,0 @@
|
||||
const $ = (element) => document.getElementById(element);
|
||||
const { Schedule } = calendarjs;
|
||||
|
||||
let dateAUtiliser = new Date().toISOString().split('T')[0];
|
||||
let currentReservationId = null;
|
||||
|
||||
const calendrier = Schedule(document.getElementById('planning-reservation'), {
|
||||
type: 'weekdays',
|
||||
value: dateAUtiliser,
|
||||
validRange: ['08:00', '18:00'],
|
||||
ondblclick: function(self, event) {
|
||||
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
||||
modal.show();
|
||||
fetch (`/gestion-salle/revervation/details/${event.guid}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
currentReservationId = data.id_reservation;
|
||||
console.log(data);
|
||||
$("id_reservation_detail").value = data.id_reservation;
|
||||
$("id_reservation_refus").value = data.id_reservation;
|
||||
$("id_reservation_zoom").value = data.id_reservation;
|
||||
$("employe").value=data.employe;
|
||||
$("salle").value=data.salle;
|
||||
$("statut-reservation").innerHTML=data.statut;
|
||||
$("date_evenement").value=data.date_evenement;
|
||||
$("heure_debut").value=data.heure_debut;
|
||||
$("heure_fin").value=data.heure_fin;
|
||||
$("motif_reservation").value=data.motif_reservation;
|
||||
$("besoin_zoom").checked=data.besoin_zoom;
|
||||
$("besoin_ordinateur").checked=data.besoin_ordinateur;
|
||||
$("lien_zoom").value=data.lien_zoom;
|
||||
|
||||
if(data.statut !== "annulee"){
|
||||
$("motif_refus_container").className = "d-none";
|
||||
}else{
|
||||
$("motif_refus").value=data.motif_refus;
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$("modalReservation").addEventListener('shown.bs.modal', (e) => {
|
||||
$("id_salle").value = $("liste-salle").value;
|
||||
})
|
||||
|
||||
$('semaineDate').addEventListener('change', () => {
|
||||
calendrier.value = $('semaineDate').value;
|
||||
calendrier.render();
|
||||
})
|
||||
|
||||
evenement_defini = null
|
||||
|
||||
$("liste-salle").addEventListener("change", (e) => {
|
||||
if(evenement_defini === null){
|
||||
evenement_defini = calendrier.getData();
|
||||
}
|
||||
evenements = evenement_defini;
|
||||
evenement_filtrer = evenements.filter((evenement) => {
|
||||
if(evenement.title == $("liste-salle").value){
|
||||
return evenement
|
||||
}
|
||||
})
|
||||
calendrier.setData(evenement_filtrer);
|
||||
})
|
||||
|
||||
function chargement_evenement(){
|
||||
const url = $("planning-reservation").dataset.url;
|
||||
fetch (url)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
calendrier.setData(data);
|
||||
})
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
chargement_evenement()
|
||||
})
|
||||
|
||||
$("bouton-annuler").addEventListener("click", (e) => {
|
||||
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
||||
const url_annuler = $("formulaire-details").dataset.urlannuler;
|
||||
|
||||
fetch(
|
||||
url_annuler,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-Requested-With": "XMTHttpRequest",
|
||||
"X-CSRFToken": csrf
|
||||
},
|
||||
body: new FormData($("formulaire-details"))
|
||||
}
|
||||
)
|
||||
.then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
})
|
||||
|
||||
if($("bouton-valider")){
|
||||
$("bouton-valider").addEventListener("click", (e) => {
|
||||
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
||||
const urlvalider = $("formulaire-details").dataset.urlvalider;
|
||||
|
||||
fetch(
|
||||
urlvalider,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"X-Requested-With": "XMTHttpRequest",
|
||||
"X-CSRFToken": csrf
|
||||
},
|
||||
body: new FormData($("formulaire-details"))
|
||||
}
|
||||
)
|
||||
.then(response => response.json())
|
||||
.then(data => console.log(data))
|
||||
})
|
||||
}
|
||||
|
||||
if($("ajoutZoom")){
|
||||
$("ajoutZoom").addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
bootstrap.Modal.getOrCreateInstance($("modalDetailReservation")).hide();
|
||||
new bootstrap.Modal($("modalZoom")).show();
|
||||
})
|
||||
}
|
||||
|
||||
if($("refuserReservation")){
|
||||
$("refuserReservation").addEventListener("click", (e) => {
|
||||
const csrf = document.querySelector("[name=csrfmiddlewaretoken]").value;
|
||||
const url = e.currentTarget.dataset.lienrefus;
|
||||
const idRes = $("id_reservation_detail").value;
|
||||
|
||||
fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"X-CSRFToken": csrf
|
||||
},
|
||||
body: JSON.stringify({ "id_reservation": idRes })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => alert(data.message))
|
||||
.catch(error => console.error("Erreur:", error));
|
||||
});
|
||||
}
|
||||
|
||||
const tableau_reservation_attente = new Tabulator("#tableau-reservation-attente", {
|
||||
columns: [
|
||||
{title: "Employé", field: "employe"},
|
||||
{title: "Salle", field: "salle"},
|
||||
{title: "Date de l'evenement", field: "date_debut"},
|
||||
{title: "Heure de début", field: "heure_debut"},
|
||||
{title: "Heure de fin", field: "heure_fin"},
|
||||
{title: "Motif de reservation", field: "motif_reservation"},
|
||||
],
|
||||
placeholder: "Aucune reservation en attente.",
|
||||
ajaxURL : $("tableau-reservation-attente").dataset.reservationattentes
|
||||
})
|
||||
|
||||
tableau_reservation_attente.on("rowClick", (row, rowData) => {
|
||||
const data = rowData.getData();
|
||||
|
||||
console.log(data);
|
||||
|
||||
if(data.besoin_zoom === false){
|
||||
$("lien_zoom_container").className = 'd-none';
|
||||
}
|
||||
|
||||
if(data.statut !== "refusee"){
|
||||
$("motif_refus_container").className = 'd-none';
|
||||
}
|
||||
|
||||
$("id_reservation_detail").value = data.id;
|
||||
$("id_reservation_refus").value = data.id;
|
||||
$("id_reservation_zoom").value = data.id;
|
||||
|
||||
$("employe").value=data.employe;
|
||||
$("salle").value=data.salle;
|
||||
$("statut-reservation").innerHTML=data.statut;
|
||||
$("date_evenement").value=data.date_debut;
|
||||
$("heure_debut").value=data.heure_debut;
|
||||
$("heure_fin").value=data.heure_fin;
|
||||
$("motif_reservation").value=data.motif_reservation;
|
||||
$("besoin_zoom").checked=data.besoin_zoom;
|
||||
$("besoin_ordinateur").checked=data.besoin_ordi;
|
||||
$("lien_zoom").value=data.lien_zoom;
|
||||
$("motif_refus").value=data.motif_refus;
|
||||
|
||||
const modal = new bootstrap.Modal($("modalDetailReservation"));
|
||||
bootstrap.Modal.getOrCreateInstance($("modalReservationAttente")).hide();
|
||||
modal.show();
|
||||
})
|
||||
@@ -1,59 +0,0 @@
|
||||
{% extends "BASE.html" %}
|
||||
{% load static %}
|
||||
{% block 'titre_page' %} Gestion des projets {% endblock %}
|
||||
{% block 'css' %}
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@calendarjs/ce/dist/style.min.css" />
|
||||
{% endblock %}
|
||||
{% block 'contenu' %}
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{% if message.tags == "error" %}danger{% else %}success{% endif %} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col py-2 px-4">
|
||||
<h1 class="text-center">Reservation de salle</h1>
|
||||
<hr>
|
||||
<div class="row d-flex justify-content-around">
|
||||
<div class="form-group col-5 me-2">
|
||||
<label>Selectionner le jour concerné :</label>
|
||||
<input type="date" class="form-control" id="semaineDate" />
|
||||
</div>
|
||||
<div class="form-group col-5 me-2">
|
||||
<label>Selectionner une salle :</label>
|
||||
<select class = "form-select" id="liste-salle">
|
||||
<option value='formation'>Salle de formation</option>
|
||||
<option value='reunion'>Salle de réunion</option>
|
||||
<option value='lien_zoom'>Lien Zoom</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col d-flex justify-content-center">
|
||||
<button class="btn btn-lg btn-primary me-2" data-bs-toggle="modal" data-bs-target="#modalReservation">Nouvelle reservation</button>
|
||||
<button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#modalReservationAttente">
|
||||
Validation en attente <span class="badge badge-light">{{ nb_reservation_attente }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div data-url="{% url 'gestion_salle:liste-reservation' %}" id="planning-reservation"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block 'modal' %}
|
||||
{% include 'gestion_salle/parts/modalCreationReservation.html' %}
|
||||
{% include 'gestion_salle/parts/ModaleAjoutLienZoom.html' %}
|
||||
{% include 'gestion_salle/parts/ModalRefusReservation.html' %}
|
||||
{% include 'gestion_salle/parts/modalDetailResevation.html' %}
|
||||
{% include 'gestion_salle/parts/modalListeValidation.html' %}
|
||||
{% endblock %}
|
||||
{% block 'js' %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@calendarjs/ce/dist/index.min.js"></script>
|
||||
<script src="{% static 'gestion_salle/js/index.js' %}"></script>
|
||||
{% endblock %}
|
||||
@@ -1,22 +0,0 @@
|
||||
<div class="modal fade" id="refusModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header ">
|
||||
<h5 class="modal-title">Motif du refus</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" id="refusForm" action="{% url 'gestion_salle:refuser-reservation' %}">
|
||||
{% csrf_token %}
|
||||
<input type='' class="form-control" id="id_reservation_refus" name='id_reservation' value="">
|
||||
<textarea class="form-control" name="motif_refus" rows="3" required></textarea>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-danger">Refuser</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,26 +0,0 @@
|
||||
<!-- Modal Ajouter/Modifier lien Zoom -->
|
||||
<div class="modal fade" id="modalZoom" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header ">
|
||||
<h5 class="modal-title">Ajouter/Modifier le lien Zoom</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="post" id="formZoom" action="{% url 'gestion_salle:ajouter-lien_zoom' %}">
|
||||
{% csrf_token %}
|
||||
<input type='hidden' class="form-control" id="id_reservation_zoom" name='id_reservation'>
|
||||
<div class="mb-3">
|
||||
<label for="lienZoom" class="form-label">Lien Zoom</label>
|
||||
<input type="url" class="form-control" name="lien_zoom" id="lienZoom"
|
||||
value="" required>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-success">Enregistrer</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,23 +0,0 @@
|
||||
<!-- Modal de création d'une nouvelle reservation -->
|
||||
<div class="modal fade" id="modalReservation" tabindex="-1" aria-labelledby="modalReservationLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="modalReservationLabel">
|
||||
Nouvelle reservation
|
||||
</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" action="{% url 'gestion_salle:reservation-salle' %}">
|
||||
{% csrf_token %}
|
||||
{{ formulaire_reservation.as_p }}
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,71 +0,0 @@
|
||||
<!-- Modal d'affichage des détails d'une reservation -->
|
||||
<div class="modal fade" id="modalDetailReservation" tabindex="-1" aria-labelledby="modalDetailReservationLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="modalDetailReservationLabel">
|
||||
Détails de la reservation (<span id='statut-reservation'></span>)
|
||||
</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="POST" data-urlannuler="{% url 'gestion_salle:annuler-reservation' %}" data-urlvalider="{% url 'gestion_salle:valider-reservation' %}" id="formulaire-details">
|
||||
{% csrf_token %}
|
||||
<input type='hidden' class="form-control" id="id_reservation_detail" name='id_reservation'>
|
||||
<div class="form-group mb-2">
|
||||
<label>Employé :</label>
|
||||
<input class="form-control" id="employe" readonly>
|
||||
</div>
|
||||
<div class="form-group mb-2">
|
||||
<label>Salle :</label>
|
||||
<input class="form-control" id="salle" readonly>
|
||||
</div>
|
||||
<div class="form-group mb-2">
|
||||
<label>Date de l'évènement :</label>
|
||||
<input type='date' class="form-control" id="date_evenement" readonly >
|
||||
</div>
|
||||
<div class="form-group mb-2">
|
||||
<label>Heure de début :</label>
|
||||
<input type='time' class="form-control" id="heure_debut" readonly>
|
||||
</div>
|
||||
<div class="form-group mb-2">
|
||||
<label>Heure de fin :</label>
|
||||
<input type='time' class="form-control" id="heure_fin" readonly >
|
||||
</div>
|
||||
<div class="form-group mb-2">
|
||||
<label>Motif de la reservation :</label>
|
||||
<textarea class="form-control" id="motif_reservation" readonly ></textarea>
|
||||
</div>
|
||||
<div class="form-check mb-2">
|
||||
<label class="form-check-label">Besoin d'un lien Zoom</label>
|
||||
<input type="checkbox" class="form-check-input" id="besoin_zoom" readonly >
|
||||
</div>
|
||||
<div class="form-group mb-2" id="lien_zoom_container">
|
||||
<label>lien Zoom :</label>
|
||||
<input type="url" class="form-control" id="lien_zoom" readonly >
|
||||
</div>
|
||||
<div class="form-check mb-2">
|
||||
<label label="form-check-label">Besoin d'un ordinateur</label>
|
||||
<input type="checkbox" class="form-check-input" id="besoin_ordinateur" readonly >
|
||||
</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'>
|
||||
{% if appartient_au_departement_informatique %}
|
||||
<button class="btn btn-primary" id="ajoutZoom">Ajout du lien zoom</button>
|
||||
{% endif %}
|
||||
{% if appartient_direction and reservation.statut == "en_attente" %}
|
||||
<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>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,16 +0,0 @@
|
||||
<!-- Modal d'affichage des détails d'une reservation -->
|
||||
<div class="modal fade" id="modalReservationAttente" tabindex="-1" aria-labelledby="modalReservationAttenteLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="modalReservationAttenteLabel">
|
||||
Liste des reservation en attente de validation
|
||||
</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="tableau-reservation-attente" data-reservationattentes = "{% url 'gestion_salle:liste-reservation-attente' %}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
@@ -1,48 +0,0 @@
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
app_name = "gestion_salle"
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
'revervation/',
|
||||
views.index,
|
||||
name='reservation-salle'
|
||||
),
|
||||
path(
|
||||
'revervation/details/<int:reservation_id>',
|
||||
views.detail_reservation,
|
||||
name='detail-reservation'
|
||||
),
|
||||
|
||||
path(
|
||||
'reservation/annuler',
|
||||
views.annuler_reservation,
|
||||
name='annuler-reservation'
|
||||
),
|
||||
path(
|
||||
'reservation/valider',
|
||||
views.valider_reservation,
|
||||
name='valider-reservation'
|
||||
),
|
||||
path(
|
||||
'reservation/refuser',
|
||||
views.refuser_reservation,
|
||||
name='refuser-reservation'
|
||||
),
|
||||
path(
|
||||
'reservation/ajout-de-lien-zoom',
|
||||
views.ajouter_lien_zoom,
|
||||
name='ajouter-lien_zoom'
|
||||
),
|
||||
path(
|
||||
'liste-reservation',
|
||||
views.liste_reservation,
|
||||
name='liste-reservation'
|
||||
),
|
||||
path(
|
||||
'liste-reservation-attente',
|
||||
views.liste_reservation_attente,
|
||||
name="liste-reservation-attente"
|
||||
)
|
||||
]
|
||||
@@ -1,195 +0,0 @@
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.shortcuts import redirect, render
|
||||
from django.http import JsonResponse, HttpRequest
|
||||
from django.forms import model_to_dict
|
||||
from gestion_employe.models import Employe
|
||||
from gestion_salle.forms import ReservationForm
|
||||
from .models import Reservation
|
||||
|
||||
@login_required
|
||||
def index(request:HttpRequest):
|
||||
"""Vue de gestion de la reservation de la salle"""
|
||||
try:
|
||||
employe = Employe.objects.get(user=request.user)
|
||||
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.")
|
||||
return redirect('gestion_conges:conge')
|
||||
|
||||
if request.method == "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.")
|
||||
return redirect('gestion_salle:reservation-salle')
|
||||
|
||||
formulaire_reservation = ReservationForm()
|
||||
departement = Employe.objects.get(user__username=request.user).departement
|
||||
appartient_direction = 'direction' in request.user.groups.values_list('name', flat=True)
|
||||
liste_demande_reservation = [
|
||||
reservation.id for reservation in
|
||||
Reservation.objects.filter(employe=employe, statut='en_attente')
|
||||
]
|
||||
|
||||
context = {
|
||||
'formulaire_reservation': formulaire_reservation,
|
||||
'nb_reservation_attente': Reservation.objects.filter(statut='en_attente').count(),
|
||||
'appartient_au_departement_informatique': 'Informatique' == departement.nom if departement else False,
|
||||
'appartient_direction': appartient_direction,
|
||||
'liste_demande_reservation': liste_demande_reservation
|
||||
}
|
||||
return render(request, "gestion_salle/index.html", context)
|
||||
|
||||
def liste_reservation(request:HttpRequest):
|
||||
"""Vue d'affichage des creneaux disponibles"""
|
||||
reservations = Reservation.objects.filter(statut = "validee")
|
||||
liste_reservation = []
|
||||
for reservation in reservations:
|
||||
color = None
|
||||
if reservation.statut == "en_attente":
|
||||
color = "#ffc107"
|
||||
elif reservation.statut == "validee":
|
||||
color = "#198754"
|
||||
else:
|
||||
color = "#dc3545"
|
||||
|
||||
liste_reservation.append({
|
||||
"guid": reservation.pk,
|
||||
"title": dict(Reservation.TYPE_CHOICES).get(reservation.salle),
|
||||
"date": reservation.date_debut,
|
||||
"start": reservation.heure_debut,
|
||||
"end": reservation.heure_fin,
|
||||
"color": color,
|
||||
})
|
||||
|
||||
return JsonResponse(liste_reservation, safe=False)
|
||||
|
||||
@login_required
|
||||
def liste_reservation_attente(request):
|
||||
reservations = Reservation.objects.filter(statut="en_attente")
|
||||
liste_reservation = [
|
||||
{
|
||||
**model_to_dict(reservation),
|
||||
"employe": f"{reservation.employe.user.first_name} {reservation.employe.user.last_name}",
|
||||
"salle": dict(Reservation.TYPE_CHOICES).get(reservation.salle)
|
||||
} for reservation in reservations
|
||||
]
|
||||
|
||||
return JsonResponse(liste_reservation, safe=False)
|
||||
|
||||
def detail_reservation(request:HttpRequest, reservation_id:int):
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
employe = reservation.employe.user
|
||||
reservation_json = {
|
||||
'id_reservation': reservation_id,
|
||||
'employe': f"{employe.first_name} {employe.last_name}",
|
||||
'salle': reservation.salle,
|
||||
'statut': reservation.statut,
|
||||
'date_evenement': reservation.date_debut.strftime('%Y-%m-%d'),
|
||||
'heure_debut': reservation.heure_debut.strftime('%H:%M'),
|
||||
'heure_fin': reservation.heure_fin.strftime('%H:%M'),
|
||||
'motif_reservation': reservation.motif_reservation,
|
||||
'besoin_zoom': reservation.besoin_zoom,
|
||||
'besoin_ordinateur': reservation.besoin_ordi,
|
||||
'lien_zoom': reservation.lien_zoom or '',
|
||||
'motif_refus': reservation.motif_refus or '',
|
||||
}
|
||||
|
||||
return JsonResponse(reservation_json, safe=True)
|
||||
|
||||
@login_required
|
||||
def ajouter_lien_zoom(request:HttpRequest):
|
||||
"""Vue de gestion de l'ajout du lien zoom"""
|
||||
if request.method == 'POST':
|
||||
reservation_id= request.POST['id_reservation']
|
||||
try:
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
except reservation.DoesNotExist:
|
||||
messages.error(request, "La resevertion selectionné n'existe pas.")
|
||||
return redirect("salle")
|
||||
|
||||
if not (reservation.besoin_zoom or reservation.salle == "lien_zoom"):
|
||||
messages.error(request, "Cette réservation ne nécessite pas de lien Zoom.")
|
||||
return redirect('gestion_salle:reservation-salle')
|
||||
elif reservation.statut in ["annulee", "refusee"]:
|
||||
messages.error(request, "Le lien Zoom ne peut être ajouté pour les réservations annulée ou refusée.")
|
||||
return redirect('gestion_salle:reservation-salle')
|
||||
|
||||
if request.method == "POST":
|
||||
lien = request.POST.get("lien_zoom")
|
||||
reservation.lien_zoom = lien
|
||||
reservation.statut = "validee"
|
||||
reservation.save()
|
||||
messages.success(request, "Le lien Zoom a été ajouté et la réservation a été validée. ")
|
||||
return redirect('gestion_salle:reservation-salle')
|
||||
|
||||
@login_required
|
||||
def annuler_reservation(request:HttpRequest):
|
||||
"""Vue de gestion de l'annulation de la reservation"""
|
||||
if request.method == 'POST':
|
||||
reservation_id= request.POST['id_reservation']
|
||||
try:
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
except Reservation.DoesNotExist:
|
||||
messages.error(request, "La resevertion selectionné n'existe pas.")
|
||||
return redirect("salle")
|
||||
|
||||
reservation.statut = 'annulee'
|
||||
reservation.save()
|
||||
messages.success(request, "Votre réservation a été annulée.")
|
||||
return redirect('gestion_salle:reservation-salle')
|
||||
|
||||
@login_required
|
||||
def valider_reservation(request:HttpRequest):
|
||||
"""Vue de gestion de l'annulation de la reservation"""
|
||||
if request.method == 'POST':
|
||||
reservation_id= request.POST['id_reservation']
|
||||
try:
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
except reservation.DoesNotExist:
|
||||
messages.error(request, "La resevertion selectionné n'existe pas.")
|
||||
return redirect("salle")
|
||||
|
||||
reservation.statut = 'validee'
|
||||
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')
|
||||
|
||||
@login_required
|
||||
def refuser_reservation(request:HttpRequest):
|
||||
"""Vue de gestion de refus de la reservation"""
|
||||
data = json.loads(request.body)
|
||||
reservation_id = data.get("id_reservation")
|
||||
try:
|
||||
reservation = Reservation.objects.get(id=reservation_id)
|
||||
except Reservation.DoesNotExist and ValueError:
|
||||
return JsonResponse({"message": "La resevertion selectionné n'existe pas."})
|
||||
else:
|
||||
reservation.statut = "refusee"
|
||||
reservation.save()
|
||||
return JsonResponse({"message": "Réservation refusée avec succès."})
|
||||
Reference in New Issue
Block a user