def calculate_budget(budgets, account_name, date_from, date_to): """Calculate budget for an account. Args: budgets: A list of :class:`Budget` entries. account_name: An account name. date_from: Starting date. date_to: End date (exclusive). Returns: A dictionary of currency to Decimal with the budget for the specified account and period. """ if account_name not in budgets: return {} currency_dict = defaultdict(Decimal) for single_day in days_in_daterange(date_from, date_to): matches = _matching_budgets(budgets, account_name, single_day) for budget in matches.values(): currency_dict[budget.currency] += \ budget.number / number_of_days_in_period(budget.period, single_day) return currency_dict
def calculate_budget( budgets: BudgetDict, account: str, date_from: datetime.date, date_to: datetime.date, ) -> Dict[str, Decimal]: """Calculate budget for an account. Args: budgets: A list of :class:`Budget` entries. account: An account name. date_from: Starting date. date_to: End date (exclusive). Returns: A dictionary of currency to Decimal with the budget for the specified account and period. """ if account not in budgets: return {} currency_dict: Dict[str, Decimal] = defaultdict(Decimal) for single_day in days_in_daterange(date_from, date_to): matches = _matching_budgets(budgets, account, single_day) for budget in matches.values(): currency_dict[ budget.currency ] += budget.number / number_of_days_in_period( budget.period, single_day ) return currency_dict
def test_number_of_days_in_period_quarterly(): # 2016 = leap year assert number_of_days_in_period('quarterly', dt(2016, 2, 1)) == 91 assert number_of_days_in_period('quarterly', dt(2016, 5, 30)) == 91 assert number_of_days_in_period('quarterly', dt(2016, 8, 15)) == 92 assert number_of_days_in_period('quarterly', dt(2016, 11, 15)) == 92 # 2017 = not a leap year assert number_of_days_in_period('quarterly', dt(2017, 2, 1)) == 90 assert number_of_days_in_period('quarterly', dt(2017, 5, 30)) == 91 assert number_of_days_in_period('quarterly', dt(2017, 8, 15)) == 92 assert number_of_days_in_period('quarterly', dt(2017, 11, 15)) == 92
def budget(self, account_name, date_from, date_to): """ Returns a dictionary (currency => number) with the budget for the specified account and period (excluding date_to). """ currency_dict = defaultdict(lambda: Decimal(0.0)) if account_name not in self.budgets.keys(): return currency_dict for single_day in days_in_daterange(date_from, date_to): budget = self._matching_budget(account_name, single_day) if budget: currency_dict[budget.currency] += budget.number / number_of_days_in_period(budget.period, single_day) return dict(currency_dict)
def calculate_budget(budgets, account_name, date_from, date_to): """ Returns a dictionary (currency => number) with the budget for the specified account and period (excluding date_to). """ if account_name not in budgets.keys(): return {} currency_dict = defaultdict(Decimal) for single_day in days_in_daterange(date_from, date_to): matches = _matching_budgets(budgets, account_name, single_day) for budget in matches.values(): currency_dict[budget.currency] += \ budget.number / number_of_days_in_period(budget.period, single_day) return dict(currency_dict)
def budget(self, account_name, date_from, date_to): """ Returns a dictionary (currency => number) with the budget for the specified account and period (excluding date_to). """ currency_dict = defaultdict(lambda: Decimal(0.0)) if account_name not in self.budgets.keys(): return currency_dict for single_day in days_in_daterange(date_from, date_to): budget = self._matching_budget(account_name, single_day) if budget: currency_dict[budget.currency] += \ budget.number / number_of_days_in_period(budget.period, single_day) return dict(currency_dict)
def test_budgets_dateline_monthly(): BUDGET = Decimal(100) budgets = get_budgets('2014-05-01 custom "budget" Expenses:Books "monthly" {} EUR'.format(BUDGET)) # noqa assert budgets.budget('Expenses:Books', date(2016, 1, 1), date(2016, 1, 2))['EUR'] == BUDGET / number_of_days_in_period('monthly', date(2016, 1, 1)) # noqa assert budgets.budget('Expenses:Books', date(2016, 2, 1), date(2016, 2, 2))['EUR'] == BUDGET / number_of_days_in_period('monthly', date(2016, 2, 1)) # noqa assert budgets.budget('Expenses:Books', date(2018, 3, 31), date(2018, 4, 1))['EUR'] == BUDGET / number_of_days_in_period('monthly', date(2016, 3, 31)) # noqa
def test_number_of_days_in_period2(): with pytest.raises(NotImplementedError): number_of_days_in_period('test', date(2011, 2, 1))
def test_number_of_days_in_period_yearly(): assert number_of_days_in_period('yearly', dt(2011, 2, 1)) == 365 assert number_of_days_in_period('yearly', dt(2015, 5, 30)) == 365 assert number_of_days_in_period('yearly', dt(2016, 8, 15)) == 366
def test_number_of_days_in_period(interval, date_str, expect): assert number_of_days_in_period(interval, _to_date(date_str)) == expect
def test_budgets_dateline_weekly(): BUDGET = Decimal(21) budgets = get_budgets('2016-05-01 custom "budget" Expenses:Books "weekly" {} EUR'.format(BUDGET)) # noqa assert budgets.budget('Expenses:Books', date(2016, 5, 1), date(2016, 5, 2))['EUR'] == BUDGET / number_of_days_in_period('weekly', date(2016, 5, 1)) # noqa assert budgets.budget('Expenses:Books', date(2016, 9, 1), date(2016, 9, 2))['EUR'] == BUDGET / number_of_days_in_period('weekly', date(2016, 9, 1)) # noqa assert budgets.budget('Expenses:Books', date(2018, 12, 31), date(2019, 1, 1))['EUR'] == BUDGET / number_of_days_in_period('weekly', date(2018, 12, 31)) # noqa
def test_number_of_days_in_period_monthly(): assert number_of_days_in_period('monthly', dt(2016, 5, 1)) == 31 assert number_of_days_in_period('monthly', dt(2016, 5, 2)) == 31 assert number_of_days_in_period('monthly', dt(2016, 5, 31)) == 31 assert number_of_days_in_period('monthly', dt(2016, 6, 1)) == 30 assert number_of_days_in_period('monthly', dt(2016, 6, 15)) == 30 assert number_of_days_in_period('monthly', dt(2016, 6, 30)) == 30 assert number_of_days_in_period('monthly', dt(2016, 7, 1)) == 31 assert number_of_days_in_period('monthly', dt(2016, 7, 15)) == 31 assert number_of_days_in_period('monthly', dt(2016, 7, 31)) == 31 assert number_of_days_in_period('monthly', dt(2016, 1, 1)) == 31 assert number_of_days_in_period('monthly', dt(2016, 2, 1)) == 29 assert number_of_days_in_period('monthly', dt(2016, 3, 31)) == 31
def test_budgets_dateline_quarterly(): BUDGET = Decimal(123456.7) budgets = get_budgets('2014-05-01 custom "budget" Expenses:Books "quarterly" {} EUR'.format(BUDGET)) # noqa assert budgets.budget('Expenses:Books', date(2016, 2, 1), date(2016, 2, 2))['EUR'] == BUDGET / number_of_days_in_period('quarterly', date(2016, 2, 1)) # noqa assert budgets.budget('Expenses:Books', date(2016, 5, 30), date(2016, 5, 31))['EUR'] == BUDGET / number_of_days_in_period('quarterly', date(2016, 5, 30)) # noqa assert budgets.budget('Expenses:Books', date(2016, 8, 15), date(2016, 8, 16))['EUR'] == BUDGET / number_of_days_in_period('quarterly', date(2016, 8, 15)) # noqa assert budgets.budget('Expenses:Books', date(2016, 11, 15), date(2016, 11, 16))['EUR'] == BUDGET / number_of_days_in_period('quarterly', date(2016, 11, 15)) # noqa
def test_number_of_days_in_period_weekly(): assert number_of_days_in_period('weekly', dt(2016, 5, 1)) == 7 assert number_of_days_in_period('weekly', dt(2016, 5, 2)) == 7 assert number_of_days_in_period('weekly', dt(2016, 5, 31)) == 7
def test_number_of_days_in_period_daily(): assert number_of_days_in_period('daily', dt(2016, 5, 1)) == 1 assert number_of_days_in_period('daily', dt(2016, 5, 2)) == 1 assert number_of_days_in_period('daily', dt(2016, 5, 31)) == 1
def test_number_of_days_in_period2(): with pytest.raises(NotImplementedError): number_of_days_in_period("test", date(2011, 2, 1))
def test_number_of_days_in_period_exception(): with pytest.raises(NotImplementedError): number_of_days_in_period('test', date(2011, 2, 1))
def test_budgets_dateline_yearly(): BUDGET = Decimal(99999.87) budgets = get_budgets('2010-01-01 custom "budget" Expenses:Books "yearly" {} EUR'.format(BUDGET)) # noqa assert budgets.budget('Expenses:Books', date(2011, 2, 1), date(2011, 2, 2))['EUR'] == BUDGET / number_of_days_in_period('yearly', date(2011, 2, 1)) # noqa assert budgets.budget('Expenses:Books', date(2015, 5, 30), date(2015, 5, 31))['EUR'] == BUDGET / number_of_days_in_period('yearly', date(2015, 5, 30)) # noqa assert budgets.budget('Expenses:Books', date(2016, 8, 15), date(2016, 8, 16))['EUR'] == BUDGET / number_of_days_in_period('yearly', date(2016, 8, 15)) # noqa
def test_number_of_days_in_period_exception(): with pytest.raises(Exception): number_of_days_in_period('test', dt(2011, 2, 1)) == 365
def test_number_of_days_in_period(interval: Interval, date_str: str, expect: int) -> None: assert number_of_days_in_period(interval, _to_date(date_str)) == expect