· 7 years ago · Jan 18, 2019, 10:14 AM
1import os
2
3from cs50 import SQL
4from flask import Flask, flash, redirect, render_template, request, session
5from flask_session import Session
6from tempfile import mkdtemp
7from werkzeug.exceptions import default_exceptions
8from werkzeug.security import check_password_hash, generate_password_hash
9from datetime import date
10
11from helpers import apology, login_required, lookup, usd
12
13# Configure application
14app = Flask(__name__)
15
16# Ensure templates are auto-reloaded
17app.config["TEMPLATES_AUTO_RELOAD"] = True
18
19# Ensure responses aren't cached
20@app.after_request
21def after_request(response):
22 response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
23 response.headers["Expires"] = 0
24 response.headers["Pragma"] = "no-cache"
25 return response
26
27# Custom filter
28app.jinja_env.filters["usd"] = usd
29
30# Configure session to use filesystem (instead of signed cookies)
31app.config["SESSION_FILE_DIR"] = mkdtemp()
32app.config["SESSION_PERMANENT"] = False
33app.config["SESSION_TYPE"] = "filesystem"
34Session(app)
35
36# Configure CS50 Library to use SQLite database
37db = SQL("sqlite:///finance.db")
38
39
40@app.route("/")
41@login_required
42def index():
43 """Show portfolio of stocks"""
44 stocks = db.execute("SELECT * FROM portfolio where id = :id", id = session["user_id"])
45 total = 0
46 print(stocks)
47 if len(stocks) == 0:
48 cash = db.execute("SELECT cash FROM users where id = :id", id = session['user_id'])[0]['cash']
49 total = cash
50 return render_template("index.html", cash = cash, total = total)
51 else:
52 for stock in stocks:
53 symbol = stock['stock']
54 print(symbol)
55 number = stock['number']
56 print(number)
57 price = lookup(symbol)['price']
58 print(price)
59 value = price * number
60 total += value
61
62 cash = db.execute("SELECT cash FROM users where id = :id", id = session['user_id'])[0]['cash']
63 total += cash
64
65 return render_template("index.html", stocks = stocks, cash = cash, total = total)
66 #return apology("TODO")
67
68
69@app.route("/buy", methods=["GET", "POST"])
70@login_required
71def buy():
72 """Buy shares of stock"""
73 # User reached route via POST (as by submitting a form via POST)
74 if request.method == "POST":
75
76 # Ensures symbol was submitted
77 if not request.form.get("symbol"):
78 return apology("must provide symbol", 403)
79
80 # Ensure positive number of shares was submitted
81 if not int(request.form.get("number")) > 0:
82 return apology("must provide number of shares", 403)
83
84 # Ensure stock symbol is valid
85 stock = lookup(request.form.get("symbol"))
86 if lookup(request.form.get("symbol")) == None:
87 return apology("must provide a valid symbol", 403)
88
89 # Declare variables
90 number = int(request.form.get('number'))
91 value = stock['price'] * number
92 cash = float(db.execute("SELECT cash FROM users WHERE id=:id", id=session["user_id"])[0]["cash"])
93 newCash = cash - value
94 row = db.execute("SELECT * FROM portfolio WHERE id = :id AND stock=:stock", id = session["user_id"], stock = stock['symbol'])
95
96 # Ensure user can afford the stock
97 if cash < value:
98 return apology("Not enough founds", 403)
99
100 # Update portfolio table
101 else:
102 # Update number of shares and cash if stock exist in portfolio
103 if len(row) != 0:
104 oldNumber = db.execute("SELECT number FROM portfolio WHERE id = :id AND stock = :stock",
105 id = session["user_id"], stock = stock['symbol'])[0]["number"]
106 db.execute("UPDATE users SET cash = :cash WHERE id = :id", cash = newCash, id = session["user_id"])
107 db.execute("UPDATE portfolio SET number = :number WHERE id = :id AND stock = :stock",
108 number = oldNumber + number, id = session["user_id"], stock=stock['symbol'])
109
110 # Insert new stock to portfolio
111 else:
112 db.execute("INSERT INTO portfolio (id, stock, number, price, date) VALUES (:id, :stock, :number, :price, :date)",
113 id=session["user_id"], stock=stock['symbol'], number=int(request.form.get('number')), price=stock['price'], date=date.today())
114 db.execute("UPDATE users SET cash = :cash WHERE id = :id", cash = newCash, id = session["user_id"])
115
116 # Redirect user to index page TO DO
117 return render_template("index.html")
118
119 # User reached route via GET (as by clicking a link or via redirect)
120 else:
121 return render_template("buy.html")
122
123
124@app.route("/history")
125@login_required
126def history():
127 """Show history of transactions"""
128 return apology("TODO")
129
130
131@app.route("/login", methods=["GET", "POST"])
132def login():
133 """Log user in"""
134
135 # Forget any user_id
136 session.clear()
137
138 # User reached route via POST (as by submitting a form via POST)
139 if request.method == "POST":
140
141 # Ensure username was submitted
142 if not request.form.get("username"):
143 return apology("must provide username", 403)
144
145 # Ensure password was submitted
146 elif not request.form.get("password"):
147 return apology("must provide password", 403)
148
149 # Query database for username
150 rows = db.execute("SELECT * FROM users WHERE username = :username",
151 username=request.form.get("username"))
152
153 # Ensure username exists and password is correct
154 if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
155 return apology("invalid username and/or password", 403)
156
157 # Remember which user has logged in
158 session["user_id"] = rows[0]["id"]
159
160 # Redirect user to home page
161 return redirect("/")
162
163 # User reached route via GET (as by clicking a link or via redirect)
164 else:
165 return render_template("login.html")
166
167
168@app.route("/logout")
169def logout():
170 """Log user out"""
171
172 # Forget any user_id
173 session.clear()
174
175 # Redirect user to login form
176 return redirect("/")
177
178
179@app.route("/quote", methods=["GET", "POST"])
180@login_required
181def quote():
182 """Get stock quote."""
183 # User reached route via POST (as by submitting a form via POST)
184 if request.method == "POST":
185
186 # Ensures symbol was submitted
187 if not request.form.get("symbol"):
188 return apology("must provide symbol", 403)
189
190 stock = lookup(request.form.get("symbol"))
191 if lookup(request.form.get("symbol")) == None:
192 return apology("must provide a valid symbol", 403)
193
194 # Redirect user to home page
195 return render_template("price.html", stock=stock)
196
197 # User reached route via GET (as by clicking a link or via redirect)
198 else:
199 return render_template("quote.html")
200
201
202@app.route("/register", methods=["GET", "POST"])
203def register():
204 """Register user"""
205
206 # User reached route via POST (as by submitting a form via POST)
207 if request.method == "POST":
208
209 # Ensure username was submitted
210 if not request.form.get("username"):
211 return apology("must provide username", 403)
212
213 # Ensure password was submitted
214 elif not request.form.get("password"):
215 return apology("must provide password", 403)
216
217 # Ensure password was confirmed
218 elif request.form.get("password") != request.form.get("confirm password"):
219 return apology("must provide same password in both fields", 403)
220
221 # Query database for username
222 rows = db.execute("SELECT * FROM users WHERE username = :username",
223 username=request.form.get("username"))
224
225 # Ensure username does not exists
226 if len(rows) != 0:
227 return apology("unsername already exist", 403)
228
229 # Register username
230 rows = db.execute("INSERT INTO users (username,hash) VALUES (:username, :hash)", username=request.form.get("username"), hash=generate_password_hash(request.form.get("password")))
231
232 # Create user porfolio table
233
234
235 # Remember which user has logged in
236 rows = db.execute("SELECT id FROM users WHERE username = :username",
237 username=request.form.get("username"))
238 session["user_id"] = rows[0]["id"]
239
240 # Redirect user to home page
241 return redirect("/")
242
243 # User reached route via GET (as by clicking a link or via redirect)
244 else:
245 return render_template("register.html")
246 # return apology("TODO")
247
248
249@app.route("/sell", methods=["GET", "POST"])
250@login_required
251def sell():
252 """Sell shares of stock"""
253 return apology("TODO")
254
255
256def errorhandler(e):
257 """Handle error"""
258 return apology(e.name, e.code)
259
260
261# listen for errors
262for code in default_exceptions:
263 app.errorhandler(code)(errorhandler)