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):