fleshed out productService and DealsService with higher order functions
This commit is contained in:
parent
a883ae42c9
commit
ec0d3f33c4
|
|
@ -16,7 +16,7 @@ class BasketService:
|
||||||
|
|
||||||
def total(self, sessionID: str) -> int:
|
def total(self, sessionID: str) -> int:
|
||||||
items = self.baskets[sessionID]
|
items = self.baskets[sessionID]
|
||||||
prices = self.dealsService.getPrices()
|
prices = self.dealsService.get_items_with_final_prices(items)
|
||||||
return sum(prices)
|
return sum(prices)
|
||||||
|
|
||||||
def scan(self, session_id: str, itemId) -> None:
|
def scan(self, session_id: str, itemId) -> None:
|
||||||
|
|
|
||||||
|
|
@ -4,34 +4,51 @@ import math
|
||||||
|
|
||||||
|
|
||||||
class DealsService:
|
class DealsService:
|
||||||
deals = []
|
# deals and promotions are global and therefor class vars instead of instance vars
|
||||||
|
deals = dict()
|
||||||
|
promotions = defaultdict(list)
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
pass
|
self.promotions["A0001"].append("two_for_one")
|
||||||
|
self.deals["two_for_one"] = DealsService.two_for_one_deal
|
||||||
def get_prices(self) -> list:
|
|
||||||
return [0]
|
|
||||||
|
|
||||||
def _round_up(self, val: float):
|
|
||||||
return math.ceil(val*100)/100
|
|
||||||
|
|
||||||
def two_for_one_deal(self, items) -> list:
|
def get_items_with_final_prices(self, items) -> list:
|
||||||
new_items = []
|
|
||||||
groups = defaultdict(list)
|
groups = defaultdict(list)
|
||||||
|
|
||||||
for obj in items:
|
for obj in items:
|
||||||
groups[obj.id].append(obj)
|
groups[obj.id].append(obj)
|
||||||
|
|
||||||
for group in groups.values():
|
for group in groups.values():
|
||||||
for deal in self.deals:
|
# the deals do not stack, the first deal in the list of deals is taken,
|
||||||
# the deals do not stack, the first deal in the list of deals is taken,
|
# ideally for the customer all deals would be calculated and the maximum value selected
|
||||||
# ideally for the customer all deals would be calculated and the maximum value selected
|
# not implemented for time reasons
|
||||||
# not implemented for time reasons
|
|
||||||
if deal(group):
|
for promotion in self.promotions.get(group[0].id):
|
||||||
|
# iterate over all promotions for this item
|
||||||
|
# lookup the higher order function that is associated with this deal name
|
||||||
|
# apply the function to the item group
|
||||||
|
# if the deal was applied to the group of items break and move on to the next item group
|
||||||
|
# this avoids discout stacking
|
||||||
|
if self.deals[promotion](group):
|
||||||
break
|
break
|
||||||
|
|
||||||
return [item for group in groups.values() for item in group]
|
return [item for group in groups.values() for item in group]
|
||||||
|
|
||||||
def two_for_one_deal(self, group):
|
@staticmethod
|
||||||
|
def two_for_one_deal(group):
|
||||||
'''' applies deal onto item group in place '''
|
'''' applies deal onto item group in place '''
|
||||||
|
# ideally would be an object implementing a "Deal"-interface,
|
||||||
|
# which has 2 functions, deal_is_applicable() and apply_deal()
|
||||||
|
def _round_up(self, val: float):
|
||||||
|
return math.ceil(val*100)/100
|
||||||
|
|
||||||
|
# could be compressed
|
||||||
|
# not done since this would be the 2 different functions in the above mentioned interface
|
||||||
|
deal_is_applicable = False
|
||||||
|
if len(group) >= 2:
|
||||||
|
deal_is_applicable = True
|
||||||
|
|
||||||
for i in range(len(group)//2):
|
for i in range(len(group)//2):
|
||||||
group[i].price = self._round_up(group[i].price / 2)
|
group[i].price = _round_up(group[i].price / 2)
|
||||||
|
return deal_is_applicable
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
from src.models import Item
|
from src.models import Item
|
||||||
|
|
||||||
|
|
||||||
class ProductService:
|
class ProductService:
|
||||||
prices = None
|
# prices are global, sheduled function to refresh prices periodically
|
||||||
|
# could save ressources under high load
|
||||||
|
prices = dict()
|
||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.prices = defaultdict()
|
# placeholder data
|
||||||
|
self.prices["A0001"] = 12.99
|
||||||
|
self.prices["A0002"] = 3.99
|
||||||
|
|
||||||
|
|
||||||
def get_item_from_id(self, item_id: str) -> Item:
|
def get_item_from_id(self, item_id: str) -> Item:
|
||||||
return Item(id=item_id, price=self.prices.get(item_id))
|
return Item(id=item_id, price=self.prices.get(item_id))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue