Compare commits

...

37 Commits

Author SHA1 Message Date
github-actions[bot]
76657b5519 Merge pull request #11428 from firefly-iii/release-1767271388
🤖 Automatically merge the PR into the develop branch.
2026-01-01 13:43:16 +01:00
JC5
775deb2142 🤖 Auto commit for release 'develop' on 2026-01-01 2026-01-01 13:43:08 +01:00
James Cole
8220d491f9 Fix popup in report helper 2026-01-01 13:39:16 +01:00
github-actions[bot]
6dd2627a6a Merge pull request #11424 from firefly-iii/release-1767125383
🤖 Automatically merge the PR into the develop branch.
2025-12-30 21:09:52 +01:00
JC5
22074568ae 🤖 Auto commit for release 'develop' on 2025-12-30 2025-12-30 21:09:43 +01:00
James Cole
df03899588 Fix whoopsie. 2025-12-30 21:05:50 +01:00
github-actions[bot]
7f4f95097b Merge pull request #11423 from firefly-iii/release-1767124577
🤖 Automatically merge the PR into the develop branch.
2025-12-30 20:56:26 +01:00
JC5
c96ada053f 🤖 Auto commit for release 'develop' on 2025-12-30 2025-12-30 20:56:17 +01:00
James Cole
523ec7c0a1 Expand settings, make accounts not mandatory. 2025-12-30 20:51:56 +01:00
James Cole
61444e9660 New variables for updates. 2025-12-30 16:39:46 +01:00
github-actions[bot]
8235c24c13 Merge pull request #11421 from firefly-iii/release-1767107945
🤖 Automatically merge the PR into the develop branch.
2025-12-30 16:19:14 +01:00
JC5
7ca96a766f 🤖 Auto commit for release 'develop' on 2025-12-30 2025-12-30 16:19:05 +01:00
James Cole
27586a7ec2 Allow transactions to be moved to the future and still have the running balance calculated correctly. 2025-12-30 16:13:28 +01:00
James Cole
dc3c3bb092 Add setting for anonymous amounts in preferences. 2025-12-30 07:24:14 +01:00
github-actions[bot]
7287c29778 Merge pull request #11419 from firefly-iii/release-1767020049
🤖 Automatically merge the PR into the develop branch.
2025-12-29 15:54:17 +01:00
JC5
7d374b22f9 🤖 Auto commit for release 'develop' on 2025-12-29 2025-12-29 15:54:09 +01:00
James Cole
e0542f1270 Fix end of quarter issue. 2025-12-29 11:10:28 +01:00
James Cole
73a9be0605 Fix #11410 2025-12-29 11:05:48 +01:00
github-actions[bot]
1f343bda1a Merge pull request #11416 from firefly-iii/release-1766995950
🤖 Automatically merge the PR into the develop branch.
2025-12-29 09:12:40 +01:00
JC5
1c8eaf93a6 🤖 Auto commit for release 'develop' on 2025-12-29 2025-12-29 09:12:30 +01:00
James Cole
ccfee25000 Merge pull request #11414 from oboxodo/develop
Add Uruguayan Peso to currency seeder
2025-12-29 09:11:25 +01:00
Diego Algorta
07c6dac766 Add Uruguayan Peso to currency seeder 2025-12-28 12:06:08 -03:00
github-actions[bot]
b0b2e5b752 Merge pull request #11411 from firefly-iii/release-1766901579
🤖 Automatically merge the PR into the develop branch.
2025-12-28 06:59:46 +01:00
JC5
ff3a935e9d 🤖 Auto commit for release 'develop' on 2025-12-28 2025-12-28 06:59:39 +01:00
James Cole
f0e2f09da7 Fix some end of period stuff. 2025-12-28 06:54:03 +01:00
github-actions[bot]
f3fbebb9a4 Merge pull request #11409 from firefly-iii/release-1766836192
🤖 Automatically merge the PR into the develop branch.
2025-12-27 12:49:59 +01:00
JC5
6e6e42dab6 🤖 Auto commit for release 'develop' on 2025-12-27 2025-12-27 12:49:53 +01:00
James Cole
d9efd63fad Add debug details. 2025-12-27 12:45:46 +01:00
github-actions[bot]
bc273ada39 Merge pull request #11406 from firefly-iii/release-1766776026
🤖 Automatically merge the PR into the develop branch.
2025-12-26 20:07:14 +01:00
JC5
75c76bb6dd 🤖 Auto commit for release 'develop' on 2025-12-26 2025-12-26 20:07:06 +01:00
James Cole
4d2dd1d8f7 Fix view of running balance column 2025-12-26 20:02:09 +01:00
James Cole
456e73ac16 Fix #11403 2025-12-26 07:09:04 +01:00
James Cole
86f1d8a1bc Fix ALE amount logging. 2025-12-24 07:45:03 +01:00
James Cole
7dac164556 Remove maxlength 2025-12-22 15:39:41 +01:00
James Cole
532df54f10 Merge pull request #11394 from firefly-iii/dependabot/composer/develop/mailersend/laravel-driver-2.12.0 2025-12-22 05:20:33 +01:00
mergify[bot]
daa76d01ca Merge branch 'develop' into dependabot/composer/develop/mailersend/laravel-driver-2.12.0 2025-12-22 03:37:04 +00:00
dependabot[bot]
6b7aed7658 Bump mailersend/laravel-driver from 2.9.1 to 2.12.0
Bumps [mailersend/laravel-driver](https://github.com/mailersend/mailersend-laravel-driver) from 2.9.1 to 2.12.0.
- [Release notes](https://github.com/mailersend/mailersend-laravel-driver/releases)
- [Commits](https://github.com/mailersend/mailersend-laravel-driver/compare/v2.9.1...v2.12.0)

---
updated-dependencies:
- dependency-name: mailersend/laravel-driver
  dependency-version: 2.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-22 03:01:04 +00:00
32 changed files with 461 additions and 339 deletions

View File

@@ -731,16 +731,16 @@
}, },
{ {
"name": "react/child-process", "name": "react/child-process",
"version": "v0.6.6", "version": "v0.6.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/reactphp/child-process.git", "url": "https://github.com/reactphp/child-process.git",
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", "url": "https://api.github.com/repos/reactphp/child-process/zipball/970f0e71945556422ee4570ccbabaedc3cf04ad3",
"reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", "reference": "970f0e71945556422ee4570ccbabaedc3cf04ad3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -794,7 +794,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/reactphp/child-process/issues", "issues": "https://github.com/reactphp/child-process/issues",
"source": "https://github.com/reactphp/child-process/tree/v0.6.6" "source": "https://github.com/reactphp/child-process/tree/v0.6.7"
}, },
"funding": [ "funding": [
{ {
@@ -802,7 +802,7 @@
"type": "open_collective" "type": "open_collective"
} }
], ],
"time": "2025-01-01T16:37:48+00:00" "time": "2025-12-23T15:25:20+00:00"
}, },
{ {
"name": "react/dns", "name": "react/dns",
@@ -1252,16 +1252,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v8.0.1", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "fcb73f69d655b48fcb894a262f074218df08bd58" "reference": "6145b304a5c1ea0bdbd0b04d297a5864f9a7d587"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/fcb73f69d655b48fcb894a262f074218df08bd58", "url": "https://api.github.com/repos/symfony/console/zipball/6145b304a5c1ea0bdbd0b04d297a5864f9a7d587",
"reference": "fcb73f69d655b48fcb894a262f074218df08bd58", "reference": "6145b304a5c1ea0bdbd0b04d297a5864f9a7d587",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1318,7 +1318,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v8.0.1" "source": "https://github.com/symfony/console/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -1338,7 +1338,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-05T15:25:33+00:00" "time": "2025-12-23T14:52:06+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -1640,16 +1640,16 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v8.0.0", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "7598dd5770580fa3517ec83e8da0c9b9e01f4291" "reference": "dd3a2953570a283a2ba4e17063bb98c734cf5b12"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/7598dd5770580fa3517ec83e8da0c9b9e01f4291", "url": "https://api.github.com/repos/symfony/finder/zipball/dd3a2953570a283a2ba4e17063bb98c734cf5b12",
"reference": "7598dd5770580fa3517ec83e8da0c9b9e01f4291", "reference": "dd3a2953570a283a2ba4e17063bb98c734cf5b12",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1684,7 +1684,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v8.0.0" "source": "https://github.com/symfony/finder/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -1704,7 +1704,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-05T14:36:47+00:00" "time": "2025-12-23T14:52:06+00:00"
}, },
{ {
"name": "symfony/options-resolver", "name": "symfony/options-resolver",
@@ -2358,16 +2358,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v8.0.0", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149" "reference": "0cbbd88ec836f8757641c651bb995335846abb78"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/a0a750500c4ce900d69ba4e9faf16f82c10ee149", "url": "https://api.github.com/repos/symfony/process/zipball/0cbbd88ec836f8757641c651bb995335846abb78",
"reference": "a0a750500c4ce900d69ba4e9faf16f82c10ee149", "reference": "0cbbd88ec836f8757641c651bb995335846abb78",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2399,7 +2399,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v8.0.0" "source": "https://github.com/symfony/process/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -2419,7 +2419,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-10-16T16:25:44+00:00" "time": "2025-12-19T10:01:18+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",

View File

@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution. Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2025 ## 2025
- Diego Algorta
- Jihad - Jihad
- jreyesr - jreyesr
- codearena-bot - codearena-bot

View File

@@ -28,10 +28,10 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Jobs\SendWebhookMessage; use FireflyIII\Jobs\SendWebhookMessage;
use FireflyIII\Models\Webhook; use FireflyIII\Models\Webhook;
use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface; use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface;
use FireflyIII\Support\Facades\FireflyConfig;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use FireflyIII\Support\Facades\FireflyConfig;
/** /**
* Class SubmitController * Class SubmitController

View File

@@ -79,8 +79,8 @@ class UpdateRequest extends FormRequest
'start_date' => 'date|nullable', 'start_date' => 'date|nullable',
'target_date' => 'date|nullable|after:start_date', 'target_date' => 'date|nullable|after:start_date',
'notes' => 'max:65000', 'notes' => 'max:65000',
'accounts' => 'required', 'accounts' => 'array',
'accounts.*' => 'array|required', 'accounts.*' => 'array',
'accounts.*.account_id' => ['required', 'numeric', 'belongsToUser:accounts,id'], 'accounts.*.account_id' => ['required', 'numeric', 'belongsToUser:accounts,id'],
'accounts.*.current_amount' => ['numeric', 'nullable', new IsValidZeroOrMoreAmount(true)], 'accounts.*.current_amount' => ['numeric', 'nullable', new IsValidZeroOrMoreAmount(true)],
'object_group_id' => 'numeric|belongsToUser:object_groups,id', 'object_group_id' => 'numeric|belongsToUser:object_groups,id',

View File

@@ -37,17 +37,19 @@ class UpdateRequest extends FormRequest
use ChecksLogin; use ChecksLogin;
use ConvertsDataTypes; use ConvertsDataTypes;
private array $booleans = ['configuration.is_demo_site', 'configuration.single_user_mode', 'configuration.enable_exchange_rates', 'configuration.use_running_balance', 'configuration.enable_external_map', 'configuration.enable_external_rates', 'configuration.allow_webhooks'];
private array $integers = ['configuration.permission_update_check', 'configuration.last_update_check'];
/** /**
* Get all data from the request. * Get all data from the request.
*/ */
public function getAll(): array public function getAll(): array
{ {
$name = $this->route()->parameter('dynamicConfigKey'); $name = $this->route()->parameter('dynamicConfigKey');
if (in_array($name, $this->booleans, true)) {
if ('configuration.is_demo_site' === $name || 'configuration.single_user_mode' === $name) {
return ['value' => $this->boolean('value')]; return ['value' => $this->boolean('value')];
} }
if ('configuration.permission_update_check' === $name || 'configuration.last_update_check' === $name) { if (in_array($name, $this->integers, true)) {
return ['value' => $this->convertInteger('value')]; return ['value' => $this->convertInteger('value')];
} }
@@ -61,13 +63,13 @@ class UpdateRequest extends FormRequest
{ {
$name = $this->route()->parameter('configName'); $name = $this->route()->parameter('configName');
if ('configuration.is_demo_site' === $name || 'configuration.single_user_mode' === $name) { if (in_array($name, $this->booleans, true)) {
return ['value' => ['required', new IsBoolean()]]; return ['value' => ['required', new IsBoolean()]];
} }
if ('configuration.permission_update_check' === $name) { if ('configuration.permission_update_check' === $name) {
return ['value' => 'required|numeric|min:-1|max:1']; return ['value' => 'required|numeric|min:-1|max:1'];
} }
if ('configuration.last_update_check' === $name) { if (in_array($name, $this->integers, true)) {
return ['value' => 'required|numeric|min:464272080']; return ['value' => 'required|numeric|min:464272080'];
} }

View File

@@ -84,7 +84,7 @@ class CorrectsAmounts extends Command
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class); $repository = app(AccountRepositoryInterface::class);
$type = TransactionType::where('type', TransactionTypeEnum::TRANSFER->value)->first(); $type = TransactionType::where('type', TransactionTypeEnum::TRANSFER->value)->first();
$journals = TransactionJournal::where('transaction_type_id', $type->id)->get(); $journals = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')->whereNotNull('transactions.foreign_amount')->where('transaction_journals.transaction_type_id', $type->id)->distinct()->get(['transaction_journals.*']);
/** @var TransactionJournal $journal */ /** @var TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
@@ -93,7 +93,7 @@ class CorrectsAmounts extends Command
$valid = $this->validateJournal($journal); $valid = $this->validateJournal($journal);
if (false === $valid) { if (false === $valid) {
Log::debug(sprintf('Journal #%d does not need to be fixed or is invalid (see previous messages)', $journal->id)); // Log::debug(sprintf('Journal #%d does not need to be fixed or is invalid (see previous messages)', $journal->id));
continue; continue;
} }
@@ -298,7 +298,7 @@ class CorrectsAmounts extends Command
return false; return false;
} }
if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) { if (null === $source->foreign_currency_id || null === $destination->foreign_currency_id) {
Log::debug('No foreign currency information is present, can safely continue with other transactions.'); // Log::debug('No foreign currency information is present, can safely continue with other transactions.');
return false; return false;
} }

View File

@@ -51,7 +51,7 @@ class TransactionJournalMetaFactory
Log::debug('Is a carbon object.'); Log::debug('Is a carbon object.');
$value = $data['data']->toW3cString(); $value = $data['data']->toW3cString();
} }
if ('' === (string) $value) { if ('' === (string)$value) {
// Log::debug('Is an empty string.'); // Log::debug('Is an empty string.');
// don't store blank strings. // don't store blank strings.
if (null !== $entry) { if (null !== $entry) {

View File

@@ -24,11 +24,12 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Observer; namespace FireflyIII\Handlers\Observer;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Models\AccountBalanceCalculator; use FireflyIII\Support\Models\AccountBalanceCalculator;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use FireflyIII\Support\Facades\FireflyConfig;
/** /**
* Class TransactionObserver * Class TransactionObserver
@@ -42,7 +43,10 @@ class TransactionObserver
Log::debug('Observe "created" of a transaction.'); Log::debug('Observe "created" of a transaction.');
if (true === FireflyConfig::get('use_running_balance', config('firefly.feature_flags.running_balance_column'))->data && (1 === bccomp($transaction->amount, '0') && self::$recalculate)) { if (true === FireflyConfig::get('use_running_balance', config('firefly.feature_flags.running_balance_column'))->data && (1 === bccomp($transaction->amount, '0') && self::$recalculate)) {
Log::debug('Trigger recalculateForJournal'); Log::debug('Trigger recalculateForJournal');
AccountBalanceCalculator::recalculateForJournal($transaction->transactionJournal); $journal = $transaction->transactionJournal;
if ($journal instanceof TransactionJournal) {
AccountBalanceCalculator::recalculateForJournal($journal);
}
} }
$this->updatePrimaryCurrencyAmount($transaction); $this->updatePrimaryCurrencyAmount($transaction);
} }
@@ -56,7 +60,10 @@ class TransactionObserver
$transaction->native_amount = null; $transaction->native_amount = null;
$transaction->native_foreign_amount = null; $transaction->native_foreign_amount = null;
// first normal amount // first normal amount
if ($transaction->transactionCurrency->id !== $userCurrency->id && (null === $transaction->foreign_currency_id || (null !== $transaction->foreign_currency_id && $transaction->foreign_currency_id !== $userCurrency->id))) { if ($transaction->transactionCurrency->id !== $userCurrency->id
&& (null === $transaction->foreign_currency_id
|| (null !== $transaction->foreign_currency_id
&& $transaction->foreign_currency_id !== $userCurrency->id))) {
$converter = new ExchangeRateConverter(); $converter = new ExchangeRateConverter();
$converter->setUserGroup($transaction->transactionJournal->user->userGroup); $converter->setUserGroup($transaction->transactionJournal->user->userGroup);
$converter->setIgnoreSettings(true); $converter->setIgnoreSettings(true);

View File

@@ -66,7 +66,7 @@ class PopupReport implements PopupReportInterface
if (null !== $currencyId) { if (null !== $currencyId) {
/** @var CurrencyRepositoryInterface $repos */ /** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class); $repos = app(CurrencyRepositoryInterface::class);
$currency = $repos->find((int) $currencyId); $currency = $repos->find((int)$currencyId);
} }
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
@@ -98,7 +98,7 @@ class PopupReport implements PopupReportInterface
if (null !== $currencyId) { if (null !== $currencyId) {
/** @var CurrencyRepositoryInterface $repos */ /** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class); $repos = app(CurrencyRepositoryInterface::class);
$currency = $repos->find((int) $currencyId); $currency = $repos->find((int)$currencyId);
} }
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
@@ -135,7 +135,7 @@ class PopupReport implements PopupReportInterface
if (null !== $currencyId) { if (null !== $currencyId) {
/** @var CurrencyRepositoryInterface $repos */ /** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class); $repos = app(CurrencyRepositoryInterface::class);
$currency = $repos->find((int) $currencyId); $currency = $repos->find((int)$currencyId);
} }
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
@@ -174,9 +174,10 @@ class PopupReport implements PopupReportInterface
if (null !== $currencyId) { if (null !== $currencyId) {
/** @var CurrencyRepositoryInterface $repos */ /** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class); $repos = app(CurrencyRepositoryInterface::class);
$currency = $repos->find((int) $currencyId); $currency = $repos->find((int)$currencyId);
} }
/** @var JournalRepositoryInterface $repository */ /** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class); $repository = app(JournalRepositoryInterface::class);
$repository->setUser($account->user); $repository->setUser($account->user);
@@ -187,11 +188,11 @@ class PopupReport implements PopupReportInterface
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
// set report accounts + the request accounts: // the source account must be in the set.
// $set = $attributes['accounts'] ?? new Collection; $set = $attributes['accounts'] ?? new Collection();
// $set->push($account);
$collector->setDestinationAccounts(new Collection()->push($account)) $collector->setDestinationAccounts(new Collection()->push($account))
->setSourceAccounts($set)
->setRange($attributes['startDate'], $attributes['endDate']) ->setRange($attributes['startDate'], $attributes['endDate'])
->withAccountInformation() ->withAccountInformation()
->withBudgetInformation() ->withBudgetInformation()

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
@@ -33,7 +32,9 @@ use FireflyIII\Http\Requests\PreferencesRequest;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Navigation;
use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Singleton\PreferencesSingleton; use FireflyIII\Support\Singleton\PreferencesSingleton;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@@ -44,7 +45,6 @@ use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use JsonException; use JsonException;
use Safe\Exceptions\FilesystemException; use Safe\Exceptions\FilesystemException;
use FireflyIII\Support\Facades\Steam;
use function Safe\file_get_contents; use function Safe\file_get_contents;
use function Safe\json_decode; use function Safe\json_decode;
@@ -63,7 +63,7 @@ class PreferencesController extends Controller
$this->middleware( $this->middleware(
static function ($request, $next) { static function ($request, $next) {
app('view')->share('title', (string) trans('firefly.preferences')); app('view')->share('title', (string)trans('firefly.preferences'));
app('view')->share('mainTitleIcon', 'fa-gear'); app('view')->share('mainTitleIcon', 'fa-gear');
return $next($request); return $next($request);
@@ -87,8 +87,8 @@ class PreferencesController extends Controller
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
$type = $account->accountType->type; $type = $account->accountType->type;
$role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role')); $role = sprintf('opt_group_%s', $repository->getMetaValue($account, 'account_role'));
if (in_array($type, [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value], true)) { if (in_array($type, [AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value], true)) {
$role = sprintf('opt_group_l_%s', $type); $role = sprintf('opt_group_l_%s', $type);
@@ -97,7 +97,7 @@ class PreferencesController extends Controller
if ('opt_group_' === $role) { if ('opt_group_' === $role) {
$role = 'opt_group_defaultAsset'; $role = 'opt_group_defaultAsset';
} }
$groupedAccounts[(string) trans(sprintf('firefly.%s', $role))][$account->id] = $account->name; $groupedAccounts[(string)trans(sprintf('firefly.%s', $role))][$account->id] = $account->name;
} }
ksort($groupedAccounts); ksort($groupedAccounts);
@@ -120,21 +120,22 @@ class PreferencesController extends Controller
if (is_array($fiscalYearStartStr)) { if (is_array($fiscalYearStartStr)) {
$fiscalYearStartStr = '01-01'; $fiscalYearStartStr = '01-01';
} }
$fiscalYearStart = sprintf('%s-%s', Carbon::now()->format('Y'), (string) $fiscalYearStartStr); $fiscalYearStart = sprintf('%s-%s', Carbon::now()->format('Y'), (string)$fiscalYearStartStr);
$tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data; $tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$availableDarkModes = config('firefly.available_dark_modes'); $availableDarkModes = config('firefly.available_dark_modes');
// notifications settings // notifications settings
$slackUrl = Preferences::getEncrypted('slack_webhook_url', '')->data; $slackUrl = Preferences::getEncrypted('slack_webhook_url', '')->data;
$pushoverAppToken = (string) Preferences::getEncrypted('pushover_app_token', '')->data; $pushoverAppToken = (string)Preferences::getEncrypted('pushover_app_token', '')->data;
$pushoverUserToken = (string) Preferences::getEncrypted('pushover_user_token', '')->data; $pushoverUserToken = (string)Preferences::getEncrypted('pushover_user_token', '')->data;
$ntfyServer = Preferences::getEncrypted('ntfy_server', 'https://ntfy.sh')->data; $ntfyServer = Preferences::getEncrypted('ntfy_server', 'https://ntfy.sh')->data;
$ntfyTopic = (string) Preferences::getEncrypted('ntfy_topic', '')->data; $ntfyTopic = (string)Preferences::getEncrypted('ntfy_topic', '')->data;
$ntfyAuth = '1' === Preferences::get('ntfy_auth', false)->data; $ntfyAuth = '1' === Preferences::get('ntfy_auth', false)->data;
$ntfyUser = Preferences::getEncrypted('ntfy_user', '')->data; $ntfyUser = Preferences::getEncrypted('ntfy_user', '')->data;
$ntfyPass = (string) Preferences::getEncrypted('ntfy_pass', '')->data; $ntfyPass = (string)Preferences::getEncrypted('ntfy_pass', '')->data;
$channels = config('notifications.channels'); $channels = config('notifications.channels');
$forcedAvailability = []; $forcedAvailability = [];
$anonymous = Steam::anonymous();
// notification preferences // notification preferences
$notifications = []; $notifications = [];
@@ -164,7 +165,7 @@ class PreferencesController extends Controller
Log::error($e->getMessage()); Log::error($e->getMessage());
$locales = []; $locales = [];
} }
$locales = ['equal' => (string) trans('firefly.equal_to_language')] + $locales; $locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
// an important fallback is that the frontPageAccount array gets refilled automatically // an important fallback is that the frontPageAccount array gets refilled automatically
// when it turns up empty. // when it turns up empty.
if (0 === count($frontpageAccounts)) { if (0 === count($frontpageAccounts)) {
@@ -184,7 +185,7 @@ class PreferencesController extends Controller
$ntfyPass = ''; $ntfyPass = '';
} }
return view('preferences.index', ['language' => $language, 'pushoverAppToken' => $pushoverAppToken, 'pushoverUserToken' => $pushoverUserToken, 'ntfyServer' => $ntfyServer, 'ntfyTopic' => $ntfyTopic, 'ntfyAuth' => $ntfyAuth, 'channels' => $channels, 'ntfyUser' => $ntfyUser, 'forcedAvailability' => $forcedAvailability, 'ntfyPass' => $ntfyPass, 'groupedAccounts' => $groupedAccounts, 'isDocker' => $isDocker, 'frontpageAccounts' => $frontpageAccounts, 'languages' => $languages, 'darkMode' => $darkMode, 'availableDarkModes' => $availableDarkModes, 'notifications' => $notifications, 'convertToPrimary' => $convertToPrimary, 'slackUrl' => $slackUrl, 'locales' => $locales, 'locale' => $locale, 'tjOptionalFields' => $tjOptionalFields, 'viewRange' => $viewRange, 'customFiscalYear' => $customFiscalYear, 'listPageSize' => $listPageSize, 'fiscalYearStart' => $fiscalYearStart]); return view('preferences.index', ['anonymous' => $anonymous, 'language' => $language, 'pushoverAppToken' => $pushoverAppToken, 'pushoverUserToken' => $pushoverUserToken, 'ntfyServer' => $ntfyServer, 'ntfyTopic' => $ntfyTopic, 'ntfyAuth' => $ntfyAuth, 'channels' => $channels, 'ntfyUser' => $ntfyUser, 'forcedAvailability' => $forcedAvailability, 'ntfyPass' => $ntfyPass, 'groupedAccounts' => $groupedAccounts, 'isDocker' => $isDocker, 'frontpageAccounts' => $frontpageAccounts, 'languages' => $languages, 'darkMode' => $darkMode, 'availableDarkModes' => $availableDarkModes, 'notifications' => $notifications, 'convertToPrimary' => $convertToPrimary, 'slackUrl' => $slackUrl, 'locales' => $locales, 'locale' => $locale, 'tjOptionalFields' => $tjOptionalFields, 'viewRange' => $viewRange, 'customFiscalYear' => $customFiscalYear, 'listPageSize' => $listPageSize, 'fiscalYearStart' => $fiscalYearStart]);
} }
/** /**
@@ -201,7 +202,7 @@ class PreferencesController extends Controller
$frontpageAccounts = []; $frontpageAccounts = [];
if (is_array($request->get('frontpageAccounts')) && count($request->get('frontpageAccounts')) > 0) { if (is_array($request->get('frontpageAccounts')) && count($request->get('frontpageAccounts')) > 0) {
foreach ($request->get('frontpageAccounts') as $id) { foreach ($request->get('frontpageAccounts') as $id) {
$frontpageAccounts[] = (int) $id; $frontpageAccounts[] = (int)$id;
} }
Preferences::set('frontpageAccounts', $frontpageAccounts); Preferences::set('frontpageAccounts', $frontpageAccounts);
} }
@@ -241,7 +242,7 @@ class PreferencesController extends Controller
} }
// convert primary // convert primary
$convertToPrimary = 1 === (int) $request->get('convertToPrimary'); $convertToPrimary = 1 === (int)$request->get('convertToPrimary');
if ($convertToPrimary && !$this->convertToPrimary) { if ($convertToPrimary && !$this->convertToPrimary) {
// set to true! // set to true!
Log::debug('User sets convertToPrimary to true.'); Log::debug('User sets convertToPrimary to true.');
@@ -253,9 +254,9 @@ class PreferencesController extends Controller
Preferences::set('convert_to_primary', $convertToPrimary); Preferences::set('convert_to_primary', $convertToPrimary);
// custom fiscal year // custom fiscal year
$customFiscalYear = 1 === (int) $request->get('customFiscalYear'); $customFiscalYear = 1 === (int)$request->get('customFiscalYear');
Preferences::set('customFiscalYear', $customFiscalYear); Preferences::set('customFiscalYear', $customFiscalYear);
$fiscalYearString = (string) $request->get('fiscalYearStart'); $fiscalYearString = (string)$request->get('fiscalYearStart');
if ('' !== $fiscalYearString) { if ('' !== $fiscalYearString) {
$fiscalYearStart = Carbon::parse($fiscalYearString, config('app.timezone'))->format('m-d'); $fiscalYearStart = Carbon::parse($fiscalYearString, config('app.timezone'))->format('m-d');
Preferences::set('fiscalYearStart', $fiscalYearStart); Preferences::set('fiscalYearStart', $fiscalYearStart);
@@ -263,7 +264,7 @@ class PreferencesController extends Controller
// save page size: // save page size:
Preferences::set('listPageSize', 50); Preferences::set('listPageSize', 50);
$listPageSize = (int) $request->get('listPageSize'); $listPageSize = (int)$request->get('listPageSize');
if ($listPageSize > 0 && $listPageSize < 1337) { if ($listPageSize > 0 && $listPageSize < 1337) {
Preferences::set('listPageSize', $listPageSize); Preferences::set('listPageSize', $listPageSize);
} }
@@ -282,7 +283,7 @@ class PreferencesController extends Controller
// same for locale: // same for locale:
if (!auth()->user()->hasRole('demo')) { if (!auth()->user()->hasRole('demo')) {
$locale = (string) $request->get('locale'); $locale = (string)$request->get('locale');
$locale = '' === $locale ? null : $locale; $locale = '' === $locale ? null : $locale;
Preferences::set('locale', $locale); Preferences::set('locale', $locale);
} }
@@ -311,7 +312,12 @@ class PreferencesController extends Controller
Preferences::set('darkMode', $darkMode); Preferences::set('darkMode', $darkMode);
} }
session()->flash('success', (string) trans('firefly.saved_preferences')); // anonymous amounts?
$anonymous = '1' === $request->get('anonymous');
Preferences::set('anonymous', $anonymous);
// save and continue
session()->flash('success', (string)trans('firefly.saved_preferences'));
Preferences::mark(); Preferences::mark();
return redirect(route('preferences.index')); return redirect(route('preferences.index'));
@@ -325,7 +331,7 @@ class PreferencesController extends Controller
switch ($channel) { switch ($channel) {
default: default:
session()->flash('error', (string) trans('firefly.notification_test_failed', ['channel' => $channel])); session()->flash('error', (string)trans('firefly.notification_test_failed', ['channel' => $channel]));
break; break;
@@ -337,7 +343,7 @@ class PreferencesController extends Controller
$user = auth()->user(); $user = auth()->user();
Log::debug(sprintf('Now in testNotification("%s") controller.', $channel)); Log::debug(sprintf('Now in testNotification("%s") controller.', $channel));
event(new UserTestNotificationChannel($channel, $user)); event(new UserTestNotificationChannel($channel, $user));
session()->flash('success', (string) trans('firefly.notification_test_executed', ['channel' => $channel])); session()->flash('success', (string)trans('firefly.notification_test_executed', ['channel' => $channel]));
} }
return ''; return '';

View File

@@ -27,8 +27,6 @@ use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Attachment; use FireflyIII\Models\Attachment;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
/** /**
@@ -38,7 +36,6 @@ use Illuminate\Support\Collection;
* @method getUserGroup() * @method getUserGroup()
* @method getUser() * @method getUser()
* @method checkUserGroupAccess(UserRoleEnum $role) * @method checkUserGroupAccess(UserRoleEnum $role)
* @method setUser(null|Authenticatable|User $user)
* @method setUserGroupById(int $userGroupId) * @method setUserGroupById(int $userGroupId)
*/ */
interface AttachmentRepositoryInterface interface AttachmentRepositoryInterface

View File

@@ -68,8 +68,7 @@ class JournalUpdateService
private ?Account $destinationAccount = null; private ?Account $destinationAccount = null;
private ?Transaction $destinationTransaction = null; private ?Transaction $destinationTransaction = null;
private array $metaDate private array $metaDate
= ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', '_internal_previous_date'];
'invoice_date', ];
private array $metaString private array $metaString
= [ = [
'sepa_cc', 'sepa_cc',
@@ -205,11 +204,9 @@ class JournalUpdateService
$validator->setUser($this->transactionJournal->user); $validator->setUser($this->transactionJournal->user);
$result = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]); $result = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName]);
Log::debug( Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true)));
sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))
);
// TODO typeoverrule the account validator may have a different opinion on the transaction type. // TODO type overrule the account validator may have a different opinion on the transaction type.
// validate submitted info: // validate submitted info:
return $result; return $result;
@@ -283,14 +280,7 @@ class JournalUpdateService
$validator->setUser($this->transactionJournal->user); $validator->setUser($this->transactionJournal->user);
$validator->source = $this->getValidSourceAccount(); $validator->source = $this->getValidSourceAccount();
$result = $validator->validateDestination(['id' => $destId, 'name' => $destName]); $result = $validator->validateDestination(['id' => $destId, 'name' => $destName]);
Log::debug( Log::debug(sprintf('hasValidDestinationAccount(%d, "%s") will return %s', $destId, $destName, var_export($result, true)));
sprintf(
'hasValidDestinationAccount(%d, "%s") will return %s',
$destId,
$destName,
var_export($result, true)
)
);
// TODO typeOverrule: the account validator may have another opinion on the transaction type. // TODO typeOverrule: the account validator may have another opinion on the transaction type.
@@ -494,6 +484,24 @@ class JournalUpdateService
// do some parsing. // do some parsing.
Log::debug(sprintf('Create date value from string "%s".', $value)); Log::debug(sprintf('Create date value from string "%s".', $value));
$this->transactionJournal->date_tz = $value->format('e'); $this->transactionJournal->date_tz = $value->format('e');
$res = $value->gt($this->transactionJournal->date);
Log::debug(sprintf('Old date: %s, new date: %s', $this->transactionJournal->date->toW3cString(), $value->toW3cString()));
/** @var TransactionJournalMetaFactory $factory */
$factory = app(TransactionJournalMetaFactory::class);
$set = [
'journal' => $this->transactionJournal,
'name' => '_internal_previous_date',
'data' => null,
];
if ($res) {
Log::debug('Transaction is set to be AFTER its current date. Save also the "_internal_previous_date"-field.');
$set['data'] = clone $this->transactionJournal->date;
}
if (!$res) {
Log::debug('Transaction is NOT set to be AFTER its current date. Remove the "_internal_previous_date"-field.');
}
$factory->updateOrCreate($set);
} }
event(new TriggeredAuditLog($this->transactionJournal->user, $this->transactionJournal, sprintf('update_%s', $fieldName), $this->transactionJournal->{$fieldName}, $value)); event(new TriggeredAuditLog($this->transactionJournal->user, $this->transactionJournal, sprintf('update_%s', $fieldName), $this->transactionJournal->{$fieldName}, $value));
@@ -652,7 +660,7 @@ class JournalUpdateService
} }
$value = $this->data['amount'] ?? ''; $value = $this->data['amount'] ?? '';
Log::debug(sprintf('Amount is now "%s"', $value)); Log::debug(sprintf('[a] Amount is now "%s"', $value));
try { try {
$amount = $this->getAmount($value); $amount = $this->getAmount($value);
@@ -661,15 +669,18 @@ class JournalUpdateService
return; return;
} }
Log::debug(sprintf('[b] Amount is now "%s"', $value));
$origSourceTransaction = $this->getSourceTransaction(); $origSourceTransaction = $this->getSourceTransaction();
$destTransaction = $this->getDestinationTransaction();
$originalSourceAmount = $origSourceTransaction->amount;
$originalDestAmount = $destTransaction->amount;
$origSourceTransaction->amount = Steam::negative($amount); $origSourceTransaction->amount = Steam::negative($amount);
$origSourceTransaction->balance_dirty = true; $origSourceTransaction->balance_dirty = true;
$origSourceTransaction->save();
$destTransaction = $this->getDestinationTransaction();
$originalAmount = $destTransaction->amount;
$destTransaction->amount = Steam::positive($amount); $destTransaction->amount = Steam::positive($amount);
$destTransaction->balance_dirty = true; $destTransaction->balance_dirty = true;
$destTransaction->save(); $destTransaction->save();
$origSourceTransaction->save();
// refresh transactions. // refresh transactions.
$this->sourceTransaction->refresh(); $this->sourceTransaction->refresh();
$this->destinationTransaction->refresh(); $this->destinationTransaction->refresh();
@@ -679,28 +690,51 @@ class JournalUpdateService
if (null === $group) { if (null === $group) {
$group = $this->transactionJournal?->transactionGroup; $group = $this->transactionJournal?->transactionGroup;
} }
if (null === $group) { if (null === $group || null === $this->transactionJournal) {
return; return;
} }
if (0 === bccomp($origSourceTransaction->amount, $originalSourceAmount)) {
Log::debug('Amount was not actually changed, return.');
// should not return in NULL but seems to do. return;
if (0 !== bccomp($originalAmount, $value)) {
event(new TriggeredAuditLog(
$group->user,
$group,
'update_amount',
[
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
'amount' => $originalAmount,
],
[
'currency_symbol' => $destTransaction->transactionCurrency->symbol,
'decimal_places' => $destTransaction->transactionCurrency->decimal_places,
'amount' => $value,
]
));
} }
Log::debug('Amount was changed.');
$transfer = TransactionTypeEnum::TRANSFER->value === $this->transactionJournal->transactionType->type;
$withdrawal = TransactionTypeEnum::WITHDRAWAL->value === $this->transactionJournal->transactionType->type;
$deposit = TransactionTypeEnum::DEPOSIT->value === $this->transactionJournal->transactionType->type;
$makePositive = $transfer || $deposit ? true : false;
// assume withdrawal, use the source for amount (negative), and destination for currency.
$originalAmount = $originalSourceAmount;
$recordCurrency = $destTransaction->transactionCurrency;
Log::debug(sprintf('Transaction is a %s, original amount is %s and currency is %s', $this->transactionJournal->transactionType->type, $originalAmount, $recordCurrency->code));
if ($withdrawal || $transfer) {
Log::debug('Use these values to record a changed withdrawal amount');
}
if (!$withdrawal && !$transfer) {
$originalAmount = $originalDestAmount;
$recordCurrency = $origSourceTransaction->transactionCurrency;
Log::debug('Use destination amount to record a changed withdrawal amount');
Log::debug(sprintf('Transaction is a %s, original amount now is %s and currency is now %s', $this->transactionJournal->transactionType->type, $originalAmount, $recordCurrency->code));
}
$originalAmount = $makePositive ? Steam::positive($originalAmount) : Steam::negative($originalAmount);
$value = $makePositive ? Steam::positive($value) : Steam::negative($value);
// should not return in NULL but seems to do.
event(new TriggeredAuditLog(
$group->user,
$group,
'update_amount',
[
'currency_symbol' => $recordCurrency->symbol,
'decimal_places' => $recordCurrency->decimal_places,
'amount' => $originalAmount,
],
[
'currency_symbol' => $recordCurrency->symbol,
'decimal_places' => $recordCurrency->decimal_places,
'amount' => $value,
]
));
} }
private function updateForeignAmount(): void private function updateForeignAmount(): void

View File

@@ -34,10 +34,16 @@ class DynamicConfigKey
{ {
public static array $accepted public static array $accepted
= [ = [
'configuration.is_demo_site', 'configuration.is_demo_site', // boolean
'configuration.permission_update_check', 'configuration.permission_update_check', // -1, 0 or 1 (never asked, no permission, permission)
'configuration.single_user_mode', 'configuration.single_user_mode', // boolean
'configuration.last_update_check', 'configuration.last_update_check', // timestamp
'configuration.enable_exchange_rates', // boolean
'configuration.use_running_balance', // boolean
'configuration.enable_external_map', // boolean
'configuration.enable_external_rates', // boolean
'configuration.allow_webhooks', // boolean
'configuration.valid_url_protocols', // string ("http,https")
]; ];
/** /**

View File

@@ -245,7 +245,6 @@ trait RenderPartialViews
if (null === $account) { if (null === $account) {
return 'This is an unknown account. Apologies.'; return 'This is an unknown account. Apologies.';
} }
$journals = $popupHelper->byExpenses($account, $attributes); $journals = $popupHelper->byExpenses($account, $attributes);
try { try {

View File

@@ -72,12 +72,25 @@ class AccountBalanceCalculator
$set[$transaction->account_id] = $transaction->account; $set[$transaction->account_id] = $transaction->account;
} }
$accounts = new Collection()->push(...$set); $accounts = new Collection()->push(...$set);
$object->optimizedCalculation($accounts, $transactionJournal->date);
// find meta value:
$date = $transactionJournal->date;
$meta = $transactionJournal->transactionJournalMeta()->where('name', '_internal_previous_date')->where('data', '!=', '')->first();
Log::debug(sprintf('Date used is "%s"', $date->toW3cString()));
if (null !== $meta) {
$date = Carbon::parse($meta->data);
Log::debug(sprintf('Date is overruled with "%s"', $date->toW3cString()));
}
$object->optimizedCalculation($accounts, $date);
} }
private function getLatestBalance(int $accountId, int $currencyId, ?Carbon $notBefore): string private function getLatestBalance(int $accountId, int $currencyId, ?Carbon $notBefore): string
{ {
if (!$notBefore instanceof Carbon) { if (!$notBefore instanceof Carbon) {
Log::debug(sprintf('Start balance for account #%d and currency #%d is 0.', $accountId, $currencyId));
return '0'; return '0';
} }
Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d'))); Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d')));

View File

@@ -23,16 +23,16 @@ declare(strict_types=1);
namespace FireflyIII\Support; namespace FireflyIII\Support;
use FireflyIII\Support\Facades\Preferences;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\IntervalException; use FireflyIII\Exceptions\IntervalException;
use FireflyIII\Helpers\Fiscal\FiscalHelperInterface; use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
use FireflyIII\Support\Calendar\Calculator; use FireflyIII\Support\Calendar\Calculator;
use FireflyIII\Support\Calendar\Periodicity; use FireflyIII\Support\Calendar\Periodicity;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Throwable; use Throwable;
use FireflyIII\Support\Facades\Steam;
/** /**
* Class Navigation. * Class Navigation.
@@ -214,6 +214,11 @@ class Navigation
Log::debug('endOfPeriod() requests "YTD" + future, set it to "1Y" instead.'); Log::debug('endOfPeriod() requests "YTD" + future, set it to "1Y" instead.');
$repeatFreq = '1Y'; $repeatFreq = '1Y';
} }
if ('QTD' === $repeatFreq && $end->isFuture()) {
// fall back to a yearly schedule if the requested period is YTD.
Log::debug('endOfPeriod() requests "YTD" + future, set it to "3M" instead.');
$repeatFreq = '3M';
}
$functionMap = [ $functionMap = [
'1D' => 'endOfDay', '1D' => 'endOfDay',
@@ -295,7 +300,25 @@ class Navigation
if (null !== $result) { if (null !== $result) {
// add sanity check. // add sanity check.
if ($currentEnd->lt($end)) { if ($currentEnd->lt($end)) {
throw new FireflyException(sprintf('[d] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString())); switch ($repeatFreq) {
case 'QTD':
$currentEnd = $end->clone()->endOfQuarter()->setMilli(0);
break;
case 'MTD':
$currentEnd = $end->clone()->endOfMonth()->setMilli(0);
break;
case 'YTD':
$currentEnd = $end->clone()->endOfYear()->setMilli(0);
break;
}
if ($currentEnd->lt($end)) {
throw new FireflyException(sprintf('[d] endOfPeriod(%s, %s) failed, because it resulted in %s.', $end->toW3cString(), $repeatFreq, $currentEnd->toW3cString()));
}
} }
return $result; return $result;

View File

@@ -28,6 +28,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Search\OperatorQuerySearch; use FireflyIII\Support\Search\OperatorQuerySearch;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
@@ -72,6 +73,7 @@ class General extends AbstractExtension
$this->hasRole(), $this->hasRole(),
$this->getRootSearchOperator(), $this->getRootSearchOperator(),
$this->carbonize(), $this->carbonize(),
$this->fireflyIIIConfig(),
]; ];
} }
@@ -393,4 +395,14 @@ class General extends AbstractExtension
static fn (string $str): string => date($str) static fn (string $str): string => date($str)
); );
} }
private function fireflyIIIConfig()
{
return new TwigFunction(
'fireflyiiiconfig',
static function (string $string, mixed $default): mixed {
return FireflyConfig::get($string, $default)->data;
}
);
}
} }

View File

@@ -75,7 +75,7 @@ class TransactionGroupTransformer extends AbstractTransformer
'recurrence_count', 'recurrence_count',
'recurrence_total', 'recurrence_total',
]; ];
$this->metaDateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date']; $this->metaDateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', '_internal_previous_date'];
} }
public function transform(array $group): array public function transform(array $group): array

View File

@@ -96,7 +96,7 @@
"league/commonmark": "^2", "league/commonmark": "^2",
"league/csv": "^9.10", "league/csv": "^9.10",
"league/fractal": "0.*", "league/fractal": "0.*",
"mailersend/laravel-driver": "^2.7", "mailersend/laravel-driver": "^2.12",
"nunomaduro/collision": "^8", "nunomaduro/collision": "^8",
"pragmarx/google2fa": "^8.0", "pragmarx/google2fa": "^8.0",
"predis/predis": "^3", "predis/predis": "^3",

343
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "8fff223d32252d22c0e6028d19a76756", "content-hash": "434b4c996dad2af3b38326bd81c57534",
"packages": [ "packages": [
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@@ -1182,24 +1182,24 @@
}, },
{ {
"name": "graham-campbell/result-type", "name": "graham-campbell/result-type",
"version": "v1.1.3", "version": "v1.1.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/GrahamCampbell/Result-Type.git", "url": "https://github.com/GrahamCampbell/Result-Type.git",
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945" "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/3ba905c11371512af9d9bdd27d99b782216b6945", "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/e01f4a821471308ba86aa202fed6698b6b695e3b",
"reference": "3ba905c11371512af9d9bdd27d99b782216b6945", "reference": "e01f4a821471308ba86aa202fed6698b6b695e3b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9.3" "phpoption/phpoption": "^1.9.5"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^8.5.39 || ^9.6.20 || ^10.5.28" "phpunit/phpunit": "^8.5.41 || ^9.6.22 || ^10.5.45 || ^11.5.7"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@@ -1228,7 +1228,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/GrahamCampbell/Result-Type/issues", "issues": "https://github.com/GrahamCampbell/Result-Type/issues",
"source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.3" "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.1.4"
}, },
"funding": [ "funding": [
{ {
@@ -1240,7 +1240,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-07-20T21:45:45+00:00" "time": "2025-12-27T19:43:20+00:00"
}, },
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
@@ -1878,16 +1878,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v12.43.1", "version": "v12.44.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "195b893593a9298edee177c0844132ebaa02102f" "reference": "592bbf1c036042958332eb98e3e8131b29102f33"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/195b893593a9298edee177c0844132ebaa02102f", "url": "https://api.github.com/repos/laravel/framework/zipball/592bbf1c036042958332eb98e3e8131b29102f33",
"reference": "195b893593a9298edee177c0844132ebaa02102f", "reference": "592bbf1c036042958332eb98e3e8131b29102f33",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2096,7 +2096,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2025-12-16T18:53:08+00:00" "time": "2025-12-23T15:29:43+00:00"
}, },
{ {
"name": "laravel/passport", "name": "laravel/passport",
@@ -2813,16 +2813,16 @@
}, },
{ {
"name": "league/csv", "name": "league/csv",
"version": "9.27.1", "version": "9.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/csv.git", "url": "https://github.com/thephpleague/csv.git",
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797" "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/26de738b8fccf785397d05ee2fc07b6cd8749797", "url": "https://api.github.com/repos/thephpleague/csv/zipball/6582ace29ae09ba5b07049d40ea13eb19c8b5073",
"reference": "26de738b8fccf785397d05ee2fc07b6cd8749797", "reference": "6582ace29ae09ba5b07049d40ea13eb19c8b5073",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2832,14 +2832,14 @@
"require-dev": { "require-dev": {
"ext-dom": "*", "ext-dom": "*",
"ext-xdebug": "*", "ext-xdebug": "*",
"friendsofphp/php-cs-fixer": "^3.75.0", "friendsofphp/php-cs-fixer": "^3.92.3",
"phpbench/phpbench": "^1.4.1", "phpbench/phpbench": "^1.4.3",
"phpstan/phpstan": "^1.12.27", "phpstan/phpstan": "^1.12.32",
"phpstan/phpstan-deprecation-rules": "^1.2.1", "phpstan/phpstan-deprecation-rules": "^1.2.1",
"phpstan/phpstan-phpunit": "^1.4.2", "phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-strict-rules": "^1.6.2", "phpstan/phpstan-strict-rules": "^1.6.2",
"phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.3.6", "phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.5.4",
"symfony/var-dumper": "^6.4.8 || ^7.3.0" "symfony/var-dumper": "^6.4.8 || ^7.4.0 || ^8.0"
}, },
"suggest": { "suggest": {
"ext-dom": "Required to use the XMLConverter and the HTMLConverter classes", "ext-dom": "Required to use the XMLConverter and the HTMLConverter classes",
@@ -2900,7 +2900,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-10-25T08:35:20+00:00" "time": "2025-12-27T15:18:42+00:00"
}, },
{ {
"name": "league/event", "name": "league/event",
@@ -3486,22 +3486,22 @@
}, },
{ {
"name": "mailersend/laravel-driver", "name": "mailersend/laravel-driver",
"version": "v2.9.1", "version": "v2.12.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/mailersend/mailersend-laravel-driver.git", "url": "https://github.com/mailersend/mailersend-laravel-driver.git",
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725" "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725", "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/15e1ec41e29e65d3ca226929c65804190aaa93eb",
"reference": "87fd5ab76808bbaac9221be0d306baef13e98725", "reference": "15e1ec41e29e65d3ca226929c65804190aaa93eb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0", "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0",
"mailersend/mailersend": "^0.31.0", "mailersend/mailersend": "^0.35.0",
"nyholm/psr7": "^1.5", "nyholm/psr7": "^1.5",
"php": ">=8.0", "php": ">=8.0",
"php-http/guzzle7-adapter": "^1.0", "php-http/guzzle7-adapter": "^1.0",
@@ -3549,29 +3549,28 @@
], ],
"support": { "support": {
"issues": "https://github.com/mailersend/mailersend-laravel-driver/issues", "issues": "https://github.com/mailersend/mailersend-laravel-driver/issues",
"source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.9.1" "source": "https://github.com/mailersend/mailersend-laravel-driver/tree/v2.12.0"
}, },
"time": "2025-04-09T09:33:07+00:00" "time": "2025-10-28T14:59:16+00:00"
}, },
{ {
"name": "mailersend/mailersend", "name": "mailersend/mailersend",
"version": "v0.31.0", "version": "v0.35.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/mailersend/mailersend-php.git", "url": "https://github.com/mailersend/mailersend-php.git",
"reference": "513ff83ee768526055ad52987cde401ea7218c67" "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67", "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/f1696cf9e727e9503fbc5882d2a111bd966ad276",
"reference": "513ff83ee768526055ad52987cde401ea7218c67", "reference": "f1696cf9e727e9503fbc5882d2a111bd966ad276",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"beberlei/assert": "^3.2", "beberlei/assert": "^3.2",
"ext-json": "*", "ext-json": "*",
"illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", "php": "^7.4 || ^8.0 <8.5",
"php": "^7.4|^8.0",
"php-http/client-common": "^2.2", "php-http/client-common": "^2.2",
"php-http/discovery": "^1.9", "php-http/discovery": "^1.9",
"php-http/httplug": "^2.1", "php-http/httplug": "^2.1",
@@ -3616,9 +3615,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/mailersend/mailersend-php/issues", "issues": "https://github.com/mailersend/mailersend-php/issues",
"source": "https://github.com/mailersend/mailersend-php/tree/v0.31.0" "source": "https://github.com/mailersend/mailersend-php/tree/v0.35.0"
}, },
"time": "2025-04-03T12:16:11+00:00" "time": "2025-10-28T13:11:43+00:00"
}, },
{ {
"name": "monolog/monolog", "name": "monolog/monolog",
@@ -3895,16 +3894,16 @@
}, },
{ {
"name": "nette/utils", "name": "nette/utils",
"version": "v4.1.0", "version": "v4.1.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nette/utils.git", "url": "https://github.com/nette/utils.git",
"reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0" "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", "url": "https://api.github.com/repos/nette/utils/zipball/c99059c0315591f1a0db7ad6002000288ab8dc72",
"reference": "fa1f0b8261ed150447979eb22e373b7b7ad5a8e0", "reference": "c99059c0315591f1a0db7ad6002000288ab8dc72",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3978,9 +3977,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nette/utils/issues", "issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v4.1.0" "source": "https://github.com/nette/utils/tree/v4.1.1"
}, },
"time": "2025-12-01T17:49:23+00:00" "time": "2025-12-22T12:14:32+00:00"
}, },
{ {
"name": "nunomaduro/collision", "name": "nunomaduro/collision",
@@ -4750,16 +4749,16 @@
}, },
{ {
"name": "phpoption/phpoption", "name": "phpoption/phpoption",
"version": "1.9.4", "version": "1.9.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/schmittjoh/php-option.git", "url": "https://github.com/schmittjoh/php-option.git",
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d" "reference": "75365b91986c2405cf5e1e012c5595cd487a98be"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/schmittjoh/php-option/zipball/638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", "url": "https://api.github.com/repos/schmittjoh/php-option/zipball/75365b91986c2405cf5e1e012c5595cd487a98be",
"reference": "638a154f8d4ee6a5cfa96d6a34dfbe0cffa9566d", "reference": "75365b91986c2405cf5e1e012c5595cd487a98be",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4809,7 +4808,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/schmittjoh/php-option/issues", "issues": "https://github.com/schmittjoh/php-option/issues",
"source": "https://github.com/schmittjoh/php-option/tree/1.9.4" "source": "https://github.com/schmittjoh/php-option/tree/1.9.5"
}, },
"funding": [ "funding": [
{ {
@@ -4821,7 +4820,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-08-21T11:53:16+00:00" "time": "2025-12-27T19:41:33+00:00"
}, },
{ {
"name": "phpseclib/phpseclib", "name": "phpseclib/phpseclib",
@@ -6205,16 +6204,16 @@
}, },
{ {
"name": "spatie/laravel-html", "name": "spatie/laravel-html",
"version": "3.12.1", "version": "3.12.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-html.git", "url": "https://github.com/spatie/laravel-html.git",
"reference": "72af3cad24d153c230ff6e1da9fa3b7b702834c9" "reference": "dd4a946ea9e2d7af8945fdfcf282663c69fac26a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-html/zipball/72af3cad24d153c230ff6e1da9fa3b7b702834c9", "url": "https://api.github.com/repos/spatie/laravel-html/zipball/dd4a946ea9e2d7af8945fdfcf282663c69fac26a",
"reference": "72af3cad24d153c230ff6e1da9fa3b7b702834c9", "reference": "dd4a946ea9e2d7af8945fdfcf282663c69fac26a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6271,7 +6270,7 @@
"spatie" "spatie"
], ],
"support": { "support": {
"source": "https://github.com/spatie/laravel-html/tree/3.12.1" "source": "https://github.com/spatie/laravel-html/tree/3.12.3"
}, },
"funding": [ "funding": [
{ {
@@ -6279,7 +6278,7 @@
"type": "custom" "type": "custom"
} }
], ],
"time": "2025-10-02T07:26:38+00:00" "time": "2025-12-22T12:05:50+00:00"
}, },
{ {
"name": "spatie/laravel-ignition", "name": "spatie/laravel-ignition",
@@ -6428,16 +6427,16 @@
}, },
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v8.0.1", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache.git", "url": "https://github.com/symfony/cache.git",
"reference": "0e67dc8145810d4e1c0d13c0e1d29ceb930b1c8e" "reference": "ef8c7dbfe613d2773d0b5e68b2ef2db72c8b025f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/0e67dc8145810d4e1c0d13c0e1d29ceb930b1c8e", "url": "https://api.github.com/repos/symfony/cache/zipball/ef8c7dbfe613d2773d0b5e68b2ef2db72c8b025f",
"reference": "0e67dc8145810d4e1c0d13c0e1d29ceb930b1c8e", "reference": "ef8c7dbfe613d2773d0b5e68b2ef2db72c8b025f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6504,7 +6503,7 @@
"psr6" "psr6"
], ],
"support": { "support": {
"source": "https://github.com/symfony/cache/tree/v8.0.1" "source": "https://github.com/symfony/cache/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -6524,7 +6523,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-04T18:17:06+00:00" "time": "2025-12-28T10:45:32+00:00"
}, },
{ {
"name": "symfony/cache-contracts", "name": "symfony/cache-contracts",
@@ -6681,16 +6680,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.4.1", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e" "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", "url": "https://api.github.com/repos/symfony/console/zipball/732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
"reference": "6d9f0fbf2ec2e9785880096e3abd0ca0c88b506e", "reference": "732a9ca6cd9dfd940c639062d5edbde2f6727fb6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6755,7 +6754,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.4.1" "source": "https://github.com/symfony/console/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -6775,7 +6774,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-05T15:23:39+00:00" "time": "2025-12-23T14:50:43+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
@@ -7225,16 +7224,16 @@
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
"version": "v7.4.0", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "340b9ed7320570f319028a2cbec46d40535e94bd" "reference": "fffe05569336549b20a1be64250b40516d6e8d06"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/340b9ed7320570f319028a2cbec46d40535e94bd", "url": "https://api.github.com/repos/symfony/finder/zipball/fffe05569336549b20a1be64250b40516d6e8d06",
"reference": "340b9ed7320570f319028a2cbec46d40535e94bd", "reference": "fffe05569336549b20a1be64250b40516d6e8d06",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7269,7 +7268,7 @@
"description": "Finds files and directories via an intuitive fluent interface", "description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/finder/tree/v7.4.0" "source": "https://github.com/symfony/finder/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -7289,20 +7288,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-05T05:42:40+00:00" "time": "2025-12-23T14:50:43+00:00"
}, },
{ {
"name": "symfony/http-client", "name": "symfony/http-client",
"version": "v8.0.1", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-client.git", "url": "https://github.com/symfony/http-client.git",
"reference": "727fda60d0aebfdfcc4c8bc4661f0cb8f44153c0" "reference": "ea062691009cc2b7bb87734fef20e02671cbd50b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/727fda60d0aebfdfcc4c8bc4661f0cb8f44153c0", "url": "https://api.github.com/repos/symfony/http-client/zipball/ea062691009cc2b7bb87734fef20e02671cbd50b",
"reference": "727fda60d0aebfdfcc4c8bc4661f0cb8f44153c0", "reference": "ea062691009cc2b7bb87734fef20e02671cbd50b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7365,7 +7364,7 @@
"http" "http"
], ],
"support": { "support": {
"source": "https://github.com/symfony/http-client/tree/v8.0.1" "source": "https://github.com/symfony/http-client/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -7385,7 +7384,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-05T14:08:45+00:00" "time": "2025-12-23T14:52:06+00:00"
}, },
{ {
"name": "symfony/http-client-contracts", "name": "symfony/http-client-contracts",
@@ -7467,16 +7466,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v7.4.1", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "bd1af1e425811d6f077db240c3a588bdb405cd27" "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/bd1af1e425811d6f077db240c3a588bdb405cd27", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a70c745d4cea48dbd609f4075e5f5cbce453bd52",
"reference": "bd1af1e425811d6f077db240c3a588bdb405cd27", "reference": "a70c745d4cea48dbd609f4075e5f5cbce453bd52",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7525,7 +7524,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.1" "source": "https://github.com/symfony/http-foundation/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -7545,20 +7544,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-07T11:13:10+00:00" "time": "2025-12-23T14:23:49+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v7.4.2", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f" "reference": "885211d4bed3f857b8c964011923528a55702aa5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/f6e6f0a5fa8763f75a504b930163785fb6dd055f", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/885211d4bed3f857b8c964011923528a55702aa5",
"reference": "f6e6f0a5fa8763f75a504b930163785fb6dd055f", "reference": "885211d4bed3f857b8c964011923528a55702aa5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7644,7 +7643,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v7.4.2" "source": "https://github.com/symfony/http-kernel/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -7664,20 +7663,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-08T07:43:37+00:00" "time": "2025-12-31T08:43:57+00:00"
}, },
{ {
"name": "symfony/mailer", "name": "symfony/mailer",
"version": "v7.4.0", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mailer.git", "url": "https://github.com/symfony/mailer.git",
"reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd" "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", "url": "https://api.github.com/repos/symfony/mailer/zipball/e472d35e230108231ccb7f51eb6b2100cac02ee4",
"reference": "a3d9eea8cfa467ece41f0f54ba28185d74bd53fd", "reference": "e472d35e230108231ccb7f51eb6b2100cac02ee4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7728,7 +7727,7 @@
"description": "Helps sending emails", "description": "Helps sending emails",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/mailer/tree/v7.4.0" "source": "https://github.com/symfony/mailer/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -7748,7 +7747,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-21T15:26:00+00:00" "time": "2025-12-16T08:02:06+00:00"
}, },
{ {
"name": "symfony/mailgun-mailer", "name": "symfony/mailgun-mailer",
@@ -8811,16 +8810,16 @@
}, },
{ {
"name": "symfony/process", "name": "symfony/process",
"version": "v7.4.0", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/process.git", "url": "https://github.com/symfony/process.git",
"reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8" "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", "url": "https://api.github.com/repos/symfony/process/zipball/2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
"reference": "7ca8dc2d0dcf4882658313aba8be5d9fd01026c8", "reference": "2f8e1a6cdf590ca63715da4d3a7a3327404a523f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -8852,7 +8851,7 @@
"description": "Executes commands in sub-processes", "description": "Executes commands in sub-processes",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/process/tree/v7.4.0" "source": "https://github.com/symfony/process/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -8872,7 +8871,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-10-16T11:21:06+00:00" "time": "2025-12-19T10:00:43+00:00"
}, },
{ {
"name": "symfony/psr-http-message-bridge", "name": "symfony/psr-http-message-bridge",
@@ -8964,16 +8963,16 @@
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v7.4.0", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "4720254cb2644a0b876233d258a32bf017330db7" "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/4720254cb2644a0b876233d258a32bf017330db7", "url": "https://api.github.com/repos/symfony/routing/zipball/5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
"reference": "4720254cb2644a0b876233d258a32bf017330db7", "reference": "5d3fd7adf8896c2fdb54e2f0f35b1bcbd9e45090",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -9025,7 +9024,7 @@
"url" "url"
], ],
"support": { "support": {
"source": "https://github.com/symfony/routing/tree/v7.4.0" "source": "https://github.com/symfony/routing/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -9045,7 +9044,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-11-27T13:27:24+00:00" "time": "2025-12-19T10:00:43+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
@@ -9226,16 +9225,16 @@
}, },
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v8.0.1", "version": "v8.0.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation.git", "url": "https://github.com/symfony/translation.git",
"reference": "770e3b8b0ba8360958abedcabacd4203467333ca" "reference": "60a8f11f0e15c48f2cc47c4da53873bb5b62135d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/770e3b8b0ba8360958abedcabacd4203467333ca", "url": "https://api.github.com/repos/symfony/translation/zipball/60a8f11f0e15c48f2cc47c4da53873bb5b62135d",
"reference": "770e3b8b0ba8360958abedcabacd4203467333ca", "reference": "60a8f11f0e15c48f2cc47c4da53873bb5b62135d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -9295,7 +9294,7 @@
"description": "Provides tools to internationalize your application", "description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/translation/tree/v8.0.1" "source": "https://github.com/symfony/translation/tree/v8.0.3"
}, },
"funding": [ "funding": [
{ {
@@ -9315,7 +9314,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-01T09:13:36+00:00" "time": "2025-12-21T10:59:45+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@@ -9479,16 +9478,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v7.4.0", "version": "v7.4.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "41fd6c4ae28c38b294b42af6db61446594a0dece" "reference": "7e99bebcb3f90d8721890f2963463280848cba92"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/41fd6c4ae28c38b294b42af6db61446594a0dece", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7e99bebcb3f90d8721890f2963463280848cba92",
"reference": "41fd6c4ae28c38b294b42af6db61446594a0dece", "reference": "7e99bebcb3f90d8721890f2963463280848cba92",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -9542,7 +9541,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v7.4.0" "source": "https://github.com/symfony/var-dumper/tree/v7.4.3"
}, },
"funding": [ "funding": [
{ {
@@ -9562,7 +9561,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-10-27T20:36:44+00:00" "time": "2025-12-18T07:04:31+00:00"
}, },
{ {
"name": "symfony/var-exporter", "name": "symfony/var-exporter",
@@ -9919,26 +9918,26 @@
}, },
{ {
"name": "vlucas/phpdotenv", "name": "vlucas/phpdotenv",
"version": "v5.6.2", "version": "v5.6.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/vlucas/phpdotenv.git", "url": "https://github.com/vlucas/phpdotenv.git",
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af" "reference": "955e7815d677a3eaa7075231212f2110983adecc"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/955e7815d677a3eaa7075231212f2110983adecc",
"reference": "24ac4c74f91ee2c193fa1aaa5c249cb0822809af", "reference": "955e7815d677a3eaa7075231212f2110983adecc",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-pcre": "*", "ext-pcre": "*",
"graham-campbell/result-type": "^1.1.3", "graham-campbell/result-type": "^1.1.4",
"php": "^7.2.5 || ^8.0", "php": "^7.2.5 || ^8.0",
"phpoption/phpoption": "^1.9.3", "phpoption/phpoption": "^1.9.5",
"symfony/polyfill-ctype": "^1.24", "symfony/polyfill-ctype": "^1.26",
"symfony/polyfill-mbstring": "^1.24", "symfony/polyfill-mbstring": "^1.26",
"symfony/polyfill-php80": "^1.24" "symfony/polyfill-php80": "^1.26"
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
@@ -9987,7 +9986,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/vlucas/phpdotenv/issues", "issues": "https://github.com/vlucas/phpdotenv/issues",
"source": "https://github.com/vlucas/phpdotenv/tree/v5.6.2" "source": "https://github.com/vlucas/phpdotenv/tree/v5.6.3"
}, },
"funding": [ "funding": [
{ {
@@ -9999,7 +9998,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-04-30T23:37:27+00:00" "time": "2025-12-27T19:49:13+00:00"
}, },
{ {
"name": "voku/portable-ascii", "name": "voku/portable-ascii",
@@ -10079,16 +10078,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "barryvdh/laravel-debugbar", "name": "barryvdh/laravel-debugbar",
"version": "v3.16.2", "version": "v3.16.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git", "url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3" "reference": "c91e57ea113edd6526f5b8cd6b1c6ee02c67b28e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/730dbf8bf41f5691e026dd771e64dd54ad1b10b3", "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c91e57ea113edd6526f5b8cd6b1c6ee02c67b28e",
"reference": "730dbf8bf41f5691e026dd771e64dd54ad1b10b3", "reference": "c91e57ea113edd6526f5b8cd6b1c6ee02c67b28e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10097,7 +10096,7 @@
"illuminate/support": "^10|^11|^12", "illuminate/support": "^10|^11|^12",
"php": "^8.1", "php": "^8.1",
"php-debugbar/php-debugbar": "^2.2.4", "php-debugbar/php-debugbar": "^2.2.4",
"symfony/finder": "^6|^7" "symfony/finder": "^6|^7|^8"
}, },
"require-dev": { "require-dev": {
"mockery/mockery": "^1.3.3", "mockery/mockery": "^1.3.3",
@@ -10148,7 +10147,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.16.2" "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.3"
}, },
"funding": [ "funding": [
{ {
@@ -10160,7 +10159,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-12-03T14:52:46+00:00" "time": "2025-12-23T17:37:00+00:00"
}, },
{ {
"name": "barryvdh/laravel-ide-helper", "name": "barryvdh/laravel-ide-helper",
@@ -10368,16 +10367,16 @@
}, },
{ {
"name": "composer/class-map-generator", "name": "composer/class-map-generator",
"version": "1.7.0", "version": "1.7.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/class-map-generator.git", "url": "https://github.com/composer/class-map-generator.git",
"reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6" "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/class-map-generator/zipball/2373419b7709815ed323ebf18c3c72d03ff4a8a6", "url": "https://api.github.com/repos/composer/class-map-generator/zipball/8f5fa3cc214230e71f54924bd0197a3bcc705eb1",
"reference": "2373419b7709815ed323ebf18c3c72d03ff4a8a6", "reference": "8f5fa3cc214230e71f54924bd0197a3bcc705eb1",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10421,7 +10420,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/composer/class-map-generator/issues", "issues": "https://github.com/composer/class-map-generator/issues",
"source": "https://github.com/composer/class-map-generator/tree/1.7.0" "source": "https://github.com/composer/class-map-generator/tree/1.7.1"
}, },
"funding": [ "funding": [
{ {
@@ -10433,7 +10432,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-11-19T10:41:15+00:00" "time": "2025-12-29T13:15:25+00:00"
}, },
{ {
"name": "composer/pcre", "name": "composer/pcre",
@@ -10516,16 +10515,16 @@
}, },
{ {
"name": "driftingly/rector-laravel", "name": "driftingly/rector-laravel",
"version": "2.1.8", "version": "2.1.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/driftingly/rector-laravel.git", "url": "https://github.com/driftingly/rector-laravel.git",
"reference": "5c5f97354e562b6742b2b7989959061bde60fa71" "reference": "aee9d4a1d489e7ec484fc79f33137f8ee051b3f7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/5c5f97354e562b6742b2b7989959061bde60fa71", "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/aee9d4a1d489e7ec484fc79f33137f8ee051b3f7",
"reference": "5c5f97354e562b6742b2b7989959061bde60fa71", "reference": "aee9d4a1d489e7ec484fc79f33137f8ee051b3f7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10546,9 +10545,9 @@
"description": "Rector upgrades rules for Laravel Framework", "description": "Rector upgrades rules for Laravel Framework",
"support": { "support": {
"issues": "https://github.com/driftingly/rector-laravel/issues", "issues": "https://github.com/driftingly/rector-laravel/issues",
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.8" "source": "https://github.com/driftingly/rector-laravel/tree/2.1.9"
}, },
"time": "2025-12-17T15:29:24+00:00" "time": "2025-12-25T23:31:36+00:00"
}, },
{ {
"name": "fakerphp/faker", "name": "fakerphp/faker",
@@ -11181,16 +11180,16 @@
}, },
{ {
"name": "php-debugbar/php-debugbar", "name": "php-debugbar/php-debugbar",
"version": "v2.2.5", "version": "v2.2.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git", "url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "c5dce08e98dd101c771e55949fd89124b216271d" "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/c5dce08e98dd101c771e55949fd89124b216271d", "url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/abb9fa3c5c8dbe7efe03ddba56782917481de3e8",
"reference": "c5dce08e98dd101c771e55949fd89124b216271d", "reference": "abb9fa3c5c8dbe7efe03ddba56782917481de3e8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11249,9 +11248,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues", "issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.5" "source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.6"
}, },
"time": "2025-12-21T08:50:08+00:00" "time": "2025-12-22T13:21:32+00:00"
}, },
{ {
"name": "phpstan/extension-installer", "name": "phpstan/extension-installer",
@@ -11451,16 +11450,16 @@
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
"version": "12.5.1", "version": "12.5.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "c467c59a4f6e04b942be422844e7a6352fa01b57" "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/c467c59a4f6e04b942be422844e7a6352fa01b57", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4a9739b51cbcb355f6e95659612f92e282a7077b",
"reference": "c467c59a4f6e04b942be422844e7a6352fa01b57", "reference": "4a9739b51cbcb355f6e95659612f92e282a7077b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11475,7 +11474,7 @@
"sebastian/environment": "^8.0.3", "sebastian/environment": "^8.0.3",
"sebastian/lines-of-code": "^4.0", "sebastian/lines-of-code": "^4.0",
"sebastian/version": "^6.0", "sebastian/version": "^6.0",
"theseer/tokenizer": "^2.0" "theseer/tokenizer": "^2.0.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^12.5.1" "phpunit/phpunit": "^12.5.1"
@@ -11516,7 +11515,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.1" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.5.2"
}, },
"funding": [ "funding": [
{ {
@@ -11536,7 +11535,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2025-12-08T07:17:58+00:00" "time": "2025-12-24T07:03:04+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@@ -11890,16 +11889,16 @@
}, },
{ {
"name": "rector/rector", "name": "rector/rector",
"version": "2.2.14", "version": "2.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rectorphp/rector.git", "url": "https://github.com/rectorphp/rector.git",
"reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d" "reference": "f7166355dcf47482f27be59169b0825995f51c7d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/6d56bb0e94d4df4f57a78610550ac76ab403657d", "url": "https://api.github.com/repos/rectorphp/rector/zipball/f7166355dcf47482f27be59169b0825995f51c7d",
"reference": "6d56bb0e94d4df4f57a78610550ac76ab403657d", "reference": "f7166355dcf47482f27be59169b0825995f51c7d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11938,7 +11937,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/rectorphp/rector/issues", "issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.14" "source": "https://github.com/rectorphp/rector/tree/2.3.0"
}, },
"funding": [ "funding": [
{ {
@@ -11946,7 +11945,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-12-09T10:57:55+00:00" "time": "2025-12-25T22:00:18+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@@ -75,11 +75,11 @@ return [
'webhooks' => true, 'webhooks' => true,
'handle_debts' => true, 'handle_debts' => true,
'expression_engine' => true, 'expression_engine' => true,
'running_balance_column' => env('USE_RUNNING_BALANCE', true), // this is only the default value, is not used. 'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => 'develop/2025-12-22', 'version' => 'develop/2026-01-01',
'build_time' => 1766374469, 'build_time' => 1767271288,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used. 'db_version' => 28, // field is no longer used.

View File

@@ -57,6 +57,7 @@ class TransactionCurrencySeeder extends Seeder
$currencies[] = ['code' => 'ARS', 'name' => 'Argentinian Peso', 'symbol' => '$', 'decimal_places' => 2]; $currencies[] = ['code' => 'ARS', 'name' => 'Argentinian Peso', 'symbol' => '$', 'decimal_places' => 2];
$currencies[] = ['code' => 'COP', 'name' => 'Colombian Peso', 'symbol' => '$', 'decimal_places' => 2]; $currencies[] = ['code' => 'COP', 'name' => 'Colombian Peso', 'symbol' => '$', 'decimal_places' => 2];
$currencies[] = ['code' => 'CLP', 'name' => 'Chilean Peso', 'symbol' => '$', 'decimal_places' => 2]; $currencies[] = ['code' => 'CLP', 'name' => 'Chilean Peso', 'symbol' => '$', 'decimal_places' => 2];
$currencies[] = ['code' => 'UYU', 'name' => 'Uruguayan Peso', 'symbol' => '$', 'decimal_places' => 2];
// oceanian currencies // oceanian currencies
$currencies[] = ['code' => 'IDR', 'name' => 'Indonesian rupiah', 'symbol' => 'Rp', 'decimal_places' => 2]; $currencies[] = ['code' => 'IDR', 'name' => 'Indonesian rupiah', 'symbol' => 'Rp', 'decimal_places' => 2];

32
package-lock.json generated
View File

@@ -4508,9 +4508,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001761", "version": "1.0.30001762",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001762.tgz",
"integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", "integrity": "sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@@ -6183,9 +6183,9 @@
} }
}, },
"node_modules/fastq": { "node_modules/fastq": {
"version": "1.19.1", "version": "1.20.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
@@ -7082,9 +7082,9 @@
} }
}, },
"node_modules/i18next-chained-backend": { "node_modules/i18next-chained-backend": {
"version": "4.6.2", "version": "4.6.3",
"resolved": "https://registry.npmjs.org/i18next-chained-backend/-/i18next-chained-backend-4.6.2.tgz", "resolved": "https://registry.npmjs.org/i18next-chained-backend/-/i18next-chained-backend-4.6.3.tgz",
"integrity": "sha512-2P092fR+nAPQlGzPUoIIxbwo7PTBqQYgLxwv1XhSTQUAUoelLo5LkX+FqRxxSDg9WEAsrc8+2WL6mJtMGIa6WQ==", "integrity": "sha512-Yg4hAKg/98zRAMQs87vJSNevTzaPPrYF3Eb7Kpx+UEaaXLd3p69g7dulAL+hpmZQHeMQ/5gFqHVtdwva53mB0Q==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.23.2" "@babel/runtime": "^7.23.2"
@@ -9650,9 +9650,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/qs": { "node_modules/qs": {
"version": "6.14.0", "version": "6.14.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
"dev": true, "dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
@@ -11577,7 +11577,7 @@
"version": "8.28.2", "version": "8.28.2",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.28.2.tgz", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.28.2.tgz",
"integrity": "sha512-C5GZjs1tYlAqjwymaaCPDjCyGo10ajUphiwA922jKt9n7KPpqR7oM1PCwYzhB/E7+nT3wfdG3oRre5raIT1rKA==", "integrity": "sha512-C5GZjs1tYlAqjwymaaCPDjCyGo10ajUphiwA922jKt9n7KPpqR7oM1PCwYzhB/E7+nT3wfdG3oRre5raIT1rKA==",
"deprecated": "Vue I18n v8.x has reached EOL and is no longer actively maintained. About maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html", "deprecated": "v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
@@ -11710,9 +11710,9 @@
} }
}, },
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.4.4", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.4.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.0.tgz",
"integrity": "sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==", "integrity": "sha512-e6vZvY6xboSwLz2GD36c16+O/2Z6fKvIf4pOXptw2rY9MVwE/TXc6RGqxD3I3x0a28lwBY7DE+76uTPSsBrrCA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

View File

@@ -34,12 +34,14 @@ $(document).ready(function () {
$('input[name="ignore_budget"]').attr('checked', false); $('input[name="ignore_budget"]').attr('checked', false);
}); });
$('input[name="tags"]').on('itemAdded', function (event) {
var isChecked = $('#tags_action_do_nothing').is(':checked');
if (true === isChecked) {
$('#tags_action_do_nothing').attr('checked', false);
$('#tags_action_do_replace').attr('checked', true);
}
$('input[name="tags"]').on('itemAdded', function(event) {
$('#tags_action_do_nothing').attr('checked', false);
$('#tags_action_do_replace').attr('checked', true);
}); });
});
});

View File

@@ -149,6 +149,9 @@ return [
'left_in_budget_limit' => 'Left to spend according to budgeting', 'left_in_budget_limit' => 'Left to spend according to budgeting',
'current_period' => 'Current period', 'current_period' => 'Current period',
'show_the_current_period_and_overview' => 'Show the current period and overview', 'show_the_current_period_and_overview' => 'Show the current period and overview',
'pref_anonymous' => 'Hidden amounts',
'pref_anonymous_help' => 'For privacy and anonymity, you can make Firefly III hide all amounts. This will not hide amounts in edit boxes, but the rest are hidden. You can also toggle this with the little "eye"-icon in the top bar.',
'pref_anonymous_label' => 'Hide amounts',
'pref_languages_locale' => 'For a language other than English to work properly, your operating system must be equipped with the correct locale-information. If these are not present, currency data, dates and amounts may be formatted wrong.', 'pref_languages_locale' => 'For a language other than English to work properly, your operating system must be equipped with the correct locale-information. If these are not present, currency data, dates and amounts may be formatted wrong.',
'budget_in_period' => 'All transactions for budget ":name" between :start and :end in :currency', 'budget_in_period' => 'All transactions for budget ":name" between :start and :end in :currency',
'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency', 'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency',
@@ -2908,6 +2911,7 @@ return [
'placeholder' => '[Placeholder]', 'placeholder' => '[Placeholder]',
// audit log entries // audit log entries
'incomplete_ale' => 'Not all events are recorded as audit log entries.',
'audit_log_entries' => 'Audit log entries', 'audit_log_entries' => 'Audit log entries',
'ale_action_log_add' => 'Added :amount to piggy bank ":name"', 'ale_action_log_add' => 'Added :amount to piggy bank ":name"',
'ale_action_log_remove' => 'Removed :amount from piggy bank ":name"', 'ale_action_log_remove' => 'Removed :amount from piggy bank ":name"',

View File

@@ -1,16 +1,21 @@
<table class="table" aria-label="Table"> <table class="table" aria-label="Table">
<thead>
<tr>
<td colspan="3"><em>{{ 'incomplete_ale'|_ }}</em></td>
</tr>
</thead>
<tbody>
{% for logEntry in logEntries %} {% for logEntry in logEntries %}
<tr> <tr>
<th style="width:20%;" scope="row"> <th style="width:20%;" scope="row">
{# link to object: #} {# link to object: #}
{% if 'FireflyIII\\Models\\Rule' == logEntry.changer_type %} {% if 'FireflyIII\\Models\\Rule' == logEntry.changer_type %}
<a href="{{ route('rules.edit', [logEntry.changer_id] ) }}"> <a href="{{ route('rules.edit', [logEntry.changer_id] ) }}">
{% endif %} {% endif %}
{% if 'FireflyIII\\User' == logEntry.changer_type %} {% if 'FireflyIII\\User' == logEntry.changer_type %}
<a href="{{ route('profile.index') }}"> <a href="{{ route('profile.index') }}">
{% endif %} {% endif %}
{{ logEntry.changer_type|replace({"FireflyIII\\Models\\": ""})|replace({"FireflyIII\\": ""}) }} {{ logEntry.changer_type|replace({"FireflyIII\\Models\\": ""})|replace({"FireflyIII\\": ""}) }} #{{ logEntry.changer_id }}
#{{ logEntry.changer_id }}
</a> </a>
</th> </th>
<td style="width:30%;" title="{{ logEntry.created_at.isoFormat(dateTimeFormat) }}"> <td style="width:30%;" title="{{ logEntry.created_at.isoFormat(dateTimeFormat) }}">
@@ -103,4 +108,5 @@
</tr> </tr>
{% endfor %} {% endfor %}
</tbody>
</table> </table>

View File

@@ -33,7 +33,7 @@
<th class="hidden-xs">&nbsp;</th> <th class="hidden-xs">&nbsp;</th>
<th>{{ trans('list.description') }}</th> <th>{{ trans('list.description') }}</th>
<th>{{ trans('list.amount') }}</th> <th>{{ trans('list.amount') }}</th>
{% if FireflyConfig.get('use_running_balance', config('firefly.feature_flags.running_balance_column')) %} {% if fireflyiiiconfig('use_running_balance', true) %}
<th>{{ trans('list.running_balance') }}</th> <th>{{ trans('list.running_balance') }}</th>
{% endif %} {% endif %}
<th>{{ trans('list.date') }}</th> <th>{{ trans('list.date') }}</th>
@@ -266,14 +266,15 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
</td> </td>
{% if FireflyConfig.get('use_running_balance', config('firefly.feature_flags.running_balance_column')) %} {% if (fireflyiiiconfig('use_running_balance', true)) %}
<td> <td>
{# RUNNING BALANCE #}
{% if (null == transaction.balance_dirty or false == transaction.balance_dirty) and null != transaction.destination_balance_after and null != transaction.source_balance_after %} {% if (null == transaction.balance_dirty or false == transaction.balance_dirty) and null != transaction.destination_balance_after and null != transaction.source_balance_after %}
{% if transaction.transaction_type_type == 'Deposit' %} {% if transaction.transaction_type_type == 'Deposit' %}
{% if transaction.source_account_id == account.id %} {% if transaction.source_account_id == account.id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Deposit, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %} {% else %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Deposit, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Withdrawal' %} {% elseif transaction.transaction_type_type == 'Withdrawal' %}
@@ -281,39 +282,39 @@
{% if 'Loan' == transaction.destination_account_type or 'Mortgage' == transaction.destination_account_type or 'Debt' == transaction.destination_account_type %} {% if 'Loan' == transaction.destination_account_type or 'Mortgage' == transaction.destination_account_type or 'Debt' == transaction.destination_account_type %}
{% if currency.id == transaction.currency_id %} {% if currency.id == transaction.currency_id %}
{% if account.id == transaction.source_account_id %} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Withdrawal, liab, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% elseif account.id == transaction.destination_account_id %} {% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Withdrawal, liab, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %} {% else %}
- -
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if currency.id == transaction.foreign_currency_id and null != transaction.destination_balance_after and null != transaction.destination_balance_after %} {% if currency.id == transaction.foreign_currency_id and null != transaction.destination_balance_after and null != transaction.destination_balance_after %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol ?? transaction.currency_symbol, transaction.foreign_currency_decimal_places ?? transaction.currency_decimal_places) }} <span title="Withdrawal, liab, dest 2">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol ?? transaction.currency_symbol, transaction.foreign_currency_decimal_places ?? transaction.currency_decimal_places) }}</span>
{% endif %} {% endif %}
{# withdrawal into an expense account #} {# withdrawal into an expense account #}
{% else %} {% else %}
{% if account.id == transaction.source_account_id %} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Withdrawal, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% elseif account.id == transaction.destination_account_id %} {% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Withdrawal, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %} {% else %}
- -
{% endif %} {% endif %}
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Opening balance' %} {% elseif transaction.transaction_type_type == 'Opening balance' %}
{% if account.id == transaction.source_account_id %} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Opening balance, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% elseif account.id == transaction.destination_account_id %} {% elseif account.id == transaction.destination_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Opening balance, src">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %} {% else %}
- -
{% endif %} {% endif %}
{% elseif transaction.transaction_type_type == 'Transfer' %} {% elseif transaction.transaction_type_type == 'Transfer' %}
{% if account.id == transaction.source_account_id %} {% if account.id == transaction.source_account_id %}
{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Transfer, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %} {% else %}
{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} <span title="Transfer, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% endif %} {% endif %}
{% else %} {% else %}
&nbsp; &nbsp;

View File

@@ -119,11 +119,11 @@
</tr> </tr>
<tr> <tr>
<td>Exchange rates</td> <td>Exchange rates</td>
<td>{% if FireflyConfig.get('enable_exchange_rates', config('cer.enabled')) %}Enabled{% else %}Disabled{% endif %}, downloads {% if FireflyConfig.get('enable_external_rates', config('cer.download_enabled')) %}enabled{% else %}disabled{% endif %}</td> <td>{% if fireflyiiiconfig('enable_exchange_rates', true) %}Enabled{% else %}Disabled{% endif %}, downloads {% if FireflyConfig.get('enable_external_rates', config('cer.download_enabled')) %}enabled{% else %}disabled{% endif %}</td>
</tr> </tr>
<tr> <tr>
<td>RB-column</td> <td>RB-column</td>
<td>{% if FireflyConfig.get('use_running_balance', config('firefly.feature_flags.running_balance_column')) %}Enabled{% else %}Disabled{% endif %}</td> <td>{% if fireflyiiiconfig('use_running_balance', true) %}Enabled{% else %}Disabled{% endif %}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@@ -226,7 +226,7 @@
<span>{{ 'currencies'|_ }}</span> <span>{{ 'currencies'|_ }}</span>
</a> </a>
</li> </li>
{% if FireflyConfig.get('enable_exchange_rates', config('cer.enabled')) %} {% if (fireflyiiiconfig('enable_exchange_rates', true)) %}
<li class="{{ activeRoutePartial('exchange-rates') }}"> <li class="{{ activeRoutePartial('exchange-rates') }}">
<a class="{{ activeRoutePartial('exchange-rates') }}" href="{{ route('exchange-rates.index') }}"> <a class="{{ activeRoutePartial('exchange-rates') }}" href="{{ route('exchange-rates.index') }}">
<span class="fa fa-angle-right fa-fw"></span> <span class="fa fa-angle-right fa-fw"></span>

View File

@@ -36,7 +36,7 @@
<td style="width:40%;">{{ 'saveOnAccounts'|_ }}</td> <td style="width:40%;">{{ 'saveOnAccounts'|_ }}</td>
<td> <td>
{% for account in piggy.accounts %} {% for account in piggy.accounts %}
<a href="{{ route('accounts.show', account.id) }}">{{ account.name }}</a><br> <a href="{{ route('accounts.show', [account.account_id]) }}">{{ account.name }}</a><br>
{% endfor %} {% endfor %}
</td> </td>
</tr> </tr>
@@ -58,7 +58,7 @@
<tr> <tr>
<td> <td>
{{ 'saved_so_far'|_ }} {{ 'saved_so_far'|_ }}
(<a href="{{ route('accounts.show', account.id) }}">{{ account.name }}</a>) (<a href="{{ route('accounts.show', account.account_id) }}">{{ account.name }}</a>)
</td> </td>
<td> <td>
{{ formatAmountBySymbol(account.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }} {{ formatAmountBySymbol(account.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }}

View File

@@ -101,7 +101,7 @@
</div> </div>
{# conversion back to primary currency #} {# conversion back to primary currency #}
{% if FireflyConfig.get('enable_exchange_rates', config('cer.enabled')) %} {% if fireflyiiiconfig('enable_exchange_rates', true) %}
<div class="preferences-box"> <div class="preferences-box">
<h3>{{ 'pref_convert_to_primary'|_ }}</h3> <h3>{{ 'pref_convert_to_primary'|_ }}</h3>
<p class="text-info"> <p class="text-info">
@@ -110,6 +110,14 @@
{{ ExpandedForm.checkbox('convertToPrimary','1',convertToPrimary,{ 'label' : 'pref_convert_primary_help'|_ }) }} {{ ExpandedForm.checkbox('convertToPrimary','1',convertToPrimary,{ 'label' : 'pref_convert_primary_help'|_ }) }}
</div> </div>
{% endif %} {% endif %}
{# conversion back to primary currency #}
<div class="preferences-box">
<h3>{{ 'pref_anonymous'|_ }}</h3>
<p class="text-info">
{{ 'pref_anonymous_help'|_ }}
</p>
{{ ExpandedForm.checkbox('anonymous','1',anonymous,{ 'label' : 'pref_anonymous_label'|_ }) }}
</div>
</div> </div>
{# general settings column B #} {# general settings column B #}

View File

@@ -20,7 +20,7 @@
<div class="form-group"> <div class="form-group">
<label for="query" class="col-sm-1 control-label">{{ 'search_query'|_ }}</label> <label for="query" class="col-sm-1 control-label">{{ 'search_query'|_ }}</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input autocomplete="off" maxlength="255" type="text" name="search" id="query" value="{{ fullQuery }}" class="form-control" spellcheck="false" <input autocomplete="off" type="text" name="search" id="query" value="{{ fullQuery }}" class="form-control" spellcheck="false"
placeholder="{{ fullQuery }}"> placeholder="{{ fullQuery }}">
</div> </div>
</div> </div>