Modifications:

- Row/column seperations in the stock table (better clarity)
- Fixed a bug that showed artifacts of the first page when going to the last page after adding a new item
- Adding the basket to the right of the screen
- Added buttons to add and remove items from the cart in the stock table
- Changing the dimensions and placement of certain elements to air out the interface
This commit is contained in:
Mylloon 2021-11-29 13:02:52 +01:00
parent 64e6789ae2
commit 513a0599e0

147
main.py
View file

@ -1,6 +1,6 @@
# Tkinter
from tkinter import IntVar, Checkbutton, LabelFrame, PhotoImage, Scrollbar, Listbox, Entry, Button, Label, Frame, Tk, Toplevel
from tkinter.ttk import Combobox
from tkinter.ttk import Combobox, Separator
from tkinter.messagebox import showerror, showinfo, showwarning, askyesno
from tkinter.filedialog import askopenfile
# Regex
@ -22,9 +22,11 @@ class GesMag:
self.nomApp = "GesMag" # nom de l'application
self.parent = Tk() # fenêtre affiché à l'utilisateur
self.parent.resizable(False, False) # empêche la fenêtre d'être redimensionnée
self.f = Frame(self.parent) # `Frame` affiché à l'écran
self.f = Frame(self.parent) # `Frame` "principale" affiché à l'écran
self.tableau = Frame() # `Frame` qui va afficher le tableau des éléments présents dans le stock
self.imagesStock = [] # liste qui va contenir nos images pour l'affichage du stock
self.dossierImage = PhotoImage(file = "img/dossier.gif") # image pour l'icone de selection
self.panierAffichage = Frame() # `Frame` qui va afficher le panier
self.panier = [] # liste des éléments "dans le panier"
def demarrer(self) -> None:
@ -199,7 +201,7 @@ class GesMag:
"""Affiche l'interface du caissier."""
caissier = Utilisateurs().recuperationUtilisateur(id=id)
self.parent.title(f"Caissier {caissier['nom']} {caissier['prenom']} {self.nomApp}")
self.dimensionsFenetre(self.parent, 1030, 690)
self.dimensionsFenetre(self.parent, 1100, 710)
# Suppresssion de la dernière Frame
self.f.destroy()
@ -224,26 +226,67 @@ class GesMag:
def __formatPrix(prix: str) -> str:
return f"{float(prix):.2f}".replace('.', ',')
def __affichageTableau(parent: Frame, page: int = 1):
def __affichageTableau(page: int = 1):
"""Fonction qui va actualiser le tableau avec une page donnée (par défaut affiche la première page)."""
# On supprime et refais la frame qui va stocker notre tableau
parent.destroy()
parent = Frame(stock)
parent.grid(column=0, row=1, columnspan=6)
self.tableau.destroy()
self.tableau = Frame(stock)
self.tableau.grid(column=0, row=1, columnspan=7)
# Filtre pour le tableau
filtres = Frame(stock) # Morceau qui va contenir nos checkbutton
ecartFiltre = 10 # écart entre les champs des filtres
Label(filtres, text="Filtre", font=self.font).grid(column=0, row=0) # titre
Checkbutton(filtres, text="Stock disponible\nuniquement", variable=stockDisponibleVerif, command=lambda: __affichageTableau(parent)).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les\nfruits & légumes", variable=fruitsLegumesVerif, command=lambda: __affichageTableau(parent)).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les produits de\nla boulangerie", variable=boulangerieVerif, command=lambda: __affichageTableau(parent)).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les produits de\nla boucherie\net poissonnerie", variable=boucheriePoissonnerieVerif, command=lambda: __affichageTableau(parent)).grid(sticky='w')
Checkbutton(filtres, text="Cacher les produits\nd'entretien", variable=entretienVerif, command=lambda: __affichageTableau(parent)).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Stock disponible\nuniquement", variable=stockDisponibleVerif, command=__affichageTableau).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les\nfruits & légumes", variable=fruitsLegumesVerif, command=__affichageTableau).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les produits de\nla boulangerie", variable=boulangerieVerif, command=__affichageTableau).grid(sticky='w', pady=ecartFiltre)
Checkbutton(filtres, text="Cacher les produits de\nla boucherie\net poissonnerie", variable=boucheriePoissonnerieVerif, command=__affichageTableau).grid(sticky='w')
Checkbutton(filtres, text="Cacher les produits\nd'entretien", variable=entretienVerif, command=__affichageTableau).grid(sticky='w', pady=ecartFiltre)
filtres.grid(column=7, row=1, sticky='w')
stockListe = Stock().listeStocks() # stock récupéré de la base de données
def ___miseAJourPanier(element: dict, action: bool):
"""
Permet d'ajouter ou de retirer des éléments au panier
-> Action
-> Vrai : Ajout
-> Faux : Retire
"""
# On compte combien de fois l'élément est présent dans le panier
nombreDeFoisPresentDansLePanier = 0
index = None
for idx, elementDansLePanier in enumerate(self.panier):
if elementDansLePanier[0] == element:
index = idx # On met à jour l'index
nombreDeFoisPresentDansLePanier = elementDansLePanier[1]
break # on peut quitter la boucle car on a trouvé notre élément
# On vérifie que on peut encore l'ajouter/retirer
if nombreDeFoisPresentDansLePanier == 0 and not action: # pop-up seulement si on veut retirer un élément pas présent
showerror("Erreur", "Impossible de retirer cet élément au panier.\nNon présent dans le panier.")
return
if nombreDeFoisPresentDansLePanier >= element["quantite"] and action: # pop-up seulement si on veut en rajouter
showerror("Erreur", "Impossible de rajouter cet élément au panier.\nLimite excédée.")
return
if index != None: # on retire l'ancienne valeur du panier si déjà présente dans le panier
self.panier.pop(index)
else: # sinon on définie un index pour pouvoir ajouté la nouvelle valeur à la fin de la liste
index = len(self.panier)
# On change la valeur dans le panier
if action: # si on ajoute
nombreDeFoisPresentDansLePanier += 1
else: # si on retire
nombreDeFoisPresentDansLePanier -= 1
# On rajoute l'élément avec sa nouvelle quantité seulement s'il y en a
if nombreDeFoisPresentDansLePanier > 0:
self.panier.insert(index, (element, nombreDeFoisPresentDansLePanier))
___affichagePanier() # Met-à-jour le panier
for i in range(0, len(stockListe)): # on retire les éléments plus présent dans la liste
if stockDisponibleVerif.get() == 1 and stockListe[i]["quantite"] < 1:
stockListe[i] = None
@ -270,18 +313,23 @@ class GesMag:
limiteIndex = elementsParPage * page # on définit une limite pour ne pas afficher plus d'éléments qu'il n'en faut par page
if len(stockListe) > 0: # si stock non vide
# Définition des colonnes
Label(parent, text="ID").grid(column=0, row=0, padx=ecart)
Label(parent, text="Image").grid(column=1, row=0, padx=ecart)
Label(parent, text="Type").grid(column=2, row=0, padx=ecart)
Label(parent, text="Nom").grid(column=3, row=0, padx=ecart)
Label(parent, text="Quantité").grid(column=4, row=0, padx=ecart)
Label(parent, text="Prix unité").grid(column=5, row=0, padx=ecart)
Label(self.tableau, text="ID").grid(column=0, row=0, padx=ecart)
Label(self.tableau, text="Image").grid(column=1, row=0, padx=ecart)
Label(self.tableau, text="Type").grid(column=2, row=0, padx=ecart)
Label(self.tableau, text="Nom").grid(column=3, row=0, padx=ecart)
Label(self.tableau, text="Quantité").grid(column=4, row=0, padx=ecart)
Label(self.tableau, text="Prix unité").grid(column=5, row=0, padx=ecart)
Label(self.tableau, text="Action").grid(column=6, row=0, padx=ecart)
Separator(self.tableau).grid(column=0, row=0, columnspan=7, sticky="sew")
Separator(self.tableau).grid(column=0, row=0, columnspan=7, sticky="new")
for j in range(0, 8):
Separator(self.tableau, orient='vertical').grid(column=j, row=0, columnspan=2, sticky="nsw")
curseur = limiteIndex - elementsParPage # on commence à partir du curseur
i = 1 # on commence à 1 car il y a déjà le nom des colonnes en position 0
self.imagesStock = [] # on vide la liste si elle contient déjà des images
for element in stockListe[curseur:limiteIndex]: # on ignore les éléments avant le curseur et après la limite
Label(parent, text=element["id"]).grid(column=0, row=i, padx=ecart)
Label(self.tableau, text=element["id"]).grid(column=0, row=i, padx=ecart)
"""
L'idée est que on a une liste `images` qui permet de stocker toutes nos images
@ -292,32 +340,37 @@ class GesMag:
self.imagesStock.append(PhotoImage(file = element["image_url"]))
else: # si l'image n'existe pas
self.imagesStock.append(PhotoImage(file = "img/defaut.gif")) # image par défaut
Label(parent, image=self.imagesStock[i - 1]).grid(column=1, row=i, padx=ecart)
Label(self.tableau, image=self.imagesStock[i - 1]).grid(column=1, row=i, padx=ecart)
Label(parent, text=element["type"].capitalize()).grid(column=2, row=i, padx=ecart)
Label(parent, text=element["nom"].capitalize()).grid(column=3, row=i, padx=ecart)
Label(parent, text=element["quantite"]).grid(column=4, row=i, padx=ecart)
Label(parent, text=__formatPrix(element["prix"])).grid(column=5, row=i, padx=ecart)
Label(self.tableau, text=element["type"].capitalize()).grid(column=2, row=i, padx=ecart)
Label(self.tableau, text=element["nom"].capitalize()).grid(column=3, row=i, padx=ecart)
Label(self.tableau, text=element["quantite"]).grid(column=4, row=i, padx=ecart)
Label(self.tableau, text=__formatPrix(element["prix"])).grid(column=5, row=i, padx=ecart)
# boutons d'actions pour le panier
Button(self.tableau, text='+', font=("Arial", 7), command=lambda e = element: ___miseAJourPanier(e, True)).grid(column=6, row=i, sticky='n', padx=ecart)
Button(self.tableau, text='', font=("Arial", 7), command=lambda e = element: ___miseAJourPanier(e, False)).grid(column=6, row=i, sticky='s')
for j in range(0, 8):
Separator(self.tableau, orient='vertical').grid(column=j, row=i, columnspan=2, sticky="nsw")
Separator(self.tableau).grid(column=j, row=i, columnspan=2, sticky="sew")
curseur += 1
i += 1
# Information sur la page actuelle
Label(parent, text=f"Page {page}/{pageMax}").grid(column=2, row=i, columnspan=2)
Label(self.tableau, text=f"Page {page}/{pageMax}").grid(column=2, row=i, columnspan=3)
# Boutons
precedent = Button(parent, text="Page précédente", command=lambda: __affichageTableau(parent, page - 1))
precedent.grid(column=0, row=i, columnspan=2, sticky='w')
suivant = Button(parent, text="Page suivante", command=lambda: __affichageTableau(parent, page + 1))
suivant.grid(column=4, row=i, columnspan=2, sticky='e')
precedent = Button(self.tableau, text="Page précédente", command=lambda: __affichageTableau(page - 1))
precedent.grid(column=0, row=i, columnspan=2, sticky='w', padx=ecart, pady=ecart)
suivant = Button(self.tableau, text="Page suivante", command=lambda: __affichageTableau(page + 1))
suivant.grid(column=5, row=i, columnspan=2, sticky='e', padx=ecart)
if page == 1: # si on est a la première page on désactive le boutton précédent
precedent.config(state="disabled")
if page == pageMax: # si on est a la dernière page on désactive le boutton suivant
suivant.config(state="disabled")
else:
Label(parent, text="Il n'y a rien en stock\nEssayez de réduire les critères dans le filtre.").grid(column=0, row=0, columnspan=6)
Label(self.tableau, text="Il n'y a rien en stock\nEssayez de réduire les critères dans le filtre.").grid(column=0, row=0, columnspan=7)
tableau = Frame(stock)
__affichageTableau(tableau) # affichage du tableau
__affichageTableau() # affichage du tableau
# Partie affichage du ticket de caisse
ecart = 10
@ -326,17 +379,27 @@ class GesMag:
Label(ticket, text=f"Date de vente : {date.today().strftime('%Y/%m/%d')}").grid(column=0, row=0, pady=ecart)
Label(ticket, text=f"Éléments achetés ({len(self.panier)}) :").grid(column=0, row=1, pady=ecart)
i = 2
prixTotal = 0
for element in self.panier:
Label(ticket, text=element).grid(column=0, row=i)
prixTotal += 0 # ajout du prix
i += 1
def ___affichagePanier():
"""Affiche le panier."""
self.panierAffichage.destroy()
self.panierAffichage = Frame(ticket)
self.panierAffichage.grid(column=0, row=1, pady=ecart)
elementsAchetes = Label(self.panierAffichage)
elementsAchetes.grid(column=0)
prixTotal = 0
compteurElements = 0
for element in self.panier:
Label(self.panierAffichage, text=f"[{element[0]['id']}] - {element[1]}x {element[0]['nom']}").grid(column=0)
prixTotal += (element[0]["prix"] * element[1]) # ajout du prix
compteurElements += element[1]
Label(ticket, text=f"Prix total : {__formatPrix(prixTotal)}").grid(column=0, row=i, pady=ecart)
elementsAchetes.config(text=f"Éléments achetés ({compteurElements}) :")
Button(ticket, text="Valider le\nticket de caisse", font=self.font).grid(column=0, row=i + 1, pady=ecart)
Label(self.panierAffichage, text=f"Prix total : {__formatPrix(prixTotal)}").grid(column=0, pady=ecart)
___affichagePanier()
Button(ticket, text="Valider le\nticket de caisse", font=self.font).grid(column=0, pady=ecart)
#.grid(column=1, row=1, sticky='s')
@ -419,7 +482,7 @@ class GesMag:
float(prix.get()),
image.get()
)
__affichageTableau(tableau) # met à jour le tableau
__affichageTableau() # met à jour le tableau
# Champs de saisie
# Image