skip to Main Content

index page after one transaction

:( buy handles valid purchase

Cause
expected to find "112.00" in page, but it wasn't found
Log
sending GET request to /signin
sending POST request to /login
sending POST request to /buy
sending POST request to /buy
checking that "112.00" is in page 

After buying stock user should be redirected to index page, where total value of stocks purchased or grand total(cash + portfolio value) is shown. I show both. I don’t know what to do next.

index route code in app.py

@app.route("/")
@login_required
def index():
    """Show portfolio of stocks"""
    user_id = session["user_id"]
    user_info = db.execute("SELECT username, cash FROM users where id = ?", user_id)
    # Get necessary data from database
    user_info[0]["grand_total"] = user_info[0]["cash"]
    user_stocks = db.execute(
        """
        SELECT
            stock_symbol,
            SUM(quantity) AS quantity,
            ROUND(AVG(transaction_amount), 2) AS avg_price,
            transaction_type,
            ROUND(SUM(transaction_amount * quantity), 2) AS total_transaction_amount
        FROM
            users_stocks
            INNER JOIN stocks ON users_stocks.stock_id = stocks.stock_id
        WHERE
            user_id = ?
        GROUP BY
            stock_symbol, transaction_type
        ORDER BY
            stock_symbol, transaction_type ASC""",
        user_id,
    )
    if not user_stocks:
        return render_template(
            "/index.html", stocks=[], user_info=user_info, totals=[], grand_total = 0
        )

    for i in range(len(user_stocks)):
        current_info = lookup(user_stocks[i]["stock_symbol"])
        if current_info:
            current_price = current_info["price"]
            user_stocks[i]["current_price"] = current_price
            user_stocks[i]["total_current_value"] = (
                user_stocks[i]["quantity"] * current_price
            )

        if user_stocks[i]["transaction_type"] == "s":
            user_stocks[i - 1]["total_transaction_amount"] -= user_stocks[i][
                "total_transaction_amount"
            ]
            user_stocks[i - 1]["quantity"] -= user_stocks[i]["quantity"]
            user_stocks[i - 1]["total_current_value"] -= user_stocks[i]["total_current_value"]


    stocks = []
    quantities = []
    averages = []
    stocks_value = 0
    totals = {"quantity": 0, "weighted_avg": 0, "total_value": 0, "total_paid": 0}
    for stock in user_stocks:
        if stock["transaction_type"] == "b" and stock["quantity"] != 0:
            stocks.append(stock)
            stocks_value += stock["total_current_value"]
            totals["quantity"] += stock["quantity"]
            totals["total_value"] += stock["total_current_value"]
            totals["total_paid"] += stock["total_transaction_amount"]
            quantities.append(stock["quantity"])
            averages.append(stock["avg_price"])

    weighted_avg = np.average(averages, weights=quantities)
    totals["weighted_avg"] = weighted_avg
    print("n", stocks, "n")
    print(totals)
    grand_total = totals['total_value'] + user_info[0]['cash']
    return render_template(
        "/index.html", stocks=stocks, user_info=user_info,
          stocks_value=stocks_value, totals=totals, grand_total=grand_total
    )


HTML

    {% extends "layout.html" %} {% block head %}
    <link rel="stylesheet" href="../static/index.css" />
    {% endblock head %} {% block main %}
    <h2>Profile</h2>
    <div class="infoBar">
    <div>
        Hello, {{ user_info[0]['username'] }}
        <a href="/changePassword" class="btn btn-primary btn-sm">change password</a>
    </div>
    <div>
        Cash Blance: {{ user_info[0]['cash'] | usd }}
        <a href="/addcash" class="btn btn-primary btn-sm">Add Cash</a>
    </div>
    {% if totals %}
    <div>Portfolio Value: {{ totals['total_value'] | usd }}</div>
    <div>Grand Total: {{ grand_total | usd }}</div>
    {% else %}
    <div>Portfolio Value: 0</div>
    {% endif %}
    </div>
    {% if stocks %}
    <div class="table-responsive">
    <table class="table table-primary">
        <thead>
        <tr>
            <th scope="col">Symbol</th>
            <th scope="col">Average Paid</th>
            <th scope="col">Quantity</th>
            <th scope="col">Total Paid</th>
            <th scope="col">Current Price</th>
            <th scope="col">Value today</th>
            <th scope="col">Sell</th>
        </tr>
        </thead>
        <br />
        <tbody>
        {% for stock in stocks %} {% if stock['quantity'] != 0 %}
        <tr class="table-info">
            <td>{{ stock['stock_symbol'] }}</td>
            <td>{{ stock['avg_price'] | usd }}</td>
            <td>{{ stock['quantity'] }}</td>
            <td>{{stock['total_transaction_amount']|usd}}</td>
            <td>{{ stock['current_price'] | usd }}</td>
            <td>{{stock["total_current_value"]|usd}}</td>
            <td>
            <form action="/sell" method="post">
                <input
                type="hidden"
                name="stock_select"
                id="stock_select"
                value="{{ 
                stock['stock_symbol'] }}"
                />
                <input
                type="hidden"
                name="quantity"
                id="quantity"
                value="{{ 
                                                stock['quantity'] }}"
                />
                <button type="submit" class="btn btn-primary btn- sm">
                Sell {{ stock['quantity'] }}
                </button>
            </form>
            </td>
        </tr>
        {% endif %} {% endfor %} {% if totals %}
        <tr>
            <td>TOTAL</td>
            <td>{{ totals['weighted_avg'] | usd }}</td>
            <td>{{ totals['quantity'] }}</td>
            <td>{{ totals['total_paid'] | usd }}</td>
            <td></td>
            <td>{{ totals['total_value'] | usd }}</td>
            <td>
            <a href="/sell" class="btn btn-primary btn-sm">sell</a>
            </td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td>Cash</td>
            <td>{{ user_info[0]['cash'] | usd }}</td>
        </tr>
        <tr>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td></td>
            <td>TOTAL</td>
            <td>{{ grand_total| usd }}</td>
        </tr>
        {% endif %}
        </tbody>
    </table>
    </div>
    {% else %}
    <br />
    <h3>You don't have any stocks</h3>
    <br />
    {% endif %} {% endblock main %}

