middleware( function ($request, $next) { $this->generator = app(CategoryChartGeneratorInterface::class); $this->categoryRepository = app(CategoryRepositoryInterface::class); $this->accountRepository = app(AccountRepositoryInterface::class); return $next($request); } ); } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * @param string $others * * @return \Illuminate\Http\JsonResponse */ public function accountExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) { /** @var bool $others */ $others = intval($others) === 1; $names = []; // collect journals (just like the category report does): $set = $this->getExpenses($accounts, $categories, $start, $end); $grouped = $this->groupByOpposingAccount($set); // show the grouped results: $result = []; $total = '0'; foreach ($grouped as $accountId => $amount) { if (!isset($names[$accountId])) { $account = $this->accountRepository->find(intval($accountId)); $names[$accountId] = $account->name; } $amount = bcmul($amount, '-1'); $total = bcadd($total, $amount); $result[] = ['name' => $names[$accountId], 'id' => $accountId, 'amount' => $amount]; } // also collect all transactions NOT in these categories. // TODO include transfers if ($others) { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]); $journals = $collector->getJournals(); $sum = strval($journals->sum('transaction_amount')); $sum = bcmul($sum, '-1'); Log::debug(sprintf('Sum of others in accountExpense is %f', $sum)); $sum = bcsub($sum, $total); $result[] = ['name' => trans('firefly.everything_else'), 'id' => 0, 'amount' => $sum]; } $data = $this->generator->pieChart($result); return Response::json($data); } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * @param string $others * * @return \Illuminate\Http\JsonResponse */ public function accountIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) { /** @var bool $others */ $others = intval($others) === 1; $names = []; // collect journals (just like the category report does): $set = $this->getIncome($accounts, $categories, $start, $end); $grouped = $this->groupByOpposingAccount($set); // loop and show the grouped results: $result = []; $total = '0'; foreach ($grouped as $accountId => $amount) { if (!isset($names[$accountId])) { $account = $this->accountRepository->find(intval($accountId)); $names[$accountId] = $account->name; } $total = bcadd($total, $amount); $result[] = ['name' => $names[$accountId], 'id' => $accountId, 'amount' => $amount]; } // also collect others? // TODO include transfers if ($others) { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]); $journals = $collector->getJournals(); $sum = strval($journals->sum('transaction_amount')); Log::debug(sprintf('Sum of others in accountIncome is %f', $sum)); $sum = bcsub($sum, $total); $result[] = ['name' => trans('firefly.everything_else'), 'id' => 0, 'amount' => $sum]; } $data = $this->generator->pieChart($result); return Response::json($data); } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * @param string $others * * @return \Illuminate\Http\JsonResponse */ public function categoryExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) { /** @var bool $others */ $others = intval($others) === 1; $names = []; // collect journals (just like the category report does): $set = $this->getExpenses($accounts, $categories, $start, $end); $grouped = $this->groupByCategory($set); // show the grouped results: $result = []; $total = '0'; foreach ($grouped as $categoryId => $amount) { if (!isset($names[$categoryId])) { $category = $this->categoryRepository->find(intval($categoryId)); $names[$categoryId] = $category->name; } $amount = bcmul($amount, '-1'); $total = bcadd($total, $amount); $result[] = ['name' => $names[$categoryId], 'id' => $categoryId, 'amount' => $amount]; } // also collect all transactions NOT in these categories. // TODO include transfers if ($others) { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]); $journals = $collector->getJournals(); $sum = strval($journals->sum('transaction_amount')); $sum = bcmul($sum, '-1'); Log::debug(sprintf('Sum of others in categoryExpense is %f', $sum)); $sum = bcsub($sum, $total); $result[] = ['name' => trans('firefly.everything_else'), 'id' => 0, 'amount' => $sum]; } $data = $this->generator->pieChart($result); return Response::json($data); } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * @param string $others * * @return \Illuminate\Http\JsonResponse */ public function categoryIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) { /** @var bool $others */ $others = intval($others) === 1; $names = []; // collect journals (just like the category report does): $set = $this->getIncome($accounts, $categories, $start, $end); $grouped = $this->groupByCategory($set); // loop and show the grouped results: $result = []; $total = '0'; foreach ($grouped as $categoryId => $amount) { if (!isset($names[$categoryId])) { $category = $this->categoryRepository->find(intval($categoryId)); $names[$categoryId] = $category->name; } $total = bcadd($total, $amount); $result[] = ['name' => $names[$categoryId], 'id' => $categoryId, 'amount' => $amount]; } // also collect others? // TODO include transfers if ($others) { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT]); $journals = $collector->getJournals(); $sum = strval($journals->sum('transaction_amount')); Log::debug(sprintf('Sum of others in categoryIncome is %f', $sum)); $sum = bcsub($sum, $total); $result[] = ['name' => trans('firefly.everything_else'), 'id' => 0, 'amount' => $sum]; } $data = $this->generator->pieChart($result); return Response::json($data); } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * * @return Collection */ private function getExpenses(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) ->setCategories($categories)->getOpposingAccount()->disableFilter(); $accountIds = $accounts->pluck('id')->toArray(); $transactions = $collector->getJournals(); $set = MonthReportGenerator::filterExpenses($transactions, $accountIds); return $set; } /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * * @return Collection */ private function getIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): Collection { $collector = new JournalCollector(auth()->user()); $collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) ->setCategories($categories)->getOpposingAccount(); $accountIds = $accounts->pluck('id')->toArray(); $transactions = $collector->getJournals(); $set = MonthReportGenerator::filterIncome($transactions, $accountIds); return $set; } /** * @param Collection $set * * @return array */ private function groupByAccount(Collection $set): array { // group by category ID: $grouped = []; /** @var Transaction $transaction */ foreach ($set as $transaction) { $accountId = $transaction->account_id; $grouped[$accountId] = $grouped[$accountId] ?? '0'; $grouped[$accountId] = bcadd($transaction->transaction_amount, $grouped[$accountId]); } return $grouped; } /** * @param Collection $set * * @return array */ private function groupByCategory(Collection $set): array { // group by category ID: $grouped = []; /** @var Transaction $transaction */ foreach ($set as $transaction) { $jrnlCatId = intval($transaction->transaction_journal_category_id); $transCatId = intval($transaction->transaction_category_id); $categoryId = max($jrnlCatId, $transCatId); $grouped[$categoryId] = $grouped[$categoryId] ?? '0'; $grouped[$categoryId] = bcadd($transaction->transaction_amount, $grouped[$categoryId]); } return $grouped; } /** * @param Collection $set * * @return array */ private function groupByOpposingAccount(Collection $set): array { $grouped = []; /** @var Transaction $transaction */ foreach ($set as $transaction) { $accountId = $transaction->opposing_account_id; $grouped[$accountId] = $grouped[$accountId] ?? '0'; $grouped[$accountId] = bcadd($transaction->transaction_amount, $grouped[$accountId]); } return $grouped; } }