diff --git a/app.py b/app.py new file mode 100644 index 0000000..cccb4a8 --- /dev/null +++ b/app.py @@ -0,0 +1,248 @@ +#coding:utf-8 +import os +from datetime import date +from flask import Flask,request, session, redirect, render_template,send_from_directory +from flask_sqlalchemy import SQLAlchemy + +basedir = os.path.abspath(os.path.dirname(__file__)) +app = Flask(__name__) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.db') +app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False +app.config['SECRET_KEY'] = "ruz@2021" +db = SQLAlchemy(app) + + +class User(db.Model): + id = db.Column(db.Integer, unique=True, primary_key=True) + username=db.Column(db.String(255)) + password= db.Column(db.String(255)) + + def __init__(self,username,password): + self.username=username + self.password=password + + def __repr__(self): + return '' % self.id + +class Book(db.Model): + isbn = db.Column(db.Integer, unique=True, primary_key=True,autoincrement=False) + name=db.Column(db.String(255)) + author= db.Column(db.Text) + pub_date= db.Column(db.Date) + description =db.Column(db.Text) + cover =db.Column(db.Text) + trade_price =db.Column(db.Integer) + retail_price =db.Column(db.Integer) + stock = db.Column(db.Integer) + + def __init__(self,isbn,name,author,pub_date,description,cover,trade_price,retail_price,stock ): + self.isbn = isbn + self.name = name + self.author = author + self.pub_date = pub_date + self.description = description + self.cover = cover + self.trade_price = trade_price + self.retail_price = retail_price + self.stock = stock + + def __repr__(self): + return '' % self.isbn + +class Order(db.Model): + id = db.Column(db.Integer, unique=True, primary_key=True,autoincrement=True) + uid= db.Column(db.Integer,db.ForeignKey('user.id')) + total = db.Column(db.Integer) + postage = db.Column(db.Integer) + + def __init__(self,uid,total,postage): + self.uid=uid + self.total=total + self.postage = postage + + def __repr__(self): + return '' % self.id + +class Cart(db.Model): + id = db.Column(db.Integer, unique=True, primary_key=True,autoincrement=True) + uid= db.Column(db.Integer,db.ForeignKey('user.id')) + bid= db.Column(db.Integer,db.ForeignKey('book.isbn')) + num = db.Column(db.Integer) + book = db.relationship('Book') + + def __init__(self,uid,bid,num): + self.uid = uid + self.bid = bid + self.num = num + + def __repr__(self): + return '' % self.id + +DIRECTORY_PATH = 'media/' + +#Home Page +@app.route('/') +@app.route('/index', methods = ['GET']) +def index(): + if session.get('admin'): + return render_template('home.html') + else: + res=Book.query.filter( Book.stock > 0 ).all() + return render_template('index.html',res=res) + +@app.route('/mycart') +def mycart(): + res = Cart.query.filter_by(uid = session.get('uid')) + total = sum([ i.book.retail_price*i.num for i in res ]) if res else 0 + return render_template('cart.html', res=res,total = total ) + + +@app.route('/add', methods = ['GET','POST']) +def addstock(): + if request.method == "POST": + isbn = request.form['isbn'] + name = request.form['name'] + author = request.form['author'] + pub_date = request.form['pub_date'] + pub_date = date( int(pub_date.split('-')[0]),int(pub_date.split('-')[1]),int(pub_date.split('-')[2]) ) + retail_price = request.form['retail_price'] + trade_price = request.form['trade_price'] + description = request.form['description'] + quantity = request.form['quantity'] + f = request.files['cover'] + book = Book.query.filter_by(isbn = int(isbn)).first() + if book: + book.name = name + book.author = author + book.pub_date = pub_date + book.retail_price = int(retail_price) + book.trade_price = int(trade_price) + book.description = description + book.quantity = int(quantity) + book.cover = '/static/img/'+f.filename + upload_path = os.path.join(basedir,'/static/img/',f.filename) + f.save(upload_path) + else: + cover = '/static/img/'+f.filename + upload_path = basedir + cover + f.save(upload_path) + b = Book(isbn=int(isbn), name=name, author=author, pub_date=pub_date, description=description, cover=cover, trade_price=int(trade_price), retail_price=int(retail_price), stock = int(quantity) ) + db.session.add(b) + db.session.commit() + return redirect('/stock') + else: + return render_template('add.html') + + +@app.route('/stock') +def stock(): + books=Book.query.all() + return render_template('stock.html',books=books) + + +@app.route('/clearall') +def doclear(): + uid = session.get('uid') + Cart.query.filter_by(uid=uid).delete() + db.session.commit() + return redirect('/index') + +@app.route('/gocheck') +def docheck(): + res = [] + total_price = 0 + postage = 0 + shortage = [] + items = Cart.query.filter_by(uid = session.get('uid')) + for item in items: + if item.num <= item.book.stock: + res.append(item) + postage += item.num + total_price += item.num * item.book.retail_price + else: + shortage.append(item) + postage = 3 if postage == 1 else postage+2 + return render_template('check.html',res=res,total_price=total_price,postage=postage) + + +@app.route('/pay') +def dopay(): + total_price = 0 + postage = 0 + items = Cart.query.filter_by(uid = session.get('uid')) + for item in items: + if item.num <= item.book.stock: + book = Book.query.get(item.book.isbn) + book.stock -= item.num + db.session.delete(item) + postage += item.num + total_price += item.num * item.book.retail_price + total = total_price+3 if postage == 1 else total_price + postage + 2 + db.session.commit() + return render_template('pay.html',total=total) + +@app.route('/delete', methods = ['GET']) +def dodelete(): + c = Cart.query.filter_by( id = int(request.args.get('cid')) ).first() + db.session.delete(c) + db.session.commit() + return redirect('/mycart') + + + +@app.route('/addtocart',methods = ['GET']) +def add(): + isbn = int(request.args.get('isbn')) + s = Cart.query.filter_by(uid=session.get('uid'), bid = isbn).first() + if s: + s.num += 1 + db.session.commit() + else: + c = Cart(uid=session.get('uid'), bid = isbn, num = 1) + db.session.add(c) + db.session.commit() + return redirect('/mycart') + +@app.route('/login',methods = ['GET', 'POST']) +def login(): + if request.method == 'POST': + uname=request.form['username'] + pwd=request.form['password'] + user = User.query.filter_by(username=uname,password=pwd).first() + if user: + session['logged_in'] = True + session['admin'] = True if uname == 'admin' else False + session['username'] = uname + session['uid'] = user.id + return redirect('/index') + else: + return render_template('login.html',info="Incorrect username or password !") + else: + return render_template('login.html') + + +#Sign out of session +@app.route('/signout') +def signout(): + session.pop('username', None) + session.pop('admin', None) + session.pop('logged_in', None) + return redirect('/login') + + +@app.before_request +def before_request(): + if request.path in ['/login','/signout','/reg']: + return None + if session.get('logged_in'): + return None + return redirect('/login') + +@app.teardown_request +def teardown_request(exception): + pass + + +if __name__ == "__main__": + app.run(host='0.0.0.0', port=5000,debug=False ) + \ No newline at end of file diff --git a/data.db b/data.db new file mode 100644 index 0000000..c08abba Binary files /dev/null and b/data.db differ diff --git a/static/img/anne.jpg b/static/img/anne.jpg new file mode 100644 index 0000000..d3d01b8 Binary files /dev/null and b/static/img/anne.jpg differ diff --git a/static/img/bad.jpg b/static/img/bad.jpg new file mode 100644 index 0000000..cb8c637 Binary files /dev/null and b/static/img/bad.jpg differ diff --git a/static/img/bitcoin.jpg b/static/img/bitcoin.jpg new file mode 100644 index 0000000..a432c1e Binary files /dev/null and b/static/img/bitcoin.jpg differ diff --git a/static/img/game.jpg b/static/img/game.jpg new file mode 100644 index 0000000..db486a4 Binary files /dev/null and b/static/img/game.jpg differ diff --git a/static/img/hp.jpg b/static/img/hp.jpg new file mode 100644 index 0000000..95346ad Binary files /dev/null and b/static/img/hp.jpg differ diff --git a/static/img/love.jpg b/static/img/love.jpg new file mode 100644 index 0000000..beb4b35 Binary files /dev/null and b/static/img/love.jpg differ diff --git a/static/img/meat.jpg b/static/img/meat.jpg new file mode 100644 index 0000000..88b966a Binary files /dev/null and b/static/img/meat.jpg differ diff --git a/static/img/python.jpg b/static/img/python.jpg new file mode 100644 index 0000000..1bf11d6 Binary files /dev/null and b/static/img/python.jpg differ diff --git a/static/img/steve.jpg b/static/img/steve.jpg new file mode 100644 index 0000000..63c7bf2 Binary files /dev/null and b/static/img/steve.jpg differ diff --git a/static/img/time.jpg b/static/img/time.jpg new file mode 100644 index 0000000..5efacbc Binary files /dev/null and b/static/img/time.jpg differ diff --git a/templates/add.html b/templates/add.html new file mode 100644 index 0000000..41e9491 --- /dev/null +++ b/templates/add.html @@ -0,0 +1,121 @@ + + + + +Book Shop + + + + + + + +
+
+ +
+
+
+

