extern crate arrayvec;
extern crate chrono;
extern crate commodity;
extern crate nanoid;
extern crate rust_decimal;
extern crate thiserror;
#[cfg(feature = "serde-support")]
extern crate serde;
#[cfg(test)]
#[cfg(feature = "serde-support")]
extern crate serde_json;
mod account;
mod actions;
mod error;
mod program;
pub use account::*;
pub use actions::*;
pub use error::AccountingError;
pub use program::*;
#[cfg(doctest)]
#[macro_use]
extern crate doc_comment;
#[cfg(doctest)]
doctest!("../README.md");
#[cfg(test)]
mod tests {
use super::{
sum_account_states, Account, AccountState, AccountStatus, BalanceAssertion,
EditAccountStatus, Program, ProgramState, Transaction, TransactionElement,
};
use crate::ActionTypeValue;
use chrono::NaiveDate;
use commodity::{Commodity, CommodityType, CommodityTypeID};
use std::rc::Rc;
use std::str::FromStr;
#[test]
fn execute_program() {
let aud = Rc::from(CommodityType::new(
CommodityTypeID::from_str("AUD").unwrap(),
None,
));
let account1 = Rc::from(Account::new_with_id(Some("Account 1"), aud.id, None));
let account2 = Rc::from(Account::new_with_id(Some("Account 2"), aud.id, None));
let accounts = vec![account1.clone(), account2.clone()];
let mut program_state = ProgramState::new(&accounts, AccountStatus::Closed);
let open_account1 = EditAccountStatus::new(
account1.id,
AccountStatus::Open,
NaiveDate::from_str("2020-01-01").unwrap(),
);
let open_account2 = EditAccountStatus::new(
account2.id,
AccountStatus::Open,
NaiveDate::from_str("2020-01-01").unwrap(),
);
let transaction1 = Transaction::new(
Some(String::from("Transaction 1")),
NaiveDate::from_str("2020-01-02").unwrap(),
vec![
TransactionElement::new(
account1.id,
Some(Commodity::from_str("-2.52 AUD").unwrap()),
None,
),
TransactionElement::new(
account2.id,
Some(Commodity::from_str("2.52 AUD").unwrap()),
None,
),
],
);
let transaction2 = Transaction::new(
Some(String::from("Transaction 2")),
NaiveDate::from_str("2020-01-02").unwrap(),
vec![
TransactionElement::new(
account1.id,
Some(Commodity::from_str("-1.0 AUD").unwrap()),
None,
),
TransactionElement::new(account2.id, None, None),
],
);
let balance_assertion = BalanceAssertion::new(
account1.id,
NaiveDate::from_str("2020-01-03").unwrap(),
Commodity::from_str("-3.52 AUD").unwrap(),
);
let actions: Vec<Rc<ActionTypeValue>> = vec![
Rc::new(open_account1.into()),
Rc::new(open_account2.into()),
Rc::new(transaction1.into()),
Rc::new(transaction2.into()),
Rc::new(balance_assertion.into()),
];
let program = Program::new(actions);
let account1_state_before: AccountState = program_state
.get_account_state(&account1.id)
.unwrap()
.clone();
assert_eq!(AccountStatus::Closed, account1_state_before.status);
program_state.execute_program(&program).unwrap();
let account1_state_after: AccountState = program_state
.get_account_state(&account1.id)
.unwrap()
.clone();
assert_eq!(AccountStatus::Open, account1_state_after.status);
assert_eq!(
Commodity::from_str("-3.52 AUD").unwrap(),
account1_state_after.amount
);
assert_eq!(
Commodity::from_str("0.0 AUD").unwrap(),
sum_account_states(
&program_state.account_states,
CommodityTypeID::from_str("AUD").unwrap(),
None
)
.unwrap()
);
}
}