Skip to content

Commit

Permalink
Merge branch 'master' of github.com:MeerkatLabs/gnucash-reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
rerobins committed Apr 1, 2018
2 parents 9a51f35 + bb002b7 commit 1941df8
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 12 deletions.
3 changes: 2 additions & 1 deletion gnucash_reports/collate/key_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from dateutil.rrule import rrule, MONTHLY

from gnucash_reports.configuration.expense_categories import get_category_for_account
from gnucash_reports.utilities import clean_account_name


def monthly(data_key):
Expand Down Expand Up @@ -33,7 +34,7 @@ def category_key_fetcher(data_key):
:param data_key: split
:return:
"""
return get_category_for_account(data_key.account.fullname.replace(':', '.'))
return get_category_for_account(clean_account_name(data_key.account.fullname))


def account_key_fetcher(data_key):
Expand Down
5 changes: 3 additions & 2 deletions gnucash_reports/configuration/expense_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
that it is stored in.
"""
from gnucash_reports.wrapper import account_walker, parse_walker_parameters
from gnucash_reports.utilities import clean_account_name

_expense_categories = dict()
_reverse = dict()
Expand All @@ -24,7 +25,7 @@ def configure(json_dictionary):
all_accounts = set()
for account in account_walker(**accounts):
# print 'loading account: %s' % account.fullname
all_accounts.add(account.fullname.replace(':', '.'))
all_accounts.add(clean_account_name(account.fullname))

