Step 5: Update exchange price endpoint to use new pricing config

- Update ExchangeConfigResponse schema with direction-specific fields
- Remove premium_percentage from PriceResponse (now in config)
- Update price endpoint to load pricing config from database
- Update frontend to use direction-specific min/max and calculate premium
- Update tests to seed pricing config
- Add logic to clamp amount when direction changes
This commit is contained in:
counterweight 2025-12-26 20:20:23 +01:00
parent d838d1be96
commit d317939ad0
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
5 changed files with 145 additions and 44 deletions

View file

@ -57,7 +57,7 @@ def mock_price_fetcher(price: float = 20000.0):
async def setup_availability_and_price(client_factory, admin_user, target_date=None):
"""Helper to set up availability and price for tests."""
"""Helper to set up availability, price, and pricing config for tests."""
if target_date is None:
target_date = tomorrow()
@ -71,9 +71,22 @@ async def setup_availability_and_price(client_factory, admin_user, target_date=N
},
)
# Create fresh price in DB
# Create fresh price in DB and pricing config
async with client_factory.get_db_session() as db:
await create_price_in_db(db, price=20000.0, minutes_ago=0)
from repositories.pricing import PricingRepository
repo = PricingRepository(db)
await repo.create_or_update(
premium_buy=5,
premium_sell=5,
small_trade_threshold_eur=20000,
small_trade_extra_premium=2,
eur_min_buy=10000,
eur_max_buy=300000,
eur_min_sell=10000,
eur_max_sell=300000,
)
return target_date
@ -89,9 +102,22 @@ class TestExchangePriceEndpoint:
@pytest.mark.asyncio
async def test_regular_user_can_get_price(self, client_factory, regular_user):
"""Regular user can access price endpoint."""
# Create fresh price in DB
# Create fresh price in DB and pricing config
async with client_factory.get_db_session() as db:
await create_price_in_db(db, price=20000.0, minutes_ago=0)
from repositories.pricing import PricingRepository
repo = PricingRepository(db)
await repo.create_or_update(
premium_buy=5,
premium_sell=5,
small_trade_threshold_eur=20000,
small_trade_extra_premium=2,
eur_min_buy=10000,
eur_max_buy=300000,
eur_min_sell=10000,
eur_max_sell=300000,
)
# Mock the price fetcher to prevent real API calls
with mock_price_fetcher(20000.0):
@ -103,8 +129,7 @@ class TestExchangePriceEndpoint:
assert "price" in data
assert "config" in data
assert data["price"]["market_price"] == 20000.0
assert data["price"]["premium_percentage"] == 5
# Note: agreed_price is calculated on frontend based on direction (buy/sell)
# Note: premium is now in config, agreed_price is calculated on frontend
@pytest.mark.asyncio
async def test_admin_cannot_get_price(self, client_factory, admin_user):
@ -123,9 +148,22 @@ class TestExchangePriceEndpoint:
@pytest.mark.asyncio
async def test_stale_price_triggers_fetch(self, client_factory, regular_user):
"""When cached price is stale, a fresh price is fetched."""
# Create stale price (6 minutes old, threshold is 5 minutes)
# Create stale price (6 minutes old, threshold is 5 minutes) and pricing config
async with client_factory.get_db_session() as db:
await create_price_in_db(db, price=19000.0, minutes_ago=6)
from repositories.pricing import PricingRepository
repo = PricingRepository(db)
await repo.create_or_update(
premium_buy=5,
premium_sell=5,
small_trade_threshold_eur=20000,
small_trade_extra_premium=2,
eur_min_buy=10000,
eur_max_buy=300000,
eur_min_sell=10000,
eur_max_sell=300000,
)
# Mock fetcher returns new price
with mock_price_fetcher(21000.0):
@ -142,6 +180,19 @@ class TestExchangePriceEndpoint:
"""Config section contains all required fields."""
async with client_factory.get_db_session() as db:
await create_price_in_db(db)
from repositories.pricing import PricingRepository
repo = PricingRepository(db)
await repo.create_or_update(
premium_buy=5,
premium_sell=6,
small_trade_threshold_eur=20000,
small_trade_extra_premium=2,
eur_min_buy=10000,
eur_max_buy=300000,
eur_min_sell=12000,
eur_max_sell=320000,
)
with mock_price_fetcher():
async with client_factory.create(cookies=regular_user["cookies"]) as client:
@ -149,13 +200,22 @@ class TestExchangePriceEndpoint:
assert response.status_code == 200
config = response.json()["config"]
assert "eur_min" in config
assert "eur_max" in config
assert "eur_min_buy" in config
assert "eur_max_buy" in config
assert "eur_min_sell" in config
assert "eur_max_sell" in config
assert "eur_increment" in config
assert "premium_percentage" in config
assert config["eur_min"] == 100
assert config["eur_max"] == 3000
assert "premium_buy" in config
assert "premium_sell" in config
assert "small_trade_threshold_eur" in config
assert "small_trade_extra_premium" in config
assert config["eur_min_buy"] == 10000
assert config["eur_max_buy"] == 300000
assert config["eur_min_sell"] == 12000
assert config["eur_max_sell"] == 320000
assert config["eur_increment"] == 20
assert config["premium_buy"] == 5
assert config["premium_sell"] == 6
# =============================================================================