🤖 Auto commit for release 'develop' on 2025-09-08

This commit is contained in:
JC5
2025-09-08 08:35:49 +02:00
parent fa0ac8a16c
commit 7aac1cdf67
13 changed files with 40 additions and 35 deletions

View File

@@ -46,7 +46,7 @@ class TransactionCurrencyFactory
$data['decimal_places'] = (int)$data['decimal_places']; $data['decimal_places'] = (int)$data['decimal_places'];
// if the code already exists (deleted) // if the code already exists (deleted)
// force delete it and then create the transaction: // force delete it and then create the transaction:
$count = TransactionCurrency::withTrashed()->whereCode($data['code'])->count(); $count = TransactionCurrency::withTrashed()->whereCode($data['code'])->count();
if (1 === $count) { if (1 === $count) {
$old = TransactionCurrency::withTrashed()->whereCode($data['code'])->first(); $old = TransactionCurrency::withTrashed()->whereCode($data['code'])->first();
$old->forceDelete(); $old->forceDelete();
@@ -104,6 +104,7 @@ class TransactionCurrencyFactory
} }
} }
Log::info(sprintf('Found currency #%d based on ID %d and code "%s".', $currency->id, $currencyId, $currencyCode)); Log::info(sprintf('Found currency #%d based on ID %d and code "%s".', $currency->id, $currencyId, $currencyCode));
return $currency; return $currency;
} }
} }

View File

@@ -1177,7 +1177,8 @@ class GroupCollector implements GroupCollectorInterface
// include budget ID + name (if any) // include budget ID + name (if any)
->withBudgetInformation() ->withBudgetInformation()
// include bill ID + name (if any) // include bill ID + name (if any)
->withBillInformation(); ->withBillInformation()
;
return $this; return $this;
} }

View File

@@ -62,7 +62,7 @@ class SubscriptionsOverdueReminder extends Notification
'bill' => $item['bill'], 'bill' => $item['bill'],
]; ];
$current['pay_dates'] = array_map( $current['pay_dates'] = array_map(
static fn(string $date): string => new Carbon($date)->isoFormat((string)trans('config.month_and_day_moment_js')), static fn (string $date): string => new Carbon($date)->isoFormat((string)trans('config.month_and_day_moment_js')),
$item['dates']['pay_dates'] $item['dates']['pay_dates']
); );
$info[] = $current; $info[] = $current;

View File

@@ -294,7 +294,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$summarizer->setConvertToPrimary($convertToPrimary); $summarizer->setConvertToPrimary($convertToPrimary);
// filter $journals by range AND currency if it is present. // filter $journals by range AND currency if it is present.
$expenses = array_filter($expenses, static fn(array $expense): bool => $expense['date']->between($start, $end) && $expense['currency_id'] === $transactionCurrency->id); $expenses = array_filter($expenses, static fn (array $expense): bool => $expense['date']->between($start, $end) && $expense['currency_id'] === $transactionCurrency->id);
return $summarizer->groupByCurrencyId($expenses, 'negative', false); return $summarizer->groupByCurrencyId($expenses, 'negative', false);
} }
@@ -306,7 +306,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$summarizer->setConvertToPrimary($convertToPrimary); $summarizer->setConvertToPrimary($convertToPrimary);
// filter $journals by range AND currency if it is present. // filter $journals by range AND currency if it is present.
$expenses = array_filter($expenses, static fn(array $expense): bool => $expense['budget_id'] === $budget->id); $expenses = array_filter($expenses, static fn (array $expense): bool => $expense['budget_id'] === $budget->id);
return $summarizer->groupByCurrencyId($expenses, 'negative', false); return $summarizer->groupByCurrencyId($expenses, 'negative', false);
} }

View File

