package com.code44.finance.ui.reports.trends; import android.content.Context; import android.database.Cursor; import com.code44.finance.R; import com.code44.finance.common.model.TransactionState; import com.code44.finance.common.model.TransactionType; import com.code44.finance.data.model.Currency; import com.code44.finance.data.model.Transaction; import com.code44.finance.graphs.line.LineGraphData; import com.code44.finance.graphs.line.LineGraphValue; import com.code44.finance.utils.BaseInterval; import org.joda.time.Interval; import org.joda.time.Period; public class TrendsGraphData { private final long totalIncome; private final long totalExpense; private final LineGraphData lineGraphData; public TrendsGraphData(Context context, Cursor cursor, Currency mainCurrency, BaseInterval interval) { long totalIncome = 0; long totalExpense = 0; final LineGraphData.Builder builder = new LineGraphData.Builder() .setColor(context.getResources().getColor(R.color.text_negative)) .setLineWidth(context.getResources().getDimension(R.dimen.divider)) .setDividerDrawable(context.getResources().getDrawable(R.drawable.trends_divider)) .setUseGlobalMinMax(false) .setSmooth(true); final Period period = getPeriod(interval); Interval currentInterval = getFirstInterval(interval, period); long expense = 0; final Interval lastInterval = getLastInterval(interval, period); if (cursor.moveToFirst()) { do { final Transaction transaction = Transaction.from(cursor); if (isTransactionValid(transaction)) { final long amount = getAmount(transaction, mainCurrency); if (transaction.getTransactionType() == TransactionType.Expense) { totalExpense += amount; if (currentInterval.contains(transaction.getDate())) { expense += amount; } else { do { builder.addValue(new LineGraphValue(expense)); expense = 0; currentInterval = new Interval(currentInterval.getEnd(), period); } while (!currentInterval.contains(transaction.getDate())); expense = amount; } } else { totalIncome += amount; } } } while (cursor.moveToNext()); } builder.addValue(new LineGraphValue(expense)); if (!currentInterval.equals(lastInterval) && !currentInterval.isAfter(lastInterval)) { do { builder.addValue(new LineGraphValue(0)); currentInterval = new Interval(currentInterval.getEnd(), period); } while (!currentInterval.equals(lastInterval)); } this.totalIncome = totalIncome; this.totalExpense = totalExpense; this.lineGraphData = builder.build(); } public long getTotalIncome() { return totalIncome; } public long getTotalExpense() { return totalExpense; } public LineGraphData getLineGraphData() { return lineGraphData; } private boolean isTransactionValid(Transaction transaction) { return transaction.includeInReports() && transaction.getTransactionType() != TransactionType.Transfer && transaction.getTransactionState() == TransactionState.Confirmed; } private long getAmount(Transaction transaction, Currency mainCurrency) { final Currency currency = transaction.getTransactionType() == TransactionType.Expense ? transaction.getAccountFrom().getCurrency() : transaction.getAccountTo().getCurrency(); if (currency.getId().equals(mainCurrency.getId())) { return transaction.getAmount(); } else { return Math.round(transaction.getAmount() * currency.getExchangeRate()); } } private Period getPeriod(BaseInterval interval) { switch (interval.getType()) { case DAY: return Period.hours(1); case WEEK: case MONTH: return Period.days(1); case YEAR: return Period.months(1); default: throw new IllegalArgumentException("Type " + interval.getType() + " is not supported."); } } private Interval getFirstInterval(BaseInterval interval, Period period) { return new Interval(interval.getInterval().getStart(), period); } private Interval getLastInterval(BaseInterval interval, Period period) { return new Interval(period, interval.getInterval().getEnd()); } }