/buy route

@app.route("/buy", methods=["GET", "POST"])
@login_required
def buy():
    """Buy shares of stock"""
    if request.method == "POST":
        # verify stock and quantity
        user_symbol = request.form.get("symbol")
        stock_quantity = request.form.get("shares")
        if "." in stock_quantity:
            return apology("Input must be integer")
        try:
            stock_quantity = int(stock_quantity)
        except:
            return apology("Input must be numeric")
        if not user_symbol:
            return apology("Please specify stock symbol")
        elif not stock_quantity:
            return apology("Please indicate quantity")
        elif stock_quantity <= 0:
            return apology("you must input positive number")
        # Check if provided stock symbol exists
        user_symbol = user_symbol.upper()
        stock_info = lookup(user_symbol)
        if stock_info:
            stock_price = stock_info["price"]
            stock_symbol = stock_info["symbol"]
            db_stock_id = db.execute("""
                                     SELECT stock_id
                                     FROM stocks
                                     WHERE stock_symbol = ?""",
                                     stock_symbol)
            if not db_stock_id:
                return apology(f"Stock {user_symbol} not found")
        else:
            return apology(f"Stock {user_symbol} not found")
        # Update users cash balance
        user_id = session["user_id"]
        user_cash = db.execute("SELECT cash FROM users WHERE id = ?", user_id)
        if user_cash:
            current_user_cash = float(user_cash[0]["cash"])
            stock_quantity = int(stock_quantity)
            total_for_stocks = stock_price * stock_quantity
            updated_user_cash = round(current_user_cash - total_for_stocks, 2)
            if updated_user_cash < 0:
                return apology("Not enough money on the balance")
            db.execute(
                "UPDATE users SET cash = ? WHERE id = ?", updated_user_cash, user_id
            )

        current_datetime = datetime.now()
        current_time = current_datetime.strftime("%H:%M:%S")
        current_date = current_datetime.date()
        # Add stock purchase to database
        db.execute(
            """INSERT INTO
            users_stocks (user_id, stock_id,
            transaction_amount, quantity,
            transaction_type, date, time)
            VALUES(?, ?, ?, ?, ?, ?, ?)""",
            user_id,
            db_stock_id[0]["stock_id"],
            stock_price,
            stock_quantity,
            "b",
            current_date,
            current_time,
        )

        return redirect("/")

    # pass info to populate purchase history table
    user_id = session["user_id"]
    user_stocks = db.execute(
        """SELECT stock_symbol, transaction_amount, quantity, date, time, transaction_type
        FROM users_stocks
        INNER JOIN stocks ON users_stocks.stock_id = stocks.stock_id
        WHERE user_id = ? AND transaction_type = 'b'
        ORDER BY date DESC, time DESC
        LIMIT 10""",
        user_id,
    )
    current_stocks = {}
    for stock in user_stocks:
        if stock["stock_symbol"] not in current_stocks:
            current_stock_info = lookup(stock["stock_symbol"])
            if current_stock_info:
                current_price = current_stock_info["price"]
                current_stocks[current_stock_info["symbol"]] = current_price
    return render_template(
        "buy.html", user_stocks=user_stocks, current_stocks=current_stocks
    )

