Add numeric accounts as property to lib, redistribute floating point errors for each account in overhead allocation
This commit is contained in:
@@ -13,6 +13,8 @@ struct MoveMoney: View {
|
|||||||
@State private var document: CsvDocument?
|
@State private var document: CsvDocument?
|
||||||
@State private var lines: String?
|
@State private var lines: String?
|
||||||
@State private var rules: String?
|
@State private var rules: String?
|
||||||
|
@State private var costCentres: String?
|
||||||
|
@State private var accounts: String?
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
FileButtonSelector(label: "Select Rules File") { result in
|
FileButtonSelector(label: "Select Rules File") { result in
|
||||||
@@ -21,6 +23,12 @@ struct MoveMoney: View {
|
|||||||
FileButtonSelector(label: "Select Lines File") { result in
|
FileButtonSelector(label: "Select Lines File") { result in
|
||||||
lines = result
|
lines = result
|
||||||
}
|
}
|
||||||
|
FileButtonSelector(label: "Select Cost Centres File") { result in
|
||||||
|
costCentres = result
|
||||||
|
}
|
||||||
|
FileButtonSelector(label: "Select Accounts File") { result in
|
||||||
|
accounts = result
|
||||||
|
}
|
||||||
Button {
|
Button {
|
||||||
move_money()
|
move_money()
|
||||||
} label: {
|
} label: {
|
||||||
@@ -43,7 +51,7 @@ struct MoveMoney: View {
|
|||||||
func move_money() {
|
func move_money() {
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
DispatchQueue.global(qos: .userInitiated).async {
|
||||||
// Run move money
|
// Run move money
|
||||||
let result = move_money_from_text(rules, lines, true)
|
let result = move_money_from_text(rules, lines, accounts, costCentres, false)
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
document = CsvDocument(data: String(cString: result!))
|
document = CsvDocument(data: String(cString: result!))
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ struct OverheadAllocation: View {
|
|||||||
func allocate_overheads() {
|
func allocate_overheads() {
|
||||||
DispatchQueue.global(qos: .userInitiated).async {
|
DispatchQueue.global(qos: .userInitiated).async {
|
||||||
// Run move money
|
// Run move money
|
||||||
let result = allocate_overheads_from_text(lines, accounts, allocationStatistics, areas, costCentres, accountType);
|
let result = allocate_overheads_from_text(lines, accounts, allocationStatistics, areas, costCentres, accountType, false);
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
document = CsvDocument(data: String(cString: result!))
|
document = CsvDocument(data: String(cString: result!))
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ pub extern "C" fn allocate_overheads_from_text(
|
|||||||
areas: *const c_char,
|
areas: *const c_char,
|
||||||
cost_centres: *const c_char,
|
cost_centres: *const c_char,
|
||||||
account_type: *const c_char,
|
account_type: *const c_char,
|
||||||
|
use_numeric_accounts: bool,
|
||||||
) -> *mut c_char {
|
) -> *mut c_char {
|
||||||
let lines = unsafe {
|
let lines = unsafe {
|
||||||
assert!(!lines.is_null());
|
assert!(!lines.is_null());
|
||||||
@@ -113,7 +114,7 @@ pub extern "C" fn allocate_overheads_from_text(
|
|||||||
csv::Reader::from_reader(areas.to_bytes()),
|
csv::Reader::from_reader(areas.to_bytes()),
|
||||||
csv::Reader::from_reader(cost_centres.to_bytes()),
|
csv::Reader::from_reader(cost_centres.to_bytes()),
|
||||||
&mut output_writer,
|
&mut output_writer,
|
||||||
true,
|
use_numeric_accounts,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
account_type.to_str().unwrap().to_owned(),
|
account_type.to_str().unwrap().to_owned(),
|
||||||
|
|||||||
@@ -549,7 +549,7 @@ fn do_solve_reciprocal<T: ReciprocalAllocationSolver>(
|
|||||||
let calculated_overheads = solver.solve(&overhead_costs_vec);
|
let calculated_overheads = solver.solve(&overhead_costs_vec);
|
||||||
|
|
||||||
let mut operating_slice_costs = vec![0.; operating_department_mappings.len()];
|
let mut operating_slice_costs = vec![0.; operating_department_mappings.len()];
|
||||||
for cost in total_costs.summed_department_costs {
|
for cost in &total_costs.summed_department_costs {
|
||||||
if operating_department_mappings.contains_key(&cost.department) {
|
if operating_department_mappings.contains_key(&cost.department) {
|
||||||
let elem = &mut operating_slice_costs
|
let elem = &mut operating_slice_costs
|
||||||
[*operating_department_mappings.get(&cost.department).unwrap()];
|
[*operating_department_mappings.get(&cost.department).unwrap()];
|
||||||
@@ -579,9 +579,30 @@ fn do_solve_reciprocal<T: ReciprocalAllocationSolver>(
|
|||||||
value: *calculated.get(*index).unwrap(),
|
value: *calculated.get(*index).unwrap(),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
// Redistribute floating point errors (only for ccs we actually allocated from/to)
|
||||||
|
// TODO: Still not sure if this is 100% correct, however it appears with this we match up
|
||||||
|
// with the line totals. I think this is because ppm just evenly redistributes floating point
|
||||||
|
// errors, whereas we keep the amounts proportional to the intial amounts
|
||||||
|
let initial_cost: f64 = total_costs
|
||||||
|
.summed_department_costs
|
||||||
|
.iter()
|
||||||
|
.filter(|cost| {
|
||||||
|
operating_department_mappings.contains_key(&cost.department)
|
||||||
|
|| overhead_department_mappings.contains_key(&cost.department)
|
||||||
|
})
|
||||||
|
.map(|cost| cost.value)
|
||||||
|
.sum();
|
||||||
|
let new_cost: f64 = converted_result.iter().map(|cost| cost.value).sum();
|
||||||
|
let diff = initial_cost - new_cost;
|
||||||
final_account_costs.push(AccountCost {
|
final_account_costs.push(AccountCost {
|
||||||
account: total_costs.account,
|
account: total_costs.account,
|
||||||
summed_department_costs: converted_result,
|
summed_department_costs: converted_result
|
||||||
|
.into_iter()
|
||||||
|
.map(|cost| TotalDepartmentCost {
|
||||||
|
department: cost.department,
|
||||||
|
value: cost.value + cost.value / new_cost * diff,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Ok(final_account_costs)
|
Ok(final_account_costs)
|
||||||
|
|||||||
Reference in New Issue
Block a user