use crate::AppService; use crate::error::AppError; use chrono::Utc; use models::users::{user_activity_log, user_preferences}; use sea_orm::*; use serde::{Deserialize, Serialize}; use session::Session; use uuid::Uuid; #[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)] pub struct PreferencesParams { pub language: Option, pub theme: Option, pub timezone: Option, pub email_notifications: Option, pub in_app_notifications: Option, } #[derive(Deserialize, Serialize, Clone, Debug, utoipa::ToSchema)] pub struct PreferencesResponse { pub language: String, pub theme: String, pub timezone: String, pub email_notifications: bool, pub in_app_notifications: bool, pub created_at: chrono::DateTime, pub updated_at: chrono::DateTime, } impl From for PreferencesResponse { fn from(prefs: user_preferences::Model) -> Self { PreferencesResponse { language: prefs.language, theme: prefs.theme, timezone: prefs.timezone, email_notifications: prefs.email_notifications, in_app_notifications: prefs.in_app_notifications, created_at: prefs.created_at, updated_at: prefs.updated_at, } } } impl AppService { pub async fn user_get_preferences( &self, context: &Session, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let prefs = user_preferences::Entity::find_by_id(user_uid) .one(&self.db) .await?; if let Some(prefs) = prefs { Ok(PreferencesResponse::from(prefs)) } else { self.user_create_default_preferences(user_uid).await } } pub async fn user_update_preferences( &self, context: &Session, params: PreferencesParams, ) -> Result { let user_uid = context.user().ok_or(AppError::Unauthorized)?; let prefs = user_preferences::Entity::find_by_id(user_uid) .one(&self.db) .await?; let updated_prefs = if let Some(prefs) = prefs { let mut active_prefs: user_preferences::ActiveModel = prefs.into(); if let Some(language) = params.language.clone() { active_prefs.language = Set(language); } if let Some(theme) = params.theme.clone() { active_prefs.theme = Set(theme); } if let Some(timezone) = params.timezone.clone() { active_prefs.timezone = Set(timezone); } if let Some(email_notifications) = params.email_notifications { active_prefs.email_notifications = Set(email_notifications); } if let Some(in_app_notifications) = params.in_app_notifications { active_prefs.in_app_notifications = Set(in_app_notifications); } active_prefs.updated_at = Set(Utc::now()); active_prefs.update(&self.db).await? } else { let new_prefs = user_preferences::ActiveModel { user: Set(user_uid), language: Set(params.language.clone().unwrap_or_else(|| "en".to_string())), theme: Set(params.theme.clone().unwrap_or_else(|| "light".to_string())), timezone: Set(params.timezone.clone().unwrap_or_else(|| "UTC".to_string())), email_notifications: Set(params.email_notifications.unwrap_or(true)), in_app_notifications: Set(params.in_app_notifications.unwrap_or(true)), created_at: Set(Utc::now()), updated_at: Set(Utc::now()), }; new_prefs.insert(&self.db).await? }; let _ = user_activity_log::ActiveModel { user_uid: Set(Some(user_uid)), action: Set("preferences_update".to_string()), ip_address: Set(context.ip_address()), user_agent: Set(context.user_agent()), details: Set(serde_json::json!({ "updated_fields": { "language": params.language.is_some(), "theme": params.theme.is_some(), "timezone": params.timezone.is_some(), "email_notifications": params.email_notifications.is_some(), "in_app_notifications": params.in_app_notifications.is_some(), } })), created_at: Set(Utc::now()), ..Default::default() } .insert(&self.db) .await; Ok(PreferencesResponse::from(updated_prefs)) } async fn user_create_default_preferences( &self, user_uid: Uuid, ) -> Result { let prefs = user_preferences::ActiveModel { user: Set(user_uid), language: Set("en".to_string()), theme: Set("light".to_string()), timezone: Set("UTC".to_string()), email_notifications: Set(true), in_app_notifications: Set(true), created_at: Set(Utc::now()), updated_at: Set(Utc::now()), }; let created_prefs = prefs.insert(&self.db).await?; Ok(PreferencesResponse::from(created_prefs)) } }