Use Amount objects, use the XML output in bal()

This commit is contained in:
Joar Wandborg 2013-12-09 21:49:38 +01:00
parent dd260aa021
commit af6e28d168
2 changed files with 62 additions and 21 deletions

View file

@ -40,7 +40,6 @@ class Ledger:
_log.info('Waiting for one second... %d/%d', i, timeout) _log.info('Waiting for one second... %d/%d', i, timeout)
time.sleep(1) time.sleep(1)
process = self.get_process() process = self.get_process()
self.locked = True self.locked = True
@ -111,25 +110,45 @@ class Ledger:
return output return output
def bal(self): def bal(self):
output = self.send_command('bal --format "%A|%t\\\\n"') output = self.send_command('xml')
if output is None: if output is None:
raise RuntimeError('bal call returned no output') raise RuntimeError('bal call returned no output')
accounts = [] accounts = []
for line in output.split(b'\n'): xml = ElementTree.fromstring(output.decode('utf8'))
try:
name, balance = line.decode('utf8').split('|')
except ValueError:
continue
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 return accounts
def reg(self): def reg(self):
output = self.send_command( 'xml') output = self.send_command('xml')
if output is None: if output is None:
raise RuntimeError('reg call returned no output') raise RuntimeError('reg call returned no output')
@ -152,7 +171,8 @@ class Ledger:
'./post-amount/amount/commodity/symbol').text './post-amount/amount/commodity/symbol').text
postings.append( postings.append(
Posting(account=account, amount=amount, symbol=symbol)) Posting(account=account,
amount=Amount(amount=amount, symbol=symbol)))
entries.append( entries.append(
Transaction(date=date, payee=payee, postings=postings)) Transaction(date=date, payee=payee, postings=postings))
@ -170,33 +190,44 @@ class Transaction:
return ('<{self.__class__.__name__} {date}' + return ('<{self.__class__.__name__} {date}' +
' {self.payee} {self.postings}').format( ' {self.payee} {self.postings}').format(
self=self, self=self,
date=self.date.isoformat()) date=self.date.strftime('%Y-%m-%d'))
class Posting: class Posting:
def __init__(self, account=None, amount=None, symbol=None): def __init__(self, account=None, amount=None):
self.account = account self.account = account
self.amount = amount self.amount = amount
def __repr__(self):
return ('<{self.__class__.__name__} "{self.account}"' +
' {self.amount}>').format(self=self)
class Amount:
def __init__(self, amount=None, symbol=None):
self.amount = amount
self.symbol = symbol self.symbol = symbol
def __repr__(self): def __repr__(self):
return ('<{self.__class__.__name__} "{self.account}"' + return ('<{self.__class__.__name__} {self.symbol}' +
' {self.symbol} {self.amount}>').format(self=self) ' {self.amount}>').format(self=self)
class Account: class Account:
def __init__(self, name=None, balance=None): def __init__(self, name=None, amounts=None, accounts=None):
self.name = name self.name = name
self.balance = balance self.amounts = amounts
self.accounts = accounts
def __repr__(self): def __repr__(self):
return '<{self.__class__.__name__}: "{self.name}" {self.balance} >'.format( return ('<{self.__class__.__name__} "{self.name}" {self.amounts}' +
self=self) ' {self.accounts}>').format(self=self)
def main(argv=None): def main(argv=None):
if argv is None: if argv is None:
argv = sys.argv argv = sys.argv
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.INFO)
ledger = Ledger(ledger_file='non-profit-test-data.ledger') ledger = Ledger(ledger_file='non-profit-test-data.ledger')
print(ledger.bal()) print(ledger.bal())
print(ledger.reg()) print(ledger.reg())

View file

@ -2,7 +2,7 @@ import logging
from flask import Flask, g, jsonify, json 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) logging.basicConfig(level=logging.DEBUG)
@ -11,12 +11,14 @@ app.config.from_pyfile('config.py')
ledger = Ledger(ledger_file=app.config['LEDGER_FILE']) ledger = Ledger(ledger_file=app.config['LEDGER_FILE'])
class AccountingEncoder(json.JSONEncoder): class AccountingEncoder(json.JSONEncoder):
def default(self, o): def default(self, o):
if isinstance(o, Account): if isinstance(o, Account):
return dict( return dict(
name=o.name, name=o.name,
balance=o.balance amounts=o.amounts,
accounts=o.accounts
) )
elif isinstance(o, Transaction): elif isinstance(o, Transaction):
return dict( return dict(
@ -28,23 +30,31 @@ class AccountingEncoder(json.JSONEncoder):
return dict( return dict(
account=o.account, account=o.account,
amount=o.amount, amount=o.amount,
)
elif isinstance(o, Amount):
return dict(
amount=o.amount,
symbol=o.symbol symbol=o.symbol
) )
return json.JSONEncoder.default(self, o) return json.JSONEncoder.default(self, o)
app.json_encoder = AccountingEncoder app.json_encoder = AccountingEncoder
@app.route('/') @app.route('/')
def index(): def index():
return 'Hello World!' return 'Hello World!'
@app.route('/balance') @app.route('/balance')
def balance_report(): def balance_report():
report_data = ledger.bal() report_data = ledger.bal()
return jsonify(balance_report=report_data) return jsonify(balance_report=report_data)
@app.route('/register') @app.route('/register')
def register_report(): def register_report():
report_data = ledger.reg() report_data = ledger.reg()