use crate::prelude::*;
#[derive(Clone, Debug, Serialize, PartialEq, Eq, Hash, Getters, Builder)]
pub struct LineItemsFlat {
#[getset(get = "pub")]
is_expenses: bool,
#[getset(get = "pub")]
items: Vec<ItemConvertedIntoTargetCurrency>,
}
impl MaybeIsExpenses for LineItemsFlat {
fn is_expenses(&self) -> bool {
self.is_expenses
}
}
impl TryFrom<(LineItemsPricedInSourceCurrency, ExchangeRates)> for LineItemsFlat {
type Error = crate::prelude::Error;
fn try_from(
(line_items, exchange_rates): (LineItemsPricedInSourceCurrency, ExchangeRates),
) -> Result<Self> {
match line_items {
LineItemsPricedInSourceCurrency::Service(item) => {
let service = item.total_cost_in_target_currency(&exchange_rates)?;
let flat = LineItemsFlat::builder()
.items(vec![service])
.is_expenses(false)
.build();
Ok(flat)
}
LineItemsPricedInSourceCurrency::Expenses(expenses) => {
let expenses = expenses
.into_iter()
.map(|expense| expense.total_cost_in_target_currency(&exchange_rates))
.collect::<Result<Vec<_>>>()?;
let flat = LineItemsFlat::builder()
.items(expenses)
.is_expenses(true)
.build();
Ok(flat)
}
}
}
}
impl HasSample for LineItemsFlat {
fn sample() -> Self {
Self::builder()
.is_expenses(false)
.items(vec![ItemConvertedIntoTargetCurrency::sample()])
.build()
}
fn sample_other() -> Self {
Self::builder()
.is_expenses(true)
.items(vec![ItemConvertedIntoTargetCurrency::sample_other()])
.build()
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
type Sut = LineItemsFlat;
#[test]
fn equality() {
assert_eq!(Sut::sample(), Sut::sample());
assert_eq!(Sut::sample_other(), Sut::sample_other());
}
#[test]
fn inequality() {
assert_ne!(Sut::sample(), Sut::sample_other());
}
#[test]
fn test_line_items_flat_conversion() {
let line_items = LineItemsPricedInSourceCurrency::sample();
let exchange_rates = ExchangeRates::builder()
.rates(ExchangeRatesMap::from_iter([(
Currency::GBP,
UnitPrice::from(dec!(10.0)),
)]))
.target_currency(Currency::EUR)
.build();
let result = Sut::try_from((line_items, exchange_rates));
assert!(
result.is_ok(),
"Expected conversion to succeed, got: {:?}",
result
);
}
#[test]
fn test_is_expenses() {
assert!(!MaybeIsExpenses::is_expenses(&Sut::sample()));
}
}