@@ -44,6 +44,7 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Override; use Override;
use function Safe\json_encode; use function Safe\json_encode;
/** /**
@@ -69,7 +70,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
public function currencyInUseAt(TransactionCurrency $currency): ?string public function currencyInUseAt(TransactionCurrency $currency): ?string
{ {
Log::debug(sprintf('Now in currencyInUse() for #%d ("%s")', $currency->id, $currency->code)); Log::debug(sprintf('Now in currencyInUse() for #%d ("%s")', $currency->id, $currency->code));
$countJournals = $this->countJournals($currency); $countJournals = $this->countJournals($currency);
if ($countJournals > 0) { if ($countJournals > 0) {
Log::info(sprintf('Count journals is %d, return true.', $countJournals)); Log::info(sprintf('Count journals is %d, return true.', $countJournals));
@@ -84,7 +85,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is being used in accounts: // is being used in accounts:
$meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count(); $meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count();
if ($meta > 0) { if ($meta > 0) {
Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
@@ -92,7 +93,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// second search using integer check. // second search using integer check.
$meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((int)$currency->id))->count(); $meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((int)$currency->id))->count();
if ($meta > 0) { if ($meta > 0) {
Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
@@ -100,7 +101,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is being used in bills: // is being used in bills:
$bills = Bill::where('transaction_currency_id', $currency->id)->count(); $bills = Bill::where('transaction_currency_id', $currency->id)->count();
if ($bills > 0) { if ($bills > 0) {
Log::info(sprintf('Used in %d bills as currency, return true. ', $bills)); Log::info(sprintf('Used in %d bills as currency, return true. ', $bills));
@@ -118,9 +119,10 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is being used in accounts (as integer) // is being used in accounts (as integer)
$meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') $meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id')
->whereNull('accounts.deleted_at') ->whereNull('accounts.deleted_at')
->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode($currency->id))->count(); ->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode($currency->id))->count()
;
if ($meta > 0) { if ($meta > 0) {
Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
@@ -136,7 +138,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is being used in budget limits // is being used in budget limits
$budgetLimit = BudgetLimit::where('transaction_currency_id', $currency->id)->count(); $budgetLimit = BudgetLimit::where('transaction_currency_id', $currency->id)->count();
if ($budgetLimit > 0) { if ($budgetLimit > 0) {
Log::info(sprintf('Used in %d budget limits as currency, return true. ', $budgetLimit)); Log::info(sprintf('Used in %d budget limits as currency, return true. ', $budgetLimit));
@@ -144,7 +146,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is the default currency for the user or the system // is the default currency for the user or the system
$count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count(); $count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count();
if ($count > 0) { if ($count > 0) {
Log::info('Is the default currency of the user, return true.'); Log::info('Is the default currency of the user, return true.');
@@ -152,7 +154,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} }
// is the default currency for the user or the system // is the default currency for the user or the system
$count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count(); $count = $this->userGroup->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('group_default', 1)->count();
if ($count > 0) { if ($count > 0) {
Log::info('Is the default currency of the user group, return true.'); Log::info('Is the default currency of the user group, return true.');
@@ -181,8 +183,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
$local = $this->get(); $local = $this->get();
return $all->map(static function (TransactionCurrency $current) use ($local) { return $all->map(static function (TransactionCurrency $current) use ($local) {
$hasId = $local->contains(static fn(TransactionCurrency $entry) => $entry->id === $current->id); $hasId = $local->contains(static fn (TransactionCurrency $entry) => $entry->id === $current->id);
$isPrimary = $local->contains(static fn(TransactionCurrency $entry) => 1 === (int)$entry->pivot->group_default && $entry->id === $current->id); $isPrimary = $local->contains(static fn (TransactionCurrency $entry) => 1 === (int)$entry->pivot->group_default && $entry->id === $current->id);
$current->userGroupEnabled = $hasId; $current->userGroupEnabled = $hasId;
$current->userGroupNative = $isPrimary; $current->userGroupNative = $isPrimary;
@@ -286,6 +288,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} catch (FireflyException) { } catch (FireflyException) {
return null; return null;
} }
return $result; return $result;
} }
@@ -299,6 +302,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
} catch (FireflyException) { } catch (FireflyException) {
return null; return null;
} }
return $result; return $result;
} }
@@ -333,9 +337,10 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
/** @var null|CurrencyExchangeRate $rate */ /** @var null|CurrencyExchangeRate $rate */
$rate = $this->user->currencyExchangeRates() $rate = $this->user->currencyExchangeRates()
->where('from_currency_id', $fromCurrency->id) ->where('from_currency_id', $fromCurrency->id)
->where('to_currency_id', $toCurrency->id) ->where('to_currency_id', $toCurrency->id)
->where('date', $date->format('Y-m-d'))->first(); ->where('date', $date->format('Y-m-d'))->first()
;
if (null !== $rate) { if (null !== $rate) {
Log::debug(sprintf('Found cached exchange rate in database for %s to %s on %s', $fromCurrency->code, $toCurrency->code, $date->format('Y-m-d'))); Log::debug(sprintf('Found cached exchange rate in database for %s to %s on %s', $fromCurrency->code, $toCurrency->code, $date->format('Y-m-d')));

View File

@@ -28,9 +28,7 @@ use Illuminate\Contracts\Validation\ValidationRule;
class IsValidSortInstruction implements ValidationRule class IsValidSortInstruction implements ValidationRule
{ {
public function __construct(private readonly string $class) public function __construct(private readonly string $class) {}
{
}
public function validate(string $attribute, mixed $value, Closure $fail): void public function validate(string $attribute, mixed $value, Closure $fail): void
{ {

View File

@@ -221,7 +221,7 @@ class JournalUpdateService
private function hasFields(array $fields): bool private function hasFields(array $fields): bool
{ {
return array_any($fields, fn($field) => array_key_exists($field, $this->data)); return array_any($fields, fn ($field) => array_key_exists($field, $this->data));
} }
private function getOriginalSourceAccount(): Account private function getOriginalSourceAccount(): Account

View File

@@ -458,7 +458,7 @@ class AccountEnrichment implements EnrichmentInterface
case 'current_balance': case 'current_balance':
case 'pc_current_balance': case 'pc_current_balance':
$this->collection = $this->collection->sortBy(static fn(Account $account) => $account->meta['balances'][$parameter[0]] ?? '0', SORT_NUMERIC, 'desc' === $parameter[1]); $this->collection = $this->collection->sortBy(static fn (Account $account) => $account->meta['balances'][$parameter[0]] ?? '0', SORT_NUMERIC, 'desc' === $parameter[1]);
break; break;
} }

View File

@@ -181,13 +181,13 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private function stringifyIds(): void private function stringifyIds(): void
{ {
$this->expenses = array_map(fn($first) => array_map(function ($second) { $this->expenses = array_map(fn ($first) => array_map(function ($second) {
$second['currency_id'] = (string)($second['currency_id'] ?? 0); $second['currency_id'] = (string)($second['currency_id'] ?? 0);
return $second; return $second;
}, $first), $this->expenses); }, $first), $this->expenses);
$this->pcExpenses = array_map(fn($first) => array_map(function ($second) { $this->pcExpenses = array_map(fn ($first) => array_map(function ($second) {
$second['currency_id'] = (string)($second['currency_id'] ?? 0); $second['currency_id'] = (string)($second['currency_id'] ?? 0);
return $second; return $second;
@@ -196,6 +196,6 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private function filterToBudget(array $expenses, int $budget): array private function filterToBudget(array $expenses, int $budget): array
{ {
return array_filter($expenses, fn(array $item) => (int)$item['budget_id'] === $budget); return array_filter($expenses, fn (array $item) => (int)$item['budget_id'] === $budget);
} }
} }

View File

@@ -274,7 +274,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
// At this point the "next match" is exactly after the last time the bill was paid. // At this point the "next match" is exactly after the last time the bill was paid.
$result = []; $result = [];
$filtered = $set->filter(fn(TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id); $filtered = $set->filter(fn (TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
foreach ($filtered as $entry) { foreach ($filtered as $entry) {
$array = [ $array = [
'transaction_group_id' => (string)$entry->transaction_group_id, 'transaction_group_id' => (string)$entry->transaction_group_id,
@@ -344,7 +344,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
*/ */
protected function lastPaidDate(Bill $subscription, Collection $dates, Carbon $default): Carbon protected function lastPaidDate(Bill $subscription, Collection $dates, Carbon $default): Carbon
{ {
$filtered = $dates->filter(fn(TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id); $filtered = $dates->filter(fn (TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
Log::debug(sprintf('Filtered down from %d to %d entries for bill #%d.', $dates->count(), $filtered->count(), $subscription->id)); Log::debug(sprintf('Filtered down from %d to %d entries for bill #%d.', $dates->count(), $filtered->count(), $subscription->id));
if (0 === $filtered->count()) { if (0 === $filtered->count()) {
return $default; return $default;

View File

@@ -348,7 +348,7 @@ class Steam
$currency = $currencies[$account->id]; $currency = $currencies[$account->id];
// second array // second array
$accountSum = array_filter($arrayOfSums, fn($entry) => $entry['account_id'] === $account->id); $accountSum = array_filter($arrayOfSums, fn ($entry) => $entry['account_id'] === $account->id);
if (0 === count($accountSum)) { if (0 === count($accountSum)) {
$result[$account->id] = $return; $result[$account->id] = $return;

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false), 'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => 'develop/2025-09-07', 'version' => 'develop/2025-09-08',
'build_time' => 1757249809, 'build_time' => 1757313229,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 26, 'db_version' => 26,

View File

@@ -116,9 +116,9 @@
"webhook_trigger_DESTROY_BUDGET": "After budget delete", "webhook_trigger_DESTROY_BUDGET": "After budget delete",
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change", "webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
"webhook_response_TRANSACTIONS": "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2", "webhook_response_TRANSACTIONS": "\u039b\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2 \u03c3\u03c5\u03bd\u03b1\u03bb\u03bb\u03b1\u03b3\u03ae\u03c2",
"webhook_response_RELEVANT": "Relevant details", "webhook_response_RELEVANT": "\u03a3\u03c7\u03b5\u03c4\u03b9\u03ba\u03ad\u03c2 \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2",
"webhook_response_ACCOUNTS": "\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd", "webhook_response_ACCOUNTS": "\u03a0\u03bb\u03b7\u03c1\u03bf\u03c6\u03bf\u03c1\u03af\u03b5\u03c2 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd",
"webhook_response_NONE": "No details", "webhook_response_NONE": "\u0394\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03c5\u03bd \u03bb\u03b5\u03c0\u03c4\u03bf\u03bc\u03ad\u03c1\u03b5\u03b9\u03b5\u03c2",
"webhook_delivery_JSON": "JSON", "webhook_delivery_JSON": "JSON",
"actions": "\u0395\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b5\u03c2", "actions": "\u0395\u03bd\u03ad\u03c1\u03b3\u03b5\u03b9\u03b5\u03c2",
"meta_data": "\u039c\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1", "meta_data": "\u039c\u03b5\u03c4\u03b1-\u03b4\u03b5\u03b4\u03bf\u03bc\u03ad\u03bd\u03b1",