From d87d49fc00c90fac2a4cb41c0a94482be7585649 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 7 Jun 2020 23:57:26 +1000 Subject: [PATCH] Combine like postings in non-commodity transaction views --- ledger_pyreport/jinja2/transaction.html | 7 +++---- ledger_pyreport/jinja2/transactions.html | 13 ++++++------- ledger_pyreport/model.py | 24 ++++++++++++++++++------ 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/ledger_pyreport/jinja2/transaction.html b/ledger_pyreport/jinja2/transaction.html index 7816b0a..168f6e9 100644 --- a/ledger_pyreport/jinja2/transaction.html +++ b/ledger_pyreport/jinja2/transaction.html @@ -50,14 +50,13 @@ Cr - {% for posting in transaction.postings %} - {% set amount = posting.exchange(report_commodity, transaction.date) %} + {% for posting in transaction.exchange(report_commodity).postings %} {% set trn_url = '/transaction?' + {'tid': transaction.id, 'cash': 'on' if cash else ''}|urlencode %} {{ posting.comment }} {{ (posting.account.name|e).__str__().replace(':', ':')|safe }} - {% if amount > 0 %}{{ amount|b }}{% endif %} - {% if amount < 0 %}{{ -amount|b }}{% endif %} + {% if posting.amount > 0 %}{{ posting.amount|b }}{% endif %} + {% if posting.amount < 0 %}{{ -posting.amount|b }}{% endif %} {% endfor %} diff --git a/ledger_pyreport/jinja2/transactions.html b/ledger_pyreport/jinja2/transactions.html index 55e58f0..c6f82d1 100644 --- a/ledger_pyreport/jinja2/transactions.html +++ b/ledger_pyreport/jinja2/transactions.html @@ -99,8 +99,7 @@ {% endif %} {% endif %} - {% for posting in transaction.postings if posting.account != account %} - {% set amount = posting.exchange(report_commodity, transaction.date) %} + {% for posting in transaction.exchange(report_commodity).postings if posting.account != account %} {% set trn_first = not transaction.has_comment_detail and loop.first %} {% set trn_last = loop.last %} @@ -116,9 +115,9 @@ {{ (posting.account.name|e).__str__().replace(':', ':')|safe }} {% if account %} {# Reverse Dr/Cr so it's from the "perspective" of this account #} - {% set ns.balance = ns.balance - amount %} - {% if amount < 0 %}{{ -amount|b }}{% endif %} - {% if amount > 0 %}{{ amount|b }}{% endif %} + {% set ns.balance = ns.balance - posting.amount %} + {% if posting.amount < 0 %}{{ -posting.amount|b }}{% endif %} + {% if posting.amount > 0 %}{{ posting.amount|b }}{% endif %} {% if loop.last %} {% if ns.balance >= 0 %} @@ -129,8 +128,8 @@ {% endif %} {% else %} - {% if amount > 0 %}{{ amount|b }}{% endif %} - {% if amount < 0 %}{{ -amount|b }}{% endif %} + {% if posting.amount > 0 %}{{ posting.amount|b }}{% endif %} + {% if posting.amount < 0 %}{{ -posting.amount|b }}{% endif %} {% endif %} {% endfor %} diff --git a/ledger_pyreport/model.py b/ledger_pyreport/model.py index c6644e5..0ee15db 100644 --- a/ledger_pyreport/model.py +++ b/ledger_pyreport/model.py @@ -19,6 +19,7 @@ from .config import config from decimal import Decimal from enum import Enum import functools +import itertools class Ledger: def __init__(self, date): @@ -78,6 +79,10 @@ class Transaction: def __repr__(self): return ''.format(self.id, self.description) + @property + def has_comment_detail(self): + return any(p.comment for p in self.postings) + def describe(self): result = ['{:%Y-%m-%d} {}'.format(self.date, self.description)] for posting in self.postings: @@ -89,9 +94,16 @@ class Transaction: result.postings = [Posting(p.transaction, p.account, -p.amount, p.comment, p.state) for p in self.postings] return result - @property - def has_comment_detail(self): - return any(p.comment for p in self.postings) + def exchange(self, commodity): + result = Transaction(self.ledger, self.id, self.date, self.description, self.code, self.uuid) + + # Combine like postings + for k, g in itertools.groupby(self.postings, key=lambda p: (p.account, p.comment, p.state)): + account, comment, state = k + posting = Posting(result, account, sum(p.exchange(commodity).amount for p in g), comment, state) + result.postings.append(posting) + + return result class Posting: class State(Enum): @@ -109,11 +121,11 @@ class Posting: def __repr__(self): return ''.format(self.account.name, self.amount.tostr(False)) - def exchange(self, commodity, date): + def exchange(self, commodity): if self.amount.commodity.name == commodity.name: - return Amount(self.amount) + return self - return self.amount.exchange(commodity, True) # Cost basis + return Posting(self.transaction, self.account, self.amount.exchange(commodity, True), self.comment, self.state) # Cost basis class Account: def __init__(self, ledger, name):