diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index e8d67ba02f..4967d366a8 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -1256,23 +1256,24 @@ }, { "name": "symfony/console", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -1329,7 +1330,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.6" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -1345,7 +1346,7 @@ "type": "tidelift" } ], - "time": "2025-04-07T19:09:28+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1416,16 +1417,16 @@ }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { @@ -1476,7 +1477,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" }, "funding": [ { @@ -1492,7 +1493,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-04-22T09:11:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -1572,7 +1573,7 @@ }, { "name": "symfony/filesystem", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -1618,7 +1619,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.0" + "source": "https://github.com/symfony/filesystem/tree/v7.3.0" }, "funding": [ { @@ -1638,16 +1639,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { @@ -1682,7 +1683,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -1698,20 +1699,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", "shasum": "" }, "require": { @@ -1749,7 +1750,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" }, "funding": [ { @@ -1765,7 +1766,7 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-04-04T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2244,16 +2245,16 @@ }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -2285,7 +2286,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -2301,7 +2302,7 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/service-contracts", @@ -2388,7 +2389,7 @@ }, { "name": "symfony/stopwatch", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", @@ -2430,7 +2431,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v7.2.4" + "source": "https://github.com/symfony/stopwatch/tree/v7.3.0" }, "funding": [ { @@ -2450,16 +2451,16 @@ }, { "name": "symfony/string", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { @@ -2517,7 +2518,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.6" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -2533,7 +2534,7 @@ "type": "tidelift" } ], - "time": "2025-04-20T20:18:16+00:00" + "time": "2025-04-20T20:19:01+00:00" } ], "packages-dev": [], diff --git a/.ci/rector.php b/.ci/rector.php index 6e98485438..1a6971352b 100644 --- a/.ci/rector.php +++ b/.ci/rector.php @@ -25,10 +25,17 @@ declare(strict_types=1); use Rector\Config\RectorConfig; use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector; +use Rector\Transform\Rector\String_\StringToClassConstantRector; +use RectorLaravel\Set\LaravelLevelSetList; + return RectorConfig::configure() ->withSkip([ ChangeOrIfContinueToMultiContinueRector::class, + StringToClassConstantRector::class => [ + __DIR__ . '/../app/Http/Controllers/Auth/LoginController.php', + ], + __DIR__.'/../bootstrap/cache/*' ]) ->withPaths([ __DIR__ . '/../app', @@ -39,6 +46,12 @@ return RectorConfig::configure() __DIR__ . '/../routes', __DIR__ . '/../tests', ]) + ->withSets([ + LaravelLevelSetList::UP_TO_LARAVEL_120, + ]) +// ->withConfiguredRule(ReplaceServiceContainerCallArgRector::class, [ +// new ReplaceServiceContainerCallArg('log', new ClassConstFetch(new Name('Illuminate\Support\Facades\Log'), 'class')), +// ]) // uncomment to reach your current PHP version ->withPhpSets() ->withPreparedSets( diff --git a/.ci/rector.sh b/.ci/rector.sh index 3bd4f802b9..6b2d4b0e13 100755 --- a/.ci/rector.sh +++ b/.ci/rector.sh @@ -25,4 +25,12 @@ SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +echo $1 + +if [ "$1" == "--dry-run" ]; then + echo "Running rector in dry run." + $SCRIPT_DIR/../vendor/bin/rector --config $SCRIPT_DIR/rector.php --dry-run + exit $? +fi + $SCRIPT_DIR/../vendor/bin/rector --config $SCRIPT_DIR/rector.php diff --git a/app/Api/V1/Controllers/Chart/AccountController.php b/app/Api/V1/Controllers/Chart/AccountController.php index dcd85072b9..9ac5cfa305 100644 --- a/app/Api/V1/Controllers/Chart/AccountController.php +++ b/app/Api/V1/Controllers/Chart/AccountController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Chart; +use FireflyIII\Exceptions\ValidationException; use FireflyIII\Models\TransactionCurrency; use Carbon\Carbon; use FireflyIII\Api\V1\Controllers\Controller; @@ -35,6 +36,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Preference; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\Chart\ChartData; +use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Http\Api\ApiSupport; use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter; @@ -139,7 +141,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/charts/getChartAccountOverview * - * @throws FireflyException + * @throws ValidationException */ public function overview(DateRequest $request): JsonResponse { @@ -160,7 +162,7 @@ class AccountController extends Controller $defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); /** @var Preference $frontpage */ - $frontpage = app('preferences')->get('frontpageAccounts', $defaultSet); + Preferences::get('frontpageAccounts', $defaultSet); if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) { $frontpage->data = $defaultSet; diff --git a/app/Api/V1/Controllers/Chart/BudgetController.php b/app/Api/V1/Controllers/Chart/BudgetController.php index 61315e2b59..c8848c8565 100644 --- a/app/Api/V1/Controllers/Chart/BudgetController.php +++ b/app/Api/V1/Controllers/Chart/BudgetController.php @@ -212,7 +212,7 @@ class BudgetController extends Controller */ private function budgetLimits(Budget $budget, Collection $limits): array { - app('log')->debug(sprintf('Now in budgetLimits(#%d)', $budget->id)); + Log::debug(sprintf('Now in budgetLimits(#%d)', $budget->id)); $data = []; /** @var BudgetLimit $limit */ @@ -233,16 +233,13 @@ class BudgetController extends Controller $end->endOfDay(); $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget])); $limitCurrencyId = $limit->transaction_currency_id; - $filtered = []; /** @var array $entry */ - foreach ($spent as $currencyId => $entry) { - // only spent the entry where the entry's currency matches the budget limit's currency - // so $filtered will only have 1 or 0 entries - if ($entry['currency_id'] === $limitCurrencyId) { - $filtered[$currencyId] = $entry; - } - } + // only spent the entry where the entry's currency matches the budget limit's currency + // so $filtered will only have 1 or 0 entries + $filtered = array_filter($spent, function ($entry) use ($limitCurrencyId) { + return $entry['currency_id'] === $limitCurrencyId; + }); $result = $this->processExpenses($budget->id, $filtered, $limit->start_date, $end); if (1 === count($result)) { $compare = bccomp($limit->amount, (string) app('steam')->positive($result[$limitCurrencyId]['spent'])); diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php index 2566ddbe58..13c06b5972 100644 --- a/app/Api/V1/Controllers/Controller.php +++ b/app/Api/V1/Controllers/Controller.php @@ -40,6 +40,7 @@ use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Routing\Controller as BaseController; +use Illuminate\Support\Facades\Log; use League\Fractal\Manager; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; @@ -123,10 +124,9 @@ abstract class Controller extends BaseController try { $date = request()->query->get($field); } catch (BadRequestException $e) { - app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); - $value = null; + Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); } $obj = null; if (null !== $date) { @@ -134,7 +134,7 @@ abstract class Controller extends BaseController $obj = Carbon::parse((string) $date); } catch (InvalidFormatException $e) { // don't care - app('log')->warning( + Log::warning( sprintf( 'Ignored invalid date "%s" in API controller parameter check: %s', substr((string) $date, 0, 20), @@ -152,9 +152,9 @@ abstract class Controller extends BaseController try { $value = request()->query->get($integer); } catch (BadRequestException $e) { - app('log')->error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer)); - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer)); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $value = null; } if (null !== $value) { @@ -192,9 +192,9 @@ abstract class Controller extends BaseController try { $param = (string) request()->query->get('sort'); } catch (BadRequestException $e) { - app('log')->error('Request field "sort" contains a non-scalar value. Value set to NULL.'); - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.'); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $param = ''; } if ('' === $param) { diff --git a/app/Api/V1/Controllers/Data/DestroyController.php b/app/Api/V1/Controllers/Data/DestroyController.php index c83e18d079..b2ed17a568 100644 --- a/app/Api/V1/Controllers/Data/DestroyController.php +++ b/app/Api/V1/Controllers/Data/DestroyController.php @@ -64,7 +64,7 @@ class DestroyController extends Controller public function destroy(DestroyRequest $request): JsonResponse { $objects = $request->getObjects(); - $this->unused = $request->boolean('unused', false); + $this->unused = $request->boolean('unused'); $allExceptAssets = [AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::REVENUE->value]; $all = [AccountTypeEnum::ASSET->value, AccountTypeEnum::BENEFICIARY->value, AccountTypeEnum::CASH->value, AccountTypeEnum::CREDITCARD->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::DEFAULT->value, AccountTypeEnum::EXPENSE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::LIABILITY_CREDIT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::RECONCILIATION->value]; @@ -176,14 +176,14 @@ class DestroyController extends Controller foreach ($collection as $account) { $count = $account->transactions()->count(); if (true === $this->unused && 0 === $count) { - app('log')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name)); + Log::info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name)); Log::channel('audit')->info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name)); $service->destroy($account, null); continue; } if (false === $this->unused) { - app('log')->info(sprintf('Deleting account #%d "%s"', $account->id, $account->name)); + Log::info(sprintf('Deleting account #%d "%s"', $account->id, $account->name)); Log::channel('audit')->warning(sprintf('Deleted account #%d "%s"', $account->id, $account->name)); $service->destroy($account, null); } diff --git a/app/Api/V1/Controllers/Data/Export/ExportController.php b/app/Api/V1/Controllers/Data/Export/ExportController.php index ac316e9930..2b847226c2 100644 --- a/app/Api/V1/Controllers/Data/Export/ExportController.php +++ b/app/Api/V1/Controllers/Data/Export/ExportController.php @@ -29,6 +29,7 @@ use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Support\Export\ExportDataGenerator; use Illuminate\Http\Response as LaravelResponse; +use Safe\Exceptions\DatetimeException; use function Safe\date; @@ -72,6 +73,7 @@ class ExportController extends Controller /** * @throws FireflyException + * @throws DatetimeException */ private function returnExport(string $key): LaravelResponse { diff --git a/app/Api/V1/Controllers/Models/Account/UpdateController.php b/app/Api/V1/Controllers/Models/Account/UpdateController.php index e30f53d63f..40dc574663 100644 --- a/app/Api/V1/Controllers/Models/Account/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Account/UpdateController.php @@ -32,6 +32,7 @@ use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Transformers\AccountTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; use League\Fractal\Resource\Item; /** @@ -67,7 +68,7 @@ class UpdateController extends Controller */ public function update(UpdateRequest $request, Account $account): JsonResponse { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $data = $request->getUpdateData(); $data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type); $account = $this->repository->update($account, $data); diff --git a/app/Api/V1/Controllers/Models/Attachment/StoreController.php b/app/Api/V1/Controllers/Models/Attachment/StoreController.php index a80856b14c..a070ff8c5d 100644 --- a/app/Api/V1/Controllers/Models/Attachment/StoreController.php +++ b/app/Api/V1/Controllers/Models/Attachment/StoreController.php @@ -80,7 +80,7 @@ class StoreController extends Controller throw new NotFoundHttpException(); } - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $data = $request->getAll(); $attachment = $this->repository->store($data); $manager = $this->getManager(); @@ -109,13 +109,13 @@ class StoreController extends Controller $helper = app(AttachmentHelperInterface::class); $body = $request->getContent(); if ('' === $body) { - app('log')->error('Body of attachment is empty.'); + Log::error('Body of attachment is empty.'); return response()->json([], 422); } $result = $helper->saveAttachmentFromApi($attachment, $body); if (false === $result) { - app('log')->error('Could not save attachment from API.'); + Log::error('Could not save attachment from API.'); return response()->json([], 422); } diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php b/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php index 5da7d3050c..6f899b19ce 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php @@ -69,7 +69,6 @@ class StoreController extends Controller $data = $request->getAll(); $data['start_date'] = $data['start']; $data['end_date'] = $data['end']; - $data['notes'] = $data['notes']; $data['budget_id'] = $budget->id; $budgetLimit = $this->blRepository->store($data); diff --git a/app/Api/V1/Controllers/Models/Transaction/DestroyController.php b/app/Api/V1/Controllers/Models/Transaction/DestroyController.php index 00ac92462a..f77339b188 100644 --- a/app/Api/V1/Controllers/Models/Transaction/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Transaction/DestroyController.php @@ -34,6 +34,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; /** * Class DestroyController @@ -73,7 +74,7 @@ class DestroyController extends Controller */ public function destroy(TransactionGroup $transactionGroup): JsonResponse { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); // grab asset account(s) from group: $accounts = []; @@ -95,7 +96,7 @@ class DestroyController extends Controller /** @var Account $account */ foreach ($accounts as $account) { - app('log')->debug(sprintf('Now going to trigger updated account event for account #%d', $account->id)); + Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id)); event(new UpdatedAccount($account)); } diff --git a/app/Api/V1/Controllers/Models/Transaction/StoreController.php b/app/Api/V1/Controllers/Models/Transaction/StoreController.php index 4491656f51..37acce2eb6 100644 --- a/app/Api/V1/Controllers/Models/Transaction/StoreController.php +++ b/app/Api/V1/Controllers/Models/Transaction/StoreController.php @@ -84,7 +84,7 @@ class StoreController extends Controller */ public function store(StoreRequest $request): JsonResponse { - app('log')->debug('Now in API StoreController::store()'); + Log::debug('Now in API StoreController::store()'); $data = $request->getAll(); $data['user'] = auth()->user(); $data['user_group'] = $this->userGroup; @@ -95,13 +95,13 @@ class StoreController extends Controller try { $transactionGroup = $this->groupRepository->store($data); } catch (DuplicateTransactionException $e) { - app('log')->warning('Caught a duplicate transaction. Return error message.'); + Log::warning('Caught a duplicate transaction. Return error message.'); $validator = Validator::make(['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction()]); throw new ValidationException($validator); } catch (FireflyException $e) { - app('log')->warning('Caught an exception. Return error message.'); - app('log')->error($e->getMessage()); + Log::warning('Caught an exception. Return error message.'); + Log::error($e->getMessage()); $message = sprintf('Internal exception: %s', $e->getMessage()); $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); diff --git a/app/Api/V1/Controllers/Models/Transaction/UpdateController.php b/app/Api/V1/Controllers/Models/Transaction/UpdateController.php index c309525526..6db7503671 100644 --- a/app/Api/V1/Controllers/Models/Transaction/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Transaction/UpdateController.php @@ -34,6 +34,7 @@ use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; use League\Fractal\Resource\Item; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -71,22 +72,25 @@ class UpdateController extends Controller */ public function update(UpdateRequest $request, TransactionGroup $transactionGroup): JsonResponse { - app('log')->debug('Now in update routine for transaction group'); - $data = $request->getAll(); - $transactionGroup = $this->groupRepository->update($transactionGroup, $data); - $manager = $this->getManager(); + Log::debug('Now in update routine for transaction group'); + $data = $request->getAll(); + $oldHash = $this->groupRepository->getCompareHash($transactionGroup); + $transactionGroup = $this->groupRepository->update($transactionGroup, $data); + $newHash = $this->groupRepository->getCompareHash($transactionGroup); + $manager = $this->getManager(); app('preferences')->mark(); - $applyRules = $data['apply_rules'] ?? true; - $fireWebhooks = $data['fire_webhooks'] ?? true; - event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks)); + $applyRules = $data['apply_rules'] ?? true; + $fireWebhooks = $data['fire_webhooks'] ?? true; + $runRecalculations = $oldHash !== $newHash; + event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, $runRecalculations)); /** @var User $admin */ - $admin = auth()->user(); + $admin = auth()->user(); // use new group collector: /** @var GroupCollectorInterface $collector */ - $collector = app(GroupCollectorInterface::class); + $collector = app(GroupCollectorInterface::class); $collector ->setUser($admin) // filter on transaction group. @@ -95,20 +99,20 @@ class UpdateController extends Controller ->withAPIInformation() ; - $selectedGroup = $collector->getGroups()->first(); + $selectedGroup = $collector->getGroups()->first(); if (null === $selectedGroup) { throw new NotFoundHttpException(); } // enrich - $enrichment = new TransactionGroupEnrichment(); + $enrichment = new TransactionGroupEnrichment(); $enrichment->setUser($admin); - $selectedGroup = $enrichment->enrichSingle($selectedGroup); + $selectedGroup = $enrichment->enrichSingle($selectedGroup); /** @var TransactionGroupTransformer $transformer */ - $transformer = app(TransactionGroupTransformer::class); + $transformer = app(TransactionGroupTransformer::class); $transformer->setParameters($this->parameters); - $resource = new Item($selectedGroup, $transformer, 'transactions'); + $resource = new Item($selectedGroup, $transformer, 'transactions'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php index e22212bd46..b7c7e69a34 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php @@ -32,6 +32,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Validation\ValidationException; /** * Class DestroyController @@ -65,6 +66,7 @@ class DestroyController extends Controller * Remove the specified resource from storage. * * @throws FireflyException + * @throws ValidationException */ public function destroy(TransactionCurrency $currency): JsonResponse { diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php index 20362f6e6d..b7052ccfb9 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php @@ -250,10 +250,8 @@ class ListController extends Controller $collection = $unfiltered->filter( static function (Recurrence $recurrence) use ($currency) { // @phpstan-ignore-line /** @var RecurrenceTransaction $transaction */ - foreach ($recurrence->recurrenceTransactions as $transaction) { - if ($transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id) { - return $recurrence; - } + if (array_any($recurrence->recurrenceTransactions, fn ($transaction) => $transaction->transaction_currency_id === $currency->id || $transaction->foreign_currency_id === $currency->id)) { + return $recurrence; } return null; @@ -297,10 +295,8 @@ class ListController extends Controller $collection = $unfiltered->filter( static function (Rule $rule) use ($currency) { // @phpstan-ignore-line /** @var RuleTrigger $trigger */ - foreach ($rule->ruleTriggers as $trigger) { - if ('currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value) { - return $rule; - } + if (array_any($rule->ruleTriggers, fn ($trigger) => 'currency_is' === $trigger->trigger_type && $currency->name === $trigger->trigger_value)) { + return $rule; } return null; diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php index e9aef4aa2a..7e534e3993 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php @@ -27,13 +27,13 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionLinkType; use Illuminate\Support\Facades\Validator; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Models\TransactionLinkType\StoreRequest; -use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\LinkTypeTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Validation\ValidationException; use League\Fractal\Resource\Item; /** @@ -71,7 +71,7 @@ class StoreController extends Controller * * Store new object. * - * @throws FireflyException + * @throws ValidationException */ public function store(StoreRequest $request): JsonResponse { diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php index 9d392ab805..2b43fa81df 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php @@ -35,6 +35,7 @@ use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\LinkTypeTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; +use Illuminate\Validation\ValidationException; use League\Fractal\Resource\Item; /** @@ -73,6 +74,7 @@ class UpdateController extends Controller * Update object. * * @throws FireflyException + * @throws ValidationException */ public function update(UpdateRequest $request, LinkType $linkType): JsonResponse { diff --git a/app/Api/V1/Controllers/Models/UserGroup/UpdateController.php b/app/Api/V1/Controllers/Models/UserGroup/UpdateController.php index 8cdfea9715..e1a9e517e5 100644 --- a/app/Api/V1/Controllers/Models/UserGroup/UpdateController.php +++ b/app/Api/V1/Controllers/Models/UserGroup/UpdateController.php @@ -30,6 +30,7 @@ use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\Transformers\UserGroupTransformer; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; class UpdateController extends Controller { @@ -54,7 +55,7 @@ class UpdateController extends Controller public function update(UpdateRequest $request, UserGroup $userGroup): JsonResponse { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $data = $request->getData(); $userGroup = $this->repository->update($userGroup, $data); $userGroup->refresh(); diff --git a/app/Api/V1/Controllers/Search/AccountController.php b/app/Api/V1/Controllers/Search/AccountController.php index 71e1e02a43..634c666db3 100644 --- a/app/Api/V1/Controllers/Search/AccountController.php +++ b/app/Api/V1/Controllers/Search/AccountController.php @@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Facades\Log; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; @@ -71,7 +72,7 @@ class AccountController extends Controller if ('' === $query || !in_array($field, $this->validFields, true)) { return response(null, 422); } - app('log')->debug(sprintf('Now in account search("%s", "%s")', $field, $query)); + Log::debug(sprintf('Now in account search("%s", "%s")', $field, $query)); $types = $this->mapAccountTypes($type); /** @var AccountSearch $search */ diff --git a/app/Api/V1/Controllers/Summary/BasicController.php b/app/Api/V1/Controllers/Summary/BasicController.php index 1878812a27..02b7bc0405 100644 --- a/app/Api/V1/Controllers/Summary/BasicController.php +++ b/app/Api/V1/Controllers/Summary/BasicController.php @@ -130,8 +130,6 @@ class BasicController extends Controller $convertToNative = Amount::convertToNative(); $default = Amount::getNativeCurrency(); // prep some arrays: - $incomes = []; - $expenses = []; $sums = []; $return = []; $currencies = [ diff --git a/app/Api/V1/Controllers/System/ConfigurationController.php b/app/Api/V1/Controllers/System/ConfigurationController.php index 281c0712f8..5b0014ee84 100644 --- a/app/Api/V1/Controllers/System/ConfigurationController.php +++ b/app/Api/V1/Controllers/System/ConfigurationController.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\System; +use FireflyIII\Support\Facades\FireflyConfig; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\System\UpdateRequest; @@ -31,6 +33,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Support\Binder\EitherConfigKey; use Illuminate\Http\JsonResponse; +use Illuminate\Validation\ValidationException; /** * Class ConfigurationController @@ -65,8 +68,8 @@ class ConfigurationController extends Controller try { $dynamicData = $this->getDynamicConfiguration(); } catch (FireflyException $e) { - app('log')->error($e->getMessage()); - app('log')->error($e->getTraceAsString()); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException('200030: Could not load config variables.', 0, $e); } @@ -92,13 +95,15 @@ class ConfigurationController extends Controller /** * Get all config values. + * + * @throws FireflyException */ private function getDynamicConfiguration(): array { - $isDemoSite = app('fireflyconfig')->get('is_demo_site'); - $updateCheck = app('fireflyconfig')->get('permission_update_check'); - $lastCheck = app('fireflyconfig')->get('last_update_check'); - $singleUser = app('fireflyconfig')->get('single_user_mode'); + $isDemoSite = FireflyConfig::get('is_demo_site'); + $updateCheck = FireflyConfig::get('permission_update_check'); + $lastCheck = FireflyConfig::get('last_update_check'); + $singleUser = FireflyConfig::get('single_user_mode'); return [ 'is_demo_site' => $isDemoSite?->data, @@ -153,6 +158,7 @@ class ConfigurationController extends Controller * Update the configuration. * * @throws FireflyException + * @throws ValidationException */ public function update(UpdateRequest $request, string $name): JsonResponse { @@ -164,7 +170,7 @@ class ConfigurationController extends Controller $data = $request->getAll(); $shortName = str_replace('configuration.', '', $name); - app('fireflyconfig')->set($shortName, $data['value']); + FireflyConfig::set($shortName, $data['value']); // get updated config: $newConfig = $this->getDynamicConfiguration(); diff --git a/app/Api/V1/Controllers/System/CronController.php b/app/Api/V1/Controllers/System/CronController.php index f51feb165c..359237b16c 100644 --- a/app/Api/V1/Controllers/System/CronController.php +++ b/app/Api/V1/Controllers/System/CronController.php @@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\System\CronRequest; use FireflyIII\Support\Http\Controllers\CronRunner; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; /** * Class CronController @@ -44,8 +45,8 @@ class CronController extends Controller { $config = $request->getAll(); - app('log')->debug(sprintf('Now in %s', __METHOD__)); - app('log')->debug(sprintf('Date is %s', $config['date']->toIsoString())); + Log::debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Date is %s', $config['date']->toIsoString())); $return = []; $return['recurring_transactions'] = $this->runRecurring($config['force'], $config['date']); $return['auto_budgets'] = $this->runAutoBudget($config['force'], $config['date']); diff --git a/app/Api/V1/Controllers/System/UserController.php b/app/Api/V1/Controllers/System/UserController.php index b650b2d3c2..0928c041a9 100644 --- a/app/Api/V1/Controllers/System/UserController.php +++ b/app/Api/V1/Controllers/System/UserController.php @@ -33,6 +33,7 @@ use FireflyIII\Transformers\UserTransformer; use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Facades\Log; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; @@ -174,7 +175,7 @@ class UserController extends Controller // can only update 'blocked' when user is admin. if (!$this->repository->hasRole(auth()->user(), 'owner')) { - app('log')->debug('Quietly drop fields "blocked" and "blocked_code" from request.'); + Log::debug('Quietly drop fields "blocked" and "blocked_code" from request.'); unset($data['blocked'], $data['blocked_code']); } diff --git a/app/Api/V1/Controllers/Webhook/ShowController.php b/app/Api/V1/Controllers/Webhook/ShowController.php index bdedcd17d9..6d0246631c 100644 --- a/app/Api/V1/Controllers/Webhook/ShowController.php +++ b/app/Api/V1/Controllers/Webhook/ShowController.php @@ -138,7 +138,7 @@ class ShowController extends Controller throw new NotFoundHttpException('Webhooks are not enabled.'); } - app('log')->debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id)); + Log::debug(sprintf('Now in triggerTransaction(%d, %d)', $webhook->id, $group->id)); Log::channel('audit')->info(sprintf('User triggers webhook #%d on transaction group #%d.', $webhook->id, $group->id)); /** @var MessageGeneratorInterface $engine */ @@ -155,7 +155,7 @@ class ShowController extends Controller $engine->generateMessages(); // trigger event to send them: - app('log')->debug('send event RequestedSendWebhookMessages'); + Log::debug('send event RequestedSendWebhookMessages'); event(new RequestedSendWebhookMessages()); return response()->json([], 204); diff --git a/app/Api/V1/Controllers/Webhook/SubmitController.php b/app/Api/V1/Controllers/Webhook/SubmitController.php index bdec19c8c5..034bea04b6 100644 --- a/app/Api/V1/Controllers/Webhook/SubmitController.php +++ b/app/Api/V1/Controllers/Webhook/SubmitController.php @@ -76,6 +76,6 @@ class SubmitController extends Controller SendWebhookMessage::dispatch($message)->afterResponse(); } - return response()->json([]); + return response()->json(); } } diff --git a/app/Api/V1/Requests/Chart/ChartRequest.php b/app/Api/V1/Requests/Chart/ChartRequest.php index 7d3f0e4a94..58ade4f0c3 100644 --- a/app/Api/V1/Requests/Chart/ChartRequest.php +++ b/app/Api/V1/Requests/Chart/ChartRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Chart; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ChartRequest diff --git a/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php b/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php index 3ada80f591..8731e354aa 100644 --- a/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php +++ b/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php @@ -24,12 +24,12 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Data\Bulk; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class MoveTransactionsRequest diff --git a/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php b/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php index da2bfb3d7c..b02ee21149 100644 --- a/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php +++ b/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Data\Bulk; +use Illuminate\Contracts\Validation\Validator; use JsonException; use FireflyIII\Enums\ClauseType; use FireflyIII\Rules\IsValidBulkClause; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\Api\Data\Bulk\ValidatesBulkTransactionQuery; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; use function Safe\json_decode; @@ -54,8 +54,8 @@ class TransactionRequest extends FormRequest 'query' => json_decode($this->get('query'), true, 8, JSON_THROW_ON_ERROR), ]; } catch (JsonException $e) { - // dont really care. the validation should catch invalid json. - app('log')->error($e->getMessage()); + // don't really care. the validation should catch invalid json. + Log::error($e->getMessage()); } return $data; diff --git a/app/Api/V1/Requests/Models/Account/UpdateRequest.php b/app/Api/V1/Requests/Models/Account/UpdateRequest.php index dbe30eab1b..5fb31b6fc8 100644 --- a/app/Api/V1/Requests/Models/Account/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Account/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Account; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Account; use FireflyIII\Models\Location; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -35,7 +36,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/AvailableBudget/Request.php b/app/Api/V1/Requests/Models/AvailableBudget/Request.php index ccf7e4d030..ad36cdb728 100644 --- a/app/Api/V1/Requests/Models/AvailableBudget/Request.php +++ b/app/Api/V1/Requests/Models/AvailableBudget/Request.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\AvailableBudget; +use Illuminate\Contracts\Validation\Validator; use Carbon\Carbon; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class Request diff --git a/app/Api/V1/Requests/Models/Bill/StoreRequest.php b/app/Api/V1/Requests/Models/Bill/StoreRequest.php index e773942ca3..727eb9afed 100644 --- a/app/Api/V1/Requests/Models/Bill/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Bill/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Bill; +use Illuminate\Contracts\Validation\Validator; use ValueError; use TypeError; use FireflyIII\Rules\IsBoolean; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest @@ -47,7 +47,7 @@ class StoreRequest extends FormRequest */ public function getAll(): array { - app('log')->debug('Raw fields in Bill StoreRequest', $this->all()); + Log::debug('Raw fields in Bill StoreRequest', $this->all()); $fields = [ 'name' => ['name', 'convertString'], 'amount_min' => ['amount_min', 'convertString'], @@ -128,7 +128,6 @@ class StoreRequest extends FormRequest $failed = $validator->fails(); } catch (TypeError $e) { Log::error($e->getMessage()); - $failed = false; } if ($failed) { Log::channel('audit')->error(sprintf('Validation errors in %s', self::class), $validator->errors()->toArray()); diff --git a/app/Api/V1/Requests/Models/Bill/UpdateRequest.php b/app/Api/V1/Requests/Models/Bill/UpdateRequest.php index 5931fc7bd2..4b69d4d6ee 100644 --- a/app/Api/V1/Requests/Models/Bill/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Bill/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Bill; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Bill; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidPositiveAmount; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/Budget/StoreRequest.php b/app/Api/V1/Requests/Models/Budget/StoreRequest.php index f6a96a6941..43f44c7720 100644 --- a/app/Api/V1/Requests/Models/Budget/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Budget/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Budget; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest diff --git a/app/Api/V1/Requests/Models/Budget/UpdateRequest.php b/app/Api/V1/Requests/Models/Budget/UpdateRequest.php index 1319df36e6..ed1d119e93 100644 --- a/app/Api/V1/Requests/Models/Budget/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Budget/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Budget; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Budget; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidPositiveAmount; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php index 1fb3d53ca9..c1ed04a9a4 100644 --- a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\BudgetLimit; +use Illuminate\Contracts\Validation\Validator; use Carbon\Carbon; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php index e7ae890499..f99939be28 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\PiggyBank; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest diff --git a/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php index f8f5091ed0..b9f736f74f 100644 --- a/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Recurrence; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidPositiveAmount; @@ -35,7 +36,6 @@ use FireflyIII\Validation\RecurrenceValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest @@ -76,7 +76,7 @@ class StoreRequest extends FormRequest /** * Returns the transaction data as it is found in the submitted data. It's a complex method according to code - * standards but it just has a lot of ??-statements because of the fields that may or may not exist. + * standards, but it just has a lot of ??-statements because of the fields that may or may not exist. */ private function getTransactionData(): array { diff --git a/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php b/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php index 5449a5edda..bd8a26f1c2 100644 --- a/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Recurrence; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Recurrence; use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\IsBoolean; @@ -36,7 +37,6 @@ use FireflyIII\Validation\RecurrenceValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest @@ -122,7 +122,7 @@ class UpdateRequest extends FormRequest /** * Returns the transaction data as it is found in the submitted data. It's a complex method according to code - * standards but it just has a lot of ??-statements because of the fields that may or may not exist. + * standards, but it just has a lot of ??-statements because of the fields that may or may not exist. */ private function getTransactionData(): array { diff --git a/app/Api/V1/Requests/Models/Rule/StoreRequest.php b/app/Api/V1/Requests/Models/Rule/StoreRequest.php index dd65d648a0..496dbc550a 100644 --- a/app/Api/V1/Requests/Models/Rule/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Rule/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Rule; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidActionExpression; use FireflyIII\Support\Request\ChecksLogin; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest diff --git a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php index 13a8a97676..8b58fbd3d8 100644 --- a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Rule; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Rule; use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsValidActionExpression; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/Transaction/StoreRequest.php b/app/Api/V1/Requests/Models/Transaction/StoreRequest.php index c9a99f88eb..4c7cb3d43d 100644 --- a/app/Api/V1/Requests/Models/Transaction/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Transaction/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Transaction; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Location; use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\IsBoolean; @@ -39,7 +40,6 @@ use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest @@ -58,7 +58,7 @@ class StoreRequest extends FormRequest */ public function getAll(): array { - app('log')->debug('get all data in TransactionStoreRequest'); + Log::debug('get all data in TransactionStoreRequest'); return [ 'group_title' => $this->convertString('group_title'), @@ -175,7 +175,7 @@ class StoreRequest extends FormRequest */ public function rules(): array { - app('log')->debug('Collect rules of TransactionStoreRequest'); + Log::debug('Collect rules of TransactionStoreRequest'); $validProtocols = config('firefly.valid_url_protocols'); $locationRules = Location::requestRules([]); @@ -276,9 +276,9 @@ class StoreRequest extends FormRequest $this->validateTransactionArray($validator); // must submit at least one transaction. - app('log')->debug('Now going to validateOneTransaction'); + Log::debug('Now going to validateOneTransaction'); $this->validateOneTransaction($validator); - app('log')->debug('Now done with validateOneTransaction'); + Log::debug('Now done with validateOneTransaction'); // all journals must have a description $this->validateDescriptions($validator); diff --git a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php index f53b5ba6df..1aa8af303d 100644 --- a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Transaction; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionGroup; use FireflyIII\Rules\BelongsUser; @@ -37,7 +38,6 @@ use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest @@ -183,7 +183,7 @@ class UpdateRequest extends FormRequest foreach ($this->dateFields as $fieldName) { app('log')->debug(sprintf('Now at date field %s', $fieldName)); if (array_key_exists($fieldName, $transaction)) { - app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); + Log::debug(sprintf('New value: "%s"', $transaction[$fieldName])); $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); } } diff --git a/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php b/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php index 638bda8306..b93334289d 100644 --- a/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\TransactionLink; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use FireflyIII\Support\Request\ChecksLogin; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\User; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest diff --git a/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php b/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php index 0ab51bccd0..ce62f5a87c 100644 --- a/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\TransactionLink; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest diff --git a/app/Api/V1/Requests/Models/UserGroup/UpdateRequest.php b/app/Api/V1/Requests/Models/UserGroup/UpdateRequest.php index fd238dcbf2..d14e47a982 100644 --- a/app/Api/V1/Requests/Models/UserGroup/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/UserGroup/UpdateRequest.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\UserGroup; -use FireflyIII\Models\UserGroup; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; @@ -53,9 +52,6 @@ class UpdateRequest extends FormRequest */ public function rules(): array { - /** @var UserGroup $userGroup */ - $userGroup = $this->route()->parameter('userGroup'); - return [ 'title' => ['required', 'min:1', 'max:255'], 'native_currency_id' => 'exists:transaction_currencies,id', diff --git a/app/Api/V1/Requests/System/UserUpdateRequest.php b/app/Api/V1/Requests/System/UserUpdateRequest.php index 553f8e54e4..d22090ba0b 100644 --- a/app/Api/V1/Requests/System/UserUpdateRequest.php +++ b/app/Api/V1/Requests/System/UserUpdateRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\System; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\User; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UserUpdateRequest diff --git a/app/Api/V2/Controllers/Controller.php b/app/Api/V2/Controllers/Controller.php index 0a2afcfac5..e9da840908 100644 --- a/app/Api/V2/Controllers/Controller.php +++ b/app/Api/V2/Controllers/Controller.php @@ -39,7 +39,6 @@ use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; use Symfony\Component\HttpFoundation\Exception\BadRequestException; use Symfony\Component\HttpFoundation\ParameterBag; @@ -82,7 +81,7 @@ class Controller extends BaseController try { $page = (int) request()->get('page'); - } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { + } catch (ContainerExceptionInterface) { $page = 1; } diff --git a/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php b/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php index 5272aa7a4d..b87ba89314 100644 --- a/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php +++ b/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php @@ -53,7 +53,7 @@ class ListController extends Controller */ public function index(): JsonResponse { - return response()->json([]); + return response()->json(); // throw new FireflyException('Needs refactoring, move to IndexController.'); // $pageSize = $this->parameters->get('limit'); // $dates = $request->getAll(); diff --git a/app/Api/V2/Controllers/Model/Transaction/UpdateController.php b/app/Api/V2/Controllers/Model/Transaction/UpdateController.php index 2304fcf93b..b27ade514f 100644 --- a/app/Api/V2/Controllers/Model/Transaction/UpdateController.php +++ b/app/Api/V2/Controllers/Model/Transaction/UpdateController.php @@ -70,7 +70,7 @@ class UpdateController extends Controller $applyRules = $data['apply_rules'] ?? true; $fireWebhooks = $data['fire_webhooks'] ?? true; - event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks)); + event(new UpdatedTransactionGroup($transactionGroup, $applyRules, $fireWebhooks, true)); app('preferences')->mark(); /** @var User $admin */ diff --git a/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php b/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php index aad0662430..7609a298a1 100644 --- a/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php +++ b/app/Api/V2/Controllers/Model/TransactionCurrency/IndexController.php @@ -31,6 +31,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Transformers\CurrencyTransformer; use Illuminate\Http\JsonResponse; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; class IndexController extends Controller { @@ -56,6 +57,7 @@ class IndexController extends Controller public function index(IndexRequest $request): JsonResponse { $settings = $request->getAll(); + $currencies = new Collection(); if (true === $settings['enabled']) { $currencies = $this->repository->get(); } diff --git a/app/Api/V2/Request/Chart/BalanceChartRequest.php b/app/Api/V2/Request/Chart/BalanceChartRequest.php index bdbb141b65..3220714cdb 100644 --- a/app/Api/V2/Request/Chart/BalanceChartRequest.php +++ b/app/Api/V2/Request/Chart/BalanceChartRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Chart; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BalanceChartRequest diff --git a/app/Api/V2/Request/Chart/ChartRequest.php b/app/Api/V2/Request/Chart/ChartRequest.php index 6ca32ea6e8..cecb7edc40 100644 --- a/app/Api/V2/Request/Chart/ChartRequest.php +++ b/app/Api/V2/Request/Chart/ChartRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Chart; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ChartRequest diff --git a/app/Api/V2/Request/Chart/DashboardChartRequest.php b/app/Api/V2/Request/Chart/DashboardChartRequest.php index 96f66e1095..6c4a3cdfa6 100644 --- a/app/Api/V2/Request/Chart/DashboardChartRequest.php +++ b/app/Api/V2/Request/Chart/DashboardChartRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Chart; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class DashboardChartRequest diff --git a/app/Api/V2/Request/Model/Transaction/StoreRequest.php b/app/Api/V2/Request/Model/Transaction/StoreRequest.php index 4e95b69e9f..18cc85d5a2 100644 --- a/app/Api/V2/Request/Model/Transaction/StoreRequest.php +++ b/app/Api/V2/Request/Model/Transaction/StoreRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Model\Transaction; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Models\UserGroup; use FireflyIII\Rules\BelongsUserGroup; @@ -40,7 +41,6 @@ use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class StoreRequest diff --git a/app/Api/V2/Request/Model/Transaction/UpdateRequest.php b/app/Api/V2/Request/Model/Transaction/UpdateRequest.php index 3aeda0e3c3..ea4727a1bc 100644 --- a/app/Api/V2/Request/Model/Transaction/UpdateRequest.php +++ b/app/Api/V2/Request/Model/Transaction/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V2\Request\Model\Transaction; +use Illuminate\Contracts\Validation\Validator; use Override; use FireflyIII\Api\V1\Requests\Models\AvailableBudget\Request; use FireflyIII\Exceptions\FireflyException; @@ -38,7 +39,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\GroupValidation; use FireflyIII\Validation\TransactionValidation; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UpdateRequest @@ -68,7 +68,7 @@ class UpdateRequest extends Request #[Override] public function getAll(): array { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $this->integerFields = ['order', 'currency_id', 'foreign_currency_id', 'transaction_journal_id', 'source_id', 'destination_id', 'budget_id', 'category_id', 'bill_id', 'recurrence_id']; $this->dateFields = ['date', 'interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date']; $this->textareaFields = ['notes']; @@ -101,7 +101,7 @@ class UpdateRequest extends Request */ private function getTransactionData(): array { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $return = []; /** @var null|array $transactions */ @@ -185,9 +185,9 @@ class UpdateRequest extends Request private function getDateData(array $current, array $transaction): array { foreach ($this->dateFields as $fieldName) { - app('log')->debug(sprintf('Now at date field %s', $fieldName)); + Log::debug(sprintf('Now at date field %s', $fieldName)); if (array_key_exists($fieldName, $transaction)) { - app('log')->debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); + Log::debug(sprintf('New value: "%s"', $transaction[$fieldName])); $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); } } @@ -252,7 +252,7 @@ class UpdateRequest extends Request #[Override] public function rules(): array { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); $validProtocols = config('firefly.valid_url_protocols'); return [ @@ -336,7 +336,7 @@ class UpdateRequest extends Request #[Override] public function withValidator(Validator $validator): void { - app('log')->debug('Now in withValidator'); + Log::debug('Now in withValidator'); /** @var TransactionGroup $transactionGroup */ $transactionGroup = $this->route()->parameter('userGroupTransaction'); diff --git a/app/Console/Commands/Correction/CorrectsGroupAccounts.php b/app/Console/Commands/Correction/CorrectsGroupAccounts.php index def997e955..39989cf164 100644 --- a/app/Console/Commands/Correction/CorrectsGroupAccounts.php +++ b/app/Console/Commands/Correction/CorrectsGroupAccounts.php @@ -58,7 +58,8 @@ class CorrectsGroupAccounts extends Command $handler = new UpdatedGroupEventHandler(); foreach ($groups as $groupId) { $group = TransactionGroup::find($groupId); - $event = new UpdatedTransactionGroup($group, true, true); + // TODO in theory the "unifyAccounts" method could lead to the need for run recalculations. + $event = new UpdatedTransactionGroup($group, true, true, false); $handler->unifyAccounts($event); } diff --git a/app/Console/Commands/Correction/CorrectsIbans.php b/app/Console/Commands/Correction/CorrectsIbans.php index d3f1705612..93062e1c8c 100644 --- a/app/Console/Commands/Correction/CorrectsIbans.php +++ b/app/Console/Commands/Correction/CorrectsIbans.php @@ -43,7 +43,7 @@ class CorrectsIbans extends Command */ public function handle(): int { - $accounts = Account::whereNotNull('iban')->get(); + $accounts = Account::with('accountMeta')->get(); $this->filterIbans($accounts); $this->countAndCorrectIbans($accounts); @@ -54,14 +54,26 @@ class CorrectsIbans extends Command { /** @var Account $account */ foreach ($accounts as $account) { - $iban = (string) $account->iban; - $newIban = app('steam')->filterSpaces($iban); + $iban = (string) $account->iban; + $newIban = app('steam')->filterSpaces($iban); if ('' !== $iban && $iban !== $newIban) { $account->iban = $newIban; $account->save(); $this->friendlyInfo(sprintf('Removed spaces from IBAN of account #%d', $account->id)); ++$this->count; } + // same for account number: + $accountNumber = $account->accountMeta->where('name', 'account_number')->first(); + if (null !== $accountNumber) { + $number = (string) $accountNumber->value; + $newNumber = app('steam')->filterSpaces($number); + if ('' !== $number && $number !== $newNumber) { + $accountNumber->value = $newNumber; + $accountNumber->save(); + $this->friendlyInfo(sprintf('Removed spaces from account number of account #%d', $account->id)); + ++$this->count; + } + } } } diff --git a/app/Console/Commands/Correction/CorrectsUnevenAmount.php b/app/Console/Commands/Correction/CorrectsUnevenAmount.php index 70b36705f0..30a6107fe1 100644 --- a/app/Console/Commands/Correction/CorrectsUnevenAmount.php +++ b/app/Console/Commands/Correction/CorrectsUnevenAmount.php @@ -30,6 +30,7 @@ use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Models\AccountBalanceCalculator; use Illuminate\Console\Command; use Illuminate\Support\Facades\DB; @@ -140,6 +141,7 @@ class CorrectsUnevenAmount extends Command /** @var stdClass $entry */ foreach ($journals as $entry) { $sum = (string) $entry->the_sum; + $sum = Steam::floatalize($sum); if (!is_numeric($sum) || '' === $sum // @phpstan-ignore-line || str_contains($sum, 'e') diff --git a/app/Console/Commands/Integrity/ReportsSums.php b/app/Console/Commands/Integrity/ReportsSums.php index 819754f819..3ebf1d7fc6 100644 --- a/app/Console/Commands/Integrity/ReportsSums.php +++ b/app/Console/Commands/Integrity/ReportsSums.php @@ -26,6 +26,7 @@ namespace FireflyIII\Console\Commands\Integrity; use FireflyIII\Console\Commands\ShowsFriendlyMessages; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Support\Facades\Steam; use FireflyIII\User; use Illuminate\Console\Command; @@ -60,6 +61,8 @@ class ReportsSums extends Command $foreign = (string) $user->transactions()->selectRaw('SUM(foreign_amount) as total')->value('total'); $sum = '' === $sum ? '0' : $sum; $foreign = '' === $foreign ? '0' : $foreign; + $sum = Steam::floatalize($sum); + $foreign = Steam::floatalize($foreign); $total = bcadd($sum, $foreign); if (0 !== bccomp($total, '0')) { diff --git a/app/Console/Commands/Upgrade/RepairsPostgresSequences.php b/app/Console/Commands/Upgrade/RepairsPostgresSequences.php index db3f2cfb84..b37f33afe8 100644 --- a/app/Console/Commands/Upgrade/RepairsPostgresSequences.php +++ b/app/Console/Commands/Upgrade/RepairsPostgresSequences.php @@ -1,7 +1,7 @@ account) { + // #10432 account has been deleted, delete piggy bank. + $piggyBank->delete(); + + return; + } $this->repository->setUser($piggyBank->account->user); $this->accountRepository->setUser($piggyBank->account->user); $repetition = $this->repository->getRepetition($piggyBank, true); diff --git a/app/Events/Model/PiggyBank/ChangedName.php b/app/Events/Model/PiggyBank/ChangedName.php new file mode 100644 index 0000000000..bed6b78f20 --- /dev/null +++ b/app/Events/Model/PiggyBank/ChangedName.php @@ -0,0 +1,16 @@ +accountMeta()->where('name', $field)->first(); // must not be an empty string: if ('' !== $value) { + if ('account_number' === $field) { + $value = Steam::filterSpaces($value); + $value = trim(str_replace([' ', "\t", "\n", "\r"], '', $value)); + } // if $data has field and $entry is null, create new one: if (null === $entry) { return $this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]); } + // if $data has field and $entry is not null, update $entry: $entry->data = $value; $entry->save(); diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index 519b56fbfd..eefd1436e5 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -46,9 +46,9 @@ class PiggyBankFactory { use CreatesObjectGroups; - public User $user; - private AccountRepositoryInterface $accountRepository; - private CurrencyRepositoryInterface $currencyRepository; + public User $user; + private AccountRepositoryInterface $accountRepository; + private CurrencyRepositoryInterface $currencyRepository; private PiggyBankRepositoryInterface $piggyBankRepository; public function __construct() @@ -78,7 +78,7 @@ class PiggyBankFactory unset($piggyBankData['object_group_title'], $piggyBankData['transaction_currency_code'], $piggyBankData['transaction_currency_id'], $piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']); // validate amount: - if (array_key_exists('target_amount', $piggyBankData) && '' === (string) $piggyBankData['target_amount']) { + if (array_key_exists('target_amount', $piggyBankData) && '' === (string)$piggyBankData['target_amount']) { $piggyBankData['target_amount'] = '0'; } @@ -108,7 +108,7 @@ class PiggyBankFactory } } // try also with ID - $objectGroupId = (int) ($data['object_group_id'] ?? 0); + $objectGroupId = (int)($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if ($objectGroup instanceof ObjectGroup) { @@ -129,10 +129,10 @@ class PiggyBankFactory $defaultCurrency = app('amount')->getNativeCurrency(); $currency = null; if (array_key_exists('transaction_currency_code', $data)) { - $currency = $this->currencyRepository->findByCode((string) ($data['transaction_currency_code'] ?? '')); + $currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? '')); } if (array_key_exists('transaction_currency_id', $data)) { - $currency = $this->currencyRepository->find((int) ($data['transaction_currency_id'] ?? 0)); + $currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0)); } $currency ??= $defaultCurrency; @@ -141,8 +141,8 @@ class PiggyBankFactory public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank { - $piggyBankId = (int) $piggyBankId; - $piggyBankName = (string) $piggyBankName; + $piggyBankId = (int)$piggyBankId; + $piggyBankName = (string)$piggyBankName; if ('' === $piggyBankName && 0 === $piggyBankId) { return null; } @@ -221,7 +221,7 @@ class PiggyBankFactory private function getMaxOrder(): int { - return (int) $this->piggyBankRepository->getPiggyBanks()->max('order'); + return (int)$this->piggyBankRepository->getPiggyBanks()->max('order'); } @@ -230,12 +230,13 @@ class PiggyBankFactory Log::debug(sprintf('Linking piggy bank #%d to %d accounts.', $piggyBank->id, count($accounts)), $accounts); // collect current current_amount so the sync does not remove them. // TODO this is a tedious check. Feels like a hack. - $toBeLinked = []; + $toBeLinked = []; + $oldSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank); foreach ($piggyBank->accounts as $account) { Log::debug(sprintf('Checking account #%d', $account->id)); foreach ($accounts as $info) { Log::debug(sprintf(' Checking other account #%d', $info['account_id'])); - if ((int) $account->id === (int) $info['account_id']) { + if ((int)$account->id === (int)$info['account_id']) { $toBeLinked[$account->id] = ['current_amount' => $account->pivot->current_amount ?? '0']; Log::debug(sprintf('Prefilled for account #%d with amount %s', $account->id, $account->pivot->current_amount ?? '0')); } @@ -244,9 +245,9 @@ class PiggyBankFactory /** @var array $info */ foreach ($accounts as $info) { - $account = $this->accountRepository->find((int) ($info['account_id'] ?? 0)); + $account = $this->accountRepository->find((int)($info['account_id'] ?? 0)); if (!$account instanceof Account) { - Log::debug(sprintf('Account #%d not found, skipping.', (int) ($info['account_id'] ?? 0))); + Log::debug(sprintf('Account #%d not found, skipping.', (int)($info['account_id'] ?? 0))); continue; } @@ -290,7 +291,16 @@ class PiggyBankFactory } Log::debug(sprintf('Link information: %s', json_encode($toBeLinked))); if (0 !== count($toBeLinked)) { + Log::debug('Syncing accounts to piggy bank.'); $piggyBank->accounts()->sync($toBeLinked); + $piggyBank->refresh(); + $newSavedAmount = $this->piggyBankRepository->getCurrentAmount($piggyBank); + Log::debug(sprintf('Old saved amount: %s, new saved amount is %s', $oldSavedAmount, $newSavedAmount)); + if (0 !== bccomp($oldSavedAmount, $newSavedAmount)) { + Log::debug('Amount changed, will create event for it.'); + // create event for difference. + event(new ChangedAmount($piggyBank, bcsub($newSavedAmount, $oldSavedAmount), null, null)); + } } if (0 === count($toBeLinked)) { Log::warning('No accounts to link to piggy bank, will not change whatever is there now.'); diff --git a/app/Handlers/Events/Model/PiggyBankEventHandler.php b/app/Handlers/Events/Model/PiggyBankEventHandler.php index ecad3759df..cea67d76b0 100644 --- a/app/Handlers/Events/Model/PiggyBankEventHandler.php +++ b/app/Handlers/Events/Model/PiggyBankEventHandler.php @@ -24,6 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events\Model; +use FireflyIII\Events\Model\PiggyBank\ChangedName; +use FireflyIII\Models\Account; +use FireflyIII\Models\Rule; +use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionGroup; use FireflyIII\Events\Model\PiggyBank\ChangedAmount; use FireflyIII\Models\PiggyBankEvent; @@ -33,6 +37,24 @@ use FireflyIII\Models\PiggyBankEvent; */ class PiggyBankEventHandler { + public function changedPiggyBankName(ChangedName $event): void + { + // loop all accounts, collect all user's rules. + /** @var Account $account */ + foreach ($event->piggyBank->accounts as $account) { + /** @var Rule $rule */ + foreach ($account->user->rules as $rule) { + /** @var RuleAction $ruleAction */ + foreach ($rule->ruleActions()->where('action_type', 'update_piggy')->get() as $ruleAction) { + if ($event->oldName === $ruleAction->action_value) { + $ruleAction->action_value = $event->newName; + $ruleAction->save(); + } + } + } + } + } + public function changePiggyAmount(ChangedAmount $event): void { // find journal if group is present. diff --git a/app/Handlers/Events/UpdatedGroupEventHandler.php b/app/Handlers/Events/UpdatedGroupEventHandler.php index a2e7209eb9..0d6c539bba 100644 --- a/app/Handlers/Events/UpdatedGroupEventHandler.php +++ b/app/Handlers/Events/UpdatedGroupEventHandler.php @@ -49,7 +49,9 @@ class UpdatedGroupEventHandler $this->processRules($event); $this->recalculateCredit($event); $this->triggerWebhooks($event); - $this->updateRunningBalance($event); + if ($event->runRecalculations) { + $this->updateRunningBalance($event); + } } diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 5daa03922e..ce96edf102 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -86,7 +86,7 @@ class GroupCollector implements GroupCollectorInterface $this->hasJoinedAttTables = false; $this->expandGroupSearch = false; $this->hasJoinedMetaTables = false; - $this->booleanFields = ['balance_dirty']; + $this->booleanFields = ['source_balance_dirty', 'destination_balance_dirty']; $this->integerFields = [ 'transaction_group_id', 'user_id', @@ -137,7 +137,7 @@ class GroupCollector implements GroupCollectorInterface // currency info: 'source.amount as amount', 'source.balance_after as source_balance_after', - 'source.balance_dirty as balance_dirty', + 'source.balance_dirty as source_balance_dirty', 'source.native_amount as native_amount', 'source.transaction_currency_id as currency_id', 'currency.code as currency_code', @@ -157,6 +157,7 @@ class GroupCollector implements GroupCollectorInterface // destination account info (always present) 'destination.account_id as destination_account_id', 'destination.balance_after as destination_balance_after', + 'destination.balance_dirty as destination_balance_dirty', ]; } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 60abcfb5f0..dc292cc570 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -61,12 +61,12 @@ class ForgotPasswordController extends Controller * * @return Factory|RedirectResponse|View */ - public function sendResetLinkEmail(Request $request, ?UserRepositoryInterface $repository = null) + public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository) { - app('log')->info('Start of sendResetLinkEmail()'); - if ('web' !== config('firefly.authentication_guard')) { + Log::info('Start of sendResetLinkEmail()'); + if ('web' !== config('firefly.authentication_guard')) { $message = sprintf('Cannot reset password when authenticating over "%s".', config('firefly.authentication_guard')); - app('log')->error($message); + Log::error($message); return view('error', compact('message')); } @@ -89,7 +89,7 @@ class ForgotPasswordController extends Controller // need to show to the user. Finally, we'll send out a proper response. $result = $this->broker()->sendResetLink($request->only('email')); if ('passwords.throttled' === $result) { - app('log')->error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id)); + Log::error(sprintf('Cowardly refuse to send a password reset message to user #%d because the reset button has been throttled.', $user->id)); } // always send the same response to the user: diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 8b8af307ce..19a1b37764 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -223,7 +223,7 @@ class LoginController extends Controller * * @throws FireflyException */ - public function showLoginForm(?Request $request = null) + public function showLoginForm(Request $request) { Log::channel('audit')->info('Show login form (1.1).'); diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index d70f894c6d..9623781c1a 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -225,6 +225,7 @@ class IndexController extends Controller 'start_date' => $limit->start_date->isoFormat($this->monthAndDayFormat), 'end_date' => $limit->end_date->isoFormat($this->monthAndDayFormat), 'in_range' => $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end), + 'total_days' => $limit->start_date->diffInDays($limit->end_date) + 1, 'currency_id' => $currency->id, 'currency_symbol' => $currency->symbol, 'currency_name' => $currency->name, diff --git a/app/Http/Controllers/PiggyBank/AmountController.php b/app/Http/Controllers/PiggyBank/AmountController.php index 3ee4d4010b..4cdec6201f 100644 --- a/app/Http/Controllers/PiggyBank/AmountController.php +++ b/app/Http/Controllers/PiggyBank/AmountController.php @@ -75,13 +75,22 @@ class AmountController extends Controller $totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank); foreach ($piggyBank->accounts as $account) { $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date); - $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account); - $leftToSave = bcsub($piggyBank->target_amount, $savedSoFar); + $leftToSave = bcsub($piggyBank->target_amount, $totalSaved); $maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave); + + Log::debug(sprintf( + 'Account "%s", left on account "%s", saved so far "%s", left to save "%s", max amount "%s".', + $account->name, + $leftOnAccount, + $totalSaved, + $leftToSave, + $maxAmount, + )); + $accounts[] = [ 'account' => $account, 'left_on_account' => $leftOnAccount, - 'saved_so_far' => $savedSoFar, + 'total_saved' => $totalSaved, 'left_to_save' => $leftToSave, 'max_amount' => $maxAmount, ]; @@ -100,18 +109,18 @@ class AmountController extends Controller public function addMobile(PiggyBank $piggyBank) { /** @var Carbon $date */ - $date = session('end', today(config('app.timezone'))); - $accounts = []; - $total = '0'; + $date = session('end', today(config('app.timezone'))); + $accounts = []; + $total = '0'; + $totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank); foreach ($piggyBank->accounts as $account) { $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date); - $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank, $account); - $leftToSave = bcsub($piggyBank->target_amount, $savedSoFar); + $leftToSave = bcsub($piggyBank->target_amount, $totalSaved); $maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave); $accounts[] = [ 'account' => $account, 'left_on_account' => $leftOnAccount, - 'saved_so_far' => $savedSoFar, + 'total_saved' => $totalSaved, 'left_to_save' => $leftToSave, 'max_amount' => $maxAmount, ]; diff --git a/app/Http/Controllers/PiggyBank/EditController.php b/app/Http/Controllers/PiggyBank/EditController.php index b7b29683ae..200d5acc6d 100644 --- a/app/Http/Controllers/PiggyBank/EditController.php +++ b/app/Http/Controllers/PiggyBank/EditController.php @@ -63,6 +63,14 @@ class EditController extends Controller ); } + public function resetHistory(PiggyBank $piggyBank): RedirectResponse + { + $this->piggyRepos->resetHistory($piggyBank); + session()->flash('success', (string) trans('firefly.piggy_history_reset')); + + return redirect(route('piggy-banks.show', [$piggyBank->id])); + } + /** * Edit a piggy bank. * diff --git a/app/Http/Controllers/RuleGroup/ExecutionController.php b/app/Http/Controllers/RuleGroup/ExecutionController.php index 40419e9656..4f1b3137b2 100644 --- a/app/Http/Controllers/RuleGroup/ExecutionController.php +++ b/app/Http/Controllers/RuleGroup/ExecutionController.php @@ -34,6 +34,7 @@ use FireflyIII\TransactionRules\Engine\RuleEngineInterface; use FireflyIII\User; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; +use Illuminate\Support\Collection; use Illuminate\View\View; /** @@ -75,7 +76,6 @@ class ExecutionController extends Controller $accounts = implode(',', $request->get('accounts')); $startDate = new Carbon($request->get('start')); $endDate = new Carbon($request->get('end')); - $rules = $this->ruleGroupRepository->getActiveRules($ruleGroup); // create new rule engine: $newRuleEngine = app(RuleEngineInterface::class); $newRuleEngine->setUser($user); @@ -86,7 +86,9 @@ class ExecutionController extends Controller $newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]); // set rules: - $newRuleEngine->setRules($rules); + // #10427, file rule group and not the set of rules. + $collection = new Collection([$ruleGroup]); + $newRuleEngine->setRuleGroups($collection); $newRuleEngine->fire(); // Tell the user that the job is queued diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index 7d48564d4f..bca008b147 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -118,7 +118,7 @@ class BulkController extends Controller // run rules on changed journals: /** @var TransactionJournal $journal */ foreach ($collection as $journal) { - event(new UpdatedTransactionGroup($journal->transactionGroup, true, true)); + event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, false)); } app('preferences')->mark(); diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index d3b00a5738..5a524db619 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -292,7 +292,7 @@ class ConvertController extends Controller $group->refresh(); session()->flash('success', (string) trans('firefly.converted_to_'.$destinationType->type)); - event(new UpdatedTransactionGroup($group, true, true)); + event(new UpdatedTransactionGroup($group, true, true, true)); return redirect(route('transactions.show', [$group->id])); } diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index bac580dc76..bb7f4609ae 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -191,15 +191,15 @@ class MassController extends Controller */ private function updateJournal(int $journalId, MassEditJournalRequest $request): void { - $journal = $this->repository->find($journalId); + $journal = $this->repository->find($journalId); if (!$journal instanceof TransactionJournal) { throw new FireflyException(sprintf('Trying to edit non-existent or deleted journal #%d', $journalId)); } - $service = app(JournalUpdateService::class); + $service = app(JournalUpdateService::class); // for each field, call the update service. $service->setTransactionJournal($journal); - $data = [ + $data = [ 'date' => $this->getDateFromRequest($request, $journal->id, 'date'), 'description' => $this->getStringFromRequest($request, $journal->id, 'description'), 'source_id' => $this->getIntFromRequest($request, $journal->id, 'source_id'), @@ -217,7 +217,8 @@ class MassController extends Controller $service->setData($data); $service->update(); // trigger rules - event(new UpdatedTransactionGroup($journal->transactionGroup, true, true)); + $runRecalculations = $service->isCompareHashChanged(); + event(new UpdatedTransactionGroup($journal->transactionGroup, true, true, $runRecalculations)); } private function getDateFromRequest(MassEditJournalRequest $request, int $journalId, string $key): ?Carbon diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index 9cd8d51163..8d99bc4765 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Models\Account; use FireflyIII\Models\Location; @@ -33,7 +34,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class AccountFormRequest. diff --git a/app/Http/Requests/AttachmentFormRequest.php b/app/Http/Requests/AttachmentFormRequest.php index f481510ee6..2da2240168 100644 --- a/app/Http/Requests/AttachmentFormRequest.php +++ b/app/Http/Requests/AttachmentFormRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class AttachmentFormRequest. diff --git a/app/Http/Requests/BillStoreRequest.php b/app/Http/Requests/BillStoreRequest.php index 37e9f7ef02..0f530a2191 100644 --- a/app/Http/Requests/BillStoreRequest.php +++ b/app/Http/Requests/BillStoreRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BillStoreRequest. diff --git a/app/Http/Requests/BillUpdateRequest.php b/app/Http/Requests/BillUpdateRequest.php index cde6978364..f4376c00b4 100644 --- a/app/Http/Requests/BillUpdateRequest.php +++ b/app/Http/Requests/BillUpdateRequest.php @@ -23,13 +23,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Bill; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BillUpdateRequest. diff --git a/app/Http/Requests/BudgetFormStoreRequest.php b/app/Http/Requests/BudgetFormStoreRequest.php index 86779d3794..cb6c99f037 100644 --- a/app/Http/Requests/BudgetFormStoreRequest.php +++ b/app/Http/Requests/BudgetFormStoreRequest.php @@ -23,13 +23,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BudgetFormStoreRequest diff --git a/app/Http/Requests/BudgetFormUpdateRequest.php b/app/Http/Requests/BudgetFormUpdateRequest.php index 5dbecfd4c8..4fc1ec8f47 100644 --- a/app/Http/Requests/BudgetFormUpdateRequest.php +++ b/app/Http/Requests/BudgetFormUpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Budget; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; @@ -30,7 +31,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\AutoBudget\ValidatesAutoBudgetRequest; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BudgetFormUpdateRequest diff --git a/app/Http/Requests/BudgetIncomeRequest.php b/app/Http/Requests/BudgetIncomeRequest.php index d75f81faa9..d0a2b96b17 100644 --- a/app/Http/Requests/BudgetIncomeRequest.php +++ b/app/Http/Requests/BudgetIncomeRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsValidPositiveAmount; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class BudgetIncomeRequest. diff --git a/app/Http/Requests/BulkEditJournalRequest.php b/app/Http/Requests/BulkEditJournalRequest.php index 4bbaafa77b..bcbbf533ca 100644 --- a/app/Http/Requests/BulkEditJournalRequest.php +++ b/app/Http/Requests/BulkEditJournalRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class MassEditBulkJournalRequest. diff --git a/app/Http/Requests/CategoryFormRequest.php b/app/Http/Requests/CategoryFormRequest.php index 8ca3455168..53e25c7be3 100644 --- a/app/Http/Requests/CategoryFormRequest.php +++ b/app/Http/Requests/CategoryFormRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Category; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class CategoryFormRequest. diff --git a/app/Http/Requests/ConfigurationRequest.php b/app/Http/Requests/ConfigurationRequest.php index 57f8a969b4..212b706b5f 100644 --- a/app/Http/Requests/ConfigurationRequest.php +++ b/app/Http/Requests/ConfigurationRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ConfigurationRequest. diff --git a/app/Http/Requests/CurrencyFormRequest.php b/app/Http/Requests/CurrencyFormRequest.php index 959678e64c..9a4f49672c 100644 --- a/app/Http/Requests/CurrencyFormRequest.php +++ b/app/Http/Requests/CurrencyFormRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class CurrencyFormRequest. diff --git a/app/Http/Requests/DeleteAccountFormRequest.php b/app/Http/Requests/DeleteAccountFormRequest.php index 31222e084a..c06cba8b51 100644 --- a/app/Http/Requests/DeleteAccountFormRequest.php +++ b/app/Http/Requests/DeleteAccountFormRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class DeleteAccountFormRequest. diff --git a/app/Http/Requests/EmailFormRequest.php b/app/Http/Requests/EmailFormRequest.php index cd4369f3ec..26f2c66750 100644 --- a/app/Http/Requests/EmailFormRequest.php +++ b/app/Http/Requests/EmailFormRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class EmailFormRequest. diff --git a/app/Http/Requests/ExistingTokenFormRequest.php b/app/Http/Requests/ExistingTokenFormRequest.php index b843012fba..37f7eb7867 100644 --- a/app/Http/Requests/ExistingTokenFormRequest.php +++ b/app/Http/Requests/ExistingTokenFormRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ExistingTokenFormRequest. diff --git a/app/Http/Requests/InviteUserFormRequest.php b/app/Http/Requests/InviteUserFormRequest.php index 2c31d965ce..5c71175d81 100644 --- a/app/Http/Requests/InviteUserFormRequest.php +++ b/app/Http/Requests/InviteUserFormRequest.php @@ -24,11 +24,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class InviteUserFormRequest diff --git a/app/Http/Requests/JournalLinkRequest.php b/app/Http/Requests/JournalLinkRequest.php index 185aaea191..f924a24ee6 100644 --- a/app/Http/Requests/JournalLinkRequest.php +++ b/app/Http/Requests/JournalLinkRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\LinkType; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class JournalLink. diff --git a/app/Http/Requests/LinkTypeFormRequest.php b/app/Http/Requests/LinkTypeFormRequest.php index 3fb7511c6a..202b3fe3b8 100644 --- a/app/Http/Requests/LinkTypeFormRequest.php +++ b/app/Http/Requests/LinkTypeFormRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class LinkTypeFormRequest. diff --git a/app/Http/Requests/MassDeleteJournalRequest.php b/app/Http/Requests/MassDeleteJournalRequest.php index 603e8a7d51..5700ac4224 100644 --- a/app/Http/Requests/MassDeleteJournalRequest.php +++ b/app/Http/Requests/MassDeleteJournalRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class MassDeleteJournalRequest. diff --git a/app/Http/Requests/MassEditJournalRequest.php b/app/Http/Requests/MassEditJournalRequest.php index 7f217aaf67..d236c3abc0 100644 --- a/app/Http/Requests/MassEditJournalRequest.php +++ b/app/Http/Requests/MassEditJournalRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class MassEditJournalRequest. diff --git a/app/Http/Requests/NewUserFormRequest.php b/app/Http/Requests/NewUserFormRequest.php index bed1e3def7..1d0da88187 100644 --- a/app/Http/Requests/NewUserFormRequest.php +++ b/app/Http/Requests/NewUserFormRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsValidAmount; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class NewUserFormRequest. diff --git a/app/Http/Requests/ObjectGroupFormRequest.php b/app/Http/Requests/ObjectGroupFormRequest.php index 8d8dcb1b8a..5febc46231 100644 --- a/app/Http/Requests/ObjectGroupFormRequest.php +++ b/app/Http/Requests/ObjectGroupFormRequest.php @@ -23,12 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\ObjectGroup; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ObjectGroupFormRequest. diff --git a/app/Http/Requests/PiggyBankStoreRequest.php b/app/Http/Requests/PiggyBankStoreRequest.php index d3ce9e2507..61ba326821 100644 --- a/app/Http/Requests/PiggyBankStoreRequest.php +++ b/app/Http/Requests/PiggyBankStoreRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Rules\IsValidPositiveAmount; @@ -31,7 +32,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class PiggyBankStoreRequest. diff --git a/app/Http/Requests/PiggyBankUpdateRequest.php b/app/Http/Requests/PiggyBankUpdateRequest.php index 56f023768c..d6facfb7de 100644 --- a/app/Http/Requests/PiggyBankUpdateRequest.php +++ b/app/Http/Requests/PiggyBankUpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -32,7 +33,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class PiggyBankFormRequest. diff --git a/app/Http/Requests/ProfileFormRequest.php b/app/Http/Requests/ProfileFormRequest.php index bf741778e6..65034257b9 100644 --- a/app/Http/Requests/ProfileFormRequest.php +++ b/app/Http/Requests/ProfileFormRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ProfileFormRequest. diff --git a/app/Http/Requests/ReconciliationStoreRequest.php b/app/Http/Requests/ReconciliationStoreRequest.php index 75a1a6d8e3..d9827230ed 100644 --- a/app/Http/Requests/ReconciliationStoreRequest.php +++ b/app/Http/Requests/ReconciliationStoreRequest.php @@ -24,13 +24,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Rules\IsValidAmount; use FireflyIII\Rules\ValidJournals; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class ReconciliationStoreRequest diff --git a/app/Http/Requests/RecurrenceFormRequest.php b/app/Http/Requests/RecurrenceFormRequest.php index 9613291d3f..8536cdf206 100644 --- a/app/Http/Requests/RecurrenceFormRequest.php +++ b/app/Http/Requests/RecurrenceFormRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\CategoryFactory; @@ -36,7 +37,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Validation\AccountValidator; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class RecurrenceFormRequest diff --git a/app/Http/Requests/ReportFormRequest.php b/app/Http/Requests/ReportFormRequest.php index 8c5de287d4..f3b96f4a3e 100644 --- a/app/Http/Requests/ReportFormRequest.php +++ b/app/Http/Requests/ReportFormRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use Carbon\Carbon; use Exception; use FireflyIII\Exceptions\FireflyException; @@ -34,7 +35,6 @@ use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; use function Safe\preg_match; diff --git a/app/Http/Requests/RuleFormRequest.php b/app/Http/Requests/RuleFormRequest.php index 8b7d9ca061..03b1beb270 100644 --- a/app/Http/Requests/RuleFormRequest.php +++ b/app/Http/Requests/RuleFormRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Rule; use FireflyIII\Rules\IsValidActionExpression; use FireflyIII\Support\Request\ChecksLogin; @@ -30,7 +31,6 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class RuleFormRequest. diff --git a/app/Http/Requests/RuleGroupFormRequest.php b/app/Http/Requests/RuleGroupFormRequest.php index 8f5c4af01b..f73cff0b74 100644 --- a/app/Http/Requests/RuleGroupFormRequest.php +++ b/app/Http/Requests/RuleGroupFormRequest.php @@ -23,13 +23,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\RuleGroup; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class RuleGroupFormRequest. diff --git a/app/Http/Requests/SelectTransactionsRequest.php b/app/Http/Requests/SelectTransactionsRequest.php index e87b4af6b1..674d3d222e 100644 --- a/app/Http/Requests/SelectTransactionsRequest.php +++ b/app/Http/Requests/SelectTransactionsRequest.php @@ -23,11 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; -use Carbon\Carbon; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class SelectTransactionsRequest. @@ -41,15 +40,9 @@ class SelectTransactionsRequest extends FormRequest */ public function rules(): array { - // fixed - /** @var Carbon $sessionFirst */ - $sessionFirst = clone session('first'); - $first = $sessionFirst->subDay()->format('Y-m-d'); - $today = today(config('app.timezone'))->addDay()->format('Y-m-d'); - return [ - 'start' => 'required|date|after:'.$first, - 'end' => 'required|date|before:'.$today, + 'start' => 'required|date|after:1900-01-01|before:2099-12-31|before:end|required_with:end', + 'end' => 'required|date|after:1900-01-01|before:2099-12-31|after:start|required_with:start', 'accounts' => 'required', 'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts', ]; diff --git a/app/Http/Requests/TagFormRequest.php b/app/Http/Requests/TagFormRequest.php index 2529907f0f..8686b2bd5d 100644 --- a/app/Http/Requests/TagFormRequest.php +++ b/app/Http/Requests/TagFormRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Models\Location; use FireflyIII\Models\Tag; use FireflyIII\Support\Request\AppendsLocationData; @@ -30,7 +31,6 @@ use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class TagFormRequest. diff --git a/app/Http/Requests/TestRuleFormRequest.php b/app/Http/Requests/TestRuleFormRequest.php index 0cf0524667..fa4e289e4e 100644 --- a/app/Http/Requests/TestRuleFormRequest.php +++ b/app/Http/Requests/TestRuleFormRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class TestRuleFormRequest. diff --git a/app/Http/Requests/TokenFormRequest.php b/app/Http/Requests/TokenFormRequest.php index 3a53cbe7ab..19c0f3bc06 100644 --- a/app/Http/Requests/TokenFormRequest.php +++ b/app/Http/Requests/TokenFormRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class TokenFormRequest. diff --git a/app/Http/Requests/TriggerRecurrenceRequest.php b/app/Http/Requests/TriggerRecurrenceRequest.php index c03e531a00..36d16331d6 100644 --- a/app/Http/Requests/TriggerRecurrenceRequest.php +++ b/app/Http/Requests/TriggerRecurrenceRequest.php @@ -24,11 +24,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class TriggerRecurrenceRequest diff --git a/app/Http/Requests/UserFormRequest.php b/app/Http/Requests/UserFormRequest.php index 409cfba453..cc89dff35b 100644 --- a/app/Http/Requests/UserFormRequest.php +++ b/app/Http/Requests/UserFormRequest.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UserFormRequest. diff --git a/app/Http/Requests/UserRegistrationRequest.php b/app/Http/Requests/UserRegistrationRequest.php index 6e26763831..8bd3504ea3 100644 --- a/app/Http/Requests/UserRegistrationRequest.php +++ b/app/Http/Requests/UserRegistrationRequest.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Support\Request\ChecksLogin; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Class UserRegistrationRequest. diff --git a/app/Models/Account.php b/app/Models/Account.php index f7110c38b7..683b4a2973 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Attributes\Scope; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Support\Models\ReturnsIntegerIdTrait; use FireflyIII\Support\Models\ReturnsIntegerUserIdTrait; @@ -46,19 +47,6 @@ class Account extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - 'deleted_at' => 'datetime', - 'active' => 'boolean', - 'encrypted' => 'boolean', - 'virtual_balance' => 'string', - 'native_virtual_balance' => 'string', - ]; - protected $fillable = ['user_id', 'user_group_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban', 'native_virtual_balance']; protected $hidden = ['encrypted']; @@ -110,15 +98,17 @@ class Account extends Model /** * Get the account number. */ - public function getAccountNumberAttribute(): string + protected function accountNumber(): Attribute { - /** @var null|AccountMeta $metaValue */ - $metaValue = $this->accountMeta() - ->where('name', 'account_number') - ->first() - ; + return Attribute::make(get: function () { + /** @var null|AccountMeta $metaValue */ + $metaValue = $this->accountMeta() + ->where('name', 'account_number') + ->first() + ; - return null !== $metaValue ? $metaValue->data : ''; + return null !== $metaValue ? $metaValue->data : ''; + }); } public function accountMeta(): HasMany @@ -126,15 +116,16 @@ class Account extends Model return $this->hasMany(AccountMeta::class); } - public function getEditNameAttribute(): string + protected function editName(): Attribute { - $name = $this->name; + return Attribute::make(get: function () { + $name = $this->name; + if (AccountTypeEnum::CASH->value === $this->accountType->type) { + return ''; + } - if (AccountTypeEnum::CASH->value === $this->accountType->type) { - return ''; - } - - return $name; + return $name; + }); } public function locations(): MorphMany @@ -163,7 +154,8 @@ class Account extends Model return $this->belongsToMany(PiggyBank::class); } - public function scopeAccountTypeIn(EloquentBuilder $query, array $types): void + #[Scope] + protected function accountTypeIn(EloquentBuilder $query, array $types): void { if (false === $this->joinedAccountTypes) { $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id'); @@ -231,4 +223,19 @@ class Account extends Model get: static fn ($value) => (string) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + 'deleted_at' => 'datetime', + 'active' => 'boolean', + 'encrypted' => 'boolean', + 'virtual_balance' => 'string', + 'native_virtual_balance' => 'string', + ]; + } } diff --git a/app/Models/AccountMeta.php b/app/Models/AccountMeta.php index c053cdafb4..61d8644ff3 100644 --- a/app/Models/AccountMeta.php +++ b/app/Models/AccountMeta.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; use FireflyIII\Support\Models\ReturnsIntegerIdTrait; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -34,12 +35,6 @@ class AccountMeta extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - ]; - protected $fillable = ['account_id', 'name', 'data']; protected $table = 'account_meta'; @@ -48,13 +43,16 @@ class AccountMeta extends Model return $this->belongsTo(Account::class); } - public function getDataAttribute(mixed $value): string + protected function data(): Attribute { - return (string) json_decode((string) $value, true); + return Attribute::make(get: fn (mixed $value) => (string) json_decode((string) $value, true), set: fn (mixed $value) => ['data' => json_encode($value)]); } - public function setDataAttribute(mixed $value): void + protected function casts(): array { - $this->attributes['data'] = json_encode($value); + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; } } diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php index c46326e7fe..2287666db1 100644 --- a/app/Models/Attachment.php +++ b/app/Models/Attachment.php @@ -40,16 +40,6 @@ class Attachment extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'uploaded' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'user_group_id', 'md5', 'filename', 'mime', 'title', 'description', 'size', 'uploaded']; /** @@ -110,4 +100,16 @@ class Attachment extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'uploaded' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/AuditLogEntry.php b/app/Models/AuditLogEntry.php index 436436340e..53773692a1 100644 --- a/app/Models/AuditLogEntry.php +++ b/app/Models/AuditLogEntry.php @@ -35,15 +35,6 @@ class AuditLogEntry extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'before' => 'array', - 'after' => 'array', - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - ]; - public function auditable(): MorphTo { return $this->morphTo(); @@ -67,4 +58,15 @@ class AuditLogEntry extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'before' => 'array', + 'after' => 'array', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + } } diff --git a/app/Models/AvailableBudget.php b/app/Models/AvailableBudget.php index 043ee93cf5..576864a2ea 100644 --- a/app/Models/AvailableBudget.php +++ b/app/Models/AvailableBudget.php @@ -39,20 +39,6 @@ class AvailableBudget extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'start_date' => 'date', - 'end_date' => 'date', - 'transaction_currency_id' => 'int', - 'amount' => 'string', - 'native_amount' => 'string', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date', 'start_date_tz', 'end_date_tz', 'native_amount']; /** @@ -117,4 +103,20 @@ class AvailableBudget extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'start_date' => 'date', + 'end_date' => 'date', + 'transaction_currency_id' => 'int', + 'amount' => 'string', + 'native_amount' => 'string', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/Bill.php b/app/Models/Bill.php index 2e3ef309ea..a0f59bc9d4 100644 --- a/app/Models/Bill.php +++ b/app/Models/Bill.php @@ -42,25 +42,6 @@ class Bill extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'date' => SeparateTimezoneCaster::class, - 'end_date' => SeparateTimezoneCaster::class, - 'extension_date' => SeparateTimezoneCaster::class, - 'skip' => 'int', - 'automatch' => 'boolean', - 'active' => 'boolean', - 'name_encrypted' => 'boolean', - 'match_encrypted' => 'boolean', - 'amount_min' => 'string', - 'amount_max' => 'string', - 'native_amount_min' => 'string', - 'native_amount_max' => 'string', - ]; - protected $fillable = [ 'name', @@ -204,4 +185,25 @@ class Bill extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'date' => SeparateTimezoneCaster::class, + 'end_date' => SeparateTimezoneCaster::class, + 'extension_date' => SeparateTimezoneCaster::class, + 'skip' => 'int', + 'automatch' => 'boolean', + 'active' => 'boolean', + 'name_encrypted' => 'boolean', + 'match_encrypted' => 'boolean', + 'amount_min' => 'string', + 'amount_max' => 'string', + 'native_amount_min' => 'string', + 'native_amount_max' => 'string', + ]; + } } diff --git a/app/Models/Budget.php b/app/Models/Budget.php index ca1f083071..c5c1c29d46 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -41,17 +41,6 @@ class Budget extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'active' => 'boolean', - 'encrypted' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'name', 'active', 'order', 'user_group_id']; protected $hidden = ['encrypted']; @@ -123,4 +112,17 @@ class Budget extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'active' => 'boolean', + 'encrypted' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index 6f1c891182..3fc20b25af 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -37,17 +37,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class BudgetLimit extends Model { use ReturnsIntegerIdTrait; - - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'start_date' => SeparateTimezoneCaster::class, - 'end_date' => SeparateTimezoneCaster::class, - 'auto_budget' => 'boolean', - 'amount' => 'string', - 'native_amount' => 'string', - ]; protected $dispatchesEvents = [ 'created' => Created::class, @@ -120,4 +109,17 @@ class BudgetLimit extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'start_date' => SeparateTimezoneCaster::class, + 'end_date' => SeparateTimezoneCaster::class, + 'auto_budget' => 'boolean', + 'amount' => 'string', + 'native_amount' => 'string', + ]; + } } diff --git a/app/Models/Category.php b/app/Models/Category.php index a426ffa0a1..3e50f448c6 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -40,16 +40,6 @@ class Category extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'encrypted' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'name']; protected $hidden = ['encrypted']; @@ -104,4 +94,16 @@ class Category extends Model { return $this->belongsToMany(Transaction::class, 'category_transaction', 'category_id'); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'encrypted' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php index 78c9e8f44e..1eeb2007dc 100644 --- a/app/Models/Configuration.php +++ b/app/Models/Configuration.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; use FireflyIII\Support\Models\ReturnsIntegerIdTrait; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; @@ -35,32 +36,24 @@ class Configuration extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - ]; - protected $table = 'configuration'; /** * TODO can be replaced with native laravel code. * - * @param mixed $value - * * @return mixed */ - public function getDataAttribute($value) + protected function data(): Attribute { - return json_decode((string) $value); + return Attribute::make(get: fn ($value) => json_decode((string) $value), set: fn ($value) => ['data' => json_encode($value)]); } - /** - * @param mixed $value - */ - public function setDataAttribute($value): void + protected function casts(): array { - $this->attributes['data'] = json_encode($value); + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; } } diff --git a/app/Models/CurrencyExchangeRate.php b/app/Models/CurrencyExchangeRate.php index 430a8c2464..f5117715fe 100644 --- a/app/Models/CurrencyExchangeRate.php +++ b/app/Models/CurrencyExchangeRate.php @@ -37,19 +37,6 @@ class CurrencyExchangeRate extends Model use ReturnsIntegerIdTrait; use ReturnsIntegerUserIdTrait; use SoftDeletes; - - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - 'from_currency_id' => 'integer', - 'to_currency_id' => 'integer', - 'date' => SeparateTimezoneCaster::class, - 'rate' => 'string', - 'user_rate' => 'string', - ]; protected $fillable = ['user_id', 'from_currency_id', 'to_currency_id', 'date', 'date_tz', 'rate']; public function fromCurrency(): BelongsTo @@ -94,4 +81,19 @@ class CurrencyExchangeRate extends Model get: static fn ($value) => (string) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + 'from_currency_id' => 'integer', + 'to_currency_id' => 'integer', + 'date' => SeparateTimezoneCaster::class, + 'rate' => 'string', + 'user_rate' => 'string', + ]; + } } diff --git a/app/Models/GroupMembership.php b/app/Models/GroupMembership.php index 1be2ef9b1d..830826967e 100644 --- a/app/Models/GroupMembership.php +++ b/app/Models/GroupMembership.php @@ -36,14 +36,6 @@ class GroupMembership extends Model use ReturnsIntegerIdTrait; use ReturnsIntegerUserIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'user_role_id']; public function user(): BelongsTo @@ -67,4 +59,14 @@ class GroupMembership extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/InvitedUser.php b/app/Models/InvitedUser.php index da0d77e670..d543d82c47 100644 --- a/app/Models/InvitedUser.php +++ b/app/Models/InvitedUser.php @@ -36,14 +36,6 @@ class InvitedUser extends Model { use ReturnsIntegerIdTrait; use ReturnsIntegerUserIdTrait; - - protected $casts - = [ - 'expires' => SeparateTimezoneCaster::class, - 'redeemed' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; protected $fillable = ['user_group_id', 'user_id', 'email', 'invite_code', 'expires', 'expires_tz', 'redeemed']; /** @@ -68,4 +60,14 @@ class InvitedUser extends Model { return $this->belongsTo(User::class); } + + protected function casts(): array + { + return [ + 'expires' => SeparateTimezoneCaster::class, + 'redeemed' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/LinkType.php b/app/Models/LinkType.php index a865277cd9..f7b662961c 100644 --- a/app/Models/LinkType.php +++ b/app/Models/LinkType.php @@ -34,14 +34,6 @@ class LinkType extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'editable' => 'boolean', - ]; - protected $fillable = ['name', 'inward', 'outward', 'editable']; /** @@ -66,4 +58,14 @@ class LinkType extends Model { return $this->hasMany(TransactionJournalLink::class); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'editable' => 'boolean', + ]; + } } diff --git a/app/Models/Location.php b/app/Models/Location.php index 50d051d532..ce5744dba9 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -34,16 +34,6 @@ class Location extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'zoomLevel' => 'int', - 'latitude' => 'float', - 'longitude' => 'float', - ]; - protected $fillable = ['locatable_id', 'locatable_type', 'latitude', 'longitude', 'zoom_level']; /** @@ -82,4 +72,16 @@ class Location extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'zoomLevel' => 'int', + 'latitude' => 'float', + 'longitude' => 'float', + ]; + } } diff --git a/app/Models/Note.php b/app/Models/Note.php index 29762af139..6c8c56653e 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -34,13 +34,6 @@ class Note extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - ]; - protected $fillable = ['title', 'text', 'noteable_id', 'noteable_type']; /** @@ -57,4 +50,13 @@ class Note extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + } } diff --git a/app/Models/ObjectGroup.php b/app/Models/ObjectGroup.php index a13614d01c..d7833412fb 100644 --- a/app/Models/ObjectGroup.php +++ b/app/Models/ObjectGroup.php @@ -37,15 +37,6 @@ class ObjectGroup extends Model { use ReturnsIntegerIdTrait; use ReturnsIntegerUserIdTrait; - - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - 'deleted_at' => 'datetime', - ]; protected $fillable = ['title', 'order', 'user_id', 'user_group_id']; /** @@ -105,4 +96,15 @@ class ObjectGroup extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + 'deleted_at' => 'datetime', + ]; + } } diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index 8d0a680941..08d5a2563d 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -39,20 +39,6 @@ class PiggyBank extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'start_date' => 'date', - 'target_date' => 'date', - 'order' => 'int', - 'active' => 'boolean', - 'encrypted' => 'boolean', - 'target_amount' => 'string', - 'native_target_amount' => 'string', - ]; - protected $fillable = ['name', 'order', 'target_amount', 'start_date', 'start_date_tz', 'target_date', 'target_date_tz', 'active', 'transaction_currency_id', 'native_target_amount']; /** @@ -154,4 +140,20 @@ class PiggyBank extends Model get: static fn ($value) => (string) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'start_date' => 'date', + 'target_date' => 'date', + 'order' => 'int', + 'active' => 'boolean', + 'encrypted' => 'boolean', + 'target_amount' => 'string', + 'native_target_amount' => 'string', + ]; + } } diff --git a/app/Models/PiggyBankEvent.php b/app/Models/PiggyBankEvent.php index 9ab7ab7c18..733792ffeb 100644 --- a/app/Models/PiggyBankEvent.php +++ b/app/Models/PiggyBankEvent.php @@ -33,15 +33,6 @@ class PiggyBankEvent extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'date' => SeparateTimezoneCaster::class, - 'amount' => 'string', - 'native_amount' => 'string', - ]; - protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'date_tz', 'amount', 'native_amount']; protected $hidden = ['amount_encrypted']; @@ -80,4 +71,15 @@ class PiggyBankEvent extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'date' => SeparateTimezoneCaster::class, + 'amount' => 'string', + 'native_amount' => 'string', + ]; + } } diff --git a/app/Models/PiggyBankRepetition.php b/app/Models/PiggyBankRepetition.php index 715d5b276c..f0f6125b53 100644 --- a/app/Models/PiggyBankRepetition.php +++ b/app/Models/PiggyBankRepetition.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Attributes\Scope; use Carbon\Carbon; use FireflyIII\Casts\SeparateTimezoneCaster; use FireflyIII\Support\Models\ReturnsIntegerIdTrait; @@ -35,15 +36,6 @@ class PiggyBankRepetition extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'start_date' => SeparateTimezoneCaster::class, - 'target_date' => SeparateTimezoneCaster::class, - 'virtual_balance' => 'string', - ]; - protected $fillable = ['piggy_bank_id', 'start_date', 'start_date_tz', 'target_date', 'target_date_tz', 'current_amount']; public function piggyBank(): BelongsTo @@ -51,7 +43,8 @@ class PiggyBankRepetition extends Model return $this->belongsTo(PiggyBank::class); } - public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $target): EloquentBuilder + #[Scope] + protected function onDates(EloquentBuilder $query, Carbon $start, Carbon $target): EloquentBuilder { return $query->where('start_date', $start->format('Y-m-d'))->where('target_date', $target->format('Y-m-d')); } @@ -59,7 +52,8 @@ class PiggyBankRepetition extends Model /** * @return EloquentBuilder */ - public function scopeRelevantOnDate(EloquentBuilder $query, Carbon $date) + #[Scope] + protected function relevantOnDate(EloquentBuilder $query, Carbon $date) { return $query->where( static function (EloquentBuilder $q) use ($date): void { @@ -100,4 +94,15 @@ class PiggyBankRepetition extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'start_date' => SeparateTimezoneCaster::class, + 'target_date' => SeparateTimezoneCaster::class, + 'virtual_balance' => 'string', + ]; + } } diff --git a/app/Models/Preference.php b/app/Models/Preference.php index dbf2ef212f..0e282cf1a5 100644 --- a/app/Models/Preference.php +++ b/app/Models/Preference.php @@ -35,15 +35,6 @@ class Preference extends Model use ReturnsIntegerIdTrait; use ReturnsIntegerUserIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'data' => 'array', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'data', 'name', 'user_group_id']; /** @@ -102,4 +93,15 @@ class Preference extends Model { return $this->belongsTo(User::class); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'data' => 'array', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/Recurrence.php b/app/Models/Recurrence.php index 5d4ad39ccd..4e369fca27 100644 --- a/app/Models/Recurrence.php +++ b/app/Models/Recurrence.php @@ -42,24 +42,6 @@ class Recurrence extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'title' => 'string', - 'id' => 'int', - 'description' => 'string', - 'first_date' => SeparateTimezoneCaster::class, - 'repeat_until' => SeparateTimezoneCaster::class, - 'latest_date' => SeparateTimezoneCaster::class, - 'repetitions' => 'int', - 'active' => 'bool', - 'apply_rules' => 'bool', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'transaction_type_id', 'title', 'description', 'first_date', 'first_date_tz', 'repeat_until', 'repeat_until_tz', 'latest_date', 'latest_date_tz', 'repetitions', 'apply_rules', 'active']; @@ -137,4 +119,24 @@ class Recurrence extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'title' => 'string', + 'id' => 'int', + 'description' => 'string', + 'first_date' => SeparateTimezoneCaster::class, + 'repeat_until' => SeparateTimezoneCaster::class, + 'latest_date' => SeparateTimezoneCaster::class, + 'repetitions' => 'int', + 'active' => 'bool', + 'apply_rules' => 'bool', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/RecurrenceMeta.php b/app/Models/RecurrenceMeta.php index c977252354..7430c942f6 100644 --- a/app/Models/RecurrenceMeta.php +++ b/app/Models/RecurrenceMeta.php @@ -35,15 +35,6 @@ class RecurrenceMeta extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'name' => 'string', - 'value' => 'string', - ]; - protected $fillable = ['recurrence_id', 'name', 'value']; protected $table = 'recurrences_meta'; @@ -59,4 +50,15 @@ class RecurrenceMeta extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'name' => 'string', + 'value' => 'string', + ]; + } } diff --git a/app/Models/RecurrenceTransaction.php b/app/Models/RecurrenceTransaction.php index b648cf4cd2..2c17d52ebb 100644 --- a/app/Models/RecurrenceTransaction.php +++ b/app/Models/RecurrenceTransaction.php @@ -36,16 +36,6 @@ class RecurrenceTransaction extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'amount' => 'string', - 'foreign_amount' => 'string', - 'description' => 'string', - ]; - protected $fillable = [ 'recurrence_id', @@ -143,4 +133,16 @@ class RecurrenceTransaction extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'amount' => 'string', + 'foreign_amount' => 'string', + 'description' => 'string', + ]; + } } diff --git a/app/Models/RecurrenceTransactionMeta.php b/app/Models/RecurrenceTransactionMeta.php index c4e5758df4..a334b9c433 100644 --- a/app/Models/RecurrenceTransactionMeta.php +++ b/app/Models/RecurrenceTransactionMeta.php @@ -35,15 +35,6 @@ class RecurrenceTransactionMeta extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'name' => 'string', - 'value' => 'string', - ]; - protected $fillable = ['rt_id', 'name', 'value']; protected $table = 'rt_meta'; @@ -59,4 +50,15 @@ class RecurrenceTransactionMeta extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'name' => 'string', + 'value' => 'string', + ]; + } } diff --git a/app/Models/Role.php b/app/Models/Role.php index 421e896d24..b1b3476ca4 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -32,16 +32,18 @@ class Role extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - ]; - protected $fillable = ['name', 'display_name', 'description']; public function users(): BelongsToMany { return $this->belongsToMany(User::class); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + } } diff --git a/app/Models/Rule.php b/app/Models/Rule.php index 86d8c36f20..5308eae4d5 100644 --- a/app/Models/Rule.php +++ b/app/Models/Rule.php @@ -39,20 +39,6 @@ class Rule extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'active' => 'boolean', - 'order' => 'int', - 'stop_processing' => 'boolean', - 'id' => 'int', - 'strict' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['rule_group_id', 'order', 'active', 'title', 'description', 'user_id', 'user_group_id', 'strict']; /** @@ -98,12 +84,9 @@ class Rule extends Model return $this->hasMany(RuleTrigger::class); } - /** - * @param mixed $value - */ - public function setDescriptionAttribute($value): void + protected function description(): Attribute { - $this->attributes['description'] = e($value); + return Attribute::make(set: fn ($value) => ['description' => e($value)]); } public function userGroup(): BelongsTo @@ -124,4 +107,20 @@ class Rule extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'active' => 'boolean', + 'order' => 'int', + 'stop_processing' => 'boolean', + 'id' => 'int', + 'strict' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/RuleAction.php b/app/Models/RuleAction.php index f7fbd2e6eb..60ebc7254f 100644 --- a/app/Models/RuleAction.php +++ b/app/Models/RuleAction.php @@ -35,15 +35,6 @@ class RuleAction extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'active' => 'boolean', - 'order' => 'int', - 'stop_processing' => 'boolean', - ]; - protected $fillable = ['rule_id', 'action_type', 'action_value', 'order', 'active', 'stop_processing']; public function getValue(array $journal): string @@ -88,4 +79,15 @@ class RuleAction extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'active' => 'boolean', + 'order' => 'int', + 'stop_processing' => 'boolean', + ]; + } } diff --git a/app/Models/RuleGroup.php b/app/Models/RuleGroup.php index 02b6494bda..1a25031a7e 100644 --- a/app/Models/RuleGroup.php +++ b/app/Models/RuleGroup.php @@ -39,18 +39,6 @@ class RuleGroup extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'active' => 'boolean', - 'stop_processing' => 'boolean', - 'order' => 'int', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'stop_processing', 'order', 'title', 'description', 'active']; /** @@ -92,4 +80,18 @@ class RuleGroup extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'active' => 'boolean', + 'stop_processing' => 'boolean', + 'order' => 'int', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/RuleTrigger.php b/app/Models/RuleTrigger.php index ac400525d9..5c9f4fca2e 100644 --- a/app/Models/RuleTrigger.php +++ b/app/Models/RuleTrigger.php @@ -32,15 +32,6 @@ class RuleTrigger extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'active' => 'boolean', - 'order' => 'int', - 'stop_processing' => 'boolean', - ]; - protected $fillable = ['rule_id', 'trigger_type', 'trigger_value', 'order', 'active', 'stop_processing']; public function rule(): BelongsTo @@ -61,4 +52,15 @@ class RuleTrigger extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'active' => 'boolean', + 'order' => 'int', + 'stop_processing' => 'boolean', + ]; + } } diff --git a/app/Models/Tag.php b/app/Models/Tag.php index fed190c86a..6a740a3730 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -40,19 +40,6 @@ class Tag extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'date' => SeparateTimezoneCaster::class, - 'zoomLevel' => 'int', - 'latitude' => 'float', - 'longitude' => 'float', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'tag', 'date', 'date_tz', 'description', 'tagMode']; protected $hidden = ['zoomLevel', 'latitude', 'longitude']; @@ -99,4 +86,19 @@ class Tag extends Model { return $this->belongsToMany(TransactionJournal::class); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'date' => SeparateTimezoneCaster::class, + 'zoomLevel' => 'int', + 'latitude' => 'float', + 'longitude' => 'float', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index cad47192fa..a563e3656f 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Attributes\Scope; use Carbon\Carbon; use FireflyIII\Support\Models\ReturnsIntegerIdTrait; use Illuminate\Database\Eloquent\Builder; @@ -39,25 +40,6 @@ class Transaction extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'identifier' => 'int', - 'encrypted' => 'boolean', // model does not have these fields though - 'bill_name_encrypted' => 'boolean', - 'reconciled' => 'boolean', - 'balance_dirty' => 'boolean', - 'balance_before' => 'string', - 'balance_after' => 'string', - 'date' => 'datetime', - 'amount' => 'string', - 'foreign_amount' => 'string', - 'native_amount' => 'string', - 'native_foreign_amount' => 'string', - ]; - protected $fillable = [ 'account_id', @@ -110,7 +92,8 @@ class Transaction extends Model /** * Check for transactions AFTER a specified date. */ - public function scopeAfter(Builder $query, Carbon $date): void + #[Scope] + protected function after(Builder $query, Carbon $date): void { if (!self::isJoined($query, 'transaction_journals')) { $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'); @@ -137,7 +120,8 @@ class Transaction extends Model /** * Check for transactions BEFORE the specified date. */ - public function scopeBefore(Builder $query, Carbon $date): void + #[Scope] + protected function before(Builder $query, Carbon $date): void { if (!self::isJoined($query, 'transaction_journals')) { $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'); @@ -145,7 +129,8 @@ class Transaction extends Model $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')); } - public function scopeTransactionTypes(Builder $query, array $types): void + #[Scope] + protected function transactionTypes(Builder $query, array $types): void { if (!self::isJoined($query, 'transaction_journals')) { $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'); @@ -215,4 +200,25 @@ class Transaction extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'identifier' => 'int', + 'encrypted' => 'boolean', // model does not have these fields though + 'bill_name_encrypted' => 'boolean', + 'reconciled' => 'boolean', + 'balance_dirty' => 'boolean', + 'balance_before' => 'string', + 'balance_after' => 'string', + 'date' => 'datetime', + 'amount' => 'string', + 'foreign_amount' => 'string', + 'native_amount' => 'string', + 'native_foreign_amount' => 'string', + ]; + } } diff --git a/app/Models/TransactionCurrency.php b/app/Models/TransactionCurrency.php index 33f08ee01b..4f93717955 100644 --- a/app/Models/TransactionCurrency.php +++ b/app/Models/TransactionCurrency.php @@ -39,14 +39,6 @@ class TransactionCurrency extends Model public ?bool $userGroupEnabled = null; public ?bool $userGroupNative = null; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'decimal_places' => 'int', - 'enabled' => 'bool', - ]; protected $fillable = ['name', 'code', 'symbol', 'decimal_places', 'enabled']; @@ -115,4 +107,15 @@ class TransactionCurrency extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'decimal_places' => 'int', + 'enabled' => 'bool', + ]; + } } diff --git a/app/Models/TransactionGroup.php b/app/Models/TransactionGroup.php index 9128667f97..a09af2b231 100644 --- a/app/Models/TransactionGroup.php +++ b/app/Models/TransactionGroup.php @@ -38,18 +38,6 @@ class TransactionGroup extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'id' => 'integer', - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'title' => 'string', - 'date' => 'datetime', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = ['user_id', 'user_group_id', 'title']; /** @@ -97,4 +85,18 @@ class TransactionGroup extends Model { return $this->belongsTo(UserGroup::class); } + + protected function casts(): array + { + return [ + 'id' => 'integer', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'title' => 'string', + 'date' => 'datetime', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index 6c39101e1a..609d7dc353 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Models; +use Illuminate\Database\Eloquent\Attributes\Scope; use Carbon\Carbon; use FireflyIII\Casts\SeparateTimezoneCaster; use FireflyIII\Enums\TransactionTypeEnum; @@ -52,23 +53,6 @@ class TransactionJournal extends Model use ReturnsIntegerUserIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - 'date' => SeparateTimezoneCaster::class, - 'interest_date' => 'date', - 'book_date' => 'date', - 'process_date' => 'date', - 'order' => 'int', - 'tag_count' => 'int', - 'encrypted' => 'boolean', - 'completed' => 'boolean', - 'user_id' => 'integer', - 'user_group_id' => 'integer', - ]; - protected $fillable = [ 'user_id', @@ -181,7 +165,8 @@ class TransactionJournal extends Model return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d H:i:s')); } - public function scopeTransactionTypes(EloquentBuilder $query, array $types): void + #[Scope] + protected function transactionTypes(EloquentBuilder $query, array $types): void { if (!self::isJoined($query, 'transaction_types')) { $query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); @@ -259,4 +244,23 @@ class TransactionJournal extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + 'date' => SeparateTimezoneCaster::class, + 'interest_date' => 'date', + 'book_date' => 'date', + 'process_date' => 'date', + 'order' => 'int', + 'tag_count' => 'int', + 'encrypted' => 'boolean', + 'completed' => 'boolean', + 'user_id' => 'integer', + 'user_group_id' => 'integer', + ]; + } } diff --git a/app/Models/TransactionJournalLink.php b/app/Models/TransactionJournalLink.php index 4d7d8a632f..92adb6a7e2 100644 --- a/app/Models/TransactionJournalLink.php +++ b/app/Models/TransactionJournalLink.php @@ -34,12 +34,6 @@ class TransactionJournalLink extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - ]; - protected $table = 'journal_links'; /** @@ -109,4 +103,12 @@ class TransactionJournalLink extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + } } diff --git a/app/Models/TransactionJournalMeta.php b/app/Models/TransactionJournalMeta.php index 51bfd13e34..144bc79e82 100644 --- a/app/Models/TransactionJournalMeta.php +++ b/app/Models/TransactionJournalMeta.php @@ -37,35 +37,20 @@ class TransactionJournalMeta extends Model use ReturnsIntegerIdTrait; use SoftDeletes; - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'deleted_at' => 'datetime', - ]; - protected $fillable = ['transaction_journal_id', 'name', 'data', 'hash']; protected $table = 'journal_meta'; /** - * @param mixed $value - * * @return mixed */ - public function getDataAttribute($value) + protected function data(): Attribute { - return json_decode((string) $value, false); - } + return Attribute::make(get: fn ($value) => json_decode((string) $value, false), set: function ($value) { + $data = json_encode($value); - /** - * @param mixed $value - */ - public function setDataAttribute($value): void - { - $data = json_encode($value); - $this->attributes['data'] = $data; - $this->attributes['hash'] = hash('sha256', (string) $data); + return ['data' => $data, 'hash' => hash('sha256', (string) $data)]; + }); } public function transactionJournal(): BelongsTo @@ -79,4 +64,13 @@ class TransactionJournalMeta extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + } } diff --git a/app/Models/WebhookMessage.php b/app/Models/WebhookMessage.php index f18347330c..77d6a0642c 100644 --- a/app/Models/WebhookMessage.php +++ b/app/Models/WebhookMessage.php @@ -36,15 +36,6 @@ class WebhookMessage extends Model { use ReturnsIntegerIdTrait; - protected $casts - = [ - 'sent' => 'boolean', - 'errored' => 'boolean', - 'uuid' => 'string', - 'message' => 'json', - 'logs' => 'json', - ]; - /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * @@ -94,4 +85,15 @@ class WebhookMessage extends Model get: static fn ($value) => (int) $value, ); } + + protected function casts(): array + { + return [ + 'sent' => 'boolean', + 'errored' => 'boolean', + 'uuid' => 'string', + 'message' => 'json', + 'logs' => 'json', + ]; + } } diff --git a/app/Notifications/Security/UserFailedLoginAttempt.php b/app/Notifications/Security/UserFailedLoginAttempt.php index c4ac85a2c6..08159020be 100644 --- a/app/Notifications/Security/UserFailedLoginAttempt.php +++ b/app/Notifications/Security/UserFailedLoginAttempt.php @@ -67,9 +67,10 @@ class UserFailedLoginAttempt extends Notification { $settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable); $message = new Message(); + $ip = Request::ip(); $message->topic($settings['ntfy_topic']); $message->title((string) trans('email.failed_login_subject')); - $message->body((string) trans('email.failed_login_message', ['email' => $this->user->email])); + $message->body((string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email])); return $message; } @@ -79,7 +80,9 @@ class UserFailedLoginAttempt extends Notification */ public function toPushover(User $notifiable): PushoverMessage { - return PushoverMessage::create((string) trans('email.failed_login_message', ['email' => $this->user->email])) + $ip = Request::ip(); + + return PushoverMessage::create((string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email])) ->title((string) trans('email.failed_login_subject')) ; } @@ -89,7 +92,8 @@ class UserFailedLoginAttempt extends Notification */ public function toSlack(User $notifiable): SlackMessage { - $message = (string) trans('email.failed_login_message', ['email' => $this->user->email]); + $ip = Request::ip(); + $message = (string) trans('email.failed_login_message', ['ip' => $ip, 'email' => $this->user->email]); return new SlackMessage()->content($message); } diff --git a/app/Providers/AccountServiceProvider.php b/app/Providers/AccountServiceProvider.php index 311aae4bba..caa4ffe49f 100644 --- a/app/Providers/AccountServiceProvider.php +++ b/app/Providers/AccountServiceProvider.php @@ -59,8 +59,7 @@ class AccountServiceProvider extends ServiceProvider private function registerRepository(): void { $this->app->bind( - AccountRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): AccountRepositoryInterface { /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepository::class); @@ -74,8 +73,7 @@ class AccountServiceProvider extends ServiceProvider ); $this->app->bind( - OperationsRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): OperationsRepositoryInterface { /** @var OperationsRepository $repository */ $repository = app(OperationsRepository::class); @@ -95,8 +93,7 @@ class AccountServiceProvider extends ServiceProvider private function registerTasker(): void { $this->app->bind( - AccountTaskerInterface::class, - static function (Application $app) { + static function (Application $app): AccountTaskerInterface { /** @var AccountTaskerInterface $tasker */ $tasker = app(AccountTasker::class); diff --git a/app/Providers/AdminServiceProvider.php b/app/Providers/AdminServiceProvider.php index ac768ddb9d..a775515130 100644 --- a/app/Providers/AdminServiceProvider.php +++ b/app/Providers/AdminServiceProvider.php @@ -54,8 +54,7 @@ class AdminServiceProvider extends ServiceProvider private function linkType(): void { $this->app->bind( - LinkTypeRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): LinkTypeRepositoryInterface { /** @var LinkTypeRepository $repository */ $repository = app(LinkTypeRepository::class); // reference to auth is not understood by phpstan. diff --git a/app/Providers/AttachmentServiceProvider.php b/app/Providers/AttachmentServiceProvider.php index 50a00766fe..4b653f5b69 100644 --- a/app/Providers/AttachmentServiceProvider.php +++ b/app/Providers/AttachmentServiceProvider.php @@ -46,8 +46,7 @@ class AttachmentServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - AttachmentRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): AttachmentRepositoryInterface { /** @var AttachmentRepositoryInterface $repository */ $repository = app(AttachmentRepository::class); // reference to auth is not understood by phpstan. diff --git a/app/Providers/BillServiceProvider.php b/app/Providers/BillServiceProvider.php index 2035762a51..0a5472304d 100644 --- a/app/Providers/BillServiceProvider.php +++ b/app/Providers/BillServiceProvider.php @@ -46,8 +46,7 @@ class BillServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - BillRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): BillRepositoryInterface { /** @var BillRepositoryInterface $repository */ $repository = app(BillRepository::class); diff --git a/app/Providers/BudgetServiceProvider.php b/app/Providers/BudgetServiceProvider.php index 25184a1aac..a6bc575d31 100644 --- a/app/Providers/BudgetServiceProvider.php +++ b/app/Providers/BudgetServiceProvider.php @@ -57,8 +57,7 @@ class BudgetServiceProvider extends ServiceProvider { // reference to auth is not understood by phpstan. $this->app->bind( - BudgetRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): BudgetRepositoryInterface { /** @var BudgetRepositoryInterface $repository */ $repository = app(BudgetRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -71,8 +70,7 @@ class BudgetServiceProvider extends ServiceProvider // available budget repos $this->app->bind( - AvailableBudgetRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): AvailableBudgetRepositoryInterface { /** @var AvailableBudgetRepositoryInterface $repository */ $repository = app(AvailableBudgetRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -85,8 +83,7 @@ class BudgetServiceProvider extends ServiceProvider // budget limit repository. $this->app->bind( - BudgetLimitRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): BudgetLimitRepositoryInterface { /** @var BudgetLimitRepositoryInterface $repository */ $repository = app(BudgetLimitRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -99,8 +96,7 @@ class BudgetServiceProvider extends ServiceProvider // no budget repos $this->app->bind( - NoBudgetRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): NoBudgetRepositoryInterface { /** @var NoBudgetRepositoryInterface $repository */ $repository = app(NoBudgetRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -113,8 +109,7 @@ class BudgetServiceProvider extends ServiceProvider // operations repos $this->app->bind( - OperationsRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): OperationsRepositoryInterface { /** @var OperationsRepositoryInterface $repository */ $repository = app(OperationsRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line diff --git a/app/Providers/CategoryServiceProvider.php b/app/Providers/CategoryServiceProvider.php index 2ab8db6ff5..6346fea046 100644 --- a/app/Providers/CategoryServiceProvider.php +++ b/app/Providers/CategoryServiceProvider.php @@ -51,8 +51,7 @@ class CategoryServiceProvider extends ServiceProvider { // phpstan does not understand reference to 'auth'. $this->app->bind( - CategoryRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): CategoryRepositoryInterface { /** @var CategoryRepository $repository */ $repository = app(CategoryRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -64,8 +63,7 @@ class CategoryServiceProvider extends ServiceProvider ); $this->app->bind( - OperationsRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): OperationsRepositoryInterface { /** @var OperationsRepository $repository */ $repository = app(OperationsRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line @@ -77,8 +75,7 @@ class CategoryServiceProvider extends ServiceProvider ); $this->app->bind( - NoCategoryRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): NoCategoryRepositoryInterface { /** @var NoCategoryRepository $repository */ $repository = app(NoCategoryRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line diff --git a/app/Providers/CurrencyServiceProvider.php b/app/Providers/CurrencyServiceProvider.php index 6ffb3688f7..3b6a751b64 100644 --- a/app/Providers/CurrencyServiceProvider.php +++ b/app/Providers/CurrencyServiceProvider.php @@ -25,7 +25,6 @@ namespace FireflyIII\Providers; use FireflyIII\Repositories\Currency\CurrencyRepository; use FireflyIII\Repositories\Currency\CurrencyRepository as GroupCurrencyRepository; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface as GroupCurrencyRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepository; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; @@ -50,8 +49,7 @@ class CurrencyServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - CurrencyRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): GroupCurrencyRepositoryInterface { /** @var CurrencyRepository $repository */ $repository = app(CurrencyRepository::class); // phpstan does not get the reference to auth @@ -63,8 +61,7 @@ class CurrencyServiceProvider extends ServiceProvider } ); $this->app->bind( - GroupCurrencyRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): GroupCurrencyRepositoryInterface { /** @var GroupCurrencyRepository $repository */ $repository = app(GroupCurrencyRepository::class); // phpstan does not get the reference to auth @@ -77,8 +74,7 @@ class CurrencyServiceProvider extends ServiceProvider ); $this->app->bind( - ExchangeRateRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): ExchangeRateRepositoryInterface { /** @var ExchangeRateRepository $repository */ $repository = app(ExchangeRateRepository::class); // phpstan does not get the reference to auth diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index b016fe0e4d..3776b71f10 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -31,6 +31,7 @@ use FireflyIII\Events\Model\BudgetLimit\Created; use FireflyIII\Events\Model\BudgetLimit\Deleted; use FireflyIII\Events\Model\BudgetLimit\Updated; use FireflyIII\Events\Model\PiggyBank\ChangedAmount; +use FireflyIII\Events\Model\PiggyBank\ChangedName; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\NewVersionAvailable; @@ -210,6 +211,9 @@ class EventServiceProvider extends ServiceProvider ChangedAmount::class => [ 'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount', ], + ChangedName::class => [ + 'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName', + ], // budget related events: CRUD budget limit Created::class => [ diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 83b4c1e585..02ff3d729b 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -163,8 +163,7 @@ class FireflyServiceProvider extends ServiceProvider $this->app->bind(ALERepositoryInterface::class, ALERepository::class); $this->app->bind( - ObjectGroupRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): ObjectGroupRepositoryInterface { /** @var ObjectGroupRepository $repository */ $repository = app(ObjectGroupRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -176,8 +175,7 @@ class FireflyServiceProvider extends ServiceProvider ); $this->app->bind( - WebhookRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): WebhookRepositoryInterface { /** @var WebhookRepository $repository */ $repository = app(WebhookRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -190,8 +188,7 @@ class FireflyServiceProvider extends ServiceProvider // rule expression language $this->app->singleton( - ExpressionLanguage::class, - static function () { + static function (): ExpressionLanguage { $expressionLanguage = new ExpressionLanguage(); $expressionLanguage->registerProvider(new ActionExpressionLanguageProvider()); @@ -200,8 +197,7 @@ class FireflyServiceProvider extends ServiceProvider ); $this->app->bind( - RuleEngineInterface::class, - static function (Application $app) { + static function (Application $app): RuleEngineInterface { /** @var SearchRuleEngine $engine */ $engine = app(SearchRuleEngine::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -213,8 +209,7 @@ class FireflyServiceProvider extends ServiceProvider ); $this->app->bind( - UserGroupRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): UserGroupRepositoryInterface { /** @var UserGroupRepository $repository */ $repository = app(UserGroupRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/JournalServiceProvider.php b/app/Providers/JournalServiceProvider.php index 3c02bbaed4..ac27b169ba 100644 --- a/app/Providers/JournalServiceProvider.php +++ b/app/Providers/JournalServiceProvider.php @@ -64,8 +64,7 @@ class JournalServiceProvider extends ServiceProvider private function registerRepository(): void { $this->app->bind( - JournalRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): JournalRepositoryInterface { /** @var JournalRepositoryInterface $repository */ $repository = app(JournalRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -78,8 +77,7 @@ class JournalServiceProvider extends ServiceProvider // also bind new API repository $this->app->bind( - JournalAPIRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): JournalAPIRepositoryInterface { /** @var JournalAPIRepositoryInterface $repository */ $repository = app(JournalAPIRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -92,8 +90,7 @@ class JournalServiceProvider extends ServiceProvider // also bind new CLI repository $this->app->bind( - JournalCLIRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): JournalCLIRepositoryInterface { /** @var JournalCLIRepositoryInterface $repository */ $repository = app(JournalCLIRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -111,8 +108,7 @@ class JournalServiceProvider extends ServiceProvider private function registerGroupRepository(): void { $this->app->bind( - TransactionGroupRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): TransactionGroupRepositoryInterface { /** @var TransactionGroupRepositoryInterface $repository */ $repository = app(TransactionGroupRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) @@ -127,8 +123,7 @@ class JournalServiceProvider extends ServiceProvider private function registerGroupCollector(): void { $this->app->bind( - GroupCollectorInterface::class, - static function (Application $app) { + static function (Application $app): GroupCollectorInterface { /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollector::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/PiggyBankServiceProvider.php b/app/Providers/PiggyBankServiceProvider.php index c89fe9c6d0..99020bc2e3 100644 --- a/app/Providers/PiggyBankServiceProvider.php +++ b/app/Providers/PiggyBankServiceProvider.php @@ -46,8 +46,7 @@ class PiggyBankServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - PiggyBankRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): PiggyBankRepositoryInterface { /** @var PiggyBankRepository $repository */ $repository = app(PiggyBankRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/RecurringServiceProvider.php b/app/Providers/RecurringServiceProvider.php index b9aeed4c4f..a8184d735f 100644 --- a/app/Providers/RecurringServiceProvider.php +++ b/app/Providers/RecurringServiceProvider.php @@ -46,8 +46,7 @@ class RecurringServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - RecurringRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): RecurringRepositoryInterface { /** @var RecurringRepositoryInterface $repository */ $repository = app(RecurringRepository::class); diff --git a/app/Providers/RuleGroupServiceProvider.php b/app/Providers/RuleGroupServiceProvider.php index df76177faf..32fa85b17e 100644 --- a/app/Providers/RuleGroupServiceProvider.php +++ b/app/Providers/RuleGroupServiceProvider.php @@ -46,8 +46,7 @@ class RuleGroupServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - RuleGroupRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): RuleGroupRepositoryInterface { /** @var RuleGroupRepository $repository */ $repository = app(RuleGroupRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/RuleServiceProvider.php b/app/Providers/RuleServiceProvider.php index 6c3df05f49..e7b235588f 100644 --- a/app/Providers/RuleServiceProvider.php +++ b/app/Providers/RuleServiceProvider.php @@ -46,8 +46,7 @@ class RuleServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - RuleRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): RuleRepositoryInterface { /** @var RuleRepository $repository */ $repository = app(RuleRepository::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/SearchServiceProvider.php b/app/Providers/SearchServiceProvider.php index 93b96a4b97..baf32f811b 100644 --- a/app/Providers/SearchServiceProvider.php +++ b/app/Providers/SearchServiceProvider.php @@ -49,8 +49,7 @@ class SearchServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - QueryParserInterface::class, - static function (): GdbotsQueryParser|QueryParser { + static function (): QueryParserInterface { $implementation = config('search.query_parser'); return match ($implementation) { @@ -61,8 +60,7 @@ class SearchServiceProvider extends ServiceProvider ); $this->app->bind( - SearchInterface::class, - static function (Application $app) { + static function (Application $app): SearchInterface { /** @var OperatorQuerySearch $search */ $search = app(OperatorQuerySearch::class); if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) diff --git a/app/Providers/TagServiceProvider.php b/app/Providers/TagServiceProvider.php index 0b11619c22..85b9b85cfe 100644 --- a/app/Providers/TagServiceProvider.php +++ b/app/Providers/TagServiceProvider.php @@ -48,8 +48,7 @@ class TagServiceProvider extends ServiceProvider public function register(): void { $this->app->bind( - TagRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): TagRepositoryInterface { /** @var TagRepository $repository */ $repository = app(TagRepository::class); @@ -62,8 +61,7 @@ class TagServiceProvider extends ServiceProvider ); $this->app->bind( - OperationsRepositoryInterface::class, - static function (Application $app) { + static function (Application $app): OperationsRepositoryInterface { /** @var OperationsRepository $repository */ $repository = app(OperationsRepository::class); diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index fdff8e8de0..3da904540d 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\PiggyBank; use FireflyIII\Events\Model\PiggyBank\ChangedAmount; +use FireflyIII\Events\Model\PiggyBank\ChangedName; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\PiggyBankFactory; use FireflyIII\Models\Account; @@ -66,7 +67,7 @@ trait ModifiesPiggyBanks { $currentAmount = $this->getCurrentAmount($piggyBank, $account); $pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot; - $pivot->current_amount = bcsub((string) $currentAmount, $amount); + $pivot->current_amount = bcsub((string)$currentAmount, $amount); $pivot->native_current_amount = null; // also update native_current_amount. @@ -89,7 +90,7 @@ trait ModifiesPiggyBanks { $currentAmount = $this->getCurrentAmount($piggyBank, $account); $pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot; - $pivot->current_amount = bcadd((string) $currentAmount, $amount); + $pivot->current_amount = bcadd((string)$currentAmount, $amount); $pivot->native_current_amount = null; // also update native_current_amount. @@ -121,13 +122,13 @@ trait ModifiesPiggyBanks if (0 !== bccomp($piggyBank->target_amount, '0')) { - $leftToSave = bcsub($piggyBank->target_amount, (string) $savedSoFar); - $maxAmount = 1 === bccomp((string) $leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount; + $leftToSave = bcsub($piggyBank->target_amount, (string)$savedSoFar); + $maxAmount = 1 === bccomp((string)$leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount; Log::debug(sprintf('Left to save: %s', $leftToSave)); Log::debug(sprintf('Maximum amount: %s', $maxAmount)); } - $compare = bccomp($amount, (string) $maxAmount); + $compare = bccomp($amount, (string)$maxAmount); $result = $compare <= 0; Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true))); @@ -139,7 +140,7 @@ trait ModifiesPiggyBanks { $savedSoFar = $this->getCurrentAmount($piggyBank, $account); - return bccomp($amount, (string) $savedSoFar) <= 0; + return bccomp($amount, (string)$savedSoFar) <= 0; } /** @@ -170,7 +171,7 @@ trait ModifiesPiggyBanks if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) { $amount = $max; } - $difference = bcsub($amount, (string) $repetition->current_amount); + $difference = bcsub($amount, (string)$repetition->current_amount); $repetition->current_amount = $amount; $repetition->save(); @@ -211,12 +212,12 @@ trait ModifiesPiggyBanks { $piggyBank = $this->updateProperties($piggyBank, $data); if (array_key_exists('notes', $data)) { - $this->updateNote($piggyBank, (string) $data['notes']); + $this->updateNote($piggyBank, (string)$data['notes']); } // update the order of the piggy bank: $oldOrder = $piggyBank->order; - $newOrder = (int) ($data['order'] ?? $oldOrder); + $newOrder = (int)($data['order'] ?? $oldOrder); if ($oldOrder !== $newOrder) { $this->setOrder($piggyBank, $newOrder); } @@ -233,9 +234,9 @@ trait ModifiesPiggyBanks // if the piggy bank is now smaller than the sum of the money saved, // remove money from all accounts until the piggy bank is the right amount. $currentAmount = $this->getCurrentAmount($piggyBank); - if (1 === bccomp((string) $currentAmount, (string) $piggyBank->target_amount) && 0 !== bccomp((string) $piggyBank->target_amount, '0')) { + if (1 === bccomp((string)$currentAmount, (string)$piggyBank->target_amount) && 0 !== bccomp((string)$piggyBank->target_amount, '0')) { Log::debug(sprintf('Current amount is %s, target amount is %s', $currentAmount, $piggyBank->target_amount)); - $difference = bcsub((string) $piggyBank->target_amount, (string) $currentAmount); + $difference = bcsub((string)$piggyBank->target_amount, (string)$currentAmount); // an amount will be removed, create "negative" event: // Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference)); @@ -248,7 +249,7 @@ trait ModifiesPiggyBanks // update using name: if (array_key_exists('object_group_title', $data)) { - $objectGroupTitle = (string) $data['object_group_title']; + $objectGroupTitle = (string)$data['object_group_title']; if ('' !== $objectGroupTitle) { $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); if (null !== $objectGroup) { @@ -264,7 +265,7 @@ trait ModifiesPiggyBanks // try also with ID: if (array_key_exists('object_group_id', $data)) { - $objectGroupId = (int) ($data['object_group_id'] ?? 0); + $objectGroupId = (int)($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if (null !== $objectGroup) { @@ -282,6 +283,7 @@ trait ModifiesPiggyBanks private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank { if (array_key_exists('name', $data) && '' !== $data['name']) { + event(new ChangedName($piggyBank, $piggyBank->name, $data['name'])); $piggyBank->name = $data['name']; } if (array_key_exists('transaction_currency_id', $data) && is_int($data['transaction_currency_id'])) { @@ -366,14 +368,14 @@ trait ModifiesPiggyBanks foreach ($piggyBank->accounts as $account) { $current = $account->pivot->current_amount; // if this account contains more than the amount, remove the amount and return. - if (1 === bccomp((string) $current, $amount)) { + if (1 === bccomp((string)$current, $amount)) { $this->removeAmount($piggyBank, $account, $amount); return; } // if this account contains less than the amount, remove the current amount, update the amount and continue. $this->removeAmount($piggyBank, $account, $current); - $amount = bcsub($amount, (string) $current); + $amount = bcsub($amount, (string)$current); } } } diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index dbead1a4af..b0b4c86f37 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\PiggyBank; +use FireflyIII\Events\Model\PiggyBank\ChangedAmount; use FireflyIII\User; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; @@ -275,7 +276,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte $amount = '' === $amount ? '0' : $amount; $sum = bcadd($sum, $amount); } - // Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum)); + Log::debug(sprintf('Current amount in piggy bank #%d ("%s") is %s', $piggyBank->id, $piggyBank->name, $sum)); return $sum; } @@ -438,4 +439,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte return $search->take($limit)->get(['piggy_banks.*']); } + + public function resetHistory(PiggyBank $piggyBank): void + { + $piggyBank->piggyBankEvents()->delete(); + foreach ($piggyBank->accounts as $account) { + if (0 !== bccomp('0', $account->pivot->current_amount)) { + event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null)); + } + } + } } diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index a6eff5b1b4..2ac344069c 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -47,6 +47,8 @@ use Illuminate\Support\Collection; */ interface PiggyBankRepositoryInterface { + public function resetHistory(PiggyBank $piggyBank): void; + public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool; public function addAmountToPiggyBank(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): void; diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepository.php b/app/Repositories/TransactionGroup/TransactionGroupRepository.php index 8ca4cfcd8c..1657fd3cf7 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepository.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepository.php @@ -217,7 +217,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, 'link' => $entry->outward, 'group' => $entry->destination->transaction_group_id, 'description' => $entry->destination->description, - 'editable' => 1 === (int) $entry->editable, + 'editable' => 1 === (int)$entry->editable, 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -230,7 +230,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, 'link' => $entry->inward, 'group' => $entry->source->transaction_group_id, 'description' => $entry->source->description, - 'editable' => 1 === (int) $entry->editable, + 'editable' => 1 === (int)$entry->editable, 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -264,7 +264,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, if (null === $transaction->foreign_amount || '' === $transaction->foreign_amount) { return ''; } - if (0 === bccomp('0', (string) $transaction->foreign_amount)) { + if (0 === bccomp('0', (string)$transaction->foreign_amount)) { return ''; } $currency = $transaction->foreignCurrency; @@ -305,7 +305,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, $return = []; foreach ($query as $row) { - $return[$row->name] = new Carbon(json_decode((string) $row->data, true, 512, JSON_THROW_ON_ERROR)); + $return[$row->name] = new Carbon(json_decode((string)$row->data, true, 512, JSON_THROW_ON_ERROR)); } return new NullArrayObject($return); @@ -325,7 +325,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, $return = []; foreach ($query as $row) { - $return[$row->name] = json_decode((string) $row->data); + $return[$row->name] = json_decode((string)$row->data); } return new NullArrayObject($return); @@ -432,4 +432,23 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface, return $service->update($transactionGroup, $data); } + + public function getCompareHash(TransactionGroup $group): string + { + $sum = '0'; + $names = ''; + + /** @var TransactionJournal $journal */ + foreach ($group->transactionJournals as $journal) { + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if (-1 === bccomp('0', (string)$transaction->amount)) { + $sum = bcadd($sum, $transaction->amount); + $names = sprintf('%s%s', $names, $transaction->account->name); + } + } + } + + return hash('sha256', sprintf('%s-%s', $names, $sum)); + } } diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php index 8a77aa7f33..e95cd68f75 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php @@ -49,6 +49,11 @@ interface TransactionGroupRepositoryInterface { public function countAttachments(int $journalId): int; + /** + * Small method that returns a hash that can be used to compare two transaction groups. + */ + public function getCompareHash(TransactionGroup $group): string; + public function destroy(TransactionGroup $group): void; /** diff --git a/app/Services/Internal/Update/JournalUpdateService.php b/app/Services/Internal/Update/JournalUpdateService.php index 025c048965..ca0f41af68 100644 --- a/app/Services/Internal/Update/JournalUpdateService.php +++ b/app/Services/Internal/Update/JournalUpdateService.php @@ -43,6 +43,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Services\Internal\Support\JournalServiceTrait; use FireflyIII\Support\Facades\FireflyConfig; use FireflyIII\Support\NullArrayObject; @@ -58,36 +59,39 @@ class JournalUpdateService { use JournalServiceTrait; - private BillRepositoryInterface $billRepository; + private BillRepositoryInterface $billRepository; private CurrencyRepositoryInterface $currencyRepository; - private array $data; - private ?Account $destinationAccount; - private ?Transaction $destinationTransaction; - private array $metaDate; - private array $metaString; - private ?Account $sourceAccount; - private ?Transaction $sourceTransaction; - private ?TransactionGroup $transactionGroup; - private ?TransactionJournal $transactionJournal; + private TransactionGroupRepositoryInterface $transactionGroupRepository; + private array $data; + private ?Account $destinationAccount; + private ?Transaction $destinationTransaction; + private array $metaDate; + private array $metaString; + private ?Account $sourceAccount; + private ?Transaction $sourceTransaction; + private ?TransactionGroup $transactionGroup; + private ?TransactionJournal $transactionJournal; + private string $startCompareHash = ''; /** * JournalUpdateService constructor. */ public function __construct() { - $this->destinationAccount = null; - $this->destinationTransaction = null; - $this->sourceAccount = null; - $this->sourceTransaction = null; - $this->transactionGroup = null; - $this->transactionJournal = null; - $this->billRepository = app(BillRepositoryInterface::class); - $this->categoryRepository = app(CategoryRepositoryInterface::class); - $this->budgetRepository = app(BudgetRepositoryInterface::class); - $this->tagFactory = app(TagFactory::class); - $this->accountRepository = app(AccountRepositoryInterface::class); - $this->currencyRepository = app(CurrencyRepositoryInterface::class); - $this->metaString = [ + $this->destinationAccount = null; + $this->destinationTransaction = null; + $this->sourceAccount = null; + $this->sourceTransaction = null; + $this->transactionGroup = null; + $this->transactionJournal = null; + $this->billRepository = app(BillRepositoryInterface::class); + $this->categoryRepository = app(CategoryRepositoryInterface::class); + $this->budgetRepository = app(BudgetRepositoryInterface::class); + $this->tagFactory = app(TagFactory::class); + $this->accountRepository = app(AccountRepositoryInterface::class); + $this->currencyRepository = app(CurrencyRepositoryInterface::class); + $this->transactionGroupRepository = app(TransactionGroupRepositoryInterface::class); + $this->metaString = [ 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', @@ -102,7 +106,7 @@ class JournalUpdateService 'external_id', 'external_url', ]; - $this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', + $this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', ]; } @@ -119,10 +123,12 @@ class JournalUpdateService $this->budgetRepository->setUser($transactionGroup->user); $this->tagFactory->setUser($transactionGroup->user); $this->accountRepository->setUser($transactionGroup->user); + $this->transactionGroupRepository->setUser($transactionGroup->user); $this->destinationAccount = null; $this->destinationTransaction = null; $this->sourceAccount = null; $this->sourceTransaction = null; + $this->startCompareHash = $this->transactionGroupRepository->getCompareHash($transactionGroup); } public function setTransactionJournal(TransactionJournal $transactionJournal): void @@ -338,7 +344,7 @@ class JournalUpdateService } $sourceInfo = [ - 'id' => (int) ($this->data['source_id'] ?? null), + 'id' => (int)($this->data['source_id'] ?? null), 'name' => $this->data['source_name'] ?? null, 'iban' => $this->data['source_iban'] ?? null, 'number' => $this->data['source_number'] ?? null, @@ -402,7 +408,7 @@ class JournalUpdateService } $destInfo = [ - 'id' => (int) ($this->data['destination_id'] ?? null), + 'id' => (int)($this->data['destination_id'] ?? null), 'name' => $this->data['destination_name'] ?? null, 'iban' => $this->data['destination_iban'] ?? null, 'number' => $this->data['destination_number'] ?? null, @@ -468,8 +474,8 @@ class JournalUpdateService ) && TransactionTypeEnum::WITHDRAWAL->value === $type ) { - $billId = (int) ($this->data['bill_id'] ?? 0); - $billName = (string) ($this->data['bill_name'] ?? ''); + $billId = (int)($this->data['bill_id'] ?? 0); + $billName = (string)($this->data['bill_name'] ?? ''); $bill = $this->billRepository->findBill($billId, $billName); $this->transactionJournal->bill_id = $bill?->id; Log::debug('Updated bill ID'); @@ -481,7 +487,7 @@ class JournalUpdateService */ private function updateField(string $fieldName): void { - if (array_key_exists($fieldName, $this->data) && '' !== (string) $this->data[$fieldName]) { + if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) { $value = $this->data[$fieldName]; if ('date' === $fieldName) { @@ -557,7 +563,7 @@ class JournalUpdateService { // update notes. if ($this->hasFields(['notes'])) { - $notes = '' === (string) $this->data['notes'] ? null : $this->data['notes']; + $notes = '' === (string)$this->data['notes'] ? null : $this->data['notes']; $this->storeNotes($this->transactionJournal, $notes); } } @@ -605,7 +611,7 @@ class JournalUpdateService foreach ($this->metaDate as $field) { if ($this->hasFields([$field])) { try { - $value = '' === (string) $this->data[$field] ? null : new Carbon($this->data[$field]); + $value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]); } catch (InvalidDateException|InvalidFormatException $e) { // @phpstan-ignore-line Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage())); @@ -673,7 +679,6 @@ class JournalUpdateService return; } - $origSourceTransaction = $this->getSourceTransaction(); $origSourceTransaction->amount = app('steam')->negative($amount); $origSourceTransaction->balance_dirty = true; @@ -705,7 +710,7 @@ class JournalUpdateService $newForeignId = $this->data['foreign_currency_id'] ?? null; $newForeignCode = $this->data['foreign_currency_code'] ?? null; $foreignCurrency = $this->currencyRepository->findCurrencyNull($newForeignId, $newForeignCode) - ?? $foreignCurrency; + ?? $foreignCurrency; // not the same as normal currency if (null !== $foreignCurrency && $foreignCurrency->id === $this->transactionJournal->transaction_currency_id) { @@ -816,4 +821,14 @@ class JournalUpdateService return false; } + + public function isCompareHashChanged(): bool + { + Log::debug(sprintf('Now in %s', __METHOD__)); + $compareHash = $this->transactionGroupRepository->getCompareHash($this->transactionGroup); + Log::debug(sprintf('Compare hash is "%s".', $compareHash)); + Log::debug(sprintf('Start compare hash is "%s".', $this->startCompareHash)); + + return $compareHash !== $this->startCompareHash; + } } diff --git a/app/Support/Cronjobs/RecurringCronjob.php b/app/Support/Cronjobs/RecurringCronjob.php index 995f31e777..cc6bb7f901 100644 --- a/app/Support/Cronjobs/RecurringCronjob.php +++ b/app/Support/Cronjobs/RecurringCronjob.php @@ -28,6 +28,8 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\CreateRecurringTransactions; use FireflyIII\Models\Configuration; +use FireflyIII\Support\Facades\FireflyConfig; +use Illuminate\Support\Facades\Log; /** * Class RecurringCronjob @@ -39,34 +41,34 @@ class RecurringCronjob extends AbstractCronjob */ public function fire(): void { - app('log')->debug(sprintf('Now in %s', __METHOD__)); + Log::debug(sprintf('Now in %s', __METHOD__)); /** @var Configuration $config */ - $config = app('fireflyconfig')->get('last_rt_job', 0); + $config = FireflyConfig::get('last_rt_job', 0); $lastTime = (int) $config->data; $diff = Carbon::now()->getTimestamp() - $lastTime; $diffForHumans = today(config('app.timezone'))->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); if (0 === $lastTime) { - app('log')->info('Recurring transactions cron-job has never fired before.'); + Log::info('Recurring transactions cron-job has never fired before.'); } // less than half a day ago: if ($lastTime > 0 && $diff <= 43200) { - app('log')->info(sprintf('It has been %s since the recurring transactions cron-job has fired.', $diffForHumans)); + Log::info(sprintf('It has been "%s" since the recurring transactions cron-job has fired.', $diffForHumans)); if (false === $this->force) { - app('log')->info('The cron-job will not fire now.'); - $this->message = sprintf('It has been %s since the recurring transactions cron-job has fired. It will not fire now.', $diffForHumans); + Log::info('The cron-job will not fire now.'); + $this->message = sprintf('It has been "%s" since the recurring transactions cron-job has fired. It will not fire now.', $diffForHumans); $this->jobFired = false; $this->jobErrored = false; $this->jobSucceeded = false; return; } - app('log')->info('Execution of the recurring transaction cron-job has been FORCED.'); + Log::info('Execution of the recurring transaction cron-job has been FORCED.'); } if ($lastTime > 0 && $diff > 43200) { - app('log')->info(sprintf('It has been %s since the recurring transactions cron-job has fired. It will fire now!', $diffForHumans)); + Log::info(sprintf('It has been "%s" since the recurring transactions cron-job has fired. It will fire now!', $diffForHumans)); } $this->fireRecurring(); @@ -76,7 +78,7 @@ class RecurringCronjob extends AbstractCronjob private function fireRecurring(): void { - app('log')->info(sprintf('Will now fire recurring cron job task for date "%s".', $this->date->format('Y-m-d H:i:s'))); + Log::info(sprintf('Will now fire recurring cron job task for date "%s".', $this->date->format('Y-m-d H:i:s'))); $job = new CreateRecurringTransactions($this->date); $job->setForce($this->force); @@ -88,8 +90,8 @@ class RecurringCronjob extends AbstractCronjob $this->jobSucceeded = true; $this->message = 'Recurring transactions cron job fired successfully.'; - app('fireflyconfig')->set('last_rt_job', (int) $this->date->format('U')); - app('log')->info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U'))); - app('log')->info('Done with recurring cron job task.'); + FireflyConfig::set('last_rt_job', (int) $this->date->format('U')); + Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U'))); + Log::info('Done with recurring cron job task.'); } } diff --git a/app/Support/FireflyConfig.php b/app/Support/FireflyConfig.php index 832a020951..499b123602 100644 --- a/app/Support/FireflyConfig.php +++ b/app/Support/FireflyConfig.php @@ -39,7 +39,7 @@ class FireflyConfig { public function delete(string $name): void { - $fullName = 'ff-config-'.$name; + $fullName = 'ff3-config-'.$name; if (Cache::has($fullName)) { Cache::forget($fullName); } @@ -81,7 +81,7 @@ class FireflyConfig */ public function get(string $name, mixed $default = null): ?Configuration { - $fullName = 'ff-config-'.$name; + $fullName = 'ff3-config-'.$name; if (Cache::has($fullName)) { return Cache::get($fullName); } diff --git a/app/Support/Http/Api/ExchangeRateConverter.php b/app/Support/Http/Api/ExchangeRateConverter.php index 2149545a69..1ff60dbaaa 100644 --- a/app/Support/Http/Api/ExchangeRateConverter.php +++ b/app/Support/Http/Api/ExchangeRateConverter.php @@ -79,12 +79,12 @@ class ExchangeRateConverter public function getCurrencyRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string { if (false === $this->enabled()) { - Log::debug('ExchangeRateConverter: disabled, return "1".'); + // Log::debug('ExchangeRateConverter: disabled, return "1".'); return '1'; } if ($from->id === $to->id) { - Log::debug('ExchangeRateConverter: From and to are the same, return "1".'); + // Log::debug('ExchangeRateConverter: From and to are the same, return "1".'); return '1'; } diff --git a/app/Support/Http/Controllers/GetConfigurationData.php b/app/Support/Http/Controllers/GetConfigurationData.php index 672a84cfb6..52ce494418 100644 --- a/app/Support/Http/Controllers/GetConfigurationData.php +++ b/app/Support/Http/Controllers/GetConfigurationData.php @@ -26,6 +26,7 @@ namespace FireflyIII\Support\Http\Controllers; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Support\Facades\FireflyConfig; use Illuminate\Support\Facades\Log; /** @@ -205,7 +206,7 @@ trait GetConfigurationData protected function verifyRecurringCronJob(): void { - $config = app('fireflyconfig')->get('last_rt_job', 0); + $config = FireflyConfig::get('last_rt_job', 0); $lastTime = (int) $config?->data; $now = Carbon::now()->getTimestamp(); app('log')->debug(sprintf('verifyRecurringCronJob: last time is %d ("%s"), now is %d', $lastTime, $config?->data, $now)); diff --git a/app/Support/Http/Controllers/PeriodOverview.php b/app/Support/Http/Controllers/PeriodOverview.php index 8104d133e3..1fae6214dd 100644 --- a/app/Support/Http/Controllers/PeriodOverview.php +++ b/app/Support/Http/Controllers/PeriodOverview.php @@ -35,6 +35,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Debug\Timer; +use Illuminate\Support\Facades\Log; /** * Trait PeriodOverview. @@ -77,6 +78,7 @@ trait PeriodOverview */ protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array { + Log::debug('Now in getAccountPeriodOverview()'); Timer::start('account-period-total'); $this->accountRepository = app(AccountRepositoryInterface::class); $range = app('navigation')->getViewRange(true); @@ -100,6 +102,7 @@ trait PeriodOverview $transactions = $this->accountRepository->periodCollection($account, $start, $end); // loop dates + Log::debug(sprintf('Count of loops: %d', count($dates))); foreach ($dates as $currentDate) { $title = app('navigation')->periodShow($currentDate['start'], $currentDate['period']); [$transactions, $spent] = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $transactions, $currentDate['start'], $currentDate['end']); @@ -119,6 +122,7 @@ trait PeriodOverview } $cache->store($entries); Timer::stop('account-period-total'); + Log::debug('End of getAccountPeriodOverview()'); return $entries; } diff --git a/app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php b/app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php index 9bac754a7c..afd96bcf59 100644 --- a/app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php +++ b/app/Support/JsonApi/Enrichments/TransactionGroupEnrichment.php @@ -30,10 +30,12 @@ use FireflyIII\Models\Attachment; use FireflyIII\Models\Location; use FireflyIII\Models\Note; use FireflyIII\Models\Tag; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\UserGroup; +use FireflyIII\Support\Facades\Amount; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; @@ -52,6 +54,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface private array $notes; // @phpstan-ignore-line private array $tags; private User $user; + private TransactionCurrency $nativeCurrency; private UserGroup $userGroup; public function __construct() @@ -63,6 +66,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface $this->locations = []; $this->attachmentCount = []; $this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date']; + $this->nativeCurrency = Amount::getNativeCurrency(); } #[Override] @@ -192,8 +196,9 @@ class TransactionGroupEnrichment implements EnrichmentInterface $metaData = $this->metaData; $locations = $this->locations; $attachmentCount = $this->attachmentCount; + $nativeCurrency = $this->nativeCurrency; - $this->collection = $this->collection->map(function (array $item) use ($notes, $tags, $metaData, $locations, $attachmentCount) { + $this->collection = $this->collection->map(function (array $item) use ($nativeCurrency, $notes, $tags, $metaData, $locations, $attachmentCount) { foreach ($item['transactions'] as $index => $transaction) { $journalId = (int) $transaction['transaction_journal_id']; @@ -213,6 +218,15 @@ class TransactionGroupEnrichment implements EnrichmentInterface 'zoom_level' => null, ]; + // native currency + $item['transactions'][$index]['native_currency'] = [ + 'id' => (string) $nativeCurrency->id, + 'code' => $nativeCurrency->code, + 'name' => $nativeCurrency->name, + 'symbol' => $nativeCurrency->symbol, + 'decimal_places' => $nativeCurrency->decimal_places, + ]; + // append meta data $item['transactions'][$index]['meta'] = []; $item['transactions'][$index]['meta_date'] = []; diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 033081a6ed..40f51114cb 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -278,6 +278,8 @@ class Steam $carbonKey = $carbon->format('Y-m-d'); // make sure sum is a string: $sumOfDay = (string) ($entry->sum_of_day ?? '0'); + // #10426 make sure sum is not in scientific notation. + $sumOfDay = $this->floatalize($sumOfDay); // find currency of this entry, does not have to exist. $currencies[$entry->transaction_currency_id] ??= TransactionCurrency::find($entry->transaction_currency_id); diff --git a/app/TransactionRules/Actions/UpdatePiggyBank.php b/app/TransactionRules/Actions/UpdatePiggyBank.php index 29937334dc..64fe735e6a 100644 --- a/app/TransactionRules/Actions/UpdatePiggyBank.php +++ b/app/TransactionRules/Actions/UpdatePiggyBank.php @@ -67,6 +67,16 @@ class UpdatePiggyBank implements ActionInterface Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name)); + // piggy bank already has an event for this transaction journal? + if ($this->alreadyEventPresent($piggyBank, $journal)) { + Log::info(sprintf('Piggy bank #%d ("%s") already has an event for transaction journal #%d, so no action will be taken.', $piggyBank->id, $piggyBank->name, $journalObj->id)); + + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $actionValue]))); + + return false; + } + + /** @var Transaction $destination */ $destination = $journalObj->transactions()->where('amount', '>', 0)->first(); @@ -231,4 +241,9 @@ class UpdatePiggyBank implements ActionInterface $repository->addAmount($piggyBank, $account, $amount, $journal); } + + private function alreadyEventPresent(PiggyBank $piggyBank, array $journal): bool + { + return $piggyBank->piggyBankEvents()->where('transaction_journal_id', $journal['transaction_journal_id'])->exists(); + } } diff --git a/app/TransactionRules/Engine/SearchRuleEngine.php b/app/TransactionRules/Engine/SearchRuleEngine.php index 385d8bdd14..f8f8700a7e 100644 --- a/app/TransactionRules/Engine/SearchRuleEngine.php +++ b/app/TransactionRules/Engine/SearchRuleEngine.php @@ -64,13 +64,13 @@ class SearchRuleEngine implements RuleEngineInterface public function addOperator(array $operator): void { - app('log')->debug('Add extra operator: ', $operator); + Log::debug('Add extra operator: ', $operator); $this->operators[] = $operator; } public function find(): Collection { - app('log')->debug('SearchRuleEngine::find()'); + Log::debug('SearchRuleEngine::find()'); $collection = new Collection(); foreach ($this->rules as $rule) { $found = new Collection(); @@ -83,7 +83,7 @@ class SearchRuleEngine implements RuleEngineInterface $collection = $collection->merge($found); } $result = $collection->unique(); - app('log')->debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count())); + Log::debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count())); return $result; } @@ -93,7 +93,7 @@ class SearchRuleEngine implements RuleEngineInterface */ private function findStrictRule(Rule $rule): Collection { - app('log')->debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0)); + Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0)); $searchArray = []; $triggers = []; if ($this->refreshTriggers) { @@ -116,18 +116,18 @@ class SearchRuleEngine implements RuleEngineInterface // if the trigger needs no context, value is different: $needsContext = (bool) (config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true); if (false === $needsContext) { - app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type)); + Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type)); $searchArray[$ruleTrigger->trigger_type][] = 'true'; } if (true === $needsContext) { - app('log')->debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value)); + Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (context): %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value)); $searchArray[$ruleTrigger->trigger_type][] = sprintf('"%s"', $ruleTrigger->trigger_value); } } // add local operators: foreach ($this->operators as $operator) { - app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value'])); + Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value'])); $searchArray[$operator['type']][] = sprintf('"%s"', $operator['value']); } $date = today(config('app.timezone')); @@ -141,11 +141,11 @@ class SearchRuleEngine implements RuleEngineInterface $searchEngine->setPage(1); $searchEngine->setLimit(31337); $searchEngine->setDate($date); - app('log')->debug('Search array', $searchArray); + Log::debug('Search array', $searchArray); foreach ($searchArray as $type => $searches) { foreach ($searches as $value) { $query = sprintf('%s:%s', $type, $value); - app('log')->debug(sprintf('SearchRuleEngine:: add query "%s"', $query)); + Log::debug(sprintf('SearchRuleEngine:: add query "%s"', $query)); $searchEngine->parseQuery($query); } } @@ -162,33 +162,33 @@ class SearchRuleEngine implements RuleEngineInterface */ private function hasSpecificJournalTrigger(array $array): bool { - app('log')->debug('Now in hasSpecificJournalTrigger.'); + Log::debug('Now in hasSpecificJournalTrigger.'); $journalTrigger = false; $dateTrigger = false; foreach ($array as $triggerName => $values) { if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) { - app('log')->debug('Found a journal_id trigger with 1 journal, true.'); + Log::debug('Found a journal_id trigger with 1 journal, true.'); $journalTrigger = true; } if (in_array($triggerName, ['date_is', 'date', 'on', 'date_before', 'before', 'date_after', 'after'], true)) { - app('log')->debug('Found a date related trigger, set to true.'); + Log::debug('Found a date related trigger, set to true.'); $dateTrigger = true; } } $result = $journalTrigger && $dateTrigger; - app('log')->debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true))); + Log::debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true))); return $result; } private function setDateFromJournalTrigger(array $array): Carbon { - app('log')->debug('Now in setDateFromJournalTrigger()'); + Log::debug('Now in setDateFromJournalTrigger()'); $journalId = 0; foreach ($array as $triggerName => $values) { if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) { $journalId = (int) trim($values[0] ?? '"0"', '"'); // follows format "123". - app('log')->debug(sprintf('Found journal ID #%d', $journalId)); + Log::debug(sprintf('Found journal ID #%d', $journalId)); } } if (0 !== $journalId) { @@ -197,12 +197,12 @@ class SearchRuleEngine implements RuleEngineInterface $journal = $repository->find($journalId); if (null !== $journal) { $date = $journal->date; - app('log')->debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d'))); + Log::debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d'))); return $date; } } - app('log')->debug('Found no journal, return default date.'); + Log::debug('Found no journal, return default date.'); return today(config('app.timezone')); } @@ -215,48 +215,48 @@ class SearchRuleEngine implements RuleEngineInterface private function findNonStrictRule(Rule $rule): Collection { - app('log')->debug(sprintf('findNonStrictRule(#%d)', $rule->id)); + Log::debug(sprintf('findNonStrictRule(#%d)', $rule->id)); // start a search query for individual each trigger: $total = new Collection(); $count = 0; $triggers = []; if ($this->refreshTriggers) { - app('log')->debug('Will refresh triggers.'); + Log::debug('Will refresh triggers.'); $triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get(); } if (!$this->refreshTriggers) { - app('log')->debug('Will not refresh triggers.'); + Log::debug('Will not refresh triggers.'); $triggers = $rule->ruleTriggers; } - app('log')->debug(sprintf('Will run %d trigger(s).', count($triggers))); + Log::debug(sprintf('Will run %d trigger(s).', count($triggers))); /** @var RuleTrigger $ruleTrigger */ foreach ($triggers as $ruleTrigger) { - app('log')->debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true))); + Log::debug(sprintf('Now at rule trigger #%d: %s:"%s" (%s).', $ruleTrigger->id, $ruleTrigger->trigger_type, $ruleTrigger->trigger_value, var_export($ruleTrigger->stop_processing, true))); if (false === $ruleTrigger->active) { - app('log')->debug('Trigger is not active, continue.'); + Log::debug('Trigger is not active, continue.'); continue; } if ('user_action' === $ruleTrigger->trigger_type) { - app('log')->debug('Skip trigger type. continue.'); + Log::debug('Skip trigger type. continue.'); continue; } $searchArray = []; $needsContext = config(sprintf('search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true; if (false === $needsContext) { - app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type)); + Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:true', $ruleTrigger->trigger_type)); $searchArray[$ruleTrigger->trigger_type] = 'true'; } if (true === $needsContext) { - app('log')->debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value)); + Log::debug(sprintf('SearchRuleEngine:: non strict, will search for: %s:"%s"', $ruleTrigger->trigger_type, $ruleTrigger->trigger_value)); $searchArray[$ruleTrigger->trigger_type] = sprintf('"%s"', $ruleTrigger->trigger_value); } // then, add local operators as well: foreach ($this->operators as $operator) { - app('log')->debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value'])); + Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value'])); $searchArray[$operator['type']] = sprintf('"%s"', $operator['value']); } @@ -272,19 +272,19 @@ class SearchRuleEngine implements RuleEngineInterface $result = $searchEngine->searchTransactions(); $collection = $result->getCollection(); - app('log')->debug(sprintf('Found in this run, %d transactions', $collection->count())); + Log::debug(sprintf('Found in this run, %d transactions', $collection->count())); $total = $total->merge($collection); - app('log')->debug(sprintf('Total collection is now %d transactions', $total->count())); + Log::debug(sprintf('Total collection is now %d transactions', $total->count())); ++$count; // if trigger says stop processing, do so. if (true === $ruleTrigger->stop_processing && $result->count() > 0) { - app('log')->debug('The trigger says to stop processing, so stop processing other triggers.'); + Log::debug('The trigger says to stop processing, so stop processing other triggers.'); break; } } - app('log')->debug(sprintf('Total collection is now %d transactions', $total->count())); - app('log')->debug(sprintf('Done running %d trigger(s)', $count)); + Log::debug(sprintf('Total collection is now %d transactions', $total->count())); + Log::debug(sprintf('Done running %d trigger(s)', $count)); // make collection unique $unique = $total->unique( @@ -295,11 +295,11 @@ class SearchRuleEngine implements RuleEngineInterface } return sprintf('%d%s', $group['id'], $str); - // app('log')->debug(sprintf('Return key: %s ', $key)); + // Log::debug(sprintf('Return key: %s ', $key)); } ); - app('log')->debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count())); + Log::debug(sprintf('SearchRuleEngine:: Found %d transactions using search engine.', $unique->count())); return $unique; } @@ -310,28 +310,28 @@ class SearchRuleEngine implements RuleEngineInterface public function fire(): void { $this->resultCount = []; - app('log')->debug('SearchRuleEngine::fire()!'); + Log::debug('SearchRuleEngine::fire()!'); // if rules and no rule groups, file each rule separately. if (0 !== $this->rules->count()) { - app('log')->debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count())); + Log::debug(sprintf('SearchRuleEngine:: found %d rule(s) to fire.', $this->rules->count())); /** @var Rule $rule */ foreach ($this->rules as $rule) { $result = $this->fireRule($rule); if (true === $result && true === $rule->stop_processing) { - app('log')->debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id)); + Log::debug(sprintf('Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.', $rule->id)); } if (false === $result && true === $rule->stop_processing) { - app('log')->debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id)); + Log::debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id)); } } - app('log')->debug('SearchRuleEngine:: done processing all rules!'); + Log::debug('SearchRuleEngine:: done processing all rules!'); return; } if (0 !== $this->groups->count()) { - app('log')->debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count())); + Log::debug(sprintf('SearchRuleEngine:: found %d rule group(s) to fire.', $this->groups->count())); // fire each group: /** @var RuleGroup $group */ @@ -339,7 +339,7 @@ class SearchRuleEngine implements RuleEngineInterface $this->fireGroup($group); } } - app('log')->debug('SearchRuleEngine:: done processing all rules!'); + Log::debug('SearchRuleEngine:: done processing all rules!'); } /** @@ -349,18 +349,18 @@ class SearchRuleEngine implements RuleEngineInterface */ private function fireRule(Rule $rule): bool { - app('log')->debug(sprintf('Now going to fire rule #%d', $rule->id)); + Log::debug(sprintf('Now going to fire rule #%d', $rule->id)); if (false === $rule->active) { - app('log')->debug(sprintf('Rule #%d is not active!', $rule->id)); + Log::debug(sprintf('Rule #%d is not active!', $rule->id)); return false; } if (true === $rule->strict) { - app('log')->debug(sprintf('Rule #%d is a strict rule.', $rule->id)); + Log::debug(sprintf('Rule #%d is a strict rule.', $rule->id)); return $this->fireStrictRule($rule); } - app('log')->debug(sprintf('Rule #%d is not strict rule.', $rule->id)); + Log::debug(sprintf('Rule #%d is not strict rule.', $rule->id)); return $this->fireNonStrictRule($rule); } @@ -372,19 +372,19 @@ class SearchRuleEngine implements RuleEngineInterface */ private function fireStrictRule(Rule $rule): bool { - app('log')->debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id)); + Log::debug(sprintf('SearchRuleEngine::fireStrictRule(%d)!', $rule->id)); $collection = $this->findStrictRule($rule); $this->processResults($rule, $collection); - app('log')->debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id)); + Log::debug(sprintf('SearchRuleEngine:: done processing strict rule #%d', $rule->id)); $result = $collection->count() > 0; if (true === $result) { - app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count())); + Log::debug(sprintf('SearchRuleEngine:: rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count())); return true; } - app('log')->debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count())); + Log::debug(sprintf('SearchRuleEngine:: rule #%d was not triggered (on %d transaction(s)).', $rule->id, $collection->count())); return false; } @@ -394,7 +394,7 @@ class SearchRuleEngine implements RuleEngineInterface */ private function processResults(Rule $rule, Collection $collection): void { - app('log')->debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count())); + Log::debug(sprintf('SearchRuleEngine:: Going to process %d results.', $collection->count())); /** @var array $group */ foreach ($collection as $group) { @@ -407,7 +407,7 @@ class SearchRuleEngine implements RuleEngineInterface */ private function processTransactionGroup(Rule $rule, array $group): void { - app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id'])); + Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction group #%d', $group['id'])); /** @var array $transaction */ foreach ($group['transactions'] as $transaction) { @@ -420,7 +420,7 @@ class SearchRuleEngine implements RuleEngineInterface */ private function processTransactionJournal(Rule $rule, array $transaction): void { - app('log')->debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id'])); + Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id'])); $actions = $rule->ruleActions()->orderBy('order', 'ASC')->get(); /** @var RuleAction $ruleAction */ @@ -440,14 +440,14 @@ class SearchRuleEngine implements RuleEngineInterface */ private function processRuleAction(RuleAction $ruleAction, array $transaction): bool { - app('log')->debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value)); + Log::debug(sprintf('Executing rule action "%s" with value "%s"', $ruleAction->action_type, $ruleAction->action_value)); $transaction = $this->addNotes($transaction); $actionClass = ActionFactory::getAction($ruleAction); $result = $actionClass->actOnArray($transaction); $journalId = $transaction['transaction_journal_id'] ?? 0; if (true === $result) { $this->resultCount[$journalId] = array_key_exists($journalId, $this->resultCount) ? $this->resultCount[$journalId]++ : 1; - app('log')->debug( + Log::debug( sprintf( 'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.', $ruleAction->action_type, @@ -457,17 +457,17 @@ class SearchRuleEngine implements RuleEngineInterface ); } if (false === $result) { - app('log')->debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type)); + Log::debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type)); } // pick up from the action if it actually acted or not: if (true === $ruleAction->stop_processing && true === $result) { - app('log')->debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type)); + Log::debug(sprintf('Rule action "%s" reports changes AND asks to break, so break!', $ruleAction->action_type)); return true; } if (true === $ruleAction->stop_processing && false === $result) { - app('log')->debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type)); + Log::debug(sprintf('Rule action "%s" reports NO changes AND asks to break, but we wont break!', $ruleAction->action_type)); } return false; @@ -492,11 +492,11 @@ class SearchRuleEngine implements RuleEngineInterface */ private function fireNonStrictRule(Rule $rule): bool { - app('log')->debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id)); + Log::debug(sprintf('SearchRuleEngine::fireNonStrictRule(%d)!', $rule->id)); $collection = $this->findNonStrictRule($rule); $this->processResults($rule, $collection); - app('log')->debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id)); + Log::debug(sprintf('SearchRuleEngine:: done processing non-strict rule #%d', $rule->id)); return $collection->count() > 0; } @@ -506,14 +506,14 @@ class SearchRuleEngine implements RuleEngineInterface */ private function fireGroup(RuleGroup $group): void { - app('log')->debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count())); + Log::debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $group->rules->count())); /** @var Rule $rule */ foreach ($group->rules as $rule) { - app('log')->debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id)); + Log::debug(sprintf('Going to fire rule #%d from group #%d', $rule->id, $group->id)); $result = $this->fireRule($rule); if (true === $result && true === $rule->stop_processing) { - app('log')->debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id)); + Log::debug(sprintf('The rule was triggered and rule->stop_processing = true, so group #%d will stop processing further rules.', $group->id)); return; } @@ -535,10 +535,10 @@ class SearchRuleEngine implements RuleEngineInterface public function setRuleGroups(Collection $ruleGroups): void { - app('log')->debug(__METHOD__); + Log::debug(__METHOD__); foreach ($ruleGroups as $group) { if ($group instanceof RuleGroup) { - app('log')->debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title)); + Log::debug(sprintf('Adding a rule group to the SearchRuleEngine: #%d ("%s")', $group->id, $group->title)); $this->groups->push($group); } } @@ -546,10 +546,10 @@ class SearchRuleEngine implements RuleEngineInterface public function setRules(Collection $rules): void { - app('log')->debug(__METHOD__); + Log::debug(__METHOD__); foreach ($rules as $rule) { if ($rule instanceof Rule) { - app('log')->debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title)); + Log::debug(sprintf('Adding a rule to the SearchRuleEngine: #%d ("%s")', $rule->id, $rule->title)); $this->rules->push($rule); } } diff --git a/app/Transformers/PiggyBankEventTransformer.php b/app/Transformers/PiggyBankEventTransformer.php index a125415676..07202d4d97 100644 --- a/app/Transformers/PiggyBankEventTransformer.php +++ b/app/Transformers/PiggyBankEventTransformer.php @@ -73,8 +73,8 @@ class PiggyBankEventTransformer extends AbstractTransformer return [ 'id' => (string) $event->id, - 'created_at' => $event->created_at->toAtomString(), - 'updated_at' => $event->updated_at->toAtomString(), + 'created_at' => $event->created_at?->toAtomString(), + 'updated_at' => $event->updated_at?->toAtomString(), 'amount' => app('steam')->bcround($event->amount, $currency->decimal_places), 'currency_id' => (string) $currency->id, 'currency_code' => $currency->code, diff --git a/app/Transformers/TransactionGroupTransformer.php b/app/Transformers/TransactionGroupTransformer.php index ef5f8213c8..8685c0246a 100644 --- a/app/Transformers/TransactionGroupTransformer.php +++ b/app/Transformers/TransactionGroupTransformer.php @@ -144,12 +144,38 @@ class TransactionGroupTransformer extends AbstractTransformer 'foreign_currency_id' => $this->stringFromArray($transaction, 'foreign_currency_id', null), 'foreign_currency_code' => $transaction['foreign_currency_code'], + 'foreign_currency_name' => $transaction['foreign_currency_name'], 'foreign_currency_symbol' => $transaction['foreign_currency_symbol'], 'foreign_currency_decimal_places' => $transaction['foreign_currency_decimal_places'], 'amount' => $amount, 'foreign_amount' => $foreignAmount, + // native amount, defaults to NULL when convertToNative is false. + 'native_amount' => $transaction['native_amount'] ?? null, + + // native currency, always present. + 'native_currency_id' => $transaction['native_currency']['id'] ?? null, + 'native_currency_code' => $transaction['native_currency']['code'] ?? null, + 'native_currency_name' => $transaction['native_currency']['name'] ?? null, + 'native_currency_symbol' => $transaction['native_currency']['symbol'] ?? null, + 'native_currency_decimal_places' => $transaction['native_currency']['decimal_places'] ?? null, + + // source balance after + 'source_balance_after' => $transaction['source_balance_after'] ?? null, + 'source_balance_dirty' => $transaction['source_balance_dirty'], + + // destination balance after + 'destination_balance_after' => $transaction['destination_balance_after'] ?? null, + 'destination_balance_dirty' => $transaction['destination_balance_dirty'], + + // balance before and after, if not dirty. + // 'running_balance_dirty' => $transaction['balance_dirty'] ?? false, + // 'running_balance_before' => $transaction['balance_before'] ?? null, + // 'running_balance_after' => $transaction['balance_after'] ?? null, + + + 'description' => $transaction['description'], 'source_id' => (string) $transaction['source_account_id'], diff --git a/app/User.php b/app/User.php index 46a0041ec3..fd7221c9ef 100644 --- a/app/User.php +++ b/app/User.php @@ -73,13 +73,6 @@ class User extends Authenticatable use HasApiTokens; use Notifiable; use ReturnsIntegerIdTrait; - - protected $casts - = [ - 'created_at' => 'datetime', - 'updated_at' => 'datetime', - 'blocked' => 'boolean', - ]; protected $fillable = ['email', 'password', 'blocked', 'blocked_code']; protected $hidden = ['password', 'remember_token']; protected $table = 'users'; @@ -539,4 +532,13 @@ class User extends Authenticatable { return $this->hasMany(Webhook::class); } + + protected function casts(): array + { + return [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'blocked' => 'boolean', + ]; + } } diff --git a/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php b/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php index 8f8cffba91..89ea275b39 100644 --- a/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php +++ b/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace FireflyIII\Validation\Api\Data\Bulk; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use Illuminate\Validation\Validator; use function Safe\json_decode; diff --git a/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php b/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php index 581e0da61c..1967857616 100644 --- a/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php +++ b/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Validation\AutoBudget; -use Illuminate\Validation\Validator; +use Illuminate\Contracts\Validation\Validator; /** * Trait ValidatesAutoBudgetRequest diff --git a/app/Validation/CurrencyValidation.php b/app/Validation/CurrencyValidation.php index 52bad8ff61..bc4711ba9e 100644 --- a/app/Validation/CurrencyValidation.php +++ b/app/Validation/CurrencyValidation.php @@ -24,8 +24,8 @@ declare(strict_types=1); namespace FireflyIII\Validation; +use Illuminate\Contracts\Validation\Validator; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Trait CurrencyValidation diff --git a/app/Validation/GroupValidation.php b/app/Validation/GroupValidation.php index 84c32cfc90..7a8176f7ec 100644 --- a/app/Validation/GroupValidation.php +++ b/app/Validation/GroupValidation.php @@ -24,10 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Validation; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionGroup; -use Illuminate\Validation\Validator; /** * Trait GroupValidation. diff --git a/app/Validation/RecurrenceValidation.php b/app/Validation/RecurrenceValidation.php index 52b829203e..9ec2ccd3ab 100644 --- a/app/Validation/RecurrenceValidation.php +++ b/app/Validation/RecurrenceValidation.php @@ -24,10 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Validation; +use Illuminate\Contracts\Validation\Validator; use Carbon\Carbon; use FireflyIII\Models\Recurrence; use FireflyIII\Models\RecurrenceTransaction; -use Illuminate\Validation\Validator; use InvalidArgumentException; /** diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php index b03511f193..c56c976c16 100644 --- a/app/Validation/TransactionValidation.php +++ b/app/Validation/TransactionValidation.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Validation; +use Illuminate\Contracts\Validation\Validator; use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Exceptions\FireflyException; @@ -36,7 +37,6 @@ use FireflyIII\Repositories\Account\AccountRepository; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Facades\Log; -use Illuminate\Validation\Validator; /** * Trait TransactionValidation diff --git a/changelog.md b/changelog.md index 572d31300c..e53b6b132d 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 6.2.17 - 2025-06-12 + +### Changed + +- Firefly III will trim account numbers with spaces for better matching during imports +- Running balance is only updated when amounts or accounts change. + +### Fixed + +- Transactions can't be linked to a piggy bank twice. +- [Issue 10229](https://github.com/firefly-iii/firefly-iii/issues/10229) (Please show transaction ID in the Meta information) reported by @srikakulamts +- [Issue 10382](https://github.com/firefly-iii/firefly-iii/issues/10382) (Have a link to search page on mobile layout) reported by @sergeolkhovik +- [Issue 10399](https://github.com/firefly-iii/firefly-iii/issues/10399) (Can not apply rules to future dates) reported by @sanderr +- [Issue 10403](https://github.com/firefly-iii/firefly-iii/issues/10403) (Piggy banks over multiple accounts are too restrictive) reported by @sanderr +- [Issue 10413](https://github.com/firefly-iii/firefly-iii/issues/10413) (Piggy Bank math seems broken, deductions are not registered, Saved so far 0 but balance is positive) reported by @Skiri-ki +- [Issue 10419](https://github.com/firefly-iii/firefly-iii/issues/10419) (Add quarters to report view to prefill date ranges) reported by @othmar52 +- [Issue 10426](https://github.com/firefly-iii/firefly-iii/issues/10426) (bcadd(): Argument #1 ($num1) is not well-formed) reported by @grgar +- [Discussion 10427](https://github.com/orgs/firefly-iii/discussions/10427) ("Stop processing" doesn't seem to work? (6.2.12)) started by @rarosalion +- [Issue 10432](https://github.com/firefly-iii/firefly-iii/issues/10432) (Error during upgrade 6.1.25 → 6.2.16: $piggyBank->account is null) reported by @Digi92 +- [Issue 10433](https://github.com/firefly-iii/firefly-iii/issues/10433) (500 error when using forgot password link (running in Docker)) reported by @jegelandsdal +- [Issue 10441](https://github.com/firefly-iii/firefly-iii/issues/10441) (Missing spent per day info on mismatching budget limit periods) reported by @Kaotic3 + +### API + +- Transactions now contain balance before/after. + ## 6.2.16 - 2025-xx-xx ### Fixed diff --git a/composer.json b/composer.json index 87e1ec158b..037c109753 100644 --- a/composer.json +++ b/composer.json @@ -114,6 +114,7 @@ "require-dev": { "barryvdh/laravel-debugbar": "^3.9", "barryvdh/laravel-ide-helper": "^3", + "driftingly/rector-laravel": "^2.0", "fakerphp/faker": "1.*", "filp/whoops": "2.*", "larastan/larastan": "^3", diff --git a/composer.lock b/composer.lock index 630b710370..719e779ea1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b630645d62adf0b4c2a9a16ccfc7a3cc", + "content-hash": "5c65637d2a997c3503e4922eb7647e2a", "packages": [ { "name": "bacon/bacon-qr-code", @@ -129,16 +129,16 @@ }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { @@ -177,7 +177,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -185,7 +185,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -939,16 +939,16 @@ }, { "name": "filp/whoops", - "version": "2.18.0", + "version": "2.18.1", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e" + "reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", - "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", + "url": "https://api.github.com/repos/filp/whoops/zipball/8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26", + "reference": "8fcc6a862f2e7b94eb4221fd0819ddba3d30ab26", "shasum": "" }, "require": { @@ -998,7 +998,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.18.0" + "source": "https://github.com/filp/whoops/tree/2.18.1" }, "funding": [ { @@ -1006,7 +1006,7 @@ "type": "github" } ], - "time": "2025-03-15T12:00:00+00:00" + "time": "2025-06-03T18:56:14+00:00" }, { "name": "firebase/php-jwt", @@ -1879,20 +1879,20 @@ }, { "name": "laravel/framework", - "version": "v12.16.0", + "version": "v12.18.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "293bb1c70224faebfd3d4328e201c37115da055f" + "reference": "7d264a0dad2bfc5c154240b38e8ce9b2c4cdd14d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f", - "reference": "293bb1c70224faebfd3d4328e201c37115da055f", + "url": "https://api.github.com/repos/laravel/framework/zipball/7d264a0dad2bfc5c154240b38e8ce9b2c4cdd14d", + "reference": "7d264a0dad2bfc5c154240b38e8ce9b2c4cdd14d", "shasum": "" }, "require": { - "brick/math": "^0.11|^0.12", + "brick/math": "^0.11|^0.12|^0.13", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -2090,7 +2090,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-05-27T15:49:44+00:00" + "time": "2025-06-10T14:48:34+00:00" }, { "name": "laravel/passport", @@ -3473,22 +3473,22 @@ }, { "name": "mailersend/laravel-driver", - "version": "v2.9.1", + "version": "v2.11.0", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-laravel-driver.git", - "reference": "87fd5ab76808bbaac9221be0d306baef13e98725" + "reference": "63acebb5064745076df27b1a80423986b6d7b69e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/87fd5ab76808bbaac9221be0d306baef13e98725", - "reference": "87fd5ab76808bbaac9221be0d306baef13e98725", + "url": "https://api.github.com/repos/mailersend/mailersend-laravel-driver/zipball/63acebb5064745076df27b1a80423986b6d7b69e", + "reference": "63acebb5064745076df27b1a80423986b6d7b69e", "shasum": "" }, "require": { "ext-json": "*", "illuminate/support": "^9.0 || ^10.0 || ^11.0 || ^12.0", - "mailersend/mailersend": "^0.31.0", + "mailersend/mailersend": "^0.34.0", "nyholm/psr7": "^1.5", "php": ">=8.0", "php-http/guzzle7-adapter": "^1.0", @@ -3536,29 +3536,28 @@ ], "support": { "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.11.0" }, - "time": "2025-04-09T09:33:07+00:00" + "time": "2025-06-04T08:47:41+00:00" }, { "name": "mailersend/mailersend", - "version": "v0.31.0", + "version": "v0.34.0", "source": { "type": "git", "url": "https://github.com/mailersend/mailersend-php.git", - "reference": "513ff83ee768526055ad52987cde401ea7218c67" + "reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/513ff83ee768526055ad52987cde401ea7218c67", - "reference": "513ff83ee768526055ad52987cde401ea7218c67", + "url": "https://api.github.com/repos/mailersend/mailersend-php/zipball/1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab", + "reference": "1cb8c42e5569e7455b1e0e794dcbf68e3b7898ab", "shasum": "" }, "require": { "beberlei/assert": "^3.2", "ext-json": "*", - "illuminate/collections": "^8.0 || ^9.0 || ^10.0 || ^11.0 || ^12.0", - "php": "^7.4|^8.0", + "php": "^7.4 || ^8.0 <8.5", "php-http/client-common": "^2.2", "php-http/discovery": "^1.9", "php-http/httplug": "^2.1", @@ -3603,9 +3602,9 @@ ], "support": { "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.34.0" }, - "time": "2025-04-03T12:16:11+00:00" + "time": "2025-06-04T07:53:52+00:00" }, { "name": "monolog/monolog", @@ -3880,16 +3879,16 @@ }, { "name": "nette/utils", - "version": "v4.0.6", + "version": "v4.0.7", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "ce708655043c7050eb050df361c5e313cf708309" + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309", - "reference": "ce708655043c7050eb050df361c5e313cf708309", + "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", "shasum": "" }, "require": { @@ -3960,29 +3959,29 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.6" + "source": "https://github.com/nette/utils/tree/v4.0.7" }, - "time": "2025-03-30T21:06:30+00:00" + "time": "2025-06-03T04:55:08+00:00" }, { "name": "nunomaduro/collision", - "version": "v8.8.0", + "version": "v8.8.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" + "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", - "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/44ccb82e3e21efb5446748d2a3c81a030ac22bd5", + "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5", "shasum": "" }, "require": { - "filp/whoops": "^2.18.0", - "nunomaduro/termwind": "^2.3.0", + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", "php": "^8.2.0", - "symfony/console": "^7.2.5" + "symfony/console": "^7.3.0" }, "conflict": { "laravel/framework": "<11.44.2 || >=13.0.0", @@ -3990,15 +3989,15 @@ }, "require-dev": { "brianium/paratest": "^7.8.3", - "larastan/larastan": "^3.2", - "laravel/framework": "^11.44.2 || ^12.6", - "laravel/pint": "^1.21.2", - "laravel/sail": "^1.41.0", - "laravel/sanctum": "^4.0.8", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", - "orchestra/testbench-core": "^9.12.0 || ^10.1", - "pestphp/pest": "^3.8.0", - "sebastian/environment": "^7.2.0 || ^8.0" + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", "extra": { @@ -4061,7 +4060,7 @@ "type": "patreon" } ], - "time": "2025-04-03T14:33:09+00:00" + "time": "2025-06-11T01:04:21+00:00" }, { "name": "nunomaduro/termwind", @@ -5747,20 +5746,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -5769,26 +5768,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -5823,19 +5819,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.8.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2025-06-01T06:28:46+00:00" }, { "name": "rcrowe/twigbridge", @@ -6423,23 +6409,23 @@ }, { "name": "symfony/cache", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee" + "reference": "c4b217b578c11ec764867aa0c73e602c602965de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/8b49dde3f5a5e9867595a3a269977f78418d75ee", - "reference": "8b49dde3f5a5e9867595a3a269977f78418d75ee", + "url": "https://api.github.com/repos/symfony/cache/zipball/c4b217b578c11ec764867aa0c73e602c602965de", + "reference": "c4b217b578c11ec764867aa0c73e602c602965de", "shasum": "" }, "require": { "php": ">=8.2", "psr/cache": "^2.0|^3.0", "psr/log": "^1.1|^2|^3", - "symfony/cache-contracts": "^2.5|^3", + "symfony/cache-contracts": "^3.6", "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/service-contracts": "^2.5|^3", "symfony/var-exporter": "^6.4|^7.0" @@ -6501,7 +6487,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v7.2.6" + "source": "https://github.com/symfony/cache/tree/v7.3.0" }, "funding": [ { @@ -6517,7 +6503,7 @@ "type": "tidelift" } ], - "time": "2025-04-08T09:06:23+00:00" + "time": "2025-05-06T19:00:13+00:00" }, { "name": "symfony/cache-contracts", @@ -6597,7 +6583,7 @@ }, { "name": "symfony/clock", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", @@ -6651,7 +6637,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.2.0" + "source": "https://github.com/symfony/clock/tree/v7.3.0" }, "funding": [ { @@ -6671,23 +6657,24 @@ }, { "name": "symfony/console", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -6744,7 +6731,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.6" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -6760,11 +6747,11 @@ "type": "tidelift" } ], - "time": "2025-04-07T19:09:28+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/css-selector", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", @@ -6809,7 +6796,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.2.0" + "source": "https://github.com/symfony/css-selector/tree/v7.3.0" }, "funding": [ { @@ -6896,16 +6883,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b" + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", - "reference": "102be5e6a8e4f4f3eb3149bcbfa33a80d1ee374b", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/cf68d225bc43629de4ff54778029aee6dc191b83", + "reference": "cf68d225bc43629de4ff54778029aee6dc191b83", "shasum": "" }, "require": { @@ -6918,9 +6905,11 @@ "symfony/http-kernel": "<6.4" }, "require-dev": { + "symfony/console": "^6.4|^7.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-kernel": "^6.4|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/serializer": "^6.4|^7.0", + "symfony/webpack-encore-bundle": "^1.0|^2.0" }, "bin": [ "Resources/bin/patch-type-declarations" @@ -6951,7 +6940,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.2.5" + "source": "https://github.com/symfony/error-handler/tree/v7.3.0" }, "funding": [ { @@ -6967,20 +6956,20 @@ "type": "tidelift" } ], - "time": "2025-03-03T07:12:39+00:00" + "time": "2025-05-29T07:19:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", - "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/497f73ac996a598c92409b44ac43b6690c4f666d", + "reference": "497f73ac996a598c92409b44ac43b6690c4f666d", "shasum": "" }, "require": { @@ -7031,7 +7020,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.3.0" }, "funding": [ { @@ -7047,7 +7036,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-04-22T09:11:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -7127,7 +7116,7 @@ }, { "name": "symfony/expression-language", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", @@ -7171,7 +7160,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v7.2.0" + "source": "https://github.com/symfony/expression-language/tree/v7.3.0" }, "funding": [ { @@ -7191,16 +7180,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { @@ -7235,7 +7224,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -7251,20 +7240,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/http-client", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -7330,7 +7319,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -7346,7 +7335,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", @@ -7428,16 +7417,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "6023ec7607254c87c5e69fb3558255aca440d72b" + "reference": "4236baf01609667d53b20371486228231eb135fd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6023ec7607254c87c5e69fb3558255aca440d72b", - "reference": "6023ec7607254c87c5e69fb3558255aca440d72b", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4236baf01609667d53b20371486228231eb135fd", + "reference": "4236baf01609667d53b20371486228231eb135fd", "shasum": "" }, "require": { @@ -7454,6 +7443,7 @@ "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", "symfony/cache": "^6.4.12|^7.1.5", + "symfony/clock": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -7486,7 +7476,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.2.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.3.0" }, "funding": [ { @@ -7502,20 +7492,20 @@ "type": "tidelift" } ], - "time": "2025-04-09T08:14:01+00:00" + "time": "2025-05-12T14:48:23+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec" + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/f9dec01e6094a063e738f8945ef69c0cfcf792ec", - "reference": "f9dec01e6094a063e738f8945ef69c0cfcf792ec", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/ac7b8e163e8c83dce3abcc055a502d4486051a9f", + "reference": "ac7b8e163e8c83dce3abcc055a502d4486051a9f", "shasum": "" }, "require": { @@ -7523,8 +7513,8 @@ "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.4|^7.0", - "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/http-foundation": "^6.4|^7.0", + "symfony/event-dispatcher": "^7.3", + "symfony/http-foundation": "^7.3", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -7600,7 +7590,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.2.6" + "source": "https://github.com/symfony/http-kernel/tree/v7.3.0" }, "funding": [ { @@ -7616,20 +7606,20 @@ "type": "tidelift" } ], - "time": "2025-05-02T09:04:03+00:00" + "time": "2025-05-29T07:47:32+00:00" }, { "name": "symfony/mailer", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "998692469d6e698c6eadc7ef37a6530a9eabb356" + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/998692469d6e698c6eadc7ef37a6530a9eabb356", - "reference": "998692469d6e698c6eadc7ef37a6530a9eabb356", + "url": "https://api.github.com/repos/symfony/mailer/zipball/0f375bbbde96ae8c78e4aa3e63aabd486e33364c", + "reference": "0f375bbbde96ae8c78e4aa3e63aabd486e33364c", "shasum": "" }, "require": { @@ -7680,7 +7670,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.2.6" + "source": "https://github.com/symfony/mailer/tree/v7.3.0" }, "funding": [ { @@ -7696,11 +7686,11 @@ "type": "tidelift" } ], - "time": "2025-04-04T09:50:51+00:00" + "time": "2025-04-04T09:51:09+00:00" }, { "name": "symfony/mailgun-mailer", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", @@ -7749,7 +7739,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v7.2.0" + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.3.0" }, "funding": [ { @@ -7769,16 +7759,16 @@ }, { "name": "symfony/mime", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1" + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/706e65c72d402539a072d0d6ad105fff6c161ef1", - "reference": "706e65c72d402539a072d0d6ad105fff6c161ef1", + "url": "https://api.github.com/repos/symfony/mime/zipball/0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", + "reference": "0e7b19b2f399c31df0cdbe5d8cbf53f02f6cfcd9", "shasum": "" }, "require": { @@ -7833,7 +7823,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.2.6" + "source": "https://github.com/symfony/mime/tree/v7.3.0" }, "funding": [ { @@ -7849,20 +7839,20 @@ "type": "tidelift" } ], - "time": "2025-04-27T13:34:41+00:00" + "time": "2025-02-19T08:51:26+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", "shasum": "" }, "require": { @@ -7900,7 +7890,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" }, "funding": [ { @@ -7916,7 +7906,7 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-04-04T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -8557,16 +8547,16 @@ }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -8598,7 +8588,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -8614,11 +8604,11 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", @@ -8681,7 +8671,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.2.0" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.3.0" }, "funding": [ { @@ -8701,16 +8691,16 @@ }, { "name": "symfony/routing", - "version": "v7.2.3", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996" + "reference": "8e213820c5fea844ecea29203d2a308019007c15" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ee9a67edc6baa33e5fae662f94f91fd262930996", - "reference": "ee9a67edc6baa33e5fae662f94f91fd262930996", + "url": "https://api.github.com/repos/symfony/routing/zipball/8e213820c5fea844ecea29203d2a308019007c15", + "reference": "8e213820c5fea844ecea29203d2a308019007c15", "shasum": "" }, "require": { @@ -8762,7 +8752,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.2.3" + "source": "https://github.com/symfony/routing/tree/v7.3.0" }, "funding": [ { @@ -8778,7 +8768,7 @@ "type": "tidelift" } ], - "time": "2025-01-17T10:56:55+00:00" + "time": "2025-05-24T20:43:28+00:00" }, { "name": "symfony/service-contracts", @@ -8865,16 +8855,16 @@ }, { "name": "symfony/string", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { @@ -8932,7 +8922,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.6" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -8948,20 +8938,20 @@ "type": "tidelift" } ], - "time": "2025-04-20T20:18:16+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "symfony/translation", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6" + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", - "reference": "e7fd8e2a4239b79a0fd9fb1fef3e0e7f969c6dc6", + "url": "https://api.github.com/repos/symfony/translation/zipball/4aba29076a29a3aa667e09b791e5f868973a8667", + "reference": "4aba29076a29a3aa667e09b791e5f868973a8667", "shasum": "" }, "require": { @@ -8971,6 +8961,7 @@ "symfony/translation-contracts": "^2.5|^3.0" }, "conflict": { + "nikic/php-parser": "<5.0", "symfony/config": "<6.4", "symfony/console": "<6.4", "symfony/dependency-injection": "<6.4", @@ -8984,7 +8975,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "psr/log": "^1|^2|^3", "symfony/config": "^6.4|^7.0", "symfony/console": "^6.4|^7.0", @@ -9027,7 +9018,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.2.6" + "source": "https://github.com/symfony/translation/tree/v7.3.0" }, "funding": [ { @@ -9043,7 +9034,7 @@ "type": "tidelift" } ], - "time": "2025-04-07T19:09:28+00:00" + "time": "2025-05-29T07:19:49+00:00" }, { "name": "symfony/translation-contracts", @@ -9125,16 +9116,16 @@ }, { "name": "symfony/uid", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426" + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", - "reference": "2d294d0c48df244c71c105a169d0190bfb080426", + "url": "https://api.github.com/repos/symfony/uid/zipball/7beeb2b885cd584cd01e126c5777206ae4c3c6a3", + "reference": "7beeb2b885cd584cd01e126c5777206ae4c3c6a3", "shasum": "" }, "require": { @@ -9179,7 +9170,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.2.0" + "source": "https://github.com/symfony/uid/tree/v7.3.0" }, "funding": [ { @@ -9195,24 +9186,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2025-05-24T14:28:13+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb" + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9c46038cd4ed68952166cf7001b54eb539184ccb", - "reference": "9c46038cd4ed68952166cf7001b54eb539184ccb", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/548f6760c54197b1084e1e5c71f6d9d523f2f78e", + "reference": "548f6760c54197b1084e1e5c71f6d9d523f2f78e", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -9262,7 +9254,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.2.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.3.0" }, "funding": [ { @@ -9278,24 +9270,25 @@ "type": "tidelift" } ], - "time": "2025-04-09T08:14:01+00:00" + "time": "2025-04-27T18:39:23+00:00" }, { "name": "symfony/var-exporter", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "422b8de94c738830a1e071f59ad14d67417d7007" + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/422b8de94c738830a1e071f59ad14d67417d7007", - "reference": "422b8de94c738830a1e071f59ad14d67417d7007", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c9a1168891b5aaadfd6332ef44393330b3498c4c", + "reference": "c9a1168891b5aaadfd6332ef44393330b3498c4c", "shasum": "" }, "require": { - "php": ">=8.2" + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3" }, "require-dev": { "symfony/property-access": "^6.4|^7.0", @@ -9338,7 +9331,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v7.2.6" + "source": "https://github.com/symfony/var-exporter/tree/v7.3.0" }, "funding": [ { @@ -9354,7 +9347,7 @@ "type": "tidelift" } ], - "time": "2025-05-02T08:36:00+00:00" + "time": "2025-05-15T09:04:05+00:00" }, { "name": "thecodingmachine/safe", @@ -10288,6 +10281,41 @@ ], "time": "2024-11-12T16:29:46+00:00" }, + { + "name": "driftingly/rector-laravel", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/driftingly/rector-laravel.git", + "reference": "ac61de4f267c23249d175d7fc9149fd01528567d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/ac61de4f267c23249d175d7fc9149fd01528567d", + "reference": "ac61de4f267c23249d175d7fc9149fd01528567d", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0", + "rector/rector": "^2.0" + }, + "type": "rector-extension", + "autoload": { + "psr-4": { + "RectorLaravel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Rector upgrades rules for Laravel Framework", + "support": { + "issues": "https://github.com/driftingly/rector-laravel/issues", + "source": "https://github.com/driftingly/rector-laravel/tree/2.0.5" + }, + "time": "2025-05-14T17:30:41+00:00" + }, { "name": "fakerphp/faker", "version": "v1.24.1", @@ -10445,16 +10473,16 @@ }, { "name": "larastan/larastan", - "version": "v3.4.0", + "version": "v3.4.2", "source": { "type": "git", "url": "https://github.com/larastan/larastan.git", - "reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222" + "reference": "36706736a0c51d3337478fab9c919d78d2e03404" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/larastan/larastan/zipball/1042fa0c2ee490bb6da7381f3323f7292ad68222", - "reference": "1042fa0c2ee490bb6da7381f3323f7292ad68222", + "url": "https://api.github.com/repos/larastan/larastan/zipball/36706736a0c51d3337478fab9c919d78d2e03404", + "reference": "36706736a0c51d3337478fab9c919d78d2e03404", "shasum": "" }, "require": { @@ -10522,7 +10550,7 @@ ], "support": { "issues": "https://github.com/larastan/larastan/issues", - "source": "https://github.com/larastan/larastan/tree/v3.4.0" + "source": "https://github.com/larastan/larastan/tree/v3.4.2" }, "funding": [ { @@ -10530,7 +10558,7 @@ "type": "github" } ], - "time": "2025-04-22T09:44:59+00:00" + "time": "2025-06-10T09:34:58+00:00" }, { "name": "laravel-json-api/testing", @@ -10742,16 +10770,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -10794,9 +10822,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "phar-io/manifest", @@ -11523,16 +11551,16 @@ }, { "name": "phpunit/phpunit", - "version": "12.1.6", + "version": "12.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2fdf0056c673c8f0f1eed00030be5f8243c1e6e0" + "reference": "5f09fda04e7caea93cff50b4e90319184f3e6ee3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2fdf0056c673c8f0f1eed00030be5f8243c1e6e0", - "reference": "2fdf0056c673c8f0f1eed00030be5f8243c1e6e0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/5f09fda04e7caea93cff50b4e90319184f3e6ee3", + "reference": "5f09fda04e7caea93cff50b4e90319184f3e6ee3", "shasum": "" }, "require": { @@ -11546,7 +11574,7 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.3", - "phpunit/php-code-coverage": "^12.2.1", + "phpunit/php-code-coverage": "^12.3.0", "phpunit/php-file-iterator": "^6.0.0", "phpunit/php-invoker": "^6.0.0", "phpunit/php-text-template": "^5.0.0", @@ -11554,7 +11582,7 @@ "sebastian/cli-parser": "^4.0.0", "sebastian/comparator": "^7.0.1", "sebastian/diff": "^7.0.0", - "sebastian/environment": "^8.0.1", + "sebastian/environment": "^8.0.2", "sebastian/exporter": "^7.0.0", "sebastian/global-state": "^8.0.0", "sebastian/object-enumerator": "^7.0.0", @@ -11568,7 +11596,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "12.1-dev" + "dev-main": "12.2-dev" } }, "autoload": { @@ -11600,7 +11628,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/12.1.6" + "source": "https://github.com/sebastianbergmann/phpunit/tree/12.2.1" }, "funding": [ { @@ -11624,25 +11652,25 @@ "type": "tidelift" } ], - "time": "2025-05-21T12:36:31+00:00" + "time": "2025-06-07T05:17:47+00:00" }, { "name": "rector/rector", - "version": "2.0.16", + "version": "2.0.18", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2" + "reference": "be3a452085b524a04056e3dfe72d861948711062" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", - "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/be3a452085b524a04056e3dfe72d861948711062", + "reference": "be3a452085b524a04056e3dfe72d861948711062", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.14" + "phpstan/phpstan": "^2.1.17" }, "conflict": { "rector/rector-doctrine": "*", @@ -11675,7 +11703,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.0.16" + "source": "https://github.com/rectorphp/rector/tree/2.0.18" }, "funding": [ { @@ -11683,7 +11711,7 @@ "type": "github" } ], - "time": "2025-05-12T16:37:16+00:00" + "time": "2025-06-11T11:19:37+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/firefly.php b/config/firefly.php index 94fa435673..1bcc8c1c0f 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -78,7 +78,7 @@ return [ 'running_balance_column' => env('USE_RUNNING_BALANCE', false), // see cer.php for exchange rates feature flag. ], - 'version' => '6.2.16', + 'version' => '6.2.17', 'api_version' => '2.1.0', // field is no longer used. 'db_version' => 25, diff --git a/package-lock.json b/package-lock.json index 0f0688b22b..08f5b60b5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,9 +43,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.3.tgz", - "integrity": "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.5.tgz", + "integrity": "sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==", "dev": true, "license": "MIT", "engines": { @@ -53,9 +53,9 @@ } }, "node_modules/@babel/core": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.3.tgz", - "integrity": "sha512-hyrN8ivxfvJ4i0fIJuV4EOlV0WDMz5Ui4StRTgVaAvWeiRCilXgwVvxJKtFQ3TKtHgJscB2YiXKGNJuVwhQMtA==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", + "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "dev": true, "license": "MIT", "dependencies": { @@ -64,10 +64,10 @@ "@babel/generator": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.3", - "@babel/parser": "^7.27.3", + "@babel/helpers": "^7.27.4", + "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", - "@babel/traverse": "^7.27.3", + "@babel/traverse": "^7.27.4", "@babel/types": "^7.27.3", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -94,13 +94,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.3.tgz", - "integrity": "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.27.3", + "@babel/parser": "^7.27.5", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", @@ -392,23 +392,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.3.tgz", - "integrity": "sha512-h/eKy9agOya1IGuLaZ9tEUgz+uIRXcbtOhRtUyyMf8JFmn1iT13vnl/IGVWSkdOCG/pC57U4S1jnAabAavTMwg==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3" + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.3.tgz", - "integrity": "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dev": true, "license": "MIT", "dependencies": { @@ -683,9 +683,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.3.tgz", - "integrity": "sha512-+F8CnfhuLhwUACIJMLWnjz6zvzYM2r0yeIHKlbgfw7ml8rOMJsXNXV/hyRcb3nb493gRs4WvYpQAndWj/qQmkQ==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.5.tgz", + "integrity": "sha512-JF6uE2s67f0y2RZcm2kpAUEbD50vH62TyWVebxwHAlbSdM49VqPz8t4a1uIjp4NIOIZ4xzLfjY5emt/RCyC7TQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1255,9 +1255,9 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.1.tgz", - "integrity": "sha512-B19lbbL7PMrKr52BNPjCqg1IyNUIjTcxKj8uX9zHO+PmWN93s19NDr/f69mIkEp2x9nmDJ08a7lgHaTTzvW7mw==", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.5.tgz", + "integrity": "sha512-uhB8yHerfe3MWnuLAhEbeQ4afVoqv8BQsPqrTv7e/jZ9y00kJL6l9a/f4OWaKxotmjzewfEyXE1vgDJenkQ2/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1304,9 +1304,9 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.3.tgz", - "integrity": "sha512-bA9ZL5PW90YwNgGfjg6U+7Qh/k3zCEQJ06BFgAGRp/yMjw9hP9UGbGPtx3KSOkHGljEPCCxaE+PH4fUR2h1sDw==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.27.4.tgz", + "integrity": "sha512-D68nR5zxU64EUzV8i7T3R5XP0Xhrou/amNnddsRQssx6GrTLdZl1rLxyjtVZBd+v/NVX4AbTPOB5aU8thAZV1A==", "dev": true, "license": "MIT", "dependencies": { @@ -1592,9 +1592,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.3.tgz", - "integrity": "sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -1616,15 +1616,15 @@ } }, "node_modules/@babel/traverse": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.3.tgz", - "integrity": "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ==", + "version": "7.27.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.4.tgz", + "integrity": "sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", - "@babel/parser": "^7.27.3", + "@babel/parser": "^7.27.4", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", @@ -1635,9 +1635,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.3.tgz", - "integrity": "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw==", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2552,9 +2552,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz", - "integrity": "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz", + "integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==", "cpu": [ "arm" ], @@ -2566,9 +2566,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz", - "integrity": "sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz", + "integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==", "cpu": [ "arm64" ], @@ -2580,9 +2580,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz", - "integrity": "sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz", + "integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==", "cpu": [ "arm64" ], @@ -2594,9 +2594,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz", - "integrity": "sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz", + "integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==", "cpu": [ "x64" ], @@ -2608,9 +2608,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz", - "integrity": "sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz", + "integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==", "cpu": [ "arm64" ], @@ -2622,9 +2622,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz", - "integrity": "sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz", + "integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==", "cpu": [ "x64" ], @@ -2636,9 +2636,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz", - "integrity": "sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz", + "integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==", "cpu": [ "arm" ], @@ -2650,9 +2650,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz", - "integrity": "sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz", + "integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==", "cpu": [ "arm" ], @@ -2664,9 +2664,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz", - "integrity": "sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz", + "integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==", "cpu": [ "arm64" ], @@ -2678,9 +2678,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz", - "integrity": "sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz", + "integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==", "cpu": [ "arm64" ], @@ -2692,9 +2692,9 @@ ] }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz", - "integrity": "sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz", + "integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==", "cpu": [ "loong64" ], @@ -2706,9 +2706,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz", - "integrity": "sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz", + "integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==", "cpu": [ "ppc64" ], @@ -2720,9 +2720,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz", - "integrity": "sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz", + "integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==", "cpu": [ "riscv64" ], @@ -2734,9 +2734,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz", - "integrity": "sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz", + "integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==", "cpu": [ "riscv64" ], @@ -2748,9 +2748,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz", - "integrity": "sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz", + "integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==", "cpu": [ "s390x" ], @@ -2762,9 +2762,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz", - "integrity": "sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz", + "integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==", "cpu": [ "x64" ], @@ -2776,9 +2776,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz", - "integrity": "sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz", + "integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==", "cpu": [ "x64" ], @@ -2790,9 +2790,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz", - "integrity": "sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz", + "integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==", "cpu": [ "arm64" ], @@ -2804,9 +2804,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz", - "integrity": "sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz", + "integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==", "cpu": [ "ia32" ], @@ -2818,9 +2818,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz", - "integrity": "sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz", + "integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==", "cpu": [ "x64" ], @@ -2887,9 +2887,9 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", "dev": true, "license": "MIT", "dependencies": { @@ -2969,9 +2969,9 @@ "license": "MIT" }, "node_modules/@types/express": { - "version": "4.17.22", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.22.tgz", - "integrity": "sha512-eZUmSnhRX9YRSkplpz0N+k6NljUUn5l3EWZIKZvYzhvMphEuNiyyy1viH/ejgt66JWgALwC/gtSUAeQKtSwW/w==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.23.tgz", + "integrity": "sha512-Crp6WY9aTYP3qPi2wGDo9iUe/rceX01UMhnF1jmwDcKCFM6cx7YhGP/Mpr3y9AASpfHixIG0E6azCcL5OcDHsQ==", "dev": true, "license": "MIT", "dependencies": { @@ -3019,9 +3019,9 @@ } }, "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", "dev": true, "license": "MIT" }, @@ -3108,13 +3108,13 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.15.21", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.21.tgz", - "integrity": "sha512-EV/37Td6c+MgKAbkcLG6vqZ2zEYHD7bvSrzqqs2RIhbA6w3x+Dqz8MZM3sP6kGTeLrdoOgKZe+Xja7tUB2DNkQ==", + "version": "24.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.0.tgz", + "integrity": "sha512-yZQa2zm87aRVcqDyH5+4Hv9KYgSdgwX1rFnGvpbzMaC7YAljmhBET93TPiTd3ObwTL+gSpIzPKg5BqVxdCvxKg==", "dev": true, "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.8.0" } }, "node_modules/@types/node-forge": { @@ -3156,9 +3156,9 @@ "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "version": "0.17.5", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz", + "integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==", "dev": true, "license": "MIT", "dependencies": { @@ -3177,9 +3177,9 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "version": "1.15.8", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz", + "integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==", "dev": true, "license": "MIT", "dependencies": { @@ -3216,42 +3216,42 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.15.tgz", - "integrity": "sha512-nGRc6YJg/kxNqbv/7Tg4juirPnjHvuVdhcmDvQWVZXlLHjouq7VsKmV1hIxM/8yKM0VUfwT/Uzc0lO510ltZqw==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.16.tgz", + "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.27.2", - "@vue/shared": "3.5.15", + "@vue/shared": "3.5.16", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.15.tgz", - "integrity": "sha512-ZelQd9n+O/UCBdL00rlwCrsArSak+YLZpBVuNDio1hN3+wrCshYZEDUO3khSLAzPbF1oQS2duEoMDUHScUlYjA==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz", + "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.15", - "@vue/shared": "3.5.15" + "@vue/compiler-core": "3.5.16", + "@vue/shared": "3.5.16" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.15.tgz", - "integrity": "sha512-3zndKbxMsOU6afQWer75Zot/aydjtxNj0T2KLg033rAFaQUn2PGuE32ZRe4iMhflbTcAxL0yEYsRWFxtPro8RQ==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz", + "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==", "dev": true, "license": "MIT", "dependencies": { "@babel/parser": "^7.27.2", - "@vue/compiler-core": "3.5.15", - "@vue/compiler-dom": "3.5.15", - "@vue/compiler-ssr": "3.5.15", - "@vue/shared": "3.5.15", + "@vue/compiler-core": "3.5.16", + "@vue/compiler-dom": "3.5.16", + "@vue/compiler-ssr": "3.5.16", + "@vue/shared": "3.5.16", "estree-walker": "^2.0.2", "magic-string": "^0.30.17", "postcss": "^8.5.3", @@ -3259,14 +3259,14 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.15.tgz", - "integrity": "sha512-gShn8zRREZbrXqTtmLSCffgZXDWv8nHc/GhsW+mbwBfNZL5pI96e7IWcIq8XGQe1TLtVbu7EV9gFIVSmfyarPg==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz", + "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.15", - "@vue/shared": "3.5.15" + "@vue/compiler-dom": "3.5.16", + "@vue/shared": "3.5.16" } }, "node_modules/@vue/component-compiler-utils": { @@ -3348,9 +3348,9 @@ "license": "MIT" }, "node_modules/@vue/shared": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.15.tgz", - "integrity": "sha512-bKvgFJJL1ZX9KxMCTQY6xD9Dhe3nusd1OhyOb1cJYGqvAr0Vg8FIjHPMOEVbJ9GDT9HG+Bjdn4oS8ohKP8EvoA==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.16.tgz", + "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==", "dev": true, "license": "MIT" }, @@ -3600,9 +3600,9 @@ } }, "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", "bin": { @@ -4139,9 +4139,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "license": "MIT", "dependencies": { @@ -4257,9 +4257,9 @@ } }, "node_modules/browserslist": { - "version": "4.24.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", - "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", + "version": "4.25.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", + "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", "dev": true, "funding": [ { @@ -4277,8 +4277,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001716", - "electron-to-chromium": "^1.5.149", + "caniuse-lite": "^1.0.30001718", + "electron-to-chromium": "^1.5.160", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -4417,9 +4417,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001718", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", - "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", + "version": "1.0.30001722", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", + "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", "dev": true, "funding": [ { @@ -4861,13 +4861,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.42.0.tgz", - "integrity": "sha512-bQasjMfyDGyaeWKBIu33lHh9qlSR0MFE/Nmc6nMjf/iU9b3rSMdAYz1Baxrv4lPdGUsTqZudHA4jIGSJy0SWZQ==", + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", + "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.24.4" + "browserslist": "^4.25.0" }, "funding": { "type": "opencollective", @@ -5632,9 +5632,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.158", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.158.tgz", - "integrity": "sha512-9vcp2xHhkvraY6AHw2WMi+GDSLPX42qe2xjYaVoZqFRJiOcilVQFq9mZmpuHEQpzlgGDelKlV7ZiGcmMsc8WxQ==", + "version": "1.5.166", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz", + "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==", "dev": true, "license": "ISC" }, @@ -6322,15 +6322,16 @@ } }, "node_modules/form-data": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", - "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.3.tgz", + "integrity": "sha512-qsITQPfmvMOSAdeyZ+12I1c+CKSstAFAwu+97zrnWAbIr5u8wfsExUzCesVLC8NgHuRUqNN4Zy6UPWUTRGslcA==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", "mime-types": "^2.1.12" }, "engines": { @@ -7713,9 +7714,9 @@ } }, "node_modules/laravel-vite-plugin": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.2.0.tgz", - "integrity": "sha512-R0pJ+IcTVeqEMoKz/B2Ij57QVq3sFTABiFmb06gAwFdivbOgsUtuhX6N2MGLEArajrS3U5JbberzwOe7uXHMHQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-1.3.0.tgz", + "integrity": "sha512-P5qyG56YbYxM8OuYmK2OkhcKe0AksNVJUjq9LUZ5tOekU9fBn9LujYyctI4t9XoLjuMvHJXXpCoPntY1oKltuA==", "dev": true, "license": "MIT", "dependencies": { @@ -8856,9 +8857,9 @@ } }, "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "version": "8.5.4", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", + "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", "dev": true, "funding": [ { @@ -8876,7 +8877,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.8", + "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -9973,9 +9974,9 @@ } }, "node_modules/rollup": { - "version": "4.41.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz", - "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==", + "version": "4.43.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz", + "integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==", "dev": true, "license": "MIT", "dependencies": { @@ -9989,26 +9990,26 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.41.1", - "@rollup/rollup-android-arm64": "4.41.1", - "@rollup/rollup-darwin-arm64": "4.41.1", - "@rollup/rollup-darwin-x64": "4.41.1", - "@rollup/rollup-freebsd-arm64": "4.41.1", - "@rollup/rollup-freebsd-x64": "4.41.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.41.1", - "@rollup/rollup-linux-arm-musleabihf": "4.41.1", - "@rollup/rollup-linux-arm64-gnu": "4.41.1", - "@rollup/rollup-linux-arm64-musl": "4.41.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.41.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.41.1", - "@rollup/rollup-linux-riscv64-gnu": "4.41.1", - "@rollup/rollup-linux-riscv64-musl": "4.41.1", - "@rollup/rollup-linux-s390x-gnu": "4.41.1", - "@rollup/rollup-linux-x64-gnu": "4.41.1", - "@rollup/rollup-linux-x64-musl": "4.41.1", - "@rollup/rollup-win32-arm64-msvc": "4.41.1", - "@rollup/rollup-win32-ia32-msvc": "4.41.1", - "@rollup/rollup-win32-x64-msvc": "4.41.1", + "@rollup/rollup-android-arm-eabi": "4.43.0", + "@rollup/rollup-android-arm64": "4.43.0", + "@rollup/rollup-darwin-arm64": "4.43.0", + "@rollup/rollup-darwin-x64": "4.43.0", + "@rollup/rollup-freebsd-arm64": "4.43.0", + "@rollup/rollup-freebsd-x64": "4.43.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.43.0", + "@rollup/rollup-linux-arm-musleabihf": "4.43.0", + "@rollup/rollup-linux-arm64-gnu": "4.43.0", + "@rollup/rollup-linux-arm64-musl": "4.43.0", + "@rollup/rollup-linux-loongarch64-gnu": "4.43.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-gnu": "4.43.0", + "@rollup/rollup-linux-riscv64-musl": "4.43.0", + "@rollup/rollup-linux-s390x-gnu": "4.43.0", + "@rollup/rollup-linux-x64-gnu": "4.43.0", + "@rollup/rollup-linux-x64-musl": "4.43.0", + "@rollup/rollup-win32-arm64-msvc": "4.43.0", + "@rollup/rollup-win32-ia32-msvc": "4.43.0", + "@rollup/rollup-win32-x64-msvc": "4.43.0", "fsevents": "~2.3.2" } }, @@ -10064,9 +10065,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.89.0", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.0.tgz", - "integrity": "sha512-ld+kQU8YTdGNjOLfRWBzewJpU5cwEv/h5yyqlSeJcj6Yh8U4TDA9UA5FPicqDz/xgRPWRSYIQNiFks21TbA9KQ==", + "version": "1.89.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.89.2.tgz", + "integrity": "sha512-xCmtksBKd/jdJ9Bt9p7nPKiuqrlBMBuuGkQlkhZjjQk3Ty48lv93k5Dq6OPkKt4XwxDJ7tvlfrTa1MPA9bf+QA==", "dev": true, "license": "MIT", "dependencies": { @@ -10414,9 +10415,9 @@ } }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", "dev": true, "license": "MIT", "engines": { @@ -10858,9 +10859,9 @@ } }, "node_modules/terser": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.40.0.tgz", - "integrity": "sha512-cfeKl/jjwSR5ar7d0FGmave9hFGJT8obyo0z+CrQOylLDbk7X81nPU6vq9VORa5jU30SkDnT2FXjLbR8HLP+xA==", + "version": "5.42.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.42.0.tgz", + "integrity": "sha512-UYCvU9YQW2f/Vwl+P0GfhxJxbUGLwd+5QrrGgLajzWAtC/23AX0vcise32kkP7Eu0Wu9VlzzHAXkLObgjQfFlQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11013,9 +11014,9 @@ } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -11133,9 +11134,9 @@ } }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", "dev": true, "license": "MIT" }, @@ -11423,9 +11424,9 @@ "license": "MIT" }, "node_modules/vite/node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", "dev": true, "license": "MIT", "peerDependencies": { @@ -12081,9 +12082,9 @@ } }, "node_modules/webpack/node_modules/webpack-sources": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.0.tgz", - "integrity": "sha512-77R0RDmJfj9dyv5p3bM5pOHa+X8/ZkO9c7kpDstigkC4nIDobadsfSGCwB4bKhMVxqAok8tajaoR8rirM7+VFQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.2.tgz", + "integrity": "sha512-ykKKus8lqlgXX/1WjudpIEjqsafjOTcOJqxnAbMLAu/KCsDCJ6GBtvscewvTkrn24HsnvFwrSCbenFrhtcCsAA==", "dev": true, "license": "MIT", "engines": { diff --git a/patches/admin-lte+4.0.0-beta2.patch b/patches/admin-lte+4.0.0-beta3.patch similarity index 100% rename from patches/admin-lte+4.0.0-beta2.patch rename to patches/admin-lte+4.0.0-beta3.patch diff --git a/public/v1/js/ff/piggy-banks/show.js b/public/v1/js/ff/piggy-banks/show.js index f6d41064ce..a6756992fb 100644 --- a/public/v1/js/ff/piggy-banks/show.js +++ b/public/v1/js/ff/piggy-banks/show.js @@ -24,4 +24,12 @@ $(function () { if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') { lineChart('chart/piggy-bank/' + piggyBankID, 'piggy-bank-history'); } -}); \ No newline at end of file + + // on submit of logout button: + $('.reset-link').click(function(e) { + console.log('here we are'); + e.preventDefault(); + document.getElementById('reset-form').submit(); + return false; + }); +}); diff --git a/resources/assets/v1/src/locales/id.json b/resources/assets/v1/src/locales/id.json index fb22dfeb81..8ca557cead 100644 --- a/resources/assets/v1/src/locales/id.json +++ b/resources/assets/v1/src/locales/id.json @@ -112,7 +112,7 @@ "webhook_trigger_DESTROY_TRANSACTION": "After transaction delete", "webhook_response_TRANSACTIONS": "Transaction details", "webhook_response_ACCOUNTS": "Account details", - "webhook_response_none_NONE": "No details", + "webhook_response_none_NONE": "Tidak ada detil", "webhook_delivery_JSON": "JSON", "actions": "Tindakan", "meta_data": "Data meta", @@ -129,7 +129,7 @@ "edit_webhook_js": "Edit webhook \"{title}\"", "webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.", "view_message": "View message", - "view_attempts": "View failed attempts", + "view_attempts": "Lihat upaya yang gagal", "message_content_title": "Webhook message content", "message_content_help": "This is the content of the message that was sent (or tried) using this webhook.", "attempt_content_title": "Webhook attempts", @@ -137,7 +137,7 @@ "no_attempts": "There are no unsuccessful attempts. That's a good thing!", "webhook_attempt_at": "Attempt at {moment}", "logs": "Log", - "response": "Response", + "response": "Tanggapan", "visit_webhook_url": "Visit webhook URL", "reset_webhook_secret": "Reset webhook secret", "header_exchange_rates": "Exchange rates", diff --git a/resources/assets/v1/src/locales/zh-tw.json b/resources/assets/v1/src/locales/zh-tw.json index 9968c2467a..e024a87eb5 100644 --- a/resources/assets/v1/src/locales/zh-tw.json +++ b/resources/assets/v1/src/locales/zh-tw.json @@ -183,6 +183,6 @@ }, "config": { "html_language": "zh-tw", - "date_time_fns": "yyyy\u5e74 M\u6708 D\u65e5 dddd \u65bc HH:mm:ss" + "date_time_fns": "yyyy\u5e74 M\u6708 d\u65e5 \u65bc HH:mm:ss" } } \ No newline at end of file diff --git a/resources/assets/v2/src/api/v1/model/budget/get.js b/resources/assets/v2/src/api/v1/model/budget/get.js index 010ebcb7b5..8dd733cd10 100644 --- a/resources/assets/v2/src/api/v1/model/budget/get.js +++ b/resources/assets/v2/src/api/v1/model/budget/get.js @@ -29,7 +29,7 @@ export default class Get { * @returns {Promise>} */ list(params) { - return api.get('/api/v2/budgets', {params: params}); + return api.get('/api/v1/budgets', {params: params}); } } diff --git a/resources/assets/v2/src/pages/transactions/create.js b/resources/assets/v2/src/pages/transactions/create.js index a876f78e88..3a2b60beae 100644 --- a/resources/assets/v2/src/pages/transactions/create.js +++ b/resources/assets/v2/src/pages/transactions/create.js @@ -490,14 +490,15 @@ let transactions = function () { // addedSplit, is called from the HTML // for source account const renderAccount = function (item, b, c) { - return item.title + '
' + i18next.t('firefly.account_type_' + item.meta.type) + ''; + return item.name_with_balance + '
' + i18next.t('firefly.account_type_' + item.type) + ''; }; + console.log('here we are in'); addAutocomplete({ selector: 'input.ac-source', serverUrl: urls.account, onRenderItem: renderAccount, valueField: 'id', - labelField: 'title', + labelField: 'name_with_balance', onChange: changeSourceAccount, onSelectItem: selectSourceAccount, hiddenValue: this.entries[count].source_account.alpine_name @@ -507,7 +508,7 @@ let transactions = function () { serverUrl: urls.account, account_types: this.filters.destination, valueField: 'id', - labelField: 'title', + labelField: 'name_with_balance', onRenderItem: renderAccount, onChange: changeDestinationAccount, onSelectItem: selectDestinationAccount diff --git a/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js b/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js index c648579df0..a71dcf023e 100644 --- a/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js +++ b/resources/assets/v2/src/pages/transactions/shared/add-autocomplete.js @@ -38,16 +38,17 @@ export function addAutocomplete(options) { 'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content } }, - queryParam: 'filter[query]', + queryParam: 'query', hiddenInput: true, // preventBrowserAutocomplete: true, highlightTyped: true, liveServer: true, }; if (typeof options.account_types !== 'undefined' && options.account_types.length > 0) { - params.serverParams['filter[account_types]'] = options.account_types; + params.serverParams['types'] = options.account_types; } if (typeof options.onRenderItem !== 'undefined' && null !== options.onRenderItem) { + console.log('overrule onRenderItem.'); params.onRenderItem = options.onRenderItem; } if (options.valueField) { diff --git a/resources/assets/v2/src/pages/transactions/shared/autocomplete-functions.js b/resources/assets/v2/src/pages/transactions/shared/autocomplete-functions.js index d878837dcc..4755f2e33c 100644 --- a/resources/assets/v2/src/pages/transactions/shared/autocomplete-functions.js +++ b/resources/assets/v2/src/pages/transactions/shared/autocomplete-functions.js @@ -55,7 +55,7 @@ export function changeDestinationAccount(item, ac) { export function selectDestinationAccount(item, ac) { const index = parseInt(ac._searchInput.attributes['data-index'].value); document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account = { - id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code, + id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code, }; document.querySelector('#form')._x_dataStack[0].changedDestinationAccount(); } @@ -78,7 +78,7 @@ export function changeSourceAccount(item, ac) { export function selectSourceAccount(item, ac) { const index = parseInt(ac._searchInput.attributes['data-index'].value); document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account = { - id: item.id, name: item.title, alpine_name: item.title, type: item.meta.type, currency_code: item.meta.currency_code, + id: item.id, name: item.name, alpine_name: item.name, type: item.type, currency_code: item.currency_code, }; document.querySelector('#form')._x_dataStack[0].changedSourceAccount(); } diff --git a/resources/assets/v2/vite.config.js b/resources/assets/v2/vite.config.js index f3f18671bb..50b1b24e05 100644 --- a/resources/assets/v2/vite.config.js +++ b/resources/assets/v2/vite.config.js @@ -83,7 +83,7 @@ export default defineConfig(({command, mode, isSsrBuild, isPreview}) => { server: { cors: true, - origin: 'https://firefly.sd.internal:5173', + origin: 'https://192.168.96.154:5173', watch: { usePolling: true, }, diff --git a/resources/lang/en_US/email.php b/resources/lang/en_US/email.php index 2bdb563656..ddc329f6fd 100644 --- a/resources/lang/en_US/email.php +++ b/resources/lang/en_US/email.php @@ -70,7 +70,7 @@ return [ // known user login attempt 'failed_login_subject' => 'Firefly III detected a failed login attempt', 'failed_login_body' => 'Firefly III detected that somebody (you?) failed to login with your account ":email". Please verify that this was you.', - 'failed_login_message' => 'A failed login attempt on your Firefly III account ":email" was detected.', + 'failed_login_message' => 'A failed login attempt (:ip) on your Firefly III account ":email" was detected.', 'failed_login_warning' => 'If you recognize this IP address or the login attempt, you can ignore this message. If you didn\'t try to login, of if you have no idea what this is about, verify your password security, change it, and log out all other sessions. To do this, go to your profile page. Of course you have 2FA enabled already, right? Stay safe!', // registered diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index d9cf68b16b..44ef268444 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -26,2880 +26,2885 @@ declare(strict_types=1); return [ // general stuff: - 'stored_in_tz' => 'stored in ":timezone"', - 'displayed_in_tz' => 'displayed in ":timezone"', - 'close' => 'Close', - 'actions' => 'Actions', - 'edit' => 'Edit', - 'delete' => 'Delete', - 'split' => 'Split', - 'single_split' => 'Split', - 'clone' => 'Clone', - 'clone_and_edit' => 'Clone and edit', - 'confirm_action' => 'Confirm action', - 'last_seven_days' => 'Last seven days', - 'last_thirty_days' => 'Last thirty days', - 'last_180_days' => 'Last 180 days', - 'month_to_date' => 'Month to date', - 'year_to_date' => 'Year to date', - 'YTD' => 'YTD', - 'welcome_back' => 'What\'s playing?', - 'main_dashboard_page_title' => 'Home', - 'everything' => 'Everything', - 'today' => 'today', - 'customRange' => 'Custom range', - 'date_range' => 'Date range', - 'apply' => 'Apply', - 'select_date' => 'Select date..', - 'cancel' => 'Cancel', - 'from' => 'From', - 'to' => 'To', - 'structure' => 'Structure', - 'help_translating' => 'This help text is not yet available in your language. Will you help translate?', - 'showEverything' => 'Show everything', - 'never' => 'Never', - 'no_results_for_empty_search' => 'Your search was empty, so nothing was found.', - 'removed_amount' => 'Removed :amount', - 'added_amount' => 'Added :amount', - 'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.', - 'Opening balance' => 'Opening balance', - 'create_new_stuff' => 'Create new stuff', - 'new_withdrawal' => 'New withdrawal', - 'create_new_transaction' => 'Create a new transaction', - 'sidebar_frontpage_create' => 'Create', - 'new_transaction' => 'New transaction', - 'no_rules_for_bill' => 'This subscription has no rules associated to it.', - 'go_to_asset_accounts' => 'View your asset accounts', - 'go_to_budgets' => 'Go to your budgets', - 'go_to_withdrawals' => 'Go to your withdrawals', - 'clones_journal_x' => 'This transaction is a clone of ":description" (#:id)', - 'go_to_categories' => 'Go to your categories', - 'go_to_bills' => 'Go to your subscriptions', - 'go_to_expense_accounts' => 'See your expense accounts', - 'go_to_revenue_accounts' => 'See your revenue accounts', - 'go_to_piggies' => 'Go to your piggy banks', - 'new_deposit' => 'New deposit', - 'new_transfer' => 'New transfer', - 'new_transfers' => 'New transfer', - 'new_asset_account' => 'New asset account', - 'new_expense_account' => 'New expense account', - 'new_revenue_account' => 'New revenue account', - 'new_liabilities_account' => 'New liability', - 'new_budget' => 'New budget', - 'new_bill' => 'New subscription', - 'block_account_logout' => 'You have been logged out. Blocked accounts cannot use this site. Did you register with a valid email address?', - 'flash_success' => 'Success!', - 'flash_info' => 'Message', - 'flash_warning' => 'Warning!', - 'flash_error' => 'Error!', - 'flash_danger' => 'Danger!', - 'flash_info_multiple' => 'There is one message|There are :count messages', - 'flash_error_multiple' => 'There is one error|There are :count errors', - 'net_worth' => 'Net worth', - 'help_for_this_page' => 'Help for this page', - 'help_for_this_page_body' => 'You can find more information about this page in the documentation.', - 'two_factor_welcome' => 'Hello!', - 'two_factor_enter_code' => 'To continue, please enter your two factor authentication code. Your application can generate it for you.', - 'two_factor_code_here' => 'Enter code here', - 'two_factor_title' => 'Two factor authentication', - 'authenticate' => 'Authenticate', - 'two_factor_forgot_title' => 'Lost two factor authentication', - 'two_factor_forgot' => 'I forgot my two-factor thing.', - 'two_factor_lost_header' => 'Lost your two factor authentication?', - 'two_factor_lost_intro' => 'If you lost your backup codes as well, you have bad luck. This is not something you can fix from the web interface. You have two choices.', - 'two_factor_lost_fix_self' => 'If you run your own instance of Firefly III, read this entry in the FAQ for instructions.', - 'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, :site_owner and ask them to reset your two factor authentication.', - 'mfa_backup_code' => 'You have used a backup code to login to Firefly III. It can\'t be used again, so cross it from your list.', - 'pref_two_factor_new_backup_codes' => 'Get new backup codes', - 'pref_two_factor_backup_code_count' => 'You have :count valid backup code.|You have :count valid backup codes.', - '2fa_i_have_them' => 'I stored them!', - 'warning_much_data' => ':days days of data may take a while to load.', - 'registered' => 'You have registered successfully!', - 'Default asset account' => 'Default asset account', - 'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the budgets-page. Budgets can help you keep track of expenses.', - 'no_bill_pointer' => 'You seem to have no subscription yet. You should create some on the subscription-page. Subscriptions can help you keep track of expenses.', - 'Savings account' => 'Savings account', - 'Credit card' => 'Credit card', - 'source_accounts' => 'Source account|Source accounts', - 'destination_accounts' => 'Destination account|Destination accounts', - 'user_id_is' => 'Your user id is :user', - 'field_supports_markdown' => 'This field supports Markdown.', - 'need_more_help' => 'If you need more help using Firefly III, please open a ticket on Github.', - 'reenable_intro_text' => 'You can also re-enable the introduction guidance.', - 'intro_boxes_after_refresh' => 'The introduction boxes will reappear when you refresh the page.', - 'show_all_no_filter' => 'Show all transactions without grouping them by date.', - 'expenses_by_category' => 'Expenses by category', - 'expenses_by_budget' => 'Expenses by budget', - 'income_by_category' => 'Income by category', - 'expenses_by_asset_account' => 'Expenses by asset account', - 'expenses_by_expense_account' => 'Expenses by expense account', - 'cannot_redirect_to_account' => 'Firefly III cannot redirect you to the correct page. Apologies.', - 'sum_of_expenses' => 'Sum of expenses', - 'sum_of_income' => 'Sum of income', - 'liabilities' => 'Liabilities', - 'spent_in_specific_budget' => 'Spent in budget ":budget"', - 'spent_in_specific_double' => 'Spent in account ":account"', - 'earned_in_specific_double' => 'Earned in account ":account"', - 'source_account' => 'Source account', - 'source_account_reconciliation' => 'You can\'t edit the source account of a reconciliation transaction.', - 'destination_account' => 'Destination account', - 'destination_account_reconciliation' => 'You can\'t edit the destination account of a reconciliation transaction.', - 'sum_of_expenses_in_budget' => 'Spent total in budget ":budget"', - 'left_in_budget_limit' => 'Left to spend according to budgeting', - 'current_period' => 'Current period', - 'show_the_current_period_and_overview' => 'Show the current period and overview', - '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', - 'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency', - 'chart_budget_in_period_only_currency' => 'The amount you budgeted was in :currency, so this chart will only show transactions in :currency.', - 'chart_account_in_period' => 'Chart for all transactions for account ":name" (:balance) between :start and :end', - 'chart_category_in_period' => 'Chart for all transactions for category ":name" between :start and :end', - 'chart_category_all' => 'Chart for all transactions for category ":name"', - 'clone_withdrawal' => 'Clone this withdrawal', - 'clone_deposit' => 'Clone this deposit', - 'clone_transfer' => 'Clone this transfer', - 'multi_select_no_selection' => 'None selected', - 'multi_select_select_all' => 'Select all', - 'multi_select_n_selected' => 'selected', - 'multi_select_all_selected' => 'All selected', - 'multi_select_filter_placeholder' => 'Find..', - 'intro_next_label' => 'Next', - 'intro_prev_label' => 'Previous', - 'intro_skip_label' => 'Skip', - 'intro_done_label' => 'Done', - 'between_dates_breadcrumb' => 'Between :start and :end', - 'all_journals_without_budget' => 'All transactions without a budget', - 'journals_without_budget' => 'Transactions without a budget', - 'all_journals_without_category' => 'All transactions without a category', - 'journals_without_category' => 'Transactions without a category', - 'all_journals_for_account' => 'All transactions for account :name', - 'chart_all_journals_for_account' => 'Chart of all transactions for account :name', - 'journals_in_period_for_account' => 'All transactions for account :name between :start and :end', - 'journals_in_period_for_account_js' => 'All transactions for account {title} between {start} and {end}', - 'transferred' => 'Transferred', - 'all_withdrawal' => 'All expenses', - 'all_transactions' => 'All transactions', - 'title_withdrawal_between' => 'All expenses between :start and :end', - 'all_deposit' => 'All revenue', - 'title_deposit_between' => 'All revenue between :start and :end', - 'all_transfers' => 'All transfers', - 'title_transfers_between' => 'All transfers between :start and :end', - 'all_transfer' => 'All transfers', - 'all_journals_for_tag' => 'All transactions for tag ":tag"', - 'title_transfer_between' => 'All transfers between :start and :end', - 'all_journals_for_category' => 'All transactions for category :name', - 'all_journals_for_budget' => 'All transactions for budget :name', - 'chart_all_journals_for_budget' => 'Chart of all transactions for budget :name', - 'journals_in_period_for_category' => 'All transactions for category :name between :start and :end', - 'journals_in_period_for_tag' => 'All transactions for tag :tag between :start and :end', - 'not_available_demo_user' => 'The feature you try to access is not available to demo users.', - 'exchange_rate_instructions' => 'Asset account "@name" only accepts transactions in @native_currency. If you wish to use @foreign_currency instead, make sure that the amount in @native_currency is known as well:', - 'transfer_exchange_rate_instructions' => 'Source asset account "@source_name" only accepts transactions in @source_currency. Destination asset account "@dest_name" only accepts transactions in @dest_currency. You must provide the transferred amount correctly in both currencies.', - 'transaction_data' => 'Transaction data', - 'invalid_server_configuration' => 'Invalid server configuration', - 'invalid_locale_settings' => 'Firefly III is unable to format monetary amounts because your server is missing the required packages. There are instructions how to do this.', - 'quickswitch' => 'Quickswitch', - 'sign_in_to_start' => 'Sign in to start your session', - 'sign_in' => 'Sign in', - 'register_new_account' => 'Register a new account', - 'forgot_my_password' => 'I forgot my password', - 'problems_with_input' => 'There were some problems with your input.', - 'reset_password' => 'Reset your password', - 'button_reset_password' => 'Reset password', - 'reset_button' => 'Reset', - 'want_to_login' => 'I want to login', - 'login_page_title' => 'Login to Firefly III', - 'register_page_title' => 'Register at Firefly III', - 'forgot_pw_page_title' => 'Forgot your password for Firefly III', - 'reset_pw_page_title' => 'Reset your password for Firefly III', - 'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.', - 'no_att_demo_user' => 'The demo user can\'t upload attachments.', - 'button_register' => 'Register', - 'authorization' => 'Authorization', - 'active_bills_only' => 'active subscription only', - 'active_bills_only_total' => 'all active subscriptions', - 'active_exp_bills_only' => 'active and expected subscriptions only', - 'active_exp_bills_only_total' => 'all active expected subscriptions only', - 'per_period_sum_1D' => 'Expected daily costs', - 'per_period_sum_1W' => 'Expected weekly costs', - 'per_period_sum_1M' => 'Expected monthly costs', - 'per_period_sum_3M' => 'Expected quarterly costs', - 'per_period_sum_6M' => 'Expected half-yearly costs', - 'per_period_sum_1Y' => 'Expected yearly costs', - 'average_per_bill' => 'average per subscription', - 'expected_total' => 'expected total', - 'reconciliation_account_name' => ':name reconciliation (:currency)', - 'saved' => 'Saved', - 'advanced_options' => 'Advanced options', - 'advanced_options_explain' => 'Some pages in Firefly III have advanced options hidden behind this button. This page doesn\'t have anything fancy here, but do check out the others!', - 'here_be_dragons' => 'Hic sunt dracones', + 'stored_in_tz' => 'stored in ":timezone"', + 'displayed_in_tz' => 'displayed in ":timezone"', + 'close' => 'Close', + 'actions' => 'Actions', + 'edit' => 'Edit', + 'transaction_journal_id' => 'Transaction journal ID', + 'delete' => 'Delete', + 'split' => 'Split', + 'single_split' => 'Split', + 'clone' => 'Clone', + 'clone_and_edit' => 'Clone and edit', + 'confirm_action' => 'Confirm action', + 'last_seven_days' => 'Last seven days', + 'last_thirty_days' => 'Last thirty days', + 'last_180_days' => 'Last 180 days', + 'month_to_date' => 'Month to date', + 'year_to_date' => 'Year to date', + 'YTD' => 'YTD', + 'welcome_back' => 'What\'s playing?', + 'main_dashboard_page_title' => 'Home', + 'everything' => 'Everything', + 'today' => 'today', + 'customRange' => 'Custom range', + 'date_range' => 'Date range', + 'apply' => 'Apply', + 'select_date' => 'Select date..', + 'cancel' => 'Cancel', + 'from' => 'From', + 'to' => 'To', + 'structure' => 'Structure', + 'help_translating' => 'This help text is not yet available in your language. Will you help translate?', + 'showEverything' => 'Show everything', + 'never' => 'Never', + 'no_results_for_empty_search' => 'Your search was empty, so nothing was found.', + 'removed_amount' => 'Removed :amount', + 'added_amount' => 'Added :amount', + 'asset_account_role_help' => 'Any extra options resulting from your choice can be set later.', + 'Opening balance' => 'Opening balance', + 'create_new_stuff' => 'Create new stuff', + 'new_withdrawal' => 'New withdrawal', + 'create_new_transaction' => 'Create a new transaction', + 'sidebar_frontpage_create' => 'Create', + 'new_transaction' => 'New transaction', + 'no_rules_for_bill' => 'This subscription has no rules associated to it.', + 'go_to_asset_accounts' => 'View your asset accounts', + 'go_to_budgets' => 'Go to your budgets', + 'go_to_withdrawals' => 'Go to your withdrawals', + 'clones_journal_x' => 'This transaction is a clone of ":description" (#:id)', + 'go_to_categories' => 'Go to your categories', + 'go_to_bills' => 'Go to your subscriptions', + 'go_to_expense_accounts' => 'See your expense accounts', + 'go_to_revenue_accounts' => 'See your revenue accounts', + 'go_to_piggies' => 'Go to your piggy banks', + 'new_deposit' => 'New deposit', + 'new_transfer' => 'New transfer', + 'new_transfers' => 'New transfer', + 'new_asset_account' => 'New asset account', + 'new_expense_account' => 'New expense account', + 'new_revenue_account' => 'New revenue account', + 'new_liabilities_account' => 'New liability', + 'new_budget' => 'New budget', + 'new_bill' => 'New subscription', + 'block_account_logout' => 'You have been logged out. Blocked accounts cannot use this site. Did you register with a valid email address?', + 'flash_success' => 'Success!', + 'flash_info' => 'Message', + 'flash_warning' => 'Warning!', + 'flash_error' => 'Error!', + 'flash_danger' => 'Danger!', + 'flash_info_multiple' => 'There is one message|There are :count messages', + 'flash_error_multiple' => 'There is one error|There are :count errors', + 'net_worth' => 'Net worth', + 'help_for_this_page' => 'Help for this page', + 'help_for_this_page_body' => 'You can find more information about this page in the documentation.', + 'two_factor_welcome' => 'Hello!', + 'two_factor_enter_code' => 'To continue, please enter your two factor authentication code. Your application can generate it for you.', + 'two_factor_code_here' => 'Enter code here', + 'two_factor_title' => 'Two factor authentication', + 'authenticate' => 'Authenticate', + 'two_factor_forgot_title' => 'Lost two factor authentication', + 'two_factor_forgot' => 'I forgot my two-factor thing.', + 'two_factor_lost_header' => 'Lost your two factor authentication?', + 'two_factor_lost_intro' => 'If you lost your backup codes as well, you have bad luck. This is not something you can fix from the web interface. You have two choices.', + 'two_factor_lost_fix_self' => 'If you run your own instance of Firefly III, read this entry in the FAQ for instructions.', + 'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, :site_owner and ask them to reset your two factor authentication.', + 'mfa_backup_code' => 'You have used a backup code to login to Firefly III. It can\'t be used again, so cross it from your list.', + 'pref_two_factor_new_backup_codes' => 'Get new backup codes', + 'pref_two_factor_backup_code_count' => 'You have :count valid backup code.|You have :count valid backup codes.', + '2fa_i_have_them' => 'I stored them!', + 'warning_much_data' => ':days days of data may take a while to load.', + 'registered' => 'You have registered successfully!', + 'Default asset account' => 'Default asset account', + 'no_budget_pointer' => 'You seem to have no budgets yet. You should create some on the budgets-page. Budgets can help you keep track of expenses.', + 'no_bill_pointer' => 'You seem to have no subscription yet. You should create some on the subscription-page. Subscriptions can help you keep track of expenses.', + 'Savings account' => 'Savings account', + 'Credit card' => 'Credit card', + 'source_accounts' => 'Source account|Source accounts', + 'destination_accounts' => 'Destination account|Destination accounts', + 'user_id_is' => 'Your user id is :user', + 'field_supports_markdown' => 'This field supports Markdown.', + 'need_more_help' => 'If you need more help using Firefly III, please open a ticket on Github.', + 'reenable_intro_text' => 'You can also re-enable the introduction guidance.', + 'intro_boxes_after_refresh' => 'The introduction boxes will reappear when you refresh the page.', + 'show_all_no_filter' => 'Show all transactions without grouping them by date.', + 'expenses_by_category' => 'Expenses by category', + 'expenses_by_budget' => 'Expenses by budget', + 'income_by_category' => 'Income by category', + 'expenses_by_asset_account' => 'Expenses by asset account', + 'expenses_by_expense_account' => 'Expenses by expense account', + 'cannot_redirect_to_account' => 'Firefly III cannot redirect you to the correct page. Apologies.', + 'sum_of_expenses' => 'Sum of expenses', + 'sum_of_income' => 'Sum of income', + 'liabilities' => 'Liabilities', + 'spent_in_specific_budget' => 'Spent in budget ":budget"', + 'spent_in_specific_double' => 'Spent in account ":account"', + 'earned_in_specific_double' => 'Earned in account ":account"', + 'source_account' => 'Source account', + 'source_account_reconciliation' => 'You can\'t edit the source account of a reconciliation transaction.', + 'destination_account' => 'Destination account', + 'destination_account_reconciliation' => 'You can\'t edit the destination account of a reconciliation transaction.', + 'sum_of_expenses_in_budget' => 'Spent total in budget ":budget"', + 'left_in_budget_limit' => 'Left to spend according to budgeting', + 'current_period' => 'Current period', + 'show_the_current_period_and_overview' => 'Show the current period and overview', + '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', + 'chart_budget_in_period' => 'Chart for all transactions for budget ":name" between :start and :end in :currency', + 'chart_budget_in_period_only_currency' => 'The amount you budgeted was in :currency, so this chart will only show transactions in :currency.', + 'chart_account_in_period' => 'Chart for all transactions for account ":name" (:balance) between :start and :end', + 'chart_category_in_period' => 'Chart for all transactions for category ":name" between :start and :end', + 'chart_category_all' => 'Chart for all transactions for category ":name"', + 'clone_withdrawal' => 'Clone this withdrawal', + 'clone_deposit' => 'Clone this deposit', + 'clone_transfer' => 'Clone this transfer', + 'multi_select_no_selection' => 'None selected', + 'multi_select_select_all' => 'Select all', + 'multi_select_n_selected' => 'selected', + 'multi_select_all_selected' => 'All selected', + 'multi_select_filter_placeholder' => 'Find..', + 'intro_next_label' => 'Next', + 'intro_prev_label' => 'Previous', + 'intro_skip_label' => 'Skip', + 'intro_done_label' => 'Done', + 'between_dates_breadcrumb' => 'Between :start and :end', + 'all_journals_without_budget' => 'All transactions without a budget', + 'journals_without_budget' => 'Transactions without a budget', + 'all_journals_without_category' => 'All transactions without a category', + 'journals_without_category' => 'Transactions without a category', + 'all_journals_for_account' => 'All transactions for account :name', + 'chart_all_journals_for_account' => 'Chart of all transactions for account :name', + 'journals_in_period_for_account' => 'All transactions for account :name between :start and :end', + 'journals_in_period_for_account_js' => 'All transactions for account {title} between {start} and {end}', + 'transferred' => 'Transferred', + 'all_withdrawal' => 'All expenses', + 'all_transactions' => 'All transactions', + 'title_withdrawal_between' => 'All expenses between :start and :end', + 'all_deposit' => 'All revenue', + 'title_deposit_between' => 'All revenue between :start and :end', + 'all_transfers' => 'All transfers', + 'title_transfers_between' => 'All transfers between :start and :end', + 'all_transfer' => 'All transfers', + 'all_journals_for_tag' => 'All transactions for tag ":tag"', + 'title_transfer_between' => 'All transfers between :start and :end', + 'all_journals_for_category' => 'All transactions for category :name', + 'all_journals_for_budget' => 'All transactions for budget :name', + 'chart_all_journals_for_budget' => 'Chart of all transactions for budget :name', + 'journals_in_period_for_category' => 'All transactions for category :name between :start and :end', + 'journals_in_period_for_tag' => 'All transactions for tag :tag between :start and :end', + 'not_available_demo_user' => 'The feature you try to access is not available to demo users.', + 'exchange_rate_instructions' => 'Asset account "@name" only accepts transactions in @native_currency. If you wish to use @foreign_currency instead, make sure that the amount in @native_currency is known as well:', + 'transfer_exchange_rate_instructions' => 'Source asset account "@source_name" only accepts transactions in @source_currency. Destination asset account "@dest_name" only accepts transactions in @dest_currency. You must provide the transferred amount correctly in both currencies.', + 'transaction_data' => 'Transaction data', + 'invalid_server_configuration' => 'Invalid server configuration', + 'invalid_locale_settings' => 'Firefly III is unable to format monetary amounts because your server is missing the required packages. There are instructions how to do this.', + 'quickswitch' => 'Quickswitch', + 'sign_in_to_start' => 'Sign in to start your session', + 'sign_in' => 'Sign in', + 'register_new_account' => 'Register a new account', + 'forgot_my_password' => 'I forgot my password', + 'problems_with_input' => 'There were some problems with your input.', + 'reset_password' => 'Reset your password', + 'button_reset_password' => 'Reset password', + 'reset_button' => 'Reset', + 'want_to_login' => 'I want to login', + 'login_page_title' => 'Login to Firefly III', + 'register_page_title' => 'Register at Firefly III', + 'forgot_pw_page_title' => 'Forgot your password for Firefly III', + 'reset_pw_page_title' => 'Reset your password for Firefly III', + 'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', + 'button_register' => 'Register', + 'authorization' => 'Authorization', + 'active_bills_only' => 'active subscription only', + 'active_bills_only_total' => 'all active subscriptions', + 'active_exp_bills_only' => 'active and expected subscriptions only', + 'active_exp_bills_only_total' => 'all active expected subscriptions only', + 'per_period_sum_1D' => 'Expected daily costs', + 'per_period_sum_1W' => 'Expected weekly costs', + 'per_period_sum_1M' => 'Expected monthly costs', + 'per_period_sum_3M' => 'Expected quarterly costs', + 'per_period_sum_6M' => 'Expected half-yearly costs', + 'per_period_sum_1Y' => 'Expected yearly costs', + 'average_per_bill' => 'average per subscription', + 'expected_total' => 'expected total', + 'reconciliation_account_name' => ':name reconciliation (:currency)', + 'saved' => 'Saved', + 'advanced_options' => 'Advanced options', + 'advanced_options_explain' => 'Some pages in Firefly III have advanced options hidden behind this button. This page doesn\'t have anything fancy here, but do check out the others!', + 'here_be_dragons' => 'Hic sunt dracones', // Webhooks - 'webhooks' => 'Webhooks', - 'webhooks_breadcrumb' => 'Webhooks', - 'webhooks_menu_disabled' => 'disabled', - 'no_webhook_messages' => 'There are no webhook messages', - 'webhook_trigger_STORE_TRANSACTION' => 'After transaction creation', - 'webhook_trigger_UPDATE_TRANSACTION' => 'After transaction update', - 'webhook_trigger_DESTROY_TRANSACTION' => 'After transaction delete', - 'webhook_response_TRANSACTIONS' => 'Transaction details', - 'webhook_response_ACCOUNTS' => 'Account details', - 'webhook_response_none_NONE' => 'No details', - 'webhook_delivery_JSON' => 'JSON', - 'inspect' => 'Inspect', - 'create_new_webhook' => 'Create new webhook', - 'webhooks_create_breadcrumb' => 'Create new webhook', - 'webhook_trigger_form_help' => 'Indicate on what event the webhook will trigger', - 'webhook_response_form_help' => 'Indicate what the webhook must submit to the URL.', - 'webhook_delivery_form_help' => 'Which format the webhook must deliver data in.', - 'webhook_active_form_help' => 'The webhook must be active or it won\'t be called.', - 'stored_new_webhook' => 'Stored new webhook ":title"', - 'delete_webhook' => 'Delete webhook', - 'deleted_webhook' => 'Deleted webhook ":title"', - 'edit_webhook' => 'Edit webhook ":title"', - 'updated_webhook' => 'Updated webhook ":title"', - 'edit_webhook_js' => 'Edit webhook "{title}"', - 'show_webhook' => 'Webhook ":title"', - 'webhook_was_triggered' => 'The webhook was triggered on the indicated transaction. Please wait for results to appear.', - 'webhook_messages' => 'Webhook message', - 'view_message' => 'View message', - 'view_attempts' => 'View failed attempts', - 'message_content_title' => 'Webhook message content', - 'message_content_help' => 'This is the content of the message that was sent (or tried) using this webhook.', - 'attempt_content_title' => 'Webhook attempts', - 'attempt_content_help' => 'These are all the unsuccessful attempts of this webhook message to submit to the configured URL. After some time, Firefly III will stop trying.', - 'no_attempts' => 'There are no unsuccessful attempts. That\'s a good thing!', - 'webhook_attempt_at' => 'Attempt at {moment}', - 'logs' => 'Logs', - 'response' => 'Response', - 'visit_webhook_url' => 'Visit webhook URL', - 'reset_webhook_secret' => 'Reset webhook secret', - 'webhook_stored_link' => 'Webhook #{ID} ("{title}") has been stored.', - 'webhook_updated_link' => 'Webhook #{ID} ("{title}") has been updated.', + 'webhooks' => 'Webhooks', + 'webhooks_breadcrumb' => 'Webhooks', + 'webhooks_menu_disabled' => 'disabled', + 'no_webhook_messages' => 'There are no webhook messages', + 'webhook_trigger_STORE_TRANSACTION' => 'After transaction creation', + 'webhook_trigger_UPDATE_TRANSACTION' => 'After transaction update', + 'webhook_trigger_DESTROY_TRANSACTION' => 'After transaction delete', + 'webhook_response_TRANSACTIONS' => 'Transaction details', + 'webhook_response_ACCOUNTS' => 'Account details', + 'webhook_response_none_NONE' => 'No details', + 'webhook_delivery_JSON' => 'JSON', + 'inspect' => 'Inspect', + 'create_new_webhook' => 'Create new webhook', + 'webhooks_create_breadcrumb' => 'Create new webhook', + 'webhook_trigger_form_help' => 'Indicate on what event the webhook will trigger', + 'webhook_response_form_help' => 'Indicate what the webhook must submit to the URL.', + 'webhook_delivery_form_help' => 'Which format the webhook must deliver data in.', + 'webhook_active_form_help' => 'The webhook must be active or it won\'t be called.', + 'stored_new_webhook' => 'Stored new webhook ":title"', + 'delete_webhook' => 'Delete webhook', + 'deleted_webhook' => 'Deleted webhook ":title"', + 'edit_webhook' => 'Edit webhook ":title"', + 'updated_webhook' => 'Updated webhook ":title"', + 'edit_webhook_js' => 'Edit webhook "{title}"', + 'show_webhook' => 'Webhook ":title"', + 'webhook_was_triggered' => 'The webhook was triggered on the indicated transaction. Please wait for results to appear.', + 'webhook_messages' => 'Webhook message', + 'view_message' => 'View message', + 'view_attempts' => 'View failed attempts', + 'message_content_title' => 'Webhook message content', + 'message_content_help' => 'This is the content of the message that was sent (or tried) using this webhook.', + 'attempt_content_title' => 'Webhook attempts', + 'attempt_content_help' => 'These are all the unsuccessful attempts of this webhook message to submit to the configured URL. After some time, Firefly III will stop trying.', + 'no_attempts' => 'There are no unsuccessful attempts. That\'s a good thing!', + 'webhook_attempt_at' => 'Attempt at {moment}', + 'logs' => 'Logs', + 'response' => 'Response', + 'visit_webhook_url' => 'Visit webhook URL', + 'reset_webhook_secret' => 'Reset webhook secret', + 'webhook_stored_link' => 'Webhook #{ID} ("{title}") has been stored.', + 'webhook_updated_link' => 'Webhook #{ID} ("{title}") has been updated.', // API access - 'authorization_request' => 'Firefly III v:version Authorization Request', - 'authorization_request_intro' => 'Application ":client" is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', - 'authorization_request_site' => 'You will be redirected to :url which will then be able to access your Firefly III data.', - 'authorization_request_invalid' => 'This access request is invalid. Please never follow this link again.', - 'scopes_will_be_able' => 'This application will be able to:', - 'button_authorize' => 'Authorize', - 'none_in_select_list' => '(none)', - 'no_piggy_bank' => '(no piggy bank)', - 'name_in_currency' => ':name in :currency', - 'paid_in_currency' => 'Paid in :currency', - 'unpaid_in_currency' => 'Unpaid in :currency', - 'is_alpha_warning' => 'You are running an ALPHA version. Be wary of bugs and issues.', - 'is_beta_warning' => 'You are running an BETA version. Be wary of bugs and issues.', - 'all_destination_accounts' => 'Destination accounts', - 'all_source_accounts' => 'Source accounts', - 'back_to_index' => 'Back to the index', - 'cant_logout_guard' => 'Firefly III can\'t log you out.', - 'internal_reference' => 'Internal reference', + 'authorization_request' => 'Firefly III v:version Authorization Request', + 'authorization_request_intro' => 'Application ":client" is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', + 'authorization_request_site' => 'You will be redirected to :url which will then be able to access your Firefly III data.', + 'authorization_request_invalid' => 'This access request is invalid. Please never follow this link again.', + 'scopes_will_be_able' => 'This application will be able to:', + 'button_authorize' => 'Authorize', + 'none_in_select_list' => '(none)', + 'no_piggy_bank' => '(no piggy bank)', + 'name_in_currency' => ':name in :currency', + 'paid_in_currency' => 'Paid in :currency', + 'unpaid_in_currency' => 'Unpaid in :currency', + 'is_alpha_warning' => 'You are running an ALPHA version. Be wary of bugs and issues.', + 'is_beta_warning' => 'You are running an BETA version. Be wary of bugs and issues.', + 'all_destination_accounts' => 'Destination accounts', + 'all_source_accounts' => 'Source accounts', + 'back_to_index' => 'Back to the index', + 'cant_logout_guard' => 'Firefly III can\'t log you out.', + 'internal_reference' => 'Internal reference', // check for updates: - 'update_check_title' => 'Check for updates', - 'admin_update_check_title' => 'Automatically check for update', - 'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact the Firefly III update server to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.', - 'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the settings to indicate if you would like this feature to be enabled.', - 'updates_ask_me_later' => 'Ask me later', - 'updates_do_not_check' => 'Do not check for updates', - 'updates_enable_check' => 'Enable the check for updates', - 'admin_update_check_now_title' => 'Check for updates now', - 'admin_update_check_now_explain' => 'If you press the button, Firefly III will see if your current version is the latest.', - 'check_for_updates_button' => 'Check now!', - 'update_new_version_alert' => 'A new version of Firefly III is available. You are running :your_version, the latest version is :new_version which was released on :date.', - 'update_version_beta' => 'This version is a BETA version. You may run into issues.', - 'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.', - 'update_current_dev_older' => 'You are running development release ":version", which is older than the latest release :new_version. Please update!', - 'update_current_dev_newer' => 'You are running development release ":version", which is newer than the latest release :new_version.', - 'update_current_version_alert' => 'You are running :version, which is the latest available release.', - 'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.', - 'update_check_error' => 'An error occurred while checking for updates: :error', - 'unknown_error' => 'Unknown error. Sorry about that.', - 'disabled_but_check' => 'You disabled update checking. So don\'t forget to check for updates yourself every now and then. Thank you!', - 'admin_update_channel_title' => 'Update channel', - 'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.', - 'update_channel_stable' => 'Stable. Everything should work as expected.', - 'update_channel_beta' => 'Beta. New features but things may be broken.', - 'update_channel_alpha' => 'Alpha. We throw stuff in, and use whatever sticks.', + 'update_check_title' => 'Check for updates', + 'admin_update_check_title' => 'Automatically check for update', + 'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact the Firefly III update server to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.', + 'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the settings to indicate if you would like this feature to be enabled.', + 'updates_ask_me_later' => 'Ask me later', + 'updates_do_not_check' => 'Do not check for updates', + 'updates_enable_check' => 'Enable the check for updates', + 'admin_update_check_now_title' => 'Check for updates now', + 'admin_update_check_now_explain' => 'If you press the button, Firefly III will see if your current version is the latest.', + 'check_for_updates_button' => 'Check now!', + 'update_new_version_alert' => 'A new version of Firefly III is available. You are running :your_version, the latest version is :new_version which was released on :date.', + 'update_version_beta' => 'This version is a BETA version. You may run into issues.', + 'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.', + 'update_current_dev_older' => 'You are running development release ":version", which is older than the latest release :new_version. Please update!', + 'update_current_dev_newer' => 'You are running development release ":version", which is newer than the latest release :new_version.', + 'update_current_version_alert' => 'You are running :version, which is the latest available release.', + 'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.', + 'update_check_error' => 'An error occurred while checking for updates: :error', + 'unknown_error' => 'Unknown error. Sorry about that.', + 'disabled_but_check' => 'You disabled update checking. So don\'t forget to check for updates yourself every now and then. Thank you!', + 'admin_update_channel_title' => 'Update channel', + 'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.', + 'update_channel_stable' => 'Stable. Everything should work as expected.', + 'update_channel_beta' => 'Beta. New features but things may be broken.', + 'update_channel_alpha' => 'Alpha. We throw stuff in, and use whatever sticks.', // search - 'search' => 'Search', - 'search_query' => 'Query', - 'search_found_transactions' => 'Firefly III found :count transaction in :time seconds.|Firefly III found :count transactions in :time seconds.', - 'search_found_more_transactions' => 'Firefly III found more than :count transactions in :time seconds.', - 'search_for_overview' => 'Firefly III is searching for transactions that fulfill all of the following conditions:', - 'search_for_query' => 'All of these words must be present: :query', - 'search_for_excluded_words' => 'None of these words may be present: :excluded_words', - 'invalid_operators_list' => 'These search parameters are not valid and have been ignored.', + 'search' => 'Search', + 'search_query' => 'Query', + 'search_found_transactions' => 'Firefly III found :count transaction in :time seconds.|Firefly III found :count transactions in :time seconds.', + 'search_found_more_transactions' => 'Firefly III found more than :count transactions in :time seconds.', + 'search_for_overview' => 'Firefly III is searching for transactions that fulfill all of the following conditions:', + 'search_for_query' => 'All of these words must be present: :query', + 'search_for_excluded_words' => 'None of these words may be present: :excluded_words', + 'invalid_operators_list' => 'These search parameters are not valid and have been ignored.', // old - 'search_modifier_date_on' => 'Transaction date is ":value"', - 'search_modifier_not_date_on' => 'Transaction date is not ":value"', - 'search_modifier_reconciled' => 'Transaction is reconciled', - 'search_modifier_not_reconciled' => 'Transaction is not reconciled', - 'search_modifier_id' => 'Transaction ID is ":value"', - 'search_modifier_not_id' => 'Transaction ID is not ":value"', - 'search_modifier_date_before' => 'Transaction date is before or on ":value"', - 'search_modifier_date_after' => 'Transaction date is after or on ":value"', - 'search_modifier_external_id_is' => 'External ID is ":value"', - 'search_modifier_not_external_id_is' => 'External ID is not ":value"', - 'search_modifier_no_external_url' => 'The transaction has no external URL', - 'search_modifier_no_external_id' => 'The transaction has no external ID', - 'search_modifier_not_any_external_url' => 'The transaction has no external URL', - 'search_modifier_not_any_external_id' => 'The transaction has no external ID', - 'search_modifier_any_external_url' => 'The transaction must have a (any) external URL', - 'search_modifier_any_external_id' => 'The transaction must have a (any) external ID', - 'search_modifier_not_no_external_url' => 'The transaction must have a (any) external URL', - 'search_modifier_not_no_external_id' => 'The transaction must have a (any) external ID', - 'search_modifier_internal_reference_is' => 'Internal reference is ":value"', - 'search_modifier_not_internal_reference_is' => 'Internal reference is not ":value"', - 'search_modifier_description_starts' => 'Description starts with ":value"', - 'search_modifier_not_description_starts' => 'Description does not start with ":value"', - 'search_modifier_description_ends' => 'Description ends on ":value"', - 'search_modifier_not_description_ends' => 'Description does not end on ":value"', - 'search_modifier_description_contains' => 'Description contains ":value"', - 'search_modifier_not_description_contains' => 'Description does not contain ":value"', - 'search_modifier_description_is' => 'Description is exactly ":value"', - 'search_modifier_not_description_is' => 'Description is exactly not ":value"', - 'search_modifier_currency_is' => 'Transaction (foreign) currency is ":value"', - 'search_modifier_not_currency_is' => 'Transaction (foreign) currency is not ":value"', - 'search_modifier_foreign_currency_is' => 'Transaction foreign currency is ":value"', - 'search_modifier_not_foreign_currency_is' => 'Transaction foreign currency is not ":value"', - 'search_modifier_has_attachments' => 'The transaction must have an attachment', - 'search_modifier_has_no_category' => 'The transaction must have no category', - 'search_modifier_not_has_no_category' => 'The transaction must have a (any) category', - 'search_modifier_not_has_any_category' => 'The transaction must have no category', - 'search_modifier_has_any_category' => 'The transaction must have a (any) category', - 'search_modifier_has_no_budget' => 'The transaction must have no budget', - 'search_modifier_not_has_any_budget' => 'The transaction must have no budget', - 'search_modifier_has_any_budget' => 'The transaction must have a (any) budget', - 'search_modifier_not_has_no_budget' => 'The transaction must have a (any) budget', - 'search_modifier_has_no_bill' => 'The transaction must have no subscription', - 'search_modifier_not_has_no_bill' => 'The transaction must have a (any) subscription', - 'search_modifier_has_any_bill' => 'The transaction must have a (any) subscription', - 'search_modifier_not_has_any_bill' => 'The transaction must have no subscription', - 'search_modifier_has_no_tag' => 'The transaction must have no tags', - 'search_modifier_not_has_any_tag' => 'The transaction must have no tags', - 'search_modifier_not_has_no_tag' => 'The transaction must have a (any) tag', - 'search_modifier_has_any_tag' => 'The transaction must have a (any) tag', - 'search_modifier_notes_contains' => 'The transaction notes contain ":value"', - 'search_modifier_not_notes_contains' => 'The transaction notes do not contain ":value"', - 'search_modifier_notes_starts' => 'The transaction notes start with ":value"', - 'search_modifier_not_notes_starts' => 'The transaction notes do not start with ":value"', - 'search_modifier_notes_ends' => 'The transaction notes end with ":value"', - 'search_modifier_not_notes_ends' => 'The transaction notes do not end with ":value"', - 'search_modifier_notes_is' => 'The transaction notes are exactly ":value"', - 'search_modifier_not_notes_is' => 'The transaction notes are exactly not ":value"', - 'search_modifier_no_notes' => 'The transaction has no notes', - 'search_modifier_not_no_notes' => 'The transaction must have notes', - 'search_modifier_any_notes' => 'The transaction must have notes', - 'search_modifier_not_any_notes' => 'The transaction has no notes', - 'search_modifier_amount_is' => 'Amount is exactly :value', - 'search_modifier_not_amount_is' => 'Amount is not :value', - 'search_modifier_amount_less' => 'Amount is less than or equal to :value', - 'search_modifier_not_amount_more' => 'Amount is less than or equal to :value', - 'search_modifier_amount_more' => 'Amount is more than or equal to :value', - 'search_modifier_not_amount_less' => 'Amount is more than or equal to :value', - 'search_modifier_source_account_is' => 'Source account name is exactly ":value"', - 'search_modifier_not_source_account_is' => 'Source account name is not ":value"', - 'search_modifier_source_account_contains' => 'Source account name contains ":value"', - 'search_modifier_not_source_account_contains' => 'Source account name does not contain ":value"', - 'search_modifier_source_account_starts' => 'Source account name starts with ":value"', - 'search_modifier_not_source_account_starts' => 'Source account name does not start with ":value"', - 'search_modifier_source_account_ends' => 'Source account name ends with ":value"', - 'search_modifier_not_source_account_ends' => 'Source account name does not end with ":value"', - 'search_modifier_source_account_id' => 'Source account ID is :value', - 'search_modifier_not_source_account_id' => 'Source account ID is not :value', - 'search_modifier_source_account_nr_is' => 'Source account number (IBAN) is ":value"', - 'search_modifier_not_source_account_nr_is' => 'Source account number (IBAN) is not ":value"', - 'search_modifier_source_account_nr_contains' => 'Source account number (IBAN) contains ":value"', - 'search_modifier_not_source_account_nr_contains' => 'Source account number (IBAN) does not contain ":value"', - 'search_modifier_source_account_nr_starts' => 'Source account number (IBAN) starts with ":value"', - 'search_modifier_not_source_account_nr_starts' => 'Source account number (IBAN) does not start with ":value"', - 'search_modifier_source_account_nr_ends' => 'Source account number (IBAN) ends on ":value"', - 'search_modifier_not_source_account_nr_ends' => 'Source account number (IBAN) does not end on ":value"', - 'search_modifier_destination_account_is' => 'Destination account name is exactly ":value"', - 'search_modifier_not_destination_account_is' => 'Destination account name is not ":value"', - 'search_modifier_destination_account_contains' => 'Destination account name contains ":value"', - 'search_modifier_not_destination_account_contains' => 'Destination account name does not contain ":value"', - 'search_modifier_destination_account_starts' => 'Destination account name starts with ":value"', - 'search_modifier_not_destination_account_starts' => 'Destination account name does not start with ":value"', - 'search_modifier_destination_account_ends' => 'Destination account name ends on ":value"', - 'search_modifier_not_destination_account_ends' => 'Destination account name does not end on ":value"', - 'search_modifier_destination_account_id' => 'Destination account ID is :value', - 'search_modifier_not_destination_account_id' => 'Destination account ID is not :value', - 'search_modifier_destination_is_cash' => 'Destination account is the "(cash)" account', - 'search_modifier_not_destination_is_cash' => 'Destination account is not the "(cash)" account', - 'search_modifier_source_is_cash' => 'Source account is the "(cash)" account', - 'search_modifier_not_source_is_cash' => 'Source account is not the "(cash)" account', - 'search_modifier_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"', - 'search_modifier_not_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"', - 'search_modifier_destination_account_nr_contains' => 'Destination account number (IBAN) contains ":value"', - 'search_modifier_not_destination_account_nr_contains' => 'Destination account number (IBAN) does not contain ":value"', - 'search_modifier_destination_account_nr_starts' => 'Destination account number (IBAN) starts with ":value"', - 'search_modifier_not_destination_account_nr_starts' => 'Destination account number (IBAN) does not start with ":value"', - 'search_modifier_destination_account_nr_ends' => 'Destination account number (IBAN) ends with ":value"', - 'search_modifier_not_destination_account_nr_ends' => 'Destination account number (IBAN) does not end with ":value"', - 'search_modifier_account_id' => 'Source or destination account ID\'s is/are: :value', - 'search_modifier_not_account_id' => 'Source or destination account ID\'s is/are not: :value', - 'search_modifier_category_is' => 'Category is ":value"', - 'search_modifier_not_category_is' => 'Category is not ":value"', - 'search_modifier_budget_is' => 'Budget is ":value"', - 'search_modifier_not_budget_is' => 'Budget is not ":value"', - 'search_modifier_bill_is' => 'Subscription is ":value"', - 'search_modifier_not_bill_is' => 'Subscription is not ":value"', - 'search_modifier_transaction_type' => 'Transaction type is ":value"', - 'search_modifier_not_transaction_type' => 'Transaction type is not ":value"', - 'search_modifier_tag_is' => 'Tag is ":value"', - 'search_modifier_tag_contains' => 'Tag contains ":value"', - 'search_modifier_not_tag_contains' => 'Tag does not contain ":value"', - 'search_modifier_tag_ends' => 'Tag ends with ":value"', - 'search_modifier_tag_starts' => 'Tag starts with ":value"', - 'search_modifier_not_tag_is' => 'No tag is ":value"', - 'search_modifier_date_on_year' => 'Transaction is in year ":value"', - 'search_modifier_not_date_on_year' => 'Transaction is not in year ":value"', - 'search_modifier_date_on_month' => 'Transaction is in month ":value"', - 'search_modifier_not_date_on_month' => 'Transaction is not in month ":value"', - 'search_modifier_date_on_day' => 'Transaction is on day of month ":value"', - 'search_modifier_not_date_on_day' => 'Transaction is not on day of month ":value"', - 'search_modifier_date_before_year' => 'Transaction is before or in year ":value"', - 'search_modifier_date_before_month' => 'Transaction is before or in month ":value"', - 'search_modifier_date_before_day' => 'Transaction is before or on day of month ":value"', - 'search_modifier_date_after_year' => 'Transaction is in or after year ":value"', - 'search_modifier_date_after_month' => 'Transaction is in or after month ":value"', - 'search_modifier_date_after_day' => 'Transaction is after or on day of month ":value"', + 'search_modifier_date_on' => 'Transaction date is ":value"', + 'search_modifier_not_date_on' => 'Transaction date is not ":value"', + 'search_modifier_reconciled' => 'Transaction is reconciled', + 'search_modifier_not_reconciled' => 'Transaction is not reconciled', + 'search_modifier_id' => 'Transaction ID is ":value"', + 'search_modifier_not_id' => 'Transaction ID is not ":value"', + 'search_modifier_date_before' => 'Transaction date is before or on ":value"', + 'search_modifier_date_after' => 'Transaction date is after or on ":value"', + 'search_modifier_external_id_is' => 'External ID is ":value"', + 'search_modifier_not_external_id_is' => 'External ID is not ":value"', + 'search_modifier_no_external_url' => 'The transaction has no external URL', + 'search_modifier_no_external_id' => 'The transaction has no external ID', + 'search_modifier_not_any_external_url' => 'The transaction has no external URL', + 'search_modifier_not_any_external_id' => 'The transaction has no external ID', + 'search_modifier_any_external_url' => 'The transaction must have a (any) external URL', + 'search_modifier_any_external_id' => 'The transaction must have a (any) external ID', + 'search_modifier_not_no_external_url' => 'The transaction must have a (any) external URL', + 'search_modifier_not_no_external_id' => 'The transaction must have a (any) external ID', + 'search_modifier_internal_reference_is' => 'Internal reference is ":value"', + 'search_modifier_not_internal_reference_is' => 'Internal reference is not ":value"', + 'search_modifier_description_starts' => 'Description starts with ":value"', + 'search_modifier_not_description_starts' => 'Description does not start with ":value"', + 'search_modifier_description_ends' => 'Description ends on ":value"', + 'search_modifier_not_description_ends' => 'Description does not end on ":value"', + 'search_modifier_description_contains' => 'Description contains ":value"', + 'search_modifier_not_description_contains' => 'Description does not contain ":value"', + 'search_modifier_description_is' => 'Description is exactly ":value"', + 'search_modifier_not_description_is' => 'Description is exactly not ":value"', + 'search_modifier_currency_is' => 'Transaction (foreign) currency is ":value"', + 'search_modifier_not_currency_is' => 'Transaction (foreign) currency is not ":value"', + 'search_modifier_foreign_currency_is' => 'Transaction foreign currency is ":value"', + 'search_modifier_not_foreign_currency_is' => 'Transaction foreign currency is not ":value"', + 'search_modifier_has_attachments' => 'The transaction must have an attachment', + 'search_modifier_has_no_category' => 'The transaction must have no category', + 'search_modifier_not_has_no_category' => 'The transaction must have a (any) category', + 'search_modifier_not_has_any_category' => 'The transaction must have no category', + 'search_modifier_has_any_category' => 'The transaction must have a (any) category', + 'search_modifier_has_no_budget' => 'The transaction must have no budget', + 'search_modifier_not_has_any_budget' => 'The transaction must have no budget', + 'search_modifier_has_any_budget' => 'The transaction must have a (any) budget', + 'search_modifier_not_has_no_budget' => 'The transaction must have a (any) budget', + 'search_modifier_has_no_bill' => 'The transaction must have no subscription', + 'search_modifier_not_has_no_bill' => 'The transaction must have a (any) subscription', + 'search_modifier_has_any_bill' => 'The transaction must have a (any) subscription', + 'search_modifier_not_has_any_bill' => 'The transaction must have no subscription', + 'search_modifier_has_no_tag' => 'The transaction must have no tags', + 'search_modifier_not_has_any_tag' => 'The transaction must have no tags', + 'search_modifier_not_has_no_tag' => 'The transaction must have a (any) tag', + 'search_modifier_has_any_tag' => 'The transaction must have a (any) tag', + 'search_modifier_notes_contains' => 'The transaction notes contain ":value"', + 'search_modifier_not_notes_contains' => 'The transaction notes do not contain ":value"', + 'search_modifier_notes_starts' => 'The transaction notes start with ":value"', + 'search_modifier_not_notes_starts' => 'The transaction notes do not start with ":value"', + 'search_modifier_notes_ends' => 'The transaction notes end with ":value"', + 'search_modifier_not_notes_ends' => 'The transaction notes do not end with ":value"', + 'search_modifier_notes_is' => 'The transaction notes are exactly ":value"', + 'search_modifier_not_notes_is' => 'The transaction notes are exactly not ":value"', + 'search_modifier_no_notes' => 'The transaction has no notes', + 'search_modifier_not_no_notes' => 'The transaction must have notes', + 'search_modifier_any_notes' => 'The transaction must have notes', + 'search_modifier_not_any_notes' => 'The transaction has no notes', + 'search_modifier_amount_is' => 'Amount is exactly :value', + 'search_modifier_not_amount_is' => 'Amount is not :value', + 'search_modifier_amount_less' => 'Amount is less than or equal to :value', + 'search_modifier_not_amount_more' => 'Amount is less than or equal to :value', + 'search_modifier_amount_more' => 'Amount is more than or equal to :value', + 'search_modifier_not_amount_less' => 'Amount is more than or equal to :value', + 'search_modifier_source_account_is' => 'Source account name is exactly ":value"', + 'search_modifier_not_source_account_is' => 'Source account name is not ":value"', + 'search_modifier_source_account_contains' => 'Source account name contains ":value"', + 'search_modifier_not_source_account_contains' => 'Source account name does not contain ":value"', + 'search_modifier_source_account_starts' => 'Source account name starts with ":value"', + 'search_modifier_not_source_account_starts' => 'Source account name does not start with ":value"', + 'search_modifier_source_account_ends' => 'Source account name ends with ":value"', + 'search_modifier_not_source_account_ends' => 'Source account name does not end with ":value"', + 'search_modifier_source_account_id' => 'Source account ID is :value', + 'search_modifier_not_source_account_id' => 'Source account ID is not :value', + 'search_modifier_source_account_nr_is' => 'Source account number (IBAN) is ":value"', + 'search_modifier_not_source_account_nr_is' => 'Source account number (IBAN) is not ":value"', + 'search_modifier_source_account_nr_contains' => 'Source account number (IBAN) contains ":value"', + 'search_modifier_not_source_account_nr_contains' => 'Source account number (IBAN) does not contain ":value"', + 'search_modifier_source_account_nr_starts' => 'Source account number (IBAN) starts with ":value"', + 'search_modifier_not_source_account_nr_starts' => 'Source account number (IBAN) does not start with ":value"', + 'search_modifier_source_account_nr_ends' => 'Source account number (IBAN) ends on ":value"', + 'search_modifier_not_source_account_nr_ends' => 'Source account number (IBAN) does not end on ":value"', + 'search_modifier_destination_account_is' => 'Destination account name is exactly ":value"', + 'search_modifier_not_destination_account_is' => 'Destination account name is not ":value"', + 'search_modifier_destination_account_contains' => 'Destination account name contains ":value"', + 'search_modifier_not_destination_account_contains' => 'Destination account name does not contain ":value"', + 'search_modifier_destination_account_starts' => 'Destination account name starts with ":value"', + 'search_modifier_not_destination_account_starts' => 'Destination account name does not start with ":value"', + 'search_modifier_destination_account_ends' => 'Destination account name ends on ":value"', + 'search_modifier_not_destination_account_ends' => 'Destination account name does not end on ":value"', + 'search_modifier_destination_account_id' => 'Destination account ID is :value', + 'search_modifier_not_destination_account_id' => 'Destination account ID is not :value', + 'search_modifier_destination_is_cash' => 'Destination account is the "(cash)" account', + 'search_modifier_not_destination_is_cash' => 'Destination account is not the "(cash)" account', + 'search_modifier_source_is_cash' => 'Source account is the "(cash)" account', + 'search_modifier_not_source_is_cash' => 'Source account is not the "(cash)" account', + 'search_modifier_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"', + 'search_modifier_not_destination_account_nr_is' => 'Destination account number (IBAN) is ":value"', + 'search_modifier_destination_account_nr_contains' => 'Destination account number (IBAN) contains ":value"', + 'search_modifier_not_destination_account_nr_contains' => 'Destination account number (IBAN) does not contain ":value"', + 'search_modifier_destination_account_nr_starts' => 'Destination account number (IBAN) starts with ":value"', + 'search_modifier_not_destination_account_nr_starts' => 'Destination account number (IBAN) does not start with ":value"', + 'search_modifier_destination_account_nr_ends' => 'Destination account number (IBAN) ends with ":value"', + 'search_modifier_not_destination_account_nr_ends' => 'Destination account number (IBAN) does not end with ":value"', + 'search_modifier_account_id' => 'Source or destination account ID\'s is/are: :value', + 'search_modifier_not_account_id' => 'Source or destination account ID\'s is/are not: :value', + 'search_modifier_category_is' => 'Category is ":value"', + 'search_modifier_not_category_is' => 'Category is not ":value"', + 'search_modifier_budget_is' => 'Budget is ":value"', + 'search_modifier_not_budget_is' => 'Budget is not ":value"', + 'search_modifier_bill_is' => 'Subscription is ":value"', + 'search_modifier_not_bill_is' => 'Subscription is not ":value"', + 'search_modifier_transaction_type' => 'Transaction type is ":value"', + 'search_modifier_not_transaction_type' => 'Transaction type is not ":value"', + 'search_modifier_tag_is' => 'Tag is ":value"', + 'search_modifier_tag_contains' => 'Tag contains ":value"', + 'search_modifier_not_tag_contains' => 'Tag does not contain ":value"', + 'search_modifier_tag_ends' => 'Tag ends with ":value"', + 'search_modifier_tag_starts' => 'Tag starts with ":value"', + 'search_modifier_not_tag_is' => 'No tag is ":value"', + 'search_modifier_date_on_year' => 'Transaction is in year ":value"', + 'search_modifier_not_date_on_year' => 'Transaction is not in year ":value"', + 'search_modifier_date_on_month' => 'Transaction is in month ":value"', + 'search_modifier_not_date_on_month' => 'Transaction is not in month ":value"', + 'search_modifier_date_on_day' => 'Transaction is on day of month ":value"', + 'search_modifier_not_date_on_day' => 'Transaction is not on day of month ":value"', + 'search_modifier_date_before_year' => 'Transaction is before or in year ":value"', + 'search_modifier_date_before_month' => 'Transaction is before or in month ":value"', + 'search_modifier_date_before_day' => 'Transaction is before or on day of month ":value"', + 'search_modifier_date_after_year' => 'Transaction is in or after year ":value"', + 'search_modifier_date_after_month' => 'Transaction is in or after month ":value"', + 'search_modifier_date_after_day' => 'Transaction is after or on day of month ":value"', // new - 'search_modifier_tag_is_not' => 'No tag is ":value"', - 'search_modifier_not_tag_is_not' => 'Tag is ":value"', - 'search_modifier_account_is' => 'Either account is ":value"', - 'search_modifier_not_account_is' => 'Neither account is ":value"', - 'search_modifier_account_contains' => 'Either account contains ":value"', - 'search_modifier_not_account_contains' => 'Neither account contains ":value"', - 'search_modifier_account_ends' => 'Either account ends with ":value"', - 'search_modifier_not_account_ends' => 'Neither account ends with ":value"', - 'search_modifier_account_starts' => 'Either account starts with ":value"', - 'search_modifier_not_account_starts' => 'Neither account starts with ":value"', - 'search_modifier_account_nr_is' => 'Either account number / IBAN is ":value"', - 'search_modifier_not_account_nr_is' => 'Neither account number / IBAN is ":value"', - 'search_modifier_account_nr_contains' => 'Either account number / IBAN contains ":value"', - 'search_modifier_not_account_nr_contains' => 'Neither account number / IBAN contains ":value"', - 'search_modifier_account_nr_ends' => 'Either account number / IBAN ends with ":value"', - 'search_modifier_not_account_nr_ends' => 'Neither account number / IBAN ends with ":value"', - 'search_modifier_account_nr_starts' => 'Either account number / IBAN starts with ":value"', - 'search_modifier_not_account_nr_starts' => 'Neither account number / IBAN starts with ":value"', - 'search_modifier_category_contains' => 'Category contains ":value"', - 'search_modifier_not_category_contains' => 'Category does not contain ":value"', - 'search_modifier_category_ends' => 'Category ends on ":value"', - 'search_modifier_not_category_ends' => 'Category does not end on ":value"', - 'search_modifier_category_starts' => 'Category starts with ":value"', - 'search_modifier_not_category_starts' => 'Category does not start with ":value"', - 'search_modifier_budget_contains' => 'Budget contains ":value"', - 'search_modifier_not_budget_contains' => 'Budget does not contain ":value"', - 'search_modifier_budget_ends' => 'Budget ends with ":value"', - 'search_modifier_not_budget_ends' => 'Budget does not end on ":value"', - 'search_modifier_budget_starts' => 'Budget starts with ":value"', - 'search_modifier_not_budget_starts' => 'Budget does not start with ":value"', - 'search_modifier_bill_contains' => 'Subscription contains ":value"', - 'search_modifier_not_bill_contains' => 'Subscription does not contain ":value"', - 'search_modifier_bill_ends' => 'Subscription ends with ":value"', - 'search_modifier_not_bill_ends' => 'Subscription does not end on ":value"', - 'search_modifier_bill_starts' => 'Subscription starts with ":value"', - 'search_modifier_not_bill_starts' => 'Subscription does not start with ":value"', - 'search_modifier_external_id_contains' => 'External ID contains ":value"', - 'search_modifier_not_external_id_contains' => 'External ID does not contain ":value"', - 'search_modifier_external_id_ends' => 'External ID ends with ":value"', - 'search_modifier_not_external_id_ends' => 'External ID does not end with ":value"', - 'search_modifier_external_id_starts' => 'External ID starts with ":value"', - 'search_modifier_not_external_id_starts' => 'External ID does not start with ":value"', - 'search_modifier_internal_reference_contains' => 'Internal reference contains ":value"', - 'search_modifier_not_internal_reference_contains' => 'Internal reference does not contain ":value"', - 'search_modifier_internal_reference_ends' => 'Internal reference ends with ":value"', - 'search_modifier_internal_reference_starts' => 'Internal reference starts with ":value"', - 'search_modifier_not_internal_reference_ends' => 'Internal reference does not end with ":value"', - 'search_modifier_not_internal_reference_starts' => 'Internal reference does not start with ":value"', - 'search_modifier_external_url_is' => 'External URL is ":value"', - 'search_modifier_not_external_url_is' => 'External URL is not ":value"', - 'search_modifier_external_url_contains' => 'External URL contains ":value"', - 'search_modifier_not_external_url_contains' => 'External URL does not contain ":value"', - 'search_modifier_external_url_ends' => 'External URL ends with ":value"', - 'search_modifier_not_external_url_ends' => 'External URL does not end with ":value"', - 'search_modifier_external_url_starts' => 'External URL starts with ":value"', - 'search_modifier_not_external_url_starts' => 'External URL does not start with ":value"', - 'search_modifier_has_no_attachments' => 'Transaction has no attachments', - 'search_modifier_not_has_no_attachments' => 'Transaction has attachments', - 'search_modifier_not_has_attachments' => 'Transaction has no attachments', - 'search_modifier_account_is_cash' => 'Either account is the "(cash)" account.', - 'search_modifier_not_account_is_cash' => 'Neither account is the "(cash)" account.', - 'search_modifier_journal_id' => 'The journal ID is ":value"', - 'search_modifier_not_journal_id' => 'The journal ID is not ":value"', - 'search_modifier_recurrence_id' => 'The recurring transaction ID is ":value"', - 'search_modifier_not_recurrence_id' => 'The recurring transaction ID is not ":value"', - 'search_modifier_foreign_amount_is' => 'The foreign amount is ":value"', - 'search_modifier_not_foreign_amount_is' => 'The foreign amount is not ":value"', - 'search_modifier_foreign_amount_less' => 'The foreign amount is less than ":value"', - 'search_modifier_not_foreign_amount_more' => 'The foreign amount is less than ":value"', - 'search_modifier_not_foreign_amount_less' => 'The foreign amount is more than ":value"', - 'search_modifier_foreign_amount_more' => 'The foreign amount is more than ":value"', - 'search_modifier_exists' => 'Transaction exists (any transaction)', - 'search_modifier_not_exists' => 'Transaction does not exist (no transaction)', + 'search_modifier_tag_is_not' => 'No tag is ":value"', + 'search_modifier_not_tag_is_not' => 'Tag is ":value"', + 'search_modifier_account_is' => 'Either account is ":value"', + 'search_modifier_not_account_is' => 'Neither account is ":value"', + 'search_modifier_account_contains' => 'Either account contains ":value"', + 'search_modifier_not_account_contains' => 'Neither account contains ":value"', + 'search_modifier_account_ends' => 'Either account ends with ":value"', + 'search_modifier_not_account_ends' => 'Neither account ends with ":value"', + 'search_modifier_account_starts' => 'Either account starts with ":value"', + 'search_modifier_not_account_starts' => 'Neither account starts with ":value"', + 'search_modifier_account_nr_is' => 'Either account number / IBAN is ":value"', + 'search_modifier_not_account_nr_is' => 'Neither account number / IBAN is ":value"', + 'search_modifier_account_nr_contains' => 'Either account number / IBAN contains ":value"', + 'search_modifier_not_account_nr_contains' => 'Neither account number / IBAN contains ":value"', + 'search_modifier_account_nr_ends' => 'Either account number / IBAN ends with ":value"', + 'search_modifier_not_account_nr_ends' => 'Neither account number / IBAN ends with ":value"', + 'search_modifier_account_nr_starts' => 'Either account number / IBAN starts with ":value"', + 'search_modifier_not_account_nr_starts' => 'Neither account number / IBAN starts with ":value"', + 'search_modifier_category_contains' => 'Category contains ":value"', + 'search_modifier_not_category_contains' => 'Category does not contain ":value"', + 'search_modifier_category_ends' => 'Category ends on ":value"', + 'search_modifier_not_category_ends' => 'Category does not end on ":value"', + 'search_modifier_category_starts' => 'Category starts with ":value"', + 'search_modifier_not_category_starts' => 'Category does not start with ":value"', + 'search_modifier_budget_contains' => 'Budget contains ":value"', + 'search_modifier_not_budget_contains' => 'Budget does not contain ":value"', + 'search_modifier_budget_ends' => 'Budget ends with ":value"', + 'search_modifier_not_budget_ends' => 'Budget does not end on ":value"', + 'search_modifier_budget_starts' => 'Budget starts with ":value"', + 'search_modifier_not_budget_starts' => 'Budget does not start with ":value"', + 'search_modifier_bill_contains' => 'Subscription contains ":value"', + 'search_modifier_not_bill_contains' => 'Subscription does not contain ":value"', + 'search_modifier_bill_ends' => 'Subscription ends with ":value"', + 'search_modifier_not_bill_ends' => 'Subscription does not end on ":value"', + 'search_modifier_bill_starts' => 'Subscription starts with ":value"', + 'search_modifier_not_bill_starts' => 'Subscription does not start with ":value"', + 'search_modifier_external_id_contains' => 'External ID contains ":value"', + 'search_modifier_not_external_id_contains' => 'External ID does not contain ":value"', + 'search_modifier_external_id_ends' => 'External ID ends with ":value"', + 'search_modifier_not_external_id_ends' => 'External ID does not end with ":value"', + 'search_modifier_external_id_starts' => 'External ID starts with ":value"', + 'search_modifier_not_external_id_starts' => 'External ID does not start with ":value"', + 'search_modifier_internal_reference_contains' => 'Internal reference contains ":value"', + 'search_modifier_not_internal_reference_contains' => 'Internal reference does not contain ":value"', + 'search_modifier_internal_reference_ends' => 'Internal reference ends with ":value"', + 'search_modifier_internal_reference_starts' => 'Internal reference starts with ":value"', + 'search_modifier_not_internal_reference_ends' => 'Internal reference does not end with ":value"', + 'search_modifier_not_internal_reference_starts' => 'Internal reference does not start with ":value"', + 'search_modifier_external_url_is' => 'External URL is ":value"', + 'search_modifier_not_external_url_is' => 'External URL is not ":value"', + 'search_modifier_external_url_contains' => 'External URL contains ":value"', + 'search_modifier_not_external_url_contains' => 'External URL does not contain ":value"', + 'search_modifier_external_url_ends' => 'External URL ends with ":value"', + 'search_modifier_not_external_url_ends' => 'External URL does not end with ":value"', + 'search_modifier_external_url_starts' => 'External URL starts with ":value"', + 'search_modifier_not_external_url_starts' => 'External URL does not start with ":value"', + 'search_modifier_has_no_attachments' => 'Transaction has no attachments', + 'search_modifier_not_has_no_attachments' => 'Transaction has attachments', + 'search_modifier_not_has_attachments' => 'Transaction has no attachments', + 'search_modifier_account_is_cash' => 'Either account is the "(cash)" account.', + 'search_modifier_not_account_is_cash' => 'Neither account is the "(cash)" account.', + 'search_modifier_journal_id' => 'The journal ID is ":value"', + 'search_modifier_not_journal_id' => 'The journal ID is not ":value"', + 'search_modifier_recurrence_id' => 'The recurring transaction ID is ":value"', + 'search_modifier_not_recurrence_id' => 'The recurring transaction ID is not ":value"', + 'search_modifier_foreign_amount_is' => 'The foreign amount is ":value"', + 'search_modifier_not_foreign_amount_is' => 'The foreign amount is not ":value"', + 'search_modifier_foreign_amount_less' => 'The foreign amount is less than ":value"', + 'search_modifier_not_foreign_amount_more' => 'The foreign amount is less than ":value"', + 'search_modifier_not_foreign_amount_less' => 'The foreign amount is more than ":value"', + 'search_modifier_foreign_amount_more' => 'The foreign amount is more than ":value"', + 'search_modifier_exists' => 'Transaction exists (any transaction)', + 'search_modifier_not_exists' => 'Transaction does not exist (no transaction)', // date fields - 'search_modifier_interest_date_on' => 'Transaction interest date is ":value"', - 'search_modifier_not_interest_date_on' => 'Transaction interest date is not ":value"', - 'search_modifier_interest_date_on_year' => 'Transaction interest date is in year ":value"', - 'search_modifier_not_interest_date_on_year' => 'Transaction interest date is not in year ":value"', - 'search_modifier_interest_date_on_month' => 'Transaction interest date is in month ":value"', - 'search_modifier_not_interest_date_on_month' => 'Transaction interest date is not in month ":value"', - 'search_modifier_interest_date_on_day' => 'Transaction interest date is on day of month ":value"', - 'search_modifier_not_interest_date_on_day' => 'Transaction interest date is not on day of month ":value"', - 'search_modifier_interest_date_before_year' => 'Transaction interest date is before or in year ":value"', - 'search_modifier_interest_date_before_month' => 'Transaction interest date is before or in month ":value"', - 'search_modifier_interest_date_before_day' => 'Transaction interest date is before or on day of month ":value"', - 'search_modifier_interest_date_after_year' => 'Transaction interest date is after or in year ":value"', - 'search_modifier_interest_date_after_month' => 'Transaction interest date is after or in month ":value"', - 'search_modifier_interest_date_after_day' => 'Transaction interest date is after or on day of month ":value"', - 'search_modifier_book_date_on_year' => 'Transaction book date is in year ":value"', - 'search_modifier_book_date_on_month' => 'Transaction book date is in month ":value"', - 'search_modifier_book_date_on_day' => 'Transaction book date is on day of month ":value"', - 'search_modifier_not_book_date_on_year' => 'Transaction book date is not in year ":value"', - 'search_modifier_not_book_date_on_month' => 'Transaction book date is not in month ":value"', - 'search_modifier_not_book_date_on_day' => 'Transaction book date is not on day of month ":value"', - 'search_modifier_book_date_before_year' => 'Transaction book date is before or in year ":value"', - 'search_modifier_book_date_before_month' => 'Transaction book date is before or in month ":value"', - 'search_modifier_book_date_before_day' => 'Transaction book date is before or on day of month ":value"', - 'search_modifier_book_date_after_year' => 'Transaction book date is after or in year ":value"', - 'search_modifier_book_date_after_month' => 'Transaction book date is after or in month ":value"', - 'search_modifier_book_date_after_day' => 'Transaction book date is after or on day of month ":value"', - 'search_modifier_process_date_on_year' => 'Transaction process date is in year ":value"', - 'search_modifier_process_date_on_month' => 'Transaction process date is in month ":value"', - 'search_modifier_process_date_on_day' => 'Transaction process date is on day of month ":value"', - 'search_modifier_not_process_date_on_year' => 'Transaction process date is not in year ":value"', - 'search_modifier_not_process_date_on_month' => 'Transaction process date is not in month ":value"', - 'search_modifier_not_process_date_on_day' => 'Transaction process date is not on day of month ":value"', - 'search_modifier_process_date_before_year' => 'Transaction process date is before or in year ":value"', - 'search_modifier_process_date_before_month' => 'Transaction process date is before or in month ":value"', - 'search_modifier_process_date_before_day' => 'Transaction process date is before or on day of month ":value"', - 'search_modifier_process_date_after_year' => 'Transaction process date is after or in year ":value"', - 'search_modifier_process_date_after_month' => 'Transaction process date is after or in month ":value"', - 'search_modifier_process_date_after_day' => 'Transaction process date is after or on day of month ":value"', - 'search_modifier_due_date_on_year' => 'Transaction due date is in year ":value"', - 'search_modifier_due_date_on_month' => 'Transaction due date is in month ":value"', - 'search_modifier_due_date_on_day' => 'Transaction due date is on day of month ":value"', - 'search_modifier_not_due_date_on_year' => 'Transaction due date is not in year ":value"', - 'search_modifier_not_due_date_on_month' => 'Transaction due date is not in month ":value"', - 'search_modifier_not_due_date_on_day' => 'Transaction due date is not on day of month ":value"', - 'search_modifier_due_date_before_year' => 'Transaction due date is before or in year ":value"', - 'search_modifier_due_date_before_month' => 'Transaction due date is before or in month ":value"', - 'search_modifier_due_date_before_day' => 'Transaction due date is before or on day of month ":value"', - 'search_modifier_due_date_after_year' => 'Transaction due date is after or in year ":value"', - 'search_modifier_due_date_after_month' => 'Transaction due date is after or in month ":value"', - 'search_modifier_due_date_after_day' => 'Transaction due date is after or on day of month ":value"', - 'search_modifier_payment_date_on_year' => 'Transaction payment date is in year ":value"', - 'search_modifier_payment_date_on_month' => 'Transaction payment date is in month ":value"', - 'search_modifier_payment_date_on_day' => 'Transaction payment date is on day of month ":value"', - 'search_modifier_not_payment_date_on_year' => 'Transaction payment date is not in year ":value"', - 'search_modifier_not_payment_date_on_month' => 'Transaction payment date is not in month ":value"', - 'search_modifier_not_payment_date_on_day' => 'Transaction payment date is not on day of month ":value"', - 'search_modifier_payment_date_before_year' => 'Transaction payment date is before or in year ":value"', - 'search_modifier_payment_date_before_month' => 'Transaction payment date is before or in month ":value"', - 'search_modifier_payment_date_before_day' => 'Transaction payment date is before or on day of month ":value"', - 'search_modifier_payment_date_after_year' => 'Transaction payment date is after or in year ":value"', - 'search_modifier_payment_date_after_month' => 'Transaction payment date is after or in month ":value"', - 'search_modifier_payment_date_after_day' => 'Transaction payment date is after or on day of month ":value"', - 'search_modifier_invoice_date_on_year' => 'Transaction invoice date is in year ":value"', - 'search_modifier_invoice_date_on_month' => 'Transaction invoice date is in month ":value"', - 'search_modifier_invoice_date_on_day' => 'Transaction invoice date is on day of month ":value"', - 'search_modifier_not_invoice_date_on_year' => 'Transaction invoice date is not in year ":value"', - 'search_modifier_not_invoice_date_on_month' => 'Transaction invoice date is not in month ":value"', - 'search_modifier_not_invoice_date_on_day' => 'Transaction invoice date is not on day of month ":value"', - 'search_modifier_invoice_date_before_year' => 'Transaction invoice date is before or in year ":value"', - 'search_modifier_invoice_date_before_month' => 'Transaction invoice date is before or in month ":value"', - 'search_modifier_invoice_date_before_day' => 'Transaction invoice date is before or on day of month ":value"', - 'search_modifier_invoice_date_after_year' => 'Transaction invoice date is after or in year ":value"', - 'search_modifier_invoice_date_after_month' => 'Transaction invoice date is after or in month ":value"', - 'search_modifier_invoice_date_after_day' => 'Transaction invoice date is after or on day of month ":value"', + 'search_modifier_interest_date_on' => 'Transaction interest date is ":value"', + 'search_modifier_not_interest_date_on' => 'Transaction interest date is not ":value"', + 'search_modifier_interest_date_on_year' => 'Transaction interest date is in year ":value"', + 'search_modifier_not_interest_date_on_year' => 'Transaction interest date is not in year ":value"', + 'search_modifier_interest_date_on_month' => 'Transaction interest date is in month ":value"', + 'search_modifier_not_interest_date_on_month' => 'Transaction interest date is not in month ":value"', + 'search_modifier_interest_date_on_day' => 'Transaction interest date is on day of month ":value"', + 'search_modifier_not_interest_date_on_day' => 'Transaction interest date is not on day of month ":value"', + 'search_modifier_interest_date_before_year' => 'Transaction interest date is before or in year ":value"', + 'search_modifier_interest_date_before_month' => 'Transaction interest date is before or in month ":value"', + 'search_modifier_interest_date_before_day' => 'Transaction interest date is before or on day of month ":value"', + 'search_modifier_interest_date_after_year' => 'Transaction interest date is after or in year ":value"', + 'search_modifier_interest_date_after_month' => 'Transaction interest date is after or in month ":value"', + 'search_modifier_interest_date_after_day' => 'Transaction interest date is after or on day of month ":value"', + 'search_modifier_book_date_on_year' => 'Transaction book date is in year ":value"', + 'search_modifier_book_date_on_month' => 'Transaction book date is in month ":value"', + 'search_modifier_book_date_on_day' => 'Transaction book date is on day of month ":value"', + 'search_modifier_not_book_date_on_year' => 'Transaction book date is not in year ":value"', + 'search_modifier_not_book_date_on_month' => 'Transaction book date is not in month ":value"', + 'search_modifier_not_book_date_on_day' => 'Transaction book date is not on day of month ":value"', + 'search_modifier_book_date_before_year' => 'Transaction book date is before or in year ":value"', + 'search_modifier_book_date_before_month' => 'Transaction book date is before or in month ":value"', + 'search_modifier_book_date_before_day' => 'Transaction book date is before or on day of month ":value"', + 'search_modifier_book_date_after_year' => 'Transaction book date is after or in year ":value"', + 'search_modifier_book_date_after_month' => 'Transaction book date is after or in month ":value"', + 'search_modifier_book_date_after_day' => 'Transaction book date is after or on day of month ":value"', + 'search_modifier_process_date_on_year' => 'Transaction process date is in year ":value"', + 'search_modifier_process_date_on_month' => 'Transaction process date is in month ":value"', + 'search_modifier_process_date_on_day' => 'Transaction process date is on day of month ":value"', + 'search_modifier_not_process_date_on_year' => 'Transaction process date is not in year ":value"', + 'search_modifier_not_process_date_on_month' => 'Transaction process date is not in month ":value"', + 'search_modifier_not_process_date_on_day' => 'Transaction process date is not on day of month ":value"', + 'search_modifier_process_date_before_year' => 'Transaction process date is before or in year ":value"', + 'search_modifier_process_date_before_month' => 'Transaction process date is before or in month ":value"', + 'search_modifier_process_date_before_day' => 'Transaction process date is before or on day of month ":value"', + 'search_modifier_process_date_after_year' => 'Transaction process date is after or in year ":value"', + 'search_modifier_process_date_after_month' => 'Transaction process date is after or in month ":value"', + 'search_modifier_process_date_after_day' => 'Transaction process date is after or on day of month ":value"', + 'search_modifier_due_date_on_year' => 'Transaction due date is in year ":value"', + 'search_modifier_due_date_on_month' => 'Transaction due date is in month ":value"', + 'search_modifier_due_date_on_day' => 'Transaction due date is on day of month ":value"', + 'search_modifier_not_due_date_on_year' => 'Transaction due date is not in year ":value"', + 'search_modifier_not_due_date_on_month' => 'Transaction due date is not in month ":value"', + 'search_modifier_not_due_date_on_day' => 'Transaction due date is not on day of month ":value"', + 'search_modifier_due_date_before_year' => 'Transaction due date is before or in year ":value"', + 'search_modifier_due_date_before_month' => 'Transaction due date is before or in month ":value"', + 'search_modifier_due_date_before_day' => 'Transaction due date is before or on day of month ":value"', + 'search_modifier_due_date_after_year' => 'Transaction due date is after or in year ":value"', + 'search_modifier_due_date_after_month' => 'Transaction due date is after or in month ":value"', + 'search_modifier_due_date_after_day' => 'Transaction due date is after or on day of month ":value"', + 'search_modifier_payment_date_on_year' => 'Transaction payment date is in year ":value"', + 'search_modifier_payment_date_on_month' => 'Transaction payment date is in month ":value"', + 'search_modifier_payment_date_on_day' => 'Transaction payment date is on day of month ":value"', + 'search_modifier_not_payment_date_on_year' => 'Transaction payment date is not in year ":value"', + 'search_modifier_not_payment_date_on_month' => 'Transaction payment date is not in month ":value"', + 'search_modifier_not_payment_date_on_day' => 'Transaction payment date is not on day of month ":value"', + 'search_modifier_payment_date_before_year' => 'Transaction payment date is before or in year ":value"', + 'search_modifier_payment_date_before_month' => 'Transaction payment date is before or in month ":value"', + 'search_modifier_payment_date_before_day' => 'Transaction payment date is before or on day of month ":value"', + 'search_modifier_payment_date_after_year' => 'Transaction payment date is after or in year ":value"', + 'search_modifier_payment_date_after_month' => 'Transaction payment date is after or in month ":value"', + 'search_modifier_payment_date_after_day' => 'Transaction payment date is after or on day of month ":value"', + 'search_modifier_invoice_date_on_year' => 'Transaction invoice date is in year ":value"', + 'search_modifier_invoice_date_on_month' => 'Transaction invoice date is in month ":value"', + 'search_modifier_invoice_date_on_day' => 'Transaction invoice date is on day of month ":value"', + 'search_modifier_not_invoice_date_on_year' => 'Transaction invoice date is not in year ":value"', + 'search_modifier_not_invoice_date_on_month' => 'Transaction invoice date is not in month ":value"', + 'search_modifier_not_invoice_date_on_day' => 'Transaction invoice date is not on day of month ":value"', + 'search_modifier_invoice_date_before_year' => 'Transaction invoice date is before or in year ":value"', + 'search_modifier_invoice_date_before_month' => 'Transaction invoice date is before or in month ":value"', + 'search_modifier_invoice_date_before_day' => 'Transaction invoice date is before or on day of month ":value"', + 'search_modifier_invoice_date_after_year' => 'Transaction invoice date is after or in year ":value"', + 'search_modifier_invoice_date_after_month' => 'Transaction invoice date is after or in month ":value"', + 'search_modifier_invoice_date_after_day' => 'Transaction invoice date is after or on day of month ":value"', // other dates - 'search_modifier_updated_at_on_year' => 'Transaction was last updated in year ":value"', - 'search_modifier_updated_at_on_month' => 'Transaction was last updated in month ":value"', - 'search_modifier_updated_at_on_day' => 'Transaction was last updated on day of month ":value"', - 'search_modifier_not_updated_at_on_year' => 'Transaction was not last updated in year ":value"', - 'search_modifier_not_updated_at_on_month' => 'Transaction was not last updated in month ":value"', - 'search_modifier_not_updated_at_on_day' => 'Transaction was not last updated on day of month ":value"', - 'search_modifier_updated_at_before_year' => 'Transaction was last updated in or before year ":value"', - 'search_modifier_updated_at_before_month' => 'Transaction was last updated in or before month ":value"', - 'search_modifier_updated_at_before_day' => 'Transaction was last updated on or before day of month ":value"', - 'search_modifier_updated_at_after_year' => 'Transaction was last updated in or after year ":value"', - 'search_modifier_updated_at_after_month' => 'Transaction was last updated in or after month ":value"', - 'search_modifier_updated_at_after_day' => 'Transaction was last updated on or after day of month ":value"', - 'search_modifier_created_at_on_year' => 'Transaction was created in year ":value"', - 'search_modifier_created_at_on_month' => 'Transaction was created in month ":value"', - 'search_modifier_created_at_on_day' => 'Transaction was created on day of month ":value"', - 'search_modifier_not_created_at_on_year' => 'Transaction was not created in year ":value"', - 'search_modifier_not_created_at_on_month' => 'Transaction was not created in month ":value"', - 'search_modifier_not_created_at_on_day' => 'Transaction was not created on day of month ":value"', - 'search_modifier_created_at_before_year' => 'Transaction was created in or before year ":value"', - 'search_modifier_created_at_before_month' => 'Transaction was created in or before month ":value"', - 'search_modifier_created_at_before_day' => 'Transaction was created on or before day of month ":value"', - 'search_modifier_created_at_after_year' => 'Transaction was created in or after year ":value"', - 'search_modifier_created_at_after_month' => 'Transaction was created in or after month ":value"', - 'search_modifier_created_at_after_day' => 'Transaction was created on or after day of month ":value"', - 'search_modifier_interest_date_before' => 'Transaction interest date is on or before ":value"', - 'search_modifier_interest_date_after' => 'Transaction interest date is on or after ":value"', - 'search_modifier_book_date_on' => 'Transaction book date is on ":value"', - 'search_modifier_not_book_date_on' => 'Transaction book date is not on ":value"', - 'search_modifier_book_date_before' => 'Transaction book date is on or before ":value"', - 'search_modifier_book_date_after' => 'Transaction book date is on or after ":value"', - 'search_modifier_process_date_on' => 'Transaction process date is on ":value"', - 'search_modifier_not_process_date_on' => 'Transaction process date is not on ":value"', - 'search_modifier_process_date_before' => 'Transaction process date is on or before ":value"', - 'search_modifier_process_date_after' => 'Transaction process date is on or after ":value"', - 'search_modifier_due_date_on' => 'Transaction due date is on ":value"', - 'search_modifier_not_due_date_on' => 'Transaction due date is not on ":value"', - 'search_modifier_due_date_before' => 'Transaction due date is on or before ":value"', - 'search_modifier_due_date_after' => 'Transaction due date is on or after ":value"', - 'search_modifier_payment_date_on' => 'Transaction payment date is on ":value"', - 'search_modifier_not_payment_date_on' => 'Transaction payment date is not on ":value"', - 'search_modifier_payment_date_before' => 'Transaction payment date is on or before ":value"', - 'search_modifier_payment_date_after' => 'Transaction payment date is on or after ":value"', - 'search_modifier_invoice_date_on' => 'Transaction invoice date is on ":value"', - 'search_modifier_not_invoice_date_on' => 'Transaction invoice date is not on ":value"', - 'search_modifier_invoice_date_before' => 'Transaction invoice date is on or before ":value"', - 'search_modifier_invoice_date_after' => 'Transaction invoice date is on or after ":value"', - 'search_modifier_created_at_on' => 'Transaction was created on ":value"', - 'search_modifier_not_created_at_on' => 'Transaction was not created on ":value"', - 'search_modifier_created_at_before' => 'Transaction was created on or before ":value"', - 'search_modifier_created_at_after' => 'Transaction was created on or after ":value"', - 'search_modifier_updated_at_on' => 'Transaction was updated on ":value"', - 'search_modifier_not_updated_at_on' => 'Transaction was not updated on ":value"', - 'search_modifier_updated_at_before' => 'Transaction was updated on or before ":value"', - 'search_modifier_updated_at_after' => 'Transaction was updated on or after ":value"', + 'search_modifier_updated_at_on_year' => 'Transaction was last updated in year ":value"', + 'search_modifier_updated_at_on_month' => 'Transaction was last updated in month ":value"', + 'search_modifier_updated_at_on_day' => 'Transaction was last updated on day of month ":value"', + 'search_modifier_not_updated_at_on_year' => 'Transaction was not last updated in year ":value"', + 'search_modifier_not_updated_at_on_month' => 'Transaction was not last updated in month ":value"', + 'search_modifier_not_updated_at_on_day' => 'Transaction was not last updated on day of month ":value"', + 'search_modifier_updated_at_before_year' => 'Transaction was last updated in or before year ":value"', + 'search_modifier_updated_at_before_month' => 'Transaction was last updated in or before month ":value"', + 'search_modifier_updated_at_before_day' => 'Transaction was last updated on or before day of month ":value"', + 'search_modifier_updated_at_after_year' => 'Transaction was last updated in or after year ":value"', + 'search_modifier_updated_at_after_month' => 'Transaction was last updated in or after month ":value"', + 'search_modifier_updated_at_after_day' => 'Transaction was last updated on or after day of month ":value"', + 'search_modifier_created_at_on_year' => 'Transaction was created in year ":value"', + 'search_modifier_created_at_on_month' => 'Transaction was created in month ":value"', + 'search_modifier_created_at_on_day' => 'Transaction was created on day of month ":value"', + 'search_modifier_not_created_at_on_year' => 'Transaction was not created in year ":value"', + 'search_modifier_not_created_at_on_month' => 'Transaction was not created in month ":value"', + 'search_modifier_not_created_at_on_day' => 'Transaction was not created on day of month ":value"', + 'search_modifier_created_at_before_year' => 'Transaction was created in or before year ":value"', + 'search_modifier_created_at_before_month' => 'Transaction was created in or before month ":value"', + 'search_modifier_created_at_before_day' => 'Transaction was created on or before day of month ":value"', + 'search_modifier_created_at_after_year' => 'Transaction was created in or after year ":value"', + 'search_modifier_created_at_after_month' => 'Transaction was created in or after month ":value"', + 'search_modifier_created_at_after_day' => 'Transaction was created on or after day of month ":value"', + 'search_modifier_interest_date_before' => 'Transaction interest date is on or before ":value"', + 'search_modifier_interest_date_after' => 'Transaction interest date is on or after ":value"', + 'search_modifier_book_date_on' => 'Transaction book date is on ":value"', + 'search_modifier_not_book_date_on' => 'Transaction book date is not on ":value"', + 'search_modifier_book_date_before' => 'Transaction book date is on or before ":value"', + 'search_modifier_book_date_after' => 'Transaction book date is on or after ":value"', + 'search_modifier_process_date_on' => 'Transaction process date is on ":value"', + 'search_modifier_not_process_date_on' => 'Transaction process date is not on ":value"', + 'search_modifier_process_date_before' => 'Transaction process date is on or before ":value"', + 'search_modifier_process_date_after' => 'Transaction process date is on or after ":value"', + 'search_modifier_due_date_on' => 'Transaction due date is on ":value"', + 'search_modifier_not_due_date_on' => 'Transaction due date is not on ":value"', + 'search_modifier_due_date_before' => 'Transaction due date is on or before ":value"', + 'search_modifier_due_date_after' => 'Transaction due date is on or after ":value"', + 'search_modifier_payment_date_on' => 'Transaction payment date is on ":value"', + 'search_modifier_not_payment_date_on' => 'Transaction payment date is not on ":value"', + 'search_modifier_payment_date_before' => 'Transaction payment date is on or before ":value"', + 'search_modifier_payment_date_after' => 'Transaction payment date is on or after ":value"', + 'search_modifier_invoice_date_on' => 'Transaction invoice date is on ":value"', + 'search_modifier_not_invoice_date_on' => 'Transaction invoice date is not on ":value"', + 'search_modifier_invoice_date_before' => 'Transaction invoice date is on or before ":value"', + 'search_modifier_invoice_date_after' => 'Transaction invoice date is on or after ":value"', + 'search_modifier_created_at_on' => 'Transaction was created on ":value"', + 'search_modifier_not_created_at_on' => 'Transaction was not created on ":value"', + 'search_modifier_created_at_before' => 'Transaction was created on or before ":value"', + 'search_modifier_created_at_after' => 'Transaction was created on or after ":value"', + 'search_modifier_updated_at_on' => 'Transaction was updated on ":value"', + 'search_modifier_not_updated_at_on' => 'Transaction was not updated on ":value"', + 'search_modifier_updated_at_before' => 'Transaction was updated on or before ":value"', + 'search_modifier_updated_at_after' => 'Transaction was updated on or after ":value"', - 'search_modifier_attachment_name_is' => 'Any attachment\'s name is ":value"', - 'search_modifier_attachment_name_contains' => 'Any attachment\'s name contains ":value"', - 'search_modifier_attachment_name_starts' => 'Any attachment\'s name starts with ":value"', - 'search_modifier_attachment_name_ends' => 'Any attachment\'s name ends with ":value"', - 'search_modifier_attachment_notes_are' => 'Any attachment\'s notes are ":value"', - 'search_modifier_attachment_notes_contains' => 'Any attachment\'s notes contain ":value"', - 'search_modifier_attachment_notes_starts' => 'Any attachment\'s notes start with ":value"', - 'search_modifier_attachment_notes_ends' => 'Any attachment\'s notes end with ":value"', - 'search_modifier_not_attachment_name_is' => 'Any attachment\'s name is not ":value"', - 'search_modifier_not_attachment_name_contains' => 'Any attachment\'s name does not contain ":value"', - 'search_modifier_not_attachment_name_starts' => 'Any attachment\'s name does not start with ":value"', - 'search_modifier_not_attachment_name_ends' => 'Any attachment\'s name does not end with ":value"', - 'search_modifier_not_attachment_notes_are' => 'Any attachment\'s notes are not ":value"', - 'search_modifier_not_attachment_notes_contains' => 'Any attachment\'s notes do not contain ":value"', - 'search_modifier_not_attachment_notes_starts' => 'Any attachment\'s notes start with ":value"', - 'search_modifier_not_attachment_notes_ends' => 'Any attachment\'s notes do not end with ":value"', - 'search_modifier_sepa_ct_is' => 'SEPA CT is ":value"', - 'update_rule_from_query' => 'Update rule ":rule" from search query', - 'create_rule_from_query' => 'Create new rule from search query', - 'rule_from_search_words' => 'The rule engine has a hard time handling ":string". The suggested rule that fits your search query may give different results. Please verify the rule triggers carefully.', + 'search_modifier_attachment_name_is' => 'Any attachment\'s name is ":value"', + 'search_modifier_attachment_name_contains' => 'Any attachment\'s name contains ":value"', + 'search_modifier_attachment_name_starts' => 'Any attachment\'s name starts with ":value"', + 'search_modifier_attachment_name_ends' => 'Any attachment\'s name ends with ":value"', + 'search_modifier_attachment_notes_are' => 'Any attachment\'s notes are ":value"', + 'search_modifier_attachment_notes_contains' => 'Any attachment\'s notes contain ":value"', + 'search_modifier_attachment_notes_starts' => 'Any attachment\'s notes start with ":value"', + 'search_modifier_attachment_notes_ends' => 'Any attachment\'s notes end with ":value"', + 'search_modifier_not_attachment_name_is' => 'Any attachment\'s name is not ":value"', + 'search_modifier_not_attachment_name_contains' => 'Any attachment\'s name does not contain ":value"', + 'search_modifier_not_attachment_name_starts' => 'Any attachment\'s name does not start with ":value"', + 'search_modifier_not_attachment_name_ends' => 'Any attachment\'s name does not end with ":value"', + 'search_modifier_not_attachment_notes_are' => 'Any attachment\'s notes are not ":value"', + 'search_modifier_not_attachment_notes_contains' => 'Any attachment\'s notes do not contain ":value"', + 'search_modifier_not_attachment_notes_starts' => 'Any attachment\'s notes start with ":value"', + 'search_modifier_not_attachment_notes_ends' => 'Any attachment\'s notes do not end with ":value"', + 'search_modifier_sepa_ct_is' => 'SEPA CT is ":value"', + 'update_rule_from_query' => 'Update rule ":rule" from search query', + 'create_rule_from_query' => 'Create new rule from search query', + 'rule_from_search_words' => 'The rule engine has a hard time handling ":string". The suggested rule that fits your search query may give different results. Please verify the rule triggers carefully.', // more new stuff - 'search_modifier_destination_balance_is' => 'Destination account balance is exactly ":value"', - 'search_modifier_not_destination_balance_is' => 'Destination account balance is NOT exactly ":value"', - 'search_modifier_source_balance_is' => 'Source account balance is exactly ":value"', - 'search_modifier_not_source_balance_is' => 'Source account balance is NOT exactly ":value"', + 'search_modifier_destination_balance_is' => 'Destination account balance is exactly ":value"', + 'search_modifier_not_destination_balance_is' => 'Destination account balance is NOT exactly ":value"', + 'search_modifier_source_balance_is' => 'Source account balance is exactly ":value"', + 'search_modifier_not_source_balance_is' => 'Source account balance is NOT exactly ":value"', - 'search_modifier_destination_balance_lte' => 'Destination account balance is less than or equal to ":value"', - 'search_modifier_not_destination_balance_lte' => 'Destination account balance is more than ":value"', - 'search_modifier_source_balance_lte' => 'Source account balance is less than or equal to ":value"', - 'search_modifier_not_source_balance_lte' => 'Source account balance is more than ":value"', + 'search_modifier_destination_balance_lte' => 'Destination account balance is less than or equal to ":value"', + 'search_modifier_not_destination_balance_lte' => 'Destination account balance is more than ":value"', + 'search_modifier_source_balance_lte' => 'Source account balance is less than or equal to ":value"', + 'search_modifier_not_source_balance_lte' => 'Source account balance is more than ":value"', - 'search_modifier_destination_balance_lt' => 'Destination account balance is less than ":value"', - 'search_modifier_not_destination_balance_lt' => 'Destination account balance is more than or equal to ":value"', - 'search_modifier_source_balance_lt' => 'Source account balance is less than ":value"', - 'search_modifier_not_source_balance_lt' => 'Source account balance is more than or equal to ":value"', + 'search_modifier_destination_balance_lt' => 'Destination account balance is less than ":value"', + 'search_modifier_not_destination_balance_lt' => 'Destination account balance is more than or equal to ":value"', + 'search_modifier_source_balance_lt' => 'Source account balance is less than ":value"', + 'search_modifier_not_source_balance_lt' => 'Source account balance is more than or equal to ":value"', - 'search_modifier_destination_balance_gte' => 'Destination account balance is more than or equal to ":value"', - 'search_modifier_not_destination_balance_gte' => 'Destination account balance is less than ":value"', - 'search_modifier_source_balance_gte' => 'Source account balance is more than or equal to ":value"', - 'search_modifier_not_source_balance_gte' => 'Source account balance is less than ":value"', + 'search_modifier_destination_balance_gte' => 'Destination account balance is more than or equal to ":value"', + 'search_modifier_not_destination_balance_gte' => 'Destination account balance is less than ":value"', + 'search_modifier_source_balance_gte' => 'Source account balance is more than or equal to ":value"', + 'search_modifier_not_source_balance_gte' => 'Source account balance is less than ":value"', - 'search_modifier_destination_balance_gt' => 'Destination account balance is more than ":value"', - 'search_modifier_not_destination_balance_gt' => 'Destination account balance is less than or equal to ":value"', - 'search_modifier_source_balance_gt' => 'Source account balance is more than ":value"', - 'search_modifier_not_source_balance_gt' => 'Source account balance is less than or equal to ":value"', + 'search_modifier_destination_balance_gt' => 'Destination account balance is more than ":value"', + 'search_modifier_not_destination_balance_gt' => 'Destination account balance is less than or equal to ":value"', + 'search_modifier_source_balance_gt' => 'Source account balance is more than ":value"', + 'search_modifier_not_source_balance_gt' => 'Source account balance is less than or equal to ":value"', // END - 'general_search_error' => 'An error occurred while searching. Please check the log files for more information.', - 'search_box' => 'Search', - 'search_box_intro' => 'Welcome to the search function of Firefly III. Enter your search query in the box. Make sure you check out the help file because the search is pretty advanced.', - 'search_error' => 'Error while searching', - 'search_searching' => 'Searching ...', - 'search_results' => 'Search results', + 'general_search_error' => 'An error occurred while searching. Please check the log files for more information.', + 'search_box' => 'Search', + 'search_box_intro' => 'Welcome to the search function of Firefly III. Enter your search query in the box. Make sure you check out the help file because the search is pretty advanced.', + 'search_error' => 'Error while searching', + 'search_searching' => 'Searching ...', + 'search_results' => 'Search results', // repeat frequencies: - 'repeat_freq_yearly' => 'yearly', - 'repeat_freq_half-year' => 'every half-year', - 'repeat_freq_quarterly' => 'quarterly', - 'repeat_freq_monthly' => 'monthly', - 'repeat_freq_weekly' => 'weekly', - 'repeat_freq_daily' => 'daily', - 'daily' => 'daily', - 'weekly' => 'weekly', - 'quarterly' => 'quarterly', - 'half-year' => 'every half year', - 'yearly' => 'yearly', + 'repeat_freq_yearly' => 'yearly', + 'repeat_freq_half-year' => 'every half-year', + 'repeat_freq_quarterly' => 'quarterly', + 'repeat_freq_monthly' => 'monthly', + 'repeat_freq_weekly' => 'weekly', + 'repeat_freq_daily' => 'daily', + 'daily' => 'daily', + 'weekly' => 'weekly', + 'quarterly' => 'quarterly', + 'half-year' => 'every half year', + 'yearly' => 'yearly', // rules - 'is_not_rule_trigger' => 'Not', - 'cannot_fire_inactive_rules' => 'You cannot execute inactive rules.', - 'show_triggers' => 'Show triggers', - 'show_actions' => 'Show actions', - 'rules' => 'Rules', - 'rule_name' => 'Name of rule', - 'rule_triggers' => 'Rule triggers when', - 'rule_actions' => 'Rule will', - 'new_rule' => 'New rule', - 'new_rule_group' => 'New rule group', - 'rule_priority_up' => 'Give rule more priority', - 'rule_priority_down' => 'Give rule less priority', - 'make_new_rule_group' => 'Make new rule group', - 'store_new_rule_group' => 'Store new rule group', - 'created_new_rule_group' => 'New rule group ":title" stored!', - 'updated_rule_group' => 'Successfully updated rule group ":title".', - 'edit_rule_group' => 'Edit rule group ":title"', - 'duplicate_rule' => 'Duplicate rule ":title"', - 'rule_copy_of' => 'Copy of ":title"', - 'duplicated_rule' => 'Duplicated rule ":title" into ":newTitle"', - 'delete_rule_group' => 'Delete rule group ":title"', - 'deleted_rule_group' => 'Deleted rule group ":title"', - 'update_rule_group' => 'Update rule group', - 'no_rules_in_group' => 'There are no rules in this group', - 'move_rule_group_up' => 'Move rule group up', - 'move_rule_group_down' => 'Move rule group down', - 'save_rules_by_moving' => 'Save this rule by moving it to another rule group:|Save these rules by moving them to another rule group:', - 'make_new_rule' => 'Make a new rule in rule group ":title"', - 'make_new_rule_no_group' => 'Make a new rule', - 'instructions_rule_from_bill' => 'In order to match transactions to your new subscription ":name", Firefly III can create a rule that will automatically be checked against any transactions you store. Please verify the details below and store the rule to have Firefly III automatically match transactions to your new bill.', - 'instructions_rule_from_journal' => 'Create a rule based on one of your transactions. Complement or submit the form below.', - 'rule_is_strict' => 'strict rule', - 'rule_is_not_strict' => 'non-strict rule', - 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed if this particular rule is executed.', - 'rule_help_strict' => 'In strict rules ALL triggers must fire for the action(s) to be executed. In non-strict rules, ANY trigger is enough for the action(s) to be executed.', - 'rule_help_active' => 'Inactive rules will never fire.', - 'stored_new_rule' => 'Stored new rule with title ":title"', - 'deleted_rule' => 'Deleted rule with title ":title"', - 'store_new_rule' => 'Store new rule', - 'updated_rule' => 'Updated rule with title ":title"', - 'default_rule_group_name' => 'Default rules', - 'default_rule_group_description' => 'All your rules not in a particular group.', - 'trigger' => 'Trigger', - 'trigger_value' => 'Trigger on value', - 'stop_processing_other_triggers' => 'Stop processing other triggers', - 'add_rule_trigger' => 'Add new trigger', - 'action' => 'Action', - 'action_value' => 'Action value', - 'stop_executing_other_actions' => 'Stop executing other actions', - 'add_rule_action' => 'Add new action', - 'edit_rule' => 'Edit rule #:nr ":title"', - 'delete_rule' => 'Delete rule ":title"', - 'update_rule' => 'Update rule', - 'test_rule_triggers' => 'See matching transactions', - 'warning_no_matching_transactions' => 'No matching transactions found.', - 'warning_no_valid_triggers' => 'No valid triggers provided.', - 'apply_rule_selection' => 'Apply rule ":title" to a selection of your transactions', - 'apply_rule_selection_intro' => 'Rules like ":title" are normally only applied to new or updated transactions, but you can tell Firefly III to run it on a selection of your existing transactions. This can be useful when you have updated a rule and you need the changes to be applied to all of your other transactions.', - 'include_transactions_from_accounts' => 'Include transactions from these accounts', - 'include' => 'Include?', - 'applied_rule_selection' => '{0} No transactions in your selection were changed by rule ":title".|[1] One transaction in your selection was changed by rule ":title".|[2,*] :count transactions in your selection were changed by rule ":title".', - 'execute' => 'Execute', - 'apply_rule_group_selection' => 'Apply rule group ":title" to a selection of your transactions', - 'apply_rule_group_selection_intro' => 'Rule groups like ":title" are normally only applied to new or updated transactions, but you can tell Firefly III to run all the rules in this group on a selection of your existing transactions. This can be useful when you have updated a group of rules and you need the changes to be applied to all of your other transactions.', - 'applied_rule_group_selection' => 'Rule group ":title" has been applied to your selection.', + 'is_not_rule_trigger' => 'Not', + 'cannot_fire_inactive_rules' => 'You cannot execute inactive rules.', + 'show_triggers' => 'Show triggers', + 'show_actions' => 'Show actions', + 'rules' => 'Rules', + 'rule_name' => 'Name of rule', + 'rule_triggers' => 'Rule triggers when', + 'rule_actions' => 'Rule will', + 'new_rule' => 'New rule', + 'new_rule_group' => 'New rule group', + 'rule_priority_up' => 'Give rule more priority', + 'rule_priority_down' => 'Give rule less priority', + 'make_new_rule_group' => 'Make new rule group', + 'store_new_rule_group' => 'Store new rule group', + 'created_new_rule_group' => 'New rule group ":title" stored!', + 'updated_rule_group' => 'Successfully updated rule group ":title".', + 'edit_rule_group' => 'Edit rule group ":title"', + 'duplicate_rule' => 'Duplicate rule ":title"', + 'rule_copy_of' => 'Copy of ":title"', + 'duplicated_rule' => 'Duplicated rule ":title" into ":newTitle"', + 'delete_rule_group' => 'Delete rule group ":title"', + 'deleted_rule_group' => 'Deleted rule group ":title"', + 'update_rule_group' => 'Update rule group', + 'no_rules_in_group' => 'There are no rules in this group', + 'move_rule_group_up' => 'Move rule group up', + 'move_rule_group_down' => 'Move rule group down', + 'save_rules_by_moving' => 'Save this rule by moving it to another rule group:|Save these rules by moving them to another rule group:', + 'make_new_rule' => 'Make a new rule in rule group ":title"', + 'make_new_rule_no_group' => 'Make a new rule', + 'instructions_rule_from_bill' => 'In order to match transactions to your new subscription ":name", Firefly III can create a rule that will automatically be checked against any transactions you store. Please verify the details below and store the rule to have Firefly III automatically match transactions to your new bill.', + 'instructions_rule_from_journal' => 'Create a rule based on one of your transactions. Complement or submit the form below.', + 'rule_is_strict' => 'strict rule', + 'rule_is_not_strict' => 'non-strict rule', + 'rule_help_stop_processing' => 'When you check this box, later rules in this group will not be executed if this particular rule is executed.', + 'rule_help_strict' => 'In strict rules ALL triggers must fire for the action(s) to be executed. In non-strict rules, ANY trigger is enough for the action(s) to be executed.', + 'rule_help_active' => 'Inactive rules will never fire.', + 'stored_new_rule' => 'Stored new rule with title ":title"', + 'deleted_rule' => 'Deleted rule with title ":title"', + 'store_new_rule' => 'Store new rule', + 'updated_rule' => 'Updated rule with title ":title"', + 'default_rule_group_name' => 'Default rules', + 'default_rule_group_description' => 'All your rules not in a particular group.', + 'trigger' => 'Trigger', + 'trigger_value' => 'Trigger on value', + 'stop_processing_other_triggers' => 'Stop processing other triggers', + 'add_rule_trigger' => 'Add new trigger', + 'action' => 'Action', + 'action_value' => 'Action value', + 'stop_executing_other_actions' => 'Stop executing other actions', + 'add_rule_action' => 'Add new action', + 'edit_rule' => 'Edit rule #:nr ":title"', + 'delete_rule' => 'Delete rule ":title"', + 'update_rule' => 'Update rule', + 'test_rule_triggers' => 'See matching transactions', + 'warning_no_matching_transactions' => 'No matching transactions found.', + 'warning_no_valid_triggers' => 'No valid triggers provided.', + 'apply_rule_selection' => 'Apply rule ":title" to a selection of your transactions', + 'apply_rule_selection_intro' => 'Rules like ":title" are normally only applied to new or updated transactions, but you can tell Firefly III to run it on a selection of your existing transactions. This can be useful when you have updated a rule and you need the changes to be applied to all of your other transactions.', + 'include_transactions_from_accounts' => 'Include transactions from these accounts', + 'include' => 'Include?', + 'applied_rule_selection' => '{0} No transactions in your selection were changed by rule ":title".|[1] One transaction in your selection was changed by rule ":title".|[2,*] :count transactions in your selection were changed by rule ":title".', + 'execute' => 'Execute', + 'apply_rule_group_selection' => 'Apply rule group ":title" to a selection of your transactions', + 'apply_rule_group_selection_intro' => 'Rule groups like ":title" are normally only applied to new or updated transactions, but you can tell Firefly III to run all the rules in this group on a selection of your existing transactions. This can be useful when you have updated a group of rules and you need the changes to be applied to all of your other transactions.', + 'applied_rule_group_selection' => 'Rule group ":title" has been applied to your selection.', // actions and triggers - 'rule_trigger_store_journal' => 'When a transaction is created', - 'rule_trigger_update_journal' => 'When a transaction is updated', - 'rule_trigger_manual' => 'Only when user-activated', - 'rule_trigger_user_action' => 'User action is ":trigger_value"', + 'rule_trigger_store_journal' => 'When a transaction is created', + 'rule_trigger_update_journal' => 'When a transaction is updated', + 'rule_trigger_manual' => 'Only when user-activated', + 'rule_trigger_user_action' => 'User action is ":trigger_value"', // OLD values (remove non-doubles later): - 'rule_trigger_source_account_starts_choice' => 'Source account name starts with..', - 'rule_trigger_source_account_starts' => 'Source account name starts with ":trigger_value"', - 'rule_trigger_source_account_ends_choice' => 'Source account name ends with..', - 'rule_trigger_source_account_ends' => 'Source account name ends with ":trigger_value"', - 'rule_trigger_source_account_is_choice' => 'Source account name is..', - 'rule_trigger_source_account_is' => 'Source account name is ":trigger_value"', - 'rule_trigger_source_account_contains_choice' => 'Source account name contains..', - 'rule_trigger_source_account_contains' => 'Source account name contains ":trigger_value"', - 'rule_trigger_account_id_choice' => 'Either account ID is exactly..', - 'rule_trigger_account_id' => 'Either account ID is exactly :trigger_value', - 'rule_trigger_source_account_id_choice' => 'Source account ID is exactly..', - 'rule_trigger_source_account_id' => 'Source account ID is exactly :trigger_value', - 'rule_trigger_destination_account_id_choice' => 'Destination account ID is exactly..', - 'rule_trigger_destination_account_id' => 'Destination account ID is exactly :trigger_value', - 'rule_trigger_account_is_cash_choice' => 'Either account is cash', - 'rule_trigger_account_is_cash' => 'Either account is cash', - 'rule_trigger_source_is_cash_choice' => 'Source account is (cash) account', - 'rule_trigger_source_is_cash' => 'Source account is (cash) account', - 'rule_trigger_destination_is_cash_choice' => 'Destination account is (cash) account', - 'rule_trigger_destination_is_cash' => 'Destination account is (cash) account', - 'rule_trigger_source_account_nr_starts_choice' => 'Source account number / IBAN starts with..', - 'rule_trigger_source_account_nr_starts' => 'Source account number / IBAN starts with ":trigger_value"', - 'rule_trigger_source_account_nr_ends_choice' => 'Source account number / IBAN ends with..', - 'rule_trigger_source_account_nr_ends' => 'Source account number / IBAN ends with ":trigger_value"', - 'rule_trigger_source_account_nr_is_choice' => 'Source account number / IBAN is..', - 'rule_trigger_source_account_nr_is' => 'Source account number / IBAN is ":trigger_value"', - 'rule_trigger_source_account_nr_contains_choice' => 'Source account number / IBAN contains..', - 'rule_trigger_source_account_nr_contains' => 'Source account number / IBAN contains ":trigger_value"', - 'rule_trigger_destination_account_starts_choice' => 'Destination account name starts with..', - 'rule_trigger_destination_account_starts' => 'Destination account name starts with ":trigger_value"', - 'rule_trigger_destination_account_ends_choice' => 'Destination account name ends with..', - 'rule_trigger_destination_account_ends' => 'Destination account name ends with ":trigger_value"', - 'rule_trigger_destination_account_is_choice' => 'Destination account name is..', - 'rule_trigger_destination_account_is' => 'Destination account name is ":trigger_value"', - 'rule_trigger_destination_account_contains_choice' => 'Destination account name contains..', - 'rule_trigger_destination_account_contains' => 'Destination account name contains ":trigger_value"', - 'rule_trigger_destination_account_nr_starts_choice' => 'Destination account number / IBAN starts with..', - 'rule_trigger_destination_account_nr_starts' => 'Destination account number / IBAN starts with ":trigger_value"', - 'rule_trigger_destination_account_nr_ends_choice' => 'Destination account number / IBAN ends with..', - 'rule_trigger_destination_account_nr_ends' => 'Destination account number / IBAN ends with ":trigger_value"', - 'rule_trigger_destination_account_nr_is_choice' => 'Destination account number / IBAN is..', - 'rule_trigger_destination_account_nr_is' => 'Destination account number / IBAN is ":trigger_value"', - 'rule_trigger_destination_account_nr_contains_choice' => 'Destination account number / IBAN contains..', - 'rule_trigger_destination_account_nr_contains' => 'Destination account number / IBAN contains ":trigger_value"', - 'rule_trigger_transaction_type_choice' => 'Transaction is of type..', - 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"', - 'rule_trigger_category_is_choice' => 'Category is..', - 'rule_trigger_category_is' => 'Category is ":trigger_value"', - 'rule_trigger_amount_less_choice' => 'Amount is less than or equal to ..', - 'rule_trigger_amount_less' => 'Amount is less than or equal to :trigger_value', - 'rule_trigger_amount_is_choice' => 'Amount is..', - 'rule_trigger_amount_is' => 'Amount is :trigger_value', - 'rule_trigger_amount_more_choice' => 'Amount is more than or equal to..', - 'rule_trigger_amount_more' => 'Amount is more than or equal to :trigger_value', - 'rule_trigger_description_starts_choice' => 'Description starts with..', - 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"', - 'rule_trigger_description_ends_choice' => 'Description ends with..', - 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"', - 'rule_trigger_description_contains_choice' => 'Description contains..', - 'rule_trigger_description_contains' => 'Description contains ":trigger_value"', - 'rule_trigger_description_is_choice' => 'Description is..', - 'rule_trigger_description_is' => 'Description is ":trigger_value"', - 'rule_trigger_date_on_choice' => 'Transaction date is..', - 'rule_trigger_date_on' => 'Transaction date is ":trigger_value"', - 'rule_trigger_date_before_choice' => 'Transaction date is before..', - 'rule_trigger_date_before' => 'Transaction date is before ":trigger_value"', - 'rule_trigger_date_after_choice' => 'Transaction date is after..', - 'rule_trigger_date_after' => 'Transaction date is after ":trigger_value"', - 'rule_trigger_created_at_on_choice' => 'Transaction was made on..', - 'rule_trigger_created_at_on' => 'Transaction was made on ":trigger_value"', - 'rule_trigger_updated_at_on_choice' => 'Transaction was last edited on..', - 'rule_trigger_updated_at_on' => 'Transaction was last edited on ":trigger_value"', - 'rule_trigger_budget_is_choice' => 'Budget is..', - 'rule_trigger_budget_is' => 'Budget is ":trigger_value"', - 'rule_trigger_tag_is_choice' => 'Any tag is..', - 'rule_trigger_tag_is' => 'Any tag is ":trigger_value"', - 'rule_trigger_tag_contains_choice' => 'Any tag contains..', - 'rule_trigger_tag_contains' => 'Any tag contains ":trigger_value"', - 'rule_trigger_tag_ends_choice' => 'Any tag ends with..', - 'rule_trigger_tag_ends' => 'Any tag ends with ":trigger_value"', - 'rule_trigger_tag_starts_choice' => 'Any tag starts with..', - 'rule_trigger_tag_starts' => 'Any tag starts with ":trigger_value"', - 'rule_trigger_currency_is_choice' => 'Transaction currency is..', - 'rule_trigger_currency_is' => 'Transaction currency is ":trigger_value"', - 'rule_trigger_foreign_currency_is_choice' => 'Transaction foreign currency is..', - 'rule_trigger_foreign_currency_is' => 'Transaction foreign currency is ":trigger_value"', - 'rule_trigger_has_attachments_choice' => 'Has any attachments', - 'rule_trigger_has_attachments' => 'Has any attachment(s)', - 'rule_trigger_has_no_category_choice' => 'Has no category', - 'rule_trigger_has_no_category' => 'Transaction has no category', - 'rule_trigger_has_any_category_choice' => 'Has a (any) category', - 'rule_trigger_has_any_category' => 'Transaction has a (any) category', - 'rule_trigger_has_no_budget_choice' => 'Has no budget', - 'rule_trigger_has_no_budget' => 'Transaction has no budget', - 'rule_trigger_has_any_budget_choice' => 'Has a (any) budget', - 'rule_trigger_has_any_budget' => 'Transaction has a (any) budget', - 'rule_trigger_has_no_bill_choice' => 'Has no subscription', - 'rule_trigger_has_no_bill' => 'Transaction has no subscription', - 'rule_trigger_has_any_bill_choice' => 'Has a (any) subscription', - 'rule_trigger_has_any_bill' => 'Transaction has a (any) subscription', - 'rule_trigger_has_no_tag_choice' => 'Has no tag(s)', - 'rule_trigger_has_no_tag' => 'Transaction has no tag(s)', - 'rule_trigger_has_any_tag_choice' => 'Has one or more (any) tags', - 'rule_trigger_has_any_tag' => 'Transaction has one or more (any) tags', - 'rule_trigger_any_notes_choice' => 'Has (any) notes', - 'rule_trigger_any_notes' => 'Transaction has (any) notes', - 'rule_trigger_no_notes_choice' => 'Has no notes', - 'rule_trigger_no_notes' => 'Transaction has no notes', - 'rule_trigger_notes_is_choice' => 'Notes are..', - 'rule_trigger_notes_is' => 'Notes are ":trigger_value"', - 'rule_trigger_notes_contains_choice' => 'Notes contain..', - 'rule_trigger_notes_contains' => 'Notes contain ":trigger_value"', - 'rule_trigger_notes_starts_choice' => 'Notes start with..', - 'rule_trigger_notes_starts' => 'Notes start with ":trigger_value"', - 'rule_trigger_notes_ends_choice' => 'Notes end with..', - 'rule_trigger_notes_ends' => 'Notes end with ":trigger_value"', - 'rule_trigger_bill_is_choice' => 'Subscription is..', - 'rule_trigger_bill_is' => 'Subscription is ":trigger_value"', - 'rule_trigger_external_id_is_choice' => 'External ID is..', - 'rule_trigger_external_id_is' => 'External ID is ":trigger_value"', - 'rule_trigger_internal_reference_is_choice' => 'Internal reference is..', - 'rule_trigger_internal_reference_is' => 'Internal reference is ":trigger_value"', - 'rule_trigger_journal_id_choice' => 'Transaction journal ID is..', - 'rule_trigger_journal_id' => 'Transaction journal ID is ":trigger_value"', - 'rule_trigger_any_external_url' => 'Transaction has an (any) external URL', - 'rule_trigger_any_external_url_choice' => 'Transaction has an (any) external URL', - 'rule_trigger_any_external_id' => 'Transaction has an (any) external ID', - 'rule_trigger_any_external_id_choice' => 'Transaction has an (any) external ID', - 'rule_trigger_no_external_url_choice' => 'Transaction has no external URL', - 'rule_trigger_no_external_url' => 'Transaction has no external URL', - 'rule_trigger_no_external_id_choice' => 'Transaction has no external ID', - 'rule_trigger_no_external_id' => 'Transaction has no external ID', - 'rule_trigger_id_choice' => 'Transaction ID is..', - 'rule_trigger_id' => 'Transaction ID is ":trigger_value"', - 'rule_trigger_sepa_ct_is_choice' => 'SEPA CT is..', - 'rule_trigger_sepa_ct_is' => 'SEPA CT is ":trigger_value"', + 'rule_trigger_source_account_starts_choice' => 'Source account name starts with..', + 'rule_trigger_source_account_starts' => 'Source account name starts with ":trigger_value"', + 'rule_trigger_source_account_ends_choice' => 'Source account name ends with..', + 'rule_trigger_source_account_ends' => 'Source account name ends with ":trigger_value"', + 'rule_trigger_source_account_is_choice' => 'Source account name is..', + 'rule_trigger_source_account_is' => 'Source account name is ":trigger_value"', + 'rule_trigger_source_account_contains_choice' => 'Source account name contains..', + 'rule_trigger_source_account_contains' => 'Source account name contains ":trigger_value"', + 'rule_trigger_account_id_choice' => 'Either account ID is exactly..', + 'rule_trigger_account_id' => 'Either account ID is exactly :trigger_value', + 'rule_trigger_source_account_id_choice' => 'Source account ID is exactly..', + 'rule_trigger_source_account_id' => 'Source account ID is exactly :trigger_value', + 'rule_trigger_destination_account_id_choice' => 'Destination account ID is exactly..', + 'rule_trigger_destination_account_id' => 'Destination account ID is exactly :trigger_value', + 'rule_trigger_account_is_cash_choice' => 'Either account is cash', + 'rule_trigger_account_is_cash' => 'Either account is cash', + 'rule_trigger_source_is_cash_choice' => 'Source account is (cash) account', + 'rule_trigger_source_is_cash' => 'Source account is (cash) account', + 'rule_trigger_destination_is_cash_choice' => 'Destination account is (cash) account', + 'rule_trigger_destination_is_cash' => 'Destination account is (cash) account', + 'rule_trigger_source_account_nr_starts_choice' => 'Source account number / IBAN starts with..', + 'rule_trigger_source_account_nr_starts' => 'Source account number / IBAN starts with ":trigger_value"', + 'rule_trigger_source_account_nr_ends_choice' => 'Source account number / IBAN ends with..', + 'rule_trigger_source_account_nr_ends' => 'Source account number / IBAN ends with ":trigger_value"', + 'rule_trigger_source_account_nr_is_choice' => 'Source account number / IBAN is..', + 'rule_trigger_source_account_nr_is' => 'Source account number / IBAN is ":trigger_value"', + 'rule_trigger_source_account_nr_contains_choice' => 'Source account number / IBAN contains..', + 'rule_trigger_source_account_nr_contains' => 'Source account number / IBAN contains ":trigger_value"', + 'rule_trigger_destination_account_starts_choice' => 'Destination account name starts with..', + 'rule_trigger_destination_account_starts' => 'Destination account name starts with ":trigger_value"', + 'rule_trigger_destination_account_ends_choice' => 'Destination account name ends with..', + 'rule_trigger_destination_account_ends' => 'Destination account name ends with ":trigger_value"', + 'rule_trigger_destination_account_is_choice' => 'Destination account name is..', + 'rule_trigger_destination_account_is' => 'Destination account name is ":trigger_value"', + 'rule_trigger_destination_account_contains_choice' => 'Destination account name contains..', + 'rule_trigger_destination_account_contains' => 'Destination account name contains ":trigger_value"', + 'rule_trigger_destination_account_nr_starts_choice' => 'Destination account number / IBAN starts with..', + 'rule_trigger_destination_account_nr_starts' => 'Destination account number / IBAN starts with ":trigger_value"', + 'rule_trigger_destination_account_nr_ends_choice' => 'Destination account number / IBAN ends with..', + 'rule_trigger_destination_account_nr_ends' => 'Destination account number / IBAN ends with ":trigger_value"', + 'rule_trigger_destination_account_nr_is_choice' => 'Destination account number / IBAN is..', + 'rule_trigger_destination_account_nr_is' => 'Destination account number / IBAN is ":trigger_value"', + 'rule_trigger_destination_account_nr_contains_choice' => 'Destination account number / IBAN contains..', + 'rule_trigger_destination_account_nr_contains' => 'Destination account number / IBAN contains ":trigger_value"', + 'rule_trigger_transaction_type_choice' => 'Transaction is of type..', + 'rule_trigger_transaction_type' => 'Transaction is of type ":trigger_value"', + 'rule_trigger_category_is_choice' => 'Category is..', + 'rule_trigger_category_is' => 'Category is ":trigger_value"', + 'rule_trigger_amount_less_choice' => 'Amount is less than or equal to ..', + 'rule_trigger_amount_less' => 'Amount is less than or equal to :trigger_value', + 'rule_trigger_amount_is_choice' => 'Amount is..', + 'rule_trigger_amount_is' => 'Amount is :trigger_value', + 'rule_trigger_amount_more_choice' => 'Amount is more than or equal to..', + 'rule_trigger_amount_more' => 'Amount is more than or equal to :trigger_value', + 'rule_trigger_description_starts_choice' => 'Description starts with..', + 'rule_trigger_description_starts' => 'Description starts with ":trigger_value"', + 'rule_trigger_description_ends_choice' => 'Description ends with..', + 'rule_trigger_description_ends' => 'Description ends with ":trigger_value"', + 'rule_trigger_description_contains_choice' => 'Description contains..', + 'rule_trigger_description_contains' => 'Description contains ":trigger_value"', + 'rule_trigger_description_is_choice' => 'Description is..', + 'rule_trigger_description_is' => 'Description is ":trigger_value"', + 'rule_trigger_date_on_choice' => 'Transaction date is..', + 'rule_trigger_date_on' => 'Transaction date is ":trigger_value"', + 'rule_trigger_date_before_choice' => 'Transaction date is before..', + 'rule_trigger_date_before' => 'Transaction date is before ":trigger_value"', + 'rule_trigger_date_after_choice' => 'Transaction date is after..', + 'rule_trigger_date_after' => 'Transaction date is after ":trigger_value"', + 'rule_trigger_created_at_on_choice' => 'Transaction was made on..', + 'rule_trigger_created_at_on' => 'Transaction was made on ":trigger_value"', + 'rule_trigger_updated_at_on_choice' => 'Transaction was last edited on..', + 'rule_trigger_updated_at_on' => 'Transaction was last edited on ":trigger_value"', + 'rule_trigger_budget_is_choice' => 'Budget is..', + 'rule_trigger_budget_is' => 'Budget is ":trigger_value"', + 'rule_trigger_tag_is_choice' => 'Any tag is..', + 'rule_trigger_tag_is' => 'Any tag is ":trigger_value"', + 'rule_trigger_tag_contains_choice' => 'Any tag contains..', + 'rule_trigger_tag_contains' => 'Any tag contains ":trigger_value"', + 'rule_trigger_tag_ends_choice' => 'Any tag ends with..', + 'rule_trigger_tag_ends' => 'Any tag ends with ":trigger_value"', + 'rule_trigger_tag_starts_choice' => 'Any tag starts with..', + 'rule_trigger_tag_starts' => 'Any tag starts with ":trigger_value"', + 'rule_trigger_currency_is_choice' => 'Transaction currency is..', + 'rule_trigger_currency_is' => 'Transaction currency is ":trigger_value"', + 'rule_trigger_foreign_currency_is_choice' => 'Transaction foreign currency is..', + 'rule_trigger_foreign_currency_is' => 'Transaction foreign currency is ":trigger_value"', + 'rule_trigger_has_attachments_choice' => 'Has any attachments', + 'rule_trigger_has_attachments' => 'Has any attachment(s)', + 'rule_trigger_has_no_category_choice' => 'Has no category', + 'rule_trigger_has_no_category' => 'Transaction has no category', + 'rule_trigger_has_any_category_choice' => 'Has a (any) category', + 'rule_trigger_has_any_category' => 'Transaction has a (any) category', + 'rule_trigger_has_no_budget_choice' => 'Has no budget', + 'rule_trigger_has_no_budget' => 'Transaction has no budget', + 'rule_trigger_has_any_budget_choice' => 'Has a (any) budget', + 'rule_trigger_has_any_budget' => 'Transaction has a (any) budget', + 'rule_trigger_has_no_bill_choice' => 'Has no subscription', + 'rule_trigger_has_no_bill' => 'Transaction has no subscription', + 'rule_trigger_has_any_bill_choice' => 'Has a (any) subscription', + 'rule_trigger_has_any_bill' => 'Transaction has a (any) subscription', + 'rule_trigger_has_no_tag_choice' => 'Has no tag(s)', + 'rule_trigger_has_no_tag' => 'Transaction has no tag(s)', + 'rule_trigger_has_any_tag_choice' => 'Has one or more (any) tags', + 'rule_trigger_has_any_tag' => 'Transaction has one or more (any) tags', + 'rule_trigger_any_notes_choice' => 'Has (any) notes', + 'rule_trigger_any_notes' => 'Transaction has (any) notes', + 'rule_trigger_no_notes_choice' => 'Has no notes', + 'rule_trigger_no_notes' => 'Transaction has no notes', + 'rule_trigger_notes_is_choice' => 'Notes are..', + 'rule_trigger_notes_is' => 'Notes are ":trigger_value"', + 'rule_trigger_notes_contains_choice' => 'Notes contain..', + 'rule_trigger_notes_contains' => 'Notes contain ":trigger_value"', + 'rule_trigger_notes_starts_choice' => 'Notes start with..', + 'rule_trigger_notes_starts' => 'Notes start with ":trigger_value"', + 'rule_trigger_notes_ends_choice' => 'Notes end with..', + 'rule_trigger_notes_ends' => 'Notes end with ":trigger_value"', + 'rule_trigger_bill_is_choice' => 'Subscription is..', + 'rule_trigger_bill_is' => 'Subscription is ":trigger_value"', + 'rule_trigger_external_id_is_choice' => 'External ID is..', + 'rule_trigger_external_id_is' => 'External ID is ":trigger_value"', + 'rule_trigger_internal_reference_is_choice' => 'Internal reference is..', + 'rule_trigger_internal_reference_is' => 'Internal reference is ":trigger_value"', + 'rule_trigger_journal_id_choice' => 'Transaction journal ID is..', + 'rule_trigger_journal_id' => 'Transaction journal ID is ":trigger_value"', + 'rule_trigger_any_external_url' => 'Transaction has an (any) external URL', + 'rule_trigger_any_external_url_choice' => 'Transaction has an (any) external URL', + 'rule_trigger_any_external_id' => 'Transaction has an (any) external ID', + 'rule_trigger_any_external_id_choice' => 'Transaction has an (any) external ID', + 'rule_trigger_no_external_url_choice' => 'Transaction has no external URL', + 'rule_trigger_no_external_url' => 'Transaction has no external URL', + 'rule_trigger_no_external_id_choice' => 'Transaction has no external ID', + 'rule_trigger_no_external_id' => 'Transaction has no external ID', + 'rule_trigger_id_choice' => 'Transaction ID is..', + 'rule_trigger_id' => 'Transaction ID is ":trigger_value"', + 'rule_trigger_sepa_ct_is_choice' => 'SEPA CT is..', + 'rule_trigger_sepa_ct_is' => 'SEPA CT is ":trigger_value"', // new values: - 'rule_trigger_user_action_choice' => 'User action is ":trigger_value"', - 'rule_trigger_tag_is_not_choice' => 'No tag is..', - 'rule_trigger_tag_is_not' => 'No tag is ":trigger_value"', - 'rule_trigger_account_is_choice' => 'Either account is exactly..', - 'rule_trigger_account_is' => 'Either account is exactly ":trigger_value"', - 'rule_trigger_account_contains_choice' => 'Either account contains..', - 'rule_trigger_account_contains' => 'Either account contains ":trigger_value"', - 'rule_trigger_account_ends_choice' => 'Either account ends with..', - 'rule_trigger_account_ends' => 'Either account ends with ":trigger_value"', - 'rule_trigger_account_starts_choice' => 'Either account starts with..', - 'rule_trigger_account_starts' => 'Either account starts with ":trigger_value"', - 'rule_trigger_account_nr_is_choice' => 'Either account number / IBAN is..', - 'rule_trigger_account_nr_is' => 'Either account number / IBAN is ":trigger_value"', - 'rule_trigger_account_nr_contains_choice' => 'Either account number / IBAN contains..', - 'rule_trigger_account_nr_contains' => 'Either account number / IBAN contains ":trigger_value"', - 'rule_trigger_account_nr_ends_choice' => 'Either account number / IBAN ends with..', - 'rule_trigger_account_nr_ends' => 'Either account number / IBAN ends with ":trigger_value"', - 'rule_trigger_account_nr_starts_choice' => 'Either account number / IBAN starts with..', - 'rule_trigger_account_nr_starts' => 'Either account number / IBAN starts with ":trigger_value"', - 'rule_trigger_category_contains_choice' => 'Category contains..', - 'rule_trigger_category_contains' => 'Category contains ":trigger_value"', - 'rule_trigger_category_ends_choice' => 'Category ends with..', - 'rule_trigger_category_ends' => 'Category ends with ":trigger_value"', - 'rule_trigger_category_starts_choice' => 'Category starts with..', - 'rule_trigger_category_starts' => 'Category starts with ":trigger_value"', - 'rule_trigger_budget_contains_choice' => 'Budget contains..', - 'rule_trigger_budget_contains' => 'Budget contains ":trigger_value"', - 'rule_trigger_budget_ends_choice' => 'Budget ends with..', - 'rule_trigger_budget_ends' => 'Budget ends with ":trigger_value"', - 'rule_trigger_budget_starts_choice' => 'Budget starts with..', - 'rule_trigger_budget_starts' => 'Budget starts with ":trigger_value"', - 'rule_trigger_bill_contains_choice' => 'Subscription contains..', - 'rule_trigger_bill_contains' => 'Subscription contains ":trigger_value"', - 'rule_trigger_bill_ends_choice' => 'Subscription ends with..', - 'rule_trigger_bill_ends' => 'Subscription ends with ":trigger_value"', - 'rule_trigger_bill_starts_choice' => 'Subscription starts with..', - 'rule_trigger_bill_starts' => 'Subscription starts with ":trigger_value"', - 'rule_trigger_external_id_contains_choice' => 'External ID contains..', - 'rule_trigger_external_id_contains' => 'External ID contains ":trigger_value"', - 'rule_trigger_external_id_ends_choice' => 'External ID ends with..', - 'rule_trigger_external_id_ends' => 'External ID ends with ":trigger_value"', - 'rule_trigger_external_id_starts_choice' => 'External ID starts with..', - 'rule_trigger_external_id_starts' => 'External ID starts with ":trigger_value"', - 'rule_trigger_internal_reference_contains_choice' => 'Internal reference contains..', - 'rule_trigger_internal_reference_contains' => 'Internal reference contains ":trigger_value"', - 'rule_trigger_internal_reference_ends_choice' => 'Internal reference ends with..', - 'rule_trigger_internal_reference_ends' => 'Internal reference ends with ":trigger_value"', - 'rule_trigger_internal_reference_starts_choice' => 'Internal reference starts with..', - 'rule_trigger_internal_reference_starts' => 'Internal reference starts with ":trigger_value"', - 'rule_trigger_external_url_is_choice' => 'External URL is..', - 'rule_trigger_external_url_is' => 'External URL is ":trigger_value"', - 'rule_trigger_external_url_contains_choice' => 'External URL contains..', - 'rule_trigger_external_url_contains' => 'External URL contains ":trigger_value"', - 'rule_trigger_external_url_ends_choice' => 'External URL ends with..', - 'rule_trigger_external_url_ends' => 'External URL ends with ":trigger_value"', - 'rule_trigger_external_url_starts_choice' => 'External URL starts with..', - 'rule_trigger_external_url_starts' => 'External URL starts with ":trigger_value"', - 'rule_trigger_has_no_attachments_choice' => 'Has no attachments', - 'rule_trigger_has_no_attachments' => 'Transaction has no attachments', - 'rule_trigger_recurrence_id_choice' => 'Recurring transaction ID is..', - 'rule_trigger_recurrence_id' => 'Recurring transaction ID is ":trigger_value"', - 'rule_trigger_interest_date_on_choice' => 'Interest date is on..', - 'rule_trigger_interest_date_on' => 'Interest date is on ":trigger_value"', - 'rule_trigger_interest_date_before_choice' => 'Interest date is before..', - 'rule_trigger_interest_date_before' => 'Interest date is before ":trigger_value"', - 'rule_trigger_interest_date_after_choice' => 'Interest date is after..', - 'rule_trigger_interest_date_after' => 'Interest date is after ":trigger_value"', - 'rule_trigger_book_date_on_choice' => 'Book date is on..', - 'rule_trigger_book_date_on' => 'Book date is on ":trigger_value"', - 'rule_trigger_book_date_before_choice' => 'Book date is before..', - 'rule_trigger_book_date_before' => 'Book date is before ":trigger_value"', - 'rule_trigger_book_date_after_choice' => 'Book date is after..', - 'rule_trigger_book_date_after' => 'Book date is after ":trigger_value"', - 'rule_trigger_process_date_on_choice' => 'Process date is on..', - 'rule_trigger_process_date_on' => 'Process date is ":trigger_value"', - 'rule_trigger_process_date_before_choice' => 'Process date is before..', - 'rule_trigger_process_date_before' => 'Process date is before ":trigger_value"', - 'rule_trigger_process_date_after_choice' => 'Process date is after..', - 'rule_trigger_process_date_after' => 'Process date is after ":trigger_value"', - 'rule_trigger_due_date_on_choice' => 'Due date is on..', - 'rule_trigger_due_date_on' => 'Due date is on ":trigger_value"', - 'rule_trigger_due_date_before_choice' => 'Due date is before..', - 'rule_trigger_due_date_before' => 'Due date is before ":trigger_value"', - 'rule_trigger_due_date_after_choice' => 'Due date is after..', - 'rule_trigger_due_date_after' => 'Due date is after ":trigger_value"', - 'rule_trigger_payment_date_on_choice' => 'Payment date is on..', - 'rule_trigger_payment_date_on' => 'Payment date is on ":trigger_value"', - 'rule_trigger_payment_date_before_choice' => 'Payment date is before..', - 'rule_trigger_payment_date_before' => 'Payment date is before ":trigger_value"', - 'rule_trigger_payment_date_after_choice' => 'Payment date is after..', - 'rule_trigger_payment_date_after' => 'Payment date is after ":trigger_value"', - 'rule_trigger_invoice_date_on_choice' => 'Invoice date is on..', - 'rule_trigger_invoice_date_on' => 'Invoice date is on ":trigger_value"', - 'rule_trigger_invoice_date_before_choice' => 'Invoice date is before..', - 'rule_trigger_invoice_date_before' => 'Invoice date is before ":trigger_value"', - 'rule_trigger_invoice_date_after_choice' => 'Invoice date is after..', - 'rule_trigger_invoice_date_after' => 'Invoice date is after ":trigger_value"', - 'rule_trigger_created_at_before_choice' => 'Transaction was created before..', - 'rule_trigger_created_at_before' => 'Transaction was created before ":trigger_value"', - 'rule_trigger_created_at_after_choice' => 'Transaction was created after..', - 'rule_trigger_created_at_after' => 'Transaction was created after ":trigger_value"', - 'rule_trigger_updated_at_before_choice' => 'Transaction was last updated before..', - 'rule_trigger_updated_at_before' => 'Transaction was last updated before ":trigger_value"', - 'rule_trigger_updated_at_after_choice' => 'Transaction was last updated after..', - 'rule_trigger_updated_at_after' => 'Transaction was last updated after ":trigger_value"', - 'rule_trigger_foreign_amount_is_choice' => 'Foreign amount is exactly..', - 'rule_trigger_foreign_amount_is' => 'Foreign amount is exactly ":trigger_value"', - 'rule_trigger_foreign_amount_less_choice' => 'Foreign amount is less than..', - 'rule_trigger_foreign_amount_less' => 'Foreign amount is less than ":trigger_value"', - 'rule_trigger_foreign_amount_more_choice' => 'Foreign amount is more than..', - 'rule_trigger_foreign_amount_more' => 'Foreign amount is more than ":trigger_value"', - 'rule_trigger_attachment_name_is_choice' => 'Any attachment\'s name is..', - 'rule_trigger_attachment_name_is' => 'Any attachment\'s name is ":trigger_value"', - 'rule_trigger_attachment_name_contains_choice' => 'Any attachment\'s name contains..', - 'rule_trigger_attachment_name_contains' => 'Any attachment\'s name contains ":trigger_value"', - 'rule_trigger_attachment_name_starts_choice' => 'Any attachment\'s name starts with..', - 'rule_trigger_attachment_name_starts' => 'Any attachment\'s name starts with ":trigger_value"', - 'rule_trigger_attachment_name_ends_choice' => 'Any attachment\'s name ends with..', - 'rule_trigger_attachment_name_ends' => 'Any attachment\'s name ends with ":trigger_value"', - 'rule_trigger_attachment_notes_are_choice' => 'Any attachment\'s notes are..', - 'rule_trigger_attachment_notes_are' => 'Any attachment\'s notes are ":trigger_value"', - 'rule_trigger_attachment_notes_contains_choice' => 'Any attachment\'s notes contain..', - 'rule_trigger_attachment_notes_contains' => 'Any attachment\'s notes contain ":trigger_value"', - 'rule_trigger_attachment_notes_starts_choice' => 'Any attachment\'s notes start with..', - 'rule_trigger_attachment_notes_starts' => 'Any attachment\'s notes start with ":trigger_value"', - 'rule_trigger_attachment_notes_ends_choice' => 'Any attachment\'s notes end with..', - 'rule_trigger_attachment_notes_ends' => 'Any attachment\'s notes end with ":trigger_value"', - 'rule_trigger_reconciled_choice' => 'Transaction is reconciled', - 'rule_trigger_reconciled' => 'Transaction is reconciled', - 'rule_trigger_exists_choice' => 'Any transaction matches(!)', - 'rule_trigger_exists' => 'Any transaction matches', + 'rule_trigger_user_action_choice' => 'User action is ":trigger_value"', + 'rule_trigger_tag_is_not_choice' => 'No tag is..', + 'rule_trigger_tag_is_not' => 'No tag is ":trigger_value"', + 'rule_trigger_account_is_choice' => 'Either account is exactly..', + 'rule_trigger_account_is' => 'Either account is exactly ":trigger_value"', + 'rule_trigger_account_contains_choice' => 'Either account contains..', + 'rule_trigger_account_contains' => 'Either account contains ":trigger_value"', + 'rule_trigger_account_ends_choice' => 'Either account ends with..', + 'rule_trigger_account_ends' => 'Either account ends with ":trigger_value"', + 'rule_trigger_account_starts_choice' => 'Either account starts with..', + 'rule_trigger_account_starts' => 'Either account starts with ":trigger_value"', + 'rule_trigger_account_nr_is_choice' => 'Either account number / IBAN is..', + 'rule_trigger_account_nr_is' => 'Either account number / IBAN is ":trigger_value"', + 'rule_trigger_account_nr_contains_choice' => 'Either account number / IBAN contains..', + 'rule_trigger_account_nr_contains' => 'Either account number / IBAN contains ":trigger_value"', + 'rule_trigger_account_nr_ends_choice' => 'Either account number / IBAN ends with..', + 'rule_trigger_account_nr_ends' => 'Either account number / IBAN ends with ":trigger_value"', + 'rule_trigger_account_nr_starts_choice' => 'Either account number / IBAN starts with..', + 'rule_trigger_account_nr_starts' => 'Either account number / IBAN starts with ":trigger_value"', + 'rule_trigger_category_contains_choice' => 'Category contains..', + 'rule_trigger_category_contains' => 'Category contains ":trigger_value"', + 'rule_trigger_category_ends_choice' => 'Category ends with..', + 'rule_trigger_category_ends' => 'Category ends with ":trigger_value"', + 'rule_trigger_category_starts_choice' => 'Category starts with..', + 'rule_trigger_category_starts' => 'Category starts with ":trigger_value"', + 'rule_trigger_budget_contains_choice' => 'Budget contains..', + 'rule_trigger_budget_contains' => 'Budget contains ":trigger_value"', + 'rule_trigger_budget_ends_choice' => 'Budget ends with..', + 'rule_trigger_budget_ends' => 'Budget ends with ":trigger_value"', + 'rule_trigger_budget_starts_choice' => 'Budget starts with..', + 'rule_trigger_budget_starts' => 'Budget starts with ":trigger_value"', + 'rule_trigger_bill_contains_choice' => 'Subscription contains..', + 'rule_trigger_bill_contains' => 'Subscription contains ":trigger_value"', + 'rule_trigger_bill_ends_choice' => 'Subscription ends with..', + 'rule_trigger_bill_ends' => 'Subscription ends with ":trigger_value"', + 'rule_trigger_bill_starts_choice' => 'Subscription starts with..', + 'rule_trigger_bill_starts' => 'Subscription starts with ":trigger_value"', + 'rule_trigger_external_id_contains_choice' => 'External ID contains..', + 'rule_trigger_external_id_contains' => 'External ID contains ":trigger_value"', + 'rule_trigger_external_id_ends_choice' => 'External ID ends with..', + 'rule_trigger_external_id_ends' => 'External ID ends with ":trigger_value"', + 'rule_trigger_external_id_starts_choice' => 'External ID starts with..', + 'rule_trigger_external_id_starts' => 'External ID starts with ":trigger_value"', + 'rule_trigger_internal_reference_contains_choice' => 'Internal reference contains..', + 'rule_trigger_internal_reference_contains' => 'Internal reference contains ":trigger_value"', + 'rule_trigger_internal_reference_ends_choice' => 'Internal reference ends with..', + 'rule_trigger_internal_reference_ends' => 'Internal reference ends with ":trigger_value"', + 'rule_trigger_internal_reference_starts_choice' => 'Internal reference starts with..', + 'rule_trigger_internal_reference_starts' => 'Internal reference starts with ":trigger_value"', + 'rule_trigger_external_url_is_choice' => 'External URL is..', + 'rule_trigger_external_url_is' => 'External URL is ":trigger_value"', + 'rule_trigger_external_url_contains_choice' => 'External URL contains..', + 'rule_trigger_external_url_contains' => 'External URL contains ":trigger_value"', + 'rule_trigger_external_url_ends_choice' => 'External URL ends with..', + 'rule_trigger_external_url_ends' => 'External URL ends with ":trigger_value"', + 'rule_trigger_external_url_starts_choice' => 'External URL starts with..', + 'rule_trigger_external_url_starts' => 'External URL starts with ":trigger_value"', + 'rule_trigger_has_no_attachments_choice' => 'Has no attachments', + 'rule_trigger_has_no_attachments' => 'Transaction has no attachments', + 'rule_trigger_recurrence_id_choice' => 'Recurring transaction ID is..', + 'rule_trigger_recurrence_id' => 'Recurring transaction ID is ":trigger_value"', + 'rule_trigger_interest_date_on_choice' => 'Interest date is on..', + 'rule_trigger_interest_date_on' => 'Interest date is on ":trigger_value"', + 'rule_trigger_interest_date_before_choice' => 'Interest date is before..', + 'rule_trigger_interest_date_before' => 'Interest date is before ":trigger_value"', + 'rule_trigger_interest_date_after_choice' => 'Interest date is after..', + 'rule_trigger_interest_date_after' => 'Interest date is after ":trigger_value"', + 'rule_trigger_book_date_on_choice' => 'Book date is on..', + 'rule_trigger_book_date_on' => 'Book date is on ":trigger_value"', + 'rule_trigger_book_date_before_choice' => 'Book date is before..', + 'rule_trigger_book_date_before' => 'Book date is before ":trigger_value"', + 'rule_trigger_book_date_after_choice' => 'Book date is after..', + 'rule_trigger_book_date_after' => 'Book date is after ":trigger_value"', + 'rule_trigger_process_date_on_choice' => 'Process date is on..', + 'rule_trigger_process_date_on' => 'Process date is ":trigger_value"', + 'rule_trigger_process_date_before_choice' => 'Process date is before..', + 'rule_trigger_process_date_before' => 'Process date is before ":trigger_value"', + 'rule_trigger_process_date_after_choice' => 'Process date is after..', + 'rule_trigger_process_date_after' => 'Process date is after ":trigger_value"', + 'rule_trigger_due_date_on_choice' => 'Due date is on..', + 'rule_trigger_due_date_on' => 'Due date is on ":trigger_value"', + 'rule_trigger_due_date_before_choice' => 'Due date is before..', + 'rule_trigger_due_date_before' => 'Due date is before ":trigger_value"', + 'rule_trigger_due_date_after_choice' => 'Due date is after..', + 'rule_trigger_due_date_after' => 'Due date is after ":trigger_value"', + 'rule_trigger_payment_date_on_choice' => 'Payment date is on..', + 'rule_trigger_payment_date_on' => 'Payment date is on ":trigger_value"', + 'rule_trigger_payment_date_before_choice' => 'Payment date is before..', + 'rule_trigger_payment_date_before' => 'Payment date is before ":trigger_value"', + 'rule_trigger_payment_date_after_choice' => 'Payment date is after..', + 'rule_trigger_payment_date_after' => 'Payment date is after ":trigger_value"', + 'rule_trigger_invoice_date_on_choice' => 'Invoice date is on..', + 'rule_trigger_invoice_date_on' => 'Invoice date is on ":trigger_value"', + 'rule_trigger_invoice_date_before_choice' => 'Invoice date is before..', + 'rule_trigger_invoice_date_before' => 'Invoice date is before ":trigger_value"', + 'rule_trigger_invoice_date_after_choice' => 'Invoice date is after..', + 'rule_trigger_invoice_date_after' => 'Invoice date is after ":trigger_value"', + 'rule_trigger_created_at_before_choice' => 'Transaction was created before..', + 'rule_trigger_created_at_before' => 'Transaction was created before ":trigger_value"', + 'rule_trigger_created_at_after_choice' => 'Transaction was created after..', + 'rule_trigger_created_at_after' => 'Transaction was created after ":trigger_value"', + 'rule_trigger_updated_at_before_choice' => 'Transaction was last updated before..', + 'rule_trigger_updated_at_before' => 'Transaction was last updated before ":trigger_value"', + 'rule_trigger_updated_at_after_choice' => 'Transaction was last updated after..', + 'rule_trigger_updated_at_after' => 'Transaction was last updated after ":trigger_value"', + 'rule_trigger_foreign_amount_is_choice' => 'Foreign amount is exactly..', + 'rule_trigger_foreign_amount_is' => 'Foreign amount is exactly ":trigger_value"', + 'rule_trigger_foreign_amount_less_choice' => 'Foreign amount is less than..', + 'rule_trigger_foreign_amount_less' => 'Foreign amount is less than ":trigger_value"', + 'rule_trigger_foreign_amount_more_choice' => 'Foreign amount is more than..', + 'rule_trigger_foreign_amount_more' => 'Foreign amount is more than ":trigger_value"', + 'rule_trigger_attachment_name_is_choice' => 'Any attachment\'s name is..', + 'rule_trigger_attachment_name_is' => 'Any attachment\'s name is ":trigger_value"', + 'rule_trigger_attachment_name_contains_choice' => 'Any attachment\'s name contains..', + 'rule_trigger_attachment_name_contains' => 'Any attachment\'s name contains ":trigger_value"', + 'rule_trigger_attachment_name_starts_choice' => 'Any attachment\'s name starts with..', + 'rule_trigger_attachment_name_starts' => 'Any attachment\'s name starts with ":trigger_value"', + 'rule_trigger_attachment_name_ends_choice' => 'Any attachment\'s name ends with..', + 'rule_trigger_attachment_name_ends' => 'Any attachment\'s name ends with ":trigger_value"', + 'rule_trigger_attachment_notes_are_choice' => 'Any attachment\'s notes are..', + 'rule_trigger_attachment_notes_are' => 'Any attachment\'s notes are ":trigger_value"', + 'rule_trigger_attachment_notes_contains_choice' => 'Any attachment\'s notes contain..', + 'rule_trigger_attachment_notes_contains' => 'Any attachment\'s notes contain ":trigger_value"', + 'rule_trigger_attachment_notes_starts_choice' => 'Any attachment\'s notes start with..', + 'rule_trigger_attachment_notes_starts' => 'Any attachment\'s notes start with ":trigger_value"', + 'rule_trigger_attachment_notes_ends_choice' => 'Any attachment\'s notes end with..', + 'rule_trigger_attachment_notes_ends' => 'Any attachment\'s notes end with ":trigger_value"', + 'rule_trigger_reconciled_choice' => 'Transaction is reconciled', + 'rule_trigger_reconciled' => 'Transaction is reconciled', + 'rule_trigger_exists_choice' => 'Any transaction matches(!)', + 'rule_trigger_exists' => 'Any transaction matches', // more values for new types: - 'rule_trigger_not_account_id' => 'Account ID is not ":trigger_value"', - 'rule_trigger_not_source_account_id' => 'Source account ID is not ":trigger_value"', - 'rule_trigger_not_destination_account_id' => 'Destination account ID is not ":trigger_value"', - 'rule_trigger_not_transaction_type' => 'Transaction type is not ":trigger_value"', - 'rule_trigger_not_tag_is' => 'Tag is not ":trigger_value"', - 'rule_trigger_not_tag_is_not' => 'Tag is ":trigger_value"', - 'rule_trigger_not_description_is' => 'Description is not ":trigger_value"', - 'rule_trigger_not_description_contains' => 'Description does not contain', - 'rule_trigger_not_description_ends' => 'Description does not end with ":trigger_value"', - 'rule_trigger_not_description_starts' => 'Description does not start with ":trigger_value"', - 'rule_trigger_not_notes_is' => 'Notes are not ":trigger_value"', - 'rule_trigger_not_notes_contains' => 'Notes do not contain ":trigger_value"', - 'rule_trigger_not_notes_ends' => 'Notes do not end on ":trigger_value"', - 'rule_trigger_not_notes_starts' => 'Notes do not start with ":trigger_value"', - 'rule_trigger_not_source_account_is' => 'Source account is not ":trigger_value"', - 'rule_trigger_not_source_account_contains' => 'Source account does not contain ":trigger_value"', - 'rule_trigger_not_source_account_ends' => 'Source account does not end on ":trigger_value"', - 'rule_trigger_not_source_account_starts' => 'Source account does not start with ":trigger_value"', - 'rule_trigger_not_source_account_nr_is' => 'Source account number / IBAN is not ":trigger_value"', - 'rule_trigger_not_source_account_nr_contains' => 'Source account number / IBAN does not contain ":trigger_value"', - 'rule_trigger_not_source_account_nr_ends' => 'Source account number / IBAN does not end on ":trigger_value"', - 'rule_trigger_not_source_account_nr_starts' => 'Source account number / IBAN does not start with ":trigger_value"', - 'rule_trigger_not_destination_account_is' => 'Destination account is not ":trigger_value"', - 'rule_trigger_not_destination_account_contains' => 'Destination account does not contain ":trigger_value"', - 'rule_trigger_not_destination_account_ends' => 'Destination account does not end on ":trigger_value"', - 'rule_trigger_not_destination_account_starts' => 'Destination account does not start with ":trigger_value"', - 'rule_trigger_not_destination_account_nr_is' => 'Destination account number / IBAN is not ":trigger_value"', - 'rule_trigger_not_destination_account_nr_contains' => 'Destination account number / IBAN does not contain ":trigger_value"', - 'rule_trigger_not_destination_account_nr_ends' => 'Destination account number / IBAN does not end on ":trigger_value"', - 'rule_trigger_not_destination_account_nr_starts' => 'Destination account number / IBAN does not start with ":trigger_value"', - 'rule_trigger_not_account_is' => 'Neither account is ":trigger_value"', - 'rule_trigger_not_account_contains' => 'Neither account contains ":trigger_value"', - 'rule_trigger_not_account_ends' => 'Neither account ends on ":trigger_value"', - 'rule_trigger_not_account_starts' => 'Neither account starts with ":trigger_value"', - 'rule_trigger_not_account_nr_is' => 'Neither account number / IBAN is ":trigger_value"', - 'rule_trigger_not_account_nr_contains' => 'Neither account number / IBAN contains ":trigger_value"', - 'rule_trigger_not_account_nr_ends' => 'Neither account number / IBAN ends on ":trigger_value"', - 'rule_trigger_not_account_nr_starts' => 'Neither account number / IBAN starts with ":trigger_value"', - 'rule_trigger_not_category_is' => 'Category is not ":trigger_value"', - 'rule_trigger_not_category_contains' => 'Category does not contain ":trigger_value"', - 'rule_trigger_not_category_ends' => 'Category does not end on ":trigger_value"', - 'rule_trigger_not_category_starts' => 'Category does not start with ":trigger_value"', - 'rule_trigger_not_budget_is' => 'Budget is not ":trigger_value"', - 'rule_trigger_not_budget_contains' => 'Budget does not contain ":trigger_value"', - 'rule_trigger_not_budget_ends' => 'Budget does not end on ":trigger_value"', - 'rule_trigger_not_budget_starts' => 'Budget does not start with ":trigger_value"', - 'rule_trigger_not_bill_is' => 'Subscription is not is ":trigger_value"', - 'rule_trigger_not_bill_contains' => 'Subscription does not contain ":trigger_value"', - 'rule_trigger_not_bill_ends' => 'Subscription does not end on ":trigger_value"', - 'rule_trigger_not_bill_starts' => 'Subscription does not end with ":trigger_value"', - 'rule_trigger_not_external_id_is' => 'External ID is not ":trigger_value"', - 'rule_trigger_not_external_id_contains' => 'External ID does not contain ":trigger_value"', - 'rule_trigger_not_external_id_ends' => 'External ID does not end on ":trigger_value"', - 'rule_trigger_not_external_id_starts' => 'External ID does not start with ":trigger_value"', - 'rule_trigger_not_internal_reference_is' => 'Internal reference is not ":trigger_value"', - 'rule_trigger_not_internal_reference_contains' => 'Internal reference does not contain ":trigger_value"', - 'rule_trigger_not_internal_reference_ends' => 'Internal reference does not end on ":trigger_value"', - 'rule_trigger_not_internal_reference_starts' => 'Internal reference does not start with ":trigger_value"', - 'rule_trigger_not_external_url_is' => 'External URL is not ":trigger_value"', - 'rule_trigger_not_external_url_contains' => 'External URL does not contain ":trigger_value"', - 'rule_trigger_not_external_url_ends' => 'External URL does not end on ":trigger_value"', - 'rule_trigger_not_external_url_starts' => 'External URL does not start with ":trigger_value"', - 'rule_trigger_not_currency_is' => 'Currency is not ":trigger_value"', - 'rule_trigger_not_foreign_currency_is' => 'Foreign currency is not ":trigger_value"', - 'rule_trigger_not_id' => 'Transaction ID is not ":trigger_value"', - 'rule_trigger_not_journal_id' => 'Transaction journal ID is not ":trigger_value"', - 'rule_trigger_not_recurrence_id' => 'Recurrence ID is not ":trigger_value"', - 'rule_trigger_not_date_on' => 'Date is not on ":trigger_value"', - 'rule_trigger_not_date_before' => 'Date is not before ":trigger_value"', - 'rule_trigger_not_date_after' => 'Date is not after ":trigger_value"', - 'rule_trigger_not_interest_date_on' => 'Interest date is not on ":trigger_value"', - 'rule_trigger_not_interest_date_before' => 'Interest date is not before ":trigger_value"', - 'rule_trigger_not_interest_date_after' => 'Interest date is not after ":trigger_value"', - 'rule_trigger_not_book_date_on' => 'Book date is not on ":trigger_value"', - 'rule_trigger_not_book_date_before' => 'Book date is not before ":trigger_value"', - 'rule_trigger_not_book_date_after' => 'Book date is not after ":trigger_value"', - 'rule_trigger_not_process_date_on' => 'Process date is not on ":trigger_value"', - 'rule_trigger_not_process_date_before' => 'Process date is not before ":trigger_value"', - 'rule_trigger_not_process_date_after' => 'Process date is not after ":trigger_value"', - 'rule_trigger_not_due_date_on' => 'Due date is not on ":trigger_value"', - 'rule_trigger_not_due_date_before' => 'Due date is not before ":trigger_value"', - 'rule_trigger_not_due_date_after' => 'Due date is not after ":trigger_value"', - 'rule_trigger_not_payment_date_on' => 'Payment date is not on ":trigger_value"', - 'rule_trigger_not_payment_date_before' => 'Payment date is not before ":trigger_value"', - 'rule_trigger_not_payment_date_after' => 'Payment date is not after ":trigger_value"', - 'rule_trigger_not_invoice_date_on' => 'Invoice date is not on ":trigger_value"', - 'rule_trigger_not_invoice_date_before' => 'Invoice date is not before ":trigger_value"', - 'rule_trigger_not_invoice_date_after' => 'Invoice date is not after ":trigger_value"', - 'rule_trigger_not_created_at_on' => 'Transaction is not created on ":trigger_value"', - 'rule_trigger_not_created_at_before' => 'Transaction is not created before ":trigger_value"', - 'rule_trigger_not_created_at_after' => 'Transaction is not created after ":trigger_value"', - 'rule_trigger_not_updated_at_on' => 'Transaction is not updated on ":trigger_value"', - 'rule_trigger_not_updated_at_before' => 'Transaction is not updated before ":trigger_value"', - 'rule_trigger_not_updated_at_after' => 'Transaction is not updated after ":trigger_value"', - 'rule_trigger_not_amount_is' => 'Transaction amount is not ":trigger_value"', - 'rule_trigger_not_amount_less' => 'Transaction amount is more than ":trigger_value"', - 'rule_trigger_not_amount_more' => 'Transaction amount is less than ":trigger_value"', - 'rule_trigger_not_foreign_amount_is' => 'Foreign transaction amount is not ":trigger_value"', - 'rule_trigger_not_foreign_amount_less' => 'Foreign transaction amount is more than ":trigger_value"', - 'rule_trigger_not_foreign_amount_more' => 'Foreign transaction amount is less than ":trigger_value"', - 'rule_trigger_not_attachment_name_is' => 'No attachment is named ":trigger_value"', - 'rule_trigger_not_attachment_name_contains' => 'No attachment name contains ":trigger_value"', - 'rule_trigger_not_attachment_name_starts' => 'No attachment name starts with ":trigger_value"', - 'rule_trigger_not_attachment_name_ends' => 'No attachment name ends on ":trigger_value"', - 'rule_trigger_not_attachment_notes_are' => 'No attachment notes are ":trigger_value"', - 'rule_trigger_not_attachment_notes_contains' => 'No attachment notes contain ":trigger_value"', - 'rule_trigger_not_attachment_notes_starts' => 'No attachment notes start with ":trigger_value"', - 'rule_trigger_not_attachment_notes_ends' => 'No attachment notes end on ":trigger_value"', - 'rule_trigger_not_reconciled' => 'Transaction is not reconciled', - 'rule_trigger_not_exists' => 'Transaction does not exist', - 'rule_trigger_not_has_attachments' => 'Transaction has no attachments', - 'rule_trigger_not_has_any_category' => 'Transaction has no category', - 'rule_trigger_not_has_any_budget' => 'Transaction has no budget', - 'rule_trigger_not_has_any_bill' => 'Transaction has no subscription', - 'rule_trigger_not_has_any_tag' => 'Transaction has no tags', - 'rule_trigger_not_any_notes' => 'Transaction has no notes', - 'rule_trigger_not_any_external_url' => 'Transaction has no external URL', - 'rule_trigger_not_has_no_attachments' => 'Transaction has a (any) attachment(s)', - 'rule_trigger_not_has_no_category' => 'Transaction has a (any) category', - 'rule_trigger_not_has_no_budget' => 'Transaction has a (any) budget', - 'rule_trigger_not_has_no_bill' => 'Transaction has a (any) subscription', - 'rule_trigger_not_has_no_tag' => 'Transaction has a (any) tag', - 'rule_trigger_not_no_notes' => 'Transaction has any notes', - 'rule_trigger_not_no_external_url' => 'Transaction has an external URL', - 'rule_trigger_not_source_is_cash' => 'Source account is not a cash account', - 'rule_trigger_not_destination_is_cash' => 'Destination account is not a cash account', - 'rule_trigger_not_account_is_cash' => 'Neither account is a cash account', + 'rule_trigger_not_account_id' => 'Account ID is not ":trigger_value"', + 'rule_trigger_not_source_account_id' => 'Source account ID is not ":trigger_value"', + 'rule_trigger_not_destination_account_id' => 'Destination account ID is not ":trigger_value"', + 'rule_trigger_not_transaction_type' => 'Transaction type is not ":trigger_value"', + 'rule_trigger_not_tag_is' => 'Tag is not ":trigger_value"', + 'rule_trigger_not_tag_is_not' => 'Tag is ":trigger_value"', + 'rule_trigger_not_description_is' => 'Description is not ":trigger_value"', + 'rule_trigger_not_description_contains' => 'Description does not contain', + 'rule_trigger_not_description_ends' => 'Description does not end with ":trigger_value"', + 'rule_trigger_not_description_starts' => 'Description does not start with ":trigger_value"', + 'rule_trigger_not_notes_is' => 'Notes are not ":trigger_value"', + 'rule_trigger_not_notes_contains' => 'Notes do not contain ":trigger_value"', + 'rule_trigger_not_notes_ends' => 'Notes do not end on ":trigger_value"', + 'rule_trigger_not_notes_starts' => 'Notes do not start with ":trigger_value"', + 'rule_trigger_not_source_account_is' => 'Source account is not ":trigger_value"', + 'rule_trigger_not_source_account_contains' => 'Source account does not contain ":trigger_value"', + 'rule_trigger_not_source_account_ends' => 'Source account does not end on ":trigger_value"', + 'rule_trigger_not_source_account_starts' => 'Source account does not start with ":trigger_value"', + 'rule_trigger_not_source_account_nr_is' => 'Source account number / IBAN is not ":trigger_value"', + 'rule_trigger_not_source_account_nr_contains' => 'Source account number / IBAN does not contain ":trigger_value"', + 'rule_trigger_not_source_account_nr_ends' => 'Source account number / IBAN does not end on ":trigger_value"', + 'rule_trigger_not_source_account_nr_starts' => 'Source account number / IBAN does not start with ":trigger_value"', + 'rule_trigger_not_destination_account_is' => 'Destination account is not ":trigger_value"', + 'rule_trigger_not_destination_account_contains' => 'Destination account does not contain ":trigger_value"', + 'rule_trigger_not_destination_account_ends' => 'Destination account does not end on ":trigger_value"', + 'rule_trigger_not_destination_account_starts' => 'Destination account does not start with ":trigger_value"', + 'rule_trigger_not_destination_account_nr_is' => 'Destination account number / IBAN is not ":trigger_value"', + 'rule_trigger_not_destination_account_nr_contains' => 'Destination account number / IBAN does not contain ":trigger_value"', + 'rule_trigger_not_destination_account_nr_ends' => 'Destination account number / IBAN does not end on ":trigger_value"', + 'rule_trigger_not_destination_account_nr_starts' => 'Destination account number / IBAN does not start with ":trigger_value"', + 'rule_trigger_not_account_is' => 'Neither account is ":trigger_value"', + 'rule_trigger_not_account_contains' => 'Neither account contains ":trigger_value"', + 'rule_trigger_not_account_ends' => 'Neither account ends on ":trigger_value"', + 'rule_trigger_not_account_starts' => 'Neither account starts with ":trigger_value"', + 'rule_trigger_not_account_nr_is' => 'Neither account number / IBAN is ":trigger_value"', + 'rule_trigger_not_account_nr_contains' => 'Neither account number / IBAN contains ":trigger_value"', + 'rule_trigger_not_account_nr_ends' => 'Neither account number / IBAN ends on ":trigger_value"', + 'rule_trigger_not_account_nr_starts' => 'Neither account number / IBAN starts with ":trigger_value"', + 'rule_trigger_not_category_is' => 'Category is not ":trigger_value"', + 'rule_trigger_not_category_contains' => 'Category does not contain ":trigger_value"', + 'rule_trigger_not_category_ends' => 'Category does not end on ":trigger_value"', + 'rule_trigger_not_category_starts' => 'Category does not start with ":trigger_value"', + 'rule_trigger_not_budget_is' => 'Budget is not ":trigger_value"', + 'rule_trigger_not_budget_contains' => 'Budget does not contain ":trigger_value"', + 'rule_trigger_not_budget_ends' => 'Budget does not end on ":trigger_value"', + 'rule_trigger_not_budget_starts' => 'Budget does not start with ":trigger_value"', + 'rule_trigger_not_bill_is' => 'Subscription is not is ":trigger_value"', + 'rule_trigger_not_bill_contains' => 'Subscription does not contain ":trigger_value"', + 'rule_trigger_not_bill_ends' => 'Subscription does not end on ":trigger_value"', + 'rule_trigger_not_bill_starts' => 'Subscription does not end with ":trigger_value"', + 'rule_trigger_not_external_id_is' => 'External ID is not ":trigger_value"', + 'rule_trigger_not_external_id_contains' => 'External ID does not contain ":trigger_value"', + 'rule_trigger_not_external_id_ends' => 'External ID does not end on ":trigger_value"', + 'rule_trigger_not_external_id_starts' => 'External ID does not start with ":trigger_value"', + 'rule_trigger_not_internal_reference_is' => 'Internal reference is not ":trigger_value"', + 'rule_trigger_not_internal_reference_contains' => 'Internal reference does not contain ":trigger_value"', + 'rule_trigger_not_internal_reference_ends' => 'Internal reference does not end on ":trigger_value"', + 'rule_trigger_not_internal_reference_starts' => 'Internal reference does not start with ":trigger_value"', + 'rule_trigger_not_external_url_is' => 'External URL is not ":trigger_value"', + 'rule_trigger_not_external_url_contains' => 'External URL does not contain ":trigger_value"', + 'rule_trigger_not_external_url_ends' => 'External URL does not end on ":trigger_value"', + 'rule_trigger_not_external_url_starts' => 'External URL does not start with ":trigger_value"', + 'rule_trigger_not_currency_is' => 'Currency is not ":trigger_value"', + 'rule_trigger_not_foreign_currency_is' => 'Foreign currency is not ":trigger_value"', + 'rule_trigger_not_id' => 'Transaction ID is not ":trigger_value"', + 'rule_trigger_not_journal_id' => 'Transaction journal ID is not ":trigger_value"', + 'rule_trigger_not_recurrence_id' => 'Recurrence ID is not ":trigger_value"', + 'rule_trigger_not_date_on' => 'Date is not on ":trigger_value"', + 'rule_trigger_not_date_before' => 'Date is not before ":trigger_value"', + 'rule_trigger_not_date_after' => 'Date is not after ":trigger_value"', + 'rule_trigger_not_interest_date_on' => 'Interest date is not on ":trigger_value"', + 'rule_trigger_not_interest_date_before' => 'Interest date is not before ":trigger_value"', + 'rule_trigger_not_interest_date_after' => 'Interest date is not after ":trigger_value"', + 'rule_trigger_not_book_date_on' => 'Book date is not on ":trigger_value"', + 'rule_trigger_not_book_date_before' => 'Book date is not before ":trigger_value"', + 'rule_trigger_not_book_date_after' => 'Book date is not after ":trigger_value"', + 'rule_trigger_not_process_date_on' => 'Process date is not on ":trigger_value"', + 'rule_trigger_not_process_date_before' => 'Process date is not before ":trigger_value"', + 'rule_trigger_not_process_date_after' => 'Process date is not after ":trigger_value"', + 'rule_trigger_not_due_date_on' => 'Due date is not on ":trigger_value"', + 'rule_trigger_not_due_date_before' => 'Due date is not before ":trigger_value"', + 'rule_trigger_not_due_date_after' => 'Due date is not after ":trigger_value"', + 'rule_trigger_not_payment_date_on' => 'Payment date is not on ":trigger_value"', + 'rule_trigger_not_payment_date_before' => 'Payment date is not before ":trigger_value"', + 'rule_trigger_not_payment_date_after' => 'Payment date is not after ":trigger_value"', + 'rule_trigger_not_invoice_date_on' => 'Invoice date is not on ":trigger_value"', + 'rule_trigger_not_invoice_date_before' => 'Invoice date is not before ":trigger_value"', + 'rule_trigger_not_invoice_date_after' => 'Invoice date is not after ":trigger_value"', + 'rule_trigger_not_created_at_on' => 'Transaction is not created on ":trigger_value"', + 'rule_trigger_not_created_at_before' => 'Transaction is not created before ":trigger_value"', + 'rule_trigger_not_created_at_after' => 'Transaction is not created after ":trigger_value"', + 'rule_trigger_not_updated_at_on' => 'Transaction is not updated on ":trigger_value"', + 'rule_trigger_not_updated_at_before' => 'Transaction is not updated before ":trigger_value"', + 'rule_trigger_not_updated_at_after' => 'Transaction is not updated after ":trigger_value"', + 'rule_trigger_not_amount_is' => 'Transaction amount is not ":trigger_value"', + 'rule_trigger_not_amount_less' => 'Transaction amount is more than ":trigger_value"', + 'rule_trigger_not_amount_more' => 'Transaction amount is less than ":trigger_value"', + 'rule_trigger_not_foreign_amount_is' => 'Foreign transaction amount is not ":trigger_value"', + 'rule_trigger_not_foreign_amount_less' => 'Foreign transaction amount is more than ":trigger_value"', + 'rule_trigger_not_foreign_amount_more' => 'Foreign transaction amount is less than ":trigger_value"', + 'rule_trigger_not_attachment_name_is' => 'No attachment is named ":trigger_value"', + 'rule_trigger_not_attachment_name_contains' => 'No attachment name contains ":trigger_value"', + 'rule_trigger_not_attachment_name_starts' => 'No attachment name starts with ":trigger_value"', + 'rule_trigger_not_attachment_name_ends' => 'No attachment name ends on ":trigger_value"', + 'rule_trigger_not_attachment_notes_are' => 'No attachment notes are ":trigger_value"', + 'rule_trigger_not_attachment_notes_contains' => 'No attachment notes contain ":trigger_value"', + 'rule_trigger_not_attachment_notes_starts' => 'No attachment notes start with ":trigger_value"', + 'rule_trigger_not_attachment_notes_ends' => 'No attachment notes end on ":trigger_value"', + 'rule_trigger_not_reconciled' => 'Transaction is not reconciled', + 'rule_trigger_not_exists' => 'Transaction does not exist', + 'rule_trigger_not_has_attachments' => 'Transaction has no attachments', + 'rule_trigger_not_has_any_category' => 'Transaction has no category', + 'rule_trigger_not_has_any_budget' => 'Transaction has no budget', + 'rule_trigger_not_has_any_bill' => 'Transaction has no subscription', + 'rule_trigger_not_has_any_tag' => 'Transaction has no tags', + 'rule_trigger_not_any_notes' => 'Transaction has no notes', + 'rule_trigger_not_any_external_url' => 'Transaction has no external URL', + 'rule_trigger_not_has_no_attachments' => 'Transaction has a (any) attachment(s)', + 'rule_trigger_not_has_no_category' => 'Transaction has a (any) category', + 'rule_trigger_not_has_no_budget' => 'Transaction has a (any) budget', + 'rule_trigger_not_has_no_bill' => 'Transaction has a (any) subscription', + 'rule_trigger_not_has_no_tag' => 'Transaction has a (any) tag', + 'rule_trigger_not_no_notes' => 'Transaction has any notes', + 'rule_trigger_not_no_external_url' => 'Transaction has an external URL', + 'rule_trigger_not_source_is_cash' => 'Source account is not a cash account', + 'rule_trigger_not_destination_is_cash' => 'Destination account is not a cash account', + 'rule_trigger_not_account_is_cash' => 'Neither account is a cash account', // new account balance things. - 'rule_trigger_destination_balance_gt_choice' => 'Destination account balance is more than..', - 'rule_trigger_destination_balance_gte_choice' => 'Destination account balance is more than or equal to..', - 'rule_trigger_destination_balance_is_choice' => 'Destination account balance is exactly..', - 'rule_trigger_destination_balance_lt_choice' => 'Destination account balance is less than..', - 'rule_trigger_destination_balance_lte_choice' => 'Destination account balance is less than or equal to..', + 'rule_trigger_destination_balance_gt_choice' => 'Destination account balance is more than..', + 'rule_trigger_destination_balance_gte_choice' => 'Destination account balance is more than or equal to..', + 'rule_trigger_destination_balance_is_choice' => 'Destination account balance is exactly..', + 'rule_trigger_destination_balance_lt_choice' => 'Destination account balance is less than..', + 'rule_trigger_destination_balance_lte_choice' => 'Destination account balance is less than or equal to..', - 'rule_trigger_source_balance_gt_choice' => 'Source account balance is more than..', - 'rule_trigger_source_balance_gte_choice' => 'Source account balance is more than or equal to..', - 'rule_trigger_source_balance_is_choice' => 'Source account balance is exactly..', - 'rule_trigger_source_balance_lt_choice' => 'Source account balance is less than..', - 'rule_trigger_source_balance_lte_choice' => 'Source account balance is less than or equal to..', + 'rule_trigger_source_balance_gt_choice' => 'Source account balance is more than..', + 'rule_trigger_source_balance_gte_choice' => 'Source account balance is more than or equal to..', + 'rule_trigger_source_balance_is_choice' => 'Source account balance is exactly..', + 'rule_trigger_source_balance_lt_choice' => 'Source account balance is less than..', + 'rule_trigger_source_balance_lte_choice' => 'Source account balance is less than or equal to..', - 'rule_trigger_destination_balance_gt' => 'Destination account balance is more than :trigger_value', - 'rule_trigger_destination_balance_gte' => 'Destination account balance is more than or equal to :trigger_value', - 'rule_trigger_destination_balance_is' => 'Destination account balance is exactly :trigger_value', - 'rule_trigger_destination_balance_lt' => 'Destination account balance is less than :trigger_value', - 'rule_trigger_destination_balance_lte' => 'Destination account balance is less than or equal to :trigger_value', + 'rule_trigger_destination_balance_gt' => 'Destination account balance is more than :trigger_value', + 'rule_trigger_destination_balance_gte' => 'Destination account balance is more than or equal to :trigger_value', + 'rule_trigger_destination_balance_is' => 'Destination account balance is exactly :trigger_value', + 'rule_trigger_destination_balance_lt' => 'Destination account balance is less than :trigger_value', + 'rule_trigger_destination_balance_lte' => 'Destination account balance is less than or equal to :trigger_value', - 'rule_trigger_source_balance_gt' => 'Source account balance is more than :trigger_value', - 'rule_trigger_source_balance_gte' => 'Source account balance is more than or equal to :trigger_value', - 'rule_trigger_source_balance_is' => 'Source account balance is exactly :trigger_value', - 'rule_trigger_source_balance_lt' => 'Source account balance is less than :trigger_value', - 'rule_trigger_source_balance_lte' => 'Source account balance is less than or equal to :trigger_value', + 'rule_trigger_source_balance_gt' => 'Source account balance is more than :trigger_value', + 'rule_trigger_source_balance_gte' => 'Source account balance is more than or equal to :trigger_value', + 'rule_trigger_source_balance_is' => 'Source account balance is exactly :trigger_value', + 'rule_trigger_source_balance_lt' => 'Source account balance is less than :trigger_value', + 'rule_trigger_source_balance_lte' => 'Source account balance is less than or equal to :trigger_value', // NOT - 'rule_trigger_not_destination_balance_gt' => 'Destination account balance is less than or equal to :trigger_value', - 'rule_trigger_not_destination_balance_gte' => 'Destination account balance is less than :trigger_value', - 'rule_trigger_not_destination_balance_is' => 'Destination account balance is not :trigger_value', - 'rule_trigger_not_destination_balance_lt' => 'Destination account balance is more than or equal to :trigger_value', - 'rule_trigger_not_destination_balance_lte' => 'Destination account balance is more than :trigger_value', + 'rule_trigger_not_destination_balance_gt' => 'Destination account balance is less than or equal to :trigger_value', + 'rule_trigger_not_destination_balance_gte' => 'Destination account balance is less than :trigger_value', + 'rule_trigger_not_destination_balance_is' => 'Destination account balance is not :trigger_value', + 'rule_trigger_not_destination_balance_lt' => 'Destination account balance is more than or equal to :trigger_value', + 'rule_trigger_not_destination_balance_lte' => 'Destination account balance is more than :trigger_value', - 'rule_trigger_not_source_balance_gt' => 'Source account balance is less than or equal to :trigger_value', - 'rule_trigger_not_source_balance_gte' => 'Source account balance is less than :trigger_value', - 'rule_trigger_not_source_balance_is' => 'Source account balance is not :trigger_value', - 'rule_trigger_not_source_balance_lt' => 'Source account balance is more than or equal to :trigger_value', - 'rule_trigger_not_source_balance_lte' => 'Source account balance is more than :trigger_value', + 'rule_trigger_not_source_balance_gt' => 'Source account balance is less than or equal to :trigger_value', + 'rule_trigger_not_source_balance_gte' => 'Source account balance is less than :trigger_value', + 'rule_trigger_not_source_balance_is' => 'Source account balance is not :trigger_value', + 'rule_trigger_not_source_balance_lt' => 'Source account balance is more than or equal to :trigger_value', + 'rule_trigger_not_source_balance_lte' => 'Source account balance is more than :trigger_value', // actions // set, clear, add, remove, append/prepend - 'rule_action_delete_transaction_choice' => 'DELETE transaction(!)', - 'rule_action_delete_transaction' => 'DELETE transaction(!)', - 'rule_action_set_category' => 'Set category to ":action_value"', - 'rule_action_clear_category' => 'Clear category', - 'rule_action_set_budget' => 'Set budget to ":action_value"', - 'rule_action_clear_budget' => 'Clear budget', - 'rule_action_add_tag' => 'Add tag ":action_value"', - 'rule_action_remove_tag' => 'Remove tag ":action_value"', - 'rule_action_remove_all_tags' => 'Remove all tags', - 'rule_action_set_description' => 'Set description to ":action_value"', - 'rule_action_append_description' => 'Append description with ":action_value"', - 'rule_action_prepend_description' => 'Prepend description with ":action_value"', - 'rule_action_set_category_choice' => 'Set category to ..', - 'rule_action_clear_category_choice' => 'Clear any category', - 'rule_action_set_budget_choice' => 'Set budget to ..', - 'rule_action_clear_budget_choice' => 'Clear any budget', - 'rule_action_add_tag_choice' => 'Add tag ..', - 'rule_action_remove_tag_choice' => 'Remove tag ..', - 'rule_action_remove_all_tags_choice' => 'Remove all tags', - 'rule_action_set_description_choice' => 'Set description to ..', - 'rule_action_update_piggy_choice' => 'Add / remove transaction amount in piggy bank ..', - 'rule_action_update_piggy' => 'Add / remove transaction amount in piggy bank ":action_value"', - 'rule_action_append_description_choice' => 'Append description with ..', - 'rule_action_prepend_description_choice' => 'Prepend description with ..', - 'rule_action_set_source_account_choice' => 'Set source account to ..', - 'rule_action_set_source_account' => 'Set source account to :action_value', - 'rule_action_set_destination_account_choice' => 'Set destination account to ..', - 'rule_action_set_destination_account' => 'Set destination account to :action_value', - 'rule_action_append_notes_choice' => 'Append notes with ..', - 'rule_action_append_notes' => 'Append notes with ":action_value"', - 'rule_action_prepend_notes_choice' => 'Prepend notes with ..', - 'rule_action_prepend_notes' => 'Prepend notes with ":action_value"', - 'rule_action_clear_notes_choice' => 'Remove any notes', - 'rule_action_clear_notes' => 'Remove any notes', - 'rule_action_set_notes_choice' => 'Set notes to ..', - 'rule_action_link_to_bill_choice' => 'Link to a subscription ..', - 'rule_action_link_to_bill' => 'Link to subscription ":action_value"', - 'rule_action_switch_accounts_choice' => 'Switch source and destination accounts (transfers only!)', - 'rule_action_switch_accounts' => 'Switch source and destination', - 'rule_action_set_notes' => 'Set notes to ":action_value"', - 'rule_action_convert_deposit_choice' => 'Convert the transaction to a deposit', - 'rule_action_convert_deposit' => 'Convert the transaction to a deposit from ":action_value"', - 'rule_action_convert_withdrawal_choice' => 'Convert the transaction to a withdrawal', - 'rule_action_convert_withdrawal' => 'Convert the transaction to a withdrawal to ":action_value"', - 'rule_action_convert_transfer_choice' => 'Convert the transaction to a transfer', - 'rule_action_convert_transfer' => 'Convert the transaction to a transfer with ":action_value"', - 'rule_action_append_descr_to_notes_choice' => 'Append the description to the transaction notes', - 'rule_action_append_notes_to_descr_choice' => 'Append the transaction notes to the description', - 'rule_action_move_descr_to_notes_choice' => 'Replace the current transaction notes with the description', - 'rule_action_move_notes_to_descr_choice' => 'Replace the current description with the transaction notes', - 'rule_action_append_descr_to_notes' => 'Append description to notes', - 'rule_action_append_notes_to_descr' => 'Append notes to description', - 'rule_action_move_descr_to_notes' => 'Replace notes with description', - 'rule_action_move_notes_to_descr' => 'Replace description with notes', - 'rule_action_set_amount_choice' => 'Set amount to ..', - 'rule_action_set_amount' => 'Set amount to ":action_value"', - 'rule_action_set_destination_to_cash_choice' => 'Set destination account to (cash)', - 'rule_action_set_source_to_cash_choice' => 'Set source account to (cash)', - 'rulegroup_for_bills_title' => 'Rule group for subscriptions', - 'rulegroup_for_bills_description' => 'A special rule group for all the rules that involve subscriptions.', - 'rule_for_bill_title' => 'Auto-generated rule for subscription ":name"', - 'rule_for_bill_description' => 'This rule is auto-generated to try to match subscription ":name".', - 'create_rule_for_bill' => 'Create a new rule for subscription ":name"', - 'create_rule_for_bill_txt' => 'You have just created a new subscription called ":name", congratulations! Firefly III can automagically match new withdrawals to this subscription. For example, whenever you pay your rent, the subscription "rent" will be linked to the expense. This way, Firefly III can accurately show you which subscriptions are due and which ones aren\'t. In order to do so, a new rule must be created. Firefly III has filled in some sensible defaults for you. Please make sure these are correct. If these values are correct, Firefly III will automatically link the correct withdrawal to the correct subscription. Please check out the triggers to see if they are correct, and add some if they\'re wrong.', - 'new_rule_for_bill_title' => 'Rule for subscription ":name"', - 'new_rule_for_bill_description' => 'This rule marks transactions for subscription ":name".', + 'rule_action_delete_transaction_choice' => 'DELETE transaction(!)', + 'rule_action_delete_transaction' => 'DELETE transaction(!)', + 'rule_action_set_category' => 'Set category to ":action_value"', + 'rule_action_clear_category' => 'Clear category', + 'rule_action_set_budget' => 'Set budget to ":action_value"', + 'rule_action_clear_budget' => 'Clear budget', + 'rule_action_add_tag' => 'Add tag ":action_value"', + 'rule_action_remove_tag' => 'Remove tag ":action_value"', + 'rule_action_remove_all_tags' => 'Remove all tags', + 'rule_action_set_description' => 'Set description to ":action_value"', + 'rule_action_append_description' => 'Append description with ":action_value"', + 'rule_action_prepend_description' => 'Prepend description with ":action_value"', + 'rule_action_set_category_choice' => 'Set category to ..', + 'rule_action_clear_category_choice' => 'Clear any category', + 'rule_action_set_budget_choice' => 'Set budget to ..', + 'rule_action_clear_budget_choice' => 'Clear any budget', + 'rule_action_add_tag_choice' => 'Add tag ..', + 'rule_action_remove_tag_choice' => 'Remove tag ..', + 'rule_action_remove_all_tags_choice' => 'Remove all tags', + 'rule_action_set_description_choice' => 'Set description to ..', + 'rule_action_update_piggy_choice' => 'Add / remove transaction amount in piggy bank ..', + 'rule_action_update_piggy' => 'Add / remove transaction amount in piggy bank ":action_value"', + 'rule_action_append_description_choice' => 'Append description with ..', + 'rule_action_prepend_description_choice' => 'Prepend description with ..', + 'rule_action_set_source_account_choice' => 'Set source account to ..', + 'rule_action_set_source_account' => 'Set source account to :action_value', + 'rule_action_set_destination_account_choice' => 'Set destination account to ..', + 'rule_action_set_destination_account' => 'Set destination account to :action_value', + 'rule_action_append_notes_choice' => 'Append notes with ..', + 'rule_action_append_notes' => 'Append notes with ":action_value"', + 'rule_action_prepend_notes_choice' => 'Prepend notes with ..', + 'rule_action_prepend_notes' => 'Prepend notes with ":action_value"', + 'rule_action_clear_notes_choice' => 'Remove any notes', + 'rule_action_clear_notes' => 'Remove any notes', + 'rule_action_set_notes_choice' => 'Set notes to ..', + 'rule_action_link_to_bill_choice' => 'Link to a subscription ..', + 'rule_action_link_to_bill' => 'Link to subscription ":action_value"', + 'rule_action_switch_accounts_choice' => 'Switch source and destination accounts (transfers only!)', + 'rule_action_switch_accounts' => 'Switch source and destination', + 'rule_action_set_notes' => 'Set notes to ":action_value"', + 'rule_action_convert_deposit_choice' => 'Convert the transaction to a deposit', + 'rule_action_convert_deposit' => 'Convert the transaction to a deposit from ":action_value"', + 'rule_action_convert_withdrawal_choice' => 'Convert the transaction to a withdrawal', + 'rule_action_convert_withdrawal' => 'Convert the transaction to a withdrawal to ":action_value"', + 'rule_action_convert_transfer_choice' => 'Convert the transaction to a transfer', + 'rule_action_convert_transfer' => 'Convert the transaction to a transfer with ":action_value"', + 'rule_action_append_descr_to_notes_choice' => 'Append the description to the transaction notes', + 'rule_action_append_notes_to_descr_choice' => 'Append the transaction notes to the description', + 'rule_action_move_descr_to_notes_choice' => 'Replace the current transaction notes with the description', + 'rule_action_move_notes_to_descr_choice' => 'Replace the current description with the transaction notes', + 'rule_action_append_descr_to_notes' => 'Append description to notes', + 'rule_action_append_notes_to_descr' => 'Append notes to description', + 'rule_action_move_descr_to_notes' => 'Replace notes with description', + 'rule_action_move_notes_to_descr' => 'Replace description with notes', + 'rule_action_set_amount_choice' => 'Set amount to ..', + 'rule_action_set_amount' => 'Set amount to ":action_value"', + 'rule_action_set_destination_to_cash_choice' => 'Set destination account to (cash)', + 'rule_action_set_source_to_cash_choice' => 'Set source account to (cash)', + 'rulegroup_for_bills_title' => 'Rule group for subscriptions', + 'rulegroup_for_bills_description' => 'A special rule group for all the rules that involve subscriptions.', + 'rule_for_bill_title' => 'Auto-generated rule for subscription ":name"', + 'rule_for_bill_description' => 'This rule is auto-generated to try to match subscription ":name".', + 'create_rule_for_bill' => 'Create a new rule for subscription ":name"', + 'create_rule_for_bill_txt' => 'You have just created a new subscription called ":name", congratulations! Firefly III can automagically match new withdrawals to this subscription. For example, whenever you pay your rent, the subscription "rent" will be linked to the expense. This way, Firefly III can accurately show you which subscriptions are due and which ones aren\'t. In order to do so, a new rule must be created. Firefly III has filled in some sensible defaults for you. Please make sure these are correct. If these values are correct, Firefly III will automatically link the correct withdrawal to the correct subscription. Please check out the triggers to see if they are correct, and add some if they\'re wrong.', + 'new_rule_for_bill_title' => 'Rule for subscription ":name"', + 'new_rule_for_bill_description' => 'This rule marks transactions for subscription ":name".', - 'new_rule_for_journal_title' => 'Rule based on transaction ":description"', - 'new_rule_for_journal_description' => 'This rule is based on transaction ":description". It will match transactions that are exactly the same.', + 'new_rule_for_journal_title' => 'Rule based on transaction ":description"', + 'new_rule_for_journal_description' => 'This rule is based on transaction ":description". It will match transactions that are exactly the same.', // tags - 'store_new_tag' => 'Store new tag', - 'update_tag' => 'Update tag', - 'no_location_set' => 'No location set.', - 'meta_data' => 'Meta data', - 'location' => 'Location', - 'location_first_split' => 'The location for this transaction can be set on the first split of this transaction.', - 'without_date' => 'Without date', - 'result' => 'Result', - 'sums_apply_to_range' => 'All sums apply to the selected range', - 'mapbox_api_key' => 'To use map, get an API key from Mapbox. Open your .env file and enter this code after MAPBOX_API_KEY=.', - 'press_object_location' => 'Right click or long press to set the object\'s location.', - 'click_tap_location' => 'Click or tap the map to add a location', - 'clear_location' => 'Clear location', - 'delete_all_selected_tags' => 'Delete all selected tags', - 'select_tags_to_delete' => 'Don\'t forget to select some tags.', - 'deleted_x_tags' => 'Deleted :count tag.|Deleted :count tags.', - 'create_rule_from_transaction' => 'Create rule based on transaction', - 'create_recurring_from_transaction' => 'Create recurring transaction based on transaction', + 'store_new_tag' => 'Store new tag', + 'update_tag' => 'Update tag', + 'no_location_set' => 'No location set.', + 'meta_data' => 'Meta data', + 'location' => 'Location', + 'location_first_split' => 'The location for this transaction can be set on the first split of this transaction.', + 'without_date' => 'Without date', + 'result' => 'Result', + 'sums_apply_to_range' => 'All sums apply to the selected range', + 'mapbox_api_key' => 'To use map, get an API key from Mapbox. Open your .env file and enter this code after MAPBOX_API_KEY=.', + 'press_object_location' => 'Right click or long press to set the object\'s location.', + 'click_tap_location' => 'Click or tap the map to add a location', + 'clear_location' => 'Clear location', + 'delete_all_selected_tags' => 'Delete all selected tags', + 'select_tags_to_delete' => 'Don\'t forget to select some tags.', + 'deleted_x_tags' => 'Deleted :count tag.|Deleted :count tags.', + 'create_rule_from_transaction' => 'Create rule based on transaction', + 'create_recurring_from_transaction' => 'Create recurring transaction based on transaction', // preferences - 'test_notifications_buttons' => 'To test your configuration, use the buttons below. Please note that the buttons have no spam control.', - 'dark_mode_option_browser' => 'Let your browser decide', - 'dark_mode_option_light' => 'Always light', - 'dark_mode_option_dark' => 'Always dark', - 'equal_to_language' => '(equal to language)', - 'dark_mode_preference' => 'Dark mode', - 'dark_mode_preference_help' => 'Tell Firefly III when to use dark mode.', - 'pref_home_screen_accounts' => 'Home screen accounts', - 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?', - 'pref_view_range' => 'View range', - 'pref_view_range_help' => 'Some charts are automatically grouped in periods. Your budgets will also be grouped in periods. What period would you prefer?', - 'pref_1D' => 'One day', - 'pref_1W' => 'One week', - 'pref_1M' => 'One month', - 'pref_3M' => 'Three months (quarter)', - 'pref_6M' => 'Six months', - 'pref_1Y' => 'One year', - 'pref_last365' => 'Last year', - 'pref_last90' => 'Last 90 days', - 'pref_last30' => 'Last 30 days', - 'pref_last7' => 'Last 7 days', - 'pref_YTD' => 'Year to date', - 'pref_QTD' => 'Quarter to date', - 'pref_MTD' => 'Month to date', - 'pref_languages' => 'Languages', - 'pref_locale' => 'Locale settings', - 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?', - 'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.', - 'pref_locale_no_demo' => 'This feature won\'t work for the demo user.', - 'pref_convert_to_native' => 'Display amounts in your native currency', - 'pref_convert_to_native_help' => 'This option will make Firefly III try to display and show your native currency in as many places as possible, converting amounts where necessary. This sacrifices accuracy for ease of use, because conversion is not always exact. Please verify that Firefly III has the necessary conversion rates on the "exchange rates"-page.', - 'pref_convert_native_help' => 'Display native amounts', - 'pref_custom_fiscal_year' => 'Fiscal year settings', - 'pref_custom_fiscal_year_label' => 'Enabled', - 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year', - 'pref_fiscal_year_start_label' => 'Fiscal year start date', - 'pref_two_factor_auth' => 'Multi-factor authentication', - 'pref_two_factor_auth_help' => 'When you enable multi-factor authentication (also known as two-factor authentication), you add an extra layer of security to your account. You sign in with something you know (your password) and something you have (a verification code). Verification codes are generated by an application on your phone, such as Authy or Google Authenticator.', - 'pref_enable_two_factor_auth' => 'Enable multi-factor authentication', - 'pref_two_factor_auth_disabled' => 'Multi-factor authentication verification code removed and disabled', - 'pref_two_factor_auth_remove_it' => 'Don\'t forget to remove the account from your authentication app!', - 'pref_two_factor_auth_code' => 'Verify code', - 'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code. The QR code changes every time you visit this page. Make sure you use the most recent one.', - 'pref_two_factor_auth_reset_code' => 'Reset verification code', - 'pref_two_factor_auth_disable_2fa' => 'Disable MFA', - '2fa_use_secret_instead' => 'If you cannot scan the QR code, feel free to use the secret instead: :secret.', - '2fa_backup_codes' => 'Store these backup codes for access in case you lose your device.', - '2fa_already_enabled' => 'Multi-factor authentication verification is already enabled.', - 'wrong_mfa_code' => 'This MFA code is not valid.', - 'pref_save_settings' => 'Save settings', - 'saved_preferences' => 'Preferences saved!', - 'preferences_general' => 'General', - 'preferences_frontpage' => 'Home screen', - 'preferences_security' => 'Security', - 'preferences_layout' => 'Layout', - 'preferences_notifications' => 'Notifications', - 'pref_home_show_deposits' => 'Show deposits on the home screen', - 'pref_home_show_deposits_info' => 'The home screen already shows your expense accounts. Should it also show your revenue accounts?', - 'pref_home_do_show_deposits' => 'Yes, show them', - 'successful_count' => 'of which :count successful', - 'list_page_size_title' => 'Page size', - 'list_page_size_help' => 'Any list of things (accounts, transactions, etc) shows at most this many per page.', - 'list_page_size_label' => 'Page size', - 'between_dates' => '(:start and :end)', - 'pref_optional_fields_transaction' => 'Optional fields for transactions', - 'pref_optional_fields_transaction_help' => 'By default not all fields are enabled when creating a new transaction (because of the clutter). Below, you can enable these fields if you think they could be useful for you. Of course, any field that is disabled, but already filled in, will be visible regardless of the setting.', - 'optional_tj_date_fields' => 'Date fields', - 'optional_tj_other_fields' => 'Other fields', - 'optional_tj_attachment_fields' => 'Attachment fields', - 'pref_optional_tj_interest_date' => 'Interest date', - 'pref_optional_tj_book_date' => 'Book date', - 'pref_optional_tj_process_date' => 'Processing date', - 'pref_optional_tj_due_date' => 'Due date', - 'pref_optional_tj_payment_date' => 'Payment date', - 'pref_optional_tj_invoice_date' => 'Invoice date', - 'pref_optional_tj_internal_reference' => 'Internal reference', - 'pref_optional_tj_notes' => 'Notes', - 'pref_optional_tj_attachments' => 'Attachments', - 'pref_optional_tj_external_url' => 'External URL', - 'pref_optional_tj_location' => 'Location', - 'pref_optional_tj_links' => 'Transaction links', - 'optional_field_meta_dates' => 'Dates', - 'optional_field_meta_business' => 'Business', - 'optional_field_attachments' => 'Attachments', - 'optional_field_meta_data' => 'Optional meta data', - 'external_url' => 'External URL', - 'pref_notification_login_failure' => 'Login failure', - 'pref_notification_bill_reminder' => 'Reminder about expiring subscriptions', - 'pref_notification_new_access_token' => 'Alert when a new API access token is created', - 'pref_notification_transaction_creation' => 'Alert when a transaction is created automatically', - 'pref_notification_user_login' => 'Alert when you login from a new location', - 'pref_notification_rule_action_failures' => 'Alert when rule actions fail to execute (not over email)', - 'pref_notification_new_password' => 'Your password changed', - 'pref_notification_enabled_mfa' => 'Multi factor authentication is enabled', - 'pref_notification_disabled_mfa' => 'Multi factor authentication is disabled', - 'pref_notification_few_left_mfa' => 'You have just a few backup codes left', - 'pref_notification_no_left_mfa' => 'You have no backup codes left', - 'pref_notification_many_failed_mfa' => 'The multi factor authentication check keeps failing', - 'pref_notification_new_backup_codes' => 'New backup codes have been generated', - 'pref_notifications' => 'Notifications', - 'pref_notifications_help' => 'Indicate if these are notifications you would like to get. Some notifications may contain sensitive financial information.', - 'pref_notifications_settings' => 'Notifications settings', - 'pref_notifications_settings_help' => 'Use these settings to configure your notification channels. Please note that notifications will be sent to ALL channels. Please save your settings FIRST.', - 'slack_url_label' => 'Slack "incoming webhook" URL', - 'discord_url_label' => 'Discord webhook URL', + 'test_notifications_buttons' => 'To test your configuration, use the buttons below. Please note that the buttons have no spam control.', + 'dark_mode_option_browser' => 'Let your browser decide', + 'dark_mode_option_light' => 'Always light', + 'dark_mode_option_dark' => 'Always dark', + 'equal_to_language' => '(equal to language)', + 'dark_mode_preference' => 'Dark mode', + 'dark_mode_preference_help' => 'Tell Firefly III when to use dark mode.', + 'pref_home_screen_accounts' => 'Home screen accounts', + 'pref_home_screen_accounts_help' => 'Which accounts should be displayed on the home page?', + 'pref_view_range' => 'View range', + 'pref_view_range_help' => 'Some charts are automatically grouped in periods. Your budgets will also be grouped in periods. What period would you prefer?', + 'pref_1D' => 'One day', + 'pref_1W' => 'One week', + 'pref_1M' => 'One month', + 'pref_3M' => 'Three months (quarter)', + 'pref_6M' => 'Six months', + 'pref_1Y' => 'One year', + 'pref_last365' => 'Last year', + 'pref_last90' => 'Last 90 days', + 'pref_last30' => 'Last 30 days', + 'pref_last7' => 'Last 7 days', + 'pref_YTD' => 'Year to date', + 'pref_QTD' => 'Quarter to date', + 'pref_MTD' => 'Month to date', + 'pref_languages' => 'Languages', + 'pref_locale' => 'Locale settings', + 'pref_languages_help' => 'Firefly III supports several languages. Which one do you prefer?', + 'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.', + 'pref_locale_no_demo' => 'This feature won\'t work for the demo user.', + 'pref_convert_to_native' => 'Display amounts in your native currency', + 'pref_convert_to_native_help' => 'This option will make Firefly III try to display and show your native currency in as many places as possible, converting amounts where necessary. This sacrifices accuracy for ease of use, because conversion is not always exact. Please verify that Firefly III has the necessary conversion rates on the "exchange rates"-page.', + 'pref_convert_native_help' => 'Display native amounts', + 'pref_custom_fiscal_year' => 'Fiscal year settings', + 'pref_custom_fiscal_year_label' => 'Enabled', + 'pref_custom_fiscal_year_help' => 'In countries that use a financial year other than January 1 to December 31, you can switch this on and specify start / end days of the fiscal year', + 'pref_fiscal_year_start_label' => 'Fiscal year start date', + 'pref_two_factor_auth' => 'Multi-factor authentication', + 'pref_two_factor_auth_help' => 'When you enable multi-factor authentication (also known as two-factor authentication), you add an extra layer of security to your account. You sign in with something you know (your password) and something you have (a verification code). Verification codes are generated by an application on your phone, such as Authy or Google Authenticator.', + 'pref_enable_two_factor_auth' => 'Enable multi-factor authentication', + 'pref_two_factor_auth_disabled' => 'Multi-factor authentication verification code removed and disabled', + 'pref_two_factor_auth_remove_it' => 'Don\'t forget to remove the account from your authentication app!', + 'pref_two_factor_auth_code' => 'Verify code', + 'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code. The QR code changes every time you visit this page. Make sure you use the most recent one.', + 'pref_two_factor_auth_reset_code' => 'Reset verification code', + 'pref_two_factor_auth_disable_2fa' => 'Disable MFA', + '2fa_use_secret_instead' => 'If you cannot scan the QR code, feel free to use the secret instead: :secret.', + '2fa_backup_codes' => 'Store these backup codes for access in case you lose your device.', + '2fa_already_enabled' => 'Multi-factor authentication verification is already enabled.', + 'wrong_mfa_code' => 'This MFA code is not valid.', + 'pref_save_settings' => 'Save settings', + 'saved_preferences' => 'Preferences saved!', + 'preferences_general' => 'General', + 'preferences_frontpage' => 'Home screen', + 'preferences_security' => 'Security', + 'preferences_layout' => 'Layout', + 'preferences_notifications' => 'Notifications', + 'pref_home_show_deposits' => 'Show deposits on the home screen', + 'pref_home_show_deposits_info' => 'The home screen already shows your expense accounts. Should it also show your revenue accounts?', + 'pref_home_do_show_deposits' => 'Yes, show them', + 'successful_count' => 'of which :count successful', + 'list_page_size_title' => 'Page size', + 'list_page_size_help' => 'Any list of things (accounts, transactions, etc) shows at most this many per page.', + 'list_page_size_label' => 'Page size', + 'between_dates' => '(:start and :end)', + 'pref_optional_fields_transaction' => 'Optional fields for transactions', + 'pref_optional_fields_transaction_help' => 'By default not all fields are enabled when creating a new transaction (because of the clutter). Below, you can enable these fields if you think they could be useful for you. Of course, any field that is disabled, but already filled in, will be visible regardless of the setting.', + 'optional_tj_date_fields' => 'Date fields', + 'optional_tj_other_fields' => 'Other fields', + 'optional_tj_attachment_fields' => 'Attachment fields', + 'pref_optional_tj_interest_date' => 'Interest date', + 'pref_optional_tj_book_date' => 'Book date', + 'pref_optional_tj_process_date' => 'Processing date', + 'pref_optional_tj_due_date' => 'Due date', + 'pref_optional_tj_payment_date' => 'Payment date', + 'pref_optional_tj_invoice_date' => 'Invoice date', + 'pref_optional_tj_internal_reference' => 'Internal reference', + 'pref_optional_tj_notes' => 'Notes', + 'pref_optional_tj_attachments' => 'Attachments', + 'pref_optional_tj_external_url' => 'External URL', + 'pref_optional_tj_location' => 'Location', + 'pref_optional_tj_links' => 'Transaction links', + 'optional_field_meta_dates' => 'Dates', + 'optional_field_meta_business' => 'Business', + 'optional_field_attachments' => 'Attachments', + 'optional_field_meta_data' => 'Optional meta data', + 'external_url' => 'External URL', + 'pref_notification_login_failure' => 'Login failure', + 'pref_notification_bill_reminder' => 'Reminder about expiring subscriptions', + 'pref_notification_new_access_token' => 'Alert when a new API access token is created', + 'pref_notification_transaction_creation' => 'Alert when a transaction is created automatically', + 'pref_notification_user_login' => 'Alert when you login from a new location', + 'pref_notification_rule_action_failures' => 'Alert when rule actions fail to execute (not over email)', + 'pref_notification_new_password' => 'Your password changed', + 'pref_notification_enabled_mfa' => 'Multi factor authentication is enabled', + 'pref_notification_disabled_mfa' => 'Multi factor authentication is disabled', + 'pref_notification_few_left_mfa' => 'You have just a few backup codes left', + 'pref_notification_no_left_mfa' => 'You have no backup codes left', + 'pref_notification_many_failed_mfa' => 'The multi factor authentication check keeps failing', + 'pref_notification_new_backup_codes' => 'New backup codes have been generated', + 'pref_notifications' => 'Notifications', + 'pref_notifications_help' => 'Indicate if these are notifications you would like to get. Some notifications may contain sensitive financial information.', + 'pref_notifications_settings' => 'Notifications settings', + 'pref_notifications_settings_help' => 'Use these settings to configure your notification channels. Please note that notifications will be sent to ALL channels. Please save your settings FIRST.', + 'slack_url_label' => 'Slack "incoming webhook" URL', + 'discord_url_label' => 'Discord webhook URL', // exchange rates - 'menu_exchange_rates_index' => 'Exchange rates', - 'header_exchange_rates' => 'Exchange rates', - 'exchange_rates_intro' => 'Firefly III supports downloading and using exchange rates. Read more about this in the documentation.', - 'exchange_rates_from_to' => 'Between {from} and {to} (and the other way around)', - 'header_exchange_rates_rates' => 'Exchange rates', - 'exchange_rates_intro_rates' => 'Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate "1" will be used.', - 'header_exchange_rates_table' => 'Table with exchange rates', - 'help_rate_form' => 'On this day, how many {to} will you get for one {from}?', - 'save_new_rate' => 'Save new rate', - 'add_new_rate' => 'Add a new exchange rate', - 'not_enough_currencies' => 'Not enough currencies', - 'not_enough_currencies_enabled' => 'If you have just one currency enabled, there is no need to add exchange rates.', + 'menu_exchange_rates_index' => 'Exchange rates', + 'header_exchange_rates' => 'Exchange rates', + 'exchange_rates_intro' => 'Firefly III supports downloading and using exchange rates. Read more about this in the documentation.', + 'exchange_rates_from_to' => 'Between {from} and {to} (and the other way around)', + 'header_exchange_rates_rates' => 'Exchange rates', + 'exchange_rates_intro_rates' => 'Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate "1" will be used.', + 'header_exchange_rates_table' => 'Table with exchange rates', + 'help_rate_form' => 'On this day, how many {to} will you get for one {from}?', + 'save_new_rate' => 'Save new rate', + 'add_new_rate' => 'Add a new exchange rate', + 'not_enough_currencies' => 'Not enough currencies', + 'not_enough_currencies_enabled' => 'If you have just one currency enabled, there is no need to add exchange rates.', // Financial administrations - 'administration_index' => 'Financial administration', - 'administrations_breadcrumb' => 'Financial administrations', - 'administrations_page_title' => 'Financial administrations', - 'administrations_index_menu' => 'Financial administrations', - 'administrations_page_sub_title' => 'Overview', - 'create_administration' => 'Create new administration', - 'administration_owner' => 'Administration owner: {{email}}', - 'administration_you' => 'Your role: {{role}}', - 'other_users_in_admin' => 'Other users in this administration', - 'administrations_create_breadcrumb' => 'Create new financial administration', - 'administrations_page_create_sub_title' => 'Create new financial administration', - 'basic_administration_information' => 'Basic administration information', - 'new_administration_created' => 'New financial administration "{{title}}" has been created', - 'edit_administration_breadcrumb' => 'Edit financial administration ":title"', - 'administrations_page_edit_sub_title' => 'Edit financial administration ":title"', - 'administrations_page_edit_sub_title_js' => 'Edit financial administration "{title}"', - 'temp_administrations_introduction' => 'Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your "default currency". This setting is now tied to the financial administration and can be different per administration.', - 'temp_administrations_introduction_edit' => 'Currently, you can only set the "native currency" of the default financial administration. This replaces the "default currency" setting. This setting is now tied to the financial administration and can be different per administration.', - 'administration_currency_form_help' => 'It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.', - 'flash_administration_updated' => 'Administration ":title" has been updated', - 'flash_administration_created' => 'Administration ":title" has been created', - 'flash_administration_deleted' => 'Administration ":title" has been deleted', + 'administration_index' => 'Financial administration', + 'administrations_breadcrumb' => 'Financial administrations', + 'administrations_page_title' => 'Financial administrations', + 'administrations_index_menu' => 'Financial administrations', + 'administrations_page_sub_title' => 'Overview', + 'create_administration' => 'Create new administration', + 'administration_owner' => 'Administration owner: {{email}}', + 'administration_you' => 'Your role: {{role}}', + 'other_users_in_admin' => 'Other users in this administration', + 'administrations_create_breadcrumb' => 'Create new financial administration', + 'administrations_page_create_sub_title' => 'Create new financial administration', + 'basic_administration_information' => 'Basic administration information', + 'new_administration_created' => 'New financial administration "{{title}}" has been created', + 'edit_administration_breadcrumb' => 'Edit financial administration ":title"', + 'administrations_page_edit_sub_title' => 'Edit financial administration ":title"', + 'administrations_page_edit_sub_title_js' => 'Edit financial administration "{title}"', + 'temp_administrations_introduction' => 'Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its native currency. This replaces the previous setting where you would set your "default currency". This setting is now tied to the financial administration and can be different per administration.', + 'temp_administrations_introduction_edit' => 'Currently, you can only set the "native currency" of the default financial administration. This replaces the "default currency" setting. This setting is now tied to the financial administration and can be different per administration.', + 'administration_currency_form_help' => 'It may take a long time for the page to load if you change the native currency because transaction may need to be converted to your (new) native currency.', + 'flash_administration_updated' => 'Administration ":title" has been updated', + 'flash_administration_created' => 'Administration ":title" has been created', + 'flash_administration_deleted' => 'Administration ":title" has been deleted', // roles - 'administration_role_owner' => 'Owner', - 'administration_role_ro' => 'Read-only', - 'administration_role_mng_trx' => 'Manage transactions', - 'administration_role_mng_meta' => 'Manage classification and meta-data', - 'administration_role_mng_budgets' => 'Manage budgets', - 'administration_role_mng_piggies' => 'Manage piggy banks', - 'administration_role_mng_subscriptions' => 'Manage subscriptions', - 'administration_role_mng_rules' => 'Manage rules', - 'administration_role_mng_recurring' => 'Manage recurring transactions', - 'administration_role_mng_webhooks' => 'Manage webhooks', - 'administration_role_mng_currencies' => 'Manage currencies', - 'administration_role_view_reports' => 'View reports', - 'administration_role_full' => 'Full access', + 'administration_role_owner' => 'Owner', + 'administration_role_ro' => 'Read-only', + 'administration_role_mng_trx' => 'Manage transactions', + 'administration_role_mng_meta' => 'Manage classification and meta-data', + 'administration_role_mng_budgets' => 'Manage budgets', + 'administration_role_mng_piggies' => 'Manage piggy banks', + 'administration_role_mng_subscriptions' => 'Manage subscriptions', + 'administration_role_mng_rules' => 'Manage rules', + 'administration_role_mng_recurring' => 'Manage recurring transactions', + 'administration_role_mng_webhooks' => 'Manage webhooks', + 'administration_role_mng_currencies' => 'Manage currencies', + 'administration_role_view_reports' => 'View reports', + 'administration_role_full' => 'Full access', // mfa - 'enable_mfa' => 'Enable multi-factor authentication', - 'mfa_index_title' => 'Multi-factor authentication', - 'mfa_index_intro' => 'Firefly III supports multi-factor authentication (MFA). You can enable MFA for your account to add an extra layer of security. Applications like Authy, Google Authenticator and FreeOTP can be used to generate the codes you need to log in. Security keys are not supported by Firefly III but you can use a security key as a storage device for your MFA secret.', - 'mfa_index_enabled' => 'Multi-factor authentication is enabled for your account.', - 'mfa_index_disabled' => 'Multi-factor authentication is not enabled for your account.', - 'mfa_index_owner' => 'The owner of this instance will always be able to disable multi-factor authentication for your account.', - 'current_password_confirm_mfa' => 'Enter your current password', - 'mfa_warning_code_changes' => 'You may get a MFA dialog after you entered your password and a MFA code. In that case, please wait for your application to generate a new MFA code, and do not recycle the one you just used.', - 'mfa_already_disabled' => 'Multi-factor authentication is not enabled, so you cannot disable it.', - 'disable_mfa_page' => 'Disable multi-factor authentication', - 'disable_mfa_intro' => 'You can disable multi-factor authentication. To do so, please enter your password and a multi-factor authentication code. If you want to disable multi-factor authentication because you have lost access to your code generator, please refer to the documentation instead.', - 'pref_disable_mfa' => 'Disable multi-factor authentication', - 'mfa_not_enabled' => 'Multi-factor authentication is not enabled.', - 'mfa_backup_codes_intro' => 'Firefly III can generate backup codes for you. These codes can be used to log in when you cannot use your code generator. You can generate a new set of codes at any time. If you generate a new set, the old set will be invalidated.', - 'mfa_backup_codes_quick' => 'If you are very fast coming from the setup page of multi-factor authentication, your app may not have generated a new code yet. Please know that MFA codes can only be used once. Make sure you use a different code from the previous one.', - 'mfa_backup_codes_title' => 'Multi-factor authentication backup codes', - 'mfa_backup_codes_post_title' => 'Multi-factor authentication backup codes', + 'enable_mfa' => 'Enable multi-factor authentication', + 'mfa_index_title' => 'Multi-factor authentication', + 'mfa_index_intro' => 'Firefly III supports multi-factor authentication (MFA). You can enable MFA for your account to add an extra layer of security. Applications like Authy, Google Authenticator and FreeOTP can be used to generate the codes you need to log in. Security keys are not supported by Firefly III but you can use a security key as a storage device for your MFA secret.', + 'mfa_index_enabled' => 'Multi-factor authentication is enabled for your account.', + 'mfa_index_disabled' => 'Multi-factor authentication is not enabled for your account.', + 'mfa_index_owner' => 'The owner of this instance will always be able to disable multi-factor authentication for your account.', + 'current_password_confirm_mfa' => 'Enter your current password', + 'mfa_warning_code_changes' => 'You may get a MFA dialog after you entered your password and a MFA code. In that case, please wait for your application to generate a new MFA code, and do not recycle the one you just used.', + 'mfa_already_disabled' => 'Multi-factor authentication is not enabled, so you cannot disable it.', + 'disable_mfa_page' => 'Disable multi-factor authentication', + 'disable_mfa_intro' => 'You can disable multi-factor authentication. To do so, please enter your password and a multi-factor authentication code. If you want to disable multi-factor authentication because you have lost access to your code generator, please refer to the documentation instead.', + 'pref_disable_mfa' => 'Disable multi-factor authentication', + 'mfa_not_enabled' => 'Multi-factor authentication is not enabled.', + 'mfa_backup_codes_intro' => 'Firefly III can generate backup codes for you. These codes can be used to log in when you cannot use your code generator. You can generate a new set of codes at any time. If you generate a new set, the old set will be invalidated.', + 'mfa_backup_codes_quick' => 'If you are very fast coming from the setup page of multi-factor authentication, your app may not have generated a new code yet. Please know that MFA codes can only be used once. Make sure you use a different code from the previous one.', + 'mfa_backup_codes_title' => 'Multi-factor authentication backup codes', + 'mfa_backup_codes_post_title' => 'Multi-factor authentication backup codes', // profile: - 'manage_mfa_settings' => 'Manage multi-factor authentication settings', - 'purge_data_title' => 'Purge data from Firefly III', - 'purge_data_expl' => '"Purging" means "deleting that which is already deleted". In normal circumstances, Firefly III deletes nothing permanently. It just hides it. The button below deletes all of these previously "deleted" records FOREVER.', - 'delete_stuff_header' => 'Delete and purge data', - 'purge_all_data' => 'Purge all deleted records', - 'purge_data' => 'Purge data', - 'purged_all_records' => 'All deleted records have been purged.', - 'delete_data_title' => 'Delete data from Firefly III', - 'permanent_delete_stuff' => 'You can delete stuff from Firefly III. Using the buttons below means that your items will be removed from view and hidden. There is no undo-button for this, but the items may remain in the database where you can salvage them if necessary.', - 'other_sessions_logged_out' => 'All your other sessions have been logged out.', - 'delete_unused_accounts' => 'Deleting unused accounts will clean your auto-complete lists.', - 'delete_all_unused_accounts' => 'Delete unused accounts', - 'deleted_all_unused_accounts' => 'All unused accounts are deleted', - 'delete_all_budgets' => 'Delete ALL your budgets', - 'delete_all_categories' => 'Delete ALL your categories', - 'delete_all_tags' => 'Delete ALL your tags', - 'delete_all_bills' => 'Delete ALL your subscriptions', - 'delete_all_piggy_banks' => 'Delete ALL your piggy banks', - 'delete_all_rules' => 'Delete ALL your rules', - 'delete_all_recurring' => 'Delete ALL your recurring transactions', - 'delete_all_object_groups' => 'Delete ALL your object groups', - 'delete_all_accounts' => 'Delete ALL your accounts', - 'delete_all_asset_accounts' => 'Delete ALL your asset accounts', - 'delete_all_expense_accounts' => 'Delete ALL your expense accounts', - 'delete_all_revenue_accounts' => 'Delete ALL your revenue accounts', - 'delete_all_liabilities' => 'Delete ALL your liabilities', - 'delete_all_transactions' => 'Delete ALL your transactions', - 'delete_all_withdrawals' => 'Delete ALL your withdrawals', - 'delete_all_deposits' => 'Delete ALL your deposits', - 'delete_all_transfers' => 'Delete ALL your transfers', - 'also_delete_transactions' => 'Deleting accounts will also delete ALL associated withdrawals, deposits and transfers!', - 'deleted_all_budgets' => 'All budgets have been deleted', - 'deleted_all_categories' => 'All categories have been deleted', - 'deleted_all_tags' => 'All tags have been deleted', - 'deleted_all_bills' => 'All subscriptions have been deleted', - 'deleted_all_piggy_banks' => 'All piggy banks have been deleted', - 'deleted_all_rules' => 'All rules and rule groups have been deleted', - 'deleted_all_object_groups' => 'All groups have been deleted', - 'deleted_all_accounts' => 'All accounts have been deleted', - 'deleted_all_asset_accounts' => 'All asset accounts have been deleted', - 'deleted_all_expense_accounts' => 'All expense accounts have been deleted', - 'deleted_all_revenue_accounts' => 'All revenue accounts have been deleted', - 'deleted_all_liabilities' => 'All liabilities have been deleted', - 'deleted_all_transactions' => 'All transactions have been deleted', - 'deleted_all_withdrawals' => 'All withdrawals have been deleted', - 'deleted_all_deposits' => 'All deposits have been deleted', - 'deleted_all_transfers' => 'All transfers have been deleted', - 'deleted_all_recurring' => 'All recurring transactions have been deleted', - 'change_your_password' => 'Change your password', - 'delete_account' => 'Delete account', - 'current_password' => 'Current password', - 'new_password' => 'New password', - 'new_password_again' => 'New password (again)', - 'delete_your_account' => 'Delete your account', - 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.', - 'delete_your_account_password' => 'Enter your password to continue.', - 'password' => 'Password', - 'are_you_sure' => 'Are you sure? You cannot undo this.', - 'are_you_sure_confirm' => 'Are you sure?', - 'delete_account_button' => 'DELETE your account', - 'invalid_current_password' => 'Invalid current password!', - 'password_changed' => 'Password changed!', - 'should_change' => 'The idea is to change your password.', - 'invalid_password' => 'Invalid password!', - 'what_is_pw_security' => 'What is "verify password security"?', - 'secure_pw_title' => 'How to choose a secure password', - 'forgot_password_response' => 'Thank you. If an account exists with this email address, you will find instructions in your inbox.', - 'secure_pw_history' => 'Not a week goes by that you read in the news about a site losing the passwords of its users. Hackers and thieves use these passwords to try to steal your private information. This information is valuable.', - 'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.', - 'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.', - 'secure_pw_working_title' => 'How does it work?', - 'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to the website of Troy Hunt to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest NIST Special Publication on this subject.', - 'secure_pw_should' => 'Should I check the box?', - 'secure_pw_long_password' => 'Yes. Always verify your password is safe.', - 'command_line_token' => 'Command line token', - 'explain_command_line_token' => 'You need this token to perform command line options, such as exporting data. Without it, that sensitive command will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', - 'regenerate_command_line_token' => 'Regenerate command line token', - 'token_regenerated' => 'A new command line token was generated', - 'change_your_email' => 'Change your email address', - 'email_verification' => 'An email message will be sent to your old AND new email address. For security purposes, you will not be able to login until you verify your new email address. If you are unsure if your Firefly III installation is capable of sending email, please do not use this feature. If you are an administrator, you can test this in the settings.', - 'email_changed_logout' => 'Until you verify your email address, you cannot login.', - 'login_with_new_email' => 'You can now login with your new email address.', - 'login_with_old_email' => 'You can now login with your old email address again.', - 'login_provider_local_only' => 'This action is not available when authenticating through ":login_provider".', - 'external_user_mgt_disabled' => 'This action is not available when Firefly III isn\'t responsible for user management or authentication handling.', - 'external_auth_disabled' => 'This action is not available when Firefly III isn\'t responsible for authentication handling.', - 'delete_local_info_only' => "Because Firefly III isn't responsible for user management or authentication handling, this function will only delete local Firefly III information.", - 'oauth' => 'OAuth', - 'profile_oauth_clients' => 'OAuth Clients', - 'profile_oauth_no_clients' => 'You have not created any OAuth clients.', - 'profile_oauth_clients_external_auth' => 'If you\'re using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.', - 'profile_oauth_clients_header' => 'Clients', - 'profile_oauth_client_id' => 'Client ID', - 'profile_oauth_client_name' => 'Name', - 'profile_oauth_client_secret' => 'Secret', - 'profile_oauth_create_new_client' => 'Create New Client', - 'profile_oauth_create_client' => 'Create Client', - 'profile_oauth_edit_client' => 'Edit Client', - 'profile_oauth_name_help' => 'Something your users will recognize and trust.', - 'profile_oauth_redirect_url' => 'Redirect URL', - 'profile_oauth_redirect_url_help' => 'Your application\'s authorization callback URL.', - 'profile_authorized_apps' => 'Authorized applications', - 'profile_authorized_clients' => 'Authorized clients', - 'profile_scopes' => 'Scopes', - 'profile_revoke' => 'Revoke', - 'profile_oauth_client_secret_title' => 'Client Secret', - 'profile_oauth_client_secret_expl' => 'Here is your new client secret. This is the only time it will be shown so don\'t lose it! You may now use this secret to make API requests.', - 'profile_personal_access_tokens' => 'Personal Access Tokens', - 'profile_personal_access_token' => 'Personal Access Token', - 'profile_oauth_confidential' => 'Confidential', - 'profile_oauth_confidential_help' => 'Require the client to authenticate with a secret. Confidential clients can hold credentials in a secure way without exposing them to unauthorized parties. Public applications, such as native desktop or JavaScript SPA applications, are unable to hold secrets securely.', - 'profile_personal_access_token_explanation' => 'Here is your new personal access token. This is the only time it will be shown so don\'t lose it! You may now use this token to make API requests.', - 'profile_no_personal_access_token' => 'You have not created any personal access tokens.', - 'profile_create_new_token' => 'Create new token', - 'profile_create_token' => 'Create token', - 'profile_create' => 'Create', - 'profile_save_changes' => 'Save changes', - 'profile_whoops' => 'Whoops!', - 'profile_something_wrong' => 'Something went wrong!', - 'profile_try_again' => 'Something went wrong. Please try again.', - 'amounts' => 'Amounts', - 'multi_account_warning_unknown' => 'Depending on the type of transaction you create, the source and/or destination account of subsequent splits may be overruled by whatever is defined in the first split of the transaction.', - 'multi_account_warning_withdrawal' => 'Keep in mind that the source account of subsequent splits will be overruled by whatever is defined in the first split of the withdrawal.', - 'multi_account_warning_deposit' => 'Keep in mind that the destination account of subsequent splits will be overruled by whatever is defined in the first split of the deposit.', - 'multi_account_warning_transfer' => 'Keep in mind that the source + destination account of subsequent splits will be overruled by whatever is defined in the first split of the transfer.', + 'manage_mfa_settings' => 'Manage multi-factor authentication settings', + 'purge_data_title' => 'Purge data from Firefly III', + 'purge_data_expl' => '"Purging" means "deleting that which is already deleted". In normal circumstances, Firefly III deletes nothing permanently. It just hides it. The button below deletes all of these previously "deleted" records FOREVER.', + 'delete_stuff_header' => 'Delete and purge data', + 'purge_all_data' => 'Purge all deleted records', + 'purge_data' => 'Purge data', + 'purged_all_records' => 'All deleted records have been purged.', + 'delete_data_title' => 'Delete data from Firefly III', + 'permanent_delete_stuff' => 'You can delete stuff from Firefly III. Using the buttons below means that your items will be removed from view and hidden. There is no undo-button for this, but the items may remain in the database where you can salvage them if necessary.', + 'other_sessions_logged_out' => 'All your other sessions have been logged out.', + 'delete_unused_accounts' => 'Deleting unused accounts will clean your auto-complete lists.', + 'delete_all_unused_accounts' => 'Delete unused accounts', + 'deleted_all_unused_accounts' => 'All unused accounts are deleted', + 'delete_all_budgets' => 'Delete ALL your budgets', + 'delete_all_categories' => 'Delete ALL your categories', + 'delete_all_tags' => 'Delete ALL your tags', + 'delete_all_bills' => 'Delete ALL your subscriptions', + 'delete_all_piggy_banks' => 'Delete ALL your piggy banks', + 'delete_all_rules' => 'Delete ALL your rules', + 'delete_all_recurring' => 'Delete ALL your recurring transactions', + 'delete_all_object_groups' => 'Delete ALL your object groups', + 'delete_all_accounts' => 'Delete ALL your accounts', + 'delete_all_asset_accounts' => 'Delete ALL your asset accounts', + 'delete_all_expense_accounts' => 'Delete ALL your expense accounts', + 'delete_all_revenue_accounts' => 'Delete ALL your revenue accounts', + 'delete_all_liabilities' => 'Delete ALL your liabilities', + 'delete_all_transactions' => 'Delete ALL your transactions', + 'delete_all_withdrawals' => 'Delete ALL your withdrawals', + 'delete_all_deposits' => 'Delete ALL your deposits', + 'delete_all_transfers' => 'Delete ALL your transfers', + 'also_delete_transactions' => 'Deleting accounts will also delete ALL associated withdrawals, deposits and transfers!', + 'deleted_all_budgets' => 'All budgets have been deleted', + 'deleted_all_categories' => 'All categories have been deleted', + 'deleted_all_tags' => 'All tags have been deleted', + 'deleted_all_bills' => 'All subscriptions have been deleted', + 'deleted_all_piggy_banks' => 'All piggy banks have been deleted', + 'deleted_all_rules' => 'All rules and rule groups have been deleted', + 'deleted_all_object_groups' => 'All groups have been deleted', + 'deleted_all_accounts' => 'All accounts have been deleted', + 'deleted_all_asset_accounts' => 'All asset accounts have been deleted', + 'deleted_all_expense_accounts' => 'All expense accounts have been deleted', + 'deleted_all_revenue_accounts' => 'All revenue accounts have been deleted', + 'deleted_all_liabilities' => 'All liabilities have been deleted', + 'deleted_all_transactions' => 'All transactions have been deleted', + 'deleted_all_withdrawals' => 'All withdrawals have been deleted', + 'deleted_all_deposits' => 'All deposits have been deleted', + 'deleted_all_transfers' => 'All transfers have been deleted', + 'deleted_all_recurring' => 'All recurring transactions have been deleted', + 'change_your_password' => 'Change your password', + 'delete_account' => 'Delete account', + 'current_password' => 'Current password', + 'new_password' => 'New password', + 'new_password_again' => 'New password (again)', + 'delete_your_account' => 'Delete your account', + 'delete_your_account_help' => 'Deleting your account will also delete any accounts, transactions, anything you might have saved into Firefly III. It\'ll be GONE.', + 'delete_your_account_password' => 'Enter your password to continue.', + 'password' => 'Password', + 'are_you_sure' => 'Are you sure? You cannot undo this.', + 'are_you_sure_confirm' => 'Are you sure?', + 'delete_account_button' => 'DELETE your account', + 'invalid_current_password' => 'Invalid current password!', + 'password_changed' => 'Password changed!', + 'should_change' => 'The idea is to change your password.', + 'invalid_password' => 'Invalid password!', + 'what_is_pw_security' => 'What is "verify password security"?', + 'secure_pw_title' => 'How to choose a secure password', + 'forgot_password_response' => 'Thank you. If an account exists with this email address, you will find instructions in your inbox.', + 'secure_pw_history' => 'Not a week goes by that you read in the news about a site losing the passwords of its users. Hackers and thieves use these passwords to try to steal your private information. This information is valuable.', + 'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.', + 'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.', + 'secure_pw_working_title' => 'How does it work?', + 'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to the website of Troy Hunt to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest NIST Special Publication on this subject.', + 'secure_pw_should' => 'Should I check the box?', + 'secure_pw_long_password' => 'Yes. Always verify your password is safe.', + 'command_line_token' => 'Command line token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as exporting data. Without it, that sensitive command will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Regenerate command line token', + 'token_regenerated' => 'A new command line token was generated', + 'change_your_email' => 'Change your email address', + 'email_verification' => 'An email message will be sent to your old AND new email address. For security purposes, you will not be able to login until you verify your new email address. If you are unsure if your Firefly III installation is capable of sending email, please do not use this feature. If you are an administrator, you can test this in the settings.', + 'email_changed_logout' => 'Until you verify your email address, you cannot login.', + 'login_with_new_email' => 'You can now login with your new email address.', + 'login_with_old_email' => 'You can now login with your old email address again.', + 'login_provider_local_only' => 'This action is not available when authenticating through ":login_provider".', + 'external_user_mgt_disabled' => 'This action is not available when Firefly III isn\'t responsible for user management or authentication handling.', + 'external_auth_disabled' => 'This action is not available when Firefly III isn\'t responsible for authentication handling.', + 'delete_local_info_only' => "Because Firefly III isn't responsible for user management or authentication handling, this function will only delete local Firefly III information.", + 'oauth' => 'OAuth', + 'profile_oauth_clients' => 'OAuth Clients', + 'profile_oauth_no_clients' => 'You have not created any OAuth clients.', + 'profile_oauth_clients_external_auth' => 'If you\'re using an external authentication provider like Authelia, OAuth Clients will not work. You can use Personal Access Tokens only.', + 'profile_oauth_clients_header' => 'Clients', + 'profile_oauth_client_id' => 'Client ID', + 'profile_oauth_client_name' => 'Name', + 'profile_oauth_client_secret' => 'Secret', + 'profile_oauth_create_new_client' => 'Create New Client', + 'profile_oauth_create_client' => 'Create Client', + 'profile_oauth_edit_client' => 'Edit Client', + 'profile_oauth_name_help' => 'Something your users will recognize and trust.', + 'profile_oauth_redirect_url' => 'Redirect URL', + 'profile_oauth_redirect_url_help' => 'Your application\'s authorization callback URL.', + 'profile_authorized_apps' => 'Authorized applications', + 'profile_authorized_clients' => 'Authorized clients', + 'profile_scopes' => 'Scopes', + 'profile_revoke' => 'Revoke', + 'profile_oauth_client_secret_title' => 'Client Secret', + 'profile_oauth_client_secret_expl' => 'Here is your new client secret. This is the only time it will be shown so don\'t lose it! You may now use this secret to make API requests.', + 'profile_personal_access_tokens' => 'Personal Access Tokens', + 'profile_personal_access_token' => 'Personal Access Token', + 'profile_oauth_confidential' => 'Confidential', + 'profile_oauth_confidential_help' => 'Require the client to authenticate with a secret. Confidential clients can hold credentials in a secure way without exposing them to unauthorized parties. Public applications, such as native desktop or JavaScript SPA applications, are unable to hold secrets securely.', + 'profile_personal_access_token_explanation' => 'Here is your new personal access token. This is the only time it will be shown so don\'t lose it! You may now use this token to make API requests.', + 'profile_no_personal_access_token' => 'You have not created any personal access tokens.', + 'profile_create_new_token' => 'Create new token', + 'profile_create_token' => 'Create token', + 'profile_create' => 'Create', + 'profile_save_changes' => 'Save changes', + 'profile_whoops' => 'Whoops!', + 'profile_something_wrong' => 'Something went wrong!', + 'profile_try_again' => 'Something went wrong. Please try again.', + 'amounts' => 'Amounts', + 'multi_account_warning_unknown' => 'Depending on the type of transaction you create, the source and/or destination account of subsequent splits may be overruled by whatever is defined in the first split of the transaction.', + 'multi_account_warning_withdrawal' => 'Keep in mind that the source account of subsequent splits will be overruled by whatever is defined in the first split of the withdrawal.', + 'multi_account_warning_deposit' => 'Keep in mind that the destination account of subsequent splits will be overruled by whatever is defined in the first split of the deposit.', + 'multi_account_warning_transfer' => 'Keep in mind that the source + destination account of subsequent splits will be overruled by whatever is defined in the first split of the transfer.', // export data: - 'export_data_title' => 'Export data from Firefly III', - 'export_data_menu' => 'Export data', - 'export_data_bc' => 'Export data from Firefly III', - 'export_data_main_title' => 'Export data from Firefly III', - 'export_data_expl' => 'This link allows you to export all transactions + meta data from Firefly III. Please refer to the help (top right (?)-icon) for more information about the process.', - 'export_data_all_transactions' => 'Export all transactions', - 'export_data_advanced_expl' => 'If you need a more advanced or specific type of export, read the help on how to use the console command php artisan help firefly-iii:export-data.', + 'export_data_title' => 'Export data from Firefly III', + 'export_data_menu' => 'Export data', + 'export_data_bc' => 'Export data from Firefly III', + 'export_data_main_title' => 'Export data from Firefly III', + 'export_data_expl' => 'This link allows you to export all transactions + meta data from Firefly III. Please refer to the help (top right (?)-icon) for more information about the process.', + 'export_data_all_transactions' => 'Export all transactions', + 'export_data_advanced_expl' => 'If you need a more advanced or specific type of export, read the help on how to use the console command php artisan help firefly-iii:export-data.', // attachments - 'nr_of_attachments' => 'One attachment|:count attachments', - 'attachments' => 'Attachments', - 'edit_attachment' => 'Edit attachment ":name"', - 'update_attachment' => 'Update attachment', - 'delete_attachment' => 'Delete attachment ":name"', - 'attachment_deleted' => 'Deleted attachment ":name"', - 'liabilities_deleted' => 'Deleted liability ":name"', - 'attachment_updated' => 'Updated attachment ":name"', - 'upload_max_file_size' => 'Maximum file size: :size', - 'list_all_attachments' => 'List of all attachments', + 'nr_of_attachments' => 'One attachment|:count attachments', + 'attachments' => 'Attachments', + 'edit_attachment' => 'Edit attachment ":name"', + 'update_attachment' => 'Update attachment', + 'delete_attachment' => 'Delete attachment ":name"', + 'attachment_deleted' => 'Deleted attachment ":name"', + 'liabilities_deleted' => 'Deleted liability ":name"', + 'attachment_updated' => 'Updated attachment ":name"', + 'upload_max_file_size' => 'Maximum file size: :size', + 'list_all_attachments' => 'List of all attachments', // transaction index - 'is_reconciled_fields_dropped' => 'Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.', - 'is_reconciled' => 'Is reconciled', - 'title_expenses' => 'Expenses', - 'title_withdrawal' => 'Expenses', - 'title_revenue' => 'Revenue / income', - 'title_deposit' => 'Revenue / income', - 'title_transfer' => 'Transfers', - 'title_transfers' => 'Transfers', - 'submission_options' => 'Submission options', - 'apply_rules_checkbox' => 'Apply rules', - 'fire_webhooks_checkbox' => 'Fire webhooks', - 'select_source_account' => 'Please select or type a valid source account name', - 'select_dest_account' => 'Please select or type a valid destination account name', + 'is_reconciled_fields_dropped' => 'Because this transaction is reconciled, you will not be able to update the accounts, nor the amount(s) unless you remove the reconciliation flag.', + 'is_reconciled' => 'Is reconciled', + 'title_expenses' => 'Expenses', + 'title_withdrawal' => 'Expenses', + 'title_revenue' => 'Revenue / income', + 'title_deposit' => 'Revenue / income', + 'title_transfer' => 'Transfers', + 'title_transfers' => 'Transfers', + 'submission_options' => 'Submission options', + 'apply_rules_checkbox' => 'Apply rules', + 'fire_webhooks_checkbox' => 'Fire webhooks', + 'select_source_account' => 'Please select or type a valid source account name', + 'select_dest_account' => 'Please select or type a valid destination account name', // convert stuff: - 'convert_is_already_type_Withdrawal' => 'This transaction is already a withdrawal', - 'convert_is_already_type_Deposit' => 'This transaction is already a deposit', - 'convert_is_already_type_Transfer' => 'This transaction is already a transfer', - 'convert_to_Withdrawal' => 'Convert ":description" to a withdrawal', - 'convert_to_Deposit' => 'Convert ":description" to a deposit', - 'convert_to_Transfer' => 'Convert ":description" to a transfer', - 'convert_options_WithdrawalDeposit' => 'Convert a withdrawal into a deposit', - 'convert_options_WithdrawalTransfer' => 'Convert a withdrawal into a transfer', - 'convert_options_DepositTransfer' => 'Convert a deposit into a transfer', - 'convert_options_DepositWithdrawal' => 'Convert a deposit into a withdrawal', - 'convert_options_TransferWithdrawal' => 'Convert a transfer into a withdrawal', - 'convert_options_TransferDeposit' => 'Convert a transfer into a deposit', - 'convert_Withdrawal_to_deposit' => 'Convert this withdrawal to a deposit', - 'convert_Withdrawal_to_transfer' => 'Convert this withdrawal to a transfer', - 'convert_Deposit_to_withdrawal' => 'Convert this deposit to a withdrawal', - 'convert_Deposit_to_transfer' => 'Convert this deposit to a transfer', - 'convert_Transfer_to_deposit' => 'Convert this transfer to a deposit', - 'convert_Transfer_to_withdrawal' => 'Convert this transfer to a withdrawal', - 'convert_please_set_revenue_source' => 'Please pick the revenue account where the money will come from.', - 'convert_please_set_asset_destination' => 'Please pick the asset account where the money will go to.', - 'convert_please_set_expense_destination' => 'Please pick the expense account where the money will go to.', - 'convert_please_set_asset_source' => 'Please pick the asset account where the money will come from.', - 'convert_expl_w_d' => 'When converting from a withdrawal to a deposit, the money will be deposited into the displayed destination account, instead of being withdrawn from it.|When converting from a withdrawal to a deposit, the money will be deposited into the displayed destination accounts, instead of being withdrawn from them.', - 'convert_expl_w_t' => 'When converting a withdrawal into a transfer, the money will be transferred away from the source account into other asset or liability account instead of being spent on the original expense account.|When converting a withdrawal into a transfer, the money will be transferred away from the source accounts into other asset or liability accounts instead of being spent on the original expense accounts.', - 'convert_expl_d_w' => 'When converting a deposit into a withdrawal, the money will be withdrawn from the displayed source account, instead of being deposited into it.|When converting a deposit into a withdrawal, the money will be withdrawn from the displayed source accounts, instead of being deposited into them.', - 'convert_expl_d_t' => 'When you convert a deposit into a transfer, the money will be deposited into the listed destination account from any of your asset or liability account.|When you convert a deposit into a transfer, the money will be deposited into the listed destination accounts from any of your asset or liability accounts.', - 'convert_expl_t_w' => 'When you convert a transfer into a withdrawal, the money will be spent on the destination account you set here, instead of being transferred away.|When you convert a transfer into a withdrawal, the money will be spent on the destination accounts you set here, instead of being transferred away.', - 'convert_expl_t_d' => 'When you convert a transfer into a deposit, the money will be deposited into the destination account you see here, instead of being transferred into it.|When you convert a transfer into a deposit, the money will be deposited into the destination accounts you see here, instead of being transferred into them.', - 'convert_select_sources' => 'To complete the conversion, please set the new source account below.|To complete the conversion, please set the new source accounts below.', - 'convert_select_destinations' => 'To complete the conversion, please select the new destination account below.|To complete the conversion, please select the new destination accounts below.', - 'converted_to_Withdrawal' => 'The transaction has been converted to a withdrawal', - 'converted_to_Deposit' => 'The transaction has been converted to a deposit', - 'converted_to_Transfer' => 'The transaction has been converted to a transfer', - 'invalid_convert_selection' => 'The account you have selected is already used in this transaction or does not exist.', - 'source_or_dest_invalid' => 'Cannot find the correct transaction details. Conversion is not possible.', - 'convert_to_withdrawal' => 'Convert to a withdrawal', - 'convert_to_deposit' => 'Convert to a deposit', - 'convert_to_transfer' => 'Convert to a transfer', + 'convert_is_already_type_Withdrawal' => 'This transaction is already a withdrawal', + 'convert_is_already_type_Deposit' => 'This transaction is already a deposit', + 'convert_is_already_type_Transfer' => 'This transaction is already a transfer', + 'convert_to_Withdrawal' => 'Convert ":description" to a withdrawal', + 'convert_to_Deposit' => 'Convert ":description" to a deposit', + 'convert_to_Transfer' => 'Convert ":description" to a transfer', + 'convert_options_WithdrawalDeposit' => 'Convert a withdrawal into a deposit', + 'convert_options_WithdrawalTransfer' => 'Convert a withdrawal into a transfer', + 'convert_options_DepositTransfer' => 'Convert a deposit into a transfer', + 'convert_options_DepositWithdrawal' => 'Convert a deposit into a withdrawal', + 'convert_options_TransferWithdrawal' => 'Convert a transfer into a withdrawal', + 'convert_options_TransferDeposit' => 'Convert a transfer into a deposit', + 'convert_Withdrawal_to_deposit' => 'Convert this withdrawal to a deposit', + 'convert_Withdrawal_to_transfer' => 'Convert this withdrawal to a transfer', + 'convert_Deposit_to_withdrawal' => 'Convert this deposit to a withdrawal', + 'convert_Deposit_to_transfer' => 'Convert this deposit to a transfer', + 'convert_Transfer_to_deposit' => 'Convert this transfer to a deposit', + 'convert_Transfer_to_withdrawal' => 'Convert this transfer to a withdrawal', + 'convert_please_set_revenue_source' => 'Please pick the revenue account where the money will come from.', + 'convert_please_set_asset_destination' => 'Please pick the asset account where the money will go to.', + 'convert_please_set_expense_destination' => 'Please pick the expense account where the money will go to.', + 'convert_please_set_asset_source' => 'Please pick the asset account where the money will come from.', + 'convert_expl_w_d' => 'When converting from a withdrawal to a deposit, the money will be deposited into the displayed destination account, instead of being withdrawn from it.|When converting from a withdrawal to a deposit, the money will be deposited into the displayed destination accounts, instead of being withdrawn from them.', + 'convert_expl_w_t' => 'When converting a withdrawal into a transfer, the money will be transferred away from the source account into other asset or liability account instead of being spent on the original expense account.|When converting a withdrawal into a transfer, the money will be transferred away from the source accounts into other asset or liability accounts instead of being spent on the original expense accounts.', + 'convert_expl_d_w' => 'When converting a deposit into a withdrawal, the money will be withdrawn from the displayed source account, instead of being deposited into it.|When converting a deposit into a withdrawal, the money will be withdrawn from the displayed source accounts, instead of being deposited into them.', + 'convert_expl_d_t' => 'When you convert a deposit into a transfer, the money will be deposited into the listed destination account from any of your asset or liability account.|When you convert a deposit into a transfer, the money will be deposited into the listed destination accounts from any of your asset or liability accounts.', + 'convert_expl_t_w' => 'When you convert a transfer into a withdrawal, the money will be spent on the destination account you set here, instead of being transferred away.|When you convert a transfer into a withdrawal, the money will be spent on the destination accounts you set here, instead of being transferred away.', + 'convert_expl_t_d' => 'When you convert a transfer into a deposit, the money will be deposited into the destination account you see here, instead of being transferred into it.|When you convert a transfer into a deposit, the money will be deposited into the destination accounts you see here, instead of being transferred into them.', + 'convert_select_sources' => 'To complete the conversion, please set the new source account below.|To complete the conversion, please set the new source accounts below.', + 'convert_select_destinations' => 'To complete the conversion, please select the new destination account below.|To complete the conversion, please select the new destination accounts below.', + 'converted_to_Withdrawal' => 'The transaction has been converted to a withdrawal', + 'converted_to_Deposit' => 'The transaction has been converted to a deposit', + 'converted_to_Transfer' => 'The transaction has been converted to a transfer', + 'invalid_convert_selection' => 'The account you have selected is already used in this transaction or does not exist.', + 'source_or_dest_invalid' => 'Cannot find the correct transaction details. Conversion is not possible.', + 'convert_to_withdrawal' => 'Convert to a withdrawal', + 'convert_to_deposit' => 'Convert to a deposit', + 'convert_to_transfer' => 'Convert to a transfer', // create new stuff: - 'create_new_withdrawal' => 'Create new withdrawal', - 'create_new_deposit' => 'Create new deposit', - 'create_new_transfer' => 'Create new transfer', - 'create_new_asset' => 'Create new asset account', - 'create_new_liabilities' => 'Create new liability', - 'create_new_expense' => 'Create new expense account', - 'create_new_revenue' => 'Create new revenue account', - 'create_new_piggy_bank' => 'Create new piggy bank', - 'create_new_bill' => 'Create new subscription', - 'create_new_subscription' => 'Create new subscription', - 'create_new_rule' => 'Create new rule', + 'create_new_withdrawal' => 'Create new withdrawal', + 'create_new_deposit' => 'Create new deposit', + 'create_new_transfer' => 'Create new transfer', + 'create_new_asset' => 'Create new asset account', + 'create_new_liabilities' => 'Create new liability', + 'create_new_expense' => 'Create new expense account', + 'create_new_revenue' => 'Create new revenue account', + 'create_new_piggy_bank' => 'Create new piggy bank', + 'create_new_bill' => 'Create new subscription', + 'create_new_subscription' => 'Create new subscription', + 'create_new_rule' => 'Create new rule', // currencies: - 'create_currency' => 'Create a new currency', - 'store_currency' => 'Store new currency', - 'update_currency' => 'Update currency', - 'new_default_currency' => '":name" is now the default currency.', - 'default_currency_failed' => 'Could not make ":name" the default currency. Please check the logs.', - 'cannot_delete_currency' => 'Cannot delete :name because it is still in use.', - 'cannot_delete_fallback_currency' => ':name is the system fallback currency and can\'t be deleted.', - 'cannot_disable_currency_journals' => 'Cannot disable :name because transactions are still using it.', - 'cannot_disable_currency_last_left' => 'Cannot disable :name because it is the last enabled currency.', - 'cannot_disable_currency_account_meta' => 'Cannot disable :name because it is used in asset accounts.', - 'cannot_disable_currency_bills' => 'Cannot disable :name because it is used in subscriptions.', - 'cannot_disable_currency_recurring' => 'Cannot disable :name because it is used in recurring transactions.', - 'cannot_disable_currency_available_budgets' => 'Cannot disable :name because it is used in available budgets.', - 'cannot_disable_currency_budget_limits' => 'Cannot disable :name because it is used in budget limits.', - 'cannot_disable_currency_current_default' => 'Cannot disable :name because it is the current default currency.', - 'cannot_disable_currency_system_fallback' => 'Cannot disable :name because it is the system default currency.', - 'disable_EUR_side_effects' => 'The Euro is the system\'s emergency fallback currency. Disabling it may have unintended side-effects and may void your warranty.', - 'deleted_currency' => 'Currency :name deleted', - 'created_currency' => 'Currency :name created', - 'could_not_store_currency' => 'Could not store the new currency.', - 'updated_currency' => 'Currency :name updated', - 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.', - 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.', - 'currencies_switch_default' => 'You can switch the native currency for your current administration on the "Financial administrations"-page.', - 'make_default_currency' => 'Make default', - 'default_currency' => 'default', - 'native_currency_button' => 'native', - 'currency_is_disabled' => 'Disabled', - 'enable_currency' => 'Enable', - 'disable_currency' => 'Disable', - 'currencies_default_disabled' => 'Most of these currencies are disabled by default. To use them, you must enable them first.', - 'currency_is_now_enabled' => 'Currency ":name" has been enabled', - 'could_not_enable_currency' => 'Could not enable currency ":name". Please review the logs.', - 'currency_is_now_disabled' => 'Currency ":name" has been disabled', - 'could_not_disable_currency' => 'Could not disable currency ":name". Perhaps it is still in use?', + 'create_currency' => 'Create a new currency', + 'store_currency' => 'Store new currency', + 'update_currency' => 'Update currency', + 'new_default_currency' => '":name" is now the default currency.', + 'default_currency_failed' => 'Could not make ":name" the default currency. Please check the logs.', + 'cannot_delete_currency' => 'Cannot delete :name because it is still in use.', + 'cannot_delete_fallback_currency' => ':name is the system fallback currency and can\'t be deleted.', + 'cannot_disable_currency_journals' => 'Cannot disable :name because transactions are still using it.', + 'cannot_disable_currency_last_left' => 'Cannot disable :name because it is the last enabled currency.', + 'cannot_disable_currency_account_meta' => 'Cannot disable :name because it is used in asset accounts.', + 'cannot_disable_currency_bills' => 'Cannot disable :name because it is used in subscriptions.', + 'cannot_disable_currency_recurring' => 'Cannot disable :name because it is used in recurring transactions.', + 'cannot_disable_currency_available_budgets' => 'Cannot disable :name because it is used in available budgets.', + 'cannot_disable_currency_budget_limits' => 'Cannot disable :name because it is used in budget limits.', + 'cannot_disable_currency_current_default' => 'Cannot disable :name because it is the current default currency.', + 'cannot_disable_currency_system_fallback' => 'Cannot disable :name because it is the system default currency.', + 'disable_EUR_side_effects' => 'The Euro is the system\'s emergency fallback currency. Disabling it may have unintended side-effects and may void your warranty.', + 'deleted_currency' => 'Currency :name deleted', + 'created_currency' => 'Currency :name created', + 'could_not_store_currency' => 'Could not store the new currency.', + 'updated_currency' => 'Currency :name updated', + 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.', + 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.', + 'currencies_switch_default' => 'You can switch the native currency for your current administration on the "Financial administrations"-page.', + 'make_default_currency' => 'Make default', + 'default_currency' => 'default', + 'native_currency_button' => 'native', + 'currency_is_disabled' => 'Disabled', + 'enable_currency' => 'Enable', + 'disable_currency' => 'Disable', + 'currencies_default_disabled' => 'Most of these currencies are disabled by default. To use them, you must enable them first.', + 'currency_is_now_enabled' => 'Currency ":name" has been enabled', + 'could_not_enable_currency' => 'Could not enable currency ":name". Please review the logs.', + 'currency_is_now_disabled' => 'Currency ":name" has been disabled', + 'could_not_disable_currency' => 'Could not disable currency ":name". Perhaps it is still in use?', // forms: - 'mandatoryFields' => 'Mandatory fields', - 'optionalFields' => 'Optional fields', - 'options' => 'Options', + 'mandatoryFields' => 'Mandatory fields', + 'optionalFields' => 'Optional fields', + 'options' => 'Options', // budgets: - 'daily_budgets' => 'Daily budgets', - 'weekly_budgets' => 'Weekly budgets', - 'monthly_budgets' => 'Monthly budgets', - 'quarterly_budgets' => 'Quarterly budgets', - 'half_year_budgets' => 'Half-yearly budgets', - 'yearly_budgets' => 'Yearly budgets', - 'other_budgets' => 'Custom timed budgets', - 'budget_limit_not_in_range' => 'This amount applies from :start to :end:', - 'total_available_budget' => 'Total available budget (between :start and :end)', - 'total_available_budget_in_currency' => 'Total available budget in :currency', - 'see_below' => 'see below', - 'create_new_budget' => 'Create a new budget', - 'store_new_budget' => 'Store new budget', - 'stored_new_budget' => 'Stored new budget ":name"', - 'available_between' => 'Available between :start and :end', - 'transactionsWithoutBudget' => 'Expenses without budget', - 'transactions_no_budget' => 'Expenses without budget between :start and :end', - 'spent_between' => 'Already spent between :start and :end', - 'spent_between_left' => 'Spent :spent between :start and :end, leaving :left.', - 'set_available_amount' => 'Set available amount', - 'update_available_amount' => 'Update available amount', - 'ab_basic_modal_explain' => 'Use this form to indicate how much you expect to be able to budget (in total, in :currency) in the indicated period.', - 'createBudget' => 'New budget', - 'invalid_currency' => 'This is an invalid currency', - 'invalid_amount' => 'Please enter an amount', - 'set_ab' => 'The available budget amount has been set', - 'updated_ab' => 'The available budget amount has been updated', - 'deleted_ab' => 'The available budget amount has been deleted', - 'deleted_bl' => 'The budgeted amount has been removed', - 'alt_currency_ab_create' => 'Set the available budget in another currency', - 'bl_create_btn' => 'Set budget in another currency', - 'inactiveBudgets' => 'Inactive budgets', - 'without_budget_between' => 'Transactions without a budget between :start and :end', - 'delete_budget' => 'Delete budget ":name"', - 'deleted_budget' => 'Deleted budget ":name"', - 'edit_budget' => 'Edit budget ":name"', - 'updated_budget' => 'Updated budget ":name"', - 'update_amount' => 'Update amount', - 'update_budget' => 'Update budget', - 'update_budget_amount_range' => 'Update (expected) available amount between :start and :end', - 'set_budget_limit_title' => 'Set budgeted amount for budget :budget between :start and :end', - 'set_budget_limit' => 'Set budgeted amount', - 'budget_period_navigator' => 'Period navigator', - 'info_on_available_amount' => 'What do I have available?', - 'available_amount_indication' => 'Use these amounts to get an indication of what your total budget could be.', - 'suggested' => 'Suggested', - 'average_between' => 'Average between :start and :end', - 'transferred_in' => 'Transferred (in)', - 'transferred_away' => 'Transferred (away)', - 'auto_budget_none' => 'No auto-budget', - 'auto_budget_reset' => 'Set a fixed amount every period', - 'auto_budget_rollover' => 'Add an amount every period', - 'auto_budget_adjusted' => 'Add an amount every period and correct for overspending', - 'auto_budget_period_daily' => 'Daily', - 'auto_budget_period_weekly' => 'Weekly', - 'auto_budget_period_monthly' => 'Monthly', - 'auto_budget_period_quarterly' => 'Quarterly', - 'auto_budget_period_half_year' => 'Every half year', - 'auto_budget_period_yearly' => 'Yearly', - 'auto_budget_help' => 'You can read more about this feature in the help. Click the top-right (?) icon.', - 'auto_budget_reset_icon' => 'This budget will be set periodically', - 'auto_budget_rollover_icon' => 'The budget amount will increase periodically', - 'auto_budget_adjusted_icon' => 'The budget amount will increase periodically and will correct for overspending', - 'remove_budgeted_amount' => 'Remove budgeted amount in :currency', + 'daily_budgets' => 'Daily budgets', + 'weekly_budgets' => 'Weekly budgets', + 'monthly_budgets' => 'Monthly budgets', + 'quarterly_budgets' => 'Quarterly budgets', + 'half_year_budgets' => 'Half-yearly budgets', + 'yearly_budgets' => 'Yearly budgets', + 'other_budgets' => 'Custom timed budgets', + 'budget_limit_not_in_range' => 'This amount applies from :start to :end:', + 'total_available_budget' => 'Total available budget (between :start and :end)', + 'total_available_budget_in_currency' => 'Total available budget in :currency', + 'see_below' => 'see below', + 'create_new_budget' => 'Create a new budget', + 'store_new_budget' => 'Store new budget', + 'stored_new_budget' => 'Stored new budget ":name"', + 'available_between' => 'Available between :start and :end', + 'transactionsWithoutBudget' => 'Expenses without budget', + 'transactions_no_budget' => 'Expenses without budget between :start and :end', + 'spent_between' => 'Already spent between :start and :end', + 'spent_between_left' => 'Spent :spent between :start and :end, leaving :left.', + 'set_available_amount' => 'Set available amount', + 'update_available_amount' => 'Update available amount', + 'ab_basic_modal_explain' => 'Use this form to indicate how much you expect to be able to budget (in total, in :currency) in the indicated period.', + 'createBudget' => 'New budget', + 'invalid_currency' => 'This is an invalid currency', + 'invalid_amount' => 'Please enter an amount', + 'set_ab' => 'The available budget amount has been set', + 'updated_ab' => 'The available budget amount has been updated', + 'deleted_ab' => 'The available budget amount has been deleted', + 'deleted_bl' => 'The budgeted amount has been removed', + 'alt_currency_ab_create' => 'Set the available budget in another currency', + 'bl_create_btn' => 'Set budget in another currency', + 'inactiveBudgets' => 'Inactive budgets', + 'without_budget_between' => 'Transactions without a budget between :start and :end', + 'delete_budget' => 'Delete budget ":name"', + 'deleted_budget' => 'Deleted budget ":name"', + 'edit_budget' => 'Edit budget ":name"', + 'updated_budget' => 'Updated budget ":name"', + 'update_amount' => 'Update amount', + 'update_budget' => 'Update budget', + 'update_budget_amount_range' => 'Update (expected) available amount between :start and :end', + 'set_budget_limit_title' => 'Set budgeted amount for budget :budget between :start and :end', + 'set_budget_limit' => 'Set budgeted amount', + 'budget_period_navigator' => 'Period navigator', + 'info_on_available_amount' => 'What do I have available?', + 'available_amount_indication' => 'Use these amounts to get an indication of what your total budget could be.', + 'suggested' => 'Suggested', + 'average_between' => 'Average between :start and :end', + 'transferred_in' => 'Transferred (in)', + 'transferred_away' => 'Transferred (away)', + 'auto_budget_none' => 'No auto-budget', + 'auto_budget_reset' => 'Set a fixed amount every period', + 'auto_budget_rollover' => 'Add an amount every period', + 'auto_budget_adjusted' => 'Add an amount every period and correct for overspending', + 'auto_budget_period_daily' => 'Daily', + 'auto_budget_period_weekly' => 'Weekly', + 'auto_budget_period_monthly' => 'Monthly', + 'auto_budget_period_quarterly' => 'Quarterly', + 'auto_budget_period_half_year' => 'Every half year', + 'auto_budget_period_yearly' => 'Yearly', + 'auto_budget_help' => 'You can read more about this feature in the help. Click the top-right (?) icon.', + 'auto_budget_reset_icon' => 'This budget will be set periodically', + 'auto_budget_rollover_icon' => 'The budget amount will increase periodically', + 'auto_budget_adjusted_icon' => 'The budget amount will increase periodically and will correct for overspending', + 'remove_budgeted_amount' => 'Remove budgeted amount in :currency', // bills: - 'skip_help_text' => 'Use the skip field to create bi-monthly (skip = 1) or other custom intervals.', - 'subscription' => 'Subscription', - 'not_expected_period' => 'Not expected this period', - 'subscriptions_in_group' => 'Subscriptions in group "%{title}"', - 'subscr_expected_x_times' => 'Expect to pay %{amount} %{times} times this period', - 'not_or_not_yet' => 'Not (yet)', - 'visit_bill' => 'Visit subscription ":name" at Firefly III', - 'match_between_amounts' => 'Subscription matches transactions between :low and :high.', - 'running_again_loss' => 'Previously linked transactions to this subscription may lose their connection, if they (no longer) match the rule(s).', - 'bill_related_rules' => 'Rules related to this subscription', - 'repeats' => 'Repeats', - 'bill_end_date_help' => 'Optional field. The subscription is expected to end on this date.', - 'bill_extension_date_help' => 'Optional field. The subscription must be extended (or cancelled) on or before this date.', - 'bill_end_index_line' => 'This subscription ends on :date', - 'bill_extension_index_line' => 'This subscription must be extended or cancelled on :date', - 'connected_journals' => 'Connected transactions', - 'auto_match_on' => 'Automatically matched by Firefly III', - 'auto_match_off' => 'Not automatically matched by Firefly III', - 'next_expected_match' => 'Next expected match', - 'delete_bill' => 'Delete subscription ":name"', - 'deleted_bill' => 'Deleted subscription ":name"', - 'edit_bill' => 'Edit subscription ":name"', - 'more' => 'More', - 'rescan_old' => 'Run rules again, on all transactions', - 'update_bill' => 'Update subscription', - 'updated_bill' => 'Updated subscription ":name"', - 'store_new_bill' => 'Store new subscription', - 'stored_new_bill' => 'Stored new subscription ":name"', - 'cannot_scan_inactive_bill' => 'Inactive subscriptions cannot be scanned.', - 'rescanned_bill' => 'Rescanned everything, and linked :count transaction to the subscription.|Rescanned everything, and linked :count transactions to the subscription.', - 'average_bill_amount_year' => 'Average subscription amount (:year)', - 'average_bill_amount_overall' => 'Average subscription amount (overall)', - 'bill_is_active' => 'Subscription is active', - 'bill_expected_between' => 'Expected between :start and :end', - 'bill_will_automatch' => 'Subscription will automatically linked to matching transactions', - 'skips_over' => 'skips over', - 'bill_store_error' => 'An unexpected error occurred while storing your new subscription. Please check the log files', - 'list_inactive_rule' => 'inactive rule', - 'bill_edit_rules' => 'Firefly III will attempt to edit the rule related to this subscription as well. If you\'ve edited this rule yourself however, Firefly III won\'t change anything.|Firefly III will attempt to edit the :count rules related to this subscription as well. If you\'ve edited these rules yourself however, Firefly III won\'t change anything.', - 'bill_expected_date' => 'Expected :date', - 'bill_expected_date_js' => 'Expected {date}', - 'expected_amount' => '(Expected) amount', - 'bill_paid_on' => 'Paid on {date}', - 'bill_repeats_weekly' => 'Repeats weekly', - 'bill_repeats_monthly' => 'Repeats monthly', - 'bill_repeats_quarterly' => 'Repeats quarterly', - 'bill_repeats_half-year' => 'Repeats every half year', - 'bill_repeats_yearly' => 'Repeats yearly', - 'bill_repeats_weekly_other' => 'Repeats every other week', - 'bill_repeats_monthly_other' => 'Repeats every other month', - 'bill_repeats_quarterly_other' => 'Repeats every other quarter', - 'bill_repeats_half-year_other' => 'Repeats yearly', - 'bill_repeats_yearly_other' => 'Repeats every other year', - 'bill_repeats_weekly_skip' => 'Repeats every {skip} weeks', - 'bill_repeats_monthly_skip' => 'Repeats every {skip} months', - 'bill_repeats_quarterly_skip' => 'Repeats every {skip} quarters', - 'bill_repeats_half-year_skip' => 'Repeats every {skip} half years', - 'bill_repeats_yearly_skip' => 'Repeats every {skip} years', - 'subscriptions' => 'Subscriptions', - 'go_to_subscriptions' => 'Go to your subscriptions', - 'forever' => 'Forever', - 'extension_date_is' => 'Extension date is {date}', + 'skip_help_text' => 'Use the skip field to create bi-monthly (skip = 1) or other custom intervals.', + 'subscription' => 'Subscription', + 'not_expected_period' => 'Not expected this period', + 'subscriptions_in_group' => 'Subscriptions in group "%{title}"', + 'subscr_expected_x_times' => 'Expect to pay %{amount} %{times} times this period', + 'not_or_not_yet' => 'Not (yet)', + 'visit_bill' => 'Visit subscription ":name" at Firefly III', + 'match_between_amounts' => 'Subscription matches transactions between :low and :high.', + 'running_again_loss' => 'Previously linked transactions to this subscription may lose their connection, if they (no longer) match the rule(s).', + 'bill_related_rules' => 'Rules related to this subscription', + 'repeats' => 'Repeats', + 'bill_end_date_help' => 'Optional field. The subscription is expected to end on this date.', + 'bill_extension_date_help' => 'Optional field. The subscription must be extended (or cancelled) on or before this date.', + 'bill_end_index_line' => 'This subscription ends on :date', + 'bill_extension_index_line' => 'This subscription must be extended or cancelled on :date', + 'connected_journals' => 'Connected transactions', + 'auto_match_on' => 'Automatically matched by Firefly III', + 'auto_match_off' => 'Not automatically matched by Firefly III', + 'next_expected_match' => 'Next expected match', + 'delete_bill' => 'Delete subscription ":name"', + 'deleted_bill' => 'Deleted subscription ":name"', + 'edit_bill' => 'Edit subscription ":name"', + 'more' => 'More', + 'rescan_old' => 'Run rules again, on all transactions', + 'update_bill' => 'Update subscription', + 'updated_bill' => 'Updated subscription ":name"', + 'store_new_bill' => 'Store new subscription', + 'stored_new_bill' => 'Stored new subscription ":name"', + 'cannot_scan_inactive_bill' => 'Inactive subscriptions cannot be scanned.', + 'rescanned_bill' => 'Rescanned everything, and linked :count transaction to the subscription.|Rescanned everything, and linked :count transactions to the subscription.', + 'average_bill_amount_year' => 'Average subscription amount (:year)', + 'average_bill_amount_overall' => 'Average subscription amount (overall)', + 'bill_is_active' => 'Subscription is active', + 'bill_expected_between' => 'Expected between :start and :end', + 'bill_will_automatch' => 'Subscription will automatically linked to matching transactions', + 'skips_over' => 'skips over', + 'bill_store_error' => 'An unexpected error occurred while storing your new subscription. Please check the log files', + 'list_inactive_rule' => 'inactive rule', + 'bill_edit_rules' => 'Firefly III will attempt to edit the rule related to this subscription as well. If you\'ve edited this rule yourself however, Firefly III won\'t change anything.|Firefly III will attempt to edit the :count rules related to this subscription as well. If you\'ve edited these rules yourself however, Firefly III won\'t change anything.', + 'bill_expected_date' => 'Expected :date', + 'bill_expected_date_js' => 'Expected {date}', + 'expected_amount' => '(Expected) amount', + 'bill_paid_on' => 'Paid on {date}', + 'bill_repeats_weekly' => 'Repeats weekly', + 'bill_repeats_monthly' => 'Repeats monthly', + 'bill_repeats_quarterly' => 'Repeats quarterly', + 'bill_repeats_half-year' => 'Repeats every half year', + 'bill_repeats_yearly' => 'Repeats yearly', + 'bill_repeats_weekly_other' => 'Repeats every other week', + 'bill_repeats_monthly_other' => 'Repeats every other month', + 'bill_repeats_quarterly_other' => 'Repeats every other quarter', + 'bill_repeats_half-year_other' => 'Repeats yearly', + 'bill_repeats_yearly_other' => 'Repeats every other year', + 'bill_repeats_weekly_skip' => 'Repeats every {skip} weeks', + 'bill_repeats_monthly_skip' => 'Repeats every {skip} months', + 'bill_repeats_quarterly_skip' => 'Repeats every {skip} quarters', + 'bill_repeats_half-year_skip' => 'Repeats every {skip} half years', + 'bill_repeats_yearly_skip' => 'Repeats every {skip} years', + 'subscriptions' => 'Subscriptions', + 'go_to_subscriptions' => 'Go to your subscriptions', + 'forever' => 'Forever', + 'extension_date_is' => 'Extension date is {date}', // accounts: - 'account_locked_currency' => 'The currency of this account must remain :name as long as piggy banks are linked to it.', - 'i_am_owed_amount' => 'I am owed amount', - 'i_owe_amount' => 'I owe amount', - 'inactive_account_link' => 'You have :count inactive (archived) account, which you can view on this separate page.|You have :count inactive (archived) accounts, which you can view on this separate page.', - 'all_accounts_inactive' => 'These are your inactive accounts.', - 'active_account_link' => 'This link goes back to your active accounts.', - 'account_missing_transaction' => 'Account #:id (":name") cannot be viewed directly, but Firefly is missing redirect information.', - 'cc_monthly_payment_date_help' => 'Select any year and any month, it will be ignored anyway. Only the day of the month is relevant.', - 'details_for_asset' => 'Details for asset account ":name"', - 'details_for_expense' => 'Details for expense account ":name"', - 'details_for_revenue' => 'Details for revenue account ":name"', - 'details_for_cash' => 'Details for cash account ":name"', - 'store_new_asset_account' => 'Store new asset account', - 'store_new_expense_account' => 'Store new expense account', - 'store_new_revenue_account' => 'Store new revenue account', - 'edit_asset_account' => 'Edit asset account ":name"', - 'edit_expense_account' => 'Edit expense account ":name"', - 'edit_revenue_account' => 'Edit revenue account ":name"', - 'delete_asset_account' => 'Delete asset account ":name"', - 'delete_expense_account' => 'Delete expense account ":name"', - 'delete_revenue_account' => 'Delete revenue account ":name"', - 'delete_liabilities_account' => 'Delete liability ":name"', - 'asset_deleted' => 'Successfully deleted asset account ":name"', - 'account_deleted' => 'Successfully deleted account ":name"', - 'expense_deleted' => 'Successfully deleted expense account ":name"', - 'revenue_deleted' => 'Successfully deleted revenue account ":name"', - 'update_asset_account' => 'Update asset account', - 'update_undefined_account' => 'Update account', - 'update_liabilities_account' => 'Update liability', - 'update_expense_account' => 'Update expense account', - 'update_revenue_account' => 'Update revenue account', - 'make_new_asset_account' => 'Create a new asset account', - 'make_new_expense_account' => 'Create a new expense account', - 'make_new_revenue_account' => 'Create a new revenue account', - 'make_new_liabilities_account' => 'Create a new liability', - 'asset_accounts' => 'Asset accounts', - 'undefined_accounts' => 'Accounts', - 'asset_accounts_inactive' => 'Asset accounts (inactive)', - 'expense_account' => 'Expense account', - 'expense_accounts' => 'Expense accounts', - 'expense_accounts_inactive' => 'Expense accounts (inactive)', - 'revenue_account' => 'Revenue account', - 'revenue_accounts' => 'Revenue accounts', - 'revenue_accounts_inactive' => 'Revenue accounts (inactive)', - 'cash_accounts' => 'Cash accounts', - 'Cash account' => 'Cash account', - 'liabilities_accounts' => 'Liabilities', - 'liabilities_accounts_inactive' => 'Liabilities (inactive)', - 'reconcile_account' => 'Reconcile account ":account"', - 'overview_of_reconcile_modal' => 'Overview of reconciliation', - 'delete_reconciliation' => 'Delete reconciliation', - 'update_reconciliation' => 'Update reconciliation', - 'amount_cannot_be_zero' => 'The amount cannot be zero', - 'end_of_reconcile_period' => 'End of reconcile period: :period', - 'start_of_reconcile_period' => 'Start of reconcile period: :period', - 'start_balance' => 'Start balance', - 'end_balance' => 'End balance', - 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', - 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', - 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', - 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', - 'update_selection' => 'Update selection', - 'store_reconcile' => 'Store reconciliation', - 'reconciliation_transaction' => 'Reconciliation transaction', - 'Reconciliation' => 'Reconciliation', - 'reconciliation' => 'Reconciliation', - 'reconcile_options' => 'Reconciliation options', - 'reconcile_range' => 'Reconciliation range', - 'start_reconcile' => 'Start reconciling', - 'cash_account_type' => 'Cash', - 'cash' => 'cash', - 'cant_find_redirect_account' => 'Firefly III tried to redirect you but couldn\'t. Sorry about that. Back to the index.', - 'account_type' => 'Account type', - 'save_transactions_by_moving' => 'Save this transaction by moving it to another account:|Save these transactions by moving them to another account:', - 'save_transactions_by_moving_js' => 'No transactions|Save this transaction by moving it to another account. |Save these transactions by moving them to another account.', - 'stored_new_account' => 'New account ":name" stored!', - 'stored_new_account_js' => 'New account "{name}" stored!', - 'updated_account' => 'Updated account ":name"', - 'updated_account_js' => 'Updated account "{title}".', - 'credit_card_options' => 'Credit card options', - 'no_transactions_account' => 'There are no transactions (in this period) for asset account ":name".', - 'no_transactions_period' => 'There are no transactions (in this period).', - 'no_data_for_chart' => 'There is not enough information (yet) to generate this chart.', - 'select_at_least_one_account' => 'Please select at least one asset account', - 'select_at_least_one_category' => 'Please select at least one category', - 'select_at_least_one_budget' => 'Please select at least one budget', - 'select_at_least_one_tag' => 'Please select at least one tag', - 'select_at_least_one_expense' => 'Please select at least one combination of expense/revenue accounts. If you have none (the list is empty) this report is not available.', - 'account_default_currency' => 'This will be the default currency associated with this account.', - 'piggy_default_currency' => 'Piggy banks can only save money in a single currency.', - 'piggy_account_currency_match' => 'Only accounts that use the previously selected currency will be accepted.', - 'reconcile_has_more' => 'Your Firefly III ledger has more money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".', - 'reconcile_has_less' => 'Your Firefly III ledger has less money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".', - 'reconcile_is_equal' => 'Your Firefly III ledger and your bank statements match. There is nothing to do. Please press "Confirm reconciliation" to confirm your input.', - 'create_pos_reconcile_transaction' => 'Clear the selected transactions, and create a correction adding :amount to this asset account.', - 'create_neg_reconcile_transaction' => 'Clear the selected transactions, and create a correction removing :amount from this asset account.', - 'reconcile_do_nothing' => 'Clear the selected transactions, but do not correct.', - 'reconcile_go_back' => 'You can always edit or delete a correction later.', - 'must_be_asset_account' => 'You can only reconcile asset accounts', - 'reconciliation_stored' => 'Reconciliation stored', - 'reconciliation_error' => 'Due to an error the transactions were marked as reconciled but the correction has not been stored: :error.', - 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', - 'sum_of_reconciliation' => 'Sum of reconciliation', - 'reconcile_this_account' => 'Reconcile this account', - 'reconcile' => 'Reconcile', - 'show' => 'Show', - 'confirm_reconciliation' => 'Confirm reconciliation', - 'submitted_start_balance' => 'Submitted start balance', - 'selected_transactions' => 'Selected transactions (:count)', - 'already_cleared_transactions' => 'Already cleared transactions (:count)', - 'submitted_end_balance' => 'Submitted end balance', - 'initial_balance_description' => 'Initial balance for ":account"', - 'liability_credit_description' => 'Liability credit for ":account"', - 'interest_calc_' => 'unknown', - 'interest_calc_daily' => 'Per day', - 'interest_calc_monthly' => 'Per month', - 'interest_calc_yearly' => 'Per year', - 'interest_calc_weekly' => 'Per week', - 'interest_calc_half-year' => 'Per half year', - 'interest_calc_quarterly' => 'Per quarter', - 'initial_balance_account' => 'Initial balance account of :account', - 'list_options' => 'List options', - 'account_column_opt_drag_and_drop' => 'Drag and drop', - 'account_column_opt_active' => 'Active', - 'account_column_opt_name' => 'Name', - 'account_column_opt_type' => 'Type', - 'account_column_opt_liability_type' => 'Liability type', - 'account_column_opt_liability_direction' => 'Liability direction', - 'account_column_opt_liability_interest' => 'Liability interest', - 'account_column_opt_number' => 'Account number', - 'account_column_opt_current_balance' => 'Current balance', - 'account_column_opt_amount_due' => 'Amount due', - 'account_column_opt_last_activity' => 'Last activity', - 'account_column_opt_balance_difference' => 'Balance difference', - 'account_column_opt_menu' => 'Menu', + 'account_locked_currency' => 'The currency of this account must remain :name as long as piggy banks are linked to it.', + 'i_am_owed_amount' => 'I am owed amount', + 'i_owe_amount' => 'I owe amount', + 'inactive_account_link' => 'You have :count inactive (archived) account, which you can view on this separate page.|You have :count inactive (archived) accounts, which you can view on this separate page.', + 'all_accounts_inactive' => 'These are your inactive accounts.', + 'active_account_link' => 'This link goes back to your active accounts.', + 'account_missing_transaction' => 'Account #:id (":name") cannot be viewed directly, but Firefly is missing redirect information.', + 'cc_monthly_payment_date_help' => 'Select any year and any month, it will be ignored anyway. Only the day of the month is relevant.', + 'details_for_asset' => 'Details for asset account ":name"', + 'details_for_expense' => 'Details for expense account ":name"', + 'details_for_revenue' => 'Details for revenue account ":name"', + 'details_for_cash' => 'Details for cash account ":name"', + 'store_new_asset_account' => 'Store new asset account', + 'store_new_expense_account' => 'Store new expense account', + 'store_new_revenue_account' => 'Store new revenue account', + 'edit_asset_account' => 'Edit asset account ":name"', + 'edit_expense_account' => 'Edit expense account ":name"', + 'edit_revenue_account' => 'Edit revenue account ":name"', + 'delete_asset_account' => 'Delete asset account ":name"', + 'delete_expense_account' => 'Delete expense account ":name"', + 'delete_revenue_account' => 'Delete revenue account ":name"', + 'delete_liabilities_account' => 'Delete liability ":name"', + 'asset_deleted' => 'Successfully deleted asset account ":name"', + 'account_deleted' => 'Successfully deleted account ":name"', + 'expense_deleted' => 'Successfully deleted expense account ":name"', + 'revenue_deleted' => 'Successfully deleted revenue account ":name"', + 'update_asset_account' => 'Update asset account', + 'update_undefined_account' => 'Update account', + 'update_liabilities_account' => 'Update liability', + 'update_expense_account' => 'Update expense account', + 'update_revenue_account' => 'Update revenue account', + 'make_new_asset_account' => 'Create a new asset account', + 'make_new_expense_account' => 'Create a new expense account', + 'make_new_revenue_account' => 'Create a new revenue account', + 'make_new_liabilities_account' => 'Create a new liability', + 'asset_accounts' => 'Asset accounts', + 'undefined_accounts' => 'Accounts', + 'asset_accounts_inactive' => 'Asset accounts (inactive)', + 'expense_account' => 'Expense account', + 'expense_accounts' => 'Expense accounts', + 'expense_accounts_inactive' => 'Expense accounts (inactive)', + 'revenue_account' => 'Revenue account', + 'revenue_accounts' => 'Revenue accounts', + 'revenue_accounts_inactive' => 'Revenue accounts (inactive)', + 'cash_accounts' => 'Cash accounts', + 'Cash account' => 'Cash account', + 'liabilities_accounts' => 'Liabilities', + 'liabilities_accounts_inactive' => 'Liabilities (inactive)', + 'reconcile_account' => 'Reconcile account ":account"', + 'overview_of_reconcile_modal' => 'Overview of reconciliation', + 'delete_reconciliation' => 'Delete reconciliation', + 'update_reconciliation' => 'Update reconciliation', + 'amount_cannot_be_zero' => 'The amount cannot be zero', + 'end_of_reconcile_period' => 'End of reconcile period: :period', + 'start_of_reconcile_period' => 'Start of reconcile period: :period', + 'start_balance' => 'Start balance', + 'end_balance' => 'End balance', + 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', + 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', + 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', + 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', + 'update_selection' => 'Update selection', + 'store_reconcile' => 'Store reconciliation', + 'reconciliation_transaction' => 'Reconciliation transaction', + 'Reconciliation' => 'Reconciliation', + 'reconciliation' => 'Reconciliation', + 'reconcile_options' => 'Reconciliation options', + 'reconcile_range' => 'Reconciliation range', + 'start_reconcile' => 'Start reconciling', + 'cash_account_type' => 'Cash', + 'cash' => 'cash', + 'cant_find_redirect_account' => 'Firefly III tried to redirect you but couldn\'t. Sorry about that. Back to the index.', + 'account_type' => 'Account type', + 'save_transactions_by_moving' => 'Save this transaction by moving it to another account:|Save these transactions by moving them to another account:', + 'save_transactions_by_moving_js' => 'No transactions|Save this transaction by moving it to another account. |Save these transactions by moving them to another account.', + 'stored_new_account' => 'New account ":name" stored!', + 'stored_new_account_js' => 'New account "{name}" stored!', + 'updated_account' => 'Updated account ":name"', + 'updated_account_js' => 'Updated account "{title}".', + 'credit_card_options' => 'Credit card options', + 'no_transactions_account' => 'There are no transactions (in this period) for asset account ":name".', + 'no_transactions_period' => 'There are no transactions (in this period).', + 'no_data_for_chart' => 'There is not enough information (yet) to generate this chart.', + 'select_at_least_one_account' => 'Please select at least one asset account', + 'select_at_least_one_category' => 'Please select at least one category', + 'select_at_least_one_budget' => 'Please select at least one budget', + 'select_at_least_one_tag' => 'Please select at least one tag', + 'select_at_least_one_expense' => 'Please select at least one combination of expense/revenue accounts. If you have none (the list is empty) this report is not available.', + 'account_default_currency' => 'This will be the default currency associated with this account.', + 'piggy_default_currency' => 'Piggy banks can only save money in a single currency.', + 'piggy_account_currency_match' => 'Only accounts that use the previously selected currency will be accepted.', + 'reconcile_has_more' => 'Your Firefly III ledger has more money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".', + 'reconcile_has_less' => 'Your Firefly III ledger has less money in it than your bank claims you should have. There are several options. Please choose what to do. Then, press "Confirm reconciliation".', + 'reconcile_is_equal' => 'Your Firefly III ledger and your bank statements match. There is nothing to do. Please press "Confirm reconciliation" to confirm your input.', + 'create_pos_reconcile_transaction' => 'Clear the selected transactions, and create a correction adding :amount to this asset account.', + 'create_neg_reconcile_transaction' => 'Clear the selected transactions, and create a correction removing :amount from this asset account.', + 'reconcile_do_nothing' => 'Clear the selected transactions, but do not correct.', + 'reconcile_go_back' => 'You can always edit or delete a correction later.', + 'must_be_asset_account' => 'You can only reconcile asset accounts', + 'reconciliation_stored' => 'Reconciliation stored', + 'reconciliation_error' => 'Due to an error the transactions were marked as reconciled but the correction has not been stored: :error.', + 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', + 'sum_of_reconciliation' => 'Sum of reconciliation', + 'reconcile_this_account' => 'Reconcile this account', + 'reconcile' => 'Reconcile', + 'show' => 'Show', + 'confirm_reconciliation' => 'Confirm reconciliation', + 'submitted_start_balance' => 'Submitted start balance', + 'selected_transactions' => 'Selected transactions (:count)', + 'already_cleared_transactions' => 'Already cleared transactions (:count)', + 'submitted_end_balance' => 'Submitted end balance', + 'initial_balance_description' => 'Initial balance for ":account"', + 'liability_credit_description' => 'Liability credit for ":account"', + 'interest_calc_' => 'unknown', + 'interest_calc_daily' => 'Per day', + 'interest_calc_monthly' => 'Per month', + 'interest_calc_yearly' => 'Per year', + 'interest_calc_weekly' => 'Per week', + 'interest_calc_half-year' => 'Per half year', + 'interest_calc_quarterly' => 'Per quarter', + 'initial_balance_account' => 'Initial balance account of :account', + 'list_options' => 'List options', + 'account_column_opt_drag_and_drop' => 'Drag and drop', + 'account_column_opt_active' => 'Active', + 'account_column_opt_name' => 'Name', + 'account_column_opt_type' => 'Type', + 'account_column_opt_liability_type' => 'Liability type', + 'account_column_opt_liability_direction' => 'Liability direction', + 'account_column_opt_liability_interest' => 'Liability interest', + 'account_column_opt_number' => 'Account number', + 'account_column_opt_current_balance' => 'Current balance', + 'account_column_opt_amount_due' => 'Amount due', + 'account_column_opt_last_activity' => 'Last activity', + 'account_column_opt_balance_difference' => 'Balance difference', + 'account_column_opt_menu' => 'Menu', // categories: - 'new_category' => 'New category', - 'create_new_category' => 'Create a new category', - 'without_category' => 'Without a category', - 'update_category' => 'Update category', - 'updated_category' => 'Updated category ":name"', - 'categories' => 'Categories', - 'edit_category' => 'Edit category ":name"', - 'no_category' => '(no category)', - 'unknown_category_plain' => 'No category', - 'category' => 'Category', - 'delete_category' => 'Delete category ":name"', - 'deleted_category' => 'Deleted category ":name"', - 'store_category' => 'Store new category', - 'stored_category' => 'Stored new category ":name"', - 'without_category_between' => 'Without category between :start and :end', + 'new_category' => 'New category', + 'create_new_category' => 'Create a new category', + 'without_category' => 'Without a category', + 'update_category' => 'Update category', + 'updated_category' => 'Updated category ":name"', + 'categories' => 'Categories', + 'edit_category' => 'Edit category ":name"', + 'no_category' => '(no category)', + 'unknown_category_plain' => 'No category', + 'category' => 'Category', + 'delete_category' => 'Delete category ":name"', + 'deleted_category' => 'Deleted category ":name"', + 'store_category' => 'Store new category', + 'stored_category' => 'Stored new category ":name"', + 'without_category_between' => 'Without category between :start and :end', // transactions: - 'wait_loading_transaction' => 'Please wait for the form to load', - 'wait_loading_data' => 'Please wait for your information to load...', - 'wait_attachments' => 'Please wait for the attachments to upload.', - 'errors_upload' => 'The upload has failed. Please check your browser console for the error.', - 'amount_foreign_if' => 'Amount in foreign currency, if any', - 'amount_destination_account' => 'Amount in the currency of the destination account', - 'edit_transaction_title' => 'Edit transaction ":description"', - 'unreconcile' => 'Undo reconciliation', - 'update_withdrawal' => 'Update withdrawal', - 'update_deposit' => 'Update deposit', - 'update_transaction' => 'Update transaction', - 'update_transfer' => 'Update transfer', - 'updated_withdrawal' => 'Updated withdrawal ":description"', - 'updated_deposit' => 'Updated deposit ":description"', - 'updated_transfer' => 'Updated transfer ":description"', - 'no_changes_withdrawal' => 'Withdrawal ":description" was not changed.', - 'no_changes_deposit' => 'Deposit ":description" was not changed.', - 'no_changes_transfer' => 'Transfer ":description" was not changed.', - 'delete_withdrawal' => 'Delete withdrawal ":description"', - 'delete_deposit' => 'Delete deposit ":description"', - 'delete_transfer' => 'Delete transfer ":description"', - 'deleted_withdrawal' => 'Successfully deleted withdrawal ":description"', - 'deleted_deposit' => 'Successfully deleted deposit ":description"', - 'deleted_transfer' => 'Successfully deleted transfer ":description"', - 'deleted_reconciliation' => 'Successfully deleted reconciliation transaction ":description"', - 'stored_journal' => 'Successfully created new transaction ":description"', - 'stored_journal_js' => 'Successfully created new transaction "{{description}}"', - 'stored_journal_no_descr' => 'Successfully created your new transaction', - 'updated_journal_no_descr' => 'Successfully updated your transaction', - 'select_transactions' => 'Select transactions', - 'rule_group_select_transactions' => 'Apply ":title" to transactions', - 'rule_select_transactions' => 'Apply ":title" to transactions', - 'stop_selection' => 'Stop selecting transactions', - 'reconcile_selected' => 'Reconcile', - 'mass_delete_journals' => 'Delete a number of transactions', - 'mass_edit_journals' => 'Edit a number of transactions', - 'mass_bulk_journals' => 'Bulk edit a number of transactions', - 'mass_bulk_journals_explain' => 'This form allows you to change properties of the transactions listed below in one sweeping update. All the transactions in the table will be updated when you change the parameters you see here.', - 'part_of_split' => 'This transaction is part of a split transaction. If you have not selected all the splits, you may end up with changing only half the transaction.', - 'bulk_set_new_values' => 'Use the inputs below to set new values. If you leave them empty, they will be made empty for all. Also, note that only withdrawals will be given a budget.', - 'no_bulk_category' => 'Don\'t update category', - 'no_bulk_budget' => 'Don\'t update budget', - 'no_bulk_tags' => 'Don\'t update tag(s)', - 'replace_with_these_tags' => 'Replace with these tags', - 'append_these_tags' => 'Add these tags', - 'mass_edit' => 'Edit selected individually', - 'bulk_edit' => 'Edit selected in bulk', - 'mass_delete' => 'Delete selected', - 'cannot_edit_other_fields' => 'You cannot mass-edit other fields than the ones here, because there is no room to show them. Please follow the link and edit them by one-by-one, if you need to edit these fields.', - 'cannot_change_amount_reconciled' => 'You can\'t change the amount or account(s) of reconciled transactions.', - 'no_budget' => '(no budget)', - 'no_bill' => '(no subscription)', - 'account_per_budget' => 'Account per budget', - 'account_per_category' => 'Account per category', - 'create_new_object' => 'Create', - 'empty' => '(empty)', - 'all_other_budgets' => '(all other budgets)', - 'all_other_accounts' => '(all other accounts)', - 'expense_per_source_account' => 'Expenses per source account', - 'expense_per_destination_account' => 'Expenses per destination account', - 'income_per_destination_account' => 'Income per destination account', - 'spent_in_specific_category' => 'Spent in category ":category"', - 'earned_in_specific_category' => 'Earned in category ":category"', - 'spent_in_specific_tag' => 'Spent in tag ":tag"', - 'earned_in_specific_tag' => 'Earned in tag ":tag"', - 'income_per_source_account' => 'Income per source account', - 'average_spending_per_destination' => 'Average expense per destination account', - 'average_spending_per_source' => 'Average expense per source account', - 'average_earning_per_source' => 'Average earning per source account', - 'average_earning_per_destination' => 'Average earning per destination account', - 'account_per_tag' => 'Account per tag', - 'tag_report_expenses_listed_once' => 'Expenses and income are never listed twice. If a transaction has multiple tags, it may only show up under one of its tags. This list may appear to be missing data, but the amounts will be correct.', - 'double_report_expenses_charted_once' => 'Expenses and income are never displayed twice. If a transaction has multiple tags, it may only show up under one of its tags. This chart may appear to be missing data, but the amounts will be correct.', - 'tag_report_chart_single_tag' => 'This chart applies to a single tag. If a transaction has multiple tags, what you see here may be reflected in the charts of other tags as well.', - 'tag' => 'Tag', - 'no_budget_squared' => '(no budget)', - 'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious. You can delete part of a split transaction from this page, so take care.', - 'mass_deleted_transactions_success' => 'Deleted :count transaction.|Deleted :count transactions.', - 'mass_edited_transactions_success' => 'Updated :count transaction.|Updated :count transactions.', - 'opt_group_' => '(no account type)', - 'opt_group_no_account_type' => '(no account type)', - 'opt_group_defaultAsset' => 'Default asset accounts', - 'opt_group_savingAsset' => 'Savings accounts', - 'opt_group_sharedAsset' => 'Shared asset accounts', - 'opt_group_ccAsset' => 'Credit cards', - 'opt_group_cashWalletAsset' => 'Cash wallets', - 'opt_group_expense_account' => 'Expense accounts', - 'opt_group_revenue_account' => 'Revenue accounts', - 'opt_group_l_Loan' => 'Liability: Loan', - 'opt_group_cash_account' => 'Cash account', - 'opt_group_l_Debt' => 'Liability: Debt', - 'opt_group_l_Mortgage' => 'Liability: Mortgage', - 'opt_group_l_Credit card' => 'Liability: Credit card', - 'notes' => 'Notes', - 'view_notes' => 'View notes', - 'set_budget_limit_notes' => 'View the notes for this budgeted amount', - 'edit_bl_notes' => 'Edit notes', - 'update_bl_notes' => 'Update notes', - 'unknown_journal_error' => 'Could not store the transaction. Please check the log files.', - 'attachment_not_found' => 'This attachment could not be found.', - 'journal_link_bill' => 'This transaction is linked to subscription :name. To remove the connection, uncheck the checkbox. Use rules to connect it to another subscription.', - 'transaction_stored_link' => 'Transaction #{ID} ("{title}") has been stored.', - 'transaction_new_stored_link' => 'Transaction #{ID} has been stored.', - 'transaction_updated_link' => 'Transaction #{ID} ("{title}") has been updated.', - 'transaction_updated_no_changes' => 'Transaction #{ID} ("{title}") did not receive any changes.', - 'first_split_decides' => 'The first split determines the value of this field', - 'first_split_overrules_source' => 'The first split may overrule the source account', - 'first_split_overrules_destination' => 'The first split may overrule the destination account', - 'spent_x_of_y' => 'Spent {amount} of {total}', + 'wait_loading_transaction' => 'Please wait for the form to load', + 'wait_loading_data' => 'Please wait for your information to load...', + 'wait_attachments' => 'Please wait for the attachments to upload.', + 'errors_upload' => 'The upload has failed. Please check your browser console for the error.', + 'amount_foreign_if' => 'Amount in foreign currency, if any', + 'amount_destination_account' => 'Amount in the currency of the destination account', + 'edit_transaction_title' => 'Edit transaction ":description"', + 'unreconcile' => 'Undo reconciliation', + 'update_withdrawal' => 'Update withdrawal', + 'update_deposit' => 'Update deposit', + 'update_transaction' => 'Update transaction', + 'update_transfer' => 'Update transfer', + 'updated_withdrawal' => 'Updated withdrawal ":description"', + 'updated_deposit' => 'Updated deposit ":description"', + 'updated_transfer' => 'Updated transfer ":description"', + 'no_changes_withdrawal' => 'Withdrawal ":description" was not changed.', + 'no_changes_deposit' => 'Deposit ":description" was not changed.', + 'no_changes_transfer' => 'Transfer ":description" was not changed.', + 'delete_withdrawal' => 'Delete withdrawal ":description"', + 'delete_deposit' => 'Delete deposit ":description"', + 'delete_transfer' => 'Delete transfer ":description"', + 'deleted_withdrawal' => 'Successfully deleted withdrawal ":description"', + 'deleted_deposit' => 'Successfully deleted deposit ":description"', + 'deleted_transfer' => 'Successfully deleted transfer ":description"', + 'deleted_reconciliation' => 'Successfully deleted reconciliation transaction ":description"', + 'stored_journal' => 'Successfully created new transaction ":description"', + 'stored_journal_js' => 'Successfully created new transaction "{{description}}"', + 'stored_journal_no_descr' => 'Successfully created your new transaction', + 'updated_journal_no_descr' => 'Successfully updated your transaction', + 'select_transactions' => 'Select transactions', + 'rule_group_select_transactions' => 'Apply ":title" to transactions', + 'rule_select_transactions' => 'Apply ":title" to transactions', + 'stop_selection' => 'Stop selecting transactions', + 'reconcile_selected' => 'Reconcile', + 'mass_delete_journals' => 'Delete a number of transactions', + 'mass_edit_journals' => 'Edit a number of transactions', + 'mass_bulk_journals' => 'Bulk edit a number of transactions', + 'mass_bulk_journals_explain' => 'This form allows you to change properties of the transactions listed below in one sweeping update. All the transactions in the table will be updated when you change the parameters you see here.', + 'part_of_split' => 'This transaction is part of a split transaction. If you have not selected all the splits, you may end up with changing only half the transaction.', + 'bulk_set_new_values' => 'Use the inputs below to set new values. If you leave them empty, they will be made empty for all. Also, note that only withdrawals will be given a budget.', + 'no_bulk_category' => 'Don\'t update category', + 'no_bulk_budget' => 'Don\'t update budget', + 'no_bulk_tags' => 'Don\'t update tag(s)', + 'replace_with_these_tags' => 'Replace with these tags', + 'append_these_tags' => 'Add these tags', + 'mass_edit' => 'Edit selected individually', + 'bulk_edit' => 'Edit selected in bulk', + 'mass_delete' => 'Delete selected', + 'cannot_edit_other_fields' => 'You cannot mass-edit other fields than the ones here, because there is no room to show them. Please follow the link and edit them by one-by-one, if you need to edit these fields.', + 'cannot_change_amount_reconciled' => 'You can\'t change the amount or account(s) of reconciled transactions.', + 'no_budget' => '(no budget)', + 'no_bill' => '(no subscription)', + 'account_per_budget' => 'Account per budget', + 'account_per_category' => 'Account per category', + 'create_new_object' => 'Create', + 'empty' => '(empty)', + 'all_other_budgets' => '(all other budgets)', + 'all_other_accounts' => '(all other accounts)', + 'expense_per_source_account' => 'Expenses per source account', + 'expense_per_destination_account' => 'Expenses per destination account', + 'income_per_destination_account' => 'Income per destination account', + 'spent_in_specific_category' => 'Spent in category ":category"', + 'earned_in_specific_category' => 'Earned in category ":category"', + 'spent_in_specific_tag' => 'Spent in tag ":tag"', + 'earned_in_specific_tag' => 'Earned in tag ":tag"', + 'income_per_source_account' => 'Income per source account', + 'average_spending_per_destination' => 'Average expense per destination account', + 'average_spending_per_source' => 'Average expense per source account', + 'average_earning_per_source' => 'Average earning per source account', + 'average_earning_per_destination' => 'Average earning per destination account', + 'account_per_tag' => 'Account per tag', + 'tag_report_expenses_listed_once' => 'Expenses and income are never listed twice. If a transaction has multiple tags, it may only show up under one of its tags. This list may appear to be missing data, but the amounts will be correct.', + 'double_report_expenses_charted_once' => 'Expenses and income are never displayed twice. If a transaction has multiple tags, it may only show up under one of its tags. This chart may appear to be missing data, but the amounts will be correct.', + 'tag_report_chart_single_tag' => 'This chart applies to a single tag. If a transaction has multiple tags, what you see here may be reflected in the charts of other tags as well.', + 'tag' => 'Tag', + 'no_budget_squared' => '(no budget)', + 'perm-delete-many' => 'Deleting many items in one go can be very disruptive. Please be cautious. You can delete part of a split transaction from this page, so take care.', + 'mass_deleted_transactions_success' => 'Deleted :count transaction.|Deleted :count transactions.', + 'mass_edited_transactions_success' => 'Updated :count transaction.|Updated :count transactions.', + 'opt_group_' => '(no account type)', + 'opt_group_no_account_type' => '(no account type)', + 'opt_group_defaultAsset' => 'Default asset accounts', + 'opt_group_savingAsset' => 'Savings accounts', + 'opt_group_sharedAsset' => 'Shared asset accounts', + 'opt_group_ccAsset' => 'Credit cards', + 'opt_group_cashWalletAsset' => 'Cash wallets', + 'opt_group_expense_account' => 'Expense accounts', + 'opt_group_revenue_account' => 'Revenue accounts', + 'opt_group_l_Loan' => 'Liability: Loan', + 'opt_group_cash_account' => 'Cash account', + 'opt_group_l_Debt' => 'Liability: Debt', + 'opt_group_l_Mortgage' => 'Liability: Mortgage', + 'opt_group_l_Credit card' => 'Liability: Credit card', + 'notes' => 'Notes', + 'view_notes' => 'View notes', + 'set_budget_limit_notes' => 'View the notes for this budgeted amount', + 'edit_bl_notes' => 'Edit notes', + 'update_bl_notes' => 'Update notes', + 'unknown_journal_error' => 'Could not store the transaction. Please check the log files.', + 'attachment_not_found' => 'This attachment could not be found.', + 'journal_link_bill' => 'This transaction is linked to subscription :name. To remove the connection, uncheck the checkbox. Use rules to connect it to another subscription.', + 'transaction_stored_link' => 'Transaction #{ID} ("{title}") has been stored.', + 'transaction_new_stored_link' => 'Transaction #{ID} has been stored.', + 'transaction_updated_link' => 'Transaction #{ID} ("{title}") has been updated.', + 'transaction_updated_no_changes' => 'Transaction #{ID} ("{title}") did not receive any changes.', + 'first_split_decides' => 'The first split determines the value of this field', + 'first_split_overrules_source' => 'The first split may overrule the source account', + 'first_split_overrules_destination' => 'The first split may overrule the destination account', + 'spent_x_of_y' => 'Spent {amount} of {total}', // new user: - 'welcome' => 'Welcome to Firefly III!', - 'submit' => 'Submit', - 'submission' => 'Submission', - 'submit_yes_really' => 'Submit (I know what I\'m doing)', - 'getting_started' => 'Getting started', - 'to_get_started' => 'It is good to see you have successfully installed Firefly III. To get started with this tool please enter your bank\'s name and the balance of your main checking account. Do not worry yet if you have multiple accounts. You can add those later. It\'s just that Firefly III needs something to start with.', - 'savings_balance_text' => 'Firefly III will automatically create a savings account for you. By default, there will be no money in your savings account, but if you tell Firefly III the balance it will be stored as such.', - 'finish_up_new_user' => 'That\'s it! You can continue by pressing Submit. You will be taken to the index of Firefly III.', - 'stored_new_accounts_new_user' => 'Yay! Your new accounts have been stored.', - 'set_preferred_language' => 'If you prefer to use Firefly III in another language, please indicate so here.', - 'language' => 'Language', - 'new_savings_account' => ':bank_name savings account', - 'cash_wallet' => 'Cash wallet', - 'currency_not_present' => 'If the currency you normally use is not listed do not worry. You can create your own currencies under Options > Currencies.', + 'welcome' => 'Welcome to Firefly III!', + 'submit' => 'Submit', + 'submission' => 'Submission', + 'submit_yes_really' => 'Submit (I know what I\'m doing)', + 'getting_started' => 'Getting started', + 'to_get_started' => 'It is good to see you have successfully installed Firefly III. To get started with this tool please enter your bank\'s name and the balance of your main checking account. Do not worry yet if you have multiple accounts. You can add those later. It\'s just that Firefly III needs something to start with.', + 'savings_balance_text' => 'Firefly III will automatically create a savings account for you. By default, there will be no money in your savings account, but if you tell Firefly III the balance it will be stored as such.', + 'finish_up_new_user' => 'That\'s it! You can continue by pressing Submit. You will be taken to the index of Firefly III.', + 'stored_new_accounts_new_user' => 'Yay! Your new accounts have been stored.', + 'set_preferred_language' => 'If you prefer to use Firefly III in another language, please indicate so here.', + 'language' => 'Language', + 'new_savings_account' => ':bank_name savings account', + 'cash_wallet' => 'Cash wallet', + 'currency_not_present' => 'If the currency you normally use is not listed do not worry. You can create your own currencies under Options > Currencies.', // home page: - 'transaction_table_description' => 'A table containing your transactions', - 'opposing_account' => 'Opposing account', - 'yourAccounts' => 'Your accounts', - 'your_accounts' => 'Your account overview', - 'category_overview' => 'Category overview', - 'expense_overview' => 'Expense account overview', - 'revenue_overview' => 'Revenue account overview', - 'budgetsAndSpending' => 'Budgets and spending', - 'budgets_and_spending' => 'Budgets and spending', - 'go_to_budget' => 'Go to budget "{budget}"', - 'go_to_deposits' => 'Go to deposits', - 'go_to_expenses' => 'Go to expenses', - 'savings' => 'Savings', - 'newWithdrawal' => 'New expense', - 'newDeposit' => 'New deposit', - 'newTransfer' => 'New transfer', - 'bills_to_pay' => 'Subscriptions to pay', - 'per_day' => 'Per day', - 'left_to_spend_per_day' => 'Left to spend per day', - 'bills_paid' => 'Subscriptions paid', - 'custom_period' => 'Custom period', - 'reset_to_current' => 'Reset to current period', - 'select_period' => 'Select a period', + 'transaction_table_description' => 'A table containing your transactions', + 'opposing_account' => 'Opposing account', + 'yourAccounts' => 'Your accounts', + 'your_accounts' => 'Your account overview', + 'category_overview' => 'Category overview', + 'expense_overview' => 'Expense account overview', + 'revenue_overview' => 'Revenue account overview', + 'budgetsAndSpending' => 'Budgets and spending', + 'budgets_and_spending' => 'Budgets and spending', + 'go_to_budget' => 'Go to budget "{budget}"', + 'go_to_deposits' => 'Go to deposits', + 'go_to_expenses' => 'Go to expenses', + 'savings' => 'Savings', + 'newWithdrawal' => 'New expense', + 'newDeposit' => 'New deposit', + 'newTransfer' => 'New transfer', + 'bills_to_pay' => 'Subscriptions to pay', + 'per_day' => 'Per day', + 'left_to_spend_per_day' => 'Left to spend per day', + 'bills_paid' => 'Subscriptions paid', + 'custom_period' => 'Custom period', + 'reset_to_current' => 'Reset to current period', + 'select_period' => 'Select a period', // menu and titles, should be recycled as often as possible: - 'currency' => 'Currency', - 'preferences' => 'Preferences', - 'logout' => 'Logout', - 'logout_other_sessions' => 'Logout all other sessions', - 'toggleNavigation' => 'Toggle navigation', - 'toggle_dropdown' => 'Toggle dropdown', - 'searchPlaceholder' => 'Search...', - 'version' => 'Version', - 'dashboard' => 'Dashboard', - 'income_and_expense' => 'Income and expense', - 'all_money' => 'All your money', - 'unknown_source_plain' => 'Unknown source account', - 'unknown_dest_plain' => 'Unknown destination account', - 'unknown_any_plain' => 'Unknown account', - 'unknown_budget_plain' => 'No budget', - 'available_budget' => 'Available budget ({currency})', - 'currencies' => 'Currencies', - 'activity' => 'Activity', - 'usage' => 'Usage', - 'accounts' => 'Accounts', - 'Asset account' => 'Asset account', - 'Default account' => 'Asset account', - 'Expense account' => 'Expense account', - 'Revenue account' => 'Revenue account', - 'Initial balance account' => 'Initial balance account', - 'account_type_Asset account' => 'Asset account', - 'account_type_Expense account' => 'Expense account', - 'account_type_Revenue account' => 'Revenue account', - 'account_type_Debt' => 'Debt', - 'account_type_Loan' => 'Loan', - 'account_type_Mortgage' => 'Mortgage', - 'account_type_debt' => 'Debt', - 'account_type_loan' => 'Loan', - 'account_type_mortgage' => 'Mortgage', - 'account_type_Credit card' => 'Credit card', - 'credit_card_type_monthlyFull' => 'Full payment every month', - 'liability_direction_credit' => 'I am owed this debt', - 'liability_direction_debit' => 'I owe this debt to somebody else', - 'liability_direction_credit_short' => 'Owed this debt', - 'liability_direction_debit_short' => 'Owe this debt', - 'liability_direction__short' => 'Unknown', - 'liability_direction_null_short' => 'Unknown', - 'Liability credit' => 'Liability credit', - 'budgets' => 'Budgets', - 'tags' => 'Tags', - 'reports' => 'Reports', - 'transactions' => 'Transactions', - 'expenses' => 'Expenses', - 'income' => 'Revenue / income', - 'transfers' => 'Transfers', - 'moneyManagement' => 'Money management', - 'money_management' => 'Money management', - 'tools' => 'Tools', - 'piggyBanks' => 'Piggy banks', - 'piggy_banks' => 'Piggy banks', - 'amount_x_of_y' => '{current} of {total}', - 'bills' => 'Subscriptions', - 'withdrawal' => 'Withdrawal', - 'opening_balance' => 'Opening balance', - 'deposit' => 'Deposit', - 'account' => 'Account', - 'transfer' => 'Transfer', - 'Withdrawal' => 'Withdrawal', - 'Deposit' => 'Deposit', - 'Transfer' => 'Transfer', - 'bill' => 'Subscription', - 'yes' => 'Yes', - 'no' => 'No', - 'amount' => 'Amount', - 'overview' => 'Overview', - 'saveOnAccount' => 'Save on account', - 'saveOnAccounts' => 'Save on account(s)', - 'unknown' => 'Unknown', - 'monthly' => 'Monthly', - 'profile' => 'Profile', - 'errors' => 'Errors', - 'debt_start_date' => 'Start date of debt', - 'debt_start_amount' => 'Start amount of debt', - 'debt_start_amount_help' => 'It\'s always best to set this value to a negative amount. Read the help pages (top right (?)-icon) for more information.', - 'interest_period_help' => 'This field is purely cosmetic and won\'t be calculated for you. As it turns out banks are very sneaky so Firefly III never gets it right.', - 'store_new_liabilities_account' => 'Store new liability', - 'edit_liabilities_account' => 'Edit liability ":name"', - 'financial_control' => 'Financial control', - 'accounting' => 'Accounting', - 'automation' => 'Automation', - 'others' => 'Others', - 'classification' => 'Classification', - 'store_transaction' => 'Store transaction', + 'currency' => 'Currency', + 'preferences' => 'Preferences', + 'logout' => 'Logout', + 'logout_other_sessions' => 'Logout all other sessions', + 'toggleNavigation' => 'Toggle navigation', + 'toggle_dropdown' => 'Toggle dropdown', + 'searchPlaceholder' => 'Search...', + 'version' => 'Version', + 'dashboard' => 'Dashboard', + 'income_and_expense' => 'Income and expense', + 'all_money' => 'All your money', + 'unknown_source_plain' => 'Unknown source account', + 'unknown_dest_plain' => 'Unknown destination account', + 'unknown_any_plain' => 'Unknown account', + 'unknown_budget_plain' => 'No budget', + 'available_budget' => 'Available budget ({currency})', + 'currencies' => 'Currencies', + 'activity' => 'Activity', + 'usage' => 'Usage', + 'accounts' => 'Accounts', + 'Asset account' => 'Asset account', + 'Default account' => 'Asset account', + 'Expense account' => 'Expense account', + 'Revenue account' => 'Revenue account', + 'Initial balance account' => 'Initial balance account', + 'account_type_Asset account' => 'Asset account', + 'account_type_Expense account' => 'Expense account', + 'account_type_Revenue account' => 'Revenue account', + 'account_type_Debt' => 'Debt', + 'account_type_Loan' => 'Loan', + 'account_type_Mortgage' => 'Mortgage', + 'account_type_debt' => 'Debt', + 'account_type_loan' => 'Loan', + 'account_type_mortgage' => 'Mortgage', + 'account_type_Credit card' => 'Credit card', + 'credit_card_type_monthlyFull' => 'Full payment every month', + 'liability_direction_credit' => 'I am owed this debt', + 'liability_direction_debit' => 'I owe this debt to somebody else', + 'liability_direction_credit_short' => 'Owed this debt', + 'liability_direction_debit_short' => 'Owe this debt', + 'liability_direction__short' => 'Unknown', + 'liability_direction_null_short' => 'Unknown', + 'Liability credit' => 'Liability credit', + 'budgets' => 'Budgets', + 'tags' => 'Tags', + 'reports' => 'Reports', + 'transactions' => 'Transactions', + 'expenses' => 'Expenses', + 'income' => 'Revenue / income', + 'transfers' => 'Transfers', + 'moneyManagement' => 'Money management', + 'money_management' => 'Money management', + 'tools' => 'Tools', + 'piggyBanks' => 'Piggy banks', + 'piggy_banks' => 'Piggy banks', + 'amount_x_of_y' => '{current} of {total}', + 'bills' => 'Subscriptions', + 'withdrawal' => 'Withdrawal', + 'opening_balance' => 'Opening balance', + 'deposit' => 'Deposit', + 'account' => 'Account', + 'transfer' => 'Transfer', + 'Withdrawal' => 'Withdrawal', + 'Deposit' => 'Deposit', + 'Transfer' => 'Transfer', + 'bill' => 'Subscription', + 'yes' => 'Yes', + 'no' => 'No', + 'amount' => 'Amount', + 'overview' => 'Overview', + 'saveOnAccount' => 'Save on account', + 'saveOnAccounts' => 'Save on account(s)', + 'unknown' => 'Unknown', + 'monthly' => 'Monthly', + 'profile' => 'Profile', + 'errors' => 'Errors', + 'debt_start_date' => 'Start date of debt', + 'debt_start_amount' => 'Start amount of debt', + 'debt_start_amount_help' => 'It\'s always best to set this value to a negative amount. Read the help pages (top right (?)-icon) for more information.', + 'interest_period_help' => 'This field is purely cosmetic and won\'t be calculated for you. As it turns out banks are very sneaky so Firefly III never gets it right.', + 'store_new_liabilities_account' => 'Store new liability', + 'edit_liabilities_account' => 'Edit liability ":name"', + 'financial_control' => 'Financial control', + 'accounting' => 'Accounting', + 'automation' => 'Automation', + 'others' => 'Others', + 'classification' => 'Classification', + 'store_transaction' => 'Store transaction', // reports: - 'report_default' => 'Default financial report between :start and :end', - 'report_audit' => 'Transaction history overview between :start and :end', - 'report_category' => 'Category report between :start and :end', - 'report_double' => 'Expense/revenue account report between :start and :end', - 'report_budget' => 'Budget report between :start and :end', - 'report_tag' => 'Tag report between :start and :end', - 'quick_link_reports' => 'Quick links', - 'quick_link_examples' => 'These are just some example links to get you started. Check out the help pages under the (?)-button for information on all reports and the magic words you can use.', - 'quick_link_default_report' => 'Default financial report', - 'quick_link_audit_report' => 'Transaction history overview', - 'report_this_month_quick' => 'Current month, all accounts', - 'report_last_month_quick' => 'Last month, all accounts', - 'report_this_year_quick' => 'Current year, all accounts', - 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts', - 'report_all_time_quick' => 'All-time, all accounts', - 'reports_can_bookmark' => 'Remember that reports can be bookmarked.', - 'incomeVsExpenses' => 'Income vs. expenses', - 'accountBalances' => 'Account balances', - 'balanceStart' => 'Balance at start of period', - 'balanceEnd' => 'Balance at end of period', - 'splitByAccount' => 'Split by account', - 'coveredWithTags' => 'Covered with tags', - 'leftInBudget' => 'Left in budget', - 'left_in_debt' => 'Amount due', - 'sumOfSums' => 'Sum of sums', - 'noCategory' => '(no category)', - 'notCharged' => 'Not charged (yet)', - 'inactive' => 'Inactive', - 'active' => 'Active', - 'difference' => 'Difference', - 'money_flowing_in' => 'In', - 'money_flowing_out' => 'Out', - 'topX' => 'top :number', - 'show_full_list' => 'Show entire list', - 'show_only_top' => 'Show only top :number', - 'report_type' => 'Report type', - 'report_type_default' => 'Default financial report', - 'report_type_audit' => 'Transaction history overview (audit)', - 'report_type_category' => 'Category report', - 'report_type_budget' => 'Budget report', - 'report_type_tag' => 'Tag report', - 'report_type_double' => 'Expense/revenue account report', - 'more_info_help' => 'More information about these types of reports can be found in the help pages. Press the (?) icon in the top right corner.', - 'report_included_accounts' => 'Included accounts', - 'report_date_range' => 'Date range', - 'report_preset_ranges' => 'Pre-set ranges', - 'shared' => 'Shared', - 'fiscal_year' => 'Fiscal year', - 'income_entry' => 'Income from account ":name" between :start and :end', - 'expense_entry' => 'Expenses to account ":name" between :start and :end', - 'category_entry' => 'Expenses and income in category ":name" between :start and :end', - 'budget_spent_amount' => 'Expenses in budget ":budget" between :start and :end', - 'balance_amount' => 'Expenses in budget ":budget" paid from account ":account" between :start and :end', - 'no_audit_activity' => 'No activity was recorded on account :account_name between :start and :end.', - 'audit_end_balance' => 'Account balance of :account_name at the end of :end was: :balance', - 'reports_extra_options' => 'Extra options', - 'report_has_no_extra_options' => 'This report has no extra options', - 'reports_submit' => 'View report', - 'end_after_start_date' => 'End date of report must be after start date.', - 'select_category' => 'Select category(ies)', - 'select_budget' => 'Select budget(s).', - 'select_tag' => 'Select tag(s).', - 'income_per_category' => 'Income per category', - 'expense_per_category' => 'Expense per category', - 'expense_per_budget' => 'Expense per budget', - 'income_per_account' => 'Income per account', - 'expense_per_account' => 'Expense per account', - 'expense_per_tag' => 'Expense per tag', - 'income_per_tag' => 'Income per tag', - 'include_expense_not_in_budget' => 'Included expenses not in the selected budget(s)', - 'include_expense_not_in_account' => 'Included expenses not in the selected account(s)', - 'include_expense_not_in_category' => 'Included expenses not in the selected category(ies)', - 'include_income_not_in_category' => 'Included income not in the selected category(ies)', - 'include_income_not_in_account' => 'Included income not in the selected account(s)', - 'include_income_not_in_tags' => 'Included income not in the selected tag(s)', - 'include_expense_not_in_tags' => 'Included expenses not in the selected tag(s)', - 'everything_else' => 'Everything else', - 'income_and_expenses' => 'Income and expenses', - 'spent_average' => 'Spent (average)', - 'income_average' => 'Income (average)', - 'transaction_count' => 'Transaction count', - 'average_spending_per_account' => 'Average spending per account', - 'average_income_per_account' => 'Average income per account', - 'total' => 'Total', - 'description' => 'Description', - 'sum_of_period' => 'Sum of period', - 'average_in_period' => 'Average in period', - 'no_account_role' => '(no role)', - 'account_role_defaultAsset' => 'Default asset account', - 'account_role_sharedAsset' => 'Shared asset account', - 'account_role_savingAsset' => 'Savings account', - 'account_role_ccAsset' => 'Credit card', - 'account_role_cashWalletAsset' => 'Cash wallet', - 'budget_chart_click' => 'Please click on a budget name in the table above to see a chart.', - 'category_chart_click' => 'Please click on a category name in the table above to see a chart.', - 'in_out_accounts' => 'Earned and spent per combination', - 'in_out_accounts_per_asset' => 'Earned and spent (per asset account)', - 'in_out_per_category' => 'Earned and spent per category', - 'out_per_budget' => 'Spent per budget', - 'select_expense_revenue' => 'Select expense/revenue account', - 'multi_currency_report_sum' => 'Because this list contains accounts with multiple currencies, the sum(s) you see may not make sense. The report will always fall back to your default currency.', - 'sum_in_default_currency' => 'The sum will always be in your default currency.', - 'net_filtered_prefs' => 'This chart will never include accounts that have the "Include in net worth"-option unchecked.', + 'report_default' => 'Default financial report between :start and :end', + 'report_audit' => 'Transaction history overview between :start and :end', + 'report_category' => 'Category report between :start and :end', + 'report_double' => 'Expense/revenue account report between :start and :end', + 'report_budget' => 'Budget report between :start and :end', + 'report_tag' => 'Tag report between :start and :end', + 'quick_link_reports' => 'Quick links', + 'quick_link_examples' => 'These are just some example links to get you started. Check out the help pages under the (?)-button for information on all reports and the magic words you can use.', + 'quick_link_default_report' => 'Default financial report', + 'quick_link_audit_report' => 'Transaction history overview', + 'report_this_month_quick' => 'Current month, all accounts', + 'report_last_month_quick' => 'Last month, all accounts', + 'report_this_year_quick' => 'Current year, all accounts', + 'report_this_fiscal_year_quick' => 'Current fiscal year, all accounts', + 'report_all_time_quick' => 'All-time, all accounts', + 'reports_can_bookmark' => 'Remember that reports can be bookmarked.', + 'incomeVsExpenses' => 'Income vs. expenses', + 'accountBalances' => 'Account balances', + 'balanceStart' => 'Balance at start of period', + 'balanceEnd' => 'Balance at end of period', + 'splitByAccount' => 'Split by account', + 'coveredWithTags' => 'Covered with tags', + 'leftInBudget' => 'Left in budget', + 'left_in_debt' => 'Amount due', + 'sumOfSums' => 'Sum of sums', + 'noCategory' => '(no category)', + 'notCharged' => 'Not charged (yet)', + 'inactive' => 'Inactive', + 'active' => 'Active', + 'difference' => 'Difference', + 'money_flowing_in' => 'In', + 'money_flowing_out' => 'Out', + 'topX' => 'top :number', + 'show_full_list' => 'Show entire list', + 'show_only_top' => 'Show only top :number', + 'report_type' => 'Report type', + 'report_type_default' => 'Default financial report', + 'report_type_audit' => 'Transaction history overview (audit)', + 'report_type_category' => 'Category report', + 'report_type_budget' => 'Budget report', + 'report_type_tag' => 'Tag report', + 'report_type_double' => 'Expense/revenue account report', + 'more_info_help' => 'More information about these types of reports can be found in the help pages. Press the (?) icon in the top right corner.', + 'report_included_accounts' => 'Included accounts', + 'report_date_range' => 'Date range', + 'report_preset_ranges' => 'Pre-set ranges', + 'shared' => 'Shared', + 'fiscal_year' => 'Fiscal year', + 'income_entry' => 'Income from account ":name" between :start and :end', + 'expense_entry' => 'Expenses to account ":name" between :start and :end', + 'category_entry' => 'Expenses and income in category ":name" between :start and :end', + 'budget_spent_amount' => 'Expenses in budget ":budget" between :start and :end', + 'balance_amount' => 'Expenses in budget ":budget" paid from account ":account" between :start and :end', + 'no_audit_activity' => 'No activity was recorded on account :account_name between :start and :end.', + 'audit_end_balance' => 'Account balance of :account_name at the end of :end was: :balance', + 'reports_extra_options' => 'Extra options', + 'report_has_no_extra_options' => 'This report has no extra options', + 'reports_submit' => 'View report', + 'end_after_start_date' => 'End date of report must be after start date.', + 'select_category' => 'Select category(ies)', + 'select_budget' => 'Select budget(s).', + 'select_tag' => 'Select tag(s).', + 'income_per_category' => 'Income per category', + 'expense_per_category' => 'Expense per category', + 'expense_per_budget' => 'Expense per budget', + 'income_per_account' => 'Income per account', + 'expense_per_account' => 'Expense per account', + 'expense_per_tag' => 'Expense per tag', + 'income_per_tag' => 'Income per tag', + 'include_expense_not_in_budget' => 'Included expenses not in the selected budget(s)', + 'include_expense_not_in_account' => 'Included expenses not in the selected account(s)', + 'include_expense_not_in_category' => 'Included expenses not in the selected category(ies)', + 'include_income_not_in_category' => 'Included income not in the selected category(ies)', + 'include_income_not_in_account' => 'Included income not in the selected account(s)', + 'include_income_not_in_tags' => 'Included income not in the selected tag(s)', + 'include_expense_not_in_tags' => 'Included expenses not in the selected tag(s)', + 'everything_else' => 'Everything else', + 'income_and_expenses' => 'Income and expenses', + 'spent_average' => 'Spent (average)', + 'income_average' => 'Income (average)', + 'transaction_count' => 'Transaction count', + 'average_spending_per_account' => 'Average spending per account', + 'average_income_per_account' => 'Average income per account', + 'total' => 'Total', + 'description' => 'Description', + 'sum_of_period' => 'Sum of period', + 'average_in_period' => 'Average in period', + 'no_account_role' => '(no role)', + 'account_role_defaultAsset' => 'Default asset account', + 'account_role_sharedAsset' => 'Shared asset account', + 'account_role_savingAsset' => 'Savings account', + 'account_role_ccAsset' => 'Credit card', + 'account_role_cashWalletAsset' => 'Cash wallet', + 'budget_chart_click' => 'Please click on a budget name in the table above to see a chart.', + 'category_chart_click' => 'Please click on a category name in the table above to see a chart.', + 'in_out_accounts' => 'Earned and spent per combination', + 'in_out_accounts_per_asset' => 'Earned and spent (per asset account)', + 'in_out_per_category' => 'Earned and spent per category', + 'out_per_budget' => 'Spent per budget', + 'select_expense_revenue' => 'Select expense/revenue account', + 'multi_currency_report_sum' => 'Because this list contains accounts with multiple currencies, the sum(s) you see may not make sense. The report will always fall back to your default currency.', + 'sum_in_default_currency' => 'The sum will always be in your default currency.', + 'net_filtered_prefs' => 'This chart will never include accounts that have the "Include in net worth"-option unchecked.', // charts: - 'chart' => 'Chart', - 'month' => 'Month', - 'budget' => 'Budget', - 'spent' => 'Spent', - 'spent_capped' => 'Spent (capped)', - 'spent_in_budget' => 'Spent in budget', - 'left_to_spend' => 'Left to spend', - 'earned' => 'Earned', - 'overspent' => 'Overspent', - 'left' => 'Left', - 'max-amount' => 'Maximum amount', - 'min-amount' => 'Minimum amount', - 'journal-amount' => 'Current subscription entry', - 'name' => 'Name', - 'expires_at' => 'Expires at', - 'date' => 'Date', - 'date_and_time' => 'Date and time', - 'time' => 'Time', - 'paid' => 'Paid', - 'unpaid' => 'Unpaid', - 'day' => 'Day', - 'budgeted' => 'Budgeted', - 'period' => 'Period', - 'balance' => 'Balance', - 'in_out_period' => 'In + out this period', - 'sum' => 'Sum', - 'summary' => 'Summary', - 'average' => 'Average', - 'balanceFor' => 'Balance for :name', - 'no_tags' => '(no tags)', - 'nothing_found' => '(nothing found)', + 'chart' => 'Chart', + 'month' => 'Month', + 'budget' => 'Budget', + 'spent' => 'Spent', + 'spent_capped' => 'Spent (capped)', + 'spent_in_budget' => 'Spent in budget', + 'left_to_spend' => 'Left to spend', + 'earned' => 'Earned', + 'overspent' => 'Overspent', + 'left' => 'Left', + 'max-amount' => 'Maximum amount', + 'min-amount' => 'Minimum amount', + 'journal-amount' => 'Current subscription entry', + 'name' => 'Name', + 'expires_at' => 'Expires at', + 'date' => 'Date', + 'date_and_time' => 'Date and time', + 'time' => 'Time', + 'paid' => 'Paid', + 'unpaid' => 'Unpaid', + 'day' => 'Day', + 'budgeted' => 'Budgeted', + 'period' => 'Period', + 'balance' => 'Balance', + 'in_out_period' => 'In + out this period', + 'sum' => 'Sum', + 'summary' => 'Summary', + 'average' => 'Average', + 'balanceFor' => 'Balance for :name', + 'no_tags' => '(no tags)', + 'nothing_found' => '(nothing found)', // page settings and wizard dialogs - 'page_settings_header' => 'Page settings', - 'visible_columns' => 'Visible columns', - 'accounts_to_show' => 'Accounts to show', - 'active_accounts_only' => 'Active accounts only', - 'in_active_accounts_only' => 'Inactive accounts only', - 'show_all_accounts' => 'Show all accounts', - 'group_accounts' => 'Group accounts', + 'page_settings_header' => 'Page settings', + 'visible_columns' => 'Visible columns', + 'accounts_to_show' => 'Accounts to show', + 'active_accounts_only' => 'Active accounts only', + 'in_active_accounts_only' => 'Inactive accounts only', + 'show_all_accounts' => 'Show all accounts', + 'group_accounts' => 'Group accounts', // piggy banks: - 'event_history' => 'Event history', - 'add_money_to_piggy' => 'Add money to piggy bank ":name"', - 'piggy_bank' => 'Piggy bank', - 'new_piggy_bank' => 'New piggy bank', - 'store_piggy_bank' => 'Store new piggy bank', - 'stored_piggy_bank' => 'Store new piggy bank ":name"', - 'account_status' => 'Account status', - 'left_for_piggy_banks' => 'Left for piggy banks', - 'sum_of_piggy_banks' => 'Sum of piggy banks', - 'saved_so_far' => 'Saved so far', - 'left_to_save' => 'Left to save', - 'suggested_amount' => 'Suggested monthly amount to save', - 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"', - 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"', - 'add' => 'Add', - 'no_money_for_piggy' => 'You have no money to put in this piggy bank.', - 'suggested_savings_per_month' => 'Suggested per month', + 'event_history' => 'Event history', + 'add_money_to_piggy' => 'Add money to piggy bank ":name"', + 'piggy_bank' => 'Piggy bank', + 'new_piggy_bank' => 'New piggy bank', + 'store_piggy_bank' => 'Store new piggy bank', + 'stored_piggy_bank' => 'Store new piggy bank ":name"', + 'account_status' => 'Account status', + 'left_for_piggy_banks' => 'Left for piggy banks', + 'sum_of_piggy_banks' => 'Sum of piggy banks', + 'saved_so_far' => 'Saved so far', + 'saved_so_far_total' => 'Saved so far in total', + 'reset_history' => 'reset history', + 'reset_history_confirm' => 'Are you sure you want to reset the history of this piggy bank? This will make the chart match the piggy bank\'s amount again.', + 'piggy_history_reset' => 'The piggy bank history has been reset', + 'left_to_save' => 'Left to save', + 'suggested_amount' => 'Suggested monthly amount to save', + 'add_money_to_piggy_title' => 'Add money to piggy bank ":name"', + 'remove_money_from_piggy_title' => 'Remove money from piggy bank ":name"', + 'add' => 'Add', + 'no_money_for_piggy' => 'You have no money to put in this piggy bank.', + 'suggested_savings_per_month' => 'Suggested per month', - 'remove' => 'Remove', - 'max_amount_add' => 'The maximum amount you can add is', - 'max_amount_remove' => 'The maximum amount you can remove is', - 'update_piggy_button' => 'Update piggy bank', - 'update_piggy_title' => 'Update piggy bank ":name"', - 'updated_piggy_bank' => 'Updated piggy bank ":name"', - 'details' => 'Details', - 'events' => 'Events', - 'target_amount' => 'Target amount', - 'start_date' => 'Start date', - 'no_start_date' => 'No start date', - 'target_date' => 'Target date', - 'no_target_date' => 'No target date', - 'table' => 'Table', - 'delete_piggy_bank' => 'Delete piggy bank ":name"', - 'cannot_add_amount_piggy' => 'Could not add :amount to ":name".', - 'cannot_remove_from_piggy' => 'Could not remove :amount from ":name".', - 'deleted_piggy_bank' => 'Deleted piggy bank ":name"', - 'added_amount_to_piggy' => 'Added :amount to ":name"', - 'removed_amount_from_piggy' => 'Removed :amount from ":name"', - 'piggy_events' => 'Related piggy banks', + 'remove' => 'Remove', + 'max_amount_add' => 'The maximum amount you can add is', + 'max_amount_remove' => 'The maximum amount you can remove is', + 'update_piggy_button' => 'Update piggy bank', + 'update_piggy_title' => 'Update piggy bank ":name"', + 'updated_piggy_bank' => 'Updated piggy bank ":name"', + 'details' => 'Details', + 'events' => 'Events', + 'target_amount' => 'Target amount', + 'start_date' => 'Start date', + 'no_start_date' => 'No start date', + 'target_date' => 'Target date', + 'no_target_date' => 'No target date', + 'table' => 'Table', + 'delete_piggy_bank' => 'Delete piggy bank ":name"', + 'cannot_add_amount_piggy' => 'Could not add :amount to ":name".', + 'cannot_remove_from_piggy' => 'Could not remove :amount from ":name".', + 'deleted_piggy_bank' => 'Deleted piggy bank ":name"', + 'added_amount_to_piggy' => 'Added :amount to ":name"', + 'removed_amount_from_piggy' => 'Removed :amount from ":name"', + 'piggy_events' => 'Related piggy banks', // tags - 'delete_tag' => 'Delete tag ":tag"', - 'deleted_tag' => 'Deleted tag ":tag"', - 'new_tag' => 'Make new tag', - 'edit_tag' => 'Edit tag ":tag"', - 'updated_tag' => 'Updated tag ":tag"', - 'created_tag' => 'Tag ":tag" has been created!', + 'delete_tag' => 'Delete tag ":tag"', + 'deleted_tag' => 'Deleted tag ":tag"', + 'new_tag' => 'Make new tag', + 'edit_tag' => 'Edit tag ":tag"', + 'updated_tag' => 'Updated tag ":tag"', + 'created_tag' => 'Tag ":tag" has been created!', - 'transaction_journal_information' => 'Transaction information', - 'transaction_journal_amount' => 'Amount information', - 'transaction_journal_meta' => 'Meta information', - 'transaction_journal_more' => 'More information', - 'basic_journal_information' => 'Basic transaction information', - 'transaction_journal_extra' => 'Extra information', - 'att_part_of_journal' => 'Stored under ":journal"', - 'total_amount' => 'Total amount', - 'number_of_decimals' => 'Number of decimals', + 'transaction_journal_information' => 'Transaction information', + 'transaction_journal_amount' => 'Amount information', + 'transaction_journal_meta' => 'Meta information', + 'transaction_journal_more' => 'More information', + 'basic_journal_information' => 'Basic transaction information', + 'transaction_journal_extra' => 'Extra information', + 'att_part_of_journal' => 'Stored under ":journal"', + 'total_amount' => 'Total amount', + 'number_of_decimals' => 'Number of decimals', // administration - 'invite_is_already_redeemed' => 'The invite to ":address" has already been redeemed.', - 'invite_is_deleted' => 'The invite to ":address" has been deleted.', - 'invite_new_user_title' => 'Invite new user', - 'invite_new_user_text' => 'As an administrator, you can invite users to register to your Firefly III installation. Using the direct link you can share with them, they will be able to register an account. The invited user and their invite link will appear in the table below. You are free to share the invitation link with them.', - 'invited_user_mail' => 'Email address', - 'invite_user' => 'Invite user', - 'user_is_invited' => 'Email address ":address" was invited to Firefly III', - 'administration' => 'Administration', - 'system_settings' => 'System settings', - 'code_already_used' => 'Invite code has been used', - 'user_administration' => 'User administration', - 'list_all_users' => 'All users', - 'all_users' => 'All users', - 'instance_configuration' => 'Configuration', - 'firefly_instance_configuration' => 'Firefly III configuration', - 'setting_single_user_mode' => 'Single user mode', - 'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as well, assuming they can reach it (when it is connected to the internet).', - 'store_configuration' => 'Store configuration', - 'single_user_administration' => 'User administration for :email', - 'edit_user' => 'Edit user :email', - 'hidden_fields_preferences' => 'You can enable more transaction options in your preferences.', - 'user_data_information' => 'User data', - 'user_information' => 'User information', - 'total_size' => 'total size', - 'budget_or_budgets' => ':count budget|:count budgets', - 'budgets_with_limits' => ':count budget with configured amount|:count budgets with configured amount', - 'nr_of_rules_in_total_groups' => ':count_rules rule(s) in :count_groups rule group(s)', - 'tag_or_tags' => ':count tag|:count tags', - 'configuration_updated' => 'The configuration has been updated', - 'setting_is_demo_site' => 'Demo site', - 'setting_is_demo_site_explain' => 'If you check this box, this installation will behave as if it is the demo site, which can have weird side effects.', - 'block_code_bounced' => 'Email message(s) bounced', - 'block_code_expired' => 'Demo account expired', - 'no_block_code' => 'No reason for block or user not blocked', - 'demo_user_export' => 'The demo user cannot export data', - 'block_code_email_changed' => 'User has not yet confirmed new email address', - 'admin_update_email' => 'Contrary to the profile page, the user will NOT be notified their email address has changed!', - 'update_user' => 'Update user', - 'updated_user' => 'User data has been changed.', - 'delete_user' => 'Delete user :email', - 'user_deleted' => 'The user has been deleted', - 'send_test_email' => 'Send test email message', - 'send_test_email_text' => 'To see if your installation is capable of sending a notification, please press this button. You will not see an error here (if any), the log files will reflect any errors. You can press this button as many times as you like. There is no spam control. The message will be sent to :email and should arrive shortly.', - 'send_message' => 'Send message', - 'send_test_triggered' => 'Test was triggered. Check your inbox and the log files.', - 'give_admin_careful' => 'Users who are given admin rights can take away yours. Be careful.', - 'admin_maintanance_title' => 'Maintenance', - 'admin_maintanance_expl' => 'Some nifty buttons for Firefly III maintenance', - 'admin_maintenance_clear_cache' => 'Clear cache', - 'owner_notifications' => 'Admin notifications', - 'owner_notifications_expl' => 'The following notifications can be enabled or disabled by the administrator. It will be sent over ALL configured channels. Some channels are configured in your environment variables, others can be set here.', - 'channel_settings' => 'Settings for notification channels', - 'notification_test_failed' => 'Notification test for channel ":channel" failed. The logs will have more details.', - 'notification_test_executed' => 'Notification test for channel ":channel" executed. Check your logs for details.', - 'settings_notifications' => 'Settings for notifications', - 'title_owner_notifications' => 'Owner notifications', - 'owner_notification_check_user_new_reg' => 'User gets post-registration welcome message', - 'owner_notification_check_admin_new_reg' => 'Administrator(s) get new user registration notification', - 'owner_notification_check_new_version' => 'A new version is available', - 'owner_notification_check_invite_created' => 'A user is invited to Firefly III', - 'owner_notification_check_invite_redeemed' => 'A user invitation is redeemed', - 'owner_notification_check_unknown_user_attempt' => 'An unknown user tries to login', - 'all_invited_users' => 'All invited users', - 'save_notification_settings' => 'Save settings', - 'notification_settings' => 'Settings for notifications', - 'notification_settings_saved' => 'The notification settings have been saved', - 'available_channels_title' => 'Available channels', - 'available_channels_expl' => 'These channels are available to send notifications over. To test your configuration, use the buttons below. Please note that the buttons have no spam control.', - 'notification_channel_name_email' => 'Email', - 'slack_discord_double' => 'The Slack notification channel can also send notifications to Discord.', - 'notification_channel_name_slack' => 'Slack', - 'notification_channel_name_ntfy' => 'Ntfy.sh', - 'notification_channel_name_pushover' => 'Pushover', - 'notification_channel_name_gotify' => 'Gotify', - 'notification_channel_name_pushbullet' => 'Pushbullet', - 'channel_not_available' => 'not available', - 'configure_channel_in_env' => 'needs environment variables', - 'test_notification_channel_name_email' => 'Test email', - 'test_notification_channel_name_slack' => 'Test Slack', - 'test_notification_channel_name_ntfy' => 'Test Ntfy.sh', - 'test_notification_channel_name_pushover' => 'Test Pushover', - 'test_notification_channel_name_gotify' => 'Test Gotify', - 'test_notification_channel_name_pushbullet' => 'Test Pushbullet', + 'invite_is_already_redeemed' => 'The invite to ":address" has already been redeemed.', + 'invite_is_deleted' => 'The invite to ":address" has been deleted.', + 'invite_new_user_title' => 'Invite new user', + 'invite_new_user_text' => 'As an administrator, you can invite users to register to your Firefly III installation. Using the direct link you can share with them, they will be able to register an account. The invited user and their invite link will appear in the table below. You are free to share the invitation link with them.', + 'invited_user_mail' => 'Email address', + 'invite_user' => 'Invite user', + 'user_is_invited' => 'Email address ":address" was invited to Firefly III', + 'administration' => 'Administration', + 'system_settings' => 'System settings', + 'code_already_used' => 'Invite code has been used', + 'user_administration' => 'User administration', + 'list_all_users' => 'All users', + 'all_users' => 'All users', + 'instance_configuration' => 'Configuration', + 'firefly_instance_configuration' => 'Firefly III configuration', + 'setting_single_user_mode' => 'Single user mode', + 'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as well, assuming they can reach it (when it is connected to the internet).', + 'store_configuration' => 'Store configuration', + 'single_user_administration' => 'User administration for :email', + 'edit_user' => 'Edit user :email', + 'hidden_fields_preferences' => 'You can enable more transaction options in your preferences.', + 'user_data_information' => 'User data', + 'user_information' => 'User information', + 'total_size' => 'total size', + 'budget_or_budgets' => ':count budget|:count budgets', + 'budgets_with_limits' => ':count budget with configured amount|:count budgets with configured amount', + 'nr_of_rules_in_total_groups' => ':count_rules rule(s) in :count_groups rule group(s)', + 'tag_or_tags' => ':count tag|:count tags', + 'configuration_updated' => 'The configuration has been updated', + 'setting_is_demo_site' => 'Demo site', + 'setting_is_demo_site_explain' => 'If you check this box, this installation will behave as if it is the demo site, which can have weird side effects.', + 'block_code_bounced' => 'Email message(s) bounced', + 'block_code_expired' => 'Demo account expired', + 'no_block_code' => 'No reason for block or user not blocked', + 'demo_user_export' => 'The demo user cannot export data', + 'block_code_email_changed' => 'User has not yet confirmed new email address', + 'admin_update_email' => 'Contrary to the profile page, the user will NOT be notified their email address has changed!', + 'update_user' => 'Update user', + 'updated_user' => 'User data has been changed.', + 'delete_user' => 'Delete user :email', + 'user_deleted' => 'The user has been deleted', + 'send_test_email' => 'Send test email message', + 'send_test_email_text' => 'To see if your installation is capable of sending a notification, please press this button. You will not see an error here (if any), the log files will reflect any errors. You can press this button as many times as you like. There is no spam control. The message will be sent to :email and should arrive shortly.', + 'send_message' => 'Send message', + 'send_test_triggered' => 'Test was triggered. Check your inbox and the log files.', + 'give_admin_careful' => 'Users who are given admin rights can take away yours. Be careful.', + 'admin_maintanance_title' => 'Maintenance', + 'admin_maintanance_expl' => 'Some nifty buttons for Firefly III maintenance', + 'admin_maintenance_clear_cache' => 'Clear cache', + 'owner_notifications' => 'Admin notifications', + 'owner_notifications_expl' => 'The following notifications can be enabled or disabled by the administrator. It will be sent over ALL configured channels. Some channels are configured in your environment variables, others can be set here.', + 'channel_settings' => 'Settings for notification channels', + 'notification_test_failed' => 'Notification test for channel ":channel" failed. The logs will have more details.', + 'notification_test_executed' => 'Notification test for channel ":channel" executed. Check your logs for details.', + 'settings_notifications' => 'Settings for notifications', + 'title_owner_notifications' => 'Owner notifications', + 'owner_notification_check_user_new_reg' => 'User gets post-registration welcome message', + 'owner_notification_check_admin_new_reg' => 'Administrator(s) get new user registration notification', + 'owner_notification_check_new_version' => 'A new version is available', + 'owner_notification_check_invite_created' => 'A user is invited to Firefly III', + 'owner_notification_check_invite_redeemed' => 'A user invitation is redeemed', + 'owner_notification_check_unknown_user_attempt' => 'An unknown user tries to login', + 'all_invited_users' => 'All invited users', + 'save_notification_settings' => 'Save settings', + 'notification_settings' => 'Settings for notifications', + 'notification_settings_saved' => 'The notification settings have been saved', + 'available_channels_title' => 'Available channels', + 'available_channels_expl' => 'These channels are available to send notifications over. To test your configuration, use the buttons below. Please note that the buttons have no spam control.', + 'notification_channel_name_email' => 'Email', + 'slack_discord_double' => 'The Slack notification channel can also send notifications to Discord.', + 'notification_channel_name_slack' => 'Slack', + 'notification_channel_name_ntfy' => 'Ntfy.sh', + 'notification_channel_name_pushover' => 'Pushover', + 'notification_channel_name_gotify' => 'Gotify', + 'notification_channel_name_pushbullet' => 'Pushbullet', + 'channel_not_available' => 'not available', + 'configure_channel_in_env' => 'needs environment variables', + 'test_notification_channel_name_email' => 'Test email', + 'test_notification_channel_name_slack' => 'Test Slack', + 'test_notification_channel_name_ntfy' => 'Test Ntfy.sh', + 'test_notification_channel_name_pushover' => 'Test Pushover', + 'test_notification_channel_name_gotify' => 'Test Gotify', + 'test_notification_channel_name_pushbullet' => 'Test Pushbullet', - 'split_transaction_title' => 'Description of the split transaction', - 'split_transaction_title_help' => 'If you create a split transaction, there must be a global description for all splits of the transaction.', - 'split_title_help' => 'If you create a split transaction, there must be a global description for all splits of the transaction.', - 'you_create_transfer' => 'You\'re creating a transfer.', - 'you_create_withdrawal' => 'You\'re creating a withdrawal.', - 'you_create_deposit' => 'You\'re creating a deposit.', + 'split_transaction_title' => 'Description of the split transaction', + 'split_transaction_title_help' => 'If you create a split transaction, there must be a global description for all splits of the transaction.', + 'split_title_help' => 'If you create a split transaction, there must be a global description for all splits of the transaction.', + 'you_create_transfer' => 'You\'re creating a transfer.', + 'you_create_withdrawal' => 'You\'re creating a withdrawal.', + 'you_create_deposit' => 'You\'re creating a deposit.', // links - 'journal_link_configuration' => 'Transaction links configuration', - 'create_new_link_type' => 'Create new link type', - 'store_new_link_type' => 'Store new link type', - 'update_link_type' => 'Update link type', - 'edit_link_type' => 'Edit link type ":name"', - 'updated_link_type' => 'Updated link type ":name"', - 'delete_link_type' => 'Delete link type ":name"', - 'deleted_link_type' => 'Deleted link type ":name"', - 'stored_new_link_type' => 'Store new link type ":name"', - 'cannot_edit_link_type' => 'Cannot edit link type ":name"', - 'link_type_help_name' => 'Ie. "Duplicates"', - 'link_type_help_inward' => 'Ie. "duplicates"', - 'link_type_help_outward' => 'Ie. "is duplicated by"', - 'save_connections_by_moving' => 'Save the link between these transactions by moving them to another link type:', - 'do_not_save_connection' => '(do not save connection)', - 'link_transaction' => 'Link transaction', - 'link_to_other_transaction' => 'Link this transaction to another transaction', - 'select_transaction_to_link' => 'Select a transaction to link this transaction to. The links are currently unused in Firefly III (apart from being shown), but I plan to change this in the future. Use the search box to select a transaction either by title or by ID. If you want to add custom link types, check out the settings.', - 'this_transaction' => 'This transaction', - 'transaction' => 'Transaction', - 'comments' => 'Comments', - 'link_notes' => 'Any notes you wish to store with the link.', - 'invalid_link_selection' => 'Cannot link these transactions', - 'selected_transaction' => 'Selected transaction', - 'journals_linked' => 'Transactions are linked.', - 'journals_error_linked' => 'These transactions are already linked.', - 'journals_link_to_self' => 'You cannot link a transaction to itself', - 'journal_links' => 'Transaction links', - 'this_withdrawal' => 'This withdrawal', - 'this_deposit' => 'This deposit', - 'this_transfer' => 'This transfer', - 'overview_for_link' => 'Overview for link type ":name"', - 'source_transaction' => 'Source transaction', - 'link_description' => 'Link description', - 'destination_transaction' => 'Destination transaction', - 'delete_journal_link' => 'Delete the link between :source and :destination', - 'deleted_link' => 'Deleted link', + 'journal_link_configuration' => 'Transaction links configuration', + 'create_new_link_type' => 'Create new link type', + 'store_new_link_type' => 'Store new link type', + 'update_link_type' => 'Update link type', + 'edit_link_type' => 'Edit link type ":name"', + 'updated_link_type' => 'Updated link type ":name"', + 'delete_link_type' => 'Delete link type ":name"', + 'deleted_link_type' => 'Deleted link type ":name"', + 'stored_new_link_type' => 'Store new link type ":name"', + 'cannot_edit_link_type' => 'Cannot edit link type ":name"', + 'link_type_help_name' => 'Ie. "Duplicates"', + 'link_type_help_inward' => 'Ie. "duplicates"', + 'link_type_help_outward' => 'Ie. "is duplicated by"', + 'save_connections_by_moving' => 'Save the link between these transactions by moving them to another link type:', + 'do_not_save_connection' => '(do not save connection)', + 'link_transaction' => 'Link transaction', + 'link_to_other_transaction' => 'Link this transaction to another transaction', + 'select_transaction_to_link' => 'Select a transaction to link this transaction to. The links are currently unused in Firefly III (apart from being shown), but I plan to change this in the future. Use the search box to select a transaction either by title or by ID. If you want to add custom link types, check out the settings.', + 'this_transaction' => 'This transaction', + 'transaction' => 'Transaction', + 'comments' => 'Comments', + 'link_notes' => 'Any notes you wish to store with the link.', + 'invalid_link_selection' => 'Cannot link these transactions', + 'selected_transaction' => 'Selected transaction', + 'journals_linked' => 'Transactions are linked.', + 'journals_error_linked' => 'These transactions are already linked.', + 'journals_link_to_self' => 'You cannot link a transaction to itself', + 'journal_links' => 'Transaction links', + 'this_withdrawal' => 'This withdrawal', + 'this_deposit' => 'This deposit', + 'this_transfer' => 'This transfer', + 'overview_for_link' => 'Overview for link type ":name"', + 'source_transaction' => 'Source transaction', + 'link_description' => 'Link description', + 'destination_transaction' => 'Destination transaction', + 'delete_journal_link' => 'Delete the link between :source and :destination', + 'deleted_link' => 'Deleted link', // link translations: - 'Paid_name' => 'Paid', - 'Refund_name' => 'Refund', - 'Reimbursement_name' => 'Reimbursement', - 'Related_name' => 'Related', - 'relates to_inward' => 'relates to', - 'is (partially) refunded by_inward' => 'is (partially) refunded by', - 'is (partially) paid for by_inward' => 'is (partially) paid for by', - 'is (partially) reimbursed by_inward' => 'is (partially) reimbursed by', - 'inward_transaction' => 'Inward transaction', - 'outward_transaction' => 'Outward transaction', - 'relates to_outward' => 'relates to', - '(partially) refunds_outward' => '(partially) refunds', - '(partially) pays for_outward' => '(partially) pays for', - '(partially) reimburses_outward' => '(partially) reimburses', - 'is (partially) refunded by' => 'is (partially) refunded by', - 'is (partially) paid for by' => 'is (partially) paid for by', - 'is (partially) reimbursed by' => 'is (partially) reimbursed by', - 'relates to' => 'relates to', - '(partially) refunds' => '(partially) refunds', - '(partially) pays for' => '(partially) pays for', - '(partially) reimburses' => '(partially) reimburses', + 'Paid_name' => 'Paid', + 'Refund_name' => 'Refund', + 'Reimbursement_name' => 'Reimbursement', + 'Related_name' => 'Related', + 'relates to_inward' => 'relates to', + 'is (partially) refunded by_inward' => 'is (partially) refunded by', + 'is (partially) paid for by_inward' => 'is (partially) paid for by', + 'is (partially) reimbursed by_inward' => 'is (partially) reimbursed by', + 'inward_transaction' => 'Inward transaction', + 'outward_transaction' => 'Outward transaction', + 'relates to_outward' => 'relates to', + '(partially) refunds_outward' => '(partially) refunds', + '(partially) pays for_outward' => '(partially) pays for', + '(partially) reimburses_outward' => '(partially) reimburses', + 'is (partially) refunded by' => 'is (partially) refunded by', + 'is (partially) paid for by' => 'is (partially) paid for by', + 'is (partially) reimbursed by' => 'is (partially) reimbursed by', + 'relates to' => 'relates to', + '(partially) refunds' => '(partially) refunds', + '(partially) pays for' => '(partially) pays for', + '(partially) reimburses' => '(partially) reimburses', // split a transaction: - 'splits' => 'Splits', - 'add_another_split' => 'Add another split', - 'cannot_edit_opening_balance' => 'You cannot edit the opening balance of an account.', - 'no_edit_multiple_left' => 'You have selected no valid transactions to edit.', - 'breadcrumb_convert_group' => 'Convert transaction', - 'convert_invalid_source' => 'Source information is invalid for transaction #%d.', - 'convert_invalid_destination' => 'Destination information is invalid for transaction #%d.', - 'create_another' => 'After storing, return here to create another one.', - 'after_update_create_another' => 'After updating, return here to continue editing.', - 'store_as_new' => 'Store as a new transaction instead of updating.', - 'reset_after' => 'Reset form after submission', - 'errors_submission' => 'There was something wrong with your submission. Please check out the errors below.', - 'errors_submission_v2' => 'There was something wrong with your submission. Please check out the errors below: {{errorMessage}}', - 'transaction_expand_split' => 'Expand split', - 'transaction_remove_split' => 'Remove split', - 'transaction_collapse_split' => 'Collapse split', + 'splits' => 'Splits', + 'add_another_split' => 'Add another split', + 'cannot_edit_opening_balance' => 'You cannot edit the opening balance of an account.', + 'no_edit_multiple_left' => 'You have selected no valid transactions to edit.', + 'breadcrumb_convert_group' => 'Convert transaction', + 'convert_invalid_source' => 'Source information is invalid for transaction #%d.', + 'convert_invalid_destination' => 'Destination information is invalid for transaction #%d.', + 'create_another' => 'After storing, return here to create another one.', + 'after_update_create_another' => 'After updating, return here to continue editing.', + 'store_as_new' => 'Store as a new transaction instead of updating.', + 'reset_after' => 'Reset form after submission', + 'errors_submission' => 'There was something wrong with your submission. Please check out the errors below.', + 'errors_submission_v2' => 'There was something wrong with your submission. Please check out the errors below: {{errorMessage}}', + 'transaction_expand_split' => 'Expand split', + 'transaction_remove_split' => 'Remove split', + 'transaction_collapse_split' => 'Collapse split', // object groups - 'default_group_title_name' => '(ungrouped)', - 'default_group_title_name_plain' => 'ungrouped', + 'default_group_title_name' => '(ungrouped)', + 'default_group_title_name_plain' => 'ungrouped', // empty lists? no objects? instructions: - 'no_accounts_title_asset' => 'Let\'s create an asset account!', - 'no_accounts_intro_asset' => 'You have no asset accounts yet. Asset accounts are your main accounts: your checking account, savings account, shared account or even your credit card.', - 'no_accounts_imperative_asset' => 'To start using Firefly III you must create at least one asset account. Let\'s do so now:', - 'no_accounts_create_asset' => 'Create an asset account', - 'no_accounts_title_expense' => 'Let\'s create an expense account!', - 'no_accounts_intro_expense' => 'You have no expense accounts yet. Expense accounts are the places where you spend money, such as shops and supermarkets.', - 'no_accounts_imperative_expense' => 'Expense accounts are created automatically when you create transactions, but you can create one manually too, if you want. Let\'s create one now:', - 'no_accounts_create_expense' => 'Create an expense account', - 'no_accounts_title_revenue' => 'Let\'s create a revenue account!', - 'no_accounts_intro_revenue' => 'You have no revenue accounts yet. Revenue accounts are the places where you receive money from, such as your employer.', - 'no_accounts_imperative_revenue' => 'Revenue accounts are created automatically when you create transactions, but you can create one manually too, if you want. Let\'s create one now:', - 'no_accounts_create_revenue' => 'Create a revenue account', - 'no_accounts_title_liabilities' => 'Let\'s create a liability!', - 'no_accounts_intro_liabilities' => 'You have no liabilities yet. Liabilities are the accounts that register your (student) loans and other debts.', - 'no_accounts_imperative_liabilities' => 'You don\'t have to use this feature, but it can be useful if you want to keep track of these things.', - 'no_accounts_create_liabilities' => 'Create a liability', - 'no_budgets_title_default' => 'Let\'s create a budget', - 'no_rules_title_default' => 'Let\'s create a rule', - 'no_budgets_intro_default' => 'You have no budgets yet. Budgets are used to organize your expenses into logical groups, which you can give a soft-cap to limit your expenses.', - 'no_rules_intro_default' => 'You have no rules yet. Rules are powerful automations that can handle transactions for you.', - 'no_rules_imperative_default' => 'Rules can be very useful when you\'re managing transactions. Let\'s create one now:', - 'no_budgets_imperative_default' => 'Budgets are the basic tools of financial management. Let\'s create one now:', - 'no_budgets_create_default' => 'Create a budget', - 'no_rules_create_default' => 'Create a rule', - 'no_categories_title_default' => 'Let\'s create a category!', - 'no_categories_intro_default' => 'You have no categories yet. Categories are used to fine tune your transactions and label them with their designated category.', - 'no_categories_imperative_default' => 'Categories are created automatically when you create transactions, but you can create one manually too. Let\'s create one now:', - 'no_categories_create_default' => 'Create a category', - 'no_tags_title_default' => 'Let\'s create a tag!', - 'no_tags_intro_default' => 'You have no tags yet. Tags are used to fine tune your transactions and label them with specific keywords.', - 'no_tags_imperative_default' => 'Tags are created automatically when you create transactions, but you can create one manually too. Let\'s create one now:', - 'no_tags_create_default' => 'Create a tag', - 'no_transactions_title_withdrawal' => 'Let\'s create an expense!', - 'no_transactions_intro_withdrawal' => 'You have no expenses yet. You should create expenses to start managing your finances.', - 'no_transactions_imperative_withdrawal' => 'Have you spent some money? Then you should write it down:', - 'no_transactions_create_withdrawal' => 'Create an expense', - 'no_transactions_title_deposit' => 'Let\'s create some income!', - 'no_transactions_intro_deposit' => 'You have no recorded income yet. You should create income entries to start managing your finances.', - 'no_transactions_imperative_deposit' => 'Have you received some money? Then you should write it down:', - 'no_transactions_create_deposit' => 'Create a deposit', - 'no_transactions_title_transfers' => 'Let\'s create a transfer!', - 'no_transactions_intro_transfers' => 'You have no transfers yet. When you move money between asset accounts, it is recorded as a transfer.', - 'no_transactions_imperative_transfers' => 'Have you moved some money around? Then you should write it down:', - 'no_transactions_create_transfers' => 'Create a transfer', - 'no_piggies_title_default' => 'Let\'s create a piggy bank!', - 'no_piggies_intro_default' => 'You have no piggy banks yet. You can create piggy banks to divide your savings and keep track of what you\'re saving up for.', - 'no_piggies_imperative_default' => 'Do you have things you\'re saving money for? Create a piggy bank and keep track:', - 'no_piggies_create_default' => 'Create a new piggy bank', - 'no_bills_title_default' => 'Let\'s create a subscription!', - 'no_bills_intro_default' => 'You have no subscriptions yet. You can create subscriptions to keep track of regular expenses, like your rent or insurance.', - 'no_bills_imperative_default' => 'Do you have such regular subscriptions? Create a subscription and keep track of your payments:', - 'no_bills_create_default' => 'Create a subscription', + 'no_accounts_title_asset' => 'Let\'s create an asset account!', + 'no_accounts_intro_asset' => 'You have no asset accounts yet. Asset accounts are your main accounts: your checking account, savings account, shared account or even your credit card.', + 'no_accounts_imperative_asset' => 'To start using Firefly III you must create at least one asset account. Let\'s do so now:', + 'no_accounts_create_asset' => 'Create an asset account', + 'no_accounts_title_expense' => 'Let\'s create an expense account!', + 'no_accounts_intro_expense' => 'You have no expense accounts yet. Expense accounts are the places where you spend money, such as shops and supermarkets.', + 'no_accounts_imperative_expense' => 'Expense accounts are created automatically when you create transactions, but you can create one manually too, if you want. Let\'s create one now:', + 'no_accounts_create_expense' => 'Create an expense account', + 'no_accounts_title_revenue' => 'Let\'s create a revenue account!', + 'no_accounts_intro_revenue' => 'You have no revenue accounts yet. Revenue accounts are the places where you receive money from, such as your employer.', + 'no_accounts_imperative_revenue' => 'Revenue accounts are created automatically when you create transactions, but you can create one manually too, if you want. Let\'s create one now:', + 'no_accounts_create_revenue' => 'Create a revenue account', + 'no_accounts_title_liabilities' => 'Let\'s create a liability!', + 'no_accounts_intro_liabilities' => 'You have no liabilities yet. Liabilities are the accounts that register your (student) loans and other debts.', + 'no_accounts_imperative_liabilities' => 'You don\'t have to use this feature, but it can be useful if you want to keep track of these things.', + 'no_accounts_create_liabilities' => 'Create a liability', + 'no_budgets_title_default' => 'Let\'s create a budget', + 'no_rules_title_default' => 'Let\'s create a rule', + 'no_budgets_intro_default' => 'You have no budgets yet. Budgets are used to organize your expenses into logical groups, which you can give a soft-cap to limit your expenses.', + 'no_rules_intro_default' => 'You have no rules yet. Rules are powerful automations that can handle transactions for you.', + 'no_rules_imperative_default' => 'Rules can be very useful when you\'re managing transactions. Let\'s create one now:', + 'no_budgets_imperative_default' => 'Budgets are the basic tools of financial management. Let\'s create one now:', + 'no_budgets_create_default' => 'Create a budget', + 'no_rules_create_default' => 'Create a rule', + 'no_categories_title_default' => 'Let\'s create a category!', + 'no_categories_intro_default' => 'You have no categories yet. Categories are used to fine tune your transactions and label them with their designated category.', + 'no_categories_imperative_default' => 'Categories are created automatically when you create transactions, but you can create one manually too. Let\'s create one now:', + 'no_categories_create_default' => 'Create a category', + 'no_tags_title_default' => 'Let\'s create a tag!', + 'no_tags_intro_default' => 'You have no tags yet. Tags are used to fine tune your transactions and label them with specific keywords.', + 'no_tags_imperative_default' => 'Tags are created automatically when you create transactions, but you can create one manually too. Let\'s create one now:', + 'no_tags_create_default' => 'Create a tag', + 'no_transactions_title_withdrawal' => 'Let\'s create an expense!', + 'no_transactions_intro_withdrawal' => 'You have no expenses yet. You should create expenses to start managing your finances.', + 'no_transactions_imperative_withdrawal' => 'Have you spent some money? Then you should write it down:', + 'no_transactions_create_withdrawal' => 'Create an expense', + 'no_transactions_title_deposit' => 'Let\'s create some income!', + 'no_transactions_intro_deposit' => 'You have no recorded income yet. You should create income entries to start managing your finances.', + 'no_transactions_imperative_deposit' => 'Have you received some money? Then you should write it down:', + 'no_transactions_create_deposit' => 'Create a deposit', + 'no_transactions_title_transfers' => 'Let\'s create a transfer!', + 'no_transactions_intro_transfers' => 'You have no transfers yet. When you move money between asset accounts, it is recorded as a transfer.', + 'no_transactions_imperative_transfers' => 'Have you moved some money around? Then you should write it down:', + 'no_transactions_create_transfers' => 'Create a transfer', + 'no_piggies_title_default' => 'Let\'s create a piggy bank!', + 'no_piggies_intro_default' => 'You have no piggy banks yet. You can create piggy banks to divide your savings and keep track of what you\'re saving up for.', + 'no_piggies_imperative_default' => 'Do you have things you\'re saving money for? Create a piggy bank and keep track:', + 'no_piggies_create_default' => 'Create a new piggy bank', + 'no_bills_title_default' => 'Let\'s create a subscription!', + 'no_bills_intro_default' => 'You have no subscriptions yet. You can create subscriptions to keep track of regular expenses, like your rent or insurance.', + 'no_bills_imperative_default' => 'Do you have such regular subscriptions? Create a subscription and keep track of your payments:', + 'no_bills_create_default' => 'Create a subscription', // recurring transactions - 'recurrence_max_count' => 'This recurring transactions will be created at most :max time(s), and has been created :count time(s) already.', - 'create_right_now' => 'Create right now', - 'no_new_transaction_in_recurrence' => 'No new transaction was created. Perhaps it was already fired for this date?', - 'recurrences' => 'Recurring transactions', - 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', - 'recurring_calendar_view' => 'Calendar', - 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', - 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', - 'no_recurring_imperative_default' => 'This is a pretty advanced feature but it can be extremely useful. Make sure you read the documentation (?)-icon in the top right corner) before you continue.', - 'no_recurring_create_default' => 'Create a recurring transaction', - 'make_new_recurring' => 'Create a recurring transaction', - 'recurring_daily' => 'Every day', - 'recurring_weekly' => 'Every week on :weekday', - 'recurring_weekly_skip' => 'Every :skip(st/nd/rd/th) week on :weekday', - 'recurring_monthly' => 'Every month on the :dayOfMonth(st/nd/rd/th) day', - 'recurring_monthly_skip' => 'Every :skip(st/nd/rd/th) month on the :dayOfMonth(st/nd/rd/th) day', - 'recurring_ndom' => 'Every month on the :dayOfMonth(st/nd/rd/th) :weekday', - 'recurring_yearly' => 'Every year on :date', - 'overview_for_recurrence' => 'Overview for recurring transaction ":title"', - 'warning_duplicates_repetitions' => 'In rare instances, dates appear twice in this list. This can happen when multiple repetitions collide. Firefly III will always generate one transaction per day.', - 'created_transactions' => 'Related transactions', - 'expected_withdrawals' => 'Expected withdrawals', - 'expected_deposits' => 'Expected deposits', - 'expected_transfers' => 'Expected transfers', - 'created_withdrawals' => 'Created withdrawals', - 'created_deposits' => 'Created deposits', - 'created_transfers' => 'Created transfers', - 'recurring_info' => 'Recurring transaction :count / :total', - 'created_from_recurrence' => 'Created from recurring transaction ":title" (#:id)', - 'recurring_never_cron' => 'It seems the cron job that is necessary to support recurring transactions has never run. This is of course normal when you have just installed Firefly III, but this should be something to set up as soon as possible. Please check out the help-pages using the (?)-icon in the top right corner of the page.', - 'recurring_cron_long_ago' => 'It looks like it has been more than 36 hours since the cron job to support recurring transactions has fired for the last time. Are you sure it has been set up correctly? Please check out the help-pages using the (?)-icon in the top right corner of the page.', + 'recurrence_max_count' => 'This recurring transactions will be created at most :max time(s), and has been created :count time(s) already.', + 'create_right_now' => 'Create right now', + 'no_new_transaction_in_recurrence' => 'No new transaction was created. Perhaps it was already fired for this date?', + 'recurrences' => 'Recurring transactions', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', + 'recurring_calendar_view' => 'Calendar', + 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', + 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', + 'no_recurring_imperative_default' => 'This is a pretty advanced feature but it can be extremely useful. Make sure you read the documentation (?)-icon in the top right corner) before you continue.', + 'no_recurring_create_default' => 'Create a recurring transaction', + 'make_new_recurring' => 'Create a recurring transaction', + 'recurring_daily' => 'Every day', + 'recurring_weekly' => 'Every week on :weekday', + 'recurring_weekly_skip' => 'Every :skip(st/nd/rd/th) week on :weekday', + 'recurring_monthly' => 'Every month on the :dayOfMonth(st/nd/rd/th) day', + 'recurring_monthly_skip' => 'Every :skip(st/nd/rd/th) month on the :dayOfMonth(st/nd/rd/th) day', + 'recurring_ndom' => 'Every month on the :dayOfMonth(st/nd/rd/th) :weekday', + 'recurring_yearly' => 'Every year on :date', + 'overview_for_recurrence' => 'Overview for recurring transaction ":title"', + 'warning_duplicates_repetitions' => 'In rare instances, dates appear twice in this list. This can happen when multiple repetitions collide. Firefly III will always generate one transaction per day.', + 'created_transactions' => 'Related transactions', + 'expected_withdrawals' => 'Expected withdrawals', + 'expected_deposits' => 'Expected deposits', + 'expected_transfers' => 'Expected transfers', + 'created_withdrawals' => 'Created withdrawals', + 'created_deposits' => 'Created deposits', + 'created_transfers' => 'Created transfers', + 'recurring_info' => 'Recurring transaction :count / :total', + 'created_from_recurrence' => 'Created from recurring transaction ":title" (#:id)', + 'recurring_never_cron' => 'It seems the cron job that is necessary to support recurring transactions has never run. This is of course normal when you have just installed Firefly III, but this should be something to set up as soon as possible. Please check out the help-pages using the (?)-icon in the top right corner of the page.', + 'recurring_cron_long_ago' => 'It looks like it has been more than 36 hours since the cron job to support recurring transactions has fired for the last time. Are you sure it has been set up correctly? Please check out the help-pages using the (?)-icon in the top right corner of the page.', - 'create_new_recurrence' => 'Create new recurring transaction', - 'help_first_date' => 'Indicate the first expected recurrence. This must be in the future.', - 'help_first_date_no_past' => 'Indicate the first expected recurrence. Firefly III will not create transactions in the past.', - 'no_currency' => '(no currency)', - 'mandatory_for_recurring' => 'Mandatory recurrence information', - 'mandatory_for_transaction' => 'Mandatory transaction information', - 'optional_for_recurring' => 'Optional recurrence information', - 'optional_for_transaction' => 'Optional transaction information', - 'change_date_other_options' => 'Change the "first date" to see more options.', - 'mandatory_fields_for_tranaction' => 'The values here will end up in the transaction(s) being created', - 'click_for_calendar' => 'Click here for a calendar that shows you when the transaction would repeat.', - 'repeat_forever' => 'Repeat forever', - 'repeat_until_date' => 'Repeat until date', - 'repeat_times' => 'Repeat a number of times', - 'recurring_skips_one' => 'Every other', - 'recurring_skips_more' => 'Skips :count occurrences', - 'store_new_recurrence' => 'Store recurring transaction', - 'stored_new_recurrence' => 'Recurring transaction ":title" stored successfully.', - 'edit_recurrence' => 'Edit recurring transaction ":title"', - 'recurring_repeats_until' => 'Repeats until :date', - 'recurring_repeats_forever' => 'Repeats forever', - 'recurring_repeats_x_times' => 'Repeats :count time|Repeats :count times', - 'update_recurrence' => 'Update recurring transaction', - 'updated_recurrence' => 'Updated recurring transaction ":title"', - 'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.', - 'delete_recurring' => 'Delete recurring transaction ":title"', - 'new_recurring_transaction' => 'New recurring transaction', - 'help_weekend' => 'What should Firefly III do when the recurring transaction falls on a Saturday or Sunday?', - 'do_nothing' => 'Just create the transaction', - 'skip_transaction' => 'Skip the occurrence', - 'jump_to_friday' => 'Create the transaction on the previous Friday instead', - 'jump_to_monday' => 'Create the transaction on the next Monday instead', - 'will_jump_friday' => 'Will be created on Friday instead of the weekends.', - 'will_jump_monday' => 'Will be created on Monday instead of the weekends.', - 'except_weekends' => 'Except weekends', - 'recurrence_deleted' => 'Recurring transaction ":title" deleted', + 'create_new_recurrence' => 'Create new recurring transaction', + 'help_first_date' => 'Indicate the first expected recurrence. This must be in the future.', + 'help_first_date_no_past' => 'Indicate the first expected recurrence. Firefly III will not create transactions in the past.', + 'no_currency' => '(no currency)', + 'mandatory_for_recurring' => 'Mandatory recurrence information', + 'mandatory_for_transaction' => 'Mandatory transaction information', + 'optional_for_recurring' => 'Optional recurrence information', + 'optional_for_transaction' => 'Optional transaction information', + 'change_date_other_options' => 'Change the "first date" to see more options.', + 'mandatory_fields_for_tranaction' => 'The values here will end up in the transaction(s) being created', + 'click_for_calendar' => 'Click here for a calendar that shows you when the transaction would repeat.', + 'repeat_forever' => 'Repeat forever', + 'repeat_until_date' => 'Repeat until date', + 'repeat_times' => 'Repeat a number of times', + 'recurring_skips_one' => 'Every other', + 'recurring_skips_more' => 'Skips :count occurrences', + 'store_new_recurrence' => 'Store recurring transaction', + 'stored_new_recurrence' => 'Recurring transaction ":title" stored successfully.', + 'edit_recurrence' => 'Edit recurring transaction ":title"', + 'recurring_repeats_until' => 'Repeats until :date', + 'recurring_repeats_forever' => 'Repeats forever', + 'recurring_repeats_x_times' => 'Repeats :count time|Repeats :count times', + 'update_recurrence' => 'Update recurring transaction', + 'updated_recurrence' => 'Updated recurring transaction ":title"', + 'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.', + 'delete_recurring' => 'Delete recurring transaction ":title"', + 'new_recurring_transaction' => 'New recurring transaction', + 'help_weekend' => 'What should Firefly III do when the recurring transaction falls on a Saturday or Sunday?', + 'do_nothing' => 'Just create the transaction', + 'skip_transaction' => 'Skip the occurrence', + 'jump_to_friday' => 'Create the transaction on the previous Friday instead', + 'jump_to_monday' => 'Create the transaction on the next Monday instead', + 'will_jump_friday' => 'Will be created on Friday instead of the weekends.', + 'will_jump_monday' => 'Will be created on Monday instead of the weekends.', + 'except_weekends' => 'Except weekends', + 'recurrence_deleted' => 'Recurring transaction ":title" deleted', // new lines for summary controller. - 'box_balance_in_currency' => 'Balance (:currency)', - 'box_spent_in_currency' => 'Spent (:currency)', - 'box_earned_in_currency' => 'Earned (:currency)', - 'box_budgeted_in_currency' => 'Budgeted (:currency)', - 'box_bill_paid_in_currency' => 'Subscriptions paid (:currency)', - 'box_bill_unpaid_in_currency' => 'Subscriptions unpaid (:currency)', - 'box_left_to_spend_in_currency' => 'Left to spend (:currency)', - 'box_net_worth_in_currency' => 'Net worth (:currency)', - 'box_spend_per_day' => 'Left to spend per day: :amount', + 'box_balance_in_currency' => 'Balance (:currency)', + 'box_spent_in_currency' => 'Spent (:currency)', + 'box_earned_in_currency' => 'Earned (:currency)', + 'box_budgeted_in_currency' => 'Budgeted (:currency)', + 'box_bill_paid_in_currency' => 'Subscriptions paid (:currency)', + 'box_bill_unpaid_in_currency' => 'Subscriptions unpaid (:currency)', + 'box_left_to_spend_in_currency' => 'Left to spend (:currency)', + 'box_net_worth_in_currency' => 'Net worth (:currency)', + 'box_spend_per_day' => 'Left to spend per day: :amount', // debug page - 'debug_page' => 'Debug page', - 'debug_submit_instructions' => 'If you are running into problems, you can use the information in this box as debug information. Please copy-and-paste into a new or existing GitHub issue. It will generate a beautiful table that can be used to quickly diagnose your problem.', - 'debug_pretty_table' => 'If you copy/paste the box below into a GitHub issue it will generate a table. Please do not surround this text with backticks or quotes.', - 'debug_additional_data' => 'You may also share the content of the box below. You can also copy-and-paste this into a new or existing GitHub issue. However, the content of this box may contain private information such as account names, transaction details or email addresses.', + 'debug_page' => 'Debug page', + 'debug_submit_instructions' => 'If you are running into problems, you can use the information in this box as debug information. Please copy-and-paste into a new or existing GitHub issue. It will generate a beautiful table that can be used to quickly diagnose your problem.', + 'debug_pretty_table' => 'If you copy/paste the box below into a GitHub issue it will generate a table. Please do not surround this text with backticks or quotes.', + 'debug_additional_data' => 'You may also share the content of the box below. You can also copy-and-paste this into a new or existing GitHub issue. However, the content of this box may contain private information such as account names, transaction details or email addresses.', // object groups - 'object_groups_menu_bar' => 'Groups', - 'object_groups_page_title' => 'Groups', - 'object_groups_breadcrumb' => 'Groups', - 'object_groups_index' => 'Overview', - 'object_groups' => 'Groups', - 'object_groups_empty_explain' => 'Some things in Firefly III can be divided into groups. Piggy banks for example, feature a "Group" field in the edit and create screens. When you set this field, you can edit the names and the order of the groups on this page. For more information, check out the help-pages in the top right corner, under the (?)-icon.', - 'object_group_title' => 'Title', - 'edit_object_group' => 'Edit group ":title"', - 'delete_object_group' => 'Delete group ":title"', - 'update_object_group' => 'Update group', - 'updated_object_group' => 'Successfully updated group ":title"', - 'deleted_object_group' => 'Successfully deleted group ":title"', - 'object_group' => 'Group', + 'object_groups_menu_bar' => 'Groups', + 'object_groups_page_title' => 'Groups', + 'object_groups_breadcrumb' => 'Groups', + 'object_groups_index' => 'Overview', + 'object_groups' => 'Groups', + 'object_groups_empty_explain' => 'Some things in Firefly III can be divided into groups. Piggy banks for example, feature a "Group" field in the edit and create screens. When you set this field, you can edit the names and the order of the groups on this page. For more information, check out the help-pages in the top right corner, under the (?)-icon.', + 'object_group_title' => 'Title', + 'edit_object_group' => 'Edit group ":title"', + 'delete_object_group' => 'Delete group ":title"', + 'update_object_group' => 'Update group', + 'updated_object_group' => 'Successfully updated group ":title"', + 'deleted_object_group' => 'Successfully deleted group ":title"', + 'object_group' => 'Group', // other stuff - 'placeholder' => '[Placeholder]', + 'placeholder' => '[Placeholder]', // audit log entries - 'audit_log_entries' => 'Audit log entries', - 'ale_action_log_add' => 'Added :amount to piggy bank ":name"', - 'ale_action_log_remove' => 'Removed :amount from piggy bank ":name"', - 'ale_action_clear_budget' => 'Removed from budget', - 'ale_action_update_group_title' => 'Updated transaction group title', - 'ale_action_update_date' => 'Updated transaction date', - 'ale_action_update_order' => 'Updated transaction order', - 'ale_action_clear_category' => 'Removed from category', - 'ale_action_clear_notes' => 'Removed notes', - 'ale_action_clear_tag' => 'Cleared tag', - 'ale_action_clear_all_tags' => 'Cleared all tags', - 'ale_action_set_bill' => 'Linked to subscription', - 'ale_action_switch_accounts' => 'Switched source and destination account', - 'ale_action_set_budget' => 'Set budget', - 'ale_action_set_category' => 'Set category', - 'ale_action_set_source' => 'Set source account', - 'ale_action_set_destination' => 'Set destination account', - 'ale_action_update_transaction_type' => 'Changed transaction type', - 'ale_action_update_notes' => 'Changed notes', - 'ale_action_update_description' => 'Changed description', - 'ale_action_add_to_piggy' => 'Piggy bank', - 'ale_action_remove_from_piggy' => 'Piggy bank', - 'ale_action_add_tag' => 'Added tag', - 'ale_action_update_amount' => 'Updated amount', + 'audit_log_entries' => 'Audit log entries', + 'ale_action_log_add' => 'Added :amount to piggy bank ":name"', + 'ale_action_log_remove' => 'Removed :amount from piggy bank ":name"', + 'ale_action_clear_budget' => 'Removed from budget', + 'ale_action_update_group_title' => 'Updated transaction group title', + 'ale_action_update_date' => 'Updated transaction date', + 'ale_action_update_order' => 'Updated transaction order', + 'ale_action_clear_category' => 'Removed from category', + 'ale_action_clear_notes' => 'Removed notes', + 'ale_action_clear_tag' => 'Cleared tag', + 'ale_action_clear_all_tags' => 'Cleared all tags', + 'ale_action_set_bill' => 'Linked to subscription', + 'ale_action_switch_accounts' => 'Switched source and destination account', + 'ale_action_set_budget' => 'Set budget', + 'ale_action_set_category' => 'Set category', + 'ale_action_set_source' => 'Set source account', + 'ale_action_set_destination' => 'Set destination account', + 'ale_action_update_transaction_type' => 'Changed transaction type', + 'ale_action_update_notes' => 'Changed notes', + 'ale_action_update_description' => 'Changed description', + 'ale_action_add_to_piggy' => 'Piggy bank', + 'ale_action_remove_from_piggy' => 'Piggy bank', + 'ale_action_add_tag' => 'Added tag', + 'ale_action_update_amount' => 'Updated amount', // dashboard - 'enable_auto_convert' => 'Enable currency conversion', - 'disable_auto_convert' => 'Disable currency conversion', + 'enable_auto_convert' => 'Enable currency conversion', + 'disable_auto_convert' => 'Disable currency conversion', ]; diff --git a/resources/lang/en_US/rules.php b/resources/lang/en_US/rules.php index 9cd328a98f..ce60269015 100644 --- a/resources/lang/en_US/rules.php +++ b/resources/lang/en_US/rules.php @@ -68,6 +68,7 @@ return [ 'cannot_find_piggy' => 'Firefly III can\'t find a piggy bank named ":name"', 'no_link_piggy' => 'This transaction\'s accounts are not linked to the piggy bank, so no action will be taken', 'both_link_piggy' => 'This transaction\'s accounts are both linked to the piggy bank, so no action will be taken', + 'already_linked' => 'This transaction is already linked to piggy bank ":name"', 'cannot_unlink_tag' => 'Tag ":tag" isn\'t linked to this transaction', 'cannot_find_budget' => 'Firefly III can\'t find budget ":name"', 'cannot_find_category' => 'Firefly III can\'t find category ":name"', diff --git a/resources/views/budgets/index.twig b/resources/views/budgets/index.twig index cdd4b359e1..becfb544f9 100644 --- a/resources/views/budgets/index.twig +++ b/resources/views/budgets/index.twig @@ -339,6 +339,7 @@ {% if spentInfo.currency_id == budgetLimit.currency_id and budgetLimit.in_range %} {# the code below is used for budget limits INSIDE the current view range. #} {% set countLimit = countLimit + 1 %} + {# the amount left is automatically calculated. #} @@ -356,7 +357,9 @@
{% endif %} {% endfor %} + {% if countLimit == 0 %} + {# this code is used for budget limits OUTSIDE the current view range. #} @@ -366,7 +369,9 @@ {% endif %} {% endfor %} {% for budgetLimit in budget.budgeted %} + D {% if null == budget.spent[budgetLimit.currency_id] %} + E {{ formatAmountBySymbol(budgetLimit.amount, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }} @@ -377,6 +382,10 @@ ({{ formatAmountBySymbol(budgetLimit.amount / activeDaysLeft, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}) {% endif %} {% endif %} + {% if not budgetLimit.in_range %} + {# For issue #10441, add per day if the budget limit is out of range. #} + ({{ formatAmountBySymbol(budgetLimit.amount / budgetLimit.total_days, budgetLimit.currency_symbol, budgetLimit.currency_decimal_places) }}) + {% endif %}
{% endif %} diff --git a/resources/views/form/multi-select.twig b/resources/views/form/multi-select.twig index acdfc38695..d21a4734b6 100644 --- a/resources/views/form/multi-select.twig +++ b/resources/views/form/multi-select.twig @@ -2,7 +2,7 @@
- {{ Html.multiselect(name~"[]", list, selected).id(options.id).class('form-control').attribute('autocomplete','off').attribute('spellcheck','false').attribute('placeholder', options.placeholder) }} + {{ Html.multiselect(name~"[]", list, selected).id(options.id).attribute('size',12).class('form-control').attribute('autocomplete','off').attribute('spellcheck','false').attribute('placeholder', options.placeholder) }} {% include 'form.help' %} {% include 'form.feedback' %} diff --git a/resources/views/list/groups.twig b/resources/views/list/groups.twig index 0ef4a4899b..e17abb91fb 100644 --- a/resources/views/list/groups.twig +++ b/resources/views/list/groups.twig @@ -163,22 +163,31 @@ {% endif %} + {# deposit #} {% if transaction.transaction_type_type == 'Deposit' %} + {# amount of deposit #} {{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_decimal_places) }} + {# foreign amount of deposit #} {% if null != transaction.foreign_amount %} ({{ formatAmountBySymbol(transaction.foreign_amount*-1, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}) {% endif %} + {# native amount of deposit #} {% if convertToNative and 0 != transaction.native_amount %} ({{ formatAmountBySymbol(transaction.native_amount*-1, defaultCurrency.symbol, defaultCurrency.decimal_places) }}) {% endif %} {# transfer #} {% elseif transaction.transaction_type_type == 'Transfer' %} - {{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_decimal_places, false) }} + {# amount of transfer #} + {{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_decimal_places, false) }} + + {# foreign amount of transfer #} {% if null != transaction.foreign_amount %} ({{ formatAmountBySymbol(transaction.foreign_amount*-1, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places, false) }}) {% endif %} + + {# native amount of transfer #} {% if convertToNative and 0 != transaction.native_amount %} ({{ formatAmountBySymbol(transaction.native_amount*-1, defaultCurrency.symbol, defaultCurrency.decimal_places) }}) {% endif %} @@ -244,10 +253,14 @@ {# THE REST #} {% else %} + {# amount of withdrawal #} {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_decimal_places) }} + + {# foreign amount of withdrawal #} {% if null != transaction.foreign_amount %} ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}) {% endif %} + {# native amount of withdrawal #} {% if convertToNative and 0 != transaction.native_amount %} ({{ formatAmountBySymbol(transaction.native_amount, defaultCurrency.symbol, defaultCurrency.decimal_places) }}) {% endif %} @@ -263,8 +276,8 @@ {% if currency.id == transaction.currency_id %} {{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }} {% endif %} - {% if currency.id == transaction.foreign_currency_id and null != transaction.destination_balance_after %} - {{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }} + {% 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) }} {% endif %} {% else %} diff --git a/resources/views/partials/menu-sidebar.twig b/resources/views/partials/menu-sidebar.twig index a4f8aaf0ec..5b262fc05d 100644 --- a/resources/views/partials/menu-sidebar.twig +++ b/resources/views/partials/menu-sidebar.twig @@ -6,6 +6,13 @@ + +
  • {{ 'financial_control'|_ }}
  • diff --git a/resources/views/piggy-banks/show.twig b/resources/views/piggy-banks/show.twig index 9bb716af79..6a5e58f3da 100644 --- a/resources/views/piggy-banks/show.twig +++ b/resources/views/piggy-banks/show.twig @@ -54,8 +54,20 @@ {% endif %} + {% for account in piggy.accounts %} + + + {{ 'saved_so_far'|_ }} + ({{ account.name }}) + + + {{ formatAmountBySymbol(account.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }} + + + + {% endfor %} - {{ 'saved_so_far'|_ }} + {{ 'saved_so_far_total'|_ }} {{ formatAmountBySymbol(piggy.current_amount, piggy.currency_symbol, piggy.currency_decimal_places) }} @@ -102,7 +114,7 @@
  • -

    {{ 'event_history'|_ }}

    +

    {{ 'event_history'|_ }} ({{ 'reset_history'|_ }})

    {% include 'list/piggy-bank-events' %} @@ -140,6 +152,9 @@
    {% endif %}
    + {% endblock %} {% block scripts %} diff --git a/resources/views/reports/index.twig b/resources/views/reports/index.twig index c2fc58d042..5c00c6a24b 100644 --- a/resources/views/reports/index.twig +++ b/resources/views/reports/index.twig @@ -74,6 +74,12 @@ {{ year }} ({{ 'fiscal_year'|_|lower }}) {% endif %} + {% if customFiscalYear == 0 %} + (Q1, + Q2, + Q3, + Q4) + {% endif %}
      {% for month in data.months %}
    • diff --git a/resources/views/transactions/show.twig b/resources/views/transactions/show.twig index f8ff13b81a..6e38065006 100644 --- a/resources/views/transactions/show.twig +++ b/resources/views/transactions/show.twig @@ -334,6 +334,10 @@ {% endif %} + + {{ 'transaction_journal_id'|_ }} + #{{ journal.transaction_journal_id }} + {% if null != journal.category_id %} {{ 'category'|_ }} diff --git a/resources/views/v2/partials/dashboard/account-list.blade.php b/resources/views/v2/partials/dashboard/account-list.blade.php index a7b2f5078d..19c999d5ec 100644 --- a/resources/views/v2/partials/dashboard/account-list.blade.php +++ b/resources/views/v2/partials/dashboard/account-list.blade.php @@ -9,7 +9,7 @@

      - @@ -42,7 +42,7 @@ -
      +
        @@ -75,7 +75,7 @@
        diff --git a/resources/views/v2/partials/dashboard/subscriptions.blade.php b/resources/views/v2/partials/dashboard/subscriptions.blade.php index 823e5ced30..d5102d6898 100644 --- a/resources/views/v2/partials/dashboard/subscriptions.blade.php +++ b/resources/views/v2/partials/dashboard/subscriptions.blade.php @@ -30,7 +30,7 @@