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