# Path: budgettracker/data.py
# def split_income_expenses(transactions):
#     income = filter(lambda tx: tx.amount > 0.0, transactions)
#     expenses = filter(lambda tx: tx.amount <= 0.0, transactions)
#     return income, expenses
# 
# def extract_transactions_by_label(transactions, labels):
#     def match_label(tx):
#         for exp in labels:
#             if re.match(exp, tx.label):
#                 return True
#         return False
#     matching = filter(match_label, transactions)
#     transactions = filter_out_transactions(transactions, matching)
#     return matching, transactions
# 
# def filter_transactions_period(transactions, start_date=None, end_date=None):
#     if not start_date and not end_date:
#         return transactions
#     return filter(
#         lambda tx: (not start_date or tx.date >= start_date) and (not end_date or tx.date < end_date),
#         transactions)
# 
# def sort_transactions(transactions):
#     return sorted(transactions, key=lambda tx: tx.date, reverse=True)
# 
# def period_to_months(start_date, end_date):
#     dates = [start_date.replace(day=1)]
#     end_date = end_date.replace(day=1) - monthdelta(1)
#     while dates[-1] < end_date:
#         dates.append(dates[-1] + monthdelta(1))
#     return dates


from collections import namedtuple, OrderedDict
from .data import (split_income_expenses, extract_transactions_by_label, filter_transactions_period,
                   sort_transactions, period_to_months)
from monthdelta import monthdelta
import datetime
        if total_savings < 0:
            _debug(' ! Not enough savings to cover this month (remaining=%s)' % total_savings)
                    
        if not remaining_goals:
            break

    savings_after_goals = max(total_savings - sum(saved.values()), 0)
    _debug('END COMPUTING OF GOALS (savings=%s, after goals=%s)' % (total_savings, savings_after_goals))

    computed = []
    for goal in budget_goals.values():
        computed.append(ComputedBudgetGoal.from_savings_goal(goal,
            saved=saved[goal.label], used=used[goal.label]))
    return computed, savings_after_goals


def budgetize(transactions, start_date, end_date, *args, **kwargs):
    budgets = BudgetList()
    for date in period_to_months(start_date, end_date):
        budgets.append(budgetize_month(transactions, date, *args, **kwargs))
    return budgets


def budgetize_month(transactions, date, income_sources=None, planned_expenses=None, budget_goals=None, income_delay=0):
    start_date = date.replace(day=1)
    end_date = start_date + monthdelta(1)

    if income_delay:
        income_transactions, _ = split_income_expenses(filter_transactions_period(
        transactions, start_date + datetime.timedelta(days=income_delay), end_date + datetime.timedelta(days=income_delay)))

# Path: budgettracker/data.py
# def split_income_expenses(transactions):
#     income = filter(lambda tx: tx.amount > 0.0, transactions)
#     expenses = filter(lambda tx: tx.amount <= 0.0, transactions)
#     return income, expenses
# 
# def extract_transactions_by_label(transactions, labels):
#     def match_label(tx):
#         for exp in labels:
#             if re.match(exp, tx.label):
#                 return True
#         return False
#     matching = filter(match_label, transactions)
#     transactions = filter_out_transactions(transactions, matching)
#     return matching, transactions
# 
# def filter_transactions_period(transactions, start_date=None, end_date=None):
#     if not start_date and not end_date:
#         return transactions
#     return filter(
#         lambda tx: (not start_date or tx.date >= start_date) and (not end_date or tx.date < end_date),
#         transactions)
# 
# def sort_transactions(transactions):
#     return sorted(transactions, key=lambda tx: tx.date, reverse=True)
# 
# def period_to_months(start_date, end_date):
#     dates = [start_date.replace(day=1)]
#     end_date = end_date.replace(day=1) - monthdelta(1)
#     while dates[-1] < end_date:
#         dates.append(dates[-1] + monthdelta(1))
#     return dates


# Path: budgettracker/budget.py
from collections import namedtuple, OrderedDict
from .data import (split_income_expenses, extract_transactions_by_label, filter_transactions_period,
                   sort_transactions, period_to_months)
from monthdelta import monthdelta
import datetime

        if total_savings < 0:
            _debug(' ! Not enough savings to cover this month (remaining=%s)' % total_savings)
                    
        if not remaining_goals:
            break

    savings_after_goals = max(total_savings - sum(saved.values()), 0)
    _debug('END COMPUTING OF GOALS (savings=%s, after goals=%s)' % (total_savings, savings_after_goals))

    computed = []
    for goal in budget_goals.values():
        computed.append(ComputedBudgetGoal.from_savings_goal(goal,
            saved=saved[goal.label], used=used[goal.label]))
    return computed, savings_after_goals


def budgetize(transactions, start_date, end_date, *args, **kwargs):
    budgets = BudgetList()
    for date in period_to_months(start_date, end_date):
        budgets.append(budgetize_month(transactions, date, *args, **kwargs))
    return budgets


def budgetize_month(transactions, date, income_sources=None, planned_expenses=None, budget_goals=None, income_delay=0):
    start_date = date.replace(day=1)
    end_date = start_date + monthdelta(1)

    if income_delay:
        income_transactions, _ = split_income_expenses(filter_transactions_period(
        transactions, start_date + datetime.timedelta(days=income_delay), end_date + datetime.timedelta(days=income_delay)))

        _, expenses_transactions = split_income_expenses(filter_transactions_period(transactions, start_date, end_date))