db/herodb_old/src/models/gov/committee.rs
2025-04-22 12:53:17 +04:00

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"
}
}