feat: T03+T04 backend - FastAPI, DB models, Rentman integration, admin auth, APScheduler
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
"""Tests for Rentman request submission pipeline (T04)."""
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock, patch, MagicMock
|
||||
from app.services.rentman_service import RentmanService
|
||||
|
||||
|
||||
def test_build_project_request_payload():
|
||||
data = {
|
||||
"event_name": "Sommerfest 2026",
|
||||
"date_start": "2026-08-15",
|
||||
"date_end": "2026-08-16",
|
||||
"contact_name": "Max Mustermann",
|
||||
"contact_company": "Firma GmbH",
|
||||
"contact_email": "max@example.com",
|
||||
"contact_phone": "+49 170 1234567",
|
||||
"contact_street": "Hauptstr. 42a",
|
||||
"contact_postalcode": "80000",
|
||||
"contact_city": "Muenchen",
|
||||
"location": "Muenchen",
|
||||
"message": "Brauchen PA",
|
||||
}
|
||||
payload = RentmanService.build_project_request_payload(data)
|
||||
assert payload["name"] == "Sommerfest 2026"
|
||||
assert payload["planperiod_start"] == "2026-08-15T08:00:00+02:00"
|
||||
assert payload["planperiod_end"] == "2026-08-16T02:00:00+02:00"
|
||||
assert payload["usageperiod_start"] == "2026-08-15T18:00:00+02:00"
|
||||
assert payload["usageperiod_end"] == "2026-08-16T23:59:00+02:00"
|
||||
assert payload["contact_name"] == "Firma GmbH"
|
||||
assert payload["contact_person_first_name"] == "Max"
|
||||
assert payload["contact_person_lastname"] == "Mustermann"
|
||||
assert payload["contact_person_email"] == "max@example.com"
|
||||
assert payload["location_mailing_street"] == "Hauptstr. 42a"
|
||||
assert payload["location_mailing_number"] == "42a"
|
||||
assert payload["location_mailing_postalcode"] == "80000"
|
||||
assert payload["location_mailing_city"] == "Muenchen"
|
||||
assert payload["remark"] == "Brauchen PA"
|
||||
|
||||
|
||||
def test_build_project_request_payload_no_company():
|
||||
"""When no company, contact_name should use contact_name."""
|
||||
data = {
|
||||
"event_name": "Test",
|
||||
"date_start": "2026-08-15",
|
||||
"date_end": "2026-08-16",
|
||||
"contact_name": "Anna Schmidt",
|
||||
"contact_company": None,
|
||||
"contact_email": "anna@example.com",
|
||||
"contact_street": "Testweg 5",
|
||||
"contact_postalcode": "10000",
|
||||
"contact_city": "Berlin",
|
||||
"location": "Berlin",
|
||||
}
|
||||
payload = RentmanService.build_project_request_payload(data)
|
||||
assert payload["contact_name"] == "Anna Schmidt"
|
||||
assert payload["contact_person_first_name"] == "Anna"
|
||||
assert payload["contact_person_lastname"] == "Schmidt"
|
||||
assert payload["location_mailing_number"] == "5"
|
||||
|
||||
|
||||
def test_build_equipment_payload():
|
||||
item = {
|
||||
"equipment_name": "L-Acoustics K2",
|
||||
"rentman_equipment_id": "101",
|
||||
"quantity": 4,
|
||||
"unit_price": 150.00,
|
||||
}
|
||||
payload = RentmanService.build_equipment_payload(item)
|
||||
assert payload["name"] == "L-Acoustics K2"
|
||||
assert payload["quantity"] == 4
|
||||
assert payload["quantity_total"] == 4
|
||||
assert payload["unit_price"] == 150.00
|
||||
assert payload["linked_equipment"] == "/equipment/101"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_projectrequest_success():
|
||||
"""Mock Rentman API: create project request returns ID, equipment added."""
|
||||
svc = RentmanService(token="test-token")
|
||||
svc.create_project_request = AsyncMock(return_value={"id": "9999", "name": "Test Event"})
|
||||
svc.add_equipment_to_request = AsyncMock(return_value={"id": "equip-1"})
|
||||
|
||||
project_payload = {"name": "Test Event", "usageperiod_start": "2026-08-15T18:00:00+02:00"}
|
||||
result = await svc.create_project_request(project_payload)
|
||||
assert result["id"] == "9999"
|
||||
|
||||
equip_payload = {"name": "K2", "quantity": 2}
|
||||
eq_result = await svc.add_equipment_to_request("9999", equip_payload)
|
||||
assert eq_result["id"] == "equip-1"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_equipment_retry():
|
||||
"""Failed equipment POST should be retried (exponential backoff simulation)."""
|
||||
svc = RentmanService(token="test-token")
|
||||
call_count = 0
|
||||
|
||||
async def mock_add(*args, **kwargs):
|
||||
nonlocal call_count
|
||||
call_count += 1
|
||||
if call_count < 3:
|
||||
raise Exception("Temporary failure")
|
||||
return {"id": "success"}
|
||||
|
||||
svc.add_equipment_to_request = mock_add
|
||||
|
||||
# Simulate retry logic
|
||||
max_retries = 3
|
||||
result = None
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
result = await svc.add_equipment_to_request("1", {"name": "test"})
|
||||
break
|
||||
except Exception:
|
||||
if attempt == max_retries - 1:
|
||||
raise
|
||||
import asyncio
|
||||
await asyncio.sleep(0.01 * (2 ** attempt))
|
||||
|
||||
assert result == {"id": "success"}
|
||||
assert call_count == 3
|
||||
Reference in New Issue
Block a user