149 lines
3.8 KiB
Rust
149 lines
3.8 KiB
Rust
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<Utc>,
|
|
pub created_at: DateTime<Utc>,
|
|
}
|
|
|
|
/// 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<u32>, // Link to Circle for access control
|
|
pub created_at: DateTime<Utc>,
|
|
pub updated_at: DateTime<Utc>,
|
|
pub members: Vec<CommitteeMember>,
|
|
}
|
|
|
|
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<Vec<User>> {
|
|
let mut users = Vec::new();
|
|
|
|
for member in &self.members {
|
|
if let Ok(user) = db.get::<User>(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"
|
|
}
|
|
} |