14 KiB
14 KiB
Governance Module Enhancement Plan (Revised)
1. Current State Analysis
The governance module currently consists of:
- Company: Company model with basic company information
- Shareholder: Shareholder model for managing company ownership
- Meeting: Meeting and Attendee models for board meetings
- User: User model for system users
- Vote: Vote, VoteOption, and Ballot models for voting
All models implement the Storable
and SledModel
traits for database integration, but the module has several limitations:
- Not imported in src/models/mod.rs, making it inaccessible to the rest of the project
- No mod.rs file to organize and re-export the types
- No README.md file to document the purpose and usage
- Inconsistent imports across files (e.g., crate::db vs crate::core)
- Limited utility methods and relationships between models
- No integration with other modules like biz, mcc, or circle
2. Planned Enhancements
2.1 Module Organization and Integration
- Create a mod.rs file to organize and re-export the types
- Add the governance module to src/models/mod.rs
- Create a README.md file to document the purpose and usage
- Standardize imports across all files
2.2 New Models
2.2.1 Resolution Model
Create a new resolution.rs
file with a Resolution model for managing board resolutions:
- Resolution information (title, description, text)
- Resolution status (Draft, Proposed, Approved, Rejected)
- Voting results and approvals
- Integration with Meeting and Vote models
2.3 Enhanced Relationships and Integration
2.3.1 Integration with Biz Module
- Link Company with biz::Customer and biz::Contract
- Link Shareholder with biz::Customer
- Link Meeting with biz::Invoice for expense tracking
2.3.2 Integration with MCC Module
- Link Meeting with mcc::Calendar and mcc::Event
- Link User with mcc::Contact
- Link Vote with mcc::Message for notifications
2.3.3 Integration with Circle Module
- Link Company with circle::Circle for group-based access control
- Link User with circle::Member for role-based permissions
2.4 Utility Methods and Functionality
- Add filtering and searching methods to all models
- Add relationship management methods between models
- Add validation and business logic methods
3. Implementation Plan
flowchart TD
A[Review Current Models] --> B[Create mod.rs and Update models/mod.rs]
B --> C[Standardize Imports and Fix Inconsistencies]
C --> D[Create Resolution Model]
D --> E[Implement Integration with Other Modules]
E --> F[Add Utility Methods]
F --> G[Create README.md and Documentation]
G --> H[Write Tests]
3.1 Detailed Changes
3.1.1 Module Organization
Create a new mod.rs
file in the governance directory:
pub mod company;
pub mod shareholder;
pub mod meeting;
pub mod user;
pub mod vote;
pub mod resolution;
// Re-export all model types for convenience
pub use company::{Company, CompanyStatus, BusinessType};
pub use shareholder::{Shareholder, ShareholderType};
pub use meeting::{Meeting, Attendee, MeetingStatus, AttendeeRole, AttendeeStatus};
pub use user::User;
pub use vote::{Vote, VoteOption, Ballot, VoteStatus};
pub use resolution::{Resolution, ResolutionStatus, Approval};
// Re-export database components from db module
pub use crate::db::{SledDB, SledDBError, SledDBResult, Storable, SledModel, DB};
Update src/models/mod.rs
to include the governance module:
pub mod biz;
pub mod mcc;
pub mod circle;
pub mod governance;
3.1.2 Resolution Model (resolution.rs
)
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBError};
use crate::models::gov::{Meeting, Vote};
/// ResolutionStatus represents the status of a resolution
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ResolutionStatus {
Draft,
Proposed,
Approved,
Rejected,
Withdrawn,
}
/// Resolution represents a board resolution
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Resolution {
pub id: u32,
pub company_id: u32,
pub meeting_id: Option<u32>,
pub vote_id: Option<u32>,
pub title: String,
pub description: String,
pub text: String,
pub status: ResolutionStatus,
pub proposed_by: u32, // User ID
pub proposed_at: DateTime<Utc>,
pub approved_at: Option<DateTime<Utc>>,
pub rejected_at: Option<DateTime<Utc>>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub approvals: Vec<Approval>,
}
/// Approval represents an approval of a resolution by a board member
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Approval {
pub id: u32,
pub resolution_id: u32,
pub user_id: u32,
pub name: String,
pub approved: bool,
pub comments: String,
pub created_at: DateTime<Utc>,
}
impl Resolution {
/// Create a new resolution with default values
pub fn new(
id: u32,
company_id: u32,
title: String,
description: String,
text: String,
proposed_by: u32,
) -> Self {
let now = Utc::now();
Self {
id,
company_id,
meeting_id: None,
vote_id: None,
title,
description,
text,
status: ResolutionStatus::Draft,
proposed_by,
proposed_at: now,
approved_at: None,
rejected_at: None,
created_at: now,
updated_at: now,
approvals: Vec::new(),
}
}
/// Propose the resolution
pub fn propose(&mut self) {
self.status = ResolutionStatus::Proposed;
self.proposed_at = Utc::now();
self.updated_at = Utc::now();
}
/// Approve the resolution
pub fn approve(&mut self) {
self.status = ResolutionStatus::Approved;
self.approved_at = Some(Utc::now());
self.updated_at = Utc::now();
}
/// Reject the resolution
pub fn reject(&mut self) {
self.status = ResolutionStatus::Rejected;
self.rejected_at = Some(Utc::now());
self.updated_at = Utc::now();
}
/// Add an approval to the resolution
pub fn add_approval(&mut self, user_id: u32, name: String, approved: bool, comments: String) -> &Approval {
let id = if self.approvals.is_empty() {
1
} else {
self.approvals.iter().map(|a| a.id).max().unwrap_or(0) + 1
};
let approval = Approval {
id,
resolution_id: self.id,
user_id,
name,
approved,
comments,
created_at: Utc::now(),
};
self.approvals.push(approval);
self.updated_at = Utc::now();
self.approvals.last().unwrap()
}
/// Link this resolution to a meeting
pub fn link_to_meeting(&mut self, meeting_id: u32) {
self.meeting_id = Some(meeting_id);
self.updated_at = Utc::now();
}
/// Link this resolution to a vote
pub fn link_to_vote(&mut self, vote_id: u32) {
self.vote_id = Some(vote_id);
self.updated_at = Utc::now();
}
}
// Implement Storable trait (provides default dump/load)
impl Storable for Resolution {}
impl Storable for Approval {}
// Implement SledModel trait
impl SledModel for Resolution {
fn get_id(&self) -> String {
self.id.to_string()
}
fn db_prefix() -> &'static str {
"resolution"
}
}
3.1.3 Enhanced Company Model (company.rs
)
Add integration with other modules:
impl Company {
// ... existing methods ...
/// Link this company to a Circle for access control
pub fn link_to_circle(&mut self, circle_id: u32) -> Result<(), SledDBError> {
// Implementation details
self.updated_at = Utc::now();
Ok(())
}
/// Link this company to a Customer in the biz module
pub fn link_to_customer(&mut self, customer_id: u32) -> Result<(), SledDBError> {
// Implementation details
self.updated_at = Utc::now();
Ok(())
}
/// Get all resolutions for this company
pub fn get_resolutions(&self, db: &SledDB<Resolution>) -> Result<Vec<Resolution>, SledDBError> {
let all_resolutions = db.list()?;
let company_resolutions = all_resolutions
.into_iter()
.filter(|resolution| resolution.company_id == self.id)
.collect();
Ok(company_resolutions)
}
}
3.1.4 Enhanced Meeting Model (meeting.rs
)
Add integration with other modules:
impl Meeting {
// ... existing methods ...
/// Link this meeting to a Calendar Event in the mcc module
pub fn link_to_event(&mut self, event_id: u32) -> Result<(), SledDBError> {
// Implementation details
self.updated_at = Utc::now();
Ok(())
}
/// Get all resolutions discussed in this meeting
pub fn get_resolutions(&self, db: &SledDB<Resolution>) -> Result<Vec<Resolution>, SledDBError> {
let all_resolutions = db.list()?;
let meeting_resolutions = all_resolutions
.into_iter()
.filter(|resolution| resolution.meeting_id == Some(self.id))
.collect();
Ok(meeting_resolutions)
}
}
3.1.5 Enhanced Vote Model (vote.rs
)
Add integration with Resolution model:
impl Vote {
// ... existing methods ...
/// Get the resolution associated with this vote
pub fn get_resolution(&self, db: &SledDB<Resolution>) -> Result<Option<Resolution>, SledDBError> {
let all_resolutions = db.list()?;
let vote_resolution = all_resolutions
.into_iter()
.find(|resolution| resolution.vote_id == Some(self.id));
Ok(vote_resolution)
}
}
3.1.6 Create README.md
Create a README.md file to document the purpose and usage of the governance module.
4. Data Model Diagram
classDiagram
class Company {
+u32 id
+String name
+String registration_number
+DateTime incorporation_date
+String fiscal_year_end
+String email
+String phone
+String website
+String address
+BusinessType business_type
+String industry
+String description
+CompanyStatus status
+DateTime created_at
+DateTime updated_at
+add_shareholder()
+link_to_circle()
+link_to_customer()
+get_resolutions()
}
class Shareholder {
+u32 id
+u32 company_id
+u32 user_id
+String name
+f64 shares
+f64 percentage
+ShareholderType type_
+DateTime since
+DateTime created_at
+DateTime updated_at
+update_shares()
}
class Meeting {
+u32 id
+u32 company_id
+String title
+DateTime date
+String location
+String description
+MeetingStatus status
+String minutes
+DateTime created_at
+DateTime updated_at
+Vec~Attendee~ attendees
+add_attendee()
+update_status()
+update_minutes()
+find_attendee_by_user_id()
+confirmed_attendees()
+link_to_event()
+get_resolutions()
}
class User {
+u32 id
+String name
+String email
+String password
+String company
+String role
+DateTime created_at
+DateTime updated_at
}
class Vote {
+u32 id
+u32 company_id
+String title
+String description
+DateTime start_date
+DateTime end_date
+VoteStatus status
+DateTime created_at
+DateTime updated_at
+Vec~VoteOption~ options
+Vec~Ballot~ ballots
+Vec~u32~ private_group
+add_option()
+add_ballot()
+get_resolution()
}
class Resolution {
+u32 id
+u32 company_id
+Option~u32~ meeting_id
+Option~u32~ vote_id
+String title
+String description
+String text
+ResolutionStatus status
+u32 proposed_by
+DateTime proposed_at
+Option~DateTime~ approved_at
+Option~DateTime~ rejected_at
+DateTime created_at
+DateTime updated_at
+Vec~Approval~ approvals
+propose()
+approve()
+reject()
+add_approval()
+link_to_meeting()
+link_to_vote()
}
Company "1" -- "many" Shareholder: has
Company "1" -- "many" Meeting: holds
Company "1" -- "many" Vote: conducts
Company "1" -- "many" Resolution: issues
Meeting "1" -- "many" Attendee: has
Meeting "1" -- "many" Resolution: discusses
Vote "1" -- "many" VoteOption: has
Vote "1" -- "many" Ballot: collects
Vote "1" -- "1" Resolution: decides
Resolution "1" -- "many" Approval: receives
5. Testing Strategy
- Unit tests for each model to verify:
- Basic functionality
- Serialization/deserialization
- Utility methods
- Integration with other models
- Integration tests to verify:
- Database operations with the models
- Relationships between models
- Integration with other modules
6. Future Considerations
- Committee Model: Add a Committee model in the future if needed
- Compliance Model: Add compliance-related models in the future if needed
- API Integration: Develop REST API endpoints for the governance module
- UI Components: Create UI components for managing governance entities
- Reporting: Implement reporting functionality for governance metrics