Advertisement
Guest User

Untitled

a guest
Aug 21st, 2017
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.68 KB | None | 0 0
  1. from cs50 import SQL
  2. from flask import Flask, flash, redirect, render_template, request, session, url_for
  3. from flask_session import Session
  4. from passlib.apps import custom_app_context as pwd_context
  5. from tempfile import mkdtemp
  6.  
  7. from helpers import *
  8.  
  9. # configure application
  10. app = Flask(__name__)
  11.  
  12. # ensure responses aren't cached
  13. if app.config["DEBUG"]:
  14.     @app.after_request
  15.     def after_request(response):
  16.         response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
  17.         response.headers["Expires"] = 0
  18.         response.headers["Pragma"] = "no-cache"
  19.         return response
  20.  
  21. # custom filter
  22. app.jinja_env.filters["usd"] = usd
  23.  
  24. # configure session to use filesystem (instead of signed cookies)
  25. app.config["SESSION_FILE_DIR"] = mkdtemp()
  26. app.config["SESSION_PERMANENT"] = False
  27. app.config["SESSION_TYPE"] = "filesystem"
  28. Session(app)
  29.  
  30. # configure CS50 Library to use SQLite database
  31. db = SQL("sqlite:///finance.db")
  32.  
  33. @app.route("/")
  34. @login_required
  35. def index():
  36.    
  37.     # get users current porfolio
  38.     rows = db.execute("SELECT stock, SUM(amount) as amount FROM history WHERE userid = :userid GROUP BY stock HAVING SUM(amount) <> 0", userid = session["user_id"])
  39.    
  40.     # map
  41.     for row in rows:
  42.        
  43.         # get current stock info
  44.         result = lookup(row["stock"])
  45.        
  46.         # handle errors
  47.         if result == None:
  48.             return apology("could not get stock info")
  49.        
  50.         # map results to rows
  51.         row["name"] = result["name"]
  52.         row["price"] = usd(result["price"])
  53.         row["total"] = usd(result["price"] * row["amount"])
  54.        
  55.         # saves unformatted one to be used in sum
  56.         row["total_unf"] = result["price"] * row["amount"]
  57.    
  58.     # figure out how much cash user has
  59.     cash = db.execute("SELECT * FROM users WHERE id = :id", id = session["user_id"])
  60.    
  61.     # sum value of portfolio
  62.     val = float(cash[0]["cash"])
  63.     for row in rows:
  64.         val += row["total_unf"]
  65.  
  66.     # render index
  67.     return render_template("index.html", stocks=rows, cash = usd(cash[0]["cash"]), total = usd(val))
  68.  
  69. @app.route("/buy", methods=["GET", "POST"])
  70. @login_required
  71. def buy():
  72.     """Buy shares of stock."""
  73.    
  74.     # if user reached route via POST (as by submitting a form via POST)
  75.     if request.method == "POST":
  76.        
  77.         # get stock info
  78.         result = lookup(request.form.get("symbol"))
  79.        
  80.         # handle invalid inputs
  81.         if result == None:
  82.             return apology("invalid symbol")
  83.        
  84.         # render apology if number to buy is not a positive int
  85.         try:
  86.             if int(request.form.get("shares")) < 1:
  87.                 return apology("number less than 1")
  88.                
  89.         except ValueError:
  90.             return apology("not an integer")
  91.  
  92.         # select current amt of user money money
  93.         money = db.execute("SELECT * FROM users WHERE id = :id", id = session["user_id"])
  94.        
  95.         # if not enough money to complete transaction, render apology
  96.         if money[0]["cash"] < result["price"] * int(request.form.get("shares")):
  97.             return apology("not enough cash")
  98.        
  99.         # else enough money to buy
  100.         else:
  101.            
  102.             # update cash in users
  103.             db.execute("UPDATE users SET cash = :cash WHERE id = :id", cash = money[0]["cash"] - (result["price"] * int(request.form.get("shares"))), id = session["user_id"])
  104.            
  105.             # add stock, price, quantity to portfolio
  106.             db.execute("INSERT INTO 'history' (userid, stock, amount, price) VALUES (:userid, :stock, :amount, :price)", userid = session["user_id"], stock = result["symbol"], amount = int(request.form.get("shares")), price = result["price"])
  107.        
  108.             # redirect user to homepage
  109.             flash("Bought!")
  110.             return redirect(url_for("index"))
  111.        
  112.     # else if user reached route via GET (as by clicking a link or via redirect)
  113.     else:
  114.         return render_template("buy.html")
  115.        
  116.        
  117. @app.route("/history")
  118. @login_required
  119. def history():
  120.     """Show history of transactions."""
  121.  
  122.     # get users transaction history
  123.     rows = db.execute("SELECT stock, amount, price, timestamp FROM history WHERE userid = :userid ORDER BY timestamp desc", userid = session["user_id"])
  124.    
  125.     # format price
  126.     for row in rows:
  127.         row["price"] = usd(row["price"])
  128.    
  129.     # render history
  130.     return render_template("history.html", stocks = rows)
  131.    
  132.  
  133. @app.route("/login", methods=["GET", "POST"])
  134. def login():
  135.     """Log user in."""
  136.  
  137.     # forget any user_id
  138.     session.clear()
  139.  
  140.     # if user reached route via POST (as by submitting a form via POST)
  141.     if request.method == "POST":
  142.  
  143.         # ensure username was submitted
  144.         if not request.form.get("username"):
  145.             return apology("must provide username")
  146.  
  147.         # ensure password was submitted
  148.         elif not request.form.get("password"):
  149.             return apology("must provide password")
  150.  
  151.         # query database for username
  152.         rows = db.execute("SELECT * FROM users WHERE username = :username", username=request.form.get("username"))
  153.  
  154.         # ensure username exists and password is correct
  155.         if len(rows) != 1 or not pwd_context.verify(request.form.get("password"), rows[0]["hash"]):
  156.             return apology("invalid username and/or password")
  157.  
  158.         # remember which user has logged in
  159.         session["user_id"] = rows[0]["id"]
  160.  
  161.         # redirect user to home page
  162.         return redirect(url_for("index"))
  163.  
  164.     # else if user reached route via GET (as by clicking a link or via redirect)
  165.     else:
  166.         return render_template("login.html")
  167.  
  168. @app.route("/logout")
  169. def logout():
  170.     """Log user out."""
  171.  
  172.     # forget any user_id
  173.     session.clear()
  174.  
  175.     # redirect user to login form
  176.     return redirect(url_for("login"))
  177.  
  178.  
  179. @app.route("/quote", methods=["GET", "POST"])
  180. @login_required
  181. def quote():
  182.     """Get stock quote."""
  183.    
  184.     # if user reached route via POST (as by submitting a form via POST)
  185.     if request.method == "POST":
  186.        
  187.         # store stock info
  188.         result = lookup(request.form.get("symbol"))
  189.        
  190.         # handle invalid inputs
  191.         if result == None:
  192.             return apology("invalid symbol")
  193.        
  194.         # render quoted page
  195.         else:    
  196.             return render_template("quoted.html", name = result["name"], symbol = result["symbol"], price = usd(result["price"]))
  197.    
  198.     # else if user reached route via GET (as by clicking a link or via redirect)
  199.     else:
  200.         return render_template("quote.html")
  201.    
  202.  
  203. @app.route("/register", methods=["GET", "POST"])
  204. def register():
  205.     """Register user."""
  206.    
  207.     # if user reached route via POST (as by submitting a form via post)
  208.     if request.method == "POST":
  209.        
  210.         # ensure username was submitted
  211.         if not request.form.get("username"):
  212.             return apology("must provide username")
  213.            
  214.         # ensure password was submitted
  215.         elif not request.form.get("password"):
  216.             return apology("must provide password")
  217.            
  218.         # ensure passwords match
  219.         elif request.form.get("password") != request.form.get("passwordCheck"):
  220.             return apology("passwords must match")
  221.            
  222.         else:
  223.            
  224.             # hash password
  225.             hashword = pwd_context.hash(request.form.get("password"))
  226.                
  227.             # insert username and hashword into db
  228.             result = db.execute("INSERT INTO users (username, hash) VALUES(:username, :hash)", username = request.form.get("username"), hash = hashword)
  229.             if not result:
  230.                 return apology("Name already exists")
  231.            
  232.             else:
  233.                 # remember which user has registered/logged in
  234.                 session["user_id"] = result
  235.  
  236.                 # redirect user to home page
  237.                 return redirect(url_for("index"))
  238.    
  239.    # else if user reached route via GET (as by clicking a link or via redirect)            
  240.     else:    
  241.         return render_template("register.html")
  242.    
  243.    
  244. @app.route("/sell", methods=["GET", "POST"])
  245. @login_required
  246. def sell():
  247.     """Sell shares of stock."""
  248.    
  249.     # if user reached route via POST (as by submitting a form via POST)
  250.     if request.method == "POST":
  251.        
  252.         # render apology if number to sell is not a positive int
  253.         try:
  254.             if int(request.form.get("shares")) < 1:
  255.                 return apology("number less than 1")
  256.                
  257.         except ValueError:
  258.             return apology("not an integer")
  259.            
  260.         # get stock info
  261.         result = lookup(request.form.get("symbol"))        
  262.        
  263.         # handle invalid inputs
  264.         if result == None:
  265.             return apology("invalid symbol")        
  266.  
  267.        
  268.         # query current number of shares owned
  269.         rows = db.execute("SELECT stock, SUM(amount) as amount FROM history WHERE userid = :userid and stock = :stock GROUP BY stock", userid = session["user_id"], stock = request.form.get("symbol"))
  270.        
  271.         # apologize if no shares owned
  272.         if not rows:
  273.             return apology("no shares owned")
  274.        
  275.         # if current shares owned is less than submitted quantity
  276.         if int(request.form.get("shares")) > rows[0]["amount"]:
  277.            
  278.             # error
  279.             return apology("don't own enough shares")
  280.        
  281.         # otherwise modify db and redirect
  282.         else:
  283.            
  284.             # add transaction to history
  285.             db.execute("INSERT INTO 'history' (userid, stock, amount, price) VALUES (:userid, :stock, :amount, :price)", userid = session["user_id"], stock = result["symbol"], amount = -int(request.form.get("shares")), price = result["price"])
  286.            
  287.             # select current amt of user money money
  288.             money = db.execute("SELECT * FROM users WHERE id = :id", id = session["user_id"])            
  289.            
  290.             # update cash
  291.             db.execute("UPDATE users SET cash = :cash WHERE id = :id", cash = money[0]["cash"] + (result["price"] * int(request.form.get("shares"))), id = session["user_id"])            
  292.            
  293.             # redirect to index
  294.             flash("Sold!")
  295.             return redirect(url_for("index"))
  296.  
  297.    # else if user reached route via GET (as by clicking a link or via redirect)            
  298.     else:
  299.        
  300.         return render_template("sell.html")
  301.        
  302.        
  303.  
  304. @app.route("/cash", methods=["GET", "POST"])
  305. @login_required
  306. def add_cash():
  307.     """Add cash to account."""
  308.    
  309.     # if user reached route via POST (as by submitting a form via POST)
  310.     if request.method == "POST":
  311.        
  312.         # try converting to float
  313.         try:
  314.            
  315.             # don't let people remove money
  316.             if float(request.form.get("money")) < 0:
  317.                 return apology("can't subtract money", "bad choice to invest with us")
  318.        
  319.         # error if not a float
  320.         except ValueError:
  321.             return apology("not a float")
  322.  
  323.         # select current amt of user money money
  324.         money = db.execute("SELECT * FROM users WHERE id = :id", id = session["user_id"])
  325.  
  326.         # update cash
  327.         db.execute("UPDATE users SET cash = :cash WHERE id = :id", cash = money[0]["cash"] + float(request.form.get("money")), id = session["user_id"])
  328.        
  329.         # redirect to index
  330.         flash("Added!")
  331.         return redirect(url_for("index"))        
  332.        
  333.     # else if user reached route via GET (as by clicking a link or via redirect)
  334.     else:
  335.         return render_template("cash.html")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement