Modifications:

- Add dependencie `csv` in documentation
- Add quantity selection when removing something from stock (now you can delete an item, but set it's quantity to 0)
- Cleanup function names (`__affichagePanier`)
- Disable the button who confirm a receipt when nothing is in the basket
- Create the CSV file when starting the app
- Add a function who update dates in the global csv file
This commit is contained in:
Mylloon 2021-11-29 20:24:27 +01:00
parent 565f5166c0
commit 2efecadfc1
4 changed files with 75 additions and 14 deletions

View file

@ -130,6 +130,7 @@
\item[\textbullet] \texttt{datetime} pour le temps \item[\textbullet] \texttt{datetime} pour le temps
\item[\textbullet] \texttt{sqlite3} pour la base de donnée SQLite \item[\textbullet] \texttt{sqlite3} pour la base de donnée SQLite
\item[\textbullet] \texttt{random} pour la génération du stock (prix et quantité) \item[\textbullet] \texttt{random} pour la génération du stock (prix et quantité)
\item[\textbullet] \texttt{csv} pour la gestion du fichier \texttt{CSV}
\end{itemize} \end{itemize}
\subsection{Cahier des charges} \subsection{Cahier des charges}

39
main.py
View file

@ -19,6 +19,7 @@ class GesMag:
"""Instancie quelques variables pour plus de clareté.""" """Instancie quelques variables pour plus de clareté."""
Utilisateurs().creationTable(presentation) # on créer la table utilisateurs si elle n'existe pas déjà Utilisateurs().creationTable(presentation) # on créer la table utilisateurs si elle n'existe pas déjà
Stock().creationTable(presentation) # on créer la table du stock si elle n'existe pas déjà Stock().creationTable(presentation) # on créer la table du stock si elle n'existe pas déjà
Stats().creationCSV() # on créer le fichier CSV qui stockera les statistiques des utilisateurs
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
@ -294,7 +295,7 @@ class GesMag:
if nombreDeFoisPresentDansLePanier > 0: if nombreDeFoisPresentDansLePanier > 0:
self.panier.insert(index, (element, nombreDeFoisPresentDansLePanier)) self.panier.insert(index, (element, nombreDeFoisPresentDansLePanier))
___affichagePanier() # met-à-jour le panier __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:
@ -388,7 +389,7 @@ 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)
def ___affichagePanier(): def __affichagePanier():
"""Affiche le panier actuel dans le ticket de caisse.""" """Affiche le panier actuel dans le ticket de caisse."""
self.panierAffichage.destroy() self.panierAffichage.destroy()
self.panierAffichage = Frame(ticket) self.panierAffichage = Frame(ticket)
@ -409,11 +410,39 @@ class GesMag:
elementsAchetes.config(text=f"Élément{'s' if compteurElements > 1 else ''} acheté{'s' if compteurElements > 1 else ''} ({compteurElements}) :") elementsAchetes.config(text=f"Élément{'s' if compteurElements > 1 else ''} acheté{'s' if compteurElements > 1 else ''} ({compteurElements}) :")
try: # désactive le bouton si rien n'est dans le panier
if len(self.panier) <= 0:
validationTicketDeCaisseBouton.config(state="disabled")
else:
validationTicketDeCaisseBouton.config(state="active")
except NameError: # si pas renseigné, alors = panier vide, déjà désactiver
pass
Label(self.panierAffichage, text=f"Prix total : {__formatPrix(prixTotal)}").grid(column=0, pady=ecart, columnspan=2) Label(self.panierAffichage, text=f"Prix total : {__formatPrix(prixTotal)}").grid(column=0, pady=ecart, columnspan=2)
___affichagePanier() __affichagePanier()
Button(ticket, text="Valider le\nticket de caisse", font=self.font).grid(column=0, pady=ecart) def __validationTicketDeCaisse():
"""Lance plusieurs méthodes pour valider le ticket de caisse."""
# Met à jour la valeur dans le fichier `CSV`
Stats().miseAJourStatsUtilisateur(id, sum([element[0]["prix"] * element[1] for element in self.panier]))
# Informe l'utilisateur que tout est validé
showinfo("Validation", "Ticket de caisse validé !")
# Retire les éléments renseigné dans le panier du stock
for element in self.panier:
Stock().suppressionStocks(element[0]["id"], element[1])
# Remet le panier à 0
self.panier = []
# Met-à-jour le panier et le tableau du stock
__affichagePanier()
__affichageTableau()
validationTicketDeCaisseBouton = Button(ticket, text="Valider le\nticket de caisse", font=self.font, command=__validationTicketDeCaisse, state="disabled")
validationTicketDeCaisseBouton.grid(column=0, pady=ecart)
# -> Partie ajout élément au stock # -> Partie ajout élément au stock
def __ajouterElementStock(): def __ajouterElementStock():
@ -544,7 +573,7 @@ class GesMag:
Button(self.f, text="Ajouter un élément\nau stock", font=self.font, command=__ajouterElementStock).grid(column=1, row=2) Button(self.f, text="Ajouter un élément\nau stock", font=self.font, command=__ajouterElementStock).grid(column=1, row=2)
# -> Partie export des statistiques # -> Partie export des statistiques
Button(self.f, text="Exporter les statistiques", font=self.font).grid(column=0, row=2, sticky='e', padx=ecart) Button(self.f, text="Exporter les statistiques", font=self.font, command=lambda: Stats().exporteCSV(id, True)).grid(column=0, row=2, sticky='e', padx=ecart)
# -> 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:

