2015-05-16 09:41:14 +02:00
|
|
|
<?php
|
2022-11-04 05:11:05 +01:00
|
|
|
|
2016-05-20 12:41:23 +02:00
|
|
|
/**
|
|
|
|
* AccountController.php
|
2020-01-31 07:32:04 +01:00
|
|
|
* Copyright (c) 2019 james@firefly-iii.org
|
2016-05-20 12:41:23 +02:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
2016-10-05 06:52:15 +02:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
2017-10-21 08:40:00 +02:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
2017-10-21 08:40:00 +02:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2019-10-02 06:37:26 +02:00
|
|
|
* GNU Affero General Public License for more details.
|
2017-10-21 08:40:00 +02:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2016-05-20 12:41:23 +02:00
|
|
|
*/
|
2017-04-09 07:44:22 +02:00
|
|
|
declare(strict_types=1);
|
2015-05-16 09:41:14 +02:00
|
|
|
|
|
|
|
namespace FireflyIII\Http\Controllers\Chart;
|
|
|
|
|
|
|
|
use Carbon\Carbon;
|
2024-12-22 16:41:55 +01:00
|
|
|
use FireflyIII\Enums\AccountTypeEnum;
|
2025-01-03 09:05:19 +01:00
|
|
|
use FireflyIII\Enums\TransactionTypeEnum;
|
2021-09-18 10:26:12 +02:00
|
|
|
use FireflyIII\Exceptions\FireflyException;
|
2016-12-11 16:02:04 +01:00
|
|
|
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
2019-05-30 12:31:19 +02:00
|
|
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
2015-05-16 09:41:14 +02:00
|
|
|
use FireflyIII\Http\Controllers\Controller;
|
|
|
|
use FireflyIII\Models\Account;
|
2018-08-27 18:59:30 +02:00
|
|
|
use FireflyIII\Models\TransactionCurrency;
|
2016-10-10 07:25:27 +02:00
|
|
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
2023-10-28 06:58:33 +02:00
|
|
|
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
|
2016-05-13 17:22:24 +02:00
|
|
|
use FireflyIII\Support\CacheProperties;
|
2024-12-24 10:29:07 +01:00
|
|
|
use FireflyIII\Support\Facades\Amount;
|
2024-12-22 19:42:06 +01:00
|
|
|
use FireflyIII\Support\Facades\Steam;
|
2018-08-11 06:39:29 +02:00
|
|
|
use FireflyIII\Support\Http\Controllers\AugumentData;
|
2018-12-31 07:58:13 +01:00
|
|
|
use FireflyIII\Support\Http\Controllers\ChartGeneration;
|
2018-07-14 23:22:08 +02:00
|
|
|
use FireflyIII\Support\Http\Controllers\DateCalculation;
|
2018-07-08 12:08:53 +02:00
|
|
|
use Illuminate\Http\JsonResponse;
|
2015-05-17 18:03:16 +02:00
|
|
|
use Illuminate\Support\Collection;
|
2024-11-19 06:31:49 +01:00
|
|
|
use Illuminate\Support\Facades\Log;
|
2015-05-16 09:41:14 +02:00
|
|
|
|
2018-07-14 23:22:08 +02:00
|
|
|
/**
|
2017-11-15 12:25:49 +01:00
|
|
|
* Class AccountController.
|
2015-05-16 09:41:14 +02:00
|
|
|
*/
|
|
|
|
class AccountController extends Controller
|
|
|
|
{
|
2022-10-30 14:24:19 +01:00
|
|
|
use AugumentData;
|
|
|
|
use ChartGeneration;
|
2023-11-04 14:18:49 +01:00
|
|
|
use DateCalculation;
|
2018-07-14 23:22:08 +02:00
|
|
|
|
2022-03-28 12:24:16 +02:00
|
|
|
protected GeneratorInterface $generator;
|
|
|
|
private AccountRepositoryInterface $accountRepository;
|
|
|
|
private CurrencyRepositoryInterface $currencyRepository;
|
2018-08-27 18:59:30 +02:00
|
|
|
|
2015-06-27 08:18:47 +02:00
|
|
|
/**
|
2018-07-21 08:06:24 +02:00
|
|
|
* AccountController constructor.
|
2015-06-27 08:18:47 +02:00
|
|
|
*/
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
parent::__construct();
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
$this->middleware(
|
|
|
|
function ($request, $next) {
|
|
|
|
$this->generator = app(GeneratorInterface::class);
|
|
|
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
|
|
|
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
|
|
|
|
|
|
|
return $next($request);
|
|
|
|
}
|
|
|
|
);
|
2015-06-27 08:18:47 +02:00
|
|
|
}
|
2021-03-28 11:46:23 +02:00
|
|
|
|
2015-12-12 10:41:51 +01:00
|
|
|
/**
|
2018-08-27 08:08:51 +02:00
|
|
|
* Shows the balances for all the user's expense accounts (on the front page).
|
2015-12-28 07:38:02 +01:00
|
|
|
*
|
2018-08-27 18:59:30 +02:00
|
|
|
* This chart is (multi) currency aware.
|
2023-12-22 20:12:38 +01:00
|
|
|
*/
|
2018-08-27 18:59:30 +02:00
|
|
|
public function expenseAccounts(): JsonResponse
|
2015-12-12 10:41:51 +01:00
|
|
|
{
|
2024-12-24 16:56:31 +01:00
|
|
|
Log::debug('RevenueAccounts');
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2018-07-27 04:46:21 +02:00
|
|
|
/** @var Carbon $start */
|
2024-12-26 05:25:46 +01:00
|
|
|
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
2023-12-20 19:35:52 +01:00
|
|
|
|
2018-07-27 04:46:21 +02:00
|
|
|
/** @var Carbon $end */
|
2024-12-26 05:25:46 +01:00
|
|
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
|
|
|
$cache = new CacheProperties();
|
2015-12-12 10:41:51 +01:00
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2024-12-24 19:03:47 +01:00
|
|
|
$cache->addProperty($this->convertToNative);
|
2016-12-11 17:05:48 +01:00
|
|
|
$cache->addProperty('chart.account.expense-accounts');
|
2015-12-12 10:41:51 +01:00
|
|
|
if ($cache->has()) {
|
2024-12-25 07:13:41 +01:00
|
|
|
return response()->json($cache->get());
|
2015-12-12 10:41:51 +01:00
|
|
|
}
|
2016-05-13 17:22:24 +02:00
|
|
|
$start->subDay();
|
2016-12-11 17:05:48 +01:00
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
// prep some vars:
|
2024-12-26 05:25:46 +01:00
|
|
|
$currencies = [];
|
|
|
|
$chartData = [];
|
|
|
|
$tempData = [];
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// grab all accounts and names
|
2024-12-26 05:25:46 +01:00
|
|
|
$accounts = $this->accountRepository->getAccountsByType([AccountTypeEnum::EXPENSE->value]);
|
|
|
|
$accountNames = $this->extractNames($accounts);
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// grab all balances
|
2024-12-22 20:32:58 +01:00
|
|
|
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
|
|
|
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
2018-08-27 08:08:51 +02:00
|
|
|
|
2024-12-24 10:29:07 +01:00
|
|
|
// loop the accounts, then check for balance and currency info.
|
2024-12-25 07:13:41 +01:00
|
|
|
foreach ($accounts as $account) {
|
2024-12-31 08:18:40 +01:00
|
|
|
// Log::debug(sprintf('[a] Now in account #%d ("%s")', $account->id, $account->name));
|
2024-12-24 10:29:07 +01:00
|
|
|
$expenses = $endBalances[$account->id] ?? false;
|
2024-12-25 07:13:41 +01:00
|
|
|
if (false === $expenses) {
|
|
|
|
Log::error(sprintf('Found no end balance for account #%d', $account->id));
|
|
|
|
|
2024-12-24 10:29:07 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-24 10:29:07 +01:00
|
|
|
/**
|
|
|
|
* @var string $key
|
|
|
|
* @var string $endBalance
|
|
|
|
*/
|
|
|
|
foreach ($expenses as $key => $endBalance) {
|
2024-12-25 07:13:41 +01:00
|
|
|
if (!$this->convertToNative && 'native_balance' === $key) {
|
2024-12-24 10:29:07 +01:00
|
|
|
Log::debug(sprintf('[a] Will skip expense array "%s"', $key));
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-24 10:29:07 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-25 07:13:41 +01:00
|
|
|
if ($this->convertToNative && 'native_balance' !== $key) {
|
2024-12-24 10:29:07 +01:00
|
|
|
Log::debug(sprintf('[b] Will skip expense array "%s"', $key));
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-23 06:55:14 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
|
2024-12-30 10:51:34 +01:00
|
|
|
$searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key;
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Search code is %s', $searchCode));
|
2018-08-27 18:59:30 +02:00
|
|
|
// see if there is an accompanying start amount.
|
|
|
|
// grab the difference and find the currency.
|
2024-12-24 10:29:07 +01:00
|
|
|
$startBalance = ($startBalances[$account->id][$key] ?? '0');
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Start balance is %s', $startBalance));
|
2024-12-26 05:25:46 +01:00
|
|
|
$diff = bcsub($endBalance, $startBalance);
|
2024-12-24 10:29:07 +01:00
|
|
|
$currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode);
|
2018-08-27 18:59:30 +02:00
|
|
|
if (0 !== bccomp($diff, '0')) {
|
|
|
|
// store the values in a temporary array.
|
|
|
|
$tempData[] = [
|
2024-12-24 10:29:07 +01:00
|
|
|
'name' => $accountNames[$account->id],
|
2018-08-27 18:59:30 +02:00
|
|
|
'difference' => $diff,
|
2024-12-22 08:43:12 +01:00
|
|
|
'diff_float' => (float) $diff, // intentional float
|
2024-12-24 10:29:07 +01:00
|
|
|
'currency_id' => $currencies[$searchCode]->id,
|
2018-08-27 18:59:30 +02:00
|
|
|
];
|
|
|
|
}
|
2016-05-13 17:22:24 +02:00
|
|
|
}
|
2016-12-11 16:38:21 +01:00
|
|
|
}
|
2024-12-23 07:13:59 +01:00
|
|
|
// recreate currencies, but on ID instead of code.
|
|
|
|
$newCurrencies = [];
|
2024-12-23 08:40:29 +01:00
|
|
|
foreach ($currencies as $currency) {
|
2024-12-23 07:13:59 +01:00
|
|
|
$newCurrencies[$currency->id] = $currency;
|
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
$currencies = $newCurrencies;
|
2024-12-23 07:13:59 +01:00
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
// sort temp array by amount.
|
2024-12-26 05:25:46 +01:00
|
|
|
$amounts = array_column($tempData, 'diff_float');
|
2018-08-27 18:59:30 +02:00
|
|
|
array_multisort($amounts, SORT_DESC, $tempData);
|
|
|
|
|
|
|
|
// loop all found currencies and build the data array for the chart.
|
|
|
|
/**
|
2023-06-21 12:34:58 +02:00
|
|
|
* @var int $currencyId
|
2018-08-27 18:59:30 +02:00
|
|
|
* @var TransactionCurrency $currency
|
|
|
|
*/
|
|
|
|
foreach ($currencies as $currencyId => $currency) {
|
|
|
|
$dataSet
|
|
|
|
= [
|
2024-12-26 05:25:46 +01:00
|
|
|
'label' => (string) trans('firefly.spent'),
|
|
|
|
'type' => 'bar',
|
|
|
|
'currency_symbol' => $currency->symbol,
|
|
|
|
'currency_code' => $currency->code,
|
|
|
|
'entries' => $this->expandNames($tempData),
|
|
|
|
];
|
2018-08-27 18:59:30 +02:00
|
|
|
$chartData[$currencyId] = $dataSet;
|
2018-08-27 08:08:51 +02:00
|
|
|
}
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// loop temp data and place data in correct array:
|
|
|
|
foreach ($tempData as $entry) {
|
|
|
|
$currencyId = $entry['currency_id'];
|
|
|
|
$name = $entry['name'];
|
2024-12-23 07:13:59 +01:00
|
|
|
$chartData[$currencyId]['entries'][$name] = (float) $entry['difference'];
|
2018-08-27 08:08:51 +02:00
|
|
|
}
|
2018-08-27 18:59:30 +02:00
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$data = $this->generator->multiSet($chartData);
|
2015-12-12 10:41:51 +01:00
|
|
|
$cache->store($data);
|
2015-06-02 17:44:50 +02:00
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($data);
|
2015-05-17 18:03:16 +02:00
|
|
|
}
|
|
|
|
|
2023-06-21 12:34:58 +02:00
|
|
|
/**
|
|
|
|
* Expenses per budget for all time, as shown on account overview.
|
|
|
|
*/
|
|
|
|
public function expenseBudgetAll(AccountRepositoryInterface $repository, Account $account): JsonResponse
|
|
|
|
{
|
|
|
|
$start = $repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth();
|
|
|
|
$end = today(config('app.timezone'));
|
|
|
|
|
|
|
|
return $this->expenseBudget($account, $start, $end);
|
|
|
|
}
|
|
|
|
|
2016-11-20 18:31:29 +01:00
|
|
|
/**
|
2018-07-21 08:06:24 +02:00
|
|
|
* Expenses per budget, as shown on account overview.
|
2016-11-20 18:31:29 +01:00
|
|
|
*/
|
2018-07-08 12:08:53 +02:00
|
|
|
public function expenseBudget(Account $account, Carbon $start, Carbon $end): JsonResponse
|
2016-11-20 18:31:29 +01:00
|
|
|
{
|
2024-12-26 05:25:46 +01:00
|
|
|
$cache = new CacheProperties();
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->addProperty($account->id);
|
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2016-12-11 17:05:48 +01:00
|
|
|
$cache->addProperty('chart.account.expense-budget');
|
2016-11-20 18:31:29 +01:00
|
|
|
if ($cache->has()) {
|
2021-09-18 10:26:12 +02:00
|
|
|
return response()->json($cache->get());
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
2023-12-20 19:35:52 +01:00
|
|
|
|
2019-05-30 12:31:19 +02:00
|
|
|
/** @var GroupCollectorInterface $collector */
|
|
|
|
$collector = app(GroupCollectorInterface::class);
|
2025-01-03 09:05:19 +01:00
|
|
|
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withBudgetInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
2019-05-30 12:31:19 +02:00
|
|
|
$journals = $collector->getExtractedJournals();
|
|
|
|
$chartData = [];
|
|
|
|
$result = [];
|
|
|
|
$budgetIds = [];
|
2023-12-20 19:35:52 +01:00
|
|
|
|
2019-05-30 12:31:19 +02:00
|
|
|
/** @var array $journal */
|
|
|
|
foreach ($journals as $journal) {
|
2024-12-26 05:25:46 +01:00
|
|
|
$budgetId = (int) $journal['budget_id'];
|
|
|
|
$key = sprintf('%d-%d', $budgetId, $journal['currency_id']);
|
|
|
|
$budgetIds[] = $budgetId;
|
2021-04-07 07:28:43 +02:00
|
|
|
if (!array_key_exists($key, $result)) {
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key] = [
|
2018-09-10 17:57:20 +02:00
|
|
|
'total' => '0',
|
|
|
|
'budget_id' => $budgetId,
|
2020-01-02 08:34:34 +01:00
|
|
|
'currency_name' => $journal['currency_name'],
|
2019-05-30 12:31:19 +02:00
|
|
|
'currency_symbol' => $journal['currency_symbol'],
|
2020-07-28 06:25:14 +02:00
|
|
|
'currency_code' => $journal['currency_code'],
|
2018-08-27 18:59:30 +02:00
|
|
|
];
|
|
|
|
}
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key]['total'] = bcadd($journal['amount'], $result[$key]['total']);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
2016-12-11 17:05:48 +01:00
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$names = $this->getBudgetNames($budgetIds);
|
2018-09-10 17:57:20 +02:00
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
foreach ($result as $row) {
|
|
|
|
$budgetId = $row['budget_id'];
|
|
|
|
$name = $names[$budgetId];
|
2024-12-22 08:43:12 +01:00
|
|
|
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
|
2020-07-28 06:25:14 +02:00
|
|
|
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
|
2016-12-11 17:05:48 +01:00
|
|
|
}
|
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$data = $this->generator->multiCurrencyPieChart($chartData);
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->store($data);
|
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($data);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-06-21 12:34:58 +02:00
|
|
|
* Expenses grouped by category for account.
|
2016-11-20 18:31:29 +01:00
|
|
|
*/
|
2023-06-21 12:34:58 +02:00
|
|
|
public function expenseCategoryAll(AccountRepositoryInterface $repository, Account $account): JsonResponse
|
2017-02-25 13:19:42 +01:00
|
|
|
{
|
2023-02-11 07:36:45 +01:00
|
|
|
$start = $repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth();
|
|
|
|
$end = today(config('app.timezone'));
|
2017-02-25 13:19:42 +01:00
|
|
|
|
2023-06-21 12:34:58 +02:00
|
|
|
return $this->expenseCategory($account, $start, $end);
|
2017-02-25 13:19:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2018-07-21 08:06:24 +02:00
|
|
|
* Expenses per category for one single account.
|
2017-02-25 13:19:42 +01:00
|
|
|
*/
|
2018-07-08 12:08:53 +02:00
|
|
|
public function expenseCategory(Account $account, Carbon $start, Carbon $end): JsonResponse
|
2016-11-20 18:31:29 +01:00
|
|
|
{
|
2024-12-26 05:25:46 +01:00
|
|
|
$cache = new CacheProperties();
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->addProperty($account->id);
|
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2016-12-11 17:05:48 +01:00
|
|
|
$cache->addProperty('chart.account.expense-category');
|
2016-11-20 18:31:29 +01:00
|
|
|
if ($cache->has()) {
|
2021-09-18 10:26:12 +02:00
|
|
|
return response()->json($cache->get());
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
|
|
|
|
2019-05-30 12:31:19 +02:00
|
|
|
/** @var GroupCollectorInterface $collector */
|
|
|
|
$collector = app(GroupCollectorInterface::class);
|
2025-01-03 09:05:19 +01:00
|
|
|
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
|
2020-03-17 15:01:00 +01:00
|
|
|
$journals = $collector->getExtractedJournals();
|
|
|
|
$result = [];
|
|
|
|
$chartData = [];
|
2019-05-30 12:31:19 +02:00
|
|
|
|
|
|
|
/** @var array $journal */
|
|
|
|
foreach ($journals as $journal) {
|
2024-12-26 05:25:46 +01:00
|
|
|
$key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']);
|
2021-04-07 07:28:43 +02:00
|
|
|
if (!array_key_exists($key, $result)) {
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key] = [
|
2018-09-10 17:57:20 +02:00
|
|
|
'total' => '0',
|
2024-12-22 08:43:12 +01:00
|
|
|
'category_id' => (int) $journal['category_id'],
|
2020-01-02 08:34:34 +01:00
|
|
|
'currency_name' => $journal['currency_name'],
|
2019-05-30 12:31:19 +02:00
|
|
|
'currency_symbol' => $journal['currency_symbol'],
|
2020-07-28 06:25:14 +02:00
|
|
|
'currency_code' => $journal['currency_code'],
|
2018-08-27 18:59:30 +02:00
|
|
|
];
|
|
|
|
}
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key]['total'] = bcadd($journal['amount'], $result[$key]['total']);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
$names = $this->getCategoryNames(array_keys($result));
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
foreach ($result as $row) {
|
|
|
|
$categoryId = $row['category_id'];
|
2018-08-28 14:20:04 +02:00
|
|
|
$name = $names[$categoryId] ?? '(unknown)';
|
2024-12-22 08:43:12 +01:00
|
|
|
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
|
2020-07-28 06:25:14 +02:00
|
|
|
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
|
2016-12-11 17:05:48 +01:00
|
|
|
}
|
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$data = $this->generator->multiCurrencyPieChart($chartData);
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->store($data);
|
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($data);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
|
|
|
|
2015-08-01 07:04:41 +02:00
|
|
|
/**
|
2016-05-13 15:53:39 +02:00
|
|
|
* Shows the balances for all the user's frontpage accounts.
|
2015-08-01 07:04:41 +02:00
|
|
|
*
|
2021-09-18 10:26:12 +02:00
|
|
|
* @throws FireflyException
|
2023-12-22 07:58:35 +01:00
|
|
|
* */
|
2018-07-08 12:08:53 +02:00
|
|
|
public function frontpage(AccountRepositoryInterface $repository): JsonResponse
|
2015-08-01 07:04:41 +02:00
|
|
|
{
|
2024-12-26 05:25:46 +01:00
|
|
|
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
|
|
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
|
|
|
$defaultSet = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
2024-11-19 06:31:49 +01:00
|
|
|
Log::debug('Default set is ', $defaultSet);
|
2024-04-01 20:26:02 +02:00
|
|
|
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
|
|
|
|
$frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
|
2024-11-19 06:31:49 +01:00
|
|
|
Log::debug('Frontpage preference set is ', $frontpageArray);
|
2024-04-01 20:26:02 +02:00
|
|
|
if (0 === count($frontpageArray)) {
|
|
|
|
app('preferences')->set('frontpageAccounts', $defaultSet);
|
2024-11-19 06:31:49 +01:00
|
|
|
Log::debug('frontpage set is empty!');
|
2016-12-11 17:30:55 +01:00
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
$accounts = $repository->getAccountsById($frontpageArray);
|
2016-05-13 17:22:24 +02:00
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($this->accountBalanceChart($accounts, $start, $end));
|
2015-08-01 07:04:41 +02:00
|
|
|
}
|
|
|
|
|
2023-06-21 12:34:58 +02:00
|
|
|
/**
|
|
|
|
* Shows the income grouped by category for an account, in all time.
|
|
|
|
*/
|
|
|
|
public function incomeCategoryAll(AccountRepositoryInterface $repository, Account $account): JsonResponse
|
|
|
|
{
|
|
|
|
$start = $repository->oldestJournalDate($account) ?? today(config('app.timezone'))->startOfMonth();
|
|
|
|
$end = today(config('app.timezone'));
|
|
|
|
|
|
|
|
return $this->incomeCategory($account, $start, $end);
|
|
|
|
}
|
|
|
|
|
2016-11-20 18:31:29 +01:00
|
|
|
/**
|
2018-07-21 08:06:24 +02:00
|
|
|
* Shows all income per account for each category.
|
2016-11-20 18:31:29 +01:00
|
|
|
*/
|
2018-07-08 12:08:53 +02:00
|
|
|
public function incomeCategory(Account $account, Carbon $start, Carbon $end): JsonResponse
|
2016-11-20 18:31:29 +01:00
|
|
|
{
|
2024-12-26 05:25:46 +01:00
|
|
|
$cache = new CacheProperties();
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->addProperty($account->id);
|
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2016-12-11 17:05:48 +01:00
|
|
|
$cache->addProperty('chart.account.income-category');
|
2016-11-20 18:31:29 +01:00
|
|
|
if ($cache->has()) {
|
2021-09-18 10:26:12 +02:00
|
|
|
return response()->json($cache->get());
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// grab all journals:
|
2019-05-30 12:31:19 +02:00
|
|
|
/** @var GroupCollectorInterface $collector */
|
|
|
|
$collector = app(GroupCollectorInterface::class);
|
|
|
|
|
2025-01-03 09:09:15 +01:00
|
|
|
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::DEPOSIT->value]);
|
2020-03-17 15:01:00 +01:00
|
|
|
$journals = $collector->getExtractedJournals();
|
|
|
|
$result = [];
|
|
|
|
$chartData = [];
|
2023-12-20 19:35:52 +01:00
|
|
|
|
2019-05-30 12:31:19 +02:00
|
|
|
/** @var array $journal */
|
|
|
|
foreach ($journals as $journal) {
|
2024-12-26 05:25:46 +01:00
|
|
|
$key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']);
|
2021-04-07 07:28:43 +02:00
|
|
|
if (!array_key_exists($key, $result)) {
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key] = [
|
2018-09-10 17:57:20 +02:00
|
|
|
'total' => '0',
|
2020-01-02 08:34:34 +01:00
|
|
|
'category_id' => $journal['category_id'],
|
|
|
|
'currency_name' => $journal['currency_name'],
|
2019-05-30 12:31:19 +02:00
|
|
|
'currency_symbol' => $journal['currency_symbol'],
|
2021-03-28 11:46:23 +02:00
|
|
|
'currency_code' => $journal['currency_code'],
|
2018-08-27 18:59:30 +02:00
|
|
|
];
|
|
|
|
}
|
2020-01-02 08:34:34 +01:00
|
|
|
$result[$key]['total'] = bcadd($journal['amount'], $result[$key]['total']);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
2016-12-11 17:05:48 +01:00
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$names = $this->getCategoryNames(array_keys($result));
|
2018-08-27 18:59:30 +02:00
|
|
|
foreach ($result as $row) {
|
|
|
|
$categoryId = $row['category_id'];
|
2018-08-28 04:29:16 +02:00
|
|
|
$name = $names[$categoryId] ?? '(unknown)';
|
2024-12-22 08:43:12 +01:00
|
|
|
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
|
2020-07-28 06:25:14 +02:00
|
|
|
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
|
2016-12-11 17:05:48 +01:00
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
$data = $this->generator->multiCurrencyPieChart($chartData);
|
2016-11-20 18:31:29 +01:00
|
|
|
$cache->store($data);
|
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($data);
|
2016-11-20 18:31:29 +01:00
|
|
|
}
|
|
|
|
|
2016-12-11 11:15:19 +01:00
|
|
|
/**
|
2018-07-21 08:06:24 +02:00
|
|
|
* Shows overview of account during a single period.
|
|
|
|
*
|
2021-09-18 10:26:12 +02:00
|
|
|
* @throws FireflyException
|
2023-12-22 20:12:38 +01:00
|
|
|
*/
|
2018-07-08 12:08:53 +02:00
|
|
|
public function period(Account $account, Carbon $start, Carbon $end): JsonResponse
|
2016-12-11 11:15:19 +01:00
|
|
|
{
|
2024-12-26 14:12:05 +01:00
|
|
|
Log::debug(sprintf('Now in period("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
2024-12-26 10:24:39 +01:00
|
|
|
$chartData = [];
|
|
|
|
$cache = new CacheProperties();
|
2018-02-09 16:47:01 +01:00
|
|
|
$cache->addProperty('chart.account.period');
|
2016-12-11 11:15:19 +01:00
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2024-12-26 05:11:32 +01:00
|
|
|
$cache->addProperty($this->convertToNative);
|
2016-12-11 11:15:19 +01:00
|
|
|
$cache->addProperty($account->id);
|
|
|
|
if ($cache->has()) {
|
2024-12-27 22:03:16 +01:00
|
|
|
return response()->json($cache->get());
|
2016-12-11 11:15:19 +01:00
|
|
|
}
|
2020-04-12 06:23:35 +02:00
|
|
|
|
2024-12-26 05:11:32 +01:00
|
|
|
// collect and filter balances for the entire period.
|
2024-12-26 10:24:39 +01:00
|
|
|
$step = $this->calculateStep($start, $end);
|
2024-12-26 05:11:32 +01:00
|
|
|
Log::debug(sprintf('Step is %s', $step));
|
2024-12-26 10:24:39 +01:00
|
|
|
$locale = app('steam')->getLocale();
|
|
|
|
$return = [];
|
2024-12-26 09:19:04 +01:00
|
|
|
|
2024-12-26 05:11:32 +01:00
|
|
|
// fix for issue https://github.com/firefly-iii/firefly-iii/issues/8041
|
|
|
|
// have to make sure this chart is always based on the balance at the END of the period.
|
|
|
|
// This period depends on the size of the chart
|
2024-12-26 10:24:39 +01:00
|
|
|
$current = clone $start;
|
|
|
|
$current = app('navigation')->endOfX($current, $step, null);
|
|
|
|
$format = (string) trans('config.month_and_day_js', [], $locale);
|
|
|
|
$accountCurrency = $this->accountRepository->getAccountCurrency($account);
|
2024-12-26 05:11:32 +01:00
|
|
|
|
|
|
|
Log::debug('One');
|
2024-12-26 10:24:39 +01:00
|
|
|
$range = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToNative);
|
2024-12-26 05:11:32 +01:00
|
|
|
Log::debug('Two');
|
2024-12-26 10:24:39 +01:00
|
|
|
$range = Steam::filterAccountBalances($range, $account, $this->convertToNative, $accountCurrency);
|
2024-12-26 05:11:32 +01:00
|
|
|
Log::debug('Three');
|
2024-12-26 08:53:16 +01:00
|
|
|
|
|
|
|
// temp, get end balance.
|
|
|
|
Log::debug('temp get end balance');
|
|
|
|
Steam::finalAccountBalance($account, $end);
|
|
|
|
Log::debug('END temp get end balance done');
|
|
|
|
|
|
|
|
$previous = array_values($range)[0];
|
2024-12-26 10:24:39 +01:00
|
|
|
$accountCurrency ??= $this->defaultCurrency; // do this AFTER getting the balances.
|
2024-12-26 08:53:16 +01:00
|
|
|
Log::debug('Start chart loop.');
|
|
|
|
|
2024-12-26 10:24:39 +01:00
|
|
|
$newRange = [];
|
|
|
|
$expectedIndex = 0;
|
2024-12-26 08:53:16 +01:00
|
|
|
Log::debug('Balances exist at:');
|
|
|
|
foreach ($range as $key => $value) {
|
|
|
|
$newRange[] = ['date' => $key, 'info' => $value];
|
|
|
|
Log::debug(sprintf(' - %s', $key));
|
|
|
|
}
|
2024-12-26 10:24:39 +01:00
|
|
|
$carbon = Carbon::createFromFormat('Y-m-d', $newRange[0]['date']);
|
2024-12-26 08:53:16 +01:00
|
|
|
while ($end->gte($current)) {
|
|
|
|
$momentBalance = $previous;
|
2024-12-26 10:24:39 +01:00
|
|
|
$theDate = $current->format('Y-m-d');
|
2024-12-26 08:53:16 +01:00
|
|
|
while ($carbon->lte($current) && array_key_exists($expectedIndex, $newRange)) {
|
|
|
|
$momentBalance = $newRange[$expectedIndex]['info'];
|
|
|
|
Log::debug(sprintf('Expected index is %d!, date is %s, current is %s', $expectedIndex, $carbon->format('Y-m-d'), $current->format('Y-m-d')));
|
2024-12-26 10:24:39 +01:00
|
|
|
$carbon = Carbon::createFromFormat('Y-m-d', $newRange[$expectedIndex]['date']);
|
|
|
|
++$expectedIndex;
|
2024-12-26 08:53:16 +01:00
|
|
|
}
|
|
|
|
|
2024-12-26 10:24:39 +01:00
|
|
|
$return = $this->updateChartKeys($return, $momentBalance);
|
|
|
|
$previous = $momentBalance;
|
2024-12-26 08:53:16 +01:00
|
|
|
|
|
|
|
Log::debug(sprintf('Now at %s', $theDate), $momentBalance);
|
2024-12-26 05:11:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
// process each balance thing.
|
2024-12-26 08:53:16 +01:00
|
|
|
foreach ($momentBalance as $key => $amount) {
|
|
|
|
$label = $current->isoFormat($format);
|
2024-12-26 05:11:32 +01:00
|
|
|
$return[$key]['entries'][$label] = $amount;
|
|
|
|
}
|
2024-12-26 10:24:39 +01:00
|
|
|
$current = app('navigation')->addPeriod($current, $step, 0);
|
2024-12-26 05:11:32 +01:00
|
|
|
// here too, to fix #8041, the data is corrected to the end of the period.
|
2024-12-26 10:24:39 +01:00
|
|
|
$current = app('navigation')->endOfX($current, $step, null);
|
2024-12-26 08:53:16 +01:00
|
|
|
Log::debug(sprintf('Next moment is %s', $current->format('Y-m-d')));
|
2024-12-26 09:19:04 +01:00
|
|
|
|
2020-04-12 06:23:35 +02:00
|
|
|
}
|
2024-12-26 08:53:16 +01:00
|
|
|
Log::debug('End of chart loop.');
|
2024-12-26 05:11:32 +01:00
|
|
|
// second loop (yes) to create nice array with info! Yay!
|
2024-12-26 10:24:39 +01:00
|
|
|
$chartData = [];
|
2024-12-26 09:19:04 +01:00
|
|
|
|
2024-12-26 08:53:16 +01:00
|
|
|
foreach ($return as $key => $info) {
|
|
|
|
if (3 === strlen($key)) {
|
2024-12-26 05:11:32 +01:00
|
|
|
// assume it's a currency:
|
2024-12-26 08:53:16 +01:00
|
|
|
$setCurrency = $this->currencyRepository->findByCode($key);
|
2024-12-26 05:11:32 +01:00
|
|
|
$info['currency_symbol'] = $setCurrency->symbol;
|
|
|
|
$info['currency_code'] = $setCurrency->code;
|
|
|
|
$info['label'] = sprintf('%s (%s)', $account->name, $setCurrency->symbol);
|
|
|
|
}
|
2024-12-26 08:53:16 +01:00
|
|
|
if ('balance' === $key) {
|
2024-12-26 05:11:32 +01:00
|
|
|
$info['currency_symbol'] = $accountCurrency->symbol;
|
|
|
|
$info['currency_code'] = $accountCurrency->code;
|
|
|
|
$info['label'] = sprintf('%s (%s)', $account->name, $accountCurrency->symbol);
|
|
|
|
}
|
2024-12-26 08:53:16 +01:00
|
|
|
if ('native_balance' === $key) {
|
2024-12-26 05:11:32 +01:00
|
|
|
$info['currency_symbol'] = $this->defaultCurrency->symbol;
|
|
|
|
$info['currency_code'] = $this->defaultCurrency->code;
|
2024-12-26 08:53:16 +01:00
|
|
|
$info['label'] = sprintf('%s (%s) (%s)', $account->name, (string) trans('firefly.sum'), $this->defaultCurrency->symbol);
|
2024-12-26 05:11:32 +01:00
|
|
|
}
|
|
|
|
$chartData[] = $info;
|
|
|
|
}
|
|
|
|
|
2024-12-26 10:24:39 +01:00
|
|
|
$data = $this->generator->multiSet($chartData);
|
2024-12-26 05:11:32 +01:00
|
|
|
$cache->store($data);
|
|
|
|
|
|
|
|
return response()->json($data);
|
2024-02-22 20:11:09 +01:00
|
|
|
}
|
|
|
|
|
2015-05-16 09:41:14 +02:00
|
|
|
/**
|
2016-05-13 15:53:39 +02:00
|
|
|
* Shows the balances for a given set of dates and accounts.
|
2015-05-16 09:41:14 +02:00
|
|
|
*
|
2022-10-30 11:43:17 +01:00
|
|
|
* TODO this chart is not multi currency aware.
|
2018-08-27 18:59:30 +02:00
|
|
|
*
|
2022-03-29 15:10:05 +02:00
|
|
|
* @throws FireflyException
|
2023-12-22 20:12:38 +01:00
|
|
|
*/
|
2018-07-08 12:08:53 +02:00
|
|
|
public function report(Collection $accounts, Carbon $start, Carbon $end): JsonResponse
|
2015-05-16 09:41:14 +02:00
|
|
|
{
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($this->accountBalanceChart($accounts, $start, $end));
|
2015-05-16 09:41:14 +02:00
|
|
|
}
|
2021-03-28 11:46:23 +02:00
|
|
|
|
2016-10-14 19:59:10 +02:00
|
|
|
/**
|
|
|
|
* Shows the balances for all the user's revenue accounts.
|
|
|
|
*
|
2018-08-27 18:59:30 +02:00
|
|
|
* This chart is multi-currency aware.
|
2023-12-22 20:12:38 +01:00
|
|
|
*/
|
2018-08-27 18:59:30 +02:00
|
|
|
public function revenueAccounts(): JsonResponse
|
2016-10-14 19:59:10 +02:00
|
|
|
{
|
2018-08-27 18:59:30 +02:00
|
|
|
/** @var Carbon $start */
|
2024-12-26 05:25:46 +01:00
|
|
|
$start = clone session('start', today(config('app.timezone'))->startOfMonth());
|
2023-12-20 19:35:52 +01:00
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
/** @var Carbon $end */
|
2024-12-26 05:25:46 +01:00
|
|
|
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
|
|
|
|
$cache = new CacheProperties();
|
2016-10-14 19:59:10 +02:00
|
|
|
$cache->addProperty($start);
|
|
|
|
$cache->addProperty($end);
|
2024-12-24 19:03:47 +01:00
|
|
|
$cache->addProperty($this->convertToNative);
|
2016-12-11 17:05:48 +01:00
|
|
|
$cache->addProperty('chart.account.revenue-accounts');
|
2016-10-14 19:59:10 +02:00
|
|
|
if ($cache->has()) {
|
2024-12-25 07:13:41 +01:00
|
|
|
return response()->json($cache->get());
|
2016-10-14 19:59:10 +02:00
|
|
|
}
|
|
|
|
$start->subDay();
|
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
// prep some vars:
|
2024-12-26 05:25:46 +01:00
|
|
|
$currencies = [];
|
|
|
|
$chartData = [];
|
|
|
|
$tempData = [];
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// grab all accounts and names
|
2024-12-26 05:25:46 +01:00
|
|
|
$accounts = $this->accountRepository->getAccountsByType([AccountTypeEnum::REVENUE->value]);
|
|
|
|
$accountNames = $this->extractNames($accounts);
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// grab all balances
|
2024-12-22 20:32:58 +01:00
|
|
|
$startBalances = app('steam')->finalAccountsBalance($accounts, $start);
|
|
|
|
$endBalances = app('steam')->finalAccountsBalance($accounts, $end);
|
2018-08-27 18:59:30 +02:00
|
|
|
|
2024-12-23 07:13:59 +01:00
|
|
|
|
2024-12-25 07:13:41 +01:00
|
|
|
// loop the accounts, then check for balance and currency info.
|
|
|
|
foreach ($accounts as $account) {
|
2024-12-31 08:18:40 +01:00
|
|
|
// Log::debug(sprintf('[b] Now in account #%d ("%s")', $account->id, $account->name));
|
2024-12-24 16:56:31 +01:00
|
|
|
$expenses = $endBalances[$account->id] ?? false;
|
2024-12-25 07:13:41 +01:00
|
|
|
if (false === $expenses) {
|
|
|
|
Log::error(sprintf('Found no end balance for account #%d', $account->id));
|
|
|
|
|
2024-12-24 16:56:31 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-24 16:56:31 +01:00
|
|
|
/**
|
|
|
|
* @var string $key
|
|
|
|
* @var string $endBalance
|
|
|
|
*/
|
|
|
|
foreach ($expenses as $key => $endBalance) {
|
2024-12-25 07:13:41 +01:00
|
|
|
if (!$this->convertToNative && 'native_balance' === $key) {
|
2024-12-24 16:56:31 +01:00
|
|
|
Log::debug(sprintf('[a] Will skip expense array "%s"', $key));
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-23 06:55:14 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-25 07:13:41 +01:00
|
|
|
if ($this->convertToNative && 'native_balance' !== $key) {
|
2024-12-24 16:56:31 +01:00
|
|
|
Log::debug(sprintf('[b] Will skip expense array "%s"', $key));
|
2024-12-25 07:13:41 +01:00
|
|
|
|
2024-12-24 16:56:31 +01:00
|
|
|
continue;
|
|
|
|
}
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
|
2024-12-30 10:51:34 +01:00
|
|
|
$searchCode = $this->convertToNative ? $this->defaultCurrency->code : $key;
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Search code is %s', $searchCode));
|
2018-08-27 18:59:30 +02:00
|
|
|
// see if there is an accompanying start amount.
|
|
|
|
// grab the difference and find the currency.
|
2024-12-24 16:56:31 +01:00
|
|
|
$startBalance = ($startBalances[$account->id][$key] ?? '0');
|
2024-12-31 08:09:51 +01:00
|
|
|
// Log::debug(sprintf('Start balance is %s', $startBalance));
|
2024-12-26 05:25:46 +01:00
|
|
|
$diff = bcsub($endBalance, $startBalance);
|
2024-12-24 16:56:31 +01:00
|
|
|
$currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode);
|
2018-08-27 18:59:30 +02:00
|
|
|
if (0 !== bccomp($diff, '0')) {
|
|
|
|
// store the values in a temporary array.
|
|
|
|
$tempData[] = [
|
2024-12-24 16:56:31 +01:00
|
|
|
'name' => $accountNames[$account->id],
|
2018-08-27 18:59:30 +02:00
|
|
|
'difference' => $diff,
|
2024-12-22 08:43:12 +01:00
|
|
|
'diff_float' => (float) $diff, // intentional float
|
2024-12-24 16:56:31 +01:00
|
|
|
'currency_id' => $currencies[$searchCode]->id,
|
2018-08-27 18:59:30 +02:00
|
|
|
];
|
|
|
|
}
|
2016-10-14 19:59:10 +02:00
|
|
|
}
|
2016-12-11 16:38:21 +01:00
|
|
|
}
|
2016-10-14 19:59:10 +02:00
|
|
|
|
2024-12-24 16:56:31 +01:00
|
|
|
|
2024-12-23 07:13:59 +01:00
|
|
|
// recreate currencies, but on ID instead of code.
|
|
|
|
$newCurrencies = [];
|
2024-12-23 08:40:29 +01:00
|
|
|
foreach ($currencies as $currency) {
|
2024-12-23 07:13:59 +01:00
|
|
|
$newCurrencies[$currency->id] = $currency;
|
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
$currencies = $newCurrencies;
|
2024-12-23 07:13:59 +01:00
|
|
|
|
2018-08-27 18:59:30 +02:00
|
|
|
// sort temp array by amount.
|
2024-12-26 05:25:46 +01:00
|
|
|
$amounts = array_column($tempData, 'diff_float');
|
2020-07-26 14:18:25 +02:00
|
|
|
array_multisort($amounts, SORT_ASC, $tempData);
|
2018-08-27 18:59:30 +02:00
|
|
|
|
|
|
|
// loop all found currencies and build the data array for the chart.
|
|
|
|
/**
|
2023-06-21 12:34:58 +02:00
|
|
|
* @var int $currencyId
|
2018-08-27 18:59:30 +02:00
|
|
|
* @var TransactionCurrency $currency
|
|
|
|
*/
|
|
|
|
foreach ($currencies as $currencyId => $currency) {
|
|
|
|
$dataSet
|
|
|
|
= [
|
2024-12-26 05:25:46 +01:00
|
|
|
'label' => (string) trans('firefly.earned'),
|
|
|
|
'type' => 'bar',
|
|
|
|
'currency_symbol' => $currency->symbol,
|
|
|
|
'currency_code' => $currency->code,
|
|
|
|
'entries' => $this->expandNames($tempData),
|
|
|
|
];
|
2018-08-27 18:59:30 +02:00
|
|
|
$chartData[$currencyId] = $dataSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
// loop temp data and place data in correct array:
|
|
|
|
foreach ($tempData as $entry) {
|
|
|
|
$currencyId = $entry['currency_id'];
|
|
|
|
$name = $entry['name'];
|
|
|
|
$chartData[$currencyId]['entries'][$name] = bcmul($entry['difference'], '-1');
|
|
|
|
}
|
|
|
|
|
2024-12-26 05:25:46 +01:00
|
|
|
$data = $this->generator->multiSet($chartData);
|
2016-10-14 19:59:10 +02:00
|
|
|
$cache->store($data);
|
|
|
|
|
2018-03-10 20:30:09 +01:00
|
|
|
return response()->json($data);
|
2016-10-14 19:59:10 +02:00
|
|
|
}
|
2024-12-26 05:11:32 +01:00
|
|
|
|
|
|
|
private function updateChartKeys(array $array, array $balances): array
|
|
|
|
{
|
|
|
|
foreach (array_keys($balances) as $key) {
|
|
|
|
$array[$key] ??= [
|
|
|
|
'key' => $key,
|
|
|
|
];
|
|
|
|
}
|
2024-12-26 05:25:46 +01:00
|
|
|
|
2024-12-26 05:11:32 +01:00
|
|
|
return $array;
|
|
|
|
}
|
2015-05-20 19:56:14 +02:00
|
|
|
}
|