Fix anonymous ordering and dish change

This commit is contained in:
Midgard 2020-02-26 21:25:51 +01:00
parent e15b085006
commit 729dab2ba4
Signed by: midgard
GPG key ID: 511C112F1331BBB4
3 changed files with 50 additions and 38 deletions

View file

@ -3,7 +3,7 @@ from datetime import datetime, timedelta
from typing import Optional from typing import Optional
from flask import session from flask import session, request
from flask_login import current_user from flask_login import current_user
from flask_wtf import FlaskForm as Form from flask_wtf import FlaskForm as Form
from wtforms import (DateTimeField, SelectField, SelectMultipleField, StringField, SubmitField, from wtforms import (DateTimeField, SelectField, SelectMultipleField, StringField, SubmitField,
@ -65,6 +65,8 @@ class OrderItemForm(Form):
(dish.id, (dish.name + ": " + self.format_price_range(dish.price_range()))) (dish.id, (dish.name + ": " + self.format_price_range(dish.price_range())))
for dish in location.dishes for dish in location.dishes
] ]
if not self.is_submitted() and self.comment.data is None:
self.comment.data = request.args.get("comment")
class AnonOrderItemForm(OrderItemForm): class AnonOrderItemForm(OrderItemForm):
@ -72,7 +74,7 @@ class AnonOrderItemForm(OrderItemForm):
Class which defines the form for a new Item in an Order Class which defines the form for a new Item in an Order
For Users who aren't logged in For Users who aren't logged in
""" """
name = StringField("Name", validators=[validators.required()]) user_name = StringField("Name", validators=[validators.required()])
def populate(self, location: Location) -> None: def populate(self, location: Location) -> None:
""" """
@ -80,8 +82,11 @@ class AnonOrderItemForm(OrderItemForm):
the name of the anon user the name of the anon user
""" """
OrderItemForm.populate(self, location) OrderItemForm.populate(self, location)
if self.name.data is None: if not self.is_submitted():
self.name.data = session.get("anon_name", None) if self.user_name.data is None:
self.user_name.data = request.args.get("user_name")
if self.user_name.data is None:
self.user_name.data = session.get("anon_name", None)
def validate(self) -> bool: def validate(self) -> bool:
"Check if the provided anon_name is not already taken" "Check if the provided anon_name is not already taken"
@ -90,8 +95,8 @@ class AnonOrderItemForm(OrderItemForm):
return False return False
# check if we have a user with this name # check if we have a user with this name
user = User.query.filter_by(username=self.name.data).first() user = User.query.filter_by(username=self.user_name.data).first()
if user is not None: if user is not None:
self.name.errors.append("Name already in use") self.user_name.errors.append("Name already in use")
return False return False
return True return True

View file

@ -42,9 +42,6 @@
{% if form -%} {% if form -%}
<div class="col-md-push-1 col-md-10 darker order_order" id="form"> <div class="col-md-push-1 col-md-10 darker order_order" id="form">
<h4>Order:</h4> <h4>Order:</h4>
{% if current_user.is_anonymous() %}
<div>Sorry, anonymous ordering is currently broken. Please log in to order.</div>
{% else %}
<form method="post" action="{{ url_for('order_bp.order_item_create', order_id=order.id) }}"> <form method="post" action="{{ url_for('order_bp.order_item_create', order_id=order.id) }}">
<span class="pull-right"> <span class="pull-right">
<a class="btn btn-primary" onclick="chooseRandom()">Choose for me</a> <a class="btn btn-primary" onclick="chooseRandom()">Choose for me</a>
@ -83,10 +80,10 @@
</div> </div>
{% if current_user.is_anonymous() %} {% if current_user.is_anonymous() %}
<div class="form-group{{ ' has-error' if form.name.errors }}{{ ' required' if form.name.flags.required }}"> <div class="form-group{{ ' has-error' if form.user_name.errors }}{{ ' required' if form.user_name.flags.required }}">
{{ form.name.label(class='control-label') }} {{ form.user_name.label(class='control-label') }}
{{ form.name(class='form-control', placeholder='Fill in your name...') }} {{ form.user_name(class='form-control', placeholder='Fill in your name...') }}
{{ util.render_form_field_errors(form.name) }} {{ util.render_form_field_errors(form.user_name) }}
</div> </div>
{% endif %} {% endif %}
<div class="form-group" style="padding-top: 8px;"> <div class="form-group" style="padding-top: 8px;">
@ -96,7 +93,6 @@
{% endif %} {% endif %}
</div> </div>
</form> </form>
{% endif %}
</div> </div>
{%- endif %} {%- endif %}
</div> </div>

