//! SeaORM entity for Mentors table //! Corresponding to ResourceEnum::Mentors use chrono::{DateTime, Utc}; use sea_orm::entity::prelude::*; use sea_orm::{ActiveModelBehavior, DeriveEntityModel, DeriveRelation}; use sea_orm::ActiveValue::Set; use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Deserialize, imphnen_macros::Builder)] #[sea_orm(table_name = "app_mentors")] pub struct Model { #[sea_orm(primary_key, default = "gen_random_uuid()", auto_increment = false)] pub id: Uuid, #[sea_orm(unique, not_null)] pub user_id: Uuid, #[sea_orm(type = "jsonb", nullable)] pub industries: Option, #[sea_orm(type = "jsonb", nullable)] pub expertise: Option, #[sea_orm(type = "jsonb", nullable)] pub languages: Option, #[sea_orm(nullable)] pub current_company: Option, #[sea_orm(nullable)] pub current_role: Option, #[sea_orm(nullable)] pub years_of_experience: Option, #[sea_orm(type = "jsonb", nullable)] pub topics_of_interest: Option, #[sea_orm(nullable)] pub preferred_mentee_level: Option, #[sea_orm(type = "jsonb", nullable)] pub preferred_mentoring_formats: Option, #[sea_orm(nullable)] pub availability_commitment: Option, #[sea_orm(nullable)] pub mentoring_rate: Option, #[sea_orm(nullable)] pub status: Option, #[sea_orm(default = "false")] pub is_deleted: bool, #[sea_orm(not_null, default = "now()")] pub created_at: DateTime, #[sea_orm(not_null, default = "now()")] pub updated_at: DateTime, } #[derive(Copy, Clone, Debug, sea_orm::EnumIter, DeriveRelation)] pub enum Relation { #[sea_orm(belongs_to = "super::users::Entity", from = "Column::UserId", to = "super::users::Column::Id")] User, } impl Related for Entity { fn to() -> RelationDef { Relation::User.def() } } impl ActiveModelBehavior for ActiveModel { // Default implementation - SeaORM will handle timestamps automatically } // Builder pattern for Mentor creation #[derive(Default, Serialize, Deserialize)] pub struct MentorBuilder { user_id: Option, industries: Option>, expertise: Option>, languages: Option>, current_company: Option, current_role: Option, years_of_experience: Option, topics_of_interest: Option>, preferred_mentee_level: Option, preferred_mentoring_formats: Option>, availability_commitment: Option, mentoring_rate: Option, status: Option, is_deleted: Option, } impl MentorBuilder { #[must_use] pub fn new() -> Self { Self::default() } #[must_use] pub fn user_id(mut self, user_id: Uuid) -> Self { self.user_id = Some(user_id); self } #[must_use] pub fn industries(mut self, industries: Vec) -> Self { self.industries = Some(industries); self } #[must_use] pub fn expertise(mut self, expertise: Vec) -> Self { self.expertise = Some(expertise); self } #[must_use] pub fn languages(mut self, languages: Vec) -> Self { self.languages = Some(languages); self } #[must_use] pub fn current_company(mut self, current_company: String) -> Self { self.current_company = Some(current_company); self } #[must_use] pub fn current_role(mut self, current_role: String) -> Self { self.current_role = Some(current_role); self } #[must_use] pub fn years_of_experience(mut self, years_of_experience: i32) -> Self { self.years_of_experience = Some(years_of_experience); self } #[must_use] pub fn topics_of_interest(mut self, topics_of_interest: Vec) -> Self { self.topics_of_interest = Some(topics_of_interest); self } #[must_use] pub fn preferred_mentee_level(mut self, preferred_mentee_level: String) -> Self { self.preferred_mentee_level = Some(preferred_mentee_level); self } #[must_use] pub fn preferred_mentoring_formats(mut self, preferred_mentoring_formats: Vec) -> Self { self.preferred_mentoring_formats = Some(preferred_mentoring_formats); self } #[must_use] pub fn availability_commitment(mut self, availability_commitment: String) -> Self { self.availability_commitment = Some(availability_commitment); self } #[must_use] pub fn mentoring_rate(mut self, mentoring_rate: f64) -> Self { self.mentoring_rate = Some(mentoring_rate); self } #[must_use] pub fn status(mut self, status: String) -> Self { self.status = Some(status); self } #[must_use] pub fn is_deleted(mut self, is_deleted: bool) -> Self { self.is_deleted = Some(is_deleted); self } pub fn build(self) -> Result { let mut active_model = ::default(); if let Some(user_id) = self.user_id { active_model.user_id = Set(user_id); } else { return Err("User ID is required".to_string()); } if let Some(industries) = self.industries { active_model.industries = Set(Some(serde_json::to_value(industries).map_err(|e| format!("Failed to serialize industries: {}", e))?)); } if let Some(expertise) = self.expertise { active_model.expertise = Set(Some(serde_json::to_value(expertise).map_err(|e| format!("Failed to serialize expertise: {}", e))?)); } if let Some(languages) = self.languages { active_model.languages = Set(Some(serde_json::to_value(languages).map_err(|e| format!("Failed to serialize languages: {}", e))?)); } if let Some(current_company) = self.current_company { active_model.current_company = Set(Some(current_company)); } if let Some(current_role) = self.current_role { active_model.current_role = Set(Some(current_role)); } if let Some(years_of_experience) = self.years_of_experience { active_model.years_of_experience = Set(Some(years_of_experience)); } if let Some(topics_of_interest) = self.topics_of_interest { active_model.topics_of_interest = Set(Some(serde_json::to_value(topics_of_interest).map_err(|e| format!("Failed to serialize topics_of_interest: {}", e))?)); } if let Some(preferred_mentee_level) = self.preferred_mentee_level { active_model.preferred_mentee_level = Set(Some(preferred_mentee_level)); } if let Some(preferred_mentoring_formats) = self.preferred_mentoring_formats { active_model.preferred_mentoring_formats = Set(Some(serde_json::to_value(preferred_mentoring_formats).map_err(|e| format!("Failed to serialize preferred_mentoring_formats: {}", e))?)); } if let Some(availability_commitment) = self.availability_commitment { active_model.availability_commitment = Set(Some(availability_commitment)); } if let Some(mentoring_rate) = self.mentoring_rate { active_model.mentoring_rate = Set(Some(mentoring_rate)); } if let Some(status) = self.status { active_model.status = Set(Some(status)); } if let Some(is_deleted) = self.is_deleted { active_model.is_deleted = Set(is_deleted); } Ok(active_model) } } #[cfg(test)] mod tests { use super::*; use crate::seaorm::common::utils::generate_uuid; use serde_json::json; #[test] fn test_mentor_model_creation() { let uid = generate_uuid(); let mentor = MentorBuilder::new() .user_id(uid) .industries(vec!["Technology".to_string(), "Finance".to_string()]) .expertise(vec!["Blockchain".to_string(), "AI".to_string()]) .languages(vec!["English".to_string(), "Spanish".to_string()]) .current_company("Tech Corp".to_string()) .current_role("Senior Engineer".to_string()) .years_of_experience(10) .topics_of_interest(vec!["Web3".to_string(), "Machine Learning".to_string()]) .preferred_mentee_level("Intermediate".to_string()) .preferred_mentoring_formats(vec!["1:1".to_string(), "Group".to_string()]) .availability_commitment("Weekly".to_string()) .mentoring_rate(150.0) .status("active".to_string()) .build(); assert!(mentor.is_ok()); let mentor_model = mentor.unwrap(); assert_eq!(mentor_model.user_id, Set(uid)); assert_eq!(mentor_model.industries, Set(Some(json!(["Technology", "Finance"])))); assert_eq!(mentor_model.expertise, Set(Some(json!(["Blockchain", "AI"])))); } #[test] fn test_mentor_model_missing_required_fields() { let mentor = MentorBuilder::new() // Missing user_id .industries(vec!["Technology".to_string()]) .build(); assert!(mentor.is_err()); assert_eq!(mentor.unwrap_err(), "User ID is required"); } }