todo: exporter

This commit is contained in:
2026-05-09 14:30:11 +02:00
parent ebab30b1ea
commit 6cd332f758
6 changed files with 96 additions and 16 deletions

View File

@@ -36,7 +36,11 @@ RUN sqlite3 /build/dev.db \
sqlite3 /build/dev.db \
< crates/adapters/sqlite/migrations/0002_users.sql && \
sqlite3 /build/dev.db \
< crates/adapters/sqlite/migrations/0003_activitypub.sql
< crates/adapters/sqlite/migrations/0003_activitypub.sql && \
sqlite3 /build/dev.db \
< crates/adapters/sqlite/migrations/0004_username.sql && \
sqlite3 /build/dev.db \
< crates/adapters/sqlite/migrations/0005_activitypub_v2.sql
ENV DATABASE_URL=sqlite:///build/dev.db

View File

@@ -1,4 +1,5 @@
use chrono::NaiveDateTime;
use domain::models::ExportFormat;
use uuid::Uuid;
pub struct LogReviewCommand {
@@ -35,3 +36,8 @@ pub struct DeleteReviewCommand {
pub review_id: Uuid,
pub requesting_user_id: Uuid,
}
pub struct ExportCommand {
pub user_id: Uuid,
pub format: ExportFormat,
}

View File

@@ -0,0 +1,23 @@
use std::sync::Arc;
use domain::{
errors::DomainError,
ports::{DiaryExporter, MovieRepository},
};
use crate::commands::ExportCommand;
pub struct ExportDiary {
repository: Arc<dyn MovieRepository>,
exporter: Arc<dyn DiaryExporter>,
}
impl ExportDiary {
pub async fn execute(&self, req: ExportCommand) -> Result<Vec<u8>, DomainError> {
// 1. fetch all diary entries for the user
// 2. delegate serialization to the port (exporter)
// Return bytes of the exported diary, which can be written to a file or returned in an HTTP response
Ok(vec![])
}
}

View File

@@ -1,4 +1,5 @@
pub mod delete_review;
pub mod export_diary;
pub mod get_activity_feed;
pub mod get_diary;
pub mod get_review_history;

View File

@@ -262,7 +262,12 @@ pub struct User {
impl User {
pub fn new(email: Email, username: Username, password_hash: PasswordHash) -> Self {
Self { id: UserId::generate(), email, username, password_hash }
Self {
id: UserId::generate(),
email,
username,
password_hash,
}
}
pub fn from_persistence(
@@ -271,17 +276,30 @@ impl User {
username: Username,
password_hash: PasswordHash,
) -> Self {
Self { id, email, username, password_hash }
Self {
id,
email,
username,
password_hash,
}
}
pub fn update_password(&mut self, new_hash: PasswordHash) {
self.password_hash = new_hash;
}
pub fn email(&self) -> &Email { &self.email }
pub fn username(&self) -> &Username { &self.username }
pub fn id(&self) -> &UserId { &self.id }
pub fn password_hash(&self) -> &PasswordHash { &self.password_hash }
pub fn email(&self) -> &Email {
&self.email
}
pub fn username(&self) -> &Username {
&self.username
}
pub fn id(&self) -> &UserId {
&self.id
}
pub fn password_hash(&self) -> &PasswordHash {
&self.password_hash
}
}
#[derive(Clone, Debug)]
@@ -294,11 +312,20 @@ impl FeedEntry {
pub fn new(entry: DiaryEntry, user_email: String) -> Self {
Self { entry, user_email }
}
pub fn movie(&self) -> &Movie { self.entry.movie() }
pub fn review(&self) -> &Review { self.entry.review() }
pub fn user_email(&self) -> &str { &self.user_email }
pub fn movie(&self) -> &Movie {
self.entry.movie()
}
pub fn review(&self) -> &Review {
self.entry.review()
}
pub fn user_email(&self) -> &str {
&self.user_email
}
pub fn user_display_name(&self) -> &str {
self.user_email.split('@').next().unwrap_or(&self.user_email)
self.user_email
.split('@')
.next()
.unwrap_or(&self.user_email)
}
}
@@ -312,9 +339,16 @@ pub struct UserSummary {
impl UserSummary {
pub fn new(user_id: UserId, email: Email, total_movies: i64, avg_rating: Option<f64>) -> Self {
Self { user_id, email, total_movies, avg_rating }
Self {
user_id,
email,
total_movies,
avg_rating,
}
}
pub fn email(&self) -> &str {
self.email.value()
}
pub fn email(&self) -> &str { self.email.value() }
}
#[derive(Clone, Debug)]
@@ -325,7 +359,6 @@ pub struct UserStats {
pub most_active_month: Option<String>,
}
#[derive(Clone, Debug)]
pub struct MonthActivity {
pub year_month: String,
@@ -354,3 +387,8 @@ pub struct UserTrends {
pub top_directors: Vec<DirectorStat>,
pub max_director_count: i64,
}
pub enum ExportFormat {
Csv,
Json,
}

View File

@@ -6,7 +6,7 @@ use crate::{
events::DomainEvent,
models::{
DiaryEntry, DiaryFilter, FeedEntry, Movie, Review, ReviewHistory, User, UserStats,
UserTrends, UserSummary,
UserSummary, UserTrends,
collections::{PageParams, Paginated},
},
value_objects::{
@@ -57,7 +57,10 @@ pub trait MovieRepository: Send + Sync {
pub enum MetadataSearchCriteria {
ImdbId(ExternalMetadataId),
Title { title: MovieTitle, year: Option<ReleaseYear> },
Title {
title: MovieTitle,
year: Option<ReleaseYear>,
},
}
#[async_trait]
@@ -119,3 +122,8 @@ pub trait PasswordHasher: Send + Sync {
async fn verify(&self, plain_password: &str, hash: &PasswordHash) -> Result<bool, DomainError>;
}
#[async_trait]
pub trait DiaryExporter: Send + Sync {
async fn serialize_reviews(&self, reviews: &[Review]) -> Result<Vec<u8>, DomainError>;
}