diff --git a/app/Api/V1/Controllers/Chart/AccountController.php b/app/Api/V1/Controllers/Chart/AccountController.php index 5b0c35373c..1e80d1c650 100644 --- a/app/Api/V1/Controllers/Chart/AccountController.php +++ b/app/Api/V1/Controllers/Chart/AccountController.php @@ -24,16 +24,16 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Chart; -use FireflyIII\Exceptions\ValidationException; -use FireflyIII\Models\TransactionCurrency; use Carbon\Carbon; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Chart\ChartRequest; use FireflyIII\Api\V1\Requests\Data\DateRequest; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Exceptions\ValidationException; use FireflyIII\Models\Account; use FireflyIII\Models\Preference; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\Chart\ChartData; use FireflyIII\Support\Facades\Preferences; @@ -42,6 +42,7 @@ use FireflyIII\Support\Http\Api\ApiSupport; use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; /** * Class AccountController @@ -90,6 +91,7 @@ class AccountController extends Controller // loop each account, and collect info: /** @var Account $account */ foreach ($accounts as $account) { + Log::debug(sprintf('Account #%d ("%s")', $account->id, $account->name)); $this->renderAccountData($queryParameters, $account); } @@ -101,15 +103,22 @@ class AccountController extends Controller */ private function renderAccountData(array $params, Account $account): void { - $currency = $this->repository->getAccountCurrency($account); + Log::debug(sprintf('Now in %s(array, #%d)', __METHOD__, $account->id)); + $currency = $this->repository->getAccountCurrency($account); + $currentStart = clone $params['start']; + $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); + + + $previous = array_values($range)[0]['balance']; + $nativePrevious = null; if (!$currency instanceof TransactionCurrency) { $currency = $this->default; } - $currentSet = [ + $currentSet = [ 'label' => $account->name, // the currency that belongs to the account. - 'currency_id' => (string) $currency->id, + 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, @@ -121,18 +130,33 @@ class AccountController extends Controller 'period' => '1D', 'entries' => [], ]; - $currentStart = clone $params['start']; - $range = Steam::finalAccountBalanceInRange($account, $params['start'], clone $params['end'], $this->convertToNative); + if ($this->convertToNative) { + $currentSet['native_entries'] = []; + $currentSet['native_currency_id'] = (string)$this->nativeCurrency->id; + $currentSet['native_currency_code'] = $this->nativeCurrency->code; + $currentSet['native_currency_symbol'] = $this->nativeCurrency->symbol; + $currentSet['native_currency_decimal_places'] = $this->nativeCurrency->decimal_places; + $nativePrevious = array_values($range)[0]['native_balance']; + } + - $previous = array_values($range)[0]['balance']; while ($currentStart <= $params['end']) { - $format = $currentStart->format('Y-m-d'); - $label = $currentStart->toAtomString(); - $balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; - $previous = $balance; + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->toAtomString(); + $balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; + $previous = $balance; + $currentSet['entries'][$label] = $balance; + + + // do the same for the native balance, if relevant: + $nativeBalance = null; + if ($this->convertToNative) { + $nativeBalance = array_key_exists($format, $range) ? $range[$format]['native_balance'] : $nativePrevious; + $nativePrevious = $nativeBalance; + $currentSet['native_entries'][$label] = $nativeBalance; + } $currentStart->addDay(); - $currentSet['entries'][$label] = $balance; } $this->chartData->add($currentSet); } @@ -146,40 +170,34 @@ class AccountController extends Controller public function overview(DateRequest $request): JsonResponse { // parameters for chart: - $dates = $request->getAll(); + $dates = $request->getAll(); + /** @var Carbon $start */ - $start = $dates['start']; + $start = $dates['start']; /** @var Carbon $end */ - $end = $dates['end']; + $end = $dates['end']; // set dates to end of day + start of day: $start->startOfDay(); $end->endOfDay(); - // user's preferences - $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); - - /** @var Preference $frontpage */ - $frontpage = Preferences::get('frontpageAccounts', $defaultSet); - - if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { - $frontpage->data = $defaultSet; - $frontpage->save(); - } - - // get accounts: - $accounts = $this->repository->getAccountsById($frontpage->data); - $chartData = []; + $frontPageIds = $this->getFrontPageAccountIds(); + $accounts = $this->repository->getAccountsById($frontPageIds); + $chartData = []; /** @var Account $account */ foreach ($accounts as $account) { - $currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency; - $field = $this->convertToNative && $currency->id !== $this->nativeCurrency->id ? 'native_balance' : 'balance'; - $currentSet = [ + Log::debug(sprintf('Rendering chart data for account %s (%d)', $account->name, $account->id)); + $currency = $this->repository->getAccountCurrency($account) ?? $this->nativeCurrency; + $currentStart = clone $start; + $range = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative); + $previous = array_values($range)[0]['balance']; + $nativePrevious = null; + $currentSet = [ 'label' => $account->name, - 'currency_id' => (string) $currency->id, + 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, @@ -189,21 +207,56 @@ class AccountController extends Controller 'yAxisID' => 0, // 0, 1, 2 'entries' => [], ]; - // TODO this code is also present in the V2 chart account controller so this method is due to be deprecated. - $currentStart = clone $start; - $range = Steam::finalAccountBalanceInRange($account, $start, clone $end, $this->convertToNative); - $previous = array_values($range)[0][$field]; - while ($currentStart <= $end) { - $format = $currentStart->format('Y-m-d'); - $label = $currentStart->toAtomString(); - $balance = array_key_exists($format, $range) ? $range[$format][$field] : $previous; - $previous = $balance; - $currentStart->addDay(); - $currentSet['entries'][$label] = $balance; + + // add "native_entries" if convertToNative is true: + if ($this->convertToNative) { + $currentSet['native_entries'] = []; + $currentSet['native_currency_id'] = (string)$this->nativeCurrency->id; + $currentSet['native_currency_code'] = $this->nativeCurrency->code; + $currentSet['native_currency_symbol'] = $this->nativeCurrency->symbol; + $currentSet['native_currency_decimal_places'] = $this->nativeCurrency->decimal_places; + $nativePrevious = array_values($range)[0]['native_balance']; + } - $chartData[] = $currentSet; + + // also get the native balance if convertToNative is true: + while ($currentStart <= $end) { + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->toAtomString(); + + // balance is based on "balance" from the $range variable. + $balance = array_key_exists($format, $range) ? $range[$format]['balance'] : $previous; + $previous = $balance; + $currentSet['entries'][$label] = $balance; + + // do the same for the native balance, if relevant: + $nativeBalance = null; + if ($this->convertToNative) { + $nativeBalance = array_key_exists($format, $range) ? $range[$format]['native_balance'] : $nativePrevious; + $nativePrevious = $nativeBalance; + $currentSet['native_entries'][$label] = $nativeBalance; + } + + $currentStart->addDay(); + + } + $chartData[] = $currentSet; } return response()->json($chartData); } + + private function getFrontPageAccountIds(): array + { + $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); + + /** @var Preference $frontpage */ + $frontpage = Preferences::get('frontpageAccounts', $defaultSet); + + if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { + $frontpage->data = $defaultSet; + $frontpage->save(); + } + return $frontpage->data ?? $defaultSet; + } } diff --git a/app/Support/Amount.php b/app/Support/Amount.php index fbbe67a957..a373758814 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -120,8 +120,6 @@ class Amount if (!$user instanceof User) { return true === Preferences::get('convert_to_native', false)->data && true === config('cer.enabled'); } - Log::debug('convertToNative setting', Preferences::getForUser($user, 'convert_to_native', false)); - return true === Preferences::getForUser($user, 'convert_to_native', false)->data && true === config('cer.enabled'); } diff --git a/app/Support/Steam.php b/app/Support/Steam.php index aa025fbe5d..a8cde113cf 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -93,7 +93,7 @@ class Steam return []; } - $defaultCurrency = app('amount')->getNativeCurrency(); + $defaultCurrency = Amount::getNativeCurrency(); if ($convertToNative) { if ($defaultCurrency->id === $currency?->id) { Log::debug(sprintf('Unset [%s] for account #%d (no longer unset "native_balance")', $defaultCurrency->code, $account->id)); @@ -224,7 +224,7 @@ class Steam $request->subDay()->endOfDay(); Log::debug(sprintf('finalAccountBalanceInRange: Call finalAccountBalance with date/time "%s"', $request->toIso8601String())); $startBalance = $this->finalAccountBalance($account, $request); - $nativeCurrency = app('amount')->getNativeCurrencyByUserGroup($account->user->userGroup); + $nativeCurrency = Amount::getNativeCurrencyByUserGroup($account->user->userGroup); $accountCurrency = $this->getAccountCurrency($account); $hasCurrency = $accountCurrency instanceof TransactionCurrency; $currency = $accountCurrency ?? $nativeCurrency; @@ -294,7 +294,7 @@ class Steam $currentBalance[$entryCurrency->code] ??= '0'; $currentBalance[$entryCurrency->code] = bcadd($sumOfDay, (string) $currentBalance[$entryCurrency->code]); - // if not convert to native, add the amount to "balance", do nothing else. + // if not requested to convert to native, add the amount to "balance", do nothing else. if (!$convertToNative) { $currentBalance['balance'] = bcadd((string) $currentBalance['balance'], $sumOfDay); } @@ -302,13 +302,13 @@ class Steam // if there is a request to convert, convert to "native_balance" and use "balance" for whichever amount is in the native currency. if ($convertToNative) { $nativeSumOfDay = $converter->convert($entryCurrency, $nativeCurrency, $carbon, $sumOfDay); - $currentBalance['native_balance'] = bcadd((string) $currentBalance['native_balance'], $nativeSumOfDay); + $currentBalance['native_balance'] = bcadd((string) ($currentBalance['native_balance'] ?? '0'), $nativeSumOfDay); + // if it's the same currency as the entry, also add to balance (see other code). if ($currency->id === $entryCurrency->id) { $currentBalance['balance'] = bcadd((string) $currentBalance['balance'], $sumOfDay); } - } - // just set it. + // add to final array. $balances[$carbonKey] = $currentBalance; Log::debug(sprintf('Updated entry [%s]', $carbonKey), $currentBalance); } diff --git a/resources/assets/v2/src/pages/dashboard/accounts.js b/resources/assets/v2/src/pages/dashboard/accounts.js index fa1b40c97a..ba1f32cff4 100644 --- a/resources/assets/v2/src/pages/dashboard/accounts.js +++ b/resources/assets/v2/src/pages/dashboard/accounts.js @@ -53,6 +53,11 @@ export default () => ({ eventListeners: { ['@convert-to-native.window'](event){ console.log('I heard that! it is now ' + event.detail); + this.convertToNative = event.detail; + this.accountList = []; + chartData = null; + this.loadChart(); + this.loadAccounts(); } }, @@ -61,6 +66,7 @@ export default () => ({ console.log('doSomeReload'); }, getFreshData() { + console.log('get fresh data'); const start = new Date(window.store.get('start')); const end = new Date(window.store.get('end')); const chartCacheKey = getCacheKey(this.localCacheKey('chart'), {start: start, end: end}) @@ -101,18 +107,20 @@ export default () => ({ dataset.label = current.label; // use the "native" currency code and use the "native_entries" as array - // if (this.convertToNative) { - // currencies.push(current.native_currency_code); - // dataset.currency_code = current.native_currency_code; - // collection = Object.values(current.native_entries); - // yAxis = 'y' + current.native_currency_code; - // } - // if (!this.convertToNative) { + if (this.convertToNative) { + console.log('Convert to native!'); + currencies.push(current.native_currency_code); + dataset.currency_code = current.native_currency_code; + collection = Object.values(current.native_entries); + yAxis = 'y' + current.native_currency_code; + } + if (!this.convertToNative) { + console.log('NO convert to native!', this.convertToNative); yAxis = 'y' + current.currency_code; dataset.currency_code = current.currency_code; currencies.push(current.currency_code); collection = Object.values(current.entries); - // } + } dataset.yAxisID = yAxis; dataset.data = collection; @@ -147,7 +155,9 @@ export default () => ({ return options; }, loadChart() { + console.log('loadChart'); if (true === this.loading) { + console.log('already loading chart'); return; } this.loading = true; @@ -165,6 +175,7 @@ export default () => ({ chart.options = options.options; chart.data = options.data; chart.update(); + console.log('refresh chart'); return; } chart = new Chart(document.querySelector("#account-chart"), options); @@ -294,6 +305,7 @@ export default () => ({ this.convertToNative = values[1] && values[3]; this.convertToNativeAvailable = values[3]; afterPromises = true; + console.log('convertToNative in accounts.js: ', values); // main dashboard chart: this.loadChart(); diff --git a/resources/assets/v2/src/pages/dashboard/dashboard.js b/resources/assets/v2/src/pages/dashboard/dashboard.js index c11f4f9961..f376a6aa97 100644 --- a/resources/assets/v2/src/pages/dashboard/dashboard.js +++ b/resources/assets/v2/src/pages/dashboard/dashboard.js @@ -78,7 +78,6 @@ let index = function () { init() { Promise.all([getVariable('convert_to_native', false)]).then((values) => { this.convertToNative = values[0]; - console.log('convert_to_native: ' + this.convertToNative); }); } } diff --git a/resources/assets/v2/src/store/get-configuration.js b/resources/assets/v2/src/store/get-configuration.js index 814f906c81..d3d2a7c53a 100644 --- a/resources/assets/v2/src/store/get-configuration.js +++ b/resources/assets/v2/src/store/get-configuration.js @@ -27,19 +27,29 @@ export function getConfiguration(name, defaultValue = null) { // to make things available quicker than if the store has to grab it through the API. // then again, it's not that slow. if (validCache && window.hasOwnProperty(name)) { - // console.log('Get from window'); + console.log('Return configuration "' + name + '" from window: ' + window[name]); return Promise.resolve(window[name]); } // load from store2, if it's present. const fromStore = window.store.get(name); if (validCache && typeof fromStore !== 'undefined') { + console.log('Return configuration "' + name + '" from store: ' + fromStore); return Promise.resolve(fromStore); } let getter = (new Get); return getter.getByName(name).then((response) => { // console.log('Get "' + name + '" from API'); - return Promise.resolve(parseResponse(name, response)); - }).catch(() => { + console.log('Return configuration "' + name + '" from API: ' + parseConfigurationResponse(name, response)); + return Promise.resolve(parseConfigurationResponse(name, response)); + }).catch((error) => { + console.log('Returning "'+name+'" from DEFAULT: ' + defaultValue); + console.warn(error); return defaultValue; }); } +export function parseConfigurationResponse(name, response) { + let value = response.data.data.value; + window.store.set(name, value); + return value; +} + diff --git a/resources/assets/v2/src/store/get-variable.js b/resources/assets/v2/src/store/get-variable.js index f0bb1b26b7..b3010827b0 100644 --- a/resources/assets/v2/src/store/get-variable.js +++ b/resources/assets/v2/src/store/get-variable.js @@ -27,16 +27,19 @@ export function getVariable(name, defaultValue = null) { // to make things available quicker than if the store has to grab it through the API. // then again, it's not that slow. if (validCache && window.hasOwnProperty(name)) { + console.log('Returning "'+name+'" from window: ' + window[name]); return Promise.resolve(window[name]); } // load from store2, if it's present. const fromStore = window.store.get(name); if (validCache && typeof fromStore !== 'undefined') { + console.log('Returning "'+name+'" from store: ' + fromStore); return Promise.resolve(fromStore); } let getter = (new Get); return getter.getByName(name).then((response) => { + console.log('Returning "'+name+'" from server: ' + parseResponse(name, response)); return Promise.resolve(parseResponse(name, response)); }).catch((error) => { if('' === defaultValue) { @@ -47,6 +50,7 @@ export function getVariable(name, defaultValue = null) { // POST it and then return it anyway. let poster = (new Post); return poster.post(name, defaultValue).then((response) => { + console.log('Returning "'+name+'" from POST: ' + parseResponse(name, response)); return Promise.resolve(parseResponse(name, response)); }); });