0

Been trying to troubleshoot this error with help from the internet but I have been unable to do so.

Below is my app.py:

import datetime

from cs50 import SQL
from flask import Flask, flash, redirect, render_template, request, session
from flask_session import Session
from werkzeug.security import check_password_hash, generate_password_hash

from helpers import apology, login_required, lookup, usd

# Configure application
app = Flask(__name__)

# Custom filter
app.jinja_env.filters["usd"] = usd

# Configure session to use filesystem (instead of signed cookies)
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.after_request
def after_request(response):
    """Ensure responses aren't cached"""
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Expires"] = 0
    response.headers["Pragma"] = "no-cache"
    return response


@app.route("/")
@login_required
def index():
    user = db.execute("SELECT * FROM users WHERE id = ?", session["user_id"])
    stocks = db.execute("SELECT * FROM purchases WHERE user_id = ? GROUP BY symbol ORDER BY cost DESC ", session["user_id"])
    totalStocksCost = 0
    info = []
    for i in stocks:
        new = {}
        symbol = i["symbol"]
        new["symbol"] = symbol
        shares = i["shares"]
        new["shares"] = shares
        price = lookup(symbol)["price"]
        new["price"] = price
        total = price*shares
        totalStocksCost += total
        new["total"] = total
        info.append(new)
    cash = user[0]["cash"]
    total = totalStocksCost + cash
    return render_template("index.html", stocks = info, cash = cash, total = total)



@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    if request.method == "POST":
        symbol = request.form.get("symbol")
        shares = request.form.get("shares")
        stock = lookup(symbol)
        if not stock or not shares.isnumeric() or int(shares) <= 0:
            return apology("Sorry, input error!", 400)
        userID = session["user_id"]
        cash = db.execute("SELECT * from users WHERE id = ?", userID)[0]["cash"]
        if not cash:
            return apology("Sorry, no cash!", 400)
        cost = stock["price"]
        total = cost*int(shares)
        if cash < total:
            return apology("Sorry, not enough cash!", 400)
        db.execute("INSERT INTO purchases(user_id, symbol, shares, cost, total) VALUES(?, ?, ?, ?, ?)", userID, symbol, int(shares), cost, total)
        leftoverCash = cash - total
        db.execute("UPDATE users SET cash = ? WHERE id = ?", leftoverCash, session["user_id"])
        db.execute("INSERT INTO history(id, symbol, state, price, shares, datetime) VALUES(?, ?, ?, ?, ?, ?)", userID, symbol, "buy", cost, int(shares), datetime.datetime.now())
        return redirect("/")
    return render_template("buy.html")


@app.route("/history")
@login_required
def history():
    history = db.execute("SELECT * FROM history WHERE id = ?", session["user_id"])
    return render_template("history.html", history = history)


@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 = ?", 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():
    if request.method == "POST":
        symbol = request.form.get('symbol')
        stock = lookup(symbol)
        if stock:
            return render_template("quoted.html", stock=stock)
        else:
            return apology("Stock doesn't exist!", 400)
    return render_template("quote.html")


@app.route("/register", methods=["GET", "POST"])
def register():
    names = db.execute("SELECT * FROM users")
    name = request.form.get("username")
    password = request.form.get("password")
    confirmation = request.form.get("confirmation")
    if request.method == "POST":
        if not name or not password or not confirmation or (password != confirmation):
            return apology("invalid username/password!", 400)
        else:
            for i in names:
                if i["username"] == name:
                    return apology("username already in use!", 400)
        hash = generate_password_hash(password)
        db.execute("INSERT into users(username, hash) VALUES(?, ?)", name, hash)
        return render_template("register.html", confirmation="You have successfully registered for an account!")
    return render_template("register.html")


