diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index 72d26d1b57..d27622374f 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -27,6 +27,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\Http\Controllers\BasicDataSupport; use Illuminate\Contracts\View\Factory; @@ -70,22 +71,22 @@ class IndexController extends Controller * */ public function inactive(Request $request, string $objectType) { - $inactivePage = true; - $subTitle = (string) trans(sprintf('firefly.%s_accounts_inactive', $objectType)); - $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); - $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); - $collection = $this->repository->getInactiveAccountsByType($types); - $total = $collection->count(); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; - $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); + $inactivePage = true; + $subTitle = (string) trans(sprintf('firefly.%s_accounts_inactive', $objectType)); + $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); + $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); + $collection = $this->repository->getInactiveAccountsByType($types); + $total = $collection->count(); + $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); + $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); unset($collection); /** @var Carbon $start */ - $start = clone session('start', today(config('app.timezone'))->startOfMonth()); + $start = clone session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $end */ - $end = clone session('end', today(config('app.timezone'))->endOfMonth()); + $end = clone session('end', today(config('app.timezone'))->endOfMonth()); $start->subDay(); $ids = $accounts->pluck('id')->toArray(); @@ -94,13 +95,13 @@ class IndexController extends Controller $activities = app('steam')->getLastActivities($ids); - $accounts->each( function (Account $account) use ($activities, $startBalances, $endBalances): void { + $currency = $this->repository->getAccountCurrency($account); $account->lastActivityDate = $this->isInArrayDate($activities, $account->id); - $account->startBalance = $this->isInArray($startBalances, $account->id); - $account->endBalance = $this->isInArray($endBalances, $account->id); - $account->difference = bcsub($account->endBalance, $account->startBalance); + $account->startBalances = $this->getBalance($account, $currency, $startBalances); + $account->endBalances = $this->getBalance($account, $currency, $endBalances); + $account->differences = $this->subtract($account->startBalances, $account->endBalances); $account->interest = app('steam')->bcround($this->repository->getMetaValue($account, 'interest'), 4); $account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))); $account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type)); @@ -110,7 +111,7 @@ class IndexController extends Controller ); // make paginator: - $accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page); + $accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page); $accounts->setPath(route('accounts.inactive.index', [$objectType])); return view('accounts.index', compact('objectType', 'inactivePage', 'subTitleIcon', 'subTitle', 'page', 'accounts')); @@ -126,9 +127,9 @@ class IndexController extends Controller public function index(Request $request, string $objectType) { app('log')->debug(sprintf('Now at %s', __METHOD__)); - $subTitle = (string) trans(sprintf('firefly.%s_accounts', $objectType)); - $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); - $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); + $subTitle = (string) trans(sprintf('firefly.%s_accounts', $objectType)); + $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); + $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); $this->repository->resetAccountOrder(); @@ -144,10 +145,10 @@ class IndexController extends Controller unset($collection); /** @var Carbon $start */ - $start = clone session('start', today(config('app.timezone'))->startOfMonth()); + $start = clone session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $end */ - $end = clone session('end', today(config('app.timezone'))->endOfMonth()); + $end = clone session('end', today(config('app.timezone'))->endOfMonth()); $start->subDay(); $ids = $accounts->pluck('id')->toArray(); @@ -155,16 +156,17 @@ class IndexController extends Controller $endBalances = app('steam')->finalAccountsBalance($accounts, $end); $activities = app('steam')->getLastActivities($ids); + $accounts->each( function (Account $account) use ($activities, $startBalances, $endBalances): void { - $interest = (string) $this->repository->getMetaValue($account, 'interest'); - $interest = '' === $interest ? '0' : $interest; + $interest = (string) $this->repository->getMetaValue($account, 'interest'); + $interest = '' === $interest ? '0' : $interest; + $currency = $this->repository->getAccountCurrency($account); - // See reference nr. 68 + $account->startBalances = $this->getBalance($account, $currency, $startBalances); + $account->endBalances = $this->getBalance($account, $currency, $endBalances); + $account->differences = $this->subtract($account->startBalances, $account->endBalances); $account->lastActivityDate = $this->isInArrayDate($activities, $account->id); - $account->startBalance = $this->isInArray($startBalances, $account->id); - $account->endBalance = $this->isInArray($endBalances, $account->id); - $account->difference = bcsub($account->endBalance, $account->startBalance); $account->interest = app('steam')->bcround($interest, 4); $account->interestPeriod = (string) trans( sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')) @@ -173,14 +175,17 @@ class IndexController extends Controller $account->location = $this->repository->getLocation($account); $account->liability_direction = $this->repository->getMetaValue($account, 'liability_direction'); $account->current_debt = $this->repository->getMetaValue($account, 'current_debt') ?? '-'; + $account->currency = $currency; $account->iban = implode(' ', str_split((string) $account->iban, 4)); + + } ); // make paginator: app('log')->debug(sprintf('Count of accounts before LAP: %d', $accounts->count())); /** @var LengthAwarePaginator $accounts */ - $accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page); + $accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page); $accounts->setPath(route('accounts.index', [$objectType])); app('log')->debug(sprintf('Count of accounts after LAP (1): %d', $accounts->count())); @@ -188,4 +193,30 @@ class IndexController extends Controller return view('accounts.index', compact('objectType', 'inactiveCount', 'subTitleIcon', 'subTitle', 'page', 'accounts')); } + + private function getBalance(Account $account, ?TransactionCurrency $currency = null, array $balances): array + { + if (!array_key_exists($account->id, $balances)) { + return []; + } + $set = $balances[$account->id]; + + if ($this->convertToNative && $this->defaultCurrency->id === $currency?->id) { + unset($set['native_balance'], $set[$this->defaultCurrency->code]); + } + if ($this->convertToNative && null !== $currency && $this->defaultCurrency->id !== $currency->id) { + unset($set['balance']); + } + + return $set; + } + + private function subtract(array $startBalances, array $endBalances) + { + $result = []; + foreach ($endBalances as $key => $value) { + $result[$key] = bcsub($value, $startBalances[$key] ?? '0'); + } + return $result; + } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index f2e42d114e..13961cea44 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Http\Controllers\RequestInformation; use FireflyIII\Support\Http\Controllers\UserNavigation; @@ -53,6 +54,7 @@ abstract class Controller extends BaseController protected string $dateTimeFormat; protected string $monthAndDayFormat; protected bool $convertToNative = false; + protected TransactionCurrency $defaultCurrency; protected string $monthFormat; protected string $redirectUrl = '/'; @@ -111,6 +113,7 @@ abstract class Controller extends BaseController $this->monthFormat = (string) trans('config.month_js', [], $locale); $this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); $this->dateTimeFormat = (string) trans('config.date_time_js', [], $locale); + $this->defaultCurrency = app('amount')->getDefaultCurrency(); $darkMode = 'browser'; // get shown-intro-preference: if (auth()->check()) { diff --git a/app/Support/Steam.php b/app/Support/Steam.php index d50ba94bf2..6454d940ee 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -336,11 +336,11 @@ class Steam } // if the currency is the same as the native currency, set the native_balance to the balance for consistency. - if($currency->id === $native->id) { - $return['native_balance'] = $return['balance']; - } +// if($currency->id === $native->id) { +// $return['native_balance'] = $return['balance']; +// } - if (!$hasCurrency) { + if (!$hasCurrency && array_key_exists('balance', $return) && array_key_exists('native_balance', $return)) { Log::debug('Account has no currency preference, dropping balance in favor of native balance.'); $sum = bcadd($return['balance'], $return['native_balance']); Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum)); diff --git a/app/Support/Twig/AmountFormat.php b/app/Support/Twig/AmountFormat.php index 403aac5884..27f36ebe6d 100644 --- a/app/Support/Twig/AmountFormat.php +++ b/app/Support/Twig/AmountFormat.php @@ -75,6 +75,7 @@ class AmountFormat extends AbstractExtension $this->formatAmountByAccount(), $this->formatAmountBySymbol(), $this->formatAmountByCurrency(), + $this->formatAmountByCode() ]; } @@ -100,6 +101,25 @@ class AmountFormat extends AbstractExtension ); } + /** + * Use the code to format a currency. + */ + protected function formatAmountByCode(): TwigFunction + { + // formatAmountByCode + return new TwigFunction( + 'formatAmountByCode', + static function (string $amount, string $code, ?bool $coloured = null): string { + $coloured ??= true; + /** @var TransactionCurrency $currency */ + $currency = TransactionCurrency::whereCode($code)->first(); + + return app('amount')->formatAnything($currency, $amount, $coloured); + }, + ['is_safe' => ['html']] + ); + } + /** * Will format the amount by the currency related to the given account. */ @@ -108,8 +128,8 @@ class AmountFormat extends AbstractExtension return new TwigFunction( 'formatAmountBySymbol', static function (string $amount, string $symbol, ?int $decimalPlaces = null, ?bool $coloured = null): string { - $decimalPlaces ??= 2; - $coloured ??= true; + $decimalPlaces ??= 2; + $coloured ??= true; $currency = new TransactionCurrency(); $currency->symbol = $symbol; $currency->decimal_places = $decimalPlaces; diff --git a/resources/views/list/accounts.twig b/resources/views/list/accounts.twig index 75624856aa..b9bf401d13 100644 --- a/resources/views/list/accounts.twig +++ b/resources/views/list/accounts.twig @@ -66,14 +66,22 @@ {% if objectType != 'liabilities' %}