From 4906db3d55ec301cba068092feceb39583c0241e Mon Sep 17 00:00:00 2001 From: Marcel Peterkau Date: Sat, 15 Aug 2026 00:02:37 +0200 Subject: [PATCH] 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"