Auto commit for release 'branch-v6.2' on 2024-12-25

This commit is contained in:
github-actions
2024-12-25 07:13:41 +01:00
parent e73fe06f7e
commit e8cc321898
28 changed files with 713 additions and 626 deletions

View File

@@ -32,7 +32,6 @@ use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Report\NetWorthInterface; use FireflyIII\Helpers\Report\NetWorthInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
@@ -323,6 +322,7 @@ class BasicController extends Controller
private function getNetWorthInfo(Carbon $start, Carbon $end): array private function getNetWorthInfo(Carbon $start, Carbon $end): array
{ {
Log::debug('getNetWorthInfo'); Log::debug('getNetWorthInfo');
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$date = now(config('app.timezone')); $date = now(config('app.timezone'));

View File

@@ -212,10 +212,10 @@ class RecalculateNativeAmounts extends Command
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.user_group_id', $userGroup->id) ->where('transaction_journals.user_group_id', $userGroup->id)
->where(function(DatabaseBuilder $q1) use ($currency) { ->where(function (DatabaseBuilder $q1) use ($currency): void {
$q1->where(function(DatabaseBuilder $q2) use ($currency) { $q1->where(function (DatabaseBuilder $q2) use ($currency): void {
$q2->whereNot('transactions.transaction_currency_id', $currency->id)->whereNull('transactions.foreign_currency_id'); $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); $q3->whereNot('transactions.transaction_currency_id', $currency->id)->whereNot('transactions.foreign_currency_id', $currency->id);
}); });
}) })

View File

@@ -194,7 +194,7 @@ class IndexController extends Controller
return view('accounts.index', compact('objectType', 'inactiveCount', 'subTitleIcon', 'subTitle', 'page', 'accounts')); 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)) { if (!array_key_exists($account->id, $balances)) {
return []; return [];
@@ -217,6 +217,7 @@ class IndexController extends Controller
foreach ($endBalances as $key => $value) { foreach ($endBalances as $key => $value) {
$result[$key] = bcsub($value, $startBalances[$key] ?? '0'); $result[$key] = bcsub($value, $startBalances[$key] ?? '0');
} }
return $result; return $result;
} }
} }

View File

