Skip to content

Commit

Permalink
Merge pull request #203 from /issues/201
Browse files Browse the repository at this point in the history
Fixes Issues/201
  • Loading branch information
jantman authored Sep 15, 2018
2 parents c62808d + 9ad1bfb commit fd61092
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 30 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
Unreleased Changes
------------------

* `Issue #201 <https://github.com/jantman/biweeklybudget/issues/201>`_ - Fix **major** bug in calculation of "Remaining" amount for pay periods, when one or more periodic budgets have a greater amount spent than allocated and a $0 starting balance. In that case, we were using the allocated amount instead of the spent amount (i.e. if we had a periodic budget with a $0 starting balance and a $2 ScheduledTransaction, and converted that ScheduledTransaction to a $1000 Transaction, the overall PayPeriod remaining amount would be based on the $2 not the $1000).
* Add testing for Python 3.7, and make 3.7 the default for tests and tox environments.
* TravisCI updates for Python 3.7.
* Upgrade SQLAlchemy from 1.2.0 to 1.2.11 for `python 3 bug fix (4291) <https://docs.sqlalchemy.org/en/latest/changelog/changelog_12.html#change-2cca6c216347ab83d04c766452b48c1a>`_.
Expand Down
4 changes: 2 additions & 2 deletions bin/t
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ class ToxIt(object):
def run_one_module(self, script_name, module_name, expr=None):
"""run one module"""
if 'tests/unit' in module_name:
env = 'py36'
env = 'py37'
mod = module_name
logger.debug('Directly-specified unit test module; env=%s mod=%s',
env, mod)
Expand All @@ -193,7 +193,7 @@ class ToxIt(object):
env, mod
)
elif script_name.endswith('t'):
env = 'py36'
env = 'py37'
mod = self._find_test_mod_for_module(module_name)
logger.debug('Discovered unit test module; env=%s mod=%s',
env, mod)
Expand Down
11 changes: 5 additions & 6 deletions biweeklybudget/biweeklypayperiod.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ def _make_overall_sums(self):
:return: dict describing sums for the pay period
:rtype: dict
"""
budgets_total = Decimal('0.0')
res = {
'allocated': Decimal('0.0'),
'spent': Decimal('0.0'),
Expand All @@ -546,15 +547,13 @@ def _make_overall_sums(self):
else:
res['income'] += abs(b['budget_amount'])
continue
if b['allocated'] > b['budget_amount']:
res['allocated'] += b['allocated']
else:
res['allocated'] += b['budget_amount']
res['allocated'] += max(b['allocated'], b['budget_amount'])
res['spent'] += b['spent']
if res['spent'] > res['allocated'] or self.is_in_past:
budgets_total += max(b['trans_total'], b['budget_amount'])
if self.is_in_past:
res['remaining'] = res['income'] - res['spent']
else:
res['remaining'] = res['income'] - res['allocated']
res['remaining'] = res['income'] - budgets_total
return res

def _trans_dict(self, t):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ def test_03_info_panels(self, base_url, selenium, testdb):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$421.10'
assert selenium.find_element_by_id('amt-spent').text == '$355.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,924.57'
assert selenium.find_element_by_id('amt-remaining').text == '$1,923.66'

def test_04_periodic_budgets(self, base_url, selenium, testdb):
self.get(
Expand Down Expand Up @@ -1386,7 +1386,7 @@ def test_22_issue152_info_panels(self, base_url, selenium):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$521.10'
assert selenium.find_element_by_id('amt-spent').text == '$455.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,824.57'
assert selenium.find_element_by_id('amt-remaining').text == '$1,823.66'

def test_23_issue152_periodic_budgets(self, base_url, selenium):
"""verify budget totals"""
Expand Down Expand Up @@ -1563,7 +1563,7 @@ def test_40_issue161_info_panels(self, base_url, selenium):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$721.10'
assert selenium.find_element_by_id('amt-spent').text == '$655.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,624.57'
assert selenium.find_element_by_id('amt-remaining').text == '$1,623.66'

def test_41_issue161_periodic_budgets(self, base_url, selenium):
"""verify budget totals"""
Expand Down Expand Up @@ -1953,7 +1953,7 @@ def test_03_info_panels(self, base_url, selenium, testdb):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$411.10'
assert selenium.find_element_by_id('amt-spent').text == '$345.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,934.57'
assert selenium.find_element_by_id('amt-remaining').text == '$1,933.66'

def test_04_periodic_budgets(self, base_url, selenium, testdb):
self.get(
Expand Down Expand Up @@ -2253,7 +2253,7 @@ def test_13_info_panels(self, base_url, selenium, testdb):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$534.55'
assert selenium.find_element_by_id('amt-spent').text == '$468.80'
assert selenium.find_element_by_id('amt-remaining').text == '$1,811.12'
assert selenium.find_element_by_id('amt-remaining').text == '$1,810.21'

def test_14_periodic_budgets(self, base_url, selenium, testdb):
self.get(
Expand Down Expand Up @@ -2597,7 +2597,7 @@ def test_03_info_panels(self, base_url, selenium, testdb):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$411.10'
assert selenium.find_element_by_id('amt-spent').text == '$345.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,934.57'
assert selenium.find_element_by_id('amt-remaining').text == '$1,933.66'

def test_04_periodic_budgets(self, base_url, selenium, testdb):
self.get(
Expand Down Expand Up @@ -2769,7 +2769,7 @@ def test_07_verify_db_ids(self, testdb):
])
assert max_r == 2

def test_08_budget_transfer(self, base_url, selenium, testdb):
def test_08_skip_scheduled(self, base_url, selenium, testdb):
self.get(
selenium,
base_url + '/payperiod/' +
Expand Down Expand Up @@ -2869,7 +2869,7 @@ def test_13_info_panels(self, base_url, selenium, testdb):
'amt-income').text == '$2,345.67'
assert selenium.find_element_by_id('amt-allocated').text == '$388.88'
assert selenium.find_element_by_id('amt-spent').text == '$345.35'
assert selenium.find_element_by_id('amt-remaining').text == '$1,956.79'
assert selenium.find_element_by_id('amt-remaining').text == '$1,955.88'

def test_14_periodic_budgets(self, base_url, selenium, testdb):
self.get(
Expand Down
164 changes: 155 additions & 9 deletions biweeklybudget/tests/acceptance/test_biweeklypayperiod.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,11 +493,11 @@ def test_3_ignore_scheduled_converted_to_real_trans(self, testdb):
@pytest.mark.incremental
class TestSums(AcceptanceHelper):

def test_0_clean_db(self, dump_file_path):
def test_10_clean_db(self, dump_file_path):
# clean the database; empty schema
restore_mysqldump(dump_file_path, get_db_engine(), with_data=False)

def test_1_add_account(self, testdb):
def test_11_add_account(self, testdb):
a = Account(
description='First Bank Account',
name='BankOne',
Expand All @@ -515,7 +515,7 @@ def test_1_add_account(self, testdb):
testdb.flush()
testdb.commit()

def test_2_add_budgets(self, testdb):
def test_12_add_budgets(self, testdb):
testdb.add(Budget(
name='1Standing',
is_periodic=False,
Expand Down Expand Up @@ -552,7 +552,7 @@ def test_2_add_budgets(self, testdb):
testdb.commit()

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_3_add_transactions(self, testdb):
def test_13_add_transactions(self, testdb):
acct = testdb.query(Account).get(1)
budgets = {x.id: x for x in testdb.query(Budget).all()}
# Budget 3 Income Transaction
Expand Down Expand Up @@ -620,7 +620,7 @@ def test_3_add_transactions(self, testdb):
testdb.commit()

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_4_budget_sums(self, testdb):
def test_14_budget_sums(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2017, 4, 10), testdb
)
Expand Down Expand Up @@ -660,7 +660,7 @@ def test_4_budget_sums(self, testdb):
}

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_5_overall_sums(self, testdb):
def test_15_overall_sums(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2017, 4, 10), testdb
)
Expand All @@ -672,7 +672,7 @@ def test_5_overall_sums(self, testdb):
}

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_6_transaction_list_ordering(self, testdb):
def test_16_transaction_list_ordering(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2017, 4, 10), testdb
)
Expand All @@ -688,7 +688,7 @@ def test_6_transaction_list_ordering(self, testdb):
]

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_7_spent_greater_than_allocated(self, testdb):
def test_17_spent_greater_than_allocated(self, testdb):
acct = testdb.query(Account).get(1)
budget = testdb.query(Budget).get(5)
t = Transaction(
Expand Down Expand Up @@ -747,7 +747,7 @@ def test_7_spent_greater_than_allocated(self, testdb):
}

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_8_sums_for_empty_period(self, testdb):
def test_18_sums_for_empty_period(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2020, 4, 9), testdb
)
Expand Down Expand Up @@ -791,3 +791,149 @@ def test_8_sums_for_empty_period(self, testdb):
'remaining': Decimal('-377.55'),
'spent': Decimal('0.0')
}

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_80_issue201_setup(self, testdb):
budg = Budget(
name='6Periodic',
is_periodic=True,
description='6Periodic',
starting_balance=Decimal('0.00')
)
testdb.add(budg)
acct = testdb.query(Account).get(1)
testdb.add(ScheduledTransaction(
amount=Decimal('2.00'),
description='B6 ST4',
account=acct,
budget=budg,
day_of_month=11
))
testdb.flush()
testdb.commit()

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_81_issue201_validate_setup(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2020, 4, 9), testdb
)
assert pp._data['budget_sums'] == {
2: {
'budget_amount': Decimal('123.45'),
'allocated': Decimal('0.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('0.0'),
'is_income': True,
'remaining': Decimal('123.45')
},
3: {
'budget_amount': Decimal('0.0'),
'allocated': Decimal('99.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('99.0'),
'is_income': True,
'remaining': Decimal('99.0')
},
4: {
'budget_amount': Decimal('500.00'),
'allocated': Decimal('0.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('0.0'),
'is_income': False,
'remaining': Decimal('500.0')
},
5: {
'budget_amount': Decimal('100.0'),
'allocated': Decimal('2.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('2.0'),
'is_income': False,
'remaining': Decimal('98.0')
},
6: {
'budget_amount': Decimal('0.0'),
'allocated': Decimal('2.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('2.0'),
'is_income': False,
'remaining': Decimal('-2.0')
}
}
assert pp._data['overall_sums'] == {
'allocated': Decimal('602.0'),
'income': Decimal('222.45'),
'remaining': Decimal('-379.55'),
'spent': Decimal('0.0')
}

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_82_issue201_st_to_trans(self, testdb):
budg = testdb.query(Budget).get(6)
st = testdb.query(ScheduledTransaction).get(4)
testdb.add(Transaction(
date=date(2020, 4, 14),
description='B6 T6 from ST4',
budget_amounts={
budg: Decimal('200.00')
},
budgeted_amount=Decimal('2.00'),
account=testdb.query(Account).get(1),
planned_budget=budg,
scheduled_trans=st
))
testdb.flush()
testdb.commit()

@patch('%s.settings.PAY_PERIOD_START_DATE' % pbm, date(2017, 4, 7))
def test_83_issue201_confirm(self, testdb):
pp = BiweeklyPayPeriod.period_for_date(
date(2020, 4, 9), testdb
)
assert pp._data['budget_sums'] == {
2: {
'budget_amount': Decimal('123.45'),
'allocated': Decimal('0.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('0.0'),
'is_income': True,
'remaining': Decimal('123.45')
},
3: {
'budget_amount': Decimal('0.0'),
'allocated': Decimal('99.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('99.0'),
'is_income': True,
'remaining': Decimal('99.0')
},
4: {
'budget_amount': Decimal('500.00'),
'allocated': Decimal('0.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('0.0'),
'is_income': False,
'remaining': Decimal('500.0')
},
5: {
'budget_amount': Decimal('100.0'),
'allocated': Decimal('2.0'),
'spent': Decimal('0.0'),
'trans_total': Decimal('2.0'),
'is_income': False,
'remaining': Decimal('98.0')
},
6: {
'budget_amount': Decimal('0.0'),
'allocated': Decimal('2.0'),
'spent': Decimal('200.0'),
'trans_total': Decimal('200.0'),
'is_income': False,
'remaining': Decimal('-200.0')
}
}
assert pp._data['overall_sums'] == {
'allocated': Decimal('602.0'),
'income': Decimal('222.45'),
'remaining': Decimal('-577.55'),
'spent': Decimal('200.0')
}
Loading

0 comments on commit fd61092

Please sign in to comment.