def messageFunction(): if request.method == "POST": # Get variables for email to send to Glenn subject1 = "Message from " + getUserName() html = request.form.get("ckeditor") text = html2text.html2text(html) body1 = "Username: "******"\nEmail: " + getUserEmail( ) + "\n\nMessage: " + text email1 = os.environ["EMAIL_SEND"] # Send email to Glenn sendMail(subject1, email1, body1) # Get variables for email to send to user subject2 = "Copy of your message" body2 = "You wrote: " + text email2 = getUserEmail() # Send copy to user sendMail(subject2, email2, body2) flash("Message sent", "success") return redirect("/") else: return render_template("message.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def addNewsFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable title = request.form.get("title") body = request.form.get("ckeditor") # Insert title and body into the table db.session.add(News(title=title, body=body)) db.session.commit() # Flash result & redirect flash("News created", "success") return redirect("/communication") else: return render_template("addNews.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def editNewsFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable news_id = request.form.get("news_id") title = request.form.get("title") html = request.form.get("ckeditor") body = html2text.html2text(html) # Update plant name, stock, price, description and show status into the table query = News.query.filter_by(id=news_id).first() query.title = title query.body = body db.session.commit() # Flash result & redirect flash("News edited", "success") return redirect("/communication") else: # Get arguments from url_for in administration thisNews = request.args.getlist("news") return render_template("editNews.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), news=thisNews)
def emailFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable user_id = session["user_id"] # Delete row in DB Users.query.filter_by(id=user_id).delete() db.session.commit() # Clear session session.clear() # Flash result & redirect flash("Account deleted", "warning") return redirect("/signin") else: return render_template("delete.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def historyFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # Get variable user_id = session["user_id"] # Query database for orders orders = Orders.query.filter_by(user_id=user_id).all() # Make array of arrays of plants in Orders plants = [] for order in orders: plants.extend([eval(order.plants)]) # User reached route via POST (as by submitting a form via POST) if request.method == "POST": print("History") else: return render_template("history.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), zip=zip(orders, plants))
def communicationFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # Query database for news to display them news = News.query.all() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": if "erase" in request.form: # Loop through the record list to match plant ID when delete button is pressed index = 0 while index < len(news): if int(request.form["erase"]) == int(news[index].id): # Query database for plant id to delete row News.query.filter(News.id == news[index].id).delete() db.session.commit() # Flash result & redirect flash("News deleted", "success") return redirect("/communication") else: index += 1 if "change" in request.form: # Loop through the record list to match plant ID when edit button is pressed index = 0 while index < len(news): if int(request.form["change"]) == int(news[index].id): # Create a list with values of DB and append them thisNews = [] thisNews.extend( [news[index].id, news[index].title, news[index].body]) return redirect( url_for("change.changeFunction", news=thisNews)) else: index += 1 else: return render_template("communication.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), news=news)
def aboutFunction(): if request.method == "POST": print("about") return render_template("about.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def newsletterFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() if request.method == "POST": # Get variable subject = request.form.get("subject") html = request.form.get("ckeditor") text = html2text.html2text(html) address = request.form.get("address") newsletter = request.form.get("newsletter") # Query database for user emails for newsletter query = Users.query.filter_by(newsletter="True").all() if query == None: flash("No email in DB", "warning") return redirect("/newsletter") if address != "" and newsletter == None: # Send email (subject, email, body) sendMail(subject, address, text) flash("Single email sent", "success") elif address == "" and newsletter == newsletter: # Loop through email list and send index = 0 while index < len(query): sendMail(subject, query[index].email, text) index += 1 # Send a copy to Glenn sendMail(subject, os.environ["EMAIL_SEND"], text) flash("Group email sent", "success") else: # Flash result & redirect flash( "Send to one address or select Send Newsletter and leave address blank", "danger") return redirect("/newsletter") return redirect("/") else: return render_template("newsletter.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def emailFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable email = request.form.get("email") user_id = session["user_id"] # Ensure email was submitted if not email: flash("Must provide email", "warning") return redirect("/email") # Ensure email fits server-side if not re.search(r"[^@]+@[^@]+\.[^@]+", email): flash("Invalid email", "danger") return redirect("/email") # Query database for email if already exists query = Users.query.filter_by(email=email).all() if len(query) != 0: flash("Email already taken", "warning") return redirect("/username") # Update database with email query = Users.query.filter_by(id=user_id).first() query.email = email db.session.commit() # Flash result & redirect flash("Email address updated", "success") return redirect("/profile") else: return render_template("email.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def passwordFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable password = request.form.get("password") user_id = session["user_id"] # Ensure password was submitted if not password: flash("Must provide password", "warning") return redirect("/password") # Query database for hash if already exists query = Users.query.filter_by(id=user_id).first() if check_password_hash(query.hash, password): flash("Password must be new", "danger") return redirect("/password") # Update database with password hash query = Users.query.filter_by(id=user_id).first() query.hash = generate_password_hash(password) db.session.commit() # Flash result & redirect flash("Password updated", "success") return redirect("/profile") else: return render_template("password.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def administrationFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # Query database for plants plants = Plants.query.all() # Query database for boxes boxes = Boxes.query.all() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Plants table section if "delete_plant" in request.form: # Loop through the record list to match plant ID when delete button is pressed index = 0 while index < len(plants): if int(request.form["delete_plant"]) == int(plants[index].id): # Query database for plant id to delete row Plants.query.filter(Plants.id == plants[index].id).delete() db.session.commit() # Flash result & redirect flash("Plant deleted", "success") return redirect("/administration") else: index += 1 if "edit_plant" in request.form: # Loop through the record list to match plant ID when edit button is pressed index = 0 while index < len(plants): if int(request.form["edit_plant"]) == int(plants[index].id): # Create a list with values of DB and append them thisPlant = [] thisPlant.extend([ plants[index].id, plants[index].name, plants[index].stock, plants[index].price, plants[index].offer, plants[index].length, plants[index].width, plants[index].height, plants[index].weight, plants[index].picture, plants[index].description, plants[index].express, plants[index].reduced, plants[index].show ]) return redirect( url_for("editPlant.editPlantFunction", plants=thisPlant)) else: index += 1 # Boxes table section if "delete_box" in request.form: # Loop through the record list to match plant ID when delete button is pressed index = 0 while index < len(boxes): if int(request.form["delete_box"]) == int(boxes[index].id): # Query database for plant id to delete row Boxes.query.filter(Boxes.id == boxes[index].id).delete() db.session.commit() # Flash result & redirect flash("Box deleted", "success") return redirect("/administration") else: index += 1 if "edit_box" in request.form: # Loop through the record list to match plant ID when edit button is pressed index = 0 while index < len(boxes): if int(request.form["edit_box"]) == int(boxes[index].id): # Create a list with values of DB and append them thisBox = [] thisBox.extend([ boxes[index].id, boxes[index].name, boxes[index].length, boxes[index].width, boxes[index].height, boxes[index].price_de, boxes[index].price_eu, boxes[index].price_ex ]) return redirect( url_for("editBox.editBoxFunction", boxes=thisBox)) else: index += 1 else: return render_template("administration.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), plants=plants, boxes=boxes)
def addPlantFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable name = request.form.get("name") stock = request.form.get("stock") price = request.form.get("price") offer = request.form.get("offer") length = request.form.get("length") width = request.form.get("width") height = request.form.get("height") weight = request.form.get("weight") description = request.form.get("ckeditor") express = request.form.get("express") reduced = request.form.get("reduced") show = request.form.get("show") # Check length getInputLength(name, 100, "Name is too long (100)", "danger", "/addPlant") getInputLength(stock, 6, "Stock is too big (6)", "danger", "/addPlant") getInputLength(price, 6, "Price is too big (6)", "danger", "/addPlant") getInputLength(offer, 6, "Offer is too big (6)", "danger", "/addPlant") getInputLength(length, 6, "Length is too big (6)", "danger", "/addPlant") getInputLength(width, 6, "Width is too big (6)", "danger", "/addPlant") getInputLength(height, 6, "Height is too big (6)", "danger", "/addPlant") getInputLength(weight, 6, "Weight is too big (6)", "danger", "/addPlant") getInputLength(description, 300, "Description is too long (300)", "danger", "/addPlant") # Convert offer value to integer if offer == "": offer = 0 # Convert express value to string if express == None: express = "No" if express == "express": express = "Yes" # Convert show value to string if show == None: show = "No" if show == "show": show = "Yes" # Convert reduced value to string if reduced == None: reduced = "No" if reduced == "reduced": reduced = "Yes" # Ensure the plant name was submitted if not name: flash("must provide plant name", "warning") return redirect("/addPlant") # Ensure the plant name fits server-side if not re.search("^[a-zA-Z 0-9]{1,100}$", name): flash("Invalid plant name", "danger") return redirect("/addPlant") # Ensure the plant stock was submitted if not stock: flash("must provide plant stock", "warning") return redirect("/addPlant") # Ensure the plant stock fits server-side if not re.search("^[0-9]+$", stock): flash("Invalid plant stock", "danger") return redirect("/addPlant") # Ensure the plant price was submitted if not price: flash("must provide plant price", "warning") return redirect("/addPlant") # Ensure the plant price fits server-side if not re.search("^[0-9]+\.?[0-9]+$", format(float(price), ".2f")): flash("Invalid plant price", "danger") return redirect("/addPlant") # Ensure the plant offer fits server-side if offer != 0: if not re.search("^[0-9]+\.?[0-9]+$", format(float(offer), ".2f")): flash("Invalid plant offer", "danger") return redirect("/addPlant") # Ensure the plant length was submitted if not length: flash("must provide plant length", "warning") return redirect("/addPlant") # Ensure the plant length fits server-side if not re.search("^[0-9]+$", length): flash("Invalid plant length", "danger") return redirect("/addPlant") # Ensure the plant width was submitted if not width: flash("must provide plant width", "warning") return redirect("/addPlant") # Ensure the plant width fits server-side if not re.search("^[0-9]+$", width): flash("Invalid plant width", "danger") return redirect("/addPlant") # Ensure the plant height was submitted if not height: flash("must provide plant height", "warning") return redirect("/addPlant") # Ensure the plant height fits server-side if not re.search("^[0-9]+$", height): flash("Invalid plant height", "danger") return redirect("/addPlant") # Ensure the plant weight was submitted if not weight: flash("must provide plant weight", "warning") return redirect("/addPlant") # Ensure the plant weight fits server-side if not re.search("^[0-9]+$", weight): flash("Invalid plant weight", "danger") return redirect("/addPlant") # Ensure the plant description was submitted if not description: flash("must provide plant description", "warning") return redirect("/addPlant") # Ensure the plant description fits server-side if not re.search("^(?!;).+", description): flash("Invalid plant description", "danger") return redirect("/addPlant") # Insert plant name, stock, price, description and show status into the table db.session.add( Plants(name=name, stock=stock, price=price, offer=offer, length=length, width=width, height=height, weight=weight, description=description, express=express, reduced=reduced, show=show)) db.session.commit() # Query database for id of the last entered plant query = Plants.query.all() plant_id = query[-1].id # Save, upload and delete picture file file1 = request.files["picture"] if file1 and allowed_file(file1.filename): filename = secure_filename(file1.filename) file1.save(os.path.join("./static", filename)) upload = uploadPicture("./static/" + filename) os.remove("./static/" + filename) # Update database with new image url query = Plants.query.filter_by(id=plant_id).first() query.picture = upload db.session.commit() # Save, upload and delete first thumbnail file file2 = request.files["thumbnail1"] if file2 and allowed_file(file2.filename): filename = secure_filename(file2.filename) file2.save(os.path.join("./static", filename)) upload = uploadPicture("./static/" + filename) os.remove("./static/" + filename) # Update database with new image url query = Plants.query.filter_by(id=plant_id).first() query.thumbnail1 = upload db.session.commit() # Save, upload and delete second thumbnail file file3 = request.files["thumbnail2"] if file3 and allowed_file(file3.filename): filename = secure_filename(file3.filename) file3.save(os.path.join("./static", filename)) upload = uploadPicture("./static/" + filename) os.remove("./static/" + filename) # Update database with new image url query = Plants.query.filter_by(id=plant_id).first() query.thumbnail2 = upload db.session.commit() # Flash result & redirect flash("Plant added", "success") return redirect("/administration") else: return render_template("addPlant.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def addBoxFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable name = request.form.get("name") length = request.form.get("length") width = request.form.get("width") height = request.form.get("height") weight_ne = request.form.get("weight_ne") weight_ex = request.form.get("weight_ex") price_de = request.form.get("price_de") price_eu = request.form.get("price_eu") price_ex = request.form.get("price_ex") # Check length getInputLength(name, 100, "Name is too long (100)", "danger", "/addBox") getInputLength(length, 6, "Length is too big (6)", "danger", "/addBox") getInputLength(width, 6, "Width is too big (6)", "danger", "/addBox") getInputLength(height, 6, "Height is too big (6)", "danger", "/addBox") getInputLength(weight_ne, 6, "Weight non-express is too big (6)", "danger", "/addBox") getInputLength(weight_ex, 6, "Weight express is too big (6)", "danger", "/addBox") getInputLength(price_de, 6, "Price for DE is too big (6)", "danger", "/addBox") getInputLength(price_eu, 6, "Price for EU is too big (6)", "danger", "/addBox") getInputLength(price_ex, 6, "Price for Express is too big (6)", "danger", "/addBox") # Ensure the box name was submitted if not name: flash("must provide box name", "warning") return redirect("/addBox") # Ensure the box name fits server-side if not re.search("^[a-zA-Z 0-9]{1,100}$", name): flash("Invalid box name", "danger") return redirect("/addBox") # Ensure the box length was submitted if not length: flash("must provide box length", "warning") return redirect("/addBox") # Ensure the box length fits server-side if not re.search("^[0-9]+$", length): flash("Invalid box length", "danger") return redirect("/addBox") # Ensure the box width was submitted if not width: flash("must provide box width", "warning") return redirect("/addBox") # Ensure the box width fits server-side if not re.search("^[0-9]+$", width): flash("Invalid box width", "danger") return redirect("/addBox") # Ensure the box height was submitted if not height: flash("must provide box height", "warning") return redirect("/addBox") # Ensure the box height fits server-side if not re.search("^[0-9]+$", height): flash("Invalid box height", "danger") return redirect("/addBox") # Ensure the box weight_ne was submitted if not weight_ne: flash("must provide box weight non-express", "warning") return redirect("/addBox") # Ensure the box weight_ne fits server-side if not re.search("^[0-9]+$", weight_ne): flash("Invalid box weight non-express", "danger") return redirect("/addBox") # Ensure the box weight_ex was submitted if not weight_ex: flash("must provide box weight express", "warning") return redirect("/addBox") # Ensure the box weight_ex fits server-side if not re.search("^[0-9]+$", weight_ex): flash("Invalid box weight express", "danger") return redirect("/addBox") # Ensure the box price in DE was submitted if not price_de: flash("must provide box price in DE", "warning") return redirect("/addBox") # Ensure the box price in DE fits server-side if not re.search("^[0-9]+\.?[0-9]+$", format(float(price_de), ".2f")): flash("Invalid box price in DE", "danger") return redirect("/addBox") # Ensure the box price in EU was submitted if not price_eu: flash("must provide box price in EU", "warning") return redirect("/addBox") # Ensure the box price in EU fits server-side if not re.search("^[0-9]+\.?[0-9]+$", format(float(price_eu), ".2f")): flash("Invalid box price in EU", "danger") return redirect("/addBox") # Ensure the box express price was submitted if not price_ex: flash("must provide box express price", "warning") return redirect("/addBox") # Ensure the box express price fits server-side if not re.search("^[0-9]+\.?[0-9]+$", format(float(price_ex), ".2f")): flash("Invalid box express price", "danger") return redirect("/addBox") # Insert box name, length, width, height, price DE, price EU and price EX into the table db.session.add( Boxes(name=name, length=length, width=width, height=height, weight_ne=weight_ne, weight_ex=weight_ex, price_de=price_de, price_eu=price_eu, price_ex=price_ex)) db.session.commit() # Flash result & redirect flash("Box added", "success") return redirect("/administration") else: return render_template("addBox.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def mailingFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable user_id = session["user_id"] # Activate newsletter and update DB if request.form.get('activate'): newsletter = "True" query = Users.query.filter_by(id=user_id).first() query.newsletter = newsletter db.session.commit() # Deactivate newsletter and update DB if request.form.get('deactivate'): newsletter = "False" query = Users.query.filter_by(id=user_id).first() query.newsletter = newsletter db.session.commit() # Flash result & redirect flash("Newsletter updated", "success") return redirect("/profile") else: return render_template("mailing.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def confirmationFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Fake pay varibale pay = request.form.get("pay") # Get variable user_id = session["user_id"] date = ctime(time()) plants = [] items = [] addresses = [] total = 0 # Convert pay value to string if pay == None: pay = "No" if pay == "pay": pay = "Yes" if pay == "Yes": # Update pay variable query = Orders.query.filter_by(user_id=user_id).all() query[-1].pay = "Yes" total = query[-1].total db.session.commit() # Make plants array from basket query = Baskets.query.filter_by(user_id=user_id) for element in query: plants.append([ str(element.plant_id), str(element.name), str(element.quantity), str(element.price) ]) # Add to plants array the plants features index = 0 while index < len(plants): query = Plants.query.filter_by(id=plants[index][0]) for element in query: plants[index].extend([ str(element.length), str(element.width), str(element.height), str(element.weight), str(element.express) ]) index += 1 # Make array with all the plants side-by-side and sort them for plant in plants: index = int(plant[2]) while index > 0: items.extend([plant]) index -= 1 # Make address array query = Users.query.filter_by(id=user_id).first() addresses.extend([ query.first, query.last, query.caresof, query.street, query.house, query.zipcode, query.city, query.country, query.additional ]) # Delete basket in DB Baskets.query.filter_by(user_id=user_id).delete() db.session.commit() # Update stock in Plants for item in items: # Query for plant stock of corresponding id query = Plants.query.filter_by(id=item[0]).first() # Check if there is still at least one unit if query.stock >= 1: # decrement by one & commit query.stock -= 1 db.session.commit() else: # Flash result & redirect flash("Not enough stock of " + str(itemCopy[1]), "danger") return redirect("/basket") # Send order confirmation email to client subject = "Your order from the Crazy Plant Crew" query = Users.query.filter_by(id=user_id).first() email = query.email body = render_template('order.html', name=getUserName(), addresses=addresses, plants=plants, total=total, date=date) sendMail(subject, email, body) # Send closed deal email to Glenn subject = "You closed a deal!" email = os.environ["EMAIL_SEND"] body = render_template('deal.html', name=getUserName(), addresses=addresses, total=total, date=date) sendMail(subject, email, body) # Flash result & redirect flash("Plant(s) ordered", "success") return redirect("/history") if pay != "Yes": # Flash result & redirect flash("Payment not completed ", "warning") return redirect("/confirmation") else: # Get variable user_id = session["user_id"] date = ctime(time()) pay = "No" subtotal = 0 shipping = 0 total = 0 cost = [] addresses = [] plants = [] items = [] boxesNE = [] boxesEX = [] boxes = [] packaging = [] weight = [] # Make plants array from basket query = Baskets.query.filter_by(user_id=user_id) for element in query: plants.append([ str(element.plant_id), str(element.name), str(element.quantity), str(element.price) ]) subtotal += element.subtotal # Add to plants array the plants features index = 0 while index < len(plants): query = Plants.query.filter_by(id=plants[index][0]) for element in query: plants[index].extend([ str(element.length), str(element.width), str(element.height), str(element.weight), str(element.express) ]) index += 1 # Make address array query = Users.query.filter_by(id=user_id).first() addresses.extend([ query.first, query.last, query.caresof, query.street, query.house, query.zipcode, query.city, query.country, query.additional ]) # Make express variable express = query.express # Make array with available boxes query = Boxes.query.all() for element in query: packaging.append([ str(element.name), str(element.length), str(element.width), str(element.height), str(element.weight_ne), str(element.weight_ex), str(element.price_de), str(element.price_eu), str(element.price_ex) ]) # Check if boxes are in the system if len(packaging) == 0: # Flash result & redirect flash("There are no box available", "danger") return redirect("/basket") # Checking plants sizes and weight against boxes sizes and capacity, if it fits, append adapted box to array of possible needed box for plant in plants: for package in packaging: # Express only works in Germany if addresses[7] == "Germany": # Check if express is needed for the whole if express == "No": # Check if express is needed on one plant if plant[8] == "No": if int(plant[4]) < int(package[1]) and int( plant[5]) < int(package[2]) and int( plant[6]) < int(package[3]) and int( plant[7]) < int(package[4]): boxesNE.append([package, plant]) break # Check if express is needed on one plant if plant[8] == "Yes": if int(plant[4]) < int(package[1]) and int( plant[5]) < int(package[2]) and int( plant[6]) < int(package[3]) and int( plant[7]) < int(package[5]): boxesEX.append([package, plant]) break # Check if express is needed for the whole if express == "Yes": if int(plant[4]) < int(package[1]) and int( plant[5]) < int(package[2]) and int( plant[6]) < int(package[3]) and int( plant[7]) < int(package[5]): boxesEX.append([package, plant]) break # Express only works in Germany if addresses[7] != "Germany": if int(plant[4]) < int(package[1]) and int(plant[5]) < int( package[2]) and int(plant[6]) < int( package[3]) and int(plant[7]) < int( package[4]): boxesNE.append([package, plant]) break # Sort arrays boxes NE & RE boxesNE = sorted(boxesNE, key=lambda x: (int(x[1][4]), int(x[1][5]), int(x[1][6])), reverse=True) boxesEX = sorted(boxesEX, key=lambda x: (int(x[1][4]), int(x[1][5]), int(x[1][6])), reverse=True) # Make array with all the plants side-by-side and sort them for plant in plants: index = int(plant[2]) while index > 0: items.extend([plant]) index -= 1 items = sorted(items, key=lambda x: (int(x[4]), int(x[5]), int(x[6])), reverse=True) # Function to take the biggest box needed from the express group first, then from the non express group. Increment sending costs. def plantLoop(thisPlant): # Express only can only be in Germany - Append needed box - Append to cost if len(boxesEX ) > 0 and express == "Yes" and addresses[7] == "Germany": for boxEX in boxesEX: if int(thisPlant[0]) == int(boxEX[1][0]): cost.append(float(boxEX[0][8])) boxes.extend([boxEX[0]]) weight.append(int(boxEX[0][5])) return # Express only can only be in Germany - Append needed box - Append to cost if len(boxesEX) > 0 and express == "No" and thisPlant[ 8] == "Yes" and addresses[7] == "Germany": for boxEX in boxesEX: if int(thisPlant[0]) == int(boxEX[1][0]): boxes.extend([boxEX[0]]) cost.append(float(boxEX[0][8])) weight.append(int(boxEX[0][5])) return # Non express but in Germany - Append needed box - Append to cost elif len(boxesNE) > 0 and express == "No" and thisPlant[ 8] == "No" and addresses[7] == "Germany": for boxNE in boxesNE: if int(thisPlant[0]) == int(boxNE[1][0]): boxes.extend([boxNE[0]]) cost.append(float(boxNE[0][6])) weight.append(int(boxNE[0][4])) return # Non express in the EU - Append needed box - Append to cost elif len(boxesNE ) > 0 and express == "No" and addresses[7] != "Germany": for boxNE in boxesNE: if int(thisPlant[0]) == int(boxNE[1][0]): boxes.extend([boxNE[0]]) cost.append(float(boxNE[0][7])) weight.append(int(boxNE[0][4])) return # Return False if there are no more plant to cover else: return False # Make a grid from the last needed box to represent its bottom def makeGrid(): if len(boxes) > 0: thisBox = [["0" for row in range(int(boxes[-1][1]))] for row in range(int(boxes[-1][2]))] return thisBox else: return False # Take plants length and width def getAttributes(thisPlant): if len(items) > 0: length = thisPlant[4] width = thisPlant[5] mass = thisPlant[7] return length, width, mass else: return False # Filler function def drawLoop(x, y, length, width, rotation, thisBox): # Fill up horizontally def drawHorizon(row): drawIndexH = 0 while drawIndexH < len(row): if rotation == False and drawIndexH >= x and drawIndexH < x + int( length): row[drawIndexH] = "1" drawIndexH += 1 elif rotation == True and drawIndexH >= x and drawIndexH < x + int( width): row[drawIndexH] = "1" drawIndexH += 1 else: drawIndexH += 1 # Fill up vertically drawIndexV = 0 while drawIndexV < len(thisBox): if rotation == False and drawIndexV >= y and drawIndexV < y + int( width): drawHorizon(thisBox[drawIndexV]) drawIndexV += 1 elif rotation == True and drawIndexV >= x and drawIndexV < x + int( width): drawHorizon(thisBox[drawIndexV]) drawIndexV += 1 else: drawIndexV += 1 # Grid looper def gridLoop(length, width, thisBox): # Horizontal checker for free space def gridHorizon(row): gridIndexH = 0 while gridIndexH < len(row): # Search of a "0" if row[gridIndexH] == "0": # Return first available "0" return gridIndexH else: gridIndexH += 1 # Vertical checker for free space gridIndexV = 0 while gridIndexV < len(thisBox): # Get free space horizontally x = gridHorizon(thisBox[gridIndexV]) # X must exist otherwise the plant never fits if x != None: # Check if fits with the length horizontally if x <= int(len(thisBox[gridIndexV]) - int(length)): # Check if fits with width vertically if gridIndexV + int(width) < len(thisBox): # Check if we find a "0" to be sure there is enough space if thisBox[gridIndexV + int(width)][x] == "0": # Set roation flag rotation = False # Set the y axis y = gridIndexV # Start drawing return drawLoop(x, y, length, width, rotation, thisBox) else: gridIndexV += 1 else: return False # Check if fits with width horizontally (flipped) elif x <= int(len(thisBox[gridIndexV]) - int(width)): # Check if fits with length vertically if gridIndexV + int(length) < len(thisBox): # Check if we find a "0" to be sure there is enough space if thisBox[gridIndexV + int(length)][x] == "0": # Set rotation flag rotation = True # Set the y axis y = gridIndexV # Start drawing return drawLoop(x, y, length, width, rotation, thisBox) else: gridIndexV += 1 else: gridIndexV += 1 else: gridIndexV += 1 else: return False # Delete dealt plants and update corresponding stock def deleteLoop(thisPlant): if len(items) > 0: return items.remove(thisPlant) else: return False # Master loop def masterLoop(): # Check for other plants to fit present box def slaveLoop(thisBox): if len(items) > 0: for item in items: # Get needed attributes length, width, mass = getAttributes(item) # Check if there is enough available weight if weight[-1] - int(mass) > 0: # Update available weight weight[-1] -= int(mass) # Check if possible to draw an other plant in the grid if gridLoop(length, width, thisBox) != False: # Delete dealt plant deleteLoop(item) # Recursively try again slaveLoop(thisBox) else: masterLoop() else: masterLoop() else: return # Start dealing with every plants if len(items) > 0: for item in items: # Take needed box plantLoop(item) # Make a grid and get needed attributes thisBox = makeGrid() length, width, mass = getAttributes(item) # Check if there is enough available weight if weight[-1] - int(mass) > 0: # Update available weight weight[-1] -= int(mass) # Fill up grid gridLoop(length, width, thisBox) # Delete dealt plants deleteLoop(item) # Start slaveLoop to check if other plants can fit in that box slaveLoop(thisBox) else: return return # Start main loop masterLoop() # Get total shipping cost for element in cost: shipping += element total = shipping + subtotal # Insert order informations into the orders table db.session.add( Orders(user_id=user_id, date=date, plants=str(plants), boxes=str(boxes), addresses=str(addresses), express=express, pay=pay, shipping=shipping, subtotal=subtotal, total=total)) db.session.commit() return render_template("confirmation.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), subtotal=subtotal, shipping=shipping, total=total)
def indexFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable plant_id = request.form.get("plant_id") user_id = session["user_id"] quantity = request.form.get("quantity") # Query database for plants name, picture, price and stock query = Plants.query.filter_by(id=plant_id).first() name = query.name picture = query.picture price = query.price existingStock = query.stock # Check if the price is reduced if query.reduced == "Yes": price = query.offer # Avoid going to negative stocks if int(existingStock) - int(quantity) < 0: flash("Not enough in stock", "warning") return redirect("/") # Check for existing stock in the basket query = Baskets.query.filter_by(plant_id=plant_id, user_id=user_id).first() if query != None: existingQuantity = query.quantity else: existingQuantity = 0 # If there is already some plant in the basket if existingQuantity > 0: # Sum up the quantities newQuantity = existingQuantity + int(quantity) user_id = session["user_id"] subtotal = int(newQuantity) * float(price) # Update database with quantity and subtotal query = Baskets.query.filter_by(plant_id=plant_id).filter_by( user_id=user_id).first() query.quantity = newQuantity query.subtotal = subtotal db.session.commit() # First time the user has put this plant in the basket else: user_id = session["user_id"] subtotal = int(quantity) * float(price) # Add quantity to database db.session.add( Baskets(plant_id=plant_id, user_id=user_id, quantity=quantity, name=name, picture=picture, price=price, subtotal=subtotal)) db.session.commit() # Flash result & redirect flash("Added to basket", "success") return redirect("/") else: # Query database for plants to display them show = "Yes" plants = Plants.query.filter_by(show=show).all() return render_template("index.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), plants=plants)
def loggedFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable remove = request.form.get("remove") promote = request.form.get("promote") demote = request.form.get("demote") if request.form.get("remove"): # Check if field is not empty if remove == "": flash("Must provide name REMOVE", "warning") return redirect("/logged") # Check if it is root if remove == os.environ.get("USERNAME"): flash("Can't remove this user", "warning") return redirect("/logged") # Check if the name matches if Users.query.filter_by(username=remove).first() == None: flash("No matching name", "warning") return redirect("/logged") # Check if it is the user itself if Users.query.filter_by(username=remove).first() == getUserName(): flash("Can't remove yourself", "warning") return redirect("/logged") # Check if it is the user is an admin query = Users.query.filter_by(username=remove).first() if query.role == "admin": flash("Can't remove admin", "warning") return redirect("/logged") # Update database by removing user else: Users.query.filter(Users.username == remove).delete() db.session.commit() flash("User deleted", "success") return redirect("/logged") if request.form.get("promote"): # Check if field is not empty if promote == "": flash("Must provide name", "warning") return redirect("/logged") # Check if the name matches if Users.query.filter_by(username=promote).first() == None: flash("No matching name", "warning") return redirect("/logged") # Check if it is the user is an admin query = Users.query.filter_by(username=promote).first() if query.role == "admin": flash("Already admin", "warning") return redirect("/logged") # Update database by promoting user else: query = Users.query.filter_by(username=promote).first() query.role = "admin" db.session.commit() flash("User promoted", "success") return redirect("/logged") if request.form.get("demote"): # Check if field is not empty if demote == "": flash("Must provide name", "warning") return redirect("/logged") # Check if it is root if demote == os.environ.get("USERNAME"): flash("Can't demote this user", "warning") return redirect("/logged") # Check if the name matches if Users.query.filter_by(username=demote).first() == None: flash("No matching name", "warning") return redirect("/logged") # Check if it is the user itself if Users.query.filter_by(username=demote).first() == getUserName(): flash("Can't demote yourself", "warning") return redirect("/logged") # Update database by demoting user else: query = Users.query.filter_by(username=demote).first() query.role = "user" db.session.commit() flash("Admin demoted", "success") return redirect("/logged") else: # Set variable users = [] admins = [] unconfirmeds = [] index = 0 # Query DB for all users query = Users.query.all() # Loop through the DB query while index < len(query): # Users list if query[index].role == "user": users.extend([[query[index].username, query[index].email]]) # Admins list if query[index].role == "admin": admins.extend([query[index].username]) # Unconfirmeds list if query[index].confirmed == "False": unconfirmeds.extend([query[index].username]) index += 1 return render_template("logged.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), users=users, admins=admins, unconfirmeds=unconfirmeds)
def profileFunction(): return render_template("profile.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def basketFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # Get variable user_id = session["user_id"] thisBasketItems = [] # Query database for plants thisBasket = Baskets.query.filter_by(user_id=user_id).all() # Query database for plants baskets = Baskets.query.all() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Check if user deletes an item in the basket if "delete" in request.form: # Loop through the record list to match plant ID when delete button is pressed index = 0 while index < len(baskets): if int(request.form["delete"]) == int(baskets[index].id): # Query database for plant id to delete row Baskets.query.filter( Baskets.id == baskets[index].id).delete() db.session.commit() # Flash result & redirect flash("Item deleted", "success") return redirect("/basket") else: index += 1 # Check for available quantities if "pay" in request.form: # Check if there are plants in the basket for item in thisBasket: thisBasketItems.append(item.name) if len(thisBasketItems) == 0: # Flash result & redirect flash("There are no plants to order", "danger") return redirect("/basket") # Set flag flag = False # Loop through the user basket for item in thisBasket: # Check with respective id's against Plants query = Plants.query.filter_by(id=item.plant_id).first() # If user orders too much if item.quantity > query.stock: # Set flag to True flag = True # Adapting basket to stock quantity and correct basket subtotal item.quantity = query.stock item.subtotal = int(query.stock) * float(item.price) db.session.commit() # Flash result & redirect flash("Not enough stock of: " + str(item.name), "warning") flash("Adapting, only " + str(query.stock) + " available", "warning") else: flag = False # Check for flag status if flag == True: return redirect("/basket") else: return redirect("/pay") else: # Get total price total = 0 for element in thisBasket: total += element.subtotal return render_template("basket.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), baskets=thisBasket, total=total)
def usernameFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable username = request.form.get("username") user_id = session["user_id"] # Ensure username was submitted if not username: flash("Must provide username", "warning") return redirect("/username") # Ensure username fits server-side if not re.search("^[a-zA-Z0-9]{2,20}$", username): flash("Invalid username", "danger") return redirect("/username") # Query database for username if already exists query = Users.query.filter_by(username=username).all() if len(query) != 0: flash("Username already taken", "danger") return redirect("/username") # Update database with username query = Users.query.filter_by(id=user_id).first() query.username = username db.session.commit() # Flash result & redirect flash("Username updated", "success") return redirect("/profile") else: return render_template("username.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def pictureFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": # Get variable user_id = session["user_id"] # Save, upload and delete picture file file = request.files["picture"] if file and allowed_file(file.filename): filename = secure_filename(file.filename) file.save(os.path.join("./static", filename)) upload = uploadPicture("./static/" + filename) os.remove("./static/" + filename) # Update database with new image url query = Users.query.filter_by(id=user_id).first() query.picture = upload db.session.commit() # Flash result & redirect flash("Profile picture updated", "success") return redirect("/") else: return render_template("picture.html", name=getUserName(), picture=getUserPicture(), role=getUserRole())
def articleFunction(): # Force flash() to get the messages on the same page as the redirect. get_flashed_messages() # User reached route via POST (as by submitting a form via POST) if request.method == "POST": return redirect("/") else: news = News.query.all() return render_template("article.html", name=getUserName(), picture=getUserPicture(), role=getUserRole(), news=news)