Skip to main content

koprogo_api/application/dto/
ag_session_dto.rs

1use crate::domain::entities::ag_session::AgSession;
2use chrono::{DateTime, Utc};
3use rust_decimal::Decimal;
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7/// DTO de création d'une session AG visioconférence
8#[derive(Debug, Clone, Deserialize)]
9pub struct CreateAgSessionDto {
10    pub meeting_id: Uuid,
11    pub platform: String, // "zoom" | "microsoft_teams" | "google_meet" | "jitsi" | "whereby" | "other"
12    pub video_url: String,
13    pub host_url: Option<String>,
14    pub scheduled_start: DateTime<Utc>,
15    pub access_password: Option<String>,
16    pub waiting_room_enabled: Option<bool>,
17    pub recording_enabled: Option<bool>,
18}
19
20/// DTO pour terminer une session
21#[derive(Debug, Clone, Deserialize)]
22pub struct EndAgSessionDto {
23    pub recording_url: Option<String>,
24}
25
26/// DTO pour enregistrer un participant distant
27#[derive(Debug, Clone, Deserialize)]
28pub struct RecordRemoteJoinDto {
29    #[serde(with = "rust_decimal::serde::float")]
30    pub voting_power: Decimal,
31    #[serde(with = "rust_decimal::serde::float")]
32    pub total_building_quotas: Decimal,
33}
34
35/// Réponse API pour une session AG
36#[derive(Debug, Clone, Serialize)]
37pub struct AgSessionResponse {
38    pub id: Uuid,
39    pub organization_id: Uuid,
40    pub meeting_id: Uuid,
41    pub platform: String,
42    pub video_url: String,
43    pub host_url: Option<String>,
44    pub status: String,
45    pub scheduled_start: DateTime<Utc>,
46    pub actual_start: Option<DateTime<Utc>>,
47    pub actual_end: Option<DateTime<Utc>>,
48    pub remote_attendees_count: i32,
49    #[serde(with = "rust_decimal::serde::float")]
50    pub remote_voting_power: Decimal,
51    #[serde(with = "rust_decimal::serde::float")]
52    pub quorum_remote_contribution: Decimal,
53    pub waiting_room_enabled: bool,
54    pub recording_enabled: bool,
55    pub recording_url: Option<String>,
56    pub duration_minutes: Option<i64>,
57    pub created_at: DateTime<Utc>,
58    pub updated_at: DateTime<Utc>,
59    pub created_by: Uuid,
60}
61
62/// Réponse pour le calcul du quorum combiné
63#[derive(Debug, Clone, Serialize)]
64pub struct CombinedQuorumResponse {
65    pub session_id: Uuid,
66    pub meeting_id: Uuid,
67    #[serde(with = "rust_decimal::serde::float")]
68    pub physical_quotas: Decimal,
69    #[serde(with = "rust_decimal::serde::float")]
70    pub remote_quotas: Decimal,
71    #[serde(with = "rust_decimal::serde::float")]
72    pub total_building_quotas: Decimal,
73    #[serde(with = "rust_decimal::serde::float")]
74    pub combined_percentage: Decimal,
75    /// Volet « têtes » du quorum double (#661) — présents physiquement,
76    /// connectés en visio, et total des copropriétaires.
77    pub physical_owners_count: i32,
78    pub remote_attendees_count: i32,
79    pub total_owners_count: i32,
80    /// Art. 3.87 §5 CC — décidé par `AgSession::is_combined_quorum_reached`,
81    /// qui applique le quorum DOUBLE (têtes ET quotités) de
82    /// `Meeting::double_quorum_reached`. Jamais recalculé ici.
83    pub quorum_reached: bool,
84}
85
86impl From<&AgSession> for AgSessionResponse {
87    fn from(s: &AgSession) -> Self {
88        Self {
89            id: s.id,
90            organization_id: s.organization_id,
91            meeting_id: s.meeting_id,
92            platform: s.platform.to_db_str().to_string(),
93            video_url: s.video_url.clone(),
94            host_url: s.host_url.clone(),
95            status: s.status.to_db_str().to_string(),
96            scheduled_start: s.scheduled_start,
97            actual_start: s.actual_start,
98            actual_end: s.actual_end,
99            remote_attendees_count: s.remote_attendees_count,
100            remote_voting_power: s.remote_voting_power,
101            quorum_remote_contribution: s.quorum_remote_contribution,
102            waiting_room_enabled: s.waiting_room_enabled,
103            recording_enabled: s.recording_enabled,
104            recording_url: s.recording_url.clone(),
105            duration_minutes: s.duration_minutes(),
106            created_at: s.created_at,
107            updated_at: s.updated_at,
108            created_by: s.created_by,
109        }
110    }
111}