Exemple #1
0
def load_total() -> pd.DataFrame:
    log.info('Loading TOTAL file')

    result = pd.read_csv(config.mankkoo_file_path('total'),
                         parse_dates=['Date'])
    result = result.astype({'Date': 'datetime64[ns]', 'Total': 'float'})
    result['Date'] = result['Date'].dt.date
    return result
Exemple #2
0
def load_stocks() -> pd.DataFrame:
    log.info('Loading STOCK file')

    result = pd.read_csv(config.mankkoo_file_path('stock'),
                         parse_dates=['Date'])
    result = result.astype({'Total Value': 'float', 'Date': 'datetime64[ns]'})
    result['Date'] = result['Date'].dt.date
    return result
Exemple #3
0
def update_output(list_of_contents, list_of_names, list_of_dates, bank_id, account_name, account_type):
    if list_of_contents is not None:
        try:
            account.add_new_operations(models.Bank[bank_id], account_name, contents=list_of_contents, account_tye=models.Account(account_type))
            return 'success'
        except Exception as ex:
            log.info(f'Error occured: {ex}')
            return 'failure'
Exemple #4
0
def load_global_config() -> dict:
    """Load global configuration from /data folder

    Returns:
        dict: global specific config from config.yaml file
    """
    log.info(f"Loading global {config_file} file")
    with open(data_path() + config_file) as c:
        return yaml.safe_load(c)
Exemple #5
0
def load_user_config() -> dict:
    """Load user configuration from .mankkoo directory

    Returns:
        dict: user specific config from config.yaml file
    """
    log.info(f"Loading user {config_file} file")
    with open(mankkoo_path() + __slash() + config_file, 'r',
              encoding='utf-8') as c:
        return yaml.safe_load(c)
Exemple #6
0
def __latest_balance_for_account(df: pd.DataFrame, account_name: str):

    result = df.loc[(df['Account'] == account_name)]
    result = result.dropna(subset=['Balance'])
    try:
        return result.iloc[-1]['Balance']
    except IndexError:
        log.info(
            'There are no latest balance for %s account. Therefore assuming 0.',
            account_name)
        return 0
Exemple #7
0
def total_money_data(data: dict) -> pd.DataFrame:
    """Get summary data of all assets sorted by categories

    Args:
        data (dict): dictionary with all financial data

    Returns:
        pd.DataFrame: grouped financial standings
    """

    log.info('Fetching latest total money data')
    checking_account = __latest_account_balance(data, 'checking')
    savings_account = __latest_account_balance(data, 'savings')
    cash = __latest_account_balance(data, 'cash')
    ppk = __latest_account_balance(data, 'retirement')

    inv = data['investment'].loc[data['investment']['Active'] == True]
    inv = inv['Start Amount'].sum()

    stock_buy = data['stock'].loc[data['stock']['Operation'] == 'Buy']
    stock_buy = stock_buy['Total Value'].sum()
    stock_sell = data['stock'].loc[data['stock']['Operation'] == 'Sell']
    stock_sell = stock_sell['Total Value'].sum()
    stock = stock_buy - stock_sell
    # TODO check how much stock units I have Broker-Title pair buy-sell
    total = checking_account + savings_account + cash + ppk + inv + stock

    return pd.DataFrame([{
        'Type': 'Checking Account',
        'Total': checking_account,
        'Percentage': checking_account / total
    }, {
        'Type': 'Savings Account',
        'Total': savings_account,
        'Percentage': savings_account / total
    }, {
        'Type': 'Cash',
        'Total': cash,
        'Percentage': cash / total
    }, {
        'Type': 'PPK',
        'Total': ppk,
        'Percentage': ppk / total
    }, {
        'Type': 'Investments',
        'Total': inv,
        'Percentage': inv / total
    }, {
        'Type': 'Stocks',
        'Total': stock,
        'Percentage': stock / total
    }])
Exemple #8
0
def load_all() -> dict:
    """Load aggregated data of all financial data (accounts, investments, etc.)

    Returns:
        dict(pandas.DataFrame): a dictonary with categorized financial data
    """
    log.info("Loading mankkoo's files")

    return dict(account=load_accounts(),
                investment=load_investments(),
                stock=load_stocks(),
                total=load_total(),
                total_monthly=load_total_monthly())
Exemple #9
0
def load_total_monthly() -> pd.DataFrame:
    log.info('Loading TOTAL MONTHLY file')

    result = pd.read_csv(config.mankkoo_file_path('total_monthly'),
                         parse_dates=['Date'])
    result = result.astype({
        'Date': 'datetime64[ns]',
        'Income': 'float',
        'Spending': 'float',
        'Profit': 'float'
    })
    result['Date'] = result['Date'].dt.date
    return result
Exemple #10
0
def load_accounts() -> pd.DataFrame:
    log.info('Loading ACCOUNT file')

    result = pd.read_csv(config.mankkoo_file_path('account'),
                         parse_dates=['Date'],
                         index_col=0)
    result = result.astype({
        'Account': 'string',
        'Balance': 'float',
        'Operation': 'float',
        'Date': 'datetime64[ns]'
    })
    result['Date'] = result['Date'].dt.date
    return result
Exemple #11
0
def load_investments() -> pd.DataFrame:
    log.info('Loading INVESTMENT file')

    result = pd.read_csv(config.mankkoo_file_path('investment'),
                         parse_dates=['Start Date', 'End Date'])
    result = result.astype({
        'Active': 'int',
        'Start Amount': 'float',
        'End amount': 'float',
        'Start Date': 'datetime64[ns]',
        'End Date': 'datetime64[ns]'
    })
    result.Active = result.Active.astype('bool')
    result['Start Date'] = result['Start Date'].dt.date
    result['End Date'] = result['End Date'].dt.date
    return result
Exemple #12
0
def add_new_operations(bank: models.Bank,
                       account_name: str,
                       file_name=None,
                       contents=None,
                       account_tye=models.Account.CHECKING) -> pd.DataFrame:
    """Append bank accounts history with new operations. 
    This method return a pandas DataFrame with calculated balance.

    Args:
        bank (importer.Bank): enum of a bank company
        file_name (str): name of a file from which data will be loaded

    Raises:
        KeyError: raised when unsupported bank enum is provided

    Returns:
        pandas.DataFrame: DataFrame that holds transactions history with newly added operations
    """
    log.info('Adding new operations for %s account in %s bank', account_name,
             bank)
    df_new = importer.load_bank_data(file_name, contents, bank, account_name)
    df_new['Type'] = account_tye.value
    df = db.load_accounts()
    __make_account_backup(df)

    df = pd.concat([df, df_new]).reset_index(drop=True)
    df = df.sort_values(by=['Date', 'Bank', 'Account'])
    df = df.reset_index(drop=True)
    df = calculate_balance(df, account_name)
    df.to_csv(config.mankkoo_file_path('account'),
              index=True,
              index_label='Row')

    total.update_total_money(df, df_new['Date'].min())
    total.update_monthly_profit(from_date=df_new['Date'].min(), force=True)
    log.info('%d new operations for %s account were added.',
             df_new['Bank'].size, account_name)
    return df
Exemple #13
0
def update_total_money(
    accounts: pd.DataFrame,
    from_date: datetime.date,
    till_date=datetime.date.today()) -> pd.DataFrame:
    """Calculate and add rows of totals for each day from pd.Series

    Args:
        accounts (pd.DataFrame): updated accounts file
        updated_dates (pd.Series): Series of updated dates for which calculation needs to be done

    Returns:
        pd.DataFrame: new, updated total assets standing
    """
    log.info('Updating and calculating total money history from %s to %s',
             str(from_date), str(till_date))
    total = db.load_total()

    total = __drop_from_total_days(total, from_date)
    total_new_lines = __calc_totals(accounts, from_date, till_date)
    total = pd.concat([total, total_new_lines]).reset_index(drop=True)
    total.to_csv(config.mankkoo_file_path('total'), index=False)
    log.info('Total money data was updated successfully')
    return total
Exemple #14
0
def calculate_balance(df: pd.DataFrame, account_name: str) -> pd.DataFrame:
    """Calculates balance for new operations

    Args:
        df (pandas.DataFrame): DataFrame with a column 'Balance' which has some rows with value NaN

    Returns:
        pandas.DataFrame: DataFrame with calucated 'Balance' after each operation
    """
    log.info('Calculating balance for %s account.', account_name)
    # TODO move to importer.py
    df = df.astype({'Balance': 'float', 'Operation': 'float'})
    non_balanced_rows = df['Balance'].index[df['Balance'].apply(pd.isna)]

    latest_balance = __latest_balance_for_account(df, account_name)

    log.info('Calculating balance for %s account from %s', account_name,
             df.iloc[non_balanced_rows[0]]['Date'])
    for i in non_balanced_rows.values.tolist():
        latest_balance = latest_balance + df.loc[i, 'Operation']
        df.loc[i, 'Balance'] = round(latest_balance, 2)

    return df
Exemple #15
0
def update_monthly_profit(from_date: datetime.date,
                          till_date=datetime.datetime.now(),
                          force=False) -> pd.DataFrame:
    log.info('Updating monthly profit info starting from %s',
             from_date.strftime("%m-%Y"))

    from_month = datetime.date(from_date.year, from_date.month, 1)
    total_monthly = db.load_total_monthly()

    should_update = __should_monthly_total_be_updated(total_monthly,
                                                      from_month, force)
    if not should_update:
        log.info("Monthly profit won't be updated.")
        return

    total = db.load_total()
    months_list = pd.date_range(from_date - relativedelta(months=1),
                                till_date,
                                freq='MS')
    result_list = []

    for month in months_list:
        profit = last_month_income(total, month)
        row_dict = {
            'Date': month,
            'Income': round(0, 2),
            'Spending': round(0, 2),
            'Profit': round(profit, 2)
        }
        result_list.append(row_dict)

    df = pd.DataFrame(result_list)
    total_monthly = total_monthly.drop(
        total_monthly[total_monthly['Date'] >= from_month].index)
    total_monthly = pd.concat([total_monthly, df], ignore_index=True)

    total_monthly.to_csv(config.mankkoo_file_path('total_monthly'),
                         index=False)
    log.info('Total monthly profit data was updated successfully')

    return total_monthly
Exemple #16
0
def stock_page():
    log.info('Loading stocks page')

    return html.Div([
        html.H3('You are on stocks page')
    ])
Exemple #17
0
    elif pathname == '/stocks':
        page = ps.stock_page()
    elif pathname == '/retirement':
        page = pr.retirement_page()
    else:
        page = main.main_page()

    return html.Div(children=[navbar.navbar(app, pathname), page])

@app.callback(Output('upload-status', 'value'),
              Input('upload-data', 'contents'),
              State('upload-data', 'filename'),
              State('upload-data', 'last_modified'),
              State('bank-id', 'value'),
              State('account-name', 'value'),
              State('account-type', 'value')
)
def update_output(list_of_contents, list_of_names, list_of_dates, bank_id, account_name, account_type):
    if list_of_contents is not None:
        try:
            account.add_new_operations(models.Bank[bank_id], account_name, contents=list_of_contents, account_tye=models.Account(account_type))
            return 'success'
        except Exception as ex:
            log.info(f'Error occured: {ex}')
            return 'failure'


if __name__ == '__main__':
    log.info("Starting mankkoo's server")
    app.run_server(debug=True)
Exemple #18
0
def init_data_folder():
    """Initilize .mankkoo directory in home folder, config file and all storage files
    """
    m_path = mankkoo_path()

    log.info("Checking if mankkoo's files are existing...")

    if not os.path.exists(m_path):
        log.info('Creating mankkoo directory...')
        os.makedirs(m_path)

    for file in mankkoo_files:
        file_path = mankkoo_file_path(file)
        if not os.path.exists(file_path):
            log.info("Creating mankkoo's " + file + " file...")
            df = pd.DataFrame(columns=__select_columns(file))
            df.to_csv(file_path, index=False)
            log.info(f"{file} was created in .mankkoo directory")

    if not os.path.exists(m_path + __slash() + config_file):
        log.info(f"Creating user {config_file} file...")
        config_d = dict(accounts=dict(
            ui=dict(default_importer='', hide_accounts=[])))

        with open(m_path + __slash() + config_file, 'w') as outfile:
            yaml.dump(config_d,
                      outfile,
                      allow_unicode=True,
                      default_flow_style=False)
        log.info(f"User {config_file} file was created in .mankkoo directory")
Exemple #19
0
def retirement_page():
    log.info('Loading retirement page')

    return html.Div([html.H3('You are on retirement page')])
Exemple #20
0
def inv_page():
    log.info("Loading investments page")

    return html.Div([html.H3('You are on investments page')])
Exemple #21
0
def account_page():
    log.info("Loading accounts page")

    global_config = config.load_global_config()
    user_config = config.load_user_config()
    bank_ids = ui.decode_bank_ids(global_config['accounts']['importers'])

    accounts_data = db.load_accounts()
    accounts_data = accounts_data.iloc[::-1]
    accounts_names = list(accounts_data.groupby(['Bank', 'Account']).groups)

    account_tabs = []

    for account_name in accounts_names:
        if account_name[0] + ' - ' + account_name[1] in user_config[
                'accounts']['ui']['hide_accounts']:
            continue

        single_account = accounts_data[
            (accounts_data['Bank'] == account_name[0])
            & (accounts_data['Account'] == account_name[1])]
        single_account = single_account[[
            'Date', 'Title', 'Details', 'Operation', 'Balance', 'Currency',
            'Comment'
        ]]

        account_tab = __account_tab(single_account, account_name)
        account_tabs.append(account_tab)

    return html.Div(
        className='height-100 container main-body',
        children=[
            html.Div(className='row',
                     children=[
                         html.Div(
                             className='col-4',
                             children=[
                                 html.Label(htmlFor='bank-id',
                                            children=['Bank']),
                                 dcc.Dropdown(id='bank-id',
                                              options=bank_ids,
                                              value=user_config['accounts']
                                              ['ui']['default_importer'])
                             ]),
                         html.Div(className='col-2',
                                  children=[
                                      html.Label(htmlFor='account-type',
                                                 children=['Account type']),
                                      dcc.Dropdown(id='account-type',
                                                   options=[{
                                                       'label': 'Checking',
                                                       'value': 'checking'
                                                   }, {
                                                       'label': 'Savings',
                                                       'value': 'savings'
                                                   }],
                                                   value='checking')
                                  ]),
                         html.Div(className='col-4',
                                  children=[
                                      html.Label(htmlFor='account-name',
                                                 children=['Account name']),
                                      dcc.Input(id='account-name',
                                                placeholder='Accunt name',
                                                type='text',
                                                style={'width': '100%'})
                                  ])
                     ]),
            html.Div(className='row',
                     children=[
                         dcc.Upload(id='upload-data',
                                    children=html.Div([
                                        'Drag and Drop or ',
                                        html.A('Select Files'),
                                        " to upload account's files"
                                    ]),
                                    style={
                                        'width': '100%',
                                        'height': '60px',
                                        'lineHeight': '60px',
                                        'borderWidth': '1px',
                                        'borderStyle': 'dashed',
                                        'borderRadius': '5px',
                                        'textAlign': 'center',
                                        'margin': '10px'
                                    },
                                    multiple=False),
                         html.Div(id='import-modal-wrapper',
                                  style={'display': 'none'})
                     ]),
            html.Div(className='row',
                     children=[
                         dcc.Tabs(id="tabs-styled-with-inline",
                                  parent_className='accounts-tabs-container',
                                  children=account_tabs)
                     ]),
            html.Div(id='upload-status-container',
                     hidden=True,
                     children=[
                         dcc.Input(id='upload-status',
                                   type='hidden',
                                   value="no-info")
                     ])
        ])
Exemple #22
0
def main_page():
    log.info("Loading main page")

    return html.Div(
        className='height-100 container main-body',
        children=[
            html.Div(
                className='row',
                children=[
                    html.Div(
                        className='col-3',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className=
                                        'card-body card-body-indicator',
                                        children=[
                                            html.Span(
                                                'Savings',
                                                className='card-body-title'),
                                            html.Span('{:,.2f} PLN'.format(
                                                total_money['Total'].sum()).
                                                      replace(',', ' '))
                                        ])
                                ])
                        ]),
                    html.Div(
                        className='col-3',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className=
                                        'card-body card-body-indicator',
                                        children=[
                                            html.Span(
                                                'Debt',
                                                className='card-body-title'),
                                            html.Span(
                                                f'No Data',
                                                style={'color': '#A40E4C'}),
                                        ])
                                ])
                        ]),
                    html.Div(
                        className='col-3',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className=
                                        'card-body card-body-indicator',
                                        children=[
                                            html.Span(
                                                'Last Month Profit',
                                                className='card-body-title'),
                                            html.Span(
                                                f'{last_month_income_sign} {last_month_income:,.2f} PLN',
                                                style={
                                                    'color':
                                                    last_month_income_color
                                                }),
                                            html.Span(
                                                last_month_str,
                                                style={'font-size': '0.4em'})
                                        ])
                                ])
                        ]),
                    html.Div(
                        className='col-3',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className=
                                        'card-body card-body-indicator',
                                        children=[
                                            html.Span(
                                                'Investments',
                                                className='card-body-title'),
                                            html.Span(
                                                f'No Data',
                                                style={'color': '#A40E4C'}),
                                        ])
                                ])
                        ]),
                ]),
            html.Div(
                className='row',
                children=[
                    html.Div(
                        className='col-4',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                style={
                                    'height':
                                    '366px',
                                    'width': '400px'
                                },
                                children=[
                                    html.Div(
                                        className='card-body card-body-plotly',
                                        children=[
                                            html.Span(
                                                'Savings Distribution',
                                                className='card-body-title',
                                                style={
                                                    'margin-bottom': '40px'
                                                }),
                                            total_money_table(total_money)
                                        ])
                                ])
                        ]),
                    html.Div(
                        className="col-5",
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className='card-body card-body-plotly',
                                        children=[
                                            html.Span(
                                                'Savings Distribution',
                                                className='card-body-title',
                                                style={
                                                    'margin-bottom': '20px'
                                                }),
                                            html.Div(dcc.Graph(
                                                figure=total_money_pie(
                                                    total_money)),
                                                     style={'width': '400px'})
                                        ])
                                ])
                        ])
                ]),
            html.Div(
                className='row',
                style={'padding-bottom': '50px'},
                children=[
                    html.Div(
                        className='col-12',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className='card-body card-body-plotly',
                                        children=[
                                            html.Span(
                                                'Savings History',
                                                className='card-body-title'),
                                            html.Div(dcc.Graph(
                                                figure=total_money_chart(
                                                    data['total'])),
                                                     style={'width': '1200px'})
                                        ])
                                ])
                        ]),
                ]),
            html.Div(
                className='row',
                style={'padding-bottom': '50px'},
                children=[
                    html.Div(
                        className='col-12',
                        children=[
                            html.Div(
                                className='card card-indicator',
                                children=[
                                    html.Div(
                                        className='card-body card-body-plotly',
                                        children=[
                                            html.Span(
                                                'Monthly Profit History',
                                                className='card-body-title'),
                                            html.Div(dcc.Graph(
                                                figure=total_monthly_bar(
                                                    data['total_monthly'])),
                                                     style={'width': '1200px'})
                                        ])
                                ])
                        ]),
                ])
        ])