db/herodb/src/models/gov/company.rs
2025-04-20 08:56:34 +02:00

186 lines
5.7 KiB
Rust

use crate::db::{Model, Storable, DbError, DbResult};
use super::shareholder::Shareholder; // Use super:: for sibling module
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
/// CompanyStatus represents the status of a company
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum CompanyStatus {
Active,
Inactive,
Suspended,
}
/// BusinessType represents the type of a business
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct BusinessType(pub String);
impl BusinessType {
pub const CORPORATION: &'static str = "Corporation";
pub const PARTNERSHIP: &'static str = "Partnership";
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 entity
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] // Added PartialEq
pub struct Company {
pub id: u32,
pub name: String,
pub registration_number: String,
pub incorporation_date: DateTime<Utc>,
pub fiscal_year_end: String,
pub email: String,
pub phone: String,
pub website: String,
pub address: String,
pub business_type: BusinessType,
pub industry: String,
pub description: String,
pub status: CompanyStatus,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
// Removed shareholders property
}
// Model requires get_id and db_prefix
impl Model for Company {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"company" // Prefix for company records in the database
}
}
impl Company {
/// Create a new company with default timestamps
pub fn new(
id: u32,
name: String,
registration_number: String,
incorporation_date: DateTime<Utc>,
fiscal_year_end: String,
email: String,
phone: String,
website: String,
address: String,
business_type: BusinessType,
industry: String,
description: String,
status: CompanyStatus,
) -> Self {
let now = Utc::now();
Self {
id,
name,
registration_number,
incorporation_date,
fiscal_year_end,
email,
phone,
website,
address,
business_type,
industry,
description,
status,
created_at: now,
updated_at: now,
}
}
/// Add a shareholder to the company, saving it to the database
pub fn add_shareholder(
&mut self,
db: &mut DB, // Pass in the DB instance
mut shareholder: Shareholder,
) -> DbResult<()> {
shareholder.company_id = self.id; // Set the company_id
db.set(&shareholder)?; // Insert the shareholder into the DB
self.updated_at = Utc::now();
Ok(())
}
/// Link this company to a Circle for access control
pub fn link_to_circle(&mut self, circle_id: u32) -> DbResult<()> {
// Implementation would involve updating a mapping in a separate database
// For now, we'll just update the timestamp to indicate the change
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) -> DbResult<()> {
// Implementation would involve updating a mapping in a separate database
// For now, we'll just update the timestamp to indicate the change
self.updated_at = Utc::now();
Ok(())
}
/// Get all resolutions for this company
pub fn get_resolutions(&self, db: &DB) -> DbResult<Vec<super::Resolution>> {
let all_resolutions = db.list::<super::Resolution>()?;
let company_resolutions = all_resolutions
.into_iter()
.filter(|resolution| resolution.company_id == self.id)
.collect();
Ok(company_resolutions)
}
// Future methods:
// /// Get all committees for this company
// pub fn get_committees(&self, db: &DB) -> DbResult<Vec<Committee>> { ... }
//
// /// Get all compliance requirements for this company
// pub fn get_compliance_requirements(&self, db: &DB) -> DbResult<Vec<ComplianceRequirement>> { ... }
}