#!/usr/bin/env python3
 """Viewer for ledger .dat files."""
-from decimal import Decimal
+from datetime import date as dt_date
+from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
 from os import environ
 from pathlib import Path
 from sys import exit as sys_exit
     @property
     def is_intro(self) -> bool:
         """Return if intro line of a Booking."""
-        return self.booking_line.is_intro if self.booking_line else False
+        return isinstance(self.booking_line, IntroLine)
 
     @property
     def booking_id(self) -> int:
 class BookingLine:
     """Parsed code part of a DatLine belonging to a Booking."""
 
-    def __init__(self, booking_id: int, code: str, as_intro: bool = False
-                 ) -> None:
+    def __init__(self, booking_id: int) -> None:
         self.error = ''
         self.booking_id = booking_id
-        self.is_intro = as_intro
-        if self.is_intro:
-            if code[0].isspace():
-                self.error = 'intro line indented'
+
+
+class IntroLine(BookingLine):
+    """First line of a Booking, expected to carry date etc."""
+
+    def __init__(self, booking_id: int, code: str) -> None:
+        super().__init__(booking_id)
+        if code[0].isspace():
+            self.error = 'intro line indented'
+        toks = code.lstrip().split(maxsplit=1)
+        if len(toks) != 2:
+            self.error = 'illegal number of tokens'
             return
+        try:
+            dt_date.fromisoformat(toks[0])
+        except ValueError:
+            self.error = 'not starting with properly formatted legal date'
+
+
+class TransactionLine(BookingLine):
+    """Non-first Booking line, expected to carry value movement."""
+
+    def __init__(self, booking_id: int, code: str) -> None:
+        super().__init__(booking_id)
         self.acc, self.amt, self.curr = '', '', ''
         if not code[0].isspace():
             self.error = 'non-intro line not indented'
             self.error = 'illegal number of tokens'
             return
         if 3 == len(toks):
-            amt_dec = Decimal(toks[1])
+            try:
+                amt_dec = Decimal(toks[1])
+            except DecimalInvalidOperation:
+                self.error = 'improper amount value'
+                return
             exp = amt_dec.as_tuple().exponent
             assert isinstance(exp, int)
             self.amt = (f'{amt_dec:.1f}…' if exp < -2
     def __init__(self, id_: int, dat_lines: list[DatLine]) -> None:
         self.id_ = id_
         self.dat_lines = dat_lines
-        self.dat_lines[0].booking_line = BookingLine(
-                self.id_, self.dat_lines[0].code, as_intro=True)
+        self.dat_lines[0].booking_line = IntroLine(self.id_,
+                                                   self.dat_lines[0].code)
         for dat_line in self.dat_lines[1:]:
-            dat_line.booking_line = BookingLine(self.id_, dat_line.code)
+            dat_line.booking_line = TransactionLine(self.id_, dat_line.code)
 
 
 class Handler(PlomHttpHandler):