2.0+ public access setup
This commit is contained in:
45 files changed
+7875
-32
No files matched your search
@@ -0,0 +1,212 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
from db import db
|
||||
|
||||
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
||||
raise RuntimeError("Database dependencies are not installed.")
|
||||
|
||||
from db_models import ( # noqa: E402
|
||||
CANONICAL_EVENT_TYPES,
|
||||
LedgerEvent,
|
||||
Player,
|
||||
PokerSession,
|
||||
User,
|
||||
canonical_event_type,
|
||||
)
|
||||
from storage import EventRow # noqa: E402
|
||||
|
||||
|
||||
def session_event_ref(session: PokerSession) -> str:
|
||||
return f"{session.session_date.isoformat()}-{session.sequence_on_date:02d}"
|
||||
|
||||
|
||||
def append_ledger_event(
|
||||
league_id: str,
|
||||
session_id: str,
|
||||
event_type: str,
|
||||
amount_cents: int,
|
||||
created_by_user_id: str,
|
||||
player_id: str | None = None,
|
||||
note: str | None = None,
|
||||
legacy_event_id: str | None = None,
|
||||
legacy_player_name: str | None = None,
|
||||
) -> LedgerEvent:
|
||||
canonical_type = canonical_event_type(event_type)
|
||||
if canonical_type not in CANONICAL_EVENT_TYPES:
|
||||
raise ValueError(f"Unsupported event type: {event_type}")
|
||||
|
||||
if canonical_type in {"note", "session_open", "session_close"}:
|
||||
amount_cents = 0
|
||||
|
||||
if player_id is None and canonical_type not in {"note", "session_open", "session_close"}:
|
||||
raise ValueError(f"Event type {canonical_type} requires a player.")
|
||||
|
||||
event = LedgerEvent(
|
||||
league_id=league_id,
|
||||
session_id=session_id,
|
||||
player_id=player_id,
|
||||
event_type=canonical_type,
|
||||
amount_cents=amount_cents,
|
||||
note=note.strip() if note else None,
|
||||
created_by_user_id=created_by_user_id,
|
||||
legacy_event_id=legacy_event_id,
|
||||
legacy_player_name=legacy_player_name,
|
||||
)
|
||||
db.session.add(event)
|
||||
return event
|
||||
|
||||
|
||||
def list_ledger_events_for_league(league_id: str) -> list[LedgerEvent]:
|
||||
return (
|
||||
LedgerEvent.query.filter_by(league_id=league_id, voided_at=None)
|
||||
.order_by(LedgerEvent.created_at.asc(), LedgerEvent.id.asc())
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def list_ledger_events_for_session(league_id: str, session_id: str) -> list[LedgerEvent]:
|
||||
return (
|
||||
LedgerEvent.query.filter_by(
|
||||
league_id=league_id,
|
||||
session_id=session_id,
|
||||
voided_at=None,
|
||||
)
|
||||
.order_by(LedgerEvent.created_at.asc(), LedgerEvent.id.asc())
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def _event_row(event: LedgerEvent, session: PokerSession, player: Player | None, user: User | None) -> EventRow:
|
||||
return EventRow(
|
||||
id=event.id,
|
||||
created_at=event.created_at.isoformat() if event.created_at else "",
|
||||
session_id=session_event_ref(session),
|
||||
session_date=session.session_date.isoformat(),
|
||||
player_name=(player.display_name if player is not None else event.legacy_player_name or ""),
|
||||
event_type=event.event_type,
|
||||
amount_cents=event.amount_cents,
|
||||
note=event.note or "",
|
||||
actor=user.email if user is not None else "",
|
||||
voided_at=event.voided_at.isoformat() if event.voided_at else "",
|
||||
void_reason=event.void_reason or "",
|
||||
)
|
||||
|
||||
|
||||
def list_all_event_rows_for_league(league_id: str) -> list[EventRow]:
|
||||
"""All events including voided — for display feeds only, not accounting."""
|
||||
rows = (
|
||||
db.session.query(LedgerEvent, PokerSession, Player, User)
|
||||
.join(
|
||||
PokerSession,
|
||||
(PokerSession.league_id == LedgerEvent.league_id)
|
||||
& (PokerSession.id == LedgerEvent.session_id),
|
||||
)
|
||||
.outerjoin(
|
||||
Player,
|
||||
(Player.league_id == LedgerEvent.league_id)
|
||||
& (Player.id == LedgerEvent.player_id),
|
||||
)
|
||||
.outerjoin(User, User.id == LedgerEvent.created_by_user_id)
|
||||
.filter(LedgerEvent.league_id == league_id)
|
||||
.order_by(
|
||||
PokerSession.session_date.asc(),
|
||||
PokerSession.sequence_on_date.asc(),
|
||||
LedgerEvent.created_at.asc(),
|
||||
LedgerEvent.id.asc(),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
return [_event_row(event, session, player, user) for event, session, player, user in rows]
|
||||
|
||||
|
||||
def void_ledger_event(event_id: str, league_id: str, user_id: str, reason: str) -> LedgerEvent:
|
||||
from datetime import datetime, timezone
|
||||
event = LedgerEvent.query.filter_by(id=event_id, league_id=league_id).first()
|
||||
if event is None:
|
||||
raise ValueError("Event not found.")
|
||||
if event.voided_at is not None:
|
||||
raise ValueError("Event is already voided.")
|
||||
event.voided_at = datetime.now(timezone.utc)
|
||||
event.voided_by_user_id = user_id
|
||||
event.void_reason = reason.strip() or "Voided by owner."
|
||||
return event
|
||||
|
||||
|
||||
def list_event_rows_for_league(league_id: str) -> list[EventRow]:
|
||||
rows = (
|
||||
db.session.query(LedgerEvent, PokerSession, Player, User)
|
||||
.join(
|
||||
PokerSession,
|
||||
(PokerSession.league_id == LedgerEvent.league_id)
|
||||
& (PokerSession.id == LedgerEvent.session_id),
|
||||
)
|
||||
.outerjoin(
|
||||
Player,
|
||||
(Player.league_id == LedgerEvent.league_id)
|
||||
& (Player.id == LedgerEvent.player_id),
|
||||
)
|
||||
.outerjoin(User, User.id == LedgerEvent.created_by_user_id)
|
||||
.filter(
|
||||
LedgerEvent.league_id == league_id,
|
||||
LedgerEvent.voided_at.is_(None),
|
||||
)
|
||||
.order_by(
|
||||
PokerSession.session_date.asc(),
|
||||
PokerSession.sequence_on_date.asc(),
|
||||
LedgerEvent.created_at.asc(),
|
||||
LedgerEvent.id.asc(),
|
||||
)
|
||||
.all()
|
||||
)
|
||||
return [_event_row(event, session, player, user) for event, session, player, user in rows]
|
||||
|
||||
|
||||
def list_all_event_rows_for_session(league_id: str, session_id: str) -> list[EventRow]:
|
||||
"""All events for a session including voided — for display only, not accounting."""
|
||||
rows = (
|
||||
db.session.query(LedgerEvent, PokerSession, Player, User)
|
||||
.join(
|
||||
PokerSession,
|
||||
(PokerSession.league_id == LedgerEvent.league_id)
|
||||
& (PokerSession.id == LedgerEvent.session_id),
|
||||
)
|
||||
.outerjoin(
|
||||
Player,
|
||||
(Player.league_id == LedgerEvent.league_id)
|
||||
& (Player.id == LedgerEvent.player_id),
|
||||
)
|
||||
.outerjoin(User, User.id == LedgerEvent.created_by_user_id)
|
||||
.filter(
|
||||
LedgerEvent.league_id == league_id,
|
||||
LedgerEvent.session_id == session_id,
|
||||
)
|
||||
.order_by(LedgerEvent.created_at.asc(), LedgerEvent.id.asc())
|
||||
.all()
|
||||
)
|
||||
return [_event_row(event, session, player, user) for event, session, player, user in rows]
|
||||
|
||||
|
||||
def list_event_rows_for_session(league_id: str, session_id: str) -> list[EventRow]:
|
||||
rows = (
|
||||
db.session.query(LedgerEvent, PokerSession, Player, User)
|
||||
.join(
|
||||
PokerSession,
|
||||
(PokerSession.league_id == LedgerEvent.league_id)
|
||||
& (PokerSession.id == LedgerEvent.session_id),
|
||||
)
|
||||
.outerjoin(
|
||||
Player,
|
||||
(Player.league_id == LedgerEvent.league_id)
|
||||
& (Player.id == LedgerEvent.player_id),
|
||||
)
|
||||
.outerjoin(User, User.id == LedgerEvent.created_by_user_id)
|
||||
.filter(
|
||||
LedgerEvent.league_id == league_id,
|
||||
LedgerEvent.session_id == session_id,
|
||||
LedgerEvent.voided_at.is_(None),
|
||||
)
|
||||
.order_by(LedgerEvent.created_at.asc(), LedgerEvent.id.asc())
|
||||
.all()
|
||||
)
|
||||
return [_event_row(event, session, player, user) for event, session, player, user in rows]
|
||||
Reference in new issue
Block a user