Add schema generation, refactor cli, add most of the derive operations

This commit is contained in:
2024-08-03 16:33:16 +09:30
parent fbf74d5299
commit 3cdaa81da1
11 changed files with 567 additions and 328 deletions

107
src/cli/commands.rs Normal file
View File

@@ -0,0 +1,107 @@
use std::path::PathBuf;
use clap::Subcommand;
#[derive(Subcommand)]
pub enum Commands {
/// Moves money between accounts and departments, using the given rules and lines
MoveMoney {
#[arg(short = 'r', long, value_name = "FILE")]
rules: PathBuf,
#[arg(short = 'l', long, value_name = "FILE")]
lines: PathBuf,
#[arg(short = 'a', long, value_name = "FILE")]
accounts: PathBuf,
#[arg(short = 'c', long, value_name = "FILE")]
cost_centres: PathBuf,
#[arg(short, long, value_name = "FILE")]
output: Option<PathBuf>,
#[arg(short, long)]
use_numeric_accounts: bool,
#[arg(short, long)]
flush_pass: bool,
},
/// Allocates servicing department amounts to operating departments
AllocateOverheads {
#[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)]
exclude_negative_allocation_statistics: bool,
#[arg(short = 'f', long)]
show_from: bool,
#[arg(short, long, default_value = "0.00000000000000001")]
zero_threshold: f64,
#[arg(short, long, value_name = "FILE", default_value = "alloc_output.csv")]
output: PathBuf,
#[arg(short, long)]
msgpack_serialisation: bool,
},
CreateProducts {
#[arg(short, long, value_name = "FILE")]
definitions: PathBuf,
#[arg(short, long, value_name = "FILE")]
encounters: PathBuf,
#[arg(short, long, value_name = "FILE")]
services: PathBuf,
#[arg(short, long, value_name = "FILE")]
transfers: PathBuf,
#[arg(short, long, value_name = "FILE")]
procedures: PathBuf,
#[arg(short, long, value_name = "FILE")]
diagnoses: PathBuf,
#[arg(short, long, value_name = "FILE")]
patients: PathBuf,
#[arg(short, long, value_name = "FILE")]
revenues: PathBuf,
#[arg(short, long, value_name = "FILE")]
output: PathBuf,
},
RunGraph {
#[arg(short, long, value_name = "FILE")]
graph: PathBuf,
#[arg(short, long, default_value_t = num_cpus::get())]
threads: usize,
},
GenerateSchema {
#[arg(short, long, value_name = "FILE", default_value = "schema.json")]
output: PathBuf,
},
}

187
src/cli/mod.rs Normal file
View File

@@ -0,0 +1,187 @@
use std::{
collections::HashMap,
fs::File,
io::{BufReader, BufWriter},
path::PathBuf,
};
use std::io::Write;
use clap::{command, Parser};
pub use commands::Commands;
use coster_rs::{
create_products::InputFile,
graph::{Graph, RunnableGraph},
SourceType,
};
use log::info;
use schemars::schema_for;
mod commands;
#[derive(Parser)]
#[command(name = "coster-rs")]
#[command(author = "Pivato M. <mpivato4@gmail.com>")]
#[command(version = "0.0.1")]
#[command(about = "Simple, fast, efficient costing tool", long_about = None)]
pub struct Cli {
#[clap(subcommand)]
pub command: Commands,
}
impl Cli {
pub fn run(self) -> anyhow::Result<()> {
match self.command {
Commands::MoveMoney {
rules,
lines,
accounts,
cost_centres,
output,
use_numeric_accounts,
flush_pass,
} => coster_rs::move_money(
&mut csv::Reader::from_path(rules)?,
&mut csv::Reader::from_path(lines)?,
&mut csv::Reader::from_path(accounts)?,
&mut csv::Reader::from_path(cost_centres)?,
&mut csv::Writer::from_path(output.unwrap_or(PathBuf::from("output.csv")))?,
use_numeric_accounts,
flush_pass,
),
Commands::AllocateOverheads {
lines,
accounts,
allocation_statistics,
areas,
cost_centres,
use_numeric_accounts,
account_type,
exclude_negative_allocation_statistics,
show_from,
zero_threshold,
output,
msgpack_serialisation,
} => {
if msgpack_serialisation {
let mut file = BufWriter::new(File::create(output)?);
coster_rs::reciprocal_allocation(
&mut csv::Reader::from_path(lines)?,
&mut csv::Reader::from_path(accounts)?,
&mut csv::Reader::from_path(allocation_statistics)?,
&mut csv::Reader::from_path(areas)?,
&mut csv::Reader::from_path(cost_centres)?,
&mut rmp_serde::Serializer::new(&mut file),
use_numeric_accounts,
exclude_negative_allocation_statistics,
true,
account_type,
show_from,
zero_threshold,
)
} else {
coster_rs::reciprocal_allocation(
&mut csv::Reader::from_path(lines)?,
&mut csv::Reader::from_path(accounts)?,
&mut csv::Reader::from_path(allocation_statistics)?,
&mut csv::Reader::from_path(areas)?,
&mut csv::Reader::from_path(cost_centres)?,
&mut csv::Writer::from_path(output)?,
use_numeric_accounts,
exclude_negative_allocation_statistics,
true,
account_type,
show_from,
zero_threshold,
)
}
}
Commands::CreateProducts {
definitions,
encounters,
services,
transfers,
procedures,
diagnoses,
patients,
revenues,
output,
} => {
let mut inputs = HashMap::new();
inputs.insert(
SourceType::Encounter,
InputFile {
file_path: encounters,
joins: HashMap::new(),
date_order_column: Some("StartDateTime".to_owned()),
},
);
inputs.insert(
SourceType::Service,
InputFile {
file_path: services,
joins: HashMap::new(),
date_order_column: Some("StartDateTime".to_owned()),
},
);
inputs.insert(
SourceType::Transfer,
InputFile {
file_path: transfers,
joins: HashMap::new(),
date_order_column: Some("StartDateTime".to_owned()),
},
);
inputs.insert(
SourceType::CodingProcedure,
InputFile {
file_path: procedures,
joins: HashMap::new(),
date_order_column: Some("ProcedureDateTime".to_owned()),
},
);
inputs.insert(
SourceType::CodingDiagnosis,
InputFile {
file_path: diagnoses,
joins: HashMap::new(),
date_order_column: None,
},
);
inputs.insert(
SourceType::Patient,
InputFile {
file_path: patients,
joins: HashMap::new(),
date_order_column: None,
},
);
inputs.insert(
SourceType::Revenue,
InputFile {
file_path: revenues,
joins: HashMap::new(),
date_order_column: None,
},
);
coster_rs::create_products::create_products_polars(definitions, vec![], output)
}
Commands::RunGraph { graph, threads } => {
let file = File::open(graph)?;
let reader = BufReader::new(file);
let graph = serde_json::from_reader(reader)?;
let graph = RunnableGraph::from_graph(graph);
graph.run_default_tasks(threads, |id, status| {
info!("Node with id {} finished with status {:?}", id, status)
})
}
Commands::GenerateSchema { output } => {
let schema = schema_for!(Graph);
let mut output = File::create(output).unwrap();
write!(output, "{}", serde_json::to_string_pretty(&schema).unwrap())?;
Ok(())
}
}
}
}