'Actual ledger classes.'
# standard libs
-from abc import ABC, abstractmethod
+from abc import ABC
from datetime import date as dt_date
from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
from pathlib import Path
from typing import Any, Generic, Iterator, Optional, Self, TypeVar
-TypeDatLine = TypeVar('TypeDatLine', bound='_DatLine')
+_TypeDatLine = TypeVar('_TypeDatLine', bound='_DatLine')
+_INDENT_CHARS = {' ', '\t'}
+_SEP_COMMENTS = ';'
_PREFIX_DEF = '#def '
DEFAULT_INDENT = 2 * ' '
class _DatLine:
'Line of .dat file parsed into comments and machine-readable data.'
- to_copy = ['code', 'comment']
- def __init__(
- self,
- code: str = '',
- comment: str = '',
- ) -> None:
- self._code_read = code
- self.comment = comment
+ def __init__(self, text: str) -> None:
+ self._raw = text
+
+ def _into_parts(self) -> tuple[str, str, str]:
+ stage_count = 0
+ indent = ''
+ code = ''
+ comment = ''
+ for c in self._raw:
+ if stage_count == 0:
+ if c in _INDENT_CHARS:
+ indent += c
+ else:
+ stage_count += 1
+ if stage_count == 1:
+ if c != _SEP_COMMENTS:
+ code += c
+ else:
+ stage_count += 1
+ if stage_count == 2:
+ comment += c
+ return indent, code, comment
+
+ @property
+ def indent(self) -> str:
+ 'All (maybe zero) the chars of whitespace line starts with.'
+ return self._into_parts()[0]
@property
def code(self) -> str:
- 'Return collected code (re-generate by subclasses for writing).'
- return self._code_read
+ 'Either IntroLine or TransferLine instructions.'
+ return self._into_parts()[1]
+
+ @property
+ def comment(self) -> str:
+ 'Anything past ";", with whitespace in-between stripped.'
+ return self._into_parts()[2][1:].lstrip()
@property
def raw(self) -> str:
"Return as how to be written in .dat file's text content."
- comment_part = ' ; '.join([''] + [s for s in [self.comment] if s])
- code_part = f'{self.code} ' if self.code else ''
- return f'{code_part}{comment_part.lstrip()}'.rstrip()
-
- def copy(self) -> Self:
- 'Create new instance copying the fields named in .to_copy.'
- kwargs = {fieldname: getattr(self, fieldname)
- for fieldname in self.to_copy}
- return self.__class__(**kwargs)
-
- @classmethod
- def from_raw(cls, line: str) -> Self:
- 'Parse line into new _DatLine.'
- halves = [t.rstrip() for t in line.split(';', maxsplit=1)]
- comment = halves[1].lstrip() if len(halves) > 1 else ''
- code = halves[0]
- return cls(code, comment)
+ return self._raw[:]
@property
def comment_instructions(self) -> dict[str, str]:
instructions = {}
if self.comment.startswith(_PREFIX_DEF):
parts = [part.strip() for part
- in self.comment[len(_PREFIX_DEF):].split(';')]
+ in self.comment[len(_PREFIX_DEF):].split(_SEP_COMMENTS)]
first_part_parts = parts[0].split(maxsplit=1)
account_name = first_part_parts[0]
desc = first_part_parts[1] if len(first_part_parts) > 1 else ''
return instructions
-class _DatLineSubclass(_DatLine, ABC):
-
- @classmethod
- @abstractmethod
- def from_dat(cls, dat_line: '_DatLine') -> Self:
- 'Evolve from mere dat_line into subclass.'
-
-
-class _GapLine(_DatLineSubclass):
-
- @classmethod
- def from_dat(cls, dat_line: _DatLine) -> Self:
- return cls('', dat_line.raw if dat_line.code else dat_line.comment)
-
-
-class _BookingLine(_DatLineSubclass):
+class _BookingLine(_DatLine, ABC):
'Parsed _DatLine belonging to a _Booking.'
- dictables = {'comment', 'errors'}
-
- def __init__(self, comment, errors: Optional[list[str]]) -> None:
- super().__init__('', comment)
- self._errors: list[str] = errors if errors else []
+ _field_names = {'errors', 'comment'}
@property
def as_dict(self) -> dict[str, Any]:
- 'Return as JSON-ready dict attributes listed in .dictables.'
+ 'Return as JSON-ready dict attributes listed in ._field_names.'
def to_dictable(value):
if isinstance(value, (str, int)):
return value
if hasattr(value, 'as_dict'):
return value.as_dict
- if isinstance(value, list):
- return [to_dictable(v) for v in value]
+ if isinstance(value, tuple):
+ return tuple(to_dictable(v) for v in value)
return str(value)
d = {}
- for name in self.dictables:
+ for name in self._field_names | _BookingLine._field_names:
d[name] = to_dictable(getattr(self, name))
return d
+ def _code_into_parts(self, n_parts: int) -> tuple[str, ...]:
+ maxsplit = n_parts + 1
+ parts = self.code.split(maxsplit=maxsplit)
+ return tuple((parts[idx] if len(parts) > idx else '')
+ for idx in range(maxsplit))
+
@property
- def errors(self) -> list[str]:
- 'Return collected errors (subclasses may add dynamic ones).'
- return self._errors[:]
+ def errors(self) -> tuple[str, ...]:
+ 'Whatever is wrong with the respective line.'
+ return tuple(f'{name} empty' for name in self._field_names
+ if not getattr(self, name))
class _IntroLine(_BookingLine):
'First line of a _Booking, expected to carry date etc.'
- to_copy = ['date', 'target', 'comment']
- dictables = {'date', 'target'} | _BookingLine.dictables
+ _field_names = {'date', 'target'}
- def __init__(
- self,
- date: str,
- target: str,
- comment: str = '',
- errors: Optional[list[str]] = None,
- ) -> None:
- super().__init__(comment, errors)
- self.target = target
- self.date = date
+ @property
+ def date(self) -> str:
+ 'YYYY-MM-DD of Booking.'
+ return self._code_into_parts(2)[0]
+
+ @property
+ def target(self) -> str:
+ 'Whatever the ledger definition actually means by that …'
+ return self._code_into_parts(2)[1]
@property
- def errors(self) -> list[str]:
- errors = super().errors
+ def errors(self) -> tuple[str, ...]:
+ errors = list(super().errors)
+ if self.indent:
+ errors += ['intro line indented']
try:
dt_date.fromisoformat(self.date)
except ValueError:
errors += [f'not properly formatted legal date: {self.date}']
- if not self.target:
- errors += ['target empty']
- return errors
-
- @classmethod
- def from_dat(cls, dat_line: _DatLine) -> Self:
- errors = []
- if dat_line.code[0].isspace():
- errors += ['(intro line indented)']
- toks = dat_line.code.lstrip().split(maxsplit=1)
- return cls(toks[0], toks[1] if len(toks) > 1 else '',
- dat_line.comment, errors)
-
- @property
- def code(self) -> str:
- return f'{self.date} {self.target}'
+ return tuple(errors)
class _TransferLine(_BookingLine):
'Non-first _Booking line, expected to carry value movement.'
- to_copy = ['account', 'amount', 'currency', 'comment']
- dictables = {'amount', 'account', 'currency'} | _BookingLine.dictables
+ _field_names = {'account', 'amount', 'currency'}
- def __init__(
- self,
- account: str,
- amount: str,
- currency: str,
- comment: str = '',
- errors: Optional[list[str]] = None
- ) -> None:
- super().__init__(comment, errors)
- self.account = account
- self._amount_str = amount
- self.currency = currency
+ @property
+ def account(self) -> str:
+ 'Name of Account.'
+ return self._code_into_parts(3)[0]
@property
def amount(self) -> Optional[Decimal] | str:
'Decimal if amount known, None if not, str if un-decimable.'
- if not self._amount_str:
+ amount_str = self._code_into_parts(3)[1]
+ if not amount_str:
return None
try:
- return Decimal(self._amount_str)
+ return Decimal(amount_str)
except DecimalInvalidOperation:
- return self._amount_str
+ return amount_str
+
+ @property
+ def currency(self) -> str:
+ 'If .amount but itself not found, will default to "€".'
+ return (self._code_into_parts(3)[2] or '€') if self.amount else ''
@property
- def errors(self) -> list[str]:
- errors = super().errors
+ def errors(self) -> tuple[str, ...]:
+ errors = list(super().errors)
+ # if not self.indent:
+ # errors += ['transfer line not indented']
if isinstance(self.amount, str):
errors += [f'improper amount value: {self.amount}']
if len(self.currency.split()) > 1:
errors += ['improper number of tokens']
- return errors
-
- @classmethod
- def from_dat(cls, dat_line: _DatLine) -> Self:
- errors = []
- currency: str = ''
- if not dat_line.code[0].isspace():
- errors += ['(transfer line not indented)']
- toks = dat_line.code.lstrip().split(maxsplit=2)
- amount_str = toks[1] if len(toks) > 1 else ''
- if len(toks) > 1:
- currency = toks[2] if 3 == len(toks) else '€'
- return cls(toks[0], amount_str, currency, dat_line.comment, errors)
-
- @property
- def code(self) -> str:
- code = f'{DEFAULT_INDENT}{self.account}'
- if self.amount is not None:
- code += f' {self.amount} {self.currency}'
- return code
+ return tuple(errors)
@property
def amount_short(self) -> str:
return ''
-class _LinesBlock(Generic[TypeDatLine]):
+class _LinesBlock(Generic[_TypeDatLine]):
+ _lines: list[_TypeDatLine]
- def __init__(self, lines: Optional[list[TypeDatLine]] = None) -> None:
- self._lines = lines if lines else []
+ def __init__(self) -> None:
+ self._lines = []
@property
- def lines(self) -> list[TypeDatLine]:
+ def lines(self) -> tuple[_TypeDatLine, ...]:
'Return collected lines.'
- return self._lines
-
- def copy(self) -> Self:
- "Re-create via .lines' copy()."
- return self.__class__([line.copy() for line in self.lines])
+ return tuple(self._lines)
+ def add(self, lines: tuple[_TypeDatLine, ...], at_end=True) -> None:
+ 'Grow block downwards by this one DatLine.'
+ if at_end:
+ self._lines += lines
+ else:
+ self._lines[0:0] = list(lines)
-class _Gap(_LinesBlock[_GapLine]):
- def add(self, lines: list[_GapLine]) -> None:
- 'Grow self by lines.'
- self._lines += lines
+class _Booking(_LinesBlock[_BookingLine]):
@property
- def redundant_empty_lines(self):
- 'If self has more empty lines than necessary.'
- redundancies = []
- prev_line = None
- idx_last_non_empty = -1
- for idx, line in enumerate(self._lines):
- if line.comment:
- idx_last_non_empty = idx
- elif '' == prev_line and not line.comment:
- redundancies += [line]
- prev_line = line
- redundancies += [line for line in self._lines[idx_last_non_empty + 2:]
- if line not in redundancies]
- return redundancies
+ def _sink_account(self) -> str:
+ for tf_line in [tl for tl in self.transfer_lines
+ if tl.amount is None and not tl.errors]:
+ return tf_line.account
+ return ''
- def remove_redundant_empty_lines(self):
- 'From self remove redundant empty lines.'
- for line in self.redundant_empty_lines:
- self._lines.remove(line)
+ @property
+ def lines(self) -> tuple[_BookingLine, ...]:
+ 'Return collected lines.'
+ return (self.intro_line, ) + self.transfer_lines
+ @property
+ def _diffs_targeted(self) -> dict[str, _Wealth]:
+ balancing_diff = _Wealth()
+ diffs_targeted: dict[str, _Wealth] = {'': _Wealth()}
+ for tf_line in [tl for tl in self.transfer_lines if not tl.errors]:
+ if tf_line.account not in diffs_targeted:
+ diffs_targeted[tf_line.account] = _Wealth()
+ if isinstance(tf_line.amount, Decimal):
+ diff = _Wealth({tf_line.currency: tf_line.amount})
+ diffs_targeted[tf_line.account] += diff
+ balancing_diff += diff
+ diffs_targeted[self._sink_account] += balancing_diff.as_sink
+ return diffs_targeted
-class _Booking(_LinesBlock[_BookingLine]):
+ @property
+ def diffs_targeted(self) -> dict[str, _Wealth]:
+ 'All wealth differences explicitly defined in transfer lines.'
+ return {acc: diff for acc, diff in self._diffs_targeted.items() if acc}
- def __init__(self, lines: list[_BookingLine]) -> None:
- super().__init__(lines)
- diffs = _Wealth()
- sink_account = None
- self.sink_error = ''
- self.diffs_targeted: dict[str, _Wealth] = {}
- for tf_line in [tl for tl in self.transfer_lines if not tl.errors]:
- if tf_line.account not in self.diffs_targeted:
- self.diffs_targeted[tf_line.account] = _Wealth()
- if tf_line.amount is None:
- if sink_account:
- self.sink_error = 'too many sinks'
- else:
- sink_account = tf_line.account
- continue
- assert isinstance(tf_line.amount, Decimal)
- diff = _Wealth({tf_line.currency: tf_line.amount})
- self.diffs_targeted[tf_line.account] += diff
- diffs += diff
- if sink_account:
- self.diffs_targeted[sink_account] += diffs.as_sink
- elif diffs.as_sink.moneys:
- self.sink_error = 'sink missing for: '\
- + ', '.join(f'{amt} {cur}'
- for cur, amt in diffs.as_sink.moneys.items())
+ @property
+ def sink_error(self) -> str:
+ 'Message on error, if any, regarding sink calculation/placement.'
+ for _ in [tl for tl in self.transfer_lines
+ if tl.account != self._sink_account
+ and tl.amount is None
+ and not tl.errors]:
+ return 'too many sinks'
+ unsunk_moneys = self._diffs_targeted[''].moneys.items()
+ return ('' if not unsunk_moneys else
+ ('sink missing for: '
+ + (', '.join(f'{amt} {cur}' for cur, amt in unsunk_moneys))))
@property
def diffs_inheriting(self) -> dict[str, _Wealth]:
@property
def intro_line(self) -> _IntroLine:
'Return collected _IntroLine.'
- assert isinstance(self._lines[0], _IntroLine)
- return self._lines[0]
-
- @property
- def transfer_lines(self) -> list[_TransferLine]:
- 'Return collected _TransferLines.' # NB: currently no easy way to
- return self._lines[1:] # type: ignore # assert mypy list be of type
+ return _IntroLine(self._lines[0].raw)
@property
- def lines(self) -> list[_BookingLine]:
- return [self.intro_line] + list(self.transfer_lines)
+ def transfer_lines(self) -> tuple[_TransferLine, ...]:
+ 'Any lines past the first with .code.'
+ return tuple(_TransferLine(line.raw) for line in self._lines[1:]
+ if line.code)
@property
def date(self) -> str:
'Main other party for transaction.'
return self.intro_line.target
- def copy_to_current_date(self) -> Self:
- 'Make copy of same lines but now as date.'
- copy = self.copy()
- copy.intro_line.date = dt_date.today().isoformat()
- return copy
+class _DatBlock(_LinesBlock[_DatLine]):
+ 'Unit of lines with optional .booking, and (possibly zero) .gap_lines.'
+ _prev: Optional[Self] = None
+ _next: Optional[Self] = None
-class _DatBlock:
- 'Unit of lines with optional .booking, and possibly empty .gap.'
+ @classmethod
+ def from_lines(cls, lines: tuple[str, ...]) -> tuple['_DatBlock', ...]:
+ 'Sequence of DatBlocks parsed from lines.'
+ i_block: _DatBlock = cls()
+ blocks = []
+ for dat_line in (_DatLine(line) for line in lines):
+ if (not dat_line.indent) and i_block.indented:
+ blocks += [i_block]
+ i_block.next = _DatBlock()
+ i_block = i_block.next
+ i_block.add((dat_line, ))
+ return tuple(blocks)
- def __init__(
- self,
- booking: Optional['_Booking'],
- gap: Optional['_Gap'] = None
- ) -> None:
- self.booking = booking
- self.gap = gap if gap else _Gap()
- self._prev: Optional[Self] = None
- self._next: Optional[Self] = None
+ @property
+ def indented(self) -> bool:
+ 'Does the block contain any indented lines?'
+ return bool([line for line in self.lines if line.indent])
+
+ @property
+ def gap_lines(self) -> tuple[_DatLine, ...]:
+ 'Sequence of all included DatLines without code and indent.'
+ return tuple(line for line in self.lines
+ if not line.indent + line.code)
+
+ @property
+ def redundant_empty_lines(self) -> tuple[_DatLine, ...]:
+ 'Empty lines in sequence (separated between .gap_lines and .booking).'
+ redundancies: list[_DatLine] = []
+ for lines in (self.gap_lines,
+ self.booking.lines if self.booking else tuple()):
+ prev_line: Optional[_DatLine] = None
+ for line in lines:
+ if prev_line and not (line.raw.strip()
+ or prev_line.raw.strip()):
+ redundancies += [line]
+ prev_line = line
+ return tuple(redundancies)
+
+ def remove_redundant_empty_lines(self):
+ 'From self remove .redundant_empty_lines.'
+ for line in self.redundant_empty_lines:
+ self._lines.remove(line)
+
+ @property
+ def booking(self) -> Optional[_Booking]:
+ 'Booking made from lines indented or with code.'
+ booking_lines = tuple(_BookingLine(line.raw) for line in self.lines
+ if line.indent or line.code)
+ if not booking_lines:
+ return None
+ booking = _Booking()
+ booking.add(booking_lines)
+ return booking
@property
def id_(self) -> int:
return 'date < previous date'
return ''
- @property
- def lines(self) -> list[_BookingLine | _GapLine]:
- 'Return .lines of .booking and .gap as list[_DatLine].'
- lines = (self.booking.lines if self.booking else []) + self.gap.lines
- if self.booking and not self.gap.lines:
- lines += [_GapLine()]
- return lines
-
def _set_neighbor(
self,
new_this: Optional[Self],
setattr(self, f'_{this}', new_this)
@property
- def next(self) -> Optional['_DatBlock']:
+ def next(self) -> Optional[Self]:
'Successor in chain.'
return self._next
@next.setter
- def next(self, new_next: Optional['_DatBlock']) -> None:
+ def next(self, new_next: Optional[Self]) -> None:
self._set_neighbor(new_next, 'next', 'prev')
@property
- def prev(self) -> Optional['_DatBlock']:
+ def prev(self) -> Optional[Self]:
'Predecessor in chain.'
return self._prev
@prev.setter
- def prev(self, new_prev: Optional['_DatBlock']):
+ def prev(self, new_prev: Optional[Self]):
self._set_neighbor(new_prev, 'prev', 'next')
@property
self.prev = old_next
old_next.prev = old_prev
- def drop(self) -> None:
- 'Remove from chain.'
- if self.prev:
- self.prev.next = self.next
- elif self.next:
- self.next.prev = self.prev
-
def fix_position(self):
'Move around in chain until properly positioned by .date.'
while self.prev and self.prev.date > self.date:
while self.next and self.next.date < self.date:
self.move(up=False)
- def replace_with(self, new_block: Self) -> None:
- 'Have new_block take own position.'
- if self.prev:
- self.prev.next = new_block
- if self.next:
- self.next.prev = new_block
- new_block.fix_position()
-
- def copy_to_current_date(self) -> '_DatBlock':
- 'Make copy of same lines but now as date, position accordingly.'
- copy = _DatBlock(
- self.booking.copy_to_current_date() if self.booking else None,
- self.gap.copy())
+ def copy_to_current_date(self) -> Self:
+ 'Make copy of same lines but date of now, position accordingly.'
+ copy = self.__class__()
+ copy.add(tuple(_DatLine(line.raw) for line in self.gap_lines))
+ if self.booking:
+ copy.add((_DatLine(' '.join((dt_date.today().isoformat(),
+ self.booking.intro_line.target,
+ self.booking.intro_line.comment))),
+ ),
+ at_end=False)
+ copy.add(tuple(_DatLine(line.raw)
+ for line in self.booking.transfer_lines))
if self.next:
self.next.prev = copy
self.next = copy
def load(self) -> None:
'Re-)read ledger from file at ._path_dat.'
- dat_lines: list[_DatLine] = [
- _DatLine.from_raw(line)
- for line in self._path_dat.read_text(encoding='utf8').splitlines()]
- if (not dat_lines) or dat_lines[-1].code: # ensure final gap line so
- dat_lines += [_DatLine()] # last booking gets finished
- booking_lines: list[_BookingLine] = []
- i_block = _DatBlock(None, _Gap())
- self._blocks_start = i_block
- for dat_line in dat_lines:
- if bool(dat_line.code):
- if not booking_lines:
- booking_lines += [_IntroLine.from_dat(dat_line)]
- else:
- booking_lines += [_TransferLine.from_dat(dat_line)]
- else: # enter new gap -> ready to start next block
- if booking_lines:
- i_block.next = _DatBlock(_Booking(booking_lines))
- i_block = i_block.next
- booking_lines = []
- i_block.gap.add([_GapLine.from_dat(dat_line)])
+ blocks = _DatBlock.from_lines(
+ tuple(self._path_dat.read_text(encoding='utf8').splitlines()))
+ self._blocks_start = blocks[0] if blocks else _DatBlock()
self.last_save_hash = self._hash_dat_lines()
@property
return blocks
@property
- def _dat_lines(self) -> list[_DatLine]:
+ def _dat_lines(self) -> tuple[_DatLine, ...]:
'From .blocks build list of current _DatLines.'
lines = []
for block in self.blocks:
- lines += block.lines
- return [_DatLine(line.code, line.comment) for line in lines]
+ lines += list(block.lines)
+ return tuple(lines)
def _calc_accounts(self) -> dict[str, _Account]:
'Build mapping of account names to _Accounts.'
@property
def _has_redundant_empty_lines(self) -> bool:
- 'If any gaps have redunant empty lines.'
- return bool([b for b in self.blocks if b.gap.redundant_empty_lines])
+ 'If any blocks have redunant empty lines.'
+ return bool([b for b in self.blocks if b.redundant_empty_lines])
def remove_redundant_empty_lines(self) -> None:
'From all .blocks remove redundant empty lines.'
- for gap in [b.gap for b in self.blocks
- if b.gap.redundant_empty_lines]:
- gap.remove_redundant_empty_lines()
+ for block in self.blocks:
+ block.remove_redundant_empty_lines()
@property
def tainted(self) -> bool:
def rewrite_block(self, old_id: int, new_lines: list[str]) -> int:
'Rewrite with new_lines, move if changed date.'
- lines_gap_pre_booking: list[_GapLine] = []
- lines_booking: list[_BookingLine] = []
- lines_gap_post_booking: list[_GapLine] = []
- for dat_line in [_DatLine.from_raw(line) for line in new_lines]:
- if dat_line.code:
- if lines_gap_post_booking: # .code belongs to _next_ Booking
- lines_gap_post_booking += [_GapLine.from_dat(dat_line)]
- elif not lines_booking:
- lines_booking += [_IntroLine.from_dat(dat_line)]
- else:
- lines_booking += [_TransferLine.from_dat(dat_line)]
- else:
- if not lines_booking:
- lines_gap_pre_booking += [_GapLine.from_dat(dat_line)]
- else:
- lines_gap_post_booking += [_GapLine.from_dat(dat_line)]
old_block = self.blocks[old_id]
- if not lines_booking:
- if old_block.prev:
- old_block.prev.gap.add(lines_gap_pre_booking)
- old_block.drop()
- else:
- old_block.booking = None
- old_block.gap.add(lines_gap_pre_booking)
- return max(0, old_id - 1)
- new_block = _DatBlock(_Booking(lines_booking),
- _Gap(lines_gap_post_booking))
- self.blocks[old_id].replace_with(new_block)
- if not new_block.prev:
- self._blocks_start = _DatBlock(None, _Gap())
- self._blocks_start.next = new_block
- assert new_block.prev is not None
- if lines_gap_pre_booking:
- new_block.prev.gap.add(lines_gap_pre_booking)
- return new_block.id_
+ old_prev, old_next = old_block.prev, old_block.next
+ new_blocks = _DatBlock.from_lines(tuple(new_lines))
+ if old_next:
+ if not new_blocks[0].booking:
+ assert len(new_blocks) == 1
+ old_next.add(new_blocks[0].lines)
+ old_next.prev = old_prev
+ return old_next.id_
+ old_next.prev = new_blocks[-1]
+ if old_prev:
+ old_prev.next = new_blocks[0]
+ else:
+ self._blocks_start = new_blocks[0]
+ for block in new_blocks:
+ block.fix_position()
+ return new_blocks[0].id_
def add_empty_block(self) -> int:
'Add new _DatBlock of empty _Booking to end of ledger.'
- new_block = _DatBlock(
- _Booking([_IntroLine(dt_date.today().isoformat(), '?')]))
+ new_block = _DatBlock()
+ new_block.add((_DatLine(f'{dt_date.today().isoformat()} ?'), ))
self.blocks[-1].next = new_block
new_block.fix_position()
return new_block.id_
'All context data relevant for rendering an edit view.'
block = self.blocks[id_]
if lines:
- return {'raw_gap_lines': [dl.raw for dl in block.gap.lines],
- 'booking_lines': (
- [block.booking.intro_line.as_dict]
- + [tf_line.as_dict
- for tf_line in block.booking.transfer_lines]
- ) if block.booking else []}
+ return {'raw_gap_lines': [dl.raw for dl in block.gap_lines],
+ 'booking_lines': ([line.as_dict
+ for line in block.booking.lines]
+ if block.booking else tuple())}
accounts = self._calc_accounts()
roots: list[dict[str, Any]] = []
for full_path in sorted(block.booking.diffs_targeted.keys()
'valid': self._blocks_valid_up_incl(id_),
'roots': roots}
if not raw:
- ctx['raw_gap_lines'] = [dl.raw for dl in block.gap.lines]
+ ctx['raw_gap_lines'] = [dl.raw for dl in block.gap_lines]
ctx['all_accounts'] = sorted(accounts.keys())
return ctx
<input id="replace_to" />
</span>
<hr />
-<table id="booking_lines" class="alternating">
-</table>
<div>Gap:</div>
<textarea id="gap_lines"
name="raw_lines"
class="tainter"
>
</textarea>
+<table id="booking_lines" class="alternating">
+</table>
</form>
<datalist id="all_accounts">
{% for acc in all_accounts %}
table = document.getElementById("booking_lines"),
textarea = document.getElementById("gap_lines");
- // empty and redo gapLines, empty bookingLines table
- textarea.value = "";
+ // empty and redo gapLines textarea, empty bookingLines table
+ textarea.innerHTML = ""
rawGapLines.forEach((line) => {
- textarea.value += `${line}\n`;
+ textarea.innerHTML += `${line}\n`;
});
table.innerHTML = "";
<tbody>
{% for block in blocks %}
{{ macros.ledger_block_columns('structured', block) -}}
+{##}{% for line in block.gap_lines %}
+ <tr>
+ <td colspan=4>{{ line.raw }} </td>
+ </tr>
+{##}{% endfor %}
{##}{% if block.booking %}
<tr>
<td colspan=3{{ ' class="critical"'
</tr>
{####}{% endfor %}
{##}{% endif %}
-{##}{% for line in block.gap.lines %}
- <tr>
- <td colspan=4>{{ line.raw }} </td>
- </tr>
-{##}{% endfor %}
{% endfor %}
</tbody>
</table>
<tbody>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_0">
- <td rowspan="2" class="block_column">
+ <td rowspan="1" class="block_column">
<input type="submit" name="ledger_moveup_0" value="^" disabled="">
<br>
<input type="submit" name="ledger_movedown_0" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_0" value="C">
</td>
- <td rowspan="2" class="block_column">
+ <td rowspan="1" class="block_column">
[<a href="#block_0">#</a>]<br>
[<a href="/balance/0">b</a>]<br>
[<a href="/edit_raw/0">e</a>]
</td>
</tr>
- <tr><td> </td></tr>
</tbody>
</table>
</form>
<tbody>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_0">
- <td rowspan="2" class="block_column">
+ <td rowspan="1" class="block_column">
<input type="submit" name="ledger_moveup_0" value="^" disabled="">
<br>
<input type="submit" name="ledger_movedown_0" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_0" value="C">
</td>
- <td rowspan="2" class="block_column">
+ <td rowspan="1" class="block_column">
[<a href="#block_0">#</a>]<br>
[<a href="/balance/0">b</a>]<br>
[<a href="/edit_structured/0">e</a>]
</td>
</tr>
- <tr>
- <td colspan="4"> </td>
- </tr>
</tbody>
</table>
<input type="submit" name="add_booking" value="add booking">
</form>
</div>
<p>
- <a href="/balance/4">prev</a>
+ <a href="/balance/3">prev</a>
<del>next</del>
|
- balance after <a href="/blocks/5">booking 5 (2001-01-03: test)</a>
+ balance after <a href="/blocks/4">booking 4 (2001-01-03: test)</a>
</p>
<table class="alternating critical">
<tbody>
--- /dev/null
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<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="/balance/3" method="POST">
+ <span class="disable_on_taint">
+ 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/2">prev</a>
+ <a href="/balance/4">next</a>
+ |
+ balance after <a href="/blocks/3">booking 3 (2001-01-03: test)</a>
+</p>
+<table class="alternating ">
+<tbody>
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"></span>bar:
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:x:
+ </td>
+ <td>bla bla bla</td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:y
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <span class="indent"> </span>:z
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <span class="indent"></span>baz
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">20</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"></span>foo:
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="money">
+ <details>
+ <summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </summary>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </details>
+ </td>
+ <td>
+ <span class="indent"> </span>:x
+ </td>
+ <td></td>
+ </tr>
+</tbody>
+</table>
+
+</body></html>
+++ /dev/null
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<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="/balance/4" method="POST">
- <span class="disable_on_taint">
- 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/3">prev</a>
- <a href="/balance/5">next</a>
- |
- balance after <a href="/blocks/4">booking 4 (2001-01-03: test)</a>
-</p>
-<table class="alternating ">
-<tbody>
- <tr>
- <td class="money">
- <details>
- <summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </details>
- </td>
- <td>
- <span class="indent"></span>bar:
- </td>
- <td></td>
- </tr>
- <tr>
- <td class="money">
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <span class="indent"> </span>:x:
- </td>
- <td>bla bla bla</td>
- </tr>
- <tr>
- <td class="money">
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <span class="indent"> </span>:y
- </td>
- <td></td>
- </tr>
- <tr>
- <td class="money">
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <span class="indent"> </span>:z
- </td>
- <td></td>
- </tr>
- <tr>
- <td class="money">
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <span class="indent"></span>baz
- </td>
- <td></td>
- </tr>
- <tr>
- <td class="money">
- <details>
- <summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">20</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </details>
- </td>
- <td>
- <span class="indent"></span>foo:
- </td>
- <td></td>
- </tr>
- <tr>
- <td class="money">
- <details>
- <summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </summary>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </details>
- </td>
- <td>
- <span class="indent"> </span>:x
- </td>
- <td></td>
- </tr>
-</tbody>
-</table>
-
-</body></html>
--- /dev/null
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/taint.js">
+</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.direct_target {
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="/edit_raw/0" method="POST">
+ <span class="disable_on_taint">
+ 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>
+<form action="/edit_raw/0" method="POST">
+<span class="disable_on_taint">
+<del>prev</del>
+<a href="/blocks/1">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_structured/0">switch to structured</a>
+·
+<a href="/balance/0">balance after</a>
+·
+<a href="/ledger_raw/#block_0">in ledger</a>
+</span>
+<hr>
+
+<textarea name="raw_lines" class="tainter" cols="100" rows="6">; #def bar:x bla bla bla
+
+2001-01-01 test ; foo
+ foo 10 €
+ bar -10 €
+</textarea>
+</form>
+<table class="alternating">
+<tbody>
+ <tr>
+ <th>account</th>
+ <th>before</th>
+ <th>diff</th>
+ <th>after</th>
+ </tr>
+ <tr>
+ <td class="direct_target">bar</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">foo</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+</body></html>
+++ /dev/null
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/taint.js">
-</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.direct_target {
- font-weight: bold;
-}
-</style>
-</head>
-<body>
-<div id="header">
- <form action="/edit_raw/1" method="POST">
- <span class="disable_on_taint">
- 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>
-<form action="/edit_raw/1" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/0">prev</a>
-<a href="/blocks/2">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_structured/1">switch to structured</a>
-·
-<a href="/balance/1">balance after</a>
-·
-<a href="/ledger_raw/#block_1">in ledger</a>
-</span>
-<hr>
-
-<textarea name="raw_lines" class="tainter" cols="100" rows="5">2001-01-01 test ; foo
- foo 10 €
- bar -10 €
-
-</textarea>
-</form>
-<table class="alternating">
-<tbody>
- <tr>
- <th>account</th>
- <th>before</th>
- <th>diff</th>
- <th>after</th>
- </tr>
- <tr>
- <td class="direct_target">bar</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">foo</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
-</tbody>
-</table>
-
-</body></html>
--- /dev/null
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/taint.js">
+</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.direct_target {
+ font-weight: bold;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="/edit_raw/3" method="POST">
+ <span class="disable_on_taint">
+ 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>
+<form action="/edit_raw/3" method="POST">
+<span class="disable_on_taint">
+<a href="/blocks/2">prev</a>
+<a href="/blocks/4">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_structured/3">switch to structured</a>
+·
+<a href="/balance/3">balance after</a>
+·
+<a href="/ledger_raw/#block_3">in ledger</a>
+</span>
+<hr>
+
+<textarea name="raw_lines" class="tainter" cols="100" rows="7">
+2001-01-03 test
+ foo:x 10 €
+ foo:x 1 USD
+ bar:x:y -10 €
+ bar:z -1 USD
+</textarea>
+</form>
+<table class="alternating">
+<tbody>
+ <tr>
+ <th>account</th>
+ <th>before</th>
+ <th>diff</th>
+ <th>after</th>
+ </tr>
+ <tr>
+ <td>bar:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>bar:x:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">bar:x:y</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">bar:z</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>foo:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">20</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">foo:x</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+</body></html>
+++ /dev/null
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/taint.js">
-</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.direct_target {
- font-weight: bold;
-}
-</style>
-</head>
-<body>
-<div id="header">
- <form action="/edit_raw/4" method="POST">
- <span class="disable_on_taint">
- 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>
-<form action="/edit_raw/4" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/3">prev</a>
-<a href="/blocks/5">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_structured/4">switch to structured</a>
-·
-<a href="/balance/4">balance after</a>
-·
-<a href="/ledger_raw/#block_4">in ledger</a>
-</span>
-<hr>
-
-<textarea name="raw_lines" class="tainter" cols="100" rows="7">2001-01-03 test
- foo:x 10 €
- foo:x 1 USD
- bar:x:y -10 €
- bar:z -1 USD
-
-</textarea>
-</form>
-<table class="alternating">
-<tbody>
- <tr>
- <th>account</th>
- <th>before</th>
- <th>diff</th>
- <th>after</th>
- </tr>
- <tr>
- <td>bar:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td>bar:x:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">bar:x:y</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">bar:z</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td>foo:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">20</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">foo:x</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
-</tbody>
-</table>
-
-</body></html>
--- /dev/null
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/edit_structured.js/0">
+</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.direct_target {
+ font-weight: bold;
+}
+
+input.amount {
+ text-align: right;
+ font-family: monospace;
+}
+#date_input {
+ margin-right: 0.3em;
+ font-family: monospace;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="/edit_structured/0" method="POST">
+ <span class="disable_on_taint">
+ 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>
+<form action="/edit_structured/0" method="POST">
+<span class="disable_on_taint">
+<del>prev</del>
+<a href="/blocks/1">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_raw/0">switch to raw</a>
+·
+<a href="/balance/0">balance after</a>
+·
+<a href="/ledger_structured/#block_0">in ledger</a>
+</span>
+<hr>
+
+<span class="disable_on_taint">
+<input id="btn_mirror" type="button" value="mirror">
+<input id="btn_sink" type="button" value="fill sink">
+|
+<input id="btn_replace" type="button" value="replace string">
+from
+<input id="replace_from">
+to
+<input id="replace_to">
+</span>
+<hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="3" class="tainter">; #def bar:x bla bla bla
+
+</textarea>
+<EXPANDED>
+<table id="booking_lines" class="alternating">
+ <tr>
+ <td colspan="1">
+ </td>
+ <td colspan="3">
+ <input name="line_0_date" size="10" value="2001-01-01" id="date_input">
+ <input name="line_0_target" size="37" value="test">
+ </td>
+ <td colspan="1">
+ <input name="line_0_comment" size="40" value="foo">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button" disabled="">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_1_account" size="30" value="foo" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_1_currency" size="3" value="€" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_1_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_2_account" size="30" value="bar" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_2_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_2_currency" size="3" value="€" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_2_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+</table>
+</EXPANDED>
+</form>
+<datalist id="all_accounts">
+<option value="bar">bar</option>
+<option value="bar:x">bar:x</option>
+<option value="bar:x:y">bar:x:y</option>
+<option value="bar:z">bar:z</option>
+<option value="baz">baz</option>
+<option value="foo">foo</option>
+<option value="foo:x">foo:x</option>
+</datalist>
+<hr>
+<table class="alternating">
+<tbody>
+ <tr>
+ <th>account</th>
+ <th>before</th>
+ <th>diff</th>
+ <th>after</th>
+ </tr>
+ <tr>
+ <td class="direct_target">bar</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">foo</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+</body></html>
+++ /dev/null
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/edit_structured.js/1">
-</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.direct_target {
- font-weight: bold;
-}
-
-input.amount {
- text-align: right;
- font-family: monospace;
-}
-#date_input {
- margin-right: 0.3em;
- font-family: monospace;
-}
-</style>
-</head>
-<body>
-<div id="header">
- <form action="/edit_structured/1" method="POST">
- <span class="disable_on_taint">
- 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>
-<form action="/edit_structured/1" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/0">prev</a>
-<a href="/blocks/2">next</a>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_raw/1">switch to raw</a>
-·
-<a href="/balance/1">balance after</a>
-·
-<a href="/ledger_structured/#block_1">in ledger</a>
-</span>
-<hr>
-
-<span class="disable_on_taint">
-<input id="btn_mirror" type="button" value="mirror">
-<input id="btn_sink" type="button" value="fill sink">
-|
-<input id="btn_replace" type="button" value="replace string">
-from
-<input id="replace_from">
-to
-<input id="replace_to">
-</span>
-<hr>
-<EXPANDED>
-<table id="booking_lines" class="alternating">
- <tr>
- <td colspan="1">
- </td>
- <td colspan="3">
- <input name="line_0_date" size="10" value="2001-01-01" id="date_input">
- <input name="line_0_target" size="37" value="test">
- </td>
- <td colspan="1">
- <input name="line_0_comment" size="40" value="foo">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button" disabled="">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_1_account" size="30" value="foo" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_1_currency" size="3" value="€" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_1_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_2_account" size="30" value="bar" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_2_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_2_currency" size="3" value="€" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_2_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
-</table>
-</EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
-</form>
-<datalist id="all_accounts">
-<option value="bar">bar</option>
-<option value="bar:x">bar:x</option>
-<option value="bar:x:y">bar:x:y</option>
-<option value="bar:z">bar:z</option>
-<option value="baz">baz</option>
-<option value="foo">foo</option>
-<option value="foo:x">foo:x</option>
-</datalist>
-<hr>
-<table class="alternating">
-<tbody>
- <tr>
- <th>account</th>
- <th>before</th>
- <th>diff</th>
- <th>after</th>
- </tr>
- <tr>
- <td class="direct_target">bar</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">foo</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">0</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
-</tbody>
-</table>
-
-</body></html>
--- /dev/null
+<!DOCTYPE html><html><head>
+<meta charset="UTF-8">
+<script type="module" src="/edit_structured.js/3">
+</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.direct_target {
+ font-weight: bold;
+}
+
+input.amount {
+ text-align: right;
+ font-family: monospace;
+}
+#date_input {
+ margin-right: 0.3em;
+ font-family: monospace;
+}
+</style>
+</head>
+<body>
+<div id="header">
+ <form action="/edit_structured/3" method="POST">
+ <span class="disable_on_taint">
+ 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>
+<form action="/edit_structured/3" method="POST">
+<span class="disable_on_taint">
+<a href="/blocks/2">prev</a>
+<a href="/blocks/4">next</a>
+</span>
+<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
+<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
+<span class="disable_on_taint">
+<a href="/edit_raw/3">switch to raw</a>
+·
+<a href="/balance/3">balance after</a>
+·
+<a href="/ledger_structured/#block_3">in ledger</a>
+</span>
+<hr>
+
+<span class="disable_on_taint">
+<input id="btn_mirror" type="button" value="mirror">
+<input id="btn_sink" type="button" value="fill sink">
+|
+<input id="btn_replace" type="button" value="replace string">
+from
+<input id="replace_from">
+to
+<input id="replace_to">
+</span>
+<hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter">
+</textarea>
+<EXPANDED>
+<table id="booking_lines" class="alternating">
+ <tr>
+ <td colspan="1">
+ </td>
+ <td colspan="3">
+ <input name="line_0_date" size="10" value="2001-01-03" id="date_input">
+ <input name="line_0_target" size="37" value="test">
+ </td>
+ <td colspan="1">
+ <input name="line_0_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button" disabled="">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_1_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_1_currency" size="3" value="€" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_1_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_2_amount" size="12" value="1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_2_currency" size="3" value="USD" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_2_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_3_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_3_currency" size="3" value="€" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_3_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <button type="button">^</button>
+ <button type="button">v</button>
+ </td>
+ <td colspan="1">
+ <input name="line_4_account" size="30" value="bar:z" list="all_accounts" autocomplete="off">
+ </td>
+ <td colspan="1">
+ <input name="line_4_amount" size="12" value="-1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ </td>
+ <td colspan="1">
+ <input name="line_4_currency" size="3" value="USD" placeholder="€">
+ </td>
+ <td colspan="1">
+ <input name="line_4_comment" size="40" value="">
+ </td>
+ <td colspan="1">
+ <button type="button">add new</button>
+ <button type="button">delete</button>
+ </td>
+ </tr>
+</table>
+</EXPANDED>
+</form>
+<datalist id="all_accounts">
+<option value="bar">bar</option>
+<option value="bar:x">bar:x</option>
+<option value="bar:x:y">bar:x:y</option>
+<option value="bar:z">bar:z</option>
+<option value="baz">baz</option>
+<option value="foo">foo</option>
+<option value="foo:x">foo:x</option>
+</datalist>
+<hr>
+<table class="alternating">
+<tbody>
+ <tr>
+ <th>account</th>
+ <th>before</th>
+ <th>diff</th>
+ <th>after</th>
+ </tr>
+ <tr>
+ <td>bar:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>bar:x:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">bar:x:y</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">bar:z</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">-1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td>foo:</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">20</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td class="direct_target">foo:x</td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">0</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ <td>
+ <table>
+ <tbody>
+ <tr>
+ <td class="balance amount">10</td>
+ <td class="balance currency">€</td>
+ </tr>
+ <tr>
+ <td class="balance amount">1</td>
+ <td class="balance currency">USD</td>
+ </tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+</tbody>
+</table>
+
+</body></html>
<form action="/edit_structured/4" method="POST">
<span class="disable_on_taint">
<a href="/blocks/3">prev</a>
-<a href="/blocks/5">next</a>
+<del>next</del>
</span>
<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
<a href="/ledger_structured/#block_4">in ledger</a>
</span>
<hr>
+<div class="critical">
+ block-wide errors:
+
+ sink missing for: -1 €, -2 USD
+</div>
+<hr>
<span class="disable_on_taint">
<input id="btn_mirror" type="button" value="mirror">
<input id="replace_to">
</span>
<hr>
+<div>Gap:</div>
+<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter">
+</textarea>
<EXPANDED>
<table id="booking_lines" class="alternating">
<tr>
<input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
</td>
<td colspan="1">
- <input name="line_2_amount" size="12" value="1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ <input name="line_2_amount" size="12" value="3" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
</td>
<td colspan="1">
<input name="line_2_currency" size="3" value="USD" placeholder="€">
<input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
</td>
<td colspan="1">
- <input name="line_3_amount" size="12" value="-10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
+ <input name="line_3_amount" size="12" value="-9" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
</td>
<td colspan="1">
<input name="line_3_currency" size="3" value="€" placeholder="€">
</tr>
</table>
</EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
</form>
<datalist id="all_accounts">
<option value="bar">bar</option>
<option value="foo:x">foo:x</option>
</datalist>
<hr>
-<table class="alternating">
+<table class="alternating critical">
<tbody>
<tr>
<th>account</th>
<table>
<tbody>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">-10</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">-1</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-9</td>
<td class="balance currency">€</td>
</tr>
<tr>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-19</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">-1</td>
+ <td class="balance amount">-2</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">-10</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-9</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-19</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">-10</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-9</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-10</td>
+ <td class="balance amount">-19</td>
<td class="balance currency">€</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">-1</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">-1</td>
+ <td class="balance amount">-2</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">10</td>
+ <td class="balance amount">20</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">1</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">1</td>
+ <td class="balance amount">3</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">20</td>
+ <td class="balance amount">30</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">1</td>
+ <td class="balance amount">4</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">10</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">0</td>
+ <td class="balance amount">1</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">1</td>
+ <td class="balance amount">3</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
<table>
<tbody>
<tr>
- <td class="balance amount">10</td>
+ <td class="balance amount">20</td>
<td class="balance currency">€</td>
</tr>
<tr>
- <td class="balance amount">1</td>
+ <td class="balance amount">4</td>
<td class="balance currency">USD</td>
</tr>
</tbody>
+++ /dev/null
-<!DOCTYPE html><html><head>
-<meta charset="UTF-8">
-<script type="module" src="/edit_structured.js/5">
-</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.direct_target {
- font-weight: bold;
-}
-
-input.amount {
- text-align: right;
- font-family: monospace;
-}
-#date_input {
- margin-right: 0.3em;
- font-family: monospace;
-}
-</style>
-</head>
-<body>
-<div id="header">
- <form action="/edit_structured/5" method="POST">
- <span class="disable_on_taint">
- 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>
-<form action="/edit_structured/5" method="POST">
-<span class="disable_on_taint">
-<a href="/blocks/4">prev</a>
-<del>next</del>
-</span>
-<input class="enable_on_taint" type="submit" name="apply" value="apply" disabled="">
-<input class="enable_on_taint" type="submit" name="revert" value="revert" disabled="">
-<span class="disable_on_taint">
-<a href="/edit_raw/5">switch to raw</a>
-·
-<a href="/balance/5">balance after</a>
-·
-<a href="/ledger_structured/#block_5">in ledger</a>
-</span>
-<hr>
-<div class="critical">
- block-wide errors:
-
- sink missing for: -1 €, -2 USD
-</div>
-<hr>
-
-<span class="disable_on_taint">
-<input id="btn_mirror" type="button" value="mirror">
-<input id="btn_sink" type="button" value="fill sink">
-|
-<input id="btn_replace" type="button" value="replace string">
-from
-<input id="replace_from">
-to
-<input id="replace_to">
-</span>
-<hr>
-<EXPANDED>
-<table id="booking_lines" class="alternating">
- <tr>
- <td colspan="1">
- </td>
- <td colspan="3">
- <input name="line_0_date" size="10" value="2001-01-03" id="date_input">
- <input name="line_0_target" size="37" value="test">
- </td>
- <td colspan="1">
- <input name="line_0_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button" disabled="">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_1_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_1_amount" size="12" value="10" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_1_currency" size="3" value="€" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_1_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_2_account" size="30" value="foo:x" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_2_amount" size="12" value="3" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_2_currency" size="3" value="USD" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_2_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_3_account" size="30" value="bar:x:y" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_3_amount" size="12" value="-9" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_3_currency" size="3" value="€" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_3_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
- <tr>
- <td colspan="1">
- <button type="button">^</button>
- <button type="button">v</button>
- </td>
- <td colspan="1">
- <input name="line_4_account" size="30" value="bar:z" list="all_accounts" autocomplete="off">
- </td>
- <td colspan="1">
- <input name="line_4_amount" size="12" value="-1" pattern="^-?[0-9]+(.[0-9]+)?$" class="amount">
- </td>
- <td colspan="1">
- <input name="line_4_currency" size="3" value="USD" placeholder="€">
- </td>
- <td colspan="1">
- <input name="line_4_comment" size="40" value="">
- </td>
- <td colspan="1">
- <button type="button">add new</button>
- <button type="button">delete</button>
- </td>
- </tr>
-</table>
-</EXPANDED>
-<div>Gap:</div>
-<textarea id="gap_lines" name="raw_lines" cols="100" rows="2" class="tainter"></textarea>
-</form>
-<datalist id="all_accounts">
-<option value="bar">bar</option>
-<option value="bar:x">bar:x</option>
-<option value="bar:x:y">bar:x:y</option>
-<option value="bar:z">bar:z</option>
-<option value="baz">baz</option>
-<option value="foo">foo</option>
-<option value="foo:x">foo:x</option>
-</datalist>
-<hr>
-<table class="alternating critical">
-<tbody>
- <tr>
- <th>account</th>
- <th>before</th>
- <th>diff</th>
- <th>after</th>
- </tr>
- <tr>
- <td>bar:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-9</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-19</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">-2</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td>bar:x:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-9</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-19</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">bar:x:y</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-10</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-9</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-19</td>
- <td class="balance currency">€</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">bar:z</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">-2</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td>foo:</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">20</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">3</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">30</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">4</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
- <tr>
- <td class="direct_target">foo:x</td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">1</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">10</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">3</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- <td>
- <table>
- <tbody>
- <tr>
- <td class="balance amount">20</td>
- <td class="balance currency">€</td>
- </tr>
- <tr>
- <td class="balance amount">4</td>
- <td class="balance currency">USD</td>
- </tr>
- </tbody>
- </table>
- </td>
- </tr>
-</tbody>
-</table>
-
-</body></html>
<tbody>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_0">
- <td rowspan="3" class="block_column">
+ <td rowspan="6" class="block_column">
<input type="submit" name="ledger_moveup_0" value="^" disabled="">
<br>
<input type="submit" name="ledger_movedown_0" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_0" value="C">
</td>
- <td rowspan="3" class="block_column">
+ <td rowspan="6" class="block_column">
[<a href="#block_0">#</a>]<br>
[<a href="/balance/0">b</a>]<br>
[<a href="/edit_raw/0">e</a>]
</tr>
<tr><td>; #def bar:x bla bla bla </td></tr>
<tr><td> </td></tr>
+ <tr><td>2001-01-01 test ; foo </td></tr>
+ <tr><td> foo 10 € </td></tr>
+ <tr><td> bar -10 € </td></tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_1">
<td rowspan="5" class="block_column">
<input type="submit" name="ledger_moveup_1" value="^" disabled="">
<br>
- <input type="submit" name="ledger_movedown_1" value="v" disabled="">
+ <input type="submit" name="ledger_movedown_1" value="v">
<br>
<input type="submit" name="ledger_copy_1" value="C">
</td>
[<a href="/edit_raw/1">e</a>]
</td>
</tr>
- <tr><td>2001-01-01 test ; foo </td></tr>
- <tr><td> foo 10 € </td></tr>
- <tr><td> bar -10 € </td></tr>
<tr><td> </td></tr>
+ <tr><td>2001-01-02 test </td></tr>
+ <tr><td> bar -10 € ; bar </td></tr>
+ <tr><td> baz 10 € </td></tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_2">
<td rowspan="6" class="block_column">
- <input type="submit" name="ledger_moveup_2" value="^" disabled="">
+ <input type="submit" name="ledger_moveup_2" value="^">
<br>
- <input type="submit" name="ledger_movedown_2" value="v">
+ <input type="submit" name="ledger_movedown_2" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_2" value="C">
</td>
[<a href="/edit_raw/2">e</a>]
</td>
</tr>
- <tr><td>2001-01-02 test </td></tr>
- <tr><td> bar -10 € ; bar </td></tr>
- <tr><td> baz 10 € </td></tr>
<tr><td> </td></tr>
<tr><td> </td></tr>
+ <tr><td>2001-01-02 test </td></tr>
+ <tr><td> bar 20 € </td></tr>
+ <tr><td> baz -20 € ; baz </td></tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_3">
- <td rowspan="5" class="block_column">
- <input type="submit" name="ledger_moveup_3" value="^">
+ <td rowspan="7" class="block_column">
+ <input type="submit" name="ledger_moveup_3" value="^" disabled="">
<br>
- <input type="submit" name="ledger_movedown_3" value="v" disabled="">
+ <input type="submit" name="ledger_movedown_3" value="v">
<br>
<input type="submit" name="ledger_copy_3" value="C">
</td>
- <td rowspan="5" class="block_column">
+ <td rowspan="7" class="block_column">
[<a href="#block_3">#</a>]<br>
[<a href="/balance/3">b</a>]<br>
[<a href="/edit_raw/3">e</a>]
</td>
</tr>
- <tr><td>2001-01-02 test </td></tr>
- <tr><td> bar 20 € </td></tr>
- <tr><td> baz -20 € ; baz </td></tr>
<tr><td> </td></tr>
+ <tr><td>2001-01-03 test </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></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_4">
<td rowspan="7" class="block_column">
- <input type="submit" name="ledger_moveup_4" value="^" disabled="">
+ <input type="submit" name="ledger_moveup_4" value="^">
<br>
- <input type="submit" name="ledger_movedown_4" value="v">
+ <input type="submit" name="ledger_movedown_4" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_4" value="C">
</td>
- <td rowspan="7" class="block_column">
+ <td rowspan="7" class="block_column critical">
[<a href="#block_4">#</a>]<br>
[<a href="/balance/4">b</a>]<br>
[<a href="/edit_raw/4">e</a>]
</td>
</tr>
- <tr><td>2001-01-03 test </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>
- <tr></tr><!-- keep the background-color alternation in proper order -->
- <tr id="block_5">
- <td rowspan="7" class="block_column">
- <input type="submit" name="ledger_moveup_5" value="^">
- <br>
- <input type="submit" name="ledger_movedown_5" value="v" disabled="">
- <br>
- <input type="submit" name="ledger_copy_5" value="C">
- </td>
- <td rowspan="7" class="block_column critical">
- [<a href="#block_5">#</a>]<br>
- [<a href="/balance/5">b</a>]<br>
- [<a href="/edit_raw/5">e</a>]
- </td>
- </tr>
<tr><td>2001-01-03 test </td></tr>
- <tr><td> foo:x 10 € </td></tr>
- <tr><td> foo:x 3 USD </td></tr>
- <tr><td> bar:x:y -9 € </td></tr>
- <tr><td> bar:z -1 USD </td></tr>
- <tr><td> </td></tr>
+ <tr><td> foo:x 10 € </td></tr>
+ <tr><td> foo:x 3 USD </td></tr>
+ <tr><td> bar:x:y -9 € </td></tr>
+ <tr><td> bar:z -1 USD </td></tr>
</tbody>
</table>
</form>
<tbody>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_0">
- <td rowspan="3" class="block_column">
+ <td rowspan="6" class="block_column">
<input type="submit" name="ledger_moveup_0" value="^" disabled="">
<br>
<input type="submit" name="ledger_movedown_0" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_0" value="C">
</td>
- <td rowspan="3" class="block_column">
+ <td rowspan="6" class="block_column">
[<a href="#block_0">#</a>]<br>
[<a href="/balance/0">b</a>]<br>
[<a href="/edit_structured/0">e</a>]
<tr>
<td colspan="4"> </td>
</tr>
+ <tr>
+ <td colspan="3">2001-01-01 test</td>
+ <td>foo</td>
+ </tr>
+ <tr>
+ <td class="amount">10.00</td>
+ <td class="currency">€</td>
+ <td>foo</td>
+ <td></td>
+ </tr>
+ <tr>
+ <td class="amount">-10.00</td>
+ <td class="currency">€</td>
+ <td>bar</td>
+ <td></td>
+ </tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_1">
<td rowspan="5" class="block_column">
<input type="submit" name="ledger_moveup_1" value="^" disabled="">
<br>
- <input type="submit" name="ledger_movedown_1" value="v" disabled="">
+ <input type="submit" name="ledger_movedown_1" value="v">
<br>
<input type="submit" name="ledger_copy_1" value="C">
</td>
</td>
</tr>
<tr>
- <td colspan="3">2001-01-01 test</td>
- <td>foo</td>
+ <td colspan="4"> </td>
</tr>
<tr>
- <td class="amount">10.00</td>
- <td class="currency">€</td>
- <td>foo</td>
+ <td colspan="3">2001-01-02 test</td>
<td></td>
</tr>
<tr>
<td class="amount">-10.00</td>
<td class="currency">€</td>
<td>bar</td>
- <td></td>
+ <td>bar</td>
</tr>
<tr>
- <td colspan="4"> </td>
+ <td class="amount">10.00</td>
+ <td class="currency">€</td>
+ <td>baz</td>
+ <td></td>
</tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
<tr id="block_2">
<td rowspan="6" class="block_column">
- <input type="submit" name="ledger_moveup_2" value="^" disabled="">
+ <input type="submit" name="ledger_moveup_2" value="^">
<br>
- <input type="submit" name="ledger_movedown_2" value="v">
+ <input type="submit" name="ledger_movedown_2" value="v" disabled="">
<br>
<input type="submit" name="ledger_copy_2" value="C">
</td>
[<a href="/edit_structured/2">e</a>]
</td>
</tr>
- <tr>
- <td colspan="3">2001-01-02 test</td>
- <td></td>
- </tr>
- <tr>
- <td class="amount">-10.00</td>
- <td class="currency">€</td>
- <td>bar</td>
- <td>bar</td>
- </tr>
- <tr>
- <td class="amount">10.00</td>
- <td class="currency">€</td>
- <td>baz</td>
- <td></td>
- </tr>
<tr>
<td colspan="4"> </td>
</tr>
<tr>
<td colspan="4"> </td>
</tr>
- <tr></tr><!-- keep the background-color alternation in proper order -->
- <tr id="block_3">
- <td rowspan="5" class="block_column">
- <input type="submit" name="ledger_moveup_3" value="^">
- <br>
- <input type="submit" name="ledger_movedown_3" value="v" disabled="">
- <br>
- <input type="submit" name="ledger_copy_3" value="C">
- </td>
- <td rowspan="5" class="block_column">
- [<a href="#block_3">#</a>]<br>
- [<a href="/balance/3">b</a>]<br>
- [<a href="/edit_structured/3">e</a>]
- </td>
- </tr>
<tr>
<td colspan="3">2001-01-02 test</td>
<td></td>
<td>baz</td>
<td>baz</td>
</tr>
- <tr>
- <td colspan="4"> </td>
- </tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
- <tr id="block_4">
+ <tr id="block_3">
<td rowspan="7" class="block_column">
- <input type="submit" name="ledger_moveup_4" value="^" disabled="">
+ <input type="submit" name="ledger_moveup_3" value="^" disabled="">
<br>
- <input type="submit" name="ledger_movedown_4" value="v">
+ <input type="submit" name="ledger_movedown_3" value="v">
<br>
- <input type="submit" name="ledger_copy_4" value="C">
+ <input type="submit" name="ledger_copy_3" value="C">
</td>
<td rowspan="7" class="block_column">
- [<a href="#block_4">#</a>]<br>
- [<a href="/balance/4">b</a>]<br>
- [<a href="/edit_structured/4">e</a>]
+ [<a href="#block_3">#</a>]<br>
+ [<a href="/balance/3">b</a>]<br>
+ [<a href="/edit_structured/3">e</a>]
</td>
</tr>
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
<tr>
<td colspan="3">2001-01-03 test</td>
<td></td>
<td>bar:z</td>
<td></td>
</tr>
- <tr>
- <td colspan="4"> </td>
- </tr>
<tr></tr><!-- keep the background-color alternation in proper order -->
- <tr id="block_5">
+ <tr id="block_4">
<td rowspan="7" class="block_column">
- <input type="submit" name="ledger_moveup_5" value="^">
+ <input type="submit" name="ledger_moveup_4" value="^">
<br>
- <input type="submit" name="ledger_movedown_5" value="v" disabled="">
+ <input type="submit" name="ledger_movedown_4" value="v" disabled="">
<br>
- <input type="submit" name="ledger_copy_5" value="C">
+ <input type="submit" name="ledger_copy_4" value="C">
</td>
<td rowspan="7" class="block_column critical">
- [<a href="#block_5">#</a>]<br>
- [<a href="/balance/5">b</a>]<br>
- [<a href="/edit_structured/5">e</a>]
+ [<a href="#block_4">#</a>]<br>
+ [<a href="/balance/4">b</a>]<br>
+ [<a href="/edit_structured/4">e</a>]
</td>
</tr>
+ <tr>
+ <td colspan="4"> </td>
+ </tr>
<tr>
<td colspan="3">2001-01-03 test</td>
<td></td>
<td>bar:z</td>
<td></td>
</tr>
- <tr>
- <td colspan="4"> </td>
- </tr>
</tbody>
</table>
<input type="submit" name="add_booking" value="add booking">