Add Stock:

+
+
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+
+   +   + +
+
+   +   + +
+
+   +   + +
+
+ + +
+ + +
+
+
+
+
+
+
+
+
© 2021 Book Shop
+
+
+ + + + + \ No newline at end of file diff --git a/templates/cart.html b/templates/cart.html new file mode 100644 index 0000000..61ca599 --- /dev/null +++ b/templates/cart.html @@ -0,0 +1,50 @@ +{% extends "layout.html" %} +{% block content %} +
+ +
+
+
+

Shopping Cart:

+ + + + + + + + + + {% for item in res %} + + + + + + + + + + {% endfor %} + +
NameThumbnailUnit PriceQuantity
{{item.book.name}} £ {{item.book.retail_price}} {{item.num}} + + Delete + +
+
+
+

Total Price: £{{total}} + Cancel All + Go Checkout +

+
+ +
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/check.html b/templates/check.html new file mode 100644 index 0000000..96e619d --- /dev/null +++ b/templates/check.html @@ -0,0 +1,59 @@ +{% extends "layout.html" %} +{% block content %} +
+ +
+
+
+

Order Check:

+ + + + + + + + + + {% for item in res %} + + + + + + + + {% endfor %} + {% for item in shortage %} + + + + + + + + + + + {% endfor %} + + +
NameThumbnailUnit PriceQuantity
{{item.book.name}} £ {{item.book.retail_price}} {{item.num}}
{{item.book.name}} £ {{item.book.retail_price}} {{item.num}} Out of Stock
+
+
+

