コード例 #1
0
ファイル: admin.py プロジェクト: muhoed/cs50-2020-web-finance
def account():
    """Show account management page"""
    user_id = session.get("user_id")

    # User reached route via POST (as by submitting a form with new username/password via POST)
    if request.method == "POST":

        username = request.form.get("newname")
        password = request.form.get("newpass")
        confirmation = request.form.get("confpass")

        if username or password:
            # if new password was submitted
            if password:
                # Check password matches pattern
                if not re.match(
                        "(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*(&|%|#)).{8,}",
                        password):
                    return apology(
                        "Password must contain at least one number, one uppercase and lowercase letter, one special symbol (&,$,#) and has at least 8 characters",
                        403)
                # Ensure password confirmation matches password
                if password != confirmation or not confirmation:
                    return apology("confirmation does not match password", 403)

                # Udate password hash in database
                cur_user = Users.query.filter(Users.id == user_id).first()
                cur_user.hash = generate_password_hash(password)
                db.session.commit()

            # if new username was submitted
            if username:
                # Ensure username is not in use
                if Users.query.filter(Users.username == username,
                                      Users.id != user_id).first() is not None:
                    return apology("username already exists", 403)

                # Udate username in database
                cur_user = Users.query.filter(Users.id == user_id).first()
                cur_user.username = username
                db.session.commit()

            # Flash success message
            flash("Your username / password were changed.")

            # Redirect user to home page
            return redirect(url_for("home.index"))

        else:
            # Flash no-change message
            flash("Your username / password were not changed")

            # Redirect user to home page
            return redirect(url_for("admin.account"))

    else:
        user = db.session.query(Users.username,
                                Users.cash).filter(Users.id == user_id)
        return render_template("account.html", user=user)
コード例 #2
0
def history():
    """Show history of transactions"""

    data = get_history("date", "desc", "all")

    if data[0] == "error":
        # return render_template('debug.html', fund = data[1])
        return apology("Database read error", 403)
    elif data == "empty":
        return apology("You did not make any transaction yet", 403)

    return render_template("history.html", history=data)
コード例 #3
0
ファイル: auth.py プロジェクト: muhoed/cs50-2020-web-finance
def register():
    """Register user"""
    # 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")
        confirmation = request.form.get("confirmation")

        # Ensure username was submitted
        if not username:
            return apology("must provide username", 403)

        # Ensure username is uniq
        elif Users.query.filter(Users.username == username).first() is not None:
            return apology("username already exists", 403)

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

        # Check password matches pattern
        if not re.match("(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*(&|%|#)).{8,}", password):
            return apology("Password must contain at least one number, one uppercase and lowercase letter, one special symbol (&,$,#) and has at least 8 characters", 403)

        # Ensure password confirmation matches password
        elif password != confirmation or not confirmation:
            return apology("confirmation does not match password", 403)

        # Insert username in database
        new_user = Users(
            username = username,
            hash = generate_password_hash(password))
        db.session.add(new_user)
        db.session.flush()

        # log newly registered user in
        #id = db.session.query(Users.id).filter(Users.username == username).first()
        session["user_id"] = new_user.id
        
        # finalize changes to database
        db.session.commit()
        
        # Flash success message
        flash("Congratulation! You were successfully registered!")

        # Redirect user to home page
        return redirect(url_for("home.index"))

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("register.html")
コード例 #4
0
ファイル: home.py プロジェクト: muhoed/cs50-2020-web-finance
def index():
    """Show portfolio of stocks"""

    # request necessary data
    data = get_portfolio("symbol", "asc")
    if data == "error":
        return apology("database read error", 403)
    #return render_template('debug.html', fund = data)
    return render_template("index.html", rows = data[1], totals = data[0])
コード例 #5
0
ファイル: auth.py プロジェクト: muhoed/cs50-2020-web-finance
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
        try:
            cur_user = Users.query.filter(Users.username == username).first()
        except Exception as error:
            return apology("database read error", 403)

        # Ensure username exists
        if cur_user is None:
            return apology("Invalid username", 403)

        # Ensure password is correct
        if not check_password_hash(cur_user.hash, password):
            return apology("invalid password", 403)

        # Remember which user has logged in
        session["user_id"] = cur_user.id

        # Redirect user to home page
        return redirect(url_for("index"))

    # User reached route via GET (as by clicking a link or via redirect)
    else:
        return render_template("/login.html")
