Transaction listing report
This commit is contained in:
parent
bb66931b0e
commit
706ac8ae87
@ -51,7 +51,7 @@ def trial():
|
||||
else:
|
||||
total_cr -= balance
|
||||
|
||||
return flask.render_template('trial.html', date=date, trial_balance=trial_balance, total_dr=total_dr, total_cr=total_cr)
|
||||
return flask.render_template('trial.html', trial_balance=trial_balance, total_dr=total_dr, total_cr=total_cr)
|
||||
else:
|
||||
# Get multiple trial balances for comparison
|
||||
dates = [date.replace(year=date.year - i) for i in range(0, compare + 1)]
|
||||
@ -65,7 +65,7 @@ def trial():
|
||||
if all(t.get_balance(account.name) == 0 for t in trial_balances):
|
||||
accounts.remove(account)
|
||||
|
||||
return flask.render_template('trial_multiple.html', dates=dates, trial_balances=trial_balances, accounts=accounts)
|
||||
return flask.render_template('trial_multiple.html', trial_balances=trial_balances, accounts=accounts)
|
||||
|
||||
@app.route('/balance')
|
||||
def balance():
|
||||
@ -85,7 +85,7 @@ def balance():
|
||||
if all(b.get_balance(account.name) == 0 and b.get_total(account.name) == 0 for b in balance_sheets):
|
||||
accounts.remove(account)
|
||||
|
||||
return flask.render_template('balance.html', dates=dates, balance_sheets=balance_sheets, accounts=accounts, config=ledger.config)
|
||||
return flask.render_template('balance.html', balance_sheets=balance_sheets, accounts=accounts, config=ledger.config)
|
||||
|
||||
@app.route('/pandl')
|
||||
def pandl():
|
||||
@ -112,7 +112,32 @@ def pandl():
|
||||
else:
|
||||
period = 'period from {} to {}'.format(date_beg.strftime('%d %B %Y'), date_end.strftime('%d %B %Y'))
|
||||
|
||||
return flask.render_template('pandl.html', period=period, dates_end=dates_end, pandls=pandls, accounts=accounts, config=ledger.config)
|
||||
return flask.render_template('pandl.html', period=period, pandls=pandls, accounts=accounts, config=ledger.config)
|
||||
|
||||
@app.route('/transactions')
|
||||
def transactions():
|
||||
date = datetime.strptime(flask.request.args['date'], '%Y-%m-%d')
|
||||
pstart = datetime.strptime(flask.request.args['pstart'], '%Y-%m-%d')
|
||||
|
||||
trial_balance_pstart = ledger.trial_balance(pstart, pstart)
|
||||
account = trial_balance_pstart.get_account(flask.request.args['account'])
|
||||
opening_balance = trial_balance_pstart.get_balance(account.name)
|
||||
|
||||
balance = opening_balance
|
||||
transactions = account.get_transactions(date, pstart)
|
||||
for transaction in transactions:
|
||||
for posting in transaction.postings[:]:
|
||||
if posting.account == account.name:
|
||||
transaction.postings.remove(posting)
|
||||
else:
|
||||
posting.amount = -posting.amount # In terms of effect on this account
|
||||
balance += posting.amount
|
||||
posting.balance = balance
|
||||
|
||||
trial_balance = ledger.trial_balance(date, pstart)
|
||||
closing_balance = trial_balance.get_balance(account.name)
|
||||
|
||||
return flask.render_template('transactions.html', date=date, pstart=pstart, account=account, transactions=transactions, opening_balance=opening_balance, closing_balance=closing_balance)
|
||||
|
||||
@app.template_filter('a')
|
||||
def filter_amount(amt):
|
||||
|
@ -14,6 +14,9 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import csv
|
||||
from decimal import Decimal
|
||||
|
||||
from . import ledger
|
||||
|
||||
# Generate balance sheet
|
||||
|
@ -18,10 +18,16 @@
|
||||
|
||||
{% macro print_rows(account, invert=False, level=0) %}
|
||||
<tr>
|
||||
<td style="padding-left: calc(2px + {{ level }}em);">{{ account.bits[-1] }}</td>
|
||||
<td style="padding-left: calc(2px + {{ level }}em);">
|
||||
{% if balance_sheets|length == 1 %}
|
||||
<a href="/transactions?{{ {'date': balance_sheets[0].date.strftime('%Y-%m-%d'), 'pstart': balance_sheets[0].pstart.strftime('%Y-%m-%d'), 'account': account.name}|urlencode }}">{{ account.bits[-1] }}</a>
|
||||
{% else %}
|
||||
{{ account.bits[-1] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% for balance_sheet in balance_sheets %}
|
||||
{% set amount = balance_sheet.get_balance(account.name) * (-1 if invert else 1) %}
|
||||
<td>{% if amount != 0 %}{{ amount|a }}{% endif %}</td>
|
||||
<td>{% if amount != 0 %}<a href="/transactions?{{ {'date': balance_sheet.date.strftime('%Y-%m-%d'), 'pstart': balance_sheet.pstart.strftime('%Y-%m-%d'), 'account': account.name}|urlencode }}">{{ amount|a }}</a>{% endif %}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
@ -36,9 +42,9 @@
|
||||
<tr>
|
||||
{% if isfirst and year_headers %}
|
||||
<th class="h2">{{ account_class.bits[-1] }} {{ label }}</th>
|
||||
{% for date in dates %}<th class="h2">{{ date.strftime('%Y') }} </th>{% endfor %}
|
||||
{% for balance_sheet in balance_sheets %}<th class="h2">{{ balance_sheet.date.strftime('%Y') }} </th>{% endfor %}
|
||||
{% else %}
|
||||
<th class="h2" colspan="{{ dates|length + 1 }}">{{ account_class.bits[-1] }} {{ label }}</th>
|
||||
<th class="h2" colspan="{{ balance_sheets|length + 1 }}">{{ account_class.bits[-1] }} {{ label }}</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
@ -63,27 +69,27 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Balance Sheet as at {{ dates[0].strftime('%d %B %Y') }}</title>
|
||||
<title>Balance Sheet as at {{ balance_sheets[0].date.strftime('%d %B %Y') }}</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Balance Sheet</h1>
|
||||
<h2>As at {{ dates[0].strftime('%d %B %Y') }}</h2>
|
||||
<h2>As at {{ balance_sheets[0].date.strftime('%d %B %Y') }}</h2>
|
||||
|
||||
<table class="ledger">
|
||||
<table class="ledger onedesc">
|
||||
{# Assets #}
|
||||
<tr><th class="h1" colspan="{{ dates|length + 1 }}">Assets</th></tr>
|
||||
<tr><th class="h1" colspan="{{ balance_sheets|length + 1 }}">Assets</th></tr>
|
||||
{{ do_accounts(config['assets_account'], 'Assets', False, True) }}
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
|
||||
{# Liabilities #}
|
||||
<tr><th class="h1" colspan="{{ dates|length + 1 }}">Liabilities</th></tr>
|
||||
<tr><th class="h1" colspan="{{ balance_sheets|length + 1 }}">Liabilities</th></tr>
|
||||
{{ do_accounts(config['liabilities_account'], 'Liabilities', True, False) }}
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
|
||||
{# Equity #}
|
||||
<tr><th class="h1" colspan="{{ dates|length + 1 }}">Equity</th></tr>
|
||||
<tr><th class="h1" colspan="{{ balance_sheets|length + 1 }}">Equity</th></tr>
|
||||
|
||||
{% for account in balance_sheets[0].get_account(config['equity_account']).children if account in accounts %}
|
||||
{{ print_rows(account, invert=True) }}
|
||||
|
@ -29,7 +29,7 @@
|
||||
<label>Date: <input name="date" value="{{ date.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>Period start: <input name="pstart" value="{{ pstart.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>Compare <input name="compare" value="0" style="width: 2em;" oninput="txtc(this)"> periods</label>
|
||||
<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>
|
||||
{#<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>#}
|
||||
</form></li>
|
||||
|
||||
<li><form action="{{ url_for('balance') }}">
|
||||
@ -37,7 +37,7 @@
|
||||
<label>Date: <input name="date" value="{{ date.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>Period start: <input name="pstart" value="{{ pstart.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>Compare <input name="compare" value="0" style="width: 2em;" oninput="txtc(this)"> periods</label>
|
||||
<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>
|
||||
{#<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>#}
|
||||
</form></li>
|
||||
|
||||
<li><form action="{{ url_for('pandl') }}">
|
||||
@ -45,7 +45,7 @@
|
||||
<label>Begin date: <input name="date_beg" value="{{ pstart.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>End date: <input name="date_end" value="{{ date.strftime('%Y-%m-%d') }}" style="width: 6em;" oninput="txtc(this)"></label>
|
||||
<label>Compare <input name="compare" value="0" style="width: 2em;" oninput="txtc(this)"> periods</label>
|
||||
<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>
|
||||
{#<label><input name="cash" type="checkbox" oninput="chbc(this)"> Cash basis</label>#}
|
||||
</form></li>
|
||||
</ul>
|
||||
|
||||
|
@ -18,10 +18,16 @@
|
||||
|
||||
{% macro print_rows(account, invert=False, level=0) %}
|
||||
<tr>
|
||||
<td style="padding-left: calc(2px + {{ level }}em);">{{ account.bits[-1] }}</td>
|
||||
<td style="padding-left: calc(2px + {{ level }}em);">
|
||||
{% if pandls|length == 1 %}
|
||||
<a href="/transactions?{{ {'date': pandls[0].date.strftime('%Y-%m-%d'), 'pstart': pandls[0].pstart.strftime('%Y-%m-%d'), 'account': account.name}|urlencode }}">{{ account.bits[-1] }}</a>
|
||||
{% else %}
|
||||
{{ account.bits[-1] }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% for pandl in pandls %}
|
||||
{% set amount = pandl.get_balance(account.name) * (-1 if invert else 1) %}
|
||||
<td>{% if amount != 0 %}{{ amount|a }}{% endif %}</td>
|
||||
<td>{% if amount != 0 %}<a href="/transactions?{{ {'date': pandl.date.strftime('%Y-%m-%d'), 'pstart': pandl.pstart.strftime('%Y-%m-%d'), 'account': account.name}|urlencode }}">{{ amount|a }}</a>{% endif %}</td>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
|
||||
@ -34,10 +40,10 @@
|
||||
<tr>
|
||||
{% if year_headers %}
|
||||
{# CSS hackery to centre-align the heading #}
|
||||
<th class="h1" style="padding-left: calc(2px + {{ dates_end|length * 6 }}em);">{{ label }}</th>
|
||||
{% for date in dates_end %}<th class="h2">{{ date.strftime('%Y') }} </th>{% endfor %}
|
||||
<th class="h1" style="padding-left: calc(2px + {{ pandls|length * 6 }}em);">{{ label }}</th>
|
||||
{% for pandl in pandls %}<th class="h2">{{ pandl.date.strftime('%Y') }} </th>{% endfor %}
|
||||
{% else %}
|
||||
<th class="h1" colspan="{{ dates_end|length + 1 }}">{{ label }}</th>
|
||||
<th class="h1" colspan="{{ pandls|length + 1 }}">{{ label }}</th>
|
||||
{% endif %}
|
||||
</tr>
|
||||
|
||||
@ -63,7 +69,7 @@
|
||||
<h1>Income Statement</h1>
|
||||
<h2>For the {{ period }}</h2>
|
||||
|
||||
<table class="ledger">
|
||||
<table class="ledger onedesc">
|
||||
{{ do_accounts(config['income_account'], 'Income', True, True) }}
|
||||
<tr><td colspan="2"> </td></tr>
|
||||
|
||||
|
89
ledger_pyreport/jinja2/transactions.html
Normal file
89
ledger_pyreport/jinja2/transactions.html
Normal file
@ -0,0 +1,89 @@
|
||||
{#
|
||||
ledger-pyreport
|
||||
Copyright © 2020 Lee Yingtong Li (RunasSudo)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Account Transactions for {{ account.name }} as at {{ date.strftime('%d %B %Y') }}</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Account Transactions</h1>
|
||||
<h2 style="margin-bottom: 0;">For {{ account.name }}</h2>
|
||||
<h2>As at {{ date.strftime('%d %B %Y') }}</h2>
|
||||
|
||||
<table class="ledger">
|
||||
<tr>
|
||||
<th style="width: 5em;">Date</th>
|
||||
<th>Description</th>
|
||||
<th style="max-width: 8em;">Account</th>
|
||||
<th class="h1" style="text-align: right; width: 5em;">Dr</th>
|
||||
<th class="h1" style="text-align: right; width: 5em;">Cr</th>
|
||||
<th class="h1" style="text-align: right; width: 6em;">Balance</th>
|
||||
</tr>
|
||||
<tr class="total">
|
||||
<td>{{ pstart.strftime('%Y-%m-%d') }}</td>
|
||||
<td>Opening Balance</td>
|
||||
<td></td>
|
||||
<td style="text-align: right;"></td>
|
||||
<td style="text-align: right;"></td>
|
||||
<td style="text-align: right;">
|
||||
{% if opening_balance >= 0 %}
|
||||
{{ opening_balance|b }} Dr
|
||||
{% else %}
|
||||
{{ -opening_balance|b }} Cr
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% for transaction in transactions %}
|
||||
{% for posting in transaction.postings %}
|
||||
<tr>
|
||||
<td>{% if loop.index0 == 0 %}{{ transaction.date.strftime('%Y-%m-%d') }}{% endif %}</td>
|
||||
<td>{% if loop.index0 == 0 %}{{ transaction.payee }}{% endif %}</td>
|
||||
<td><a href="/transactions?{{ {'date': date.strftime('%Y-%m-%d'), 'pstart': pstart.strftime('%Y-%m-%d'), 'account': posting.account}|urlencode }}">{{ (posting.account|e).__str__().replace(':', ':<wbr>')|safe }}</a></td>
|
||||
<td style="text-align: right;">{% if posting.amount > 0 %}{{ posting.amount|b }}{% endif %}</td>
|
||||
<td style="text-align: right;">{% if posting.amount < 0 %}{{ -posting.amount|b }}{% endif %}</td>
|
||||
<td style="text-align: right;">
|
||||
{% if posting.balance >= 0 %}
|
||||
{{ posting.balance|b }} Dr
|
||||
{% else %}
|
||||
{{ -posting.balance|b }} Cr
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
<tr class="total">
|
||||
<td>{{ date.strftime('%Y-%m-%d') }}</td>
|
||||
<td>Closing Balance</td>
|
||||
<td></td>
|
||||
<td style="text-align: right;"></td>
|
||||
<td style="text-align: right;"></td>
|
||||
<td style="text-align: right;">
|
||||
{% if closing_balance >= 0 %}
|
||||
{{ closing_balance|b }} Dr
|
||||
{% else %}
|
||||
{{ -closing_balance|b }} Cr
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -20,15 +20,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Trial Balance as at {{ date.strftime('%d %B %Y') }}</title>
|
||||
<title>Trial Balance as at {{ trial_balance.date.strftime('%d %B %Y') }}</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Trial Balance</h1>
|
||||
<h2>As at {{ date.strftime('%d %B %Y') }}</h2>
|
||||
<h2>As at {{ trial_balance.date.strftime('%d %B %Y') }}</h2>
|
||||
|
||||
<table class="ledger">
|
||||
<table class="ledger onedesc">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="h1">Dr</th>
|
||||
@ -36,11 +36,12 @@
|
||||
</tr>
|
||||
{% for account in trial_balance.accounts.values() %}
|
||||
{% set balance = trial_balance.get_balance(account.name) %}
|
||||
{% set trn_url = "/transactions?" + {'date': trial_balance.date.strftime('%Y-%m-%d'), 'pstart': trial_balance.pstart.strftime('%Y-%m-%d'), 'account': account.name}|urlencode %}
|
||||
{% if balance != 0 %}
|
||||
<tr>
|
||||
<td>{{ account.name }}</td>
|
||||
<td>{% if balance > 0 %}{{ balance|b }}{% endif %}</td>
|
||||
<td>{% if balance < 0 %}{{ -balance|b }}{% endif %}</td>
|
||||
<td><a href="{{ trn_url }}">{{ account.name }}</a></td>
|
||||
<td>{% if balance > 0 %}<a href="{{ trn_url }}">{{ balance|b }}</a>{% endif %}</td>
|
||||
<td>{% if balance < 0 %}<a href="{{ trn_url }}">{{ -balance|b }}</a>{% endif %}</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
@ -20,18 +20,18 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Trial Balance as at {{ dates[0].strftime('%d %B %Y') }}</title>
|
||||
<title>Trial Balance as at {{ trial_balances[0].date.strftime('%d %B %Y') }}</title>
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" integrity="sha256-l85OmPOjvil/SOvVt3HnSSjzF1TUMyT9eV0c2BzEGzU=" crossorigin="anonymous">
|
||||
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Trial Balance</h1>
|
||||
<h2>As at {{ dates[0].strftime('%d %B %Y') }}</h2>
|
||||
<h2>As at {{ trial_balances[0].date.strftime('%d %B %Y') }}</h2>
|
||||
|
||||
<table class="ledger">
|
||||
<table class="ledger onedesc">
|
||||
<tr>
|
||||
<th></th>
|
||||
{% for date in dates %}<th class="h2">{{ date.strftime('%Y') }} </th>{% endfor %}
|
||||
{% for trial_balance in trial_balances %}<th class="h2">{{ trial_balance.date.strftime('%Y') }} </th>{% endfor %}
|
||||
</tr>
|
||||
{% for account in accounts %}
|
||||
<tr>
|
||||
|
@ -15,7 +15,7 @@
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import csv
|
||||
from datetime import timedelta
|
||||
from datetime import datetime, timedelta
|
||||
from decimal import Decimal
|
||||
import re
|
||||
import subprocess
|
||||
@ -28,7 +28,9 @@ with open('config.yml', 'r') as f:
|
||||
# Helper commands to run Ledger
|
||||
|
||||
def run_ledger(*args):
|
||||
proc = subprocess.Popen(['ledger', '--args-only', '--file', config['ledger_file'], '-X', config['report_currency'], '--unround'] + config['ledger_args'] + list(args), encoding='utf-8', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
ledger_args = ['ledger', '--args-only', '--file', config['ledger_file'], '-X', config['report_currency'], '--date-format', '%Y-%m-%d', '--unround'] + config['ledger_args'] + list(args)
|
||||
#print(' '.join(ledger_args))
|
||||
proc = subprocess.Popen(ledger_args, encoding='utf-8', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
stdout, stderr = proc.communicate()
|
||||
|
||||
if stderr:
|
||||
@ -98,24 +100,64 @@ class Account:
|
||||
@property
|
||||
def is_expense(self):
|
||||
return self.matches(config['expenses_account'])
|
||||
@property
|
||||
def is_cash(self):
|
||||
return any(self.matches(a) for a in config['cash_asset_accounts'])
|
||||
|
||||
#def get_balance(self, date, is_market=None):
|
||||
# if is_market is None:
|
||||
# if self.is_income or self.is_expense:
|
||||
# basis = '--cost'
|
||||
# else:
|
||||
# basis = '--market'
|
||||
# elif is_market == True:
|
||||
# basis = '--market'
|
||||
# else:
|
||||
# basis = '--cost'
|
||||
#
|
||||
# output = run_ledger_date(date, 'balance', '--balance-format', '%(display_total)', '--no-total', '--flat', '--empty', basis, '--limit', 'account=~/^{}$/'.format(re.escape(self.name).replace('/', '\\/')))
|
||||
#
|
||||
# return parse_amount(output)
|
||||
def get_transactions(self, date, pstart):
|
||||
transactions = []
|
||||
|
||||
output = run_ledger_date(date, 'register', '--no-rounding', '--register-format', '%(quoted(format_date(date))),%(quoted(payee)),%(quoted(account)),%(quoted(display_amount))\n', '--limit', 'account=~/^{}$/'.format(re.escape(self.name).replace('/', '\\/')), '--cost' if self.is_income or self.is_expense else '--market', '--related-all', '--no-revalued')
|
||||
|
||||
output += run_ledger_date(date, 'register', '--no-rounding', '--register-format', '%(quoted(format_date(date))),%(quoted(payee)),%(quoted(account)),%(quoted(display_amount))\n', '--limit', 'account=~/^{}$/'.format(re.escape(self.name).replace('/', '\\/')), '--cost' if self.is_income or self.is_expense else '--market', '--revalued-only')
|
||||
|
||||
reader = csv.reader(output.splitlines())
|
||||
for row in reader:
|
||||
t_date = datetime.strptime(row[0], '%Y-%m-%d')
|
||||
if t_date < pstart:
|
||||
continue
|
||||
|
||||
posting = Posting(row[2], parse_amount(row[3]))
|
||||
|
||||
if posting.account == '<Revalued>':
|
||||
posting.account = self.name
|
||||
|
||||
if transactions and t_date == transactions[-1].date and row[1] == transactions[-1].payee:
|
||||
# Posting for previous transaction
|
||||
transactions[-1].postings.append(posting)
|
||||
else:
|
||||
# New transaction
|
||||
transactions.append(Transaction(t_date, row[1], [posting]))
|
||||
|
||||
transactions.sort(key=lambda t: t.date)
|
||||
|
||||
# Balance transactions
|
||||
for transaction in transactions:
|
||||
t_total = sum(p.amount for p in transaction.postings)
|
||||
if t_total != 0:
|
||||
# Transaction requires balancing, probably due to unrealised gain/revaluation?
|
||||
transaction.postings.append(Posting(config['unrealized_gains'], -t_total))
|
||||
|
||||
return transactions
|
||||
|
||||
class Transaction:
|
||||
def __init__(self, date, payee, postings):
|
||||
self.date = date
|
||||
self.payee = payee
|
||||
self.postings = postings
|
||||
|
||||
class Posting:
|
||||
def __init__(self, account, amount):
|
||||
self.account = account
|
||||
self.amount = amount
|
||||
|
||||
self.balance = None
|
||||
|
||||
class Snapshot:
|
||||
def __init__(self):
|
||||
def __init__(self, date):
|
||||
self.date = date
|
||||
self.pstart = None
|
||||
|
||||
self.accounts = {}
|
||||
self.balances = {}
|
||||
|
||||
@ -170,7 +212,7 @@ def get_accounts():
|
||||
|
||||
# Raw Ledger output, unlikely to balance
|
||||
def get_raw_snapshot(date, basis=None):
|
||||
snapshot = Snapshot()
|
||||
snapshot = Snapshot(date)
|
||||
|
||||
# Get balances from Ledger
|
||||
output = (
|
||||
@ -206,10 +248,11 @@ def get_snapshot(date):
|
||||
# Ledger output, simulating closing of books
|
||||
def trial_balance(date, pstart):
|
||||
# Get balances at period start
|
||||
snapshot_pstart = get_snapshot(pstart)
|
||||
snapshot_pstart = get_snapshot(pstart - timedelta(days=1))
|
||||
|
||||
# Get balances at date
|
||||
snapshot = get_snapshot(date)
|
||||
snapshot.pstart = pstart
|
||||
|
||||
# Calculate Retained Earnings, and adjust income/expense accounts
|
||||
total_pandl = Decimal(0)
|
||||
|
@ -57,11 +57,21 @@ table.ledger tr.total td {
|
||||
border-bottom: 1pt solid black;
|
||||
}
|
||||
|
||||
table.ledger tr td:not(:first-child), table.ledger tr th:not(:first-child) {
|
||||
table.ledger.onedesc tr td:not(:first-child), table.ledger.onedesc tr th:not(:first-child) {
|
||||
text-align: right;
|
||||
width: 6em;
|
||||
}
|
||||
|
||||
table.ledger a {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
table.ledger a:hover {
|
||||
color: blue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
body {
|
||||
padding: 2em;
|
||||
|
Reference in New Issue
Block a user