@@ -84,6 +84,7 @@ class AccountController extends Controller
public function expenseAccounts(): JsonResponse public function expenseAccounts(): JsonResponse
{ {
Log::debug('RevenueAccounts'); Log::debug('RevenueAccounts');
/** @var Carbon $start */ /** @var Carbon $start */
$start = clone session('start', today(config('app.timezone'))->startOfMonth()); $start = clone session('start', today(config('app.timezone'))->startOfMonth());
@@ -119,8 +120,10 @@ class AccountController extends Controller
$expenses = $endBalances[$account->id] ?? false; $expenses = $endBalances[$account->id] ?? false;
if (false === $expenses) { if (false === $expenses) {
Log::error(sprintf('Found no end balance for account #%d', $account->id)); Log::error(sprintf('Found no end balance for account #%d', $account->id));
continue; continue;
} }
/** /**
* @var string $key * @var string $key
* @var string $endBalance * @var string $endBalance
@@ -128,10 +131,12 @@ class AccountController extends Controller
foreach ($expenses as $key => $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)); Log::debug(sprintf('[a] Will skip expense array "%s"', $key));
continue; continue;
} }
if ($this->convertToNative && 'native_balance' !== $key) { if ($this->convertToNative && 'native_balance' !== $key) {
Log::debug(sprintf('[b] Will skip expense array "%s"', $key)); Log::debug(sprintf('[b] Will skip expense array "%s"', $key));
continue; continue;
} }
Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));
@@ -547,8 +552,10 @@ class AccountController extends Controller
$expenses = $endBalances[$account->id] ?? false; $expenses = $endBalances[$account->id] ?? false;
if (false === $expenses) { if (false === $expenses) {
Log::error(sprintf('Found no end balance for account #%d', $account->id)); Log::error(sprintf('Found no end balance for account #%d', $account->id));
continue; continue;
} }
/** /**
* @var string $key * @var string $key
* @var string $endBalance * @var string $endBalance
@@ -556,10 +563,12 @@ class AccountController extends Controller
foreach ($expenses as $key => $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)); Log::debug(sprintf('[a] Will skip expense array "%s"', $key));
continue; continue;
} }
if ($this->convertToNative && 'native_balance' !== $key) { if ($this->convertToNative && 'native_balance' !== $key) {
Log::debug(sprintf('[b] Will skip expense array "%s"', $key)); Log::debug(sprintf('[b] Will skip expense array "%s"', $key));
continue; continue;
} }
Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance)); Log::debug(sprintf('Will process expense array "%s" with amount %s', $key, $endBalance));

View File

@@ -387,7 +387,7 @@ class BudgetController extends Controller
if ($cache->has()) { if ($cache->has()) {
// return response()->json($cache->get()); // return response()->json($cache->get());
} }
Log::debug(sprintf('Regenerate frontpage chart from scratch.')); Log::debug('Regenerate frontpage chart from scratch.');
$chartGenerator = app(FrontpageChartGenerator::class); $chartGenerator = app(FrontpageChartGenerator::class);
$chartGenerator->setUser(auth()->user()); $chartGenerator->setUser(auth()->user());
$chartGenerator->setStart($start); $chartGenerator->setStart($start);

View File

@@ -33,7 +33,6 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Http\Controllers\GetConfigurationData; use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use FireflyIII\Support\Models\AccountBalanceCalculator; use FireflyIII\Support\Models\AccountBalanceCalculator;
use FireflyIII\User; use FireflyIII\User;
use Http\Discovery\Exception\NotFoundException;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -68,30 +67,33 @@ class DebugController extends Controller
} }
$routes = Route::getRoutes(); $routes = Route::getRoutes();
$return = []; $return = [];
/** @var \Illuminate\Routing\Route $route */ /** @var \Illuminate\Routing\Route $route */
foreach ($routes as $route) { foreach ($routes as $route) {
// skip API and other routes. // skip API and other routes.
if ( if (
str_starts_with($route->uri(), 'api') || str_starts_with($route->uri(), 'api')
str_starts_with($route->uri(), '_debugbar') || || str_starts_with($route->uri(), '_debugbar')
str_starts_with($route->uri(), '_ignition') || || str_starts_with($route->uri(), '_ignition')
str_starts_with($route->uri(), 'oauth') || || str_starts_with($route->uri(), 'oauth')
str_starts_with($route->uri(), 'sanctum') || str_starts_with($route->uri(), 'sanctum')
) { ) {
continue; continue;
} }
// skip non GET routes // skip non GET routes
if (!in_array('GET', $route->methods())) { if (!in_array('GET', $route->methods(), true)) {
continue; continue;
} }
// no name route: // no name route:
if (null === $route->getName()) { if (null === $route->getName()) {
var_dump($route); var_dump($route);
exit; exit;
} }
if (!str_contains($route->uri(), '{')) { if (!str_contains($route->uri(), '{')) {
$return[$route->getName()] = route($route->getName()); $return[$route->getName()] = route($route->getName());
continue; continue;
} }
$params = []; $params = [];
@@ -106,12 +108,13 @@ class DebugController extends Controller
echo sprintf('<h2>%s</h2>', $count); echo sprintf('<h2>%s</h2>', $count);
foreach ($return as $name => $path) { foreach ($return as $name => $path) {
echo sprintf('<a href="%1$s">%2$s</a><br>', $path, $name).PHP_EOL; echo sprintf('<a href="%1$s">%2$s</a><br>', $path, $name).PHP_EOL;
$count++; ++$count;
if (0 === $count % 10) { if (0 === $count % 10) {
echo '<hr>'; echo '<hr>';
echo sprintf('<h2>%s</h2>', $count); echo sprintf('<h2>%s</h2>', $count);
} }
} }
exit; exit;
var_dump($return); var_dump($return);
} }
@@ -407,81 +410,118 @@ class DebugController extends Controller
switch ($name) { switch ($name) {
default: default:
throw new FireflyException(sprintf('Unknown parameter "%s"', $name)); throw new FireflyException(sprintf('Unknown parameter "%s"', $name));
case 'cliToken': case 'cliToken':
case 'token': case 'token':
case 'code': case 'code':
case 'oldAddressHash': case 'oldAddressHash':
return 'fake-token'; return 'fake-token';
case 'objectType': case 'objectType':
return 'asset'; return 'asset';
case 'account': case 'account':
return '1'; return '1';
case 'start_date': case 'start_date':
return '20241201'; return '20241201';
case 'end_date': case 'end_date':
return '20241231'; return '20241231';
case 'attachment': case 'attachment':
return '1'; return '1';
case 'bill': case 'bill':
return '1'; return '1';
case 'budget': case 'budget':
return '1'; return '1';
case 'budgetLimit': case 'budgetLimit':
return '1'; return '1';
case 'category': case 'category':
return '1'; return '1';
case 'currency': case 'currency':
return '1'; return '1';
case 'fromCurrencyCode': case 'fromCurrencyCode':
return 'EUR'; return 'EUR';
case 'toCurrencyCode': case 'toCurrencyCode':
return 'USD'; return 'USD';
case 'accountList': case 'accountList':
return '1,6'; return '1,6';
case 'budgetList': case 'budgetList':
return '1,2'; return '1,2';
case 'categoryList': case 'categoryList':
return '1,2'; return '1,2';
case 'doubleList': case 'doubleList':
return '1,2'; return '1,2';
case 'tagList': case 'tagList':
return '1,2'; return '1,2';
case 'tag': case 'tag':
return '1'; return '1';
case 'piggyBank': case 'piggyBank':
return '1'; return '1';
case 'objectGroup': case 'objectGroup':
return '1'; return '1';
case 'route': case 'route':
return 'accounts'; return 'accounts';
case 'specificPage': case 'specificPage':
return 'show'; return 'show';
case 'recurrence': case 'recurrence':
return '1'; return '1';
case 'tj': case 'tj':
return '1'; return '1';
case 'reportType': case 'reportType':
return 'default'; return 'default';
case 'ruleGroup': case 'ruleGroup':
return '1'; return '1';
case 'rule': case 'rule':
return '1'; return '1';
case 'tagOrId': case 'tagOrId':
return '1'; return '1';
case 'transactionGroup': case 'transactionGroup':
return '1'; return '1';
case 'journalList': case 'journalList':
return '1,2'; return '1,2';
case 'transactionType': case 'transactionType':
return 'withdrawal'; return 'withdrawal';
case 'journalLink': case 'journalLink':
return '1'; return '1';
case 'webhook': case 'webhook':
return '1'; return '1';
case 'user': case 'user':
return '1'; return '1';
case 'linkType': case 'linkType':
return '1'; return '1';
case 'userGroup': case 'userGroup':
return '1'; return '1';

View File

@@ -85,7 +85,8 @@ class BoxController extends Controller
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end) $collector->setRange($start, $end)
->setTypes([TransactionType::DEPOSIT]); ->setTypes([TransactionType::DEPOSIT])
;
$set = $collector->getExtractedJournals(); $set = $collector->getExtractedJournals();
/** @var array $journal */ /** @var array $journal */
@@ -102,7 +103,8 @@ class BoxController extends Controller
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end) $collector->setRange($start, $end)
->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); ->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
;
$set = $collector->getExtractedJournals(); $set = $collector->getExtractedJournals();
/** @var array $journal */ /** @var array $journal */

View File

@@ -61,7 +61,8 @@ class BillRepository implements BillRepositoryInterface
$search->whereLike('name', sprintf('%%%s', $query)); $search->whereLike('name', sprintf('%%%s', $query));
} }
$search->orderBy('name', 'ASC') $search->orderBy('name', 'ASC')
->where('active', true); ->where('active', true)
;
return $search->take($limit)->get(); return $search->take($limit)->get();
} }
@@ -73,7 +74,8 @@ class BillRepository implements BillRepositoryInterface
$search->whereLike('name', sprintf('%s%%', $query)); $search->whereLike('name', sprintf('%s%%', $query));
} }
$search->orderBy('name', 'ASC') $search->orderBy('name', 'ASC')
->where('active', true); ->where('active', true)
;
return $search->take($limit)->get(); return $search->take($limit)->get();
} }
@@ -177,7 +179,8 @@ class BillRepository implements BillRepositoryInterface
return $this->user->bills() return $this->user->bills()
->orderBy('order', 'ASC') ->orderBy('order', 'ASC')
->orderBy('active', 'DESC') ->orderBy('active', 'DESC')
->orderBy('name', 'ASC')->get(); ->orderBy('name', 'ASC')->get()
;
} }
public function getBillsForAccounts(Collection $accounts): Collection public function getBillsForAccounts(Collection $accounts): Collection
@@ -218,7 +221,8 @@ class BillRepository implements BillRepositoryInterface
->orderBy('bills.active', 'DESC') ->orderBy('bills.active', 'DESC')
->orderBy('bills.name', 'ASC') ->orderBy('bills.name', 'ASC')
->groupBy($fields) ->groupBy($fields)
->get($fields); ->get($fields)
;
} }
/** /**
@@ -292,7 +296,8 @@ class BillRepository implements BillRepositoryInterface
{ {
return $this->user->bills() return $this->user->bills()
->orderBy('active', 'DESC') ->orderBy('active', 'DESC')
->orderBy('name', 'ASC')->paginate($size); ->orderBy('name', 'ASC')->paginate($size)
;
} }
/** /**
@@ -311,7 +316,8 @@ class BillRepository implements BillRepositoryInterface
'transaction_journals.date', 'transaction_journals.date',
'transaction_journals.transaction_group_id', 'transaction_journals.transaction_group_id',
] ]
); )
;
} }
/** /**
@@ -323,7 +329,8 @@ class BillRepository implements BillRepositoryInterface
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
->where('rule_actions.action_type', 'link_to_bill') ->where('rule_actions.action_type', 'link_to_bill')
->where('rule_actions.action_value', $bill->name) ->where('rule_actions.action_value', $bill->name)
->get(['rules.*']); ->get(['rules.*'])
;
} }
/** /**
@@ -337,7 +344,8 @@ class BillRepository implements BillRepositoryInterface
$rules = $this->user->rules() $rules = $this->user->rules()
->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id') ->leftJoin('rule_actions', 'rule_actions.rule_id', '=', 'rules.id')
->where('rule_actions.action_type', 'link_to_bill') ->where('rule_actions.action_type', 'link_to_bill')
->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active']); ->get(['rules.id', 'rules.title', 'rule_actions.action_value', 'rules.active'])
;
$array = []; $array = [];
/** @var Rule $rule */ /** @var Rule $rule */
@@ -365,7 +373,8 @@ class BillRepository implements BillRepositoryInterface
$journals = $bill->transactionJournals() $journals = $bill->transactionJournals()
->where('date', '>=', $date->year.'-01-01 00:00:00') ->where('date', '>=', $date->year.'-01-01 00:00:00')
->where('date', '<=', $date->year.'-12-31 23:59:59') ->where('date', '<=', $date->year.'-12-31 23:59:59')
->get(); ->get()
;
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
@@ -523,6 +532,7 @@ class BillRepository implements BillRepositoryInterface
'sum' => '0', 'sum' => '0',
]; ];
$setAmount = '0'; $setAmount = '0';
/** @var TransactionJournal $transactionJournal */ /** @var TransactionJournal $transactionJournal */
foreach ($set as $transactionJournal) { foreach ($set as $transactionJournal) {
$setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal)); $setAmount = bcadd($setAmount, Amount::getAmountFromJournalObject($transactionJournal));
@@ -567,7 +577,7 @@ class BillRepository implements BillRepositoryInterface
if ($total > 0) { if ($total > 0) {
$currency = $convertToNative && $bill->transactionCurrency->id !== $default->id ? $default : $bill->transactionCurrency; $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)); 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, 'id' => (string) $currency->id,

