Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- from cs50 import SQL
- from flask import Flask, flash, redirect, render_template, request, session
- from flask_session import Session
- from passlib.apps import custom_app_context as pwd_context
- from tempfile import mkdtemp
- from time import gmtime, strftime
- from werkzeug.exceptions import default_exceptions
- from werkzeug.security import check_password_hash, generate_password_hash
- from helpers import apology, login_required, lookup, usd
- # Configure application
- app = Flask(__name__)
- # Ensure templates are auto-reloaded
- app.config["TEMPLATES_AUTO_RELOAD"] = True
- # Ensure responses aren't cached
- @app.after_request
- def after_request(response):
- response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
- response.headers["Expires"] = 0
- response.headers["Pragma"] = "no-cache"
- return response
- # Custom filter
- app.jinja_env.filters["usd"] = usd
- # Configure session to use filesystem (instead of signed cookies)
- app.config["SESSION_FILE_DIR"] = mkdtemp()
- app.config["SESSION_PERMANENT"] = False
- app.config["SESSION_TYPE"] = "filesystem"
- Session(app)
- # Configure CS50 Library to use SQLite database
- db = SQL("sqlite:///finance.db")
- @app.route("/")
- @login_required
- def index():
- """Show portfolio of stocks"""
- # NOTE: TABLE to use is (most probably) portfolio
- # An array of arrays to store stock info (ID-wise)
- # Use jinja for-loop to generate table rows
- # User ID
- userID = session["user_id"]
- username = db.execute("SELECT username FROM users WHERE id = :userid", userid=userID)[0]["username"]
- portfolio = db.execute("SELECT symbol, name, shares, price, total FROM portfolio WHERE id=:userid", userid=userID)
- # How many rows to generate
- dblength = len(portfolio)
- # Cash in account
- csh = db.execute("SELECT cash FROM users WHERE id = :userid", userid=userID)[0]["cash"]
- cash = usd(csh)
- # Total worth
- grandtotal = 0
- for i in range(dblength):
- grandtotal += portfolio[i]["cash"]
- # All stocks
- #return apology("TODO")
- return render_template("index.html")
- @app.route("/buy", methods=["GET", "POST"])
- @login_required
- def buy():
- """Buy shares of stock"""
- # Display form
- # Add stock to user porfolio
- # Update cash
- #--->show chart (of transaction (Portfolio))
- # User reached via POST
- if request.method == "POST":
- # Ensure symbol was submitted
- if not request.form.get("symbol"):
- return apology("Missing symbol", 400)
- # Validate symbol
- symbol = request.form.get("symbol")
- if not symbol:
- return apology("Invalid symbol", 400)
- # Ensure shares was submitted
- if not request.form.get("shares"):
- return apology("Must provide number of shares", 400)
- shares = request.form.get("shares")
- # Which user
- userID = session["user_id"]
- # Credit in account
- cash = db.execute("SELECT cash FROM users WHERE id = :userid", userid=userID)[0]["cash"]
- # Quote the share value
- quote = lookup(request.form.get("symbol"))
- price = usd(quote['price'])
- # Variables to put in the database
- total = price * shares
- name = lookup(symbol)["name"]
- # If enough money in cash
- if cash > (price * shares):
- # userID, shares, price >> are declared elsewhere in this function
- datetime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
- # Check if symbol is already in database
- matched_symbol = db.execute("SELECT symbol FROM portfolio WHERE id = :id", id=userID)[0]
- if matched_symbol["symbol"] == symbol:
- # Add symbol data
- db.execute("UPDATE portfolio SET shares = shares + :shares, price = :price, total = total + :total WHERE id=:id AND symbol=:symbol", shares=shares, price=price, total=total, id=userID, symbol=symbol)
- # Add in History datatbase
- db.execute("INSERT INTO history (id, symbol, shares, price, transacted) VALUES (:id, :symbol, :shares, :price, :transacted)", id=userID, symbol=symbol, shares=shares, price=price, transacted=datetime)
- # If symbol not in database
- else:
- # Entry into transaction database
- db.execute("INSERT INTO portfolio (id, symbol, name, shares, price, total) VALUES (:id, :symbol, :name, :shares, :price, :total)", id=userID, symbol=symbol, name=name, shares=shares, price=price, total=total)
- # Add in History database
- db.execute("INSERT INTO history (id, symbol, shares, price, transacted) VALUES (:id, :symbol, :shares, :price, :transacted)", id=userID, symbol=symbol, shares=shares, price=price, transacted=datetime)
- # Update cash
- cash -= price * shares
- # Update cash in users database
- db.execute("UPDATE users SET cash = cash + :total WHERE id = :user_id", total=total, user_id=userID)
- # Redirect user to home page
- return redirect("/")
- # If NOT enough money in cash
- else:
- return apology("Can't afford", 400)
- # User reached via GET
- else:
- render_template("buy.html")
- @app.route("/history")
- @login_required
- def history():
- """Show history of transactions"""
- # Select all the tables from history database
- history = db.execute("SELECT * FROM history")
- # Show all list items (dict) in html
- return render_template("history.html")
- @app.route("/login", methods=["GET", "POST"])
- def login():
- """Log user in"""
- # Forget any user_id
- session.clear()
- # User reached route via POST (as by submitting a form via POST)
- if request.method == "POST":
- # Ensure username was submitted
- if not request.form.get("username"):
- return apology("must provide username", 403)
- # Ensure password was submitted
- elif not request.form.get("password"):
- return apology("must provide password", 403)
- # Query database for username
- rows = db.execute("SELECT * FROM users WHERE username = :username",
- username=request.form.get("username"))
- # Ensure username exists and password is correct
- if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
- return apology("invalid username and/or password", 403)
- # Remember which user has logged in
- session["user_id"] = rows[0]["id"]
- # Redirect user to home page
- return redirect("/")
- # User reached route via GET (as by clicking a link or via redirect)
- else:
- return render_template("login.html")
- @app.route("/logout")
- def logout():
- """Log user out"""
- # Forget any user_id
- session.clear()
- # Redirect user to login form
- return redirect("/")
- @app.route("/quote", methods=["GET", "POST"])
- @login_required
- def quote():
- """Get stock quote."""
- # User reached via POST (via submitting the form)
- if request.method == 'POST':
- # Ensure symbol was submitted
- if not request.form.get("symbol"):
- return apology("Missing symbol", 400)
- quoted = lookup(request.form.get("symbol"))
- # Ensre symbol is valid
- if not quote:
- return apology("Invalid symbol", 400)
- return render_template("showquote.html", company=quoted['name'], symbol=quoted['symbol'], usd=quoted['price'])
- # User reached via GET
- else:
- return render_template("quote.html")
- @app.route("/register", methods=["GET", "POST"])
- def register():
- """Register user"""
- # Forget any user_id
- session.clear()
- # User reached route via POST (as by submitting a form via POST)
- if request.method == "POST":
- # Ensure username was submitted
- if not request.form.get("username"):
- return apology("must provide username", 403)
- # Ensure password was submitted
- elif not request.form.get("password"):
- return apology("must provide password", 403)
- # Ensure password was submitted (twice)
- elif not request.form.get("passwordConfirm"):
- return apology("must provide password", 403)
- # Hash password
- hashpass = pwd_context.hash(request.form.get("password"))
- # Query database for username
- result = db.execute("INSERT INTO users (username, hash) VALUES(:username, :hash)", username=request.form.get("username"), hash=hashpass)
- if not result:
- return apology("Username already exists.")
- # Remember which user has logged in
- session["user_id"] = result[0]["id"]
- # Redirect user to home page
- return redirect("/")
- # User reached route via GET (as by clicking a link or via redirect)
- else:
- return render_template("register.html")
- @app.route("/sell", methods=["GET", "POST"])
- @login_required
- def sell():
- """Sell shares of stock"""
- # User reached route via POST (as by submitting a form via POST)
- if request.method == "POST":
- # Ensure symbol was submitted
- if not request.form.get("symbol"):
- return apology("Missing symbol", 400)
- symbol = request.form.get("symbol")
- # Ensure shares was submitted
- if not request.form.get("shares"):
- return apology("Missing shares", 400)
- shares = request.form.get("shares")
- # List all the symbols in user's portfolio
- db_symbols = db.execute("SELECT symbol FROM portfolio WHERE id = :id", id=session["user_id"])
- symbols_total = len(db_symbols)
- # Number of share in database
- db_shares = db.execute("SELECT shares FROM portfolio WHERE id = :id AND symbol = :symbol", id=session["user_id"], symbol=symbol)[0]["shares"]
- # Ensure user has enough share(s)
- if not db_shares >= shares:
- return apology("Too many shares", 400)
- # Present date-time
- datetime = strftime("%Y-%m-%d %H:%M:%S", gmtime())
- # Present price
- price = lookup(symbol)["price"]
- # Total price if bought
- total_price = shares * price
- # Subtract/Remove shares from user's portfolio
- if (db_shares - shares) > 0:
- db.execute("UPDATE portfolio SET shares - :shares, total - :totalPr WHERE id=:id AND symbol=:symbol", shares=shares, totalPr=total_price, id=session["user_id"], symbol=symbol)
- else:
- db.execute("DELETE FROM portfolio WHERE id=:id", id=session["user_id"])
- # Add transaction in history database
- db.execute("INSERT INTO history (id, symbol, shares, price, transacted) VALUES (:id, :symbol, :shares, :price, :transacted)", id=session["user_id"], symbol=symbol, shares=(-shares), price=price, transacted=datetime)
- # Update cash in users database
- db.execute("UPDATE users SET cash + :totalPr WHERE id=:id", totalPr=total_price, id=session["user_id"])
- # User reached route via GET (as by clicking a link or via redirect)
- else:
- return render_template("sell.html")
- def errorhandler(e):
- """Handle error"""
- return apology(e.name, e.code)
- #return apology(e)
- # listen for errors
- for code in default_exceptions:
- app.errorhandler(code)(errorhandler)
Advertisement
Add Comment
Please, Sign In to add comment