home · contact · privacy
Some refactoring of warning markings.
authorChristian Heller <c.heller@plomlompom.de>
Wed, 22 Jan 2025 11:32:18 +0000 (12:32 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Wed, 22 Jan 2025 11:32:18 +0000 (12:32 +0100)
ledger.py

index 2a13d4badc563d4095af28da02e7a1dfd2f68b08..5fc80a40839f7bb4e499d637241b1b217337c2e8 100755 (executable)
--- a/ledger.py
+++ b/ledger.py
@@ -57,7 +57,6 @@ class DatLine:
         self.comment = halves[1] if len(halves) > 1 else ''
         self.code = halves[0]
         self.booking_line: Optional[BookingLine] = None
-        self.questionable = False
 
     @property
     def is_intro(self) -> bool:
@@ -67,13 +66,19 @@ class DatLine:
     @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
+        return self.booking_line.booking.id_ if self.booking_line else -1
 
     @property
     def error(self) -> str:
         """Return error if registered on attempt to parse into BookingLine."""
         return self.booking_line.error if self.booking_line else ''
 
+    @property
+    def questionable(self) -> bool:
+        """Return whether line be questionable per associated Booking."""
+        return (self.booking_line.booking.questionable if self.booking_line
+                else False)
+
     @property
     def is_empty(self) -> bool:
         """Return if both .code and .comment are empty."""
@@ -90,16 +95,16 @@ class DatLine:
 class BookingLine:
     """Parsed code part of a DatLine belonging to a Booking."""
 
-    def __init__(self, booking_id: int) -> None:
+    def __init__(self, booking: 'Booking') -> None:
         self.error = ''
-        self.booking_id = booking_id
+        self.booking = booking
 
 
 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)
+    def __init__(self, booking: 'Booking', code: str) -> None:
+        super().__init__(booking)
         if code[0].isspace():
             self.error = 'intro line indented'
         toks = code.lstrip().split(maxsplit=1)
@@ -115,8 +120,8 @@ class IntroLine(BookingLine):
 class TransferLine(BookingLine):
     """Non-first Booking line, expected to carry value movement."""
 
-    def __init__(self, booking_id: int, code: str) -> None:
-        super().__init__(booking_id)
+    def __init__(self, booking: 'Booking', code: str) -> None:
+        super().__init__(booking)
         if not code[0].isspace():
             self.error = 'transfer line not indented'
             return
@@ -151,10 +156,10 @@ class Booking:
     def __init__(self, id_: int, dat_lines: list[DatLine]) -> None:
         self.id_ = id_
         self.dat_lines = dat_lines
-        self.dat_lines[0].booking_line = IntroLine(self.id_,
+        self.dat_lines[0].booking_line = IntroLine(self,
                                                    self.dat_lines[0].code)
         for dat_line in self.dat_lines[1:]:
-            dat_line.booking_line = TransferLine(self.id_, dat_line.code)
+            dat_line.booking_line = TransferLine(self, dat_line.code)
         self.account_changes: dict[str, Wealth] = {}
         self.sink_account = None
         changes = Wealth()
@@ -164,21 +169,22 @@ class Booking:
                 self.account_changes[transfer_line.account] = Wealth()
             if transfer_line.amount is None:
                 if self.sink_account:
-                    transfer_line.error = 'second sink'
-                    return
+                    transfer_line.error = 'too many sinks'
+                    break
                 self.sink_account = transfer_line.account
                 continue
             change = Wealth({transfer_line.currency: transfer_line.amount})
             self.account_changes[transfer_line.account] += change
             changes += change
+        self.questionable = False
         if self.sink_account:
             self.account_changes[self.sink_account] += changes.as_sink
         elif not changes.sink_empty:
             assert self.dat_lines[-1].booking_line is not None
             self.dat_lines[-1].booking_line.error = 'needed sink missing'
         for dat_line in [dl for dl in self.dat_lines if dl.error]:
-            for dl in self.dat_lines:
-                dl.questionable = True
+            self.questionable = True
+            break
 
 
 class Handler(PlomHttpHandler):