From fc630e90616a7a088a1345da0e54da478cb12e34 Mon Sep 17 00:00:00 2001 From: Midgard Date: Sun, 27 Mar 2022 19:33:14 +0200 Subject: [PATCH] Support marking items as paid --- app/models/orderitem.py | 9 +++++++ app/templates/order.html | 25 +++++++++++++----- app/views/order.py | 56 ++++++++++++++++++++++++++-------------- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/app/models/orderitem.py b/app/models/orderitem.py index b865b51..6e85e6c 100644 --- a/app/models/orderitem.py +++ b/app/models/orderitem.py @@ -73,3 +73,12 @@ class OrderItem(db.Model): if user and (user.is_admin() or user == self.order.courier): return True return False + + # pylint: disable=W0613 + def can_modify_payment(self, order_id: int, user_id: int) -> bool: + if int(self.order_id) != int(order_id): + return False + user = User.query.filter(User.id == user_id).first() + if user and (user.is_admin() or user == self.order.courier): + return True + return False diff --git a/app/templates/order.html b/app/templates/order.html index 8ac6f4e..60e1cf5 100644 --- a/app/templates/order.html +++ b/app/templates/order.html @@ -267,6 +267,7 @@

Items per person

+
@@ -276,12 +277,20 @@
TotalNameItems
{% set paid = order_items | map(attribute="paid") | all %} - + {% set can_modify_payment = True %} + {% for order_item in order_items %} + {% if not order_item.can_modify_payment(order.id, current_user.id) %} + {% set can_modify_payment = False %} + {% endif %} + {% endfor %} + - {{ order_items | map(attribute="price") | sum | euro }} + + {{ order_items | map(attribute="price") | sum | euro }} + - {% if paid %}paid{% endif %} + {% if paid %}{% endif %} {{ user_name }} @@ -315,10 +324,12 @@ + {% endblock %} diff --git a/app/views/order.py b/app/views/order.py index 49ca679..ad2ccad 100644 --- a/app/views/order.py +++ b/app/views/order.py @@ -225,29 +225,47 @@ def order_item_create(order_id: int) -> typing.Any: return redirect(url_for("order_bp.order_from_id", order_id=order_id)) -@order_bp.route("///user_paid", methods=["POST"]) +@order_bp.route("//users_paid", methods=["POST"]) @login_required # pylint: disable=R1710 -def items_user_paid(order_id: int, user_name: str) -> typing.Optional[Response]: - "Indicate payment status for a user in an order" - user = User.query.filter(User.username == user_name).first() - items: typing.List[OrderItem] = [] - if user: - items = OrderItem.query.filter( - (OrderItem.user_id == user.id) & (OrderItem.order_id == order_id) - ).all() +def items_user_paid(order_id: int) -> typing.Optional[Response]: + user_names = request.form.getlist("user_names") + if request.form.get("action") == "mark_paid": + return set_items_paid(order_id, user_names, True) + elif request.form.get("action") == "mark_unpaid": + return set_items_paid(order_id, user_names, False) else: - items = OrderItem.query.filter( - (OrderItem.user_name == user_name) & (OrderItem.order_id == order_id) - ).all() - current_order = Order.query.filter(Order.id == order_id).first() - if current_order.courier_id == current_user.id or current_user.admin: + abort(404) + +def set_items_paid(order_id: int, user_names: typing.Iterable[str], paid: bool): + total_paid_items = 0 + total_failed_items = 0 + for user_name in user_names: + user = User.query.filter(User.username == user_name).first() + items: typing.List[OrderItem] = [] + if user: + items = OrderItem.query.filter( + (OrderItem.user_id == user.id) & (OrderItem.order_id == order_id) + ).all() + else: + items = OrderItem.query.filter( + (OrderItem.user_name == user_name) & (OrderItem.order_id == order_id) + ).all() + for item in items: - item.paid = True - db.session.commit() - flash("Paid %d items for %s" % (len(items), item.for_name), "success") - return redirect(url_for("order_bp.order_from_id", order_id=order_id)) - abort(404) + if item.can_modify_payment(order_id, current_user.id): + if item.paid != paid: + item.paid = paid + total_paid_items += 1 + else: + total_failed_items += 1 + + db.session.commit() + if total_failed_items == 0: + flash("Marked %d items as paid" % (total_paid_items,), "success") + else: + flash("Failed to mark %d items as paid (succeeded in marking %d items as paid)" % (total_failed_items, total_paid_items), "error") + return redirect(url_for("order_bp.order_from_id", order_id=order_id)) @order_bp.route("///delete", methods=["POST"])