From 5813909eff91cd0599bed9112f82954f51067cef Mon Sep 17 00:00:00 2001 From: Soriba SYLLA Date: Fri, 18 Sep 2026 12:54:44 +0000 Subject: [PATCH] Fix: Integration de la pagination dans le filtre de produit --- Jenkinsfile | 51 -------- SGL/templates/parts/menu_application.html | 3 + .../__pycache__/models.cpython-310.pyc | Bin 4600 -> 4600 bytes .../__pycache__/urls.cpython-310.pyc | Bin 1569 -> 1779 bytes .../__pycache__/views.cpython-310.pyc | Bin 14477 -> 16737 bytes .../templates/gestion_produit/index.html | 73 +++++------ gestion_produit/urls.py | 10 ++ gestion_produit/views.py | 118 +++++++++++++++++- static/js/gestion_produit.js | 30 +---- 9 files changed, 169 insertions(+), 116 deletions(-) delete mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index ee9f705..0000000 --- a/Jenkinsfile +++ /dev/null @@ -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 - ''' - } - } - } -} \ No newline at end of file diff --git a/SGL/templates/parts/menu_application.html b/SGL/templates/parts/menu_application.html index 1868637..bd72bcb 100644 --- a/SGL/templates/parts/menu_application.html +++ b/SGL/templates/parts/menu_application.html @@ -15,6 +15,9 @@ + diff --git a/gestion_produit/__pycache__/models.cpython-310.pyc b/gestion_produit/__pycache__/models.cpython-310.pyc index 0b38abe764d3df44df2bd58f8a1b86c8e4c4dc12..8b85b9927a606bad2a4822e8d8b834cd5faa0037 100644 GIT binary patch delta 19 ZcmeyN{6m>5pO=@50SIhaH*&ob1OPTl1keBg delta 19 ZcmeyN{6m>5pO=@50SI!LHgdfa1OPW%1pNR2 diff --git a/gestion_produit/__pycache__/urls.cpython-310.pyc b/gestion_produit/__pycache__/urls.cpython-310.pyc index 012669b6d824742dafa93b6c99eae32a59b8c4d8..03f22ba7cd06b315353ec1da343ce935d9a6476a 100644 GIT binary patch delta 308 zcmZ3;^O;vCpO=@50SLB9tU>d4WlB*iQ z)b#wK%v61w%)An-%#?Vzh@Ji|S*VtHsFrx37KDN-3Al+slk)O&VJ7R}5{GL9Y5>Z_ z7jQx>_0yEte3UtW(YOfYm0MyEbzpPB${?z4ahDe56eO0Eq!#5BuVg6F0IDt0n5@kj T#JFX09qYo$=UGLVIMxFIl$&BM delta 113 zcmey&yO2jGpO=@50SJ!yPtE$m&cN^(#6bqaK#l_t7yn|IsPly@oj*!6MIo3$Q*pB! z;|wNdKTWaCX)FPZVz;hC9jm7l%g5IU`{Z4<*!__2KR_pFkcO5?qTLG8Fs)nmTqlVR8lm;eo%Xkb_;o&`6sky$k4O z+9K)QK)2F1NymV0ryY{+2D+1WNxBEec^Zj!5N3Amn6*xr)j z{yX~Sycg!R{2|GqvcnaQ@?pv1a}1c!SIA8QOS!CjDvO<#tSURb$*EA^HqQF(GaG9i z@ocSzA++o%X(u2Eu6iAR$xF@a%2oYvMV|mj=PT)}X2}PX;RH$^8gznA$O$`jP6VDp zG`ymejFL+0UiDp9!4Hx3U-~q1Qs}moVsjUTN7T)yvyR1%ryOgcz|xlR&ux&b1?;&- zL^PYeU}dvbGMSz$7&N<$9ss zdGai4gIR`tW~~51O=Yue7d{3N+7WaF4L}$WK*`0_g2faZt4D|+L=hSgFplDWwj2IL zP)a)IB=f19CBmCFz~?559YLND3T-7TI`N;FW2f(c@ml4)={&WbnuQtrEI_y}Od=$r zL;-bT5apJxXrD*aEn3&2a#ZrC5JAM3l#*;ZDP( z@Xp+Q>f{+=r0wLTR5ne8W~VM$3^S0a03e~Xr#4?;xf&5ggOz920vM55Y{QJN^R7rQ zd2Ib?j5C-{d^K{|? zBp(EbhuK3&%a>%hZi!R#rgW0j%*Hn!LD;lnT$5I0i~N)3=E!-RtJ0c#Tl&fG_z++b zELASc?d1NtyT6QaIr{MC;^-Zgs96dgMPs#BASZJvh+hq=sBOZushSY9@Kx9)c-&TZ zaY^{``&w6|3^Q>ebX+0roOSJCy7I_$tC2?*_YPQrbs{t&;DT}0)%{VRg_%nwsU;<< zwg66T3ntp@GQr8~u~B>x4W3z?=Egk9#>+Md^AFv+@Qfc3SXArt(m_A%1L*V<3r zC*wi7=_|-oLXcuz14;yP1t&e9WY&DquH>Qc?JS#&$sT^9W2W&Gyb4DgmKrzsKs)|g zN6&DTKXGmupc91;1ED~1&~NFg643t<46|ka$Bs7|F#O`W@KXyaaCWwkV`+Y~bMjua zUOdD?@F(k{8~0nf$QY9fJ&i05Rb=cL{%Utu6Xr$w1<(rP!gf+l(ProP2i@N&*JO!X zr*Pvl-NpSDXctqG@L(*AangVQVOzr-4LF^ zfx8gyM!=P7EGt@=HCJ4;upnmB{7`?OYZ;>eLpV}rlAvM|MNxrF8Ni*qNw)|3$CANAkS4R=fA8X~y6aC+s|$x{OsCior!uRWR*^zQ78_MO*euLbouxY_=a}p#R#9Tzv@Grm;z^BJX2-Gy|b~lz{e64Ppbo z5fUZZzw}#I_E*fkaiH__gMDRL_Oz;`k=@xwoq@$fFin%2-G?wLIc$r_29Q0S&P?;Bni*g?$dX7BkkyrE4w>?vZ+hZ zi>>5M9LeYq@)|hROXaBJ+je14sZPs2Xx!Z_(4e)~r~!?;x3Y;JmeNb!Rewpx4&E`L zQ#YN!M&}Ms0UCt9-3Qqds`TyQ;)NZvr;DG^`v3A}MDlFp3%poK6rlnwqgh@S*bvxq>t;~K`ou;NWKiux3PY`?3d-~H zub?2i4JNM)x&leZRw*!gI9r%YW$oL6fS{GP2Zk-mR&jssxrN93B(yMN4)SGM}NF#!=ZKPw*cN_6MY|-73QW zFgVcC2B(OP9tcO_3Zy7r{og@@y|q3#^f7@3%osUP#zMoc0nEgWs!C?#a0=l90!28F zFb4o0u0vWj`{+#JPc1CK1p^LuhBk7W32blVo$T-6iQe#X}mn#%6K|=&}+I9+aPh3PRz|UjW zv3J(n$6iv~rPfJ&SDI5Qx`vP6VV{g~KG6vl+8kB#k@=7}glI2WORQi4jS j(rPHC`I#~SUDYA}LylV z zT!^@@6gDHd2yj0Sl%i%V7c=9zxY?2GFgtUdW>>C@)`F#OGm%S}dvbfsWG-p;*Vz=686JGH%|~x1K-1w#0P-)@D%Yu z;Jv($_z>`Zo+iE*_y8XyJ`8+_?9)WPA}mML4c05)Rwr3T{#upwQ4kjyz{5WukP!Tzgnvr_*sgVUSNXto*Ui}n>?*T8 zt!D+E74GJq8?G8V1;M=Pw!Jks_g+`7dTOq9^{$Vru*X~T-1XPIz*IX>b8(*?v_p2- zj@Zd4JVGvSDK)jG@ZfvC>u&Hb)VSsMu(;R*=R1L7!PeI*!qDZX(L`n$4eJJ2bJbkm zQo$fN{5soIE-1?`k%0wGb_A1;X^Nv9n09;{qQa|&O)E_pL9N00l404!in+1yZFsii z*MrabH6{j0!OwzM*+v`h4e`PEh?TuPA_2{Z8N9sP09^< zwu<|nMQ8<3^H2ckTqpizRppJcWf#gtU7W?ukHWx4Ed(1ouFCBbKNXJ7i{y3T6;&iaQS|(n*JPKvGA;>bzv5S zj|w*WnJCHM^uD2D--{u+(znJm`HQ}329vaJ=?o>D@=(SN6$CQq0x&0JR%~N6FZ9)_ z^<{rKzTK^&qU)5e_AhoXz^gE-aTqkK3;dG*=pWvfK?wo+Aua)gVK!S)Ac|XM>KCe8 z390`IN5v&Mo&Hf5)|aL_0j}Exqm-?f;+*^>J^L)iO^b*ye9`1;7WN}wsEEiR3%8J0 zZBfU&dAQp59)1gFpH|FyjyNK;Zqge%2w>tmvI=h@*r&7 zi~XRf%`p;eH2@cNT>KsadAy4+PNcfQLvYLF$sqfnoE-Tkd#&;Pkt?i@caWGuz&R`S zBj7;R0^2&3jHR2wgX@nYP%|GwhW7!E5ae?RUqLv6fSTGO>m-F`I2LkA;{m zZ;th`*Bd__`-tT!#;4)EmBlRhOJSqSh87<6DrK-aR)xOHF^TO{wKdFd%fC(}+090E z`aevi`86-^cl93;FM$e;LETb%W95pOU#(O{*|03g?n8ML<$4(=^@cDk9mEsz{=rnD zt#~Fu*{_)V_rdHOb%SqPEGcdgG&qGowMxEt#c>oA5j1&iW;C=-tNd_gB6$zH1$By@!=o3d)s=QJiCoX-I6!wGm{c1 z<_5L-aW3yNM`>aW%a7)3>@E4?(cjJOrqe>5?;unWb{a|=X65q2`J)tZLAmx*dpKTe zqh#2Qs$aJCGH(lTGoX}p=xF)b!jT=hK6Q*4FIjZS%NLG!*BvkZ;;@>()ToU*&=I^VniKj7 zWG4`^2pr)&f`L#%z(FmpA-sn0I>JqaO$1Dcl`5USGA-sKqg%l r7M{lySHg@wN?7Svdi+W-_&;R^F4rkJ{?&=7k^(xQOb3|~kFx&*SR&4{ diff --git a/gestion_produit/templates/gestion_produit/index.html b/gestion_produit/templates/gestion_produit/index.html index b07a5e8..c4696a5 100644 --- a/gestion_produit/templates/gestion_produit/index.html +++ b/gestion_produit/templates/gestion_produit/index.html @@ -54,46 +54,49 @@
-
- -
-
- -
+
+
+ +
+
+ +
+
+ +
+
-
+
{% for produit in page_obj %}
-
- {% if produit.image %} - {{ produit.libelle }} - {% else %} - Image par défaut - {% endif %} -
-
{{ produit.libelle }}
- - {% if user|has_group:"logistique" %} -

- Quantite en stock: {{ produit.stockActuel }} -

- +
+ {% if produit.image %} + {{ produit.libelle }} + {% else %} + Image par défaut {% endif %} - -
-
+
+
{{ produit.libelle }}
+ + {% if user|has_group:"logistique" %} +

+ Quantite en stock: {{ produit.stockActuel }} +

+ + {% endif %} + +
+
{% empty %}

Aucun produit disponible.

diff --git a/gestion_produit/urls.py b/gestion_produit/urls.py index ac8d6c6..1f34f6b 100644 --- a/gestion_produit/urls.py +++ b/gestion_produit/urls.py @@ -81,4 +81,14 @@ urlpatterns = [ views.detail_demande, name="detail_demande" ), + path( + "filtrer-produit-par-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" + ), ] diff --git a/gestion_produit/views.py b/gestion_produit/views.py index b491173..a5bc386 100644 --- a/gestion_produit/views.py +++ b/gestion_produit/views.py @@ -2,7 +2,7 @@ from django.shortcuts import render, redirect from django.core.paginator import Paginator -from django.db.models import Sum +from django.db.models import Sum, Q from authentification.models import Profile from django.contrib.auth.decorators import login_required @@ -90,9 +90,25 @@ def index(request): La réponse HTTP contenant la page rendue. """ - liste_produit = Produit.objects.all().order_by("-id") + product_name = request.GET.get("search", "") + categorie_name = request.GET.get("filterCategorie", "") liste_categorie = Categorie.objects.all().order_by("categorie") + if product_name == "" and categorie_name == "": + liste_produit = Produit.objects.all().order_by("-id") + elif product_name != "" and categorie_name == "": + liste_produit = Produit.objects.filter( + Q(libelle__icontains=product_name) + ).order_by("-id") + elif product_name == "" and categorie_name != "": + liste_produit = Produit.objects.filter( + Q(categorie=categorie_name) + ).order_by("-id") + else: + liste_produit = Produit.objects.filter( + Q(categorie=categorie_name) & Q(libelle__icontains=product_name) + ).order_by("-id") + liste_produit_finale = [ calcul_stock_produit(produit) for produit in liste_produit ] @@ -172,7 +188,7 @@ def enregistrer_produit(request): return redirect("gestion_produit:index") @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. Parameters @@ -422,6 +438,102 @@ def enregistrer_categorie(request): return JsonResponse({"success": False}) 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 == "": + liste_produit = Produit.objects.all().order_by("-id") + else: + liste_produit = Produit.objects.filter(libelle__icontains=nom_produit).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, 1) + + 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, + }, + ) + # ----------------------------------------------------------- + # 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 def recuperer_fournisseur_par_categorie(_request, id_produit): """Récupèrez les fournisseurs associés à la catégorie d'un produit donné. diff --git a/static/js/gestion_produit.js b/static/js/gestion_produit.js index 7eecfe7..e9feffa 100644 --- a/static/js/gestion_produit.js +++ b/static/js/gestion_produit.js @@ -82,17 +82,8 @@ document.addEventListener('DOMContentLoaded', function () { }) // --------------------------- FILTRE PAR NOM DU PRODUIT ------------------------- - $('searchInput').addEventListener('keyup', function() { - const filter = this.value.toLowerCase(); - const cards = document.querySelectorAll('.card'); - cards.forEach(card => { - const title = card.querySelector('.card-title').textContent.toLowerCase(); - if (title.includes(filter)) { - card.style.display = ''; - } else { - card.style.display = 'none'; - } - }); + $('searchInput').addEventListener('submit', function() { + $('searchForm').submit(); }) // Enregistrement de commande @@ -138,22 +129,7 @@ document.addEventListener('DOMContentLoaded', function () { // Filtre des produits par categorie $("filterCategorie").addEventListener("change", function(){ - const card = document.querySelectorAll(".card"); - const filtre = this.value; - if(filtre === ""){ - card.forEach(carte => { - carte.style.display = ""; - }); - }else{ - card.forEach(carte => { - categorie = carte.querySelector(".categorie-produit").textContent.toLowerCase(); - if(parseInt(categorie) === parseInt(filtre)){ - carte.style.display = ""; - }else{ - carte.style.display = 'none' - } - }); - } + $('searchForm').submit(); }) // Enregistrement de nouveau produit