total method

Money total({
  1. required Currency currency,
  2. List<ExchangeRate>? exchangeRates,
  3. DateTime? from,
  4. ExpenseOrIncome? expenseOrIncome,
  5. DateTime? until,
})

Calculates and returns the sum of all transactions of this list. Also, allows to perform the sum of only expenses or only income. It is also possible to limit the sum to a time interval.

The sum is done by normalizing all values to the same currency. For this, exchangeRates list must contain all the exchange rates necessary for conversions. If even one of these is missing, throws a FormatException.

Implementation

Money total({
  required Currency currency,
  List<ExchangeRate>? exchangeRates,
  DateTime? from,
  ExpenseOrIncome? expenseOrIncome,
  DateTime? until,
}) {
  if (isEmpty) return Money(amount: 0, currency: currency);

  final List<MoneyTransaction> listEOI = expenseOrIncome == null
      ? this
      : where((e) => e.expenseOrIncome == expenseOrIncome).toList();
  final List<MoneyTransaction> listFrom = from == null
      ? listEOI
      : listEOI
          .where((e) =>
              e.dateTime.isAtSameMomentAs(from) || e.dateTime.isAfter(from))
          .toList();
  final List<MoneyTransaction> listUntil = until == null
      ? listFrom
      : listFrom
          .where((e) =>
              e.dateTime.isAtSameMomentAs(until) ||
              e.dateTime.isBefore(until))
          .toList()
    ..sort();

  final List<MoneyTransaction> normalizedTransactions = listUntil.normalize(
    currency: currency,
    exchangeRates: exchangeRates,
  );

  final List<Money> expenseValues = normalizedTransactions
      .where((t) => t.expenseOrIncome == ExpenseOrIncome.expense)
      .map<Money>((t) => t.value)
      .toList()
        ..sort();
  final List<Money> incomeValues = normalizedTransactions
      .where((t) => t.expenseOrIncome == ExpenseOrIncome.income)
      .map<Money>((t) => t.value)
      .toList()
        ..sort();

  final Money expenseTotal = expenseValues.fold<Money>(
    Money(amount: 0, currency: currency),
    (previousValue, money) => previousValue + money,
  );
  final Money incomeTotal = incomeValues.fold<Money>(
    Money(amount: 0, currency: currency),
    (previousValue, money) => previousValue + money,
  );

  if (expenseOrIncome == ExpenseOrIncome.expense) {
    return expenseTotal;
  } else {
    return incomeTotal - expenseTotal;
  }
}