This commit is contained in:
despiegk 2025-04-05 10:17:23 +02:00
parent c7a7201cfd
commit 8e91ad93ee
13 changed files with 384 additions and 741 deletions

View File

@ -1 +0,0 @@
../../rhaj/rhai_engine/rhaibook

View File

@ -1 +0,0 @@
../../rhaj/rhai_engine/rhaiexamples

View File

@ -112,7 +112,11 @@ fn test_company_operations(base_path: &Path) -> Result<(), Box<dyn std::error::E
"123-456-7890".to_string(), "123-456-7890".to_string(),
"www.testcorp.com".to_string(), "www.testcorp.com".to_string(),
"123 Test St".to_string(), "123 Test St".to_string(),
BusinessType::Global, BusinessType::new(BusinessType::GLOBAL.to_string())
.unwrap_or_else(|e| {
eprintln!("Warning: {}", e);
BusinessType::new_unchecked(BusinessType::GLOBAL.to_string())
}),
"Technology".to_string(), "Technology".to_string(),
"A test company".to_string(), "A test company".to_string(),
CompanyStatus::Active, CompanyStatus::Active,

View File

@ -49,7 +49,11 @@ fn test_zaz_db_factory() {
"123-456-7890".to_string(), "123-456-7890".to_string(),
"www.ftc.com".to_string(), "www.ftc.com".to_string(),
"123 Factory St".to_string(), "123 Factory St".to_string(),
BusinessType::Global, BusinessType::new(BusinessType::GLOBAL.to_string())
.unwrap_or_else(|e| {
eprintln!("Warning: {}", e);
BusinessType::new_unchecked(BusinessType::GLOBAL.to_string())
}),
"Technology".to_string(), "Technology".to_string(),
"A test company for the factory pattern".to_string(), "A test company for the factory pattern".to_string(),
CompanyStatus::Active, CompanyStatus::Active,
@ -167,7 +171,11 @@ fn test_dynamic_registration() {
"123-456-7890".to_string(), "123-456-7890".to_string(),
"www.dtc.com".to_string(), "www.dtc.com".to_string(),
"123 Dynamic St".to_string(), "123 Dynamic St".to_string(),
BusinessType::Global, BusinessType::new(BusinessType::GLOBAL.to_string())
.unwrap_or_else(|e| {
eprintln!("Warning: {}", e);
BusinessType::new_unchecked(BusinessType::GLOBAL.to_string())
}),
"Technology".to_string(), "Technology".to_string(),
"A test company for dynamic registration".to_string(), "A test company for dynamic registration".to_string(),
CompanyStatus::Active, CompanyStatus::Active,

View File

@ -45,7 +45,11 @@ pub fn run_db_examples() -> Result<(), Box<dyn std::error::Error>> {
"123-456-7890".to_string(), "123-456-7890".to_string(),
"www.example.com".to_string(), "www.example.com".to_string(),
"123 Example St, Example City".to_string(), "123 Example St, Example City".to_string(),
BusinessType::Global, BusinessType::new(BusinessType::GLOBAL.to_string())
.unwrap_or_else(|e| {
eprintln!("Warning: {}", e);
BusinessType::new_unchecked(BusinessType::GLOBAL.to_string())
}),
"Technology".to_string(), "Technology".to_string(),
"An example company".to_string(), "An example company".to_string(),
CompanyStatus::Active, CompanyStatus::Active,

View File

@ -47,7 +47,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
"+1-555-123-4567".to_string(), "+1-555-123-4567".to_string(),
"https://acmecorp.com".to_string(), "https://acmecorp.com".to_string(),
"123 Main St, Anytown, USA".to_string(), "123 Main St, Anytown, USA".to_string(),
BusinessType::Coop, BusinessType::new(BusinessType::COOP.to_string())
.unwrap_or_else(|e| {
eprintln!("Warning: {}", e);
BusinessType::new_unchecked(BusinessType::COOP.to_string())
}),
"Technology".to_string(), "Technology".to_string(),
"A leading technology company".to_string(), "A leading technology company".to_string(),
CompanyStatus::Active, CompanyStatus::Active,
@ -56,7 +60,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Insert the company // Insert the company
db.insert(&company)?; db.insert(&company)?;
println!("Company created: {} (ID: {})", company.name, company.id); println!("Company created: {} (ID: {})", company.name, company.id);
println!("Status: {:?}, Business Type: {:?}", company.status, company.business_type); println!("Status: {:?}, Business Type: {}", company.status, company.business_type.as_str());
println!("\n2. Creating Users"); println!("\n2. Creating Users");
println!("---------------"); println!("---------------");

View File

@ -152,7 +152,7 @@ impl ProductComponentBuilder {
} }
} }
/// Product represents a product or service offered by the Freezone /// Product represents a product or service offered in the system
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Product { pub struct Product {
pub id: u32, pub id: u32,

View File

@ -1,496 +0,0 @@
# 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
```mermaid
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:
```rust
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:
```rust
pub mod biz;
pub mod mcc;
pub mod circle;
pub mod governance;
```
#### 3.1.2 Resolution Model (`resolution.rs`)
```rust
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBError};
use crate::models::governance::{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:
```rust
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:
```rust
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:
```rust
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
```mermaid
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

View File

@ -1,6 +1,6 @@
# Governance Module # Corporate Governance Module
This directory contains the core data structures used in the Freezone Manager governance module. These models serve as the foundation for corporate governance functionality, providing essential data structures for companies, shareholders, meetings, voting, and more. This directory contains the core data structures used for corporate governance functionality. These models serve as the foundation for managing companies, shareholders, meetings, voting, resolutions, committees, and more in any organizational context.
## Overview ## Overview
@ -15,52 +15,341 @@ The governance models implement the Serde traits (Serialize/Deserialize) and dat
### Company (`company.rs`) ### Company (`company.rs`)
The Company model represents a company registered in the Freezone: The Company model represents a company entity with its basic information:
- **Company**: Main struct with fields for company information - **Company**: Main struct with fields for company information
- Basic details: name, registration number, incorporation date
- Contact information: email, phone, website, address
- Business information: business type, industry, description
- Status tracking: current status, timestamps
- **CompanyStatus**: Enum for possible company statuses (Active, Inactive, Suspended) - **CompanyStatus**: Enum for possible company statuses (Active, Inactive, Suspended)
- **BusinessType**: Enum for possible business types (Coop, Single, Twin, Starter, Global) - **BusinessType**: String-based type with validation for business types (Corporation, Partnership, LLC, etc.)
Key methods:
- `add_shareholder()`: Add a shareholder to the company
- `link_to_circle()`: Link the company to a Circle for access control
- `link_to_customer()`: Link the company to a Customer in the biz module
- `get_resolutions()`: Get all resolutions for this company
### Shareholder (`shareholder.rs`) ### Shareholder (`shareholder.rs`)
The Shareholder model represents a shareholder of a company: The Shareholder model represents a shareholder of a company:
- **Shareholder**: Main struct with fields for shareholder information - **Shareholder**: Main struct with fields for shareholder information
- Identifiers: id, company_id, user_id
- Ownership details: shares, percentage
- Type and timestamps: shareholder type, since date, created/updated timestamps
- **ShareholderType**: Enum for possible shareholder types (Individual, Corporate) - **ShareholderType**: Enum for possible shareholder types (Individual, Corporate)
Key methods:
- `update_shares()`: Update the shares owned by this shareholder
### Meeting (`meeting.rs`) ### Meeting (`meeting.rs`)
The Meeting model represents a board meeting of a company: The Meeting model represents a board meeting of a company:
- **Meeting**: Main struct with fields for meeting information - **Meeting**: Main struct with fields for meeting information
- Basic details: id, company_id, title, date, location, description
- Status and content: meeting status, minutes
- Timestamps and attendees: created/updated timestamps, list of attendees
- **Attendee**: Represents an attendee of a meeting - **Attendee**: Represents an attendee of a meeting
- Details: id, meeting_id, user_id, name, role, status, created timestamp
- **MeetingStatus**: Enum for possible meeting statuses (Scheduled, Completed, Cancelled) - **MeetingStatus**: Enum for possible meeting statuses (Scheduled, Completed, Cancelled)
- **AttendeeRole**: Enum for possible attendee roles (Coordinator, Member, Secretary, etc.) - **AttendeeRole**: Enum for possible attendee roles (Coordinator, Member, Secretary, etc.)
- **AttendeeStatus**: Enum for possible attendee statuses (Confirmed, Pending, Declined) - **AttendeeStatus**: Enum for possible attendee statuses (Confirmed, Pending, Declined)
Key methods:
- `add_attendee()`: Add an attendee to the meeting
- `update_status()`: Update the status of the meeting
- `update_minutes()`: Update the meeting minutes
- `find_attendee_by_user_id()`: Find an attendee by user ID
- `confirmed_attendees()`: Get all confirmed attendees
- `link_to_event()`: Link the meeting to a Calendar Event
- `get_resolutions()`: Get all resolutions discussed in this meeting
### User (`user.rs`) ### User (`user.rs`)
The User model represents a user in the Freezone Manager system: The User model represents a user in the governance system:
- **User**: Main struct with fields for user information - **User**: Main struct with fields for user information
- Basic details: id, name, email, password
- Role information: company, role
- Timestamps: created/updated timestamps
### Vote (`vote.rs`) ### Vote (`vote.rs`)
The Vote model represents a voting item in the Freezone: The Vote model represents a voting item for corporate decision-making:
- **Vote**: Main struct with fields for vote information - **Vote**: Main struct with fields for vote information
- Basic details: id, company_id, title, description
- Timing: start_date, end_date
- Status and timestamps: vote status, created/updated timestamps
- Options and results: list of vote options, list of ballots, private group
- **VoteOption**: Represents an option in a vote - **VoteOption**: Represents an option in a vote
- Details: id, vote_id, text, count, min_valid
- **Ballot**: Represents a ballot cast by a user - **Ballot**: Represents a ballot cast by a user
- Details: id, vote_id, user_id, vote_option_id, shares_count, created timestamp
- **VoteStatus**: Enum for possible vote statuses (Open, Closed, Cancelled) - **VoteStatus**: Enum for possible vote statuses (Open, Closed, Cancelled)
Key methods:
- `add_option()`: Add a voting option to this vote
- `add_ballot()`: Add a ballot to this vote
- `get_resolution()`: Get the resolution associated with this vote
### Resolution (`resolution.rs`)
The Resolution model represents a board resolution:
- **Resolution**: Main struct with fields for resolution information
- Identifiers: id, company_id, meeting_id, vote_id
- Content: title, description, text
- Status and tracking: resolution status, proposed_by, proposed_at, approved_at, rejected_at
- Timestamps and approvals: created/updated timestamps, list of approvals
- **Approval**: Represents an approval of a resolution by a board member
- Details: id, resolution_id, user_id, name, approved, comments, created timestamp
- **ResolutionStatus**: Enum for possible resolution statuses (Draft, Proposed, Approved, Rejected, Withdrawn)
Key methods:
- `propose()`: Propose the resolution
- `approve()`: Approve the resolution
- `reject()`: Reject the resolution
- `withdraw()`: Withdraw the resolution
- `add_approval()`: Add an approval to the resolution
- `find_approval_by_user_id()`: Find an approval by user ID
- `get_approvals()`: Get all approvals
- `approval_count()`: Get approval count
- `rejection_count()`: Get rejection count
- `link_to_meeting()`: Link this resolution to a meeting
- `link_to_vote()`: Link this resolution to a vote
- `get_meeting()`: Get the meeting associated with this resolution
- `get_vote()`: Get the vote associated with this resolution
### Committee (`committee.rs`)
The Committee model represents a board committee:
- **Committee**: Main struct with fields for committee information
- Basic details: id, company_id, name, description, purpose
- Integration: circle_id
- Timestamps and members: created/updated timestamps, list of members
- **CommitteeMember**: Represents a member of a committee
- Details: id, committee_id, user_id, name, role, since, created timestamp
- **CommitteeRole**: Enum for possible committee roles (Chair, ViceChair, Secretary, Member, Advisor, Observer)
Key methods:
- `add_member()`: Add a member to the committee
- `find_member_by_user_id()`: Find a member by user ID
- `remove_member()`: Remove a member from the committee
- `link_to_circle()`: Link this committee to a Circle for access control
- `get_member_users()`: Get all users who are members of this committee
## Model Relationships
The following diagram illustrates the relationships between the governance models:
```mermaid
graph TD
Company --> |has many| Shareholder
Company --> |has many| Meeting
Company --> |has many| Resolution
Company --> |has many| Vote
Company --> |has many| Committee
Meeting --> |has many| Attendee
Attendee --> |is a| User
Resolution --> |can be linked to| Meeting
Resolution --> |can be linked to| Vote
Resolution --> |has many| Approval
Vote --> |has many| VoteOption
Vote --> |has many| Ballot
Ballot --> |cast by| User
Committee --> |has many| CommitteeMember
CommitteeMember --> |is a| User
```
## Key Relationships
- **Company-Shareholder**: A company has multiple shareholders who own shares in the company
- **Company-Meeting**: A company holds multiple meetings for governance purposes
- **Company-Resolution**: A company creates resolutions that need to be approved
- **Company-Vote**: A company conducts votes on various matters
- **Company-Committee**: A company can have multiple committees for specialized governance functions
- **Meeting-Resolution**: Resolutions can be discussed and approved in meetings
- **Resolution-Vote**: Resolutions can be subject to formal voting
- **User-Governance**: Users participate in governance as shareholders, meeting attendees, committee members, and by casting votes
## Integration with Other Modules
The governance module integrates with other modules in the system:
### Integration with Biz Module
- **Company-Customer**: Companies can be linked to customers in the biz module
- **Company-Contract**: Companies can be linked to contracts in the biz module
- **Shareholder-Customer**: Shareholders can be linked to customers in the biz module
- **Meeting-Invoice**: Meetings can be linked to invoices for expense tracking
### Integration with MCC Module
- **Meeting-Calendar/Event**: Meetings can be linked to calendar events in the mcc module
- **User-Contact**: Users can be linked to contacts in the mcc module
- **Vote-Message**: Votes can be linked to messages for notifications
### Integration with Circle Module
- **Company-Circle**: Companies can be linked to circles for group-based access control
- **User-Member**: Users can be linked to members for role-based permissions
## Detailed Data Model
A more detailed class diagram showing the fields and methods of each model:
```mermaid
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()
}
class Committee {
+u32 id
+u32 company_id
+String name
+String description
+String purpose
+Option~u32~ circle_id
+DateTime created_at
+DateTime updated_at
+Vec~CommitteeMember~ members
+add_member()
+find_member_by_user_id()
+remove_member()
+link_to_circle()
+get_member_users()
}
Company "1" -- "many" Shareholder: has
Company "1" -- "many" Meeting: holds
Company "1" -- "many" Vote: conducts
Company "1" -- "many" Resolution: issues
Company "1" -- "many" Committee: establishes
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
Committee "1" -- "many" CommitteeMember: has
```
## Usage ## Usage
These models are used by the governance module to manage corporate governance. They are typically accessed through the database handlers that implement the generic SledDB interface. These models are used by the governance module to manage corporate governance. They are typically accessed through the database handlers that implement the generic SledDB interface.
## Future Enhancements
See the [GOVERNANCE_ENHANCEMENT_PLAN.md](./GOVERNANCE_ENHANCEMENT_PLAN.md) file for details on planned enhancements to the governance module, including:
1. New models for committees, resolutions, and compliance
2. Enhanced relationships with other modules (biz, mcc, circle)
3. Additional utility methods and functionality

View File

@ -13,16 +13,60 @@ pub enum CompanyStatus {
} }
/// BusinessType represents the type of a business /// BusinessType represents the type of a business
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum BusinessType { pub struct BusinessType(pub String);
Coop,
Single, impl BusinessType {
Twin, pub const CORPORATION: &'static str = "Corporation";
Starter, pub const PARTNERSHIP: &'static str = "Partnership";
Global, pub const LLC: &'static str = "LLC";
pub const COOP: &'static str = "Coop";
pub const SINGLE: &'static str = "Single";
pub const TWIN: &'static str = "Twin";
pub const STARTER: &'static str = "Starter";
pub const GLOBAL: &'static str = "Global";
/// Create a new BusinessType, validating that the type is one of the predefined types
pub fn new(type_str: String) -> Result<Self, String> {
if Self::is_valid(&type_str) {
Ok(BusinessType(type_str))
} else {
Err(format!("Invalid business type: {}. Valid types are: {}",
type_str, Self::valid_types().join(", ")))
}
}
/// Create a new BusinessType without validation (use with caution)
pub fn new_unchecked(type_str: String) -> Self {
BusinessType(type_str)
}
/// Get the string value of the business type
pub fn as_str(&self) -> &str {
&self.0
}
/// Check if a string is a valid business type
pub fn is_valid(type_str: &str) -> bool {
Self::valid_types().contains(&type_str.to_string())
}
/// Get a list of all valid business types
pub fn valid_types() -> Vec<String> {
vec![
Self::CORPORATION.to_string(),
Self::PARTNERSHIP.to_string(),
Self::LLC.to_string(),
Self::COOP.to_string(),
Self::SINGLE.to_string(),
Self::TWIN.to_string(),
Self::STARTER.to_string(),
Self::GLOBAL.to_string(),
]
}
} }
/// Company represents a company registered in the Freezone /// Company represents a company entity
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] // Added PartialEq #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] // Added PartialEq
pub struct Company { pub struct Company {
pub id: u32, pub id: u32,

View File

@ -1,212 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable, SledDB, SledDBError};
use crate::models::governance::Company;
/// ComplianceRequirement represents a regulatory requirement
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ComplianceRequirement {
pub id: u32,
pub company_id: u32,
pub title: String,
pub description: String,
pub regulation: String,
pub authority: String,
pub deadline: DateTime<Utc>,
pub status: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
/// ComplianceDocument represents a compliance document
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ComplianceDocument {
pub id: u32,
pub requirement_id: u32,
pub title: String,
pub description: String,
pub file_path: String,
pub file_type: String,
pub uploaded_by: u32, // User ID
pub uploaded_at: DateTime<Utc>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
/// ComplianceAudit represents a compliance audit
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ComplianceAudit {
pub id: u32,
pub company_id: u32,
pub title: String,
pub description: String,
pub auditor: String,
pub start_date: DateTime<Utc>,
pub end_date: DateTime<Utc>,
pub status: String,
pub findings: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl ComplianceRequirement {
/// Create a new compliance requirement with default values
pub fn new(
id: u32,
company_id: u32,
title: String,
description: String,
regulation: String,
authority: String,
deadline: DateTime<Utc>,
) -> Self {
let now = Utc::now();
Self {
id,
company_id,
title,
description,
regulation,
authority,
deadline,
status: "Pending".to_string(),
created_at: now,
updated_at: now,
}
}
/// Update the status of the requirement
pub fn update_status(&mut self, status: String) {
self.status = status;
self.updated_at = Utc::now();
}
/// Get the company associated with this requirement
pub fn get_company(&self, db: &SledDB<Company>) -> Result<Company, SledDBError> {
db.get(&self.company_id.to_string())
}
/// Get all documents associated with this requirement
pub fn get_documents(&self, db: &SledDB<ComplianceDocument>) -> Result<Vec<ComplianceDocument>, SledDBError> {
let all_documents = db.list()?;
let requirement_documents = all_documents
.into_iter()
.filter(|doc| doc.requirement_id == self.id)
.collect();
Ok(requirement_documents)
}
}
impl ComplianceDocument {
/// Create a new compliance document with default values
pub fn new(
id: u32,
requirement_id: u32,
title: String,
description: String,
file_path: String,
file_type: String,
uploaded_by: u32,
) -> Self {
let now = Utc::now();
Self {
id,
requirement_id,
title,
description,
file_path,
file_type,
uploaded_by,
uploaded_at: now,
created_at: now,
updated_at: now,
}
}
/// Get the requirement associated with this document
pub fn get_requirement(&self, db: &SledDB<ComplianceRequirement>) -> Result<ComplianceRequirement, SledDBError> {
db.get(&self.requirement_id.to_string())
}
}
impl ComplianceAudit {
/// Create a new compliance audit with default values
pub fn new(
id: u32,
company_id: u32,
title: String,
description: String,
auditor: String,
start_date: DateTime<Utc>,
end_date: DateTime<Utc>,
) -> Self {
let now = Utc::now();
Self {
id,
company_id,
title,
description,
auditor,
start_date,
end_date,
status: "Planned".to_string(),
findings: String::new(),
created_at: now,
updated_at: now,
}
}
/// Update the status of the audit
pub fn update_status(&mut self, status: String) {
self.status = status;
self.updated_at = Utc::now();
}
/// Update the findings of the audit
pub fn update_findings(&mut self, findings: String) {
self.findings = findings;
self.updated_at = Utc::now();
}
/// Get the company associated with this audit
pub fn get_company(&self, db: &SledDB<Company>) -> Result<Company, SledDBError> {
db.get(&self.company_id.to_string())
}
}
// Implement Storable trait (provides default dump/load)
impl Storable for ComplianceRequirement {}
impl Storable for ComplianceDocument {}
impl Storable for ComplianceAudit {}
// Implement SledModel trait
impl SledModel for ComplianceRequirement {
fn get_id(&self) -> String {
self.id.to_string()
}
fn db_prefix() -> &'static str {
"compliance_requirement"
}
}
impl SledModel for ComplianceDocument {
fn get_id(&self) -> String {
self.id.to_string()
}
fn db_prefix() -> &'static str {
"compliance_document"
}
}
impl SledModel for ComplianceAudit {
fn get_id(&self) -> String {
self.id.to_string()
}
fn db_prefix() -> &'static str {
"compliance_audit"
}
}

View File

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use crate::db::{SledModel, Storable}; // Import Sled traits use crate::db::{SledModel, Storable}; // Import Sled traits
// use std::collections::HashMap; // Removed unused import // use std::collections::HashMap; // Removed unused import
/// User represents a user in the Freezone Manager system /// User represents a user in the governance system
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User { pub struct User {
pub id: u32, pub id: u32,

View File

@ -13,7 +13,7 @@ pub enum VoteStatus {
Cancelled, Cancelled,
} }
/// Vote represents a voting item in the Freezone /// Vote represents a voting item for corporate decision-making
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Vote { pub struct Vote {
pub id: u32, pub id: u32,