From 80af6663861438a3fc8e2b4d57cce3dd2da6b8cc Mon Sep 17 00:00:00 2001 From: scoobybejesus Date: Sun, 17 Nov 2019 22:00:53 -0500 Subject: [PATCH] Fixed ToSelf txn cost basis bug. Resolves #52. Point release version bump, at a minimum, is warranted. --- src/crptls_lib/create_lots_mvmts.rs | 6 ++-- src/crptls_lib/import_cost_proceeds_etc.rs | 37 ++++++++++++---------- src/crptls_lib/transaction.rs | 4 +-- src/tests/test.rs | 4 +-- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/crptls_lib/create_lots_mvmts.rs b/src/crptls_lib/create_lots_mvmts.rs index 7ec9d25..c0a4efe 100644 --- a/src/crptls_lib/create_lots_mvmts.rs +++ b/src/crptls_lib/create_lots_mvmts.rs @@ -606,7 +606,7 @@ fn get_base_and_quote_acct_for_dual_actionrecord_flow_tx( let og_flow_ar = ar_map.get(txn.action_record_idx_vec.first().unwrap()).unwrap(); - let og_ar_mvmts_list = &og_flow_ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let og_ar_mvmts_list = &og_flow_ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); let og_ar_list_first_mvmt = &og_ar_mvmts_list.first().unwrap(); // TODO: then this takes the one mvmt let og_ar_list_first_mvmt_ar = ar_map.get(&og_ar_list_first_mvmt.action_record_key).unwrap(); let og_ar_list_first_mvmt_ar_acct = acct_map.get(&og_ar_list_first_mvmt_ar.account_key).unwrap(); @@ -828,12 +828,12 @@ fn process_multiple_incoming_lots_and_mvmts( let mut all_but_last_incoming_mvmt_amt = d128!(0.0); let mut all_but_last_incoming_mvmt_ratio = d128!(0.0); // println!("Txn date: {}. Outgoing mvmts: {}, Outgoing amount: {}", txn.date, outgoing_ar.movements.borrow().len(), outgoing_ar.amount); - let list_of_mvmts_of_outgoing_ar = outgoing_ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let list_of_mvmts_of_outgoing_ar = outgoing_ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); let final_mvmt = list_of_mvmts_of_outgoing_ar.last().unwrap(); // First iteration, for all but final movement for outgoing_mvmt in list_of_mvmts_of_outgoing_ar .iter() - .take(outgoing_ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map).len() - 1) { + .take(outgoing_ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map).len() - 1) { let ratio_of_outgoing_mvmt_to_total_ar = outgoing_mvmt.amount / outgoing_ar.amount; // Negative divided by negative is positive // println!("Ratio of outgoing amt to total actionrecord amt: {:.8}", ratio_of_outgoing_to_total_ar); let tentative_incoming_amt = ratio_of_outgoing_mvmt_to_total_ar * incoming_ar.amount; diff --git a/src/crptls_lib/import_cost_proceeds_etc.rs b/src/crptls_lib/import_cost_proceeds_etc.rs index 516cd37..f0fa05a 100644 --- a/src/crptls_lib/import_cost_proceeds_etc.rs +++ b/src/crptls_lib/import_cost_proceeds_etc.rs @@ -31,16 +31,17 @@ pub(crate) fn add_cost_basis_to_movements( let ar = ars.get(ar_num).unwrap(); let acct = acct_map.get(&ar.account_key).unwrap(); let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap(); - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); - for mvmt in movements.iter() { + for (idx, mvmt) in movements.iter().enumerate() { let polarity = ar.direction(); let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?; let is_home_curr = raw_acct.is_home_currency(&settings.home_currency); let mvmt_copy = mvmt.clone(); let borrowed_mvmt = mvmt_copy.clone(); - // println!("Txn: {} on {} of type: {:?}",txn.tx_number,txn.date, txn.transaction_type()); + // println!("Txn: {} on {} of type: {:?}", + // txn.tx_number,txn.date, txn.transaction_type(ars, raw_acct_map, acct_map)); if !raw_acct.is_margin { @@ -113,16 +114,17 @@ pub(crate) fn add_cost_basis_to_movements( TxType::ToSelf => { - let ratio_of_amt_to_incoming_mvmts_in_a_r = - borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r; - let cb_outgoing_ar = retrieve_cost_basis_from_corresponding_outgoing_toself( + let cb_vec_outgoing_ar = retrieve_cb_vec_from_corresponding_outgoing_toself( txn_num, &ars, txns_map, acct_map ); - let unrounded_basis = cb_outgoing_ar * ratio_of_amt_to_incoming_mvmts_in_a_r; + assert!(idx <= cb_vec_outgoing_ar.len(), + "ToSelf txn had different # of in- and out- mvmts (more outs than ins)."); + + let unrounded_basis = cb_vec_outgoing_ar[idx]; let rounded_basis = round_d128_1e2(&unrounded_basis); mvmt.cost_basis.set(-rounded_basis); @@ -154,26 +156,27 @@ pub(crate) fn add_cost_basis_to_movements( } } } - fn retrieve_cost_basis_from_corresponding_outgoing_toself( + + fn retrieve_cb_vec_from_corresponding_outgoing_toself( txn_num: u32, ars: &HashMap, txns_map: &HashMap, acct_map: &HashMap, - ) -> d128 { + ) -> Vec { let txn = txns_map.get(&txn_num).unwrap(); let other_ar_borrowed = &ars.get(&txn.action_record_idx_vec[0]).unwrap(); assert_eq!(other_ar_borrowed.direction(), Polarity::Outgoing); - let mut basis = d128!(0); - let movements = other_ar_borrowed.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = other_ar_borrowed.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); + let mut vec = Vec::new(); for mvmt in movements.iter() { - basis += mvmt.cost_basis.get(); + vec.push(mvmt.cost_basis.get()); } - basis + vec }; Ok(()) @@ -198,7 +201,7 @@ pub(crate) fn add_proceeds_to_movements( let ar = ars.get(ar_num).unwrap(); let acct = acct_map.get(&ar.account_key).unwrap(); let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap(); - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); if !raw_acct.is_margin { @@ -303,7 +306,7 @@ fn update_current_txn_for_prior_likekind_treatment( let ar = ars.get(ar_num).unwrap(); let acct = acct_map.get(&ar.account_key).unwrap(); let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap(); - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); for mvmt in movements.iter() { @@ -400,7 +403,7 @@ fn perform_likekind_treatment_on_txn( for ar_num in txn.action_record_idx_vec.iter() { let ar = ars.get(ar_num).unwrap(); - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); for mvmt in movements.iter() { @@ -445,7 +448,7 @@ fn perform_likekind_treatment_on_txn( for ar_num in txn.action_record_idx_vec.iter() { let ar = ars.get(ar_num).unwrap(); - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); let polarity = ar.direction(); diff --git a/src/crptls_lib/transaction.rs b/src/crptls_lib/transaction.rs index c612a12..b5f12b1 100644 --- a/src/crptls_lib/transaction.rs +++ b/src/crptls_lib/transaction.rs @@ -167,7 +167,7 @@ impl Transaction { if !raw_acct.is_home_currency(user_home_currency) & !raw_acct.is_margin { - let movements = ar.get_mvmts_in_ar_in_date_order(acct_map, txns_map); + let movements = ar.get_mvmts_in_ar_in_lot_date_order(acct_map, txns_map); match self.transaction_type(ars, raw_acct_map, acct_map)? { TxType::Exchange => { @@ -307,7 +307,7 @@ impl ActionRecord { /// ordered by their creation date (`date`), so later `Lot`s may have earlier `basis_date`s /// by virtue of them being the result of a `ToSelf` type `Transaction` that transferred /// old "coins." - pub fn get_mvmts_in_ar_in_date_order( + pub fn get_mvmts_in_ar_in_lot_date_order( &self, acct_map: &HashMap, txns_map: &HashMap, diff --git a/src/tests/test.rs b/src/tests/test.rs index bb1819b..a0171c8 100644 --- a/src/tests/test.rs +++ b/src/tests/test.rs @@ -67,7 +67,7 @@ fn compare_movements_across_implementations( + " with amount: " + &ar.amount.to_string() + &"\n".to_string() ); - let mvmts = ar.get_mvmts_in_ar_in_date_order(&account_map, &transactions_map); + let mvmts = ar.get_mvmts_in_ar_in_lot_date_order(&account_map, &transactions_map); let mut amts = d128!(0); for mvmt in mvmts { amts += mvmt.amount; @@ -156,7 +156,7 @@ pub fn test_action_records_amts_vs_mvmt_amts( for ar_num in &txn.action_record_idx_vec { let ar = action_records_map.get(&(ar_num)).unwrap(); - let mvmts = ar.get_mvmts_in_ar_in_date_order(&account_map, &transactions_map); + let mvmts = ar.get_mvmts_in_ar_in_lot_date_order(&account_map, &transactions_map); for mvmt in mvmts { mvmt_amt_ar += mvmt.amount }