From 05d2d7751547f36cc6fad4ca641885fce95dbc53 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Tue, 17 Mar 2026 14:32:02 +0100 Subject: [PATCH] feat(infra): schedule history list, get-by-id, delete-after methods --- .../infra/src/schedule_repository/sqlite.rs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/k-tv-backend/infra/src/schedule_repository/sqlite.rs b/k-tv-backend/infra/src/schedule_repository/sqlite.rs index 2f2dff1..b699b05 100644 --- a/k-tv-backend/infra/src/schedule_repository/sqlite.rs +++ b/k-tv-backend/infra/src/schedule_repository/sqlite.rs @@ -4,6 +4,7 @@ use chrono::{DateTime, Utc}; use std::collections::HashMap; use domain::{BlockId, ChannelId, DomainError, DomainResult, GeneratedSchedule, MediaItemId, PlaybackRecord, ScheduleRepository}; +use uuid::Uuid; use super::mapping::{map_schedule, LastSlotRow, PlaybackRecordRow, ScheduleRow, SlotRow}; @@ -183,6 +184,77 @@ impl ScheduleRepository for SqliteScheduleRepository { Ok(map) } + async fn list_schedule_history( + &self, + channel_id: ChannelId, + ) -> DomainResult> { + let rows: Vec = sqlx::query_as( + "SELECT id, channel_id, valid_from, valid_until, generation \ + FROM generated_schedules WHERE channel_id = ? ORDER BY generation DESC", + ) + .bind(channel_id.to_string()) + .fetch_all(&self.pool) + .await + .map_err(|e| DomainError::RepositoryError(e.to_string()))?; + + rows.into_iter() + .map(|r| map_schedule(r, vec![])) + .collect() + } + + async fn get_schedule_by_id( + &self, + channel_id: ChannelId, + schedule_id: Uuid, + ) -> DomainResult> { + let row: Option = sqlx::query_as( + "SELECT id, channel_id, valid_from, valid_until, generation \ + FROM generated_schedules WHERE id = ? AND channel_id = ?", + ) + .bind(schedule_id.to_string()) + .bind(channel_id.to_string()) + .fetch_optional(&self.pool) + .await + .map_err(|e| DomainError::RepositoryError(e.to_string()))?; + + match row { + None => Ok(None), + Some(r) => { + let slots = self.fetch_slots(&r.id).await?; + Some(map_schedule(r, slots)).transpose() + } + } + } + + async fn delete_schedules_after( + &self, + channel_id: ChannelId, + target_generation: u32, + ) -> DomainResult<()> { + let target_gen = target_generation as i64; + let ch = channel_id.to_string(); + + sqlx::query( + "DELETE FROM playback_records WHERE channel_id = ? AND generation > ?", + ) + .bind(&ch) + .bind(target_gen) + .execute(&self.pool) + .await + .map_err(|e| DomainError::RepositoryError(e.to_string()))?; + + sqlx::query( + "DELETE FROM generated_schedules WHERE channel_id = ? AND generation > ?", + ) + .bind(&ch) + .bind(target_gen) + .execute(&self.pool) + .await + .map_err(|e| DomainError::RepositoryError(e.to_string()))?; + + Ok(()) + } + async fn save_playback_record(&self, record: &PlaybackRecord) -> DomainResult<()> { sqlx::query( r#"