- Add PricingConfigResponse and PricingConfigUpdate schemas - Create PricingService with validation logic - Add GET and PUT endpoints in routes/pricing.py - Add MANAGE_PRICING permission to admin role - Register pricing router in main.py - Add comprehensive API tests for permissions and validation
106 lines
4 KiB
Python
106 lines
4 KiB
Python
"""Pricing service for managing pricing configuration."""
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from exceptions import BadRequestError, NotFoundError
|
|
from repositories.pricing import PricingRepository
|
|
from schemas import PricingConfigResponse, PricingConfigUpdate
|
|
|
|
|
|
class PricingService:
|
|
"""Service for pricing configuration business logic."""
|
|
|
|
def __init__(self, db: AsyncSession):
|
|
self.db = db
|
|
self.repo = PricingRepository(db)
|
|
|
|
async def get_config(self) -> PricingConfigResponse:
|
|
"""Get current pricing configuration.
|
|
|
|
Returns:
|
|
PricingConfigResponse with current config
|
|
|
|
Raises:
|
|
NotFoundError: If no config exists
|
|
"""
|
|
config = await self.repo.get_current()
|
|
if config is None:
|
|
raise NotFoundError("Pricing configuration not found")
|
|
|
|
return PricingConfigResponse(
|
|
premium_buy=config.premium_buy,
|
|
premium_sell=config.premium_sell,
|
|
small_trade_threshold_eur=config.small_trade_threshold_eur,
|
|
small_trade_extra_premium=config.small_trade_extra_premium,
|
|
eur_min_buy=config.eur_min_buy,
|
|
eur_max_buy=config.eur_max_buy,
|
|
eur_min_sell=config.eur_min_sell,
|
|
eur_max_sell=config.eur_max_sell,
|
|
)
|
|
|
|
async def update_config(self, data: PricingConfigUpdate) -> PricingConfigResponse:
|
|
"""Update pricing configuration with validation.
|
|
|
|
Args:
|
|
data: Pricing configuration update data
|
|
|
|
Returns:
|
|
PricingConfigResponse with updated config
|
|
|
|
Raises:
|
|
BadRequestError: If validation fails
|
|
"""
|
|
# Validate premium values (-100 to 100)
|
|
if not (-100 <= data.premium_buy <= 100):
|
|
raise BadRequestError("premium_buy must be between -100 and 100")
|
|
if not (-100 <= data.premium_sell <= 100):
|
|
raise BadRequestError("premium_sell must be between -100 and 100")
|
|
if not (-100 <= data.small_trade_extra_premium <= 100):
|
|
raise BadRequestError(
|
|
"small_trade_extra_premium must be between -100 and 100"
|
|
)
|
|
|
|
# Validate min amounts (positive integers)
|
|
if data.eur_min_buy <= 0:
|
|
raise BadRequestError("eur_min_buy must be positive")
|
|
if data.eur_min_sell <= 0:
|
|
raise BadRequestError("eur_min_sell must be positive")
|
|
|
|
# Validate max amounts (positive integers)
|
|
if data.eur_max_buy <= 0:
|
|
raise BadRequestError("eur_max_buy must be positive")
|
|
if data.eur_max_sell <= 0:
|
|
raise BadRequestError("eur_max_sell must be positive")
|
|
|
|
# Validate min < max for both directions
|
|
if data.eur_min_buy >= data.eur_max_buy:
|
|
raise BadRequestError("eur_min_buy must be less than eur_max_buy")
|
|
if data.eur_min_sell >= data.eur_max_sell:
|
|
raise BadRequestError("eur_min_sell must be less than eur_max_sell")
|
|
|
|
# Validate threshold (positive integer)
|
|
if data.small_trade_threshold_eur <= 0:
|
|
raise BadRequestError("small_trade_threshold_eur must be positive")
|
|
|
|
# Update config
|
|
config = await self.repo.create_or_update(
|
|
premium_buy=data.premium_buy,
|
|
premium_sell=data.premium_sell,
|
|
small_trade_threshold_eur=data.small_trade_threshold_eur,
|
|
small_trade_extra_premium=data.small_trade_extra_premium,
|
|
eur_min_buy=data.eur_min_buy,
|
|
eur_max_buy=data.eur_max_buy,
|
|
eur_min_sell=data.eur_min_sell,
|
|
eur_max_sell=data.eur_max_sell,
|
|
)
|
|
|
|
return PricingConfigResponse(
|
|
premium_buy=config.premium_buy,
|
|
premium_sell=config.premium_sell,
|
|
small_trade_threshold_eur=config.small_trade_threshold_eur,
|
|
small_trade_extra_premium=config.small_trade_extra_premium,
|
|
eur_min_buy=config.eur_min_buy,
|
|
eur_max_buy=config.eur_max_buy,
|
|
eur_min_sell=config.eur_min_sell,
|
|
eur_max_sell=config.eur_max_sell,
|
|
)
|