Skip to main content
Bumped by Community user
Save the concerns for the question body. The title should simply state what the code does.
Link
Mast
  • 13.9k
  • 12
  • 57
  • 128

How to remove nested conditionals inside flask Flask static url view

Tweeted twitter.com/StackCodeReview/status/1447079501553442816
added 914 characters in body
Source Link
sat1017
  • 141
  • 2

Am I stuck with this mess until I use a rest framework to send a function call based on the button clicked?

Edit: added import lines

#from importsdatetime import date
#import json
import os
import re
import threading
import time

from bs4 import BeautifulSoup
import click
from flask import Blueprint, current_app
import requests
from requests.exceptions import HTTPError, Timeout
from sqlalchemy.exc import IntegrityError, SQLAlchemyError, StatementError
from werkzeug.security import check_password_hash, generate_password_hash


from project.crud import create_user, create_index, create_portfolio_balance, check_user_email
from project.database import Base, db_session, engine
from project.log import logger
from project.models import Company, DimCompanyInfo, Index, DimIndexPrice, DimCompanyPrice
from project.utils import row2dict

dashboard_blueprint = Blueprint('dashboard', __name__, url_prefix='/dashboard')

@dashboard_blueprint.route('/home', methods=('GET', 'POST'))
@login_required
def home():
    # dirty way of not using REST api to distinguish between buy/sell/add funds
    # use button key as quasi switch case
    # button 1: 'tickerBought' buys shares of a stock
    # button 2: 'tickerSold' sells shares of a stock
    # button 3: 'addFunds' add funds to your portfolio

    # button 1: 'tickerBought' buys shares of a stock
    if request.method == 'POST':
        f = request.form
        if 'tickerBought' in f.keys():
            user_id = session.get('user_id')
            row = {}
            row['PortfolioID']= session.get('user_id')
            row['Symbol']= request.form['tickerBought'].upper()
            row['NumberShares'] = float(request.form['amountSharesBought'])
            row['Date'] = date.fromisoformat(request.form['dateBought'])

            query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(DimCompanyPrice.Date <= row.get('Date')).\
                filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()
            logger.info(query)
            
            if query is None:
                flash('Price data not available for this transaction. Pick another date.')
            # check if there is enough avail balance to cover transaction
            price = query[1].CloseAdjusted
            shares = row['NumberShares']
            total_price = float(price*shares)
            sym = row['Symbol']

            query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
            
            balance = query.Balance
            if balance >= total_price:
                row['TotalPrice'] = total_price
                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance - total_price})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_bought_shares_email.delay(user_id, int(shares), sym)
            else:
                logger.info('Not enough available balance to complete the transaction')
                flash('Not enough available balance to complete the transaction')
        elif 'tickerSold' in f.keys(): # button 2: 'tickerSold' sells shares of a stock
            user_id = session.get('user_id')
            date_sold = date.fromisoformat(request.form['dateSold'])
            sym = request.form['tickerSold'].upper()
            amount_shares_sold = float(request.form['amountSharesSold'])
            
            q = db_session.query(Portfolio.Symbol, func.sum(Portfolio.NumberShares)).\
                filter(Portfolio.PortfolioID == user_id).\
                filter(Portfolio.Symbol == sym).\
                filter(Portfolio.Date <= date_sold).\
                all()
            
            if q[0][1] is None:
                flash('You do not own any shares to sell')
            elif q[0][1] >= amount_shares_sold:
                row = {}
                row['PortfolioID']= user_id
                row['Symbol']= sym
                row['NumberShares'] = -amount_shares_sold
                row['Date'] = date_sold

                query = db_session.query(Company, DimCompanyPrice).\
                    join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                    filter(DimCompanyPrice.Date >= row.get('Date')).\
                    filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                    order_by(DimCompanyPrice.Date.desc()).\
                    first()
                # logger.info(query)
                price = query[1].CloseAdjusted
                shares = row['NumberShares']
                row['TotalPrice'] = float(price*shares)

                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance + abs(row.get('TotalPrice'))})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_sold_shares_email.delay(user_id, int(amount_shares_sold), sym)   
            else:
                logger.info('Not enough shares owned to complete the transaction')
                flash('Not enough shares owned to complete the transaction')
        else: # button 3: 'addFunds' add funds to your portfolio
            user_id = session.get('user_id')
            addFunds = float(request.form['addFunds'])
            if addFunds < 0:
                flash('Cannot add negative funds')
            else:    
                # check if PortfolioID exits
                balance_query = db_session.query(PortfolioBalance).\
                    filter(PortfolioBalance.PortfolioID == user_id).\
                    update({'Balance': PortfolioBalance.Balance + addFunds})
                db_session.commit()

    # Get Method
    row = {}
    payload={}
    user_id = session.get('user_id')
    chart_labels = []
    chart_data = []

    balance_query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
    payload['balance'] = balance_query.Balance

    chart_data.append(balance_query.Balance)
    chart_labels.append('Cash')

    # Total price and total number of shares
    payload['portfolio_cols'] = ['#','Symbol', 'Quantity', 'Total Cost', 'Current Balance', 'Return']
    try:
        query = db_session.query(Portfolio, func.sum(Portfolio.TotalPrice).label('TotalPrice'),\
                                 func.sum(Portfolio.NumberShares).label('TotalShares')).\
                                 filter(Portfolio.PortfolioID == user_id).\
                                 group_by(Portfolio.Symbol).\
                                 all()
        # logger.info(query)
    except OperationalError as e: # prevent error on empty portfolio
        pass
    else:
        # each symbol in the portfolio
        portfolio_list = []
        for row in query:
            _symbol = str(row[0].Symbol)
            chart_labels.append(_symbol)

            # current price for calculating the return
            cur_price_query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(Company.Symbol==_symbol).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()

            temp = {
                'Symbol': _symbol,
                'TotalCost': row.TotalPrice,
                'Quantity': row.TotalShares,
                'CurrentBalance': row.TotalShares*cur_price_query[1].CloseAdjusted,
                'CurrentPrice': cur_price_query[1].CloseAdjusted,
            }
            balance, cost = temp.get('CurrentBalance'), temp.get('TotalCost')
            _return = (balance-cost)/cost*100
            temp['Return'] = _return
            portfolio_list.append(temp)
            chart_data.append(balance)

        payload['portfolio'] = portfolio_list
        payload['chart_labels'] = chart_labels
        payload['chart_data'] = chart_data

        payload['table_cols'] = ['#','Date', 'Symbol', 'Quantity', 'Amount']

        buys = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares > 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        buys_list = []
        for row in buys:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            buys_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['buys'] = buys_list 

        sells = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares < 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        sells_list = []
        for row in sells:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            sells_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['sells'] = sells_list

    return render_template('dashboard/home.html', payload=payload, enumerate=enumerate)
