diff --git a/main.py b/main.py index 1ef7481..7fdfed8 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,5 @@ -import tkinter.messagebox as messagebox - -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, messagebox +from tkinter.ttk import Combobox from re import sub 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.""" caissier = Utilisateurs().recuperationUtilisateur(id=id) 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 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 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) + 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 (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 """ - try: # on essaie d'ouvrir l'image - open(element["image_url"], "r") + if Stock().fichierExiste(element["image_url"]): # si l'image existe, utilisation de la fonction de `db.py` 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 - 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["nom"].capitalize()).grid(column=3, row=i) - Label(parent, text=element["quantite"]).grid(column=4, row=i) - Label(parent, text=f"{float(element['prix']):.2f} €".replace('.', ',')).grid(column=5, 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, padx=ecart) + 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, padx=ecart) curseur += 1 i += 1 @@ -312,6 +310,118 @@ class GesMag: ticket.grid(column=1, row=1, sticky='n', padx=5) 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 if caissier["metier"] == 0: 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(): """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`. + Si la liste `mauvaisChamps` contient un élément alors un test n'est pas ok. """ - ok = True mauvaisChamps = [] # vérification pour le nom d'utilisateur if self.utilisateurCorrect(pseudo.get())[0] == False or Utilisateurs().utilisateurExistant(pseudo.get()) == True: - ok = False mauvaisChamps.append(pseudo) # vérification pour le mot de passe if self.motDePasseCorrect(passe.get())[0] == False: - ok = False mauvaisChamps.append(passe) # vérification pour le nom if self.nomCorrect(nom.get()) == False: - ok = False mauvaisChamps.append(nom) # vérification pour le prénom if self.prenomCorrect(prenom.get()) == False: - ok = False mauvaisChamps.append(prenom) # vérification pour la date de naissance if self.naissanceCorrect(naissance.get()) == False: - ok = False mauvaisChamps.append(naissance) # vérification pour l'adresse if self.adresseCorrect(adresse.get()) == False: - ok = False mauvaisChamps.append(adresse) # vérification pour le code postal if self.postalCorrect(postal.get()) == False: - ok = False mauvaisChamps.append(postal) - if ok == False: + if len(mauvaisChamps) != 0: """ 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 diff --git a/stock.py b/stock.py index 083bd90..c1cf5fa 100644 --- a/stock.py +++ b/stock.py @@ -123,3 +123,24 @@ class Stock(BaseDeDonnees): ) """ 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