This commit is contained in:
2025-04-20 09:21:32 +02:00
parent 4b2e8ca6b9
commit c956db8adf
36 changed files with 4391 additions and 229 deletions

View File

@@ -0,0 +1,108 @@
// This example demonstrates the basic functionality of the circle models
// without using the database functionality
use herodb::models::circle::{Circle, Member, Name, Wallet, Role, Record, RecordType};
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Circle Module Basic Demo");
// Create a circle
let circle = Circle::new(
1,
"ThreeFold Community".to_string(),
"A circle for ThreeFold community members".to_string(),
);
println!("Created circle: {:?}", circle);
// Create members
let mut alice = Member::new(
1,
"Alice".to_string(),
"Core contributor".to_string(),
Role::Admin,
);
alice.add_email("alice@example.com".to_string());
let mut bob = Member::new(
2,
"Bob".to_string(),
"Community member".to_string(),
Role::Member,
);
bob.add_email("bob@example.com".to_string());
println!("Created members: {:?}, {:?}", alice, bob);
// Create a domain name
let mut domain = Name::new(
1,
"threefold.io".to_string(),
"ThreeFold main domain".to_string(),
);
let record = Record {
name: "www".to_string(),
text: "ThreeFold Website".to_string(),
category: RecordType::A,
addr: vec!["192.168.1.1".to_string()],
};
domain.add_record(record);
domain.add_admin("alice_pubkey".to_string());
println!("Created domain: {:?}", domain);
// Create wallets
let mut alice_wallet = Wallet::new(
1,
"Alice's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GALICE...".to_string(),
);
alice_wallet.set_asset("TFT".to_string(), 1000.0);
alice_wallet.set_asset("XLM".to_string(), 100.0);
let mut bob_wallet = Wallet::new(
2,
"Bob's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GBOB...".to_string(),
);
bob_wallet.set_asset("TFT".to_string(), 500.0);
println!("Created wallets: {:?}, {:?}", alice_wallet, bob_wallet);
// Link wallets to members
alice.link_wallet(alice_wallet.id);
bob.link_wallet(bob_wallet.id);
println!("Linked wallets to members");
// Demonstrate wallet operations
println!("\nDemonstrating wallet operations:");
println!("Alice's wallet before transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
println!("Bob's wallet before transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
// Simulate a transfer of 100 TFT from Alice to Bob
alice_wallet.set_asset("TFT".to_string(), 900.0); // Decrease Alice's TFT by 100
bob_wallet.set_asset("TFT".to_string(), 600.0); // Increase Bob's TFT by 100
println!("Alice's wallet after transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
println!("Bob's wallet after transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
println!("\nCircle basic demo completed successfully!");
Ok(())
}

View File

@@ -0,0 +1,151 @@
use herodb::db::{DB, DBBuilder};
use herodb::models::circle::{Circle, Member, Name, Wallet, Asset, Role, Record, RecordType};
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a temporary directory for the database
let db_path = Path::new("./tmp/circle_demo");
if db_path.exists() {
std::fs::remove_dir_all(db_path)?;
}
std::fs::create_dir_all(db_path)?;
println!("Creating database at {:?}", db_path);
// Create a database with all circle models registered
let db = DBBuilder::new(db_path)
.register_model::<Circle>()
.register_model::<Member>()
.register_model::<Name>()
.register_model::<Wallet>()
.build()?;
// Create a circle
let mut circle = Circle::new(
1,
"ThreeFold Community".to_string(),
"A circle for ThreeFold community members".to_string(),
);
println!("Created circle: {:?}", circle);
db.set(&circle)?;
// Create members
let mut alice = Member::new(
1,
"Alice".to_string(),
"Core contributor".to_string(),
Role::Admin,
);
alice.add_email("alice@example.com".to_string());
let mut bob = Member::new(
2,
"Bob".to_string(),
"Community member".to_string(),
Role::Member,
);
bob.add_email("bob@example.com".to_string());
println!("Created members: {:?}, {:?}", alice, bob);
db.set(&alice)?;
db.set(&bob)?;
// Create a domain name
let mut domain = Name::new(
1,
"threefold.io".to_string(),
"ThreeFold main domain".to_string(),
);
let record = Record {
name: "www".to_string(),
text: "ThreeFold Website".to_string(),
category: RecordType::A,
addr: vec!["192.168.1.1".to_string()],
};
domain.add_record(record);
domain.add_admin("alice_pubkey".to_string());
println!("Created domain: {:?}", domain);
db.set(&domain)?;
// Create wallets
let mut alice_wallet = Wallet::new(
1,
"Alice's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GALICE...".to_string(),
);
alice_wallet.set_asset("TFT".to_string(), 1000.0);
alice_wallet.set_asset("XLM".to_string(), 100.0);
let mut bob_wallet = Wallet::new(
2,
"Bob's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GBOB...".to_string(),
);
bob_wallet.set_asset("TFT".to_string(), 500.0);
println!("Created wallets: {:?}, {:?}", alice_wallet, bob_wallet);
db.set(&alice_wallet)?;
db.set(&bob_wallet)?;
// Link wallets to members
alice.link_wallet(alice_wallet.id);
bob.link_wallet(bob_wallet.id);
db.set(&alice)?;
db.set(&bob)?;
// Retrieve and display all data
println!("\nRetrieving data from database:");
let circles = db.list_circles()?;
println!("Circles: {:#?}", circles);
let members = db.list_members()?;
println!("Members: {:#?}", members);
let names = db.list_names()?;
println!("Names: {:#?}", names);
let wallets = db.list_wallets()?;
println!("Wallets: {:#?}", wallets);
// Demonstrate wallet operations
println!("\nDemonstrating wallet operations:");
let mut alice_wallet = db.get_wallet(1)?;
println!("Alice's wallet before transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
let mut bob_wallet = db.get_wallet(2)?;
println!("Bob's wallet before transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
// Simulate a transfer of 100 TFT from Alice to Bob
alice_wallet.set_asset("TFT".to_string(), 900.0); // Decrease Alice's TFT by 100
bob_wallet.set_asset("TFT".to_string(), 600.0); // Increase Bob's TFT by 100
db.set(&alice_wallet)?;
db.set(&bob_wallet)?;
let alice_wallet = db.get_wallet(1)?;
println!("Alice's wallet after transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
let bob_wallet = db.get_wallet(2)?;
println!("Bob's wallet after transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
println!("\nCircle models demo completed successfully!");
Ok(())
}

View File

@@ -0,0 +1,106 @@
//! This is a standalone example that demonstrates the circle models
//! without using any database functionality.
use herodb::models::circle::{Circle, Member, Name, Wallet, Role, Record, RecordType};
fn main() {
println!("Circle Module Standalone Demo");
// Create a circle
let circle = Circle::new(
1,
"ThreeFold Community".to_string(),
"A circle for ThreeFold community members".to_string(),
);
println!("Created circle: {:?}", circle);
// Create members
let mut alice = Member::new(
1,
"Alice".to_string(),
"Core contributor".to_string(),
Role::Admin,
);
alice.add_email("alice@example.com".to_string());
let mut bob = Member::new(
2,
"Bob".to_string(),
"Community member".to_string(),
Role::Member,
);
bob.add_email("bob@example.com".to_string());
println!("Created members: {:?}, {:?}", alice, bob);
// Create a domain name
let mut domain = Name::new(
1,
"threefold.io".to_string(),
"ThreeFold main domain".to_string(),
);
let record = Record {
name: "www".to_string(),
text: "ThreeFold Website".to_string(),
category: RecordType::A,
addr: vec!["192.168.1.1".to_string()],
};
domain.add_record(record);
domain.add_admin("alice_pubkey".to_string());
println!("Created domain: {:?}", domain);
// Create wallets
let mut alice_wallet = Wallet::new(
1,
"Alice's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GALICE...".to_string(),
);
alice_wallet.set_asset("TFT".to_string(), 1000.0);
alice_wallet.set_asset("XLM".to_string(), 100.0);
let mut bob_wallet = Wallet::new(
2,
"Bob's TFT Wallet".to_string(),
"Main TFT wallet".to_string(),
"Stellar".to_string(),
"GBOB...".to_string(),
);
bob_wallet.set_asset("TFT".to_string(), 500.0);
println!("Created wallets: {:?}, {:?}", alice_wallet, bob_wallet);
// Link wallets to members
alice.link_wallet(alice_wallet.id);
bob.link_wallet(bob_wallet.id);
println!("Linked wallets to members");
// Demonstrate wallet operations
println!("\nDemonstrating wallet operations:");
println!("Alice's wallet before transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
println!("Bob's wallet before transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
// Simulate a transfer of 100 TFT from Alice to Bob
alice_wallet.set_asset("TFT".to_string(), 900.0); // Decrease Alice's TFT by 100
bob_wallet.set_asset("TFT".to_string(), 600.0); // Increase Bob's TFT by 100
println!("Alice's wallet after transfer: {:?}", alice_wallet);
println!("Alice's wallet total value: {}", alice_wallet.total_value());
println!("Bob's wallet after transfer: {:?}", bob_wallet);
println!("Bob's wallet total value: {}", bob_wallet.total_value());
println!("\nCircle standalone demo completed successfully!");
}

View File

@@ -6,6 +6,7 @@ use crate::models::gov::{
Company, Shareholder, Meeting, User, Vote, Resolution,
Committee, ComplianceRequirement, ComplianceDocument, ComplianceAudit
};
use crate::models::circle::{Circle, Member, Name, Wallet, Asset};
// Implement model-specific methods for Product
impl_model_methods!(Product, product, products);
@@ -59,4 +60,16 @@ impl_model_methods!(ComplianceRequirement, compliance_requirement, compliance_re
impl_model_methods!(ComplianceDocument, compliance_document, compliance_documents);
// Implement model-specific methods for ComplianceAudit
impl_model_methods!(ComplianceAudit, compliance_audit, compliance_audits);
impl_model_methods!(ComplianceAudit, compliance_audit, compliance_audits);
// Implement model-specific methods for Circle
impl_model_methods!(Circle, circle, circles);
// Implement model-specific methods for Member
impl_model_methods!(Member, member, members);
// Implement model-specific methods for Name
impl_model_methods!(Name, name, names);
// Implement model-specific methods for Wallet
impl_model_methods!(Wallet, wallet, wallets);

View File

@@ -235,6 +235,10 @@ impl ContractBuilder {
}
}
impl Storable for Contract {}
// Implement Model trait
impl Model for Contract {
fn get_id(&self) -> u32 {

View File

@@ -1,4 +1,5 @@
use crate::db::model::{Model, Storable};
use crate::db::model::Model;
use crate::db::{Storable, DbError, DbResult};
use chrono::{DateTime, Duration, Utc};
use rhai::{CustomType, EvalAltResult, TypeBuilder};
use serde::{Deserialize, Serialize};
@@ -72,6 +73,9 @@ impl CurrencyBuilder {
}
}
// Implement Storable trait
impl Storable for Currency {}
// Implement Model trait
impl Model for Currency {
fn get_id(&self) -> u32 {

View File

@@ -133,6 +133,9 @@ impl CustomerBuilder {
}
}
impl Storable for Customer {}
// Implement Model trait
impl Model for Customer {
fn get_id(&self) -> u32 {

View File

@@ -91,6 +91,9 @@ impl ExchangeRateBuilder {
}
}
impl Storable for ExchangeRate {}
// Implement Model trait
impl Model for ExchangeRate {
fn get_id(&self) -> u32 {

View File

@@ -500,6 +500,8 @@ impl InvoiceBuilder {
}
}
impl Storable for Invoice {}
// Implement Model trait
impl Model for Invoice {
fn get_id(&self) -> u32 {

View File

@@ -1,4 +1,5 @@
use crate::db::model::{Model, Storable};
use crate::db::model::Model;
use crate::db::Storable;
use chrono::{DateTime, Duration, Utc};
use rhai::{CustomType, EvalAltResult, TypeBuilder, export_module};
use serde::{Deserialize, Serialize};
@@ -342,6 +343,9 @@ impl ProductBuilder {
}
}
// Implement Storable trait
impl Storable for Product {}
// Implement Model trait
impl Model for Product {
fn get_id(&self) -> u32 {

View File

@@ -1,4 +1,4 @@
use crate::db::{Model, Storable};
use crate::db::{Model, Storable, DbError, DbResult};
use crate::models::biz::Currency; // Use crate:: for importing from the module
// use super::db::Model; // Removed old Model trait import
use chrono::{DateTime, Utc};
@@ -566,6 +566,9 @@ impl SaleBuilder {
}
}
// Implement Storable trait
impl Storable for Sale {}
// Implement Model trait
impl Model for Sale {
fn get_id(&self) -> u32 {

View File

@@ -1,5 +1,5 @@
use crate::models::biz::Currency; // Use crate:: for importing from the module
use crate::db::{Model, Storable}; // Import Model trait from db module
use crate::db::{Model, Storable, DbError, DbResult}; // Import Model trait from db module
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
@@ -491,6 +491,10 @@ impl ServiceBuilder {
}
}
// Implement Storable trait
impl Storable for Service {
}
// Implement Model trait
impl Model for Service {
fn get_id(&self) -> u32 {

View File

@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Circle represents a collection of members (users or other circles)
@@ -28,6 +28,9 @@ impl Circle {
}
}
// Implement Storable trait
impl Storable for Circle {}
// Implement Model trait
impl Model for Circle {
fn get_id(&self) -> u32 {

View File

@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Role represents the role of a member in a circle
@@ -67,6 +67,10 @@ impl Member {
}
}
// Implement Storable trait
impl Storable for Member {
}
// Implement Model trait
impl Model for Member {
fn get_id(&self) -> u32 {

View File

@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable};
use crate::db::{Model, Storable, DbError, DbResult};
/// Record types for a DNS record
#[derive(Debug, Clone, Serialize, Deserialize)]
@@ -57,6 +57,10 @@ impl Name {
}
}
// Implement Storable trait
impl Storable for Name {
}
// Implement Model trait
impl Model for Name {
fn get_id(&self) -> u32 {

View File

@@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable};
use crate::db::{Model, Storable, DbError, DbResult};
use std::collections::HashMap;
/// Asset represents a cryptocurrency asset in a wallet
@@ -70,7 +70,8 @@ impl Wallet {
}
// Implement Storable trait
impl Storable for Wallet {}
impl Storable for Wallet {
}
// Implement Model trait
impl Model for Wallet {

View File

@@ -1,5 +1,7 @@
use crate::db::{Model, Storable, DbError, DbResult};
use crate::db::{Model, Storable, DbResult};
use crate::db::db::DB;
use super::shareholder::Shareholder; // Use super:: for sibling module
use super::Resolution;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@@ -87,7 +89,7 @@ pub struct Company {
// Removed shareholders property
}
impl Storable for Company{}
// Model requires get_id and db_prefix
impl Model for Company {
@@ -150,24 +152,22 @@ impl Company {
}
/// Link this company to a Circle for access control
pub fn link_to_circle(&mut self, circle_id: u32) -> DbResult<()> {
pub fn link_to_circle(&mut self, circle_id: u32) {
// 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<()> {
pub fn link_to_customer(&mut self, customer_id: u32) {
// 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>()?;
pub fn get_resolutions(&self, db: &DB) -> DbResult<Vec<Resolution>> {
let all_resolutions = db.list::<Resolution>()?;
let company_resolutions = all_resolutions
.into_iter()
.filter(|resolution| resolution.company_id == self.id)

View File

@@ -1,207 +0,0 @@
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::db::{Model, Storable, DB, DbError, DbResult};
use crate::models::gov::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: &DB) -> DbResult<Company> {
db.get::<Company>(self.company_id)
}
/// Get all documents associated with this requirement
pub fn get_documents(&self, db: &DB) -> DbResult<Vec<ComplianceDocument>> {
let all_documents = db.list::<ComplianceDocument>()?;
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: &DB) -> DbResult<ComplianceRequirement> {
db.get::<ComplianceRequirement>(self.requirement_id)
}
}
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: &DB) -> DbResult<Company> {
db.get::<Company>(self.company_id)
}
}
// Implement Model trait
impl Model for ComplianceRequirement {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"compliance_requirement"
}
}
impl Model for ComplianceDocument {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"compliance_document"
}
}
impl Model for ComplianceAudit {
fn get_id(&self) -> u32 {
self.id
}
fn db_prefix() -> &'static str {
"compliance_audit"
}
}

View File

@@ -175,6 +175,7 @@ impl Meeting {
}
}
impl Storable for Meeting{}
// Implement Model trait
impl Model for Meeting {
fn get_id(&self) -> u32 {

View File

@@ -6,7 +6,6 @@ pub mod vote;
pub mod resolution;
// All modules:
pub mod committee;
pub mod compliance;
// Re-export all model types for convenience
pub use company::{Company, CompanyStatus, BusinessType};
@@ -16,7 +15,6 @@ pub use user::User;
pub use vote::{Vote, VoteOption, Ballot, VoteStatus};
pub use resolution::{Resolution, ResolutionStatus, Approval};
pub use committee::{Committee, CommitteeMember, CommitteeRole};
pub use compliance::{ComplianceRequirement, ComplianceDocument, ComplianceAudit};
// Re-export database components from db module
pub use crate::db::{DB, DBBuilder, Model, Storable, DbError, DbResult};

View File

@@ -180,6 +180,9 @@ impl Resolution {
}
}
impl Storable for Resolution{}
// Implement Model trait
impl Model for Resolution {
fn get_id(&self) -> u32 {

View File

@@ -63,6 +63,8 @@ impl Shareholder {
}
}
impl Storable for Shareholder{}
// Implement Model trait
impl Model for Shareholder {
fn get_id(&self) -> u32 {

View File

@@ -42,6 +42,8 @@ impl User {
}
}
impl Storable for User{}
// Implement Model trait
impl Model for User {
fn get_id(&self) -> u32 {

View File

@@ -51,7 +51,7 @@ pub struct Ballot {
pub created_at: DateTime<Utc>,
}
// Removed old Model trait implementation
impl Storable for Vote{}
impl Vote {
/// Create a new vote with default timestamps