Compare commits

..

23 Commits

Author SHA1 Message Date
github-actions[bot]
4799c3c97f Merge pull request #12173 from firefly-iii/release-1776876664
🤖 Automatically merge the PR into the develop branch.
2026-04-22 18:51:12 +02:00
JC5
0a4d401f57 🤖 Auto commit for release 'develop' on 2026-04-22 2026-04-22 18:51:05 +02:00
James Cole
f890f55864 Fix if-statement. 2026-04-22 18:45:45 +02:00
James Cole
a2189a8577 Fix thingie. 2026-04-22 18:40:21 +02:00
James Cole
e81af7e051 Fix #12169 2026-04-22 18:34:16 +02:00
James Cole
32250ddc1a Fix https://github.com/firefly-iii/firefly-iii/issues/12169 2026-04-22 07:54:53 +02:00
github-actions[bot]
a9723a85d1 Merge pull request #12163 from firefly-iii/release-1776658280
🤖 Automatically merge the PR into the develop branch.
2026-04-20 06:11:26 +02:00
JC5
28fd3600b2 🤖 Auto commit for release 'develop' on 2026-04-20 2026-04-20 06:11:21 +02:00
github-actions[bot]
4df332e0d5 Merge pull request #12156 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2026-04-19 11:15:56 +02:00
github-actions[bot]
f72e168a0d Merge pull request #12155 from firefly-iii/release-1776590142
🤖 Automatically merge the PR into the develop branch.
2026-04-19 11:15:51 +02:00
JC5
a567280d1b 🤖 Auto commit for release 'v6.6.1' on 2026-04-19 2026-04-19 11:15:43 +02:00
James Cole
420f436fb6 Update changelog. 2026-04-19 11:09:52 +02:00
James Cole
10a6d96134 Fix https://github.com/firefly-iii/firefly-iii/issues/12154 2026-04-19 11:07:10 +02:00
github-actions[bot]
9ee2d4d487 Merge pull request #12153 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2026-04-19 09:59:51 +02:00
github-actions[bot]
66b6e057f2 Merge pull request #12152 from firefly-iii/release-1776585580
🤖 Automatically merge the PR into the develop branch.
2026-04-19 09:59:46 +02:00
JC5
fade8cc41e 🤖 Auto commit for release 'v6.6.0' on 2026-04-19 2026-04-19 09:59:40 +02:00
James Cole
7690042ab7 Add missing fixed issue. 2026-04-19 09:54:22 +02:00
github-actions[bot]
ef6ffb6f2d Merge pull request #12150 from firefly-iii/release-1776534459
🤖 Automatically merge the PR into the develop branch.
2026-04-18 19:47:47 +02:00
JC5
a158e4596c 🤖 Auto commit for release 'develop' on 2026-04-18 2026-04-18 19:47:39 +02:00
James Cole
e6f616880a Fix call to header. 2026-04-18 19:42:04 +02:00
github-actions[bot]
c57233a5f7 Merge pull request #12149 from firefly-iii/release-1776514174
🤖 Automatically merge the PR into the develop branch.
2026-04-18 14:09:41 +02:00
JC5
c1816e2136 🤖 Auto commit for release 'develop' on 2026-04-18 2026-04-18 14:09:34 +02:00
James Cole
fdcf73b775 Fix broken oauth controller 2026-04-18 14:04:12 +02:00
36 changed files with 319 additions and 295 deletions

View File

@@ -158,10 +158,7 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
}
}

View File

@@ -155,10 +155,7 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
}
}

View File

@@ -49,7 +49,7 @@ class StoreRequest extends FormRequest
*/
public function getAll(): array
{
$fields = ['order' => ['order', 'convertInteger']];
$fields = ['order' => ['order', 'convertInteger']];
$data = $this->getAllData($fields);
$data['name'] = $this->convertString('name');
$data['accounts'] = $this->parseAccounts($this->get('accounts'));

View File

@@ -70,7 +70,7 @@ class UpdateRequest extends FormRequest
];
$reps = $this->getRepetitionData();
$transactions = $this->getTransactionData();
$return = ['recurrence' => $this->getAllData($fields)];
$return = ['recurrence' => $this->getAllData($fields)];
if (null !== $reps) {
$return['repetitions'] = $reps;
}

View File

