fix: derive valid slot minutes from SLOT_DURATION_MINUTES constant

Replace hardcoded (0, 15, 30, 45) tuple with computed range based on
the SLOT_DURATION_MINUTES constant. This ensures the validation stays
in sync if the slot duration is ever changed.

Add test to verify slot minute boundary validation.
This commit is contained in:
counterweight 2025-12-23 12:17:40 +01:00
parent 0d8369ce65
commit 2efbd2c665
Signed by: counterweight
GPG key ID: 883EDBAA726BD96C
2 changed files with 23 additions and 2 deletions

View file

@ -401,8 +401,8 @@ async def create_exchange(
detail=f"EUR amount must be a multiple of €{EUR_TRADE_INCREMENT}",
)
# Validate slot timing
valid_minutes = (0, 15, 30, 45)
# Validate slot timing - compute valid boundaries from slot duration
valid_minutes = tuple(range(0, 60, SLOT_DURATION_MINUTES))
if request.slot_start.minute not in valid_minutes:
raise HTTPException(
status_code=400,

View file

@ -332,6 +332,27 @@ class TestCreateExchange:
assert response.status_code == 400
assert "multiple" in response.json()["detail"]
@pytest.mark.asyncio
async def test_slot_not_on_minute_boundary_rejected(
self, client_factory, regular_user, admin_user
):
"""Slot start time not on slot duration boundary is rejected."""
target_date = await setup_availability_and_price(client_factory, admin_user)
with mock_price_fetcher(20000.0):
async with client_factory.create(cookies=regular_user["cookies"]) as client:
response = await client.post(
"/api/exchange",
json={
"slot_start": f"{target_date}T09:07:00Z", # 07 is not on 15-min boundary
"direction": "buy",
"eur_amount": 10000,
},
)
assert response.status_code == 400
assert "boundary" in response.json()["detail"].lower()
@pytest.mark.asyncio
async def test_stale_price_blocks_booking(
self, client_factory, regular_user, admin_user