def do_POST(self) -> None:
# pylint: disable=invalid-name,missing-function-docstring
+ redir_path = Path('/')
+ if self.pagename.startswith('edit_'):
+ id_ = int(self.path_toks[2])
+ redir_path = Path('/').joinpath('booking').joinpath(str(id_))
if self.pagename == 'file':
if 'reload' in self.postvars.as_dict:
self.server.load()
elif 'save' in self.postvars.as_dict:
self.server.save()
- elif self.pagename == 'edit':
- id_ = int(self.path_toks[2])
- old_booking = self.server.bookings[id_]
- start_idx = self.server.dat_lines.index(old_booking.dat_lines[0])
- end_idx = self.server.dat_lines.index(old_booking.dat_lines[-1])
+ elif self.pagename == 'edit_structured':
+ line_keys = self.postvars.keys_prefixed('line_')
+ lineno_to_inputs: dict[int, list[str]] = {}
+ for key in line_keys:
+ toks = key.split('_', maxsplit=2)
+ lineno = int(toks[1])
+ if lineno not in lineno_to_inputs:
+ lineno_to_inputs[lineno] = []
+ lineno_to_inputs[lineno] += [toks[2]]
+ new_dat_lines = []
+ indent = ' '
+ for lineno, input_names in lineno_to_inputs.items():
+ data = ''
+ comment = self.postvars.first(f'line_{lineno}_comment')
+ for name in input_names:
+ input_ = self.postvars.first(f'line_{lineno}_{name}')
+ if name == 'intro':
+ data = input_
+ elif name == 'error':
+ data = f'{indent}{input_}'
+ elif name == 'account':
+ data = f'{indent}{input_}'
+ elif name in {'amount', 'currency'}:
+ data += f' {input_}'
+ new_dat_lines += [
+ DatLine(f'{data} ; {comment}' if comment else data)]
+ self.server.rewrite_booking(id_, new_dat_lines)
+ elif self.pagename == 'edit_raw':
new_dat_lines = [DatLine(line) for line
in self.postvars.first('booking').splitlines()]
- self.server.dat_lines = (self.server.dat_lines[:start_idx]
- + new_dat_lines
- + self.server.dat_lines[end_idx+1:])
- self.server.load_bookings()
- self.redirect(Path('/').joinpath('booking').joinpath(str(id_)))
- return
- self.redirect(Path('/'))
+ self.server.rewrite_booking(id_, new_dat_lines)
+ self.redirect(redir_path)
def do_GET(self) -> None:
# pylint: disable=invalid-name,missing-function-docstring
ctx = {'tainted': self.server.tainted}
- if self.pagename in {'booking', 'edit'}:
+ if self.pagename == 'booking' or self.pagename.startswith('edit_'):
ctx['id'] = int(self.path_toks[2])
ctx['dat_lines'] = self.server.bookings[ctx['id']].dat_lines
if self.pagename == 'balance':
int(self.params.first('cutoff') or '0'))
self.send_rendered(Path('balance.tmpl'),
ctx | {'roots': balance_roots, 'valid': valid})
- elif self.pagename == 'booking':
- self.send_rendered(Path('booking.tmpl'), ctx)
- elif self.pagename == 'edit':
- self.send_rendered(Path('edit.tmpl'), ctx)
- elif self.pagename == 'raw':
- self.send_rendered(Path('raw.tmpl'),
+ elif self.pagename in {'booking', 'edit_structured'}:
+ self.send_rendered(Path('edit_structured.tmpl'), ctx)
+ elif self.pagename == 'edit_raw':
+ self.send_rendered(Path('edit_raw.tmpl'), ctx)
+ elif self.pagename == 'ledger_raw':
+ self.send_rendered(Path('ledger_raw.tmpl'),
ctx | {'dat_lines': self.server.dat_lines})
else:
self.send_rendered(
- Path('index.tmpl'),
+ Path('ledger_structured.tmpl'),
ctx | {'dat_lines': self.server.dat_lines_sans_empty})
class Server(PlomHttpServer):
"""Extends parent by loading .dat file into database for Handler."""
bookings: list[Booking]
+ dat_lines: list[DatLine]
def __init__(self, path_dat: Path, *args, **kwargs) -> None:
super().__init__(PATH_TEMPLATES, (SERVER_HOST, SERVER_PORT), Handler)
'\n'.join([line.raw for line in self.dat_lines]), encoding='utf8')
self.load()
+ def rewrite_booking(self, id_: int, new_dat_lines: list[DatLine]) -> None:
+ """Rewrite .dat_lines for Booking of .id_ with new_dat_lines."""
+ old_booking = self.bookings[id_]
+ start_idx = self.dat_lines.index(old_booking.dat_lines[0])
+ end_idx = self.dat_lines.index(old_booking.dat_lines[-1])
+ self.dat_lines = (self.dat_lines[:start_idx]
+ + new_dat_lines + self.dat_lines[end_idx+1:])
+ self.load_bookings()
+
@property
def dat_lines_sans_empty(self) -> list[DatLine]:
"""Return only those .data_lines with .code or .comment."""
td.invalid, tr.warning td.invalid { background-color: #ff0000; }
{% endmacro %}
-{% macro table_dat_lines(dat_lines, single, raw) %}
+{% macro table_dat_lines(dat_lines, raw) %}
<table>
{% for dat_line in dat_lines %}
- {% if (not (raw or single)) and dat_line.is_intro and loop.index > 1 %}
+ {% if (not raw) and dat_line.is_intro and loop.index > 1 %}
<tr><td colspan=5> </td></tr>
{% endif %}
<tr{% if dat_line.is_questionable %} class="warning"{% endif %}>
- {% if not single %}
- {% if dat_line.is_intro %}
- <td id="{{dat_line.booking_id}}"><a href="#{{dat_line.booking_id}}">#</a>/<a href="/balance?cutoff={{dat_line.booking_id+1}}">b</a></td>
- {% else %}
- <td></td>
- {% endif %}
+ {% if dat_line.is_intro %}
+ <td id="{{dat_line.booking_id}}"><a href="#{{dat_line.booking_id}}">#</a>/<a href="/balance?cutoff={{dat_line.booking_id+1}}">b</a></td>
+ {% else %}
+ <td></td>
{% endif %}
{% if raw %}
<td{% if dat_line.error %} class="invalid"{% endif %}>
</tr>
{% if dat_line.error and not raw %}
<tr class="warning">
- {% if not single %}
- <td></td>
- {% endif %}
+ <td></td>
<td class="invalid" colspan=3>{{dat_line.error}}</td>
<td></td>
</tr>
--- /dev/null
+{% extends '_base.tmpl' %}
+
+
+{% block css %}
+{{ macros.css_td_money() }}
+{{ macros.css_errors() }}
+{% endblock %}
+
+{% block content %}
+<a href="/edit_raw/{{id}}">edit raw</a>
+<hr />
+<form action="/edit_structured/{{id}}" method="POST">
+<table>
+{% for dat_line in dat_lines %}
+ <tr>
+ {% if dat_line.is_intro %}
+ <td{% if dat_line.error %} class="invalid"{% endif %} colspan=3><input name="line_{{loop.index0}}_intro" value="{{dat_line.code}}"/></td>
+ {% elif not dat_line.error %}
+ <td><input name="line_{{loop.index0}}_account" value="{{dat_line.booking_line.account}}" /></td>
+ <td><input name="line_{{loop.index0}}_amount" value="{{dat_line.booking_line.amount or ''}}" /></td>
+ <td><input name="line_{{loop.index0}}_currency" value="{{dat_line.booking_line.currency or ''}}" /></td>
+ {% else %}
+ <td class="invalid" colspan=3><input name="line_{{loop.index0}}_error" value="{{dat_line.code|trim}}" /></td>
+ {% endif %}
+ <td><input name="line_{{loop.index0}}_comment" value="{{dat_line.comment|trim}}" /></td>
+ </tr>
+ {% if dat_line.error %}
+ <tr class="warning">
+ <td class="invalid" colspan=3>{{dat_line.error}}</td>
+ <td></td>
+ </tr>
+ {% endif %}
+{% endfor %}
+</table>
+<input type="submit" value="update" />
+</form>
+{% endblock %}