Add endpoint to get a single trade by ID
This commit is contained in:
parent
04192799ab
commit
0c75583930
2 changed files with 96 additions and 0 deletions
|
|
@ -565,6 +565,29 @@ async def get_my_trades(
|
|||
return [_to_exchange_response(ex, current_user.email) for ex in exchanges]
|
||||
|
||||
|
||||
@trades_router.get("/{exchange_id}", response_model=ExchangeResponse)
|
||||
async def get_my_trade(
|
||||
exchange_id: int,
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_permission(Permission.VIEW_OWN_EXCHANGES)),
|
||||
) -> ExchangeResponse:
|
||||
"""Get a specific trade by ID. User can only access their own trades."""
|
||||
result = await db.execute(
|
||||
select(Exchange).where(
|
||||
and_(Exchange.id == exchange_id, Exchange.user_id == current_user.id)
|
||||
)
|
||||
)
|
||||
exchange = result.scalar_one_or_none()
|
||||
|
||||
if not exchange:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="Trade not found or you don't have permission to view it.",
|
||||
)
|
||||
|
||||
return _to_exchange_response(exchange, current_user.email)
|
||||
|
||||
|
||||
@trades_router.post("/{exchange_id}/cancel", response_model=ExchangeResponse)
|
||||
async def cancel_my_trade(
|
||||
exchange_id: int,
|
||||
|
|
|
|||
|
|
@ -646,6 +646,79 @@ class TestUserTrades:
|
|||
assert len(data) == 2
|
||||
|
||||
|
||||
class TestGetMyTrade:
|
||||
"""Test getting a single trade by ID."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_my_trade_success(self, client_factory, regular_user, admin_user):
|
||||
"""Can get own trade by ID."""
|
||||
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:
|
||||
# Create a trade
|
||||
create_response = await client.post(
|
||||
"/api/exchange",
|
||||
json={
|
||||
"slot_start": f"{target_date}T09:00:00Z",
|
||||
"direction": "buy",
|
||||
"bitcoin_transfer_method": "onchain",
|
||||
"eur_amount": 10000,
|
||||
},
|
||||
)
|
||||
assert create_response.status_code == 200
|
||||
trade_id = create_response.json()["id"]
|
||||
|
||||
# Get the trade
|
||||
get_response = await client.get(f"/api/trades/{trade_id}")
|
||||
|
||||
assert get_response.status_code == 200
|
||||
data = get_response.json()
|
||||
assert data["id"] == trade_id
|
||||
assert data["direction"] == "buy"
|
||||
assert data["bitcoin_transfer_method"] == "onchain"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cannot_get_other_user_trade(
|
||||
self, client_factory, regular_user, alt_regular_user, admin_user
|
||||
):
|
||||
"""Cannot get another user's trade."""
|
||||
target_date = await setup_availability_and_price(client_factory, admin_user)
|
||||
|
||||
with mock_price_fetcher(20000.0):
|
||||
# First user creates a trade
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
create_response = await client.post(
|
||||
"/api/exchange",
|
||||
json={
|
||||
"slot_start": f"{target_date}T09:00:00Z",
|
||||
"direction": "buy",
|
||||
"bitcoin_transfer_method": "onchain",
|
||||
"eur_amount": 10000,
|
||||
},
|
||||
)
|
||||
assert create_response.status_code == 200
|
||||
trade_id = create_response.json()["id"]
|
||||
|
||||
# Second user tries to get it
|
||||
async with client_factory.create(
|
||||
cookies=alt_regular_user["cookies"]
|
||||
) as client:
|
||||
get_response = await client.get(f"/api/trades/{trade_id}")
|
||||
|
||||
assert get_response.status_code == 404
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_nonexistent_trade_returns_404(
|
||||
self, client_factory, regular_user
|
||||
):
|
||||
"""Getting a nonexistent trade returns 404."""
|
||||
async with client_factory.create(cookies=regular_user["cookies"]) as client:
|
||||
response = await client.get("/api/trades/99999")
|
||||
|
||||
assert response.status_code == 404
|
||||
|
||||
|
||||
class TestCancelTrade:
|
||||
"""Test cancelling trades."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue