use heromodels::db::Db; use macros::{ register_authorized_create_by_id_fn, register_authorized_delete_by_id_fn, register_authorized_get_by_id_fn, }; use rhai::plugin::*; use rhai::{Array, Engine, EvalAltResult, Module, Position, FLOAT, INT}; use std::mem; use std::sync::Arc; use heromodels::db::hero::OurDB; use heromodels::db::Collection; use heromodels::models::biz::product::{Product, ProductComponent, ProductStatus, ProductType}; use heromodels::models::biz::company::{BusinessType, Company, CompanyStatus}; use heromodels::models::biz::sale::{Sale, SaleItem, SaleStatus}; use heromodels::models::biz::shareholder::{Shareholder, ShareholderType}; type RhaiProduct = Product; type RhaiProductComponent = ProductComponent; type RhaiCompany = Company; type RhaiSale = Sale; type RhaiSaleItem = SaleItem; type RhaiShareholder = Shareholder; #[export_module] mod rhai_product_component_module { use super::{RhaiProductComponent, INT}; #[rhai_fn(name = "new_product_component", return_raw)] pub fn new_product_component() -> Result> { Ok(ProductComponent::new()) } #[rhai_fn(name = "name", return_raw)] pub fn set_name( component: &mut RhaiProductComponent, name: String, ) -> Result> { let owned = std::mem::take(component); *component = owned.name(name); Ok(component.clone()) } #[rhai_fn(name = "description", return_raw)] pub fn set_description( component: &mut RhaiProductComponent, description: String, ) -> Result> { let owned = std::mem::take(component); *component = owned.description(description); Ok(component.clone()) } #[rhai_fn(name = "quantity", return_raw)] pub fn set_quantity( component: &mut RhaiProductComponent, quantity: INT, ) -> Result> { let owned = std::mem::take(component); *component = owned.quantity(quantity as u32); Ok(component.clone()) } // --- Getters --- #[rhai_fn(name = "get_name")] pub fn get_name(c: &mut RhaiProductComponent) -> String { c.name.clone() } #[rhai_fn(name = "get_description")] pub fn get_description(c: &mut RhaiProductComponent) -> String { c.description.clone() } #[rhai_fn(name = "get_quantity")] pub fn get_quantity(c: &mut RhaiProductComponent) -> INT { c.quantity as INT } } #[export_module] mod rhai_product_module { use super::{Array, ProductStatus, ProductType, RhaiProduct, RhaiProductComponent, FLOAT, INT}; #[rhai_fn(name = "new_product", return_raw)] pub fn new_product() -> Result> { Ok(Product::new()) } // --- Setters --- #[rhai_fn(name = "name", return_raw)] pub fn set_name( product: &mut RhaiProduct, name: String, ) -> Result> { let owned = std::mem::take(product); *product = owned.name(name); Ok(product.clone()) } #[rhai_fn(name = "description", return_raw)] pub fn set_description( product: &mut RhaiProduct, description: String, ) -> Result> { let owned = std::mem::take(product); *product = owned.description(description); Ok(product.clone()) } #[rhai_fn(name = "price", return_raw)] pub fn set_price( product: &mut RhaiProduct, price: FLOAT, ) -> Result> { let owned = std::mem::take(product); *product = owned.price(price); Ok(product.clone()) } #[rhai_fn(name = "category", return_raw)] pub fn set_category( product: &mut RhaiProduct, category: String, ) -> Result> { let owned = std::mem::take(product); *product = owned.category(category); Ok(product.clone()) } #[rhai_fn(name = "max_amount", return_raw)] pub fn set_max_amount( product: &mut RhaiProduct, max_amount: INT, ) -> Result> { let owned = std::mem::take(product); *product = owned.max_amount(max_amount as u32); Ok(product.clone()) } #[rhai_fn(name = "purchase_till", return_raw)] pub fn set_purchase_till( product: &mut RhaiProduct, purchase_till: INT, ) -> Result> { let owned = std::mem::take(product); *product = owned.purchase_till(purchase_till); Ok(product.clone()) } #[rhai_fn(name = "active_till", return_raw)] pub fn set_active_till( product: &mut RhaiProduct, active_till: INT, ) -> Result> { let owned = std::mem::take(product); *product = owned.active_till(active_till); Ok(product.clone()) } #[rhai_fn(name = "type", return_raw)] pub fn set_type( product: &mut RhaiProduct, type_str: String, ) -> Result> { let product_type = match type_str.to_lowercase().as_str() { "physical" => ProductType::Physical, "digital" => ProductType::Digital, "service" => ProductType::Service, "subscription" => ProductType::Subscription, _ => { return Err(EvalAltResult::ErrorSystem( "Invalid ProductType".to_string(), "Must be one of: Physical, Digital, Service, Subscription".into(), ) .into()) } }; let owned = std::mem::take(product); *product = owned.product_type(product_type); Ok(product.clone()) } #[rhai_fn(name = "status", return_raw)] pub fn set_status( product: &mut RhaiProduct, status_str: String, ) -> Result> { let status = match status_str.to_lowercase().as_str() { "active" => ProductStatus::Active, "inactive" => ProductStatus::Inactive, "discontinued" => ProductStatus::Discontinued, _ => { return Err(EvalAltResult::ErrorSystem( "Invalid ProductStatus".to_string(), "Must be one of: Active, Inactive, Discontinued".into(), ) .into()) } }; let owned = std::mem::take(product); *product = owned.status(status); Ok(product.clone()) } #[rhai_fn(name = "add_component", return_raw)] pub fn add_component( product: &mut RhaiProduct, component: RhaiProductComponent, ) -> Result> { let owned = std::mem::take(product); *product = owned.add_component(component); Ok(product.clone()) } #[rhai_fn(name = "set_components", return_raw)] pub fn set_components( product: &mut RhaiProduct, components: Array, ) -> Result> { let mut product_components = Vec::new(); for component_dynamic in components { if let Ok(component) = component_dynamic.try_cast::() { product_components.push(component); } else { return Err(EvalAltResult::ErrorSystem( "Invalid component type".to_string(), "All components must be ProductComponent objects".into(), ) .into()); } } let owned = std::mem::take(product); *product = owned.components(product_components); Ok(product.clone()) } // --- Getters --- #[rhai_fn(name = "get_id")] pub fn get_id(p: &mut RhaiProduct) -> i64 { p.base.id as i64 } #[rhai_fn(name = "get_name")] pub fn get_name(p: &mut RhaiProduct) -> String { p.name.clone() } #[rhai_fn(name = "get_description")] pub fn get_description(p: &mut RhaiProduct) -> String { p.description.clone() } #[rhai_fn(name = "get_price")] pub fn get_price(p: &mut RhaiProduct) -> FLOAT { p.price } #[rhai_fn(name = "get_category")] pub fn get_category(p: &mut RhaiProduct) -> String { p.category.clone() } #[rhai_fn(name = "get_max_amount")] pub fn get_max_amount(p: &mut RhaiProduct) -> INT { p.max_amount as INT } #[rhai_fn(name = "get_purchase_till")] pub fn get_purchase_till(p: &mut RhaiProduct) -> INT { p.purchase_till } #[rhai_fn(name = "get_active_till")] pub fn get_active_till(p: &mut RhaiProduct) -> INT { p.active_till } #[rhai_fn(name = "get_type")] pub fn get_type(p: &mut RhaiProduct) -> String { format!("{:?}", p.product_type) } #[rhai_fn(name = "get_status")] pub fn get_status(p: &mut RhaiProduct) -> String { format!("{:?}", p.status) } #[rhai_fn(name = "get_components")] pub fn get_components(p: &mut RhaiProduct) -> Array { p.components .iter() .map(|c| rhai::Dynamic::from(c.clone())) .collect() } } pub fn register_product_rhai_module(engine: &mut Engine) { let mut product_module = exported_module!(rhai_product_module); let mut component_module = exported_module!(rhai_product_component_module); register_authorized_create_by_id_fn!( product_module: &mut product_module, rhai_fn_name: "save_product", resource_type_str: "Product", rhai_return_rust_type: heromodels::models::biz::product::Product ); register_authorized_get_by_id_fn!( product_module: &mut product_module, rhai_fn_name: "get_product", resource_type_str: "Product", rhai_return_rust_type: heromodels::models::biz::product::Product ); register_authorized_delete_by_id_fn!( product_module: &mut product_module, rhai_fn_name: "delete_product", resource_type_str: "Product", rhai_return_rust_type: heromodels::models::biz::product::Product ); engine.register_global_module(product_module.into()); engine.register_global_module(component_module.into()); } // Company Rhai wrapper functions #[export_module] mod rhai_company_module { use super::{BusinessType, CompanyStatus, RhaiCompany}; #[rhai_fn(name = "new_company", return_raw)] pub fn new_company() -> Result> { Ok(Company::new()) } #[rhai_fn(name = "name", return_raw)] pub fn set_name( company: &mut RhaiCompany, name: String, ) -> Result> { let owned = std::mem::take(company); *company = owned.name(name); Ok(company.clone()) } #[rhai_fn(name = "get_company_id")] pub fn get_company_id(company: &mut RhaiCompany) -> i64 { company.id() as i64 } #[rhai_fn(name = "get_company_name")] pub fn get_company_name(company: &mut RhaiCompany) -> String { company.name().clone() } } pub fn register_company_rhai_module(engine: &mut Engine) { let mut module = exported_module!(rhai_company_module); register_authorized_create_by_id_fn!( module: &mut module, rhai_fn_name: "save_company", resource_type_str: "Company", rhai_return_rust_type: heromodels::models::biz::company::Company ); register_authorized_get_by_id_fn!( module: &mut module, rhai_fn_name: "get_company", resource_type_str: "Company", rhai_return_rust_type: heromodels::models::biz::company::Company ); engine.register_global_module(module.into()); } // Sale Rhai wrapper functions #[export_module] mod rhai_sale_module { use super::{RhaiSale, RhaiSaleItem, SaleStatus}; #[rhai_fn(name = "new_sale", return_raw)] pub fn new_sale() -> Result> { Ok(Sale::new()) } #[rhai_fn(name = "new_sale_item", return_raw)] pub fn new_sale_item() -> Result> { Ok(SaleItem::new()) } #[rhai_fn(name = "company_id", return_raw)] pub fn set_sale_company_id(sale: &mut RhaiSale, company_id: i64) -> Result> { let owned = std::mem::take(sale); *sale = owned.company_id(company_id as u32); Ok(sale.clone()) } #[rhai_fn(name = "total_amount", return_raw)] pub fn set_sale_total_amount(sale: &mut RhaiSale, total_amount: f64) -> Result> { let owned = std::mem::take(sale); *sale = owned.total_amount(total_amount); Ok(sale.clone()) } #[rhai_fn(name = "get_sale_id")] pub fn get_sale_id(sale: &mut RhaiSale) -> i64 { sale.id() as i64 } #[rhai_fn(name = "get_sale_total_amount")] pub fn get_sale_total_amount(sale: &mut RhaiSale) -> f64 { sale.total_amount() } } pub fn register_sale_rhai_module(engine: &mut Engine) { let mut module = exported_module!(rhai_sale_module); register_authorized_create_by_id_fn!( module: &mut module, rhai_fn_name: "save_sale", resource_type_str: "Sale", rhai_return_rust_type: heromodels::models::biz::sale::Sale ); register_authorized_get_by_id_fn!( module: &mut module, rhai_fn_name: "get_sale", resource_type_str: "Sale", rhai_return_rust_type: heromodels::models::biz::sale::Sale ); engine.register_global_module(module.into()); }