View File

@@ -104,7 +104,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
->where('transaction_currency_id', $currency->id) ->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d')) ->where('start_date', $start->format('Y-m-d'))
->where('end_date', $end->format('Y-m-d')) ->where('end_date', $end->format('Y-m-d'))
->first(); ->first()
;
} }
public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string
@@ -115,7 +116,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
$availableBudget = $this->user->availableBudgets() $availableBudget = $this->user->availableBudgets()
->where('transaction_currency_id', $currency->id) ->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d')) ->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()
;
if (null !== $availableBudget) { if (null !== $availableBudget) {
$amount = $availableBudget->amount; $amount = $availableBudget->amount;
} }
@@ -128,7 +130,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
$return = []; $return = [];
$availableBudgets = $this->user->availableBudgets() $availableBudgets = $this->user->availableBudgets()
->where('start_date', $start->format('Y-m-d')) ->where('start_date', $start->format('Y-m-d'))
->where('end_date', $end->format('Y-m-d'))->get(); ->where('end_date', $end->format('Y-m-d'))->get()
;
// use native amount if necessary? // use native amount if necessary?
$convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data; $convertToNative = app('preferences')->getForUser($this->user, 'convert_to_native', false)->data;
@@ -138,9 +141,10 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
foreach ($availableBudgets as $availableBudget) { foreach ($availableBudgets as $availableBudget) {
$currencyId = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? $default->id : $availableBudget->transaction_currency_id; $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'; $field = $convertToNative && $availableBudget->transaction_currency_id !== $default->id ? 'native_amount' : 'amount';
$return[$currencyId] = $return[$currencyId] ?? '0'; $return[$currencyId] ??= '0';
$return[$currencyId] = bcadd($return[$currencyId], $availableBudget->$field); $return[$currencyId] = bcadd($return[$currencyId], $availableBudget->{$field});
} }
return $return; return $return;
} }
@@ -177,7 +181,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
return $this->user->availableBudgets() return $this->user->availableBudgets()
->where('start_date', '=', $start->format('Y-m-d')) ->where('start_date', '=', $start->format('Y-m-d'))
->where('end_date', '=', $end->format('Y-m-d')) ->where('end_date', '=', $end->format('Y-m-d'))
->get(); ->get()
;
} }
public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget
@@ -186,7 +191,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
->availableBudgets() ->availableBudgets()
->where('transaction_currency_id', $currency->id) ->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d')) ->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()
;
} }
/** /**
@@ -197,7 +203,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
$availableBudget = $this->user->availableBudgets() $availableBudget = $this->user->availableBudgets()
->where('transaction_currency_id', $currency->id) ->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d')) ->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()
;
if (null === $availableBudget) { if (null === $availableBudget) {
$availableBudget = new AvailableBudget(); $availableBudget = new AvailableBudget();
$availableBudget->user()->associate($this->user); $availableBudget->user()->associate($this->user);

View File

@@ -210,8 +210,7 @@ class OperationsRepository implements OperationsRepositoryInterface
?Collection $accounts = null, ?Collection $accounts = null,
?Collection $budgets = null, ?Collection $budgets = null,
?TransactionCurrency $currency = null ?TransactionCurrency $currency = null
): array ): array {
{
Log::debug('Start of sumExpenses.'); Log::debug('Start of sumExpenses.');
// this collector excludes all transfers TO liabilities (which are also withdrawals) // 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. // because those expenses only become expenses once they move from the liability to the friend.
@@ -240,7 +239,8 @@ class OperationsRepository implements OperationsRepositoryInterface
$collector->setUser($this->user) $collector->setUser($this->user)
->setRange($start, $end) ->setRange($start, $end)
// ->excludeDestinationAccounts($selection) // ->excludeDestinationAccounts($selection)
->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); ->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
;
if (null !== $accounts) { if (null !== $accounts) {
$collector->setAccounts($accounts); $collector->setAccounts($accounts);
@@ -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(sprintf('Journal #%d adds amount %s %s', $journal['transaction_journal_id'], $currencyCode, $amount));
} }
Log::debug('End of sumExpenses.', $array); Log::debug('End of sumExpenses.', $array);
return $array; return $array;
} }
} }

View File

@@ -200,7 +200,8 @@ class OperationsRepository implements OperationsRepositoryInterface
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER])
->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts); ->setDestinationAccounts($accounts)->excludeSourceAccounts($accounts)
;
if (null !== $categories && $categories->count() > 0) { if (null !== $categories && $categories->count() > 0) {
$collector->setCategories($categories); $collector->setCategories($categories);
} }
@@ -262,7 +263,8 @@ class OperationsRepository implements OperationsRepositoryInterface
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER]) $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::TRANSFER])
->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts); ->setSourceAccounts($accounts)->excludeDestinationAccounts($accounts)
;
if (null !== $categories && $categories->count() > 0) { if (null !== $categories && $categories->count() > 0) {
$collector->setCategories($categories); $collector->setCategories($categories);
} }
@@ -393,7 +395,8 @@ class OperationsRepository implements OperationsRepositoryInterface
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end) $collector->setUser($this->user)->setRange($start, $end)
->setTypes([TransactionType::DEPOSIT]); ->setTypes([TransactionType::DEPOSIT])
;
if (null !== $accounts && $accounts->count() > 0) { if (null !== $accounts && $accounts->count() > 0) {
$collector->setAccounts($accounts); $collector->setAccounts($accounts);
@@ -429,7 +432,8 @@ class OperationsRepository implements OperationsRepositoryInterface
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end) $collector->setUser($this->user)->setRange($start, $end)
->setTypes([TransactionType::TRANSFER]); ->setTypes([TransactionType::TRANSFER])
;
if (null !== $accounts && $accounts->count() > 0) { if (null !== $accounts && $accounts->count() > 0) {
$collector->setAccounts($accounts); $collector->setAccounts($accounts);

View File

@@ -64,6 +64,7 @@ class Amount
$amount = $journal['foreign_amount']; $amount = $journal['foreign_amount'];
// Log::debug(sprintf('Overruled, amount is now %s', $amount)); // Log::debug(sprintf('Overruled, amount is now %s', $amount));
} }
return $amount; return $amount;
} }
@@ -76,20 +77,21 @@ class Amount
$convertToNative = app('preferences')->get('convert_to_native', false)->data; $convertToNative = app('preferences')->get('convert_to_native', false)->data;
$currency = app('amount')->getDefaultCurrency(); $currency = app('amount')->getDefaultCurrency();
$field = $convertToNative && $currency->id !== $journal->transaction_currency_id ? 'native_amount' : 'amount'; $field = $convertToNative && $currency->id !== $journal->transaction_currency_id ? 'native_amount' : 'amount';
/** @var null|Transaction $sourceTransaction */ /** @var null|Transaction $sourceTransaction */
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first(); $sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
if (null === $sourceTransaction) { if (null === $sourceTransaction) {
return '0'; return '0';
} }
$amount = $sourceTransaction->$field; $amount = $sourceTransaction->{$field};
if ((int) $sourceTransaction->foreign_currency_id === $currency->id) { if ((int) $sourceTransaction->foreign_currency_id === $currency->id) {
// use foreign amount instead! // use foreign amount instead!
$amount = (string) $sourceTransaction->foreign_amount; // hard coded to be foreign amount. $amount = (string) $sourceTransaction->foreign_amount; // hard coded to be foreign amount.
} }
return $amount; return $amount;
} }
/** /**
* This method will properly format the given number, in color or "black and white", * 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. * as a currency, given two things: the currency required and the current locale.

View File

@@ -48,7 +48,6 @@ class FrontpageChartGenerator
public bool $convertToNative = false; public bool $convertToNative = false;
public TransactionCurrency $default; public TransactionCurrency $default;
/** /**
* FrontpageChartGenerator constructor. * FrontpageChartGenerator constructor.
*/ */
@@ -100,10 +99,12 @@ class FrontpageChartGenerator
if (0 === $limits->count()) { if (0 === $limits->count()) {
$result = $this->noBudgetLimits($data, $budget); $result = $this->noBudgetLimits($data, $budget);
Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name)); Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name));
return $result; return $result;
} }
$result = $this->budgetLimits($data, $budget, $limits); $result = $this->budgetLimits($data, $budget, $limits);
Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name)); Log::debug(sprintf('Now DONE processing budget #%d ("%s")', $budget->id, $budget->name));
return $result; return $result;
} }
@@ -132,6 +133,7 @@ class FrontpageChartGenerator
private function budgetLimits(array $data, Budget $budget, Collection $limits): array private function budgetLimits(array $data, Budget $budget, Collection $limits): array
{ {
Log::debug('Start processing budget limits.'); Log::debug('Start processing budget limits.');
/** @var BudgetLimit $limit */ /** @var BudgetLimit $limit */
foreach ($limits as $limit) { foreach ($limits as $limit) {
$data = $this->processLimit($data, $budget, $limit); $data = $this->processLimit($data, $budget, $limit);
@@ -158,6 +160,7 @@ class FrontpageChartGenerator
$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))); Log::debug(sprintf('Spent array has %d entries.', count($spent)));
/** @var array $entry */ /** @var array $entry */
foreach ($spent as $entry) { foreach ($spent as $entry) {
// only spent the entry where the entry's currency matches the budget limit's currency // only spent the entry where the entry's currency matches the budget limit's currency

View File

@@ -30,7 +30,6 @@ use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\User;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -187,7 +186,8 @@ class ExchangeRateConverter
->where('to_currency_id', $to) ->where('to_currency_id', $to)
->where('date', '<=', $date) ->where('date', '<=', $date)
->orderBy('date', 'DESC') ->orderBy('date', 'DESC')
->first(); ->first()
;
++$this->queryCount; ++$this->queryCount;
$rate = (string) $result?->rate; $rate = (string) $result?->rate;
@@ -292,7 +292,8 @@ class ExchangeRateConverter
->where('to_currency_id', $to->id) ->where('to_currency_id', $to->id)
->where('date', '<=', $end->format('Y-m-d')) ->where('date', '<=', $end->format('Y-m-d'))
->where('date', '>=', $start->format('Y-m-d')) ->where('date', '>=', $start->format('Y-m-d'))
->orderBy('date', 'DESC')->get(); ->orderBy('date', 'DESC')->get()
;
++$this->queryCount; ++$this->queryCount;
if (0 === $set->count()) { if (0 === $set->count()) {
Log::debug('No prepared rates found in this period, use the fallback'); Log::debug('No prepared rates found in this period, use the fallback');

View File

@@ -39,6 +39,7 @@ trait BasicDataSupport
protected function isInArray(array $array, int $entryId) protected function isInArray(array $array, int $entryId)
{ {
$key = $this->convertToNative ? 'native_balance' : 'balance'; $key = $this->convertToNative ? 'native_balance' : 'balance';
return $array[$entryId][$key] ?? '0'; return $array[$entryId][$key] ?? '0';
} }

View File

@@ -118,7 +118,8 @@ class Steam
\DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), \DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'),
\DB::raw('SUM(transactions.native_amount) AS modified_native'), \DB::raw('SUM(transactions.native_amount) AS modified_native'),
] ]
); )
;
$currentBalance = $startBalance; $currentBalance = $startBalance;
@@ -272,7 +273,6 @@ class Steam
* Wil je niks weten van native currencies, pak je: * Wil je niks weten van native currencies, pak je:
* *
* Eerst een som van alle transacties gegroepeerd op currency. Einde. * Eerst een som van alle transacties gegroepeerd op currency. Einde.
*
*/ */
public function finalAccountBalance(Account $account, Carbon $date): array public function finalAccountBalance(Account $account, Carbon $date): array
{ {
@@ -291,7 +291,8 @@ class Steam
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->where('transactions.transaction_currency_id', $native->id) ->where('transactions.transaction_currency_id', $native->id)
->sum('transactions.amount'); ->sum('transactions.amount')
;
// plus virtual balance, if the account has a virtual_balance in the native currency // 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']); $return['balance'] = bcadd('' === (string) $account->virtual_balance ? '0' : $account->virtual_balance, $return['balance']);
@@ -303,7 +304,8 @@ class Steam
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->whereNot('transactions.transaction_currency_id', $native->id) ->whereNot('transactions.transaction_currency_id', $native->id)
->sum('transactions.native_amount'); ->sum('transactions.native_amount')
;
// plus native virtual balance. // plus native virtual balance.
$return['native_balance'] = bcadd('' === (string) $account->native_virtual_balance ? '0' : $account->native_virtual_balance, $return['native_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'])); Log::debug(sprintf('native_balance is (all transactions to %s) %s (with virtual balance)', $native->code, $return['native_balance']));
@@ -314,7 +316,8 @@ class Steam
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->whereNot('transactions.transaction_currency_id', $native->id) ->whereNot('transactions.transaction_currency_id', $native->id)
->where('transactions.foreign_currency_id', $native->id) ->where('transactions.foreign_currency_id', $native->id)
->sum('transactions.foreign_amount'); ->sum('transactions.foreign_amount')
;
$return['native_balance'] = bcadd($return['native_balance'], $sum); $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'])); Log::debug(sprintf('Foreign amount transactions add (%s only) %s, total native_balance is now %s', $native->code, $sum, $return['native_balance']));
@@ -325,7 +328,8 @@ class Steam
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id') ->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transactions.transaction_currency_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')) ->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s'))
->get(['transaction_currencies.code', 'transactions.amount'])->toArray(); ->get(['transaction_currencies.code', 'transactions.amount'])->toArray()
;
$others = $this->groupAndSumTransactions($array, 'code', 'amount'); $others = $this->groupAndSumTransactions($array, 'code', 'amount');
Log::debug('All balances are (joined)', $others); Log::debug('All balances are (joined)', $others);
// if the account has no own currency preference, drop balance in favor of native balance // if the account has no own currency preference, drop balance in favor of native balance

