use std::{collections::HashMap, error::Error, io::Write, path::PathBuf}; use clap::{Parser, Subcommand}; use coster_rs::CsvCost; use serde::Deserialize; #[derive(Parser)] #[command(name = "coster-rs")] #[command(author = "Pivato M. ")] #[command(version = "0.0.1")] #[command(about = "Simple, fast, efficient costing tool", long_about = None)] struct Cli { #[clap(subcommand)] command: Commands, } #[derive(Subcommand)] enum Commands { /// Moves money between accounts and departments, using the given rules and lines move_money { #[arg(short = 'r', long, value_name = "FILE")] rules: PathBuf, #[arg(short = 'l', long, value_name = "FILE")] lines: PathBuf, #[arg(short, long, value_name = "FILE")] output: Option, #[arg(short, long)] use_numeric_accounts: bool, }, /// Combines rules to the minimum set required smush_rules { #[arg(short = 'r', long, value_name = "FILE")] rules: PathBuf, #[arg(short, long, value_name = "FILE")] output: Option, }, /// Allocates servicing department amounts to operating departments allocate_overheads { #[arg(short, long, value_name = "FILE")] lines: PathBuf, #[arg(short, long, value_name = "FILE")] accounts: PathBuf, #[arg(short = 's', long, value_name = "FILE")] allocation_statistics: PathBuf, #[arg(short, long, value_name = "FILE")] areas: PathBuf, #[arg(short, long, value_name = "FILE")] cost_centres: PathBuf, #[arg(short, long)] use_numeric_accounts: bool, #[arg(long, default_value = "E")] account_type: String, #[arg(short, long, value_name = "FILE")] output: Option, }, } fn main() -> anyhow::Result<()> { let cli = Cli::parse(); match cli.command { Commands::move_money { rules, lines, output, use_numeric_accounts, } => move_money(rules, lines, output, use_numeric_accounts), Commands::smush_rules { rules, output } => smush_rules(rules, output), Commands::allocate_overheads { lines, accounts, allocation_statistics, areas, cost_centres, use_numeric_accounts, account_type, output, } => allocate_overheads( lines, accounts, allocation_statistics, areas, cost_centres, use_numeric_accounts, account_type, output, ), } } fn move_money( rules: PathBuf, lines: PathBuf, output: Option, use_numeric_accounts: bool, ) -> anyhow::Result<()> { coster_rs::move_money( csv::Reader::from_path(rules)?, csv::Reader::from_path(lines)?, &mut csv::Writer::from_path(output.unwrap_or(PathBuf::from("output.csv")))?, use_numeric_accounts, ) } fn smush_rules(rules_path: PathBuf, output: Option) -> anyhow::Result<()> { Ok(()) } fn allocate_overheads( lines: PathBuf, accounts: PathBuf, allocation_statistics: PathBuf, areas: PathBuf, cost_centres: PathBuf, use_numeric_accounts: bool, account_type: String, output: Option, ) -> anyhow::Result<()> { coster_rs::reciprocal_allocation( csv::Reader::from_path(lines)?, csv::Reader::from_path(accounts)?, csv::Reader::from_path(allocation_statistics)?, csv::Reader::from_path(areas)?, csv::Reader::from_path(cost_centres)?, &mut csv::Writer::from_path(output.unwrap_or(PathBuf::from("alloc_output.csv")))?, use_numeric_accounts, false, true, account_type, ) } #[derive(Debug, Deserialize)] struct CsvOverheadAllocationRule { from_overhead_department: String, to_department: String, percent: f64, to_department_type: String, }