db/herodb/src/models/gov/GOVERNANCE_ENHANCEMENT_PLAN.md
2025-04-19 09:02:35 +02:00

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

  1. Unit tests for each model to verify:
    • Basic functionality
    • Serialization/deserialization
    • Utility methods
    • Integration with other models
  2. Integration tests to verify:
    • Database operations with the models
    • Relationships between models
    • Integration with other modules

6. Future Considerations

  1. Committee Model: Add a Committee model in the future if needed
  2. Compliance Model: Add compliance-related models in the future if needed
  3. API Integration: Develop REST API endpoints for the governance module
  4. UI Components: Create UI components for managing governance entities
  5. Reporting: Implement reporting functionality for governance metrics