Fix: Filtre des produits

This commit is contained in:
2026-09-18 11:03:52 +00:00
parent 165894c92b
commit a8b5ac27d9
9 changed files with 162 additions and 96 deletions

51
Jenkinsfile vendored
View File

@@ -1,51 +0,0 @@
pipeline
{
agent any
options {
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/sgl
echo $SUDO_PASSWORD | sudo -S chown -R jenkins:jenkins /var/www/sgl
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/sgl
echo "Deploiement reussi"
echo $SUDO_PASSWORD | sudo -S supervisorctl restart sgl
'''
}
}
}
}

View File

@@ -15,6 +15,9 @@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" aria-current="page" href="{{ LIEN_SGL }}">SGL</a> <a class="nav-link active" aria-current="page" href="{{ LIEN_SGL }}">SGL</a>
</li> </li>
<li class="nav-item">
<a class="nav-link" aria-current="page" href="#">Laboratoire</a>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View File

@@ -67,33 +67,31 @@
</div> </div>
</div> </div>
<div class="row p-2 justify-content-around"> <div class="row p-2 justify-content-around" id = "cardContainer">
{% for produit in page_obj %} {% for produit in page_obj %}
<div class="col-3"> <div class="col-3">
<div class="card p-2 mt-2" style="width: 13rem;"> <div class="card p-2 mt-2" style="width: 13rem;">
{% if produit.image %} {% if produit.image %}
<img class="card-img-top m-auto d-block" src="{{ produit.image.url }}" style="width: 160px; height: 120px;" alt="{{ produit.libelle }}"> <img class="card-img-top m-auto d-block" src="{{ produit.image.url }}" style="width: 160px; height: 120px;" alt="{{ produit.libelle }}">
{% else %} {% else %}
<img class="card-img-top m-auto d-block" src="https://placehold.co/600x400" style="width: 160px; height: 120px;" alt="Image par défaut"> <img class="card-img-top m-auto d-block" src="https://placehold.co/600x400" style="width: 160px; height: 120px;" alt="Image par défaut">
{% endif %}
<div class="card-body">
<h5 class="card-title text-center produitModifTitre" style="cursor: pointer;" data-idproduit={{ produit.id }}>{{ produit.libelle }}</h5>
<p class="categorie-produit" style="display: none;">{{ produit.categorie_id }} </p>
{% if user|has_group:"logistique" %}
<p class="card-text text-center">
<small>Quantite en stock: {{ produit.stockActuel }}</small>
</p>
<button class="btn btn-warning d-block listeCommanderButton w-100" data-id="{{ produit.id }}">
<i class="bi bi-caret-down-square-fill"></i>
Commander
</button>
{% endif %} {% endif %}
<button class="btn btn-primary d-block w-100 listeDemandeButton mt-1" data-id="{{ produit.id }}"> <div class="card-body">
<i class="bi bi-archive"></i> <h5 class="card-title text-center produitModifTitre" style="cursor: pointer;" data-idproduit={{ produit.id }}>{{ produit.libelle }}</h5>
Demander <p class="categorie-produit" style="display: none;">{{ produit.categorie_id }} </p>
</button> {% if user|has_group:"logistique" %}
</div> <p class="card-text text-center">
</div> <small>Quantite en stock: {{ produit.stockActuel }}</small>
</p>
<button class="btn btn-warning d-block listeCommanderButton w-100" data-id="{{ produit.id }}">
<i class="bi bi-caret-down-square-fill"></i>Commander
</button>
{% endif %}
<button class="btn btn-primary d-block w-100 listeDemandeButton mt-1" data-id="{{ produit.id }}">
<i class="bi bi-archive"></i>Demander
</button>
</div>
</div>
</div> </div>
{% empty %} {% empty %}
<p class="text-center">Aucun produit disponible.</p> <p class="text-center">Aucun produit disponible.</p>

View File

@@ -81,4 +81,14 @@ urlpatterns = [
views.detail_demande, views.detail_demande,
name="detail_demande" name="detail_demande"
), ),
path(
"filtrer-produit-par-categorie/<int:id_categorie>/",
views.filtrer_produit_par_categorie,
name="filtrer_produit_par_categorie"
),
path(
"filtrer-par-nom-produit/",
views.filtre_par_nom_produit,
name="filtrer_par_nom_produit"
),
] ]

View File

@@ -172,7 +172,7 @@ def enregistrer_produit(request):
return redirect("gestion_produit:index") return redirect("gestion_produit:index")
@login_required @login_required
def detail_produit(request, id_produit): def detail_produit(_request, id_produit):
"""Renvoyez les détails d'un produit spécifique au format JSON. """Renvoyez les détails d'un produit spécifique au format JSON.
Parameters Parameters
@@ -422,6 +422,73 @@ def enregistrer_categorie(request):
return JsonResponse({"success": False}) return JsonResponse({"success": False})
return None return None
def filtrer_produit_par_categorie(request, id_categorie):
"""Filtrez les produits par catégorie et renvoyez-les au format JSON.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
id_categorie : int
L'ID de la catégorie pour laquelle filtrer les produits.
Returns
-------
JsonResponse
Réponse JSON contenant la liste des produits filtrés par catégorie.
"""
produits = Produit.objects.filter(categorie_id=id_categorie)
produits_filtres = [
{
"id": produit.id,
"libelle": produit.libelle,
"conditionnement": produit.conditionnement,
"quantite_stock": produit.quantite_stock,
"seuil_pre_rupture": produit.seuil_pre_rupture,
"image": produit.image.url if produit.image else "",
"appartient_logistique": request.user.groups.filter(name="Logistique").exists(),
}
for produit in produits
]
return JsonResponse(produits_filtres, safe=False)
def filtre_par_nom_produit(request):
"""Filtrez les produits par nom et renvoyez-les au format JSON.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
nom_produit : str
Le nom du produit pour lequel filtrer les produits.
Returns
-------
JsonResponse
Réponse JSON contenant la liste des produits filtrés par nom.
"""
nom_produit = request.GET.get("nom", "")
if nom_produit == "":
produits = Produit.objects.all()
else:
produits = Produit.objects.filter(libelle__icontains=nom_produit)
produits_filtres = [
{
"id": produit.id,
"libelle": produit.libelle,
"conditionnement": produit.conditionnement,
"quantite_stock": produit.quantite_stock,
"seuil_pre_rupture": produit.seuil_pre_rupture,
"image": produit.image.url if produit.image else "",
"appartient_logistique": request.user.groups.filter(name="Logistique").exists(),
}
for produit in produits
]
return JsonResponse(produits_filtres, safe=False)
@login_required @login_required
def recuperer_fournisseur_par_categorie(_request, id_produit): def recuperer_fournisseur_par_categorie(_request, id_produit):
"""Récupèrez les fournisseurs associés à la catégorie d'un produit donné. """Récupèrez les fournisseurs associés à la catégorie d'un produit donné.

View File

@@ -84,15 +84,34 @@ document.addEventListener('DOMContentLoaded', function () {
// --------------------------- FILTRE PAR NOM DU PRODUIT ------------------------- // --------------------------- FILTRE PAR NOM DU PRODUIT -------------------------
$('searchInput').addEventListener('keyup', function() { $('searchInput').addEventListener('keyup', function() {
const filter = this.value.toLowerCase(); const filter = this.value.toLowerCase();
const cards = document.querySelectorAll('.card');
cards.forEach(card => { fetch(`/gestion-produit/filtrer-par-nom-produit/?nom=${filter}`)
const title = card.querySelector('.card-title').textContent.toLowerCase(); .then(response => response.json())
if (title.includes(filter)) { .then(data => {
card.style.display = ''; const cardContainer = document.querySelector("#cardContainer");
} else { cardContainer.innerHTML = "";
card.style.display = 'none'; data.forEach(produit => {
} cardContainer.innerHTML += `
<div class="col-3">
<div class="card p-2 mt-2" style="width: 13rem;">
<img class="card-img-top m-auto d-block" src="${produit.image.url ? produit.image : 'https://placehold.co/600x400'}" style="width: 160px; height: 120px;" alt="${produit.libelle}">
<div class="card-body">
<h5 class="card-title text-center produitModifTitre" style="cursor: pointer;" data-idproduit=${produit.id}>${produit.libelle}</h5>
<p class="categorie-produit" style="display: none;">${produit.categorie_id} </p>
${produit.appartient_logistique ? `<p class="card-text text-center">
<small>Quantite en stock: ${produit.stockActuel}</small>
</p> ` : ""}
${produit.appartient_logistique ? `<button class="btn btn-warning d-block listeCommanderButton w-100" data-id="${produit.id}">
<i class="bi bi-caret-down-square-fill"></i>Commander : ${produit.stockActuel}
</button>` : ""}
<button class="btn btn-primary d-block w-100 listeDemandeButton mt-1" data-id="${produit.id}">
<i class="bi bi-archive"></i>Demander
</button>
</div>
</div>
</div>`;
}); });
})
}) })
// Enregistrement de commande // Enregistrement de commande
@@ -138,21 +157,41 @@ document.addEventListener('DOMContentLoaded', function () {
// Filtre des produits par categorie // Filtre des produits par categorie
$("filterCategorie").addEventListener("change", function(){ $("filterCategorie").addEventListener("change", function(){
const card = document.querySelectorAll(".card");
const filtre = this.value; const filtre = this.value;
if(filtre === ""){ if(filtre === ""){
card.forEach(carte => { location.reload();
carte.style.display = "";
});
}else{ }else{
card.forEach(carte => { fetch(`/gestion-produit/filtrer-produit-par-categorie/${filtre}/`)
categorie = carte.querySelector(".categorie-produit").textContent.toLowerCase(); .then(response => response.json())
if(parseInt(categorie) === parseInt(filtre)){ .then(data => {
carte.style.display = ""; console.log(data);
}else{ const cardContainer = document.querySelector("#cardContainer");
carte.style.display = 'none' cardContainer.innerHTML = "";
} data.forEach(produit => {
}); cardContainer.innerHTML += `
<div class="col-3">
<div class="card p-2 mt-2" style="width: 13rem;">
<img class="card-img-top m-auto d-block" src="${produit.image.url ? produit.image : 'https://placehold.co/600x400'}" style="width: 160px; height: 120px;" alt="${produit.libelle}">
<div class="card-body">
<h5 class="card-title text-center produitModifTitre" style="cursor: pointer;" data-idproduit=${produit.id}>${produit.libelle}</h5>
<p class="categorie-produit" style="display: none;">${produit.categorie_id} </p>
<p class="card-text text-center">
<small>Quantite en stock: ${produit.stockActuel}</small>
</p>
${produit.appartient_logistique ? `<button class="btn btn-warning d-block listeCommanderButton w-100" data-id="${produit.id}">
<i class="bi bi-caret-down-square-fill"></i>Commander : ${produit.stockActuel}
</button>` : ""}
${produit.appartient_logistique ? `<button class="btn btn-warning d-block listeCommanderButton w-100" data-id="${produit.id}">
<i class="bi bi-caret-down-square-fill"></i>Commander
</button>` : ""}
<button class="btn btn-primary d-block w-100 listeDemandeButton mt-1" data-id="${produit.id}">
<i class="bi bi-archive"></i>Demander
</button>
</div>
</div>
</div>`;
});
})
} }
}) })