...
This commit is contained in:
		
							
								
								
									
										428
									
								
								herodb/examples/business_models_demo.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										428
									
								
								herodb/examples/business_models_demo.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,428 @@
 | 
			
		||||
use chrono::{DateTime, Duration, Utc};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
 | 
			
		||||
/// This example demonstrates business models in action:
 | 
			
		||||
/// 1. Defining products (2 types of server nodes)
 | 
			
		||||
/// 2. Defining components (parts of the nodes)
 | 
			
		||||
/// 3. Setting up pricing
 | 
			
		||||
/// 4. Creating a function to check which products can be bought
 | 
			
		||||
/// 5. Simulating a user buying a product
 | 
			
		||||
/// 6. Generating an invoice
 | 
			
		||||
/// 7. Simulating payment
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    println!("Business Models Example");
 | 
			
		||||
    println!("=======================\n");
 | 
			
		||||
 | 
			
		||||
    // Create a customer
 | 
			
		||||
    let customer = create_customer();
 | 
			
		||||
    println!("Created customer: {}", customer.name);
 | 
			
		||||
 | 
			
		||||
    // Define products (server nodes)
 | 
			
		||||
    let (standard_node, premium_node) = create_server_products();
 | 
			
		||||
    println!("Created server products:");
 | 
			
		||||
    println!("  - Standard Node: ${} {}", standard_node.price.amount, standard_node.price.currency_code);
 | 
			
		||||
    println!("  - Premium Node: ${} {}", premium_node.price.amount, premium_node.price.currency_code);
 | 
			
		||||
 | 
			
		||||
    // Check which products can be purchased
 | 
			
		||||
    println!("\nChecking which products can be purchased:");
 | 
			
		||||
    let purchasable_products = get_purchasable_products(&[&standard_node, &premium_node]);
 | 
			
		||||
    for product in purchasable_products {
 | 
			
		||||
        println!("  - {} is available for purchase", product.name);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Simulate a user buying a product
 | 
			
		||||
    println!("\nSimulating purchase of a Premium Node:");
 | 
			
		||||
    let sale = create_sale(&customer, &premium_node);
 | 
			
		||||
    println!("  - Sale created with ID: {}", sale.id);
 | 
			
		||||
    println!("  - Total amount: ${} {}", sale.total_amount.amount, sale.total_amount.currency_code);
 | 
			
		||||
    
 | 
			
		||||
    // Generate an invoice
 | 
			
		||||
    println!("\nGenerating invoice:");
 | 
			
		||||
    let invoice = create_invoice(&customer, &sale);
 | 
			
		||||
    println!("  - Invoice created with ID: {}", invoice.id);
 | 
			
		||||
    println!("  - Total amount: ${} {}", invoice.total_amount.amount, invoice.total_amount.currency_code);
 | 
			
		||||
    println!("  - Due date: {}", invoice.due_date);
 | 
			
		||||
    println!("  - Status: {:?}", invoice.status);
 | 
			
		||||
    
 | 
			
		||||
    // Simulate payment
 | 
			
		||||
    println!("\nSimulating payment:");
 | 
			
		||||
    let paid_invoice = process_payment(invoice);
 | 
			
		||||
    println!("  - Payment processed");
 | 
			
		||||
    println!("  - New balance due: ${} {}", paid_invoice.balance_due.amount, paid_invoice.balance_due.currency_code);
 | 
			
		||||
    println!("  - Payment status: {:?}", paid_invoice.payment_status);
 | 
			
		||||
    println!("  - Invoice status: {:?}", paid_invoice.status);
 | 
			
		||||
    
 | 
			
		||||
    println!("\nBusiness transaction completed successfully!");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ===== Model Definitions =====
 | 
			
		||||
 | 
			
		||||
// Currency represents a monetary value with amount and currency code
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Currency {
 | 
			
		||||
    amount: f64,
 | 
			
		||||
    currency_code: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Customer represents a customer who can purchase products
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Customer {
 | 
			
		||||
    id: u32,
 | 
			
		||||
    name: String,
 | 
			
		||||
    description: String,
 | 
			
		||||
    pubkey: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProductType represents the type of a product
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
enum ProductType {
 | 
			
		||||
    Product,
 | 
			
		||||
    Service,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProductStatus represents the status of a product
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
enum ProductStatus {
 | 
			
		||||
    Available,
 | 
			
		||||
    Unavailable,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProductComponent represents a component of a product
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct ProductComponent {
 | 
			
		||||
    id: i64,
 | 
			
		||||
    name: String,
 | 
			
		||||
    description: String,
 | 
			
		||||
    quantity: i64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Product represents a product or service offered
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Product {
 | 
			
		||||
    id: i64,
 | 
			
		||||
    name: String,
 | 
			
		||||
    description: String,
 | 
			
		||||
    price: Currency,
 | 
			
		||||
    type_: ProductType,
 | 
			
		||||
    category: String,
 | 
			
		||||
    status: ProductStatus,
 | 
			
		||||
    max_amount: i64,
 | 
			
		||||
    purchase_till: DateTime<Utc>,
 | 
			
		||||
    active_till: DateTime<Utc>,
 | 
			
		||||
    components: Vec<ProductComponent>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaleStatus represents the status of a sale
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
enum SaleStatus {
 | 
			
		||||
    Pending,
 | 
			
		||||
    Completed,
 | 
			
		||||
    Cancelled,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SaleItem represents an item in a sale
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct SaleItem {
 | 
			
		||||
    id: u32,
 | 
			
		||||
    sale_id: u32,
 | 
			
		||||
    product_id: u32,
 | 
			
		||||
    name: String,
 | 
			
		||||
    description: String,
 | 
			
		||||
    comments: String,
 | 
			
		||||
    quantity: i32,
 | 
			
		||||
    unit_price: Currency,
 | 
			
		||||
    subtotal: Currency,
 | 
			
		||||
    tax_rate: f64,
 | 
			
		||||
    tax_amount: Currency,
 | 
			
		||||
    active_till: DateTime<Utc>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sale represents a sale of products or services
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Sale {
 | 
			
		||||
    id: u32,
 | 
			
		||||
    company_id: u32,
 | 
			
		||||
    customer_id: u32,
 | 
			
		||||
    buyer_name: String,
 | 
			
		||||
    buyer_email: String,
 | 
			
		||||
    subtotal_amount: Currency,
 | 
			
		||||
    tax_amount: Currency,
 | 
			
		||||
    total_amount: Currency,
 | 
			
		||||
    status: SaleStatus,
 | 
			
		||||
    service_id: Option<u32>,
 | 
			
		||||
    sale_date: DateTime<Utc>,
 | 
			
		||||
    items: Vec<SaleItem>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvoiceStatus represents the status of an invoice
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
enum InvoiceStatus {
 | 
			
		||||
    Draft,
 | 
			
		||||
    Sent,
 | 
			
		||||
    Paid,
 | 
			
		||||
    Overdue,
 | 
			
		||||
    Cancelled,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PaymentStatus represents the payment status of an invoice
 | 
			
		||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
 | 
			
		||||
enum PaymentStatus {
 | 
			
		||||
    Unpaid,
 | 
			
		||||
    PartiallyPaid,
 | 
			
		||||
    Paid,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Payment represents a payment made against an invoice
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Payment {
 | 
			
		||||
    amount: Currency,
 | 
			
		||||
    date: DateTime<Utc>,
 | 
			
		||||
    method: String,
 | 
			
		||||
    comment: String,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// InvoiceItem represents an item in an invoice
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct InvoiceItem {
 | 
			
		||||
    id: u32,
 | 
			
		||||
    invoice_id: u32,
 | 
			
		||||
    description: String,
 | 
			
		||||
    amount: Currency,
 | 
			
		||||
    sale_id: Option<u32>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invoice represents an invoice sent to a customer
 | 
			
		||||
#[derive(Debug, Clone, Serialize, Deserialize)]
 | 
			
		||||
struct Invoice {
 | 
			
		||||
    id: u32,
 | 
			
		||||
    customer_id: u32,
 | 
			
		||||
    total_amount: Currency,
 | 
			
		||||
    balance_due: Currency,
 | 
			
		||||
    status: InvoiceStatus,
 | 
			
		||||
    payment_status: PaymentStatus,
 | 
			
		||||
    issue_date: DateTime<Utc>,
 | 
			
		||||
    due_date: DateTime<Utc>,
 | 
			
		||||
    items: Vec<InvoiceItem>,
 | 
			
		||||
    payments: Vec<Payment>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ===== Implementation Functions =====
 | 
			
		||||
 | 
			
		||||
// Create a customer for our example
 | 
			
		||||
fn create_customer() -> Customer {
 | 
			
		||||
    Customer {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        name: "TechCorp Inc.".to_string(),
 | 
			
		||||
        description: "Enterprise technology company".to_string(),
 | 
			
		||||
        pubkey: "tech-corp-public-key-123".to_string(),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create two types of server node products with their components
 | 
			
		||||
fn create_server_products() -> (Product, Product) {
 | 
			
		||||
    let now = Utc::now();
 | 
			
		||||
    
 | 
			
		||||
    // Create currency for pricing
 | 
			
		||||
    let usd = |amount| {
 | 
			
		||||
        Currency {
 | 
			
		||||
            amount,
 | 
			
		||||
            currency_code: "USD".to_string(),
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Standard Node Components
 | 
			
		||||
    let cpu_standard = ProductComponent {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        name: "CPU".to_string(),
 | 
			
		||||
        description: "4-core CPU".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
        
 | 
			
		||||
    let ram_standard = ProductComponent {
 | 
			
		||||
        id: 2,
 | 
			
		||||
        name: "RAM".to_string(),
 | 
			
		||||
        description: "16GB RAM".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
        
 | 
			
		||||
    let storage_standard = ProductComponent {
 | 
			
		||||
        id: 3,
 | 
			
		||||
        name: "Storage".to_string(),
 | 
			
		||||
        description: "500GB SSD".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Premium Node Components
 | 
			
		||||
    let cpu_premium = ProductComponent {
 | 
			
		||||
        id: 4,
 | 
			
		||||
        name: "CPU".to_string(),
 | 
			
		||||
        description: "8-core CPU".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
        
 | 
			
		||||
    let ram_premium = ProductComponent {
 | 
			
		||||
        id: 5,
 | 
			
		||||
        name: "RAM".to_string(),
 | 
			
		||||
        description: "32GB RAM".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
        
 | 
			
		||||
    let storage_premium = ProductComponent {
 | 
			
		||||
        id: 6,
 | 
			
		||||
        name: "Storage".to_string(),
 | 
			
		||||
        description: "1TB SSD".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
        
 | 
			
		||||
    let gpu_premium = ProductComponent {
 | 
			
		||||
        id: 7,
 | 
			
		||||
        name: "GPU".to_string(),
 | 
			
		||||
        description: "Dedicated GPU".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Create Standard Node Product
 | 
			
		||||
    let standard_node = Product {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        name: "Standard Server Node".to_string(),
 | 
			
		||||
        description: "Basic server node for general workloads".to_string(),
 | 
			
		||||
        price: usd(99.99),
 | 
			
		||||
        type_: ProductType::Product,
 | 
			
		||||
        category: "Servers".to_string(),
 | 
			
		||||
        status: ProductStatus::Available,
 | 
			
		||||
        max_amount: 100,
 | 
			
		||||
        purchase_till: now + Duration::days(365),
 | 
			
		||||
        active_till: now + Duration::days(365),
 | 
			
		||||
        components: vec![cpu_standard, ram_standard, storage_standard],
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Create Premium Node Product
 | 
			
		||||
    let premium_node = Product {
 | 
			
		||||
        id: 2,
 | 
			
		||||
        name: "Premium Server Node".to_string(),
 | 
			
		||||
        description: "High-performance server node for demanding workloads".to_string(),
 | 
			
		||||
        price: usd(199.99),
 | 
			
		||||
        type_: ProductType::Product,
 | 
			
		||||
        category: "Servers".to_string(),
 | 
			
		||||
        status: ProductStatus::Available,
 | 
			
		||||
        max_amount: 50,
 | 
			
		||||
        purchase_till: now + Duration::days(365),
 | 
			
		||||
        active_till: now + Duration::days(365),
 | 
			
		||||
        components: vec![cpu_premium, ram_premium, storage_premium, gpu_premium],
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    (standard_node, premium_node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check which products can be purchased
 | 
			
		||||
fn get_purchasable_products<'a>(products: &[&'a Product]) -> Vec<&'a Product> {
 | 
			
		||||
    products.iter()
 | 
			
		||||
        .filter(|p| p.status == ProductStatus::Available && Utc::now() <= p.purchase_till)
 | 
			
		||||
        .copied()
 | 
			
		||||
        .collect()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create a sale for a customer buying a product
 | 
			
		||||
fn create_sale(customer: &Customer, product: &Product) -> Sale {
 | 
			
		||||
    let now = Utc::now();
 | 
			
		||||
    let active_till = now + Duration::days(365);
 | 
			
		||||
    
 | 
			
		||||
    // Create a sale item for the product
 | 
			
		||||
    let sale_item = SaleItem {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        sale_id: 1,
 | 
			
		||||
        product_id: product.id as u32,
 | 
			
		||||
        name: product.name.clone(),
 | 
			
		||||
        description: product.description.clone(),
 | 
			
		||||
        comments: "Customer requested expedited setup".to_string(),
 | 
			
		||||
        quantity: 1,
 | 
			
		||||
        unit_price: product.price.clone(),
 | 
			
		||||
        subtotal: Currency {
 | 
			
		||||
            amount: product.price.amount * 1.0,
 | 
			
		||||
            currency_code: product.price.currency_code.clone(),
 | 
			
		||||
        },
 | 
			
		||||
        tax_rate: 10.0, // 10% tax rate
 | 
			
		||||
        tax_amount: Currency {
 | 
			
		||||
            amount: product.price.amount * 0.1,
 | 
			
		||||
            currency_code: product.price.currency_code.clone(),
 | 
			
		||||
        },
 | 
			
		||||
        active_till,
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Calculate totals
 | 
			
		||||
    let subtotal = sale_item.subtotal.clone();
 | 
			
		||||
    let tax_amount = sale_item.tax_amount.clone();
 | 
			
		||||
    let total_amount = Currency {
 | 
			
		||||
        amount: subtotal.amount + tax_amount.amount,
 | 
			
		||||
        currency_code: subtotal.currency_code.clone(),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Create the sale
 | 
			
		||||
    Sale {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        company_id: 101, // Assuming company ID 101
 | 
			
		||||
        customer_id: customer.id,
 | 
			
		||||
        buyer_name: customer.name.clone(),
 | 
			
		||||
        buyer_email: "contact@techcorp.com".to_string(), // Example email
 | 
			
		||||
        subtotal_amount: subtotal,
 | 
			
		||||
        tax_amount,
 | 
			
		||||
        total_amount,
 | 
			
		||||
        status: SaleStatus::Completed,
 | 
			
		||||
        service_id: None,
 | 
			
		||||
        sale_date: now,
 | 
			
		||||
        items: vec![sale_item],
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Create an invoice for a sale
 | 
			
		||||
fn create_invoice(customer: &Customer, sale: &Sale) -> Invoice {
 | 
			
		||||
    let now = Utc::now();
 | 
			
		||||
    let due_date = now + Duration::days(30); // Due in 30 days
 | 
			
		||||
    
 | 
			
		||||
    // Create an invoice item for the sale
 | 
			
		||||
    let invoice_item = InvoiceItem {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        invoice_id: 1,
 | 
			
		||||
        description: format!("Purchase of {}", sale.items[0].name),
 | 
			
		||||
        amount: sale.total_amount.clone(),
 | 
			
		||||
        sale_id: Some(sale.id),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Create the invoice
 | 
			
		||||
    Invoice {
 | 
			
		||||
        id: 1,
 | 
			
		||||
        customer_id: customer.id,
 | 
			
		||||
        total_amount: sale.total_amount.clone(),
 | 
			
		||||
        balance_due: sale.total_amount.clone(),
 | 
			
		||||
        status: InvoiceStatus::Sent,
 | 
			
		||||
        payment_status: PaymentStatus::Unpaid,
 | 
			
		||||
        issue_date: now,
 | 
			
		||||
        due_date,
 | 
			
		||||
        items: vec![invoice_item],
 | 
			
		||||
        payments: Vec::new(),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Process a payment for an invoice
 | 
			
		||||
fn process_payment(mut invoice: Invoice) -> Invoice {
 | 
			
		||||
    // Create a payment for the full amount
 | 
			
		||||
    let payment = Payment {
 | 
			
		||||
        amount: invoice.total_amount.clone(),
 | 
			
		||||
        date: Utc::now(),
 | 
			
		||||
        method: "Credit Card".to_string(),
 | 
			
		||||
        comment: "Payment received via credit card ending in 1234".to_string(),
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Add the payment to the invoice
 | 
			
		||||
    invoice.payments.push(payment);
 | 
			
		||||
    
 | 
			
		||||
    // Update the balance due
 | 
			
		||||
    invoice.balance_due.amount = 0.0;
 | 
			
		||||
    
 | 
			
		||||
    // Update the payment status
 | 
			
		||||
    invoice.payment_status = PaymentStatus::Paid;
 | 
			
		||||
    invoice.status = InvoiceStatus::Paid;
 | 
			
		||||
    
 | 
			
		||||
    invoice
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user