diff --git a/store/forms.py b/store/forms.py
index 5c1902d2c45c32f33c86d870724a2184da29774b..7daa55392a7be29d6814f23a575b4b1c64f0ae99 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 3597e5f00bab99de0de2ae00a429edafcdd8ee5e..8ac45a32128f3f28efeb968a670d9b39c6790f63 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 4d11e65bf08cf3dc4757574bdef53840a88724ae..7ecd7c30bf1fd77fe0c1a464916c399ebc05ca54 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 6f3ec9a8f5b20d72d9206b1b4e09f4279b35aa04..590fba667ca004d4782c6a46db9d05a17b94b236 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")