koprogo_api/application/use_cases/
meeting_use_cases.rs

1use crate::application::dto::{
2    AddAgendaItemRequest, CompleteMeetingRequest, CreateMeetingRequest, MeetingResponse,
3    PageRequest, UpdateMeetingRequest,
4};
5use crate::application::ports::MeetingRepository;
6use crate::domain::entities::Meeting;
7use std::sync::Arc;
8use uuid::Uuid;
9
10pub struct MeetingUseCases {
11    repository: Arc<dyn MeetingRepository>,
12}
13
14impl MeetingUseCases {
15    pub fn new(repository: Arc<dyn MeetingRepository>) -> Self {
16        Self { repository }
17    }
18
19    pub async fn create_meeting(
20        &self,
21        request: CreateMeetingRequest,
22    ) -> Result<MeetingResponse, String> {
23        let meeting = Meeting::new(
24            request.organization_id,
25            request.building_id,
26            request.meeting_type,
27            request.title,
28            request.description,
29            request.scheduled_date,
30            request.location,
31        )?;
32
33        let created = self.repository.create(&meeting).await?;
34        Ok(MeetingResponse::from(created))
35    }
36
37    pub async fn get_meeting(&self, id: Uuid) -> Result<Option<MeetingResponse>, String> {
38        let meeting = self.repository.find_by_id(id).await?;
39        Ok(meeting.map(MeetingResponse::from))
40    }
41
42    pub async fn list_meetings_by_building(
43        &self,
44        building_id: Uuid,
45    ) -> Result<Vec<MeetingResponse>, String> {
46        let meetings = self.repository.find_by_building(building_id).await?;
47        Ok(meetings.into_iter().map(MeetingResponse::from).collect())
48    }
49
50    pub async fn list_meetings_paginated(
51        &self,
52        page_request: &PageRequest,
53        organization_id: Option<Uuid>,
54    ) -> Result<(Vec<MeetingResponse>, i64), String> {
55        let (meetings, total) = self
56            .repository
57            .find_all_paginated(page_request, organization_id)
58            .await?;
59
60        let dtos = meetings.into_iter().map(MeetingResponse::from).collect();
61        Ok((dtos, total))
62    }
63
64    pub async fn update_meeting(
65        &self,
66        id: Uuid,
67        request: UpdateMeetingRequest,
68    ) -> Result<MeetingResponse, String> {
69        let mut meeting = self
70            .repository
71            .find_by_id(id)
72            .await?
73            .ok_or_else(|| "Meeting not found".to_string())?;
74
75        // Update fields if provided
76        if let Some(title) = request.title {
77            if title.is_empty() {
78                return Err("Title cannot be empty".to_string());
79            }
80            meeting.title = title;
81        }
82
83        if let Some(description) = request.description {
84            meeting.description = Some(description);
85        }
86
87        if let Some(scheduled_date) = request.scheduled_date {
88            meeting.scheduled_date = scheduled_date;
89        }
90
91        if let Some(location) = request.location {
92            if location.is_empty() {
93                return Err("Location cannot be empty".to_string());
94            }
95            meeting.location = location;
96        }
97
98        meeting.updated_at = chrono::Utc::now();
99
100        let updated = self.repository.update(&meeting).await?;
101        Ok(MeetingResponse::from(updated))
102    }
103
104    pub async fn add_agenda_item(
105        &self,
106        id: Uuid,
107        request: AddAgendaItemRequest,
108    ) -> Result<MeetingResponse, String> {
109        let mut meeting = self
110            .repository
111            .find_by_id(id)
112            .await?
113            .ok_or_else(|| "Meeting not found".to_string())?;
114
115        meeting.add_agenda_item(request.item)?;
116
117        let updated = self.repository.update(&meeting).await?;
118        Ok(MeetingResponse::from(updated))
119    }
120
121    pub async fn complete_meeting(
122        &self,
123        id: Uuid,
124        request: CompleteMeetingRequest,
125    ) -> Result<MeetingResponse, String> {
126        let mut meeting = self
127            .repository
128            .find_by_id(id)
129            .await?
130            .ok_or_else(|| "Meeting not found".to_string())?;
131
132        meeting.complete(request.attendees_count);
133
134        let updated = self.repository.update(&meeting).await?;
135        Ok(MeetingResponse::from(updated))
136    }
137
138    pub async fn cancel_meeting(&self, id: Uuid) -> Result<MeetingResponse, String> {
139        let mut meeting = self
140            .repository
141            .find_by_id(id)
142            .await?
143            .ok_or_else(|| "Meeting not found".to_string())?;
144
145        meeting.cancel();
146
147        let updated = self.repository.update(&meeting).await?;
148        Ok(MeetingResponse::from(updated))
149    }
150
151    pub async fn delete_meeting(&self, id: Uuid) -> Result<bool, String> {
152        self.repository.delete(id).await
153    }
154}