# imports 
# ...

dashboard_blueprint = Blueprint('dashboard', __name__, url_prefix='/dashboard')

@dashboard_blueprint.route('/home', methods=('GET', 'POST'))
@login_required
def home():
    # dirty way of not using REST api to distinguish between buy/sell/add funds
    # use button key as quasi switch case
    # button 1: 'tickerBought' buys shares of a stock
    # button 2: 'tickerSold' sells shares of a stock
    # button 3: 'addFunds' add funds to your portfolio

    # button 1: 'tickerBought' buys shares of a stock
    if request.method == 'POST':
        f = request.form
        if 'tickerBought' in f.keys():
            user_id = session.get('user_id')
            row = {}
            row['PortfolioID']= session.get('user_id')
            row['Symbol']= request.form['tickerBought'].upper()
            row['NumberShares'] = float(request.form['amountSharesBought'])
            row['Date'] = date.fromisoformat(request.form['dateBought'])

            query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(DimCompanyPrice.Date <= row.get('Date')).\
                filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()
            logger.info(query)
            
            if query is None:
                flash('Price data not available for this transaction. Pick another date.')
            # check if there is enough avail balance to cover transaction
            price = query[1].CloseAdjusted
            shares = row['NumberShares']
            total_price = float(price*shares)
            sym = row['Symbol']

            query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
            
            balance = query.Balance
            if balance >= total_price:
                row['TotalPrice'] = total_price
                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance - total_price})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_bought_shares_email.delay(user_id, int(shares), sym)
            else:
                logger.info('Not enough available balance to complete the transaction')
                flash('Not enough available balance to complete the transaction')
        elif 'tickerSold' in f.keys(): # button 2: 'tickerSold' sells shares of a stock
            user_id = session.get('user_id')
            date_sold = date.fromisoformat(request.form['dateSold'])
            sym = request.form['tickerSold'].upper()
            amount_shares_sold = float(request.form['amountSharesSold'])
            
            q = db_session.query(Portfolio.Symbol, func.sum(Portfolio.NumberShares)).\
                filter(Portfolio.PortfolioID == user_id).\
                filter(Portfolio.Symbol == sym).\
                filter(Portfolio.Date <= date_sold).\
                all()
            
            if q[0][1] is None:
                flash('You do not own any shares to sell')
            elif q[0][1] >= amount_shares_sold:
                row = {}
                row['PortfolioID']= user_id
                row['Symbol']= sym
                row['NumberShares'] = -amount_shares_sold
                row['Date'] = date_sold

                query = db_session.query(Company, DimCompanyPrice).\
                    join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                    filter(DimCompanyPrice.Date >= row.get('Date')).\
                    filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                    order_by(DimCompanyPrice.Date.desc()).\
                    first()
                # logger.info(query)
                price = query[1].CloseAdjusted
                shares = row['NumberShares']
                row['TotalPrice'] = float(price*shares)

                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance + abs(row.get('TotalPrice'))})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_sold_shares_email.delay(user_id, int(amount_shares_sold), sym)   
            else:
                logger.info('Not enough shares owned to complete the transaction')
                flash('Not enough shares owned to complete the transaction')
        else: # button 3: 'addFunds' add funds to your portfolio
            user_id = session.get('user_id')
            addFunds = float(request.form['addFunds'])
            if addFunds < 0:
                flash('Cannot add negative funds')
            else:    
                # check if PortfolioID exits
                balance_query = db_session.query(PortfolioBalance).\
                    filter(PortfolioBalance.PortfolioID == user_id).\
                    update({'Balance': PortfolioBalance.Balance + addFunds})
                db_session.commit()

    # Get Method
    row = {}
    payload={}
    user_id = session.get('user_id')
    chart_labels = []
    chart_data = []

    balance_query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
    payload['balance'] = balance_query.Balance

    chart_data.append(balance_query.Balance)
    chart_labels.append('Cash')

    # Total price and total number of shares
    payload['portfolio_cols'] = ['#','Symbol', 'Quantity', 'Total Cost', 'Current Balance', 'Return']
    try:
        query = db_session.query(Portfolio, func.sum(Portfolio.TotalPrice).label('TotalPrice'),\
                                 func.sum(Portfolio.NumberShares).label('TotalShares')).\
                                 filter(Portfolio.PortfolioID == user_id).\
                                 group_by(Portfolio.Symbol).\
                                 all()
        # logger.info(query)
    except OperationalError as e: # prevent error on empty portfolio
        pass
    else:
        # each symbol in the portfolio
        portfolio_list = []
        for row in query:
            _symbol = str(row[0].Symbol)
            chart_labels.append(_symbol)

            # current price for calculating the return
            cur_price_query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(Company.Symbol==_symbol).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()

            temp = {
                'Symbol': _symbol,
                'TotalCost': row.TotalPrice,
                'Quantity': row.TotalShares,
                'CurrentBalance': row.TotalShares*cur_price_query[1].CloseAdjusted,
                'CurrentPrice': cur_price_query[1].CloseAdjusted,
            }
            balance, cost = temp.get('CurrentBalance'), temp.get('TotalCost')
            _return = (balance-cost)/cost*100
            temp['Return'] = _return
            portfolio_list.append(temp)
            chart_data.append(balance)

        payload['portfolio'] = portfolio_list
        payload['chart_labels'] = chart_labels
        payload['chart_data'] = chart_data

        payload['table_cols'] = ['#','Date', 'Symbol', 'Quantity', 'Amount']

        buys = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares > 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        buys_list = []
        for row in buys:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            buys_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['buys'] = buys_list 

        sells = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares < 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        sells_list = []
        for row in sells:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            sells_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['sells'] = sells_list

    return render_template('dashboard/home.html', payload=payload, enumerate=enumerate)

Am I stuck with this mess until I use a rest framework to send a function call based on the button clicked?

Edit: added import lines

from datetime import date
import json
import os
import re
import threading
import time

from bs4 import BeautifulSoup
import click
from flask import Blueprint, current_app
import requests
from requests.exceptions import HTTPError, Timeout
from sqlalchemy.exc import IntegrityError, SQLAlchemyError, StatementError
from werkzeug.security import check_password_hash, generate_password_hash


from project.crud import create_user, create_index, create_portfolio_balance, check_user_email
from project.database import Base, db_session, engine
from project.log import logger
from project.models import Company, DimCompanyInfo, Index, DimIndexPrice, DimCompanyPrice
from project.utils import row2dict

dashboard_blueprint = Blueprint('dashboard', __name__, url_prefix='/dashboard')

@dashboard_blueprint.route('/home', methods=('GET', 'POST'))
@login_required
def home():
    # dirty way of not using REST api to distinguish between buy/sell/add funds
    # use button key as quasi switch case
    # button 1: 'tickerBought' buys shares of a stock
    # button 2: 'tickerSold' sells shares of a stock
    # button 3: 'addFunds' add funds to your portfolio

    # button 1: 'tickerBought' buys shares of a stock
    if request.method == 'POST':
        f = request.form
        if 'tickerBought' in f.keys():
            user_id = session.get('user_id')
            row = {}
            row['PortfolioID']= session.get('user_id')
            row['Symbol']= request.form['tickerBought'].upper()
            row['NumberShares'] = float(request.form['amountSharesBought'])
            row['Date'] = date.fromisoformat(request.form['dateBought'])

            query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(DimCompanyPrice.Date <= row.get('Date')).\
                filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()
            logger.info(query)
            
            if query is None:
                flash('Price data not available for this transaction. Pick another date.')
            # check if there is enough avail balance to cover transaction
            price = query[1].CloseAdjusted
            shares = row['NumberShares']
            total_price = float(price*shares)
            sym = row['Symbol']

            query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
            
            balance = query.Balance
            if balance >= total_price:
                row['TotalPrice'] = total_price
                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance - total_price})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_bought_shares_email.delay(user_id, int(shares), sym)
            else:
                logger.info('Not enough available balance to complete the transaction')
                flash('Not enough available balance to complete the transaction')
        elif 'tickerSold' in f.keys(): # button 2: 'tickerSold' sells shares of a stock
            user_id = session.get('user_id')
            date_sold = date.fromisoformat(request.form['dateSold'])
            sym = request.form['tickerSold'].upper()
            amount_shares_sold = float(request.form['amountSharesSold'])
            
            q = db_session.query(Portfolio.Symbol, func.sum(Portfolio.NumberShares)).\
                filter(Portfolio.PortfolioID == user_id).\
                filter(Portfolio.Symbol == sym).\
                filter(Portfolio.Date <= date_sold).\
                all()
            
            if q[0][1] is None:
                flash('You do not own any shares to sell')
            elif q[0][1] >= amount_shares_sold:
                row = {}
                row['PortfolioID']= user_id
                row['Symbol']= sym
                row['NumberShares'] = -amount_shares_sold
                row['Date'] = date_sold

                query = db_session.query(Company, DimCompanyPrice).\
                    join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                    filter(DimCompanyPrice.Date >= row.get('Date')).\
                    filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                    order_by(DimCompanyPrice.Date.desc()).\
                    first()
                # logger.info(query)
                price = query[1].CloseAdjusted
                shares = row['NumberShares']
                row['TotalPrice'] = float(price*shares)

                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance + abs(row.get('TotalPrice'))})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_sold_shares_email.delay(user_id, int(amount_shares_sold), sym)   
            else:
                logger.info('Not enough shares owned to complete the transaction')
                flash('Not enough shares owned to complete the transaction')
        else: # button 3: 'addFunds' add funds to your portfolio
            user_id = session.get('user_id')
            addFunds = float(request.form['addFunds'])
            if addFunds < 0:
                flash('Cannot add negative funds')
            else:    
                # check if PortfolioID exits
                balance_query = db_session.query(PortfolioBalance).\
                    filter(PortfolioBalance.PortfolioID == user_id).\
                    update({'Balance': PortfolioBalance.Balance + addFunds})
                db_session.commit()

    # Get Method
    row = {}
    payload={}
    user_id = session.get('user_id')
    chart_labels = []
    chart_data = []

    balance_query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
    payload['balance'] = balance_query.Balance

    chart_data.append(balance_query.Balance)
    chart_labels.append('Cash')

    # Total price and total number of shares
    payload['portfolio_cols'] = ['#','Symbol', 'Quantity', 'Total Cost', 'Current Balance', 'Return']
    try:
        query = db_session.query(Portfolio, func.sum(Portfolio.TotalPrice).label('TotalPrice'),\
                                 func.sum(Portfolio.NumberShares).label('TotalShares')).\
                                 filter(Portfolio.PortfolioID == user_id).\
                                 group_by(Portfolio.Symbol).\
                                 all()
        # logger.info(query)
    except OperationalError as e: # prevent error on empty portfolio
        pass
    else:
        # each symbol in the portfolio
        portfolio_list = []
        for row in query:
            _symbol = str(row[0].Symbol)
            chart_labels.append(_symbol)

            # current price for calculating the return
            cur_price_query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(Company.Symbol==_symbol).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()

            temp = {
                'Symbol': _symbol,
                'TotalCost': row.TotalPrice,
                'Quantity': row.TotalShares,
                'CurrentBalance': row.TotalShares*cur_price_query[1].CloseAdjusted,
                'CurrentPrice': cur_price_query[1].CloseAdjusted,
            }
            balance, cost = temp.get('CurrentBalance'), temp.get('TotalCost')
            _return = (balance-cost)/cost*100
            temp['Return'] = _return
            portfolio_list.append(temp)
            chart_data.append(balance)

        payload['portfolio'] = portfolio_list
        payload['chart_labels'] = chart_labels
        payload['chart_data'] = chart_data

        payload['table_cols'] = ['#','Date', 'Symbol', 'Quantity', 'Amount']

        buys = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares > 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        buys_list = []
        for row in buys:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            buys_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['buys'] = buys_list 

        sells = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares < 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        sells_list = []
        for row in sells:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            sells_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['sells'] = sells_list

    return render_template('dashboard/home.html', payload=payload, enumerate=enumerate)
