diff --git a/static/css/style.css b/static/css/style.css index 1a9470b..727b1be 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -832,6 +832,54 @@ td a:hover { min-height: 260px; } +.status-none { + color: #94a3b8; + background: rgba(148, 163, 184, 0.1); + border: 1px solid rgba(148, 163, 184, 0.2); +} + +.status-unpaid { + color: #f59e0b; + background: rgba(245, 158, 11, 0.12); + border: 1px solid rgba(245, 158, 11, 0.24); +} + +.status-partial { + color: #fb923c; + background: rgba(251, 146, 60, 0.12); + border: 1px solid rgba(251, 146, 60, 0.24); +} + +.status-paid { + color: #22c55e; + background: rgba(34, 197, 94, 0.12); + border: 1px solid rgba(34, 197, 94, 0.24); +} + +.pill-paid { + color: #22c55e; + background: rgba(34, 197, 94, 0.12); + border: 1px solid rgba(34, 197, 94, 0.22); +} + +.pill-cashout { + color: #f59e0b; + background: rgba(245, 158, 11, 0.12); + border: 1px solid rgba(245, 158, 11, 0.22); +} + +.pill-buyin { + color: #60a5fa; + background: rgba(96, 165, 250, 0.12); + border: 1px solid rgba(96, 165, 250, 0.22); +} + +.pill-note { + color: #cbd5e1; + background: rgba(203, 213, 225, 0.08); + border: 1px solid rgba(203, 213, 225, 0.14); +} + @media (max-width: 980px) { .site-shell { width: min(100% - 24px, 100%); diff --git a/stats.py b/stats.py index 9092688..f742373 100644 --- a/stats.py +++ b/stats.py @@ -30,12 +30,31 @@ class SessionEntry: player_name: str buy_in_cents: int = 0 cash_out_cents: int = 0 + paid_cents: int = 0 notes: list[str] = field(default_factory=list) @property def net_cents(self) -> int: return self.cash_out_cents - self.buy_in_cents + @property + def payout_due_cents(self) -> int: + return max(self.cash_out_cents, 0) + + @property + def payout_remaining_cents(self) -> int: + return max(self.payout_due_cents - self.paid_cents, 0) + + @property + def payout_status(self) -> str: + if self.payout_due_cents <= 0: + return "none" + if self.paid_cents <= 0: + return "unpaid" + if self.payout_remaining_cents <= 0: + return "paid" + return "partial" + @dataclass class SessionSummary: @@ -171,6 +190,8 @@ def build_session_summaries(events: list[EventRow]) -> list[SessionSummary]: entry.buy_in_cents += event["amount_cents"] elif event_type == "cashout": entry.cash_out_cents += event["amount_cents"] + elif event_type == "paid": + entry.paid_cents += event["amount_cents"] if event["note"]: entry.notes.append(event["note"]) diff --git a/storage.py b/storage.py index d2d1ee4..985445f 100644 --- a/storage.py +++ b/storage.py @@ -30,7 +30,14 @@ class EventRow(TypedDict): actor: str -VALID_EVENT_TYPES = {"buyin", "cashout", "note", "session_open", "session_close"} +VALID_EVENT_TYPES = { + "buyin", + "cashout", + "paid", + "note", + "session_open", + "session_close", +} def ensure_data_file(csv_path: Path) -> None: diff --git a/templates/admin_dashboard.html b/templates/admin_dashboard.html index 6ee5f48..029e231 100644 --- a/templates/admin_dashboard.html +++ b/templates/admin_dashboard.html @@ -34,6 +34,7 @@ @@ -45,7 +46,7 @@ @@ -135,7 +136,7 @@
{{ event.player_name }} - {{ event.event_type }} + {{ event.event_type }}

{{ event.amount_cents | money }}

{{ event.session_date | pretty_date }}

diff --git a/templates/session_detail.html b/templates/session_detail.html index be66edb..7a74b90 100644 --- a/templates/session_detail.html +++ b/templates/session_detail.html @@ -35,6 +35,9 @@ Player Buy-in Cash-out + Paid + Remaining + Status Net Notes @@ -45,7 +48,18 @@ {{ entry.player_name }} {{ entry.buy_in_cents | money }} {{ entry.cash_out_cents | money }} - {{ entry.net_cents | money }} + {{ entry.paid_cents | money }} + + {{ entry.payout_remaining_cents | money }} + + + + {{ entry.payout_status }} + + + + {{ entry.net_cents | money }} + {% if entry.notes %}