koprogo_api/infrastructure/web/handlers/
public_handlers.rs

1use crate::application::dto::PublicSyndicInfoResponse;
2use crate::infrastructure::web::AppState;
3use actix_web::{get, web, HttpResponse, Responder};
4
5/// GET /api/v1/public/buildings/:slug/syndic
6/// Get public syndic information for a building (no authentication required)
7///
8/// This endpoint is publicly accessible to comply with Belgian law requiring
9/// syndics to display contact information publicly.
10///
11/// # Path Parameters
12/// * `slug` - URL-friendly building identifier (e.g., "residence-les-jardins-brussels")
13///
14/// # Returns
15/// * `200 OK` - Public syndic information
16/// * `404 Not Found` - Building not found or slug invalid
17/// * `500 Internal Server Error` - Database error
18///
19/// # Example
20/// ```
21/// GET /api/v1/public/buildings/residence-les-jardins-brussels/syndic
22///
23/// Response 200 OK:
24/// {
25///   "building_name": "Résidence Les Jardins",
26///   "building_address": "123 Rue de la Paix",
27///   "building_city": "Brussels",
28///   "building_postal_code": "1000",
29///   "building_country": "Belgium",
30///   "slug": "residence-les-jardins-brussels",
31///   "syndic_name": "Syndic ASBL",
32///   "syndic_email": "contact@syndic.be",
33///   "syndic_phone": "+32 2 123 4567",
34///   "syndic_address": "Avenue Louise 123, 1000 Brussels",
35///   "syndic_office_hours": "Mon-Fri 9h-17h",
36///   "syndic_emergency_contact": "+32 475 123 456",
37///   "has_syndic_info": true
38/// }
39/// ```
40#[get("/public/buildings/{slug}/syndic")]
41pub async fn get_public_syndic_info(
42    data: web::Data<AppState>,
43    slug: web::Path<String>,
44) -> impl Responder {
45    let slug = slug.into_inner();
46
47    // Find building by slug using BuildingUseCases
48    match data.building_use_cases.find_by_slug(&slug).await {
49        Ok(Some(building)) => {
50            let response = PublicSyndicInfoResponse::from(building);
51            HttpResponse::Ok().json(response)
52        }
53        Ok(None) => HttpResponse::NotFound().json(serde_json::json!({
54            "error": format!("Building not found with slug: {}", slug)
55        })),
56        Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({
57            "error": format!("Failed to fetch building information: {}", e)
58        })),
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    // Note: Full integration tests with actual AppState would require proper initialization
65    // of all use cases. These handler tests are covered by E2E tests in tests/e2e/
66
67    #[test]
68    fn test_handler_structure_public_syndic() {
69        // This test just verifies the handler function signature compiles
70        // Real testing happens in E2E tests with testcontainers
71    }
72}