View File

@@ -75,7 +75,7 @@ class AmountFormat extends AbstractExtension
$this->formatAmountByAccount(), $this->formatAmountByAccount(),
$this->formatAmountBySymbol(), $this->formatAmountBySymbol(),
$this->formatAmountByCurrency(), $this->formatAmountByCurrency(),
$this->formatAmountByCode() $this->formatAmountByCode(),
]; ];
} }
@@ -111,6 +111,7 @@ class AmountFormat extends AbstractExtension
'formatAmountByCode', 'formatAmountByCode',
static function (string $amount, string $code, ?bool $coloured = null): string { static function (string $amount, string $code, ?bool $coloured = null): string {
$coloured ??= true; $coloured ??= true;
/** @var TransactionCurrency $currency */ /** @var TransactionCurrency $currency */
$currency = TransactionCurrency::whereCode($code)->first(); $currency = TransactionCurrency::whereCode($code)->first();

View File

@@ -79,6 +79,7 @@ class General extends AbstractExtension
if (!$useNative) { if (!$useNative) {
$strings[] = app('amount')->formatAnything($currency, $balance, false); $strings[] = app('amount')->formatAnything($currency, $balance, false);
} }
continue; continue;
} }
if ('native_balance' === $key) { if ('native_balance' === $key) {

12
composer.lock generated
View File

@@ -10845,16 +10845,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "barryvdh/laravel-debugbar", "name": "barryvdh/laravel-debugbar",
"version": "v3.14.9", "version": "v3.14.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git", "url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef" "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/2e805a6bd4e1aa83774316bb062703c65d0691ef", "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/56b9bd235e3fe62e250124804009ce5bab97cc63",
"reference": "2e805a6bd4e1aa83774316bb062703c65d0691ef", "reference": "56b9bd235e3fe62e250124804009ce5bab97cc63",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10913,7 +10913,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues", "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": [ "funding": [
{ {
@@ -10925,7 +10925,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-11-25T14:51:20+00:00" "time": "2024-12-23T10:10:42+00:00"
}, },
{ {
"name": "barryvdh/laravel-ide-helper", "name": "barryvdh/laravel-ide-helper",

24
package-lock.json generated
View File

@@ -3621,9 +3621,9 @@
} }
}, },
"node_modules/admin-lte": { "node_modules/admin-lte": {
"version": "4.0.0-beta2", "version": "4.0.0-beta3",
"resolved": "https://registry.npmjs.org/admin-lte/-/admin-lte-4.0.0-beta2.tgz", "resolved": "https://registry.npmjs.org/admin-lte/-/admin-lte-4.0.0-beta3.tgz",
"integrity": "sha512-Ofav0BKnCnz+IeeXrHQZ6JWnHouwv+fDYyfagRpjfFaMBmYCljA2Qo1+fCGkJuJn/SfNPhFpJhbUt+l2tH0LwA==", "integrity": "sha512-q2VoAOu1DtZ7z41M2gQ05VMNYkFCAMxFU+j/HUMwCOlr/e3VhO+qww2SGJw4OxBw5nZQ7YV78+wK2RiB7ConzQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/ag-charts-types": { "node_modules/ag-charts-types": {
@@ -3702,9 +3702,9 @@
} }
}, },
"node_modules/alpinejs": { "node_modules/alpinejs": {
"version": "3.14.7", "version": "3.14.8",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.7.tgz", "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.8.tgz",
"integrity": "sha512-ScnbydNBcWVnCiVupD3wWUvoMPm8244xkvDNMxVCspgmap9m4QuJ7pjc+77UtByU+1+Ejg0wzYkP4mQaOMcvng==", "integrity": "sha512-wT2fuP2DXpGk/jKaglwy7S/IJpm1FD+b7U6zUrhwErjoq5h27S4dxkJEXVvhbdwyPv9U+3OkUuNLkZT4h2Kfrg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@vue/reactivity": "~3.1.1" "@vue/reactivity": "~3.1.1"
@@ -5646,9 +5646,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.5.75", "version": "1.5.76",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz",
"integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", "integrity": "sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@@ -6104,9 +6104,9 @@
} }
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.17.1", "version": "1.18.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {