diff --git a/app/Api/V1/Controllers/Summary/BasicController.php b/app/Api/V1/Controllers/Summary/BasicController.php index e374d0f78c..cce6a7dc4a 100644 --- a/app/Api/V1/Controllers/Summary/BasicController.php +++ b/app/Api/V1/Controllers/Summary/BasicController.php @@ -32,7 +32,6 @@ use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; @@ -94,24 +93,24 @@ class BasicController extends Controller public function basic(DateRequest $request): JsonResponse { // parameters for boxes: - $dates = $request->getAll(); - $start = $dates['start']; - $end = $dates['end']; - $code = $request->get('currency_code'); + $dates = $request->getAll(); + $start = $dates['start']; + $end = $dates['end']; + $code = $request->get('currency_code'); // balance information: $balanceData = $this->getBalanceInformation($start, $end); $billData = $this->getBillInformation($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end); $netWorthData = $this->getNetWorthInfo($start, $end); -// $balanceData = []; -// $billData = []; -// $spentData = []; -// $netWorthData = []; + // $balanceData = []; + // $billData = []; + // $spentData = []; + // $netWorthData = []; $total = array_merge($balanceData, $billData, $spentData, $netWorthData); // give new keys - $return = []; + $return = []; foreach ($total as $entry) { if (null === $code || ($code === $entry['currency_code'])) { $return[$entry['key']] = $entry; @@ -125,19 +124,19 @@ class BasicController extends Controller { // some config settings $convertToNative = app('preferences')->get('convert_to_native', false)->data; - $default = app('amount')->getDefaultCurrency(); + $default = app('amount')->getDefaultCurrency(); // prep some arrays: - $incomes = []; - $expenses = []; - $sums = []; - $return = []; + $incomes = []; + $expenses = []; + $sums = []; + $return = []; // collect income of user using the new group collector. /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::DEPOSIT->value]); - $set = $collector->getExtractedJournals(); + $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { @@ -154,14 +153,14 @@ class BasicController extends Controller // collect expenses of user using the new group collector. /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end)->setPage($this->parameters->get('page'))->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); - $set = $collector->getExtractedJournals(); + $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { - $currencyId = $convertToNative ? $default->id : (int) $journal['currency_id']; - $amount = Amount::getAmountFromJournal($journal); + $currencyId = $convertToNative ? $default->id : (int) $journal['currency_id']; + $amount = Amount::getAmountFromJournal($journal); $expenses[$currencyId] ??= '0'; $expenses[$currencyId] = bcadd($expenses[$currencyId], $amount); $sums[$currencyId] ??= '0'; @@ -169,7 +168,7 @@ class BasicController extends Controller } // format amounts: - $keys = array_keys($sums); + $keys = array_keys($sums); foreach ($keys as $currencyId) { $currency = $this->currencyRepos->find($currencyId); if (null === $currency) { @@ -186,8 +185,8 @@ class BasicController extends Controller 'currency_decimal_places' => $currency->decimal_places, 'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false), 'local_icon' => 'balance-scale', - 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) . - ' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), + 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false). + ' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), ]; $return[] = [ 'key' => sprintf('spent-in-%s', $currency->code), @@ -228,7 +227,7 @@ class BasicController extends Controller $paidAmount = $this->billRepository->sumPaidInRange($start, $end); $unpaidAmount = $this->billRepository->sumUnpaidInRange($start, $end); - $return = []; + $return = []; /** * @var array $info @@ -298,7 +297,7 @@ class BasicController extends Controller Log::debug(sprintf('Spent %s %s', $row['currency_code'], $row['sum'])); - $return[] = [ + $return[] = [ 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]), 'monetary_value' => $leftToSpend, @@ -323,9 +322,10 @@ class BasicController extends Controller private function getNetWorthInfo(Carbon $start, Carbon $end): array { Log::debug('getNetWorthInfo'); + /** @var User $user */ - $user = auth()->user(); - $date = now(config('app.timezone')); + $user = auth()->user(); + $date = now(config('app.timezone')); // start and end in the future? use $end if ($this->notInDateRange($date, $start, $end)) { /** @var Carbon $date */ @@ -335,10 +335,10 @@ class BasicController extends Controller /** @var NetWorthInterface $netWorthHelper */ $netWorthHelper = app(NetWorthInterface::class); $netWorthHelper->setUser($user); - $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]); + $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value]); // filter list on preference of being included. - $filtered = $allAccounts->filter( + $filtered = $allAccounts->filter( function (Account $account) { $includeNetWorth = $this->accountRepository->getMetaValue($account, 'include_net_worth'); @@ -346,13 +346,13 @@ class BasicController extends Controller } ); - $netWorthSet = $netWorthHelper->byAccounts($filtered, $date); - $return = []; + $netWorthSet = $netWorthHelper->byAccounts($filtered, $date); + $return = []; foreach ($netWorthSet as $key => $data) { if ('native' === $key) { continue; } - $amount = $data['balance']; + $amount = $data['balance']; if (0 === bccomp($amount, '0')) { continue; } diff --git a/app/Console/Commands/Correction/RecalculateNativeAmounts.php b/app/Console/Commands/Correction/RecalculateNativeAmounts.php index 9d97a2c091..226e5ff538 100644 --- a/app/Console/Commands/Correction/RecalculateNativeAmounts.php +++ b/app/Console/Commands/Correction/RecalculateNativeAmounts.php @@ -212,10 +212,10 @@ class RecalculateNativeAmounts extends Command ->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->where('transaction_journals.user_group_id', $userGroup->id) - ->where(function(DatabaseBuilder $q1) use ($currency) { - $q1->where(function(DatabaseBuilder $q2) use ($currency) { + ->where(function (DatabaseBuilder $q1) use ($currency): void { + $q1->where(function (DatabaseBuilder $q2) use ($currency): void { $q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id'); - })->orWhere(function(DatabaseBuilder $q3) use ($currency) { + })->orWhere(function (DatabaseBuilder $q3) use ($currency): void { $q3->whereNot('transactions.transaction_currency_id', $currency->id)->whereNot('transactions.foreign_currency_id', $currency->id); }); }) diff --git a/app/Helpers/Report/NetWorth.php b/app/Helpers/Report/NetWorth.php index 1a8a9d5a9f..2b5c17c944 100644 --- a/app/Helpers/Report/NetWorth.php +++ b/app/Helpers/Report/NetWorth.php @@ -77,28 +77,28 @@ class NetWorth implements NetWorthInterface // return $cache->get(); } Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s'))); - $default = Amount::getDefaultCurrency(); - $netWorth = []; - $balances = Steam::finalAccountsBalance($accounts, $date); + $default = Amount::getDefaultCurrency(); + $netWorth = []; + $balances = Steam::finalAccountsBalance($accounts, $date); /** @var Account $account */ foreach ($accounts as $account) { Log::debug(sprintf('Now at account #%d ("%s")', $account->id, $account->name)); - $currency = $this->getRepository()->getAccountCurrency($account) ?? $default; - $useNative = $convertToNative && $default->id !== $currency->id; - $currency = $useNative ? $default : $currency; - $currencyCode = $currency->code; - $balance = '0'; - $nativeBalance = '0'; + $currency = $this->getRepository()->getAccountCurrency($account) ?? $default; + $useNative = $convertToNative && $default->id !== $currency->id; + $currency = $useNative ? $default : $currency; + $currencyCode = $currency->code; + $balance = '0'; + $nativeBalance = '0'; if (array_key_exists($account->id, $balances)) { $balance = $balances[$account->id]['balance'] ?? '0'; $nativeBalance = $balances[$account->id]['native_balance'] ?? '0'; } Log::debug(sprintf('Balance is %s, native balance is %s', $balance, $nativeBalance)); // always subtract virtual balance again. - $balance = '' !== (string) $account->virtual_balance ? bcsub($balance, $account->virtual_balance) : $balance; - $nativeBalance = '' !== (string) $account->native_virtual_balance ? bcsub($nativeBalance, $account->native_virtual_balance) : $nativeBalance; - $amountToUse = $useNative ? $nativeBalance : $balance; + $balance = '' !== (string) $account->virtual_balance ? bcsub($balance, $account->virtual_balance) : $balance; + $nativeBalance = '' !== (string) $account->native_virtual_balance ? bcsub($nativeBalance, $account->native_virtual_balance) : $nativeBalance; + $amountToUse = $useNative ? $nativeBalance : $balance; Log::debug(sprintf('Will use %s %s', $currencyCode, $amountToUse)); $netWorth[$currencyCode] ??= [ @@ -117,7 +117,7 @@ class NetWorth implements NetWorthInterface return $netWorth; } - private function getRepository(): AccountRepositoryInterface | AdminAccountRepositoryInterface + private function getRepository(): AccountRepositoryInterface|AdminAccountRepositoryInterface { if (null === $this->userGroup) { return $this->accountRepository; @@ -126,19 +126,19 @@ class NetWorth implements NetWorthInterface return $this->adminAccountRepository; } - public function setUser(null | Authenticatable | User $user): void + public function setUser(null|Authenticatable|User $user): void { if (!$user instanceof User) { return; } - $this->user = $user; - $this->userGroup = null; + $this->user = $user; + $this->userGroup = null; // make repository: $this->accountRepository = app(AccountRepositoryInterface::class); $this->accountRepository->setUser($this->user); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); + $this->currencyRepos = app(CurrencyRepositoryInterface::class); $this->currencyRepos->setUser($this->user); } @@ -161,16 +161,16 @@ class NetWorth implements NetWorthInterface $return = []; $balances = Steam::finalAccountsBalance($accounts, $date); foreach ($accounts as $account) { - $currency = $this->getRepository()->getAccountCurrency($account); - $balance = $balances[$account->id]['balance'] ?? '0'; + $currency = $this->getRepository()->getAccountCurrency($account); + $balance = $balances[$account->id]['balance'] ?? '0'; // always subtract virtual balance. - $virtualBalance = $account->virtual_balance; + $virtualBalance = $account->virtual_balance; if ('' !== $virtualBalance) { $balance = bcsub($balance, $virtualBalance); } - $return[$currency->id] ??= [ + $return[$currency->id] ??= [ 'id' => (string) $currency->id, 'name' => $currency->name, 'symbol' => $currency->symbol, diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index d27622374f..e95c7de9c6 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -71,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(); @@ -111,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')); @@ -127,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(); @@ -145,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(); @@ -159,9 +159,9 @@ class IndexController extends Controller $accounts->each( function (Account $account) use ($activities, $startBalances, $endBalances): void { - $interest = (string) $this->repository->getMetaValue($account, 'interest'); - $interest = '' === $interest ? '0' : $interest; - $currency = $this->repository->getAccountCurrency($account); + $interest = (string) $this->repository->getMetaValue($account, 'interest'); + $interest = '' === $interest ? '0' : $interest; + $currency = $this->repository->getAccountCurrency($account); $account->startBalances = $this->getBalance($account, $currency, $startBalances); $account->endBalances = $this->getBalance($account, $currency, $endBalances); @@ -175,7 +175,7 @@ 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->currency = $currency; $account->iban = implode(' ', str_split((string) $account->iban, 4)); @@ -185,7 +185,7 @@ class IndexController extends Controller 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())); @@ -194,7 +194,7 @@ 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 + private function getBalance(Account $account, ?TransactionCurrency $currency, array $balances): array { if (!array_key_exists($account->id, $balances)) { return []; @@ -217,6 +217,7 @@ class IndexController extends Controller foreach ($endBalances as $key => $value) { $result[$key] = bcsub($value, $startBalances[$key] ?? '0'); } + return $result; } } diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 385dcb3eb5..c16b13862e 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -84,6 +84,7 @@ class AccountController extends Controller public function expenseAccounts(): JsonResponse { Log::debug('RevenueAccounts'); + /** @var Carbon $start */ $start = clone session('start', today(config('app.timezone'))->startOfMonth()); @@ -95,7 +96,7 @@ class AccountController extends Controller $cache->addProperty($this->convertToNative); $cache->addProperty('chart.account.expense-accounts'); if ($cache->has()) { - return response()->json($cache->get()); + return response()->json($cache->get()); } $start->subDay(); @@ -114,34 +115,38 @@ class AccountController extends Controller $endBalances = app('steam')->finalAccountsBalance($accounts, $end); // loop the accounts, then check for balance and currency info. - foreach($accounts as $account) { + foreach ($accounts as $account) { Log::debug(sprintf('Now in account #%d ("%s")', $account->id, $account->name)); $expenses = $endBalances[$account->id] ?? false; - if(false === $expenses) { - Log::error(sprintf('Found no end balance for account #%d',$account->id)); + if (false === $expenses) { + Log::error(sprintf('Found no end balance for account #%d', $account->id)); + continue; } + /** * @var string $key * @var string $endBalance */ foreach ($expenses as $key => $endBalance) { - if(!$this->convertToNative && 'native_balance' === $key) { + if (!$this->convertToNative && 'native_balance' === $key) { Log::debug(sprintf('[a] Will skip expense array "%s"', $key)); + continue; } - if($this->convertToNative && 'native_balance' !== $key) { + if ($this->convertToNative && 'native_balance' !== $key) { Log::debug(sprintf('[b] Will skip expense array "%s"', $key)); + continue; } Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); - $searchCode = $this->convertToNative ? $default->code: $key; + $searchCode = $this->convertToNative ? $default->code : $key; Log::debug(sprintf('Search code is %s', $searchCode)); // see if there is an accompanying start amount. // grab the difference and find the currency. $startBalance = ($startBalances[$account->id][$key] ?? '0'); Log::debug(sprintf('Start balance is %s', $startBalance)); - $diff = bcsub($endBalance, $startBalance); + $diff = bcsub($endBalance, $startBalance); $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); if (0 !== bccomp($diff, '0')) { // store the values in a temporary array. @@ -522,7 +527,7 @@ class AccountController extends Controller $cache->addProperty($this->convertToNative); $cache->addProperty('chart.account.revenue-accounts'); if ($cache->has()) { - return response()->json($cache->get()); + return response()->json($cache->get()); } $start->subDay(); @@ -541,35 +546,39 @@ class AccountController extends Controller $endBalances = app('steam')->finalAccountsBalance($accounts, $end); -// loop the accounts, then check for balance and currency info. - foreach($accounts as $account) { + // loop the accounts, then check for balance and currency info. + foreach ($accounts as $account) { Log::debug(sprintf('Now in account #%d ("%s")', $account->id, $account->name)); $expenses = $endBalances[$account->id] ?? false; - if(false === $expenses) { - Log::error(sprintf('Found no end balance for account #%d',$account->id)); + if (false === $expenses) { + Log::error(sprintf('Found no end balance for account #%d', $account->id)); + continue; } + /** * @var string $key * @var string $endBalance */ foreach ($expenses as $key => $endBalance) { - if(!$this->convertToNative && 'native_balance' === $key) { + if (!$this->convertToNative && 'native_balance' === $key) { Log::debug(sprintf('[a] Will skip expense array "%s"', $key)); + continue; } - if($this->convertToNative && 'native_balance' !== $key) { + if ($this->convertToNative && 'native_balance' !== $key) { Log::debug(sprintf('[b] Will skip expense array "%s"', $key)); + continue; } Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); - $searchCode = $this->convertToNative ? $default->code: $key; + $searchCode = $this->convertToNative ? $default->code : $key; Log::debug(sprintf('Search code is %s', $searchCode)); // see if there is an accompanying start amount. // grab the difference and find the currency. $startBalance = ($startBalances[$account->id][$key] ?? '0'); Log::debug(sprintf('Start balance is %s', $startBalance)); - $diff = bcsub($endBalance, $startBalance); + $diff = bcsub($endBalance, $startBalance); $currencies[$searchCode] ??= $this->currencyRepository->findByCode($searchCode); if (0 !== bccomp($diff, '0')) { // store the values in a temporary array. diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index ff45fe7a6a..887d57c656 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -85,11 +85,11 @@ class BudgetController extends Controller public function budget(Budget $budget): JsonResponse { /** @var Carbon $start */ - $start = $this->repository->firstUseDate($budget) ?? session('start', today(config('app.timezone'))); + $start = $this->repository->firstUseDate($budget) ?? session('start', today(config('app.timezone'))); /** @var Carbon $end */ - $end = session('end', today(config('app.timezone'))); - $cache = new CacheProperties(); + $end = session('end', today(config('app.timezone'))); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.budget.budget'); @@ -107,19 +107,19 @@ class BudgetController extends Controller $defaultEntries = []; while ($end >= $loopStart) { /** @var Carbon $loopEnd */ - $loopEnd = app('navigation')->endOfPeriod($loopStart, $step); - $spent = $this->opsRepository->sumExpenses($loopStart, $loopEnd, null, $collection); - $label = trim(app('navigation')->periodShow($loopStart, $step)); + $loopEnd = app('navigation')->endOfPeriod($loopStart, $step); + $spent = $this->opsRepository->sumExpenses($loopStart, $loopEnd, null, $collection); + $label = trim(app('navigation')->periodShow($loopStart, $step)); foreach ($spent as $row) { - $currencyId = $row['currency_id']; + $currencyId = $row['currency_id']; $currencies[$currencyId] ??= $row; // don't mind the field 'sum' // also store this day's sum: $currencies[$currencyId]['spent'][$label] = $row['sum']; } $defaultEntries[$label] = 0; // set loop start to the next period: - $loopStart = clone $loopEnd; + $loopStart = clone $loopEnd; $loopStart->addSecond(); } // loop all currencies: @@ -135,7 +135,7 @@ class BudgetController extends Controller $chartData[$currencyId]['entries'][$label] = bcmul($spent, '-1'); } } - $data = $this->generator->multiSet(array_values($chartData)); + $data = $this->generator->multiSet(array_values($chartData)); $cache->store($data); return response()->json($data); @@ -152,9 +152,9 @@ class BudgetController extends Controller throw new FireflyException('This budget limit is not part of this budget.'); } - $start = clone $budgetLimit->start_date; - $end = clone $budgetLimit->end_date; - $cache = new CacheProperties(); + $start = clone $budgetLimit->start_date; + $end = clone $budgetLimit->end_date; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.budget.budget.limit'); @@ -164,11 +164,11 @@ class BudgetController extends Controller if ($cache->has()) { return response()->json($cache->get()); } - $locale = app('steam')->getLocale(); - $entries = []; - $amount = $budgetLimit->amount; - $budgetCollection = new Collection([$budget]); - $currency = $budgetLimit->transactionCurrency; + $locale = app('steam')->getLocale(); + $entries = []; + $amount = $budgetLimit->amount; + $budgetCollection = new Collection([$budget]); + $currency = $budgetLimit->transactionCurrency; while ($start <= $end) { $current = clone $start; $expenses = $this->opsRepository->sumExpenses($current, $current, null, $budgetCollection, $currency); @@ -179,7 +179,7 @@ class BudgetController extends Controller $start->addDay(); } - $data = $this->generator->singleSet((string) trans('firefly.left'), $entries); + $data = $this->generator->singleSet((string) trans('firefly.left'), $entries); // add currency symbol from budget limit: $data['datasets'][0]['currency_symbol'] = $budgetLimit->transactionCurrency->symbol; $data['datasets'][0]['currency_code'] = $budgetLimit->transactionCurrency->code; @@ -200,8 +200,8 @@ class BudgetController extends Controller $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-asset'); - $start = session('first', today(config('app.timezone'))->startOfYear()); - $end = today(); + $start = session('first', today(config('app.timezone'))->startOfYear()); + $end = today(); if (null !== $budgetLimit) { $start = $budgetLimit->start_date; @@ -216,14 +216,14 @@ class BudgetController extends Controller } $collector->setRange($start, $end); $collector->setBudget($budget); - $journals = $collector->getExtractedJournals(); - $result = []; - $chartData = []; + $journals = $collector->getExtractedJournals(); + $result = []; + $chartData = []; // group by asset account ID: foreach ($journals as $journal) { $key = sprintf('%d-%d', (int) $journal['source_account_id'], $journal['currency_id']); - $result[$key] ??= [ + $result[$key] ??= [ 'amount' => '0', 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], @@ -232,20 +232,20 @@ class BudgetController extends Controller $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } - $names = $this->getAccountNames(array_keys($result)); + $names = $this->getAccountNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); $assetId = (int) $parts[0]; $title = sprintf('%s (%s)', $names[$assetId] ?? '(empty)', $info['currency_name']); $chartData[$title] = [ - 'amount' => $info['amount'], - 'currency_symbol' => $info['currency_symbol'], - 'currency_code' => $info['currency_code'], - ]; + 'amount' => $info['amount'], + 'currency_symbol' => $info['currency_symbol'], + 'currency_code' => $info['currency_code'], + ]; } - $data = $this->generator->multiCurrencyPieChart($chartData); + $data = $this->generator->multiCurrencyPieChart($chartData); $cache->store($data); return response()->json($data); @@ -263,8 +263,8 @@ class BudgetController extends Controller $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-category'); - $start = session('first', today(config('app.timezone'))->startOfYear()); - $end = today(); + $start = session('first', today(config('app.timezone'))->startOfYear()); + $end = today(); if (null !== $budgetLimit) { $start = $budgetLimit->start_date; $end = $budgetLimit->end_date; @@ -278,12 +278,12 @@ class BudgetController extends Controller } $collector->setRange($start, $end); $collector->setBudget($budget)->withCategoryInformation(); - $journals = $collector->getExtractedJournals(); - $result = []; - $chartData = []; + $journals = $collector->getExtractedJournals(); + $result = []; + $chartData = []; foreach ($journals as $journal) { $key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']); - $result[$key] ??= [ + $result[$key] ??= [ 'amount' => '0', 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], @@ -292,7 +292,7 @@ class BudgetController extends Controller $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } - $names = $this->getCategoryNames(array_keys($result)); + $names = $this->getCategoryNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); $categoryId = (int) $parts[0]; @@ -303,7 +303,7 @@ class BudgetController extends Controller 'currency_code' => $info['currency_code'], ]; } - $data = $this->generator->multiCurrencyPieChart($chartData); + $data = $this->generator->multiCurrencyPieChart($chartData); $cache->store($data); return response()->json($data); @@ -321,8 +321,8 @@ class BudgetController extends Controller $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-expense'); - $start = session('first', today(config('app.timezone'))->startOfYear()); - $end = today(); + $start = session('first', today(config('app.timezone'))->startOfYear()); + $end = today(); if (null !== $budgetLimit) { $start = $budgetLimit->start_date; $end = $budgetLimit->end_date; @@ -336,14 +336,14 @@ class BudgetController extends Controller } $collector->setRange($start, $end); $collector->setTypes([TransactionType::WITHDRAWAL])->setBudget($budget)->withAccountInformation(); - $journals = $collector->getExtractedJournals(); - $result = []; - $chartData = []; + $journals = $collector->getExtractedJournals(); + $result = []; + $chartData = []; /** @var array $journal */ foreach ($journals as $journal) { $key = sprintf('%d-%d', $journal['destination_account_id'], $journal['currency_id']); - $result[$key] ??= [ + $result[$key] ??= [ 'amount' => '0', 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], @@ -352,7 +352,7 @@ class BudgetController extends Controller $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } - $names = $this->getAccountNames(array_keys($result)); + $names = $this->getAccountNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); $opposingId = (int) $parts[0]; @@ -365,7 +365,7 @@ class BudgetController extends Controller ]; } - $data = $this->generator->multiCurrencyPieChart($chartData); + $data = $this->generator->multiCurrencyPieChart($chartData); $cache->store($data); return response()->json($data); @@ -376,10 +376,10 @@ class BudgetController extends Controller */ public function frontpage(): JsonResponse { - $start = session('start', today(config('app.timezone'))->startOfMonth()); - $end = session('end', today(config('app.timezone'))->endOfMonth()); + $start = session('start', today(config('app.timezone'))->startOfMonth()); + $end = session('end', today(config('app.timezone'))->endOfMonth()); // chart properties for cache: - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($this->convertToNative); @@ -387,16 +387,16 @@ class BudgetController extends Controller if ($cache->has()) { // return response()->json($cache->get()); } - Log::debug(sprintf('Regenerate frontpage chart from scratch.')); - $chartGenerator = app(FrontpageChartGenerator::class); + Log::debug('Regenerate frontpage chart from scratch.'); + $chartGenerator = app(FrontpageChartGenerator::class); $chartGenerator->setUser(auth()->user()); $chartGenerator->setStart($start); $chartGenerator->setEnd($end); $chartGenerator->convertToNative = $this->convertToNative; $chartGenerator->default = Amount::getDefaultCurrency(); - $chartData = $chartGenerator->generate(); - $data = $this->generator->multiSet($chartData); + $chartData = $chartGenerator->generate(); + $data = $this->generator->multiSet($chartData); $cache->store($data); return response()->json($data); @@ -412,7 +412,7 @@ class BudgetController extends Controller public function period(Budget $budget, TransactionCurrency $currency, Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($accounts); @@ -441,11 +441,11 @@ class BudgetController extends Controller ], ]; - $currentStart = clone $start; + $currentStart = clone $start; while ($currentStart <= $end) { - $currentStart = app('navigation')->startOfPeriod($currentStart, $preferredRange); - $title = $currentStart->isoFormat($titleFormat); - $currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange); + $currentStart = app('navigation')->startOfPeriod($currentStart, $preferredRange); + $title = $currentStart->isoFormat($titleFormat); + $currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange); // default limit is no limit: $chartData[0]['entries'][$title] = 0; @@ -454,7 +454,7 @@ class BudgetController extends Controller $chartData[1]['entries'][$title] = 0; // get budget limit in this period for this currency. - $limit = $this->blRepository->find($budget, $currency, $currentStart, $currentEnd); + $limit = $this->blRepository->find($budget, $currency, $currentStart, $currentEnd); if (null !== $limit) { $chartData[1]['entries'][$title] = app('steam')->bcround($limit->amount, $currency->decimal_places); } @@ -464,11 +464,11 @@ class BudgetController extends Controller $amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0'); $chartData[0]['entries'][$title] = app('steam')->bcround($amount, $currency->decimal_places); - $currentStart = clone $currentEnd; + $currentStart = clone $currentEnd; $currentStart->addDay()->startOfDay(); } - $data = $this->generator->multiSet($chartData); + $data = $this->generator->multiSet($chartData); $cache->store($data); return response()->json($data); @@ -480,7 +480,7 @@ class BudgetController extends Controller public function periodNoBudget(TransactionCurrency $currency, Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($accounts); @@ -504,7 +504,7 @@ class BudgetController extends Controller $currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0); } - $data = $this->generator->singleSet((string) trans('firefly.spent'), $chartData); + $data = $this->generator->singleSet((string) trans('firefly.spent'), $chartData); $cache->store($data); return response()->json($data); diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index f4f6958dd9..6e87ee5e26 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -70,7 +70,7 @@ class CategoryController extends Controller public function all(Category $category): JsonResponse { // cache results: - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty('chart.category.all'); $cache->addProperty($category->id); if ($cache->has()) { @@ -78,11 +78,11 @@ class CategoryController extends Controller } /** @var CategoryRepositoryInterface $repository */ - $repository = app(CategoryRepositoryInterface::class); - $start = $repository->firstUseDate($category) ?? $this->getDate(); - $range = app('navigation')->getViewRange(false); - $start = app('navigation')->startOfPeriod($start, $range); - $end = $this->getDate(); + $repository = app(CategoryRepositoryInterface::class); + $start = $repository->firstUseDate($category) ?? $this->getDate(); + $range = app('navigation')->getViewRange(false); + $start = app('navigation')->startOfPeriod($start, $range); + $end = $this->getDate(); /** @var WholePeriodChartGenerator $chartGenerator */ $chartGenerator = app(WholePeriodChartGenerator::class); @@ -104,10 +104,10 @@ class CategoryController extends Controller */ public function frontPage(): JsonResponse { - $start = session('start', today(config('app.timezone'))->startOfMonth()); - $end = session('end', today(config('app.timezone'))->endOfMonth()); + $start = session('start', today(config('app.timezone'))->startOfMonth()); + $end = session('end', today(config('app.timezone'))->endOfMonth()); // chart properties for cache: - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($this->convertToNative); @@ -139,7 +139,7 @@ class CategoryController extends Controller if ($cache->has()) { return response()->json($cache->get()); } - $data = $this->reportPeriodChart($accounts, $start, $end, $category); + $data = $this->reportPeriodChart($accounts, $start, $end, $category); $cache->store($data); @@ -160,8 +160,8 @@ class CategoryController extends Controller $noCatRepository = app(NoCategoryRepositoryInterface::class); // this gives us all currencies - $expenses = $noCatRepository->listExpenses($start, $end, $accounts); - $income = $noCatRepository->listIncome($start, $end, $accounts); + $expenses = $noCatRepository->listExpenses($start, $end, $accounts); + $income = $noCatRepository->listIncome($start, $end, $accounts); } if (null !== $category) { @@ -169,9 +169,9 @@ class CategoryController extends Controller $opsRepository = app(OperationsRepositoryInterface::class); $categoryId = $category->id; // this gives us all currencies - $collection = new Collection([$category]); - $expenses = $opsRepository->listExpenses($start, $end, $accounts, $collection); - $income = $opsRepository->listIncome($start, $end, $accounts, $collection); + $collection = new Collection([$category]); + $expenses = $opsRepository->listExpenses($start, $end, $accounts, $collection); + $income = $opsRepository->listIncome($start, $end, $accounts, $collection); } $currencies = array_unique(array_merge(array_keys($income), array_keys($expenses))); $periods = app('navigation')->listOfPeriods($start, $end); @@ -185,19 +185,19 @@ class CategoryController extends Controller $inKey = sprintf('%d-in', $currencyId); $chartData[$outKey] = [ - 'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currencyInfo['currency_name']), - 'entries' => [], - 'type' => 'bar', - 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red - ]; + 'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currencyInfo['currency_name']), + 'entries' => [], + 'type' => 'bar', + 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red + ]; $chartData[$inKey] - = [ - 'label' => sprintf('%s (%s)', (string) trans('firefly.earned'), $currencyInfo['currency_name']), - 'entries' => [], - 'type' => 'bar', - 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green - ]; + = [ + 'label' => sprintf('%s (%s)', (string) trans('firefly.earned'), $currencyInfo['currency_name']), + 'entries' => [], + 'type' => 'bar', + 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green + ]; // loop empty periods: foreach (array_keys($periods) as $period) { $label = $periods[$period]; @@ -205,7 +205,7 @@ class CategoryController extends Controller $chartData[$inKey]['entries'][$label] = '0'; } // loop income and expenses for this category.: - $outSet = $expenses[$currencyId]['categories'][$categoryId] ?? ['transaction_journals' => []]; + $outSet = $expenses[$currencyId]['categories'][$categoryId] ?? ['transaction_journals' => []]; foreach ($outSet['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $date = $journal['date']->isoFormat($format); @@ -214,7 +214,7 @@ class CategoryController extends Controller $chartData[$outKey]['entries'][$date] = bcadd($amount, $chartData[$outKey]['entries'][$date]); } - $inSet = $income[$currencyId]['categories'][$categoryId] ?? ['transaction_journals' => []]; + $inSet = $income[$currencyId]['categories'][$categoryId] ?? ['transaction_journals' => []]; foreach ($inSet['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $date = $journal['date']->isoFormat($format); @@ -240,7 +240,7 @@ class CategoryController extends Controller if ($cache->has()) { return response()->json($cache->get()); } - $data = $this->reportPeriodChart($accounts, $start, $end, null); + $data = $this->reportPeriodChart($accounts, $start, $end, null); $cache->store($data); @@ -255,14 +255,14 @@ class CategoryController extends Controller */ public function specificPeriod(Category $category, Carbon $date): JsonResponse { - $range = app('navigation')->getViewRange(false); - $start = app('navigation')->startOfPeriod($date, $range); - $end = session()->get('end'); + $range = app('navigation')->getViewRange(false); + $start = app('navigation')->startOfPeriod($date, $range); + $end = session()->get('end'); if ($end < $start) { [$end, $start] = [$start, $end]; } - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($category->id); diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php index 0d3bd93ec6..e08bbe706f 100644 --- a/app/Http/Controllers/DebugController.php +++ b/app/Http/Controllers/DebugController.php @@ -33,7 +33,6 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Support\Http\Controllers\GetConfigurationData; use FireflyIII\Support\Models\AccountBalanceCalculator; use FireflyIII\User; -use Http\Discovery\Exception\NotFoundException; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -63,55 +62,59 @@ class DebugController extends Controller public function routes(): never { - if(!auth()->user()->hasRole('owner')) { + if (!auth()->user()->hasRole('owner')) { throw new NotFoundHttpException(); } $routes = Route::getRoutes(); $return = []; + /** @var \Illuminate\Routing\Route $route */ foreach ($routes as $route) { // skip API and other routes. if ( - str_starts_with($route->uri(), 'api') || - str_starts_with($route->uri(), '_debugbar') || - str_starts_with($route->uri(), '_ignition') || - str_starts_with($route->uri(), 'oauth') || - str_starts_with($route->uri(), 'sanctum') + str_starts_with($route->uri(), 'api') + || str_starts_with($route->uri(), '_debugbar') + || str_starts_with($route->uri(), '_ignition') + || str_starts_with($route->uri(), 'oauth') + || str_starts_with($route->uri(), 'sanctum') ) { continue; } // skip non GET routes - if (!in_array('GET', $route->methods())) { + if (!in_array('GET', $route->methods(), true)) { continue; } // no name route: if (null === $route->getName()) { var_dump($route); + exit; } if (!str_contains($route->uri(), '{')) { $return[$route->getName()] = route($route->getName()); + continue; } - $params = []; + $params = []; foreach ($route->parameterNames() as $name) { $params[] = $this->getParameter($name); } $return[$route->getName()] = route($route->getName(), $params); } - $count = 0; + $count = 0; echo '
'; echo '

Routes

'; echo sprintf('

%s

', $count); - foreach($return as $name => $path) { - echo sprintf('%2$s
', $path, $name) . PHP_EOL; - $count++; - if(0 === $count % 10) { + foreach ($return as $name => $path) { + echo sprintf('%2$s
', $path, $name).PHP_EOL; + ++$count; + if (0 === $count % 10) { echo '
'; echo sprintf('

%s

', $count); } } + exit; var_dump($return); } @@ -176,12 +179,12 @@ class DebugController extends Controller */ public function index() { - $table = $this->generateTable(); - $table = str_replace(["\n", "\t", ' '], '', $table); - $now = now(config('app.timezone'))->format('Y-m-d H:i:s'); + $table = $this->generateTable(); + $table = str_replace(["\n", "\t", ' '], '', $table); + $now = now(config('app.timezone'))->format('Y-m-d H:i:s'); // get latest log file: - $logger = Log::driver(); + $logger = Log::driver(); // PHPstan doesn't recognize the method because of its polymorphic nature. $handlers = $logger->getHandlers(); // @phpstan-ignore-line $logContent = ''; @@ -195,7 +198,7 @@ class DebugController extends Controller } if ('' !== $logContent) { // last few lines - $logContent = 'Truncated from this point <----|' . substr((string) $logContent, -16384); + $logContent = 'Truncated from this point <----|'.substr((string) $logContent, -16384); } return view('debug', compact('table', 'now', 'logContent')); @@ -275,7 +278,7 @@ class DebugController extends Controller private function getAppInfo(): array { - $userGuard = config('auth.defaults.guard'); + $userGuard = config('auth.defaults.guard'); $config = app('fireflyconfig')->get('last_rt_job', 0); $lastTime = (int) $config->data; @@ -300,24 +303,24 @@ class DebugController extends Controller // any of the cron jobs will do, they always run at the same time. // but this job is the oldest, so the biggest chance it ran once - 'last_cronjob' => $lastCronjob, - 'last_cronjob_ago' => $lastCronjobAgo, + 'last_cronjob' => $lastCronjob, + 'last_cronjob_ago' => $lastCronjobAgo, ]; } private function getuserInfo(): array { - $userFlags = $this->getUserFlags(); + $userFlags = $this->getUserFlags(); // user info - $userAgent = request()->header('user-agent'); + $userAgent = request()->header('user-agent'); // set languages, see what happens: $original = setlocale(LC_ALL, '0'); $localeAttempts = []; $parts = app('steam')->getLocaleArray(app('steam')->getLocale()); foreach ($parts as $code) { - $code = trim($code); + $code = trim($code); app('log')->debug(sprintf('Trying to set %s', $code)); $result = setlocale(LC_ALL, $code); $localeAttempts[$code] = $result === $code; @@ -338,10 +341,10 @@ class DebugController extends Controller private function getUserFlags(): string { - $flags = []; + $flags = []; /** @var User $user */ - $user = auth()->user(); + $user = auth()->user(); // has liabilities if ($user->accounts()->accountTypeIn([AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE])->count() > 0) { @@ -357,7 +360,7 @@ class DebugController extends Controller } // has stored reconciliations - $type = TransactionType::whereType(TransactionType::RECONCILIATION)->first(); + $type = TransactionType::whereType(TransactionType::RECONCILIATION)->first(); if ($user->transactionJournals()->where('transaction_type_id', $type->id)->count() > 0) { $flags[] = ':ledger:'; } @@ -407,81 +410,118 @@ class DebugController extends Controller switch ($name) { default: throw new FireflyException(sprintf('Unknown parameter "%s"', $name)); + case 'cliToken': case 'token': case 'code': case 'oldAddressHash': return 'fake-token'; + case 'objectType': return 'asset'; + case 'account': return '1'; + case 'start_date': return '20241201'; + case 'end_date': return '20241231'; + case 'attachment': return '1'; + case 'bill': return '1'; + case 'budget': return '1'; + case 'budgetLimit': return '1'; + case 'category': return '1'; + case 'currency': return '1'; + case 'fromCurrencyCode': return 'EUR'; + case 'toCurrencyCode': return 'USD'; + case 'accountList': return '1,6'; + case 'budgetList': return '1,2'; + case 'categoryList': return '1,2'; + case 'doubleList': return '1,2'; + case 'tagList': return '1,2'; + case 'tag': return '1'; + case 'piggyBank': return '1'; + case 'objectGroup': return '1'; + case 'route': return 'accounts'; + case 'specificPage': return 'show'; + case 'recurrence': return '1'; + case 'tj': return '1'; + case 'reportType': return 'default'; + case 'ruleGroup': return '1'; + case 'rule': return '1'; + case 'tagOrId': return '1'; + case 'transactionGroup': return '1'; + case 'journalList': return '1,2'; + case 'transactionType': return 'withdrawal'; + case 'journalLink': return '1'; + case 'webhook': return '1'; + case 'user': return '1'; + case 'linkType': return '1'; + case 'userGroup': return '1'; diff --git a/app/Http/Controllers/Json/BoxController.php b/app/Http/Controllers/Json/BoxController.php index bfcf049956..d7781be69a 100644 --- a/app/Http/Controllers/Json/BoxController.php +++ b/app/Http/Controllers/Json/BoxController.php @@ -62,31 +62,32 @@ class BoxController extends Controller { // Cache result, return cache if present. /** @var Carbon $start */ - $start = session('start', today(config('app.timezone'))->startOfMonth()); + $start = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $end */ - $end = session('end', today(config('app.timezone'))->endOfMonth()); - $cache = new CacheProperties(); + $end = session('end', today(config('app.timezone'))->endOfMonth()); + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($this->convertToNative); $cache->addProperty('box-balance'); if ($cache->has()) { - return response()->json($cache->get()); + return response()->json($cache->get()); } // prep some arrays: - $incomes = []; - $expenses = []; - $sums = []; - $currency = app('amount')->getDefaultCurrency(); + $incomes = []; + $expenses = []; + $sums = []; + $currency = app('amount')->getDefaultCurrency(); // collect income of user: /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end) - ->setTypes([TransactionType::DEPOSIT]); - $set = $collector->getExtractedJournals(); + ->setTypes([TransactionType::DEPOSIT]) + ; + $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { @@ -102,8 +103,9 @@ class BoxController extends Controller /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end) - ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); - $set = $collector->getExtractedJournals(); + ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]) + ; + $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { @@ -116,7 +118,7 @@ class BoxController extends Controller } // format amounts: - $keys = array_keys($sums); + $keys = array_keys($sums); foreach ($keys as $currencyId) { $currency = $repository->find($currencyId); $sums[$currencyId] = app('amount')->formatAnything($currency, $sums[$currencyId], false); @@ -130,7 +132,7 @@ class BoxController extends Controller $expenses[$currency->id] = app('amount')->formatAnything($currency, '0', false); } - $response = [ + $response = [ 'incomes' => $incomes, 'expenses' => $expenses, 'sums' => $sums, @@ -147,7 +149,7 @@ class BoxController extends Controller */ public function netWorth(): JsonResponse { - $date = today(config('app.timezone'))->endOfDay(); + $date = today(config('app.timezone'))->endOfDay(); // start and end in the future? use $end if ($this->notInSessionRange($date)) { @@ -156,7 +158,7 @@ class BoxController extends Controller } /** @var NetWorthInterface $netWorthHelper */ - $netWorthHelper = app(NetWorthInterface::class); + $netWorthHelper = app(NetWorthInterface::class); $netWorthHelper->setUser(auth()->user()); /** @var AccountRepositoryInterface $accountRepository */ @@ -167,7 +169,7 @@ class BoxController extends Controller app('log')->debug(sprintf('Found %d accounts.', $allAccounts->count())); // filter list on preference of being included. - $filtered = $allAccounts->filter( + $filtered = $allAccounts->filter( static function (Account $account) use ($accountRepository) { $includeNetWorth = $accountRepository->getMetaValue($account, 'include_net_worth'); $result = null === $includeNetWorth ? true : '1' === $includeNetWorth; @@ -179,15 +181,15 @@ class BoxController extends Controller } ); - $netWorthSet = $netWorthHelper->byAccounts($filtered, $date); - $return = []; + $netWorthSet = $netWorthHelper->byAccounts($filtered, $date); + $return = []; foreach ($netWorthSet as $key => $data) { if ('native' === $key) { continue; } $return[$data['currency_id']] = app('amount')->formatFlat($data['currency_symbol'], $data['currency_decimal_places'], $data['balance'], false); } - $return = [ + $return = [ 'net_worths' => array_values($return), ]; diff --git a/app/Models/Account.php b/app/Models/Account.php index c56940e2ee..541949e718 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -61,7 +61,7 @@ class Account extends Model 'virtual_balance' => 'string', ]; - protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban','native_virtual_balance']; + protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban', 'native_virtual_balance']; protected $hidden = ['encrypted']; private bool $joinedAccountTypes = false; diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index 0a13fdf53f..8e69f95d15 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -57,7 +57,7 @@ class BudgetLimit extends Model 'deleted' => Deleted::class, ]; - protected $fillable = ['budget_id', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'amount', 'transaction_currency_id','native_amount']; + protected $fillable = ['budget_id', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'amount', 'transaction_currency_id', 'native_amount']; /** * Route binder. Converts the key in the URL to the specified object (or throw 404). diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 7dd401ecf5..ee74192f52 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -61,7 +61,8 @@ class BillRepository implements BillRepositoryInterface $search->whereLike('name', sprintf('%%%s', $query)); } $search->orderBy('name', 'ASC') - ->where('active', true); + ->where('active', true) + ; return $search->take($limit)->get(); } @@ -73,7 +74,8 @@ class BillRepository implements BillRepositoryInterface $search->whereLike('name', sprintf('%s%%', $query)); } $search->orderBy('name', 'ASC') - ->where('active', true); + ->where('active', true) + ; return $search->take($limit)->get(); } @@ -156,7 +158,7 @@ class BillRepository implements BillRepositoryInterface */ public function getAttachments(Bill $bill): Collection { - $set = $bill->attachments()->get(); + $set = $bill->attachments()->get(); /** @var \Storage $disk */ $disk = \Storage::disk('upload'); @@ -175,9 +177,10 @@ class BillRepository implements BillRepositoryInterface public function getBills(): Collection { return $this->user->bills() - ->orderBy('order', 'ASC') - ->orderBy('active', 'DESC') - ->orderBy('name', 'ASC')->get(); + ->orderBy('order', 'ASC') + ->orderBy('active', 'DESC') + ->orderBy('name', 'ASC')->get() + ; } public function getBillsForAccounts(Collection $accounts): Collection @@ -201,24 +204,25 @@ class BillRepository implements BillRepositoryInterface $ids = $accounts->pluck('id')->toArray(); return $this->user->bills() - ->leftJoin( - 'transaction_journals', - static function (JoinClause $join): void { - $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at'); - } - ) - ->leftJoin( - 'transactions', - static function (JoinClause $join): void { - $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); - } - ) - ->whereIn('transactions.account_id', $ids) - ->whereNull('transaction_journals.deleted_at') - ->orderBy('bills.active', 'DESC') - ->orderBy('bills.name', 'ASC') - ->groupBy($fields) - ->get($fields); + ->leftJoin( + 'transaction_journals', + static function (JoinClause $join): void { + $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at'); + } + ) + ->leftJoin( + 'transactions', + static function (JoinClause $join): void { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); + } + ) + ->whereIn('transactions.account_id', $ids) + ->whereNull('transaction_journals.deleted_at') + ->orderBy('bills.active', 'DESC') + ->orderBy('bills.name', 'ASC') + ->groupBy($fields) + ->get($fields) + ; } /** @@ -243,7 +247,7 @@ class BillRepository implements BillRepositoryInterface public function getOverallAverage(Bill $bill): array { /** @var JournalRepositoryInterface $repos */ - $repos = app(JournalRepositoryInterface::class); + $repos = app(JournalRepositoryInterface::class); $repos->setUser($this->user); // get and sort on currency @@ -256,7 +260,7 @@ class BillRepository implements BillRepositoryInterface $transaction = $journal->transactions()->where('amount', '<', 0)->first(); $currencyId = (int) $journal->transaction_currency_id; $currency = $journal->transactionCurrency; - $result[$currencyId] ??= [ + $result[$currencyId] ??= [ 'sum' => '0', 'count' => 0, 'avg' => '0', @@ -281,7 +285,7 @@ class BillRepository implements BillRepositoryInterface return $result; } - public function setUser(null | Authenticatable | User $user): void + public function setUser(null|Authenticatable|User $user): void { if ($user instanceof User) { $this->user = $user; @@ -291,8 +295,9 @@ class BillRepository implements BillRepositoryInterface public function getPaginator(int $size): LengthAwarePaginator { return $this->user->bills() - ->orderBy('active', 'DESC') - ->orderBy('name', 'ASC')->paginate($size); + ->orderBy('active', 'DESC') + ->orderBy('name', 'ASC')->paginate($size) + ; } /** @@ -305,13 +310,14 @@ class BillRepository implements BillRepositoryInterface Log::debug(sprintf('Search for linked journals between %s and %s', $start->toW3cString(), $end->toW3cString())); return $bill->transactionJournals() - ->before($end)->after($start)->get( + ->before($end)->after($start)->get( [ 'transaction_journals.id', 'transaction_journals.date', 'transaction_journals.transaction_group_id', ] - ); + ) + ; } /** @@ -320,10 +326,11 @@ class BillRepository implements BillRepositoryInterface public function getRulesForBill(Bill $bill): Collection { return $this->user->rules() - ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') - ->where('rule_actions.action_type', 'link_to_bill') - ->where('rule_actions.action_value', $bill->name) - ->get(['rules.*']); + ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') + ->where('rule_actions.action_type', 'link_to_bill') + ->where('rule_actions.action_value', $bill->name) + ->get(['rules.*']) + ; } /** @@ -334,15 +341,16 @@ class BillRepository implements BillRepositoryInterface */ public function getRulesForBills(Collection $collection): array { - $rules = $this->user->rules() - ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') - ->where('rule_actions.action_type', 'link_to_bill') - ->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active']); - $array = []; + $rules = $this->user->rules() + ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') + ->where('rule_actions.action_type', 'link_to_bill') + ->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active']) + ; + $array = []; /** @var Rule $rule */ foreach ($rules as $rule) { - $array[$rule->action_value] ??= []; + $array[$rule->action_value] ??= []; $array[$rule->action_value][] = ['id' => $rule->id, 'title' => $rule->title, 'active' => $rule->active]; } $return = []; @@ -356,27 +364,28 @@ class BillRepository implements BillRepositoryInterface public function getYearAverage(Bill $bill, Carbon $date): array { /** @var JournalRepositoryInterface $repos */ - $repos = app(JournalRepositoryInterface::class); + $repos = app(JournalRepositoryInterface::class); $repos->setUser($this->user); // get and sort on currency - $result = []; + $result = []; $journals = $bill->transactionJournals() - ->where('date', '>=', $date->year . '-01-01 00:00:00') - ->where('date', '<=', $date->year . '-12-31 23:59:59') - ->get(); + ->where('date', '>=', $date->year.'-01-01 00:00:00') + ->where('date', '<=', $date->year.'-12-31 23:59:59') + ->get() + ; /** @var TransactionJournal $journal */ foreach ($journals as $journal) { /** @var null|Transaction $transaction */ - $transaction = $journal->transactions()->where('amount', '<', 0)->first(); + $transaction = $journal->transactions()->where('amount', '<', 0)->first(); if (null === $transaction) { continue; } $currencyId = (int) $journal->transaction_currency_id; $currency = $journal->transactionCurrency; - $result[$currencyId] ??= [ + $result[$currencyId] ??= [ 'sum' => '0', 'count' => 0, 'avg' => '0', @@ -420,7 +429,7 @@ class BillRepository implements BillRepositoryInterface */ public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon { - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($bill->id); $cache->addProperty('nextExpectedMatch'); $cache->addProperty($date); @@ -428,17 +437,17 @@ class BillRepository implements BillRepositoryInterface return $cache->get(); } // find the most recent date for this bill NOT in the future. Cache this date: - $start = clone $bill->date; + $start = clone $bill->date; $start->startOfDay(); - app('log')->debug('nextExpectedMatch: Start is ' . $start->format('Y-m-d')); + app('log')->debug('nextExpectedMatch: Start is '.$start->format('Y-m-d')); while ($start < $date) { app('log')->debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s'))); $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); - app('log')->debug('Start is now ' . $start->format('Y-m-d H:i:s')); + app('log')->debug('Start is now '.$start->format('Y-m-d H:i:s')); } - $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); $end->endOfDay(); // see if the bill was paid in this period. @@ -450,8 +459,8 @@ class BillRepository implements BillRepositoryInterface $start = clone $end; $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); } - app('log')->debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d')); - app('log')->debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d')); + app('log')->debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d')); + app('log')->debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d')); $cache->store($start); @@ -512,8 +521,8 @@ class BillRepository implements BillRepositoryInterface foreach ($bills as $bill) { /** @var Collection $set */ - $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); - $currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency; + $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); + $currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency; $return[(int) $currency->id] ??= [ 'id' => (string) $currency->id, 'name' => $currency->name, @@ -522,7 +531,8 @@ class BillRepository implements BillRepositoryInterface 'decimal_places' => $currency->decimal_places, 'sum' => '0', ]; - $setAmount = '0'; + $setAmount = '0'; + /** @var TransactionJournal $transactionJournal */ foreach ($set as $transactionJournal) { $setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal)); @@ -538,10 +548,10 @@ class BillRepository implements BillRepositoryInterface public function getActiveBills(): Collection { return $this->user->bills() - ->where('active', true) - ->orderBy('bills.name', 'ASC') - ->get(['bills.*', \DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line - ; + ->where('active', true) + ->orderBy('bills.name', 'ASC') + ->get(['bills.*', \DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount')]) // @phpstan-ignore-line + ; } public function sumUnpaidInRange(Carbon $start, Carbon $end): array @@ -555,21 +565,21 @@ class BillRepository implements BillRepositoryInterface /** @var Bill $bill */ foreach ($bills as $bill) { // app('log')->debug(sprintf('Processing bill #%d ("%s")', $bill->id, $bill->name)); - $dates = $this->getPayDatesInRange($bill, $start, $end); - $count = $bill->transactionJournals()->after($start)->before($end)->count(); - $total = $dates->count() - $count; + $dates = $this->getPayDatesInRange($bill, $start, $end); + $count = $bill->transactionJournals()->after($start)->before($end)->count(); + $total = $dates->count() - $count; // app('log')->debug(sprintf('Pay dates: %d, count: %d, left: %d', $dates->count(), $count, $total)); // app('log')->debug('dates', $dates->toArray()); $minField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_min' : 'amount_min'; $maxField = $convertToNative && $bill->transactionCurrency->id !== $default->id ? 'native_amount_max' : 'amount_max'; - //Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField)); + // Log::debug(sprintf('min field is %s, max field is %s', $minField, $maxField)); if ($total > 0) { $currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency; - $average = bcdiv(bcadd($bill->$maxField, $bill->$minField), '2'); + $average = bcdiv(bcadd($bill->{$maxField}, $bill->{$minField}), '2'); Log::debug(sprintf('Amount to pay is %s %s (%d times)', $currency->code, $average, $total)); - $return[$currency->id] ??= [ + $return[$currency->id] ??= [ 'id' => (string) $currency->id, 'name' => $currency->name, 'symbol' => $currency->symbol, @@ -607,7 +617,7 @@ class BillRepository implements BillRepositoryInterface // app('log')->debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); - $currentStart = clone $nextExpectedMatch; + $currentStart = clone $nextExpectedMatch; } return $set; diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index 30def078e2..ff14595d01 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -47,9 +47,9 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface /** @var AvailableBudget $availableBudget */ foreach ($availableBudgets as $availableBudget) { - $start = $availableBudget->start_date->format('Y-m-d'); - $end = $availableBudget->end_date->format('Y-m-d'); - $key = sprintf('%s-%s-%s', $availableBudget->transaction_currency_id, $start, $end); + $start = $availableBudget->start_date->format('Y-m-d'); + $end = $availableBudget->end_date->format('Y-m-d'); + $key = sprintf('%s-%s-%s', $availableBudget->transaction_currency_id, $start, $end); if (array_key_exists($key, $exists)) { app('log')->debug(sprintf('Found duplicate AB: %s %s, %s-%s. Has been deleted', $availableBudget->transaction_currency_id, $availableBudget->amount, $start, $end)); $availableBudget->delete(); @@ -101,21 +101,23 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget { return $this->user->availableBudgets() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d')) - ->first(); + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d')) + ->first() + ; } public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string { - $amount = '0'; + $amount = '0'; /** @var null|AvailableBudget $availableBudget */ $availableBudget = $this->user->availableBudgets() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->first(); + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->first() + ; if (null !== $availableBudget) { $amount = $availableBudget->amount; } @@ -127,20 +129,22 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface { $return = []; $availableBudgets = $this->user->availableBudgets() - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->get(); + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->get() + ; // use native amount if necessary? - $convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data; - $default = app('amount')->getDefaultCurrency(); + $convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data; + $default = app('amount')->getDefaultCurrency(); /** @var AvailableBudget $availableBudget */ foreach ($availableBudgets as $availableBudget) { $currencyId = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? $default->id : $availableBudget->transaction_currency_id; $field = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? 'native_amount' : 'amount'; - $return[$currencyId] = $return[$currencyId] ?? '0'; - $return[$currencyId] = bcadd($return[$currencyId], $availableBudget->$field); + $return[$currencyId] ??= '0'; + $return[$currencyId] = bcadd($return[$currencyId], $availableBudget->{$field}); } + return $return; } @@ -175,9 +179,10 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection { return $this->user->availableBudgets() - ->where('start_date', '=', $start->format('Y-m-d')) - ->where('end_date', '=', $end->format('Y-m-d')) - ->get(); + ->where('start_date', '=', $start->format('Y-m-d')) + ->where('end_date', '=', $end->format('Y-m-d')) + ->get() + ; } public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget @@ -186,7 +191,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface ->availableBudgets() ->where('transaction_currency_id', $currency->id) ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->first(); + ->where('end_date', $end->format('Y-m-d'))->first() + ; } /** @@ -194,12 +200,13 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface */ public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget { - $availableBudget = $this->user->availableBudgets() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->first(); + $availableBudget = $this->user->availableBudgets() + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->first() + ; if (null === $availableBudget) { - $availableBudget = new AvailableBudget(); + $availableBudget = new AvailableBudget(); $availableBudget->user()->associate($this->user); $availableBudget->transactionCurrency()->associate($currency); $availableBudget->start_date = $start->startOfDay()->format('Y-m-d'); // @phpstan-ignore-line @@ -213,7 +220,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $availableBudget; } - public function setUser(null | Authenticatable | User $user): void + public function setUser(null|Authenticatable|User $user): void { if ($user instanceof User) { $this->user = $user; @@ -226,7 +233,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface if ($start instanceof Carbon) { $start = $data['start']->startOfDay(); } - $end = $data['end']; + $end = $data['end']; if ($end instanceof Carbon) { $end = $data['end']->endOfDay(); } diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 95f649a71a..1caaf5b532 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -63,7 +63,7 @@ class OperationsRepository implements OperationsRepositoryInterface ++$count; app('log')->debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total)); } - $avg = $total; + $avg = $total; if ($count > 0) { $avg = bcdiv($total, (string) $count); } @@ -85,21 +85,21 @@ class OperationsRepository implements OperationsRepositoryInterface // get all transactions: /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setAccounts($accounts)->setRange($start, $end); $collector->setBudgets($budgets); - $journals = $collector->getExtractedJournals(); + $journals = $collector->getExtractedJournals(); // loop transactions: /** @var array $journal */ foreach ($journals as $journal) { // prep data array for currency: - $budgetId = (int) $journal['budget_id']; - $budgetName = $journal['budget_name']; - $currencyId = (int) $journal['currency_id']; - $key = sprintf('%d-%d', $budgetId, $currencyId); + $budgetId = (int) $journal['budget_id']; + $budgetName = $journal['budget_name']; + $currencyId = (int) $journal['currency_id']; + $key = sprintf('%d-%d', $budgetId, $currencyId); - $data[$key] ??= [ + $data[$key] ??= [ 'id' => $budgetId, 'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']), 'sum' => '0', @@ -137,13 +137,13 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setBudgets($this->getBudgets()); } $collector->withBudgetInformation()->withAccountInformation()->withCategoryInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $budgetId = (int) $journal['budget_id']; - $budgetName = (string) $journal['budget_name']; + $currencyId = (int) $journal['currency_id']; + $budgetId = (int) $journal['budget_id']; + $budgetName = (string) $journal['budget_name']; // catch "no category" entries. if (0 === $budgetId) { @@ -151,7 +151,7 @@ class OperationsRepository implements OperationsRepositoryInterface } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'budgets' => [], 'currency_id' => $currencyId, 'currency_name' => $journal['currency_name'], @@ -186,7 +186,7 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } - public function setUser(null | Authenticatable | User $user): void + public function setUser(null|Authenticatable|User $user): void { if ($user instanceof User) { $this->user = $user; @@ -210,8 +210,7 @@ class OperationsRepository implements OperationsRepositoryInterface ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null - ): array - { + ): array { Log::debug('Start of sumExpenses.'); // this collector excludes all transfers TO liabilities (which are also withdrawals) // because those expenses only become expenses once they move from the liability to the friend. @@ -219,10 +218,10 @@ class OperationsRepository implements OperationsRepositoryInterface // 2024-12-24 disable the exclusion for now. - $repository = app(AccountRepositoryInterface::class); + $repository = app(AccountRepositoryInterface::class); $repository->setUser($this->user); - $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); - $selection = new Collection(); + $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); + $selection = new Collection(); // default currency information for native stuff. $convertToNative = app('preferences')->get('convert_to_native', false)->data; @@ -236,11 +235,12 @@ class OperationsRepository implements OperationsRepositoryInterface } /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user) - ->setRange($start, $end) + ->setRange($start, $end) // ->excludeDestinationAccounts($selection) - ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); + ->setTypes([TransactionTypeEnum::WITHDRAWAL->value]) + ; if (null !== $accounts) { $collector->setAccounts($accounts); @@ -253,46 +253,46 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setNormalCurrency($currency); } $collector->setBudgets($budgets); - $journals = $collector->getExtractedJournals(); + $journals = $collector->getExtractedJournals(); // same but for transactions in the foreign currency: if (null !== $currency) { Log::debug('STOP looking for transactions in the foreign currency.'); -// Log::debug(sprintf('Look for transactions with foreign currency %s', $currency->code)); -// // app('log')->debug(sprintf('Currency is "%s".', $currency->name)); -// /** @var GroupCollectorInterface $collector */ -// $collector = app(GroupCollectorInterface::class); -// $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setForeignCurrency($currency)->setBudgets($budgets); -// -// if (null !== $accounts) { -// $collector->setAccounts($accounts); -// } -// $result = $collector->getExtractedJournals(); -// // app('log')->debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code)); -// // do not use array_merge because you want keys to overwrite (otherwise you get double results): -// Log::debug(sprintf('Found %d extra journals in foreign currency.', count($result))); -// $journals = $result + $journals; + // Log::debug(sprintf('Look for transactions with foreign currency %s', $currency->code)); + // // app('log')->debug(sprintf('Currency is "%s".', $currency->name)); + // /** @var GroupCollectorInterface $collector */ + // $collector = app(GroupCollectorInterface::class); + // $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value])->setForeignCurrency($currency)->setBudgets($budgets); + // + // if (null !== $accounts) { + // $collector->setAccounts($accounts); + // } + // $result = $collector->getExtractedJournals(); + // // app('log')->debug(sprintf('Found %d journals with currency %s.', count($result), $currency->code)); + // // do not use array_merge because you want keys to overwrite (otherwise you get double results): + // Log::debug(sprintf('Found %d extra journals in foreign currency.', count($result))); + // $journals = $result + $journals; } - $array = []; + $array = []; foreach ($journals as $journal) { -// Log::debug(sprintf('Journal #%d.', $journal['transaction_journal_id'])); -// Log::debug(sprintf('Amounts: %1$s %2$s (amount), %3$s %4$s (foreign_amount), %5$s %6$s (native_amount) %5$s %7$s (foreign native amount)', -// $journal['currency_code'], $journal['amount'], $journal['foreign_currency_code'], $journal['foreign_amount'], -// $default->code, $journal['native_amount'], $journal['native_foreign_amount']) -// ); + // Log::debug(sprintf('Journal #%d.', $journal['transaction_journal_id'])); + // Log::debug(sprintf('Amounts: %1$s %2$s (amount), %3$s %4$s (foreign_amount), %5$s %6$s (native_amount) %5$s %7$s (foreign native amount)', + // $journal['currency_code'], $journal['amount'], $journal['foreign_currency_code'], $journal['foreign_amount'], + // $default->code, $journal['native_amount'], $journal['native_foreign_amount']) + // ); // TODO same as in category::sumexpenses - $amount = '0'; - $currencyId = (int) $journal['currency_id']; - $currencyName = $journal['currency_name']; - $currencySymbol = $journal['currency_symbol']; - $currencyCode = $journal['currency_code']; - $currencyDecimalPlaces = $journal['currency_decimal_places']; + $amount = '0'; + $currencyId = (int) $journal['currency_id']; + $currencyName = $journal['currency_name']; + $currencySymbol = $journal['currency_symbol']; + $currencyCode = $journal['currency_code']; + $currencyDecimalPlaces = $journal['currency_decimal_places']; if ($convertToNative) { $useNative = $default->id !== (int) $journal['currency_id']; - $amount = Amount::getAmountFromJournal($journal); - if($useNative) { + $amount = Amount::getAmountFromJournal($journal); + if ($useNative) { Log::debug(sprintf('Journal #%d switches to native amount (original is %s)', $journal['transaction_journal_id'], $journal['currency_code'])); $currencyId = $default->id; $currencyName = $default->name; @@ -302,12 +302,12 @@ class OperationsRepository implements OperationsRepositoryInterface } } if (!$convertToNative) { - $amount = $journal['amount']; + $amount = $journal['amount']; // if the amount is not in $currency (but should be), use the foreign_amount if that one is correct. // otherwise, ignore the transaction all together. if (null !== $currency && $currencyId !== $currency->id && $currency->id === (int) $journal['foreign_currency_id']) { Log::debug(sprintf('Journal #%d switches to foreign amount because it matches native.', $journal['transaction_journal_id'])); - $amount = $journal['foreign_amount']; + $amount = $journal['foreign_amount']; $currencyId = (int) $journal['foreign_currency_id']; $currencyName = $journal['foreign_currency_name']; $currencySymbol = $journal['foreign_currency_symbol']; @@ -315,7 +315,7 @@ class OperationsRepository implements OperationsRepositoryInterface $currencyDecimalPlaces = $journal['foreign_currency_decimal_places']; } } - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'sum' => '0', 'currency_id' => $currencyId, 'currency_name' => $currencyName, @@ -327,6 +327,7 @@ class OperationsRepository implements OperationsRepositoryInterface Log::debug(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount)); } Log::debug('End of sumExpenses.', $array); + return $array; } } diff --git a/app/Repositories/Category/NoCategoryRepository.php b/app/Repositories/Category/NoCategoryRepository.php index a5c8dfe2e5..9b6fca8aec 100644 --- a/app/Repositories/Category/NoCategoryRepository.php +++ b/app/Repositories/Category/NoCategoryRepository.php @@ -145,26 +145,26 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null): array { /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->withoutCategory(); if (null !== $accounts && $accounts->count() > 0) { $collector->setAccounts($accounts); } - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; // default currency information for native stuff. $convertToNative = app('preferences')->get('convert_to_native', false)->data; $default = app('amount')->getDefaultCurrency(); foreach ($journals as $journal) { // Almost the same as in \FireflyIII\Repositories\Budget\OperationsRepository::sumExpenses - $amount = '0'; - $currencyId = (int) $journal['currency_id']; - $currencyName = $journal['currency_name']; - $currencySymbol = $journal['currency_symbol']; - $currencyCode = $journal['currency_code']; - $currencyDecimalPlaces = $journal['currency_decimal_places']; + $amount = '0'; + $currencyId = (int) $journal['currency_id']; + $currencyName = $journal['currency_name']; + $currencySymbol = $journal['currency_symbol']; + $currencyCode = $journal['currency_code']; + $currencyDecimalPlaces = $journal['currency_decimal_places']; if ($convertToNative) { $useNative = $default->id !== (int) $journal['currency_id']; $amount = Amount::getAmountFromJournal($journal); @@ -184,7 +184,7 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface } - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'sum' => '0', 'currency_id' => (string) $currencyId, 'currency_name' => $currencyName, diff --git a/app/Repositories/Category/OperationsRepository.php b/app/Repositories/Category/OperationsRepository.php index d51264dd61..5f62bf2433 100644 --- a/app/Repositories/Category/OperationsRepository.php +++ b/app/Repositories/Category/OperationsRepository.php @@ -63,13 +63,13 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setCategories($this->getCategories()); } $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -77,7 +77,7 @@ class OperationsRepository implements OperationsRepositoryInterface } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'categories' => [], 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], @@ -112,7 +112,7 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } - public function setUser(null | Authenticatable | User $user): void + public function setUser(null|Authenticatable|User $user): void { if ($user instanceof User) { $this->user = $user; @@ -147,13 +147,13 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setCategories($this->getCategories()); } $collector->withCategoryInformation()->withAccountInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -161,7 +161,7 @@ class OperationsRepository implements OperationsRepositoryInterface } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'categories' => [], 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], @@ -200,7 +200,8 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) - ->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts); + ->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts) + ; if (null !== $categories && $categories->count() > 0) { $collector->setCategories($categories); } @@ -208,13 +209,13 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setCategories($this->getCategories()); } $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -222,7 +223,7 @@ class OperationsRepository implements OperationsRepositoryInterface } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'categories' => [], 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], @@ -262,7 +263,8 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) - ->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts); + ->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts) + ; if (null !== $categories && $categories->count() > 0) { $collector->setCategories($categories); } @@ -270,13 +272,13 @@ class OperationsRepository implements OperationsRepositoryInterface $collector->setCategories($this->getCategories()); } $collector->withCategoryInformation()->withAccountInformation()->withBudgetInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int) $journal['currency_id']; + $categoryId = (int) $journal['category_id']; + $categoryName = (string) $journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -284,7 +286,7 @@ class OperationsRepository implements OperationsRepositoryInterface } // info about the currency: - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'categories' => [], 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], @@ -325,7 +327,7 @@ class OperationsRepository implements OperationsRepositoryInterface public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array { /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); // default currency information for native stuff. @@ -339,19 +341,19 @@ class OperationsRepository implements OperationsRepositoryInterface } $collector->setCategories($categories); $collector->withCategoryInformation(); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; Log::debug(sprintf('Collected %d journals', count($journals))); foreach ($journals as $journal) { // Almost the same as in \FireflyIII\Repositories\Budget\OperationsRepository::sumExpenses - $amount = '0'; - $currencyId = (int) $journal['currency_id']; - $currencyName = $journal['currency_name']; - $currencySymbol = $journal['currency_symbol']; - $currencyCode = $journal['currency_code']; - $currencyDecimalPlaces = $journal['currency_decimal_places']; + $amount = '0'; + $currencyId = (int) $journal['currency_id']; + $currencyName = $journal['currency_name']; + $currencySymbol = $journal['currency_symbol']; + $currencyCode = $journal['currency_code']; + $currencyDecimalPlaces = $journal['currency_decimal_places']; if ($convertToNative) { $useNative = $default->id !== (int) $journal['currency_id']; $amount = Amount::getAmountFromJournal($journal); @@ -371,7 +373,7 @@ class OperationsRepository implements OperationsRepositoryInterface } - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'sum' => '0', 'currency_id' => (string) $currencyId, 'currency_name' => $currencyName, @@ -393,7 +395,8 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end) - ->setTypes([TransactionType::DEPOSIT]); + ->setTypes([TransactionType::DEPOSIT]) + ; if (null !== $accounts && $accounts->count() > 0) { $collector->setAccounts($accounts); @@ -402,12 +405,12 @@ class OperationsRepository implements OperationsRepositoryInterface $categories = $this->getCategories(); } $collector->setCategories($categories); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { $currencyId = (int) $journal['currency_id']; - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'sum' => '0', 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], @@ -429,7 +432,8 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end) - ->setTypes([TransactionType::TRANSFER]); + ->setTypes([TransactionType::TRANSFER]) + ; if (null !== $accounts && $accounts->count() > 0) { $collector->setAccounts($accounts); @@ -438,12 +442,12 @@ class OperationsRepository implements OperationsRepositoryInterface $categories = $this->getCategories(); } $collector->setCategories($categories); - $journals = $collector->getExtractedJournals(); - $array = []; + $journals = $collector->getExtractedJournals(); + $array = []; foreach ($journals as $journal) { $currencyId = (int) $journal['currency_id']; - $array[$currencyId] ??= [ + $array[$currencyId] ??= [ 'sum' => '0', 'currency_id' => (string) $currencyId, 'currency_name' => $journal['currency_name'], diff --git a/app/Support/Amount.php b/app/Support/Amount.php index 8674225ecd..2bfc6fb070 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -58,12 +58,13 @@ class Amount $currency = app('amount')->getDefaultCurrency(); $field = $convertToNative && $currency->id !== $journal['currency_id'] ? 'native_amount' : 'amount'; $amount = $journal[$field] ?? '0'; - //Log::debug(sprintf('Field is %s, amount is %s', $field, $amount)); + // Log::debug(sprintf('Field is %s, amount is %s', $field, $amount)); // fallback, the transaction has a foreign amount in $currency. if ($convertToNative && null !== $journal['foreign_amount'] && $currency->id === (int)$journal['foreign_currency_id']) { $amount = $journal['foreign_amount']; - //Log::debug(sprintf('Overruled, amount is now %s', $amount)); + // Log::debug(sprintf('Overruled, amount is now %s', $amount)); } + return $amount; } @@ -73,23 +74,24 @@ class Amount */ public function getAmountFromJournalObject(TransactionJournal $journal): string { - $convertToNative = app('preferences')->get('convert_to_native', false)->data; - $currency = app('amount')->getDefaultCurrency(); - $field = $convertToNative && $currency->id !== $journal->transaction_currency_id ? 'native_amount' : 'amount'; + $convertToNative = app('preferences')->get('convert_to_native', false)->data; + $currency = app('amount')->getDefaultCurrency(); + $field = $convertToNative && $currency->id !== $journal->transaction_currency_id ? 'native_amount' : 'amount'; + /** @var null|Transaction $sourceTransaction */ $sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first(); if (null === $sourceTransaction) { return '0'; } - $amount = $sourceTransaction->$field; + $amount = $sourceTransaction->{$field}; if ((int) $sourceTransaction->foreign_currency_id === $currency->id) { // use foreign amount instead! $amount = (string) $sourceTransaction->foreign_amount; // hard coded to be foreign amount. } + return $amount; } - /** * This method will properly format the given number, in color or "black and white", * as a currency, given two things: the currency required and the current locale. @@ -100,15 +102,15 @@ class Amount */ public function formatFlat(string $symbol, int $decimalPlaces, string $amount, ?bool $coloured = null): string { - $locale = app('steam')->getLocale(); - $rounded = app('steam')->bcround($amount, $decimalPlaces); + $locale = app('steam')->getLocale(); + $rounded = app('steam')->bcround($amount, $decimalPlaces); $coloured ??= true; - $fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); + $fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); $fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $symbol); $fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $decimalPlaces); $fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $decimalPlaces); - $result = (string) $fmt->format((float) $rounded); // intentional float + $result = (string) $fmt->format((float) $rounded); // intentional float if (true === $coloured) { if (1 === bccomp($rounded, '0')) { @@ -154,7 +156,7 @@ class Amount public function getDefaultCurrencyByUserGroup(UserGroup $userGroup): TransactionCurrency { - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty('getDefaultCurrencyByGroup'); $cache->addProperty($userGroup->id); if ($cache->has()) { @@ -217,20 +219,20 @@ class Amount private function getLocaleInfo(): array { // get config from preference, not from translation: - $locale = app('steam')->getLocale(); - $array = app('steam')->getLocaleArray($locale); + $locale = app('steam')->getLocale(); + $array = app('steam')->getLocaleArray($locale); setlocale(LC_MONETARY, $array); - $info = localeconv(); + $info = localeconv(); // correct variables - $info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes'); - $info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes'); + $info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes'); + $info['p_cs_precedes'] = $this->getLocaleField($info, 'p_cs_precedes'); - $info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space'); - $info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space'); + $info['n_sep_by_space'] = $this->getLocaleField($info, 'n_sep_by_space'); + $info['p_sep_by_space'] = $this->getLocaleField($info, 'p_sep_by_space'); - $fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); + $fmt = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); $info['mon_decimal_point'] = $fmt->getSymbol(\NumberFormatter::MONETARY_SEPARATOR_SYMBOL); $info['mon_thousands_sep'] = $fmt->getSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL); @@ -253,7 +255,7 @@ class Amount public static function getAmountJsConfig(bool $sepBySpace, int $signPosn, string $sign, bool $csPrecedes): string { // negative first: - $space = ' '; + $space = ' '; // require space between symbol and amount? if (false === $sepBySpace) { @@ -262,11 +264,11 @@ class Amount // there are five possible positions for the "+" or "-" sign (if it is even used) // pos_a and pos_e could be the ( and ) symbol. - $posA = ''; // before everything - $posB = ''; // before currency symbol - $posC = ''; // after currency symbol - $posD = ''; // before amount - $posE = ''; // after everything + $posA = ''; // before everything + $posB = ''; // before currency symbol + $posC = ''; // after currency symbol + $posD = ''; // before amount + $posE = ''; // after everything // format would be (currency before amount) // AB%sC_D%vE @@ -308,11 +310,11 @@ class Amount } // default is amount before currency - $format = $posA . $posD . '%v' . $space . $posB . '%s' . $posC . $posE; + $format = $posA.$posD.'%v'.$space.$posB.'%s'.$posC.$posE; if ($csPrecedes) { // alternative is currency before amount - $format = $posA . $posB . '%s' . $posC . $space . $posD . '%v' . $posE; + $format = $posA.$posB.'%s'.$posC.$space.$posD.'%v'.$posE; } return $format; diff --git a/app/Support/Chart/Budget/FrontpageChartGenerator.php b/app/Support/Chart/Budget/FrontpageChartGenerator.php index b67973b1c2..0481718c47 100644 --- a/app/Support/Chart/Budget/FrontpageChartGenerator.php +++ b/app/Support/Chart/Budget/FrontpageChartGenerator.php @@ -48,7 +48,6 @@ class FrontpageChartGenerator public bool $convertToNative = false; public TransactionCurrency $default; - /** * FrontpageChartGenerator constructor. */ @@ -100,10 +99,12 @@ class FrontpageChartGenerator if (0 === $limits->count()) { $result = $this->noBudgetLimits($data, $budget); Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name)); + return $result; } $result = $this->budgetLimits($data, $budget, $limits); Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name)); + return $result; } @@ -132,6 +133,7 @@ class FrontpageChartGenerator private function budgetLimits(array $data, Budget $budget, Collection $limits): array { Log::debug('Start processing budget limits.'); + /** @var BudgetLimit $limit */ foreach ($limits as $limit) { $data = $this->processLimit($data, $budget, $limit); @@ -156,8 +158,9 @@ class FrontpageChartGenerator Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $limit->transactionCurrency->code, $limit->amount)); } - $spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $currency); + $spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $currency); Log::debug(sprintf('Spent array has %d entries.', count($spent))); + /** @var array $entry */ foreach ($spent as $entry) { // only spent the entry where the entry's currency matches the budget limit's currency @@ -182,7 +185,7 @@ class FrontpageChartGenerator */ private function processRow(array $data, Budget $budget, BudgetLimit $limit, array $entry): array { - $title = sprintf('%s (%s)', $budget->name, $entry['currency_name']); + $title = sprintf('%s (%s)', $budget->name, $entry['currency_name']); Log::debug(sprintf('Title is "%s"', $title)); if ($limit->start_date->startOfDay()->ne($this->start->startOfDay()) || $limit->end_date->startOfDay()->ne($this->end->startOfDay())) { $title = sprintf( @@ -193,22 +196,22 @@ class FrontpageChartGenerator $limit->end_date->isoFormat($this->monthAndDayFormat) ); } - $useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id; - $amount = $limit->amount; - if($useNative) { + $useNative = $this->convertToNative && $this->default->id !== $limit->transaction_currency_id; + $amount = $limit->amount; + if ($useNative) { $amount = $limit->native_amount; } - $sumSpent = bcmul($entry['sum'], '-1'); // spent + $sumSpent = bcmul($entry['sum'], '-1'); // spent $data[0]['entries'][$title] ??= '0'; $data[1]['entries'][$title] ??= '0'; $data[2]['entries'][$title] ??= '0'; $data[0]['entries'][$title] = bcadd($data[0]['entries'][$title], 1 === bccomp($sumSpent, $amount) ? $amount : $sumSpent); // spent - $data[1]['entries'][$title] = bcadd($data[1]['entries'][$title],1 === bccomp($amount, $sumSpent) ? bcadd($entry['sum'], $amount) : '0'); // left to spent - $data[2]['entries'][$title] = bcadd($data[2]['entries'][$title],1 === bccomp($amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $amount), '-1')); // overspent + $data[1]['entries'][$title] = bcadd($data[1]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? bcadd($entry['sum'], $amount) : '0'); // left to spent + $data[2]['entries'][$title] = bcadd($data[2]['entries'][$title], 1 === bccomp($amount, $sumSpent) ? '0' : bcmul(bcadd($entry['sum'], $amount), '-1')); // overspent Log::debug(sprintf('Amount [spent] is now %s.', $data[0]['entries'][$title])); Log::debug(sprintf('Amount [left] is now %s.', $data[1]['entries'][$title])); diff --git a/app/Support/Chart/Category/FrontpageChartGenerator.php b/app/Support/Chart/Category/FrontpageChartGenerator.php index d46992d107..d9d8da6884 100644 --- a/app/Support/Chart/Category/FrontpageChartGenerator.php +++ b/app/Support/Chart/Category/FrontpageChartGenerator.php @@ -67,11 +67,11 @@ class FrontpageChartGenerator public function generate(): array { Log::debug('Now in generate()'); - $categories = $this->repository->getCategories(); - $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]); + $categories = $this->repository->getCategories(); + $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]); // get expenses + income per category: - $collection = []; + $collection = []; /** @var Category $category */ foreach ($categories as $category) { @@ -82,10 +82,10 @@ class FrontpageChartGenerator // collect for no-category: $collection[] = $this->collectNoCatExpenses($accounts); - $tempData = array_merge(...$collection); + $tempData = array_merge(...$collection); // sort temp array by amount. - $amounts = array_column($tempData, 'sum_float'); + $amounts = array_column($tempData, 'sum_float'); array_multisort($amounts, SORT_ASC, $tempData); $currencyData = $this->createCurrencyGroups($tempData); diff --git a/app/Support/Http/Api/ExchangeRateConverter.php b/app/Support/Http/Api/ExchangeRateConverter.php index 2062bacae4..dfe9cd7753 100644 --- a/app/Support/Http/Api/ExchangeRateConverter.php +++ b/app/Support/Http/Api/ExchangeRateConverter.php @@ -30,7 +30,6 @@ use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\UserGroup; use FireflyIII\Support\CacheProperties; -use FireflyIII\User; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Log; @@ -101,8 +100,8 @@ class ExchangeRateConverter */ private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string { - $key = $this->getCacheKey($from, $to, $date); - $res = Cache::get($key, null); + $key = $this->getCacheKey($from, $to, $date); + $res = Cache::get($key, null); // find in cache if (null !== $res) { @@ -112,7 +111,7 @@ class ExchangeRateConverter } // find in database - $rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d')); + $rate = $this->getFromDB($from->id, $to->id, $date->format('Y-m-d')); if (null !== $rate) { Cache::forever($key, $rate); Log::debug(sprintf('ExchangeRateConverter: Return DB rate from #%d to #%d on %s.', $from->id, $to->id, $date->format('Y-m-d'))); @@ -121,7 +120,7 @@ class ExchangeRateConverter } // find reverse in database - $rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d')); + $rate = $this->getFromDB($to->id, $from->id, $date->format('Y-m-d')); if (null !== $rate) { $rate = bcdiv('1', $rate); Cache::forever($key, $rate); @@ -159,7 +158,7 @@ class ExchangeRateConverter if ($from === $to) { return '1'; } - $key = sprintf('cer-%d-%d-%s', $from, $to, $date); + $key = sprintf('cer-%d-%d-%s', $from, $to, $date); // perhaps the rate has been cached during this particular run $preparedRate = $this->prepared[$date][$from][$to] ?? null; @@ -169,7 +168,7 @@ class ExchangeRateConverter return $preparedRate; } - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($key); if ($cache->has()) { $rate = $cache->get(); @@ -182,14 +181,15 @@ class ExchangeRateConverter } /** @var null|CurrencyExchangeRate $result */ - $result = $this->userGroup->currencyExchangeRates() - ->where('from_currency_id', $from) - ->where('to_currency_id', $to) - ->where('date', '<=', $date) - ->orderBy('date', 'DESC') - ->first(); + $result = $this->userGroup->currencyExchangeRates() + ->where('from_currency_id', $from) + ->where('to_currency_id', $to) + ->where('date', '<=', $date) + ->orderBy('date', 'DESC') + ->first() + ; ++$this->queryCount; - $rate = (string) $result?->rate; + $rate = (string) $result?->rate; if ('' === $rate) { app('log')->debug(sprintf('ExchangeRateConverter: Found no rate for #%d->#%d (%s) in the DB.', $from, $to, $date)); @@ -229,13 +229,13 @@ class ExchangeRateConverter if ($euroId === $currency->id) { return '1'; } - $rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d')); + $rate = $this->getFromDB($currency->id, $euroId, $date->format('Y-m-d')); if (null !== $rate) { // app('log')->debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate)); return $rate; } - $rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d')); + $rate = $this->getFromDB($euroId, $currency->id, $date->format('Y-m-d')); if (null !== $rate) { return bcdiv('1', $rate); // app('log')->debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate)); @@ -264,7 +264,7 @@ class ExchangeRateConverter if ($cache->has()) { return (int) $cache->get(); } - $euro = TransactionCurrency::whereCode('EUR')->first(); + $euro = TransactionCurrency::whereCode('EUR')->first(); ++$this->queryCount; if (null === $euro) { throw new FireflyException('Cannot find EUR in system, cannot do currency conversion.'); @@ -286,13 +286,14 @@ class ExchangeRateConverter $start->startOfDay(); $end->endOfDay(); Log::debug(sprintf('Preparing for %s to %s between %s and %s', $from->code, $to->code, $start->format('Y-m-d'), $end->format('Y-m-d'))); - $set = $this->userGroup - ->currencyExchangeRates() - ->where('from_currency_id', $from->id) - ->where('to_currency_id', $to->id) - ->where('date', '<=', $end->format('Y-m-d')) - ->where('date', '>=', $start->format('Y-m-d')) - ->orderBy('date', 'DESC')->get(); + $set = $this->userGroup + ->currencyExchangeRates() + ->where('from_currency_id', $from->id) + ->where('to_currency_id', $to->id) + ->where('date', '<=', $end->format('Y-m-d')) + ->where('date', '>=', $start->format('Y-m-d')) + ->orderBy('date', 'DESC')->get() + ; ++$this->queryCount; if (0 === $set->count()) { Log::debug('No prepared rates found in this period, use the fallback'); @@ -306,10 +307,10 @@ class ExchangeRateConverter $this->isPrepared = true; // so there is a fallback just in case. Now loop the set of rates we DO have. - $temp = []; - $count = 0; + $temp = []; + $count = 0; foreach ($set as $rate) { - $date = $rate->date->format('Y-m-d'); + $date = $rate->date->format('Y-m-d'); $temp[$date] ??= [ $from->id => [ $to->id => $rate->rate, @@ -318,11 +319,11 @@ class ExchangeRateConverter ++$count; } Log::debug(sprintf('Found %d rates in this period.', $count)); - $currentStart = clone $start; + $currentStart = clone $start; while ($currentStart->lte($end)) { - $currentDate = $currentStart->format('Y-m-d'); + $currentDate = $currentStart->format('Y-m-d'); $this->prepared[$currentDate] ??= []; - $fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0'; + $fallback = $temp[$currentDate][$from->id][$to->id] ?? $this->fallback[$from->id][$to->id] ?? '0'; if (0 === count($this->prepared[$currentDate]) && 0 !== bccomp('0', $fallback)) { // fill from temp or fallback or from temp (see before) $this->prepared[$currentDate][$from->id][$to->id] = $fallback; diff --git a/app/Support/Http/Controllers/BasicDataSupport.php b/app/Support/Http/Controllers/BasicDataSupport.php index ccaba3aeb8..2030c58f85 100644 --- a/app/Support/Http/Controllers/BasicDataSupport.php +++ b/app/Support/Http/Controllers/BasicDataSupport.php @@ -39,6 +39,7 @@ trait BasicDataSupport protected function isInArray(array $array, int $entryId) { $key = $this->convertToNative ? 'native_balance' : 'balance'; + return $array[$entryId][$key] ?? '0'; } diff --git a/app/Support/Http/Controllers/ChartGeneration.php b/app/Support/Http/Controllers/ChartGeneration.php index e0fec6c262..4f425483d9 100644 --- a/app/Support/Http/Controllers/ChartGeneration.php +++ b/app/Support/Http/Controllers/ChartGeneration.php @@ -54,7 +54,7 @@ trait ChartGeneration $cache->addProperty($accounts); $cache->addProperty($convertToNative); if ($cache->has()) { - //return $cache->get(); + // return $cache->get(); } app('log')->debug('Regenerate chart.account.account-balance-chart from scratch.'); $locale = app('steam')->getLocale(); @@ -70,10 +70,10 @@ trait ChartGeneration /** @var Account $account */ foreach ($accounts as $account) { - $currency = $accountRepos->getAccountCurrency($account) ?? $default; - $useNative = $convertToNative && $default->id !== $currency->id; - $field =$useNative ? 'native_balance' : 'balance'; - $currency = $useNative ? $default : $currency; + $currency = $accountRepos->getAccountCurrency($account) ?? $default; + $useNative = $convertToNative && $default->id !== $currency->id; + $field = $useNative ? 'native_balance' : 'balance'; + $currency = $useNative ? $default : $currency; $currentSet = [ 'label' => $account->name, 'currency_symbol' => $currency->symbol, diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 6454d940ee..72807b4c0f 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -38,8 +38,8 @@ class Steam { public function getAccountCurrency(Account $account): ?TransactionCurrency { - $type = $account->accountType->type; - $list = config('firefly.valid_currency_account_types'); + $type = $account->accountType->type; + $list = config('firefly.valid_currency_account_types'); // return null if not in this list. if (!in_array($type, $list, true)) { @@ -62,7 +62,7 @@ class Steam $value = (string) ($transaction[$key] ?? '0'); $value = '' === $value ? '0' : $value; $sum = bcadd($sum, $value); - //Log::debug(sprintf('Add value from "%s": %s', $key, $value)); + // Log::debug(sprintf('Add value from "%s": %s', $key, $value)); } Log::debug(sprintf('Sum of "%s"-fields is %s', $key, $sum)); @@ -76,7 +76,7 @@ class Steam $end->addDay()->endOfDay(); // set up cache - $cache = new CacheProperties(); + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty('final-balance-in-range'); $cache->addProperty($start); @@ -85,51 +85,52 @@ class Steam // return $cache->get(); } - $balances = []; - $formatted = $start->format('Y-m-d'); - $startBalance = $this->finalAccountBalance($account, $start); - $defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); - $currency = $this->getAccountCurrency($account) ?? $defaultCurrency; - $currencies = [ + $balances = []; + $formatted = $start->format('Y-m-d'); + $startBalance = $this->finalAccountBalance($account, $start); + $defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($account->user->userGroup); + $currency = $this->getAccountCurrency($account) ?? $defaultCurrency; + $currencies = [ $currency->id => $currency, $defaultCurrency->id => $defaultCurrency, ]; $startBalance[$defaultCurrency->code] ??= '0'; $startBalance[$currency->code] ??= '0'; - $balances[$formatted] = $startBalance; + $balances[$formatted] = $startBalance; // sums up the balance changes per day, for foreign, native and normal amounts. - $set = $account->transactions() - ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s')) - ->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s')) - ->groupBy('transaction_journals.date') - ->groupBy('transactions.transaction_currency_id') - ->groupBy('transactions.foreign_currency_id') - ->orderBy('transaction_journals.date', 'ASC') - ->whereNull('transaction_journals.deleted_at') - ->get( - [ // @phpstan-ignore-line - 'transaction_journals.date', - 'transactions.transaction_currency_id', - \DB::raw('SUM(transactions.amount) AS modified'), - 'transactions.foreign_currency_id', - \DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), - \DB::raw('SUM(transactions.native_amount) AS modified_native'), - ] - ); + $set = $account->transactions() + ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d H:i:s')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d H:i:s')) + ->groupBy('transaction_journals.date') + ->groupBy('transactions.transaction_currency_id') + ->groupBy('transactions.foreign_currency_id') + ->orderBy('transaction_journals.date', 'ASC') + ->whereNull('transaction_journals.deleted_at') + ->get( + [ // @phpstan-ignore-line + 'transaction_journals.date', + 'transactions.transaction_currency_id', + \DB::raw('SUM(transactions.amount) AS modified'), + 'transactions.foreign_currency_id', + \DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), + \DB::raw('SUM(transactions.native_amount) AS modified_native'), + ] + ) + ; - $currentBalance = $startBalance; + $currentBalance = $startBalance; /** @var Transaction $entry */ foreach ($set as $entry) { // normal, native and foreign amount - $carbon = new Carbon($entry->date, $entry->date_tz); - $modified = (string) (null === $entry->modified ? '0' : $entry->modified); - $foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign); - $nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native); + $carbon = new Carbon($entry->date, $entry->date_tz); + $modified = (string) (null === $entry->modified ? '0' : $entry->modified); + $foreignModified = (string) (null === $entry->modified_foreign ? '0' : $entry->modified_foreign); + $nativeModified = (string) (null === $entry->modified_native ? '0' : $entry->modified_native); // add "modified" to amount if the currency id matches the account currency id. if ($entry->transaction_currency_id === $currency->id) { @@ -138,7 +139,7 @@ class Steam } // always add the native balance, even if it ends up at zero. - $currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeModified); + $currentBalance['native_balance'] = bcadd($currentBalance['native_balance'], $nativeModified); // add modified foreign to the array if (null !== $entry->foreign_currency_id) { @@ -184,10 +185,10 @@ class Steam // Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision)); if (str_contains($number, '.')) { if ('-' !== $number[0]) { - return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision); + return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision); } - return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision); + return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision); } return $number; @@ -272,7 +273,6 @@ class Steam * Wil je niks weten van native currencies, pak je: * * Eerst een som van alle transacties gegroepeerd op currency. Einde. - * */ public function finalAccountBalance(Account $account, Carbon $date): array { @@ -282,67 +282,71 @@ class Steam $accountCurrency = $this->getAccountCurrency($account); $hasCurrency = null !== $accountCurrency; $currency = $hasCurrency ? $accountCurrency : $native; - $return = []; + $return = []; // first, the "balance", as described earlier. if ($convertToNative) { // normal balance - $return['balance'] = (string) $account->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) - ->where('transactions.transaction_currency_id', $native->id) - ->sum('transactions.amount'); + $return['balance'] = (string) $account->transactions() + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) + ->where('transactions.transaction_currency_id', $native->id) + ->sum('transactions.amount') + ; // plus virtual balance, if the account has a virtual_balance in the native currency - if($native->id === $accountCurrency?->id) { + if ($native->id === $accountCurrency?->id) { $return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']); } Log::debug(sprintf('balance is (%s only) %s (with virtual balance)', $native->code, $return['balance'])); // native balance $return['native_balance'] = (string) $account->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) - ->whereNot('transactions.transaction_currency_id', $native->id) - ->sum('transactions.native_amount'); + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) + ->whereNot('transactions.transaction_currency_id', $native->id) + ->sum('transactions.native_amount') + ; // plus native virtual balance. $return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_balance']); Log::debug(sprintf('native_balance is (all transactions to %s) %s (with virtual balance)', $native->code, $return['native_balance'])); // plus foreign transactions in THIS currency. $sum = (string) $account->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) - ->whereNot('transactions.transaction_currency_id', $native->id) - ->where('transactions.foreign_currency_id', $native->id) - ->sum('transactions.foreign_amount'); + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) + ->whereNot('transactions.transaction_currency_id', $native->id) + ->where('transactions.foreign_currency_id', $native->id) + ->sum('transactions.foreign_amount') + ; $return['native_balance'] = bcadd($return['native_balance'], $sum); Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $sum, $return['native_balance'])); } // balance(s) in other (all) currencies. - $array = $account->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) - ->get(['transaction_currencies.code', 'transactions.amount'])->toArray(); - $others = $this->groupAndSumTransactions($array, 'code', 'amount'); + $array = $account->transactions() + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') + ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) + ->get(['transaction_currencies.code', 'transactions.amount'])->toArray() + ; + $others = $this->groupAndSumTransactions($array, 'code', 'amount'); Log::debug('All balances are (joined)', $others); // if the account has no own currency preference, drop balance in favor of native balance if ($hasCurrency && !$convertToNative) { - $return['balance'] = $others[$currency->code] ?? '0'; + $return['balance'] = $others[$currency->code] ?? '0'; $return['native_balance'] = $others[$currency->code] ?? '0'; Log::debug(sprintf('Set balance + native_balance to %s', $return['balance'])); } // 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 && 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']); + $sum = bcadd($return['balance'], $return['native_balance']); Log::debug(sprintf('%s + %s = %s', $return['balance'], $return['native_balance'], $sum)); $return['native_balance'] = $sum; unset($return['balance']); @@ -388,15 +392,15 @@ class Steam { $list = []; - $set = auth()->user()->transactions() - ->whereIn('transactions.account_id', $accounts) - ->groupBy(['transactions.account_id', 'transaction_journals.user_id']) - ->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line + $set = auth()->user()->transactions() + ->whereIn('transactions.account_id', $accounts) + ->groupBy(['transactions.account_id', 'transaction_journals.user_id']) + ->get(['transactions.account_id', \DB::raw('MAX(transaction_journals.date) AS max_date')]) // @phpstan-ignore-line ; /** @var Transaction $entry */ foreach ($set as $entry) { - $date = new Carbon($entry->max_date, config('app.timezone')); + $date = new Carbon($entry->max_date, config('app.timezone')); $date->setTimezone(config('app.timezone')); $list[(int) $entry->account_id] = $date; } @@ -471,9 +475,9 @@ class Steam public function getSafeUrl(string $unknownUrl, string $safeUrl): string { // Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl)); - $returnUrl = $safeUrl; - $unknownHost = parse_url($unknownUrl, PHP_URL_HOST); - $safeHost = parse_url($safeUrl, PHP_URL_HOST); + $returnUrl = $safeUrl; + $unknownHost = parse_url($unknownUrl, PHP_URL_HOST); + $safeHost = parse_url($safeUrl, PHP_URL_HOST); if (null !== $unknownHost && $unknownHost === $safeHost) { $returnUrl = $unknownUrl; @@ -510,7 +514,7 @@ class Steam */ public function floatalize(string $value): string { - $value = strtoupper($value); + $value = strtoupper($value); if (!str_contains($value, 'E')) { return $value; } diff --git a/app/Support/Twig/AmountFormat.php b/app/Support/Twig/AmountFormat.php index 27f36ebe6d..015378ab29 100644 --- a/app/Support/Twig/AmountFormat.php +++ b/app/Support/Twig/AmountFormat.php @@ -75,7 +75,7 @@ class AmountFormat extends AbstractExtension $this->formatAmountByAccount(), $this->formatAmountBySymbol(), $this->formatAmountByCurrency(), - $this->formatAmountByCode() + $this->formatAmountByCode(), ]; } @@ -111,6 +111,7 @@ class AmountFormat extends AbstractExtension 'formatAmountByCode', static function (string $amount, string $code, ?bool $coloured = null): string { $coloured ??= true; + /** @var TransactionCurrency $currency */ $currency = TransactionCurrency::whereCode($code)->first(); @@ -128,8 +129,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/app/Support/Twig/General.php b/app/Support/Twig/General.php index e7d396808e..09e1e3118f 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -69,9 +69,9 @@ class General extends AbstractExtension $date = session('end', today(config('app.timezone'))->endOfMonth()); $info = Steam::finalAccountBalance($account, $date); $currency = Steam::getAccountCurrency($account); - $default = Amount::getDefaultCurrency(); + $default = Amount::getDefaultCurrency(); $convertToNative = app('preferences')->get('convert_to_native', false)->data; - $useNative = $convertToNative && $default->id !== $currency->id; + $useNative = $convertToNative && $default->id !== $currency->id; $strings = []; foreach ($info as $key => $balance) { if ('balance' === $key) { @@ -79,6 +79,7 @@ class General extends AbstractExtension if (!$useNative) { $strings[] = app('amount')->formatAnything($currency, $balance, false); } + continue; } if ('native_balance' === $key) { diff --git a/composer.lock b/composer.lock index b99bd9f6fa..3533151403 100644 --- a/composer.lock +++ b/composer.lock @@ -10845,16 +10845,16 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.14.9", + "version": "v3.14.10", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef" + "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/2e805a6bd4e1aa83774316bb062703c65d0691ef", - "reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/56b9bd235e3fe62e250124804009ce5bab97cc63", + "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63", "shasum": "" }, "require": { @@ -10913,7 +10913,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-debugbar/issues", - "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.9" + "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.14.10" }, "funding": [ { @@ -10925,7 +10925,7 @@ "type": "github" } ], - "time": "2024-11-25T14:51:20+00:00" + "time": "2024-12-23T10:10:42+00:00" }, { "name": "barryvdh/laravel-ide-helper", diff --git a/package-lock.json b/package-lock.json index 5cd70d1786..b16373dd61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3621,9 +3621,9 @@ } }, "node_modules/admin-lte": { - "version": "4.0.0-beta2", - "resolved": "https://registry.npmjs.org/admin-lte/-/admin-lte-4.0.0-beta2.tgz", - "integrity": "sha512-Ofav0BKnCnz+IeeXrHQZ6JWnHouwv+fDYyfagRpjfFaMBmYCljA2Qo1+fCGkJuJn/SfNPhFpJhbUt+l2tH0LwA==", + "version": "4.0.0-beta3", + "resolved": "https://registry.npmjs.org/admin-lte/-/admin-lte-4.0.0-beta3.tgz", + "integrity": "sha512-q2VoAOu1DtZ7z41M2gQ05VMNYkFCAMxFU+j/HUMwCOlr/e3VhO+qww2SGJw4OxBw5nZQ7YV78+wK2RiB7ConzQ==", "license": "MIT" }, "node_modules/ag-charts-types": { @@ -3702,9 +3702,9 @@ } }, "node_modules/alpinejs": { - "version": "3.14.7", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.7.tgz", - "integrity": "sha512-ScnbydNBcWVnCiVupD3wWUvoMPm8244xkvDNMxVCspgmap9m4QuJ7pjc+77UtByU+1+Ejg0wzYkP4mQaOMcvng==", + "version": "3.14.8", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.8.tgz", + "integrity": "sha512-wT2fuP2DXpGk/jKaglwy7S/IJpm1FD+b7U6zUrhwErjoq5h27S4dxkJEXVvhbdwyPv9U+3OkUuNLkZT4h2Kfrg==", "license": "MIT", "dependencies": { "@vue/reactivity": "~3.1.1" @@ -5646,9 +5646,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.75", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz", - "integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", + "version": "1.5.76", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz", + "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==", "dev": true, "license": "ISC" }, @@ -6104,9 +6104,9 @@ } }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "dev": true, "license": "ISC", "dependencies": { diff --git a/routes/web.php b/routes/web.php index 33c6b1e120..147d547579 100644 --- a/routes/web.php +++ b/routes/web.php @@ -80,7 +80,7 @@ Route::group( Route::group( ['middleware' => 'binders-only', 'namespace' => 'FireflyIII\Http\Controllers\System'], static function (): void { - //Route::get('offline', static fn () => view('errors.offline')); + // Route::get('offline', static fn () => view('errors.offline')); Route::get('health', ['uses' => 'HealthcheckController@check', 'as' => 'healthcheck']); } );