# Path: budgettracker/data.py
# class Account(namedtuple('Account', ['id', 'title', 'amount'])):
#     @classmethod
#     def from_dict(cls, dct):
#         return cls(**dct)
# 
#     def update(self, **kwargs):
#         return Account(**dict(self._asdict(), **kwargs))
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'title': self.title,
#             'amount': self.amount
#         }
# 
# class Transaction(namedtuple('Transaction', ['id', 'label', 'date', 'amount', 'account', 'categories', 'goal'])):
#     @classmethod
#     def from_dict(cls, dct):
#         return cls(
#             id=dct['id'],
#             label=dct['label'],
#             date=datetime.datetime.strptime(dct['date'], "%Y-%m-%d").date(),
#             amount=float(dct['amount']),
#             account=dct['account'],
#             categories=dct.get('categories') or [],
#             goal=dct.get('goal')
#         )
# 
#     def update(self, **kwargs):
#         return Transaction(**dict(self._asdict(), **kwargs))
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'label': self.label,
#             'date': self.date.isoformat(),
#             'amount': self.amount,
#             'account': self.account,
#             'categories': self.categories,
#             'goal': self.goal
#         }
# 
#     def to_str(self, famount):
#         return u"%s - %s = %s%s%s" % (self.date.isoformat(), self.label, famount(self.amount),
#             ' #%s' % ', #'.join(self.categories) if self.categories else '',
#             ' [%s%s]' % (famount(self.goal)) if self.goal else '')
# 
#     def __unicode__(self):
#         return self.to_str()
# 
# 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
# 
# 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)


import os, json, inspect, unicodecsv, codecs, datetime, re
from .data import Account, Transaction, period_to_months, filter_transactions_period
            writer = unicodecsv.writer(f)
            for tx in transactions:
                writer.writerow(self._transaction_to_csv_row(tx))

    def _csv_row_to_account(self, row):
        return Account(row[0], row[1], float(row[2]))

    def _csv_row_to_transaction(self, row):
        return Transaction(row[0], row[1], datetime.datetime.strptime(row[2], "%Y-%m-%d").date(),
            float(row[3]), row[4], filter(unicode.strip, row[5].split(',')), row[6] or None)

    def _transaction_to_csv_row(self, tx):
        return [tx.id, tx.label, tx.date.isoformat(), tx.amount, tx.account, ', '.join(tx.categories), tx.goal]


class JSONStorage(FileStorageBase):
    name = 'json'
    extension = 'json'

    def load_accounts(self):
        filename = self.get_accounts_filename()
        if not os.path.exists(filename):
            return []
        with codecs.open(filename) as f:
            return json.load(f, object_hook=lambda dct: Account.from_dict(dct))

    def load_transactions(self, filename):
        if not os.path.exists(filename):
            return []
        with codecs.open(filename) as f:

# Path: budgettracker/data.py
# class Account(namedtuple('Account', ['id', 'title', 'amount'])):
#     @classmethod
#     def from_dict(cls, dct):
#         return cls(**dct)
# 
#     def update(self, **kwargs):
#         return Account(**dict(self._asdict(), **kwargs))
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'title': self.title,
#             'amount': self.amount
#         }
# 
# class Transaction(namedtuple('Transaction', ['id', 'label', 'date', 'amount', 'account', 'categories', 'goal'])):
#     @classmethod
#     def from_dict(cls, dct):
#         return cls(
#             id=dct['id'],
#             label=dct['label'],
#             date=datetime.datetime.strptime(dct['date'], "%Y-%m-%d").date(),
#             amount=float(dct['amount']),
#             account=dct['account'],
#             categories=dct.get('categories') or [],
#             goal=dct.get('goal')
#         )
# 
#     def update(self, **kwargs):
#         return Transaction(**dict(self._asdict(), **kwargs))
# 
#     def to_dict(self):
#         return {
#             'id': self.id,
#             'label': self.label,
#             'date': self.date.isoformat(),
#             'amount': self.amount,
#             'account': self.account,
#             'categories': self.categories,
#             'goal': self.goal
#         }
# 
#     def to_str(self, famount):
#         return u"%s - %s = %s%s%s" % (self.date.isoformat(), self.label, famount(self.amount),
#             ' #%s' % ', #'.join(self.categories) if self.categories else '',
#             ' [%s%s]' % (famount(self.goal)) if self.goal else '')
# 
#     def __unicode__(self):
#         return self.to_str()
# 
# 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
# 
# 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)


# Path: budgettracker/storage.py
import os, json, inspect, unicodecsv, codecs, datetime, re
from .data import Account, Transaction, period_to_months, filter_transactions_period

            writer = unicodecsv.writer(f)
            for tx in transactions:
                writer.writerow(self._transaction_to_csv_row(tx))

    def _csv_row_to_account(self, row):
        return Account(row[0], row[1], float(row[2]))

    def _csv_row_to_transaction(self, row):
        return Transaction(row[0], row[1], datetime.datetime.strptime(row[2], "%Y-%m-%d").date(),
            float(row[3]), row[4], filter(unicode.strip, row[5].split(',')), row[6] or None)

    def _transaction_to_csv_row(self, tx):
        return [tx.id, tx.label, tx.date.isoformat(), tx.amount, tx.account, ', '.join(tx.categories), tx.goal]


class JSONStorage(FileStorageBase):
    name = 'json'
    extension = 'json'

    def load_accounts(self):
        filename = self.get_accounts_filename()
        if not os.path.exists(filename):
            return []
        with codecs.open(filename) as f:
            return json.load(f, object_hook=lambda dct: Account.from_dict(dct))

    def load_transactions(self, filename):
        if not os.path.exists(filename):
            return []
        with codecs.open(filename) as f:

            return json.load(f, object_hook=lambda dct: Transaction.from_dict(dct))