for account in all_accounts:
_reverse[account] = category
Expand All @@ -39,7 +40,7 @@ def get_category_for_account(account_name):
:return:
"""
# Translate the account name to use the common formatting.
account_name = account_name.replace(':', '.')
account_name = clean_account_name(account_name)
value = _reverse.get(account_name, _default_category)

if value == _default_category:
Expand Down
2 changes: 1 addition & 1 deletion gnucash_reports/reports/budget_level.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def budget_level(definition):
yearly_balance = Decimal('0.0')

for account in account_walker(**accounts):
split_list = get_splits(account, PeriodStart.this_year.date, PeriodEnd.this_year.date, debit=False)
split_list = get_splits(account, PeriodStart.this_year.date, PeriodEnd.today.date, debit=False)

for split in split_list:
yearly_balance += split.value
Expand Down
2 changes: 1 addition & 1 deletion gnucash_reports/reports/expenses_monthly.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def expenses_box(definition):

def expenses_categories(definition):
expense_accounts = parse_walker_parameters(definition.get('expenses_base', []))
start_period = PeriodStart(definition.get('period_start', PeriodStart.this_month_year_ago))
start_period = PeriodStart(definition.get('period_start', PeriodStart.this_month))
end_period = PeriodEnd(definition.get('period_end', PeriodEnd.this_month))

bucket = CategoryCollate(decimal_generator, split_summation)
Expand Down
27 changes: 27 additions & 0 deletions gnucash_reports/reports/income_tax.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from gnucash_reports.configuration.tax_tables import calculate_tax
from gnucash_reports.periods import PeriodStart, PeriodEnd
from gnucash_reports.wrapper import get_splits, account_walker, parse_walker_parameters
from gnucash_reports.utilities import clean_account_name


def income_tax(definition):
Expand All @@ -15,20 +16,46 @@ def income_tax(definition):
period_end = PeriodEnd(definition.get('period_end', PeriodEnd.this_year))
tax_name = definition.get('tax_name', 'federal')
tax_status = definition.get('tax_status', 'single')
deductions = definition.get('deductions', [])
deduction_accounts = parse_walker_parameters(definition.get('deduction_accounts', []))

total_income = Decimal(0.0)
total_taxes = Decimal(0.0)
pre_tax_deductions = Decimal(0.0)

# Find all of the deduction accounts, and store them in a list so that they can be walked when handling the
# income from the income accounts
deduction_account_names = set()
for account in account_walker(**deduction_accounts):
deduction_account_names.add(clean_account_name(account.fullname))

# Calculate all of the income that has been received, and calculate all of the contributions to the deduction
# accounts that will reduce tax burden.
for account in account_walker(**income_accounts):
for split in get_splits(account, period_start.date, period_end.date):
value = split.value * -1 # negate the value because income is leaving these accounts
total_income += value

# Go through the split's parent and find all of the values that are in the deduction accounts as well
transaction = split.transaction
for t_split in transaction.splits:
if clean_account_name(t_split.account.fullname) in deduction_account_names:
pre_tax_deductions += t_split.value

# Calculate all of the taxes that have been currently paid
for account in account_walker(**tax_accounts):
for split in get_splits(account, period_start.date, period_end.date):
value = split.value
total_taxes += value

# Remove all of the deductions from the total income value
for deduction in deductions:
pre_tax_deductions += Decimal(deduction)

# Remove all of the contributions from the income accounts that went into pre-tax accounts and any standard
# deductions
total_income -= pre_tax_deductions

tax_value = calculate_tax(tax_name, tax_status, total_income)

return dict(income=total_income, tax_value=tax_value, taxes_paid=total_taxes)
5 changes: 3 additions & 2 deletions gnucash_reports/reports/retirement_401k.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from gnucash_reports.periods import PeriodStart, PeriodEnd
from gnucash_reports.wrapper import get_account, get_splits
from gnucash_reports.utilities import clean_account_name


def retirement_401k_report(definition):
Expand All @@ -23,7 +24,7 @@ def retirement_401k_report(definition):
today = date.today()
beginning_of_year = date(today.year, 1, 1)

retirement_accounts = [account_name.replace(':', '.') for account_name in retirement_accounts]
retirement_accounts = [clean_account_name(account_name) for account_name in retirement_accounts]

for account_name in income_accounts:
account = get_account(account_name)
Expand All @@ -33,7 +34,7 @@ def retirement_401k_report(definition):

for income_split in parent.splits:

account_full_name = income_split.account.fullname.replace(':', '.')
account_full_name = clean_account_name(income_split.account.fullname)

if account_full_name in retirement_accounts:
contribution_total += income_split.value
Expand Down
7 changes: 6 additions & 1 deletion gnucash_reports/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ def load_plugins():
# Register the configuration
for ep in pkg_resources.iter_entry_points(group='gnucash_reports_configuration'):
loader = ep.load()
loader()
loader()


def clean_account_name(account_name):
"""Replace account names with colons as separators with periods as separators."""
return account_name.replace(':', '.')
27 changes: 23 additions & 4 deletions gnucash_reports/wrapper.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from datetime import datetime
from decimal import Decimal
from gnucash_reports.configuration.current_date import get_today
from gnucash_reports.utilities import clean_account_name

import enum
import piecash
Expand Down Expand Up @@ -29,6 +30,8 @@ class AccountTypes(enum.Enum):

gnucash_session = None

_account_cache = dict()


def initialize(file_uri, read_only=True, do_backup=False):
global gnucash_session
Expand All @@ -41,14 +44,28 @@ def get_session():


def get_account(account_name):
global _account_cache
current_account = gnucash_session.root_account

current_account_name = ''

for child_name in re.split('[:.]', account_name):
account = gnucash_session.session.query(piecash.Account).filter(piecash.Account.parent == current_account,
piecash.Account.name == child_name).one_or_none()

if current_account_name:
current_account_name = current_account_name + '.' + child_name
else:
current_account_name = child_name

account = _account_cache.get(current_account_name, None)

if account is None:
raise RuntimeError('Account %s is not found in %s' % (account_name, current_account))
account = gnucash_session.session.query(piecash.Account).filter(piecash.Account.parent == current_account,
piecash.Account.name == child_name).one_or_none()

if account is None:
raise RuntimeError('Account %s is not found in %s' % (account_name, current_account))

_account_cache[current_account_name] = account

current_account = account

Expand Down Expand Up @@ -104,6 +121,8 @@ def account_walker(accounts, ignores=None, place_holders=False, recursive=True,

_account_list = [a for a in accounts]

ignores = [clean_account_name(account_name) for account_name in ignores]

while _account_list:
account_name = _account_list.pop()
if account_name in ignores:
Expand All @@ -114,7 +133,7 @@ def account_walker(accounts, ignores=None, place_holders=False, recursive=True,
yield account

if recursive:
_account_list += [a.fullname for a in account.children]
_account_list += [clean_account_name(a.fullname) for a in account.children]


def parse_walker_parameters(definition):
Expand Down

0 comments on commit 1941df8

Please sign in to comment.