use crate::error::{AppError, Result};
use crate::features::examples::models::{
CreateUserRequest, UpdateUserRequest, User, UserListResponse,
};
use crate::features::examples::repository::UserRepository;
use uuid::Uuid;
#[derive(Clone)]
pub struct UserService {
repository: UserRepository,
}
impl UserService {
pub fn new(repository: UserRepository) -> Self {
Self { repository }
}
pub async fn get_user(&self, id: Uuid) -> Result<User> {
self.repository
.find_by_id(id)
.await?
.ok_or_else(|| AppError::NotFound(format!("User with id {} not found", id)))
}
pub async fn list_users(&self, page: u64, per_page: u64) -> Result<UserListResponse> {
if page == 0 {
return Err(AppError::BadRequest("Page must be at least 1".to_string()));
}
if per_page == 0 || per_page > 100 {
return Err(AppError::BadRequest(
"Per page must be between 1 and 100".to_string(),
));
}
let (users, total) = self.repository.list(page, per_page).await?;
Ok(UserListResponse {
users,
total,
page,
per_page,
})
}
pub async fn create_user(&self, request: CreateUserRequest) -> Result<User> {
request
.validate()
.map_err(|e| AppError::Validation(e.to_string()))?;
if self.repository.email_exists(&request.email).await? {
return Err(AppError::BadRequest(format!(
"User with email {} already exists",
request.email
)));
}
self.repository.create(&request).await
}
pub async fn update_user(&self, id: Uuid, request: UpdateUserRequest) -> Result<User> {
request
.validate()
.map_err(|e| AppError::Validation(e.to_string()))?;
if let Some(new_email) = &request.email {
if let Some(existing_user) = self.repository.find_by_email(new_email).await? {
if existing_user.id != id {
return Err(AppError::BadRequest(format!(
"User with email {} already exists",
new_email
)));
}
}
}
self.repository.update(id, &request).await
}
pub async fn delete_user(&self, id: Uuid) -> Result<()> {
self.get_user(id).await?;
self.repository.delete(id).await
}
pub async fn search_by_email(&self, email: &str) -> Result<Option<User>> {
self.repository.find_by_email(email).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_service_compiles() {
}
}