Visual improvements, add navbar

This commit is contained in:
RunasSudo 2022-12-24 16:57:53 +11:00
parent b34ec8473e
commit cf92c9b638
Signed by: RunasSudo
GPG Key ID: 7234E476BF21C61A
10 changed files with 316 additions and 272 deletions

View File

@ -80,6 +80,9 @@ class TrialBalancer:
# TODO: Keep a record of internal transactions? # TODO: Keep a record of internal transactions?
if source_account not in self.accounts:
return
if destination_account not in self.accounts: if destination_account not in self.accounts:
self.accounts[destination_account] = Amount(0, '$') # FIXME: Other commodities self.accounts[destination_account] = Amount(0, '$') # FIXME: Other commodities

View File

@ -25,6 +25,17 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css" integrity="sha256-4RctOgogjPAdwGbwq+rxfwAmSpZhWaafcZR9btzUk18=" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.2/font/bootstrap-icons.css" integrity="sha256-4RctOgogjPAdwGbwq+rxfwAmSpZhWaafcZR9btzUk18=" crossorigin="anonymous">
</head> </head>
<body> <body>
{% block body %}{% endblock %} {% block body %}
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="/">DrCr</a>
</div>
</nav>
<div class="container">
{% block content %}{% endblock %}
</div>
{% endblock %}
{% block scripts %}{% endblock %}
</body> </body>
</html> </html>

View File

