Centralise commodity tracking logic

Per Ledger behaviour, commodities considered equivalent if same name regardless of whether prefix or suffix
Commodity display drawn from Ledger data, no longer explicitly specified in config
This commit is contained in:
RunasSudo 2020-04-04 04:28:43 +11:00
parent b200501e37
commit 3fa8f8a829
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
5 changed files with 28 additions and 21 deletions

View File

@ -1,7 +1,7 @@
# Set up how we will call Ledger
ledger_file: /path/to/ledger.journal
ledger_args: ['--pedantic', '--recursive-aliases']
report_commodity: ['$', True] # True if prefix, False if suffix
report_commodity: '$'
# Tell ledger-pyreport about the top-level account categories
assets_account: Assets

View File

@ -1,7 +1,7 @@
# Set up how we will call Ledger
ledger_file: demo/ledger.journal
ledger_args: []
report_commodity: ['$', True] # True if prefix, False if suffix
report_commodity: '$'
# Tell ledger-pyreport about the top-level account categories
assets_account: Assets

View File

@ -40,11 +40,10 @@ def trial():
compare = int(flask.request.args['compare'])
cash = flask.request.args.get('cash', False)
report_commodity = Commodity(*config['report_commodity'])
if compare == 0:
# Get trial balance
l = ledger.raw_transactions_at_date(date)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
trial_balance = accounting.trial_balance(l, date, pstart, report_commodity)
@ -67,6 +66,7 @@ def trial():
pstarts = [pstart.replace(year=pstart.year - i) for i in range(0, compare + 1)]
l = ledger.raw_transactions_at_date(date)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
trial_balances = [accounting.trial_balance(l.clone(), d, p, report_commodity) for d, p in zip(dates, pstarts)]
@ -89,8 +89,8 @@ def balance():
dates = [date.replace(year=date.year - i) for i in range(0, compare + 1)]
pstarts = [pstart.replace(year=pstart.year - i) for i in range(0, compare + 1)]
report_commodity = Commodity(*config['report_commodity'])
l = ledger.raw_transactions_at_date(date)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
balance_sheets = [accounting.balance_sheet(accounting.trial_balance(l.clone(), d, p, report_commodity)) for d, p in zip(dates, pstarts)]
@ -122,8 +122,8 @@ def pandl():
dates_beg = [date_beg.replace(year=date_beg.year - i) for i in range(0, compare + 1)]
dates_end = [date_end.replace(year=date_end.year - i) for i in range(0, compare + 1)]
report_commodity = Commodity(*config['report_commodity'])
l = ledger.raw_transactions_at_date(date_end)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
pandls = [accounting.trial_balance(l.clone(), de, db, report_commodity) for de, db in zip(dates_end, dates_beg)]
@ -146,8 +146,8 @@ def cashflow():
dates_beg = [date_beg.replace(year=date_beg.year - i) for i in range(0, compare + 1)]
dates_end = [date_end.replace(year=date_end.year - i) for i in range(0, compare + 1)]
report_commodity = Commodity(*config['report_commodity'])
l = ledger.raw_transactions_at_date(date_end)
report_commodity = l.get_commodity(config['report_commodity'])
cash_accounts = [a for a in l.accounts.values() if a.is_cash]
@ -193,10 +193,9 @@ def transactions():
cash = flask.request.args.get('cash', False)
commodity = flask.request.args.get('commodity', False)
report_commodity = Commodity(*config['report_commodity'])
# General ledger
l = ledger.raw_transactions_at_date(date_end)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
@ -240,10 +239,9 @@ def transaction():
cash = flask.request.args.get('cash', False)
commodity = flask.request.args.get('commodity', False)
report_commodity = Commodity(*config['report_commodity'])
# General ledger
l = ledger.raw_transactions_at_date(None)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)
@ -326,9 +324,8 @@ def debug_noncash_transactions():
pstart = datetime.strptime(flask.request.args['pstart'], '%Y-%m-%d')
account = flask.request.args.get('account')
report_commodity = Commodity(*config['report_commodity'])
l = ledger.raw_transactions_at_date(date)
report_commodity = l.get_commodity(config['report_commodity'])
account = l.get_account(account)
transactions = [t for t in l.transactions if any(p.account == account for p in t.postings)]
@ -343,9 +340,8 @@ def debug_imbalances():
pstart = datetime.strptime(flask.request.args['pstart'], '%Y-%m-%d')
cash = flask.request.args.get('cash', False)
report_commodity = Commodity(*config['report_commodity'])
l = ledger.raw_transactions_at_date(date)
report_commodity = l.get_commodity(config['report_commodity'])
if cash:
l = accounting.ledger_to_cash(l, report_commodity)

View File

@ -104,7 +104,11 @@ def raw_transactions_at_date(date):
if ';' in comment:
comment = comment[comment.index(';')+1:].strip()
posting = Posting(transaction, ledger.get_account(account_str), parse_amount(amount_str), comment=comment)
amount = parse_amount(amount_str)
posting = Posting(transaction, ledger.get_account(account_str), amount, comment=comment)
transaction.postings.append(posting)
if amount.commodity.name not in ledger.commodities:
ledger.commodities[amount.commodity.name] = amount.commodity.strip_price()
return ledger

View File

@ -27,6 +27,7 @@ class Ledger:
self.accounts = {}
self.transactions = []
self.commodities = {}
self.prices = []
def clone(self):
@ -51,6 +52,9 @@ class Ledger:
return account
def get_commodity(self, name):
return self.commodities[name]
def get_price(self, commodity_from, commodity_to, date):
prices = [p for p in self.prices if p[1] == commodity_from.name and p[2].commodity == commodity_to and p[0].date() <= date.date()]
@ -89,7 +93,7 @@ class Posting:
return '<Posting "{}" {}>'.format(self.account.name, self.amount.tostr(False))
def exchange(self, commodity, date):
if self.amount.commodity.name == commodity.name and self.amount.commodity.is_prefix == commodity.is_prefix:
if self.amount.commodity.name == commodity.name:
return Amount(self.amount)
return self.amount.exchange(commodity, True) # Cost basis
@ -235,10 +239,10 @@ class Amount:
return Amount(other - self.amount, self.commodity)
def exchange(self, commodity, is_cost, price=None):
if self.commodity.name == commodity.name and self.commodity.is_prefix == commodity.is_prefix:
if self.commodity.name == commodity.name:
return Amount(self)
if is_cost and self.commodity.price and self.commodity.price.commodity.name == commodity.name and self.commodity.price.commodity.is_prefix == commodity.is_prefix:
if is_cost and self.commodity.price and self.commodity.price.commodity.name == commodity.name:
return Amount(self.amount * self.commodity.price.amount, commodity)
if price:
@ -268,7 +272,7 @@ class Balance:
def exchange(self, commodity, is_cost, date=None, ledger=None):
result = Amount(0, commodity)
for amount in self.amounts:
if is_cost or (amount.commodity.name == commodity.name and amount.commodity.is_prefix == amount.commodity.is_prefix):
if is_cost or amount.commodity.name == commodity.name:
result += amount.exchange(commodity, is_cost)
else:
if any(p[1] == amount.commodity.name for p in ledger.prices):
@ -338,7 +342,10 @@ class Commodity:
def __eq__(self, other):
if not isinstance(other, Commodity):
return False
return self.name == other.name and self.is_prefix == other.is_prefix and self.price == other.price
return self.name == other.name and self.price == other.price
def strip_price(self):
return Commodity(self.name, self.is_prefix)
class TrialBalance:
def __init__(self, ledger, date, pstart):