Skip to main content

koprogo_api/application/ports/
building_repository.rs

1use crate::application::dto::{BuildingFilters, PageRequest};
2use crate::domain::entities::{Building, BuildingMetrics};
3use async_trait::async_trait;
4use uuid::Uuid;
5
6/// Port (interface) pour le repository de bâtiments
7#[async_trait]
8pub trait BuildingRepository: Send + Sync {
9    async fn create(&self, building: &Building) -> Result<Building, String>;
10    async fn find_by_id(&self, id: Uuid) -> Result<Option<Building>, String>;
11    async fn find_all(&self) -> Result<Vec<Building>, String>;
12
13    /// Find all buildings with pagination and filters
14    /// Returns tuple of (buildings, total_count)
15    async fn find_all_paginated(
16        &self,
17        page_request: &PageRequest,
18        filters: &BuildingFilters,
19    ) -> Result<(Vec<Building>, i64), String>;
20
21    async fn update(&self, building: &Building) -> Result<Building, String>;
22    async fn delete(&self, id: Uuid) -> Result<bool, String>;
23
24    /// Find building by URL slug (for public pages - Issue #92)
25    async fn find_by_slug(&self, slug: &str) -> Result<Option<Building>, String>;
26
27    /// Story 1.4 — Find building + aggregate metrics in a single query
28    /// (LEFT JOIN units + COUNT(*) + SUM(quota::NUMERIC)).
29    ///
30    /// Decimal strict (cf. ADR-0007 + mémoire `no-f64-in-money`) — SUM est
31    /// cast en NUMERIC côté SQL pour éviter toute conversion float.
32    /// Renvoie `Ok(None)` si l'id n'existe pas (le use-case mappera en
33    /// `AppError::NotFound`).
34    async fn find_by_id_with_metrics(
35        &self,
36        id: Uuid,
37    ) -> Result<Option<(Building, BuildingMetrics)>, String>;
38}