Boards
leadr.boards¶
Modules:
leadr.boards.adapters¶
Modules:
- orm – Board ORM model.
leadr.boards.adapters.orm¶
Board ORM model.
Classes:
- BoardORM – Board ORM model.
- BoardTemplateORM – BoardTemplate ORM model.
leadr.boards.adapters.orm.BoardORM¶
Bases: Base
Board ORM model.
Represents a leaderboard/board that belongs to a game in the database. Maps to the boards table with foreign keys to accounts and games, a unique constraint on short_code (globally unique for direct sharing), and a partial unique constraint on (account_id, game_id, slug) for active boards only.
Attributes:
- account (
Mapped[AccountORM]) – - account_id (
Mapped[UUID]) – - created_at (
Mapped[timestamp]) – - created_from_template_id (
Mapped[UUID | None]) – - deleted_at (
Mapped[nullable_timestamp]) – - description (
Mapped[str | None]) – - ends_at (
Mapped[datetime | None]) – - game (
Mapped[GameORM]) – - game_id (
Mapped[UUID]) – - icon (
Mapped[str | None]) – - id (
Mapped[uuid_pk]) – - is_active (
Mapped[bool]) – - is_published (
Mapped[bool]) – - keep_strategy (
Mapped[str]) – - name (
Mapped[str]) – - short_code (
Mapped[str]) – - slug (
Mapped[str]) – - sort_direction (
Mapped[str]) – - starts_at (
Mapped[datetime | None]) – - tags (
Mapped[list[str]]) – - template_name (
Mapped[str | None]) – - unit (
Mapped[str | None]) – - updated_at (
Mapped[timestamp]) –
# leadr.boards.adapters.orm.BoardORM.account¶
account: Mapped[AccountORM] = relationship('AccountORM')
# leadr.boards.adapters.orm.BoardORM.account_id¶
account_id: Mapped[UUID] = mapped_column(ForeignKey('accounts.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.boards.adapters.orm.BoardORM.created_at¶
created_at: Mapped[timestamp]
# leadr.boards.adapters.orm.BoardORM.created_from_template_id¶
created_from_template_id: Mapped[UUID | None] = mapped_column(nullable=True, default=None)
# leadr.boards.adapters.orm.BoardORM.deleted_at¶
deleted_at: Mapped[nullable_timestamp]
# leadr.boards.adapters.orm.BoardORM.description¶
description: Mapped[str | None] = mapped_column(String, nullable=True, default=None)
# leadr.boards.adapters.orm.BoardORM.ends_at¶
ends_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, default=None)
# leadr.boards.adapters.orm.BoardORM.game¶
game: Mapped[GameORM] = relationship('GameORM')
# leadr.boards.adapters.orm.BoardORM.game_id¶
game_id: Mapped[UUID] = mapped_column(ForeignKey('games.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.boards.adapters.orm.BoardORM.icon¶
icon: Mapped[str | None] = mapped_column(String, nullable=True)
# leadr.boards.adapters.orm.BoardORM.id¶
id: Mapped[uuid_pk]
# leadr.boards.adapters.orm.BoardORM.is_active¶
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False)
# leadr.boards.adapters.orm.BoardORM.is_published¶
is_published: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, server_default=(sa.text('true')))
# leadr.boards.adapters.orm.BoardORM.keep_strategy¶
keep_strategy: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardORM.name¶
name: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardORM.short_code¶
short_code: Mapped[str] = mapped_column(String, nullable=False, unique=True, index=True)
# leadr.boards.adapters.orm.BoardORM.slug¶
slug: Mapped[str] = mapped_column(String, nullable=False, index=True)
# leadr.boards.adapters.orm.BoardORM.sort_direction¶
sort_direction: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardORM.starts_at¶
starts_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, default=None)
# leadr.boards.adapters.orm.BoardORM.tags¶
tags: Mapped[list[str]] = mapped_column(ARRAY(String), nullable=False, default=list, server_default='{}')
# leadr.boards.adapters.orm.BoardORM.template_name¶
template_name: Mapped[str | None] = mapped_column(String, nullable=True, default=None)
# leadr.boards.adapters.orm.BoardORM.unit¶
unit: Mapped[str | None] = mapped_column(String, nullable=True)
# leadr.boards.adapters.orm.BoardORM.updated_at¶
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.boards.adapters.orm.BoardTemplateORM¶
Bases: Base
BoardTemplate ORM model.
Represents a template for automatically generating boards at regular intervals. Maps to the board_templates table with foreign keys to accounts and games. Uses JSONB column for config to support flexible procedural generation configuration.
Functions:
- from_domain – Convert domain entity to ORM model.
- to_domain – Convert ORM model to domain entity.
Attributes:
- account (
Mapped[AccountORM]) – - account_id (
Mapped[UUID]) – - config (
Mapped[dict[str, Any]]) – - created_at (
Mapped[timestamp]) – - deleted_at (
Mapped[nullable_timestamp]) – - ends_at (
Mapped[datetime | None]) – - game (
Mapped[GameORM]) – - game_id (
Mapped[UUID]) – - icon (
Mapped[str | None]) – - id (
Mapped[uuid_pk]) – - is_active (
Mapped[bool]) – - is_published (
Mapped[bool]) – - keep_strategy (
Mapped[str]) – - name (
Mapped[str]) – - name_template (
Mapped[str | None]) – - next_run_at (
Mapped[datetime]) – - repeat_interval (
Mapped[str]) – - series (
Mapped[str | None]) – - slug (
Mapped[str | None]) – - sort_direction (
Mapped[str]) – - starts_at (
Mapped[datetime | None]) – - tags (
Mapped[list[str]]) – - unit (
Mapped[str | None]) – - updated_at (
Mapped[timestamp]) –
# leadr.boards.adapters.orm.BoardTemplateORM.account¶
account: Mapped[AccountORM] = relationship('AccountORM')
# leadr.boards.adapters.orm.BoardTemplateORM.account_id¶
account_id: Mapped[UUID] = mapped_column(ForeignKey('accounts.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.boards.adapters.orm.BoardTemplateORM.config¶
config: Mapped[dict[str, Any]] = mapped_column(JSONB, nullable=False, default=dict, server_default='{}')
# leadr.boards.adapters.orm.BoardTemplateORM.created_at¶
created_at: Mapped[timestamp]
# leadr.boards.adapters.orm.BoardTemplateORM.deleted_at¶
deleted_at: Mapped[nullable_timestamp]
# leadr.boards.adapters.orm.BoardTemplateORM.ends_at¶
ends_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, default=None)
# leadr.boards.adapters.orm.BoardTemplateORM.from_domain¶
from_domain(entity)
Convert domain entity to ORM model.
Parameters:
- entity (
BoardTemplate) – The BoardTemplate domain entity to convert.
Returns:
BoardTemplateORM– BoardTemplateORM model with all fields populated from domain entity.
# leadr.boards.adapters.orm.BoardTemplateORM.game¶
game: Mapped[GameORM] = relationship('GameORM')
# leadr.boards.adapters.orm.BoardTemplateORM.game_id¶
game_id: Mapped[UUID] = mapped_column(ForeignKey('games.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.boards.adapters.orm.BoardTemplateORM.icon¶
icon: Mapped[str | None] = mapped_column(String, nullable=True)
# leadr.boards.adapters.orm.BoardTemplateORM.id¶
id: Mapped[uuid_pk]
# leadr.boards.adapters.orm.BoardTemplateORM.is_active¶
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.is_published¶
is_published: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, server_default=(sa.text('true')))
# leadr.boards.adapters.orm.BoardTemplateORM.keep_strategy¶
keep_strategy: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.name¶
name: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.name_template¶
name_template: Mapped[str | None] = mapped_column(String, nullable=True, default=None)
# leadr.boards.adapters.orm.BoardTemplateORM.next_run_at¶
next_run_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.repeat_interval¶
repeat_interval: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.series¶
series: Mapped[str | None] = mapped_column(String, nullable=True, default=None)
# leadr.boards.adapters.orm.BoardTemplateORM.slug¶
slug: Mapped[str | None] = mapped_column(String, nullable=True, default=None)
# leadr.boards.adapters.orm.BoardTemplateORM.sort_direction¶
sort_direction: Mapped[str] = mapped_column(String, nullable=False)
# leadr.boards.adapters.orm.BoardTemplateORM.starts_at¶
starts_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, default=None)
# leadr.boards.adapters.orm.BoardTemplateORM.tags¶
tags: Mapped[list[str]] = mapped_column(ARRAY(String), nullable=False, default=list, server_default='{}')
# leadr.boards.adapters.orm.BoardTemplateORM.to_domain¶
to_domain()
Convert ORM model to domain entity.
Returns:
BoardTemplate– BoardTemplate domain entity with all fields populated from ORM model.
# leadr.boards.adapters.orm.BoardTemplateORM.unit¶
unit: Mapped[str | None] = mapped_column(String, nullable=True)
# leadr.boards.adapters.orm.BoardTemplateORM.updated_at¶
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.boards.api¶
Modules:
- board_routes – Board API routes.
- board_schemas – API request and response models for boards.
- board_template_routes – Board template API routes.
- board_template_schemas – API request and response models for board templates.
leadr.boards.api.board_routes¶
Board API routes.
Functions:
- create_board – Create a new board.
- get_board – Get a board by ID.
- handle_list_boards – Shared handler for listing boards with filtering.
- list_boards_admin – List boards (Admin API).
- list_boards_client – List boards (Client API).
- update_board – Update a board.
Attributes:
- client_router –
- logger –
- router –
leadr.boards.api.board_routes.client_router¶
client_router = APIRouter()
leadr.boards.api.board_routes.create_board¶
create_board(request, service, auth)
Create a new board.
Creates a new leaderboard associated with an existing game and account. The game must belong to the specified account.
For regular users, account_id must match their API key's account. For superadmins, any account_id is accepted.
Parameters:
- request (
BoardCreateRequest) – Board creation details including account_id, game_id, name, and settings. - service (
BoardServiceDep) – Injected board service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardResponse– BoardResponse with the created board including auto-generated ID and timestamps.
Raises:
403– User does not have access to the specified account.404– Game or account not found.400– Game doesn't belong to the specified account.
leadr.boards.api.board_routes.get_board¶
get_board(board_id, service, auth)
Get a board by ID.
Parameters:
- board_id (
BoardID) – Unique identifier for the board. - service (
BoardServiceDep) – Injected board service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardResponse– BoardResponse with full board details.
Raises:
403– User does not have access to this board's account.404– Board not found.
leadr.boards.api.board_routes.handle_list_boards¶
handle_list_boards(auth, service, game_service, pagination, account_id, game_id, code, game_slug, slug, is_active, is_published, starts_before, starts_after, ends_before, ends_after)
Shared handler for listing boards with filtering.
Parameters:
- auth (
AuthContext) – Authentication context with user info. - service (
BoardService) – Board service instance. - game_service (
GameService) – Game service instance for game_slug resolution. - pagination (
PaginationParams) – Pagination parameters (cursor, limit, sort). - account_id (
AccountID | None) – Optional account ID to filter boards by. - game_id (
GameID | None) – Optional game ID to filter boards by. - code (
str | None) – Optional short code to filter boards by. - game_slug (
str | None) – Optional game slug to filter boards by game (resolves to game_id). - slug (
str | None) – Optional board slug to filter by specific board (requires game_slug). - is_active (
bool | None) – Optional filter for active status. - is_published (
bool | None) – Optional filter for published status. - starts_before (
datetime | None) – Optional filter for boards starting before this time. - starts_after (
datetime | None) – Optional filter for boards starting after this time. - ends_before (
datetime | None) – Optional filter for boards ending before this time. - ends_after (
datetime | None) – Optional filter for boards ending after this time.
Returns:
PaginatedResponse[BoardResponse]– PaginatedResponse with boards and pagination metadata.
Raises:
400– Invalid cursor, sort field, or cursor state mismatch.404– Game or board not found when using slug filters.
leadr.boards.api.board_routes.list_boards_admin¶
list_boards_admin(auth, service, game_service, pagination, account_id=None, game_id=None, code=None, game_slug=None, slug=None, is_active=None, is_published=None, starts_before=None, starts_after=None, ends_before=None, ends_after=None)
List boards (Admin API).
For regular users:
- If account_id not provided, defaults to their API key's account
- If account_id provided and they are superadmin, can access any account
- If account_id provided and NOT superadmin, must match their account (validated in AuthContext)
Filtering:
- Use ?game_id={id} or ?game_slug={slug} to filter boards by game
- Use ?game_slug={game_slug}&slug={slug} to find a specific board within a game
- Use ?code={code} to filter boards by short code
- Use ?is_active=true/false to filter by active status
- Use ?is_published=true/false to filter by published status
- Use ?starts_before=
&starts_after= for start date range - Use ?ends_before=
&ends_after= for end date range - Note: board slug filter requires game_slug parameter
Pagination:
- Default: 20 items per page, sorted by created_at:desc,id:asc
- Custom sort: Use ?sort=name:asc,created_at:desc
- Valid sort fields: id, name, slug, short_code, created_at, updated_at
- Navigation: Use next_cursor/prev_cursor from response
Example
GET /v1/boards?account_id=acc_123&limit=50&sort=name:asc GET /v1/boards?game_slug=my-game&is_active=true GET /v1/boards?game_slug=my-game&slug=weekly-challenge GET /v1/boards?starts_after=2025-01-01T00:00:00Z&ends_before=2025-12-31T23:59:59ZParameters:
- auth (
AdminAuthContextDep) – Admin authentication context with user info. - service (
BoardServiceDep) – Injected board service dependency. - game_service (
GameServiceDep) – Injected game service dependency. - pagination (
Annotated[PaginationParams, Depends()]) – Pagination parameters (cursor, limit, sort). - account_id (
Annotated[AccountID | None, Query(description='Filter by account ID')]) – Optional account ID to filter boards by. - game_id (
Annotated[GameID | None, Query(description='Filter by game ID')]) – Optional game ID to filter boards by. - code (
Annotated[str | None, Query(description='Filter by short code')]) – Optional short code to filter boards by. - game_slug (
Annotated[str | None, Query(description='Filter by game slug')]) – Optional game slug to filter boards by game (resolves to game_id). - slug (
Annotated[str | None, Query(description='Filter by board slug (requires game_slug)')]) – Optional board slug to filter by specific board (requires game_slug). - is_active (
Annotated[bool | None, Query(description='Filter by active status')]) – Optional filter for active status. - is_published (
Annotated[bool | None, Query(description='Filter by published status')]) – Optional filter for published status. - starts_before (
Annotated[datetime | None, Query(description='Filter boards starting before this time (ISO 8601)')]) – Optional filter for boards starting before this time. - starts_after (
Annotated[datetime | None, Query(description='Filter boards starting after this time (ISO 8601)')]) – Optional filter for boards starting after this time. - ends_before (
Annotated[datetime | None, Query(description='Filter boards ending before this time (ISO 8601)')]) – Optional filter for boards ending before this time. - ends_after (
Annotated[datetime | None, Query(description='Filter boards ending after this time (ISO 8601)')]) – Optional filter for boards ending after this time.
Returns:
PaginatedResponse[BoardResponse]– PaginatedResponse with boards and pagination metadata.
Raises:
400– Invalid cursor, sort field, cursor state mismatch, or slug without game_slug.404– Game or board not found when using slug filters.
leadr.boards.api.board_routes.list_boards_client¶
list_boards_client(auth, service, game_service, pagination, game_id=None, code=None, game_slug=None, slug=None, is_active=None, is_published=None, starts_before=None, starts_after=None, ends_before=None, ends_after=None)
List boards (Client API).
Account ID is automatically derived from the authenticated device's account. Clients can optionally filter by various criteria to find specific boards.
Filtering:
- Use ?game_id={id} or ?game_slug={slug} to filter boards by game
- Use ?game_slug={game_slug}&slug={slug} to find a specific board within a game
- Use ?code={code} to filter boards by short code
- Use ?is_active=true/false to filter by active status
- Use ?is_published=true/false to filter by published status
- Use ?starts_before=
&starts_after= for start date range - Use ?ends_before=
&ends_after= for end date range - Note: board slug filter requires game_slug parameter
Pagination:
- Default: 20 items per page, sorted by created_at:desc,id:asc
- Custom sort: Use ?sort=name:asc,created_at:desc
- Valid sort fields: id, name, slug, short_code, created_at, updated_at
- Navigation: Use next_cursor/prev_cursor from response
Example
GET /v1/client/boards?code=WEEKLY-CHALLENGE&limit=50 GET /v1/client/boards?game_slug=my-game&is_active=true GET /v1/client/boards?game_slug=my-game&slug=weekly-challenge GET /v1/client/boards?starts_after=2025-01-01T00:00:00ZParameters:
- auth (
ClientAuthContextDep) – Client authentication context with device info. - service (
BoardServiceDep) – Injected board service dependency. - game_service (
GameServiceDep) – Injected game service dependency. - pagination (
Annotated[PaginationParams, Depends()]) – Pagination parameters (cursor, limit, sort). - game_id (
Annotated[GameID | None, Query(description='Filter by game ID')]) – Optional game ID to filter boards by. - code (
Annotated[str | None, Query(description='Filter by short code')]) – Optional short code to filter boards by. - game_slug (
Annotated[str | None, Query(description='Filter by game slug')]) – Optional game slug to filter boards by game (resolves to game_id). - slug (
Annotated[str | None, Query(description='Filter by board slug (requires game_slug)')]) – Optional board slug to filter by specific board (requires game_slug). - is_active (
Annotated[bool | None, Query(description='Filter by active status')]) – Optional filter for active status. - is_published (
Annotated[bool | None, Query(description='Filter by published status')]) – Optional filter for published status. - starts_before (
Annotated[datetime | None, Query(description='Filter boards starting before this time (ISO 8601)')]) – Optional filter for boards starting before this time. - starts_after (
Annotated[datetime | None, Query(description='Filter boards starting after this time (ISO 8601)')]) – Optional filter for boards starting after this time. - ends_before (
Annotated[datetime | None, Query(description='Filter boards ending before this time (ISO 8601)')]) – Optional filter for boards ending before this time. - ends_after (
Annotated[datetime | None, Query(description='Filter boards ending after this time (ISO 8601)')]) – Optional filter for boards ending after this time.
Returns:
PaginatedResponse[BoardResponse]– PaginatedResponse with boards and pagination metadata.
Raises:
400– Invalid cursor, sort field, cursor state mismatch, or slug without game_slug.404– Game or board not found when using slug filters.
leadr.boards.api.board_routes.logger¶
logger = logging.getLogger(__name__)
leadr.boards.api.board_routes.router¶
router = APIRouter()
leadr.boards.api.board_routes.update_board¶
update_board(board_id, request, service, auth)
Update a board.
Supports updating any board field or soft-deleting the board.
Parameters:
- board_id (
BoardID) – Unique identifier for the board. - request (
BoardUpdateRequest) – Board update details (all fields optional). - service (
BoardServiceDep) – Injected board service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardResponse– BoardResponse with the updated board details.
Raises:
403– User does not have access to this board's account.404– Board not found.
leadr.boards.api.board_schemas¶
API request and response models for boards.
Classes:
- BoardCreateRequest – Request model for creating a board.
- BoardResponse – Response model for a board.
- BoardUpdateRequest – Request model for updating a board.
leadr.boards.api.board_schemas.BoardCreateRequest¶
Bases: BaseModel
Request model for creating a board.
Attributes:
- account_id (
AccountID) – - created_from_template_id (
BoardTemplateID | None) – - description (
str | None) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - is_active (
bool) – - is_published (
bool) – - keep_strategy (
KeepStrategy) – - name (
str) – - short_code (
str | None) – - slug (
str | None) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str] | None) – - template_name (
str | None) – - unit (
str | None) –
# leadr.boards.api.board_schemas.BoardCreateRequest.account_id¶
account_id: AccountID = Field(description='ID of the account this board belongs to')
# leadr.boards.api.board_schemas.BoardCreateRequest.created_from_template_id¶
created_from_template_id: BoardTemplateID | None = Field(default=None, description='Optional template ID this board was created from')
# leadr.boards.api.board_schemas.BoardCreateRequest.description¶
description: str | None = Field(default=None, description='Optional short description of the board')
# leadr.boards.api.board_schemas.BoardCreateRequest.ends_at¶
ends_at: datetime | None = Field(default=None, description='Optional end time for time-bounded boards (UTC)')
# leadr.boards.api.board_schemas.BoardCreateRequest.game_id¶
game_id: GameID = Field(description='ID of the game this board belongs to')
# leadr.boards.api.board_schemas.BoardCreateRequest.icon¶
icon: str | None = Field(default='fa-crown', description="Icon identifier for the board. Defaults to 'fa-crown'")
# leadr.boards.api.board_schemas.BoardCreateRequest.is_active¶
is_active: bool = Field(default=True, description='Whether the board is currently active')
# leadr.boards.api.board_schemas.BoardCreateRequest.is_published¶
is_published: bool = Field(default=True, description='Whether the board is published and visible on public web views')
# leadr.boards.api.board_schemas.BoardCreateRequest.keep_strategy¶
keep_strategy: KeepStrategy = Field(default=(KeepStrategy.ALL), description='Strategy for keeping multiple scores from the same user')
# leadr.boards.api.board_schemas.BoardCreateRequest.name¶
name: str = Field(description='Name of the board')
# leadr.boards.api.board_schemas.BoardCreateRequest.short_code¶
short_code: str | None = Field(default=None, description='Globally unique short code for direct sharing. Auto-generated if not provided')
# leadr.boards.api.board_schemas.BoardCreateRequest.slug¶
slug: str | None = Field(default=None, description='Optional URL-friendly slug. If not provided, will be auto-generated from name')
# leadr.boards.api.board_schemas.BoardCreateRequest.sort_direction¶
sort_direction: SortDirection = Field(default=(SortDirection.DESCENDING), description='Direction to sort scores')
# leadr.boards.api.board_schemas.BoardCreateRequest.starts_at¶
starts_at: datetime | None = Field(default=None, description='Optional start time for time-bounded boards (UTC)')
# leadr.boards.api.board_schemas.BoardCreateRequest.tags¶
tags: list[str] | None = Field(default=None, description='Optional list of tags for categorization')
# leadr.boards.api.board_schemas.BoardCreateRequest.template_name¶
template_name: str | None = Field(default=None, description='Optional template name this board was created from')
# leadr.boards.api.board_schemas.BoardCreateRequest.unit¶
unit: str | None = Field(default=None, description="Unit of measurement for scores (e.g., 'seconds', 'points'). Optional")
leadr.boards.api.board_schemas.BoardResponse¶
Bases: BaseModel
Response model for a board.
Functions:
- from_domain – Convert domain entity to response model.
Attributes:
- account_id (
AccountID) – - created_at (
datetime) – - created_from_template_id (
BoardTemplateID | None) – - description (
str | None) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - id (
BoardID) – - is_active (
bool) – - is_published (
bool) – - keep_strategy (
KeepStrategy) – - name (
str) – - short_code (
str) – - slug (
str) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str]) – - template_name (
str | None) – - unit (
str | None) – - updated_at (
datetime) –
# leadr.boards.api.board_schemas.BoardResponse.account_id¶
account_id: AccountID = Field(description='ID of the account this board belongs to')
# leadr.boards.api.board_schemas.BoardResponse.created_at¶
created_at: datetime = Field(description='Timestamp when the board was created (UTC)')
# leadr.boards.api.board_schemas.BoardResponse.created_from_template_id¶
created_from_template_id: BoardTemplateID | None = Field(default=None, description='Template ID this board was created from, or null')
# leadr.boards.api.board_schemas.BoardResponse.description¶
description: str | None = Field(default=None, description='Short description of the board')
# leadr.boards.api.board_schemas.BoardResponse.ends_at¶
ends_at: datetime | None = Field(default=None, description='End time for time-bounded boards (UTC)')
# leadr.boards.api.board_schemas.BoardResponse.from_domain¶
from_domain(board)
Convert domain entity to response model.
Parameters:
- board (
Board) – The domain Board entity to convert.
Returns:
BoardResponse– BoardResponse with all fields populated from the domain entity.
# leadr.boards.api.board_schemas.BoardResponse.game_id¶
game_id: GameID = Field(description='ID of the game this board belongs to')
# leadr.boards.api.board_schemas.BoardResponse.icon¶
icon: str | None = Field(description='Icon identifier for the board, or null')
# leadr.boards.api.board_schemas.BoardResponse.id¶
id: BoardID = Field(description='Unique identifier for the board')
# leadr.boards.api.board_schemas.BoardResponse.is_active¶
is_active: bool = Field(description='Whether the board is currently active')
# leadr.boards.api.board_schemas.BoardResponse.is_published¶
is_published: bool = Field(description='Whether the board is published and visible on public web views')
# leadr.boards.api.board_schemas.BoardResponse.keep_strategy¶
keep_strategy: KeepStrategy = Field(description='Strategy for keeping scores from same user')
# leadr.boards.api.board_schemas.BoardResponse.name¶
name: str = Field(description='Name of the board')
# leadr.boards.api.board_schemas.BoardResponse.short_code¶
short_code: str = Field(description='Globally unique short code for direct sharing')
# leadr.boards.api.board_schemas.BoardResponse.slug¶
slug: str = Field(description='URL-friendly slug for the board (auto-generated, read-only)')
# leadr.boards.api.board_schemas.BoardResponse.sort_direction¶
sort_direction: SortDirection = Field(description='Direction to sort scores')
# leadr.boards.api.board_schemas.BoardResponse.starts_at¶
starts_at: datetime | None = Field(default=None, description='Start time for time-bounded boards (UTC)')
# leadr.boards.api.board_schemas.BoardResponse.tags¶
tags: list[str] = Field(default_factory=list, description='List of tags for categorization')
# leadr.boards.api.board_schemas.BoardResponse.template_name¶
template_name: str | None = Field(default=None, description='Template name this board was created from, or null')
# leadr.boards.api.board_schemas.BoardResponse.unit¶
unit: str | None = Field(description='Unit of measurement for scores, or null')
# leadr.boards.api.board_schemas.BoardResponse.updated_at¶
updated_at: datetime = Field(description='Timestamp of last update (UTC)')
leadr.boards.api.board_schemas.BoardUpdateRequest¶
Bases: BaseModel
Request model for updating a board.
Attributes:
- created_from_template_id (
BoardTemplateID | None) – - deleted (
bool | None) – - description (
str | None) – - ends_at (
datetime | None) – - icon (
str | None) – - is_active (
bool | None) – - is_published (
bool | None) – - keep_strategy (
KeepStrategy | None) – - name (
str | None) – - short_code (
str | None) – - sort_direction (
SortDirection | None) – - starts_at (
datetime | None) – - tags (
list[str] | None) – - template_name (
str | None) – - unit (
str | None) –
# leadr.boards.api.board_schemas.BoardUpdateRequest.created_from_template_id¶
created_from_template_id: BoardTemplateID | None = Field(default=None, description='Updated template ID')
# leadr.boards.api.board_schemas.BoardUpdateRequest.deleted¶
deleted: bool | None = Field(default=None, description='Set to true to soft delete the board')
# leadr.boards.api.board_schemas.BoardUpdateRequest.description¶
description: str | None = Field(default=None, description='Updated board description')
# leadr.boards.api.board_schemas.BoardUpdateRequest.ends_at¶
ends_at: datetime | None = Field(default=None, description='Updated end time')
# leadr.boards.api.board_schemas.BoardUpdateRequest.icon¶
icon: str | None = Field(default=None, description='Updated icon identifier')
# leadr.boards.api.board_schemas.BoardUpdateRequest.is_active¶
is_active: bool | None = Field(default=None, description='Updated active status')
# leadr.boards.api.board_schemas.BoardUpdateRequest.is_published¶
is_published: bool | None = Field(default=None, description='Updated published status')
# leadr.boards.api.board_schemas.BoardUpdateRequest.keep_strategy¶
keep_strategy: KeepStrategy | None = Field(default=None, description='Updated keep strategy')
# leadr.boards.api.board_schemas.BoardUpdateRequest.name¶
name: str | None = Field(default=None, description='Updated board name')
# leadr.boards.api.board_schemas.BoardUpdateRequest.short_code¶
short_code: str | None = Field(default=None, description='Updated short code')
# leadr.boards.api.board_schemas.BoardUpdateRequest.sort_direction¶
sort_direction: SortDirection | None = Field(default=None, description='Updated sort direction')
# leadr.boards.api.board_schemas.BoardUpdateRequest.starts_at¶
starts_at: datetime | None = Field(default=None, description='Updated start time')
# leadr.boards.api.board_schemas.BoardUpdateRequest.tags¶
tags: list[str] | None = Field(default=None, description='Updated tags list')
# leadr.boards.api.board_schemas.BoardUpdateRequest.template_name¶
template_name: str | None = Field(default=None, description='Updated template name')
# leadr.boards.api.board_schemas.BoardUpdateRequest.unit¶
unit: str | None = Field(default=None, description='Updated unit of measurement')
leadr.boards.api.board_template_routes¶
Board template API routes.
Functions:
- create_board_template – Create a new board template.
- get_board_template – Get a board template by ID.
- list_board_templates – List board templates for an account with pagination, optionally filtered by game.
- update_board_template – Update a board template.
Attributes:
- router –
leadr.boards.api.board_template_routes.create_board_template¶
create_board_template(request, service, auth)
Create a new board template.
Creates a template for automatically generating boards at regular intervals. The game must belong to the specified account.
For regular users, account_id must match their API key's account. For superadmins, any account_id is accepted.
Parameters:
- request (
BoardTemplateCreateRequest) – Template creation details including repeat_interval and configuration. - service (
BoardTemplateServiceDep) – Injected board template service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardTemplateResponse– BoardTemplateResponse with the created template including auto-generated ID.
Raises:
403– User does not have access to the specified account.404– Game or account not found.400– Game doesn't belong to the specified account.
leadr.boards.api.board_template_routes.get_board_template¶
get_board_template(template_id, service, auth)
Get a board template by ID.
Parameters:
- template_id (
BoardTemplateID) – Unique identifier for the template. - service (
BoardTemplateServiceDep) – Injected board template service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardTemplateResponse– BoardTemplateResponse with full template details.
Raises:
403– User does not have access to this template's account.404– Template not found.
leadr.boards.api.board_template_routes.list_board_templates¶
list_board_templates(auth, service, pagination, account_id=None, game_id=None)
List board templates for an account with pagination, optionally filtered by game.
For regular users, account_id is automatically derived from their API key. For superadmins, account_id is optional - if omitted, returns templates from all accounts.
Pagination:
- Default: 20 items per page, sorted by created_at:desc,id:asc
- Custom sort: Use ?sort=name:asc,created_at:desc
- Valid sort fields: id, name, created_at, updated_at
- Navigation: Use next_cursor/prev_cursor from response
Example
GET /v1/board-templates?account_id=acc_123&game_id=gam_456&limit=50&sort=name:ascParameters:
- auth (
AdminAuthContextDep) – Authentication context with user info. - service (
BoardTemplateServiceDep) – Injected board template service dependency. - pagination (
Annotated[PaginationParams, Depends()]) – Pagination parameters (cursor, limit, sort). - account_id (
Annotated[AccountID | None, Query(description='Account ID filter')]) – Optional account_id query parameter (superadmins can omit to see all). - game_id (
Annotated[GameID | None, Query(description='Filter by game ID')]) – Optional game ID to filter templates by.
Returns:
PaginatedResponse[BoardTemplateResponse]– PaginatedResponse with board templates and pagination metadata.
Raises:
400– Invalid cursor, sort field, or cursor state mismatch.403– User does not have access to the specified account.
leadr.boards.api.board_template_routes.router¶
router = APIRouter()
leadr.boards.api.board_template_routes.update_board_template¶
update_board_template(template_id, request, service, auth)
Update a board template.
Supports updating any template field or soft-deleting the template.
Parameters:
- template_id (
BoardTemplateID) – Unique identifier for the template. - request (
BoardTemplateUpdateRequest) – Template update details (all fields optional). - service (
BoardTemplateServiceDep) – Injected board template service dependency. - auth (
AdminAuthContextDep) – Authentication context with user info.
Returns:
BoardTemplateResponse– BoardTemplateResponse with the updated template details.
Raises:
403– User does not have access to this template's account.404– Template not found.
leadr.boards.api.board_template_schemas¶
API request and response models for board templates.
Classes:
- BoardTemplateCreateRequest – Request model for creating a board template.
- BoardTemplateResponse – Response model for a board template.
- BoardTemplateUpdateRequest – Request model for updating a board template.
leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest¶
Bases: BaseModel
Request model for creating a board template.
Attributes:
- account_id (
AccountID) – - config (
dict[str, Any] | None) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - is_active (
bool) – - is_published (
bool) – - keep_strategy (
KeepStrategy) – - name (
str) – - name_template (
str | None) – - next_run_at (
datetime) – - repeat_interval (
str) – - series (
str | None) – - slug (
str | None) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str] | None) – - unit (
str | None) –
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.account_id¶
account_id: AccountID = Field(description='ID of the account this template belongs to')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.config¶
config: dict[str, Any] | None = Field(default=None, description='Reserved for future procedural generation (bounds, variables, randomization rules)')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.ends_at¶
ends_at: datetime | None = Field(default=None, description='Optional end time for time-bounded boards')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.game_id¶
game_id: GameID = Field(description='ID of the game this template belongs to')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.icon¶
icon: str | None = Field(default='fa-crown', description='Icon identifier for boards created from this template')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.is_active¶
is_active: bool = Field(description='Whether the template is currently active')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.is_published¶
is_published: bool = Field(default=True, description='Whether boards created from this template should be published')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.keep_strategy¶
keep_strategy: KeepStrategy = Field(default=(KeepStrategy.ALL), description='Strategy for keeping multiple scores from the same user')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.name¶
name: str = Field(description='Name of the template')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.name_template¶
name_template: str | None = Field(default=None, description='Optional template string for generating board names')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.next_run_at¶
next_run_at: datetime = Field(description='Next scheduled time to create a board from this template (UTC)')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.repeat_interval¶
repeat_interval: str = Field(description="PostgreSQL interval syntax for repeat frequency (e.g., '7 days', '1 month')")
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.series¶
series: str | None = Field(default=None, description='Optional series identifier for sequential board naming')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.slug¶
slug: str | None = Field(default=None, description='URL-friendly slug for boards created from this template')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.sort_direction¶
sort_direction: SortDirection = Field(default=(SortDirection.DESCENDING), description='Direction to sort scores (ascending/descending)')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.starts_at¶
starts_at: datetime | None = Field(default=None, description='Optional start time for time-bounded boards')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.tags¶
tags: list[str] | None = Field(default=None, description='List of tags for categorizing boards created from this template')
# leadr.boards.api.board_template_schemas.BoardTemplateCreateRequest.unit¶
unit: str | None = Field(default=None, description="Unit of measurement for scores (e.g., 'seconds', 'points')")
leadr.boards.api.board_template_schemas.BoardTemplateResponse¶
Bases: BaseModel
Response model for a board template.
Functions:
- from_domain – Convert domain entity to response model.
Attributes:
- account_id (
AccountID) – - config (
dict[str, Any]) – - created_at (
datetime) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - id (
BoardTemplateID) – - is_active (
bool) – - is_published (
bool) – - keep_strategy (
KeepStrategy) – - name (
str) – - name_template (
str | None) – - next_run_at (
datetime) – - repeat_interval (
str) – - series (
str | None) – - slug (
str | None) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str]) – - unit (
str | None) – - updated_at (
datetime) –
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.account_id¶
account_id: AccountID = Field(description='ID of the account this template belongs to')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.config¶
config: dict[str, Any] = Field(default_factory=dict, description='Reserved for future procedural generation (bounds, variables, randomization rules)')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.created_at¶
created_at: datetime = Field(description='Timestamp when the template was created (UTC)')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.ends_at¶
ends_at: datetime | None = Field(description='Optional end time for time-bounded boards')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.from_domain¶
from_domain(template)
Convert domain entity to response model.
Parameters:
- template (
BoardTemplate) – The domain BoardTemplate entity to convert.
Returns:
BoardTemplateResponse– BoardTemplateResponse with all fields populated from the domain entity.
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.game_id¶
game_id: GameID = Field(description='ID of the game this template belongs to')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.icon¶
icon: str | None = Field(description='Icon identifier for boards created from this template')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.id¶
id: BoardTemplateID = Field(description='Unique identifier for the template')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.is_active¶
is_active: bool = Field(description='Whether the template is currently active')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.is_published¶
is_published: bool = Field(description='Whether boards created from this template should be published')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.keep_strategy¶
keep_strategy: KeepStrategy = Field(description='Strategy for keeping multiple scores from the same user')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.name¶
name: str = Field(description='Name of the template')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.name_template¶
name_template: str | None = Field(default=None, description='Template string for generating board names, or null')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.next_run_at¶
next_run_at: datetime = Field(description='Next scheduled run time (UTC)')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.repeat_interval¶
repeat_interval: str = Field(description='Repeat frequency in PostgreSQL interval syntax')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.series¶
series: str | None = Field(default=None, description='Series identifier for sequential board naming, or null')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.slug¶
slug: str | None = Field(description='URL-friendly slug for boards created from this template, or null')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.sort_direction¶
sort_direction: SortDirection = Field(description='Direction to sort scores (ascending/descending)')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.starts_at¶
starts_at: datetime | None = Field(description='Optional start time for time-bounded boards')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.tags¶
tags: list[str] = Field(description='List of tags for categorizing boards created from this template')
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.unit¶
unit: str | None = Field(description="Unit of measurement for scores (e.g., 'seconds', 'points')")
# leadr.boards.api.board_template_schemas.BoardTemplateResponse.updated_at¶
updated_at: datetime = Field(description='Timestamp of last update (UTC)')
leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest¶
Bases: BaseModel
Request model for updating a board template.
Attributes:
- config (
dict[str, Any] | None) – - deleted (
bool | None) – - ends_at (
datetime | None) – - icon (
str | None) – - is_active (
bool | None) – - is_published (
bool | None) – - keep_strategy (
KeepStrategy | None) – - name (
str | None) – - name_template (
str | None) – - next_run_at (
datetime | None) – - repeat_interval (
str | None) – - series (
str | None) – - slug (
str | None) – - sort_direction (
SortDirection | None) – - starts_at (
datetime | None) – - tags (
list[str] | None) – - unit (
str | None) –
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.config¶
config: dict[str, Any] | None = Field(default=None, description='Updated config (reserved for procedural generation)')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.deleted¶
deleted: bool | None = Field(default=None, description='Set to true to soft delete the template')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.ends_at¶
ends_at: datetime | None = Field(default=None, description='Updated end time')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.icon¶
icon: str | None = Field(default=None, description='Updated icon identifier')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.is_active¶
is_active: bool | None = Field(default=None, description='Updated active status')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.is_published¶
is_published: bool | None = Field(default=None, description='Updated published status')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.keep_strategy¶
keep_strategy: KeepStrategy | None = Field(default=None, description='Updated keep strategy')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.name¶
name: str | None = Field(default=None, description='Updated template name')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.name_template¶
name_template: str | None = Field(default=None, description='Updated name template')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.next_run_at¶
next_run_at: datetime | None = Field(default=None, description='Updated next run time')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.repeat_interval¶
repeat_interval: str | None = Field(default=None, description='Updated repeat interval')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.series¶
series: str | None = Field(default=None, description='Updated series identifier')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.slug¶
slug: str | None = Field(default=None, description='Updated slug')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.sort_direction¶
sort_direction: SortDirection | None = Field(default=None, description='Updated sort direction')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.starts_at¶
starts_at: datetime | None = Field(default=None, description='Updated start time')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.tags¶
tags: list[str] | None = Field(default=None, description='Updated tags list')
# leadr.boards.api.board_template_schemas.BoardTemplateUpdateRequest.unit¶
unit: str | None = Field(default=None, description='Updated unit of measurement')
leadr.boards.domain¶
Modules:
- board – Board domain model.
- board_template – BoardTemplate domain model.
- interval_parser – Utilities for parsing PostgreSQL interval syntax.
leadr.boards.domain.board¶
Board domain model.
Classes:
- Board – Board domain entity.
- KeepStrategy – Strategy for keeping scores from the same user.
- SortDirection – Sort direction for board scores.
leadr.boards.domain.board.Board¶
Bases: Entity
Board domain entity.
Represents a leaderboard/board that belongs to a game. Boards define how scores are tracked, sorted, and displayed. Each board has a globally unique short_code for direct sharing and can be time-bounded with start/end dates.
Each board belongs to exactly one game and inherits the game's account for multi-tenancy. Boards can be created from templates and can have custom tags for categorization.
Functions:
- restore – Restore a soft-deleted entity.
- soft_delete – Mark entity as soft-deleted.
- validate_name – Validate board name is not empty.
- validate_short_code – Validate short_code is not empty.
- validate_slug – Validate slug format (lowercase alphanumeric with hyphens).
Attributes:
- account_id (
AccountID) – - created_at (
datetime) – - created_from_template_id (
BoardTemplateID | None) – - deleted_at (
datetime | None) – - description (
str | None) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - id (
BoardID) – - is_active (
bool) – - is_deleted (
bool) – Check if entity is soft-deleted. - is_published (
bool) – - keep_strategy (
KeepStrategy) – - model_config –
- name (
str) – - short_code (
str) – - slug (
str) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str]) – - template_name (
str | None) – - unit (
str | None) – - updated_at (
datetime) –
# leadr.boards.domain.board.Board.account_id¶
account_id: AccountID = Field(frozen=True, description='ID of the account this board belongs to (immutable)')
# leadr.boards.domain.board.Board.created_at¶
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.boards.domain.board.Board.created_from_template_id¶
created_from_template_id: BoardTemplateID | None = Field(default=None, description='Optional template ID this board was created from')
# leadr.boards.domain.board.Board.deleted_at¶
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.boards.domain.board.Board.description¶
description: str | None = Field(default=None, description='Short description of the board')
# leadr.boards.domain.board.Board.ends_at¶
ends_at: datetime | None = Field(default=None, description='Optional end time for time-bounded boards')
# leadr.boards.domain.board.Board.game_id¶
game_id: GameID = Field(frozen=True, description='ID of the game this board belongs to (immutable)')
# leadr.boards.domain.board.Board.icon¶
icon: str | None = Field(description='Icon identifier for the board', default='fa-crown')
# leadr.boards.domain.board.Board.id¶
id: BoardID = Field(frozen=True, default_factory=BoardID, description='Unique board identifier')
# leadr.boards.domain.board.Board.is_active¶
is_active: bool = Field(description='Whether the board is currently active', default=True)
# leadr.boards.domain.board.Board.is_deleted¶
is_deleted: bool
Check if entity is soft-deleted.
Returns:
bool– True if the entity has a deleted_at timestamp, False otherwise.
# leadr.boards.domain.board.Board.is_published¶
is_published: bool = Field(description='Whether the board is published and visible on public web views', default=True)
# leadr.boards.domain.board.Board.keep_strategy¶
keep_strategy: KeepStrategy = Field(description='Strategy for keeping multiple scores from the same user', default=(KeepStrategy.ALL))
# leadr.boards.domain.board.Board.model_config¶
model_config = ConfigDict(validate_assignment=True)
# leadr.boards.domain.board.Board.name¶
name: str = Field(description='Name of the board')
# leadr.boards.domain.board.Board.restore¶
restore()
Restore a soft-deleted entity.
Clears the deleted_at timestamp, making the entity active again.
Example
> > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False# leadr.boards.domain.board.Board.short_code¶
short_code: str = Field(description='Globally unique short code for direct board sharing')
# leadr.boards.domain.board.Board.slug¶
slug: str = Field(description='URL-friendly slug for the board (unique per game when active)')
# leadr.boards.domain.board.Board.soft_delete¶
soft_delete()
Mark entity as soft-deleted.
Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).
Example
> > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True# leadr.boards.domain.board.Board.sort_direction¶
sort_direction: SortDirection = Field(description='Direction to sort scores (ascending/descending)', default=(SortDirection.DESCENDING))
# leadr.boards.domain.board.Board.starts_at¶
starts_at: datetime | None = Field(default=None, description='Optional start time for time-bounded boards')
# leadr.boards.domain.board.Board.tags¶
tags: list[str] = Field(default_factory=list, description='List of tags for categorizing the board')
# leadr.boards.domain.board.Board.template_name¶
template_name: str | None = Field(default=None, description='Optional name of the template this board was created from')
# leadr.boards.domain.board.Board.unit¶
unit: str | None = Field(description="Unit of measurement for scores (e.g., 'seconds', 'points')", default=None)
# leadr.boards.domain.board.Board.updated_at¶
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.boards.domain.board.Board.validate_name¶
validate_name(value)
Validate board name is not empty.
Parameters:
- value (
str) – The board name to validate.
Returns:
str– The validated and trimmed board name.
Raises:
ValueError– If board name is empty or whitespace only.
# leadr.boards.domain.board.Board.validate_short_code¶
validate_short_code(value)
Validate short_code is not empty.
Parameters:
- value (
str) – The short_code to validate.
Returns:
str– The validated and trimmed short_code.
Raises:
ValueError– If short_code is empty or whitespace only.
# leadr.boards.domain.board.Board.validate_slug¶
validate_slug(value)
Validate slug format (lowercase alphanumeric with hyphens).
Parameters:
- value (
str) – The slug to validate.
Returns:
str– The validated slug.
Raises:
ValueError– If slug is invalid.
leadr.boards.domain.board.KeepStrategy¶
Strategy for keeping scores from the same user.
Attributes:
- ALL –
- BEST_ONLY –
- FIRST_ONLY –
- LATEST_ONLY –
# leadr.boards.domain.board.KeepStrategy.ALL¶
ALL = 'ALL'
# leadr.boards.domain.board.KeepStrategy.BEST_ONLY¶
BEST_ONLY = 'BEST_ONLY'
# leadr.boards.domain.board.KeepStrategy.FIRST_ONLY¶
FIRST_ONLY = 'FIRST_ONLY'
# leadr.boards.domain.board.KeepStrategy.LATEST_ONLY¶
LATEST_ONLY = 'LATEST_ONLY'
leadr.boards.domain.board.SortDirection¶
Sort direction for board scores.
Attributes:
- ASCENDING –
- DESCENDING –
# leadr.boards.domain.board.SortDirection.ASCENDING¶
ASCENDING = 'ASCENDING'
# leadr.boards.domain.board.SortDirection.DESCENDING¶
DESCENDING = 'DESCENDING'
leadr.boards.domain.board_template¶
BoardTemplate domain model.
Classes:
- BoardTemplate – BoardTemplate domain entity.
leadr.boards.domain.board_template.BoardTemplate¶
Bases: Entity
BoardTemplate domain entity.
Represents a template for automatically generating boards at regular intervals. Templates belong to a game and define the configuration for boards that will be created by the pg_cron scheduler.
Each template specifies a repeat interval (PostgreSQL interval syntax), configuration for boards to be created, and can optionally use template variables in the name generation. Templates can be activated/deactivated and track the next scheduled run.
Functions:
- generate_name – Generate a board name using the name template.
- restore – Restore a soft-deleted entity.
- soft_delete – Mark entity as soft-deleted.
- validate_name – Validate template name is not empty.
- validate_repeat_interval – Validate repeat_interval uses PostgreSQL interval syntax.
- validate_slug – Validate slug format (lowercase alphanumeric with hyphens).
Attributes:
- account_id (
AccountID) – - config (
dict[str, Any]) – - created_at (
datetime) – - deleted_at (
datetime | None) – - ends_at (
datetime | None) – - game_id (
GameID) – - icon (
str | None) – - id (
BoardTemplateID) – - is_active (
bool) – - is_deleted (
bool) – Check if entity is soft-deleted. - is_published (
bool) – - keep_strategy (
KeepStrategy) – - model_config –
- name (
str) – - name_template (
str | None) – - next_run_at (
datetime) – - repeat_interval (
str) – - series (
str | None) – - slug (
str | None) – - sort_direction (
SortDirection) – - starts_at (
datetime | None) – - tags (
list[str]) – - unit (
str | None) – - updated_at (
datetime) –
# leadr.boards.domain.board_template.BoardTemplate.account_id¶
account_id: AccountID = Field(frozen=True, description='ID of the account this template belongs to (immutable)')
# leadr.boards.domain.board_template.BoardTemplate.config¶
config: dict[str, Any] = Field(default_factory=dict, description='Reserved for future procedural generation (bounds, variables, randomization rules)')
# leadr.boards.domain.board_template.BoardTemplate.created_at¶
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.boards.domain.board_template.BoardTemplate.deleted_at¶
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.boards.domain.board_template.BoardTemplate.ends_at¶
ends_at: datetime | None = Field(default=None, description='Optional end time for time-bounded boards')
# leadr.boards.domain.board_template.BoardTemplate.game_id¶
game_id: GameID = Field(frozen=True, description='ID of the game this template belongs to (immutable)')
# leadr.boards.domain.board_template.BoardTemplate.generate_name¶
generate_name(timestamp, series_value)
Generate a board name using the name template.
If name_template is None, returns the template's name. Otherwise, substitutes placeholders with values derived from the timestamp and series.
Supported placeholders:
- {year}: 4-digit year (e.g., 2025)
- {month}: Full month name (e.g., July)
- {month_short}: Abbreviated month (e.g., Jul)
- {week}: ISO week number (e.g., 29)
- {quarter}: Quarter (e.g., Q1, Q2, Q3, Q4)
- {date}: ISO date (e.g., 2025-07-15)
- {series}: Sequential series value
Parameters:
- timestamp (
datetime) – The datetime to use for generating time-based placeholders. - series_value (
int | None) – Optional series value for {series} placeholder.
Returns:
str– The generated board name.
Raises:
ValueError– If the name_template contains invalid placeholders or if {series} is used but series_value is None.
# leadr.boards.domain.board_template.BoardTemplate.icon¶
icon: str | None = Field(description='Icon identifier for boards created from this template', default='fa-crown')
# leadr.boards.domain.board_template.BoardTemplate.id¶
id: BoardTemplateID = Field(frozen=True, default_factory=BoardTemplateID, description='Unique board template identifier')
# leadr.boards.domain.board_template.BoardTemplate.is_active¶
is_active: bool = Field(description='Whether the template is currently active')
# leadr.boards.domain.board_template.BoardTemplate.is_deleted¶
is_deleted: bool
Check if entity is soft-deleted.
Returns:
bool– True if the entity has a deleted_at timestamp, False otherwise.
# leadr.boards.domain.board_template.BoardTemplate.is_published¶
is_published: bool = Field(description='Whether boards created from this template should be published', default=True)
# leadr.boards.domain.board_template.BoardTemplate.keep_strategy¶
keep_strategy: KeepStrategy = Field(description='Strategy for keeping multiple scores from the same user', default=(KeepStrategy.ALL))
# leadr.boards.domain.board_template.BoardTemplate.model_config¶
model_config = ConfigDict(validate_assignment=True)
# leadr.boards.domain.board_template.BoardTemplate.name¶
name: str = Field(description='Name of the template')
# leadr.boards.domain.board_template.BoardTemplate.name_template¶
name_template: str | None = Field(default=None, description='Optional template string for generating board names')
# leadr.boards.domain.board_template.BoardTemplate.next_run_at¶
next_run_at: datetime = Field(description='Next scheduled time to create a board from this template')
# leadr.boards.domain.board_template.BoardTemplate.repeat_interval¶
repeat_interval: str = Field(description="PostgreSQL interval syntax for repeat frequency (e.g., '7 days', '1 month')")
# leadr.boards.domain.board_template.BoardTemplate.restore¶
restore()
Restore a soft-deleted entity.
Clears the deleted_at timestamp, making the entity active again.
Example
> > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False# leadr.boards.domain.board_template.BoardTemplate.series¶
series: str | None = Field(default=None, description="Optional series identifier for sequential board naming (e.g., 'weekly', 'seasonal')")
# leadr.boards.domain.board_template.BoardTemplate.slug¶
slug: str | None = Field(default=None, description='URL-friendly slug for boards created from this template')
# leadr.boards.domain.board_template.BoardTemplate.soft_delete¶
soft_delete()
Mark entity as soft-deleted.
Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).
Example
> > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True# leadr.boards.domain.board_template.BoardTemplate.sort_direction¶
sort_direction: SortDirection = Field(description='Direction to sort scores (ascending/descending)', default=(SortDirection.DESCENDING))
# leadr.boards.domain.board_template.BoardTemplate.starts_at¶
starts_at: datetime | None = Field(default=None, description='Optional start time for time-bounded boards')
# leadr.boards.domain.board_template.BoardTemplate.tags¶
tags: list[str] = Field(default_factory=list, description='List of tags for categorizing boards created from this template')
# leadr.boards.domain.board_template.BoardTemplate.unit¶
unit: str | None = Field(description="Unit of measurement for scores (e.g., 'seconds', 'points')", default=None)
# leadr.boards.domain.board_template.BoardTemplate.updated_at¶
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.boards.domain.board_template.BoardTemplate.validate_name¶
validate_name(value)
Validate template name is not empty.
Parameters:
- value (
str) – The template name to validate.
Returns:
str– The validated and trimmed template name.
Raises:
ValueError– If template name is empty or whitespace only.
# leadr.boards.domain.board_template.BoardTemplate.validate_repeat_interval¶
validate_repeat_interval(value)
Validate repeat_interval uses PostgreSQL interval syntax.
Parameters:
- value (
str) – The interval string to validate.
Returns:
str– The validated interval string.
Raises:
ValueError– If interval syntax is invalid.
# leadr.boards.domain.board_template.BoardTemplate.validate_slug¶
validate_slug(value)
Validate slug format (lowercase alphanumeric with hyphens).
Parameters:
- value (
str | None) – The slug to validate, or None.
Returns:
str | None– The validated slug, or None if not provided.
Raises:
ValueError– If slug is invalid.
leadr.boards.domain.interval_parser¶
Utilities for parsing PostgreSQL interval syntax.
Functions:
- parse_interval_to_timedelta – Parse PostgreSQL interval syntax to Python timedelta.
leadr.boards.domain.interval_parser.parse_interval_to_timedelta¶
parse_interval_to_timedelta(interval_string)
Parse PostgreSQL interval syntax to Python timedelta.
Supports formats like:
- "7 days"
- "1 week"
- "2 hours"
- "30 minutes"
Parameters:
- interval_string (
str) – PostgreSQL interval syntax string.
Returns:
timedelta– Equivalent Python timedelta.
Raises:
ValueError– If interval format is invalid or unsupported.
Example
> > > parse_interval_to_timedelta("7 days") > > > timedelta(days=7) > > > parse_interval_to_timedelta("1 week") > > > timedelta(weeks=1)leadr.boards.services¶
Modules:
- board_service – Board service for managing board operations.
- board_tasks – Background tasks for board processing.
- board_template_service – BoardTemplate service for managing board template operations.
- dependencies – Board service dependency injection.
- repositories – Board repository services.
- short_code_generator – Utility for generating unique short codes for boards.
leadr.boards.services.board_service¶
Board service for managing board operations.
Classes:
- BoardService – Service for managing board lifecycle and operations.
leadr.boards.services.board_service.BoardService¶
Bases: BaseService[Board, BoardRepository]
Service for managing board lifecycle and operations.
This service orchestrates board creation, updates, and retrieval by coordinating between the domain models and repository layer. Ensures business rules like game validation are enforced.
Functions:
- create_board – Create a new board.
- create_board_from_template – Create a new board from a board template.
- delete – Soft-delete an entity.
- get_board – Get a board by its ID.
- get_board_by_short_code – Get a board by its short_code.
- get_by_id – Get an entity by its ID.
- get_by_id_or_raise – Get an entity by its ID or raise EntityNotFoundError.
- list_all – List all non-deleted entities.
- list_boards – List boards with optional filtering.
- list_boards_by_account – List all boards for an account.
- soft_delete – Soft-delete an entity and return it before deletion.
- update_board – Update board fields.
Attributes:
# leadr.boards.services.board_service.BoardService.create_board¶
create_board(account_id, game_id, name, icon='fa-crown', unit=None, is_active=True, is_published=True, sort_direction=SortDirection.DESCENDING, keep_strategy=KeepStrategy.ALL, slug=None, short_code=None, created_from_template_id=None, template_name=None, starts_at=None, ends_at=None, tags=None, description=None)
Create a new board.
Parameters:
- account_id (
AccountID) – The ID of the account that owns this board. - game_id (
GameID) – The ID of the game this board belongs to. - name (
str) – The board name. - icon (
str | None) – Icon identifier for the board. Defaults to "fa-crown". - unit (
str | None) – Unit of measurement for scores. Defaults to None. - is_active (
bool) – Whether the board is currently active. Defaults to True. - is_published (
bool) – Whether the board is published and visible on public web views. Defaults to True. - sort_direction (
SortDirection) – Direction to sort scores. Defaults to DESCENDING. - keep_strategy (
KeepStrategy) – Strategy for keeping multiple scores from same user. Defaults to ALL. - slug (
str | None) – Optional URL-friendly slug. If not provided, auto-generated from name. - short_code (
str | None) – Globally unique short code for direct sharing. - created_from_template_id (
BoardTemplateID | None) – Optional template ID this board was created from. - template_name (
str | None) – Optional template name. - starts_at (
datetime | None) – Optional start time for time-bounded boards. - ends_at (
datetime | None) – Optional end time for time-bounded boards. - tags (
list[str] | None) – Optional list of tags for categorization. - description (
str | None) – Optional short description of the board.
Returns:
Board– The created Board domain entity.
Raises:
EntityNotFoundError– If the game doesn't exist.ValueError– If the game doesn't belong to the specified account or slug is invalid.
Example
> > > board = await service.create_board( > > > ... account_id=account.id, > > > ... game_id=game.id, > > > ... name="Speed Run Board", > > > ... icon="trophy", > > > ... unit="seconds", > > > ... is_active=True, > > > ... sort_direction=SortDirection.ASCENDING, > > > ... keep_strategy=KeepStrategy.BEST_ONLY, > > > ... )# leadr.boards.services.board_service.BoardService.create_board_from_template¶
create_board_from_template(template)
Create a new board from a board template.
Extracts configuration from the template and calculates time boundaries based on the template's repeat_interval. Automatically generates a unique short code for the board. If the template has a series field, generates a sequential series value and uses it in the board name.
Parameters:
- template (
BoardTemplate) – The BoardTemplate to create a board from.
Returns:
Board– The created Board domain entity.
Raises:
ValueError– If interval parsing fails, game doesn't belong to account, or name generation fails.
Example
> > > board = await service.create_board_from_template(template)# leadr.boards.services.board_service.BoardService.delete¶
delete(entity_id)
Soft-delete an entity.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to delete
Raises:
EntityNotFoundError– If the entity doesn't exist
# leadr.boards.services.board_service.BoardService.get_board¶
get_board(board_id)
Get a board by its ID.
Parameters:
- board_id (
BoardID) – The ID of the board to retrieve.
Returns:
Board | None– The Board domain entity if found, None otherwise.
# leadr.boards.services.board_service.BoardService.get_board_by_short_code¶
get_board_by_short_code(short_code)
Get a board by its short_code.
Parameters:
- short_code (
str) – The short_code to search for.
Returns:
Board | None– The Board domain entity if found, None otherwise.
# leadr.boards.services.board_service.BoardService.get_by_id¶
get_by_id(entity_id)
Get an entity by its ID.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to retrieve
Returns:
DomainEntityT | None– The domain entity if found, None otherwise
# leadr.boards.services.board_service.BoardService.get_by_id_or_raise¶
get_by_id_or_raise(entity_id)
Get an entity by its ID or raise EntityNotFoundError.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to retrieve
Returns:
DomainEntityT– The domain entity
Raises:
EntityNotFoundError– If the entity is not found (converted to HTTP 404 by global handler)
# leadr.boards.services.board_service.BoardService.list_all¶
list_all()
List all non-deleted entities.
Returns:
list[DomainEntityT]– List of domain entities
# leadr.boards.services.board_service.BoardService.list_boards¶
list_boards(account_id=None, game_id=None, code=None, is_active=None, is_published=None, starts_before=None, starts_after=None, ends_before=None, ends_after=None, pagination=None)
List boards with optional filtering.
Parameters:
- account_id (
AccountID | None) – Optional account ID to filter by - game_id (
GameID | None) – Optional game ID to filter by - code (
str | None) – Optional short code to filter by - is_active (
bool | None) – Optional filter for active status - is_published (
bool | None) – Optional filter for published status - starts_before (
datetime | None) – Optional filter for boards starting before this time - starts_after (
datetime | None) – Optional filter for boards starting after this time - ends_before (
datetime | None) – Optional filter for boards ending before this time - ends_after (
datetime | None) – Optional filter for boards ending after this time - pagination (
PaginationParams | None) – Optional pagination parameters
Returns:
list[Board] | PaginatedResult[Board]– List of Board entities if no pagination, PaginatedResult if pagination provided.
# leadr.boards.services.board_service.BoardService.list_boards_by_account¶
list_boards_by_account(account_id)
List all boards for an account.
Parameters:
- account_id (
AccountID) – The ID of the account to list boards for.
Returns:
# leadr.boards.services.board_service.BoardService.repository¶
repository = self._create_repository(session)
# leadr.boards.services.board_service.BoardService.soft_delete¶
soft_delete(entity_id)
Soft-delete an entity and return it before deletion.
Useful for endpoints that need to return the deleted entity in the response.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to delete
Returns:
DomainEntityT– The entity before it was deleted
Raises:
EntityNotFoundError– If the entity doesn't exist
# leadr.boards.services.board_service.BoardService.update_board¶
update_board(board_id, name=None, icon=None, short_code=None, unit=None, is_active=None, is_published=None, sort_direction=None, keep_strategy=None, created_from_template_id=None, template_name=None, starts_at=None, ends_at=None, tags=None, description=None)
Update board fields.
Parameters:
- board_id (
BoardID) – The ID of the board to update - name (
str | None) – New board name, if provided - icon (
str | None) – New icon, if provided - short_code (
str | None) – New short_code, if provided - unit (
str | None) – New unit, if provided - is_active (
bool | None) – New is_active status, if provided - is_published (
bool | None) – New is_published status, if provided - sort_direction (
SortDirection | None) – New sort_direction, if provided - keep_strategy (
KeepStrategy | None) – New keep_strategy, if provided - created_from_template_id (
BoardTemplateID | None) – New created_from_template_id, if provided - template_name (
str | None) – New template_name, if provided - starts_at (
datetime | None) – New starts_at, if provided - ends_at (
datetime | None) – New ends_at, if provided - tags (
list[str] | None) – New tags list, if provided - description (
str | None) – New description, if provided
Returns:
Board– The updated Board domain entity
Raises:
EntityNotFoundError– If the board doesn't exist
leadr.boards.services.board_tasks¶
Background tasks for board processing.
Contains tasks for:
- Processing due board templates and creating boards
- Expiring boards past their end date
Functions:
- expire_boards – Expire boards that have passed their end date.
- process_due_templates – Process all due board templates and create boards.
Attributes:
- logger –
leadr.boards.services.board_tasks.expire_boards¶
expire_boards()
Expire boards that have passed their end date.
Queries for active boards where ends_at \<= now() and sets is_active=False.
This task is designed to be called periodically (e.g., every minute).
leadr.boards.services.board_tasks.logger¶
logger = logging.getLogger(__name__)
leadr.boards.services.board_tasks.process_due_templates¶
process_due_templates()
Process all due board templates and create boards.
Queries for active templates where next_run_at \<= now(), creates boards from each template, and updates the template's next_run_at.
This task is designed to be called periodically (e.g., every minute).
leadr.boards.services.board_template_service¶
BoardTemplate service for managing board template operations.
Classes:
- BoardTemplateService – Service for managing board template lifecycle and operations.
leadr.boards.services.board_template_service.BoardTemplateService¶
Bases: BaseService[BoardTemplate, BoardTemplateRepository]
Service for managing board template lifecycle and operations.
This service orchestrates board template creation, updates, and retrieval by coordinating between the domain models and repository layer. Ensures business rules like game validation are enforced.
Functions:
- advance_template_schedule – Advance a template's next_run_at by its repeat_interval.
- create_board_template – Create a new board template.
- delete – Soft-delete an entity.
- get_board_template – Get a board template by its ID.
- get_by_id – Get an entity by its ID.
- get_by_id_or_raise – Get an entity by its ID or raise EntityNotFoundError.
- list_all – List all non-deleted entities.
- list_board_templates_by_account – List all board templates for an account with optional pagination.
- list_board_templates_by_game – List all board templates for a specific game with optional pagination.
- soft_delete – Soft-delete an entity and return it before deletion.
- update_board_template – Update board template fields.
Attributes:
# leadr.boards.services.board_template_service.BoardTemplateService.advance_template_schedule¶
advance_template_schedule(template_id)
Advance a template's next_run_at by its repeat_interval.
This is typically called after successfully creating a board from the template.
Parameters:
- template_id (
BoardTemplateID) – The ID of the template to advance.
Returns:
BoardTemplate– The updated BoardTemplate with advanced next_run_at.
Raises:
EntityNotFoundError– If the template doesn't exist.ValueError– If the repeat_interval cannot be parsed.
Example
> > > template = await service.advance_template_schedule(template.id) > > > > > > # template.next_run_at is now advanced by repeat_interval# leadr.boards.services.board_template_service.BoardTemplateService.create_board_template¶
create_board_template(account_id, game_id, name, slug, repeat_interval, next_run_at, is_active, is_published=True, name_template=None, series=None, icon='fa-crown', unit=None, sort_direction=SortDirection.DESCENDING, keep_strategy=KeepStrategy.ALL, starts_at=None, ends_at=None, tags=None, config=None)
Create a new board template.
Parameters:
- account_id (
AccountID) – The ID of the account that owns this template. - game_id (
GameID) – The ID of the game this template belongs to. - name (
str) – The template name. - repeat_interval (
str) – PostgreSQL interval syntax for repeat frequency. - next_run_at (
datetime) – Next scheduled time to create a board. - is_active (
bool) – Whether the template is currently active. - name_template (
str | None) – Optional template string for generating board names. - series (
str | None) – Optional series identifier for sequential board naming. - config (
dict[str, Any] | None) – Optional configuration object for boards created from this template. - config_template – Optional template configuration for random generation.
Returns:
BoardTemplate– The created BoardTemplate domain entity.
Raises:
EntityNotFoundError– If the game doesn't exist.ValueError– If the game doesn't belong to the specified account or if name_template contains invalid placeholders.
Example
> > > template = await service.create_board_template( > > > ... account_id=account.id, > > > ... game_id=game.id, > > > ... name="Weekly Speed Run Template", > > > ... name_template="Week {series} - {year}", > > > ... series="weekly", > > > ... repeat_interval="7 days", > > > ... next_run_at=datetime.now(UTC) + timedelta(days=7), > > > ... is_active=True, > > > ... )# leadr.boards.services.board_template_service.BoardTemplateService.delete¶
delete(entity_id)
Soft-delete an entity.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to delete
Raises:
EntityNotFoundError– If the entity doesn't exist
# leadr.boards.services.board_template_service.BoardTemplateService.get_board_template¶
get_board_template(template_id)
Get a board template by its ID.
Parameters:
- template_id (
BoardTemplateID) – The ID of the template to retrieve.
Returns:
BoardTemplate | None– The BoardTemplate domain entity if found, None otherwise.
# leadr.boards.services.board_template_service.BoardTemplateService.get_by_id¶
get_by_id(entity_id)
Get an entity by its ID.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to retrieve
Returns:
DomainEntityT | None– The domain entity if found, None otherwise
# leadr.boards.services.board_template_service.BoardTemplateService.get_by_id_or_raise¶
get_by_id_or_raise(entity_id)
Get an entity by its ID or raise EntityNotFoundError.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to retrieve
Returns:
DomainEntityT– The domain entity
Raises:
EntityNotFoundError– If the entity is not found (converted to HTTP 404 by global handler)
# leadr.boards.services.board_template_service.BoardTemplateService.list_all¶
list_all()
List all non-deleted entities.
Returns:
list[DomainEntityT]– List of domain entities
# leadr.boards.services.board_template_service.BoardTemplateService.list_board_templates_by_account¶
list_board_templates_by_account(account_id, pagination=None)
List all board templates for an account with optional pagination.
Parameters:
- account_id (
AccountID | None) – The ID of the account to list templates for. If None, returns all templates (superadmin use case). - pagination (
PaginationParams | None) – Optional pagination parameters.
Returns:
list[BoardTemplate] | PaginatedResult[BoardTemplate]– List of BoardTemplate entities if no pagination, PaginatedResult if pagination provided.
# leadr.boards.services.board_template_service.BoardTemplateService.list_board_templates_by_game¶
list_board_templates_by_game(account_id, game_id, pagination=None)
List all board templates for a specific game with optional pagination.
Parameters:
- account_id (
AccountID | None) – The ID of the account. If None, returns templates from all accounts (superadmin use case). - game_id (
GameID) – The ID of the game to list templates for. - pagination (
PaginationParams | None) – Optional pagination parameters.
Returns:
list[BoardTemplate] | PaginatedResult[BoardTemplate]– List of BoardTemplate entities if no pagination, PaginatedResult if pagination provided.
# leadr.boards.services.board_template_service.BoardTemplateService.repository¶
repository = self._create_repository(session)
# leadr.boards.services.board_template_service.BoardTemplateService.soft_delete¶
soft_delete(entity_id)
Soft-delete an entity and return it before deletion.
Useful for endpoints that need to return the deleted entity in the response.
Parameters:
- entity_id (
UUID | PrefixedID) – The ID of the entity to delete
Returns:
DomainEntityT– The entity before it was deleted
Raises:
EntityNotFoundError– If the entity doesn't exist
# leadr.boards.services.board_template_service.BoardTemplateService.update_board_template¶
update_board_template(template_id, name=None, slug=None, name_template=None, series=None, icon=None, unit=None, sort_direction=None, keep_strategy=None, starts_at=None, ends_at=None, tags=None, repeat_interval=None, config=None, next_run_at=None, is_active=None, is_published=None)
Update board template fields.
Parameters:
- template_id (
BoardTemplateID) – The ID of the template to update. - name (
str | None) – New template name, if provided. - name_template (
str | None) – New name template, if provided. - series (
str | None) – New series identifier, if provided. - repeat_interval (
str | None) – New repeat interval, if provided. - config (
dict[str, Any] | None) – New config, if provided. - config_template – New config template, if provided.
- next_run_at (
datetime | None) – New next_run_at, if provided. - is_active (
bool | None) – New is_active status, if provided.
Returns:
BoardTemplate– The updated BoardTemplate domain entity.
Raises:
EntityNotFoundError– If the template doesn't exist.ValueError– If name_template contains invalid placeholders.
leadr.boards.services.dependencies¶
Board service dependency injection.
Functions:
- get_board_service – Get BoardService dependency.
- get_board_template_service – Get BoardTemplateService dependency.
Attributes:
leadr.boards.services.dependencies.BoardServiceDep¶
BoardServiceDep = Annotated[BoardService, Depends(get_board_service)]
leadr.boards.services.dependencies.BoardTemplateServiceDep¶
BoardTemplateServiceDep = Annotated[BoardTemplateService, Depends(get_board_template_service)]
leadr.boards.services.dependencies.get_board_service¶
get_board_service(db)
Get BoardService dependency.
Parameters:
- db (
DatabaseSession) – Database session from dependency injection
Returns:
BoardService– BoardService instance for handling board operations
leadr.boards.services.dependencies.get_board_template_service¶
get_board_template_service(db)
Get BoardTemplateService dependency.
Parameters:
- db (
DatabaseSession) – Database session from dependency injection
Returns:
BoardTemplateService– BoardTemplateService instance for handling board template operations
leadr.boards.services.repositories¶
Board repository services.
Classes:
- BoardRepository – Board repository for managing board persistence.
- BoardTemplateRepository – BoardTemplate repository for managing board template persistence.
leadr.boards.services.repositories.BoardRepository¶
Bases: BaseRepository[Board, BoardORM]
Board repository for managing board persistence.
Functions:
- count_boards_by_template – Count boards created from a specific template.
- create – Create a new entity in the database.
- delete – Soft delete an entity by setting its deleted_at timestamp.
- filter – Filter boards by account and optional criteria.
- get_by_id – Get an entity by its ID.
- get_by_short_code – Get board by short_code.
- get_by_slug – Get board by slug within account and game scope.
- list_boards – List boards with optional filtering.
- update – Update an existing entity in the database.
Attributes:
# leadr.boards.services.repositories.BoardRepository.SORTABLE_FIELDS¶
SORTABLE_FIELDS = {'id', 'name', 'slug', 'short_code', 'created_at', 'updated_at'}
# leadr.boards.services.repositories.BoardRepository.count_boards_by_template¶
count_boards_by_template(template_id)
Count boards created from a specific template.
Parameters:
- template_id (
BoardTemplateID) – The template ID to count boards for
Returns:
int– Number of boards created from this template
# leadr.boards.services.repositories.BoardRepository.create¶
create(entity)
Create a new entity in the database.
Parameters:
- entity (
DomainEntityT) – Domain entity to create
Returns:
DomainEntityT– Created domain entity with refreshed data
# leadr.boards.services.repositories.BoardRepository.delete¶
delete(entity_id)
Soft delete an entity by setting its deleted_at timestamp.
Parameters:
- entity_id (
UUID4 | PrefixedID) – ID of entity to delete
Raises:
EntityNotFoundError– If entity is not found
# leadr.boards.services.repositories.BoardRepository.filter¶
filter(account_id=None, **kwargs)
Filter boards by account and optional criteria.
Parameters:
- account_id (
UUID4 | PrefixedID | None) – Optional account ID to filter by. If None, returns all boards (superadmin use case). Regular users should always pass account_id. - **kwargs (
Any) – Additional filter parameters (reserved for future use)
Returns:
# leadr.boards.services.repositories.BoardRepository.get_by_id¶
get_by_id(entity_id, include_deleted=False)
Get an entity by its ID.
Parameters:
- entity_id (
UUID4 | PrefixedID) – Entity ID to retrieve - include_deleted (
bool) – If True, include soft-deleted entities. Defaults to False.
Returns:
DomainEntityT | None– Domain entity if found, None otherwise
# leadr.boards.services.repositories.BoardRepository.get_by_short_code¶
get_by_short_code(short_code)
Get board by short_code.
Parameters:
- short_code (
str) – The short_code to search for
Returns:
Board | None– Board entity if found, None otherwise
# leadr.boards.services.repositories.BoardRepository.get_by_slug¶
get_by_slug(account_id, game_id, slug, is_active=None)
Get board by slug within account and game scope.
Lookups are scoped to account_id and game_id to respect the partial unique constraint (account_id, game_id, slug) WHERE is_active=true.
Parameters:
- account_id (
UUID4 | AccountID) – The account ID to filter by - game_id (
UUID4 | GameID) – The game ID to filter by - slug (
str) – The slug to search for - is_active (
bool | None) – Optional filter for active status. If None, returns board regardless of active status.
Returns:
Board | None– Board entity if found, None otherwise
# leadr.boards.services.repositories.BoardRepository.list_boards¶
list_boards(account_id=None, game_id=None, code=None, is_active=None, is_published=None, starts_before=None, starts_after=None, ends_before=None, ends_after=None, pagination=None)
List boards with optional filtering.
Parameters:
- account_id (
UUID4 | AccountID | None) – Optional account ID to filter by - game_id (
UUID4 | GameID | None) – Optional game ID to filter by - code (
str | None) – Optional short code to filter by - is_active (
bool | None) – Optional filter for active status - is_published (
bool | None) – Optional filter for published status - starts_before (
datetime | None) – Optional filter for boards starting before this time - starts_after (
datetime | None) – Optional filter for boards starting after this time - ends_before (
datetime | None) – Optional filter for boards ending before this time - ends_after (
datetime | None) – Optional filter for boards ending after this time - pagination (
PaginationParams | None) – Optional pagination parameters
Returns:
list[Board] | PaginatedResult[Board]– List of boards if no pagination, PaginatedResult if pagination provided
Raises:
ValueError– If sort field is not in SORTABLE_FIELDSCursorValidationError– If cursor is invalid or state doesn't match
# leadr.boards.services.repositories.BoardRepository.session¶
session = session
# leadr.boards.services.repositories.BoardRepository.update¶
update(entity)
Update an existing entity in the database.
Parameters:
- entity (
DomainEntityT) – Domain entity with updated data
Returns:
DomainEntityT– Updated domain entity with refreshed data
Raises:
EntityNotFoundError– If entity is not found
leadr.boards.services.repositories.BoardTemplateRepository¶
Bases: BaseRepository[BoardTemplate, BoardTemplateORM]
BoardTemplate repository for managing board template persistence.
Functions:
- create – Create a new entity in the database.
- delete – Soft delete an entity by setting its deleted_at timestamp.
- filter – Filter board templates by account and optional game.
- get_by_id – Get an entity by its ID.
- update – Update an existing entity in the database.
Attributes:
# leadr.boards.services.repositories.BoardTemplateRepository.SORTABLE_FIELDS¶
SORTABLE_FIELDS = {'id', 'name', 'created_at', 'updated_at'}
# leadr.boards.services.repositories.BoardTemplateRepository.create¶
create(entity)
Create a new entity in the database.
Parameters:
- entity (
DomainEntityT) – Domain entity to create
Returns:
DomainEntityT– Created domain entity with refreshed data
# leadr.boards.services.repositories.BoardTemplateRepository.delete¶
delete(entity_id)
Soft delete an entity by setting its deleted_at timestamp.
Parameters:
- entity_id (
UUID4 | PrefixedID) – ID of entity to delete
Raises:
EntityNotFoundError– If entity is not found
# leadr.boards.services.repositories.BoardTemplateRepository.filter¶
filter(account_id=None, game_id=None, pagination=None, **kwargs)
Filter board templates by account and optional game.
Parameters:
- account_id (
AccountID | None) – Optional account ID to filter by. If None, returns all templates (superadmin use case). Regular users should always pass account_id. - game_id (
GameID | None) – OPTIONAL - Game ID to filter by - pagination (
PaginationParams | None) – Optional pagination parameters - **kwargs (
Any) – Additional filter parameters (reserved for future use)
Returns:
list[BoardTemplate] | PaginatedResult[BoardTemplate]– List of board templates if no pagination, PaginatedResult if pagination provided
Raises:
ValueError– If sort field is not in SORTABLE_FIELDSCursorValidationError– If cursor is invalid or state doesn't match
# leadr.boards.services.repositories.BoardTemplateRepository.get_by_id¶
get_by_id(entity_id, include_deleted=False)
Get an entity by its ID.
Parameters:
- entity_id (
UUID4 | PrefixedID) – Entity ID to retrieve - include_deleted (
bool) – If True, include soft-deleted entities. Defaults to False.
Returns:
DomainEntityT | None– Domain entity if found, None otherwise
# leadr.boards.services.repositories.BoardTemplateRepository.session¶
session = session
# leadr.boards.services.repositories.BoardTemplateRepository.update¶
update(entity)
Update an existing entity in the database.
Parameters:
- entity (
DomainEntityT) – Domain entity with updated data
Returns:
DomainEntityT– Updated domain entity with refreshed data
Raises:
EntityNotFoundError– If entity is not found
leadr.boards.services.short_code_generator¶
Utility for generating unique short codes for boards.
Short codes are used for direct board sharing (e.g., example.com/board/ABC123XY). They must be globally unique across all boards.
Functions:
- generate_short_code – Generate a random 8-character alphanumeric short code.
- generate_unique_short_code – Generate a globally unique short code with collision retry logic.
Attributes:
- CHARSET –
- CODE_LENGTH –
leadr.boards.services.short_code_generator.CHARSET¶
CHARSET = '23456789ABCDEFGHJKMNPQRSTUVWXYZ'
leadr.boards.services.short_code_generator.CODE_LENGTH¶
CODE_LENGTH = 5
leadr.boards.services.short_code_generator.generate_short_code¶
generate_short_code()
Generate a random 8-character alphanumeric short code.
Uses cryptographically strong random number generator for security. Excludes ambiguous characters (0/O, 1/I/l) for better readability.
Returns:
str– 5-character uppercase alphanumeric code (e.g., 'A7B3X').
Example
> > > code = generate_short_code() > > > len(code) > > > 5 > > > code.isupper() > > > Trueleadr.boards.services.short_code_generator.generate_unique_short_code¶
generate_unique_short_code(session, max_retries=10)
Generate a globally unique short code with collision retry logic.
Generates random codes and checks database for uniqueness. If a collision is detected, retries up to max_retries times before raising an error.
Parameters:
- session (
AsyncSession) – Database session for uniqueness checking. - max_retries (
int) – Maximum number of generation attempts (default 10).
Returns:
str– Unique 5-character short code guaranteed not to exist in database.
Raises:
RuntimeError– If unable to generate unique code within max_retries attempts.