From 9d1e8af87522bece0b57099618f52466dc0826fe Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Mon, 18 May 2020 23:56:31 +1000 Subject: [PATCH] Ensure unique transaction IDs --- ledger_pyreport/__init__.py | 4 ++-- ledger_pyreport/jinja2/transactions.html | 2 +- .../jinja2/transactions_commodity.html | 2 +- ledger_pyreport/ledger.py | 16 +++++++++++++++- ledger_pyreport/model.py | 3 ++- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ledger_pyreport/__init__.py b/ledger_pyreport/__init__.py index 869aa2c..3551475 100644 --- a/ledger_pyreport/__init__.py +++ b/ledger_pyreport/__init__.py @@ -304,7 +304,7 @@ def transactions(): @app.route('/transaction') def transaction(): - tid = flask.request.args['tid'] + uuid = flask.request.args['uuid'] cash = flask.request.args.get('cash', False) commodity = flask.request.args.get('commodity', False) @@ -314,7 +314,7 @@ def transaction(): if cash: l = accounting.ledger_to_cash(l, report_commodity) - transaction = next((t for t in l.transactions if str(t.id) == tid)) + transaction = next((t for t in l.transactions if str(t.uuid) == uuid)) if commodity: total_dr = sum((p.amount for p in transaction.postings if p.amount > 0), Balance()).clean() diff --git a/ledger_pyreport/jinja2/transactions.html b/ledger_pyreport/jinja2/transactions.html index bfc9708..55e58f0 100644 --- a/ledger_pyreport/jinja2/transactions.html +++ b/ledger_pyreport/jinja2/transactions.html @@ -67,7 +67,7 @@ {% endif %} {% for transaction in transactions %} - {% set trn_url = '/transaction?' + {'tid': transaction.id, 'cash': 'on' if cash else ''}|urlencode %} + {% set trn_url = '/transaction?' + {'uuid': transaction.uuid, 'cash': 'on' if cash else ''}|urlencode %} {% if transaction.has_comment_detail %} diff --git a/ledger_pyreport/jinja2/transactions_commodity.html b/ledger_pyreport/jinja2/transactions_commodity.html index c8f08ce..38a002d 100644 --- a/ledger_pyreport/jinja2/transactions_commodity.html +++ b/ledger_pyreport/jinja2/transactions_commodity.html @@ -66,7 +66,7 @@ {% set ns.balance = opening_balance %} {% for transaction in transactions %} - {% set trn_url = '/transaction?' + {'tid': transaction.id, 'cash': 'on' if cash else ''}|urlencode %} + {% set trn_url = '/transaction?' + {'uuid': transaction.uuid, 'cash': 'on' if cash else ''}|urlencode %} {% for posting in transaction.postings if posting.account == account %} {% set ns.balance = ns.balance + posting.amount %} {% endfor %} diff --git a/ledger_pyreport/ledger.py b/ledger_pyreport/ledger.py index 805c417..fb7a4f4 100644 --- a/ledger_pyreport/ledger.py +++ b/ledger_pyreport/ledger.py @@ -20,6 +20,7 @@ from .model import * import csv from datetime import datetime, timedelta from decimal import Decimal +import hashlib import re import subprocess @@ -92,11 +93,24 @@ def raw_transactions_at_date(date): output = run_ledger_date(date, 'csv', '--csv-format', '%(quoted(parent.id)),%(quoted(format_date(date))),%(quoted(parent.code)),%(quoted(payee)),%(quoted(account)),%(quoted(display_amount)),%(quoted(comment)),%(quoted(state))\n') + uuids = set() + reader = csv.reader(output.splitlines(), dialect='ledger') for trn_id, date_str, code, payee, account_str, amount_str, comment, state_str in reader: if not ledger.transactions or trn_id != ledger.transactions[-1].id: - transaction = Transaction(ledger, trn_id, datetime.strptime(date_str, '%Y-%m-%d'), payee, code=code) + if trn_id in uuids: + digest = hashlib.sha256() + digest.update(trn_id.encode('utf-8')) + digest.update(date_str.encode('utf-8')) + digest.update(payee.encode('utf-8')) + uuid = digest.hexdigest() + else: + uuid = trn_id + + transaction = Transaction(ledger, trn_id, datetime.strptime(date_str, '%Y-%m-%d'), payee, code=code, uuid=uuid) ledger.transactions.append(transaction) + + uuids.add(uuid) else: # Transaction ID matches: continuation of previous transaction transaction = ledger.transactions[-1] diff --git a/ledger_pyreport/model.py b/ledger_pyreport/model.py index 838c536..ddb28ae 100644 --- a/ledger_pyreport/model.py +++ b/ledger_pyreport/model.py @@ -65,12 +65,13 @@ class Ledger: return max(prices, key=lambda p: p[0])[2] class Transaction: - def __init__(self, ledger, id, date, description, code=None): + def __init__(self, ledger, id, date, description, code=None, uuid=None): self.ledger = ledger self.id = id self.date = date self.description = description self.code = code + self.uuid = uuid self.postings = []