@ -18,38 +18,36 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}General journal{% endblock %} {% block title %}General journal{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">General journal</h1>
<h1 class="h2 mt-4 mb-4">General journal</h1>
<table class="table"> <table class="table">
<thead> <thead>
<tr>
<th>Date</th>
<th colspan="2">Description</th>
<th>Dr</th>
<th>Cr</th>
</tr>
</thead>
<tbody>
{% for transaction in transactions %}
<tr> <tr>
<th>Date</th> <td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<th colspan="2">Description</th> <td colspan="2">{{ transaction.description }}</td>
<th>Dr</th> <td></td>
<th>Cr</th> <td></td>
</tr> </tr>
</thead> {% for posting in transaction.postings %}
<tbody>
{% for transaction in transactions %}
<tr> <tr>
<td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<td colspan="2">{{ transaction.description }}</td>
<td></td>
<td></td> <td></td>
<td>{{ posting.description or '' }}</td>
<td><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i> {{ posting.account }}</td>
<td>{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td>{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
</tr> </tr>
{% for posting in transaction.postings %}
<tr>
<td></td>
<td>{{ posting.description or '' }}</td>
<td><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i> {{ posting.account }}</td>
<td>{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td>{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
</tr>
{% endfor %}
{% endfor %} {% endfor %}
</tbody> {% endfor %}
</table> </tbody>
</div> </table>
{% endblock %} {% endblock %}

View File

@ -18,38 +18,36 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}General ledger{% endblock %} {% block title %}General ledger{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">General ledger</h1>
<h1 class="h2 mt-4 mb-4">General ledger</h1>
<table class="table"> <table class="table">
<thead> <thead>
<tr>
<th>Date</th>
<th colspan="2">Description</th>
<th>Dr</th>
<th>Cr</th>
</tr>
</thead>
<tbody>
{% for transaction in transactions %}
<tr> <tr>
<th>Date</th> <td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<th colspan="2">Description</th> <td colspan="2">{{ transaction.description }}</td>
<th>Dr</th> <td></td>
<th>Cr</th> <td></td>
</tr> </tr>
</thead> {% for posting in transaction.postings %}
<tbody>
{% for transaction in transactions %}
<tr> <tr>
<td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<td colspan="2">{{ transaction.description }}</td>
<td></td>
<td></td> <td></td>
<td>{{ posting.description or '' }}</td>
<td><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i> {{ posting.account }}</td>
<td>{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td>{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
</tr> </tr>
{% for posting in transaction.postings %}
<tr>
<td></td>
<td>{{ posting.description or '' }}</td>
<td><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i> {{ posting.account }}</td>
<td>{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td>{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
</tr>
{% endfor %}
{% endfor %} {% endfor %}
</tbody> {% endfor %}
</table> </tbody>
</div> </table>
{% endblock %} {% endblock %}

38
drcr/templates/index.html Normal file
View File

@ -0,0 +1,38 @@
{# DrCr: Web-based double-entry bookkeeping framework
Copyright (C) 2022 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/>.
#}
{% extends 'base.html' %}
{% block title %}DrCr{% endblock %}
{% block content %}
<h1 class="h2 my-4">Data sources</h1>
<ul>
<li><a href="/general-journal">General journal</a></li>
<li><a href="/statement-lines">Statement lines</a></li>
</ul>
<h1 class="h2 my-4">General reports</h1>
<ul>
<li><a href="/general-ledger">General ledger</a></li>
<li><a href="/trial-balance">Trial balance</a></li>
</ul>
<h1 class="h2 my-4">Advanced reports</h1>
<ul>
<li><a href="/reports/balance-sheet">Balance sheet</a></li>
</ul>
{% endblock %}

View File

@ -18,99 +18,99 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Edit statement line charge{% endblock %} {% block title %}Edit statement line charge{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">Statement line</h1>
<h1 class="h2 mt-4 mb-4">Statement line</h1>
<table class="table">
<thead>
<tr>
<th>Source account</th>
<th>Date</th>
<th>Description</th>
<th>Dr</th>
<th>Cr</th>
<th>Balance</th>
</tr>
</thead>
<tbody>
<tr id="statement-line" data-quantity="{{ statement_line.amount().quantity_string() }}" data-commodity="{{ statement_line.commodity }}">
<td>{{ statement_line.source_account }}</td>
<td>{{ statement_line.dt.strftime('%Y-%m-%d') }}</td>
<td>{{ statement_line.description }}</td>
<td>{{ statement_line.amount().format() if statement_line.quantity >= 0 else '' }}</td>
<td>{{ (statement_line.amount()|abs).format() if statement_line.quantity < 0 else '' }}</td>
<td>{{ statement_line.balance or '' }}</td>
</tr>
</tbody>
</table>
<h1 class="h2 mt-4 mb-4">Transaction</h1>
<form method="POST">
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Source account</th>
<th>Date</th> <th>Date</th>
<th>Description</th> <th colspan="2">Description</th>
<th>Dr</th> <th>Dr</th>
<th>Cr</th> <th>Cr</th>
<th>Balance</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr id="statement-line" data-quantity="{{ statement_line.amount().quantity_string() }}" data-commodity="{{ statement_line.commodity }}"> {# FIXME: Customise date, etc. #}
<td>{{ statement_line.source_account }}</td> <tr>
<td>{{ statement_line.dt.strftime('%Y-%m-%d') }}</td> <td>{{ statement_line.dt.strftime('%Y-%m-%d') }}</td>
<td>{{ statement_line.description }}</td> <td colspan="2"><input type="text" name="description" value="{{ statement_line.description }}" class="w-100"></td>
<td>{{ statement_line.amount().format() if statement_line.quantity >= 0 else '' }}</td> <td></td>
<td>{{ (statement_line.amount()|abs).format() if statement_line.quantity < 0 else '' }}</td> <td></td>
<td>{{ statement_line.balance or '' }}</td> </tr>
<tr data-side="source">
{# Source line #}
<td></td>
<td></td>
<td><i>{{ 'Dr' if statement_line.quantity >= 0 else 'Cr' }}</i> {{ statement_line.source_account }} {#<a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a>#}</td>
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{# Charge lines #}
{% if transaction == None %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{% elif transaction.postings|length == 2 %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account" value="{{ transaction.charge_account(statement_line.source_account) }}"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{% else %}
{% for posting in transaction.postings if posting.account != statement_line.source_account %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account" value="{{ posting.account }}"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ posting.commodity }}<input type="number" name="charge-amount" step="0.01" value="{{ posting.amount().quantity_string() }}"></td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ posting.commodity }}<input type="number" name="charge-amount" step="0.01" value="{{ (posting.amount()|abs).quantity_string() }}"></td>{% else %}<td></td>{% endif %}
</tr>
{% endfor %}
{% endif %}
</tr> </tr>
</tbody> </tbody>
</table> </table>
<h1 class="h2 mt-4 mb-4">Transaction</h1> <div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary">Save</button>
<form method="POST"> </div>
<table class="table"> </form>
<thead> {% endblock %}
<tr>
<th>Date</th>
<th colspan="2">Description</th>
<th>Dr</th>
<th>Cr</th>
</tr>
</thead>
<tbody>
{# FIXME: Customise date, etc. #}
<tr>
<td>{{ statement_line.dt.strftime('%Y-%m-%d') }}</td>
<td colspan="2"><input type="text" name="description" value="{{ statement_line.description }}" class="w-100"></td>
<td></td>
<td></td>
</tr>
<tr data-side="source">
{# Source line #}
<td></td>
<td></td>
<td><i>{{ 'Dr' if statement_line.quantity >= 0 else 'Cr' }}</i> {{ statement_line.source_account }} {#<a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a>#}</td>
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{# Charge lines #}
{% if transaction == None %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{% elif transaction.postings|length == 2 %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account" value="{{ transaction.charge_account(statement_line.source_account) }}"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ (statement_line.amount()|abs).format() }}</td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ statement_line.amount().format() }}</td>{% else %}<td></td>{% endif %}
</tr>
{% else %}
{% for posting in transaction.postings if posting.account != statement_line.source_account %}
<tr data-side="charge">
<td></td>
<td></td>
<td><i>{{ 'Cr' if statement_line.quantity >= 0 else 'Dr' }}</i> <input type="text" name="charge-account" value="{{ posting.account }}"> <a class="text-primary" href="#" onclick="addPosting(this);return false;"><i class="bi bi-plus-circle-fill"></i></a></td>
{% if statement_line.quantity < 0 %}<td class="has-amount">{{ posting.commodity }}<input type="number" name="charge-amount" step="0.01" value="{{ posting.amount().quantity_string() }}"></td>{% else %}<td></td>{% endif %}
{% if statement_line.quantity >= 0 %}<td class="has-amount">{{ posting.commodity }}<input type="number" name="charge-amount" step="0.01" value="{{ (posting.amount()|abs).quantity_string() }}"></td>{% else %}<td></td>{% endif %}
</tr>
{% endfor %}
{% endif %}
</tr>
</tbody>
</table>
<div class="d-flex justify-content-end">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
</div>
{% block scripts %}
<script> <script>
function addPosting(el) { function addPosting(el) {
let trPosting = el.parentNode.parentNode; let trPosting = el.parentNode.parentNode;

View File

@ -18,55 +18,55 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Statement lines{% endblock %} {% block title %}Statement lines{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">Statement lines</h1>
<h1 class="h2 mt-4 mb-4">Statement lines</h1>
<form method="POST"> <form method="POST">
<div class="mb-2"> <div class="mb-2">
<button type="submit" class="btn btn-outline-secondary" formaction="/statement-lines/reconcile-transfer">Reconcile selected as transfer</button> <button type="submit" class="btn btn-outline-secondary" formaction="/statement-lines/reconcile-transfer">Reconcile selected as transfer</button>
</div> </div>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th></th> <th></th>
<th>Source account</th> <th>Source account</th>
<th>Date</th> <th>Date</th>
<th>Description</th> <th>Description</th>
<th>Charged to</th> <th>Charged to</th>
<th>Dr</th> <th>Dr</th>
<th>Cr</th> <th>Cr</th>
<th>Balance</th> <th>Balance</th>
</tr>
</thead>
<tbody>
{% for line in statement_lines %}
<tr data-line-id="{{ line.id }}">
<td><input type="checkbox" name="sel-line-id" value="{{ line.id }}"></td>
<td>{{ line.source_account }}</td>
<td>{{ line.dt.strftime('%Y-%m-%d') }}</td>
<td>{{ line.description }}</td>
<td class="charge-account">
{% if line.postings|length == 0 %}
<a href="#" class="text-danger" onclick="classifyLine({{ line.id }});return false;">Unclassified</a>
{% elif line.is_complex() %}
<i>(Complex)</i>
{% else %}
<a href="#" class="text-body" onclick="classifyLine({{ line.id }});return false;">{{ line.postings[0].transaction.charge_account(line.source_account) }}</a>
{% endif %}
<a href="/statement-lines/edit-transaction?line-id={{ line.id }}" class="text-muted"><i class="bi bi-pencil"></i></a>
</td>
<td>{{ line.amount().format() if line.quantity >= 0 else '' }}</td>
<td>{{ (line.amount()|abs).format() if line.quantity < 0 else '' }}</td>
<td>{{ line.balance or '' }}</td>
</tr> </tr>
</thead> {% endfor %}
<tbody> </tbody>
{% for line in statement_lines %} </table>
<tr data-line-id="{{ line.id }}"> </form>
<td><input type="checkbox" name="sel-line-id" value="{{ line.id }}"></td> {% endblock %}
<td>{{ line.source_account }}</td>
<td>{{ line.dt.strftime('%Y-%m-%d') }}</td>
<td>{{ line.description }}</td>
<td class="charge-account">
{% if line.postings|length == 0 %}
<a href="#" class="text-danger" onclick="classifyLine({{ line.id }});return false;">Unclassified</a>
{% elif line.is_complex() %}
<i>(Complex)</i>
{% else %}
<a href="#" class="text-body" onclick="classifyLine({{ line.id }});return false;">{{ line.postings[0].transaction.charge_account(line.source_account) }}</a>
{% endif %}
<a href="/statement-lines/edit-transaction?line-id={{ line.id }}" class="text-muted"><i class="bi bi-pencil"></i></a>
</td>
<td>{{ line.amount().format() if line.quantity >= 0 else '' }}</td>
<td>{{ (line.amount()|abs).format() if line.quantity < 0 else '' }}</td>
<td>{{ line.balance or '' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
{% block scripts %}
<script> <script>
function classifyLine(lineId) { function classifyLine(lineId) {
let chargeAccount = prompt('Charge to:'); let chargeAccount = prompt('Charge to:');

View File

@ -18,72 +18,70 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Account transactions{% endblock %} {% block title %}Account transactions{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">Account transactions</h1>
<h1 class="h2 mt-4 mb-4">Account transactions</h1>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Date</th> <th>Date</th>
<th>Description</th> <th>Description</th>
<th>Related Account</th> <th>Related Account</th>
<th class="text-end">Dr</th> <th class="text-end">Dr</th>
<th class="text-end">Cr</th> <th class="text-end">Cr</th>
<th class="text-end">Balance</th> <th class="text-end">Balance</th>
<th></th> <th></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for transaction in transactions %} {% for transaction in transactions %}
{% if transaction.postings|length == 2 %} {% if transaction.postings|length == 2 %}
{% for posting in transaction.postings if posting.account == account %} {% for posting in transaction.postings if posting.account == account %}
{% set _ = running_total.__setattr__('quantity', running_total.quantity + posting.quantity) %} {% set _ = running_total.__setattr__('quantity', running_total.quantity + posting.quantity) %}
<tr>
<td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<td>{{ transaction.description }}</td>
<td>{% for p in transaction.postings if p.account != account %}{{ p.account }}{% endfor %}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td class="text-end">{{ (running_total|abs).format() }}</td>
<td>{{ 'Dr' if running_total.quantity >= 0 else 'Cr' }}</td>
</tr>
{% endfor %}
{% else %}
<tr> <tr>
<td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td> <td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<td colspan="2">{{ transaction.description }}</td> <td>{{ transaction.description }}</td>
<td>{% for p in transaction.postings if p.account != account %}{{ p.account }}{% endfor %}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td class="text-end">{{ (running_total|abs).format() }}</td>
<td>{{ 'Dr' if running_total.quantity >= 0 else 'Cr' }}</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>{{ transaction.dt.strftime('%Y-%m-%d') }}</td>
<td colspan="2">{{ transaction.description }}</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
{% for posting in transaction.postings if posting.account == account %}
{% set _ = running_total.__setattr__('quantity', running_total.quantity + posting.quantity) %}
<tr>
<td></td> <td></td>
<td class="text-end"><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i></td>
<td>{{ account }}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td class="text-end">{{ (running_total|abs).format() }}</td>
<td>{{ 'Dr' if running_total.quantity >= 0 else 'Cr' }}</td>
</tr>
{% endfor %}
{% for posting in transaction.postings if posting.account != account %}
<tr>
<td></td> <td></td>
<td class="text-end"><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i></td>
<td>{{ posting.account }}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td></td> <td></td>
<td></td> <td></td>
</tr> </tr>
{% for posting in transaction.postings if posting.account == account %} {% endfor %}
{% set _ = running_total.__setattr__('quantity', running_total.quantity + posting.quantity) %} {% endif %}
<tr> {% endfor %}
<td></td> </tbody>
<td class="text-end"><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i></td> </table>
<td>{{ account }}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td class="text-end">{{ (running_total|abs).format() }}</td>
<td>{{ 'Dr' if running_total.quantity >= 0 else 'Cr' }}</td>
</tr>
{% endfor %}
{% for posting in transaction.postings if posting.account != account %}
<tr>
<td></td>
<td class="text-end"><i>{{ 'Dr' if posting.quantity >= 0 else 'Cr' }}</i></td>
<td>{{ posting.account }}</td>
<td class="text-end">{{ posting.amount().format() if posting.quantity >= 0 else '' }}</td>
<td class="text-end">{{ (posting.amount()|abs).format() if posting.quantity < 0 else '' }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %} {% endblock %}

View File

@ -18,32 +18,30 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% block title %}Trial balance{% endblock %} {% block title %}Trial balance{% endblock %}
{% block body %} {% block content %}
<div class="container"> <h1 class="h2 my-4">Trial balance</h1>
<h1 class="h2 mt-4 mb-4">Trial balance</h1>
<table class="table"> <table class="table">
<thead> <thead>
<tr>
<th>Account</th>
<th class="text-end">Dr</th>
<th class="text-end">Cr</th>
</tr>
</thead>
<tbody>
{% for name, balance in accounts.items() %}
<tr> <tr>
<th>Account</th> <td><a href="/account-transactions?account={{ name }}">{{ name }}</a></td>
<th class="text-end">Dr</th> <td class="text-end">{{ balance.format() if balance.quantity >= 0 else '' }}</td>
<th class="text-end">Cr</th> <td class="text-end">{{ (balance|abs).format() if balance.quantity < 0 else '' }}</td>
</tr> </tr>
</thead> {% endfor %}
<tbody> <tr>
{% for name, balance in accounts.items() %} <th>Total</th>
<tr> <th class="text-end">{{ total_dr.format() }}</th>
<td><a href="/account-transactions?account={{ name }}">{{ name }}</a></td> <th class="text-end">{{ (total_cr|abs).format() }}</th>
<td class="text-end">{{ balance.format() if balance.quantity >= 0 else '' }}</td> </tr>
<td class="text-end">{{ (balance|abs).format() if balance.quantity < 0 else '' }}</td> </tbody>
</tr> </table>
{% endfor %}
<tr>
<th>Total</th>
<th class="text-end">{{ total_dr.format() }}</th>
<th class="text-end">{{ (total_cr|abs).format() }}</th>
</tr>
</tbody>
</table>
</div>
{% endblock %} {% endblock %}

View File

@ -21,7 +21,7 @@ from .webapp import all_transactions, app
@app.route('/') @app.route('/')
def index(): def index():
return '<a href="/general-journal">General journal</a><br><a href="/statement-lines">Statement lines</a><br><a href="/general-ledger">General ledger</a><br><a href="/trial-balance">Trial balance</a>' return render_template('index.html')
@app.route('/general-ledger') @app.route('/general-ledger')
def general_ledger(): def general_ledger():