From c3bd46d7c01732573d15f627b603904f87958c24 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Jun 2022 19:24:08 +0200 Subject: [PATCH] Preference can be turned on and off (is always off now) --- .../Controllers/Chart/AccountController.php | 121 ++++++++++++ .../V2/Request/Generic/SingleDateRequest.php | 62 +++++++ .../Http/Api/ConvertsExchangeRates.php | 66 ++++++- .../src/api/v2/chart/account/dashboard.js | 30 +++ .../src/components/dashboard/AccountChart.vue | 175 ++++++++++++++++++ .../dashboard/NetWorthInsightBox.vue | 6 + frontend/src/pages/dashboard/Dashboard.vue | 6 +- routes/api.php | 11 ++ 8 files changed, 473 insertions(+), 4 deletions(-) create mode 100644 app/Api/V2/Controllers/Chart/AccountController.php create mode 100644 app/Api/V2/Request/Generic/SingleDateRequest.php create mode 100644 frontend/src/api/v2/chart/account/dashboard.js create mode 100644 frontend/src/components/dashboard/AccountChart.vue diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php new file mode 100644 index 0000000000..67be4015ce --- /dev/null +++ b/app/Api/V2/Controllers/Chart/AccountController.php @@ -0,0 +1,121 @@ +. + */ + +namespace FireflyIII\Api\V2\Controllers\Chart; + +use Carbon\Carbon; +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use Illuminate\Http\JsonResponse; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ + use ConvertsExchangeRates; + + private AccountRepositoryInterface $repository; + + /** + * + */ + public function __construct() + { + $this->middleware( + function ($request, $next) { + $this->repository = app(AccountRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function dashboard(DateRequest $request): JsonResponse + { + // parameters for chart: + $dates = $request->getAll(); + /** @var Carbon $start */ + $start = $dates['start']; + /** @var Carbon $end */ + $end = $dates['end']; + + // user's preferences + $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray(); + $frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); + $default = app('amount')->getDefaultCurrency(); + $accounts = $this->repository->getAccountsById($frontPage->data); + $chartData = []; + + if (empty($frontPage->data)) { + $frontPage->data = $defaultSet; + $frontPage->save(); + } + + /** @var Account $account */ + foreach ($accounts as $account) { + $currency = $this->repository->getAccountCurrency($account); + if (null === $currency) { + $currency = $default; + } + $currentSet = [ + 'label' => $account->name, + 'currency_id' => (string) $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + 'native_id' => null, + 'native_code' => null, + 'native_symbol' => null, + 'native_decimal_places' => null, + 'start_date' => $start->toAtomString(), + 'end_date' => $end->toAtomString(), + 'type' => 'line', // line, area or bar + 'yAxisID' => 0, // 0, 1, 2 + 'entries' => [], + ]; + $currentStart = clone $start; + $range = app('steam')->balanceInRange($account, $start, clone $end); + $previous = round((float) array_values($range)[0], 12); + while ($currentStart <= $end) { + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->toAtomString(); + $balance = array_key_exists($format, $range) ? round((float) $range[$format], 12) : $previous; + $previous = $balance; + $currentStart->addDay(); + $currentSet['entries'][$label] = $balance; + } + $currentSet = $this->cerChartSet($currentSet); + $chartData[] = $currentSet; + } + + return response()->json($chartData); + return response()->json(['x']); + } + +} diff --git a/app/Api/V2/Request/Generic/SingleDateRequest.php b/app/Api/V2/Request/Generic/SingleDateRequest.php new file mode 100644 index 0000000000..76a6ab096c --- /dev/null +++ b/app/Api/V2/Request/Generic/SingleDateRequest.php @@ -0,0 +1,62 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Request\Generic; + +use Carbon\Carbon; +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Request class for end points that require a date parameter. + * + * Class SingleDateRequest + */ +class SingleDateRequest extends FormRequest +{ + use ConvertsDataTypes, ChecksLogin; + + /** + * Get all data from the request. + * + * @return Carbon + */ + public function getDate(): Carbon + { + return $this->getCarbonDate('date'); + } + + /** + * The rules that the incoming request must be matched against. + * + * @return array + */ + public function rules(): array + { + return [ + 'date' => 'required|date', + ]; + } +} diff --git a/app/Support/Http/Api/ConvertsExchangeRates.php b/app/Support/Http/Api/ConvertsExchangeRates.php index 4b94e50cbe..e56c64a909 100644 --- a/app/Support/Http/Api/ConvertsExchangeRates.php +++ b/app/Support/Http/Api/ConvertsExchangeRates.php @@ -22,6 +22,7 @@ namespace FireflyIII\Support\Http\Api; use Carbon\Carbon; +use DateTimeInterface; use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\TransactionCurrency; use Log; @@ -31,6 +32,8 @@ use Log; */ trait ConvertsExchangeRates { + private ?bool $enabled = null; + /** * For a sum of entries, get the exchange rate to the native currency of * the user. @@ -39,12 +42,29 @@ trait ConvertsExchangeRates */ public function cerSum(array $entries): array { + if (null === $this->enabled) { + $this->getPreference(); + } + + // if false, return the same array without conversion info + if (false === $this->enabled) { + $return = []; + /** @var array $entry */ + foreach ($entries as $entry) { + $entry['converted'] = false; + $return[] = $entry; + } + return $return; + } + + /** @var TransactionCurrency $native */ $native = app('amount')->getDefaultCurrency(); $return = []; /** @var array $entry */ foreach ($entries as $entry) { - $currency = $this->getCurrency((int) $entry['id']); + $currency = $this->getCurrency((int) $entry['id']); + $entry['converted'] = true; if ($currency->id !== $native->id) { $amount = $this->convertAmount($entry['sum'], $currency, $native); $entry['native_sum'] = $amount; @@ -68,6 +88,42 @@ trait ConvertsExchangeRates return $return; } + /** + * @param array $set + * @return array + */ + public function cerChartSet(array $set): array + { + if (null === $this->enabled) { + $this->getPreference(); + } + + // if not enabled, return the same array but without conversion: + if (false === $this->enabled) { + $set['converted'] = false; + return $set; + } + + $set['converted'] = true; + /** @var TransactionCurrency $native */ + $native = app('amount')->getDefaultCurrency(); + $currency = $this->getCurrency((int) $set['currency_id']); + if ($native->id === $currency->id) { + $set['native_id'] = (string) $currency->id; + $set['native_code'] = $currency->code; + $set['native_symbol'] = $currency->symbol; + $set['native_decimal_places'] = $currency->decimal_places; + return $set; + } + foreach ($set['entries'] as $date => $entry) { + $carbon = Carbon::createFromFormat(DateTimeInterface::ATOM, $date); + $rate = $this->getRate($currency, $native, $carbon); + $rate = '0' === $rate ? '1' : $rate; + $set['entries'][$date] = (float) bcmul((string) $entry, $rate); + } + return $set; + } + /** * @param int $currencyId * @return TransactionCurrency @@ -199,4 +255,12 @@ trait ConvertsExchangeRates return '0'; } + /** + * @return void + */ + private function getPreference(): void + { + $this->enabled = false; + } + } diff --git a/frontend/src/api/v2/chart/account/dashboard.js b/frontend/src/api/v2/chart/account/dashboard.js new file mode 100644 index 0000000000..c131ff2ae9 --- /dev/null +++ b/frontend/src/api/v2/chart/account/dashboard.js @@ -0,0 +1,30 @@ +/* + * overview.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class Dashboard { + overview(range, cacheKey) { + let startStr = format(range.start, 'y-MM-dd'); + let endStr = format(range.end, 'y-MM-dd'); + return api.get('/api/v2/chart/account/dashboard', {params: {start: startStr, end: endStr, cache: cacheKey}}); + } +} diff --git a/frontend/src/components/dashboard/AccountChart.vue b/frontend/src/components/dashboard/AccountChart.vue new file mode 100644 index 0000000000..89cf6a4172 --- /dev/null +++ b/frontend/src/components/dashboard/AccountChart.vue @@ -0,0 +1,175 @@ + + + + + + + diff --git a/frontend/src/components/dashboard/NetWorthInsightBox.vue b/frontend/src/components/dashboard/NetWorthInsightBox.vue index 6f5d9048cb..2b9ba204ef 100644 --- a/frontend/src/components/dashboard/NetWorthInsightBox.vue +++ b/frontend/src/components/dashboard/NetWorthInsightBox.vue @@ -96,10 +96,16 @@ export default { for (let i in data) { if (data.hasOwnProperty(i)) { const current = data[i]; + + if(parseFloat(current.sum) <= 0) { + continue; + } + const hasNative = current.native_id !== current.id && current.native_sum !== '0'; if (hasNative || current.native_id === current.id) { this.primary = this.primary + parseFloat(current.native_sum); } + this.netWorth.push( { sum: current.sum, diff --git a/frontend/src/pages/dashboard/Dashboard.vue b/frontend/src/pages/dashboard/Dashboard.vue index 4835e58ec3..c7d0cf5699 100644 --- a/frontend/src/pages/dashboard/Dashboard.vue +++ b/frontend/src/pages/dashboard/Dashboard.vue @@ -35,7 +35,7 @@
- Account chart box +
@@ -89,12 +89,12 @@