Source Link
sat1017
  • 141
  • 2

How to remove nested conditionals inside flask static url view

The code runs fine and was manageable without any error handling.

Once I started to handle errors and build out the code the if/elif/else branches quickly became too much. How can I route the view function conditionally based on the button that sent the request without all the conditionals? I tried refactoring the get code into a helper function that could be called within the home() function but I ran into a flask 'return None' error. There has to be a better design pattern than this mess of if statements.

This is my first code review but there have to be many ways to improve this code. Please don't hold back.

# imports 
# ...

dashboard_blueprint = Blueprint('dashboard', __name__, url_prefix='/dashboard')

@dashboard_blueprint.route('/home', methods=('GET', 'POST'))
@login_required
def home():
    # dirty way of not using REST api to distinguish between buy/sell/add funds
    # use button key as quasi switch case
    # button 1: 'tickerBought' buys shares of a stock
    # button 2: 'tickerSold' sells shares of a stock
    # button 3: 'addFunds' add funds to your portfolio

    # button 1: 'tickerBought' buys shares of a stock
    if request.method == 'POST':
        f = request.form
        if 'tickerBought' in f.keys():
            user_id = session.get('user_id')
            row = {}
            row['PortfolioID']= session.get('user_id')
            row['Symbol']= request.form['tickerBought'].upper()
            row['NumberShares'] = float(request.form['amountSharesBought'])
            row['Date'] = date.fromisoformat(request.form['dateBought'])

            query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(DimCompanyPrice.Date <= row.get('Date')).\
                filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()
            logger.info(query)
            
            if query is None:
                flash('Price data not available for this transaction. Pick another date.')
            # check if there is enough avail balance to cover transaction
            price = query[1].CloseAdjusted
            shares = row['NumberShares']
            total_price = float(price*shares)
            sym = row['Symbol']

            query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
            
            balance = query.Balance
            if balance >= total_price:
                row['TotalPrice'] = total_price
                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance - total_price})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_bought_shares_email.delay(user_id, int(shares), sym)
            else:
                logger.info('Not enough available balance to complete the transaction')
                flash('Not enough available balance to complete the transaction')
        elif 'tickerSold' in f.keys(): # button 2: 'tickerSold' sells shares of a stock
            user_id = session.get('user_id')
            date_sold = date.fromisoformat(request.form['dateSold'])
            sym = request.form['tickerSold'].upper()
            amount_shares_sold = float(request.form['amountSharesSold'])
            
            q = db_session.query(Portfolio.Symbol, func.sum(Portfolio.NumberShares)).\
                filter(Portfolio.PortfolioID == user_id).\
                filter(Portfolio.Symbol == sym).\
                filter(Portfolio.Date <= date_sold).\
                all()
            
            if q[0][1] is None:
                flash('You do not own any shares to sell')
            elif q[0][1] >= amount_shares_sold:
                row = {}
                row['PortfolioID']= user_id
                row['Symbol']= sym
                row['NumberShares'] = -amount_shares_sold
                row['Date'] = date_sold

                query = db_session.query(Company, DimCompanyPrice).\
                    join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                    filter(DimCompanyPrice.Date >= row.get('Date')).\
                    filter(Company.Symbol == str.upper(row.get('Symbol'))).\
                    order_by(DimCompanyPrice.Date.desc()).\
                    first()
                # logger.info(query)
                price = query[1].CloseAdjusted
                shares = row['NumberShares']
                row['TotalPrice'] = float(price*shares)

                _row = Portfolio(**row)
                try:
                    db_session.add(_row)
                    db_session.commit()
                    logger.info('commited')
                except StatementError as e:
                    logger.info(f'{e} error')
                try:
                    balance_query = db_session.query(PortfolioBalance).\
                        filter(PortfolioBalance.PortfolioID == user_id).\
                        update({'Balance': PortfolioBalance.Balance + abs(row.get('TotalPrice'))})
                    db_session.commit()
                    logger.info('balance updated')
                except StatementError as e:
                    logger.info(f'{e} error')

                # create celery task to send a transaction email
                send_sold_shares_email.delay(user_id, int(amount_shares_sold), sym)   
            else:
                logger.info('Not enough shares owned to complete the transaction')
                flash('Not enough shares owned to complete the transaction')
        else: # button 3: 'addFunds' add funds to your portfolio
            user_id = session.get('user_id')
            addFunds = float(request.form['addFunds'])
            if addFunds < 0:
                flash('Cannot add negative funds')
            else:    
                # check if PortfolioID exits
                balance_query = db_session.query(PortfolioBalance).\
                    filter(PortfolioBalance.PortfolioID == user_id).\
                    update({'Balance': PortfolioBalance.Balance + addFunds})
                db_session.commit()

    # Get Method
    row = {}
    payload={}
    user_id = session.get('user_id')
    chart_labels = []
    chart_data = []

    balance_query = db_session.query(PortfolioBalance).\
                filter(PortfolioBalance.PortfolioID == user_id).\
                first()
    payload['balance'] = balance_query.Balance

    chart_data.append(balance_query.Balance)
    chart_labels.append('Cash')

    # Total price and total number of shares
    payload['portfolio_cols'] = ['#','Symbol', 'Quantity', 'Total Cost', 'Current Balance', 'Return']
    try:
        query = db_session.query(Portfolio, func.sum(Portfolio.TotalPrice).label('TotalPrice'),\
                                 func.sum(Portfolio.NumberShares).label('TotalShares')).\
                                 filter(Portfolio.PortfolioID == user_id).\
                                 group_by(Portfolio.Symbol).\
                                 all()
        # logger.info(query)
    except OperationalError as e: # prevent error on empty portfolio
        pass
    else:
        # each symbol in the portfolio
        portfolio_list = []
        for row in query:
            _symbol = str(row[0].Symbol)
            chart_labels.append(_symbol)

            # current price for calculating the return
            cur_price_query = db_session.query(Company, DimCompanyPrice).\
                join(DimCompanyPrice, Company.ID == DimCompanyPrice.CompanyID).\
                filter(Company.Symbol==_symbol).\
                order_by(DimCompanyPrice.Date.desc()).\
                first()

            temp = {
                'Symbol': _symbol,
                'TotalCost': row.TotalPrice,
                'Quantity': row.TotalShares,
                'CurrentBalance': row.TotalShares*cur_price_query[1].CloseAdjusted,
                'CurrentPrice': cur_price_query[1].CloseAdjusted,
            }
            balance, cost = temp.get('CurrentBalance'), temp.get('TotalCost')
            _return = (balance-cost)/cost*100
            temp['Return'] = _return
            portfolio_list.append(temp)
            chart_data.append(balance)

        payload['portfolio'] = portfolio_list
        payload['chart_labels'] = chart_labels
        payload['chart_data'] = chart_data

        payload['table_cols'] = ['#','Date', 'Symbol', 'Quantity', 'Amount']

        buys = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares > 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        buys_list = []
        for row in buys:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            buys_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['buys'] = buys_list 

        sells = db_session.query(Portfolio).\
            filter(Portfolio.PortfolioID == user_id).\
            filter(Portfolio.NumberShares < 0).\
            order_by(Portfolio.Date.desc()).\
            all()

        sells_list = []
        for row in sells:
            temp = {'Date': row.Date,
                    'Symbol': row.Symbol,
                    'Quantity': row.NumberShares,
                    'Amount': row.TotalPrice
            }
            sells_list.append(temp)
            # logger.info('{} {} {}'.format(row.Symbol, row.NumberShares, row.Date))
        payload['sells'] = sells_list

    return render_template('dashboard/home.html', payload=payload, enumerate=enumerate)