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> { 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::() .register_model::() .register_model::() .register_model::() .register_model::() .register_model::() .register_model::() .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.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.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.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.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(()) }