File diff 124bd1706d79 → f2b9decf2752
accounting/storage/ledgercli.py
Show inline comments
...
 
@@ -5,25 +5,28 @@ import time
 

	
 
from datetime import datetime
 
from xml.etree import ElementTree
 
from contextlib import contextmanager
 

	
 
from accounting.models import Account, Transaction, Posting, Amount
 
from accounting.storage import Storage
 

	
 
_log = logging.getLogger(__name__)
 

	
 

	
 
class Ledger(Storage):
 
    def __init__(self, ledger_file=None, ledger_bin=None):
 
    def __init__(self, app=None, ledger_file=None, ledger_bin=None):
 
        if app:
 
            ledger_file = app.config['LEDGER_FILE']
 

	
 
        if ledger_file is None:
 
            raise ValueError('ledger_file cannot be None')
 

	
 
        self.ledger_bin = ledger_bin or 'ledger'
 
        self.ledger_file = ledger_file
 
        _log.info('ledger file: %s', ledger_file)
 

	
 
        self.locked = False
 
        self.ledger_process = None
 

	
 
    @contextmanager
 
    def locked_process(self):
...
 
@@ -149,45 +152,48 @@ class Ledger(Storage):
 
            self.ledger_process.wait()
 
            self.ledger_process = None
 

	
 
            return output
 

	
 
    def add_transaction(self, transaction):
 
        '''
 
        Writes a transaction to the ledger file by opening it in 'ab' mode and
 
        writing a ledger transaction based on the
 
        :class:`~accounting.models.Transaction` instance in
 
        :data:`transaction`.
 
        '''
 
        if not transaction.metadata.get('Id'):
 
        if transaction.id is None:
 
            _log.debug('No ID found. Generating an ID.')
 
            transaction.generate_id()
 

	
 
        transaction.metadata.update({'Id': transaction.id})
 

	
 
        transaction_template = ('\n{date} {t.payee}\n'
 
                                '{tags}'
 
                                '{metadata}'
 
                                '{postings}')
 

	
 
        metadata_template = '   ;{0}: {1}\n'
 

	
 
        # TODO: Generate metadata for postings
 
        posting_template = ('  {account} {p.amount.symbol}'
 
                            ' {p.amount.amount}\n')
 

	
 
        output = b''
 

	
 
        # XXX: Even I hardly understands what this does, however I indent it it
 
        # stays unreadable.
 
        output += transaction_template.format(
 
            date=transaction.date.strftime('%Y-%m-%d'),
 
            t=transaction,
 
            tags=''.join([
 
            metadata=''.join([
 
                metadata_template.format(k, v)
 
                for k, v in transaction.metadata.items()]),
 
            postings=''.join([posting_template.format(
 
                p=p,
 
                account=p.account + ' ' * (
 
                    80 - (len(p.account) + len(p.amount.symbol) +
 
                          len(str(p.amount.amount)) + 1 + 2)
 
                )) for p in transaction.postings
 
            ])
 
        ).encode('utf8')
 

	
 
        with open(self.ledger_file, 'ab') as f:
...
 
@@ -230,24 +236,27 @@ class Ledger(Storage):
 
                    symbol = amount.find('./commodity/symbol').text
 

	
 
                    amounts.append(Amount(amount=quantity, symbol=symbol))
 
            else:
 
                _log.warning('Account %s does not have any amounts', name)
 

	
 
            accounts.append(Account(name=name,
 
                                    amounts=amounts,
 
                                    accounts=self._recurse_accounts(account)))
 

	
 
        return accounts
 

	
 
    def get_transactions(self):
 
        return self.reg()
 

	
 
    def reg(self):
 
        output = self.send_command('xml')
 

	
 
        if output is None:
 
            raise RuntimeError('reg call returned no output')
 

	
 
        entries = []
 

	
 
        reg_xml = ElementTree.fromstring(output.decode('utf8'))
 

	
 
        for transaction in reg_xml.findall('./transactions/transaction'):
 
            date = datetime.strptime(transaction.find('./date').text,
...
 
@@ -292,24 +301,27 @@ class Ledger(Storage):
 
                    _log.debug('metadata: %s: %s', key, value)
 

	
 
                    metadata.update({key: value})
 

	
 
            # Add a Transaction instance to the list
 
            id = metadata.pop('Id')
 
            entries.append(
 
                Transaction(id=id, date=date, payee=payee, postings=postings,
 
                            metadata=metadata))
 

	
 
        return entries
 

	
 
    def update_transaction(self, transaction):
 
        _log.debug('DUMMY: Updated transaction: %s', transaction)
 

	
 

	
 
def main(argv=None):
 
    import argparse
 
    if argv is None:
 
        argv = sys.argv
 

	
 
    parser = argparse.ArgumentParser()
 
    parser.add_argument('-v', '--verbosity',
 
                        default='INFO',
 
                        help=('Filter logging output. Possible values:' +
 
                              ' CRITICAL, ERROR, WARNING, INFO, DEBUG'))