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:
parent
565f5166c0
commit
2efecadfc1
4 changed files with 75 additions and 14 deletions
|
@ -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
39
main.py
|
@ -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:
|
||||||
|
|
31
stats.py
31
stats.py
|
@ -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
|
||||||
où il souhaite que le fichier soit exporté) - (utilisé par le bouton d'exportation de
|
où 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)
|
||||||
|
|
18
stock.py
18
stock.py
|
@ -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."""
|
||||||
|
|
Reference in a new issue