Commit c35b0117 authored by Robin Trioux's avatar Robin Trioux
Browse files

Huge refacto

Product selector tree created
watchout product dict is "force" coded
TODO: Convert google timestamp into QTime
parent f033e976
from Console import *
class UIProperties:
def __init__(self):
self.text = (
......@@ -50,8 +55,6 @@ class UIProperties:
def getToolTip(self):
return self.toolTip
class Atom:
def __init__(self):
self.ui = UIProperties()
......@@ -98,6 +101,37 @@ class Atom:
def getToolTip(self):
return self.ui.getToolTip()
def getUI(self):
return self.ui
class HappyHours(Atom):
def __init__(self):
super().__init__()
self.start = None # QTime
self.end = None # QTime
self.price = None # Eur
def setStart(self,start):
self.start = start
return self
def setEnd(self, end):
self.end = end
return self
def setPrice(self, price):
self.price = price
return self
def getStart(self):
return self.start
def getEnd(self):
return self.end
def getPrice(self):
return self.price
class User(Atom):
def __init__(self):
......@@ -108,12 +142,15 @@ class User(Atom):
def setId(self, id):
self.id = id
return self
def setBalance(self, balance):
self.balance = balance
return self
def setCanDrink(self, canDrink):
self.canDrink = canDrink
return self
def getId(self):
return self.id
......@@ -133,21 +170,36 @@ class Product(Atom):
self.code = None # short name
self.price = None # The price is either updated when it's in a the selctor, either retreived from database when it's in history
self.quantity = None # When product is used as selector, quantity is 1 and when used in a basket, it may vary
self.happyHours = None # List of happy hours
self.category = None # string e.g "Drinks.Alcool.Wine"
def setId(self, id):
self.id = id
return self
def setName(self, name):
self.name = name
return self
def setCode(self, code):
self.code = code
return self
def setPrice(self, price):
def setPrice(self, price): # price is never a float but something inherited from Decimal (Money.Eur)
self.price = price
return self
def setQuantity(self, quantity):
self.quantity = quantity
return self
def setHappyHours(self,happyHours):
self.happyHours = happyHours
return self
def setCategory(self, category):
self.category = category
return self
def getId(self):
return self.id
......@@ -164,6 +216,18 @@ class Product(Atom):
def getQuantity(self):
return self.quantity
def getHappyHours(self):
return self.happyHours
def getCategory(self):
return self.category
def __repr__(self):
return "Product({0}, {1})".format(self.id,self.name)
def __str__(self):
return "{0}: {1}".format(self.id,self.name)
class Operation(Atom):
def __init__(self):
......@@ -177,18 +241,23 @@ class Operation(Atom):
def setId(self, id):
self.id = id
return self
def setLabel(self, label):
self.label = label
return self
def setRefounded(self, refounded):
self.refounded = refounded
return self
def setCounterId(self, counterId):
self.counterId = counterId
return self
def setDate(self, date):
self.date = date
return self
def getId(self):
return self.id
......@@ -214,13 +283,16 @@ class Buying(Operation):
self.basketItems = None # List of "Product", their unit price should be download from the history
def setPrice(self, price):
self.price = print
self.price = price
return self
def setPayment(self, payments):
self.payments = payments
return self
def setBasketItems(self, basketItems):
self.basketItems = basketItems
return self
def getPrice(self):
return self.price
......@@ -236,13 +308,22 @@ class Refilling(Operation):
def __init__(self):
super().__init__()
self.amount = None
self.newBalance = None
def setAmount(self, amount):
self.amount = amount
return self
def getAmount(self):
return self.amount
def setNewBalance(self, balance):
self.newBalance = balance
return self
def getNewBalance(self):
return self.newBalance
class Counter(Atom):
def __init__(self):
......@@ -252,9 +333,11 @@ class Counter(Atom):
def setId(self, id):
self.id = id
return self
def setName(self, name):
self.name = name
return self
def getId(self):
return self.id
......@@ -267,3 +350,82 @@ class Counter(Atom):
def __str__(self):
return "{0}: {1}".format(self.id,self.name)
class Distribution(Atom):
def __init__(self):
super().__init__()
self.userList = [] # list of user uid
self.userBalance = [] # the current balance of each user before transaction
self.amount = [] # the amount paid by each user
self.totalPrice = None # The total price to pay
def setUserList(self,uidList):
self.userList = uidList
return self
def getUserList(self):
return self.userList
def addUser(self,uid):
self.userList.append(uid)
return self
def removeUser(self,uid):
try:
indexUser = self.userList.index(uid)
del(self.userList[indexUser])
return self
except ValueError:
printE("User {} not found".format(uid))
return None
def setUserBalanceList(self, balanceList):
self.userBalance = balanceList
return self
def getUserBalanceList(self):
return self.userBalance
def setUserBalance(self, uid, balance):
try:
indexUser = self.userList.index(uid)
self.userBalance[indexUser] = balance
except ValueError:
printE("User {} not found".format(uid))
return None
def getUserBalance(self, uid):
try:
indexUser = self.userList.index(uid)
return self.userBalance[indexUser]
except ValueError:
printE("User {} not found".format(uid))
return None
def setAmountList(self, amountList):
self.amount
def setUserAmount(self, uid, amount):
try:
userIndex = self.userList.index(uid)
if amount <= self.userBalance[userIndex]:
self.amount[userIndex] = amount
else:
printWW("Insufficient balance for user {}".format(uid))
self.amount[userIndex] = self.userBalance[userIndex]
except ValueError:
printE("user {} not found".format(uid))
def getAmountList(self):
return self.amount
def getUserAmount(self, uid):
try:
userIndex = self.userList.index(uid)
return self.amount[userIndex]
except ValueError:
printE("user {} not found".format(uid))
def setFairDistribution(self):
pass
\ No newline at end of file
from __future__ import print_function
import grpc
......@@ -6,10 +5,44 @@ from grpc import RpcError
import com_pb2
import com_pb2_grpc
from google.protobuf.timestamp_pb2 import Timestamp
from google.protobuf.json_format import MessageToDict
from Atoms import *
from QAtoms import *
from Console import *
from convert import *
#def addProduct(product,categoryList):
# try:
# if isinstance(product,dict):
# productDict={categoryList[-1]:product}
# else:
# productDict={categoryList[-1]:[product]}
# return addProduct(productDict,categoryList[:-1])
# except IndexError:
# return product
#def parseProducts(productsReply):
# pbProductList = productsReply.products # get protobuff products
# for i in pbProductList:
# happyHoursList = []
# pbHappyHoursList = i.happy_hours
# for j in pbHappyHoursList:
# newHappyHour = HappyHours()
# newHappyHour.setStart(j.start) #Still need to be converted in QTime
# newHappyHour.setEnd(j.end)
# newHappyHour.setPrice(pb_money_to_eur(j.price)) # Since we choosed a securised money format we need to convert
# happyHoursList.append(newHappyHour)
# newProduct = Product()
# newProduct.setId(i.id)
# newProduct.setName(i.name)
# newProduct.setCode(i.code)
# newProduct.setPrice(pb_money_to_eur(i.default_price))
# newProduct.setHappyHours(happyHoursList)
# newProduct.setCategory(i.category)
#
class ClientSingleton(type):
_instance = {}
......@@ -33,24 +66,7 @@ class Client(metaclass=ClientSingleton):
repeated Payment payments
repeated BasketItem basket
"""
# Mockup
mockupProduct = Product()
mockupProduct.price = 8
mockupProduct.quantity = 2
mockupProduct.name = "Bouteille"
mockupProduct.id = 0
mockupProduct.code = "BOUBOU"
buying = Buying()
buying.date = Timestamp().GetCurrentTime()
buying.id = 1
buying.label = "label"
buying.price = 16
buying.refounded = False
buying.counterId = 0
buying.basketItems = [mockupProduct]
return mockupProduct
pass
def requestRefilling(self, **kwargs):
......@@ -61,18 +77,17 @@ class Client(metaclass=ClientSingleton):
PaymentMethod payment_method
double amount
"""
# Mockup
refilling = Refilling()
refilling.amount = 42
refilling.counterId = 0
refilling.date = Timestamp().GetCurrentTime()
refilling.id = 2
refilling.label = "label"
refilling.refounded = False
return refilling
try:
refillingRequest = com_pb2.RefillingRequest(**kwargs)
refillingReply = self.stub.Refill(refillingRequest)
self.now = refillingReply.now
newBalance = unpackMoney(refillingReply.amount)
refilling = unpackRefilling(refillingReply.refilling)
refilling.setNewBalance(newBalance)
return refilling
except RpcError:
printE("Unable to refill")
return None
def requestHistory(self, **kwargs):
pass
......@@ -86,68 +101,65 @@ class Client(metaclass=ClientSingleton):
"""
int64 counter_id
"""
counterProduct = {}
productList = []
try:
productsRequest = com_pb2.ProductsRequest(counter_id=kwargs['counter_id'])
productsRequest = com_pb2.ProductsRequest(**kwargs)
productsReply = self.stub.Products(productsRequest)
self.now = productsReply.now
return MessageToDict(productsReply)['items']
# Fill product List
pbProductList = productsReply.products # get protobuff products
for pb_product in pbProductList:
newProduct = unpackProduct(pb_product)
productList.append(newProduct)
return productList
except RpcError:
printE("Unable to get product list")
return None
# Mockup
mockupProduct1 = Product()
mockupProduct1.name = "Coca"
mockupProduct1.price = 1
mockupProduct1.quantity = 1
mockupProduct1.id = 0
mockupProduct1.code = "COCA"
mockupProduct2 = Product()
mockupProduct2.name = "Bièrre"
mockupProduct2.price = 2
mockupProduct2.quantity = 1
mockupProduct2.id = 1
mockupProduct2.code = "BIBINE"
products = {"Soft": mockupProduct1, "Alcool": mockupProduct2}
return products
return None
def requestUserBalance(self, **kwargs):
"""
string customer_id
"""
# Mockup
return 30
try:
balanceRequest = com_pb2.BalanceRequest(customer_id = kwargs['customer_id'])
balanceReply = self.stub.Balance(balanceRequest)
self.now = balanceReply.now
return unpackMoney(balanceReply.balance)
except RpcError:
printE("Unable to get customer balance")
return None
return None
def requestCounterList(self, **kwargs):
"""No parameters requiered"""
counterList = []
counterListRequest = com_pb2.CounterListRequest()
try:
counterListRequest = com_pb2.CounterListRequest()
counterListReply = self.stub.CounterList(counterListRequest)
grpcCounterList = counterListReply.counters #get the payload
pbCounterList = counterListReply.counters #get the payload
self.now = counterListReply.now #update the time
for i in grpcCounterList:
newCounter = Counter()
newCounter.setId(i.id)
newCounter.setName(i.name)
for pb_counter in pbCounterList:
newCounter = unpackCounter(pb_counter)
counterList.append(newCounter)
return counterList
except RpcError:
printE("Unable to get counter list")
return None
return None
def requestTransfert(self, **kwargs):
pass
from termcolor import colored
from babel.numbers import format_currency
# At the moment I assume we only print single strings
def printE(string): #Error
......@@ -7,6 +8,9 @@ def printE(string): #Error
def printW(string): #Warning
print(colored("WARNING: " + str(string),'yellow'))
def printWW(string): #Super Warning
print(colored("WARNING: " + str(string),'yellow',attrs=['bold']))
def printN(string): #Nice
print(colored(str(string),'green'))
......@@ -19,6 +23,9 @@ def printI(string): #Info
def printNFC(string): #NFC message
print(colored(string,'magenta'))
def printM(eur): #Money
print(colored(eur.format('fr_FR'),'yellow'))
#Suggestion: create printEE, printEEE, printWW, printWWW ... to create a hierarchy among the message
# could be usefull to filter the message to print in the future ...
......
from money import Money
from babel.numbers import format_currency
from Console import *
# money is based on Decimal, this class handle perfect float representation
# every single amount of money should be generated through this library to avoid float virgule problem
# e.g with regular float 1.1 + 1.2 = 2.30000000000000003
# with money/Decimal class 1.1 + 1.2 = 2.30
#TEST
import money
#money could theoricaly handle multi device program, here we just need euro so we create a specialized class
class Eur(Money):
......@@ -13,3 +16,16 @@ class Eur(Money):
super().__init__(amount=amount,currency='EUR')
if isinstance(amount,float) is True:
printW("Eur should not be instancied with a float number, approximation may occure")
if 100*amount != 100*int(amount):
printWW("Money with more than two decimals. Unforseen behavior may occure")
def __str__(self): # Overloaded function ... allow me to use XX.YY€ instead of EUR XX.YY
print('__str__')
try:
return self.format('fr_FR')
except:
return self.__unicode__()
def __unicode__(self):
return u"{} {:,.2f}".format(self._currency, self._amount)
\ No newline at end of file
......@@ -30,9 +30,6 @@ PWD = os.getcwd() + "/"
# Get item tree
# INITIALISATION
dm = QDataManager()
uim = QUIManager()
nfcm = QNFCManager()
def setFont(Widget, Font):
......@@ -70,6 +67,7 @@ class QMainTab(QTabWidget):
class QMainMenu(QMainWindow):
def __init__(self):
super().__init__()
......
from Atoms import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from QUtils import *
class QDelButton(QToolButton):
deleted = pyqtSignal(QToolButton)
def __init__(self, parent=None):
super().__init__(parent)
self.row = -1
self.clicked.connect(self.delete)
self.setIcon(QIcon("ressources/icones/delete.png"))
self.setIconSize(QSize(32, 32))
self.setFixedSize(QSize(48, 48))
def setRow(self, row):
self.row = row
def getRow(self):
return self.row
def delete(self):
self.deleted.emit(self)
class QQuantity(QWidget):
quantityChanged = pyqtSignal()
def __init__(self, parent=None):
super().__init__(parent)
# Definition
self.mainHBoxLayout = QHBoxLayout()
self.minusButton = QToolButton()
self.quantityEditLine = QLineEdit()
self.plusButton = QToolButton()
self.quantity = 1
# Settings
self.minusButton.setText("-")
self.quantityEditLine.setText("1")
self.quantityEditLine.setAlignment(Qt.AlignHCenter)
self.quantityEditLine.setFixedWidth(50)
self.plusButton.setText("+")
self.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
# Link
self.mainHBoxLayout.addWidget(self.minusButton)
self.mainHBoxLayout.addWidget(self.quantityEditLine)
self.mainHBoxLayout.addWidget(self.plusButton)
self.setLayout(self.mainHBoxLayout)
self.plusButton.clicked.connect(self.incQuantity)
self.minusButton.clicked.connect(self.decQuantity)
self.quantityEditLine.textChanged.connect(self.editingFinished)
self.quantityEditLine.editingFinished.connect(self.__noBlank)
def incQuantity(self):
self.quantity += 1
self.quantityEditLine.setText(str(self.quantity))
self.quantityEditLine.editingFinished.emit()
# self.quantityChanged.emit()