halves = [t.rstrip() for t in line.split(';', maxsplit=1)]
self.comment = halves[1] if len(halves) > 1 else ''
self.code = halves[0]
- self.type = 'no_data'
- self.booking: Optional[Booking] = None
- if self.code:
- self.type = 'invalid'
- if self.code[0].isspace():
- toks = self.code.lstrip().split()
- self.acc = toks[0]
- if 1 == len(toks):
- self.amt, self.curr = '', ''
- self.type = 'value'
- elif 3 == len(toks):
- amt_dec = Decimal(toks[1])
- exp = amt_dec.as_tuple().exponent
- assert isinstance(exp, int)
- self.amt = (f'{amt_dec:.1f}…' if exp < -2
- else f'{amt_dec:.2f}')
- self.curr = toks[2]
- self.type = 'value'
- else:
- self.type = 'intro'
+ self.booking_line: Optional[BookingLine] = None
+
+ @property
+ def type(self) -> str:
+ """Provide categorization of .code part."""
+ return self.booking_line.type if self.booking_line else 'no_data'
+
+ @property
+ def booking_id(self) -> int:
+ """If .booking_line, its .booking_id, else -1."""
+ return self.booking_line.booking_id if self.booking_line else -1
@property
def is_empty(self) -> bool:
return self.raw.replace(' ', ' ')
+class BookingLine:
+ """Parsed code part of a DatLine belonging to a Booking."""
+
+ def __init__(self, booking_id: int, code: str) -> None:
+ self.booking_id = booking_id
+ self.type = 'invalid'
+ self.acc, self.amt, self.curr = '', '', ''
+ if code[0].isspace():
+ toks = code.lstrip().split()
+ self.acc = toks[0]
+ if 1 == len(toks):
+ self.type = 'value'
+ elif 3 == len(toks):
+ amt_dec = Decimal(toks[1])
+ exp = amt_dec.as_tuple().exponent
+ assert isinstance(exp, int)
+ self.amt = (f'{amt_dec:.1f}…' if exp < -2
+ else f'{amt_dec:.2f}')
+ self.curr = toks[2]
+ self.type = 'value'
+ else:
+ self.type = 'intro'
+
+
class Booking:
"""Represents lines of individual booking."""
# pylint: disable=too-few-public-methods
- def __init__(self, id_: int, idx_start: int, b_lines: list[str]) -> None:
+ def __init__(self, id_: int, idx_start: int, dat_lines: list[DatLine]
+ ) -> None:
self.id_ = id_
self.idx_start = idx_start
- self.b_lines = b_lines
- self.idx_end = self.idx_start + len(self.b_lines)
+ self.idx_end = self.idx_start + len(dat_lines)
+ for dat_line in dat_lines:
+ dat_line.booking_line = BookingLine(self.id_, dat_line.code)
class Handler(PlomHttpHandler):
DatLine(line)
for line in path_dat.read_text(encoding='utf8').splitlines()]
self.bookings: list[Booking] = []
- code_lines = [dl.code for dl in self.dat_lines]
last_booking_start = -1
- b_lines: list[str] = []
- for idx, code in enumerate(code_lines + ['']):
- if code:
- if not b_lines:
+ booking_lines: list[DatLine] = []
+ for idx, dat_line in enumerate(self.dat_lines + [DatLine('')]):
+ if dat_line.code:
+ if not booking_lines:
last_booking_start = idx
- b_lines += [code]
- elif b_lines:
+ booking_lines += [dat_line]
+ elif booking_lines:
self.bookings += [Booking(len(self.bookings),
- last_booking_start, b_lines)]
- b_lines.clear()
- self.dat_lines[last_booking_start].booking = self.bookings[-1]
+ last_booking_start, booking_lines)]
+ booking_lines.clear()
@property
def dat_lines_sans_empty(self) -> list[DatLine]:
{% if "intro" == l.type and loop.index > 1 %}<tr><td colspan=5> </td></tr>{% endif %}
<tr class="{{l.type}}">
{% if l.type == "intro" %}
- <td id="{{l.booking.id_}}"><a href="#{{l.booking.id_}}">#</a></td>
+ <td id="{{l.booking_id}}"><a href="#{{l.booking_id}}">#</a></td>
{% else %}
<td></td>
{% endif %}
{% if l.type == "value" %}
- <td class="amt">{{l.amt}}</td><td class="curr">{{l.curr|truncate(4,true,"…")}}</td><td>{{l.acc}}</td>
+ <td class="amt">{{l.booking_line.amt}}</td><td class="curr">{{l.booking_line.curr|truncate(4,true,"…")}}</td><td>{{l.booking_line.acc}}</td>
{% elif l.type == "intro" %}
- <td class="code" colspan=3><a href="/booking/{{l.booking.id_}}">{{l.code}}</a></td>
+ <td class="code" colspan=3><a href="/booking/{{l.booking_id}}">{{l.code}}</a></td>
{% else %}
<td colspan=3>{{l.code}}</td>
{% endif %}