diff --git a/app/forms.py b/app/forms.py index 5a1520e..e5c6981 100644 --- a/app/forms.py +++ b/app/forms.py @@ -7,10 +7,10 @@ from flask_wtf import FlaskForm as Form from wtforms import (DateTimeField, SelectField, StringField, SubmitField, validators) +from utils import euro_string from hlds.definitions import location_definitions from hlds.models import Location from models import User -from utils import euro_string class OrderForm(Form): @@ -18,7 +18,7 @@ class OrderForm(Form): # pylint: disable=R0903 courier_id = SelectField("Courier", coerce=int) location_id = SelectField( - "Location", coerce=int, validators=[validators.required()] + "Location", coerce=str, validators=[validators.required()] ) starttime = DateTimeField( "Starttime", default=datetime.now, format="%d-%m-%Y %H:%M" @@ -47,15 +47,15 @@ class OrderForm(Form): class OrderItemForm(Form): "Class which defines the form for a new Item in an Order" # pylint: disable=R0903 - product_id = SelectField("Item", coerce=int) - extra = StringField("Extra") + dish_id = SelectField("Dish") + comment = StringField("Comment") submit_button = SubmitField("Submit") def populate(self, location: Location) -> None: - "Fill in all the product options from the location" - self.product_id.choices = [ + "Fill in all the dish options from the location" + self.dish_id.choices = [ (i.id, (i.name + ": " + euro_string(i.price))) - for i in location.products + for i in location.dishes ] @@ -68,7 +68,7 @@ class AnonOrderItemForm(OrderItemForm): def populate(self, location: Location) -> None: """ - Fill in all the product options from the location and + Fill in all the dish options from the location and the name of the anon user """ OrderItemForm.populate(self, location) diff --git a/app/hlds/models.py b/app/hlds/models.py index dc1ec81..68160f1 100644 --- a/app/hlds/models.py +++ b/app/hlds/models.py @@ -2,6 +2,7 @@ # pylint: disable=too-few-public-methods from typing import Iterable, List, Mapping, Any, Optional +from utils import euro_string def _format_tags(tags: Iterable[str]) -> str: @@ -13,7 +14,7 @@ def _format_tags(tags: Iterable[str]) -> str: def _format_price(price: int) -> str: - return " € {}.{:02}".format(*divmod(price, 100)) if price else "" + return " {}".format(euro_string(price)) if price else "" def _format_type_and_choice(type_and_choice): diff --git a/app/models/order.py b/app/models/order.py index cf27ae2..4cdb185 100644 --- a/app/models/order.py +++ b/app/models/order.py @@ -2,6 +2,8 @@ import typing from datetime import datetime +from utils import first +from hlds.definitions import location_definitions from .database import db from .user import User @@ -18,13 +20,12 @@ class Order(db.Model): items = db.relationship("OrderItem", backref="order", lazy="dynamic") - def configure(self, courier: User, - starttime: db.DateTime, stoptime: db.DateTime,) -> None: - "Configure the Order" - # pylint: disable=W0201 - self.courier = courier - self.starttime = starttime - self.stoptime = stoptime + def __getattr__(self, name): + if name == "location": + location = first(filter(lambda l: l.id == self.location_id, location_definitions)) + if location: + return location + raise AttributeError() def __repr__(self) -> str: # pylint: disable=R1705 @@ -33,6 +34,14 @@ class Order(db.Model): else: return "Order %d" % (self.id) + def update_from_hlds(self) -> None: + """ + Update the location name from the HLDS definition. + User should commit after running this to make the change persistent. + """ + assert self.location_id, "location_id must be configured before updating from HLDS" + self.location_name = self.location.name + def group_by_user(self) -> typing.Dict[str, typing.Any]: "Group items of an Order by user" group: typing.Dict[str, typing.Any] = dict() @@ -44,20 +53,20 @@ class Order(db.Model): item.price if not item.paid else 0 ) user["paid"] = user.get("paid", True) and item.paid - user["products"] = user.get("products", []) + [item.dish_name] + user["dishes"] = user.get("dishes", []) + [item.dish_name] group[item.get_name()] = user return group - def group_by_product(self) -> typing.Dict[str, typing.Any]: - "Group items of an Order by product" + def group_by_dish(self) -> typing.Dict[str, typing.Any]: + "Group items of an Order by dish" group: typing.Dict[str, typing.Any] = dict() for item in self.items: - product = group.get(item.dish_name, dict()) - product["count"] = product.get("count", 0) + 1 - if item.extra: - product["extras"] = product.get("extras", []) + [item.comment] - group[item.dish_name] = product + dish = group.get(item.dish_name, dict()) + dish["count"] = dish.get("count", 0) + 1 + if item.comment: + dish["comments"] = dish.get("comments", []) + [item.comment] + group[item.dish_name] = dish return group diff --git a/app/models/orderitem.py b/app/models/orderitem.py index f597163..ec2cc88 100644 --- a/app/models/orderitem.py +++ b/app/models/orderitem.py @@ -1,6 +1,8 @@ "Script for everything OrderItem related in the database" from datetime import datetime +from utils import first +from hlds.definitions import location_definitions from .database import db from .order import Order from .user import User @@ -23,17 +25,21 @@ class OrderItem(db.Model): choices = db.relationship("OrderItemChoice", backref="order_item", lazy="dynamic") - def configure(self, user: User, order: Order) -> None: - "Configure the OrderItem" - # pylint: disable=W0201 - self.user = user - self.order = order + def __getattr__(self, name): + if name == "dish": + location_id = Order.query.filter(Order.id == self.order_id).first().location_id + location = first(filter(lambda l: l.id == location_id, location_definitions)) + if location: + return first(filter(lambda d: d.id == self.dish_id, location.dishes)) + else: + raise ValueError("No Location found with id: " + location_id) + raise AttributeError() def get_name(self) -> str: "Get the name of the user which 'owns' the item" if self.user_id is not None and self.user_id > 0: return self.user.username - return self.name + return self.user_name def __repr__(self) -> str: return "Order %d: %s wants %s" % ( @@ -42,6 +48,16 @@ class OrderItem(db.Model): self.dish_name or "None", ) + def update_from_hlds(self) -> None: + """ + Update the dish name and price from the HLDS definition. + User should commit after running this to make the change persistent. + """ + assert self.order_id, "order_id must be configured before updating from HLDS" + assert self.dish_id, "dish_id must be configured before updating from HLDS" + self.dish_name = self.dish.name + self.price = self.dish.price + # pylint: disable=W0613 def can_delete(self, order_id: int, user_id: int, name: str) -> bool: "Check if a user can delete an item" diff --git a/app/notification.py b/app/notification.py index 023b346..1218aa9 100644 --- a/app/notification.py +++ b/app/notification.py @@ -10,30 +10,30 @@ from flask import url_for from models.order import Order -def webhook_text(order_item: Order) -> typing.Optional[str]: +def webhook_text(order: Order) -> typing.Optional[str]: "Function that makes the text for the notification" - if "Testlocation" in order_item.location.name: + if order.location_id == "test": return None - if order_item.courier is not None: + if order.courier is not None: # pylint: disable=C0301 return " {3} is going to {1}, order <{0}|here>! Deadline in {2} minutes!".format( - url_for("order_bp.order_from_id", order_id=order_item.id, _external=True), - order_item.location.name, - remaining_minutes(order_item.stoptime), - order_item.courier.username.title(), + url_for("order_bp.order_from_id", order_id=order.id, _external=True), + order.location_name, + remaining_minutes(order.stoptime), + order.courier.username.title(), ) return " New order for {}. Deadline in {} minutes. <{}|Open here.>".format( - order_item.location.name, - remaining_minutes(order_item.stoptime), - url_for("order_bp.order_from_id", order_id=order_item.id, _external=True), + order.location_name, + remaining_minutes(order.stoptime), + url_for("order_bp.order_from_id", order_id=order.id, _external=True), ) -def post_order_to_webhook(order_item: Order) -> None: +def post_order_to_webhook(order: Order) -> None: "Function that sends the notification for the order" - message = webhook_text(order_item) + message = webhook_text(order) if message: webhookthread = WebhookSenderThread( message, app.config["SLACK_WEBHOOK"]) diff --git a/app/templates/order.html b/app/templates/order.html index 6783119..1fc3b78 100644 --- a/app/templates/order.html +++ b/app/templates/order.html @@ -43,15 +43,15 @@ Choose for me {{ form.csrf_token }} -