_SERVER_PORT = 8084
_TOK_RAW = 'raw'
_TOK_STRUCTURED = 'structured'
+PAGENAME_BALANCE = 'balance'
_PAGENAME_EDIT_RAW = f'{_PREFIX_EDIT}{_TOK_RAW}'
_PAGENAME_EDIT_STRUCTURED = f'{_PREFIX_EDIT}{_TOK_STRUCTURED}'
PAGENAME_LEDGER_RAW = f'{_PREFIX_LEDGER}{_TOK_RAW}'
### start = time_ns()
ctx = {'unsaved_changes': self.server.ledger.tainted,
'path': self.path}
- if self.pagename == 'balance':
+ if self.pagename == PAGENAME_BALANCE:
self.get_balance(ctx)
elif self.pagename.startswith(_PREFIX_EDIT):
self.get_edit(ctx, self.pagename == _PAGENAME_EDIT_RAW)
ctx['valid'] = self.server.ledger.blocks_valid_up_incl(id_)
ctx['block'] = self.server.ledger.blocks[id_]
ctx['path_up_incl'] = f'{self.path_toks[1]}?up_incl='
- self._send_rendered('balance', ctx)
+ self._send_rendered(PAGENAME_BALANCE, ctx)
def get_edit(self, ctx, raw: bool) -> None:
'Display edit form for individual Booking.'
# built-ins
from sys import exit as sys_exit
from pathlib import Path
-from typing import Optional
+from typing import Any, Optional
# requirements.txt
from jinja2 import (Environment as JinjaEnv,
FileSystemLoader as JinjaFSLoader)
# ourselves
-from ledgplom.http import (PAGENAME_LEDGER_RAW, PAGENAME_LEDGER_STRUCTURED,
- PATH_TEMPLATES)
+from ledgplom.http import (
+ PAGENAME_BALANCE, PAGENAME_LEDGER_RAW, PAGENAME_LEDGER_STRUCTURED,
+ PATH_TEMPLATES)
from ledgplom.ledger import Ledger
jinja = JinjaEnv(loader=JinjaFSLoader(PATH_TEMPLATES),
autoescape=True,
trim_blocks=True)
- templates = {item: jinja.get_template(f'{item}.tmpl')
- for item in (PAGENAME_LEDGER_RAW, PAGENAME_LEDGER_STRUCTURED)}
+ templates = {item: jinja.get_template(f'{item}.tmpl') for item in (
+ PAGENAME_BALANCE, PAGENAME_LEDGER_RAW, PAGENAME_LEDGER_STRUCTURED)}
for path in [p for p in _PATH_TESTS.iterdir()
if p.parts[-1].endswith(_EXT_DAT)]:
+ ledger = Ledger(path)
for key, template in templates.items():
test_path = Path(str(path)[:-len(_EXT_DAT)] + f'.{key}')
if not test_path.exists():
with test_path.open('r', encoding='utf8') as f:
lines_expected = [line.rstrip('\n')
for line in f.readlines()]
- ledger = Ledger(path)
- ctx = {
- 'blocks': ledger.blocks,
- 'has_redundant_empty_lines': ledger.has_redundant_empty_lines}
+ ctx: dict[str, Any] = {}
+ if key == PAGENAME_BALANCE:
+ id_ = len(ledger.blocks) - 1
+ ctx['roots'] = sorted([ac for
+ ac in ledger.calc_accounts().values()
+ if not ac.parent],
+ key=lambda r: r.basename)
+ ctx['valid'] = ledger.blocks_valid_up_incl(id_)
+ ctx['block'] = ledger.blocks[id_]
+ ctx['path_up_incl'] = f'{PAGENAME_BALANCE}?up_incl='
+ else:
+ ctx['blocks'] = ledger.blocks
+ ctx['has_redundant_empty_lines'] =\
+ ledger.has_redundant_empty_lines
lines_rendered = template.render(**ctx).split('\n')
msg_prefix = f'test for {test_path}:'
for idx0, line in enumerate(lines_rendered):
float: left;
}
summary::marker {
- {{ macros.css_noninput_monospace() }}
+{{ macros.css_noninput_monospace() -}}
}
summary {
list-style-type: "[…]";
-{% macro account_with_children(block_id, account, indent) %}
-{% macro tr_money_balance(amount, currency) %}
- <tr>
- <td class="balance amount">{{amount}}</td>
- <td class="balance currency">{{ macros.currency_short(currency) }}</td>
- </tr>
+{% macro account_with_children(block_id, account, name_indent) %}
+
+{%- macro _(code_indent=1) %}
+{{- " " * 4 * code_indent -}}
+{% endmacro %}
+
+{%- macro tr_money_balance(amount, currency, i=4) %}
+{{_(i)}}<tr>
+{{_(i)}} <td class="balance amount">
+ {{- amount -}}
+ </td>
+{{_(i)}} <td class="balance currency">
+ {{- macros.currency_short(currency) -}}
+ </td>
+{{_(i)}}</tr>
{% endmacro %}
-{% if account.get_wealth_at(block_id).moneys|length > 0 %}
- <tr>
- <td class="money">
- {% if account.get_wealth_at(block_id).moneys|length == 1 %}
- <table>
- {% for currency, amount in account.get_wealth_at(block_id).moneys.items() %}
- {{tr_money_balance(amount, currency)}}
- {% endfor %}
- </table>
- {% else %}
- <details>
- <summary>
- <table>
- {% for currency, amount in account.get_wealth_at(block_id).moneys.items() %}
- {% if 1 == loop.index %}
- {{tr_money_balance(amount, currency)}}
- {% endif %}
- {% endfor %}
- </table>
- </summary>
- <table>
- {% for currency, amount in account.get_wealth_at(block_id).moneys.items() %}
- {% if 1 < loop.index %}
- {{tr_money_balance(amount, currency)}}
- {% endif %}
- {% endfor %}
- </table>
- </details>
- {% endif %}
- </td>
- <td>
- <span class="indent">{%
- for i in range(indent) %} {%
- endfor
- %}</span>{%
- if account.parent
- %}:{%
- endif
- %}{{account.basename}}{%
- if account.children
- %}:{%
- endif
- %}
- </td>
- <td>{{account.desc}}</td>
- </tr>
- {% for child in account.children_euro_sorted_at(block_id) %}
- {{account_with_children(block_id, child, indent=indent+1)}}
- {% endfor %}
+
+{%- if account.get_wealth_at(block_id).moneys | length > 0 %}
+{{_()}}<tr>
+{{_()}} <td class="money">
+{##}{% if account.get_wealth_at(block_id).moneys | length == 1 %}
+{{_()}} <table>
+{######}{% for cur, amt in account.get_wealth_at(block_id).moneys.items() %}
+ {{- tr_money_balance(amt, cur) -}}
+{######}{% endfor %}
+{{_()}} </table>
+{##}{% else %}
+{{_()}} <details>
+{{_()}} <summary>
+{{_()}} <table>
+{######}{% for cur, amt in account.get_wealth_at(block_id).moneys.items() %}
+ {{- tr_money_balance(amt, cur, i=6)
+ if 1 == loop.index -}}
+{######}{% endfor %}
+{{_()}} </table>
+{{_()}} </summary>
+{{_()}} <table>
+{######}{% for cur, amt in account.get_wealth_at(block_id).moneys.items() %}
+ {{- tr_money_balance(amt, cur, 5) if 1 < loop.index -}}
+{######}{% endfor %}
+{{_()}} </table>
+{{_()}} </details>
+{##}{% endif %}
+{{_()}} </td>
+{{_()}} <td>
+{{_()}} <span class="indent">{##}
+{######}{% for n in range(name_indent) -%}
+ {# -#}
+{######}{% endfor -%}
+ </span>
+ {{- ":" if account.parent }}
+ {{- account.basename }}
+ {{- ":" if account.children }}
+{{_()}} </td>
+{{_()}} <td>{{ account.desc }}</td>
+{{_()}}</tr>
+{##}{% for child in account.children_euro_sorted_at(block_id) %}
+ {{- account_with_children(block_id, child, name_indent=name_indent+1) -}}
+{##}{% endfor %}
{% endif %}
{% endmacro %}
{% block content %}
<p>
-{{macros.conditional_block_nav(path_up_incl,'prev',block)}}
-{{macros.conditional_block_nav(path_up_incl,'next',block)}}
-|
-balance after <a href="/blocks/{{block.id_}}">booking {{block.id_}} ({{block.booking.date}}: {{block.booking.target}})</a>
+ {{ macros.conditional_block_nav(path_up_incl, 'prev', block) -}}{##}
+ {{ macros.conditional_block_nav(path_up_incl, 'next', block) }}{##}
+ |
+ balance after {# -#}
+ <a href="/blocks/{{block.id_}}">{# -#}
+ booking {{block.id_}} {# -#}
+ ({{ block.booking.date }}: {{ block.booking.target }}){# -#}
+ </a>
</p>
<table class="alternating {% if not valid %}critical{% endif %}">
{% for root in roots %}
- {{account_with_children(block.id_,root,indent=0)}}
+{{ account_with_children(block.id_, root, name_indent=0) -}}
{% endfor %}
</table>
{% endblock %}
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+</script>
+<style>
+html {
+ scroll-padding-top: 2em;
+}
+body {
+ background: #ffffff;
+ font-family: sans-serif;
+ text-align: left;
+ margin: 0;
+ padding: 0;
+}
+#header {
+ background: #ffffff;
+ position: sticky;
+ top: 0;
+ padding-left: 0.5em;
+ padding-bottom: 0.25em;
+ border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+ background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+ background: #ffffff;
+}
+td {
+ vertical-align: top;
+}
+.critical {
+ background: #ff6666 !important;
+}
+td.amount {
+ text-align: right;
+}
+td.amount,
+td.currency {
+ font-family: monospace;
+ font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+ background-color: #ff8a8a;
+}
+td.balance.amount {
+ width: 10em;
+}
+td.balance.currency {
+ width: 3em;
+}
+td.money table {
+ float: left;
+}
+summary::marker {
+ font-family: monospace;
+ font-size: 1.25em;
+}
+summary {
+ list-style-type: "[…]";
+}
+details[open] > summary {
+ list-style-type: "[^]";
+}
+span.indent {
+ letter-spacing: 3em;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="" method="POST">
+ <span class="disable_on_change">
+ ledger <a href="/ledger_structured">structured</a>
+ / <a href="/ledger_raw">raw</a>
+ · <a href="/balance">balance</a>
+ · <input type="submit"name="file_load" value="reload" />
+ </span>
+ </form>
+</div>
+<p>
+ <del>prev</del>
+ <del>next</del>
+ |
+ balance after <a href="/blocks/0">booking 0 (: )</a>
+</p>
+<table class="alternating ">
+</table>
+</body>
+</html>
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+</script>
+<style>
+html {
+ scroll-padding-top: 2em;
+}
+body {
+ background: #ffffff;
+ font-family: sans-serif;
+ text-align: left;
+ margin: 0;
+ padding: 0;
+}
+#header {
+ background: #ffffff;
+ position: sticky;
+ top: 0;
+ padding-left: 0.5em;
+ padding-bottom: 0.25em;
+ border-bottom: 1px solid black;
+}
+table.alternating > tbody > tr:nth-child(odd) {
+ background-color: #dcdcdc;
+}
+table.alternating > tbody > tr:nth-child(even) {
+ background: #ffffff;
+}
+td {
+ vertical-align: top;
+}
+.critical {
+ background: #ff6666 !important;
+}
+td.amount {
+ text-align: right;
+}
+td.amount,
+td.currency {
+ font-family: monospace;
+ font-size: 1.25em;
+}
+table.alternating.critical > tbody > tr:nth-child(even) {
+ background-color: #ff8a8a;
+}
+td.balance.amount {
+ width: 10em;
+}
+td.balance.currency {
+ width: 3em;
+}
+td.money table {
+ float: left;
+}
+summary::marker {
+ font-family: monospace;
+ font-size: 1.25em;
+}
+summary {
+ list-style-type: "[…]";
+}
+details[open] > summary {
+ list-style-type: "[^]";
+}
+span.indent {
+ letter-spacing: 3em;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="" method="POST">
+ <span class="disable_on_change">
+ ledger <a href="/ledger_structured">structured</a>
+ / <a href="/ledger_raw">raw</a>
+ · <a href="/balance">balance</a>
+ · <input type="submit"name="file_load" value="reload" />
+ </span>
+ </form>
+</div>
+<p>
+ <a href="balance?up_incl=3">prev</a>
+ <del>next</del>
+ |
+ balance after <a href="/blocks/4">booking 4 (2001-01-01: test)</a>
+</p>
+<table class="alternating ">
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </summary>
+ <table>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"></span>bar:
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:x:
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:y
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:z
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </td>
+ <td>
+ <span class="indent"></span>baz
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tr>
+ <td class="balance amount">20</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </summary>
+ <table>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"></span>foo:
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </table>
+ </summary>
+ <table>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"> </span>:x
+ </td>
+ <td></td>
+ </tr>
+</table>
+</body>
+</html>
baz -20 € ; baz
2001-01-01 test
- foo 10 €
- bar -10 €
-
+ foo:x 10 €
+ foo:x 1 USD
+ bar:x:y -10 €
+ bar:z -1 USD
<tr><td> </td></tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_4">
- <td rowspan=5 class="block_column critical">
+ <td rowspan=7 class="block_column critical">
<input type="submit"
name="ledger_moveup_4"
value="^"
<br />
<input type="submit" name="ledger_copy_4" value="C"/>
</td>
- <td rowspan=5 class="block_column">
+ <td rowspan=7 class="block_column">
[<a href="#block_4">#</a>]<br />
[<a href="/balance?up_incl=4">b</a>]<br />
[<a href="/edit_raw/4">e</a>]
</td>
</tr>
<tr><td>2001-01-01 test </td></tr>
- <tr><td> foo 10 € </td></tr>
- <tr><td> bar -10 € </td></tr>
+ <tr><td> foo:x 10 € </td></tr>
+ <tr><td> foo:x 1 USD </td></tr>
+ <tr><td> bar:x:y -10 € </td></tr>
+ <tr><td> bar:z -1 USD </td></tr>
<tr><td> </td></tr>
</table>
</form>
</tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_4">
- <td rowspan=5 class="block_column critical">
+ <td rowspan=7 class="block_column critical">
<input type="submit"
name="ledger_moveup_4"
value="^"
<br />
<input type="submit" name="ledger_copy_4" value="C"/>
</td>
- <td rowspan=5 class="block_column">
+ <td rowspan=7 class="block_column">
[<a href="#block_4">#</a>]<br />
[<a href="/balance?up_incl=4">b</a>]<br />
[<a href="/edit_structured/4">e</a>]
<tr>
<td class="amount">10.00</td>
<td class="currency">€</td>
- <td>foo</td>
+ <td>foo:x</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="amount">1.00</td>
+ <td class="currency">USD</td>
+ <td>foo:x</td>
<td></td>
</tr>
<tr>
<td class="amount">-10.00</td>
<td class="currency">€</td>
- <td>bar</td>
+ <td>bar:x:y</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="amount">-1.00</td>
+ <td class="currency">USD</td>
+ <td>bar:z</td>
<td></td>
</tr>
<tr>