home · contact · privacy
Invalidate Booking for out-of-order date.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 22 Jan 2025 12:38:18 +0000 (13:38 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 22 Jan 2025 12:38:18 +0000 (13:38 +0100)
ledger.py
templates/_macros.tmpl
templates/raw.tmpl

index f2566bd072c3b40386897af635c9f352c32a16f4..0687377b895fdf29c8862ad14794e72d81e2fea8 100755 (executable)
--- a/ledger.py
+++ b/ledger.py
@@ -74,9 +74,9 @@ class DatLine:
         return '; '.join(self.booking_line.errors) if self.booking_line else ''
 
     @property
-    def questionable(self) -> bool:
+    def is_questionable(self) -> bool:
         """Return whether line be questionable per associated Booking."""
-        return (self.booking_line.booking.questionable if self.booking_line
+        return (self.booking_line.booking.is_questionable if self.booking_line
                 else False)
 
     @property
@@ -112,10 +112,13 @@ class IntroLine(BookingLine):
             self.errors += ['illegal number of tokens']
         if len(toks) < 1:
             return
+        self.date = '#'
         try:
             dt_date.fromisoformat(toks[0])
         except ValueError:
             self.errors += [f'not properly formatted legal date: {toks[0]}']
+        else:
+            self.date = toks[0]
 
 
 class TransferLine(BookingLine):
@@ -154,16 +157,17 @@ class Booking:
     # pylint: disable=too-few-public-methods
 
     def __init__(self, id_: int, dat_lines: list[DatLine]) -> None:
-        dat_lines[0].booking_line = IntroLine(self, dat_lines[0].code)
-        intro_line = dat_lines[0].booking_line
-        transfer_lines = []
+        self.intro_line = IntroLine(self, dat_lines[0].code)
+        dat_lines[0].booking_line = self.intro_line
+        self._transfer_lines = []
         for dat_line in dat_lines[1:]:
             dat_line.booking_line = TransferLine(self, dat_line.code)
-            transfer_lines += [dat_line.booking_line]
+            self._transfer_lines += [dat_line.booking_line]
         changes = Wealth()
         self.account_changes: dict[str, Wealth] = {}
         self.sink_account = None
-        for transfer_line in [tl for tl in transfer_lines if not tl.errors]:
+        for transfer_line in [tl for tl in self._transfer_lines
+                              if not tl.errors]:
             if transfer_line.account not in self.account_changes:
                 self.account_changes[transfer_line.account] = Wealth()
             if transfer_line.amount is None:
@@ -177,14 +181,18 @@ class Booking:
         if self.sink_account:
             self.account_changes[self.sink_account] += changes.as_sink
         elif not changes.sink_empty:
-            transfer_lines[-1].errors += ['needed sink missing']
-        self.questionable = False
-        for _ in [bl for bl in [intro_line] + transfer_lines if bl.errors]:
-            self.questionable = True
-            break
+            self._transfer_lines[-1].errors += ['needed sink missing']
         self.id_ = id_
         self.dat_lines = dat_lines
 
+    @property
+    def is_questionable(self) -> bool:
+        """Whether lines count any errors."""
+        for _ in [bl for bl in [self.intro_line] + self._transfer_lines
+                  if bl.errors]:
+            return True
+        return False
+
 
 class Handler(PlomHttpHandler):
     # pylint: disable=missing-class-docstring
@@ -219,11 +227,17 @@ class Server(PlomHttpServer):
                 for line in path_dat.read_text(encoding='utf8').splitlines()]
         self.bookings: list[Booking] = []
         booking_lines: list[DatLine] = []
+        last_date = ''
         for dat_line in self.dat_lines + [DatLine('')]:
             if dat_line.code:
                 booking_lines += [dat_line]
             elif booking_lines:
-                self.bookings += [Booking(len(self.bookings), booking_lines)]
+                booking = Booking(len(self.bookings), booking_lines)
+                if last_date > booking.intro_line.date:
+                    booking.intro_line.errors += ['date < previous valid date']
+                else:
+                    last_date = booking.intro_line.date
+                self.bookings += [booking]
                 booking_lines = []
 
     @property
index d1f6cf274622aa2f63f6adbdcc671617185a29f2..2a349b5c8c386cd4725ebe10d4b124412a2a1b19 100644 (file)
@@ -12,7 +12,7 @@ td.curr { text-align: center; }
   {% if (not (raw or single)) and dat_line.is_intro and loop.index > 1 %}
     <tr><td colspan=5>&nbsp;</td></tr>
   {% endif %}
-  <tr{% if dat_line.questionable %} class="warning"{% endif %}>
+  <tr{% if dat_line.is_questionable %} class="warning"{% endif %}>
   {% if not single %}
     {% if dat_line.is_intro %}
       <td id="{{dat_line.booking_id}}"><a href="#{{dat_line.booking_id}}">#</a></td>
index fd3c0b43e2b145a01e7152271e6ceae18eedc382..6851d939a93bb1919d7d9575db910be58cc8f946 100644 (file)
@@ -2,8 +2,6 @@
 
 {% block css %}
 table { font-family: monospace; }
-tr.warning td { background-color: #ff8888; }
-td.invalid, tr.warning td.invalid { background-color: #ff0000; }
 {% endblock %}
 
 {% block content %}