koprogo_api/application/ports/meeting_completion_checker.rs
1//! Track H Story H3 — Port `MeetingCompletionCheckerPort`.
2//!
3//! Construit la `MeetingCompletionChecklist` (cf. domain) à partir de l'état
4//! DB courant (convocations, résolutions, présences, units, minutes). Une
5//! seule query SQL agrégée fait le travail (cf. adapter sqlx
6//! `meeting_completion_checker_impl.rs`).
7//!
8//! **Hexagonal** : ce port permet à `Meeting::assert_can_complete()` de rester
9//! pur (pas d'I/O). Le use-case `complete_meeting()` orchestre :
10//! 1. `completion_checker.build_checklist(meeting_id)` (DB)
11//! 2. `meeting.assert_can_complete(&checklist)` (pure domain)
12//! 3. `meeting.complete_internal()` (state machine)
13
14use async_trait::async_trait;
15use uuid::Uuid;
16
17use crate::domain::entities::MeetingCompletionChecklist;
18
19#[async_trait]
20pub trait MeetingCompletionCheckerPort: Send + Sync {
21 /// Construit la checklist Art. 3.87 §3-5 CC pour le meeting donné.
22 ///
23 /// Retourne `Err(String)` si :
24 /// - le meeting n'existe pas (ou est soft-deleted).
25 /// - la query DB échoue (timeout, contrainte, etc.).
26 ///
27 /// **Pas de side-effect** : pure read-only.
28 async fn build_checklist(&self, meeting_id: Uuid)
29 -> Result<MeetingCompletionChecklist, String>;
30}