Merge branch 'development_add_incremental_mode_to_heromodels'
This commit is contained in:
		
							
								
								
									
										357
									
								
								heromodels/examples/governance_activity_example.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										357
									
								
								heromodels/examples/governance_activity_example.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,357 @@
 | 
			
		||||
// heromodels/examples/governance_activity_example.rs
 | 
			
		||||
 | 
			
		||||
use chrono::{Duration, Utc};
 | 
			
		||||
use heromodels::db::{Collection, Db};
 | 
			
		||||
use heromodels::models::governance::{
 | 
			
		||||
    ActivityType, GovernanceActivity, Proposal, ProposalStatus, VoteEventStatus,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    println!("Governance Activity Tracking Example\n");
 | 
			
		||||
 | 
			
		||||
    // Create a new DB instance with a unique path, reset before every run
 | 
			
		||||
    let db_path = format!(
 | 
			
		||||
        "/tmp/ourdb_governance_activity_example_{}",
 | 
			
		||||
        chrono::Utc::now().timestamp()
 | 
			
		||||
    );
 | 
			
		||||
    let db = heromodels::db::hero::OurDB::new(&db_path, true).expect("Can create DB");
 | 
			
		||||
 | 
			
		||||
    // Get collections for proposals and activities
 | 
			
		||||
    let proposal_collection = db
 | 
			
		||||
        .collection::<Proposal>()
 | 
			
		||||
        .expect("can open proposal collection");
 | 
			
		||||
    let activity_collection = db
 | 
			
		||||
        .collection::<GovernanceActivity>()
 | 
			
		||||
        .expect("can open activity collection");
 | 
			
		||||
 | 
			
		||||
    // === STEP 1: Create a proposal and track the activity ===
 | 
			
		||||
    println!("=== Creating a Proposal ===");
 | 
			
		||||
 | 
			
		||||
    let now = Utc::now();
 | 
			
		||||
    let mut proposal = Proposal::new(
 | 
			
		||||
        None, // auto-generated ID
 | 
			
		||||
        "user_creator_123",
 | 
			
		||||
        "Alice Johnson",
 | 
			
		||||
        "Community Fund Allocation for Q4",
 | 
			
		||||
        "Proposal to allocate funds for community projects in the fourth quarter.",
 | 
			
		||||
        ProposalStatus::Draft,
 | 
			
		||||
        now,
 | 
			
		||||
        now,
 | 
			
		||||
        now,
 | 
			
		||||
        now + Duration::days(14),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Save the proposal
 | 
			
		||||
    let (proposal_id, saved_proposal) = proposal_collection
 | 
			
		||||
        .set(&proposal)
 | 
			
		||||
        .expect("can save proposal");
 | 
			
		||||
    proposal = saved_proposal;
 | 
			
		||||
 | 
			
		||||
    println!(
 | 
			
		||||
        "Created proposal: '{}' (ID: {})",
 | 
			
		||||
        proposal.title, proposal_id
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Track the proposal creation activity
 | 
			
		||||
    let creation_activity = GovernanceActivity::proposal_created(
 | 
			
		||||
        proposal_id,
 | 
			
		||||
        &proposal.title,
 | 
			
		||||
        &proposal.creator_id,
 | 
			
		||||
        &proposal.creator_name,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let (activity_id, _) = activity_collection
 | 
			
		||||
        .set(&creation_activity)
 | 
			
		||||
        .expect("can save activity");
 | 
			
		||||
 | 
			
		||||
    println!(
 | 
			
		||||
        "Tracked activity: Proposal creation (Activity ID: {})",
 | 
			
		||||
        activity_id
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // === STEP 2: Add vote options and track activities ===
 | 
			
		||||
    println!("\n=== Adding Vote Options ===");
 | 
			
		||||
 | 
			
		||||
    proposal = proposal.add_option(1, "Approve Allocation", None::<String>);
 | 
			
		||||
    proposal = proposal.add_option(2, "Reject Allocation", None::<String>);
 | 
			
		||||
    proposal = proposal.add_option(3, "Abstain", None::<String>);
 | 
			
		||||
 | 
			
		||||
    // Track vote option additions
 | 
			
		||||
    for option in &proposal.options {
 | 
			
		||||
        let option_activity = GovernanceActivity::vote_option_added(
 | 
			
		||||
            proposal_id,
 | 
			
		||||
            &proposal.title,
 | 
			
		||||
            option.id,
 | 
			
		||||
            &option.text,
 | 
			
		||||
            Some(&proposal.creator_id),
 | 
			
		||||
            Some(&proposal.creator_name),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let (option_activity_id, _) = activity_collection
 | 
			
		||||
            .set(&option_activity)
 | 
			
		||||
            .expect("can save option activity");
 | 
			
		||||
 | 
			
		||||
        println!(
 | 
			
		||||
            "Added option '{}' and tracked activity (ID: {})",
 | 
			
		||||
            option.text, option_activity_id
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // === STEP 3: Start voting and track activity ===
 | 
			
		||||
    println!("\n=== Starting Voting Period ===");
 | 
			
		||||
 | 
			
		||||
    let voting_start_activity = GovernanceActivity::voting_started(
 | 
			
		||||
        proposal_id,
 | 
			
		||||
        &proposal.title,
 | 
			
		||||
        proposal.vote_start_date,
 | 
			
		||||
        proposal.vote_end_date,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let (voting_start_id, _) = activity_collection
 | 
			
		||||
        .set(&voting_start_activity)
 | 
			
		||||
        .expect("can save voting start activity");
 | 
			
		||||
 | 
			
		||||
    println!("Voting period started (Activity ID: {})", voting_start_id);
 | 
			
		||||
 | 
			
		||||
    // === STEP 4: Cast votes and track activities ===
 | 
			
		||||
    println!("\n=== Casting Votes ===");
 | 
			
		||||
 | 
			
		||||
    // Simulate vote casting
 | 
			
		||||
    let votes = vec![
 | 
			
		||||
        (101, 1, 1, 100, "Bob Smith"),
 | 
			
		||||
        (102, 2, 2, 50, "Carol Davis"),
 | 
			
		||||
        (0, 3, 1, 75, "David Wilson"), // auto-generated ballot ID
 | 
			
		||||
        (0, 4, 3, 20, "Eve Brown"),    // auto-generated ballot ID
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    for (ballot_id, user_id, option_id, shares, voter_name) in votes {
 | 
			
		||||
        // Cast the vote
 | 
			
		||||
        proposal = proposal.cast_vote(
 | 
			
		||||
            if ballot_id == 0 {
 | 
			
		||||
                None
 | 
			
		||||
            } else {
 | 
			
		||||
                Some(ballot_id)
 | 
			
		||||
            },
 | 
			
		||||
            user_id,
 | 
			
		||||
            option_id,
 | 
			
		||||
            shares,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Find the option text
 | 
			
		||||
        let option_text = proposal
 | 
			
		||||
            .options
 | 
			
		||||
            .iter()
 | 
			
		||||
            .find(|opt| opt.id == option_id)
 | 
			
		||||
            .map(|opt| opt.text.clone())
 | 
			
		||||
            .unwrap_or_else(|| "Unknown".to_string());
 | 
			
		||||
 | 
			
		||||
        // Track the vote casting activity
 | 
			
		||||
        let vote_activity = GovernanceActivity::vote_cast(
 | 
			
		||||
            proposal_id,
 | 
			
		||||
            &proposal.title,
 | 
			
		||||
            ballot_id,
 | 
			
		||||
            user_id.to_string(),
 | 
			
		||||
            voter_name,
 | 
			
		||||
            &option_text,
 | 
			
		||||
            shares,
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        let (vote_activity_id, _) = activity_collection
 | 
			
		||||
            .set(&vote_activity)
 | 
			
		||||
            .expect("can save vote activity");
 | 
			
		||||
 | 
			
		||||
        println!(
 | 
			
		||||
            "{} voted '{}' with {} shares (Activity ID: {})",
 | 
			
		||||
            voter_name, option_text, shares, vote_activity_id
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // === STEP 5: Change proposal status and track activity ===
 | 
			
		||||
    println!("\n=== Changing Proposal Status ===");
 | 
			
		||||
 | 
			
		||||
    let old_status = format!("{:?}", proposal.status);
 | 
			
		||||
    proposal = proposal.change_proposal_status(ProposalStatus::Active);
 | 
			
		||||
    let new_status = format!("{:?}", proposal.status);
 | 
			
		||||
 | 
			
		||||
    let status_change_activity = GovernanceActivity::proposal_status_changed(
 | 
			
		||||
        proposal_id,
 | 
			
		||||
        &proposal.title,
 | 
			
		||||
        &old_status,
 | 
			
		||||
        &new_status,
 | 
			
		||||
        Some("admin_user"),
 | 
			
		||||
        Some("Admin User"),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let (status_activity_id, _) = activity_collection
 | 
			
		||||
        .set(&status_change_activity)
 | 
			
		||||
        .expect("can save status change activity");
 | 
			
		||||
 | 
			
		||||
    println!(
 | 
			
		||||
        "Proposal status changed from {} to {} (Activity ID: {})",
 | 
			
		||||
        old_status, new_status, status_activity_id
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // === STEP 6: End voting and track activity ===
 | 
			
		||||
    println!("\n=== Ending Voting Period ===");
 | 
			
		||||
 | 
			
		||||
    proposal = proposal.change_vote_event_status(VoteEventStatus::Closed);
 | 
			
		||||
 | 
			
		||||
    let total_votes = proposal.ballots.len();
 | 
			
		||||
    let total_shares: i64 = proposal.ballots.iter().map(|b| b.shares_count).sum();
 | 
			
		||||
 | 
			
		||||
    let voting_end_activity =
 | 
			
		||||
        GovernanceActivity::voting_ended(proposal_id, &proposal.title, total_votes, total_shares);
 | 
			
		||||
 | 
			
		||||
    let (voting_end_id, _) = activity_collection
 | 
			
		||||
        .set(&voting_end_activity)
 | 
			
		||||
        .expect("can save voting end activity");
 | 
			
		||||
 | 
			
		||||
    println!(
 | 
			
		||||
        "Voting period ended. Total votes: {}, Total shares: {} (Activity ID: {})",
 | 
			
		||||
        total_votes, total_shares, voting_end_id
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // === STEP 7: Display all activities ===
 | 
			
		||||
    println!("\n=== Recent Governance Activities ===");
 | 
			
		||||
 | 
			
		||||
    // Try to retrieve activities one by one to identify the problematic one
 | 
			
		||||
    println!("Trying to retrieve activities by ID...");
 | 
			
		||||
    for id in 2..=12 {
 | 
			
		||||
        match activity_collection.get_by_id(id) {
 | 
			
		||||
            Ok(Some(activity)) => {
 | 
			
		||||
                println!(
 | 
			
		||||
                    "ID {}: {} (Type: {:?})",
 | 
			
		||||
                    id, activity.title, activity.activity_type
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
            Ok(None) => {
 | 
			
		||||
                println!("ID {}: Not found", id);
 | 
			
		||||
            }
 | 
			
		||||
            Err(e) => {
 | 
			
		||||
                println!("ID {}: Error - {:?}", id, e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let all_activities = match activity_collection.get_all() {
 | 
			
		||||
        Ok(activities) => {
 | 
			
		||||
            println!("Successfully retrieved {} activities", activities.len());
 | 
			
		||||
            activities
 | 
			
		||||
        }
 | 
			
		||||
        Err(e) => {
 | 
			
		||||
            println!("Error retrieving all activities: {:?}", e);
 | 
			
		||||
            println!(
 | 
			
		||||
                "This might be due to enum serialization changes. Continuing with empty list."
 | 
			
		||||
            );
 | 
			
		||||
            Vec::new()
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Sort activities by occurred_at timestamp (most recent first)
 | 
			
		||||
    let mut sorted_activities = all_activities;
 | 
			
		||||
    sorted_activities.sort_by(|a, b| b.occurred_at.cmp(&a.occurred_at));
 | 
			
		||||
 | 
			
		||||
    for (i, activity) in sorted_activities.iter().enumerate() {
 | 
			
		||||
        println!("{}. {}", i + 1, activity.summary());
 | 
			
		||||
 | 
			
		||||
        // Show additional details for some activities
 | 
			
		||||
        if !activity.metadata.is_empty() {
 | 
			
		||||
            println!("   Details: {}", activity.metadata);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if !activity.tags.is_empty() {
 | 
			
		||||
            println!("   Tags: {:?}", activity.tags);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        println!(
 | 
			
		||||
            "   Severity: {:?}, Status: {:?}",
 | 
			
		||||
            activity.severity, activity.status
 | 
			
		||||
        );
 | 
			
		||||
        println!();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // === STEP 8: Filter activities by type ===
 | 
			
		||||
    println!("=== Vote-Related Activities ===");
 | 
			
		||||
 | 
			
		||||
    let vote_activities: Vec<_> = sorted_activities
 | 
			
		||||
        .iter()
 | 
			
		||||
        .filter(|activity| {
 | 
			
		||||
            matches!(
 | 
			
		||||
                activity.activity_type,
 | 
			
		||||
                ActivityType::VoteCast
 | 
			
		||||
                    | ActivityType::VotingStarted
 | 
			
		||||
                    | ActivityType::VotingEnded
 | 
			
		||||
                    | ActivityType::VoteOptionAdded
 | 
			
		||||
            )
 | 
			
		||||
        })
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    for (i, activity) in vote_activities.iter().enumerate() {
 | 
			
		||||
        println!("{}. {}", i + 1, activity.summary());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // // === STEP 9: Filter activities by user - "My Requests" ===
 | 
			
		||||
    // println!("\n=== My Requests (Alice Johnson's Activities) ===");
 | 
			
		||||
 | 
			
		||||
    // let my_activities: Vec<_> = sorted_activities
 | 
			
		||||
    //     .iter()
 | 
			
		||||
    //     .filter(|activity| activity.actor_name.as_deref() == Some("Alice Johnson"))
 | 
			
		||||
    //     .collect();
 | 
			
		||||
 | 
			
		||||
    // if my_activities.is_empty() {
 | 
			
		||||
    //     println!("No activities found for Alice Johnson");
 | 
			
		||||
    // } else {
 | 
			
		||||
    //     for (i, activity) in my_activities.iter().enumerate() {
 | 
			
		||||
    //         println!("{}. {}", i + 1, activity.summary());
 | 
			
		||||
 | 
			
		||||
    //         // Show additional details for user's own activities
 | 
			
		||||
    //         if !activity.metadata.is_empty() {
 | 
			
		||||
    //             println!("   Details: {}", activity.metadata);
 | 
			
		||||
    //         }
 | 
			
		||||
 | 
			
		||||
    //         if !activity.tags.is_empty() {
 | 
			
		||||
    //             println!("   Tags: {:?}", activity.tags);
 | 
			
		||||
    //         }
 | 
			
		||||
    //         println!();
 | 
			
		||||
    //     }
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    // === STEP 10: Filter activities by another user ===
 | 
			
		||||
    println!("=== Bob Smith's Activities ===");
 | 
			
		||||
 | 
			
		||||
    let bob_activities: Vec<_> = sorted_activities
 | 
			
		||||
        .iter()
 | 
			
		||||
        .filter(|activity| activity.actor_name.as_deref() == Some("Bob Smith"))
 | 
			
		||||
        .collect();
 | 
			
		||||
 | 
			
		||||
    if bob_activities.is_empty() {
 | 
			
		||||
        println!("No activities found for Bob Smith");
 | 
			
		||||
    } else {
 | 
			
		||||
        for (i, activity) in bob_activities.iter().enumerate() {
 | 
			
		||||
            println!("{}. {}", i + 1, activity.summary());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // === STEP 9: Show statistics ===
 | 
			
		||||
    println!("\n=== Activity Statistics ===");
 | 
			
		||||
    println!("Total activities recorded: {}", sorted_activities.len());
 | 
			
		||||
 | 
			
		||||
    let activity_counts =
 | 
			
		||||
        sorted_activities
 | 
			
		||||
            .iter()
 | 
			
		||||
            .fold(std::collections::HashMap::new(), |mut acc, activity| {
 | 
			
		||||
                *acc.entry(format!("{:?}", activity.activity_type))
 | 
			
		||||
                    .or_insert(0) += 1;
 | 
			
		||||
                acc
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
    for (activity_type, count) in activity_counts {
 | 
			
		||||
        println!("- {}: {}", activity_type, count);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    println!("\nExample finished. DB stored at {}", db_path);
 | 
			
		||||
    println!(
 | 
			
		||||
        "To clean up, you can manually delete the directory: {}",
 | 
			
		||||
        db_path
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										328
									
								
								heromodels/examples/marketplace_example.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								heromodels/examples/marketplace_example.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,328 @@
 | 
			
		||||
use chrono::{Duration, Utc};
 | 
			
		||||
use heromodels::db::{Collection, Db};
 | 
			
		||||
use heromodels::models::finance::marketplace::{Bid, Listing, ListingType};
 | 
			
		||||
use heromodels::models::finance::asset::AssetType;
 | 
			
		||||
use heromodels_core::Model;
 | 
			
		||||
 | 
			
		||||
// Helper function to print listing details
 | 
			
		||||
fn print_listing_details(listing: &Listing) {
 | 
			
		||||
    println!("\n--- Listing Details ---");
 | 
			
		||||
    println!("ID: {}", listing.get_id());
 | 
			
		||||
    println!("Title: {}", listing.title);
 | 
			
		||||
    println!("Description: {}", listing.description);
 | 
			
		||||
    println!("Asset ID: {}", listing.asset_id);
 | 
			
		||||
    println!("Asset Type: {:?}", listing.asset_type);
 | 
			
		||||
    println!("Seller ID: {}", listing.seller_id);
 | 
			
		||||
    println!("Price: {} {}", listing.price, listing.currency);
 | 
			
		||||
    println!("Listing Type: {:?}", listing.listing_type);
 | 
			
		||||
    println!("Status: {:?}", listing.status);
 | 
			
		||||
    
 | 
			
		||||
    if let Some(expires_at) = listing.expires_at {
 | 
			
		||||
        println!("Expires At: {}", expires_at);
 | 
			
		||||
    } else {
 | 
			
		||||
        println!("Expires At: Never");
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if let Some(sold_at) = listing.sold_at {
 | 
			
		||||
        println!("Sold At: {}", sold_at);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if let Some(buyer_id) = &listing.buyer_id {
 | 
			
		||||
        println!("Buyer ID: {}", buyer_id);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if let Some(sale_price) = listing.sale_price {
 | 
			
		||||
        println!("Sale Price: {} {}", sale_price, listing.currency);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    println!("Bids: {}", listing.bids.len());
 | 
			
		||||
    println!("Tags: {:?}", listing.tags);
 | 
			
		||||
    
 | 
			
		||||
    if let Some(image_url) = &listing.image_url {
 | 
			
		||||
        println!("Image URL: {}", image_url);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    println!("Created At: {}", listing.base_data.created_at);
 | 
			
		||||
    println!("Modified At: {}", listing.base_data.modified_at);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper function to print bid details
 | 
			
		||||
fn print_bid_details(bid: &Bid) {
 | 
			
		||||
    println!("\n--- Bid Details ---");
 | 
			
		||||
    println!("Listing ID: {}", bid.listing_id);
 | 
			
		||||
    println!("Bidder ID: {}", bid.bidder_id);
 | 
			
		||||
    println!("Amount: {} {}", bid.amount, bid.currency);
 | 
			
		||||
    println!("Status: {:?}", bid.status);
 | 
			
		||||
    println!("Created At: {}", bid.created_at);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    // Create a new DB instance in /tmp/marketplace_db, and reset before every run
 | 
			
		||||
    let db = heromodels::db::hero::OurDB::new("/tmp/marketplace_db", true).expect("Can create DB");
 | 
			
		||||
 | 
			
		||||
    println!("Hero Models - Marketplace Example");
 | 
			
		||||
    println!("================================");
 | 
			
		||||
 | 
			
		||||
    // Create listings with auto-generated IDs
 | 
			
		||||
 | 
			
		||||
    // Fixed price listing
 | 
			
		||||
    let fixed_price_listing = Listing::new(
 | 
			
		||||
        None, // Auto-generated ID
 | 
			
		||||
        "Vintage Guitar",
 | 
			
		||||
        "A beautiful vintage guitar in excellent condition",
 | 
			
		||||
        "asset123",
 | 
			
		||||
        AssetType::Erc721, // NFT representing a physical item
 | 
			
		||||
        "seller456",
 | 
			
		||||
        1200.0,
 | 
			
		||||
        "USD",
 | 
			
		||||
        ListingType::FixedPrice,
 | 
			
		||||
        Some(Utc::now() + Duration::days(30)), // Expires in 30 days
 | 
			
		||||
        vec!["music".to_string(), "instrument".to_string(), "vintage".to_string()],
 | 
			
		||||
        Some("https://example.com/images/vintage_guitar.jpg"),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Auction listing
 | 
			
		||||
    let auction_listing = Listing::new(
 | 
			
		||||
        None, // Auto-generated ID
 | 
			
		||||
        "Rare Painting",
 | 
			
		||||
        "A rare painting from the 19th century",
 | 
			
		||||
        "asset789",
 | 
			
		||||
        AssetType::Erc721, // NFT representing a physical item
 | 
			
		||||
        "seller456",
 | 
			
		||||
        5000.0, // Starting price
 | 
			
		||||
        "USD",
 | 
			
		||||
        ListingType::Auction,
 | 
			
		||||
        Some(Utc::now() + Duration::days(7)), // Auction ends in 7 days
 | 
			
		||||
        vec!["art".to_string(), "painting".to_string(), "antique".to_string()],
 | 
			
		||||
        Some("https://example.com/images/rare_painting.jpg"),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Exchange listing
 | 
			
		||||
    let exchange_listing = Listing::new(
 | 
			
		||||
        None, // Auto-generated ID
 | 
			
		||||
        "Digital Artwork NFT",
 | 
			
		||||
        "A unique digital artwork as an NFT",
 | 
			
		||||
        "asset101",
 | 
			
		||||
        AssetType::Erc1155, // Multi-token for digital art
 | 
			
		||||
        "seller789",
 | 
			
		||||
        0.5, // Price in ETH
 | 
			
		||||
        "ETH",
 | 
			
		||||
        ListingType::Exchange,
 | 
			
		||||
        Some(Utc::now() + Duration::days(14)), // Expires in 14 days
 | 
			
		||||
        vec!["digital".to_string(), "nft".to_string(), "art".to_string()],
 | 
			
		||||
        Some("https://example.com/images/digital_artwork.jpg"),
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Save all listings to database and get their assigned IDs and updated models
 | 
			
		||||
    let (fixed_price_id, db_fixed_price) = db.collection().expect("can open listing collection").set(&fixed_price_listing).expect("can set listing");
 | 
			
		||||
    let (auction_id, db_auction) = db.collection().expect("can open listing collection").set(&auction_listing).expect("can set listing");
 | 
			
		||||
    let (exchange_id, db_exchange) = db.collection().expect("can open listing collection").set(&exchange_listing).expect("can set listing");
 | 
			
		||||
 | 
			
		||||
    println!("Fixed Price Listing assigned ID: {}", fixed_price_id);
 | 
			
		||||
    println!("Auction Listing assigned ID: {}", auction_id);
 | 
			
		||||
    println!("Exchange Listing assigned ID: {}", exchange_id);
 | 
			
		||||
 | 
			
		||||
    // Print all listings retrieved from database
 | 
			
		||||
    println!("\n--- Listings Retrieved from Database ---");
 | 
			
		||||
    println!("\n1. Fixed Price Listing:");
 | 
			
		||||
    print_listing_details(&db_fixed_price);
 | 
			
		||||
 | 
			
		||||
    println!("\n2. Auction Listing:");
 | 
			
		||||
    print_listing_details(&db_auction);
 | 
			
		||||
 | 
			
		||||
    println!("\n3. Exchange Listing:");
 | 
			
		||||
    print_listing_details(&db_exchange);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate working with bids on an auction listing
 | 
			
		||||
    println!("\n--- Working with Bids ---");
 | 
			
		||||
 | 
			
		||||
    // Create bids for the auction listing
 | 
			
		||||
    let bid1 = Bid::new(
 | 
			
		||||
        auction_id,
 | 
			
		||||
        101, // Bidder ID
 | 
			
		||||
        5200.0,
 | 
			
		||||
        "USD",
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    let bid2 = Bid::new(
 | 
			
		||||
        auction_id,
 | 
			
		||||
        102, // Bidder ID
 | 
			
		||||
        5500.0,
 | 
			
		||||
        "USD",
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Print the bids
 | 
			
		||||
    println!("\n1. First Bid:");
 | 
			
		||||
    print_bid_details(&bid1);
 | 
			
		||||
 | 
			
		||||
    println!("\n2. Second Bid:");
 | 
			
		||||
    print_bid_details(&bid2);
 | 
			
		||||
 | 
			
		||||
    // Add bids to the auction listing
 | 
			
		||||
    let updated_auction = db_auction
 | 
			
		||||
        .add_bid(bid1.clone())
 | 
			
		||||
        .expect("can add first bid")
 | 
			
		||||
        .add_bid(bid2.clone())
 | 
			
		||||
        .expect("can add second bid");
 | 
			
		||||
 | 
			
		||||
    // Save the updated auction listing
 | 
			
		||||
    let (_, db_updated_auction) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&updated_auction)
 | 
			
		||||
        .expect("can set updated auction");
 | 
			
		||||
 | 
			
		||||
    println!("\n3. Auction Listing After Adding Bids:");
 | 
			
		||||
    print_listing_details(&db_updated_auction);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate retrieving the highest bid
 | 
			
		||||
    if let Some(highest_bid) = db_updated_auction.highest_bid() {
 | 
			
		||||
        println!("\n4. Highest Bid:");
 | 
			
		||||
        print_bid_details(highest_bid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Demonstrate completing a sale for the fixed price listing
 | 
			
		||||
    println!("\n--- Completing a Sale ---");
 | 
			
		||||
 | 
			
		||||
    // Complete the fixed price listing sale
 | 
			
		||||
    let completed_fixed_price = db_fixed_price
 | 
			
		||||
        .complete_sale("buyer123", 1200.0)
 | 
			
		||||
        .expect("can complete sale");
 | 
			
		||||
 | 
			
		||||
    // Save the updated listing
 | 
			
		||||
    let (_, db_completed_fixed_price) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&completed_fixed_price)
 | 
			
		||||
        .expect("can set completed listing");
 | 
			
		||||
 | 
			
		||||
    println!("\n1. Fixed Price Listing After Sale:");
 | 
			
		||||
    print_listing_details(&db_completed_fixed_price);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate completing an auction
 | 
			
		||||
    println!("\n--- Completing an Auction ---");
 | 
			
		||||
 | 
			
		||||
    // Complete the auction with the highest bidder
 | 
			
		||||
    // Store the bidder_id and amount before moving db_updated_auction
 | 
			
		||||
    let bidder_id = db_updated_auction.highest_bid().unwrap().bidder_id;
 | 
			
		||||
    let amount = db_updated_auction.highest_bid().unwrap().amount;
 | 
			
		||||
    
 | 
			
		||||
    // Now complete the sale
 | 
			
		||||
    let completed_auction = db_updated_auction
 | 
			
		||||
        .complete_sale(bidder_id.to_string(), amount)
 | 
			
		||||
        .expect("can complete auction");
 | 
			
		||||
 | 
			
		||||
    // Save the updated auction listing
 | 
			
		||||
    let (_, db_completed_auction) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&completed_auction)
 | 
			
		||||
        .expect("can set completed auction");
 | 
			
		||||
 | 
			
		||||
    println!("\n1. Auction Listing After Completion:");
 | 
			
		||||
    print_listing_details(&db_completed_auction);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate cancelling a listing
 | 
			
		||||
    println!("\n--- Cancelling a Listing ---");
 | 
			
		||||
 | 
			
		||||
    // Cancel the exchange listing
 | 
			
		||||
    let cancelled_exchange = db_exchange
 | 
			
		||||
        .cancel()
 | 
			
		||||
        .expect("can cancel listing");
 | 
			
		||||
 | 
			
		||||
    // Save the updated listing
 | 
			
		||||
    let (_, db_cancelled_exchange) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&cancelled_exchange)
 | 
			
		||||
        .expect("can set cancelled listing");
 | 
			
		||||
 | 
			
		||||
    println!("\n1. Exchange Listing After Cancellation:");
 | 
			
		||||
    print_listing_details(&db_cancelled_exchange);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate checking for expired listings
 | 
			
		||||
    println!("\n--- Checking for Expired Listings ---");
 | 
			
		||||
 | 
			
		||||
    // Create a listing that's already expired
 | 
			
		||||
    let expired_listing = Listing::new(
 | 
			
		||||
        None, // Auto-generated ID
 | 
			
		||||
        "Already Expired Item",
 | 
			
		||||
        "This item's listing has already expired",
 | 
			
		||||
        "asset202",
 | 
			
		||||
        AssetType::Erc721, // NFT representing a physical item
 | 
			
		||||
        "seller456",
 | 
			
		||||
        50.0,
 | 
			
		||||
        "USD",
 | 
			
		||||
        ListingType::FixedPrice,
 | 
			
		||||
        Some(Utc::now() - Duration::days(1)), // Expired 1 day ago
 | 
			
		||||
        vec!["expired".to_string()],
 | 
			
		||||
        None::<String>,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Save the expired listing
 | 
			
		||||
    let (expired_id, db_expired) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&expired_listing)
 | 
			
		||||
        .expect("can set expired listing");
 | 
			
		||||
 | 
			
		||||
    println!("Expired Listing assigned ID: {}", expired_id);
 | 
			
		||||
 | 
			
		||||
    // Check expiration
 | 
			
		||||
    let checked_expired = db_expired.check_expiration();
 | 
			
		||||
 | 
			
		||||
    // Save the checked listing
 | 
			
		||||
    let (_, db_checked_expired) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&checked_expired)
 | 
			
		||||
        .expect("can set checked listing");
 | 
			
		||||
 | 
			
		||||
    println!("\n1. Listing After Expiration Check:");
 | 
			
		||||
    print_listing_details(&db_checked_expired);
 | 
			
		||||
 | 
			
		||||
    // Demonstrate updating listing details
 | 
			
		||||
    println!("\n--- Updating Listing Details ---");
 | 
			
		||||
 | 
			
		||||
    // Create a new listing to update
 | 
			
		||||
    let listing_to_update = Listing::new(
 | 
			
		||||
        None, // Auto-generated ID
 | 
			
		||||
        "Original Title",
 | 
			
		||||
        "Original description",
 | 
			
		||||
        "asset303",
 | 
			
		||||
        AssetType::Erc20, // Token for a digital asset
 | 
			
		||||
        "seller456",
 | 
			
		||||
        75.0,
 | 
			
		||||
        "USD",
 | 
			
		||||
        ListingType::FixedPrice,
 | 
			
		||||
        Some(Utc::now() + Duration::days(30)),
 | 
			
		||||
        vec!["original".to_string()],
 | 
			
		||||
        None::<String>,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Save the listing
 | 
			
		||||
    let (update_id, db_to_update) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&listing_to_update)
 | 
			
		||||
        .expect("can set listing to update");
 | 
			
		||||
 | 
			
		||||
    println!("Listing to Update assigned ID: {}", update_id);
 | 
			
		||||
    println!("\n1. Original Listing:");
 | 
			
		||||
    print_listing_details(&db_to_update);
 | 
			
		||||
 | 
			
		||||
    // Update the listing details
 | 
			
		||||
    let updated_listing = db_to_update
 | 
			
		||||
        .update_details(
 | 
			
		||||
            Some("Updated Title"),
 | 
			
		||||
            Some("Updated description with more details"),
 | 
			
		||||
            Some(85.0),
 | 
			
		||||
            Some("https://example.com/images/updated_image.jpg"),
 | 
			
		||||
        )
 | 
			
		||||
        .add_tags(vec!["updated".to_string(), "premium".to_string()]);
 | 
			
		||||
 | 
			
		||||
    // Save the updated listing
 | 
			
		||||
    let (_, db_updated_listing) = db.collection()
 | 
			
		||||
        .expect("can open listing collection")
 | 
			
		||||
        .set(&updated_listing)
 | 
			
		||||
        .expect("can set updated listing");
 | 
			
		||||
 | 
			
		||||
    println!("\n2. Listing After Update:");
 | 
			
		||||
    print_listing_details(&db_updated_listing);
 | 
			
		||||
 | 
			
		||||
    println!("\n--- Model Information ---");
 | 
			
		||||
    println!("Listing DB Prefix: {}", Listing::db_prefix());
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user