pub trait AcpRepository: Send + Sync {
// Required methods
fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn find_by_id<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<Acp>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn find_by_id_with_metrics<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn list<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<Acp>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn list_with_metrics<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn update<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn archive<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<(), AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn count_buildings<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
}Expand description
Port repository ACP.
Required Methods§
Sourcefn create<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn create<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Persiste une nouvelle ACP. Retourne l’entité telle que stockée
(incl. created_at / updated_at côté DB si différents).
Sourcefn find_by_id<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<Acp>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn find_by_id<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<Acp>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Récupère par id. None si absent (pas une erreur).
Sourcefn find_by_id_with_metrics<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn find_by_id_with_metrics<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<Option<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Story H6 (CL1) — récupère l’ACP avec ses métriques agrégées (Σ units,
Σ lots déclarés, Σ quotités, nb blocs) sur TOUS ses buildings. Source
de vérité de la conformité ACP-level (Acp::assert_conformant, ADR-0010).
None si l’ACP n’existe pas.
Sourcefn list<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<Acp>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<Acp>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Liste filtrée par scope. Tri implémentation : created_at DESC.
Sourcefn list_with_metrics<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn list_with_metrics<'life0, 'async_trait>(
&'life0 self,
scope: ListScope,
) -> Pin<Box<dyn Future<Output = Result<Vec<(Acp, AcpMetrics)>, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
La même liste, avec les métriques de chaque ACP.
── Pourquoi une seconde méthode plutôt qu’un enrichissement ────────
find_by_id_with_metrics existait déjà, mais par identifiant : afficher
une table de quatre ACP demandait quatre allers-retours, et cinquante
en demandaient cinquante. Le tableau de bord du syndic montre ses ACP
avec leurs blocs, leurs lots encodés et déclarés, et la somme de leurs
quotités — c’est une lecture de liste, pas quatre lectures unitaires.
Elle est SÉPARÉE de list parce que les métriques coûtent quatre
sous-requêtes par ligne : les appelants qui n’ont besoin que des noms
— un sélecteur, une liste déroulante — ne doivent pas les payer.
Les sous-requêtes sont identiques à celles de
find_by_id_with_metrics. Deux définitions divergentes de « lots
encodés » seraient pires que pas de table du tout : la fiche d’une ACP
et la ligne de la même ACP dans la liste afficheraient des nombres
différents, sans qu’on sache lequel croire.
Sourcefn update<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn update<'life0, 'life1, 'async_trait>(
&'life0 self,
acp: &'life1 Acp,
) -> Pin<Box<dyn Future<Output = Result<Acp, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Met à jour une ACP existante (UPDATE … WHERE id = $1).
Retourne AppError::NotFound si aucune ligne affectée.
Sourcefn archive<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<(), AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn archive<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<(), AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
“Archive” = DELETE physique pour cette Story 1.1 (pas de soft-delete
en v0.1.0 sur cette table ; la story 5.1 introduira archived_at sur
acp_enabled_modules, pas ici). Retourne Ok(()) si suppression OK,
AppError::NotFound si aucune ligne affectée.
Sourcefn count_buildings<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn count_buildings<'life0, 'async_trait>(
&'life0 self,
id: Uuid,
) -> Pin<Box<dyn Future<Output = Result<i64, AppError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Compte les buildings rattachés à l’ACP (utilisé par use-cases /
fiche ACP). Renvoie 0 tant que la story 1.2 n’a pas ajouté la
colonne buildings.acp_id ; alors la méthode reste compatible
puisque le SQL utilise COALESCE.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".