Example #1
0
def category_edit(cid):
    category_object = Category()

    if request.method == 'GET':
        try:
            category = category_object.fetch_one_by_id(cid)

            commit_database()
            return render_template('setting/edit/edit_category.html',
                                   category=category)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('setting.category_view', cid=cid))

    cat_name = request.form.get('name', '')
    if not cat_name.strip():
        flash('No Category name!', 'error')
        return redirect(url_for('setting.category_view', cid=cid))

    category_object.name = cat_name
    category_object.id = cid
    try:
        category_object.update_category()
        flash('Category updated!', 'success')

        commit_database()
    except Exception as e:
        flash(e, 'error')

        rollback_database()

    return redirect(url_for('setting.category_view', cid=cid))
Example #2
0
def degree_edit(degree_id):
    degree_object = Degree()
    degree_object.id = degree_id

    if request.method == 'GET':
        try:
            degree = degree_object.fetch_one_by_id(degree_id)

            commit_database()
            return render_template('setting/edit/edit_degree.html',
                                   degree=degree)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('setting.degree_view',
                                    degree_id=degree_id))

    try:
        degree_object.name = request.form.get('name', '')
        degree_object.update_degree()
        flash('Degree got updated!', 'success')

        commit_database()
    except Exception as e:
        flash(e, 'error')

        rollback_database()

    return redirect(url_for('setting.degree_view', degree_id=degree_id))
Example #3
0
def sub_category_edit(sid):
    sub_category_object = SubCategory()

    if request.method == 'GET':
        try:
            sub_category = sub_category_object.fetch_one_by_id(sid)
            categories = Category().fetch_all_in_order()
            cards = Card().fetch_all_in_order(order='bank, name')
            degrees = Degree().fetch_all_in_order(order='id')

            commit_database()
            return render_template('setting/edit/edit_subcategory.html',
                                   sub_category=sub_category,
                                   category=categories,
                                   cards=cards,
                                   degrees=degrees)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('setting.sub_category_view', sid=sid))

    try:
        sub_category_object.load_a_sub_category(request.form)
        sub_category_object.id = sid
        sub_category_object.update_sub_category()

        flash('Sub-category updated!', 'success')

        commit_database()
    except Exception as e:
        flash(e, 'error')
        rollback_database()

    return redirect(url_for('setting.sub_category_view', sid=sid))
Example #4
0
def spending_edit(spending_id):
    category_object = Category()
    sub_category_object = SubCategory()
    card_object = Card()
    degree_object = Degree()
    spending_object = Spending()
    spending_object.id = spending_id

    if request.method == 'GET':
        try:
            categories = category_object.fetch_all_in_order()
            sub_categories = sub_category_object.fetch_all_in_order()
            cards = card_object.fetch_all_in_order(order='bank, name')
            degrees = degree_object.fetch_all_in_order()
            spending = spending_object.fetch_one_by_id(spending_id)
            date = '/'.join([
                str(spending['mon']),
                str(spending['daynum']),
                str(spending['yr'])
            ])
            settings = {
                'cats': categories,
                'subCats': sub_categories,
                'cards': cards,
                'degrees': degrees
            }

            commit_database()
            return render_template('spending/edit_spending.html',
                                   settings=settings,
                                   spending=spending,
                                   date=date)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('report.view_all_spending'))

    spending_object.load_spending_values(request)
    spending_object.category = sub_category_object.fetch_one_by_id(
        spending_object.sub_category)['c_id']

    try:
        balance = card_object.fetch_one_by_id(
            spending_object.card)['cur_balance']
        balance += spending_object.amount
        card_object.id = spending_object.card
        card_object.cur_balance = balance

        spending_object.update_a_spending()
        card_object.update_card_balance()

        commit_database()
        flash('Spending has been updated!', 'success')
    except Exception as e:
        flash(e, 'error')

        rollback_database()
    finally:
        return redirect(url_for('report.view_all_spending'))
Example #5
0
def sub_category_add(cid):
    if request.method == 'GET':
        try:
            category = Category().fetch_one_by_id(cid)
            cards = Card().fetch_all_in_order(order='bank, name')
            degrees = Degree().fetch_all_in_order(order='id')

            commit_database()
            return render_template('setting/add_subcategory.html',
                                   category=category,
                                   cards=cards,
                                   degrees=degrees)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('setting.catalog'))

    sub_category_object = SubCategory()

    try:
        sub_category_object.load_a_sub_category(request.form)
        sub_category_object.add_a_sub_category()

        flash('Sub-category added!', 'success')
        commit_database()
    except Exception as e:
        flash(e, 'error')
        rollback_database()

    return redirect(url_for('setting.catalog'))
Example #6
0
def card_edit(card_id):
    card_object = Card()
    card_object.id = card_id
    if request.method == 'GET':
        try:
            card = card_object.fetch_one_by_id(card_id)

            commit_database()
            return render_template('setting/edit/edit_card.html', card=card)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('setting.card_view', card_id=card_id))

    try:
        card_object.load_a_card(request.form)
        card_object.update_card_information()
        flash('Card information updated!', 'success')

        commit_database()

    except Exception as e:
        flash(e, 'error')
        rollback_database()

    return redirect(url_for('setting.card_view', card_id=card_id))
Example #7
0
def spending_add_from_card(card_id):
    category_object = Category()
    sub_category_object = SubCategory()
    card_object = Card()
    degree_object = Degree()
    spending_object = Spending()

    if request.method == 'GET':
        try:
            categories = category_object.fetch_all_in_order()
            sub_categories = sub_category_object.fetch_all_in_order()
            degrees = degree_object.fetch_all_in_order(order='id')
            card_info = card_object.fetch_one_by_id(card_id)
            settings = {
                'cats': categories,
                'subCats': sub_categories,
                'card': card_info,
                'degrees': degrees
            }

            commit_database()
            return render_template('spending/add_card_spending.html',
                                   settings=settings)
        except Exception as e:
            flash(e, 'error')

            rollback_database()
            return redirect(url_for('index.index'))

    spending_object.load_spending_values(request)
    spending_object.category = sub_category_object.fetch_one_by_id(
        spending_object.sub_category)['c_id']
    mode = request.form.get('mode', 'com')

    try:
        balance = card_object.fetch_one_by_id(
            spending_object.card)['cur_balance']
        balance += spending_object.amount
        card_object.id = spending_object.card
        card_object.cur_balance = balance

        spending_object.add_a_spending()
        card_object.update_card_balance()

        commit_database()
        flash('A spending has been added!', 'success')
    except Exception as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('index.index'))

    if mode == 'com':  # Add and Complete
        return redirect(url_for('index.index'))
    elif mode == 'aaa':  # Add and Another
        return redirect(
            url_for('spending.spending_add_from_card', card_id=card_id))
Example #8
0
def index():
    try:
        cards = Card().fetch_all_in_order(order='bank, name')
    except Exception as e:
        flash(e, 'error')
        cards = []

    commit_database()
    return render_template('index.html', cards=cards)
Example #9
0
def card_view(card_id):
    try:
        card = Card().fetch_one_by_id(card_id)

        commit_database()
        return render_template('setting/view/view_card.html', card=card)
    except Exception as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('setting.catalog'))
Example #10
0
def degree_view(degree_id):
    try:
        degree = Degree().fetch_one_by_id(degree_id)

        commit_database()
        return render_template('setting/view/view_degree.html', degree=degree)
    except Exception as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('setting.catalog'))
Example #11
0
def card_add():
    if request.method == 'GET':
        return render_template('setting/add_card.html')

    card_object = Card()
    try:
        card_object.load_a_card(request.form)
        card_object.add_a_new_card()
        flash('A new card added!', 'success')

        commit_database()
    except Exception as e:
        flash(e, 'error')

        rollback_database()

    return redirect(url_for('setting.catalog'))
Example #12
0
def sub_category_view(sid):
    try:
        sub_category = SubCategory().fetch_one_by_id(sid)
        sub_cat_dict = dict(sub_category)
        sub_cat_dict['c_name'] = Category().fetch_one_by_id(
            sub_category['c_id'])['name']
        sub_cat_dict['default_card'] = Card().get_a_card_name(
            sub_category['default_card'])
        sub_cat_dict['default_degree'] = Degree().get_a_degree_name(
            sub_category['default_degree'])

        commit_database()
        return render_template('setting/view/view_subcategory.html',
                               sub_category=sub_cat_dict)
    except Exception as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('setting.catalog'))
Example #13
0
def degree_add():
    if request.method == 'GET':
        return render_template('setting/add_degree.html')

    degree_object = Degree()
    degree_object.name = request.form.get('name', '')
    if not degree_object.name.strip():
        flash('No Degree name!', 'error')
        return redirect(url_for('setting.catalog'))

    try:
        degree_object.add_a_degree()
        flash('A new degree added!', 'success')

        commit_database()
    except Exception as e:
        flash(e, 'error')

        rollback_database()

    return redirect(url_for('setting.catalog'))
Example #14
0
def catalog():
    try:
        categories = Category().fetch_all_in_order()
        sub_categories = SubCategory().fetch_all_in_order()
        cards = Card().fetch_all_in_order(order='bank, name')
        degrees = Degree().fetch_all_in_order(order='id')

        settings = {
            'cat': categories,
            'sub': sub_categories,
            'card': cards,
            'degree': degrees
        }

        commit_database()
        return render_template('setting/catalog.html', settings=settings)
    except Exception as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('index.index'))
Example #15
0
def category_add():
    if request.method == 'GET':
        return render_template('setting/add_category.html')

    cat_name = request.form.get('name', '')
    if not cat_name.strip():
        flash('No Category name!', 'error')
        return redirect(url_for('setting.catalog'))

    category_object = Category()
    category_object.name = cat_name
    try:
        category_object.add_a_category()
        flash('Category added!', 'success')

        commit_database()

    except Exception as e:
        flash(e, 'error')

        rollback_database()

    return redirect(url_for('setting.catalog'))
Example #16
0
def save_statement_data():
    sub_category_object = SubCategory()
    card_object = Card()

    # initiate the transaction counts and valid transactions with the count of transactions and 0
    transaction_counts, valid_transactions = int(request.form.get('count',
                                                                  0)), 0
    # get the card name from the form
    card_name = request.form.get('card', '')
    statement_name = request.form.get('filename', '')
    # then get the card database entry by the card name
    card = card_object.fetch_one_card_by_name(card_name)
    total_amount = card['cur_balance']
    # get the preset from form, which is in json format, and converted into dictionary using ast.literal_eval()
    preset = ast.literal_eval(request.form.get('preset', ''))

    try:
        # loop through all the transactions
        for index in range(transaction_counts):
            # if this transaction is not excluded, then save the transaction into database
            if request.form.get(f'exclude{index + 1}', 'False') == 'False':
                spending = Spending()
                # Compose each single transaction's detail by getting those information by the index

                spending.name = request.form.get(f'name{index + 1}', 'N/A')
                spending.sub_category = request.form.get(
                    f'category{index + 1}', -1)
                spending.amount = request.form.get(f'amount{index + 1}', 0)
                spending.card = card.id
                spending.degree = request.form.get(f'degree{index + 1}', -1)
                spending.comments = request.form.get(f'note{index + 1}', '')
                date = request.form.get(f'date{index + 1}', '01/01/1960')

                # get the sub_category object from database using the sub_category_id
                spending.category = sub_category_object.fetch_one_by_id(
                    spending.sub_category)['c_id']
                # match the date information from transaction using regular expression
                # by doing so, I can get the year, month and day using the position of the date_match
                date_match = re.fullmatch(
                    r"([0-9]{1,2})/([0-9]{1,2})/([0-9]{2,4})", date)
                spending.yr = int(date_match.group(3))
                spending.mon = int(date_match.group(1))
                spending.daynum = int(date_match.group(2))

                spending.add_a_spending()

                # increase the valid transaction number
                valid_transactions += 1
                total_amount += float(spending.amount)
                # if the transaction is not already in the preset,
                # then save the transaction into the preset dictionary.
                if spending.name not in preset:
                    preset[spending.name] = {
                        'name': spending.name,
                        'category': spending.sub_category,
                        'degree': spending.degree
                    }

        card_object.id = card.id
        card_object.cur_balance = total_amount
        card_object.last_statement = statement_name

        card_object.update_card_statement_information()
        # Update card information
        # db.execute(
        #     'UPDATE cards SET last_statement = ?, cur_balance = ?'
        #     ' WHERE id = ?',
        #     (statement_name, total_amount, card['id'])
        # )
        # Then commit the database after all transactions are saved

        # save the preset back to the preset file, if the preset is not empty
        if preset:
            if card_name in ('Freedom - Chase', 'Unlimited - Chase',
                             'Sapphire - Chase'):
                transaction_preset = os.path.join(
                    current_app.config['PRELOAD_FOLDER'],
                    'chase_credit_' + current_app.config['PRESET_FILE_NAME'])
            elif card == 'Checking - Chase':
                transaction_preset = os.path.join(
                    current_app.config['PRELOAD_FOLDER'],
                    'chase_checking_' + current_app.config['PRESET_FILE_NAME'])
            elif card == 'Apple - Goldman Sachs':
                transaction_preset = os.path.join(
                    current_app.config['PRELOAD_FOLDER'],
                    'apple_' + current_app.config['PRESET_FILE_NAME'])
            elif card in ('AA - Citi', 'Costco - Citi',
                          'Double Cash Back - Citi'):
                transaction_preset = os.path.join(
                    current_app.config['PRELOAD_FOLDER'],
                    'citi_' + current_app.config['PRESET_FILE_NAME'])
            else:
                transaction_preset = os.path.join(
                    current_app.config['PRELOAD_FOLDER'],
                    current_app.config['PRESET_FILE_NAME'])

            # get a list of the keys of preset dictionary, which are the saved transaction name
            sample_entrys = list(preset.keys())
            # create an empty list to hold all the transactions in dictionary format
            # and save each transaction into the list
            dict_list = []
            for entry in sample_entrys:
                dict_list.append(preset[entry])
            # Then get the keys from a single transaction, which will be the header of the preset csv file
            keys = preset[sample_entrys[0]].keys()

            # Open the preset csv files in the writing mode, and save the list of dictionary into the csv,
            # with the keys as header
            with open(transaction_preset, 'w+', newline='') as output_file:
                dict_writer = csv.DictWriter(output_file, keys)
                dict_writer.writeheader()
                dict_writer.writerows(dict_list)

        # Flash the successful message to the screen
        flash(f'{valid_transactions} spendings are added!', 'success')
        # and return to the report page of that card

        commit_database()
        return redirect(url_for('report.add_spending_card',
                                card_id=card['id']))
    # If any exception raised, flash the error message and rollback the database and return to the index page.
    except TypeError as e:
        flash(e, 'error')

        rollback_database()
        return redirect(url_for('index.index'))
