diff options
Diffstat (limited to 'src/infrastructure/persistence/calendar_repository.rs')
| -rw-r--r-- | src/infrastructure/persistence/calendar_repository.rs | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/src/infrastructure/persistence/calendar_repository.rs b/src/infrastructure/persistence/calendar_repository.rs new file mode 100644 index 0000000..d0b758d --- /dev/null +++ b/src/infrastructure/persistence/calendar_repository.rs @@ -0,0 +1,119 @@ +use async_trait::async_trait; +use sqlx::SqlitePool; +use crate::{ + domain::{ + calendar::Calendar, + repository::{CalendarRepository, RepositoryError, Result}, + value_objects::CalendarId, + }, + infrastructure::persistence::models::CalendarModel +}; +use super::mappers::CalendarMapper; + +pub struct SqliteCalendarRepository { + pool: SqlitePool, +} + +impl SqliteCalendarRepository { + pub fn new(pool: SqlitePool) -> Self { + Self { pool } + } +} + +#[async_trait] +impl CalendarRepository for SqliteCalendarRepository { + async fn save(&self, calendar: &Calendar) -> Result<()> { + let model = CalendarMapper::to_model(calendar); + + sqlx::query!( + r#" + INSERT INTO calendars ( + id, name, description, is_archived, + created_at, updated_at + ) + VALUES (?1, ?2, ?3, ?4, ?5, ?6) + ON CONFLICT(id) DO UPDATE SET + name = excluded.name, + description = excluded.description, + is_archived = excluded.is_archived, + updated_at = excluded.updated_at + "#, + model.id, + model.name, + model.description, + model.is_archived, + model.created_at, + model.updated_at, + ) + .execute(&self.pool) + .await + .map_err(|e| RepositoryError::DatabaseError(e.to_string()))?; + + Ok(()) + } + + async fn find_by_id(&self, id: &CalendarId) -> Result<Option<Calendar>> { + let id_str = id.to_string(); + + let model = sqlx::query_as::<_, CalendarModel>( + r#" + SELECT id, name, description, is_archived, created_at, updated_at + FROM calendars + WHERE id = ?1 + "# + ) + .bind(&id_str) + .fetch_optional(&self.pool) + .await + .map_err(|e| RepositoryError::DatabaseError(e.to_string()))?; + + match model { + Some(m) => { + let calendar = CalendarMapper::to_domain(m) + .map_err(|e| RepositoryError::DatabaseError(e))?; + Ok(Some(calendar)) + } + None => Ok(None), + } + } + + async fn find_all_active(&self) -> Result<Vec<Calendar>> { + let models = sqlx::query_as::<_, CalendarModel>( + r#" + SELECT id, name, description, is_archived, created_at, updated_at + FROM calendars + WHERE is_archived = 0 + ORDER BY name + "# + ) + .fetch_all(&self.pool) + .await + .map_err(|e| RepositoryError::DatabaseError(e.to_string()))?; + + models + .into_iter() + .map(|m| CalendarMapper::to_domain(m) + .map_err(|e| RepositoryError::DatabaseError(e))) + .collect() + } + + async fn delete(&self, id: &CalendarId) -> Result<()> { + let id_str = id.to_string(); + + let result = sqlx::query!( + r#" + DELETE FROM calendars WHERE id = ?1 + "#, + id_str, + ) + .execute(&self.pool) + .await + .map_err(|e| RepositoryError::DatabaseError(e.to_string()))?; + + if result.rows_affected() == 0 { + return Err(RepositoryError::NotFound); + } + + Ok(()) + } +} |