コード例 #6
0
ファイル: admin.py プロジェクト: muhoed/cs50-2020-web-finance
def changefund():
    """Manage cash funds in portfolio"""
    user_id = session.get("user_id")

    # User reached route via POST by submitting a form
    if request.method == "POST":

        operation = request.form.get("cashop")
        amount = int(request.form.get("amount"))

        if not amount or amount < 0:
            return apology(
                "Please enter amount of cash you would like to add / withdraw a a positive number",
                403)

        #current = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id = user_id)
        current = Users.query.filter(Users.id == user_id).first()

        if operation == "add":
            new_amount = current.cash + amount
            message = "You successfully added funds to your account"

        if operation == "withdraw":
            if amount > current.cash:
                return apology(
                    "The amount of cash in your account is not enough", 403)
            new_amount = current.cash - amount
            message = "You successfully withdrew funds from your account"

        # Udate cash amount in database
        current.cash = new_amount
        db.session.commit()

        # Flash success message
        flash(message)

        # Redirect user to home page
        return redirect(url_for("home.index"))

    else:
        return redirect(url_for("admin.account"))
コード例 #7
0
def sell():
    """Sell shares of stock"""

    rows = db.session.query(
        Transactions.symbol,
        Transactions.shares).filter_by(user_id=current_user.id).all()
    symbols = [row[0] for row in rows]

    form = SellForm()
    form.symbol.choices = ['Select Symbol'] + list(set(symbols))

    if form.validate_on_submit():
        if form.symbol.data not in symbols:
            return apology('symbol not in portfolio', 403)

        elif int(form.shares.data) > sum(
            [row[1] for row in rows if row[0] == form.symbol.data]):
            return apology('share number exceeded', 403)

        user = User.query.filter_by(id=current_user.id).first()
        resp = lookup(form.symbol.data)
        total_price = int(form.shares.data) * resp['price']

        user.cash += total_price
        transaction = Transactions(symbol=form.symbol.data,
                                   shares=-form.shares.data,
                                   price=resp['price'],
                                   user_id=user.id)

        db.session.add(transaction)
        db.session.commit()

        flash('SOLD!', 'success')

        return redirect('/')
    else:
        return render_template('sell.html', symbols=symbols, form=form)
コード例 #8
0
def buy():
    """Buy shares of stock"""
    form = BuyForm()

    if form.validate_on_submit():
        resp = lookup(form.symbol.data)
        user = User.query.filter_by(id=current_user.id).first()

        total_price = int(form.shares.data) * resp['price']

        if user.cash < total_price:
            return apology("not enough cash to complete the transaction")

        user.cash -= total_price
        transaction = Transactions(symbol=form.symbol.data,
                                   shares=form.shares.data,
                                   price=resp['price'],
                                   user_id=user.id)
        db.session.add(transaction)
        db.session.commit()
        flash('BOUGHT!', 'success')
        return redirect('/')
    return render_template('buy.html', form=form)
コード例 #9
0
ファイル: __init__.py プロジェクト: munhod/finance-web
def errorhandler(e):
    """Handle error"""
    if not isinstance(e, HTTPException):
        e = InternalServerError()
    return apology(e.name, e.code)
コード例 #10
0
def buy():
    """Buy shares of stock"""

    # return base buy page if no url variiables
    if not request.args and request.method == "GET":
        return render_template("buy.html")

    # get user id
    user_id = session.get("user_id")

    # request stock ticker symbol from URL
    symbol = request.args.get("symbol", '')
    shares = request.args.get("shares", '')

    # set shares if no number is provided
    if not shares:
        shares = 0

    # check 'shares' is positive number
    if int(shares) < 0:
        return apology("Please enter positive number of shares to buy", 403)

    # get cash available
    #fund = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id = user_id)
    fund = Users.query.filter(Users.id == user_id).first()
    funds = float(fund.cash)

    # no stock ticker symbol was provided through GET method
    if not symbol:

        # User reached route via POST (as by submitting a form via POST)
        if request.method == "POST":

            symbol = request.form.get("symbol")
            name = request.form.get("name")
            shares = int(request.form.get("shares"))
            price = float(request.form.get("price"))

            # load apology if symbol is not provided
            if not symbol:
                return apology("please enter stock ticker symbol", 403)

            # load apology if number is not provided
            if not shares or shares <= 0:
                return apology("Please enter positive number of shares to buy",
                               403)

            # check funds available
            if funds < price * shares:
                return apology("Sorry, not enough funds for this transaction",
                               403)

            # prepare data to be inserted into db
            amount = round(shares * price, 2)
            cash_after = funds - amount

            # fill in transactions table with new data
            new_transaction = Transactions(user_id=user_id,
                                           symbol=symbol,
                                           name=name,
                                           number=shares,
                                           price=price,
                                           amount=shares * price,
                                           type="buy")
            db.session.add(new_transaction)
            db.session.commit()

            # update cash
            cur_user = Users.query.filter(Users.id == user_id).first()
            cur_user.cash = cash_after
            db.session.commit()

            message = "You've successfully bought " + str(
                shares) + " shares of " + symbol
            flash(message)
            return redirect(url_for("index"))

        else:
            return apology("please enter stock ticker symbol", 403)

    # request symbol information from IEX cloud
    quoteInfo = lookup(symbol)

    # redirect to buy page with error message if no symbol was found
    if quoteInfo is None:
        return apology(
            "The symbol was not found or something else went wrong.", 403)

    # load buy page with stock ticker information filled in
    return render_template("buy.html",
                           quoteInfo=quoteInfo,
                           shares=shares,
                           price=quoteInfo["price"],
                           cash=funds,
                           required=quoteInfo["price"] * int(shares))
コード例 #11
0
def sell():
    """Sell shares of stock"""

    user_id = session.get("user_id")

    # request a list of owned shares
    #holdings = db.execute("SELECT symbol, name, SUM(number) shares, SUM(amount) total, (SUM(amount) / SUM(number)) avgprice FROM transactions WHERE user_id = :user_id GROUP BY symbol", user_id = user_id)
    holdings = db.session.query(Transactions.symbol, Transactions.name,
                                func.sum(Transactions.number).label('shares'),
                                func.sum(Transactions.amount).label('total'),
                                label('avgprice', func.sum(Transactions.amount) / func.sum(Transactions.number))).\
                                filter(Transactions.user_id == user_id).group_by(Transactions.symbol).all()

    # return base sell page if no url variiables
    if not request.args and request.method == "GET":

        if holdings is not None:

            # prepare a list of owned shares to choose from
            list = []
            for row in holdings:
                list.append(row.symbol)

            # load sell page
            return render_template("sell.html", list=list)

        # return apology if user does not own any stock
        else:
            return apology("You do not own any stock to sell", 403)

    # request stock ticker symbol from URL
    symbol = request.args.get("symbol", '')

    # no stock ticker symbol was provided via GET
    if not symbol:

        # User reached route via POST (as by submitting a form via POST)
        if request.method == "POST":

            symbol = request.form.get("symbol")
            name = request.form.get("name")
            shares = request.form.get("shares")
            price = float(request.form.get("price"))

            # load apology if symbol is not provided
            if not symbol:
                return apology(
                    "Please choose ticker symbol of stock you want to sell",
                    403)

            # load apology if number is not provided
            if not shares or int(shares) <= 0:
                return apology(
                    "Please enter positive number of shares to sell", 403)

            # get owned number of stocks
            for row in holdings:
                if symbol == row.symbol:
                    sharesOwned = row.shares
                    break

            # check number of shares available
            if int(shares) > sharesOwned:
                return apology(
                    "Sorry, you do not own enough number of shares ", 403)

            # prepare data to be inserted into db
            amount = round(int(shares) * price, 2) * -1

            #funds = db.execute("SELECT cash FROM users WHERE id = :user_id", user_id = user_id)
            funds = Users.query.filter(Users.id == user_id).first()
            cash_after = float(funds.cash) - amount

            # fill in transactions table with new data
            new_transaction = Transactions(user_id=user_id,
                                           symbol=symbol,
                                           name=name,
                                           number=int(shares) * -1,
                                           price=price,
                                           amount=amount,
                                           type="sell")
            db.session.add(new_transaction)
            db.session.commit()

            cur_user = Users.query.filter(Users.id == user_id).first()
            cur_user.cash = cash_after
            db.session.commit()

            message = "You've successfully sold " + str(
                shares) + " shares of " + symbol
            flash(message)
            return redirect(url_for("index"))

        else:
            return apology("must enter stock ticker symbol", 403)

    # request symbol information from IEX cloud
    quoteInfo = lookup(symbol)

    # redirect to buy page with error message if no symbol was found
    if quoteInfo is None:
        return apology(
            "The symbol was not found or something else went wrong.", 403)

    # get number of owned stocks and average price of aquisition
    for row in holdings:
        if symbol == row.symbol:
            sharesOwned = row.shares
            avgPrice = row.avgprice
            amount = row.total
            break

    # load sell page with stock ticker information filled in
    return render_template("sell.html",
                           quoteInfo=quoteInfo,
                           sharesOwned=sharesOwned,
                           avgPrice=avgPrice,
                           amount=amount)