368 lines
12 KiB
Rust
368 lines
12 KiB
Rust
use chrono::{Utc, Duration};
|
|
use herodb::db::{DBBuilder, DB};
|
|
use herodb::models::gov::{
|
|
Company, CompanyStatus, BusinessType,
|
|
Shareholder, ShareholderType,
|
|
Meeting, Attendee, MeetingStatus, AttendeeRole, AttendeeStatus,
|
|
User,
|
|
Vote, VoteOption, Ballot, VoteStatus,
|
|
Resolution, ResolutionStatus, Approval,
|
|
Committee, CommitteeRole, CommitteeMember
|
|
};
|
|
use std::path::PathBuf;
|
|
use std::fs;
|
|
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
println!("DB Example: Gov Module");
|
|
println!("============================");
|
|
|
|
// Create a temporary directory for the database
|
|
let db_path = PathBuf::from("/tmp/dbexample_gov");
|
|
if db_path.exists() {
|
|
fs::remove_dir_all(&db_path)?;
|
|
}
|
|
fs::create_dir_all(&db_path)?;
|
|
println!("Database path: {:?}", db_path);
|
|
|
|
// Create a database instance with our governance models registered
|
|
let db = DBBuilder::new(&db_path)
|
|
.register_model::<Company>()
|
|
.register_model::<Shareholder>()
|
|
.register_model::<Meeting>()
|
|
.register_model::<User>()
|
|
.register_model::<Vote>()
|
|
.register_model::<Resolution>()
|
|
.register_model::<Committee>()
|
|
.build()?;
|
|
|
|
println!("\n1. Creating a Company");
|
|
println!("-------------------");
|
|
|
|
// Create a company
|
|
let company = Company::new(
|
|
1,
|
|
"Acme Corporation".to_string(),
|
|
"ACM123456".to_string(),
|
|
Utc::now(),
|
|
"December 31".to_string(),
|
|
"info@acmecorp.com".to_string(),
|
|
"+1-555-123-4567".to_string(),
|
|
"https://acmecorp.com".to_string(),
|
|
"123 Main St, Anytown, USA".to_string(),
|
|
BusinessType::new(BusinessType::COOP.to_string())
|
|
.unwrap_or_else(|e| {
|
|
eprintln!("Warning: {}", e);
|
|
BusinessType::new_unchecked(BusinessType::COOP.to_string())
|
|
}),
|
|
"Technology".to_string(),
|
|
"A leading technology company".to_string(),
|
|
CompanyStatus::Active,
|
|
);
|
|
|
|
// Insert the company
|
|
db.set(&company)?;
|
|
println!("Company created: {} (ID: {})", company.name, company.id);
|
|
println!("Status: {:?}, Business Type: {}", company.status, company.business_type.as_str());
|
|
|
|
println!("\n2. Creating Users");
|
|
println!("---------------");
|
|
|
|
// Create users
|
|
let user1 = User::new(
|
|
1,
|
|
"John Doe".to_string(),
|
|
"john.doe@acmecorp.com".to_string(),
|
|
"password123".to_string(), // In a real app, this would be hashed
|
|
"Acme Corporation".to_string(),
|
|
"CEO".to_string(),
|
|
);
|
|
|
|
let user2 = User::new(
|
|
2,
|
|
"Jane Smith".to_string(),
|
|
"jane.smith@acmecorp.com".to_string(),
|
|
"password456".to_string(), // In a real app, this would be hashed
|
|
"Acme Corporation".to_string(),
|
|
"CFO".to_string(),
|
|
);
|
|
|
|
let user3 = User::new(
|
|
3,
|
|
"Bob Johnson".to_string(),
|
|
"bob.johnson@acmecorp.com".to_string(),
|
|
"password789".to_string(), // In a real app, this would be hashed
|
|
"Acme Corporation".to_string(),
|
|
"CTO".to_string(),
|
|
);
|
|
|
|
// Insert the users
|
|
db.set(&user1)?;
|
|
db.set(&user2)?;
|
|
db.set(&user3)?;
|
|
|
|
println!("User created: {} ({})", user1.name, user1.role);
|
|
println!("User created: {} ({})", user2.name, user2.role);
|
|
println!("User created: {} ({})", user3.name, user3.role);
|
|
|
|
println!("\n3. Creating Shareholders");
|
|
println!("----------------------");
|
|
|
|
// Create shareholders
|
|
let mut shareholder1 = Shareholder::new(
|
|
1,
|
|
company.id,
|
|
user1.id,
|
|
user1.name.clone(),
|
|
1000.0,
|
|
40.0,
|
|
ShareholderType::Individual,
|
|
);
|
|
|
|
let mut shareholder2 = Shareholder::new(
|
|
2,
|
|
company.id,
|
|
user2.id,
|
|
user2.name.clone(),
|
|
750.0,
|
|
30.0,
|
|
ShareholderType::Individual,
|
|
);
|
|
|
|
let mut shareholder3 = Shareholder::new(
|
|
3,
|
|
company.id,
|
|
user3.id,
|
|
user3.name.clone(),
|
|
750.0,
|
|
30.0,
|
|
ShareholderType::Individual,
|
|
);
|
|
|
|
// Insert the shareholders
|
|
db.set(&shareholder1)?;
|
|
db.set(&shareholder2)?;
|
|
db.set(&shareholder3)?;
|
|
|
|
println!("Shareholder created: {} ({} shares, {}%)",
|
|
shareholder1.name, shareholder1.shares, shareholder1.percentage);
|
|
println!("Shareholder created: {} ({} shares, {}%)",
|
|
shareholder2.name, shareholder2.shares, shareholder2.percentage);
|
|
println!("Shareholder created: {} ({} shares, {}%)",
|
|
shareholder3.name, shareholder3.shares, shareholder3.percentage);
|
|
|
|
// Update shareholder shares
|
|
shareholder1.update_shares(1100.0, 44.0);
|
|
db.set(&shareholder1)?;
|
|
println!("Updated shareholder: {} ({} shares, {}%)",
|
|
shareholder1.name, shareholder1.shares, shareholder1.percentage);
|
|
|
|
println!("\n4. Creating a Meeting");
|
|
println!("------------------");
|
|
|
|
// Create a meeting
|
|
let mut meeting = Meeting::new(
|
|
1,
|
|
company.id,
|
|
"Q2 Board Meeting".to_string(),
|
|
Utc::now() + Duration::days(7), // Meeting in 7 days
|
|
"Conference Room A".to_string(),
|
|
"Quarterly board meeting to discuss financial results".to_string(),
|
|
);
|
|
|
|
// Create attendees
|
|
let attendee1 = Attendee::new(
|
|
1,
|
|
meeting.id,
|
|
user1.id,
|
|
user1.name.clone(),
|
|
AttendeeRole::Coordinator,
|
|
);
|
|
|
|
let attendee2 = Attendee::new(
|
|
2,
|
|
meeting.id,
|
|
user2.id,
|
|
user2.name.clone(),
|
|
AttendeeRole::Member,
|
|
);
|
|
|
|
let attendee3 = Attendee::new(
|
|
3,
|
|
meeting.id,
|
|
user3.id,
|
|
user3.name.clone(),
|
|
AttendeeRole::Member,
|
|
);
|
|
|
|
// Add attendees to the meeting
|
|
meeting.add_attendee(attendee1);
|
|
meeting.add_attendee(attendee2);
|
|
meeting.add_attendee(attendee3);
|
|
|
|
// Insert the meeting
|
|
db.set(&meeting)?;
|
|
println!("Meeting created: {} ({})", meeting.title, meeting.date.format("%Y-%m-%d %H:%M"));
|
|
println!("Status: {:?}, Attendees: {}", meeting.status, meeting.attendees.len());
|
|
|
|
// Update attendee status
|
|
if let Some(attendee) = meeting.find_attendee_by_user_id_mut(user2.id) {
|
|
attendee.update_status(AttendeeStatus::Confirmed);
|
|
}
|
|
if let Some(attendee) = meeting.find_attendee_by_user_id_mut(user3.id) {
|
|
attendee.update_status(AttendeeStatus::Confirmed);
|
|
}
|
|
db.set(&meeting)?;
|
|
|
|
// Get confirmed attendees
|
|
let confirmed = meeting.confirmed_attendees();
|
|
println!("Confirmed attendees: {}", confirmed.len());
|
|
for attendee in confirmed {
|
|
println!(" - {} ({})", attendee.name, match attendee.role {
|
|
AttendeeRole::Coordinator => "Coordinator",
|
|
AttendeeRole::Member => "Member",
|
|
AttendeeRole::Secretary => "Secretary",
|
|
AttendeeRole::Participant => "Participant",
|
|
AttendeeRole::Advisor => "Advisor",
|
|
AttendeeRole::Admin => "Admin",
|
|
});
|
|
}
|
|
|
|
println!("\n5. Creating a Resolution");
|
|
println!("----------------------");
|
|
|
|
// Create a resolution
|
|
let mut resolution = Resolution::new(
|
|
1,
|
|
company.id,
|
|
"Approval of Q1 Financial Statements".to_string(),
|
|
"Resolution to approve the Q1 financial statements".to_string(),
|
|
"The Board of Directors hereby approves the financial statements for Q1 2025.".to_string(),
|
|
user1.id, // Proposed by the CEO
|
|
);
|
|
|
|
// Link the resolution to the meeting
|
|
resolution.link_to_meeting(meeting.id);
|
|
|
|
// Insert the resolution
|
|
db.set(&resolution)?;
|
|
println!("Resolution created: {} (Status: {:?})", resolution.title, resolution.status);
|
|
|
|
// Propose the resolution
|
|
resolution.propose();
|
|
db.set(&resolution)?;
|
|
println!("Resolution proposed on {}", resolution.proposed_at.format("%Y-%m-%d"));
|
|
|
|
// Add approvals
|
|
resolution.add_approval(user1.id, user1.name.clone(), true, "Approved as proposed".to_string());
|
|
resolution.add_approval(user2.id, user2.name.clone(), true, "Financials look good".to_string());
|
|
resolution.add_approval(user3.id, user3.name.clone(), true, "No concerns".to_string());
|
|
db.set(&resolution)?;
|
|
|
|
// Check approval status
|
|
println!("Approvals: {}, Rejections: {}",
|
|
resolution.approval_count(),
|
|
resolution.rejection_count());
|
|
|
|
// Approve the resolution
|
|
resolution.approve();
|
|
db.set(&resolution)?;
|
|
println!("Resolution approved on {}",
|
|
resolution.approved_at.unwrap().format("%Y-%m-%d"));
|
|
|
|
println!("\n6. Creating a Vote");
|
|
println!("----------------");
|
|
|
|
// Create a vote
|
|
let mut vote = Vote::new(
|
|
1,
|
|
company.id,
|
|
"Vote on New Product Line".to_string(),
|
|
"Vote to approve investment in new product line".to_string(),
|
|
Utc::now(),
|
|
Utc::now() + Duration::days(3), // Voting period of 3 days
|
|
VoteStatus::Open,
|
|
);
|
|
|
|
// Add voting options
|
|
vote.add_option("Approve".to_string(), 0);
|
|
vote.add_option("Reject".to_string(), 0);
|
|
vote.add_option("Abstain".to_string(), 0);
|
|
|
|
// Insert the vote
|
|
db.set(&vote)?;
|
|
println!("Vote created: {} (Status: {:?})", vote.title, vote.status);
|
|
println!("Voting period: {} to {}",
|
|
vote.start_date.format("%Y-%m-%d"),
|
|
vote.end_date.format("%Y-%m-%d"));
|
|
|
|
// Cast ballots
|
|
vote.add_ballot(user1.id, 1, 1000); // User 1 votes "Approve" with 1000 shares
|
|
vote.add_ballot(user2.id, 1, 750); // User 2 votes "Approve" with 750 shares
|
|
vote.add_ballot(user3.id, 3, 750); // User 3 votes "Abstain" with 750 shares
|
|
db.set(&vote)?;
|
|
|
|
// Check voting results
|
|
println!("Voting results:");
|
|
for option in &vote.options {
|
|
println!(" - {}: {} votes", option.text, option.count);
|
|
}
|
|
|
|
// Create a resolution for this vote
|
|
let mut vote_resolution = Resolution::new(
|
|
2,
|
|
company.id,
|
|
"Investment in New Product Line".to_string(),
|
|
"Resolution to approve investment in new product line".to_string(),
|
|
"The Board of Directors hereby approves an investment of $1,000,000 in the new product line.".to_string(),
|
|
user1.id, // Proposed by the CEO
|
|
);
|
|
|
|
// Link the resolution to the vote
|
|
vote_resolution.link_to_vote(vote.id);
|
|
vote_resolution.propose();
|
|
db.set(&vote_resolution)?;
|
|
println!("Created resolution linked to vote: {}", vote_resolution.title);
|
|
|
|
println!("\n7. Retrieving Related Objects");
|
|
println!("---------------------------");
|
|
|
|
// Retrieve company and related objects
|
|
let retrieved_company = db.get::<Company>(company.id)?;
|
|
println!("Company: {} (ID: {})", retrieved_company.name, retrieved_company.id);
|
|
|
|
// Get resolutions for this company
|
|
let company_resolutions = retrieved_company.get_resolutions(&db)?;
|
|
println!("Company has {} resolutions:", company_resolutions.len());
|
|
for res in company_resolutions {
|
|
println!(" - {} (Status: {:?})", res.title, res.status);
|
|
}
|
|
|
|
// Get meeting and its resolutions
|
|
let retrieved_meeting = db.get::<Meeting>(meeting.id)?;
|
|
println!("Meeting: {} ({})", retrieved_meeting.title, retrieved_meeting.date.format("%Y-%m-%d"));
|
|
|
|
let meeting_resolutions = retrieved_meeting.get_resolutions(&db)?;
|
|
println!("Meeting has {} resolutions:", meeting_resolutions.len());
|
|
for res in meeting_resolutions {
|
|
println!(" - {} (Status: {:?})", res.title, res.status);
|
|
}
|
|
|
|
// Get vote and its resolution
|
|
let retrieved_vote = db.get::<Vote>(vote.id)?;
|
|
println!("Vote: {} (Status: {:?})", retrieved_vote.title, retrieved_vote.status);
|
|
|
|
if let Ok(Some(vote_res)) = retrieved_vote.get_resolution(&db) {
|
|
println!("Vote is linked to resolution: {}", vote_res.title);
|
|
}
|
|
|
|
// Get resolution and its related objects
|
|
let retrieved_resolution = db.get::<Resolution>(resolution.id)?;
|
|
println!("Resolution: {} (Status: {:?})", retrieved_resolution.title, retrieved_resolution.status);
|
|
|
|
if let Ok(Some(res_meeting)) = retrieved_resolution.get_meeting(&db) {
|
|
println!("Resolution is discussed in meeting: {}", res_meeting.title);
|
|
}
|
|
|
|
println!("\nExample completed successfully!");
|
|
Ok(())
|
|
} |