@app.route("/sell", methods=["GET", "POST"])
@login_required
def sell():
    stocks = db.execute("SELECT * FROM purchases")
    list = []
    for i in stocks:
        if i["symbol"] not in list:
            list.append(i["symbol"])
    if request.method == "POST":
        sold = request.form.get("symbol")
        if not sold:
            return apology("Stock not found!", 400)
        shares = request.form.get("shares")
        if not shares.isnumeric() or int(shares) <= 0:
            return apology("Invalid input!", 400)
        stock = lookup(sold)
        ownedStocks = db.execute("SELECT * FROM purchases WHERE user_id = ?", session["user_id"])
        stocksList = []
        for j in ownedStocks:
            if j["symbol"] not in stocksList:
                stocksList.append(j["symbol"])
        print(stocksList)
        if sold not in stocksList:
            return apology("Stock not found!", 400)
        else:
            totalStocks = 0
            for k in ownedStocks:
                if k["symbol"] == sold:
                    totalStocks += k["shares"]
                    print(k)
            if totalStocks < int(shares):
                return apology("Not enough stocks!", 400)
            else:
                totalStocks = int(shares)
                stockPrice = stock["price"]
                cash = db.execute("SELECT * FROM users")[0]["cash"]
                for m in ownedStocks:
                    if m["symbol"] == sold:
                        if m["shares"] > totalStocks:
                            db.execute("UPDATE purchases SET shares = ? WHERE id = ?", m["shares"] - totalStocks, m["id"])
                        elif m["shares"] == totalStocks:
                            db.execute("DELETE FROM purchases WHERE id = ?", m["id"])
                        else:
                            totalStocks -= m["shares"]
                            db.execute("DELETE FROM purchases WHERE id = ?", m["id"])
                        cash += stockPrice*totalStocks
                        db.execute("UPDATE users SET cash = ? WHERE id = ?", cash, session["user_id"])
                db.execute("INSERT INTO history(id, symbol, state, price, shares, datetime) VALUES(?, ?, ?, ?, ?, ?)", session["user_id"], sold, "sell", stockPrice, totalStocks, datetime.datetime.now())
        return redirect('/')
    return render_template("sell.html", stocks = list)

@app.route('/add', methods=["GET","POST"])
def add():
    if request.method == "POST":
        funds = request.form.get("money")
        if not funds or not funds.isnumeric():
            return render_template("add.html", error = "Error!")
        currentFunds = db.execute("SELECT * FROM users WHERE id = ?", session["user_id"])[0]["cash"] + int(funds)
        db.execute("UPDATE users SET cash = ? WHERE id = ?", currentFunds, session["user_id"])
        return render_template("add.html", error="Added successfully!")
    return render_template("add.html")

And below is my index.html:


{% block title %}
    Index
{% endblock %}

{% block main %}

    <table class="table table-hover table-striped">
        <thead>
            <tr>
                <th class="text-start">Stocks</th>
                <th class="text-end">Shares</th>
                <th class="text-end">Price</th>
                <th class="text-end">Total</th>
            </tr>
        </thead>
        <tbody>
            {% for i in stocks %}
            <tr scope="row">
                <td class="text-start">{{ i.symbol }}</td>
                <td class="text-end">{{ i.shares }}</td>
                <td class="text-end">{{ i.price | usd }}</td>
                <td class="text-end">{{ i.total | usd }}</td>
            </tr>
            {% endfor %}
            <tr>
                <td class="border-0 fw-bold text-end" colspan="3">Cash</td>
                <td class="border-0 w-bold text-end">{{cash | usd}}</td>
            </tr>
            <tr>
                <td class="border-0 fw-bold text-end" colspan="3">TOTAL</td>
                <td class="border-0 w-bold text-end">{{total | usd}}</td>
            </tr>
        </tbody>
    </table>

{% endblock %}

I have already converted all the values on index.html to usd as said by many others with the help of jinja but to no avail. What should I do?

4
  • what is wrong? whats not working
    – UpAndAdam
    Commented Jan 11 at 18:09
  • don't use 'new' and 'list' as variable names. thats going to cause problems or a nightmare later.
    – UpAndAdam
    Commented Jan 11 at 18:10
  • would help if you included your table schemas
    – UpAndAdam
    Commented Jan 11 at 18:12
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer.
    – Community Bot
    Commented Jan 12 at 0:50

1 Answer 1

0

Your sell method is quite broken. It is unclear what your aim is in having a basically replicated table of purchases and history, where purchases does not seem to have stock being a unique key based on your search through it to find the total shares of a stock. every single buy leads to a row in purchases.

The key problem is that when you are selling and updating the database you are subtracting the sold shares from every single purchase instead of just one, the only case you sorta handle properly is the amounts that are less than enough to cover the full sale. if you had a purchases of 50,10,5,5,1 and tried to sell 10, the 50 would be reduced to 40, the 10 deleted, and the two 5's would be deleted. but the 1 would remain. clearly this is wrong.

What you should be doing instead is as you cancel out any purchase and potentially delete it, you always need to decrement the totalshares and your loop contingent needs to also be contingent on totalshares > 0

I would strongly suggest you reconsider your database design at the moment as it seems unnecessarily complicated. and some of your searches are just as such as well. When you are selecting rows from purchases in sales for example to find purchases of the given symbol, why not include the symbol as part of the where condition and let the database do that filtration for you? anytime you are getting data from the database you should do what you can to have it do as much of the filtering for you as you can.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .