use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use crate::db::{Model, Storable, DB, DbError, DbResult}; use crate::models::gov::User; /// CommitteeRole represents the role of a member in a committee #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum CommitteeRole { Chair, ViceChair, Secretary, Member, Advisor, Observer, } /// CommitteeMember represents a member of a committee #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct CommitteeMember { pub id: u32, pub committee_id: u32, pub user_id: u32, pub name: String, pub role: CommitteeRole, pub since: DateTime, pub created_at: DateTime, } /// Committee represents a board committee #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Committee { pub id: u32, pub company_id: u32, pub name: String, pub description: String, pub purpose: String, pub circle_id: Option, // Link to Circle for access control pub created_at: DateTime, pub updated_at: DateTime, pub members: Vec, } impl Committee { /// Create a new committee with default values pub fn new( id: u32, company_id: u32, name: String, description: String, purpose: String, ) -> Self { let now = Utc::now(); Self { id, company_id, name, description, purpose, circle_id: None, created_at: now, updated_at: now, members: Vec::new(), } } /// Add a member to the committee pub fn add_member(&mut self, user_id: u32, name: String, role: CommitteeRole) -> &CommitteeMember { let id = if self.members.is_empty() { 1 } else { self.members.iter().map(|m| m.id).max().unwrap_or(0) + 1 }; let now = Utc::now(); let member = CommitteeMember { id, committee_id: self.id, user_id, name, role, since: now, created_at: now, }; self.members.push(member); self.updated_at = now; self.members.last().unwrap() } /// Find a member by user ID pub fn find_member_by_user_id(&self, user_id: u32) -> Option<&CommitteeMember> { self.members.iter().find(|m| m.user_id == user_id) } /// Find a member by user ID (mutable version) pub fn find_member_by_user_id_mut(&mut self, user_id: u32) -> Option<&mut CommitteeMember> { self.members.iter_mut().find(|m| m.user_id == user_id) } /// Remove a member from the committee pub fn remove_member(&mut self, member_id: u32) -> bool { let len = self.members.len(); self.members.retain(|m| m.id != member_id); let removed = self.members.len() < len; if removed { self.updated_at = Utc::now(); } removed } /// Link this committee to a Circle for access control pub fn link_to_circle(&mut self, circle_id: u32) { self.circle_id = Some(circle_id); self.updated_at = Utc::now(); } /// Get all users who are members of this committee pub fn get_member_users(&self, db: &DB) -> DbResult> { let mut users = Vec::new(); for member in &self.members { if let Ok(user) = db.get::(member.user_id) { users.push(user); } } Ok(users) } } // Implement Storable trait impl Storable for Committee { } impl Storable for CommitteeMember { } // Implement Model trait impl Model for Committee { fn get_id(&self) -> u32 { self.id } fn db_prefix() -> &'static str { "committee" } }