Use Amount objects, use the XML output in bal()
This commit is contained in:
		
							parent
							
								
									dd260aa021
								
							
						
					
					
						commit
						af6e28d168
					
				
					 2 changed files with 62 additions and 21 deletions
				
			
		|  | @ -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,20 +110,40 @@ 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 | ||||||
| 
 | 
 | ||||||
|  | @ -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()) | ||||||
|  |  | ||||||
|  | @ -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() | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Joar Wandborg
						Joar Wandborg