View file

@ -129,16 +129,13 @@ def order_item_create(order_id: int) -> typing.Any:
dish_id = form.dish_id.data if form.is_submitted() else request.args.get("dish") dish_id = form.dish_id.data if form.is_submitted() else request.args.get("dish")
if dish_id and not location.dish_by_id(dish_id): if dish_id and not location.dish_by_id(dish_id):
abort(404) abort(404)
if not form.is_submitted():
form.dish_id.data = dish_id form.dish_id.data = dish_id
form.populate(current_order.location) form.populate(current_order.location)
# If the form was not submitted (GET request), the form had errors, if form.is_submitted():
# or the dish was changed: show form again form_for_dish = request.form.get("form_for_dish_id")
dish_was_changed = request.form.get("form_for_dish_id") and request.form["form_for_dish_id"] != dish_id dish_was_changed = form_for_dish is not None and form_for_dish != dish_id
if not form.validate_on_submit() or dish_was_changed:
return order_from_id(order_id, form=form, dish_id=dish_id)
# Form was submitted and is valid
# The form's validation tests that dish_id is valid and gives a friendly error if it's not # The form's validation tests that dish_id is valid and gives a friendly error if it's not
choices = location.dish_by_id(form.dish_id.data).choices choices = location.dish_by_id(form.dish_id.data).choices
@ -151,9 +148,20 @@ def order_item_create(order_id: int) -> typing.Any:
for (choice_type, choice) in choices for (choice_type, choice) in choices
] ]
all_choices_present = all(x is not None for x in chosen) all_choices_present = all(x is not None for x in chosen)
if not all_choices_present:
if dish_was_changed or not all_choices_present:
user_name = form.user_name.data if form.user_name.validate(form) else None
comment = form.comment.data if form.comment.validate(form) else None
return redirect(url_for("order_bp.order_item_create", return redirect(url_for("order_bp.order_item_create",
order_id=order_id, dish=form.dish_id.data)) order_id=order_id, dish=form.dish_id.data,
user_name=user_name, comment=comment))
# If the form was not submitted (GET request) or the form had errors: show form again
if not form.validate_on_submit():
return order_from_id(order_id, form=form, dish_id=dish_id)
# Form was submitted and is valid
item = OrderItem() item = OrderItem()
form.populate_obj(item) form.populate_obj(item)
@ -162,15 +170,18 @@ def order_item_create(order_id: int) -> typing.Any:
if not current_user.is_anonymous(): if not current_user.is_anonymous():
item.user_id = current_user.id item.user_id = current_user.id
else: else:
session["anon_name"] = item.name session["anon_name"] = item.user_name
# XXX Temporary until OrderItemChoice is used # XXX Temporary until OrderItemChoice is used
def _name(option): def _name(option):
no_text_tag = "no_text"
try: try:
if not option or no_text_tag in option.tags:
return None
return option.name return option.name
except AttributeError: except AttributeError:
return ", ".join(o.name for o in option) return ", ".join(o.name for o in option if no_text_tag not in o.tags)
comments = [_name(option) for option in chosen if option and "no_text" not in option.tags] comments = list(ignore_none(_name(option) for option in chosen))
if item.comment: if item.comment:
comments.append("Comment: " + item.comment) comments.append("Comment: " + item.comment)
item.comment = "; ".join(comments) item.comment = "; ".join(comments)
@ -221,7 +232,7 @@ def items_user_paid(order_id: int, user_name: str) -> typing.Optional[Response]:
).all() ).all()
else: else:
items = OrderItem.query.filter( items = OrderItem.query.filter(
(OrderItem.name == user_name) & (OrderItem.order_id == order_id) (OrderItem.user_name == user_name) & (OrderItem.order_id == order_id)
).all() ).all()
current_order = Order.query.filter(Order.id == order_id).first() current_order = Order.query.filter(Order.id == order_id).first()
for item in items: for item in items: