Skip to content

Commit

Permalink
init for public
Browse files Browse the repository at this point in the history
  • Loading branch information
dvorak0 committed Sep 20, 2023
1 parent cc48347 commit 93b0cb6
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 95 deletions.
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
include monthly_expenses/templates/*
include monthly_expenses/templates/*.html
93 changes: 27 additions & 66 deletions monthly_expenses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
from beancount.core.number import ZERO

from fava.ext import FavaExtensionBase
from fava.helpers import FavaAPIException
#from fava.helpers import FavaAPIException
from fava.template_filters import cost_or_value

from beancount.loader import load_file
from beancount.query.query import run_query
from beancount.query.numberify import numberify_results
from beancount.core.data import Custom
import os
import numpy as np
import pandas as pd
Expand All @@ -27,20 +28,24 @@ class MonthlyExpenses(FavaExtensionBase): # pragma: no cover

report_title = "Monthly Expenses"

def get_all_report(self):
return [self.build_report_for_account(account) for account in self.config['accounts'] ]



def get_valid_month_number(self):
FileName= '/mnt/c/Users/dvorak/Dropbox/beancount/a.beancount'
if not os.path.isfile(FileName):
os.system("bean-example > {}".format(FileName))
account = self.config['account_used_to_get_valid_month']
print("options", self.ledger.options)
print("config", self.config)

# Load an Example beancount Journal File
entries, _, opts = load_file(FileName)
# Main currency
entries = self.ledger.all_entries
opts = self.ledger.options

cols, rows = run_query(entries, opts,
"SELECT year, month, account, COUNT(position)\
WHERE account ~ 'Expenses:Life:Food'\
WHERE account ~ '{}'\
GROUP BY year, month, account\
ORDER BY year, month, account"
ORDER BY year, month, account".format(account)
)
cols, rows = numberify_results(cols, rows)
month_count = {}
Expand All @@ -49,29 +54,22 @@ def get_valid_month_number(self):
for row in rows:
if row[3] > 10:
month_count[row[0]] = month_count[row[0]] + 1

print("month ", month_count)
return cols, month_count


def build_report_life(self):
FileName= '/mnt/c/Users/dvorak/Dropbox/beancount/a.beancount'
if not os.path.isfile(FileName):
os.system("bean-example > {}".format(FileName))

# Load an Example beancount Journal File
entries, _, opts = load_file(FileName)
# Main currency
def build_report_for_account(self, account):
print("build report for ", account)
entries = self.ledger.all_entries
opts = self.ledger.options
currency = opts["operating_currency"][0]
cols, rows = run_query(entries, opts,
"SELECT account, YEAR(date) AS year, convert(sum(position),'CNY') AS amount\
WHERE account ~ 'Expenses:Life'\
GROUP BY account, year ORDER BY account, year".format(currency)
WHERE account ~ '{}'\
GROUP BY account, year ORDER BY account, year".format(account)
)

cols, rows = numberify_results(cols, rows)

month_count = self.get_valid_month_number()[1]

month_count = self.get_valid_month_number()[1]

# Converting Result Rows to a Pandas Dataframe
df = pd.DataFrame(rows, columns=[k[0] for k in cols])
Expand All @@ -80,56 +78,19 @@ def build_report_life(self):
df['amount (CNY)'] = df['amount (CNY)'] / df['month_count']
df = df.drop(columns=['month_count'])
df.rename(columns={"account": "Account", "year":"Year", "amount ({})".format(currency): "Amount ({})".format(currency)}, inplace=True)
df = df.astype({"Account": str, "Year": int, "Amount ({})".format(currency): np.float});
df = df.astype({"Account": str, "Year": int, "Amount ({})".format(currency): np.float64});
#print(df[["Account", "Year", "Amount ({})".format(currency)]].fillna(0))

# Pivoting a Table by Year
df = df.pivot_table(index="Account", columns=[ 'Year']).fillna(0).reset_index();
# Creating Multi-Level Accounts
n_levels = df["Account"].str.count(":").max() + 1
cols = ["Account_L{}".format(k) for k in range(n_levels)]
df[cols] = df["Account"].str.split(':', n_levels - 1, expand=True)
df[cols] = df["Account"].str.split(':', n=n_levels - 1, expand=True)
df = df.fillna('').drop(columns="Account", level=0).set_index(cols)
return (df.groupby(["Account_L0", "Account_L1","Account_L2"]).sum().round(decimals=2)).to_html(),df.groupby(["Account_L0", "Account_L1","Account_L2"]).sum().sum().to_frame().to_html()

selected_levels = len(account.split(":")) + 1
groups_name = ["Account_L{}".format(i) for i in range(selected_levels)]


def build_report(self):
FileName= '/mnt/c/Users/dvorak/Dropbox/beancount/a.beancount'
if not os.path.isfile(FileName):
os.system("bean-example > {}".format(FileName))

# Load an Example beancount Journal File
entries, _, opts = load_file(FileName)
# Main currency
currency = opts["operating_currency"][0]
cols, rows = run_query(entries, opts,
"SELECT account, YEAR(date) AS year, convert(sum(position),'CNY') AS amount\
WHERE account ~ 'Expenses'\
GROUP BY account, year ORDER BY account, year".format(currency)
)

cols, rows = numberify_results(cols, rows)

month_count = self.get_valid_month_number()[1]

# Converting Result Rows to a Pandas Dataframe
df = pd.DataFrame(rows, columns=[k[0] for k in cols])
df['month_count'] = df['year']
month_count_html = df['year']
df = df.replace({'month_count': month_count})
df['amount (CNY)'] = df['amount (CNY)'] / df['month_count']
df = df.drop(columns=['month_count'])
df.rename(columns={"account": "Account", "year":"Year", "amount ({})".format(currency): "Amount ({})".format(currency)}, inplace=True)
df = df.astype({"Account": str, "Year": int, "Amount ({})".format(currency): np.float});
#print(df[["Account", "Year", "Amount ({})".format(currency)]].fillna(0))

# Pivoting a Table by Year
df = df.pivot_table(index="Account", columns=[ 'Year']).fillna(0).reset_index();
# Creating Multi-Level Accounts
n_levels = df["Account"].str.count(":").max() + 1
cols = ["Account_L{}".format(k) for k in range(n_levels)]
df[cols] = df["Account"].str.split(':', n_levels - 1, expand=True)
df = df.fillna('').drop(columns="Account", level=0).set_index(cols)
return (df.groupby(["Account_L0", "Account_L1"]).sum().round(decimals=2)).to_html(),df.groupby(["Account_L0", "Account_L1"]).sum().sum().to_frame().to_html(),pd.DataFrame(month_count.items(), columns=['Year', 'count']).to_html()
return (df.groupby(groups_name).sum().round(decimals=2)).to_html(),df.groupby(groups_name).sum().sum().to_frame().to_html(),pd.DataFrame(month_count.items(), columns=['Year', 'count']).to_html(),pd.DataFrame(month_count.items(), columns=['Year', 'count']).to_html()

33 changes: 14 additions & 19 deletions monthly_expenses/templates/MonthlyExpenses.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,18 @@ <h2>Monthly Expenses</h2>
<br />

<div class="row">
{% set report1 = extension.build_report() %}
{% set report2 = extension.build_report_life() %}
<div class="column">
{{report1[0] |safe}}
</div>
<div class="column">
{{report1[1] |safe}}
</div>
<div class="column">
{{report1[2] |safe}}
</div>
</div>
<div class="row">
<div class="column">
{{report2[0] |safe}}
</div>
<div class="column">
{{report2[1] |safe}}
</div>
{% set reports = extension.get_all_report() %}
{% for report in reports %}
<div class="row">
<div class="column">
{{report[0] |safe}}
</div>
<div class="column">
{{report[1] |safe}}
</div>
<div class="column">
{{report[2] |safe}}
</div>
</div>
{% endfor %}
</div>
20 changes: 11 additions & 9 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
__author__ = "Ghislain Bourgeois"
__author__ = "YANG Zhenfei"
__copyright__ = "Copyright (C) 2018 Ghislain Bourgeois"
__license__ = "GNU GPLv2"

import setuptools
from setuptools import find_packages


setuptools.setup(
name="monthly_expenses",
version="0.2.0",
packages=setuptools.find_packages(),
version="0.5",
packages=find_packages(),
package_data={'monthly_expenses.templates':['*.html']},
setup_requires=['pytest-runner'],
install_requires=['beancount>=2.1.2', 'tabulate', 'pandas'],
install_requires=['beancount>=2.1.2', 'tabulate', 'pandas', 'fava'],
tests_require=['pytest', 'testfixtures'],

test_suite="tests",

author="Ghislain Bourgeois",
author_email="ghislain.bourgeois@gmail.com",
description="Beancount portfolio allocation report",
author="YANG Zhenfei",
author_email="yangzhenfei0@gmail.com",
description="Beancount monthly expenses report",
license="GPLv2",
keywords="beancount report portfolio allocation",
url="https://github.com/ghislainbourgeois/beancount_portfolio_allocation/",
keywords="beancount monthly expenses report",
url="https://github.com/dvorak0/fava-monthly-expenses/",
include_package_data = True,

classifiers=(
Expand Down

0 comments on commit 93b0cb6

Please sign in to comment.