Example #17
0
def spending_add_from_statement():
    # Check if there is file received from the form
    # If there is not, then return to the index page; otherwise, continue
    if 'statement_pdf' not in request.files:
        flash('No file part')
        return redirect(url_for('index.index'))
    # Get the card information from the form
    card = request.form['card']
    # get the actual file object from the form
    file = request.files['statement_pdf']
    # If there is no filename, then return to the index page
    if file.filename == '':
        flash('No selected file')
        return redirect(url_for('index.index'))

    # get the filename from the file object
    filename = secure_filename(file.filename)
    # compose the /path_to_statement/filename by adding the CONSTANTS from the application
    path_to_statement = os.path.join(
        current_app.config['UPLOAD_STATEMENT_FOLDER'], filename)
    # save the file to the temporary directory, which will be deleted later
    file.save(path_to_statement)

    # create an empty list for the content of pdf files
    inputs = []
    # extract information from the statements of different cards,
    # and generate the path to the preset according to differnet card
    if card in ('Freedom - Chase', 'Unlimited - Chase', 'Sapphire - Chase'):
        inputs = read_pdf_statement_chase(path_to_statement, 'chase_credit')

        transaction_preset = os.path.join(
            current_app.config['PRELOAD_FOLDER'],
            'chase_credit_' + current_app.config['PRESET_FILE_NAME'])
    elif card == 'Checking - Chase':
        inputs = read_pdf_statement_chase(path_to_statement, 'chase_checking')

        transaction_preset = os.path.join(
            current_app.config['PRELOAD_FOLDER'],
            'chase_checking_' + current_app.config['PRESET_FILE_NAME'])
    elif card == 'Apple - Goldman Sachs':
        inputs = read_apple_csv_transactions(path_to_statement)

        transaction_preset = os.path.join(
            current_app.config['PRELOAD_FOLDER'],
            'apple_' + current_app.config['PRESET_FILE_NAME'])
    elif card in ('AA - Citi', 'Costco - Citi', 'Double Cash Back - Citi'):
        inputs = read_pdf_statement_citi(path_to_statement, 'citi')

        transaction_preset = os.path.join(
            current_app.config['PRELOAD_FOLDER'],
            'citi_' + current_app.config['PRESET_FILE_NAME'])
    else:
        transaction_preset = os.path.join(
            current_app.config['PRELOAD_FOLDER'],
            current_app.config['PRESET_FILE_NAME'])

    # open the 'preset' csv file, and read the contents into a dictionary,
    # whose key is name of each transaction, and value would be another dictionary,
    # whose keys are name, category and degree, whose value are the value from each transaction
    try:
        with open(transaction_preset, 'r') as csv_file:
            preset = {
                row['name']: {k: v
                              for k, v in row.items()}
                for row in csv.DictReader(csv_file, skipinitialspace=True)
            }
    except FileNotFoundError:
        with open('temp/preload/transaction_preset.csv', 'r') as csv_file:
            preset = {
                row['name']: {k: v
                              for k, v in row.items()}
                for row in csv.DictReader(csv_file, skipinitialspace=True)
            }

    # def generate():
    #     with open(path) as f:
    #         yield from f
    #
    #     os.remove(path)

    # After reading and extracting the context from the pdf statements,
    # delete the pdf files saved in the temporary directory
    os.remove(path_to_statement)

    # getting those basic information from the database
    category_object = Category()
    sub_category_object = SubCategory()
    degree_object = Degree()

    categories = category_object.fetch_all_in_order()
    sub_categories = sub_category_object.fetch_all_in_order()
    degrees = degree_object.fetch_all_in_order(order='id')
    settings = {
        'cats': categories,
        'subCats': sub_categories,
        'degrees': degrees
    }
    subcat_degree_map = {
        sub_category['id']: sub_category['default_degree']
        for sub_category in sub_categories
    }

    commit_database()

    # Then pass the pdf contents, preset configuration and basic information into the template
    return render_template('spending/add_spending_from_statement.html',
                           card=card,
                           inputs=inputs,
                           settings=settings,
                           preset=preset,
                           filename=filename,
                           subcat_degree_map=json.dumps(subcat_degree_map))