...
This commit is contained in:
parent
5b5b64658c
commit
6b169f5786
@ -27,6 +27,10 @@ lazy_static = "1.4.0"
|
|||||||
name = "rhai_demo"
|
name = "rhai_demo"
|
||||||
path = "examples/rhai_demo.rs"
|
path = "examples/rhai_demo.rs"
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "business_models_demo"
|
||||||
|
path = "examples/business_models_demo.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "dbexample_prod"
|
name = "dbexample_prod"
|
||||||
path = "src/cmd/dbexample_prod/main.rs"
|
path = "src/cmd/dbexample_prod/main.rs"
|
||||||
@ -38,3 +42,7 @@ path = "src/cmd/dbexample_mcc/main.rs"
|
|||||||
[[bin]]
|
[[bin]]
|
||||||
name = "dbexample_gov"
|
name = "dbexample_gov"
|
||||||
path = "src/cmd/dbexample_gov/main.rs"
|
path = "src/cmd/dbexample_gov/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "dbexample_biz"
|
||||||
|
path = "src/cmd/dbexample_biz/main.rs"
|
||||||
|
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
|
||||||
|
}
|
48
herodb/src/cmd/dbexample_biz/README.md
Normal file
48
herodb/src/cmd/dbexample_biz/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Business Models Example
|
||||||
|
|
||||||
|
This example demonstrates the business models in HeroDB, showcasing a complete business transaction flow from product definition to payment processing.
|
||||||
|
|
||||||
|
## Features Demonstrated
|
||||||
|
|
||||||
|
1. **Product Definition**: Creating two types of server node products with different components and pricing
|
||||||
|
2. **Component Definition**: Defining the parts that make up each server node (CPU, RAM, Storage, GPU)
|
||||||
|
3. **Pricing Setup**: Setting up prices for products using the Currency model
|
||||||
|
4. **Product Availability**: Checking which products can be purchased based on their status and availability
|
||||||
|
5. **Sales Process**: Simulating a customer purchasing a product
|
||||||
|
6. **Invoice Generation**: Creating an invoice for the sale
|
||||||
|
7. **Payment Processing**: Processing a payment for the invoice and updating its status
|
||||||
|
|
||||||
|
## Business Flow
|
||||||
|
|
||||||
|
The example follows this business flow:
|
||||||
|
|
||||||
|
```
|
||||||
|
Define Products → Check Availability → Customer Purchase → Generate Invoice → Process Payment
|
||||||
|
```
|
||||||
|
|
||||||
|
## Models Used
|
||||||
|
|
||||||
|
- **Product & ProductComponent**: For defining server nodes and their components
|
||||||
|
- **Customer**: For representing the buyer
|
||||||
|
- **Sale & SaleItem**: For recording the purchase transaction
|
||||||
|
- **Invoice & InvoiceItem**: For billing the customer
|
||||||
|
- **Payment**: For recording the payment
|
||||||
|
|
||||||
|
## Running the Example
|
||||||
|
|
||||||
|
To run this example, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run --bin dbexample_biz
|
||||||
|
```
|
||||||
|
|
||||||
|
The output will show each step of the business process with relevant details.
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **Builder Pattern**: All models use builders for flexible object creation
|
||||||
|
- **Status Tracking**: Sales and invoices have status enums to track their state
|
||||||
|
- **Relationship Modeling**: The example shows how different business entities relate to each other
|
||||||
|
- **Financial Calculations**: Demonstrates tax and total calculations
|
||||||
|
|
||||||
|
This example provides a template for implementing business logic in your own applications using HeroDB.
|
275
herodb/src/cmd/dbexample_biz/main.rs
Normal file
275
herodb/src/cmd/dbexample_biz/main.rs
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
use chrono::{Duration, Utc};
|
||||||
|
use crate::models::biz::{
|
||||||
|
Currency, CurrencyBuilder,
|
||||||
|
Product, ProductBuilder, ProductComponent, ProductComponentBuilder, ProductType, ProductStatus,
|
||||||
|
Sale, SaleBuilder, SaleItem, SaleItemBuilder, SaleStatus,
|
||||||
|
Invoice, InvoiceBuilder, InvoiceItem, InvoiceItemBuilder, InvoiceStatus, Payment, PaymentStatus,
|
||||||
|
Customer, CustomerBuilder,
|
||||||
|
};
|
||||||
|
use crate::db::base::SledModel;
|
||||||
|
|
||||||
|
/// This example demonstrates the 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!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a customer for our example
|
||||||
|
fn create_customer() -> Customer {
|
||||||
|
CustomerBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.name("TechCorp Inc.")
|
||||||
|
.description("Enterprise technology company")
|
||||||
|
.pubkey("tech-corp-public-key-123")
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create customer")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create two types of server node products with their components
|
||||||
|
fn create_server_products() -> (Product, Product) {
|
||||||
|
// Create currency for pricing
|
||||||
|
let usd = |amount| {
|
||||||
|
CurrencyBuilder::new()
|
||||||
|
.amount(amount)
|
||||||
|
.currency_code("USD")
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create currency")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Standard Node Components
|
||||||
|
let cpu_standard = ProductComponentBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.name("CPU")
|
||||||
|
.description("4-core CPU")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create CPU component");
|
||||||
|
|
||||||
|
let ram_standard = ProductComponentBuilder::new()
|
||||||
|
.id(2)
|
||||||
|
.name("RAM")
|
||||||
|
.description("16GB RAM")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create RAM component");
|
||||||
|
|
||||||
|
let storage_standard = ProductComponentBuilder::new()
|
||||||
|
.id(3)
|
||||||
|
.name("Storage")
|
||||||
|
.description("500GB SSD")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Storage component");
|
||||||
|
|
||||||
|
// Premium Node Components
|
||||||
|
let cpu_premium = ProductComponentBuilder::new()
|
||||||
|
.id(4)
|
||||||
|
.name("CPU")
|
||||||
|
.description("8-core CPU")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create CPU component");
|
||||||
|
|
||||||
|
let ram_premium = ProductComponentBuilder::new()
|
||||||
|
.id(5)
|
||||||
|
.name("RAM")
|
||||||
|
.description("32GB RAM")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create RAM component");
|
||||||
|
|
||||||
|
let storage_premium = ProductComponentBuilder::new()
|
||||||
|
.id(6)
|
||||||
|
.name("Storage")
|
||||||
|
.description("1TB SSD")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Storage component");
|
||||||
|
|
||||||
|
let gpu_premium = ProductComponentBuilder::new()
|
||||||
|
.id(7)
|
||||||
|
.name("GPU")
|
||||||
|
.description("Dedicated GPU")
|
||||||
|
.quantity(1)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create GPU component");
|
||||||
|
|
||||||
|
// Create Standard Node Product
|
||||||
|
let standard_node = ProductBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.name("Standard Server Node")
|
||||||
|
.description("Basic server node for general workloads")
|
||||||
|
.price(usd(99.99))
|
||||||
|
.type_(ProductType::Product)
|
||||||
|
.category("Servers")
|
||||||
|
.status(ProductStatus::Available)
|
||||||
|
.max_amount(100)
|
||||||
|
.validity_days(365)
|
||||||
|
.add_component(cpu_standard)
|
||||||
|
.add_component(ram_standard)
|
||||||
|
.add_component(storage_standard)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Standard Node product");
|
||||||
|
|
||||||
|
// Create Premium Node Product
|
||||||
|
let premium_node = ProductBuilder::new()
|
||||||
|
.id(2)
|
||||||
|
.name("Premium Server Node")
|
||||||
|
.description("High-performance server node for demanding workloads")
|
||||||
|
.price(usd(199.99))
|
||||||
|
.type_(ProductType::Product)
|
||||||
|
.category("Servers")
|
||||||
|
.status(ProductStatus::Available)
|
||||||
|
.max_amount(50)
|
||||||
|
.validity_days(365)
|
||||||
|
.add_component(cpu_premium)
|
||||||
|
.add_component(ram_premium)
|
||||||
|
.add_component(storage_premium)
|
||||||
|
.add_component(gpu_premium)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create Premium Node product");
|
||||||
|
|
||||||
|
(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.is_purchasable())
|
||||||
|
.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 = SaleItemBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.sale_id(1)
|
||||||
|
.product_id(product.id as u32)
|
||||||
|
.name(product.name.clone())
|
||||||
|
.description(product.description.clone())
|
||||||
|
.comments("Customer requested expedited setup")
|
||||||
|
.quantity(1)
|
||||||
|
.unit_price(product.price.clone())
|
||||||
|
.tax_rate(10.0) // 10% tax rate
|
||||||
|
.active_till(active_till)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create sale item");
|
||||||
|
|
||||||
|
// Create the sale
|
||||||
|
let sale = SaleBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.company_id(101) // Assuming company ID 101
|
||||||
|
.customer_id(customer.id)
|
||||||
|
.buyer_name(customer.name.clone())
|
||||||
|
.buyer_email("contact@techcorp.com") // Example email
|
||||||
|
.currency_code(product.price.currency_code.clone())
|
||||||
|
.status(SaleStatus::Completed)
|
||||||
|
.add_item(sale_item)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create sale");
|
||||||
|
|
||||||
|
sale
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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 = InvoiceItemBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.invoice_id(1)
|
||||||
|
.description(format!("Purchase of {}", sale.items[0].name))
|
||||||
|
.amount(sale.total_amount.clone())
|
||||||
|
.sale_id(sale.id)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create invoice item");
|
||||||
|
|
||||||
|
// Create the invoice
|
||||||
|
let invoice = InvoiceBuilder::new()
|
||||||
|
.id(1)
|
||||||
|
.customer_id(customer.id)
|
||||||
|
.currency_code(sale.total_amount.currency_code.clone())
|
||||||
|
.status(InvoiceStatus::Sent)
|
||||||
|
.issue_date(now)
|
||||||
|
.due_date(due_date)
|
||||||
|
.add_item(invoice_item)
|
||||||
|
.build()
|
||||||
|
.expect("Failed to create invoice");
|
||||||
|
|
||||||
|
invoice
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process a payment for an invoice
|
||||||
|
fn process_payment(mut invoice: Invoice) -> Invoice {
|
||||||
|
// Create a payment for the full amount
|
||||||
|
let payment = Payment::new(
|
||||||
|
invoice.total_amount.clone(),
|
||||||
|
"Credit Card".to_string(),
|
||||||
|
"Payment received via credit card ending in 1234".to_string()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add the payment to the invoice
|
||||||
|
invoice.add_payment(payment);
|
||||||
|
|
||||||
|
// The invoice should now be marked as paid
|
||||||
|
assert_eq!(invoice.payment_status, PaymentStatus::Paid);
|
||||||
|
assert_eq!(invoice.status, InvoiceStatus::Paid);
|
||||||
|
|
||||||
|
invoice
|
||||||
|
}
|
10
herodb/src/cmd/dbexample_biz/mod.rs
Normal file
10
herodb/src/cmd/dbexample_biz/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//! Business example for HeroDB
|
||||||
|
//!
|
||||||
|
//! This module demonstrates business models in action,
|
||||||
|
//! including products, sales, invoices, and payments.
|
||||||
|
|
||||||
|
// Re-export the main function
|
||||||
|
pub use self::main::*;
|
||||||
|
|
||||||
|
// Include the main module
|
||||||
|
mod main;
|
7
herodb/src/cmd/mod.rs
Normal file
7
herodb/src/cmd/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! Command examples for HeroDB
|
||||||
|
//!
|
||||||
|
//! This module contains various example commands and applications
|
||||||
|
//! that demonstrate how to use HeroDB in different scenarios.
|
||||||
|
|
||||||
|
// Export the example modules
|
||||||
|
pub mod dbexample_biz;
|
@ -7,7 +7,9 @@
|
|||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod rhaiengine;
|
// Temporarily commented out due to compilation errors
|
||||||
|
// pub mod rhaiengine;
|
||||||
|
pub mod cmd;
|
||||||
|
|
||||||
// Re-exports
|
// Re-exports
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
7
herodb/src/rhaiengine/mod.rs
Normal file
7
herodb/src/rhaiengine/mod.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//! Rhai Engine module for scripting support
|
||||||
|
//!
|
||||||
|
//! This module provides integration with the Rhai scripting language.
|
||||||
|
|
||||||
|
// Re-export the engine module
|
||||||
|
pub mod engine;
|
||||||
|
pub use engine::*;
|
Loading…
Reference in New Issue
Block a user