Remove unneeded dependencies, start work on csv parsing
This commit is contained in:
@@ -88,9 +88,8 @@ pub fn move_money_2(
|
||||
initial_totals: HashMap<Unit, f64>,
|
||||
rules: &Vec<MovementRule>,
|
||||
) -> HashMap<Unit, f64> {
|
||||
// TODO: Should probably validate that all the rules have departments that actually exist in initial_totals.
|
||||
// Note: It's potentially a bit more intensive to use cloned totals, but it's much simpler code and, and since we're only working line-by-line
|
||||
// it isn't really that much memory. in practice
|
||||
// Note: It's potentially a bit more intensive to use cloned totals (rather than just update temp_total per rule),
|
||||
// but it's much simpler code and, and since we're only working line-by-line, it isn't really that much memory in practice
|
||||
let mut running_total = HashMap::from(initial_totals);
|
||||
let mut temp_total = running_total.clone();
|
||||
for rule in rules {
|
||||
@@ -135,11 +134,9 @@ pub enum DepartmentType {
|
||||
Overhead,
|
||||
}
|
||||
|
||||
// TODO: Could also look at BigDecimal rather than f64 for higher precision (even i64 might be fine if we don't need to divide...)
|
||||
// Note: remember these are overhead departments only when calculating the lu decomposition or pseudoinverse, and for each department,
|
||||
// you either need -1 or rest negative for a row to subtract the initial amounts so we end up effectively 0 (simultaneous equations end
|
||||
// up with negative there so yes this is expected)
|
||||
// Also, we could potentially use this same struct for non-overhead departments when mapping from overhead to
|
||||
pub struct OverheadAllocationRule {
|
||||
from_overhead_department: String,
|
||||
to_department: String,
|
||||
|
||||
89
src/main.rs
89
src/main.rs
@@ -1,6 +1,7 @@
|
||||
use std::{error::Error, io::Write, path::PathBuf};
|
||||
use std::{collections::HashMap, error::Error, io::Write, path::PathBuf};
|
||||
|
||||
use clap::{builder::PathBufValueParser, Parser, Subcommand};
|
||||
use coster_rs::Unit;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Parser)]
|
||||
@@ -47,7 +48,6 @@ enum Commands {
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: Return error (implement the required trait to allow an error to be returned)
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
|
||||
@@ -57,23 +57,67 @@ fn main() -> anyhow::Result<()> {
|
||||
lines,
|
||||
output,
|
||||
} => move_money(rules, lines, output),
|
||||
Commands::smush_rules { rules, output } => smush_rules(rules, output)?,
|
||||
Commands::smush_rules { rules, output } => smush_rules(rules, output),
|
||||
Commands::allocate_overheads {
|
||||
rules,
|
||||
lines,
|
||||
output,
|
||||
} => allocate_overheads(rules, lines, output)?,
|
||||
};
|
||||
Ok(())
|
||||
} => allocate_overheads(rules, lines, output),
|
||||
}
|
||||
}
|
||||
|
||||
fn move_money(rules: PathBuf, lines: PathBuf, output: Option<PathBuf>) {
|
||||
// read rules into required struct (basically map each line into an array)
|
||||
fn move_money(rules: PathBuf, lines: PathBuf, output: Option<PathBuf>) -> anyhow::Result<()> {
|
||||
let mut rdr = csv::Reader::from_path(lines)?;
|
||||
let headers = rdr.headers()?;
|
||||
let mut account_index = 0;
|
||||
let mut department_index = 0;
|
||||
for (index, field) in headers.iter().enumerate() {
|
||||
if field == "Account" {
|
||||
account_index = index;
|
||||
} else if field == "Department" {
|
||||
department_index = index;
|
||||
}
|
||||
}
|
||||
|
||||
let lines: HashMap<Unit, f64> = rdr
|
||||
.records()
|
||||
.map(|record| {
|
||||
let record = record.unwrap();
|
||||
let account = record.get(account_index).unwrap();
|
||||
let department = record.get(department_index).unwrap();
|
||||
let sum = record
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(i, _)| *i != account_index && *i != department_index)
|
||||
.map(|(_, f)| f.parse::<f64>().unwrap())
|
||||
.sum();
|
||||
(
|
||||
Unit {
|
||||
account: account.into(),
|
||||
department: department.into(),
|
||||
},
|
||||
sum,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
// read rules into required struct (basically map each line into an array). Need to figure out the input format...
|
||||
let mut rdr = csv::Reader::from_path(rules)?;
|
||||
for result in rdr.deserialize() {
|
||||
let record: CsvMovementRule = result?;
|
||||
// TODO: Problem is the from/to are ranges, that rely on the gl data, so need to get a list of
|
||||
//
|
||||
}
|
||||
|
||||
// Read gl lines data (all of it). For each line, sum the periods, and insert the summed
|
||||
// line into a hashmap (need to read the whole gl in as we can move between every line)
|
||||
// We use a record, everything that's not an account/department is assumed to be a period
|
||||
|
||||
// Then run move_moeny, and output the result into a new file at the given output location
|
||||
// Then run move_moeny
|
||||
|
||||
// Ouput the list moved moneys
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn smush_rules(rules_path: PathBuf, output: Option<PathBuf>) -> anyhow::Result<()> {
|
||||
@@ -86,14 +130,15 @@ fn allocate_overheads(
|
||||
output: Option<PathBuf>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut rdr = csv::Reader::from_path(rules_path)?;
|
||||
|
||||
for result in rdr.deserialize() {
|
||||
let record: CsvMovementRule = result?;
|
||||
let record: CsvOverheadAllocationRule = result?;
|
||||
}
|
||||
|
||||
let mut account_reader = csv::Reader::from_path(lines)?;
|
||||
|
||||
for result in account_reader.deserialize() {
|
||||
let record: CsvAccountCost = result?;
|
||||
let record: CsvCost = result?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -101,15 +146,31 @@ fn allocate_overheads(
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CsvMovementRule {
|
||||
from_department: String,
|
||||
to_department: String,
|
||||
#[serde(rename = "FromCC")]
|
||||
// Need strings to further split later
|
||||
from_departments: String,
|
||||
to_departments: String,
|
||||
all_from_departments: bool,
|
||||
all_to_departments: bool,
|
||||
from_accounts: String,
|
||||
to_accounts: String,
|
||||
all_from_accounts: bool,
|
||||
all_to_accounts: bool,
|
||||
amount: f64,
|
||||
is_percent: Option<bool>,
|
||||
is_separator: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CsvAccountCost {
|
||||
struct CsvOverheadAllocationRule {
|
||||
from_overhead_department: String,
|
||||
to_department: String,
|
||||
percent: f64,
|
||||
to_department_type: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CsvCost {
|
||||
account: String,
|
||||
department: String,
|
||||
value: f64,
|
||||
|
||||
Reference in New Issue
Block a user