Merged dg2 branch which tracked changed related to preserving historical cost basis and proceeds that are changed as a result of like-kind treatment.

This commit is contained in:
scoobybejesus 2019-09-21 13:57:16 -04:00
parent 46b764df3a
commit 8c62211b64
7 changed files with 594 additions and 148 deletions

View File

@ -52,11 +52,21 @@ impl Account {
total_amount
}
pub fn get_sum_of_basis_in_lots(&self) -> d128 {
pub fn get_sum_of_lk_basis_in_lots(&self) -> d128 {
let lots = self.list_of_lots.borrow();
let mut total_amount = d128!(0);
for lot in lots.iter() {
let sum = lot.get_sum_of_basis_in_lot();
let sum = lot.get_sum_of_lk_basis_in_lot();
total_amount += sum;
}
total_amount
}
pub fn get_sum_of_orig_basis_in_lots(&self) -> d128 {
let lots = self.list_of_lots.borrow();
let mut total_amount = d128!(0);
for lot in lots.iter() {
let sum = lot.get_sum_of_orig_basis_in_lot();
total_amount += sum;
}
total_amount
@ -87,7 +97,13 @@ impl Lot {
// d128!(0) == Self::get_sum_of_amts_in_lot(&self)
// }
pub fn get_sum_of_basis_in_lot(&self) -> d128 {
pub fn get_sum_of_lk_basis_in_lot(&self) -> d128 {
let mut amts = d128!(0);
self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis_lk.get());
amts
}
pub fn get_sum_of_orig_basis_in_lot(&self) -> d128 {
let mut amts = d128!(0);
self.movements.borrow().iter().for_each(|movement| amts += movement.cost_basis.get());
amts
@ -106,6 +122,8 @@ pub struct Movement {
pub ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell<d128>, // Set in wrap_mvmt_and_push()
pub lot_num: u32,
pub proceeds: Cell<d128>, // Initialized with 0. Set in add_proceeds_to_movements()
pub proceeds_lk: Cell<d128>,
pub cost_basis_lk: Cell<d128>,
}
impl Movement {
@ -126,17 +144,67 @@ impl Movement {
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> d128 {
// println!("Lot #: {}", self.lot.lot_number);
let ar = ar_map.get(&self.action_record_key).unwrap();
let acct = acct_map.get(&ar.account_key).unwrap();
let lot = &acct.list_of_lots.borrow()[self.lot_num as usize - 1]; // lots start at 1 and indexes at 0
let borrowed_mvmt_list = lot.movements.borrow();
let ratio = self.amount / borrowed_mvmt_list.first().unwrap().amount;
// println!("ratio_of_amt_to_lots_first_mvmt: {}", ratio.abs());
// // println!("Lot #: {}", self.lot.lot_number);
// let ar = ar_map.get(&self.action_record_key).unwrap();
// let acct = acct_map.get(&ar.account_key).unwrap();
// let lot = &acct.list_of_lots.borrow()[self.lot_num as usize - 1]; // lots start at 1 and indexes at 0
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
let ratio = self.amount / list_of_lot_mvmts.first().unwrap().amount;
ratio.abs()
}
pub fn get_gain_or_loss(&self) -> d128 {
pub fn get_lk_cost_basis_of_lots_first_mvmt(
&self,
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> d128 {
// let ar = ar_map.get(&self.action_record_key).unwrap();
// let acct = acct_map.get(&ar.account_key).unwrap();
// let lot = &acct.list_of_lots.borrow()[self.lot_num as usize - 1]; // lots start at 1 and indexes at 0
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
let cost_basis_lk = list_of_lot_mvmts.first().unwrap().cost_basis_lk.get();
cost_basis_lk
}
pub fn get_cost_basis_of_lots_first_mvmt(
&self,
acct_map: &HashMap<u16, Account>,
ar_map: &HashMap<u32, ActionRecord>
) -> d128 {
// let ar = ar_map.get(&self.action_record_key).unwrap();
// let acct = acct_map.get(&ar.account_key).unwrap();
// let lot = &acct.list_of_lots.borrow()[self.lot_num as usize - 1]; // lots start at 1 and indexes at 0
// let borrowed_mvmt_list = lot.movements.borrow();
let lot = self.get_lot(acct_map, ar_map);
let list_of_lot_mvmts = lot.movements.borrow();
let cost_basis = list_of_lot_mvmts.first().unwrap().cost_basis.get();
cost_basis
}
// pub fn get_lk_proceeds_of_lots_first_mvmt(
// &self,
// acct_map: &HashMap<u16, Account>,
// ar_map: &HashMap<u32, ActionRecord>
// ) -> d128 {
// let ar = ar_map.get(&self.action_record_key).unwrap();
// let acct = acct_map.get(&ar.account_key).unwrap();
// let lot = &acct.list_of_lots.borrow()[self.lot_num as usize - 1]; // lots start at 1 and indexes at 0
// let borrowed_mvmt_list = lot.movements.borrow();
// let proceeds_lk = borrowed_mvmt_list.first().unwrap().proceeds_lk.get();
// proceeds_lk
// }
pub fn get_lk_gain_or_loss(&self) -> d128 { // Returns proceeds*2 for Incoming+Flow txns
self.proceeds_lk.get() + self.cost_basis_lk.get()
}
pub fn get_orig_gain_or_loss(&self) -> d128 { // Returns proceeds*2 for Incoming+Flow txns
self.proceeds.get() + self.cost_basis.get()
}
@ -147,19 +215,27 @@ impl Movement {
let lot = Self::get_lot(&self, acct_map, ar_map);
match ar.direction() {
Polarity::Incoming => {
let today = Utc::now();
let utc_lot_date = Self::create_date_time_from_atlantic(lot.date_for_basis_purposes, NaiveTime::from_hms_milli(12, 34, 56, 789));
let utc_lot_date = Self::create_date_time_from_atlantic(
lot.date_for_basis_purposes,
NaiveTime::from_hms_milli(12, 34, 56, 789)
);
// if today.signed_duration_since(self.lot.date_for_basis_purposes) > 365
if (today - utc_lot_date) > Duration::days(365) { // TODO: figure out how to instantiate today's date and convert it to compare to NaiveDate
if (today - utc_lot_date) > Duration::days(365) {
// TODO: figure out how to instantiate today's date and convert it to compare to NaiveDate
Term::LT
}
else {
Term::ST
}
}
Polarity::Outgoing => {
let lot_date_for_basis_purposes = lot.date_for_basis_purposes;
if self.date.signed_duration_since(lot_date_for_basis_purposes) > Duration::days(365) {
return Term::LT
}
@ -169,8 +245,10 @@ impl Movement {
}
pub fn create_date_time_from_atlantic(date: NaiveDate, time: NaiveTime) -> DateTime<Utc> {
let naive_datetime = NaiveDateTime::new(date, time);
let east_time = Eastern.from_local_datetime(&naive_datetime).unwrap();
east_time.with_timezone(&Utc)
}
@ -184,11 +262,15 @@ impl Movement {
)-> Result<d128, Box<dyn Error>> { // Returns 0 or positive number
let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?");
match txn.transaction_type(ar_map, raw_accts, acct_map)? {
TxType::Flow => {
let ar = ar_map.get(&self.action_record_key).unwrap();
if ar.direction() == Polarity::Incoming {
Ok(self.proceeds.get())
Ok(-self.proceeds_lk.get())
}
else { Ok(d128!(0)) }
}
@ -206,11 +288,15 @@ impl Movement {
)-> Result<d128, Box<dyn Error>> { // Returns 0 or negative number
let txn = txns_map.get(&self.transaction_key).expect("Couldn't get txn. Tx num invalid?");
match txn.transaction_type(ar_map, raw_accts, acct_map)? {
TxType::Flow => {
let ar = ar_map.get(&self.action_record_key).unwrap();
if ar.direction() == Polarity::Outgoing {
let expense = -self.proceeds.get();
let expense = -self.proceeds_lk.get();
Ok(expense)
}
else { Ok(d128!(0)) }

View File

@ -136,6 +136,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: base_lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(base_mvmt, &base_ar, &base_lot, &settings, &raw_acct_map, &acct_map);
@ -150,6 +152,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: quote_lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(quote_mvmt, &quote_ar, &quote_lot, &settings, &raw_acct_map, &acct_map);
@ -191,6 +195,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(whole_mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
acct.list_of_lots.borrow_mut().push(lot);
@ -210,6 +216,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(whole_mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
continue
@ -239,6 +247,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(whole_mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
continue
@ -326,6 +336,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot_to_use.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
fit_into_lots(
@ -365,6 +377,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
continue
@ -395,6 +409,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
} else {
assert_eq!(txn.action_record_idx_vec.len(), 2);
@ -451,6 +467,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: inner_lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(inner_mvmt, &ar, &inner_lot, &settings, &raw_acct_map, &acct_map);
acct.list_of_lots.borrow_mut().push(inner_lot);
@ -483,6 +501,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
}
wrap_mvmt_and_push(mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
@ -539,6 +559,8 @@ pub fn create_lots_and_movements(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(whole_mvmt, &ar, &lot, &settings, &raw_acct_map, &acct_map);
acct.list_of_lots.borrow_mut().push(lot);
@ -693,6 +715,8 @@ fn fit_into_lots(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: newly_chosen_lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
fit_into_lots(
txn_num,
@ -710,8 +734,6 @@ fn fit_into_lots(
}
assert!(sum_of_mvmts_in_lot > d128!(0.0));
let remainder_amt = mvmt_to_fit.amount;
// println!("Sum of mvmts in lot: {}; Remainder amount: {}; Net: {}",
// sum_of_mvmts_in_lot, remainder_amt, sum_of_mvmts_in_lot + remainder_amt);
let does_remainder_fit: bool = (sum_of_mvmts_in_lot + remainder_amt) >= d128!(0.0);
@ -727,6 +749,8 @@ fn fit_into_lots(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(remainder_that_fits, &spawning_ar, &lot, &settings, &raw_acct_map, &acct_map);
return // And we're done
@ -746,6 +770,8 @@ fn fit_into_lots(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
wrap_mvmt_and_push(mvmt_that_fits_in_lot, &spawning_ar, &lot, &settings, &raw_acct_map, &acct_map);
let remainder_amt_to_recurse = remainder_amt + sum_of_mvmts_in_lot;
@ -765,6 +791,8 @@ fn fit_into_lots(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)), // This acts as a dummy value.
lot_num: newly_chosen_lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
assert!(current_index_position < vec_of_ordered_index_values.len());
fit_into_lots(
@ -841,6 +869,8 @@ fn process_multiple_incoming_lots_and_mvmts(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// println!("From first set of incoming movements, amount: {} {} to account: {}",
// incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num);
@ -878,6 +908,8 @@ fn process_multiple_incoming_lots_and_mvmts(
ratio_of_amt_to_outgoing_mvmts_in_a_r: Cell::new(d128!(1.0)),
lot_num: lot.lot_number,
proceeds: Cell::new(d128!(0.0)),
proceeds_lk: Cell::new(d128!(0.0)),
cost_basis_lk: Cell::new(d128!(0.0)),
};
// println!("Final incoming mvmt for this actionrecord, amount: {} {} to account: {}",
// incoming_mvmt.amount, acct_incoming_ar.ticker, acct_incoming_ar.account_num);

View File

@ -46,23 +46,23 @@ pub fn _1_account_sums_to_csv(
} else { balance = tentative_balance.to_string() }
let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap();
let cost_basis: String;
let lk_cost_basis: String;
if raw_acct.is_margin { cost_basis = "0.00".to_string() } else {
let tentative_cost_basis = acct.get_sum_of_basis_in_lots();
if tentative_cost_basis == d128!(0) {
cost_basis = "0.00".to_string()
} else { cost_basis = tentative_cost_basis.to_string() }
if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else {
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
}
row.push(raw_acct.name.to_string());
row.push(balance);
row.push(raw_acct.ticker.to_string());
row.push(cost_basis);
row.push(lk_cost_basis);
row.push(acct.list_of_lots.borrow().len().to_string());
rows.push(row);
}
let file_name = PathBuf::from("1_Acct_Sum_with_cost_basis.csv");
let file_name = PathBuf::from("C1_Acct_Sum_with_cost_basis.csv");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
@ -111,26 +111,102 @@ pub fn _2_account_sums_nonzero_to_csv(
balance = "0.00".to_string()
} else { balance_d128 += tentative_balance; balance = tentative_balance.to_string() }
let cost_basis: String;
let lk_cost_basis: String;
if raw_acct.is_margin { cost_basis = "0.00".to_string() } else {
let tentative_cost_basis = acct.get_sum_of_basis_in_lots();
if tentative_cost_basis == d128!(0) {
cost_basis = "0.00".to_string()
} else { cost_basis = tentative_cost_basis.to_string() }
if raw_acct.is_margin { lk_cost_basis = "0.00".to_string() } else {
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
}
if balance_d128 != d128!(0) {
row.push(name);
row.push(balance);
row.push(raw_acct.ticker.to_string());
row.push(cost_basis);
row.push(lk_cost_basis);
row.push(acct.list_of_lots.borrow().len().to_string());
rows.push(row);
}
}
let file_name = PathBuf::from("2_Acct_Sum_with_nonzero_cost_basis.csv");
let file_name = PathBuf::from("C2_Acct_Sum_with_nonzero_cost_basis.csv");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
let buffer = File::create(full_path).unwrap();
let mut wtr = csv::Writer::from_writer(buffer);
for row in rows.iter() {
wtr.write_record(row).expect("Could not write row to CSV file");
}
wtr.flush().expect("Could not flush Writer, though file should exist and be complete");
}
pub fn _3_account_sums_to_csv_with_orig_basis(
settings: &ImportProcessParameters,
raw_acct_map: &HashMap<u16, RawAccount>,
acct_map: &HashMap<u16, Account>
) {
let mut rows: Vec<Vec<String>> = [].to_vec();
let mut header: Vec<String> = [].to_vec();
header.extend_from_slice(&[
"Account".to_string(),
"Balance".to_string(),
"Ticker".to_string(),
"Orig. Cost Basis".to_string(),
"LK Cost Basis".to_string(),
"Total lots".to_string(),
]);
rows.push(header);
let length = acct_map.len();
for j in 1..=length {
let acct = acct_map.get(&(j as u16)).unwrap();
let mut row: Vec<String> = [].to_vec();
let balance: String;
let tentative_balance = acct.get_sum_of_amts_in_lots();
if tentative_balance == d128!(0) {
balance = "0.00".to_string()
} else { balance = tentative_balance.to_string() }
let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap();
let lk_cost_basis: String;
let orig_cost_basis: String;
if raw_acct.is_margin {
lk_cost_basis = "0.00".to_string();
orig_cost_basis = "0.00".to_string();
} else {
let tentative_lk_cost_basis = acct.get_sum_of_lk_basis_in_lots();
let tentative_orig_cost_basis = acct.get_sum_of_orig_basis_in_lots();
if tentative_lk_cost_basis == d128!(0) {
lk_cost_basis = "0.00".to_string()
} else { lk_cost_basis = tentative_lk_cost_basis.to_string() }
if tentative_orig_cost_basis == d128!(0) {
orig_cost_basis = "0.00".to_string()
} else { orig_cost_basis = tentative_orig_cost_basis.to_string() }
}
row.push(raw_acct.name.to_string());
row.push(balance);
row.push(raw_acct.ticker.to_string());
row.push(orig_cost_basis);
row.push(lk_cost_basis);
row.push(acct.list_of_lots.borrow().len().to_string());
rows.push(row);
}
let file_name = PathBuf::from("C3_Acct_Sum_with_orig_and_lk_cost_basis.csv");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
@ -197,15 +273,15 @@ pub fn _4_transaction_mvmt_detail_to_csv(
amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example
let ticker = raw_acct.ticker.to_string();
let term = mvmt.get_term(acct_map, ars).to_string();
let mut proceeds = mvmt.proceeds.get();
let mut cost_basis = mvmt.cost_basis.get();
let mut gain_loss = mvmt.get_gain_or_loss();
let mut proceeds_lk = mvmt.proceeds_lk.get();
let mut cost_basis_lk = mvmt.cost_basis_lk.get();
let mut gain_loss = mvmt.get_lk_gain_or_loss();
let income = mvmt.get_income(ars, &raw_acct_map, &acct_map, &txns_map)?;
let expense = mvmt.get_expense(ars, &raw_acct_map, &acct_map, &txns_map)?;
if tx_type == TxType::Flow && amount > d128!(0) {
proceeds = d128!(0);
cost_basis = d128!(0);
proceeds_lk = d128!(0);
cost_basis_lk = d128!(0);
gain_loss = d128!(0);
}
@ -218,8 +294,8 @@ pub fn _4_transaction_mvmt_detail_to_csv(
row.push(amount.to_string());
row.push(ticker);
row.push(term);
row.push(proceeds.to_string());
row.push(cost_basis.to_string());
row.push(proceeds_lk.to_string());
row.push(cost_basis_lk.to_string());
row.push(gain_loss.to_string());
row.push(income.to_string());
row.push(expense.to_string());
@ -227,7 +303,7 @@ pub fn _4_transaction_mvmt_detail_to_csv(
}
}
let file_name = PathBuf::from("4_Txns_mvmts_detail.csv");
let file_name = PathBuf::from("C4_Txns_mvmts_detail.csv");
let path = PathBuf::from(&settings.export_path);
let full_path: PathBuf = [path, file_name].iter().collect();
@ -324,8 +400,8 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
if term == Term::LT {
amount_lt += mvmt.amount;
proceeds_lt += mvmt.proceeds.get();
cost_basis_lt += mvmt.cost_basis.get();
proceeds_lt += mvmt.proceeds_lk.get();
cost_basis_lt += mvmt.cost_basis_lk.get();
match term_lt {
None => { term_lt = Some(term)}
_ => {}
@ -333,8 +409,8 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
} else {
assert_eq!(term, Term::ST);
amount_st += mvmt.amount;
proceeds_st += mvmt.proceeds.get();
cost_basis_st += mvmt.cost_basis.get();
proceeds_st += mvmt.proceeds_lk.get();
cost_basis_st += mvmt.cost_basis_lk.get();
if term_st == None {
term_st = Some(term);
}
@ -346,10 +422,10 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
&raw_acct_map,
&acct_map)? == TxType::Flow
) & (polarity == Some(Polarity::Incoming)) {
income_st = proceeds_st;
income_st = -proceeds_st; // Proceeds are negative for incoming txns
proceeds_st = d128!(0);
cost_basis_st = d128!(0);
income_lt = proceeds_lt;
income_lt = -proceeds_lt; // Proceeds are negative for incoming txns
proceeds_lt = d128!(0);
cost_basis_lt = d128!(0);
}
@ -403,7 +479,118 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
}
}
let file_name = PathBuf::from("5_Txns_mvmts_summary.csv");
let file_name = PathBuf::from("C5_Txns_mvmts_summary.csv");
let path = PathBuf::from(&settings.export_path);
let full_path: PathBuf = [path, file_name].iter().collect();
let buffer = File::create(full_path).unwrap();
let mut wtr = csv::Writer::from_writer(buffer);
for row in rows.iter() {
wtr.write_record(row).expect("Could not write row to CSV file");
}
wtr.flush().expect("Could not flush Writer, though file should exist and be complete");
Ok(())
}
pub fn _6_transaction_mvmt_detail_to_csv_w_orig(
settings: &ImportProcessParameters,
ars: &HashMap<u32, ActionRecord>,
raw_acct_map: &HashMap<u16, RawAccount>,
acct_map: &HashMap<u16, Account>,
txns_map: &HashMap<u32, Transaction>,
) -> Result<(), Box<dyn Error>> {
let mut rows: Vec<Vec<String>> = [].to_vec();
let mut header: Vec<String> = [].to_vec();
header.extend_from_slice(&[
"Date".to_string(),
"Txn#".to_string(),
"Type".to_string(),
"Memo".to_string(),
"Amount".to_string(),
"Ticker".to_string(),
"Term".to_string(),
"Proceeds".to_string(),
"Cost basis".to_string(),
"Gain/loss".to_string(),
"Income".to_string(),
"Expense".to_string(),
"Orig. Proceeds".to_string(),
"Orig. Cost basis".to_string(),
"Orig. Gain/loss".to_string(),
]);
rows.push(header);
let length = txns_map.len();
for txn_num in 1..=length {
let txn_num = txn_num as u32;
let txn = txns_map.get(&(txn_num)).unwrap();
let flow_or_outgoing_exchange_movements = txn.get_outgoing_exchange_and_flow_mvmts(
&settings.home_currency,
ars,
raw_acct_map,
acct_map,
txns_map
)?;
for mvmt in flow_or_outgoing_exchange_movements.iter() {
let lot = mvmt.get_lot(acct_map, ars);
let acct = acct_map.get(&lot.account_key).unwrap();
let raw_acct = raw_acct_map.get(&acct.raw_key).unwrap();
let date = txn.date.format("%Y/%m/%d").to_string();
let tx_number = txn.tx_number.to_string();
let tx_type = txn.transaction_type(&ars, &raw_acct_map, &acct_map)?;
let memo = txn.memo.to_string();
let mut amount = d128!(0);
amount += mvmt.amount; // To prevent printing -5E+1 instead of 50, for example
let ticker = raw_acct.ticker.to_string();
let term = mvmt.get_term(acct_map, ars).to_string();
let mut proceeds_lk = mvmt.proceeds_lk.get();
let mut cost_basis_lk = mvmt.cost_basis_lk.get();
let mut gain_loss = mvmt.get_lk_gain_or_loss();
let income = mvmt.get_income(ars, &raw_acct_map, &acct_map, &txns_map)?;
let expense = mvmt.get_expense(ars, &raw_acct_map, &acct_map, &txns_map)?;
let mut orig_proc = mvmt.proceeds.get();
let mut orig_cost = mvmt.cost_basis.get();
let mut orig_gain_loss = mvmt.get_orig_gain_or_loss();
if tx_type == TxType::Flow && amount > d128!(0) {
proceeds_lk = d128!(0);
cost_basis_lk = d128!(0);
gain_loss = d128!(0);
orig_proc = d128!(0);
orig_cost = d128!(0);
orig_gain_loss = d128!(0);
}
let mut row: Vec<String> = [].to_vec();
row.push(date);
row.push(tx_number);
row.push(tx_type.to_string());
row.push(memo);
row.push(amount.to_string());
row.push(ticker);
row.push(term);
row.push(proceeds_lk.to_string());
row.push(cost_basis_lk.to_string());
row.push(gain_loss.to_string());
row.push(income.to_string());
row.push(expense.to_string());
row.push(orig_proc.to_string());
row.push(orig_cost.to_string());
row.push(orig_gain_loss.to_string());
rows.push(row);
}
}
let file_name = PathBuf::from("C6_Txns_mvmts_detail_w_orig.csv");
let path = PathBuf::from(&settings.export_path);
let full_path: PathBuf = [path, file_name].iter().collect();
@ -465,7 +652,7 @@ pub fn _5_transaction_mvmt_summaries_to_csv(
// row.push(txn.transaction_type(ars, &raw_acct_map, &acct_map).to_string());
// row.push(txn.memo.to_string());
// row.push(mvmt.amount.to_string());
// row.push(mvmt.proceeds.get().to_string());
// row.push(mvmt.proceeds_lk.get().to_string());
// row.push(mvmt.cost_basis.get().to_string());
// row.push(mvmt.get_gain_or_loss().to_string());
// row.push(mvmt.get_term(acct_map, ars).to_string());

View File

@ -137,6 +137,7 @@ pub fn import_transactions(
let mut this_proceeds: &str = "";
let mut this_memo: &str = "";
let mut this: String;
let mut proceeds_parsed = 0f32;
// Next, create action_records.
let mut action_records_map_keys_vec: Vec<u32> = [].to_vec();
@ -152,6 +153,7 @@ pub fn import_transactions(
else if idx == 1 {
this = field.replace(",", "");
this_proceeds = this.as_str();
proceeds_parsed = this_proceeds.parse::<f32>()?;
}
else if idx == 2 { this_memo = field; }
@ -213,7 +215,7 @@ pub fn import_transactions(
date_as_string: this_tx_date.to_string(),
date: tx_date,
memo: this_memo.to_string(),
proceeds: this_proceeds.parse::<f32>()?,
proceeds: proceeds_parsed,
action_record_idx_vec: action_records_map_keys_vec,
};

View File

@ -44,36 +44,52 @@ pub fn add_cost_basis_to_movements(
// println!("Txn: {} on {} of type: {:?}",txn.tx_number,txn.date, txn.transaction_type());
if !raw_acct.is_margin {
match polarity {
Polarity::Outgoing => {
if is_home_curr {
let mvmts_amt = mvmt_copy.amount;
mvmt.cost_basis.set(mvmts_amt);
mvmt.cost_basis_lk.set(mvmts_amt);
} else {
let mvmt_lot = mvmt_copy.get_lot(acct_map, ars);
let borrowed_mvmt_list = mvmt_lot.movements.borrow().clone();
let lots_first_mvmt = borrowed_mvmt_list.first().unwrap().clone();
let cb_of_lots_first_mvmt = lots_first_mvmt.cost_basis.get();
// let mvmt_lot = mvmt_copy.get_lot(acct_map, ars);
// let borrowed_mvmt_list = mvmt_lot.movements.borrow().clone();
// let lots_first_mvmt = borrowed_mvmt_list.first().unwrap().clone();
// let cb_of_lots_first_mvmt = lots_first_mvmt.cost_basis.get();
let cb_of_lots_first_mvmt = mvmt_copy.get_cost_basis_of_lots_first_mvmt(acct_map, ars);
let ratio_of_amt_to_lots_first_mvmt = borrowed_mvmt.ratio_of_amt_to_lots_first_mvmt(acct_map, ars);
let unrounded_basis = -(cb_of_lots_first_mvmt * ratio_of_amt_to_lots_first_mvmt);
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(rounded_basis);
// if txn.tx_number == 5 {
// println!("Txn#: {}, ratio: {}, cb of lot's 1st mvmt: {}, cost basis: {}", txn.tx_number, ratio_of_amt_to_lots_first_mvmt, cb_of_lots_first_mvmt, cost_basis)
// };
mvmt.cost_basis_lk.set(rounded_basis);
}
// println!("Outgoing a_r from txn: {} of type: {:?}, with {} {} with cost basis: {}",
// txn.tx_number, txn.transaction_type(), borrowed_mvmt.amount, ar.account.ticker, cost_basis);
assert!(mvmt.cost_basis.get() <= d128!(0));
// assert!(mvmt.cost_basis_lk.get() <= d128!(0)); // Same as above assert.
continue
}
Polarity::Incoming => {
if is_home_curr {
let mvmts_amt = mvmt_copy.amount;
mvmt.cost_basis.set(mvmts_amt);
mvmt.cost_basis_lk.set(mvmts_amt);
} else {
match tx_type {
TxType::Exchange => {
let other_ar = ars.get(&txn.action_record_idx_vec[0]).unwrap();
let other_acct = acct_map.get(&other_ar.account_key).unwrap();
let raw_other_acct = raw_acct_map.get(&other_acct.raw_key).unwrap();
@ -82,42 +98,66 @@ pub fn add_cost_basis_to_movements(
if other_ar_is_home_curr {
mvmt.cost_basis.set(-(other_ar.amount));
mvmt.cost_basis_lk.set(-(other_ar.amount));
} else {
let ratio_of_amt_to_incoming_mvmts_in_a_r =
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r;
let txn_proceeds = txn.proceeds.to_string().parse::<d128>().unwrap();
let unrounded_basis = txn_proceeds * ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(rounded_basis);
}
}
TxType::ToSelf => {
let cb_outgoing_ar = retrieve_cost_basis_from_corresponding_outgoing_toself(
txn_num, &ars, txns_map, acct_map);
let ratio_of_amt_to_incoming_mvmts_in_a_r = borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r;
let this_ratio = (ratio_of_amt_to_incoming_mvmts_in_a_r)
let txn_proceeds = txn.proceeds
.to_string()
.parse::<d128>()
.unwrap();
let unrounded_basis = cb_outgoing_ar * this_ratio;
let unrounded_basis = txn_proceeds * ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(rounded_basis);
mvmt.cost_basis_lk.set(rounded_basis);
}
}
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(
txn_num,
&ars,
txns_map,
acct_map
);
// let this_ratio = ratio_of_amt_to_incoming_mvmts_in_a_r
// .to_string()
// .parse::<d128>()
// .unwrap(); // I don't recall why this was once needed in the next line.
let unrounded_basis = cb_outgoing_ar * ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(-rounded_basis);
mvmt.cost_basis_lk.set(-rounded_basis);
}
TxType::Flow => {
let txn_proceeds = txn.proceeds.to_string().parse::<d128>().unwrap();
let mvmt_proceeds = round_d128_1e2(&(txn_proceeds *
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r));
let mvmt_proceeds = round_d128_1e2(
&(txn_proceeds *
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r)
); // Ratio should always be 1.0, but we do the calc anyway, for future-proofing.
mvmt.cost_basis.set(mvmt_proceeds);
mvmt.cost_basis_lk.set(mvmt_proceeds);
}
}
}
// println!("Incoming a_r from txn: {} of type: {:?}, with {} {} with cost basis: {}",
// txn.tx_number, txn.transaction_type(), borrowed_mvmt.amount, ar.account.ticker, cost_basis);
assert!(mvmt.cost_basis.get() >= d128!(0));
// assert!(mvmt.cost_basis_lk.get() >= d128!(0)); // Same as above assert.
continue
}
}
} else {
// Do nothing. Future changes can add a code path where margin txns "settle"
// as they happen, though, if desired. Just need to write the code.
}
}
}
@ -174,27 +214,46 @@ pub fn add_proceeds_to_movements(
let borrowed_mvmt = mvmt_copy.clone();
match tx_type {
TxType::Exchange => {
TxType::Exchange | TxType::Flow => {
match polarity {
Polarity::Outgoing => {
let ratio = borrowed_mvmt.amount / ar.amount;
let proceeds_unrounded = txn.proceeds.to_string().parse::<d128>().unwrap() * ratio;
let proceeds_rounded = round_d128_1e2(&proceeds_unrounded);
mvmt.proceeds.set(proceeds_rounded);
mvmt.proceeds_lk.set(proceeds_rounded);
}
Polarity::Incoming => {}
Polarity::Incoming => {
// For a time, this was blank. As part of the commit(s) to add cost_basis_lk
// and proceeds_lk, let's change this to reflect that incoming proceeds are now
// negative, which net against the positive cost_basis to result in a gain of $0.
// Additionally, we apply the same treatment to Flow txns.
mvmt.proceeds.set(-mvmt.cost_basis.get());
mvmt.proceeds_lk.set(-mvmt.cost_basis_lk.get());
}
}
TxType::Flow => {
let ratio = borrowed_mvmt.amount / ar.amount;
let proceeds_unrounded = txn.proceeds.to_string().parse::<d128>().unwrap() * ratio;
let proceeds_rounded = round_d128_1e2(&proceeds_unrounded);
mvmt.proceeds.set(proceeds_rounded);
}
TxType::ToSelf => {}
// TxType::Flow => {
// let ratio = borrowed_mvmt.amount / ar.amount;
// let proceeds_unrounded = txn.proceeds.to_string().parse::<d128>().unwrap() * ratio;
// let proceeds_rounded = round_d128_1e2(&proceeds_unrounded);
// mvmt.proceeds.set(proceeds_rounded);
// }
TxType::ToSelf => {
// Originally did nothing. Now explicity creating a condition where a report containing
// ToSelf txns would reflect a $0 gain/loss.
mvmt.proceeds.set(-mvmt.cost_basis.get());
mvmt.proceeds_lk.set(-mvmt.cost_basis_lk.get());
}
}
// println!("Txn: {}, type: {:?} of {} {} w/ proceeds: {} & basis: {}",
// txn.tx_number, txn.transaction_type(), borrowed_mvmt.amount, ar.account.ticker, proceeds, borrowed_mvmt.cost_basis);
}
}
}
@ -222,6 +281,9 @@ pub fn apply_like_kind_treatment(
if txn.date <= cutoff_date {
perform_likekind_treatment_on_txn(txn_num, &settings, &ars, &raw_acct_map, &acct_map, &txns_map)?;
}
// else {
// // carry_forward_deferred_gains(txn_num, &settings, &ars, &raw_acct_map, &acct_map, &txns_map)?;
// }
}
Ok(())
@ -236,7 +298,7 @@ fn update_current_txn_for_prior_likekind_treatment(
txns_map: &HashMap<u32, Transaction>,
) -> Result<(), Box<dyn Error>> {
let mut sum_of_outgoing_cost_basis_in_ar = d128!(0);
let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0);
let txn = txns_map.get(&txn_num).unwrap();
for ar_num in txn.action_record_idx_vec.iter() {
@ -256,31 +318,58 @@ fn update_current_txn_for_prior_likekind_treatment(
let borrowed_mvmt = mvmt_copy.clone();
if !raw_acct.is_margin {
match polarity {
Polarity::Outgoing => {
if !is_home_curr {
let borrowed_mvmt_lot = borrowed_mvmt.get_lot(acct_map, ars);
let borrowed_mvmt_list = borrowed_mvmt_lot.movements.borrow();
let cb_of_lots_first_mvmt = borrowed_mvmt_list.first().unwrap().cost_basis.get();
// let borrowed_mvmt_lot = borrowed_mvmt.get_lot(acct_map, ars);
// let borrowed_mvmt_list = borrowed_mvmt_lot.movements.borrow();
// let lk_cb_of_lots_first_mvmt = borrowed_mvmt_list.first().unwrap().cost_basis_lk.get();
let lk_cb_of_lots_first_mvmt = borrowed_mvmt.get_lk_cost_basis_of_lots_first_mvmt(acct_map, ars);
let ratio_of_amt_to_lots_first_mvmt = borrowed_mvmt.ratio_of_amt_to_lots_first_mvmt(acct_map, ars);
let unrounded_basis = -(cb_of_lots_first_mvmt * ratio_of_amt_to_lots_first_mvmt);
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(rounded_basis);
let unrounded_lk_basis = -(lk_cb_of_lots_first_mvmt * ratio_of_amt_to_lots_first_mvmt);
let rounded_lk_basis = round_d128_1e2(&unrounded_lk_basis);
mvmt.cost_basis_lk.set(rounded_lk_basis);
if tx_type == TxType::ToSelf {
mvmt.proceeds_lk.set(-rounded_lk_basis)
}
sum_of_outgoing_cost_basis_in_ar += mvmt.cost_basis.get()
}
sum_of_outgoing_lk_cost_basis_in_ar += mvmt.cost_basis_lk.get()
}
Polarity::Incoming => {
match tx_type {
TxType::Exchange => {}
TxType::Flow => {}
TxType::Exchange => {
// Do nothing.
// If txn.date is after the LK treatment date, the incoming mvmt goes untreated.
// If txn.date is before the LK date, incoming mvmt gets treatment in apply_lk_treatment next.
}
TxType::Flow => {
if txn.action_record_idx_vec.len() == 2 {
mvmt.cost_basis_lk.set(d128!(0));
mvmt.proceeds_lk.set(d128!(0));
}
// Do nothing for non-margin txns.
}
TxType::ToSelf => {
if !is_home_curr {
let ratio_of_amt_to_incoming_mvmts_in_a_r =
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r;
let unrounded_basis = sum_of_outgoing_cost_basis_in_ar *
let unrounded_lk_basis = sum_of_outgoing_lk_cost_basis_in_ar *
ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(-rounded_basis);
let rounded_lk_basis = round_d128_1e2(&unrounded_lk_basis);
mvmt.cost_basis_lk.set(-rounded_lk_basis);
mvmt.proceeds_lk.set(rounded_lk_basis);
}
}
}
@ -305,6 +394,10 @@ fn perform_likekind_treatment_on_txn(
let txn = txns_map.get(&txn_num).unwrap();
let tx_type = txn.transaction_type(ars, raw_acct_map, acct_map)?;
match tx_type {
TxType::Exchange => {
let og_ar = ars.get(&txn.action_record_idx_vec.first().unwrap()).unwrap();
let ic_ar = ars.get(&txn.action_record_idx_vec.last().unwrap()).unwrap();
let og_acct = acct_map.get(&og_ar.account_key).unwrap();
@ -312,20 +405,15 @@ fn perform_likekind_treatment_on_txn(
let raw_og_acct = raw_acct_map.get(&og_acct.raw_key).unwrap();
let raw_ic_acct = raw_acct_map.get(&ic_acct.raw_key).unwrap();
fn both_are_non_home_curr(raw_og_acct: &RawAccount, raw_ic_acct: &RawAccount, settings: &ImportProcessParameters) -> bool {
let og_is_home_curr = raw_og_acct.is_home_currency(&settings.home_currency);
let ic_is_home_curr = raw_ic_acct.is_home_currency(&settings.home_currency);
let both_are_non_home_curr = !ic_is_home_curr && !og_is_home_curr;
both_are_non_home_curr
}
if _both_are_non_home_curr(raw_og_acct, raw_ic_acct, settings) {
let mut sum_of_outgoing_lk_cost_basis_in_ar = d128!(0);
match tx_type {
TxType::Exchange => {
if both_are_non_home_curr(raw_og_acct, raw_ic_acct, settings) {
let mut sum_of_outgoing_cost_basis_in_ar = d128!(0);
for ar_num in txn.action_record_idx_vec.iter() {
let ar = ars.get(ar_num).unwrap();
let movements = ar.get_mvmts_in_ar(acct_map, txns_map);
for mvmt in movements.iter() {
let polarity = ar.direction();
@ -334,26 +422,38 @@ fn perform_likekind_treatment_on_txn(
let borrowed_mvmt = mvmt_copy.clone();
match polarity {
Polarity::Outgoing => {
let cb = borrowed_mvmt.cost_basis.get();
sum_of_outgoing_cost_basis_in_ar += cb;
mvmt.proceeds.set(-cb);
let cb = borrowed_mvmt.cost_basis_lk.get();
sum_of_outgoing_lk_cost_basis_in_ar += cb;
mvmt.proceeds_lk.set(-cb);
}
Polarity::Incoming => {
let ratio_of_amt_to_incoming_mvmts_in_a_r =
borrowed_mvmt.ratio_of_amt_to_incoming_mvmts_in_a_r;
let unrounded_basis = sum_of_outgoing_cost_basis_in_ar *
let unrounded_basis = sum_of_outgoing_lk_cost_basis_in_ar *
ratio_of_amt_to_incoming_mvmts_in_a_r;
let rounded_basis = round_d128_1e2(&unrounded_basis);
mvmt.cost_basis.set(-rounded_basis);
mvmt.cost_basis_lk.set(-rounded_basis);
mvmt.proceeds_lk.set(rounded_basis);
}
}
}
}
}
}
TxType::Flow => {
if txn.action_record_idx_vec.len() == 2 {
// Consider asserting TxHasMargin::OneAR
for ar_num in txn.action_record_idx_vec.iter() {
let ar = ars.get(ar_num).unwrap();
@ -364,7 +464,13 @@ fn perform_likekind_treatment_on_txn(
for mvmt in movements.iter() {
match polarity {
Polarity::Outgoing => {}
Polarity::Outgoing => {
// Do nothing.
// If 'spot' acct outgoing, the loss nets to the basis in the spent coins.
// If margin acct outgoing, no gain, and the incoming gets no cost basis.
}
Polarity::Incoming => {
// Reminder: May need extra logic here if margin exchange trades get cost_basis and proceeds
mvmt.cost_basis.set(d128!(0));
@ -375,7 +481,23 @@ fn perform_likekind_treatment_on_txn(
}
}
}
TxType::ToSelf => {}
TxType::ToSelf => {
// Like-kind "exchange," so do nothing.
}
}
fn _both_are_non_home_curr(
raw_og_acct: &RawAccount,
raw_ic_acct: &RawAccount,
settings: &ImportProcessParameters
) -> bool {
let og_is_home_curr = raw_og_acct.is_home_currency(&settings.home_currency);
let ic_is_home_curr = raw_ic_acct.is_home_currency(&settings.home_currency);
let both_are_non_home_curr = !ic_is_home_curr && !og_is_home_curr;
both_are_non_home_curr
}
Ok(())

View File

@ -275,6 +275,12 @@ fn main() -> Result<(), Box<dyn Error>> {
&raw_acct_map
);
csv_export::_3_account_sums_to_csv_with_orig_basis(
&settings,
&raw_acct_map,
&account_map
);
csv_export::_4_transaction_mvmt_detail_to_csv(
&settings,
&action_records_map,
@ -291,6 +297,14 @@ fn main() -> Result<(), Box<dyn Error>> {
&transactions_map
)?;
csv_export::_6_transaction_mvmt_detail_to_csv_w_orig(
&settings,
&action_records_map,
&raw_acct_map,
&account_map,
&transactions_map
)?;
txt_export::_1_account_lot_detail_to_txt(
&settings,
&raw_acct_map,

View File

@ -9,7 +9,7 @@ use std::io::prelude::Write;
use decimal::d128;
use crate::transaction::{Transaction, ActionRecord, TxType};
use crate::transaction::{Transaction, ActionRecord};
use crate::account::{Account, RawAccount};
use crate::core_functions::{ImportProcessParameters};
@ -60,7 +60,7 @@ pub fn _1_account_lot_detail_to_txt(
let file_name = PathBuf::from("1_Acct_lot_detail.txt");
let file_name = PathBuf::from("T1_Acct_lot_detail.txt");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
@ -99,14 +99,16 @@ Enable like-kind treatment: {}",
writeln!(file, "Account balance: {} {}; Total cost basis: {}",
acct.get_sum_of_amts_in_lots(),
raw_acct.ticker,
acct.get_sum_of_basis_in_lots()
acct.get_sum_of_lk_basis_in_lots()
)?;
} else {
continue
}
if raw_acct.is_margin { writeln!(file, "Margin Account")?; }
for (lot_idx, lot) in acct.list_of_lots.borrow().iter().enumerate() {
let lot_basis = lot.get_sum_of_basis_in_lot();
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let movements_sum = lot.get_sum_of_amts_in_lot();
if acct.list_of_lots.borrow().len() > 0 {
@ -115,7 +117,7 @@ Enable like-kind treatment: {}",
writeln!(file, " Lot {}", (lot_idx+1))?;
writeln!(file, "\t• Σ: {}, with remaining cost basis of {} and basis date of {}",
movements_sum,
lot_basis,
lk_lot_basis,
lot.date_for_basis_purposes
)?;
writeln!(file, "\t Movements:")?;
@ -137,26 +139,27 @@ Enable like-kind treatment: {}",
writeln!(file, "{}", description_str)?;
let proceeds = mvmt.proceeds.get();
let cost_basis = mvmt.cost_basis.get();
let lk_proceeds = mvmt.proceeds_lk.get();
let lk_cost_basis = mvmt.cost_basis_lk.get();
let gain_loss: d128;
if mvmt.amount > d128!(0) { // Can't have a gain on an incoming txn
gain_loss = d128!(0)
} else if raw_acct.is_home_currency(&settings.home_currency) { // Can't have a gain disposing home currency
gain_loss = d128!(0)
} else if tx_type == TxType::ToSelf { // Can't have a gain sending to yourself
// if mvmt.amount > d128!(0) { // Can't have a gain on an incoming txn
// gain_loss = d128!(0)
// } else
if raw_acct.is_home_currency(&settings.home_currency) { // Can't have a gain disposing home currency
gain_loss = d128!(0)
// } else if tx_type == TxType::ToSelf { // Can't have a gain sending to yourself
// gain_loss = d128!(0)
} else {
gain_loss = proceeds + cost_basis
gain_loss = lk_proceeds + lk_cost_basis;
}
let income = mvmt.get_income(ars, raw_acct_map, acct_map, txns_map)?;
let expense = mvmt.get_expense(ars, raw_acct_map, acct_map, txns_map)?;
let activity_str = format!("\t\t\tProceeds: {}; Cost basis: {}; for Gain/loss: {} {}; Inc.: {}; Exp.: {}.",
proceeds,
cost_basis,
lk_proceeds,
lk_cost_basis,
mvmt.get_term(acct_map, ars),
gain_loss,
income,
@ -166,8 +169,8 @@ Enable like-kind treatment: {}",
writeln!(file, "{}", activity_str)?;
// if settings.enable_like_kind_treatment {
// let dg_prev = mvmt.deferred_gain_prev.get();
// let dg_curr = mvmt.deferred_gain_curr.get();
// let dg_prev = mvmt.proceeds_lk.get();
// let dg_curr = mvmt.cost_basis_lk.get();
// let activity_str = format!("\t\t\tGain deferred in this txn: {}; Accumulated in prior txns: {}",
// dg_curr,
@ -205,7 +208,7 @@ pub fn _2_account_lot_summary_to_txt(
let file_name = PathBuf::from("2_Acct_lot_summary.txt");
let file_name = PathBuf::from("T2_Acct_lot_summary.txt");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
@ -244,14 +247,14 @@ Enable like-kind treatment: {}",
writeln!(file, "Account balance: {} {}; Total cost basis: {}",
acct.get_sum_of_amts_in_lots(),
raw_acct.ticker,
acct.get_sum_of_basis_in_lots()
acct.get_sum_of_lk_basis_in_lots()
)?;
}
if raw_acct.is_margin { writeln!(file, "Margin Account")?; }
for (lot_idx, lot) in acct.list_of_lots.borrow().iter().enumerate() {
let lot_basis = lot.get_sum_of_basis_in_lot();
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let movements_sum = lot.get_sum_of_amts_in_lot();
if acct.list_of_lots.borrow().len() > 0 {
@ -259,7 +262,7 @@ Enable like-kind treatment: {}",
writeln!(file, " Lot {} • Σ: {}, with remaining cost basis of {} and basis date of {}",
(lot_idx+1),
movements_sum,
lot_basis,
lk_lot_basis,
lot.date_for_basis_purposes
)?;
}
@ -287,7 +290,7 @@ pub fn _3_account_lot_summary_non_zero_to_txt(
let file_name = PathBuf::from("3_Acct_lot_summary_non_zero.txt");
let file_name = PathBuf::from("T3_Acct_lot_summary_non_zero.txt");
let path = PathBuf::from(&settings.export_path.clone());
let full_path: PathBuf = [path, file_name].iter().collect();
@ -328,7 +331,7 @@ Enable like-kind treatment: {}",
writeln!(file, "Account balance: {} {}; Total cost basis: {}",
amt_in_acct,
raw_acct.ticker,
acct.get_sum_of_basis_in_lots()
acct.get_sum_of_lk_basis_in_lots()
)?;
} else {
continue
@ -338,7 +341,7 @@ Enable like-kind treatment: {}",
for (lot_idx, lot) in acct.list_of_lots.borrow().iter().enumerate() {
let lot_basis = lot.get_sum_of_basis_in_lot();
let lk_lot_basis = lot.get_sum_of_lk_basis_in_lot();
let movements_sum = lot.get_sum_of_amts_in_lot();
if acct.list_of_lots.borrow().len() > 0 {
@ -347,7 +350,7 @@ Enable like-kind treatment: {}",
writeln!(file, " Lot {} • Σ: {}, with remaining cost basis of {} and basis date of {}",
(lot_idx+1),
movements_sum,
lot_basis,
lk_lot_basis,
lot.date_for_basis_purposes
)?;
}