+ Subtotal: £{{total_price}}   + Postage: £{{postage}}   + Total: £{{ [total_price,postage]|sum}} +

+
+
Pay now + +
+ + +
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..02440d2 --- /dev/null +++ b/templates/home.html @@ -0,0 +1,67 @@ + + + + +Book Shop + + + + + + + +
+
+ +
+
+
+

Home Page

+
+ Stock Levels + +
+
+
+
+
+ + +
+
+
© 2021 Book Shop
+
+
+ + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..6caf0d4 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,35 @@ +{% extends "layout.html" %} +{% block content %} +
+ +
+
+
+

Book Lists:

+
+ + + + {% for m in res %} + + + + + + + {% endfor %} + +
{{m.name}} {{m.name}} + + Add to Cart + +
+ + +
+ + +
+
+
+{% endblock %} \ No newline at end of file diff --git a/templates/layout.html b/templates/layout.html new file mode 100644 index 0000000..f0b4539 --- /dev/null +++ b/templates/layout.html @@ -0,0 +1,54 @@ + + + + +Book Shop + + + + + + + +
+ {% block content %} + {% endblock %} +
+
+
+
© 2021 Book Shop
+
+
+ + \ No newline at end of file diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..48501a4 --- /dev/null +++ b/templates/login.html @@ -0,0 +1,71 @@ + + + + +User Login + + + + +
+
+
+ +
+
+
+ +
+
+
+
+ +
+
+
© 2021 Book Shop
+
+
+ + diff --git a/templates/pay.html b/templates/pay.html new file mode 100644 index 0000000..61dcf68 --- /dev/null +++ b/templates/pay.html @@ -0,0 +1,27 @@ +{% extends "layout.html" %} +{% block content %} +
+ +
+
+
+

Pay Confirm

+
+ + +
+ Amount: £{{ total }} +
+
+
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/stock.html b/templates/stock.html new file mode 100644 index 0000000..5549049 --- /dev/null +++ b/templates/stock.html @@ -0,0 +1,85 @@ + + + + +Book Shop + + + + + + + +
+
+ +
+
+

Book Stock Levels: Add Stock

+
+ + + + + + + + + + {% for book in books %} + + + + + + + {% endfor %} + +
ThumbnailNameISBN-13Stock Quantity
{{book.name}} {{book.isbn}} + {{book.stock}} +
+ +
+
+
+
+
+ + +
+
+
© 2021 Book Shop
+
+
+ + \ No newline at end of file