finql_data/
transaction.rs

1///! Implementation of basic transaction types
2
3use serde::{Deserialize, Serialize};
4use super::{DataError, DataItem};
5use crate::cash_flow::CashFlow;
6
7/// Type of transaction
8#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
9pub enum TransactionType {
10    Cash,
11    Asset { asset_id: usize, position: f64 },
12    Dividend { asset_id: usize },
13    Interest { asset_id: usize },
14    Tax { transaction_ref: Option<usize> },
15    Fee { transaction_ref: Option<usize> },
16}
17
18/// Basic transaction data
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Transaction {
21    // Before a transaction is stored to a database, the id maybe None
22    pub id: Option<usize>,
23    pub transaction_type: TransactionType,
24    pub cash_flow: CashFlow,
25    pub note: Option<String>,
26}
27
28impl Transaction {
29    /// Assign or change transaction's asset_id, if possible
30    /// This is often required for transactions on new assets
31    pub fn set_asset_id(&mut self, asset_id: usize) {
32        self.transaction_type = match self.transaction_type {
33            TransactionType::Asset {
34                asset_id: _,
35                position,
36            } => TransactionType::Asset { asset_id, position },
37            TransactionType::Dividend { asset_id: _ } => TransactionType::Dividend { asset_id },
38            TransactionType::Interest { asset_id: _ } => TransactionType::Interest { asset_id },
39            _ => self.transaction_type,
40        }
41    }
42
43    /// Assign new transaction reference, if applicable
44    pub fn set_transaction_ref(&mut self, trans_ref: usize) {
45        self.transaction_type = match self.transaction_type {
46            TransactionType::Tax { transaction_ref: _ } => TransactionType::Tax {
47                transaction_ref: Some(trans_ref),
48            },
49            TransactionType::Fee { transaction_ref: _ } => TransactionType::Fee {
50                transaction_ref: Some(trans_ref),
51            },
52            _ => self.transaction_type,
53        }
54    }
55}
56
57impl DataItem for Transaction {
58    // get id or return error if id hasn't been set yet
59    fn get_id(&self) -> Result<usize, DataError> {
60        match self.id {
61            Some(id) => Ok(id),
62            None => Err(DataError::DataAccessFailure(
63                "tried to get id of temporary transaction".to_string(),
64            )),
65        }
66    }
67    // set id or return error if id has already been set
68    fn set_id(&mut self, id: usize) -> Result<(), DataError> {
69        match self.id {
70            Some(_) => Err(DataError::DataAccessFailure(
71                "tried to change valid transaction id".to_string(),
72            )),
73            None => {
74                self.id = Some(id);
75                Ok(())
76            }
77        }
78    }
79}