From 4b8f82da3c7a07c497ad1850c1f69609fd4719b3 Mon Sep 17 00:00:00 2001 From: b4-sharp <Bradley2.Sharp@live.uwe.ac.uk> Date: Mon, 24 Apr 2023 15:23:19 +0100 Subject: [PATCH] Fix add item issue, and checkout --- store/forms.py | 42 +-------------- store/routes.py | 99 +++++++++++++++++++++++++++++++---- store/templates/checkout.html | 4 +- store/utility.py | 46 ++++++---------- 4 files changed, 109 insertions(+), 82 deletions(-) diff --git a/store/forms.py b/store/forms.py index 5c1902d..7daa553 100644 --- a/store/forms.py +++ b/store/forms.py @@ -14,7 +14,6 @@ from wtforms import ( validators, ) import datetime -from store.utility import validate_address, validate_cvv_2 class RegistrationForm(FlaskForm): @@ -70,44 +69,5 @@ class AddForm(FlaskForm): "Table", choices=["Item", "Item Set"], validators=[validators.DataRequired()] ) description = StringField("Description", validators=[validators.DataRequired()]) - price = DecimalField(default=0, validators=[validators.InputRequired()]) + price = IntegerField(default=0, validators=[validators.InputRequired()]) submit = SubmitField("Submit") - - -class CheckoutForm(FlaskForm): - months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] - today = datetime.date.today() - year = int(today.year) - years = [year] - for year in range(year, year + 50, 1): - years.append(year) - name = StringField( - "Name on card", [validators.Length(min=2, max=30), validators.DataRequired()] - ) - card_number = StringField( - "Card Number", [validators.Length(min=15, max=16), validators.DataRequired()] - ) - exp_date_month = SelectField("Month", [validators.DataRequired()], choices=months) - exp_date_year = SelectField("Year", [validators.DataRequired()], choices=years) - cvv_2 = StringField( - "CVV2", - [validators.Length(min=3, max=4), validators.DataRequired(), validate_cvv_2], - ) - address = TextAreaField( - "Address", - [ - validators.Length(min=10, max=250), - validators.DataRequired(), - validate_address, - ], - ) - postcode = StringField( - "Postcode", - [ - validators.Length(min=6, max=10), - validators.DataRequired(), - validate_address, - ], - ) - - submit = SubmitField("Complete Payment") diff --git a/store/routes.py b/store/routes.py index 3597e5f..8ac45a3 100644 --- a/store/routes.py +++ b/store/routes.py @@ -9,6 +9,20 @@ from flask import ( session, abort, ) +from flask_wtf import FlaskForm +from flask_wtf.csrf import generate_csrf +import requests +import datetime +import re +from wtforms import ( + Form, + StringField, + validators, + SelectField, + TextAreaField, + ValidationError, + HiddenField, +) import json from store.utility import * from store.forms import * @@ -485,6 +499,71 @@ def ChangePhNumber(): return render_template("userContent/ChangePhNumber.html") +def validate_cvv_2(form, field): + regex = "^[0-9]{3,4}$" + p = re.compile(regex) + if not re.search(p, field.data): + raise ValidationError("CVV2 is incorrect") + + +def validate_address(form, field): + # Uses the google maps geocoding api to check if a postcode or address exists + + url = "https://maps.googleapis.com/maps/api/geocode/json" + + api_key = "AIzaSyCz4xyIl5yaIg869orL07ye2ainw7kv5Pc" + + params = {"address": field, "key": api_key} + + response = requests.get(url, params=params).json() + + # Check if response status is "OK" and has at least one result + if response["status"] == "OK" and len(response["results"]) > 0: + print("Valid address or postcode") + pass + else: + raise ValidationError("Enter valid address") + + +class CheckoutForm(Form): + months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] + today = datetime.date.today() + year = int(today.year) + years = [year] + for year in range(year, year + 50, 1): + years.append(year) + name = StringField( + "Name on card", [validators.Length(min=2, max=30), validators.DataRequired()] + ) + card_number = StringField( + "Card Number", [validators.Length(min=15, max=16), validators.DataRequired()] + ) + exp_date_month = SelectField("Month", [validators.DataRequired()], choices=months) + exp_date_year = SelectField("Year", [validators.DataRequired()], choices=years) + cvv_2 = StringField( + "CVV2", + [validators.Length(min=3, max=4), validators.DataRequired(), validate_cvv_2], + ) + address = TextAreaField( + "Address", + [ + validators.Length(min=10, max=250), + validators.DataRequired(), + validate_address, + ], + ) + postcode = StringField( + "Postcode", + [ + validators.Length(min=6, max=10), + validators.DataRequired(), + validate_address, + ], + ) + # Cross-site request forgery token to make sure requests are sent from our site + csrf_token = HiddenField() + + @app.route("/order_summary") def order_summary(): total_price = 0 @@ -514,19 +593,21 @@ def checkout(): total_price = total_price + item["price"] if request.method == "POST" and form.validate(): session["address"] = str(form.address.data + ", " + form.postcode.data) - try: - for item_id, item, is_item_set in session["basket"]: - if is_item_set == True: - sell_item(get_item_set_by_id(item_id)) - else: - sell_item(get_item_by_id(item_id)) - return redirect(url_for("order_summary")) - except: - flash("One or more items in basket have already been sold!") + for item_id in session["basket"]: + item = session["basket"][item_id] + if item["is_item_set"] == True: + print("Sell item set: ", item_id) + sell_item_set(get_item_set_by_id(item_id)) + else: + print("Sell item: ", item_id) + sell_item(get_item_by_id(item_id)) + return redirect(url_for("order_summary")) + csrf_token = generate_csrf() return render_template( "checkout.html", form=form, total_price=total_price, + csrf_token=csrf_token, items=items, ) diff --git a/store/templates/checkout.html b/store/templates/checkout.html index 4d11e65..7ecd7c3 100644 --- a/store/templates/checkout.html +++ b/store/templates/checkout.html @@ -9,7 +9,7 @@ <div class="col"> <h1>Checkout</h1> <form method='POST'> - {{ form.hidden_tag() }} + {{ form.csrf_token }} {{ render_field(form.name, class="form-control") }} {{ render_field(form.card_number, class="form-control") }} {{ render_field(form.exp_date_month, class="form-control") }} @@ -17,7 +17,7 @@ {{ render_field(form.cvv_2, class="form-control") }} {{ render_field(form.address, class="form-control") }} {{ render_field(form.postcode, class="form-control") }} - {{form.submit(class="btn btn-primary")}} + <input class="btn btn-primary" type="submit" value="Complete payment"> </form> </div> <div class="col"> diff --git a/store/utility.py b/store/utility.py index 6f3ec9a..590fba6 100644 --- a/store/utility.py +++ b/store/utility.py @@ -83,10 +83,13 @@ def get_by_keyword(substring): This is most useful for a user keyword search. """ substring = substring.lower() - return ( - ItemSet.query.filter(func.lower(ItemSet.description.contains(substring))).all() - + Item.query.filter(func.lower(Item.description.contains(substring))).all() - ) + items = Item.query.filter(func.lower(Item.description.contains(substring))).all() + items = [item for item in items if item.date_sold == None] + item_sets = ItemSet.query.filter( + func.lower(ItemSet.description.contains(substring)) + ).all() + + return item_sets + items def get_itemsets_by_item_id(item_id): @@ -126,6 +129,15 @@ def remove_item_set(item): db.session.commit() +def sell_item_set(item_set, date=datetime.datetime.today()): + for item in item_set.items: + item.date_sold = date + + db.session.commit() + remove_item_set(item_set) + db.session.commit() + + def sell_item(item, date=datetime.datetime.today()): update_set(item) item.date_sold = date @@ -164,29 +176,3 @@ def update_set(reference_item): def get_item_by_id(id): return Item.query.get(id) - - -def validate_address(form, field): - # Uses the google maps geocoding api to check if a postcode or address exists - - url = "https://maps.googleapis.com/maps/api/geocode/json" - - api_key = "AIzaSyCz4xyIl5yaIg869orL07ye2ainw7kv5Pc" - - params = {"address": field, "key": api_key} - - response = requests.get(url, params=params).json() - - # Check if response status is "OK" and has at least one result - if response["status"] == "OK" and len(response["results"]) > 0: - print("Valid address or postcode") - pass - else: - raise ValidationError("Enter valid address") - - -def validate_cvv_2(form, field): - regex = "^[0-9]{3,4}$" - p = re.compile(regex) - if not re.search(p, field.data): - raise ValidationError("CVV2 is incorrect") -- GitLab