Files
sgl/gestion_produit/views.py

523 lines
16 KiB
Python
Raw Normal View History

2025-12-19 09:43:33 +00:00
"""Views pour la gestion des produits."""
from django.shortcuts import render, redirect
from django.core.paginator import Paginator
from django.db.models import Sum
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from .models import (
Categorie,
Produit,
Demander,
Fournisseur,
Commander
)
from .forms import (
EnregistrementProduit,
EnregistrementCategorie,
CommanderProduit,
DemanderProduit,
)
PRODUIT_NON_A__RENDRE = False
PRODUIT_NON_RENDU = False
def gestion_affichage_demande(
request,
option_validation_chef,
ordre_inverse=False
):
"""Affichez les demandes de produit selon le profil de l'utilisateur.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
option_validation_chef : bool or None
Filtre pour la validation par le chef de département.
1- True : demandes validées par le chef.
2- False : demandes non validées par le chef.
3- None : demandes en attentes.
ordre_inverse : bool, optional
Si True, les demandes sont triées par ordre décroissant,
par défaut False.
Returns
-------
QuerySet:
Ensemble des demandes filtrées selon les critères spécifiés.
"""
mes_demandes = Demander.objects.filter(
valider_par_chef=option_validation_chef, user=request.user.profile
)
demandes_departement = None
if request.user.profile.chef_departement:
demandes_departement = Demander.objects.filter(
valider_par_chef=option_validation_chef,
user__departement=request.user.profile.departement,
)
if ordre_inverse:
return (
(mes_demandes | demandes_departement).order_by("-id")
if demandes_departement
else mes_demandes
)
return (
(mes_demandes | demandes_departement)
if demandes_departement
else mes_demandes
)
@login_required(login_url="login")
def index(request):
"""Gérer le rendu de la page d'accueil de la gestion des produits.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
HttpResponse
La réponse HTTP contenant la page rendue.
"""
liste_produit = Produit.objects.all().order_by("-id")
liste_categorie = Categorie.objects.all().order_by("categorie")
liste_produit_finale = [
calcul_stock_produit(produit) for produit in liste_produit
]
pagination = Paginator(liste_produit_finale, 8)
page_number = request.GET.get("page")
page_obj = pagination.get_page(page_number)
return render(
request,
"gestion_produit/index.html",
{
"formulaireEnregistrementCategorie": EnregistrementCategorie,
"formulaireEnregistrementProduit": EnregistrementProduit,
"formulaireCommanderProduit": CommanderProduit,
"formulaireDemanderProduit": DemanderProduit,
"mes_demandes": gestion_affichage_demande(
request, option_validation_chef=None
),
"page_obj": page_obj,
"liste_categorie": liste_categorie,
},
)
def liste_categories(request): # noqa: ARG001
"""Récupère et renvoie la liste des catégories de produits au format JSON.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
JsonResponse
Réponse JSON contenant la liste des catégories de produits.
"""
mes_categories = [
{"categorie": categorie.categorie}
for categorie in Categorie.objects.all()
]
return JsonResponse(mes_categories, safe=False)
@login_required(login_url="login")
@csrf_exempt
def enregistrer_produit(request):
"""Enregistre un nouveau produit à partir des données POST.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
JsonResponse
Réponse JSON indiquant le succès ou l'échec de l'enregistrement.
"""
if request.method == "POST":
p = EnregistrementProduit(request.POST, request.FILES)
if p.is_valid():
p.save()
return JsonResponse(
{"success": True, "message": "Produit enregistré avec succès"}
)
return JsonResponse(
{
"success": False,
"message": "L'enregistrement du produit a échoué",
}
)
return redirect(index)
@login_required(login_url="login")
def enregistrer_commande(request):
"""Enregistrez une nouvelle commande de produit."""
if request.method == "POST":
form = CommanderProduit(request.POST)
if form.is_valid():
form.save()
return redirect("gestion_produit:index")
@login_required(login_url="login")
def enregistrer_demande(request):
"""Enregistrez une nouvelle demande de produit."""
if request.method == "POST":
form = DemanderProduit(request.POST)
if form.is_valid():
ma_demande = form.save(commit=False)
ma_demande.user = request.user.profile
if request.user.profile.chef_departement:
ma_demande.valider_par_chef = True
ma_demande.save()
return redirect("gestion_produit:index")
@login_required(login_url="login")
def liste_demandes(request):
"""Retournez la liste des demandes de produits au format JSON."""
liste_demandes = gestion_affichage_demande(
request, option_validation_chef=True, ordre_inverse=True
)
les_demandes = [
{
"dateDemande": demande.date_de_mise_a_dispo_souhaite,
"produit": demande.produit.libelle,
"motifs": demande.motifs,
"a_rendre": demande.a_rendre,
"dateDeMiseADispoSouhaite": demande.date_de_mise_a_dispo_souhaite,
"valider_par_chef": demande.valider_par_chef,
"valider_par_logisticien": demande.valider_par_logisticien,
"motifs_refus": demande.motif_refus,
}
for demande in liste_demandes
]
return JsonResponse(les_demandes, safe=False)
@login_required(login_url="login")
def detail_demande(request, id_demande):
"""Renvoyez les détails d'une demande spécifique de produit."""
detail_demande = Demander.objects.get(id=id_demande)
demande = {
# "image": detail_demande.produit.image.url,
"detailNom": detail_demande.produit.libelle,
"detailCategorie": detail_demande.produit.categorie.categorie,
"detailmotif": detail_demande.motifs,
"detailDeMiseADispo": detail_demande.date_de_mise_a_dispo_souhaite,
"detailARendre": detail_demande.a_rendre,
"chef_departement": request.user.profile.chef_departement,
}
return JsonResponse(demande)
@login_required(login_url="login")
@csrf_exempt
def update_statut(request):
"""Met à jour le statut d'une demande de produit.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
request.id : int
L'ID de la demande à mettre à jour.
request.action : str
L'action à effectuer ('confirmer' ou 'refuser').
request.emetteur : str
L'émetteur de la demande ('chef' ou 'logisticien').
request.motif_refus : str
Le motif de refus (si applicable).
Returns
-------
JsonResponse
Réponse JSON indiquant le succès ou l'échec de la mise à jour.
"""
if request.method == "POST":
produit_id = request.POST.get("id")
action = request.POST.get("action")
emetteur = request.POST.get("emetteur")
motifs = request.POST.get("motif_refus")
try:
demande = Demander.objects.get(id=produit_id)
except Demander.DoesNotExist:
return JsonResponse(
{
"success": False,
"message": "Demande introuvable"
},
status=404
)
if action == "1":
if emetteur == "chef":
demande.valider_par_chef = True
elif emetteur == "logisticien":
demande.valider_par_logisticien = True
elif action == "0":
if emetteur == "chef":
demande.valider_par_chef = False
elif emetteur == "logisticien":
demande.valider_par_logisticien = False
demande.motif_refus = motifs
else:
return JsonResponse(
{"success": False, "message": "Action invalide"}, status=400
)
demande.save()
return JsonResponse({"success": True, "message": "Statut mis à jour"})
return JsonResponse(
{"success": False, "message": "Méthode non autorisée"}, status=405
)
@login_required(login_url="login")
def recuperer_liste_produit(request):
"""Récupèrez et renvoyez la liste des produits paginée.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
HttpResponse
La réponse HTTP contenant la page rendue avec la liste des produits.
"""
liste_produit = Produit.objects.all().order_by("-id")
pagination = Paginator(liste_produit, 8)
page_number = request.GET.get("page")
page_obj = pagination.get_page(page_number)
return render(
request,
"gestion_produit/index.html",
{"page_obj": page_obj}
)
@login_required(login_url="login")
@csrf_exempt
def enregistrer_categorie(request):
"""Enregistrez une nouvelle catégorie de produit.
Cette vue est appelée via une requête AJAX avec la méthode POST et
enregistre une nouvelle.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
JsonResponse
Réponse JSON indiquant le succès ou l'échec de l'enregistrement.
"""
if request.method == "POST":
categories = EnregistrementCategorie(request.POST)
if categories.is_valid():
categories.save()
return JsonResponse({"success": True})
return JsonResponse({"success": False})
return None
@login_required(login_url="login")
def recuperer_fournisseur_par_categorie(request, id_produit): # noqa: ARG001
"""Récupèrez les fournisseurs associés à la catégorie d'un produit donné.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
id_produit : int
L'ID du produit dont on veut récupérer les fournisseurs.
Returns
-------
JsonResponse
Réponse JSON contenant la liste des fournisseurs associés à la
catégorie du produit.
"""
produit = Produit.objects.get(id=id_produit)
fournisseur = Fournisseur.objects.filter(categorie=produit.categorie)
produit_founisseur = [
{
"id": fournisseur_produit.id,
"nom_fournisseur": fournisseur_produit.nom_entreprise,
}
for fournisseur_produit in fournisseur
]
return JsonResponse(produit_founisseur, safe=False)
# @login_required(login_url="login")
def calcul_stock_produit(produit):
"""Calculez le stock actuel d'un produit donné.
Parameters
----------
produit : Produit
L'instance du produit pour lequel calculer le stock.
Returns
-------
dict
Dictionnaire contenant les détails du produit et son stock actuel.
"""
quantite_livrer = (
Commander.objects.filter(livrer=True, produit=produit).aggregate(
Sum("quantite_commander")
)["quantite_commander__sum"]
or 0
)
produit_demander_a_rendre = Demander.objects.filter(
produit=produit,
valider_par_logisticien=True,
)
quantite_produit_sortis = 0
for produit_demander in produit_demander_a_rendre:
if (
(produit_demander.a_rendre and produit_demander.rendu is False)
or produit_demander.a_rendre is False
):
quantite_produit_sortis += produit_demander.quantite
## Stock actuel = Quantite initiale + total livrer - quantiteSorties
stock_actuel = (produit.quantite_stock
+ quantite_livrer
- quantite_produit_sortis)
return {
"id": produit.id,
"libelle": produit.libelle,
"quantite_stock": produit.quantite_stock,
"conditionnement": produit.conditionnement,
"seuil_pre_rupture": produit.seuil_pre_rupture,
"image": produit.image,
"categorie_id": produit.categorie_id,
"stockActuel": stock_actuel,
}
@login_required(login_url="login")
def mouvement_stock(request):
"""Rendez la page de mouvement de stock.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
Returns
-------
HttpResponse
La réponse HTTP contenant la page rendue.
"""
return render(request, "gestion_produit/mouvement_stock.html")
@login_required(login_url="login")
def rapport_mouvement_stock(request):
"""Générez un rapport de mouvement de stock basé sur les filtres donnés.
Parameters
----------
request : HttpRequest
La requête HTTP entrante.
request.GET["dateFiltre"] : str
La date de filtre au format "YYYY-MM".
request.GET["typeFiltre"] : str
Le type de filtre ("entree" ou "sortie").
Returns
-------
JsonResponse
Réponse JSON contenant le rapport de mouvement de stock.
"""
mes_commandes = []
date_filtre = request.GET["dateFiltre"]
annee, mois = date_filtre.split("-")
type_filtre = request.GET["typeFiltre"]
if type_filtre == "entree":
mes_commandes.extend([
{
"produit": commande.produit.libelle,
"categorie": commande.produit.categorie.categorie,
"conditionnement": commande.produit.conditionnement,
"fournisseur": commande.fournisseur.nom_entreprise,
"date_commande": commande.date_commande,
"date_livraison": commande.date_livraison,
"quantite_commander": commande.quantite_commander,
}
for commande in Commander.objects.filter(
date_livraison__year=annee,
date_livraison__month=mois,
livrer=True
)
])
elif type_filtre == "sortie":
mes_commandes.extend([
{
"produit": demande.produit.libelle,
"categorie": demande.produit.categorie.categorie,
"conditionnement": demande.produit.conditionnement,
"date_demande": demande.dateDemande,
# "date_mise_a_dispo": commande.date_commande,
"quantite_demander": demande.quantite,
}
for demande in Demander.objects.filter(
dateDemande__year=annee,
dateDemande__month=mois,
valider_par_logisticien=True,
)
])
return JsonResponse(mes_commandes, safe=False)