@@ -57,12 +57,13 @@ class Cron extends Command
public function handle(): int
{
$doAll = !$this->option('download-cer')
&& !$this->option('create-recurring')
&& !$this->option('create-auto-budgets')
&& !$this->option('send-subscription-warnings')
&& !$this->option('check-version')
&& !$this->option('send-webhook-messages');
$doAll
= !$this->option('download-cer')
&& !$this->option('create-recurring')
&& !$this->option('create-auto-budgets')
&& !$this->option('send-subscription-warnings')
&& !$this->option('check-version')
&& !$this->option('send-webhook-messages');
$date = null;
try {

View File

@@ -26,7 +26,9 @@ namespace FireflyIII\Console\Commands\Upgrade;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class RepairsPostgresSequences extends Command
{
@@ -72,8 +74,6 @@ class RepairsPostgresSequences extends Command
'locations',
'migrations',
'notes',
'oauth_clients',
'oauth_personal_access_clients',
'object_groups',
'permissions',
'piggy_bank_events',
@@ -106,11 +106,23 @@ class RepairsPostgresSequences extends Command
foreach ($tablesToCheck as $tableToCheck) {
$this->friendlyLine(sprintf('Checking the next id sequence for table "%s".', $tableToCheck));
$highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first();
$nextId = DB::table($tableToCheck)
->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))
->first()
;
try {
$highestId = DB::table($tableToCheck)->select(DB::raw('MAX(id)'))->first();
} catch (QueryException $e) {
Log::warning(sprintf('Could not select max, but will ignore this: %s', $e->getMessage()));
continue;
}
try {
$nextId = DB::table($tableToCheck)
->select(DB::raw(sprintf('nextval(\'%s_id_seq\')', $tableToCheck)))
->first()
;
} catch (QueryException $e) {
Log::warning(sprintf('Could not get nextval, but will ignore this: %s', $e->getMessage()));
$nextId = null;
}
if (null === $nextId) {
$this->friendlyInfo(sprintf('nextval is NULL for table "%s", go to next table.', $tableToCheck));

View File

@@ -48,10 +48,12 @@ class TransactionGroupEventObjects
public function appendFromTransactionGroup(TransactionGroup $transactionGroup): void
{
Log::debug(sprintf('Appended transaction group #%d', $transactionGroup->id));
$this->transactionGroups->push($transactionGroup);
/** @var TransactionJournal $journal */
foreach ($transactionGroup->transactionJournals as $journal) {
Log::debug(sprintf('Appended transaction journal #%d', $journal->id));
$this->transactionJournals->push($journal);
$this->budgets = $this->budgets->merge($journal->budgets);
$this->categories = $this->categories->merge($journal->categories);
@@ -59,6 +61,7 @@ class TransactionGroupEventObjects
/** @var Transaction $transaction */
foreach ($journal->transactions as $transaction) {
Log::debug(sprintf('Appended account #%d', $transaction->account->id));
$this->accounts->push($transaction->account);
}
}
@@ -69,4 +72,25 @@ class TransactionGroupEventObjects
$this->tags = $this->tags->unique('id');
$this->accounts = $this->accounts->unique('id');
}
public function collectFromCollection(Collection $collection): void
{
Log::debug('Will now collect info from collection.');
/** @var array|TransactionGroup $object */
foreach ($collection as $object) {
if ($object instanceof TransactionGroup) {
Log::debug(sprintf('Added group #%d', $object->id));
$this->appendFromTransactionGroup($object);
}
if (is_array($object) && array_key_exists('id', $object)) {
// FIXME technically speaking not sure of this is the user's transaction group.
$group = TransactionGroup::find((int) $object['id']);
if (null !== $group) {
Log::debug(sprintf('Added group #%d', $group->id));
$this->appendFromTransactionGroup($group);
}
}
}
}
}

View File

@@ -192,10 +192,12 @@ class TransactionFactory
return;
}
// validate info:
$validator = Validator::make(['iban' => $this->accountInformation['iban']], ['iban' => [
'required',
new UniqueIban($this->account, $this->account->accountType->type),
]]);
$validator = Validator::make(['iban' => $this->accountInformation['iban']], [
'iban' => [
'required',
new UniqueIban($this->account, $this->account->accountType->type),
],
]);
if ($validator->fails()) {
Log::debug('Invalid or non-unique IBAN, will not update.');

View File

@@ -56,7 +56,7 @@ class ReportHelper implements ReportHelperInterface
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$bills = $repository->getBillsForAccounts($accounts);
$report = ['bills' => []];
$report = ['bills' => []];
/** @var Bill $bill */
foreach ($bills as $bill) {

View File

@@ -78,12 +78,14 @@ final class CreateController extends Controller
$roles = $this->getRoles();
$liabilityTypes = $this->getLiabilityTypes();
$hasOldInput = null !== $request->old('_token');
$locations = ['location' => [
'latitude' => $hasOldInput ? old('location_latitude') : config('firefly.default_location.latitude'),
'longitude' => $hasOldInput ? old('location_longitude') : config('firefly.default_location.longitude'),
'zoom_level' => $hasOldInput ? old('location_zoom_level') : config('firefly.default_location.zoom_level'),
'has_location' => $hasOldInput && 'true' === old('location_has_location'),
]];
$locations = [
'location' => [
'latitude' => $hasOldInput ? old('location_latitude') : config('firefly.default_location.latitude'),
'longitude' => $hasOldInput ? old('location_longitude') : config('firefly.default_location.longitude'),
'zoom_level' => $hasOldInput ? old('location_zoom_level') : config('firefly.default_location.zoom_level'),
'has_location' => $hasOldInput && 'true' === old('location_has_location'),
],
];
$liabilityDirections = ['debit' => trans('firefly.liability_direction_debit'), 'credit' => trans('firefly.liability_direction_credit')];
// interest calculation periods:

View File

@@ -96,12 +96,14 @@ final class EditController extends Controller
$zoomLevel = $location instanceof Location ? $location->zoom_level : config('firefly.default_location.zoom_level');
$canEditCurrency = 0 === $account->piggyBanks()->count();
$hasLocation = $location instanceof Location;
$locations = ['location' => [
'latitude' => old('location_latitude') ?? $latitude,
'longitude' => old('location_longitude') ?? $longitude,
'zoom_level' => old('location_zoom_level') ?? $zoomLevel,
'has_location' => $hasLocation || 'true' === old('location_has_location'),
]];
$locations = [
'location' => [
'latitude' => old('location_latitude') ?? $latitude,
'longitude' => old('location_longitude') ?? $longitude,
'zoom_level' => old('location_zoom_level') ?? $zoomLevel,
'has_location' => $hasLocation || 'true' === old('location_has_location'),
],
];
$liabilityDirections = ['debit' => trans('firefly.liability_direction_debit'), 'credit' => trans('firefly.liability_direction_credit')];

View File

@@ -255,10 +255,7 @@ final class IndexController extends Controller
if (count($bill['paid_dates']) < count($bill['pay_dates'])) {
$count = count($bill['pay_dates']) - count($bill['paid_dates']);
if ($count > 0) {
$avg = bcdiv(
bcadd((string) $bill['amount_min'], (string) $bill['amount_max']),
'2'
);
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
$avg = bcmul($avg, (string) $count);
$sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg);
Log::debug(

View File

@@ -198,13 +198,7 @@ final class BudgetLimitController extends Controller
if ($request->expectsJson()) {
$array = $limit->toArray();
// add some extra metadata:
$spentArr = $this->opsRepository->sumExpenses(
$limit->start_date,
$limit->end_date,
null,
new Collection()->push($budget),
$currency
);
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
$array['left_formatted'] = Amount::formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount']));
$array['amount_formatted'] = Amount::formatAnything($limit->transactionCurrency, $limit['amount']);

View File

@@ -245,7 +245,13 @@ final class IndexController extends Controller
$inPast = $limitPeriod->startsBefore(now()) && $limitPeriod->endsBefore(now());
$currency = $limit->transactionCurrency ?? $primaryCurrency;
$amount = Steam::bcround($limit->amount, $currency->decimal_places);
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
$spent = $this->opsRepository->sumExpenses(
$limit->start_date,
$limit->end_date,
null,
new Collection()->push($budget),
$currency
);
$spentAmount = $spent[$currency->id]['sum'] ?? '0';
$array['budgeted'][] = [
'id' => $limit->id,
@@ -283,10 +289,7 @@ final class IndexController extends Controller
if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['spent_outside'] = bcmul(
bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']),
'-1'
);
$array['spent'][$currency->id]['spent_outside'] = bcmul(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']), '-1');
$array['spent'][$currency->id]['currency_id'] = $currency->id;
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;

View File

@@ -539,13 +539,7 @@ final class BudgetController extends Controller
}
// get spent amount in this period for this currency.
$sum = $this->opsRepository->sumExpenses(
$currentStart,
$currentEnd,
$accounts,
new Collection()->push($budget),
$currency
);
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
$amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
$chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places);

View File

@@ -59,7 +59,7 @@ final class JavascriptController extends Controller
AccountTypeEnum::MORTGAGE->value,
AccountTypeEnum::CREDITCARD->value,
]);
$data = ['accounts' => []];
$data = ['accounts' => []];
/** @var Account $account */
foreach ($accounts as $account) {
@@ -79,7 +79,7 @@ final class JavascriptController extends Controller
public function currencies(CurrencyRepositoryInterface $repository): Response
{
$currencies = $repository->get();
$data = ['currencies' => []];
$data = ['currencies' => []];
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {

View File

@@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Profile;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
@@ -59,8 +58,6 @@ final class OAuthController extends Controller
$authGuard = config('firefly.authentication_guard');
$this->internalAuth = 'web' === $authGuard;
Log::debug(sprintf('ProfileController::__construct(). Authentication guard is "%s"', $authGuard));
$this->middleware(IsDemoUser::class)->except(['index']);
}
public function destroyClient(Request $request, string $clientId): Response
@@ -118,6 +115,7 @@ final class OAuthController extends Controller
public function listClients(): JsonResponse
{
Log::debug('Now in listClients()');
// Retrieving all the OAuth app clients that belong to the user...
$clients = auth()->user()->oauthApps()->where('revoked', false)->get();
$array = [];

View File

@@ -82,12 +82,14 @@ final class TagController extends Controller
// location info:
$hasOldInput = null !== $request->old('_token');
$locations = ['location' => [
'latitude' => $hasOldInput ? old('location_latitude') : config('firefly.default_location.latitude'),
'longitude' => $hasOldInput ? old('location_longitude') : config('firefly.default_location.longitude'),
'zoom_level' => $hasOldInput ? old('location_zoom_level') : config('firefly.default_location.zoom_level'),
'has_location' => $hasOldInput && 'true' === old('location_has_location'),
]];
$locations = [
'location' => [
'latitude' => $hasOldInput ? old('location_latitude') : config('firefly.default_location.latitude'),
'longitude' => $hasOldInput ? old('location_longitude') : config('firefly.default_location.longitude'),
'zoom_level' => $hasOldInput ? old('location_zoom_level') : config('firefly.default_location.zoom_level'),
'has_location' => $hasOldInput && 'true' === old('location_has_location'),
],
];
// put previous url in session if not redirect from store (not "create another").
if (true !== session('tags.create.fromStore')) {
@@ -142,12 +144,14 @@ final class TagController extends Controller
$longitude = $location instanceof Location ? $location->longitude : config('firefly.default_location.longitude');
$zoomLevel = $location instanceof Location ? $location->zoom_level : config('firefly.default_location.zoom_level');
$hasLocation = $location instanceof Location;
$locations = ['location' => [
'latitude' => old('location_latitude') ?? $latitude,
'longitude' => old('location_longitude') ?? $longitude,
'zoom_level' => old('location_zoom_level') ?? $zoomLevel,
'has_location' => $hasLocation || 'true' === old('location_has_location'),
]];
$locations = [
'location' => [
'latitude' => old('location_latitude') ?? $latitude,
'longitude' => old('location_longitude') ?? $longitude,
'zoom_level' => old('location_zoom_level') ?? $zoomLevel,
'has_location' => $hasLocation || 'true' === old('location_has_location'),
],
];
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('tags.edit.fromUpdate')) {

View File

@@ -82,7 +82,7 @@ final class DeleteController extends Controller
if ($this->repository->currencyInUse($currency)) {
$location = $this->repository->currencyInUseAt($currency);
$message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
$message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
$request->session()->flash('error', $message);
Log::channel('audit')->warning(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code));

View File

@@ -129,7 +129,7 @@ class SecureHeaders
$response->header('Content-Security-Policy', implode('; ', $csp));
}
if (!method_exists($response, 'header')) {
$response->header('Content-Security-Policy', implode('; ', $csp));
$response->headers->set('Content-Security-Policy', implode('; ', $csp));
}
}
if (method_exists($response, 'header')) {

View File

@@ -122,13 +122,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
@@ -218,13 +212,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));

View File

@@ -49,7 +49,7 @@ class PiggyBankForm
$piggyBanks = $repository->getPiggyBanksWithAmount();
$title = (string) trans('firefly.default_group_title_name');
$array = [];
$subList = [0 => ['group' => ['title' => $title], 'piggies' => [(string) trans('firefly.none_in_select_list')]]];
$subList = [0 => ['group' => ['title' => $title], 'piggies' => [(string) trans('firefly.none_in_select_list')]]];
/** @var PiggyBank $piggy */
foreach ($piggyBanks as $piggy) {

View File

@@ -222,14 +222,7 @@ trait AugumentData
$currentEnd->addMonth();
}
// primary currency amount.
$expenses = $opsRepository->sumExpenses(
$currentStart,
$currentEnd,
null,
$budgetCollection,
$entry->transactionCurrency,
$this->convertToPrimary
);
$expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $entry->transactionCurrency, $this->convertToPrimary);
$spent = $expenses[$currency->id]['sum'] ?? '0';
$entry->pc_spent = $spent;

View File

@@ -117,7 +117,7 @@ trait CreateStuff
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$savingsAccount = [
'name' => (string) trans('firefly.new_savings_account', ['bank_name' => $request->get('bank_name')], $language),
'name' => (string) trans('firefly.new_savings_account', ['bank_name' => $request->get('bank_name')], $language),
'iban' => null,
'account_type_name' => 'asset',
'account_type_id' => null,

View File

@@ -354,10 +354,7 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var RecurrenceRepetition $repetition */
foreach ($set as $repetition) {
$recurrence = $this->collection
->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)
->first()
;
$recurrence = $this->collection->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)->first();
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
$recurrenceId = (int) $repetition->recurrence_id;
$repId = (int) $repetition->id;

View File

@@ -470,10 +470,9 @@ class SubscriptionEnrichment implements EnrichmentInterface
} catch (InvalidFormatException) {
$temp2 = today(config('app.timezone'));
}
$nemDiff = trans('firefly.bill_expected_date', ['date' => $temp2->diffForHumans(
today(config('app.timezone')),
CarbonInterface::DIFF_RELATIVE_TO_NOW
)]);
$nemDiff = trans('firefly.bill_expected_date', [
'date' => $temp2->diffForHumans(today(config('app.timezone')), CarbonInterface::DIFF_RELATIVE_TO_NOW),
]);
}
unset($temp2);

View File

@@ -317,14 +317,14 @@ class General extends AbstractExtension
return new TwigFilter(
'mimeIcon',
static fn (string $string): string => match ($string) {
'application/pdf' => 'fa-file-pdf-o',
'application/pdf' => 'fa-file-pdf-o',
'image/webp',
'image/png',
'image/jpeg',
'image/svg+xml',
'image/heic',
'image/heic-sequence',
'application/vnd.oasis.opendocument.image' => 'fa-file-image-o',
'application/vnd.oasis.opendocument.image' => 'fa-file-image-o',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
@@ -337,7 +337,7 @@ class General extends AbstractExtension
'application/vnd.oasis.opendocument.text',
'application/vnd.oasis.opendocument.text-template',
'application/vnd.oasis.opendocument.text-web',
'application/vnd.oasis.opendocument.text-master' => 'fa-file-word-o',
'application/vnd.oasis.opendocument.text-master' => 'fa-file-word-o',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
@@ -345,7 +345,7 @@ class General extends AbstractExtension
'application/vnd.sun.xml.calc.template',
'application/vnd.stardivision.calc',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.oasis.opendocument.spreadsheet-template' => 'fa-file-excel-o',
'application/vnd.oasis.opendocument.spreadsheet-template' => 'fa-file-excel-o',
'application/vnd.ms-powerpoint',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.openxmlformats-officedocument.presentationml.template',
@@ -354,18 +354,18 @@ class General extends AbstractExtension
'application/vnd.sun.xml.impress.template',
'application/vnd.stardivision.impress',
'application/vnd.oasis.opendocument.presentation',
'application/vnd.oasis.opendocument.presentation-template' => 'fa-file-powerpoint-o',
'application/vnd.oasis.opendocument.presentation-template' => 'fa-file-powerpoint-o',
'application/vnd.sun.xml.draw',
'application/vnd.sun.xml.draw.template',
'application/vnd.stardivision.draw',
'application/vnd.oasis.opendocument.chart' => 'fa-paint-brush',
'application/vnd.oasis.opendocument.chart' => 'fa-paint-brush',
'application/vnd.oasis.opendocument.graphics',
'application/vnd.oasis.opendocument.graphics-template',
'application/vnd.sun.xml.math',
'application/vnd.stardivision.math',
'application/vnd.oasis.opendocument.formula',
'application/vnd.oasis.opendocument.database' => 'fa-calculator',
default => 'fa-file-o'
'application/vnd.oasis.opendocument.database' => 'fa-calculator',
default => 'fa-file-o'
},
['is_safe' => ['html']]
);

View File

@@ -25,6 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Engine;
use Carbon\Carbon;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Note;
use FireflyIII\Models\Rule;
@@ -399,9 +402,17 @@ class SearchRuleEngine implements RuleEngineInterface
private function fireNonStrictRule(Rule $rule): bool
{
Log::debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id));
$collection = $this->findNonStrictRule($rule);
$flags = new TransactionGroupEventFlags();
$flags->applyRules = false;
$flags->fireWebhooks = false;
$objects = new TransactionGroupEventObjects();
$collection = $this->findNonStrictRule($rule);
$objects->collectFromCollection($collection);
$this->processResults($rule, $collection);
// collect from collection, again!
$objects->collectFromCollection($collection);
event(new UpdatedSingleTransactionGroup($flags, $objects));
Log::debug(sprintf('SearchRuleEngine:: Done processing non-strict rule #%d', $rule->id));
return $collection->count() > 0;
@@ -438,11 +449,23 @@ class SearchRuleEngine implements RuleEngineInterface
private function fireStrictRule(Rule $rule): bool
{
Log::debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id));
$collection = $this->findStrictRule($rule);
$flags = new TransactionGroupEventFlags();
$flags->applyRules = false;
$flags->fireWebhooks = false;
$objects = new TransactionGroupEventObjects();
$collection = $this->findStrictRule($rule);
$objects->collectFromCollection($collection);
$this->processResults($rule, $collection);
$result = $collection->count() > 0;
// collect from collection, again!
$objects->collectFromCollection($collection);
// fire event for changed groups.
event(new UpdatedSingleTransactionGroup($flags, $objects));
$result = $collection->count() > 0;
if ($result) {
Log::debug(sprintf('SearchRuleEngine:: Done. Rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));

View File

@@ -3,12 +3,40 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## v6.6.1 - 2026-04-19
<!-- summary: This releases upgrades many dependencies and will invalidate all of your OAuth-tokens and clients. -->
> [!WARNING]
> This releases will invalidate ALL of your OAuth-tokens and clients. Integrations with Home Assistant, AI-agents or the Firefly III Data Importer must be reconfigured with newly generated tokens. Old tokens and clients will no longer work. Sorry about that.
### Changed
- Updated many dependencies, amongst which are some backwards incompatible ones. Sorry about your OAuth-tokens.
### Fixed
- [Issue 12029](https://github.com/firefly-iii/firefly-iii/issues/12029) (PrimaryAmountRecalculationService - Attempt to read property "data" on null.) reported by @MihataBG
- [Issue 12030](https://github.com/firefly-iii/firefly-iii/issues/12030) (Rule engine fires twice in some cases) reported by @Robubble
- [Issue 12034](https://github.com/firefly-iii/firefly-iii/issues/12034) (The new Piggy Banks accounts are not being displayed properly grouped in the record creation form) reported by @jgmm81
- [Issue 12035](https://github.com/firefly-iii/firefly-iii/issues/12035) (Foreign currency account value in primary currency does not update after changing exchange rates (Dashboard)) reported by @gattacus
- [Issue 12043](https://github.com/firefly-iii/firefly-iii/issues/12043) (Detail in the Running balance indicator through the Liabilities accounts (multi currencies)) reported by @jgmm81
- [Discussion 12044](https://github.com/orgs/firefly-iii/discussions/12044) (Very slow startup) started by @pelaxa
- [Issue 12056](https://github.com/firefly-iii/firefly-iii/issues/12056) (Details regarding the Note records in the Database and the "Purge data from Firefly III" function) reported by @jgmm81
- [Issue 12063](https://github.com/firefly-iii/firefly-iii/issues/12063) (Cannot set budget higher than 268435456) reported by @Permagate
- [Issue 12066](https://github.com/firefly-iii/firefly-iii/issues/12066) (Email notifications ignore user language preferences) reported by @examosa
- [Issue 12070](https://github.com/firefly-iii/firefly-iii/issues/12070) (can't add money to piggy bank) reported by @4e868df3
- [Issue 12081](https://github.com/firefly-iii/firefly-iii/issues/12081) (Discord changes webhook domain) reported by @MinDBreaK
- [Issue 12083](https://github.com/firefly-iii/firefly-iii/issues/12083) (Hide or remove the Ntfy fields if they dont work.) reported by @OrakMoya
- [Issue 12107](https://github.com/firefly-iii/firefly-iii/issues/12107) (Exception sending test email notification) reported by @antrv
- [Issue 12154](https://github.com/firefly-iii/firefly-iii/issues/12154) (Error on artisan firefly-iii:upgrade-database v6.6.0) reported by @Tealk
## v6.6.0 - 2026-04-19
<!-- summary: This releases upgrades many dependencies and will invalidate all of your OAuth-tokens and clients. -->
> [!WARNING]
> This releases will invalidate ALL of your OAuth-tokens and clients. Sorry about that.
> This releases will invalidate ALL of your OAuth-tokens and clients. Integrations with Home Assistant, AI-agents or the Firefly III Data Importer must be reconfigured with newly generated tokens. Old tokens and clients will no longer work. Sorry about that.
### Changed
@@ -28,6 +56,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- [Issue 12070](https://github.com/firefly-iii/firefly-iii/issues/12070) (can't add money to piggy bank) reported by @4e868df3
- [Issue 12081](https://github.com/firefly-iii/firefly-iii/issues/12081) (Discord changes webhook domain) reported by @MinDBreaK
- [Issue 12083](https://github.com/firefly-iii/firefly-iii/issues/12083) (Hide or remove the Ntfy fields if they dont work.) reported by @OrakMoya
- [Issue 12107](https://github.com/firefly-iii/firefly-iii/issues/12107) (Exception sending test email notification) reported by @antrv
## v6.5.9 - 2026-03-23

86
composer.lock generated
View File

@@ -1879,16 +1879,16 @@
},
{
"name": "laravel/framework",
"version": "v13.5.0",
"version": "v13.6.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "ffa1850049a691b93129808f27ecd10e65c9d1a5"
"reference": "416a93ea9c53161e0d4b8a44045f447b65a7d2f1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/ffa1850049a691b93129808f27ecd10e65c9d1a5",
"reference": "ffa1850049a691b93129808f27ecd10e65c9d1a5",
"url": "https://api.github.com/repos/laravel/framework/zipball/416a93ea9c53161e0d4b8a44045f447b65a7d2f1",
"reference": "416a93ea9c53161e0d4b8a44045f447b65a7d2f1",
"shasum": ""
},
"require": {
@@ -2098,20 +2098,20 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2026-04-14T13:55:03+00:00"
"time": "2026-04-21T13:32:11+00:00"
},
{
"name": "laravel/passport",
"version": "v13.7.4",
"version": "v13.7.5",
"source": {
"type": "git",
"url": "https://github.com/laravel/passport.git",
"reference": "16c45794c6a6176792fdf555f986aa1b944d9081"
"reference": "90053dc4ba681c076855779250109bb624f961f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/passport/zipball/16c45794c6a6176792fdf555f986aa1b944d9081",
"reference": "16c45794c6a6176792fdf555f986aa1b944d9081",
"url": "https://api.github.com/repos/laravel/passport/zipball/90053dc4ba681c076855779250109bb624f961f6",
"reference": "90053dc4ba681c076855779250109bb624f961f6",
"shasum": ""
},
"require": {
@@ -2173,20 +2173,20 @@
"issues": "https://github.com/laravel/passport/issues",
"source": "https://github.com/laravel/passport"
},
"time": "2026-04-09T13:39:45+00:00"
"time": "2026-04-16T14:00:29+00:00"
},
{
"name": "laravel/prompts",
"version": "v0.3.16",
"version": "v0.3.17",
"source": {
"type": "git",
"url": "https://github.com/laravel/prompts.git",
"reference": "11e7d5f93803a2190b00e145142cb00a33d17ad2"
"reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/prompts/zipball/11e7d5f93803a2190b00e145142cb00a33d17ad2",
"reference": "11e7d5f93803a2190b00e145142cb00a33d17ad2",
"url": "https://api.github.com/repos/laravel/prompts/zipball/6a82ac19a28b916ae0885828795dbd4c59d9a818",
"reference": "6a82ac19a28b916ae0885828795dbd4c59d9a818",
"shasum": ""
},
"require": {
@@ -2230,9 +2230,9 @@
"description": "Add beautiful and user-friendly forms to your command-line applications.",
"support": {
"issues": "https://github.com/laravel/prompts/issues",
"source": "https://github.com/laravel/prompts/tree/v0.3.16"
"source": "https://github.com/laravel/prompts/tree/v0.3.17"
},
"time": "2026-03-23T14:35:33+00:00"
"time": "2026-04-20T16:07:33+00:00"
},
{
"name": "laravel/serializable-closure",
@@ -3938,23 +3938,23 @@
},
{
"name": "nunomaduro/collision",
"version": "v8.9.3",
"version": "v8.9.4",
"source": {
"type": "git",
"url": "https://github.com/nunomaduro/collision.git",
"reference": "b0d8ab95b29c3189aeeb902d81215231df4c1b64"
"reference": "716af8f95a470e9094cfca09ed897b023be191a5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/b0d8ab95b29c3189aeeb902d81215231df4c1b64",
"reference": "b0d8ab95b29c3189aeeb902d81215231df4c1b64",
"url": "https://api.github.com/repos/nunomaduro/collision/zipball/716af8f95a470e9094cfca09ed897b023be191a5",
"reference": "716af8f95a470e9094cfca09ed897b023be191a5",
"shasum": ""
},
"require": {
"filp/whoops": "^2.18.4",
"nunomaduro/termwind": "^2.4.0",
"php": "^8.2.0",
"symfony/console": "^7.4.8 || ^8.0.4"
"symfony/console": "^7.4.8 || ^8.0.8"
},
"conflict": {
"laravel/framework": "<11.48.0 || >=14.0.0",
@@ -3962,12 +3962,12 @@
},
"require-dev": {
"brianium/paratest": "^7.8.5",
"larastan/larastan": "^3.9.3",
"laravel/framework": "^11.48.0 || ^12.56.0 || ^13.2.0",
"laravel/pint": "^1.29.0",
"orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.0.0",
"larastan/larastan": "^3.9.6",
"laravel/framework": "^11.48.0 || ^12.56.0 || ^13.5.0",
"laravel/pint": "^1.29.1",
"orchestra/testbench-core": "^9.12.0 || ^10.12.1 || ^11.2.1",
"pestphp/pest": "^3.8.5 || ^4.4.3 || ^5.0.0",
"sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.0.0"
"sebastian/environment": "^7.2.1 || ^8.0.4 || ^9.3.0"
},
"type": "library",
"extra": {
@@ -4030,7 +4030,7 @@
"type": "patreon"
}
],
"time": "2026-04-06T19:25:53+00:00"
"time": "2026-04-21T14:04:20+00:00"
},
{
"name": "nunomaduro/termwind",
@@ -10473,16 +10473,16 @@
},
{
"name": "fruitcake/laravel-debugbar",
"version": "v4.2.6",
"version": "v4.2.8",
"source": {
"type": "git",
"url": "https://github.com/fruitcake/laravel-debugbar.git",
"reference": "68c3de788feb7047bea547b51253e71a54e7936a"
"reference": "799d70c1101d3f8840dd76ff68ff6a78f9352905"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/68c3de788feb7047bea547b51253e71a54e7936a",
"reference": "68c3de788feb7047bea547b51253e71a54e7936a",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/799d70c1101d3f8840dd76ff68ff6a78f9352905",
"reference": "799d70c1101d3f8840dd76ff68ff6a78f9352905",
"shasum": ""
},
"require": {
@@ -10559,7 +10559,7 @@
],
"support": {
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.2.6"
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.2.8"
},
"funding": [
{
@@ -10571,7 +10571,7 @@
"type": "github"
}
],
"time": "2026-04-10T07:24:18+00:00"
"time": "2026-04-20T13:31:29+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@@ -11141,16 +11141,16 @@
},
{
"name": "php-debugbar/php-debugbar",
"version": "v3.7.4",
"version": "v3.7.5",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "af82a54530c56919ce3c6fba1942a247ac9f6777"
"reference": "dbf77f48fa6e6b57ed57ae67aa047b2535697788"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/af82a54530c56919ce3c6fba1942a247ac9f6777",
"reference": "af82a54530c56919ce3c6fba1942a247ac9f6777",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/dbf77f48fa6e6b57ed57ae67aa047b2535697788",
"reference": "dbf77f48fa6e6b57ed57ae67aa047b2535697788",
"shasum": ""
},
"require": {
@@ -11227,7 +11227,7 @@
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.7.4"
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.7.5"
},
"funding": [
{
@@ -11239,7 +11239,7 @@
"type": "github"
}
],
"time": "2026-04-09T11:28:41+00:00"
"time": "2026-04-15T11:58:43+00:00"
},
{
"name": "php-debugbar/symfony-bridge",
@@ -11357,11 +11357,11 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.50",
"version": "2.1.51",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/d452086fb4cf648c6b2d8cf3b639351f79e4f3e2",
"reference": "d452086fb4cf648c6b2d8cf3b639351f79e4f3e2",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59",
"reference": "dc3b523c45e714c70de2ac5113b958223b55dc59",
"shasum": ""
},
"require": {
@@ -11406,7 +11406,7 @@
"type": "github"
}
],
"time": "2026-04-17T13:10:32+00:00"
"time": "2026-04-21T18:22:01+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)envDefaultWhenEmpty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-04-18',
'build_time' => 1776513742,
'version' => 'develop/2026-04-22',
'build_time' => 1776876664,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

View File

@@ -1,38 +1,19 @@
<?php
/*
* passport.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
return [
/*
|--------------------------------------------------------------------------
| Passport Guard
|--------------------------------------------------------------------------
|
| Here you may specify which authentication guard Passport will use when
| authenticating users. This value should correspond with one of your
| guards that is already present in your "auth" configuration file.
|
*/
|--------------------------------------------------------------------------
| Passport Guard
|--------------------------------------------------------------------------
|
| Here you may specify which authentication guard Passport will use when
| authenticating users. This value should correspond with one of your
| guards that is already present in your "auth" configuration file.
|
*/
'guard' => envDefaultWhenEmpty(env('AUTHENTICATION_GUARD'), 'web'),
@@ -51,32 +32,12 @@ return [
'public_key' => env('PASSPORT_PUBLIC_KEY'),
/*
|--------------------------------------------------------------------------
| Client UUIDs
|--------------------------------------------------------------------------
|
| By default, Passport uses auto-incrementing primary keys when assigning
| IDs to clients. However, if Passport is installed using the provided
| --uuids switch, this will be set to "true" and UUIDs will be used.
|
*/
'client_uuids' => false,
/*
|--------------------------------------------------------------------------
| Personal Access Client
|--------------------------------------------------------------------------
|
| If you enable client hashing, you should set the personal access client
| ID and unhashed secret within your environment file. The values will
| get used while issuing fresh personal access tokens to your users.
|
*/
'personal_access_client' => [
'id' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_ID'),
'secret' => env('PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET'),
],
'middleware' => [],
'connection' => env('PASSPORT_CONNECTION'),
];

104
package-lock.json generated
View File

@@ -2900,57 +2900,57 @@
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz",
"integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==",
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.33.tgz",
"integrity": "sha512-3PZLQwFw4Za3TC8t0FvTy3wI16Kt+pmwcgNZca4Pj9iWL2E72a/gZlpBtAJvEdDMdCxdG/qq0C7PN0bsJuv0Rw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.2",
"@vue/shared": "3.5.32",
"@vue/shared": "3.5.33",
"entities": "^7.0.1",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz",
"integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==",
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.33.tgz",
"integrity": "sha512-PXq0yrfCLzzL07rbXO4awtXY1Z06LG2eu6Adg3RJFa/j3Cii217XxxLXG22N330gw7GmALCY0Z8RgXEviwgpjA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.32",
"@vue/shared": "3.5.32"
"@vue/compiler-core": "3.5.33",
"@vue/shared": "3.5.33"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz",
"integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==",
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.33.tgz",
"integrity": "sha512-UTUvRO9cY+rROrx/pvN9P5Z7FgA6QGfokUCfhQE4EnmUj3rVnK+CHI0LsEO1pg+I7//iRYMUfcNcCPe7tg0CoA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.2",
"@vue/compiler-core": "3.5.32",
"@vue/compiler-dom": "3.5.32",
"@vue/compiler-ssr": "3.5.32",
"@vue/shared": "3.5.32",
"@vue/compiler-core": "3.5.33",
"@vue/compiler-dom": "3.5.33",
"@vue/compiler-ssr": "3.5.33",
"@vue/shared": "3.5.33",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.21",
"postcss": "^8.5.8",
"postcss": "^8.5.10",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz",
"integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==",
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.33.tgz",
"integrity": "sha512-IErjYdnj1qIupG5xxiVIYiiRvDhGWV4zuh/RCrwfYpuL+HWQzeU6lCk/nF9r7olWMnjKxCAkOctT2qFWFkzb1A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.32",
"@vue/shared": "3.5.32"
"@vue/compiler-dom": "3.5.33",
"@vue/shared": "3.5.33"
}
},
"node_modules/@vue/component-compiler-utils": {
@@ -3032,9 +3032,9 @@
"license": "MIT"
},
"node_modules/@vue/shared": {
"version": "3.5.32",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz",
"integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==",
"version": "3.5.33",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.33.tgz",
"integrity": "sha512-5vR2QIlmaLG77Ygd4pMP6+SGQ5yox9VhtnbDWTy9DzMzdmeLxZ1QqxrywEZ9sa1AVubfIJyaCG3ytyWU81ufcQ==",
"dev": true,
"license": "MIT"
},
@@ -3569,9 +3569,9 @@
}
},
"node_modules/axios": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz",
"integrity": "sha512-wWyJDlAatxk30ZJer+GeCWS209sA42X+N5jU2jy6oHTp7ufw8uzUTVFBX9+wTfAlhiJXGS0Bq7X6efruWjuK9Q==",
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.15.2.tgz",
"integrity": "sha512-wLrXxPtcrPTsNlJmKjkPnNPK2Ihe0hn0wGSaTEiHRPxwjvJwT3hKmXF4dpqxmPO9SoNb2FsYXj/xEo0gHN+D5A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3681,9 +3681,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.19",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz",
"integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==",
"version": "2.10.21",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.21.tgz",
"integrity": "sha512-Q+rUQ7Uz8AHM7DEaNdwvfFCTq7a43lNTzuS94eiWqwyxfV/wJv+oUivef51T91mmRY4d4A1u9rcSvkeufCVXlA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4133,9 +4133,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001788",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz",
"integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==",
"version": "1.0.30001790",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001790.tgz",
"integrity": "sha512-bOoxfJPyYo+ds6W0YfptaCWbFnJYjh2Y1Eow5lRv+vI2u8ganPZqNm1JwNh0t2ELQCqIWg4B3dWEusgAmsoyOw==",
"dev": true,
"funding": [
{
@@ -5337,9 +5337,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.340",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.340.tgz",
"integrity": "sha512-908qahOGocRMinT2nM3ajCEM99H4iPdv84eagPP3FfZy/1ZGeOy2CZYzjhms81ckOPCXPlW7LkY4XpxD8r1DrA==",
"version": "1.5.343",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.343.tgz",
"integrity": "sha512-YHnQ3MXI08icvL9ZKnEBy05F2EQ8ob01UaMOuMbM8l+4UcAq6MPPbBTJBbsBUg3H8JeZNt+O4fjsoWth3p6IFg==",
"dev": true,
"license": "ISC"
},
@@ -6646,9 +6646,9 @@
}
},
"node_modules/i18next": {
"version": "26.0.5",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.5.tgz",
"integrity": "sha512-9uHb4T27TdV36phJXcbpnRPt5yzAfqHXVrdASvmHZyPuZJtrLythd+GyXhiaHV5LlpuuskbAqhwPjmfTbKbi8w==",
"version": "26.0.6",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-26.0.6.tgz",
"integrity": "sha512-A4U6eCXodIbrhf8EarRurB9/4ebyaurH4+fu4gig9bqxmpSt+fCAFm/GpRQDcN1Xzu/LdFCx4nYHsnM1edIIbg==",
"funding": [
{
"type": "individual",
@@ -6686,9 +6686,9 @@
}
},
"node_modules/i18next-http-backend": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.4.tgz",
"integrity": "sha512-udwrBIE6cNpqn1gRAqRULq3+7MzIIuaiKRWrz++dVz5SqWW2VwXmPJtAgkI0JtMLFaADC9qNmnZAxWAhsxXx2g==",
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-3.0.5.tgz",
"integrity": "sha512-QaWHnsxieEDcqKe+vo/RFqpiIFRi/KBqlOSPcUlvinBaISCeiTRCbtrazHAjtHtsLC66oDsROAH8frWkQzfMMQ==",
"license": "MIT",
"dependencies": {
"cross-fetch": "4.1.0"
@@ -7212,9 +7212,9 @@
}
},
"node_modules/jsonfile": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
"integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
@@ -8269,9 +8269,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.37",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
"integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==",
"version": "2.0.38",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz",
"integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
"dev": true,
"license": "MIT"
},
@@ -10748,9 +10748,9 @@
}
},
"node_modules/tapable": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.2.tgz",
"integrity": "sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==",
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
"integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
"dev": true,
"license": "MIT",
"engines": {

View File

@@ -1,8 +1,8 @@
{
"firefly": {
"explain_pats": "Personal Access Tokens are long lived (with a maximum of 1 year) keys that allow direct and unlimited access to your Firefly III data. Tools like the Firefly III Data Importer and the Firefly III integration in Home Assistant use such tokens to connect to Firefly III and do their thing. When you create a token, it is only visible once. The token is also very long.",
"profile_oauth_clients_explain": "An OAuth client can be used to connect \"smart\" applications to Firefly III: applications that are capable of redirecting you to your Firefly III, get your permission, and return you back. The Firefly III Data Importer is such an application. OAuth clients can be generated with or without a \"secret\". This secret is used to authenticate the client. Since not all clients are capable of storing the secret, so you have the option to generate a client without one.",
"regenerate_secret": "Regenerate secret",
"explain_pats": "Les jetons d'acc\u00e8s personnels sont des cl\u00e9s de longue dur\u00e9e (avec un maximum de 1 an) qui permettent un acc\u00e8s direct et illimit\u00e9 \u00e0 vos donn\u00e9es Firefly III. Des outils comme l'importateur de donn\u00e9es Firefly III et l'int\u00e9gration de Firefly III dans Home Assistant utilisent de tels jetons pour se connecter \u00e0 Firefly III et faire leur travail. Lorsque vous cr\u00e9ez un jeton, il n'est visible qu'une seule fois. Le jeton est \u00e9galement tr\u00e8s long.",
"profile_oauth_clients_explain": "Un client OAuth peut \u00eatre utilis\u00e9 pour connecter des applications \"intelligentes\" \u00e0 Firefly III : des applications capables de vous rediriger vers votre Firefly III, obtenir votre permission, et vous faire revenir en arri\u00e8re. L'importateur de donn\u00e9es Firefly III en est un exemple. Les clients OAuth peuvent \u00eatre g\u00e9n\u00e9r\u00e9s avec ou sans \"secret\". Ce secret est utilis\u00e9 pour authentifier le client. Puisque tous les clients ne sont pas capables de stocker le secret, vous avez donc la possibilit\u00e9 de g\u00e9n\u00e9rer un client sans secret.",
"regenerate_secret": "Reg\u00e9n\u00e9rer le secret",
"administrations_page_title": "Administrations financi\u00e8res",
"administrations_index_menu": "Administrations financi\u00e8res",
"expires_at": "Expire le",
@@ -75,8 +75,8 @@
"profile_whoops": "Oups !",
"profile_something_wrong": "Une erreur s'est produite !",
"profile_try_again": "Une erreur s\u2019est produite. Merci d\u2019essayer \u00e0 nouveau.",
"profile_oauth_clients": "OAuth Clients and Applications",
"profile_oauth_no_clients": "You have not created any OAuth clients or applications.",
"profile_oauth_clients": "Clients et applications OAuth",
"profile_oauth_no_clients": "Vous n'avez pas cr\u00e9\u00e9 de clients ou d'applications OAuth.",
"profile_oauth_clients_header": "Clients",
"profile_oauth_client_id": "Identifiant",
"profile_oauth_client_name": "Nom",
@@ -86,7 +86,7 @@
"profile_oauth_edit_client": "Modifier le client",
"profile_oauth_name_help": "Quelque chose que vos utilisateurs reconna\u00eetront et qui inspirera confiance.",
"profile_oauth_redirect_url": "URL de redirection",
"profile_oauth_clients_external_auth": "Please note that if you're using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.",
"profile_oauth_clients_external_auth": "Si vous utilisez un fournisseur d'authentification externe comme Authelia, les clients OAuth ne fonctionneront pas. Vous ne pouvez utiliser que des jetons d'acc\u00e8s personnel.",
"profile_oauth_redirect_url_help": "URL de callback de votre application.",
"profile_authorized_apps": "Applications autoris\u00e9es",
"profile_authorized_clients": "Clients autoris\u00e9s",
@@ -104,8 +104,8 @@
"piggy_bank": "Tirelire",
"profile_oauth_client_secret_title": "Secret du client",
"profile_oauth_client_secret_expl": "Voici votre nouveau secret de client. C'est la seule fois qu'il sera affich\u00e9, donc ne le perdez pas ! Vous pouvez maintenant utiliser ce secret pour faire des requ\u00eates d'API.",
"profile_oauth_confidential": "Keep a secret?",
"profile_oauth_confidential_help": "Can the application you're using this for keep a secret? The Firefly III Data Importer CANNOT keep a secret, so UNCHECK the box. In other cases, it's up to you.",
"profile_oauth_confidential": "Garder un secret ?",
"profile_oauth_confidential_help": "L'application que vous utilisez peut garder un secret ? L'importateur de donn\u00e9es Firefly III ne peut PAS garder un secret, alors DECOCHEZ la case. Dans d'autres cas, c'est \u00e0 vous de voir.",
"multi_account_warning_unknown": "Selon le type d'op\u00e9ration que vous cr\u00e9ez, le(s) compte(s) source et\/ou de destination des s\u00e9parations suivantes peuvent \u00eatre remplac\u00e9s par celui de la premi\u00e8re s\u00e9paration de l'op\u00e9ration.",
"multi_account_warning_withdrawal": "Gardez en t\u00eate que le compte source des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration de la d\u00e9pense.",
"multi_account_warning_deposit": "Gardez en t\u00eate que le compte de destination des s\u00e9parations suivantes peut \u00eatre remplac\u00e9 par celui de la premi\u00e8re s\u00e9paration du d\u00e9p\u00f4t.",

View File

@@ -1,8 +1,8 @@
{
"firefly": {
"explain_pats": "Personal Access Tokens are long lived (with a maximum of 1 year) keys that allow direct and unlimited access to your Firefly III data. Tools like the Firefly III Data Importer and the Firefly III integration in Home Assistant use such tokens to connect to Firefly III and do their thing. When you create a token, it is only visible once. The token is also very long.",
"profile_oauth_clients_explain": "An OAuth client can be used to connect \"smart\" applications to Firefly III: applications that are capable of redirecting you to your Firefly III, get your permission, and return you back. The Firefly III Data Importer is such an application. OAuth clients can be generated with or without a \"secret\". This secret is used to authenticate the client. Since not all clients are capable of storing the secret, so you have the option to generate a client without one.",
"regenerate_secret": "Regenerate secret",
"explain_pats": "Osebni \u017eetoni za dostop so dolgo\u017eivi (najve\u010d 1 leto) klju\u010di, ki omogo\u010dajo neposreden in neomejen dostop do va\u0161ih podatkov Firefly III. Orodja kot sta Uvoz podatkov Firefly III in integracija Firefly III v Home Assistant uporabljajo tak\u0161ne \u017eetone za povezavo s Firefly III. Ko ustvarite \u017eeton, je viden samo enkrat. \u017deton je tudi zelo dolg.",
"profile_oauth_clients_explain": "OAuth odjemalec se lahko uporabi za povezavo \u00bbpametnih\u00ab aplikacij s Firefly III: aplikacij, ki vas znajo preusmeriti na va\u0161 Firefly III, pridobiti va\u0161e dovoljenje in vas vrniti nazaj. Uvoz podatkov Firefly III je ena tak\u0161nih aplikacij. OAuth odjemalce je mogo\u010de ustvariti z \u00bbskrivnostjo\u00ab ali brez nje. Ta skrivnost se uporablja za avtentikacijo odjemalca. Ker niso vsi odjemalci zmo\u017eni shraniti skrivnosti, imate mo\u017enost ustvariti odjemalca brez nje.",
"regenerate_secret": "Obnovi skrivnost",
"administrations_page_title": "Finan\u010dne administracije",
"administrations_index_menu": "Finan\u010dne administracije",
"expires_at": "Pote\u010de ob",
@@ -75,8 +75,8 @@
"profile_whoops": "Ups!",
"profile_something_wrong": "Nekaj je \u0161lo narobe!",
"profile_try_again": "Nekaj \u200b\u200bje \u0161lo narobe. Prosim poskusite znova.",
"profile_oauth_clients": "OAuth Clients and Applications",
"profile_oauth_no_clients": "You have not created any OAuth clients or applications.",
"profile_oauth_clients": "OAuth odjemalci in aplikacije",
"profile_oauth_no_clients": "Niste ustvarili \u0161e nobenega odjemalca OAuth ali aplikacije.",
"profile_oauth_clients_header": "Odjemalci",
"profile_oauth_client_id": "Client ID",
"profile_oauth_client_name": "Ime",
@@ -86,7 +86,7 @@
"profile_oauth_edit_client": "Urejanje odjemalca",
"profile_oauth_name_help": "Nekaj, kar bodo va\u0161i uporabniki prepoznali in mu zaupali.",
"profile_oauth_redirect_url": "URL preusmeritve",
"profile_oauth_clients_external_auth": "Please note that if you're using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.",
"profile_oauth_clients_external_auth": "Upo\u0161tevajte, da odjemalci OAuth ne bodo delovali, \u010de uporabljate zunanjega ponudnika avtentikacije kot je Authelia. Uporabite lahko samo osebne \u017eetone za dostop.",
"profile_oauth_redirect_url_help": "URL povratnega klica avtorizacije va\u0161e aplikacije.",
"profile_authorized_apps": "Poobla\u0161\u010dene aplikacije",
"profile_authorized_clients": "Poobla\u0161\u010deni odjemalci",
@@ -104,8 +104,8 @@
"piggy_bank": "Dodaj hranilnik",
"profile_oauth_client_secret_title": "Skrivna koda odjemalca",
"profile_oauth_client_secret_expl": "Tukaj je skrivna koda va\u0161ega odjemalca. To je edini \u010das, da bo prikazana, zato je ne izgubite! Zdaj lahko uporabite to skrivno kodo za po\u0161iljanje zahtev API.",
"profile_oauth_confidential": "Keep a secret?",
"profile_oauth_confidential_help": "Can the application you're using this for keep a secret? The Firefly III Data Importer CANNOT keep a secret, so UNCHECK the box. In other cases, it's up to you.",
"profile_oauth_confidential": "Obdr\u017ei skrivnost?",
"profile_oauth_confidential_help": "Ali lahko aplikacija, za katero jo uporabljate, ohrani skrivnost? Uvoz podatkov Firefly III NE MORE ohraniti skrivnosti, zato ODKLJUKAJTE polje. V ostalih primerih je odlo\u010ditev va\u0161a.",
"multi_account_warning_unknown": "Odvisno od vrste transakcije, ki jo ustvarite, lahko izvorni in\/ali ciljni ra\u010dun poznej\u0161ih razdelitev preglasi tisto, kar je definirano v prvi razdelitvi transakcije.",
"multi_account_warning_withdrawal": "Upo\u0161tevajte, da bo izvorni ra\u010dun poznej\u0161ih razdelitev preglasilo tisto, kar je definirano v prvi razdelitvi odliva.",
"multi_account_warning_deposit": "Upo\u0161tevajte, da bo ciljni ra\u010dun poznej\u0161ih delitev preglasilo tisto, kar je opredeljeno v prvi delitvi priliva.",

View File

@@ -32,9 +32,9 @@
<tr>
<th class="hidden-xs">&nbsp;</th>
<th>{{ trans('list.description') }}</th>
<th>{{ trans('list.amount') }}</th>
<th class="text-right">{{ trans('list.amount') }}</th>
{% if fireflyiiiconfig('use_running_balance', true) %}
<th>{{ trans('list.running_balance') }}</th>
<th class="text-right">{{ trans('list.running_balance') }}</th>
{% endif %}
<th>{{ trans('list.date') }}</th>
<th>{{ trans('list.source_account') }}</th>
@@ -282,8 +282,15 @@
{% if transaction.source_account_id == account.id %}
<span title="Deposit, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %}
{% if transaction.source_account_type == 'Revenue account' %}
<span title="Deposit from revenue">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %}
<span title="Deposit from liab">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}</span>
{% endif %}
{# if this is a deposit from revenue account, use the destination account currency? For #12043 and #12169 #}
{# otherwise, keep at source account #}
{# changed from normal currency_symbol to foreign_currency_symbol for #12043 #}
<span title="Deposit, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}</span>
{% endif %}
{% elseif transaction.transaction_type_type == 'Withdrawal' %}