mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-08-25 06:55:17 +02:00
Add asset records, claims, and credit workflows
This commit is contained in:
+141
-3
@@ -5,16 +5,17 @@ from tkinter import messagebox, ttk
|
||||
|
||||
from ccma import __version__
|
||||
from ccma.config import AppConfig
|
||||
from ccma.domain.models import HousekeeperFinding, Member
|
||||
from ccma.domain.models import Asset, HousekeeperFinding, Member
|
||||
from ccma.services.housekeeper import Housekeeper
|
||||
from ccma.storage.repository import MemberRepository, RepositoryError
|
||||
from ccma.ui.asset_tab import AssetTab
|
||||
from ccma.ui.claim_tab import ClaimTab
|
||||
from ccma.ui.dialogs import NewMemberDialog
|
||||
from ccma.ui.dialogs import EditAssetDialog, IssueAssetDialog, NewAssetDialog, NewMemberDialog
|
||||
from ccma.ui.icons import IconStore
|
||||
from ccma.ui.member_tab import MemberTab
|
||||
from ccma.ui.options_dialog import OptionsDialog
|
||||
from ccma.ui.theme import load_theme
|
||||
from ccma.ui.work_tabs import DashboardTab, HousekeeperTab, MembersTab, SearchResultsTab
|
||||
from ccma.ui.work_tabs import AssetsTab, DashboardTab, HousekeeperTab, MembersTab, SearchResultsTab
|
||||
|
||||
|
||||
class TabManager:
|
||||
@@ -175,6 +176,17 @@ class MainWindow(ttk.Frame):
|
||||
)
|
||||
members_button.image = members_icon
|
||||
members_button.pack(side="left", padx=(0, 6))
|
||||
assets_icon = self.icons.get("key-variant", 24) or self.icons.get("package-variant-closed", 24)
|
||||
assets_button = ttk.Button(
|
||||
actions,
|
||||
text="Inventar",
|
||||
image=assets_icon,
|
||||
compound="top",
|
||||
width=14,
|
||||
command=self.open_assets,
|
||||
)
|
||||
assets_button.image = assets_icon
|
||||
assets_button.pack(side="left", padx=(0, 6))
|
||||
new_icon = self.icons.get("account-plus", 24)
|
||||
new_button = ttk.Button(
|
||||
actions,
|
||||
@@ -278,6 +290,9 @@ class MainWindow(ttk.Frame):
|
||||
on_close=lambda: self.tabs.close(key),
|
||||
on_changed=self.refresh_overview,
|
||||
on_open_claim=self.open_claim,
|
||||
on_open_assets=self.open_assets,
|
||||
on_open_asset=self.open_asset,
|
||||
on_return_asset=self.return_asset,
|
||||
)
|
||||
self.tabs.add(
|
||||
key,
|
||||
@@ -312,6 +327,34 @@ class MainWindow(ttk.Frame):
|
||||
icon_name="receipt",
|
||||
)
|
||||
|
||||
def open_asset(self, asset_id: str) -> None:
|
||||
key = f"asset:{asset_id}"
|
||||
if self.tabs.focus(key):
|
||||
return
|
||||
try:
|
||||
asset = self.repository.get_asset(asset_id)
|
||||
except RepositoryError as exc:
|
||||
messagebox.showerror("Asset konnte nicht geöffnet werden", str(exc), parent=self)
|
||||
return
|
||||
tab = AssetTab(
|
||||
self.notebook,
|
||||
self.repository,
|
||||
asset_id,
|
||||
on_close=lambda: self.tabs.close(key),
|
||||
on_changed=self.refresh_overview,
|
||||
on_open_member=self.open_member,
|
||||
on_issue_asset=self.issue_asset,
|
||||
on_return_asset=self.return_asset,
|
||||
on_open_claim=self.open_claim,
|
||||
)
|
||||
self.tabs.add(
|
||||
key,
|
||||
tab,
|
||||
asset.label or asset.asset_id,
|
||||
image=self.icons.get("key-variant", 16) or self.icons.get("package-variant-closed", 16),
|
||||
icon_name="key-variant",
|
||||
)
|
||||
|
||||
def _claim_changed(self, member_id: str) -> None:
|
||||
member_tab = self.tabs.tabs.get(f"member:{member_id}")
|
||||
if isinstance(member_tab, MemberTab) and member_tab.winfo_exists():
|
||||
@@ -336,14 +379,91 @@ class MainWindow(ttk.Frame):
|
||||
icon_name="account-group",
|
||||
)
|
||||
|
||||
def open_assets(self) -> None:
|
||||
key = "assets"
|
||||
if self.tabs.focus(key):
|
||||
return
|
||||
tab = AssetsTab(
|
||||
self.notebook,
|
||||
self.repository.list_assets(),
|
||||
self._member_reference_label,
|
||||
self.new_asset,
|
||||
self.open_asset,
|
||||
self.edit_asset,
|
||||
self.issue_asset,
|
||||
self.return_asset,
|
||||
lambda: self.tabs.close(key),
|
||||
)
|
||||
self.tabs.add(
|
||||
key,
|
||||
tab,
|
||||
"Inventar",
|
||||
image=self.icons.get("key-variant", 16) or self.icons.get("package-variant-closed", 16),
|
||||
icon_name="key-variant",
|
||||
)
|
||||
|
||||
def new_member(self) -> None:
|
||||
NewMemberDialog(self, self.repository, self._member_created)
|
||||
|
||||
def new_asset(self) -> None:
|
||||
NewAssetDialog(self, self.repository, self._asset_created)
|
||||
|
||||
def _member_created(self, member: Member) -> None:
|
||||
self.refresh_overview()
|
||||
self.open_member(member.member_id)
|
||||
self.status_var.set(f"Mitgliederakte für {member.display_name} angelegt.")
|
||||
|
||||
def _asset_created(self, asset: Asset) -> None:
|
||||
self.refresh_overview()
|
||||
self.open_assets()
|
||||
self.status_var.set(f"Asset angelegt: {asset.label}")
|
||||
|
||||
def issue_asset(self, asset_id: str, preselected_member_id: str = "") -> None:
|
||||
try:
|
||||
IssueAssetDialog(
|
||||
self,
|
||||
self.repository,
|
||||
asset_id,
|
||||
self._asset_changed,
|
||||
preselected_member_id=preselected_member_id,
|
||||
)
|
||||
except (RepositoryError, tk.TclError) as exc:
|
||||
messagebox.showerror("Asset konnte nicht ausgegeben werden", str(exc), parent=self)
|
||||
|
||||
def edit_asset(self, asset_id: str) -> None:
|
||||
try:
|
||||
EditAssetDialog(
|
||||
self,
|
||||
self.repository,
|
||||
asset_id,
|
||||
self._asset_changed,
|
||||
)
|
||||
except (RepositoryError, tk.TclError) as exc:
|
||||
messagebox.showerror("Asset konnte nicht bearbeitet werden", str(exc), parent=self)
|
||||
|
||||
def return_asset(self, asset_id: str) -> None:
|
||||
try:
|
||||
asset = self.repository.get_asset(asset_id)
|
||||
except RepositoryError as exc:
|
||||
messagebox.showerror("Asset konnte nicht geladen werden", str(exc), parent=self)
|
||||
return
|
||||
if not messagebox.askyesno(
|
||||
"Asset zurücknehmen",
|
||||
f"{asset.label}\n\nDieses Asset wirklich als zurückgegeben markieren?",
|
||||
parent=self,
|
||||
):
|
||||
return
|
||||
try:
|
||||
asset = self.repository.return_asset(asset_id)
|
||||
except RepositoryError as exc:
|
||||
messagebox.showerror("Rückgabe fehlgeschlagen", str(exc), parent=self)
|
||||
return
|
||||
self._asset_changed(asset)
|
||||
|
||||
def _asset_changed(self, asset: Asset) -> None:
|
||||
self.refresh_overview()
|
||||
self.status_var.set(f"Asset aktualisiert: {asset.label}")
|
||||
|
||||
def open_housekeeper(self) -> None:
|
||||
key = "housekeeper"
|
||||
if self.tabs.focus(key):
|
||||
@@ -383,6 +503,14 @@ class MainWindow(ttk.Frame):
|
||||
members_tab = self.tabs.tabs.get("members")
|
||||
if isinstance(members_tab, MembersTab) and members_tab.winfo_exists():
|
||||
members_tab.refresh(self.repository.list_members())
|
||||
assets_tab = self.tabs.tabs.get("assets")
|
||||
if isinstance(assets_tab, AssetsTab) and assets_tab.winfo_exists():
|
||||
assets_tab.refresh(self.repository.list_assets())
|
||||
for key, widget in self.tabs.tabs.items():
|
||||
if key.startswith("member:") and isinstance(widget, MemberTab) and widget.winfo_exists():
|
||||
widget.refresh()
|
||||
if key.startswith("asset:") and isinstance(widget, AssetTab) and widget.winfo_exists():
|
||||
widget.refresh()
|
||||
if self.housekeeper_button and self.housekeeper_button.winfo_exists():
|
||||
self.housekeeper_button.configure(text=f"Hausmeister ({len(self.findings)})")
|
||||
|
||||
@@ -422,3 +550,13 @@ class MainWindow(ttk.Frame):
|
||||
"Der Store enthält ungültige Akten:\n\n" + "\n".join(self.validation_errors[:12]),
|
||||
parent=self,
|
||||
)
|
||||
|
||||
def _member_reference_label(self, member_id: str) -> str:
|
||||
if not member_id:
|
||||
return "—"
|
||||
try:
|
||||
member = self.repository.get_member(member_id)
|
||||
except RepositoryError:
|
||||
return member_id
|
||||
prefix = member.member_number or member.member_id
|
||||
return f"{prefix} · {member.display_name or member.member_id}"
|
||||
|
||||
Reference in New Issue
Block a user