Modifications:

- Standardization of imports
- Adding padding in the table of stock
- Added the possibility to add stock
- Cleanup some code
This commit is contained in:
Mylloon 2021-11-28 11:48:31 +01:00
parent 313aebc040
commit 79840a57f2
2 changed files with 146 additions and 25 deletions

150
main.py
View file

@ -1,6 +1,5 @@
import tkinter.messagebox as messagebox from tkinter import IntVar, Checkbutton, LabelFrame, PhotoImage, Scrollbar, Listbox, Entry, Button, Label, Frame, Tk, Toplevel, messagebox
from tkinter.ttk import Combobox
from tkinter import IntVar, Checkbutton, LabelFrame, PhotoImage, Scrollbar, Listbox, Entry, Button, Label, Frame, Tk, Toplevel
from re import sub from re import sub
from users import Utilisateurs # import de mon fichier pour gérer la base de donnée from users import Utilisateurs # import de mon fichier pour gérer la base de donnée
@ -189,7 +188,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.parent.title(f"Caissier {caissier['nom']} {caissier['prenom']}")
self.dimensionsFenetre(self.parent, 900, 670) self.dimensionsFenetre(self.parent, 940, 670)
# Suppresssion de la dernière Frame # Suppresssion de la dernière Frame
self.f.destroy() self.f.destroy()
@ -268,24 +267,23 @@ class GesMag:
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) Label(parent, 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
(c'est une limitation de tkinter que de garder nos images en mémoire) (c'est une limitation de tkinter que de garder nos images en mémoire)
Une fois ajouté à la liste, on l'affiche dans notre Label Une fois ajouté à la liste, on l'affiche dans notre Label
""" """
try: # on essaie d'ouvrir l'image if Stock().fichierExiste(element["image_url"]): # si l'image existe, utilisation de la fonction de `db.py`
open(element["image_url"], "r")
self.imagesStock.append(PhotoImage(file = element["image_url"])) self.imagesStock.append(PhotoImage(file = element["image_url"]))
except FileNotFoundError: # 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) Label(parent, image=self.imagesStock[i - 1]).grid(column=1, row=i, padx=ecart)
Label(parent, text=element["type"].capitalize()).grid(column=2, row=i) Label(parent, text=element["type"].capitalize()).grid(column=2, row=i, padx=ecart)
Label(parent, text=element["nom"].capitalize()).grid(column=3, row=i) Label(parent, text=element["nom"].capitalize()).grid(column=3, row=i, padx=ecart)
Label(parent, text=element["quantite"]).grid(column=4, row=i) Label(parent, text=element["quantite"]).grid(column=4, row=i, padx=ecart)
Label(parent, text=f"{float(element['prix']):.2f}".replace('.', ',')).grid(column=5, row=i) Label(parent, text=f"{float(element['prix']):.2f}".replace('.', ',')).grid(column=5, row=i, padx=ecart)
curseur += 1 curseur += 1
i += 1 i += 1
@ -312,6 +310,118 @@ class GesMag:
ticket.grid(column=1, row=1, sticky='n', padx=5) ticket.grid(column=1, row=1, sticky='n', padx=5)
Label(ticket, text="TODO").grid() Label(ticket, text="TODO").grid()
# Partie ajout élément au stock
def __ajouterElementStock():
"""Ouvre une fenêtre qui permet d'ajouter un nouvel élément à la base de donnée."""
"""
L'enfant (`TopLevel`) dépend de la `Frame` et non du parent (`Tk`)
pour éviter de resté ouverte meme lorsque le caissier se déconnecte.
"""
enfant = Toplevel(self.f)
enfant.title(f"Ajouter un élément au stock")
def ___verification():
"""Vérifie si les champs renseignées sont valides."""
"""
La variable `ok` sert à savoir si la vérification est passée
si elle vaut `True` alors tout est bon,
Par contre si elle vaut `False` alors il y a eu une erreur.
Les valeurs `Entry` qui ne sont pas passés seront dans
la liste `mauvaisChamps`.
"""
ok = True
mauvaisChamps = []
# vérification pour l'image, on utilise la fonction du fichier `db.py`
if Stock().fichierExiste(image.get()) == False:
ok = False
mauvaisChamps.append(image)
# vérification pour le type
if type.get() not in Stock().listeTypes():
ok = False
# Pas de coloration orange si le type est mauvais parce que on ne peut pas changé la couleur de fond d'une ComboBox
# vérification pour le nom
if Stock().elementStockExistant(nom.get()) == True:
ok = False
mauvaisChamps.append(nom)
# vérification pour la quantité
try:
int(quantite.get()) # conversion en int
except: # si la conversion a échoué
ok = False
mauvaisChamps.append(quantite)
# vérification pour le prix
try:
float(prix.get()) # conversion en float
except: # si la conversion a échoué
ok = False
mauvaisChamps.append(prix)
if ok == False:
"""
Tous les champs qui n'ont pas réunies les conditions nécéssaires
sont mis en orange pendant 3 secondes pour bien comprendre quelles champs
sont à modifié.
La fonction lambda `remettreCouleur` permet de remettre la couleur initial
après les 3 secondes.
"""
remettreCouleur = lambda widget, ancienneCouleur: widget.configure(bg=ancienneCouleur)
for champs in mauvaisChamps:
couleur = champs["background"] # couleur d'avant changement
champs.configure(bg="orange") # on change la couleur du champs en orange
# dans 3 secondes on fait : `remettreCouleur(champs, couleur)`
champs.after(3000, remettreCouleur, champs, couleur)
else:
"""
Tous les tests sont passés, on peut ajouter l'utilisateur à la base de donnée
Pas besoin de gérer les erreurs lors des casts car on a déjà vérifié que c'était bien les bons types avant
"""
Stock().ajoutStock(
type.get,
nom.get(),
int(quantite.get()),
float(prix.get()),
image.get()
)
__affichageTableau(tableau) # met à jour le tableau
# Champs de saisie
# Image
Label(enfant, text="Image :").grid(column=0, row=0, sticky='e')
image = Entry(enfant)
image.grid(column=1, row=0, sticky='w')
# Type (ComboBox)
Label(enfant, text="Type :").grid(column=0, row=1, sticky='e')
type = Combobox(enfant, values=Stock().listeTypes())
# type.current(0) # valeur 0 par défaut
type.grid(column=1, row=1, sticky='w')
# Nom
Label(enfant, text="Nom :").grid(column=0, row=2, sticky='e')
nom = Entry(enfant)
nom.grid(column=1, row=2, sticky='w')
# Quantité
Label(enfant, text="Quantité :").grid(column=0, row=3, sticky='e')
quantite = Entry(enfant)
quantite.grid(column=1, row=3, sticky='w')
# Prix à l'unité
Label(enfant, text="Prix à l'unité :").grid(column=0, row=4, sticky='e')
prix = Entry(enfant)
prix.grid(column=1, row=4, sticky='w')
def ___viderChamps():
"""Vide tout les champs de leur contenu"""
# On récupère toutes les `Entry` de la fenêtre et on change leur contenu
for champ in [widget for type, widget in enfant.children.items() if "entry" in type]:
champ.delete(0, "end")
champ.update()
# Boutons
Button(enfant, text="Valider", command=___verification).grid(column=0, row=8, columnspan=3, sticky='w')
Button(enfant, text="Vider les champs", command=___viderChamps).grid(column=0, row=8, columnspan=3)
Button(enfant, text="Quitter", command=enfant.destroy).grid(column=0, row=8, columnspan=3, sticky='e')
Button(self.f, text="Ajouter un élément\nau stock", font=self.font, command=__ajouterElementStock).grid(column=1, row=1, sticky='s')
# Boutton pour passer en mode manager si la personne est un manager # Boutton pour passer en mode manager si la personne est un manager
if caissier["metier"] == 0: if caissier["metier"] == 0:
Button(self.f, text="Passer en mode Manager", font=self.font, command=lambda: self._interfaceManager(id)).grid() Button(self.f, text="Passer en mode Manager", font=self.font, command=lambda: self._interfaceManager(id)).grid()
@ -351,44 +461,34 @@ class GesMag:
def ___verification(): def ___verification():
"""Vérifie si les champs renseignées sont valides.""" """Vérifie si les champs renseignées sont valides."""
""" """
La variable `ok` sert à savoir si la vérification est passée
si elle vaut `True` alors tout est bon,
Par contre si elle vaut `False` alors il y a eu une erreur.
Les valeurs `Entry` qui ne sont pas passés seront dans Les valeurs `Entry` qui ne sont pas passés seront dans
la liste `mauvaisChamps`. la liste `mauvaisChamps`.
Si la liste `mauvaisChamps` contient un élément alors un test n'est pas ok.
""" """
ok = True
mauvaisChamps = [] mauvaisChamps = []
# vérification pour le nom d'utilisateur # vérification pour le nom d'utilisateur
if self.utilisateurCorrect(pseudo.get())[0] == False or Utilisateurs().utilisateurExistant(pseudo.get()) == True: if self.utilisateurCorrect(pseudo.get())[0] == False or Utilisateurs().utilisateurExistant(pseudo.get()) == True:
ok = False
mauvaisChamps.append(pseudo) mauvaisChamps.append(pseudo)
# vérification pour le mot de passe # vérification pour le mot de passe
if self.motDePasseCorrect(passe.get())[0] == False: if self.motDePasseCorrect(passe.get())[0] == False:
ok = False
mauvaisChamps.append(passe) mauvaisChamps.append(passe)
# vérification pour le nom # vérification pour le nom
if self.nomCorrect(nom.get()) == False: if self.nomCorrect(nom.get()) == False:
ok = False
mauvaisChamps.append(nom) mauvaisChamps.append(nom)
# vérification pour le prénom # vérification pour le prénom
if self.prenomCorrect(prenom.get()) == False: if self.prenomCorrect(prenom.get()) == False:
ok = False
mauvaisChamps.append(prenom) mauvaisChamps.append(prenom)
# vérification pour la date de naissance # vérification pour la date de naissance
if self.naissanceCorrect(naissance.get()) == False: if self.naissanceCorrect(naissance.get()) == False:
ok = False
mauvaisChamps.append(naissance) mauvaisChamps.append(naissance)
# vérification pour l'adresse # vérification pour l'adresse
if self.adresseCorrect(adresse.get()) == False: if self.adresseCorrect(adresse.get()) == False:
ok = False
mauvaisChamps.append(adresse) mauvaisChamps.append(adresse)
# vérification pour le code postal # vérification pour le code postal
if self.postalCorrect(postal.get()) == False: if self.postalCorrect(postal.get()) == False:
ok = False
mauvaisChamps.append(postal) mauvaisChamps.append(postal)
if ok == False: if len(mauvaisChamps) != 0:
""" """
Tous les champs qui n'ont pas réunies les conditions nécéssaires Tous les champs qui n'ont pas réunies les conditions nécéssaires
sont mis en orange pendant 3 secondes pour bien comprendre quelles champs sont mis en orange pendant 3 secondes pour bien comprendre quelles champs

View file

@ -123,3 +123,24 @@ class Stock(BaseDeDonnees):
) )
""" """
return True if self.affichageResultat(self.requete(requete, stock.lower()))[0][0] == 1 else False return True if self.affichageResultat(self.requete(requete, stock.lower()))[0][0] == 1 else False
def listeTypes(self) -> list:
"""Renvoie la liste des types disponibles dans la base de donnée."""
requete = """
SELECT type FROM stocks
"""
res = []
for i in self.affichageResultat(self.requete(requete)):
if i[0] not in res:
res.append(i[0])
return res
def elementStockExistant(self, element: str) -> bool:
"""Vérifie si l'élément donnée existe déjà dans la base de donnée."""
requete = """
SELECT EXISTS (
SELECT 1 FROM stocks
WHERE nom = ?
)
"""
return True if self.affichageResultat(self.requete(requete, element.lower()))[0][0] == 1 else False