Skip to main content

koprogo_api/infrastructure/database/repositories/
board_alert_repository_impl.rs

1use crate::application::error::AppError;
2use crate::application::ports::BoardAlertRepository;
3use crate::domain::entities::{AlertSeverity, BoardAlert};
4use crate::infrastructure::database::pool::DbPool;
5use async_trait::async_trait;
6use sqlx::Row;
7use uuid::Uuid;
8
9pub struct PostgresBoardAlertRepository {
10    pool: DbPool,
11}
12
13impl PostgresBoardAlertRepository {
14    pub fn new(pool: DbPool) -> Self {
15        Self { pool }
16    }
17}
18
19fn row_to_alert(row: sqlx::postgres::PgRow) -> BoardAlert {
20    let severity_str: String = row.get("severity");
21    let severity = severity_str.parse().unwrap_or(AlertSeverity::Info);
22
23    BoardAlert {
24        id: row.get("id"),
25        building_id: row.get("building_id"),
26        raised_by_board_member_id: row.get("raised_by_board_member_id"),
27        text: row.get("text"),
28        severity,
29        target_meeting_id: row.get("target_meeting_id"),
30        created_at: row.get("created_at"),
31    }
32}
33
34#[async_trait]
35impl BoardAlertRepository for PostgresBoardAlertRepository {
36    async fn create(&self, alert: &BoardAlert) -> Result<BoardAlert, AppError> {
37        sqlx::query(
38            r#"
39            INSERT INTO board_alerts
40                (id, building_id, raised_by_board_member_id, text, severity, target_meeting_id, created_at)
41            VALUES ($1, $2, $3, $4, $5, $6, $7)
42            "#,
43        )
44        .bind(alert.id)
45        .bind(alert.building_id)
46        .bind(alert.raised_by_board_member_id)
47        .bind(&alert.text)
48        .bind(alert.severity.to_string())
49        .bind(alert.target_meeting_id)
50        .bind(alert.created_at)
51        .execute(&self.pool)
52        .await
53        .map_err(|e| AppError::Database(format!("Failed to create board alert: {}", e)))?;
54
55        Ok(alert.clone())
56    }
57
58    async fn find_by_target_meeting(&self, meeting_id: Uuid) -> Result<Vec<BoardAlert>, AppError> {
59        let rows = sqlx::query(
60            r#"
61            SELECT id, building_id, raised_by_board_member_id, text, severity, target_meeting_id, created_at
62            FROM board_alerts
63            WHERE target_meeting_id = $1
64            ORDER BY created_at ASC
65            "#,
66        )
67        .bind(meeting_id)
68        .fetch_all(&self.pool)
69        .await
70        .map_err(|e| AppError::Database(format!("Failed to list board alerts: {}", e)))?;
71
72        Ok(rows.into_iter().map(row_to_alert).collect())
73    }
74}