biz rhai wrapper module wip
This commit is contained in:
parent
dc8c887026
commit
0ea836894b
2164
herodb/src/models/biz/rhai/Cargo.lock
generated
Normal file
2164
herodb/src/models/biz/rhai/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
herodb/src/models/biz/rhai/Cargo.toml
Normal file
19
herodb/src/models/biz/rhai/Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
||||
[package]
|
||||
name = "biz_rhai"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rhai = "1.21.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
chrono = "0.4"
|
||||
herodb = { path = "../../../.." }
|
||||
|
||||
[lib]
|
||||
name = "biz_rhai"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "example"
|
||||
path = "examples/example.rs"
|
168
herodb/src/models/biz/rhai/examples/example.rhai
Normal file
168
herodb/src/models/biz/rhai/examples/example.rhai
Normal file
@ -0,0 +1,168 @@
|
||||
// Example script demonstrating the use of Business module operations
|
||||
|
||||
// Custom repeat function since Rhai doesn't have a built-in repeat method
|
||||
fn repeat_str(str, count) {
|
||||
let result = "";
|
||||
for i in 0..count {
|
||||
result += str;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Print a section header
|
||||
fn print_section(title) {
|
||||
let line = repeat_str("=", 50);
|
||||
print(line);
|
||||
print(" " + title);
|
||||
print(line);
|
||||
}
|
||||
|
||||
print_section("BUSINESS MODULE OPERATIONS EXAMPLE");
|
||||
|
||||
// Currency Operations
|
||||
print_section("CURRENCY OPERATIONS");
|
||||
|
||||
// Create a currency
|
||||
print("\nCreating currencies...");
|
||||
let usd = create_currency(100.0, "USD");
|
||||
print("USD Currency created: " + usd.amount + " " + usd.currency_code);
|
||||
|
||||
// Convert currencies
|
||||
print("\nConverting currencies...");
|
||||
let eur = create_currency(150.0, "EUR");
|
||||
print("EUR Currency created: " + eur.amount + " " + eur.currency_code);
|
||||
|
||||
let eur_to_usd = convert_currency(eur, "USD");
|
||||
print("EUR to USD: " + eur.amount + " EUR = " + eur_to_usd.amount + " USD");
|
||||
|
||||
// Product Component Operations
|
||||
print_section("PRODUCT COMPONENT OPERATIONS");
|
||||
|
||||
// Create a product component
|
||||
print("\nCreating product components...");
|
||||
let component1 = create_product_component(1, "CPU", "Intel i7 Processor", 1);
|
||||
print("Component created: " + component1.name);
|
||||
print(" ID: " + component1.id);
|
||||
print(" Description: " + component1.description);
|
||||
print(" Quantity: " + component1.quantity);
|
||||
|
||||
// Create another component
|
||||
let component2 = create_product_component(2, "RAM", "32GB DDR4 Memory", 2);
|
||||
print("Component created: " + component2.name);
|
||||
print(" ID: " + component2.id);
|
||||
print(" Description: " + component2.description);
|
||||
print(" Quantity: " + component2.quantity);
|
||||
|
||||
// Product Operations
|
||||
print_section("PRODUCT OPERATIONS");
|
||||
|
||||
// Create a product using builder pattern
|
||||
print("\nCreating a product...");
|
||||
let product = create_product_builder()
|
||||
.product_name("High-End Gaming PC")
|
||||
.product_description("Ultimate gaming experience")
|
||||
.product_price(create_currency(1999.99, "USD"))
|
||||
.product_validity_days(365)
|
||||
.build();
|
||||
|
||||
print("Product created: " + product.name);
|
||||
print(" ID: " + product.id);
|
||||
print(" Description: " + product.description);
|
||||
print(" Price: " + product.price.amount + " " + product.price.currency_code);
|
||||
|
||||
// Add components to the product
|
||||
print("\nAdding components to product...");
|
||||
let product_with_components = product
|
||||
.add_component(component1)
|
||||
.add_component(component2);
|
||||
|
||||
print("Components added to product");
|
||||
|
||||
// Get components from the product
|
||||
let components = get_product_components(product_with_components);
|
||||
print("Number of components: " + components.len());
|
||||
|
||||
// Customer Operations
|
||||
print_section("CUSTOMER OPERATIONS");
|
||||
|
||||
// Create a customer
|
||||
print("\nCreating a customer...");
|
||||
let customer = create_customer("John Doe", "john@example.com", "+1234567890", "123 Main St");
|
||||
print("Customer created: " + customer.name);
|
||||
print(" Email: " + customer.email);
|
||||
print(" Phone: " + customer.phone);
|
||||
print(" Address: " + customer.address);
|
||||
|
||||
// Sale Operations
|
||||
print_section("SALE OPERATIONS");
|
||||
|
||||
// Create a sale
|
||||
print("\nCreating a sale...");
|
||||
let sale = create_sale(customer, "2025-04-19");
|
||||
print("Sale created for customer: " + sale.customer.name);
|
||||
print(" Date: " + sale.date);
|
||||
|
||||
// Add product to sale
|
||||
let sale_with_item = add_sale_item(sale, product_with_components, 1);
|
||||
print("Added product to sale: " + product_with_components.name);
|
||||
|
||||
// Service Operations
|
||||
print_section("SERVICE OPERATIONS");
|
||||
|
||||
// Create a service
|
||||
print("\nCreating a service...");
|
||||
let service = create_service(
|
||||
"Premium Support",
|
||||
"24/7 Technical Support",
|
||||
create_currency(49.99, "USD"),
|
||||
30
|
||||
);
|
||||
print("Service created: " + service.name);
|
||||
print(" Description: " + service.description);
|
||||
print(" Price: " + service.price.amount + " " + service.price.currency_code);
|
||||
print(" Duration: " + service.duration + " days");
|
||||
|
||||
// Contract Operations
|
||||
print_section("CONTRACT OPERATIONS");
|
||||
|
||||
// Create a contract
|
||||
print("\nCreating a contract...");
|
||||
let contract = create_contract(
|
||||
"Support Agreement",
|
||||
"Annual support contract",
|
||||
"2025-04-19",
|
||||
"2026-04-19",
|
||||
create_currency(599.99, "USD"),
|
||||
"Active"
|
||||
);
|
||||
print("Contract created: " + contract.title);
|
||||
print(" Description: " + contract.description);
|
||||
print(" Start Date: " + contract.start_date);
|
||||
print(" End Date: " + contract.end_date);
|
||||
print(" Value: " + contract.value.amount + " " + contract.value.currency_code);
|
||||
print(" Status: " + contract.status);
|
||||
|
||||
// Invoice Operations
|
||||
print_section("INVOICE OPERATIONS");
|
||||
|
||||
// Create an invoice
|
||||
print("\nCreating an invoice...");
|
||||
let invoice = create_invoice(
|
||||
"INV-2025-001",
|
||||
"2025-04-19",
|
||||
"2025-05-19",
|
||||
customer,
|
||||
create_currency(2499.99, "USD"),
|
||||
"Issued",
|
||||
"Pending"
|
||||
);
|
||||
print("Invoice created: " + invoice.number);
|
||||
print(" Date: " + invoice.date);
|
||||
print(" Due Date: " + invoice.due_date);
|
||||
print(" Customer: " + invoice.customer.name);
|
||||
print(" Amount: " + invoice.amount.amount + " " + invoice.amount.currency_code);
|
||||
print(" Status: " + invoice.status);
|
||||
print(" Payment Status: " + invoice.payment_status);
|
||||
|
||||
print_section("EXAMPLE COMPLETED");
|
||||
print("All business module operations completed successfully!");
|
41
herodb/src/models/biz/rhai/examples/example.rs
Normal file
41
herodb/src/models/biz/rhai/examples/example.rs
Normal file
@ -0,0 +1,41 @@
|
||||
use std::{fs, path::Path};
|
||||
use biz_rhai::create_rhai_engine;
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("=== Business Module Rhai Wrapper Example ===");
|
||||
|
||||
// Create a Rhai engine with business module functionality
|
||||
let mut engine = create_rhai_engine();
|
||||
println!("Successfully created Rhai engine");
|
||||
|
||||
// Get the path to the example.rhai script
|
||||
let script_path = get_script_path()?;
|
||||
println!("Loading script from: {}", script_path.display());
|
||||
|
||||
// Load the script content
|
||||
let script = fs::read_to_string(&script_path)
|
||||
.map_err(|e| format!("Failed to read script file: {}", e))?;
|
||||
|
||||
// Run the script
|
||||
println!("\n=== Running Rhai script ===");
|
||||
match engine.eval::<()>(&script) {
|
||||
Ok(_) => println!("\nScript executed successfully!"),
|
||||
Err(e) => println!("\nScript execution error: {}", e),
|
||||
}
|
||||
|
||||
println!("\nExample completed!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_script_path() -> Result<std::path::PathBuf, String> {
|
||||
// When running with cargo run --example, the script will be in the examples directory
|
||||
let script_path = Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("examples")
|
||||
.join("example.rhai");
|
||||
|
||||
if script_path.exists() {
|
||||
Ok(script_path)
|
||||
} else {
|
||||
Err(format!("Could not find example.rhai script at {}", script_path.display()))
|
||||
}
|
||||
}
|
88
herodb/src/models/biz/rhai/src/engine.rs
Normal file
88
herodb/src/models/biz/rhai/src/engine.rs
Normal file
@ -0,0 +1,88 @@
|
||||
use rhai::{Engine, EvalAltResult, Map, Dynamic, Array};
|
||||
use crate::wrapper::*;
|
||||
use crate::generic_wrapper::ToRhai;
|
||||
|
||||
/// Create a new Rhai engine with business module functionality
|
||||
pub fn create_rhai_engine() -> Engine {
|
||||
let mut engine = Engine::new();
|
||||
|
||||
// Register business module types and functions
|
||||
register_business_types(&mut engine);
|
||||
|
||||
engine
|
||||
}
|
||||
|
||||
/// Register business module types and functions
|
||||
fn register_business_types(engine: &mut Engine) {
|
||||
// Currency functions
|
||||
engine.register_fn("create_currency", create_currency);
|
||||
engine.register_fn("convert_currency", convert_currency);
|
||||
|
||||
// Product functions
|
||||
engine.register_fn("create_product_builder", create_product_builder);
|
||||
engine.register_fn("product_name", product_builder_name);
|
||||
engine.register_fn("product_description", product_builder_description);
|
||||
engine.register_fn("product_price", product_builder_price);
|
||||
engine.register_fn("product_validity_days", product_builder_validity_days);
|
||||
engine.register_fn("add_component", product_builder_add_component);
|
||||
engine.register_fn("build", product_builder_build);
|
||||
|
||||
// Product component functions
|
||||
engine.register_fn("create_product_component", create_product_component);
|
||||
engine.register_fn("component_name", product_component_name);
|
||||
engine.register_fn("component_description", product_component_description);
|
||||
engine.register_fn("component_quantity", product_component_quantity);
|
||||
|
||||
// Sale functions
|
||||
engine.register_fn("create_sale", create_sale);
|
||||
engine.register_fn("add_sale_item", add_sale_item);
|
||||
engine.register_fn("sale_customer", sale_customer);
|
||||
engine.register_fn("sale_date", sale_date);
|
||||
engine.register_fn("sale_status", sale_status);
|
||||
|
||||
// Customer functions
|
||||
engine.register_fn("create_customer", create_customer);
|
||||
engine.register_fn("customer_name", customer_name);
|
||||
engine.register_fn("customer_email", customer_email);
|
||||
engine.register_fn("customer_phone", customer_phone);
|
||||
engine.register_fn("customer_address", customer_address);
|
||||
|
||||
// Service functions
|
||||
engine.register_fn("create_service", create_service);
|
||||
engine.register_fn("service_name", service_name);
|
||||
engine.register_fn("service_description", service_description);
|
||||
engine.register_fn("service_price", service_price);
|
||||
engine.register_fn("service_duration", service_duration);
|
||||
|
||||
// Contract functions
|
||||
engine.register_fn("create_contract", create_contract);
|
||||
engine.register_fn("contract_title", contract_title);
|
||||
engine.register_fn("contract_description", contract_description);
|
||||
engine.register_fn("contract_start_date", contract_start_date);
|
||||
engine.register_fn("contract_end_date", contract_end_date);
|
||||
engine.register_fn("contract_value", contract_value);
|
||||
engine.register_fn("contract_status", contract_status);
|
||||
|
||||
// Invoice functions
|
||||
engine.register_fn("create_invoice", create_invoice);
|
||||
engine.register_fn("invoice_number", invoice_number);
|
||||
engine.register_fn("invoice_date", invoice_date);
|
||||
engine.register_fn("invoice_due_date", invoice_due_date);
|
||||
engine.register_fn("invoice_customer", invoice_customer);
|
||||
engine.register_fn("invoice_amount", invoice_amount);
|
||||
engine.register_fn("invoice_status", invoice_status);
|
||||
engine.register_fn("invoice_payment_status", invoice_payment_status);
|
||||
|
||||
// Helper function to get components from a product
|
||||
engine.register_fn("get_product_components", |product_map: Map| -> Array {
|
||||
let mut array = Array::new();
|
||||
|
||||
if let Some(components) = product_map.get("components") {
|
||||
if let Some(components_array) = components.clone().try_cast::<Array>() {
|
||||
return components_array;
|
||||
}
|
||||
}
|
||||
|
||||
array
|
||||
});
|
||||
}
|
132
herodb/src/models/biz/rhai/src/generic_wrapper.rs
Normal file
132
herodb/src/models/biz/rhai/src/generic_wrapper.rs
Normal file
@ -0,0 +1,132 @@
|
||||
use std::collections::HashMap;
|
||||
use rhai::{Dynamic, Map, Array};
|
||||
|
||||
/// Local wrapper trait for sal::rhai::ToRhai to avoid orphan rule violations
|
||||
pub trait ToRhai {
|
||||
/// Convert to a Rhai Dynamic value
|
||||
fn to_rhai(&self) -> Dynamic;
|
||||
}
|
||||
|
||||
// Implementation of ToRhai for Dynamic
|
||||
impl ToRhai for Dynamic {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic trait for wrapping Rust functions to be used with Rhai
|
||||
pub trait RhaiWrapper {
|
||||
/// Wrap a function that takes ownership of self
|
||||
fn wrap_consuming<F, R>(self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(Self) -> R,
|
||||
R: ToRhai;
|
||||
|
||||
/// Wrap a function that takes a mutable reference to self
|
||||
fn wrap_mut<F, R>(&mut self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
R: ToRhai;
|
||||
|
||||
/// Wrap a function that takes an immutable reference to self
|
||||
fn wrap<F, R>(&self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(&Self) -> R,
|
||||
R: ToRhai;
|
||||
}
|
||||
|
||||
/// Implementation of RhaiWrapper for any type
|
||||
impl<T> RhaiWrapper for T {
|
||||
fn wrap_consuming<F, R>(self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(Self) -> R,
|
||||
R: ToRhai,
|
||||
{
|
||||
let result = f(self);
|
||||
result.to_rhai()
|
||||
}
|
||||
|
||||
fn wrap_mut<F, R>(&mut self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
R: ToRhai,
|
||||
{
|
||||
let result = f(self);
|
||||
result.to_rhai()
|
||||
}
|
||||
|
||||
fn wrap<F, R>(&self, f: F) -> Dynamic
|
||||
where
|
||||
Self: Sized + Clone,
|
||||
F: FnOnce(&Self) -> R,
|
||||
R: ToRhai,
|
||||
{
|
||||
let result = f(self);
|
||||
result.to_rhai()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a Rhai Map to a Rust HashMap
|
||||
pub fn map_to_hashmap(map: &Map) -> HashMap<String, String> {
|
||||
let mut result = HashMap::new();
|
||||
for (key, value) in map.iter() {
|
||||
let k = key.clone().to_string();
|
||||
let v = value.clone().to_string();
|
||||
if !k.is_empty() && !v.is_empty() {
|
||||
result.insert(k, v);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Convert a HashMap<String, String> to a Rhai Map
|
||||
pub fn hashmap_to_map(map: &HashMap<String, String>) -> Map {
|
||||
let mut result = Map::new();
|
||||
for (key, value) in map.iter() {
|
||||
result.insert(key.clone().into(), Dynamic::from(value.clone()));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Convert a Rhai Array to a Vec of strings
|
||||
pub fn array_to_vec_string(array: &Array) -> Vec<String> {
|
||||
array.iter()
|
||||
.filter_map(|item| {
|
||||
let s = item.clone().to_string();
|
||||
if !s.is_empty() { Some(s) } else { None }
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Helper function to convert Dynamic to Option<String>
|
||||
pub fn dynamic_to_string_option(value: &Dynamic) -> Option<String> {
|
||||
if value.is_string() {
|
||||
Some(value.clone().to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to convert Dynamic to Option<u32>
|
||||
pub fn dynamic_to_u32_option(value: &Dynamic) -> Option<u32> {
|
||||
if value.is_int() {
|
||||
Some(value.as_int().unwrap() as u32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to convert Dynamic to Option<&str> with lifetime management
|
||||
pub fn dynamic_to_str_option<'a>(value: &Dynamic, storage: &'a mut String) -> Option<&'a str> {
|
||||
if value.is_string() {
|
||||
*storage = value.clone().to_string();
|
||||
Some(storage.as_str())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
11
herodb/src/models/biz/rhai/src/lib.rs
Normal file
11
herodb/src/models/biz/rhai/src/lib.rs
Normal file
@ -0,0 +1,11 @@
|
||||
// Re-export the utility modules
|
||||
pub mod generic_wrapper;
|
||||
pub mod wrapper;
|
||||
pub mod engine;
|
||||
|
||||
// Re-export the utility traits and functions
|
||||
pub use generic_wrapper::{RhaiWrapper, map_to_hashmap, array_to_vec_string,
|
||||
dynamic_to_string_option, hashmap_to_map};
|
||||
pub use engine::create_rhai_engine;
|
||||
|
||||
// The create_rhai_engine function is now in the engine module
|
640
herodb/src/models/biz/rhai/src/wrapper.rs
Normal file
640
herodb/src/models/biz/rhai/src/wrapper.rs
Normal file
@ -0,0 +1,640 @@
|
||||
//! Rhai wrappers for Business module functions
|
||||
//!
|
||||
//! This module provides Rhai wrappers for the functions in the Business module.
|
||||
|
||||
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map, Position};
|
||||
use std::collections::HashMap;
|
||||
use crate::generic_wrapper::{ToRhai, RhaiWrapper, map_to_hashmap, dynamic_to_string_option, dynamic_to_u32_option};
|
||||
|
||||
// Import business module types
|
||||
use chrono::{DateTime, Utc, Duration};
|
||||
use herodb::models::biz::{
|
||||
Currency, CurrencyBuilder,
|
||||
Product, ProductBuilder, ProductComponent, ProductComponentBuilder, ProductType, ProductStatus,
|
||||
Customer, CustomerBuilder,
|
||||
Sale, SaleBuilder, SaleItem, SaleItemBuilder, SaleStatus,
|
||||
Service, ServiceBuilder, ServiceItem, ServiceItemBuilder, ServiceStatus, BillingFrequency,
|
||||
ExchangeRate, ExchangeRateBuilder, ExchangeRateService, EXCHANGE_RATE_SERVICE,
|
||||
Contract, ContractBuilder, ContractStatus,
|
||||
Invoice, InvoiceBuilder, InvoiceItem, InvoiceItemBuilder, InvoiceStatus, PaymentStatus, Payment
|
||||
};
|
||||
|
||||
// Business module ToRhai implementations
|
||||
|
||||
// Currency ToRhai implementation
|
||||
impl ToRhai for Currency {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("amount".into(), Dynamic::from(self.amount));
|
||||
map.insert("currency_code".into(), Dynamic::from(self.currency_code.clone()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// ProductType ToRhai implementation
|
||||
impl ToRhai for ProductType {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
ProductType::Product => "Product",
|
||||
ProductType::Service => "Service",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// ProductStatus ToRhai implementation
|
||||
impl ToRhai for ProductStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
ProductStatus::Active => "Active",
|
||||
ProductStatus::Error => "Error",
|
||||
ProductStatus::EndOfLife => "EndOfLife",
|
||||
ProductStatus::Paused => "Paused",
|
||||
ProductStatus::Available => "Available",
|
||||
ProductStatus::Unavailable => "Unavailable",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// ProductComponent ToRhai implementation
|
||||
impl ToRhai for ProductComponent {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("name".into(), Dynamic::from(self.name.clone()));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("quantity".into(), Dynamic::from(self.quantity));
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
map.insert("energy_usage".into(), Dynamic::from(self.energy_usage));
|
||||
map.insert("cost".into(), self.cost.to_rhai());
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Product ToRhai implementation
|
||||
impl ToRhai for Product {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("name".into(), Dynamic::from(self.name.clone()));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("price".into(), self.price.to_rhai());
|
||||
map.insert("type".into(), self.type_.to_rhai());
|
||||
map.insert("category".into(), Dynamic::from(self.category.clone()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
map.insert("max_amount".into(), Dynamic::from(self.max_amount));
|
||||
map.insert("purchase_till".into(), Dynamic::from(self.purchase_till.to_string()));
|
||||
map.insert("active_till".into(), Dynamic::from(self.active_till.to_string()));
|
||||
|
||||
// Convert components to an array
|
||||
let components_array: Array = self.components.iter()
|
||||
.map(|component| component.to_rhai())
|
||||
.collect();
|
||||
map.insert("components".into(), Dynamic::from(components_array));
|
||||
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// SaleStatus ToRhai implementation
|
||||
impl ToRhai for SaleStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
SaleStatus::Pending => "Pending",
|
||||
SaleStatus::Completed => "Completed",
|
||||
SaleStatus::Cancelled => "Cancelled",
|
||||
SaleStatus::Refunded => "Refunded",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// SaleItem ToRhai implementation
|
||||
impl ToRhai for SaleItem {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("product_id".into(), Dynamic::from(self.product_id));
|
||||
map.insert("quantity".into(), Dynamic::from(self.quantity));
|
||||
map.insert("price".into(), self.price.to_rhai());
|
||||
map.insert("discount".into(), Dynamic::from(self.discount));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Sale ToRhai implementation
|
||||
impl ToRhai for Sale {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("customer_id".into(), Dynamic::from(self.customer_id));
|
||||
map.insert("date".into(), Dynamic::from(self.date.to_string()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
|
||||
// Convert items to an array
|
||||
let items_array: Array = self.items.iter()
|
||||
.map(|item| item.to_rhai())
|
||||
.collect();
|
||||
map.insert("items".into(), Dynamic::from(items_array));
|
||||
|
||||
map.insert("total".into(), self.total.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Customer ToRhai implementation
|
||||
impl ToRhai for Customer {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("name".into(), Dynamic::from(self.name.clone()));
|
||||
map.insert("email".into(), Dynamic::from(self.email.clone()));
|
||||
map.insert("phone".into(), Dynamic::from(self.phone.clone()));
|
||||
map.insert("address".into(), Dynamic::from(self.address.clone()));
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceStatus ToRhai implementation
|
||||
impl ToRhai for ServiceStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
ServiceStatus::Active => "Active",
|
||||
ServiceStatus::Inactive => "Inactive",
|
||||
ServiceStatus::Pending => "Pending",
|
||||
ServiceStatus::Cancelled => "Cancelled",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// BillingFrequency ToRhai implementation
|
||||
impl ToRhai for BillingFrequency {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
BillingFrequency::OneTime => "OneTime",
|
||||
BillingFrequency::Daily => "Daily",
|
||||
BillingFrequency::Weekly => "Weekly",
|
||||
BillingFrequency::Monthly => "Monthly",
|
||||
BillingFrequency::Quarterly => "Quarterly",
|
||||
BillingFrequency::Yearly => "Yearly",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// ServiceItem ToRhai implementation
|
||||
impl ToRhai for ServiceItem {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("name".into(), Dynamic::from(self.name.clone()));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("price".into(), self.price.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Service ToRhai implementation
|
||||
impl ToRhai for Service {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("customer_id".into(), Dynamic::from(self.customer_id));
|
||||
map.insert("name".into(), Dynamic::from(self.name.clone()));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
map.insert("start_date".into(), Dynamic::from(self.start_date.to_string()));
|
||||
map.insert("end_date".into(), Dynamic::from(self.end_date.to_string()));
|
||||
map.insert("billing_frequency".into(), self.billing_frequency.to_rhai());
|
||||
|
||||
// Convert items to an array
|
||||
let items_array: Array = self.items.iter()
|
||||
.map(|item| item.to_rhai())
|
||||
.collect();
|
||||
map.insert("items".into(), Dynamic::from(items_array));
|
||||
|
||||
map.insert("total".into(), self.total.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// ContractStatus ToRhai implementation
|
||||
impl ToRhai for ContractStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
ContractStatus::Draft => "Draft",
|
||||
ContractStatus::Pending => "Pending",
|
||||
ContractStatus::Active => "Active",
|
||||
ContractStatus::Completed => "Completed",
|
||||
ContractStatus::Cancelled => "Cancelled",
|
||||
ContractStatus::Expired => "Expired",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Contract ToRhai implementation
|
||||
impl ToRhai for Contract {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("customer_id".into(), Dynamic::from(self.customer_id));
|
||||
map.insert("title".into(), Dynamic::from(self.title.clone()));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
map.insert("start_date".into(), Dynamic::from(self.start_date.to_string()));
|
||||
map.insert("end_date".into(), Dynamic::from(self.end_date.to_string()));
|
||||
map.insert("value".into(), self.value.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// InvoiceStatus ToRhai implementation
|
||||
impl ToRhai for InvoiceStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
InvoiceStatus::Draft => "Draft",
|
||||
InvoiceStatus::Sent => "Sent",
|
||||
InvoiceStatus::Paid => "Paid",
|
||||
InvoiceStatus::Overdue => "Overdue",
|
||||
InvoiceStatus::Cancelled => "Cancelled",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// PaymentStatus ToRhai implementation
|
||||
impl ToRhai for PaymentStatus {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let value = match self {
|
||||
PaymentStatus::Pending => "Pending",
|
||||
PaymentStatus::Completed => "Completed",
|
||||
PaymentStatus::Failed => "Failed",
|
||||
PaymentStatus::Refunded => "Refunded",
|
||||
};
|
||||
Dynamic::from(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Payment ToRhai implementation
|
||||
impl ToRhai for Payment {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("amount".into(), self.amount.to_rhai());
|
||||
map.insert("date".into(), Dynamic::from(self.date.to_string()));
|
||||
map.insert("method".into(), Dynamic::from(self.method.clone()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
map.insert("reference".into(), Dynamic::from(self.reference.clone()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// InvoiceItem ToRhai implementation
|
||||
impl ToRhai for InvoiceItem {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("description".into(), Dynamic::from(self.description.clone()));
|
||||
map.insert("quantity".into(), Dynamic::from(self.quantity));
|
||||
map.insert("unit_price".into(), self.unit_price.to_rhai());
|
||||
map.insert("total".into(), self.total.to_rhai());
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// Invoice ToRhai implementation
|
||||
impl ToRhai for Invoice {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("id".into(), Dynamic::from(self.id));
|
||||
map.insert("customer_id".into(), Dynamic::from(self.customer_id));
|
||||
map.insert("date".into(), Dynamic::from(self.date.to_string()));
|
||||
map.insert("due_date".into(), Dynamic::from(self.due_date.to_string()));
|
||||
map.insert("status".into(), self.status.to_rhai());
|
||||
|
||||
// Convert items to an array
|
||||
let items_array: Array = self.items.iter()
|
||||
.map(|item| item.to_rhai())
|
||||
.collect();
|
||||
map.insert("items".into(), Dynamic::from(items_array));
|
||||
|
||||
// Convert payments to an array
|
||||
let payments_array: Array = self.payments.iter()
|
||||
.map(|payment| payment.to_rhai())
|
||||
.collect();
|
||||
map.insert("payments".into(), Dynamic::from(payments_array));
|
||||
|
||||
map.insert("subtotal".into(), self.subtotal.to_rhai());
|
||||
map.insert("tax".into(), self.tax.to_rhai());
|
||||
map.insert("total".into(), self.total.to_rhai());
|
||||
map.insert("created_at".into(), Dynamic::from(self.created_at.to_string()));
|
||||
map.insert("updated_at".into(), Dynamic::from(self.updated_at.to_string()));
|
||||
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
// ExchangeRate ToRhai implementation
|
||||
impl ToRhai for ExchangeRate {
|
||||
fn to_rhai(&self) -> Dynamic {
|
||||
let mut map = Map::new();
|
||||
map.insert("from_currency".into(), Dynamic::from(self.from_currency.clone()));
|
||||
map.insert("to_currency".into(), Dynamic::from(self.to_currency.clone()));
|
||||
map.insert("rate".into(), Dynamic::from(self.rate));
|
||||
map.insert("date".into(), Dynamic::from(self.date.to_string()));
|
||||
Dynamic::from_map(map)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Business Module Function Wrappers
|
||||
//
|
||||
|
||||
// Currency Functions
|
||||
pub fn currency_new(amount: f64, currency_code: &str) -> Currency {
|
||||
Currency::new(amount, currency_code.to_string())
|
||||
}
|
||||
|
||||
pub fn currency_to_usd(currency: &Currency) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match currency.to_usd() {
|
||||
Some(usd) => Ok(usd.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
"Failed to convert currency to USD".into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn currency_to_currency(currency: &Currency, target_currency: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match currency.to_currency(target_currency) {
|
||||
Some(converted) => Ok(converted.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to convert currency to {}", target_currency).into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// CurrencyBuilder Functions
|
||||
pub fn currency_builder_new() -> CurrencyBuilder {
|
||||
CurrencyBuilder::new()
|
||||
}
|
||||
|
||||
pub fn currency_builder_amount(builder: CurrencyBuilder, amount: f64) -> CurrencyBuilder {
|
||||
builder.amount(amount)
|
||||
}
|
||||
|
||||
pub fn currency_builder_currency_code(builder: CurrencyBuilder, currency_code: &str) -> CurrencyBuilder {
|
||||
builder.currency_code(currency_code)
|
||||
}
|
||||
|
||||
pub fn currency_builder_build(builder: CurrencyBuilder) -> Result<Currency, Box<EvalAltResult>> {
|
||||
builder.build().map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
e.into(),
|
||||
Position::NONE
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// ProductComponent Functions
|
||||
pub fn product_component_new(id: i64, name: &str, description: &str, quantity: i64) -> ProductComponent {
|
||||
ProductComponent::new(id as u32, name.to_string(), description.to_string(), quantity as i32)
|
||||
}
|
||||
|
||||
pub fn product_component_total_energy_usage(component: &ProductComponent) -> f64 {
|
||||
component.total_energy_usage()
|
||||
}
|
||||
|
||||
pub fn product_component_total_cost(component: &ProductComponent) -> Currency {
|
||||
component.total_cost()
|
||||
}
|
||||
|
||||
// ProductComponentBuilder Functions
|
||||
pub fn product_component_builder_new() -> ProductComponentBuilder {
|
||||
ProductComponentBuilder::new()
|
||||
}
|
||||
|
||||
pub fn product_component_builder_id(builder: ProductComponentBuilder, id: i64) -> ProductComponentBuilder {
|
||||
builder.id(id as u32)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_name(builder: ProductComponentBuilder, name: &str) -> ProductComponentBuilder {
|
||||
builder.name(name)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_description(builder: ProductComponentBuilder, description: &str) -> ProductComponentBuilder {
|
||||
builder.description(description)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_quantity(builder: ProductComponentBuilder, quantity: i64) -> ProductComponentBuilder {
|
||||
builder.quantity(quantity as i32)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_energy_usage(builder: ProductComponentBuilder, energy_usage: f64) -> ProductComponentBuilder {
|
||||
builder.energy_usage(energy_usage)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_cost(builder: ProductComponentBuilder, cost: Currency) -> ProductComponentBuilder {
|
||||
builder.cost(cost)
|
||||
}
|
||||
|
||||
pub fn product_component_builder_build(builder: ProductComponentBuilder) -> Result<ProductComponent, Box<EvalAltResult>> {
|
||||
builder.build().map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
e.into(),
|
||||
Position::NONE
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// Product Functions
|
||||
pub fn product_type_product() -> ProductType {
|
||||
ProductType::Product
|
||||
}
|
||||
|
||||
pub fn product_type_service() -> ProductType {
|
||||
ProductType::Service
|
||||
}
|
||||
|
||||
pub fn product_status_active() -> ProductStatus {
|
||||
ProductStatus::Active
|
||||
}
|
||||
|
||||
pub fn product_status_error() -> ProductStatus {
|
||||
ProductStatus::Error
|
||||
}
|
||||
|
||||
pub fn product_status_end_of_life() -> ProductStatus {
|
||||
ProductStatus::EndOfLife
|
||||
}
|
||||
|
||||
pub fn product_status_paused() -> ProductStatus {
|
||||
ProductStatus::Paused
|
||||
}
|
||||
|
||||
pub fn product_status_available() -> ProductStatus {
|
||||
ProductStatus::Available
|
||||
}
|
||||
|
||||
pub fn product_status_unavailable() -> ProductStatus {
|
||||
ProductStatus::Unavailable
|
||||
}
|
||||
|
||||
pub fn product_add_component(product: &mut Product, component: ProductComponent) {
|
||||
product.add_component(component);
|
||||
}
|
||||
|
||||
pub fn product_set_purchase_period(product: &mut Product, purchase_till_days: i64) {
|
||||
let purchase_till = Utc::now() + Duration::days(purchase_till_days);
|
||||
product.set_purchase_period(purchase_till);
|
||||
}
|
||||
|
||||
pub fn product_set_active_period(product: &mut Product, active_till_days: i64) {
|
||||
let active_till = Utc::now() + Duration::days(active_till_days);
|
||||
product.set_active_period(active_till);
|
||||
}
|
||||
|
||||
pub fn product_is_purchasable(product: &Product) -> bool {
|
||||
product.is_purchasable()
|
||||
}
|
||||
|
||||
pub fn product_is_active(product: &Product) -> bool {
|
||||
product.is_active()
|
||||
}
|
||||
|
||||
pub fn product_cost_in_currency(product: &Product, currency_code: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match product.cost_in_currency(currency_code) {
|
||||
Some(cost) => Ok(cost.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to calculate cost in {}", currency_code).into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn product_cost_in_usd(product: &Product) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match product.cost_in_usd() {
|
||||
Some(cost) => Ok(cost.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
"Failed to calculate cost in USD".into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn product_total_energy_usage(product: &Product) -> f64 {
|
||||
product.total_energy_usage()
|
||||
}
|
||||
|
||||
pub fn product_components_cost(product: &Product, currency_code: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match product.components_cost(currency_code) {
|
||||
Some(cost) => Ok(cost.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to calculate components cost in {}", currency_code).into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn product_components_cost_in_usd(product: &Product) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||
match product.components_cost_in_usd() {
|
||||
Some(cost) => Ok(cost.to_rhai()),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
"Failed to calculate components cost in USD".into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
// ProductBuilder Functions
|
||||
pub fn product_builder_new() -> ProductBuilder {
|
||||
ProductBuilder::new()
|
||||
}
|
||||
|
||||
pub fn product_builder_id(builder: ProductBuilder, id: i64) -> ProductBuilder {
|
||||
builder.id(id as u32)
|
||||
}
|
||||
|
||||
pub fn product_builder_name(builder: ProductBuilder, name: &str) -> ProductBuilder {
|
||||
builder.name(name)
|
||||
}
|
||||
|
||||
pub fn product_builder_description(builder: ProductBuilder, description: &str) -> ProductBuilder {
|
||||
builder.description(description)
|
||||
}
|
||||
|
||||
pub fn product_builder_price(builder: ProductBuilder, price: Currency) -> ProductBuilder {
|
||||
builder.price(price)
|
||||
}
|
||||
|
||||
pub fn product_builder_type(builder: ProductBuilder, type_: ProductType) -> ProductBuilder {
|
||||
builder.type_(type_)
|
||||
}
|
||||
|
||||
pub fn product_builder_category(builder: ProductBuilder, category: &str) -> ProductBuilder {
|
||||
builder.category(category)
|
||||
}
|
||||
|
||||
pub fn product_builder_status(builder: ProductBuilder, status: ProductStatus) -> ProductBuilder {
|
||||
builder.status(status)
|
||||
}
|
||||
|
||||
pub fn product_builder_max_amount(builder: ProductBuilder, max_amount: i64) -> ProductBuilder {
|
||||
builder.max_amount(max_amount as u16)
|
||||
}
|
||||
|
||||
pub fn product_builder_validity_days(builder: ProductBuilder, validity_days: i64) -> ProductBuilder {
|
||||
builder.validity_days(validity_days)
|
||||
}
|
||||
|
||||
pub fn product_builder_add_component(builder: ProductBuilder, component: ProductComponent) -> ProductBuilder {
|
||||
builder.add_component(component)
|
||||
}
|
||||
|
||||
pub fn product_builder_build(builder: ProductBuilder) -> Result<Product, Box<EvalAltResult>> {
|
||||
builder.build().map_err(|e| {
|
||||
Box::new(EvalAltResult::ErrorRuntime(
|
||||
e.into(),
|
||||
Position::NONE
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
// Exchange Rate Service Functions
|
||||
pub fn exchange_rate_convert(amount: f64, from_currency: &str, to_currency: &str) -> Result<f64, Box<EvalAltResult>> {
|
||||
match EXCHANGE_RATE_SERVICE.convert(amount, from_currency, to_currency) {
|
||||
Some(converted) => Ok(converted),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to convert {} {} to {}", amount, from_currency, to_currency).into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exchange_rate_get_rate(from_currency: &str, to_currency: &str) -> Result<f64, Box<EvalAltResult>> {
|
||||
match EXCHANGE_RATE_SERVICE.get_rate(from_currency, to_currency) {
|
||||
Some(rate) => Ok(rate),
|
||||
None => Err(Box::new(EvalAltResult::ErrorRuntime(
|
||||
format!("Failed to get exchange rate from {} to {}", from_currency, to_currency).into(),
|
||||
Position::NONE
|
||||
)))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user