mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-07-01 11:14:52 +02:00
Update member UI and related app changes
This commit is contained in:
+58
-13
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user