From 4906db3d55ec301cba068092feceb39583c0241e Mon Sep 17 00:00:00 2001 From: Marcel Peterkau Date: Sat, 15 Aug 2026 00:02:37 +0200 Subject: [PATCH 1/2] Prefill the allocation amount when clicking an unallocated claim/donation Clicking a claim or donation row in the payment allocation table used to just show "0.00" if nothing was allocated to it yet, requiring the board to type the amount by hand every time. It now suggests whichever is smaller: what that claim/donation still has open, or what's left unused of the payment -- so the common case is click the row, then Zuordnung setzen, done. Rows that already have an allocation still show their current value instead, so editing one isn't overwritten by the suggestion. Co-Authored-By: Claude Sonnet 5 --- src/ccma/ui/payment_dialog.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/ccma/ui/payment_dialog.py b/src/ccma/ui/payment_dialog.py index ff41443..2a60c65 100644 --- a/src/ccma/ui/payment_dialog.py +++ b/src/ccma/ui/payment_dialog.py @@ -42,12 +42,14 @@ class _AllocationTable: claim_allocations: dict[str, str], donation_allocations: dict[str, str], on_change: Callable[[], None], + get_payment_amount: Callable[[], Decimal], ): self.repository = repository self.member_id = member_id self.claim_allocations = claim_allocations self.donation_allocations = donation_allocations self.on_change = on_change + self.get_payment_amount = get_payment_amount # Fixed snapshot of what this payment already covered when the dialog opened. # Capacities are computed against this baseline rather than the live, editable # dicts above -- otherwise "Maximal zuordenbar" would inflate every time the @@ -182,7 +184,23 @@ class _AllocationTable: return kind, target_id = self._target(selected[0]) allocations = self.claim_allocations if kind == "claim" else self.donation_allocations - self.amount_var.set(allocations.get(target_id, "0.00")) + current = allocations.get(target_id) + if current: + # Already allocated: show the existing amount so it can be reviewed/edited. + self.amount_var.set(current) + return + # Not yet allocated: suggest whichever is smaller -- what this claim/donation + # still needs, or what's left of the payment -- so the common case is just + # "click the row, then Zuordnung setzen". + capacity = (self.claim_capacity if kind == "claim" else self.donation_capacity)[target_id] + free = max(self._payment_amount() - self.total_allocated(), Decimal("0")) + self.amount_var.set(money_text(min(capacity, free))) + + def _payment_amount(self) -> Decimal: + try: + return self.get_payment_amount() + except ValueError: + return Decimal("0") def _set(self) -> None: selected = self.tree.selection() @@ -314,6 +332,7 @@ class PaymentCreateDialog(tk.Toplevel): claim_allocations=self.claim_allocations, donation_allocations=self.donation_allocations, on_change=self._refresh_totals, + get_payment_amount=self._current_payment_amount, ) ttk.Label(self, textvariable=self.total_var, style="Mono.TLabel").grid( @@ -328,10 +347,13 @@ class PaymentCreateDialog(tk.Toplevel): ).pack(side="left") self._refresh_totals() + def _current_payment_amount(self) -> Decimal: + return decimal_value(self.variables["amount"].get()) + def _refresh_totals(self) -> None: allocated = self.allocation_table.total_allocated() if self.allocation_table else Decimal("0") try: - payment_amount = decimal_value(self.variables["amount"].get()) + payment_amount = self._current_payment_amount() free = payment_amount - allocated self.total_var.set(f"Zugeordnet: {money_text(allocated)} EUR · Frei: {money_text(free)} EUR") except (ValueError, InvalidOperation): @@ -448,6 +470,7 @@ class PaymentEditDialog(tk.Toplevel): claim_allocations=self.claim_allocations, donation_allocations=self.donation_allocations, on_change=self._refresh_totals, + get_payment_amount=self._current_payment_amount, ) ttk.Label(self, textvariable=self.total_var, style="Mono.TLabel").grid( @@ -474,10 +497,13 @@ class PaymentEditDialog(tk.Toplevel): except tk.TclError: return + def _current_payment_amount(self) -> Decimal: + return decimal_value(self.variables["amount"].get()) + def _refresh_totals(self) -> None: allocated = self.allocation_table.total_allocated() if self.allocation_table else Decimal("0") try: - payment_amount = decimal_value(self.variables["amount"].get()) + payment_amount = self._current_payment_amount() free = payment_amount - allocated self.total_var.set( f"Zugeordnet: {money_text(allocated)} EUR · Frei: {money_text(free)} EUR" From 44228dd7ddf5bb707999b21717e85b5cb611de11 Mon Sep 17 00:00:00 2001 From: Marcel Peterkau Date: Sat, 15 Aug 2026 00:57:32 +0200 Subject: [PATCH 2/2] Document the payment allocation amount prefill in the changelog Co-Authored-By: Claude Sonnet 5 --- src/ccma/assets/CHANGELOG.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ccma/assets/CHANGELOG.json b/src/ccma/assets/CHANGELOG.json index 35db039..817a2e0 100644 --- a/src/ccma/assets/CHANGELOG.json +++ b/src/ccma/assets/CHANGELOG.json @@ -26,7 +26,8 @@ "Der Hausmeister meldet eine überfällige Forderung nicht mehr doppelt als eigene Überfällig- und Mahnungsmeldung; bei Mitgliedern mit aktivem Lastschriftmandat erscheint statt einer Mahnung ein Hinweis, dass der Lastschrifteinzug geprüft werden sollte.", "Die Spaltenbreiten in den Tabellen für Forderungen, Zahlungen, Spenden und Hausmeister-Vorgänge sind jetzt einheitlich: Datum-, Betrag- und Statusspalten haben eine feste Breite, nur die abschließende Beschreibungs- bzw. Referenzspalte passt sich dynamisch an die Fensterbreite an.", "Die Chronik im Mitgliedsfenster nimmt standardmäßig ein Drittel der Fensterbreite ein.", - "Der GnuCash-Import öffnet sich mit 80 % der Bildschirmgröße und erlaubt die Mehrfachauswahl von Buchungen per Klick, Strg+Klick oder Umschalt+Klick; Buchungen, die einer bereits vorhandenen Zahlung entsprechen, können beim Import übersprungen oder mit der Beschreibung aus GnuCash aktualisiert werden." + "Der GnuCash-Import öffnet sich mit 80 % der Bildschirmgröße und erlaubt die Mehrfachauswahl von Buchungen per Klick, Strg+Klick oder Umschalt+Klick; Buchungen, die einer bereits vorhandenen Zahlung entsprechen, können beim Import übersprungen oder mit der Beschreibung aus GnuCash aktualisiert werden.", + "Beim Anklicken einer noch nicht zugeordneten Forderung oder Spende im Zahlungsfenster wird der Betrag automatisch mit dem sinnvollen Vorschlag vorausgefüllt." ] }, {