/login route

@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":
        username = request.form.get("username")
        password = request.form.get("password")
        # Ensure username was submitted
        if not username:
            return apology("must provide username", 403)

        # Ensure password was submitted
        elif not password:
            return apology("must provide password", 403)

        # Query database for username
        rows = db.execute("SELECT * FROM users WHERE username = ?", username)

        # Ensure username exists and password is correct
        if len(rows) != 1 or not check_password_hash(rows[0]["hash"], 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")

I tried placing portfolio value(total value of stocks) and grand total(portfolio value + users cash) in several places, but check still can not find value. Also, money is formatted with " | usd" everywhere.

2

Answers


  1. Chosen as BEST ANSWER

    I figured it out. Problem was in buy function. CS50 check was testing with stock which was not in my database(106328 stocks). So, I added check to buy function.

    Functionality added.

    After getting stock info from yahoo, If stock is not in database, add stock symbol to database.

    @app.route("/buy", methods=["GET", "POST"])
    @login_required
    def buy():
        """Buy shares of stock"""
        if request.method == "POST":
            # verify stock and quantity
            user_symbol = request.form.get("symbol")
            stock_quantity = request.form.get("shares")
            if "." in stock_quantity:
                return apology("Input must be integer")
            try:
                stock_quantity = int(stock_quantity)
            except:
                return apology("Input must be numeric")
            if not user_symbol:
                return apology("Please specify stock symbol")
            elif not stock_quantity:
                return apology("Please indicate quantity")
            elif stock_quantity <= 0:
                return apology("you must input positive number")
    
            # Check if provided stock symbol exists
            user_symbol = user_symbol.upper()
            stock_info = lookup(user_symbol)
            if stock_info:
                stock_price = stock_info["price"]
                stock_symbol = stock_info["symbol"]
                existing_stocks = db.execute("""
                SELECT
                    stock_symbol
                FROM
                    stocks
                """,)
                
                # Check if stock is in database
                in_database = False
                for i in range(len(existing_stocks)):
                    if user_symbol == existing_stocks[i]["stock_symbol"]:
                        in_database = True
                        break
                if not in_database:
                    db.execute("""
                            INSERT INTO stocks (stock_symbol)
                            VALUES(?)
                            """,
                            stock_symbol
                    )
    

  2. In the code there is a table named stocks. It is apparently used to store the stock symbol. However, there is no INSERT to create the row. buy will not work for a newly registered because it will return an apology when program tries to select stock_id from stocks table. (check50 uses the newly registered user). You should be able to reproduce the result by registering a new user and then executing a buy.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search