use super::config::AccountingConfig;
use super::hook::{AccountingHook, DefaultAccountingHook};
use super::resources::BudgetLedger;
use super::service::AccountingService;
use super::state::AccountingState;
use super::system::AccountingSystem;
use super::types::Currency;
use crate::plugin::{Plugin, PluginBuilder, PluginBuilderExt};
use async_trait::async_trait;
use std::sync::Arc;
pub struct AccountingPlugin {
hook: Arc<dyn AccountingHook>,
config: AccountingConfig,
starting_cash: Currency,
}
impl AccountingPlugin {
pub fn new() -> Self {
Self {
hook: Arc::new(DefaultAccountingHook),
config: AccountingConfig::default(),
starting_cash: Currency::new(2400),
}
}
pub fn with_hook<H: AccountingHook + 'static>(mut self, hook: H) -> Self {
self.hook = Arc::new(hook);
self
}
pub fn with_config(mut self, config: AccountingConfig) -> Self {
self.config = config;
self
}
pub fn with_starting_cash(mut self, starting_cash: Currency) -> Self {
self.starting_cash = starting_cash;
self
}
}
impl Default for AccountingPlugin {
fn default() -> Self {
Self::new()
}
}
#[async_trait]
impl Plugin for AccountingPlugin {
fn name(&self) -> &'static str {
"issun:accounting"
}
fn build(&self, builder: &mut dyn PluginBuilder) {
builder.register_resource(self.config.clone());
builder.register_runtime_state(AccountingState::new());
builder.register_runtime_state(BudgetLedger::new(self.starting_cash));
builder.register_service(Box::new(AccountingService::new()));
builder.register_system(Box::new(AccountingSystem::new(self.hook.clone())));
}
fn dependencies(&self) -> Vec<&'static str> {
vec!["issun:time"]
}
async fn initialize(&mut self) {
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_plugin_creation() {
let plugin = AccountingPlugin::new();
assert_eq!(plugin.name(), "issun:accounting");
}
#[test]
fn test_plugin_dependencies() {
let plugin = AccountingPlugin::default();
assert_eq!(plugin.dependencies(), vec!["issun:time"]);
}
#[test]
fn test_plugin_with_custom_hook() {
struct CustomHook;
#[async_trait::async_trait]
impl AccountingHook for CustomHook {}
let plugin = AccountingPlugin::new().with_hook(CustomHook);
assert_eq!(plugin.name(), "issun:accounting");
}
#[test]
fn test_plugin_with_custom_config() {
let config = AccountingConfig {
settlement_period_days: 30,
};
let plugin = AccountingPlugin::new().with_config(config);
assert_eq!(plugin.name(), "issun:accounting");
}
#[test]
fn test_plugin_with_starting_cash() {
let starting_cash = Currency::new(5000);
let plugin = AccountingPlugin::new().with_starting_cash(starting_cash);
assert_eq!(plugin.starting_cash.amount(), 5000);
}
}