lmrc-cli 0.3.16

CLI tool for scaffolding LMRC Stack infrastructure projects
Documentation
//! Domain models for examples feature
//!
//! These are your core business entities. They should be:
//! - Independent of database/HTTP concerns
//! - Contain validation logic
//! - Express business rules clearly

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;

/// User entity - represents a user in the system
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
    pub id: Uuid,
    pub email: String,
    pub name: String,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

/// Request to create a new user
#[derive(Debug, Deserialize)]
pub struct CreateUserRequest {
    pub email: String,
    pub name: String,
}

impl CreateUserRequest {
    /// Validate the create user request
    pub fn validate(&self) -> Result<(), String> {
        if self.email.is_empty() {
            return Err("Email cannot be empty".to_string());
        }

        if !self.email.contains('@') {
            return Err("Email must be valid".to_string());
        }

        if self.name.is_empty() {
            return Err("Name cannot be empty".to_string());
        }

        if self.name.len() < 2 {
            return Err("Name must be at least 2 characters".to_string());
        }

        Ok(())
    }
}

/// Request to update an existing user
#[derive(Debug, Deserialize)]
pub struct UpdateUserRequest {
    pub email: Option<String>,
    pub name: Option<String>,
}

impl UpdateUserRequest {
    /// Validate the update user request
    pub fn validate(&self) -> Result<(), String> {
        if let Some(email) = &self.email {
            if email.is_empty() {
                return Err("Email cannot be empty".to_string());
            }
            if !email.contains('@') {
                return Err("Email must be valid".to_string());
            }
        }

        if let Some(name) = &self.name {
            if name.is_empty() {
                return Err("Name cannot be empty".to_string());
            }
            if name.len() < 2 {
                return Err("Name must be at least 2 characters".to_string());
            }
        }

        Ok(())
    }
}

/// Response for listing users with pagination
#[derive(Debug, Serialize)]
pub struct UserListResponse {
    pub users: Vec<User>,
    pub total: u64,
    pub page: u64,
    pub per_page: u64,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_create_user_validation_valid() {
        let request = CreateUserRequest {
            email: "test@example.com".to_string(),
            name: "Test User".to_string(),
        };

        assert!(request.validate().is_ok());
    }

    #[test]
    fn test_create_user_validation_empty_email() {
        let request = CreateUserRequest {
            email: "".to_string(),
            name: "Test User".to_string(),
        };

        assert!(request.validate().is_err());
    }

    #[test]
    fn test_create_user_validation_invalid_email() {
        let request = CreateUserRequest {
            email: "invalid-email".to_string(),
            name: "Test User".to_string(),
        };

        assert!(request.validate().is_err());
    }

    #[test]
    fn test_create_user_validation_short_name() {
        let request = CreateUserRequest {
            email: "test@example.com".to_string(),
            name: "A".to_string(),
        };

        assert!(request.validate().is_err());
    }

    #[test]
    fn test_update_user_validation_valid() {
        let request = UpdateUserRequest {
            email: Some("updated@example.com".to_string()),
            name: Some("Updated Name".to_string()),
        };

        assert!(request.validate().is_ok());
    }

    #[test]
    fn test_update_user_validation_partial() {
        let request = UpdateUserRequest {
            email: Some("updated@example.com".to_string()),
            name: None,
        };

        assert!(request.validate().is_ok());
    }
}