diff --git a/accounting/__init__.py b/accounting/__init__.py index ad8bf421630fb5280811858e396b6c9360265a44..537ce83640031334941d0ae19577592820a4752a 100644 --- a/accounting/__init__.py +++ b/accounting/__init__.py @@ -40,7 +40,6 @@ class Ledger: _log.info('Waiting for one second... %d/%d', i, timeout) time.sleep(1) - process = self.get_process() self.locked = True @@ -111,25 +110,45 @@ class Ledger: return output def bal(self): - output = self.send_command('bal --format "%A|%t\\\\n"') + output = self.send_command('xml') if output is None: raise RuntimeError('bal call returned no output') accounts = [] - for line in output.split(b'\n'): - try: - name, balance = line.decode('utf8').split('|') - except ValueError: - continue + xml = ElementTree.fromstring(output.decode('utf8')) - accounts.append(Account(name=name, balance=balance)) + accounts = self._recurse_accounts(xml.find('./accounts')) + + return accounts + + def _recurse_accounts(self, root): + accounts = [] + + for account in root.findall('./account'): + name = account.find('./fullname').text + + amounts = [] + + account_amounts = account.findall('./account-total/balance/amount') or \ + account.findall('./account-amount/amount') + + if account_amounts: + for amount in account_amounts: + quantity = amount.find('./quantity').text + symbol = amount.find('./commodity/symbol').text + + amounts.append(Amount(amount=quantity, symbol=symbol)) + + accounts.append(Account(name=name, + amounts=amounts, + accounts=self._recurse_accounts(account))) return accounts def reg(self): - output = self.send_command( 'xml') + output = self.send_command('xml') if output is None: raise RuntimeError('reg call returned no output') @@ -152,7 +171,8 @@ class Ledger: './post-amount/amount/commodity/symbol').text postings.append( - Posting(account=account, amount=amount, symbol=symbol)) + Posting(account=account, + amount=Amount(amount=amount, symbol=symbol))) entries.append( Transaction(date=date, payee=payee, postings=postings)) @@ -170,33 +190,44 @@ class Transaction: return ('<{self.__class__.__name__} {date}' + ' {self.payee} {self.postings}').format( self=self, - date=self.date.isoformat()) + date=self.date.strftime('%Y-%m-%d')) + class Posting: - def __init__(self, account=None, amount=None, symbol=None): + def __init__(self, account=None, amount=None): self.account = account self.amount = amount - self.symbol = symbol def __repr__(self): return ('<{self.__class__.__name__} "{self.account}"' + - ' {self.symbol} {self.amount}>').format(self=self) + ' {self.amount}>').format(self=self) + + +class Amount: + def __init__(self, amount=None, symbol=None): + self.amount = amount + self.symbol = symbol + + def __repr__(self): + return ('<{self.__class__.__name__} {self.symbol}' + + ' {self.amount}>').format(self=self) class Account: - def __init__(self, name=None, balance=None): + def __init__(self, name=None, amounts=None, accounts=None): self.name = name - self.balance = balance + self.amounts = amounts + self.accounts = accounts def __repr__(self): - return '<{self.__class__.__name__}: "{self.name}" {self.balance} >'.format( - self=self) + return ('<{self.__class__.__name__} "{self.name}" {self.amounts}' + + ' {self.accounts}>').format(self=self) def main(argv=None): if argv is None: argv = sys.argv - logging.basicConfig(level=logging.DEBUG) + logging.basicConfig(level=logging.INFO) ledger = Ledger(ledger_file='non-profit-test-data.ledger') print(ledger.bal()) print(ledger.reg()) diff --git a/accounting/web.py b/accounting/web.py index 4b155423823721dcdc18fa9d460e93d5f3606d2f..c3e1d8f58d9f5f700868e51b8135e0ecc82136f2 100644 --- a/accounting/web.py +++ b/accounting/web.py @@ -2,7 +2,7 @@ import logging from flask import Flask, g, jsonify, json -from accounting import Ledger, Account, Posting, Transaction +from accounting import Ledger, Account, Posting, Transaction, Amount logging.basicConfig(level=logging.DEBUG) @@ -11,12 +11,14 @@ app.config.from_pyfile('config.py') ledger = Ledger(ledger_file=app.config['LEDGER_FILE']) + class AccountingEncoder(json.JSONEncoder): def default(self, o): if isinstance(o, Account): return dict( name=o.name, - balance=o.balance + amounts=o.amounts, + accounts=o.accounts ) elif isinstance(o, Transaction): return dict( @@ -28,23 +30,31 @@ class AccountingEncoder(json.JSONEncoder): return dict( account=o.account, amount=o.amount, + ) + elif isinstance(o, Amount): + return dict( + amount=o.amount, symbol=o.symbol ) return json.JSONEncoder.default(self, o) + app.json_encoder = AccountingEncoder + @app.route('/') def index(): return 'Hello World!' + @app.route('/balance') def balance_report(): report_data = ledger.bal() return jsonify(balance_report=report_data) + @app.route('/register') def register_report(): report_data = ledger.reg()