View file

@ -1,9 +1,23 @@
import csv
from datetime import date, timedelta
from users import Utilisateurs from users import Utilisateurs
class Stats(Utilisateurs): class Stats(Utilisateurs):
"""Gère les statistiques et son export en format CSV.""" """Gère les statistiques et son export en format CSV."""
def __init__(self): def creationCSV(self):
super().__init__(r"db.sqlite3") """Créer le fichier `CSV` qui stockera les statistiques pour tous les utilisateurs."""
if not self.fichierExiste("stats.csv"):
entete = ["id", "pseudo"]
dateAujourdHui = date.today()
for _ in range(0, 8):
entete.append(dateAujourdHui)
dateAujourdHui = dateAujourdHui - timedelta(days=1)
with open("stats.csv", 'w') as f:
writer = csv.writer(f)
writer.writerow(entete)
def miseAJourStatsUtilisateur(self, utilisateurID: int, prix: float): def miseAJourStatsUtilisateur(self, utilisateurID: int, prix: float):
""" """
@ -19,17 +33,18 @@ class Stats(Utilisateurs):
Procéder normalement consiste à ajouter le prix au prix totale stocké dans la base de donnée. Procéder normalement consiste à ajouter le prix au prix totale stocké dans la base de donnée.
""" """
print(prix)
pass pass
def exportCSV(self, utilisateurID: int, mode: bool = False): def exporteCSV(self, utilisateurID: int, mode: bool = False):
""" """
Exporte les statistiques d'un utilisateur dans un fichier `CSV`. Exporte les statistiques d'un utilisateur dans un fichier `CSV`.
Deux modes : Deux modes :
- `False` : exporte dans le fichier globale (qui contient tous les utilisateurs, utilisés - `False` : exporte dans le fichier globale (qui contient tous les utilisateurs, utilisés
par l'histogramme de l'interface du Manager) par l'histogramme de l'interface du Manager)
- si le fichier `CSV` ne contient aucune donnée de l'utilisateur, on créer - si le fichier `CSV` ne contient aucune donnée de l'utilisateur, on y rajoute les
le fichier (sa structure, etc.) et on y rajoute les données de l'utilisateur données de l'utilisateur
- ne garde qu'un historique des 7 derniers jours maximum - ne garde qu'un historique des 7 derniers jours maximum
- `True` : exporte dans un fichier séparé l'utilisateur choisie (demande à l'utilisateur - `True` : exporte dans un fichier séparé l'utilisateur choisie (demande à l'utilisateur
il souhaite que le fichier soit exporté) - (utilisé par le bouton d'exportation de il souhaite que le fichier soit exporté) - (utilisé par le bouton d'exportation de
@ -37,3 +52,9 @@ class Stats(Utilisateurs):
- A savoir : n'exporte que l'état actuel de la base de donnée - A savoir : n'exporte que l'état actuel de la base de donnée
""" """
pass pass
def miseAJourDatesCSV(self):
"""Mets-à-jour les dates trop anciennes du fichier globales `CSV`."""
with open("stats.csv", 'r') as f:
fichier = csv.DictReader(f)
print(fichier)

View file

@ -91,13 +91,23 @@ class Stock(BaseDeDonnees):
self.requete(requete, [typeElement.lower(), nom.lower(), quantite, prix, imageURL]) self.requete(requete, [typeElement.lower(), nom.lower(), quantite, prix, imageURL])
return self.affichageResultat(self.requete("SELECT last_insert_rowid();")) return self.affichageResultat(self.requete("SELECT last_insert_rowid();"))
def suppressionStocks(self, id: int) -> None: def suppressionStocks(self, id: int, quantiteARetirer: int) -> None:
"""Supprime un stock.""" """Supprime un stock."""
requete = """ requeteA = """
DELETE FROM stocks SELECT quantite FROM stocks
WHERE id = ? WHERE id = ?
""" """
self.requete(requete, id) quantiteActuelle: int = self.affichageResultat(self.requete(requeteA, id))[0][0]
if quantiteActuelle <= quantiteARetirer: # il ne reste plus rien
quantiteFinale = 0
else: # il reste quelque chose
quantiteFinale = quantiteActuelle - quantiteARetirer
requeteB = """
UPDATE stocks
SET quantite = ?
WHERE id = ?
"""
self.requete(requeteB, [quantiteFinale, id])
def listeStocks(self) -> list: def listeStocks(self) -> list:
"""Retourne la liste des éléments en stock sous forme de dictionnaire.""" """Retourne la liste des éléments en stock sous forme de dictionnaire."""