"""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, ) 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): """Recuperez et renvoyez la liste des catégories de produit 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") def enregistrer_produit(request): """Enregistrez 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": form = EnregistrementProduit(request.POST, request.FILES) if form.is_valid(): form.save() return JsonResponse( {"success": True, "message": "Produit enregistré avec succès"} ) return JsonResponse( { "success": False, "message": "L'enregistrement du produit a échoué", } ) return redirect("gestion_produit:index") @login_required(login_url="login") def detail_produit(request, id_produit): """Renvoyez les détails d'un produit spécifique au format JSON. Parameters ---------- request : HttpRequest La requête HTTP entrante. id_produit : int L'ID du produit dont on veut récupérer les détails. Returns ------- JsonResponse Réponse JSON contenant les détails du produit. """ detail_produit = calcul_stock_produit(Produit.objects.get(id=id_produit)) categories = Categorie.objects.all() produit = { "detailId": detail_produit["id"], "detailLibelle": detail_produit["libelle"], "detailCategorie": detail_produit["categorie_id"], "detailConditionnement": detail_produit["conditionnement"], "detailSeuilPreRupture": detail_produit["seuil_pre_rupture"], "detailQuantiteStock": detail_produit["stockActuel"], "detailImage": detail_produit["image"].url if detail_produit["image"] else "", "listeCategorie": [ {"id": categorie.id, "categorie": categorie.categorie} for categorie in categories ], } return JsonResponse(produit) @login_required(login_url="login") def enregistrer_modification_produit(request): """Enregistrez les modifications apportées au 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": id_produit = request.POST.get("id_produit") produit_instance = Produit.objects.get(id=id_produit) produit_instance.libelle = request.POST.get("libelle") produit_instance.conditionnement = request.POST.get("conditionnement") produit_instance.seuil_pre_rupture = request.POST.get("seuil_pre_rupture") categorie_id = request.POST.get("categorie") produit_instance.categorie = Categorie.objects.get(id=categorie_id) produit_instance.quantite_stock = request.POST.get("quantite_stock") produit_instance.save() return JsonResponse( {"success": True, "message": "Produit modifié avec succès"} ) return redirect("gestion_produit: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 = { "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") 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 : int L'action effectuée 1: Pour confirmer 0: Pour refuser request.emetteur : str L'émetteur de la demande ('chef' ou 'logisticien'). request.motif_refus : str Le motif de refus. 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") if not all([produit_id, action, emetteur]): return JsonResponse( {"success": False, "message": "Données manquantes"}, status=400 ) try: demande = Demander.objects.get(id=produit_id) except Demander.DoesNotExist: return JsonResponse( {"success": False, "message": "Demande introuvable"}, status=404 ) match action, emetteur: case "1", "chef": demande.valider_par_chef = True case "1", "logisticien": demande.valider_par_logisticien = True case "0", "chef": demande.valider_par_chef = False case "0", "logisticien": demande.valider_par_logisticien = False demande.motif_refus = motifs case _: return JsonResponse( {"success": False, "message": "Données invalides"}, 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és. 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") 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): """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) 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 = (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): """Retournez 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_entree": commande.produit.libelle, "categorie_entree": commande.produit.categorie.categorie, "conditionnement_entree": commande.produit.conditionnement, "fournisseur_entree": commande.fournisseur.nom_entreprise, "date_commande_entree": commande.date_commande, "date_livraison_entree": commande.date_livraison, "quantite_commander_entree": 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_sortie": demande.produit.libelle, "categorie_sortie": demande.produit.categorie.categorie, "conditionnement_sortie": demande.produit.conditionnement, "date_demande_sortie": demande.date_de_mise_a_dispo_souhaite, # "date_mise_a_dispo": commande.date_commande, "quantite_demander_sortie": demande.quantite, } for demande in Demander.objects.filter( date_de_mise_a_dispo_souhaite__year=annee, date_de_mise_a_dispo_souhaite__month=mois, valider_par_logisticien=True, ) ]) return JsonResponse(mes_commandes, safe=False)