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:
parent
64e6789ae2
commit
513a0599e0
1 changed files with 105 additions and 42 deletions
143
main.py
143
main.py
|
@ -1,6 +1,6 @@
|
||||||
# Tkinter
|
# Tkinter
|
||||||
from tkinter import IntVar, Checkbutton, LabelFrame, PhotoImage, Scrollbar, Listbox, Entry, Button, Label, Frame, Tk, Toplevel
|
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.messagebox import showerror, showinfo, showwarning, askyesno
|
||||||
from tkinter.filedialog import askopenfile
|
from tkinter.filedialog import askopenfile
|
||||||
# Regex
|
# Regex
|
||||||
|
@ -22,9 +22,11 @@ class GesMag:
|
||||||
self.nomApp = "GesMag" # nom de l'application
|
self.nomApp = "GesMag" # nom de l'application
|
||||||
self.parent = Tk() # fenêtre affiché à l'utilisateur
|
self.parent = Tk() # fenêtre affiché à l'utilisateur
|
||||||
self.parent.resizable(False, False) # empêche la fenêtre d'être redimensionnée
|
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.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.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"
|
self.panier = [] # liste des éléments "dans le panier"
|
||||||
|
|
||||||
def demarrer(self) -> None:
|
def demarrer(self) -> None:
|
||||||
|
@ -199,7 +201,7 @@ class GesMag:
|
||||||
"""Affiche l'interface du caissier."""
|
"""Affiche l'interface du caissier."""
|
||||||
caissier = Utilisateurs().recuperationUtilisateur(id=id)
|
caissier = Utilisateurs().recuperationUtilisateur(id=id)
|
||||||
self.parent.title(f"Caissier {caissier['nom']} {caissier['prenom']} – {self.nomApp}")
|
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
|
# Suppresssion de la dernière Frame
|
||||||
self.f.destroy()
|
self.f.destroy()
|
||||||
|
@ -224,26 +226,67 @@ class GesMag:
|
||||||
def __formatPrix(prix: str) -> str:
|
def __formatPrix(prix: str) -> str:
|
||||||
return f"{float(prix):.2f} €".replace('.', ',')
|
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)."""
|
"""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
|
# On supprime et refais la frame qui va stocker notre tableau
|
||||||
parent.destroy()
|
self.tableau.destroy()
|
||||||
parent = Frame(stock)
|
self.tableau = Frame(stock)
|
||||||
parent.grid(column=0, row=1, columnspan=6)
|
self.tableau.grid(column=0, row=1, columnspan=7)
|
||||||
|
|
||||||
# Filtre pour le tableau
|
# Filtre pour le tableau
|
||||||
filtres = Frame(stock) # Morceau qui va contenir nos checkbutton
|
filtres = Frame(stock) # Morceau qui va contenir nos checkbutton
|
||||||
ecartFiltre = 10 # écart entre les champs des filtres
|
ecartFiltre = 10 # écart entre les champs des filtres
|
||||||
Label(filtres, text="Filtre", font=self.font).grid(column=0, row=0) # titre
|
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="Stock disponible\nuniquement", variable=stockDisponibleVerif, command=__affichageTableau).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\nfruits & légumes", variable=fruitsLegumesVerif, command=__affichageTableau).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 boulangerie", variable=boulangerieVerif, command=__affichageTableau).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 de\nla boucherie\net poissonnerie", variable=boucheriePoissonnerieVerif, command=__affichageTableau).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="Cacher les produits\nd'entretien", variable=entretienVerif, command=__affichageTableau).grid(sticky='w', pady=ecartFiltre)
|
||||||
filtres.grid(column=7, row=1, sticky='w')
|
filtres.grid(column=7, row=1, sticky='w')
|
||||||
|
|
||||||
stockListe = Stock().listeStocks() # stock récupéré de la base de données
|
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
|
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:
|
if stockDisponibleVerif.get() == 1 and stockListe[i]["quantite"] < 1:
|
||||||
stockListe[i] = None
|
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
|
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
|
if len(stockListe) > 0: # si stock non vide
|
||||||
# Définition des colonnes
|
# Définition des colonnes
|
||||||
Label(parent, text="ID").grid(column=0, row=0, padx=ecart)
|
Label(self.tableau, text="ID").grid(column=0, row=0, padx=ecart)
|
||||||
Label(parent, text="Image").grid(column=1, row=0, padx=ecart)
|
Label(self.tableau, text="Image").grid(column=1, row=0, padx=ecart)
|
||||||
Label(parent, text="Type").grid(column=2, row=0, padx=ecart)
|
Label(self.tableau, text="Type").grid(column=2, row=0, padx=ecart)
|
||||||
Label(parent, text="Nom").grid(column=3, row=0, padx=ecart)
|
Label(self.tableau, text="Nom").grid(column=3, row=0, padx=ecart)
|
||||||
Label(parent, text="Quantité").grid(column=4, row=0, padx=ecart)
|
Label(self.tableau, 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="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
|
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
|
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
|
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
|
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
|
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"]))
|
self.imagesStock.append(PhotoImage(file = element["image_url"]))
|
||||||
else: # si l'image n'existe pas
|
else: # si l'image n'existe pas
|
||||||
self.imagesStock.append(PhotoImage(file = "img/defaut.gif")) # image par défaut
|
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(self.tableau, 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(self.tableau, text=element["nom"].capitalize()).grid(column=3, row=i, padx=ecart)
|
||||||
Label(parent, text=element["quantite"]).grid(column=4, row=i, padx=ecart)
|
Label(self.tableau, 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=__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
|
curseur += 1
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# Information sur la page actuelle
|
# 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
|
# Boutons
|
||||||
precedent = Button(parent, text="Page précédente", command=lambda: __affichageTableau(parent, page - 1))
|
precedent = Button(self.tableau, text="Page précédente", command=lambda: __affichageTableau(page - 1))
|
||||||
precedent.grid(column=0, row=i, columnspan=2, sticky='w')
|
precedent.grid(column=0, row=i, columnspan=2, sticky='w', padx=ecart, pady=ecart)
|
||||||
suivant = Button(parent, text="Page suivante", command=lambda: __affichageTableau(parent, page + 1))
|
suivant = Button(self.tableau, text="Page suivante", command=lambda: __affichageTableau(page + 1))
|
||||||
suivant.grid(column=4, row=i, columnspan=2, sticky='e')
|
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
|
if page == 1: # si on est a la première page on désactive le boutton précédent
|
||||||
precedent.config(state="disabled")
|
precedent.config(state="disabled")
|
||||||
if page == pageMax: # si on est a la dernière page on désactive le boutton suivant
|
if page == pageMax: # si on est a la dernière page on désactive le boutton suivant
|
||||||
suivant.config(state="disabled")
|
suivant.config(state="disabled")
|
||||||
else:
|
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() # affichage du tableau
|
||||||
__affichageTableau(tableau) # affichage du tableau
|
|
||||||
|
|
||||||
# Partie affichage du ticket de caisse
|
# Partie affichage du ticket de caisse
|
||||||
ecart = 10
|
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"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)
|
def ___affichagePanier():
|
||||||
i = 2
|
"""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
|
prixTotal = 0
|
||||||
|
compteurElements = 0
|
||||||
for element in self.panier:
|
for element in self.panier:
|
||||||
Label(ticket, text=element).grid(column=0, row=i)
|
Label(self.panierAffichage, text=f"[{element[0]['id']}] - {element[1]}x {element[0]['nom']}").grid(column=0)
|
||||||
prixTotal += 0 # ajout du prix
|
prixTotal += (element[0]["prix"] * element[1]) # ajout du prix
|
||||||
i += 1
|
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')
|
#.grid(column=1, row=1, sticky='s')
|
||||||
|
|
||||||
|
@ -419,7 +482,7 @@ class GesMag:
|
||||||
float(prix.get()),
|
float(prix.get()),
|
||||||
image.get()
|
image.get()
|
||||||
)
|
)
|
||||||
__affichageTableau(tableau) # met à jour le tableau
|
__affichageTableau() # met à jour le tableau
|
||||||
|
|
||||||
# Champs de saisie
|
# Champs de saisie
|
||||||
# Image
|
# Image
|
||||||
|
|
Reference in a new issue