Update member UI and related app changes

This commit is contained in:
Marcel Peterkau
2026-06-26 21:57:11 +02:00
parent 833075f0dc
commit 30b6d253b2
18 changed files with 490 additions and 84 deletions
+58 -13
View File
@@ -16,6 +16,27 @@ from ccma.ui.file_open import open_path
from ccma.ui.labels import display_label, storage_key
CLAIM_TABLE_COLUMNS = (
("title", "Forderung", 220),
("due", "Fällig", 100),
("amount", "Betrag", 90),
("status", "Status", 110),
)
def _claim_sort_value(data, claim: dict, column: str) -> str:
if column == "title":
return str(claim.get("title", ""))
if column == "due":
return str(claim.get("due_date", ""))
if column == "amount":
return f"{claim_total(claim):012.2f}"
if column == "status":
status = claim_status(data, claim)
return CLAIM_STATUS_LABELS.get(status, status.upper())
return ""
class MemberTab(ttk.Frame):
def __init__(
self,
@@ -34,6 +55,7 @@ class MemberTab(ttk.Frame):
self.on_open_claim = on_open_claim
self.member = repository.get_member(member_id)
self.variables: dict[str, tk.Variable] = {}
self.notes_text: tk.Text | None = None
self._build_ui()
self.refresh()
@@ -97,6 +119,7 @@ class MemberTab(ttk.Frame):
("Mitgliedsnummer", "member_number"),
("Vorname", "first_name"),
("Nachname", "last_name"),
("Nickname", "nickname"),
("E-Mail-Adresse", "email"),
("Telefonnummer", "phone"),
(f"Geburtsdatum ({date_input_hint()})", "birth_date"),
@@ -120,7 +143,8 @@ class MemberTab(ttk.Frame):
"write", lambda *_args, source=variable: self.age_var.set(age_label(source.get()))
)
else:
ttk.Entry(data_tab, textvariable=variable, width=42).grid(
entry_state = "readonly" if key == "member_number" else "normal"
ttk.Entry(data_tab, textvariable=variable, width=42, state=entry_state).grid(
row=row, column=1, sticky="ew", pady=5
)
self.variables["status"] = tk.StringVar()
@@ -132,13 +156,11 @@ class MemberTab(ttk.Frame):
state="readonly",
width=39,
).grid(row=len(fields), column=1, sticky="ew", pady=5)
self.variables["notes"] = tk.StringVar()
ttk.Label(data_tab, text="Interne Notiz").grid(
row=len(fields) + 1, column=0, sticky="nw", pady=5, padx=(0, 12)
)
ttk.Entry(data_tab, textvariable=self.variables["notes"]).grid(
row=len(fields) + 1, column=1, sticky="ew", pady=5
)
self.notes_text = tk.Text(data_tab, width=42, height=6, wrap="word")
self.notes_text.grid(row=len(fields) + 1, column=1, sticky="ew", pady=5)
data_tab.columnconfigure(1, weight=1)
ttk.Button(data_tab, text="Änderungen speichern", style="Accent.TButton", command=self._save).grid(
row=len(fields) + 2, column=1, sticky="e", pady=(18, 0)
@@ -197,13 +219,10 @@ class MemberTab(ttk.Frame):
self.claims = ttk.Treeview(
contribution_tab, columns=("title", "due", "amount", "status"), show="headings"
)
for key, title, width in (
("title", "Forderung", 220),
("due", "Fällig", 100),
("amount", "Betrag", 90),
("status", "Status", 110),
):
self.claims.heading(key, text=title)
self.claim_sort_column = "due"
self.claim_sort_descending = False
for key, title, width in CLAIM_TABLE_COLUMNS:
self.claims.heading(key, text=title, command=lambda column=key: self._toggle_claim_sort(column))
self.claims.column(key, width=width, anchor="w")
self.claims.grid(row=1, column=0, sticky="nsew")
self.claims.bind("<Double-1>", lambda _event: self._open_selected_claim())
@@ -287,6 +306,9 @@ class MemberTab(ttk.Frame):
variable.set(display_label(STATUS_LABELS, str(value)))
else:
variable.set(format_date_for_display(value) if key in date_fields else value)
if self.notes_text is not None:
self.notes_text.delete("1.0", "end")
self.notes_text.insert("1.0", self.member.notes)
self._refresh_events()
self._refresh_contributions()
self._refresh_documents()
@@ -308,7 +330,13 @@ class MemberTab(ttk.Frame):
except RepositoryError as exc:
self.contribution_summary.set(f"FEHLER: {exc}")
return
for index, claim in enumerate(data.claims):
claims = sorted(
data.claims,
key=lambda claim: _claim_sort_value(data, claim, self.claim_sort_column).casefold(),
reverse=self.claim_sort_descending,
)
self._update_claim_headings()
for index, claim in enumerate(claims):
claim_id = str(claim.get("claim_id") or f"missing-id-{index}")
status = claim_status(data, claim)
self.claims.insert(
@@ -324,6 +352,21 @@ class MemberTab(ttk.Frame):
)
self.contribution_summary.set(f"{len(data.claims)} Forderungen · {len(data.payments)} Zahlungen")
def _toggle_claim_sort(self, column: str) -> None:
if self.claim_sort_column == column:
self.claim_sort_descending = not self.claim_sort_descending
else:
self.claim_sort_column = column
self.claim_sort_descending = False
self._refresh_contributions()
def _update_claim_headings(self) -> None:
for key, title, _width in CLAIM_TABLE_COLUMNS:
suffix = ""
if key == self.claim_sort_column:
suffix = " v" if self.claim_sort_descending else " ^"
self.claims.heading(key, text=f"{title}{suffix}", command=lambda column=key: self._toggle_claim_sort(column))
def _open_selected_claim(self) -> None:
selected = self.claims.selection()
if selected and not selected[0].startswith("missing-id-"):
@@ -363,6 +406,8 @@ class MemberTab(ttk.Frame):
if key == "status":
value = storage_key(STATUS_LABELS, value)
setattr(self.member, key, value)
if self.notes_text is not None:
self.member.notes = self.notes_text.get("1.0", "end-1c").strip()
try:
self.repository.save_member(self.member)
except RepositoryError as exc: