major file restrucutre
This commit is contained in:
1 parent
ac278065d2
commit
6da4c3e379
53 files changed
+188
-180
No files matched your search
@@ -1,66 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from __future__ import annotations
|
from boker import create_app
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import click
|
|
||||||
from flask import Flask
|
|
||||||
|
|
||||||
from auth import current_user_id, is_logged_in
|
|
||||||
from config import Config, ProductionConfig
|
|
||||||
from db import database_extensions_available, db, init_database
|
|
||||||
from extensions import csrf, limiter, mail
|
|
||||||
from routes.account import account_bp
|
|
||||||
from routes.leagues import leagues_bp
|
|
||||||
from routes.public import public_bp
|
|
||||||
from storage import ensure_data_file
|
|
||||||
from utils import cents_to_dollars, safe_date_label
|
|
||||||
|
|
||||||
|
|
||||||
def create_app(config_overrides: dict | None = None) -> Flask:
|
|
||||||
app = Flask(__name__)
|
|
||||||
cfg = ProductionConfig if os.getenv("FLASK_ENV") == "production" else Config
|
|
||||||
app.config.from_object(cfg)
|
|
||||||
if config_overrides:
|
|
||||||
app.config.update(config_overrides)
|
|
||||||
|
|
||||||
ensure_data_file(app.config["DATA_PATH"])
|
|
||||||
init_database(app)
|
|
||||||
csrf.init_app(app)
|
|
||||||
limiter.init_app(app)
|
|
||||||
mail.init_app(app)
|
|
||||||
|
|
||||||
app.jinja_env.filters["money"] = cents_to_dollars
|
|
||||||
app.jinja_env.filters["pretty_date"] = safe_date_label
|
|
||||||
|
|
||||||
@app.context_processor
|
|
||||||
def inject_globals() -> dict:
|
|
||||||
return {
|
|
||||||
"app_version": app.config["APP_VERSION"],
|
|
||||||
"current_user_id": current_user_id(),
|
|
||||||
"is_logged_in": is_logged_in(),
|
|
||||||
}
|
|
||||||
|
|
||||||
app.register_blueprint(public_bp)
|
|
||||||
app.register_blueprint(account_bp)
|
|
||||||
app.register_blueprint(leagues_bp)
|
|
||||||
|
|
||||||
@app.cli.command("init-db")
|
|
||||||
def init_db_command() -> None:
|
|
||||||
if not database_extensions_available() or db is None:
|
|
||||||
raise click.ClickException(
|
|
||||||
"Database dependencies are not installed. Run pip install -r requirements.txt."
|
|
||||||
)
|
|
||||||
|
|
||||||
with app.app_context():
|
|
||||||
db.create_all()
|
|
||||||
|
|
||||||
click.echo("Initialized database tables.")
|
|
||||||
|
|
||||||
return app
|
|
||||||
|
|
||||||
|
|
||||||
app = create_app()
|
app = create_app()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
import os
|
||||||
app.run(debug=os.getenv("FLASK_DEBUG", "0") == "1")
|
app.run(debug=os.getenv("FLASK_DEBUG", "0") == "1")
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import click
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
from .auth import current_user_id, is_logged_in
|
||||||
|
from .config import Config, ProductionConfig
|
||||||
|
from .db import database_extensions_available, db, init_database
|
||||||
|
from .extensions import csrf, limiter, mail
|
||||||
|
from .routes.account import account_bp
|
||||||
|
from .routes.leagues import leagues_bp
|
||||||
|
from .routes.public import public_bp
|
||||||
|
from .storage import ensure_data_file
|
||||||
|
from .utils import cents_to_dollars, safe_date_label
|
||||||
|
|
||||||
|
|
||||||
|
def create_app(config_overrides: dict | None = None) -> Flask:
|
||||||
|
app = Flask(__name__)
|
||||||
|
cfg = ProductionConfig if os.getenv("FLASK_ENV") == "production" else Config
|
||||||
|
app.config.from_object(cfg)
|
||||||
|
if config_overrides:
|
||||||
|
app.config.update(config_overrides)
|
||||||
|
|
||||||
|
ensure_data_file(app.config["DATA_PATH"])
|
||||||
|
init_database(app)
|
||||||
|
csrf.init_app(app)
|
||||||
|
limiter.init_app(app)
|
||||||
|
mail.init_app(app)
|
||||||
|
|
||||||
|
app.jinja_env.filters["money"] = cents_to_dollars
|
||||||
|
app.jinja_env.filters["pretty_date"] = safe_date_label
|
||||||
|
|
||||||
|
@app.context_processor
|
||||||
|
def inject_globals() -> dict:
|
||||||
|
return {
|
||||||
|
"app_version": app.config["APP_VERSION"],
|
||||||
|
"current_user_id": current_user_id(),
|
||||||
|
"is_logged_in": is_logged_in(),
|
||||||
|
}
|
||||||
|
|
||||||
|
app.register_blueprint(public_bp)
|
||||||
|
app.register_blueprint(account_bp)
|
||||||
|
app.register_blueprint(leagues_bp)
|
||||||
|
|
||||||
|
@app.cli.command("init-db")
|
||||||
|
def init_db_command() -> None:
|
||||||
|
if not database_extensions_available() or db is None:
|
||||||
|
raise click.ClickException(
|
||||||
|
"Database dependencies are not installed. Run pip install -r requirements.txt."
|
||||||
|
)
|
||||||
|
|
||||||
|
with app.app_context():
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
click.echo("Initialized database tables.")
|
||||||
|
|
||||||
|
return app
|
||||||
File renamed without changes.
@@ -4,8 +4,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from models import SessionEntry, SessionSummary
|
from .models import SessionEntry, SessionSummary
|
||||||
from utils import net_result_bucket, session_chart_label, session_sort_key
|
from .utils import net_result_bucket, session_chart_label, session_sort_key
|
||||||
|
|
||||||
PLAYER_PALETTE = [
|
PLAYER_PALETTE = [
|
||||||
"#9b8cf0", # --line-1 violet
|
"#9b8cf0", # --line-1 violet
|
||||||
@@ -4,12 +4,12 @@ from __future__ import annotations
|
|||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).resolve().parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
DATA_PATH = BASE_DIR / "data" / "entries.csv"
|
DATA_PATH = BASE_DIR / "data" / "entries.csv"
|
||||||
DEFAULT_DATABASE_URL = f"sqlite:///{BASE_DIR / 'data' / 'boker-dev.sqlite3'}"
|
DEFAULT_DATABASE_URL = f"sqlite:///{BASE_DIR / 'data' / 'boker-dev.sqlite3'}"
|
||||||
|
|
||||||
ELIGIBLE_MIN_SESSIONS = 3
|
ELIGIBLE_MIN_SESSIONS = 3
|
||||||
APP_VERSION = "2.3.0"
|
APP_VERSION = "2.3.1"
|
||||||
|
|
||||||
|
|
||||||
def load_local_env(env_path: Path) -> None:
|
def load_local_env(env_path: Path) -> None:
|
||||||
+1
-1
@@ -24,7 +24,7 @@ def init_database(app: Any) -> bool:
|
|||||||
app.config["DATABASE_EXTENSIONS_AVAILABLE"] = False
|
app.config["DATABASE_EXTENSIONS_AVAILABLE"] = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
import db_models # noqa: F401 - registers SQLAlchemy models with metadata.
|
from . import db_models # noqa: F401 - registers SQLAlchemy models with metadata.
|
||||||
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
migrate.init_app(app, db)
|
migrate.init_app(app, db)
|
||||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
import uuid
|
import uuid
|
||||||
from datetime import date, datetime, timezone
|
from datetime import date, datetime, timezone
|
||||||
|
|
||||||
from db import db
|
from .db import db
|
||||||
|
|
||||||
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
||||||
raise RuntimeError("Database dependencies are not installed.")
|
raise RuntimeError("Database dependencies are not installed.")
|
||||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
from flask import current_app
|
from flask import current_app
|
||||||
from flask_mail import Message
|
from flask_mail import Message
|
||||||
|
|
||||||
from extensions import mail
|
from .extensions import mail
|
||||||
|
|
||||||
|
|
||||||
def send_password_reset(to_email: str, reset_url: str) -> None:
|
def send_password_reset(to_email: str, reset_url: str) -> None:
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -5,13 +5,13 @@ import secrets
|
|||||||
import string
|
import string
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from auth import hash_password, normalize_email
|
from ..auth import hash_password, normalize_email
|
||||||
from db import db
|
from ..db import db
|
||||||
|
|
||||||
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
||||||
raise RuntimeError("Database dependencies are not installed.")
|
raise RuntimeError("Database dependencies are not installed.")
|
||||||
|
|
||||||
from db_models import ( # noqa: E402
|
from ..db_models import ( # noqa: E402
|
||||||
LedgerEvent,
|
LedgerEvent,
|
||||||
League,
|
League,
|
||||||
LeagueMembership,
|
LeagueMembership,
|
||||||
@@ -24,7 +24,7 @@ from db_models import ( # noqa: E402
|
|||||||
make_user,
|
make_user,
|
||||||
normalize_lookup,
|
normalize_lookup,
|
||||||
)
|
)
|
||||||
from utils import slugify
|
from ..utils import slugify
|
||||||
|
|
||||||
PUBLIC_KEY_ALPHABET = string.ascii_lowercase + string.digits
|
PUBLIC_KEY_ALPHABET = string.ascii_lowercase + string.digits
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ def set_session_status(session: PokerSession, status: str) -> PokerSession:
|
|||||||
if status not in {"open", "closed"}:
|
if status not in {"open", "closed"}:
|
||||||
raise ValueError(f"Unsupported session status: {status}")
|
raise ValueError(f"Unsupported session status: {status}")
|
||||||
|
|
||||||
from db_models import utc_now
|
from ..db_models import utc_now
|
||||||
|
|
||||||
session.status = status
|
session.status = status
|
||||||
if status == "open":
|
if status == "open":
|
||||||
@@ -313,7 +313,7 @@ def add_league_member(
|
|||||||
|
|
||||||
|
|
||||||
def remove_league_member(league_id: str, user_id: str) -> None:
|
def remove_league_member(league_id: str, user_id: str) -> None:
|
||||||
from db_models import utc_now
|
from ..db_models import utc_now
|
||||||
|
|
||||||
membership = LeagueMembership.query.filter_by(
|
membership = LeagueMembership.query.filter_by(
|
||||||
league_id=league_id,
|
league_id=league_id,
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from db import db
|
from ..db import db
|
||||||
|
|
||||||
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
if db is None: # pragma: no cover - imported only when DB dependencies exist.
|
||||||
raise RuntimeError("Database dependencies are not installed.")
|
raise RuntimeError("Database dependencies are not installed.")
|
||||||
|
|
||||||
from db_models import ( # noqa: E402
|
from ..db_models import ( # noqa: E402
|
||||||
CANONICAL_EVENT_TYPES,
|
CANONICAL_EVENT_TYPES,
|
||||||
LedgerEvent,
|
LedgerEvent,
|
||||||
Player,
|
Player,
|
||||||
@@ -14,7 +14,7 @@ from db_models import ( # noqa: E402
|
|||||||
User,
|
User,
|
||||||
canonical_event_type,
|
canonical_event_type,
|
||||||
)
|
)
|
||||||
from storage import EventRow # noqa: E402
|
from ..storage import EventRow # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
def session_event_ref(session: PokerSession) -> str:
|
def session_event_ref(session: PokerSession) -> str:
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -5,7 +5,7 @@ from urllib.parse import urlparse
|
|||||||
|
|
||||||
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
||||||
|
|
||||||
from auth import (
|
from ..auth import (
|
||||||
current_user_id,
|
current_user_id,
|
||||||
generate_invite_token,
|
generate_invite_token,
|
||||||
generate_reset_token,
|
generate_reset_token,
|
||||||
@@ -18,8 +18,8 @@ from auth import (
|
|||||||
verify_password,
|
verify_password,
|
||||||
verify_reset_token,
|
verify_reset_token,
|
||||||
)
|
)
|
||||||
from db import database_extensions_available, db
|
from ..db import database_extensions_available, db
|
||||||
from extensions import limiter
|
from ..extensions import limiter
|
||||||
|
|
||||||
account_bp = Blueprint("account", __name__, url_prefix="/account")
|
account_bp = Blueprint("account", __name__, url_prefix="/account")
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ def register():
|
|||||||
}
|
}
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
from league_repositories import create_user, find_user_by_email
|
from ..repositories.leagues import create_user, find_user_by_email
|
||||||
|
|
||||||
email = normalize_email(form["email"])
|
email = normalize_email(form["email"])
|
||||||
password = request.form.get("password", "")
|
password = request.form.get("password", "")
|
||||||
@@ -88,7 +88,7 @@ def login():
|
|||||||
}
|
}
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
from league_repositories import find_user_by_email
|
from ..repositories.leagues import find_user_by_email
|
||||||
|
|
||||||
user = find_user_by_email(form["email"])
|
user = find_user_by_email(form["email"])
|
||||||
password = request.form.get("password", "")
|
password = request.form.get("password", "")
|
||||||
@@ -122,7 +122,7 @@ def settings():
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("leagues.index"))
|
return redirect(url_for("leagues.index"))
|
||||||
|
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
|
|
||||||
user = db.session.get(User, current_user_id())
|
user = db.session.get(User, current_user_id())
|
||||||
if user is None:
|
if user is None:
|
||||||
@@ -139,7 +139,7 @@ def update_email():
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("account.settings"))
|
return redirect(url_for("account.settings"))
|
||||||
|
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
|
|
||||||
user = db.session.get(User, current_user_id())
|
user = db.session.get(User, current_user_id())
|
||||||
if user is None:
|
if user is None:
|
||||||
@@ -154,7 +154,7 @@ def update_email():
|
|||||||
elif not verify_password(user.password_hash, current_password):
|
elif not verify_password(user.password_hash, current_password):
|
||||||
flash("Current password is incorrect.", "error")
|
flash("Current password is incorrect.", "error")
|
||||||
else:
|
else:
|
||||||
from league_repositories import find_user_by_email
|
from ..repositories.leagues import find_user_by_email
|
||||||
|
|
||||||
existing = find_user_by_email(new_email)
|
existing = find_user_by_email(new_email)
|
||||||
if existing and existing.id != user.id:
|
if existing and existing.id != user.id:
|
||||||
@@ -174,7 +174,7 @@ def update_password():
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("account.settings"))
|
return redirect(url_for("account.settings"))
|
||||||
|
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
|
|
||||||
user = db.session.get(User, current_user_id())
|
user = db.session.get(User, current_user_id())
|
||||||
if user is None:
|
if user is None:
|
||||||
@@ -206,7 +206,7 @@ def delete_account():
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("account.settings"))
|
return redirect(url_for("account.settings"))
|
||||||
|
|
||||||
from db_models import League, User, utc_now
|
from ..db_models import League, User, utc_now
|
||||||
|
|
||||||
user = db.session.get(User, current_user_id())
|
user = db.session.get(User, current_user_id())
|
||||||
if user is None:
|
if user is None:
|
||||||
@@ -246,9 +246,10 @@ def forgot_password():
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("account.forgot_password"))
|
return redirect(url_for("account.forgot_password"))
|
||||||
|
|
||||||
from emails import send_password_reset
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from league_repositories import find_user_by_email
|
|
||||||
|
from ..emails import send_password_reset
|
||||||
|
from ..repositories.leagues import find_user_by_email
|
||||||
|
|
||||||
email = normalize_email(request.form.get("email", ""))
|
email = normalize_email(request.form.get("email", ""))
|
||||||
user = find_user_by_email(email)
|
user = find_user_by_email(email)
|
||||||
@@ -282,7 +283,7 @@ def reset_password(token):
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("account.login"))
|
return redirect(url_for("account.login"))
|
||||||
|
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
|
|
||||||
user = db.session.get(User, user_id)
|
user = db.session.get(User, user_id)
|
||||||
if user is None or user.disabled_at is not None:
|
if user is None or user.disabled_at is not None:
|
||||||
@@ -320,8 +321,8 @@ def accept_invite(token):
|
|||||||
flash("Account database is not available.", "error")
|
flash("Account database is not available.", "error")
|
||||||
return redirect(url_for("leagues.index"))
|
return redirect(url_for("leagues.index"))
|
||||||
|
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
from league_repositories import add_league_member, find_league_by_id, find_membership
|
from ..repositories.leagues import add_league_member, find_league_by_id, find_membership
|
||||||
|
|
||||||
user = db.session.get(User, current_user_id())
|
user = db.session.get(User, current_user_id())
|
||||||
if user is None or user.email != data.get("email"):
|
if user is None or user.email != data.get("email"):
|
||||||
@@ -16,16 +16,16 @@ from flask import (
|
|||||||
url_for,
|
url_for,
|
||||||
)
|
)
|
||||||
|
|
||||||
from auth import is_admin
|
from ..auth import is_admin
|
||||||
from services import (
|
from ..services import (
|
||||||
build_session_summaries,
|
build_session_summaries,
|
||||||
next_session_id,
|
next_session_id,
|
||||||
pending_payout_carry_items,
|
pending_payout_carry_items,
|
||||||
prunable_empty_session_ids,
|
prunable_empty_session_ids,
|
||||||
unique_player_names,
|
unique_player_names,
|
||||||
)
|
)
|
||||||
from storage import CSV_HEADERS, append_event, load_events, write_events
|
from ..storage import CSV_HEADERS, append_event, load_events, write_events
|
||||||
from utils import cents_to_dollars, session_label
|
from ..utils import cents_to_dollars, session_label
|
||||||
|
|
||||||
admin_bp = Blueprint("admin", __name__)
|
admin_bp = Blueprint("admin", __name__)
|
||||||
|
|
||||||
@@ -9,12 +9,12 @@ from datetime import datetime, timezone
|
|||||||
|
|
||||||
from flask import Blueprint, abort, flash, make_response, redirect, render_template, request, url_for
|
from flask import Blueprint, abort, flash, make_response, redirect, render_template, request, url_for
|
||||||
|
|
||||||
from auth import current_user_id, login_required, normalize_email
|
from ..auth import current_user_id, login_required, normalize_email
|
||||||
from charts import cumulative_profit_series, player_session_series
|
from ..charts import cumulative_profit_series, player_session_series
|
||||||
from db import database_extensions_available, db
|
from ..db import database_extensions_available, db
|
||||||
from models import SessionSummary
|
from ..models import SessionSummary
|
||||||
from services import apply_rank_changes, build_leaderboard, build_session_summaries, session_events
|
from ..services import apply_rank_changes, build_leaderboard, build_session_summaries, session_events
|
||||||
from utils import cents_to_dollars, session_label, session_sort_key
|
from ..utils import cents_to_dollars, session_label, session_sort_key
|
||||||
|
|
||||||
leagues_bp = Blueprint("leagues", __name__)
|
leagues_bp = Blueprint("leagues", __name__)
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ def split_league_ref(league_ref: str) -> tuple[str, str]:
|
|||||||
|
|
||||||
|
|
||||||
def require_league(league_ref: str, allowed_roles: set[str]):
|
def require_league(league_ref: str, allowed_roles: set[str]):
|
||||||
from league_repositories import find_league_by_public_key, user_has_league_role
|
from ..repositories.leagues import find_league_by_public_key, user_has_league_role
|
||||||
|
|
||||||
_slug, public_key = split_league_ref(league_ref)
|
_slug, public_key = split_league_ref(league_ref)
|
||||||
league = find_league_by_public_key(public_key)
|
league = find_league_by_public_key(public_key)
|
||||||
@@ -64,7 +64,7 @@ def require_league(league_ref: str, allowed_roles: set[str]):
|
|||||||
|
|
||||||
def get_league_with_visibility_gate(league_ref: str):
|
def get_league_with_visibility_gate(league_ref: str):
|
||||||
"""Load league; if private, enforce login + membership. Returns (league, None) or (None, redirect)."""
|
"""Load league; if private, enforce login + membership. Returns (league, None) or (None, redirect)."""
|
||||||
from league_repositories import find_league_by_public_key, user_has_league_role
|
from ..repositories.leagues import find_league_by_public_key, user_has_league_role
|
||||||
|
|
||||||
_slug, public_key = split_league_ref(league_ref)
|
_slug, public_key = split_league_ref(league_ref)
|
||||||
league = find_league_by_public_key(public_key)
|
league = find_league_by_public_key(public_key)
|
||||||
@@ -99,8 +99,8 @@ def empty_session_summary(session) -> SessionSummary:
|
|||||||
|
|
||||||
|
|
||||||
def session_ref_map(league_id: str) -> dict[str, str]:
|
def session_ref_map(league_id: str) -> dict[str, str]:
|
||||||
from ledger_repositories import session_event_ref
|
from ..repositories.ledger import session_event_ref
|
||||||
from league_repositories import list_sessions_for_league
|
from ..repositories.leagues import list_sessions_for_league
|
||||||
|
|
||||||
return {session_event_ref(session): session.id for session in list_sessions_for_league(league_id)}
|
return {session_event_ref(session): session.id for session in list_sessions_for_league(league_id)}
|
||||||
|
|
||||||
@@ -112,8 +112,8 @@ def index():
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return render_template("leagues_index.html", leagues=[])
|
return render_template("leagues_index.html", leagues=[])
|
||||||
|
|
||||||
from league_repositories import list_leagues_for_user
|
from ..repositories.leagues import list_leagues_for_user
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
|
|
||||||
memberships = list_leagues_for_user(current_user_id() or "")
|
memberships = list_leagues_for_user(current_user_id() or "")
|
||||||
league_summaries = []
|
league_summaries = []
|
||||||
@@ -190,8 +190,8 @@ def new():
|
|||||||
}
|
}
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
from db_models import User
|
from ..db_models import User
|
||||||
from league_repositories import create_league, unique_league_slug
|
from ..repositories.leagues import create_league, unique_league_slug
|
||||||
|
|
||||||
owner = db.session.get(User, current_user_id())
|
owner = db.session.get(User, current_user_id())
|
||||||
if owner is None:
|
if owner is None:
|
||||||
@@ -221,7 +221,7 @@ def dashboard(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import league_counts, user_has_league_role
|
from ..repositories.leagues import league_counts, user_has_league_role
|
||||||
|
|
||||||
league, resp = get_league_with_visibility_gate(league_ref)
|
league, resp = get_league_with_visibility_gate(league_ref)
|
||||||
if resp:
|
if resp:
|
||||||
@@ -242,7 +242,7 @@ def legacy_dashboard_redirect(league_id: str, league_slug: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import find_league_by_id, user_has_league_role
|
from ..repositories.leagues import find_league_by_id, user_has_league_role
|
||||||
|
|
||||||
league = find_league_by_id(league_id)
|
league = find_league_by_id(league_id)
|
||||||
if league is None:
|
if league is None:
|
||||||
@@ -259,9 +259,9 @@ def leaderboard(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from config import ELIGIBLE_MIN_SESSIONS
|
from ..config import ELIGIBLE_MIN_SESSIONS
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
from league_repositories import list_players_for_league, user_has_league_role
|
from ..repositories.leagues import list_players_for_league, user_has_league_role
|
||||||
|
|
||||||
league, resp = get_league_with_visibility_gate(league_ref)
|
league, resp = get_league_with_visibility_gate(league_ref)
|
||||||
if resp:
|
if resp:
|
||||||
@@ -366,12 +366,12 @@ def ledger(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import (
|
from ..repositories.ledger import (
|
||||||
append_ledger_event,
|
append_ledger_event,
|
||||||
list_all_event_rows_for_league,
|
list_all_event_rows_for_league,
|
||||||
list_event_rows_for_league,
|
list_event_rows_for_league,
|
||||||
)
|
)
|
||||||
from league_repositories import (
|
from ..repositories.leagues import (
|
||||||
find_player_for_league,
|
find_player_for_league,
|
||||||
find_session_for_league,
|
find_session_for_league,
|
||||||
list_players_for_league,
|
list_players_for_league,
|
||||||
@@ -506,7 +506,7 @@ def void_event(league_ref: str, event_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import void_ledger_event
|
from ..repositories.ledger import void_ledger_event
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner"})
|
league = require_league(league_ref, {"owner"})
|
||||||
reason = request.form.get("void_reason", "").strip()
|
reason = request.form.get("void_reason", "").strip()
|
||||||
@@ -529,8 +529,8 @@ def player_detail(league_ref: str, player_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
from league_repositories import find_player_for_league, user_has_league_role
|
from ..repositories.leagues import find_player_for_league, user_has_league_role
|
||||||
|
|
||||||
league, resp = get_league_with_visibility_gate(league_ref)
|
league, resp = get_league_with_visibility_gate(league_ref)
|
||||||
if resp:
|
if resp:
|
||||||
@@ -588,7 +588,7 @@ def players(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import (
|
from ..repositories.leagues import (
|
||||||
create_player,
|
create_player,
|
||||||
list_players_for_league,
|
list_players_for_league,
|
||||||
player_name_exists,
|
player_name_exists,
|
||||||
@@ -627,7 +627,7 @@ def players(league_ref: str):
|
|||||||
flash("Player added.", "success")
|
flash("Player added.", "success")
|
||||||
return redirect(url_for("leagues.players", **league_url_values(league)))
|
return redirect(url_for("leagues.players", **league_url_values(league)))
|
||||||
|
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
|
|
||||||
all_sessions = build_session_summaries(list_event_rows_for_league(league.id))
|
all_sessions = build_session_summaries(list_event_rows_for_league(league.id))
|
||||||
board = build_leaderboard(all_sessions)
|
board = build_leaderboard(all_sessions)
|
||||||
@@ -661,7 +661,7 @@ def update_player_status(league_ref: str, player_id: str, status: str, message:
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import find_player_for_league, set_player_status
|
from ..repositories.leagues import find_player_for_league, set_player_status
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
player = find_player_for_league(league.id, player_id)
|
player = find_player_for_league(league.id, player_id)
|
||||||
@@ -681,7 +681,7 @@ def edit_player(league_ref: str, player_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import find_player_for_league, player_name_taken, update_player
|
from ..repositories.leagues import find_player_for_league, player_name_taken, update_player
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
player = find_player_for_league(league.id, player_id)
|
player = find_player_for_league(league.id, player_id)
|
||||||
@@ -709,8 +709,8 @@ def sessions(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import append_ledger_event
|
from ..repositories.ledger import append_ledger_event
|
||||||
from league_repositories import (
|
from ..repositories.leagues import (
|
||||||
create_poker_session,
|
create_poker_session,
|
||||||
list_sessions_for_league,
|
list_sessions_for_league,
|
||||||
user_has_league_role,
|
user_has_league_role,
|
||||||
@@ -747,7 +747,7 @@ def sessions(league_ref: str):
|
|||||||
session.label = form["label"] or None
|
session.label = form["label"] or None
|
||||||
session.notes = form["notes"] or None
|
session.notes = form["notes"] or None
|
||||||
if status == "open":
|
if status == "open":
|
||||||
from league_repositories import set_session_status
|
from ..repositories.leagues import set_session_status
|
||||||
|
|
||||||
set_session_status(session, "open")
|
set_session_status(session, "open")
|
||||||
|
|
||||||
@@ -765,8 +765,8 @@ def sessions(league_ref: str):
|
|||||||
flash(f"Created {session.display_label}.", "success")
|
flash(f"Created {session.display_label}.", "success")
|
||||||
return redirect(url_for("leagues.sessions", **league_url_values(league)))
|
return redirect(url_for("leagues.sessions", **league_url_values(league)))
|
||||||
|
|
||||||
from db_models import LedgerEvent
|
from ..db_models import LedgerEvent
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
|
|
||||||
all_sessions = list_sessions_for_league(league.id)
|
all_sessions = list_sessions_for_league(league.id)
|
||||||
summaries = build_session_summaries(list_event_rows_for_league(league.id))
|
summaries = build_session_summaries(list_event_rows_for_league(league.id))
|
||||||
@@ -803,8 +803,8 @@ def prune_empty_sessions(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from db_models import LedgerEvent, PokerSession
|
from ..db_models import LedgerEvent, PokerSession
|
||||||
from league_repositories import list_sessions_for_league
|
from ..repositories.leagues import list_sessions_for_league
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
|
|
||||||
@@ -839,7 +839,7 @@ def delete_session(league_ref: str, session_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import find_session_for_league
|
from ..repositories.leagues import find_session_for_league
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner"})
|
league = require_league(league_ref, {"owner"})
|
||||||
session = find_session_for_league(league.id, session_id)
|
session = find_session_for_league(league.id, session_id)
|
||||||
@@ -859,7 +859,7 @@ def edit_session(league_ref: str, session_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import find_session_for_league
|
from ..repositories.leagues import find_session_for_league
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
session = find_session_for_league(league.id, session_id)
|
session = find_session_for_league(league.id, session_id)
|
||||||
@@ -877,7 +877,7 @@ def edit_session(league_ref: str, session_id: str):
|
|||||||
return redirect(url_for("leagues.session_detail", league_ref=league.url_ref, session_id=session_id))
|
return redirect(url_for("leagues.session_detail", league_ref=league.url_ref, session_id=session_id))
|
||||||
|
|
||||||
if new_date != session.session_date:
|
if new_date != session.session_date:
|
||||||
from db_models import PokerSession as _PS
|
from ..db_models import PokerSession as _PS
|
||||||
max_seq = db.session.query(db.func.max(_PS.sequence_on_date)).filter(
|
max_seq = db.session.query(db.func.max(_PS.sequence_on_date)).filter(
|
||||||
_PS.league_id == league.id,
|
_PS.league_id == league.id,
|
||||||
_PS.session_date == new_date,
|
_PS.session_date == new_date,
|
||||||
@@ -900,8 +900,8 @@ def session_detail(league_ref: str, session_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import append_ledger_event, list_all_event_rows_for_session, list_event_rows_for_session
|
from ..repositories.ledger import append_ledger_event, list_all_event_rows_for_session, list_event_rows_for_session
|
||||||
from league_repositories import (
|
from ..repositories.leagues import (
|
||||||
find_session_for_league,
|
find_session_for_league,
|
||||||
list_players_for_league,
|
list_players_for_league,
|
||||||
user_has_league_role,
|
user_has_league_role,
|
||||||
@@ -989,9 +989,9 @@ def session_public_view(league_ref: str, session_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from charts import session_breakdown_series
|
from ..charts import session_breakdown_series
|
||||||
from ledger_repositories import list_event_rows_for_league, list_event_rows_for_session
|
from ..repositories.ledger import list_event_rows_for_league, list_event_rows_for_session
|
||||||
from league_repositories import find_league_by_public_key, find_session_for_league, list_sessions_for_league, user_has_league_role
|
from ..repositories.leagues import find_league_by_public_key, find_session_for_league, list_sessions_for_league, user_has_league_role
|
||||||
|
|
||||||
_slug, public_key = split_league_ref(league_ref)
|
_slug, public_key = split_league_ref(league_ref)
|
||||||
league = find_league_by_public_key(public_key)
|
league = find_league_by_public_key(public_key)
|
||||||
@@ -1062,8 +1062,8 @@ def update_session_status(league_ref: str, session_id: str, status: str, message
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import append_ledger_event
|
from ..repositories.ledger import append_ledger_event
|
||||||
from league_repositories import find_session_for_league, set_session_status
|
from ..repositories.leagues import find_session_for_league, set_session_status
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
session = find_session_for_league(league.id, session_id)
|
session = find_session_for_league(league.id, session_id)
|
||||||
@@ -1114,7 +1114,7 @@ def league_settings(league_ref: str):
|
|||||||
elif form["visibility"] not in ("private", "public"):
|
elif form["visibility"] not in ("private", "public"):
|
||||||
flash("Invalid visibility value.", "error")
|
flash("Invalid visibility value.", "error")
|
||||||
else:
|
else:
|
||||||
from utils import slugify
|
from ..utils import slugify
|
||||||
|
|
||||||
league.name = form["name"]
|
league.name = form["name"]
|
||||||
league.slug = slugify(form["name"])
|
league.slug = slugify(form["name"])
|
||||||
@@ -1124,7 +1124,7 @@ def league_settings(league_ref: str):
|
|||||||
flash("League settings saved.", "success")
|
flash("League settings saved.", "success")
|
||||||
return redirect(url_for("leagues.league_settings", league_ref=league.url_ref))
|
return redirect(url_for("leagues.league_settings", league_ref=league.url_ref))
|
||||||
|
|
||||||
from league_repositories import list_members_for_league
|
from ..repositories.leagues import list_members_for_league
|
||||||
|
|
||||||
members = list_members_for_league(league.id)
|
members = list_members_for_league(league.id)
|
||||||
return render_template("league_settings.html", league=league, form=form, is_owner=True, members=members)
|
return render_template("league_settings.html", league=league, form=form, is_owner=True, members=members)
|
||||||
@@ -1137,10 +1137,11 @@ def invite_member(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from auth import generate_invite_token
|
|
||||||
from emails import send_league_invite
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from league_repositories import find_membership, find_user_by_email
|
|
||||||
|
from ..auth import generate_invite_token
|
||||||
|
from ..emails import send_league_invite
|
||||||
|
from ..repositories.leagues import find_membership, find_user_by_email
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner"})
|
league = require_league(league_ref, {"owner"})
|
||||||
email = normalize_email(request.form.get("email", ""))
|
email = normalize_email(request.form.get("email", ""))
|
||||||
@@ -1181,7 +1182,7 @@ def remove_member(league_ref: str, user_id: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from league_repositories import remove_league_member
|
from ..repositories.leagues import remove_league_member
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner"})
|
league = require_league(league_ref, {"owner"})
|
||||||
|
|
||||||
@@ -1202,7 +1203,7 @@ def archive_league(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from db_models import utc_now
|
from ..db_models import utc_now
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner"})
|
league = require_league(league_ref, {"owner"})
|
||||||
confirm_name = request.form.get("confirm_name", "").strip()
|
confirm_name = request.form.get("confirm_name", "").strip()
|
||||||
@@ -1224,8 +1225,8 @@ def export_ledger_csv(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from ledger_repositories import list_event_rows_for_league
|
from ..repositories.ledger import list_event_rows_for_league
|
||||||
from storage import CSV_HEADERS
|
from ..storage import CSV_HEADERS
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager", "viewer"})
|
league = require_league(league_ref, {"owner", "manager", "viewer"})
|
||||||
rows = list_event_rows_for_league(league.id)
|
rows = list_event_rows_for_league(league.id)
|
||||||
@@ -1250,14 +1251,14 @@ def import_ledger_csv(league_ref: str):
|
|||||||
flash("League database is not available.", "error")
|
flash("League database is not available.", "error")
|
||||||
return redirect(url_for("public.home"))
|
return redirect(url_for("public.home"))
|
||||||
|
|
||||||
from db_models import CANONICAL_EVENT_TYPES, canonical_event_type
|
from ..db_models import CANONICAL_EVENT_TYPES, canonical_event_type
|
||||||
from ledger_repositories import (
|
from ..repositories.ledger import (
|
||||||
append_ledger_event,
|
append_ledger_event,
|
||||||
list_ledger_events_for_league,
|
list_ledger_events_for_league,
|
||||||
session_event_ref,
|
session_event_ref,
|
||||||
)
|
)
|
||||||
from league_repositories import list_players_for_league, list_sessions_for_league
|
from ..repositories.leagues import list_players_for_league, list_sessions_for_league
|
||||||
from storage import CSV_HEADERS
|
from ..storage import CSV_HEADERS
|
||||||
|
|
||||||
league = require_league(league_ref, {"owner", "manager"})
|
league = require_league(league_ref, {"owner", "manager"})
|
||||||
|
|
||||||
@@ -4,16 +4,16 @@ from __future__ import annotations
|
|||||||
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
from flask import Blueprint, flash, redirect, render_template, request, url_for
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from charts import cumulative_profit_series, player_session_series, session_breakdown_series
|
from ..charts import cumulative_profit_series, player_session_series, session_breakdown_series
|
||||||
from config import ELIGIBLE_MIN_SESSIONS
|
from ..config import ELIGIBLE_MIN_SESSIONS
|
||||||
from services import (
|
from ..services import (
|
||||||
apply_rank_changes,
|
apply_rank_changes,
|
||||||
build_leaderboard,
|
build_leaderboard,
|
||||||
build_session_summaries,
|
build_session_summaries,
|
||||||
session_events,
|
session_events,
|
||||||
)
|
)
|
||||||
from storage import load_events
|
from ..storage import load_events
|
||||||
from utils import session_label, session_sort_key
|
from ..utils import session_label, session_sort_key
|
||||||
|
|
||||||
public_bp = Blueprint("public", __name__)
|
public_bp = Blueprint("public", __name__)
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ def help():
|
|||||||
|
|
||||||
@public_bp.get("/explore")
|
@public_bp.get("/explore")
|
||||||
def explore():
|
def explore():
|
||||||
from auth import is_logged_in
|
from ..auth import is_logged_in
|
||||||
from db import database_extensions_available
|
from ..db import database_extensions_available
|
||||||
from league_repositories import league_counts, list_public_leagues
|
from ..repositories.leagues import league_counts, list_public_leagues
|
||||||
|
|
||||||
q = request.args.get("q", "").strip()
|
q = request.args.get("q", "").strip()
|
||||||
leagues = list_public_leagues(q) if database_extensions_available() else []
|
leagues = list_public_leagues(q) if database_extensions_available() else []
|
||||||
@@ -4,9 +4,9 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from models import PlayerStats, SessionEntry, SessionSummary
|
from .models import PlayerStats, SessionEntry, SessionSummary
|
||||||
from storage import EventRow
|
from .storage import EventRow
|
||||||
from utils import entry_sort_key, net_result_bucket, session_sort_key
|
from .utils import entry_sort_key, net_result_bucket, session_sort_key
|
||||||
|
|
||||||
SESSION_MARKER_TYPES = {"session_open", "session_close"}
|
SESSION_MARKER_TYPES = {"session_open", "session_close"}
|
||||||
|
|
||||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -7,7 +7,7 @@ import re
|
|||||||
|
|
||||||
from markupsafe import Markup
|
from markupsafe import Markup
|
||||||
|
|
||||||
from models import SessionEntry, SessionSummary
|
from .models import SessionEntry, SessionSummary
|
||||||
|
|
||||||
BREAK_EVEN_TOLERANCE_CENTS = 100
|
BREAK_EVEN_TOLERANCE_CENTS = 100
|
||||||
|
|
||||||
+15
-13
@@ -2,15 +2,17 @@ from pathlib import Path
|
|||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import app as app_module
|
from boker import create_app
|
||||||
from charts import player_session_series
|
from boker.charts import player_session_series
|
||||||
from services import (
|
from boker.services import (
|
||||||
build_leaderboard,
|
build_leaderboard,
|
||||||
build_session_summaries,
|
build_session_summaries,
|
||||||
pending_payout_carry_items,
|
pending_payout_carry_items,
|
||||||
)
|
)
|
||||||
from storage import load_events, write_events
|
from boker.storage import load_events, write_events
|
||||||
from utils import session_sort_key
|
from boker.utils import session_sort_key
|
||||||
|
|
||||||
|
_app = create_app()
|
||||||
|
|
||||||
|
|
||||||
def cents(amount: float) -> int:
|
def cents(amount: float) -> int:
|
||||||
@@ -203,8 +205,8 @@ class AccountingTests(unittest.TestCase):
|
|||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
data_path = Path(tmpdir) / "entries.csv"
|
data_path = Path(tmpdir) / "entries.csv"
|
||||||
write_events(data_path, rows)
|
write_events(data_path, rows)
|
||||||
original_path = app_module.app.config["DATA_PATH"]
|
original_path = _app.config["DATA_PATH"]
|
||||||
app_module.app.config["DATA_PATH"] = data_path
|
_app.config["DATA_PATH"] = data_path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sessions = build_session_summaries(load_events(data_path))
|
sessions = build_session_summaries(load_events(data_path))
|
||||||
@@ -213,7 +215,7 @@ class AccountingTests(unittest.TestCase):
|
|||||||
[{"player_name": "A", "amount_cents": cents(5)}],
|
[{"player_name": "A", "amount_cents": cents(5)}],
|
||||||
)
|
)
|
||||||
|
|
||||||
with app_module.app.test_client() as client:
|
with _app.test_client() as client:
|
||||||
with client.session_transaction() as flask_session:
|
with client.session_transaction() as flask_session:
|
||||||
flask_session["is_admin"] = True
|
flask_session["is_admin"] = True
|
||||||
|
|
||||||
@@ -222,7 +224,7 @@ class AccountingTests(unittest.TestCase):
|
|||||||
data={"session_id": "s2", "player_name": "A"},
|
data={"session_id": "s2", "player_name": "A"},
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
app_module.app.config["DATA_PATH"] = original_path
|
_app.config["DATA_PATH"] = original_path
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
updated_sessions = build_session_summaries(load_events(data_path))
|
updated_sessions = build_session_summaries(load_events(data_path))
|
||||||
@@ -261,17 +263,17 @@ class AccountingTests(unittest.TestCase):
|
|||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
data_path = Path(tmpdir) / "entries.csv"
|
data_path = Path(tmpdir) / "entries.csv"
|
||||||
write_events(data_path, rows)
|
write_events(data_path, rows)
|
||||||
original_path = app_module.app.config["DATA_PATH"]
|
original_path = _app.config["DATA_PATH"]
|
||||||
app_module.app.config["DATA_PATH"] = data_path
|
_app.config["DATA_PATH"] = data_path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with app_module.app.test_client() as client:
|
with _app.test_client() as client:
|
||||||
with client.session_transaction() as flask_session:
|
with client.session_transaction() as flask_session:
|
||||||
flask_session["is_admin"] = True
|
flask_session["is_admin"] = True
|
||||||
|
|
||||||
response = client.post("/admin/prune-empty-sessions")
|
response = client.post("/admin/prune-empty-sessions")
|
||||||
finally:
|
finally:
|
||||||
app_module.app.config["DATA_PATH"] = original_path
|
_app.config["DATA_PATH"] = original_path
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
remaining = load_events(data_path)
|
remaining = load_events(data_path)
|
||||||
|
|||||||
+3
-2
@@ -1,6 +1,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from stats import SessionEntry, SessionSummary, build_leaderboard
|
from boker.models import SessionEntry, SessionSummary
|
||||||
|
from boker.services import build_leaderboard
|
||||||
|
|
||||||
|
|
||||||
class CashInAccountingTest(unittest.TestCase):
|
class CashInAccountingTest(unittest.TestCase):
|
||||||
@@ -78,7 +79,7 @@ class CashInAccountingTest(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(player.total_buy_in_cents, 2500)
|
self.assertEqual(player.total_buy_in_cents, 2500)
|
||||||
self.assertEqual(player.total_front_collected_cents, 0)
|
self.assertEqual(player.total_front_collected_cents, 0)
|
||||||
self.assertEqual(player.total_cash_in_cents, 3000)
|
self.assertEqual(player.total_real_cash_in_cents, 2500)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in new issue
Block a user