Source code for app.services.user_points_service

"""Public entry point for user-points operations.

``UserPointsService`` composes four focused mixins (see
:mod:`app.services.user_points`) so its read, write, simulation and
persistence concerns live in separate modules without changing the single
DI-injected class that endpoints and strategy engines depend on:

* :class:`PointsQueryMixin` - read-only aggregations and lookups.
* :class:`PointsAssignmentMixin` - the scoring/write path (also brings the
  persistence helpers it builds on).
* :class:`PointsSimulationMixin` - non-persisting simulation of built-ins.
* :class:`PointsPersistenceMixin` - the atomic points/wallet/transaction write.
"""

import logging

from app.repository.game_repository import GameRepository
from app.repository.task_repository import TaskRepository
from app.repository.user_game_config_repository import UserGameConfigRepository
from app.repository.user_points_repository import UserPointsRepository
from app.repository.user_repository import UserRepository
from app.repository.wallet_repository import WalletRepository
from app.repository.wallet_transaction_repository import WalletTransactionRepository
from app.services.base_service import BaseService
from app.services.strategy_service import StrategyService
from app.services.user_points import (PointsAssignmentMixin, PointsQueryMixin,
                                      PointsSimulationMixin)

logger = logging.getLogger(__name__)


[docs] class UserPointsService( BaseService, PointsQueryMixin, PointsAssignmentMixin, PointsSimulationMixin, ): def __init__( self, user_points_repository: UserPointsRepository, users_repository: UserRepository, users_game_config_repository: UserGameConfigRepository, game_repository: GameRepository, task_repository: TaskRepository, wallet_repository: WalletRepository, wallet_transaction_repository: WalletTransactionRepository, strategy_service: "StrategyService | None" = None, ) -> None: self.user_points_repository = user_points_repository self.users_repository = users_repository self.users_game_config_repository = users_game_config_repository self.game_repository = game_repository self.task_repository = task_repository self.wallet_repository = wallet_repository self.wallet_transaction_repository = wallet_transaction_repository # When constructed via DI (the production path) the container # injects a fully-wired StrategyService that can resolve # ``custom:<uuid>`` ids against the DB. The no-arg fallback # preserves the legacy behaviour for tests that build this # service positionally and monkey-patch ``self.strategy_service``. self.strategy_service = strategy_service or StrategyService() super().__init__(user_points_repository)