From 106bf1e521ff02e128863bf8378992299d41bedb Mon Sep 17 00:00:00 2001
From: Christian Heller <c.heller@plomlompom.de>
Date: Wed, 29 Jan 2025 03:56:33 +0100
Subject: [PATCH] Add copying of Bookings.

---
 ledger.py              | 18 ++++++++++++++----
 templates/_macros.tmpl |  2 ++
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/ledger.py b/ledger.py
index ebb188f..f61cbec 100755
--- a/ledger.py
+++ b/ledger.py
@@ -260,6 +260,11 @@ class Handler(PlomHttpHandler):
                 self.server.move_booking(id_, up=toks[2] == 'up')
                 self.redirect(Path(self.pagename).joinpath(f'#{id_}'))
                 return
+            for key in self.postvars.keys_prefixed('copy_'):
+                id_ = int(key.split('_')[1])
+                self.server.copy_booking(id_)
+                self.redirect(Path('/bookings').joinpath(f'{id_}'))
+                return
         elif self.pagename == 'edit_structured':
             if self.postvars.first('apply'):
                 line_keys = self.postvars.keys_prefixed('line_')
@@ -350,7 +355,7 @@ class Server(PlomHttpServer):
             DatLine(line)
             for line in self._path_dat.read_text(encoding='utf8').splitlines()]
         self.last_save_hash = self._hash_dat_lines()
-        self.load_bookings()
+        self._load_bookings()
 
     def _hash_dat_lines(self) -> int:
         return hash(tuple(dl.raw for dl in self.dat_lines))
@@ -360,8 +365,7 @@ class Server(PlomHttpServer):
         """If .dat_lines different to those of last .load()."""
         return self._hash_dat_lines() != self.last_save_hash
 
-    def load_bookings(self) -> None:
-        """Read .dat_lines into Bookings / full ledger."""
+    def _load_bookings(self) -> None:
         self.bookings = []
         booking_lines: list[DatLine] = []
         last_date = ''
@@ -396,7 +400,7 @@ class Server(PlomHttpServer):
         self.dat_lines = (self.dat_lines[:start_idx]
                           + new_lines
                           + self.dat_lines[end_idx+1:])
-        self.load_bookings()
+        self._load_bookings()
 
     def move_booking(self, id_: int, up: bool) -> None:
         """Move Booking of id_ one step up or downwards"""
@@ -418,6 +422,12 @@ class Server(PlomHttpServer):
         self._replace_from_to(*self._margin_indices(self.bookings[id_]),
                               new_dat_lines)
 
+    def copy_booking(self, id_: int) -> None:
+        """Append copy of Booking of id_ to end of ledger."""
+        self.dat_lines += [DatLine('')] + [DatLine(dat_line.raw) for dat_line
+                                           in self.bookings[id_].dat_lines]
+        self._load_bookings()
+
     @property
     def dat_lines_sans_empty(self) -> list[DatLine]:
         """Return only those .data_lines with .code or .comment."""
diff --git a/templates/_macros.tmpl b/templates/_macros.tmpl
index 6c2e57c..dc7b13d 100644
--- a/templates/_macros.tmpl
+++ b/templates/_macros.tmpl
@@ -23,6 +23,8 @@ table.ledger tr > td:first-child { background-color: white; }
     <td id="{{dat_line.booking_id}}"><a href="#{{dat_line.booking_id}}">[#]</a><input type="submit" name="move_{{dat_line.booking_id}}_up" value="^"{% if dat_line.booking_id == 0 %} disabled{% endif %}/></td>
   {% elif dat_line.booking_line.idx == 1 %}
     <td><a href="/balance?up_incl={{dat_line.booking_id}}">[b]</a><input type="submit" name="move_{{dat_line.booking_id}}_down" value="v"{% if dat_line.booking_id == max_id %} disabled{% endif %}/></td>
+  {% elif dat_line.booking_line.idx == 2 %}
+    <td><input type="submit" name="copy_{{dat_line.booking_id}}" value="c" /></td>
   {% else %}
     <td></td>
   {% endif %}
-- 
2.30.2