formatting

This commit is contained in:
Askill 2024-08-15 18:02:13 +02:00
parent f94c87c06f
commit 12b58e7bf1
7 changed files with 32 additions and 30 deletions

View File

@ -4,6 +4,7 @@ import uuid
from src.services import BasketService from src.services import BasketService
class Basket(Resource): class Basket(Resource):
basket_service = BasketService() basket_service = BasketService()
@ -15,11 +16,13 @@ class Basket(Resource):
def get(self): def get(self):
if "session_id" not in session: if "session_id" not in session:
session["session_id"] = self.get_session_id() session["session_id"] = self.get_session_id()
return Response({"total": self.basket_service.total()}, mimetype="application/json") return Response(
{"total": self.basket_service.total()}, mimetype="application/json"
)
def post(self): def post(self):
# expects something similar: {"items": [{"item_id": abc002}]} # expects something similar: {"items": [{"item_id": abc002}]}
if "session_id" not in session: if "session_id" not in session:
session["session_id"] = self.get_session_id() session["session_id"] = self.get_session_id()
jsonData = request.get_json(force=True) jsonData = request.get_json(force=True)

View File

@ -7,14 +7,14 @@ import logging
import endpoints.BasketEndpoint as BasketEndpoint import endpoints.BasketEndpoint as BasketEndpoint
app = Flask(__name__) app = Flask(__name__)
app.secret_key = 'SUPER_DUPER_BAD_SECRET_KEY' app.secret_key = "SUPER_DUPER_BAD_SECRET_KEY"
api = Api(app) api = Api(app)
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
api.add_resource(BasketEndpoint.Basket,'/api/v1/basket/') api.add_resource(BasketEndpoint.Basket, "/api/v1/basket/")
@app.route("/") @app.route("/")
def index(): def index():
"""in lieu of a UI redirect to the API doc""" """in lieu of a UI redirect to the API doc"""
app.logger.info(f"request from {request.remote_addr}") app.logger.info(f"request from {request.remote_addr}")
return redirect("/api/doc/swagger.json", code=302) return redirect("/api/doc/swagger.json", code=302)

View File

@ -1,6 +1,7 @@
from dataclasses import dataclass from dataclasses import dataclass
@dataclass @dataclass
class Item: class Item:
id: str id: str
price: str price: str

View File

@ -2,4 +2,4 @@ from main import app
# disabled threading for easier session handleing in this demo project # disabled threading for easier session handleing in this demo project
# if threaded was True, as session store would be needed # if threaded was True, as session store would be needed
app.run(host="0.0.0.0", port='80', debug=False, threaded=False) app.run(host="0.0.0.0", port="80", debug=False, threaded=False)

View File

@ -1,4 +1,3 @@
from collections import defaultdict from collections import defaultdict
from DealsService import DealsService from DealsService import DealsService
from ProductService import ProductService from ProductService import ProductService
@ -18,7 +17,7 @@ class BasketService:
items = self.baskets[sessionID] items = self.baskets[sessionID]
prices = self.dealsService.get_items_with_final_prices(items) 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:
item = self.productService.get_item_from_id(itemId) item = self.productService.get_item_from_id(itemId)
self.baskets[session_id].append(item) self.baskets[session_id].append(item)

View File

@ -1,4 +1,3 @@
from collections import defaultdict from collections import defaultdict
import math import math
@ -14,10 +13,9 @@ class DealsService:
self.promotions["A0001"].append("two_for_one") self.promotions["A0001"].append("two_for_one")
self.promotions["A0002"].append("ten_percent_off") self.promotions["A0002"].append("ten_percent_off")
# deal behavior needs to be programmed an can only be # deal behavior needs to be programmed an can only be
# changed with the rollout of a new version, # changed with the rollout of a new version,
self.deals["two_for_one"] = DealsService.two_for_one_deal self.deals["two_for_one"] = DealsService.two_for_one_deal
def get_items_with_final_prices(self, items) -> list: def get_items_with_final_prices(self, items) -> list:
groups = defaultdict(list) groups = defaultdict(list)
@ -26,7 +24,7 @@ class DealsService:
groups[obj.id].append(obj) groups[obj.id].append(obj)
for group in groups.values(): for group in groups.values():
# 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
@ -40,36 +38,38 @@ class DealsService:
break break
return [item for group in groups.values() for item in group] return [item for group in groups.values() for item in group]
@staticmethod @staticmethod
def two_for_one_deal(group): 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() # 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): def _round_up(self, val: float):
return math.ceil(val*100)/100 return math.ceil(val * 100) / 100
# could be compressed # could be compressed
# not done since this would be the 2 different functions in the above mentioned interface # not done since this would be the 2 different functions in the above mentioned interface
deal_is_applicable = False deal_is_applicable = False
if len(group) >= 2: if len(group) >= 2:
deal_is_applicable = True deal_is_applicable = True
for i in range(len(group)//2): for i in range(len(group) // 2):
group[i].price = _round_up(group[i].price / 2) group[i].price = _round_up(group[i].price / 2)
return deal_is_applicable return deal_is_applicable
@staticmethod @staticmethod
def ten_percent_off(group): def ten_percent_off(group):
# the percentage discount could be added to function signature # the percentage discount could be added to function signature
'''' 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() # 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): def _round_up(self, val: float):
return math.ceil(val*100)/100 return math.ceil(val * 100) / 100
deal_is_applicable = True deal_is_applicable = True
for i in range(len(group)): for i in range(len(group)):
group[i].price = _round_up(group[i].price * 0.9) group[i].price = _round_up(group[i].price * 0.9)
return deal_is_applicable return deal_is_applicable

View File

@ -2,7 +2,7 @@ from src.models import Item
class ProductService: class ProductService:
# prices are global, sheduled function to refresh prices periodically # prices are global, sheduled function to refresh prices periodically
# could save ressources under high load # could save ressources under high load
prices = dict() prices = dict()
@ -11,6 +11,5 @@ class ProductService:
self.prices["A0001"] = 12.99 self.prices["A0001"] = 12.99
self.prices["A0002"] = 3.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))