diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index 9fd9dd7843..1452192fe3 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -16,9 +16,8 @@ namespace FireflyIII\Http\Controllers\Chart; use Carbon\Carbon; use FireflyIII\Generator\Chart\Basic\GeneratorInterface; -use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; use Log; @@ -166,6 +165,8 @@ class ReportController extends Controller if ($cache->has()) { return Response::json($cache->get()); // @codeCoverageIgnore } + + $source = $this->getChartData($accounts, $start, $end); $numbers = [ 'sum_earned' => '0', @@ -249,31 +250,38 @@ class ReportController extends Controller $cache->addProperty($accounts); $cache->addProperty($end); if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore + // return $cache->get(); // @codeCoverageIgnore } $currentStart = clone $start; $spentArray = []; $earnedArray = []; + + /** @var AccountTaskerInterface $tasker */ + $tasker = app(AccountTaskerInterface::class); + while ($currentStart <= $end) { $currentEnd = Navigation::endOfPeriod($currentStart, '1M'); + $earned = strval( + array_sum( + array_map( + function ($item) { + return $item['sum']; + }, $tasker->getIncomeReport($currentStart, $currentEnd, $accounts) + ) + ) + ); - // try a collector for income: - /** @var JournalCollectorInterface $collector */ - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts($accounts)->setRange($currentStart, $currentEnd) - ->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) - ->withOpposingAccount(); - $earned = strval($collector->getJournals()->sum('transaction_amount')); - - // try a collector for expenses: - /** @var JournalCollectorInterface $collector */ - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts($accounts)->setRange($currentStart, $currentEnd) - ->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) - ->withOpposingAccount(); - $spent = strval($collector->getJournals()->sum('transaction_amount')); + $spent = strval( + array_sum( + array_map( + function ($item) { + return $item['sum']; + }, $tasker->getExpenseReport($currentStart, $currentEnd, $accounts) + ) + ) + ); $label = $currentStart->format('Y-m') . '-01'; diff --git a/app/Http/Controllers/Report/OperationsController.php b/app/Http/Controllers/Report/OperationsController.php index 0ddf9148df..5081ba6554 100644 --- a/app/Http/Controllers/Report/OperationsController.php +++ b/app/Http/Controllers/Report/OperationsController.php @@ -19,6 +19,7 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountTaskerInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; @@ -31,13 +32,14 @@ class OperationsController extends Controller { /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param AccountTaskerInterface $tasker + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string */ - public function expenses(Collection $accounts, Carbon $start, Carbon $end) + public function expenses(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -48,7 +50,7 @@ class OperationsController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $entries = $this->getExpenseReport($start, $end, $accounts); + $entries = $tasker->getExpenseReport($start, $end, $accounts); $type = 'expense-entry'; $result = view('reports.partials.income-expenses', compact('entries', 'type'))->render(); $cache->store($result); @@ -58,13 +60,14 @@ class OperationsController extends Controller } /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param AccountTaskerInterface $tasker + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return string */ - public function income(Collection $accounts, Carbon $start, Carbon $end) + public function income(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -75,7 +78,7 @@ class OperationsController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $entries = $this->getIncomeReport($start, $end, $accounts); + $entries = $tasker->getIncomeReport($start, $end, $accounts); $type = 'income-entry'; $result = view('reports.partials.income-expenses', compact('entries', 'type'))->render(); @@ -86,13 +89,14 @@ class OperationsController extends Controller } /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param AccountTaskerInterface $tasker + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string */ - public function operations(Collection $accounts, Carbon $start, Carbon $end) + public function operations(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -104,8 +108,8 @@ class OperationsController extends Controller return $cache->get(); // @codeCoverageIgnore } - $incomes = $this->getIncomeReport($start, $end, $accounts); - $expenses = $this->getExpenseReport($start, $end, $accounts); + $incomes = $tasker->getIncomeReport($start, $end, $accounts); + $expenses = $tasker->getExpenseReport($start, $end, $accounts); $incomeSum = array_sum( array_map( function ($item) { @@ -129,125 +133,4 @@ class OperationsController extends Controller } - /** - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * - * @return array - */ - private function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): array - { - // get all expenses for the given accounts in the given period! - // also transfers! - // get all transactions: - /** @var JournalCollectorInterface $collector */ - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts($accounts)->setRange($start, $end); - $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) - ->withOpposingAccount() - ->enableInternalFilter(); - $transactions = $collector->getJournals(); - $transactions = $transactions->filter( - function (Transaction $transaction) { - // return negative amounts only. - if (bccomp($transaction->transaction_amount, '0') === -1) { - return $transaction; - } - - return false; - } - ); - $expenses = $this->groupByOpposing($transactions); - - // sort the result - // Obtain a list of columns - $sum = []; - foreach ($expenses as $accountId => $row) { - $sum[$accountId] = floatval($row['sum']); - } - - array_multisort($sum, SORT_ASC, $expenses); - - return $expenses; - } - - /** - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * - * @return array - */ - private function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): array - { - // get all expenses for the given accounts in the given period! - // also transfers! - // get all transactions: - /** @var JournalCollectorInterface $collector */ - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts($accounts)->setRange($start, $end); - $collector->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) - ->withOpposingAccount() - ->enableInternalFilter(); - $transactions = $collector->getJournals(); - $transactions = $transactions->filter( - function (Transaction $transaction) { - // return positive amounts only. - if (bccomp($transaction->transaction_amount, '0') === 1) { - return $transaction; - } - - return false; - } - ); - $income = $this->groupByOpposing($transactions); - - // sort the result - // Obtain a list of columns - $sum = []; - foreach ($income as $accountId => $row) { - $sum[$accountId] = floatval($row['sum']); - } - - array_multisort($sum, SORT_DESC, $income); - - return $income; - } - - /** - * @param Collection $transactions - * - * @return array - */ - private function groupByOpposing(Collection $transactions): array - { - $expenses = []; - // join the result together: - foreach ($transactions as $transaction) { - $opposingId = $transaction->opposing_account_id; - $name = $transaction->opposing_account_name; - if (!isset($expenses[$opposingId])) { - $expenses[$opposingId] = [ - 'id' => $opposingId, - 'name' => $name, - 'sum' => '0', - 'average' => '0', - 'count' => 0, - ]; - } - $expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount); - $expenses[$opposingId]['count']++; - } - // do averages: - foreach ($expenses as $key => $entry) { - if ($expenses[$key]['count'] > 1) { - $expenses[$key]['average'] = bcdiv($expenses[$key]['sum'], strval($expenses[$key]['count'])); - } - } - - - return $expenses; - } - } diff --git a/app/Repositories/Account/AccountTasker.php b/app/Repositories/Account/AccountTasker.php index 7e31de5c4e..fd11485ad5 100644 --- a/app/Repositories/Account/AccountTasker.php +++ b/app/Repositories/Account/AccountTasker.php @@ -14,9 +14,10 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Account; use Carbon\Carbon; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionType; use FireflyIII\User; -use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; use Log; use Steam; @@ -89,6 +90,92 @@ class AccountTasker implements AccountTaskerInterface return $return; } + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return array + */ + public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): array + { + // get all expenses for the given accounts in the given period! + // also transfers! + // get all transactions: + /** @var JournalCollectorInterface $collector */ + $collector = app(JournalCollectorInterface::class); + $collector->setAccounts($accounts)->setRange($start, $end); + $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) + ->withOpposingAccount() + ->enableInternalFilter(); + $transactions = $collector->getJournals(); + $transactions = $transactions->filter( + function (Transaction $transaction) { + // return negative amounts only. + if (bccomp($transaction->transaction_amount, '0') === -1) { + return $transaction; + } + + return false; + } + ); + $expenses = $this->groupByOpposing($transactions); + + // sort the result + // Obtain a list of columns + $sum = []; + foreach ($expenses as $accountId => $row) { + $sum[$accountId] = floatval($row['sum']); + } + + array_multisort($sum, SORT_ASC, $expenses); + + return $expenses; + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return array + */ + public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): array + { + // get all expenses for the given accounts in the given period! + // also transfers! + // get all transactions: + /** @var JournalCollectorInterface $collector */ + $collector = app(JournalCollectorInterface::class); + $collector->setAccounts($accounts)->setRange($start, $end); + $collector->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) + ->withOpposingAccount() + ->enableInternalFilter(); + $transactions = $collector->getJournals(); + $transactions = $transactions->filter( + function (Transaction $transaction) { + // return positive amounts only. + if (bccomp($transaction->transaction_amount, '0') === 1) { + return $transaction; + } + + return false; + } + ); + $income = $this->groupByOpposing($transactions); + + // sort the result + // Obtain a list of columns + $sum = []; + foreach ($income as $accountId => $row) { + $sum[$accountId] = floatval($row['sum']); + } + + array_multisort($sum, SORT_DESC, $income); + + return $income; + } + /** * @param User $user */ @@ -97,4 +184,38 @@ class AccountTasker implements AccountTaskerInterface $this->user = $user; } + /** + * @param Collection $transactions + * + * @return array + */ + private function groupByOpposing(Collection $transactions): array + { + $expenses = []; + // join the result together: + foreach ($transactions as $transaction) { + $opposingId = $transaction->opposing_account_id; + $name = $transaction->opposing_account_name; + if (!isset($expenses[$opposingId])) { + $expenses[$opposingId] = [ + 'id' => $opposingId, + 'name' => $name, + 'sum' => '0', + 'average' => '0', + 'count' => 0, + ]; + } + $expenses[$opposingId]['sum'] = bcadd($expenses[$opposingId]['sum'], $transaction->transaction_amount); + $expenses[$opposingId]['count']++; + } + // do averages: + foreach ($expenses as $key => $entry) { + if ($expenses[$key]['count'] > 1) { + $expenses[$key]['average'] = bcdiv($expenses[$key]['sum'], strval($expenses[$key]['count'])); + } + } + + + return $expenses; + } } diff --git a/app/Repositories/Account/AccountTaskerInterface.php b/app/Repositories/Account/AccountTaskerInterface.php index 7ab6fea905..af04994f1c 100644 --- a/app/Repositories/Account/AccountTaskerInterface.php +++ b/app/Repositories/Account/AccountTaskerInterface.php @@ -33,6 +33,24 @@ interface AccountTaskerInterface */ public function getAccountReport(Collection $accounts, Carbon $start, Carbon $end): array; + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return array + */ + public function getExpenseReport(Carbon $start, Carbon $end, Collection $accounts): array; + + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return array + */ + public function getIncomeReport(Carbon $start, Carbon $end, Collection $accounts): array; + /** * @param User $user */