mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-02-15 16:20:33 +00:00
Compare commits
66 Commits
develop-20
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7110556ef0 | ||
|
|
3e1b703dfc | ||
|
|
fce0750509 | ||
|
|
f5385d0229 | ||
|
|
8599c4a3c1 | ||
|
|
d210e7dcdd | ||
|
|
8de9e0ba29 | ||
|
|
7fa9e79f2a | ||
|
|
4a5281fd80 | ||
|
|
ad60974430 | ||
|
|
195794881b | ||
|
|
3e6a997dd5 | ||
|
|
2eedfd9f26 | ||
|
|
9ec0515bb6 | ||
|
|
6b197eecb9 | ||
|
|
591c970882 | ||
|
|
15d91dbe1b | ||
|
|
6ff87bf447 | ||
|
|
147ce154d8 | ||
|
|
2c8be33000 | ||
|
|
b472890c84 | ||
|
|
2fabcf5193 | ||
|
|
5ed4e7aa79 | ||
|
|
973caad7e4 | ||
|
|
d273503a15 | ||
|
|
cc149adb5d | ||
|
|
ac8bcb786b | ||
|
|
642deefba5 | ||
|
|
5b13b64fd7 | ||
|
|
653a64d0a8 | ||
|
|
c9dcdc90ec | ||
|
|
1f04888331 | ||
|
|
28c21ecb7e | ||
|
|
7382030e61 | ||
|
|
a573e19dbc | ||
|
|
b152a2c8d9 | ||
|
|
7e14c36fc0 | ||
|
|
58bfc7f8ce | ||
|
|
6b8c005108 | ||
|
|
ceb660fd02 | ||
|
|
7fac1e8614 | ||
|
|
809e34f5fe | ||
|
|
73ca57c8c4 | ||
|
|
63088ffeb1 | ||
|
|
4e88ebd52d | ||
|
|
85fd38d146 | ||
|
|
e83d7051eb | ||
|
|
567f2dae17 | ||
|
|
c231ae4016 | ||
|
|
fb13a4cdcb | ||
|
|
724042e1d8 | ||
|
|
84a30c3c8f | ||
|
|
6c9dac831a | ||
|
|
e605ddb779 | ||
|
|
4b19ed8f07 | ||
|
|
57bd8e09d4 | ||
|
|
32f1a7c9c2 | ||
|
|
fc5b0db43f | ||
|
|
c2721f3f48 | ||
|
|
96291c9bce | ||
|
|
ab9400aaee | ||
|
|
31d1ee11cb | ||
|
|
694dc3816c | ||
|
|
c647fa7b94 | ||
|
|
022d59bfdd | ||
|
|
057b82b471 |
62
.ci/php-cs-fixer/composer.lock
generated
62
.ci/php-cs-fixer/composer.lock
generated
@@ -402,16 +402,16 @@
|
||||
},
|
||||
{
|
||||
"name": "friendsofphp/php-cs-fixer",
|
||||
"version": "v3.93.1",
|
||||
"version": "v3.94.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||
"reference": "b3546ab487c0762c39f308dc1ec0ea2c461fc21a"
|
||||
"reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/b3546ab487c0762c39f308dc1ec0ea2c461fc21a",
|
||||
"reference": "b3546ab487c0762c39f308dc1ec0ea2c461fc21a",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/883b20fb38c7866de9844ab6d0a205c423bde2d4",
|
||||
"reference": "883b20fb38c7866de9844ab6d0a205c423bde2d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -428,7 +428,7 @@
|
||||
"react/event-loop": "^1.5",
|
||||
"react/socket": "^1.16",
|
||||
"react/stream": "^1.4",
|
||||
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
|
||||
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0",
|
||||
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
|
||||
@@ -442,18 +442,18 @@
|
||||
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.7",
|
||||
"infection/infection": "^0.32",
|
||||
"justinrainbow/json-schema": "^6.6",
|
||||
"facile-it/paraunit": "^1.3.1 || ^2.7.1",
|
||||
"infection/infection": "^0.32.3",
|
||||
"justinrainbow/json-schema": "^6.6.4",
|
||||
"keradus/cli-executor": "^2.3",
|
||||
"mikey179/vfsstream": "^1.6.12",
|
||||
"php-coveralls/php-coveralls": "^2.9",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
|
||||
"phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.48",
|
||||
"php-coveralls/php-coveralls": "^2.9.1",
|
||||
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7",
|
||||
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7",
|
||||
"phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51",
|
||||
"symfony/polyfill-php85": "^1.33",
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0"
|
||||
"symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4",
|
||||
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
@@ -494,7 +494,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.93.1"
|
||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -502,7 +502,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-28T23:50:50+00:00"
|
||||
"time": "2026-02-11T16:44:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
@@ -1185,29 +1185,29 @@
|
||||
},
|
||||
{
|
||||
"name": "sebastian/diff",
|
||||
"version": "7.0.0",
|
||||
"version": "8.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/diff.git",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f"
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"reference": "7ab1ea946c012266ca32390913653d844ecd085f",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"reference": "a2b6d09d7729ee87d605a439469f9dcc39be5ea3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3"
|
||||
"php": ">=8.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^12.0",
|
||||
"phpunit/phpunit": "^13.0",
|
||||
"symfony/process": "^7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "7.0-dev"
|
||||
"dev-main": "8.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1240,15 +1240,27 @@
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/diff/issues",
|
||||
"security": "https://github.com/sebastianbergmann/diff/security/policy",
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/7.0.0"
|
||||
"source": "https://github.com/sebastianbergmann/diff/tree/8.0.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://liberapay.com/sebastianbergmann",
|
||||
"type": "liberapay"
|
||||
},
|
||||
{
|
||||
"url": "https://thanks.dev/u/gh/sebastianbergmann",
|
||||
"type": "thanks_dev"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/sebastian/diff",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-07T04:55:46+00:00"
|
||||
"time": "2026-02-06T04:42:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
|
||||
7
.github/mergify.yml
vendored
7
.github/mergify.yml
vendored
@@ -1,11 +1,4 @@
|
||||
pull_request_rules:
|
||||
- name: Make sure PR are up to date before merging
|
||||
description: This automatically updates PRs when they are out-of-date with the
|
||||
base branch to avoid semantic conflicts (next step is using a merge
|
||||
queue).
|
||||
conditions: []
|
||||
actions:
|
||||
update:
|
||||
- name: Close all on main
|
||||
conditions:
|
||||
- base=main
|
||||
|
||||
@@ -63,6 +63,9 @@ class UpdateRequest extends FormRequest
|
||||
{
|
||||
/** @var TransactionCurrency $currency */
|
||||
$currency = $this->route()->parameter('currency_code');
|
||||
if (is_string($currency)) {
|
||||
$currency = TransactionCurrency::whereCode($currency)->first();
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => sprintf('min:1|max:255|unique:transaction_currencies,name,%d', $currency->id),
|
||||
|
||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands\System;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Console\Commands\Tools\VerifiesDatabaseConnectionTrait;
|
||||
use Illuminate\Console\Command;
|
||||
use PDO;
|
||||
use PDOException;
|
||||
@@ -32,6 +33,7 @@ use PDOException;
|
||||
class CreatesDatabase extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
use VerifiesDatabaseConnectionTrait;
|
||||
|
||||
protected $description = 'Tries to create the database if it doesn\'t exist yet.';
|
||||
|
||||
@@ -39,21 +41,27 @@ class CreatesDatabase extends Command
|
||||
|
||||
public function handle(): int
|
||||
{
|
||||
if ('mysql' !== env('DB_CONNECTION')) { // @phpstan-ignore larastan.noEnvCallsOutsideOfConfig */
|
||||
$this->friendlyInfo(sprintf('CreateDB does not apply to "%s", skipped.', env('DB_CONNECTION')));
|
||||
$connected = $this->verifyDatabaseConnection();
|
||||
if (!$connected) {
|
||||
$this->friendlyError('Failed to connect to the database. Is it up?');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
if ('mysql' !== config('database.default')) { // @phpstan-ignore larastan.noEnvCallsOutsideOfConfig */
|
||||
$this->friendlyInfo(sprintf('CreateDB does not apply to "%s", skipped.', config('database.default')));
|
||||
|
||||
return 0;
|
||||
}
|
||||
// try to set up a raw connection:
|
||||
$exists = false;
|
||||
$dsn = sprintf('mysql:host=%s;port=%d;charset=utf8mb4', env('DB_HOST'), env('DB_PORT'));
|
||||
$exists = false;
|
||||
$dsn = sprintf('mysql:host=%s;port=%d;charset=utf8mb4', env('DB_HOST'), env('DB_PORT'));
|
||||
|
||||
if ('' !== (string) env('DB_SOCKET')) {
|
||||
$dsn = sprintf('mysql:unix_socket=%s;charset=utf8mb4', env('DB_SOCKET'));
|
||||
}
|
||||
$this->friendlyLine(sprintf('DSN is %s', $dsn));
|
||||
|
||||
$options = [
|
||||
$options = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
PDO::ATTR_EMULATE_PREPARES => false,
|
||||
@@ -71,7 +79,7 @@ class CreatesDatabase extends Command
|
||||
// only continue when no error.
|
||||
// with PDO, try to list DB's (
|
||||
/** @var array $stmt */
|
||||
$stmt = $pdo->query('SHOW DATABASES;');
|
||||
$stmt = $pdo->query('SHOW DATABASES;');
|
||||
// slightly more complex but less error-prone.
|
||||
foreach ($stmt as $row) {
|
||||
$name = $row['Database'] ?? false;
|
||||
|
||||
64
app/Console/Commands/Tools/VerifiesDatabaseConnection.php
Normal file
64
app/Console/Commands/Tools/VerifiesDatabaseConnection.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* VerifiesDatabaseConnection.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Tools;
|
||||
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class VerifiesDatabaseConnection extends Command
|
||||
{
|
||||
use ShowsFriendlyMessages;
|
||||
use VerifiesDatabaseConnectionTrait;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:verify-database-connection';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This command tries to connect to the database.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$connected = $this->verifyDatabaseConnection();
|
||||
if ($connected) {
|
||||
$this->friendlyPositive('Connected to the database.');
|
||||
|
||||
return Command::SUCCESS;
|
||||
}
|
||||
$this->friendlyError('Failed to connect to the database. Is it up?');
|
||||
|
||||
return Command::FAILURE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* VerifiesDatabaseConnectionTrait.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Tools;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
trait VerifiesDatabaseConnectionTrait
|
||||
{
|
||||
protected function verifyDatabaseConnection(): bool
|
||||
{
|
||||
$loops = 30;
|
||||
$loop = 0;
|
||||
$queries = ['pgsql' => 'SELECT * FROM pg_catalog.pg_tables;', 'sqlite' => 'SELECT name FROM sqlite_schema;', 'mysql' => 'SHOW TABLES;'];
|
||||
$default = config('database.default');
|
||||
if (!array_key_exists($default, $queries)) {
|
||||
$this->friendlyWarning(sprintf('Cannot validate database connection for "%s"', $default));
|
||||
|
||||
return true;
|
||||
}
|
||||
$query = $queries[$default];
|
||||
$connected = false;
|
||||
Log::debug(sprintf('Connecting to database "%s"...', config('database.default')));
|
||||
while (!$connected && $loop < $loops) {
|
||||
try {
|
||||
DB::select($query);
|
||||
$connected = true;
|
||||
} catch (QueryException $e) {
|
||||
Log::error(sprintf('Loop #%d: connection failed: %s', $loop, $e->getMessage()));
|
||||
$this->friendlyWarning(sprintf('Database connection attempt #%d failed. Sleep for 10 seconds...', $loop + 1));
|
||||
sleep(10);
|
||||
} catch (Exception $e) {
|
||||
Log::error(sprintf('Loop #%d: not connected yet because of a %s: %s', $loop, get_class($e), $e->getMessage()));
|
||||
$this->friendlyWarning(sprintf('Database connection attempt #%d failed. Sleep for 10 seconds...', $loop + 1));
|
||||
sleep(10);
|
||||
}
|
||||
++$loop;
|
||||
}
|
||||
|
||||
return $connected;
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,7 @@ class UpgradesDatabase extends Command
|
||||
|
||||
private function callInitialCommands(): void
|
||||
{
|
||||
$this->call('firefly-iii:verify-database-connection');
|
||||
$this->call('migrate', ['--seed' => true, '--force' => true, '--no-interaction' => true]);
|
||||
$this->call('upgrade:600-pgsql-sequences');
|
||||
$this->call('upgrade:480-decrypt-all');
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2020 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Override;
|
||||
|
||||
/**
|
||||
* File to make sure commands work.
|
||||
*/
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*/
|
||||
#[Override]
|
||||
protected function commands(): void
|
||||
{
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*/
|
||||
#[Override]
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
$schedule->call(static function (): void {
|
||||
Log::error('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions at https://docs.firefly-iii.org/');
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
echo wordwrap('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions here:');
|
||||
echo "\n";
|
||||
echo 'https://docs.firefly-iii.org/';
|
||||
echo "\n\n";
|
||||
echo 'Disable this cron job!';
|
||||
echo "\n";
|
||||
echo '------------';
|
||||
echo "\n";
|
||||
})->daily();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* api-noauth.php
|
||||
* Copyright (c) 2021 james@firefly-iii.org
|
||||
* UpdatedExistingBill.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -20,20 +22,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace FireflyIII\Events\Model\Bill;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
// Cron job API routes:
|
||||
use FireflyIII\Http\Middleware\AcceptHeaders;
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\Bill;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
Route::group(
|
||||
[
|
||||
'namespace' => 'FireflyIII\Api\V1\Controllers\System',
|
||||
'prefix' => '',
|
||||
'as' => 'api.v1.cron.',
|
||||
'middleware' => [AcceptHeaders::class],
|
||||
],
|
||||
static function (): void {
|
||||
Route::get('{cliToken}', ['uses' => 'CronController@cron', 'as' => 'index']);
|
||||
}
|
||||
);
|
||||
class UpdatedExistingBill extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*/
|
||||
public function __construct(
|
||||
public Bill $bill,
|
||||
public array $oldData
|
||||
) {}
|
||||
}
|
||||
@@ -36,13 +36,13 @@ class ConvertsAmountToPrimaryAmount
|
||||
$primaryAmountField = $params->primaryAmountField;
|
||||
|
||||
if (!Amount::convertToPrimary($params->user)) {
|
||||
Log::debug(sprintf(
|
||||
'User does not want to do conversion, no need to convert "%s" and store it in field "%s" for %s #%d.',
|
||||
$params->amountField,
|
||||
$params->primaryAmountField,
|
||||
get_class($params->model),
|
||||
$params->model->id
|
||||
));
|
||||
// Log::debug(sprintf(
|
||||
// 'User does not want to do conversion, no need to convert "%s" and store it in field "%s" for %s #%d.',
|
||||
// $params->amountField,
|
||||
// $params->primaryAmountField,
|
||||
// get_class($params->model),
|
||||
// $params->model->id
|
||||
// ));
|
||||
$params->model->{$primaryAmountField} = null;
|
||||
$params->model->saveQuietly();
|
||||
|
||||
|
||||
@@ -115,6 +115,7 @@ class ConfigurationController extends Controller
|
||||
FireflyConfig::set('enable_external_map', $data['enable_external_map']);
|
||||
FireflyConfig::set('enable_external_rates', $data['enable_external_rates']);
|
||||
FireflyConfig::set('allow_webhooks', $data['allow_webhooks']);
|
||||
FireflyConfig::set('enable_batch_processing', $data['enable_batch_processing']);
|
||||
|
||||
FireflyConfig::set('valid_url_protocols', $data['valid_url_protocols']);
|
||||
FireflyConfig::set('is_demo_site', $data['is_demo_site']);
|
||||
|
||||
@@ -190,6 +190,14 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function showLoginForm(Request $request): Factory|Redirector|RedirectResponse|View
|
||||
{
|
||||
if ('remote_user_guard' === config('auth.defaults.guard')) {
|
||||
$message = sprintf(
|
||||
'Firefly III is configured to use the "remote user guard", but was unable to link you to a user. Are you sure the "%s" header is in place?',
|
||||
config('auth.guard_header')
|
||||
);
|
||||
|
||||
return view('errors.error', ['message' => $message]);
|
||||
}
|
||||
Log::channel('audit')->info('Show login form (1.1).');
|
||||
|
||||
$count = DB::table('users')->count();
|
||||
|
||||
@@ -80,6 +80,14 @@ abstract class Controller extends BaseController
|
||||
View::share('FF_VERSION', config('firefly.version'));
|
||||
View::share('FF_BUILD_TIME', config('firefly.build_time'));
|
||||
|
||||
// this breaks when running < php 8.5 and is totally intentional.
|
||||
// $input = ' James is cool';
|
||||
// $output = $input
|
||||
// |> trim(...)
|
||||
// |> (fn (string $string) => str_replace(' ', '-', $string))
|
||||
// |> (fn (string $string) => str_replace(['.', '/', '…'], '', $string))
|
||||
// |> strtolower(...);
|
||||
|
||||
// is webhooks enabled?
|
||||
View::share(
|
||||
'featuringWebhooks',
|
||||
|
||||
@@ -103,10 +103,11 @@ class IndexController extends Controller
|
||||
$firstJournal = $this->repository->firstNull();
|
||||
$startPeriod = $firstJournal instanceof TransactionJournal ? $firstJournal->date : new Carbon();
|
||||
$endPeriod = clone $end;
|
||||
|
||||
// limit to 3 years for the time being.
|
||||
if (now()->diffInYears($startPeriod, true) > 3) {
|
||||
$startPeriod = now()->subYears(3);
|
||||
$endPeriod->endOfDay();
|
||||
// limit to 6 years for the time being.
|
||||
$max = 6;
|
||||
if (now()->diffInYears($startPeriod, true) > $max) {
|
||||
$startPeriod = now()->subYears($max);
|
||||
}
|
||||
|
||||
$periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2019 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http;
|
||||
|
||||
use FireflyIII\Http\Middleware\Authenticate;
|
||||
use FireflyIII\Http\Middleware\Binder;
|
||||
use FireflyIII\Http\Middleware\InstallationId;
|
||||
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\TrimStrings;
|
||||
use FireflyIII\Http\Middleware\TrustProxies;
|
||||
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
|
||||
use Illuminate\Auth\Middleware\Authorize;
|
||||
use Illuminate\Foundation\Http\Kernel as HttpKernel;
|
||||
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
|
||||
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
|
||||
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\Routing\Middleware\ThrottleRequests;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
|
||||
/**
|
||||
* Class Kernel
|
||||
*/
|
||||
class Kernel extends HttpKernel
|
||||
{
|
||||
protected $middleware = [
|
||||
// SecureHeaders::class,
|
||||
CheckForMaintenanceMode::class,
|
||||
ValidatePostSize::class,
|
||||
TrimStrings::class,
|
||||
ConvertEmptyStringsToNull::class,
|
||||
TrustProxies::class,
|
||||
InstallationId::class,
|
||||
];
|
||||
protected $middlewareAliases = [
|
||||
'auth' => Authenticate::class,
|
||||
'auth.basic' => AuthenticateWithBasicAuth::class,
|
||||
'bindings' => Binder::class,
|
||||
'can' => Authorize::class,
|
||||
'guest' => RedirectIfAuthenticated::class,
|
||||
'throttle' => ThrottleRequests::class,
|
||||
];
|
||||
protected $middlewarePriority = [StartFireflySession::class, ShareErrorsFromSession::class, Authenticate::class, Binder::class, Authorize::class];
|
||||
}
|
||||
@@ -82,22 +82,25 @@ class Authenticate
|
||||
protected function authenticate($request, array $guards)
|
||||
{
|
||||
if (0 === count($guards)) {
|
||||
// go for default guard:
|
||||
// @noinspection PhpUndefinedMethodInspection
|
||||
if ($this->auth->check()) {
|
||||
// do an extra check on user object.
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->auth->authenticate();
|
||||
Log::debug('in Authenticate::authenticate() with zero guards.');
|
||||
// There are no guards defined, go for the default guard:
|
||||
if (auth()->check()) {
|
||||
Log::debug('User is authenticated.');
|
||||
$user = auth()->user();
|
||||
$this->validateBlockedUser($user, $guards);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// @noinspection PhpUndefinedMethodInspection
|
||||
return $this->auth->authenticate();
|
||||
$this->auth->authenticate();
|
||||
if (!$this->auth->check()) {
|
||||
throw new AuthenticationException('The user is not logged in but must be.', $guards);
|
||||
}
|
||||
}
|
||||
|
||||
exit('five');
|
||||
foreach ($guards as $guard) {
|
||||
exit('six');
|
||||
if ('api' !== $guard) {
|
||||
$this->auth->guard($guard)->authenticate();
|
||||
}
|
||||
@@ -111,6 +114,7 @@ class Authenticate
|
||||
}
|
||||
}
|
||||
|
||||
exit('seven');
|
||||
// this is a massive hack, but if the handler has the oauth exception
|
||||
// at this point we can report its error instead of a generic one.
|
||||
$message = 'Unauthenticated.';
|
||||
@@ -143,5 +147,6 @@ class Authenticate
|
||||
// @phpstan-ignore-line (thinks function is undefined)
|
||||
throw new AuthenticationException('Blocked account.', $guards);
|
||||
}
|
||||
Log::debug(sprintf('User #%d is not blocked.', $user->id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use Override;
|
||||
/**
|
||||
* Class StartFireflySession.
|
||||
*/
|
||||
class StartFireflySession extends StartSession
|
||||
class StartFireflyIIISession extends StartSession
|
||||
{
|
||||
/**
|
||||
* Store the current URL for the request if necessary.
|
||||
81
app/Listeners/Model/Bill/UpdatesRulesForChangedBill.php
Normal file
81
app/Listeners/Model/Bill/UpdatesRulesForChangedBill.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* UpdatesRulesForChangedBill.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\Bill;
|
||||
|
||||
use FireflyIII\Events\Model\Bill\UpdatedExistingBill;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UpdatesRulesForChangedBill implements ShouldQueue
|
||||
{
|
||||
public function handle(UpdatedExistingBill $event): void
|
||||
{
|
||||
// update rule actions.
|
||||
if ($event->bill->name !== $event->oldData['name']) {
|
||||
$this->updateBillTriggersAndActions($event->bill, $event->oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateBillTriggersAndActions(Bill $bill, array $oldData): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updateBillTriggersAndActions(#%d)', $bill->id));
|
||||
$repository = app(RuleRepositoryInterface::class);
|
||||
$repository->setUser($bill->user);
|
||||
$rules = $repository->getAll();
|
||||
|
||||
/** @var Rule $rule */
|
||||
foreach ($rules as $rule) {
|
||||
$this->updateRule($bill, $rule, $oldData);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateRule(Bill $bill, Rule $rule, array $oldData): void
|
||||
{
|
||||
$triggers = ['bill_is', 'bill_ends', 'bill_starts', 'bill_contains'];
|
||||
|
||||
/** @var RuleTrigger $trigger */
|
||||
foreach ($rule->ruleTriggers as $trigger) {
|
||||
if (in_array($trigger->trigger_type, $triggers, true) && $trigger->trigger_value === $oldData['name']) {
|
||||
Log::debug(sprintf('Updated trigger #%d in rule #%d to new subscription name', $trigger->id, $rule->id));
|
||||
$trigger->trigger_value = $bill->name;
|
||||
$trigger->save();
|
||||
}
|
||||
}
|
||||
|
||||
/** @var RuleAction $action */
|
||||
foreach ($rule->ruleActions as $action) {
|
||||
if ('link_to_bill' === $action->action_type && $action->action_value === $oldData['name']) {
|
||||
Log::debug(sprintf('Updated action #%d in rule #%d to new subscription name', $action->id, $rule->id));
|
||||
$action->action_value = $bill->name;
|
||||
$action->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,7 +104,9 @@ trait SupportsGroupProcessingTrait
|
||||
$repository->deleteStatisticsForType(Category::class, $objects->categories, $dates);
|
||||
$repository->deleteStatisticsForType(Tag::class, $objects->tags, $dates);
|
||||
|
||||
// remove if no stuff present:
|
||||
// remove generic statistics:
|
||||
$repository->deleteStatisticsForPrefix('all_', $dates);
|
||||
|
||||
// remove for no tag, no cat, etc.
|
||||
if (0 === $objects->budgets->count()) {
|
||||
Log::debug('No budgets, delete "no_category" stats.');
|
||||
|
||||
@@ -149,12 +149,10 @@ class RecalculatesPrimaryCurrencyAmounts
|
||||
->join('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.user_group_id', $userGroup->id)
|
||||
->where(static function (Builder $q): void {
|
||||
$q
|
||||
->whereNotNull('native_amount')
|
||||
->orWhereNotNull('native_foreign_amount')
|
||||
->orWhere('native_amount', '!=', '')
|
||||
->orWhere('native_foreign_amount', '!=', '')
|
||||
;
|
||||
$q->whereNotNull('native_amount')->orWhereNotNull('native_foreign_amount');
|
||||
if ('pgsql' !== config('database.default')) {
|
||||
$q->orWhere('native_amount', '!=', '')->orWhere('native_foreign_amount', '!=', '');
|
||||
}
|
||||
})
|
||||
->update(['native_amount' => null, 'native_foreign_amount' => null])
|
||||
;
|
||||
|
||||
@@ -34,10 +34,6 @@ use Laravel\Passport\Passport;
|
||||
*/
|
||||
class AuthServiceProvider extends ServiceProvider
|
||||
{
|
||||
protected $policies = [
|
||||
// 'FireflyIII\Model' => 'FireflyIII\Policies\ModelPolicy',
|
||||
];
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\StartFireflyIIISession;
|
||||
use Illuminate\Session\SessionManager;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Override;
|
||||
@@ -43,7 +43,7 @@ class FireflySessionProvider extends ServiceProvider
|
||||
|
||||
$this->registerSessionDriver();
|
||||
|
||||
$this->app->singleton(StartFireflySession::class);
|
||||
$this->app->singleton(StartFireflyIIISession::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,20 +42,18 @@ class RouteServiceProvider extends ServiceProvider
|
||||
#[Override]
|
||||
public function boot(): void
|
||||
{
|
||||
$this->routes(function (): void {
|
||||
Route::prefix('api')
|
||||
->middleware('api')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api.php'))
|
||||
;
|
||||
|
||||
Route::prefix('api/v1/cron')
|
||||
->middleware('api_basic')
|
||||
->namespace($this->namespace)
|
||||
->group(base_path('routes/api-noauth.php'))
|
||||
;
|
||||
|
||||
Route::middleware('web')->namespace($this->namespace)->group(base_path('routes/web.php'));
|
||||
});
|
||||
// $this->routes(function (): void {
|
||||
// Route::prefix('api')
|
||||
// ->middleware('api')
|
||||
// ->namespace($this->namespace)
|
||||
// ->group(base_path('routes/api.php'))
|
||||
// ;
|
||||
// Route::prefix('api/v1/cron')
|
||||
// ->middleware('api_basic')
|
||||
// ->namespace($this->namespace)
|
||||
// ->group(base_path('routes/api-noauth.php'))
|
||||
// ;
|
||||
// Route::middleware('web')->namespace($this->namespace)->group(base_path('routes/web.php'));
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\StartFireflyIIISession;
|
||||
use Illuminate\Session\SessionServiceProvider as BaseSessionServiceProvider;
|
||||
use Override;
|
||||
|
||||
@@ -42,6 +42,6 @@ class SessionServiceProvider extends BaseSessionServiceProvider
|
||||
|
||||
$this->registerSessionDriver();
|
||||
|
||||
$this->app->singleton(StartFireflySession::class);
|
||||
$this->app->singleton(StartFireflyIIISession::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
foreach ($set as $bill) {
|
||||
if ($bill->order !== $current) {
|
||||
$bill->order = $current;
|
||||
$bill->save();
|
||||
$bill->saveQuietly();
|
||||
}
|
||||
++$current;
|
||||
}
|
||||
@@ -613,7 +613,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
|
||||
public function setOrder(Bill $bill, int $order): void
|
||||
{
|
||||
$bill->order = $order;
|
||||
$bill->save();
|
||||
$bill->saveQuietly();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,9 @@ class PeriodStatisticRepository implements PeriodStatisticRepositoryInterface, U
|
||||
#[Override]
|
||||
public function allInRangeForPrefix(string $prefix, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
Log::debug(sprintf('Collect all statistics where type starts with "%s"', $prefix));
|
||||
Log::debug(sprintf('Between %s and %s', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
|
||||
|
||||
return $this->userGroup
|
||||
->periodStatistics()
|
||||
->where('type', 'LIKE', sprintf('%s%%', $prefix))
|
||||
@@ -156,6 +159,7 @@ class PeriodStatisticRepository implements PeriodStatisticRepositoryInterface, U
|
||||
int $count,
|
||||
string $amount
|
||||
): PeriodStatistic {
|
||||
Log::debug(sprintf('Store as type "%s"', sprintf('%s_%s', $prefix, $type)));
|
||||
$stat = new PeriodStatistic();
|
||||
$stat->transaction_currency_id = $currencyId;
|
||||
$stat->user_group_id = $this->getUserGroup()->id;
|
||||
|
||||
@@ -102,7 +102,7 @@ class RuleRepository implements RuleRepositoryInterface, UserGroupInterface
|
||||
{
|
||||
return $this->user
|
||||
->rules()
|
||||
->with(['ruleGroup'])
|
||||
->with(['ruleGroup', 'ruleTriggers', 'ruleActions'])
|
||||
->get()
|
||||
;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Rules\UniqueIban;
|
||||
use FireflyIII\Support\NullArrayObject;
|
||||
use Illuminate\Database\UniqueConstraintViolationException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Safe\Exceptions\JsonException;
|
||||
|
||||
@@ -227,7 +228,12 @@ trait JournalServiceTrait
|
||||
$set = array_unique($set);
|
||||
Log::debug('End of loop.');
|
||||
Log::debug(sprintf('Total nr. of tags: %d', count($tags)), $tags);
|
||||
$journal->tags()->sync($set);
|
||||
|
||||
try {
|
||||
$journal->tags()->sync($set);
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
Log::error(sprintf('Firefly III could not sync tags: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,12 +24,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Services\Internal\Update;
|
||||
|
||||
use FireflyIII\Events\Model\Bill\UpdatedExistingBill;
|
||||
use FireflyIII\Factory\TransactionCurrencyFactory;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleTrigger;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Services\Internal\Support\BillServiceTrait;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
@@ -50,6 +50,7 @@ class BillUpdateService
|
||||
public function update(Bill $bill, array $data): Bill
|
||||
{
|
||||
$this->user = $bill->user;
|
||||
$oldData = $bill->toArray();
|
||||
|
||||
if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) {
|
||||
$factory = app(TransactionCurrencyFactory::class);
|
||||
@@ -68,13 +69,6 @@ class BillUpdateService
|
||||
$bill = $this->updateBillProperties($bill, $data);
|
||||
$bill->save();
|
||||
$bill->refresh();
|
||||
// old values
|
||||
$oldData = [
|
||||
'name' => $bill->name,
|
||||
'amount_min' => $bill->amount_min,
|
||||
'amount_max' => $bill->amount_max,
|
||||
'transaction_currency_name' => $bill->transactionCurrency->name,
|
||||
];
|
||||
// update note:
|
||||
if (array_key_exists('notes', $data)) {
|
||||
$this->updateNote($bill, (string) $data['notes']);
|
||||
@@ -90,12 +84,6 @@ class BillUpdateService
|
||||
}
|
||||
}
|
||||
|
||||
// update rule actions.
|
||||
if (array_key_exists('name', $data)) {
|
||||
$this->updateBillActions($bill, $oldData['name'], $data['name']);
|
||||
$this->updateBillTriggers($bill, $oldData, $data);
|
||||
}
|
||||
|
||||
// update using name:
|
||||
if (array_key_exists('object_group_title', $data)) {
|
||||
$objectGroupTitle = $data['object_group_title'] ?? '';
|
||||
@@ -127,6 +115,7 @@ class BillUpdateService
|
||||
$bill->objectGroups()->sync([]);
|
||||
$bill->save();
|
||||
}
|
||||
event(new UpdatedExistingBill($bill, $oldData));
|
||||
|
||||
return $bill;
|
||||
}
|
||||
@@ -181,39 +170,6 @@ class BillUpdateService
|
||||
return $bill;
|
||||
}
|
||||
|
||||
private function updateBillTriggers(Bill $bill, array $oldData, array $newData): void
|
||||
{
|
||||
Log::debug(sprintf('Now in updateBillTriggers(%d, "%s")', $bill->id, $bill->name));
|
||||
|
||||
/** @var BillRepositoryInterface $repository */
|
||||
$repository = app(BillRepositoryInterface::class);
|
||||
$repository->setUser($bill->user);
|
||||
$rules = $repository->getRulesForBill($bill);
|
||||
if (0 === $rules->count()) {
|
||||
Log::debug('Found no rules.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug(sprintf('Found %d rules', $rules->count()));
|
||||
$fields = [
|
||||
'name' => 'description_contains',
|
||||
'amount_min' => 'amount_more',
|
||||
'amount_max' => 'amount_less',
|
||||
'transaction_currency_name' => 'currency_is',
|
||||
];
|
||||
foreach ($fields as $field => $ruleTriggerKey) {
|
||||
if (!array_key_exists($field, $newData)) {
|
||||
continue;
|
||||
}
|
||||
if ($oldData[$field] === $newData[$field]) {
|
||||
Log::debug(sprintf('Field %s is unchanged ("%s"), continue.', $field, $oldData[$field]));
|
||||
|
||||
continue;
|
||||
}
|
||||
$this->updateRules($rules, $ruleTriggerKey, $oldData[$field], $newData[$field]);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
|
||||
{
|
||||
if ($newOrder > $oldOrder) {
|
||||
|
||||
@@ -31,6 +31,7 @@ use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\UserProvider;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,7 @@ class RemoteUserGuard implements Guard
|
||||
{
|
||||
protected Application $application;
|
||||
protected ?User $user = null;
|
||||
private $tried = false;
|
||||
|
||||
/**
|
||||
* Create a new authentication guard.
|
||||
@@ -49,13 +51,19 @@ class RemoteUserGuard implements Guard
|
||||
Application $app
|
||||
) {
|
||||
$app->get('request');
|
||||
// Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $request?->getMethod(), $request?->getRequestUri()));
|
||||
Log::debug(sprintf('Created RemoteUserGuard for %s "%s"', $app->get('request')?->getMethod(), $app->get('request')?->getRequestUri()));
|
||||
$this->application = $app;
|
||||
}
|
||||
|
||||
public function authenticate(): void
|
||||
{
|
||||
// Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
$this->tried = true;
|
||||
Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
if (App::runningInConsole()) {
|
||||
Log::debug('Running in console, will not authenticate.');
|
||||
|
||||
return;
|
||||
}
|
||||
if ($this->user instanceof User) {
|
||||
Log::debug(sprintf('%s is found: #%d, "%s".', $this->user::class, $this->user->id, $this->user->email));
|
||||
|
||||
@@ -70,10 +78,14 @@ class RemoteUserGuard implements Guard
|
||||
$userID = request()->server($header) ?? apache_request_headers()[$header] ?? null;
|
||||
}
|
||||
|
||||
// test value for development
|
||||
// $userID = 'james@firefly';
|
||||
|
||||
if (null === $userID || '' === $userID) {
|
||||
Log::error(sprintf('No user in header "%s".', $header));
|
||||
|
||||
throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
// throw new FireflyException('The guard header was unexpectedly empty. See the logs.');
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug(sprintf('User ID found in header is "%s"', $userID));
|
||||
@@ -145,8 +157,18 @@ class RemoteUserGuard implements Guard
|
||||
|
||||
public function user(): ?User
|
||||
{
|
||||
if (App::runningInConsole()) {
|
||||
Log::debug('Running in console, will not authenticate.');
|
||||
|
||||
return null;
|
||||
}
|
||||
if (false === $this->tried) {
|
||||
Log::debug('Have not tried authentication, do it now.');
|
||||
$this->authenticate();
|
||||
}
|
||||
// Log::debug(sprintf('Now at %s', __METHOD__));
|
||||
$user = $this->user;
|
||||
|
||||
if (!$user instanceof User) {
|
||||
Log::debug('User is NULL');
|
||||
|
||||
|
||||
@@ -35,20 +35,8 @@ class Calculator
|
||||
{
|
||||
public const int DEFAULT_INTERVAL = 1;
|
||||
|
||||
private static ?SplObjectStorage $intervalMap = null; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private static array $intervals = [];
|
||||
private static ?SplObjectStorage $intervalMap = null;
|
||||
private static array $intervals = [];
|
||||
|
||||
public function isAvailablePeriodicity(Periodicity $periodicity): bool
|
||||
{
|
||||
|
||||
@@ -114,6 +114,38 @@ class ExportDataGenerator
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->accounts = new Collection();
|
||||
|
||||
@@ -37,7 +37,6 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Repositories\PeriodStatistic\PeriodStatisticRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
@@ -80,44 +79,8 @@ trait PeriodOverview
|
||||
protected TagRepositoryInterface $tagRepository;
|
||||
protected JournalRepositoryInterface $journalRepos;
|
||||
protected PeriodStatisticRepositoryInterface $periodStatisticRepo;
|
||||
private Collection $statistics; // temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
// temp data holder
|
||||
private array $transactions; // temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
|
||||
// temp data holder
|
||||
private Collection $statistics;
|
||||
private array $transactions;
|
||||
|
||||
/**
|
||||
* This method returns "period entries", so nov-2015, dec-2015, etc. (this depends on the users session range)
|
||||
@@ -178,6 +141,34 @@ trait PeriodOverview
|
||||
return $entries;
|
||||
}
|
||||
|
||||
protected function getGenericPeriod(string $type, string $period, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$return = [
|
||||
'title' => Navigation::periodShow($start, $period),
|
||||
'route' => route('transactions.index', [$type, $start->format('Y-m-d'), $end->format('Y-m-d')]),
|
||||
'total_transactions' => 0,
|
||||
];
|
||||
$setTypes = [
|
||||
'withdrawal' => 'spent',
|
||||
'expenses' => 'spent',
|
||||
'deposit' => 'earned',
|
||||
'revenue' => 'earned',
|
||||
'transfer' => 'transferred',
|
||||
'transfers' => 'transferred',
|
||||
];
|
||||
if (!array_key_exists($type, $setTypes)) {
|
||||
throw new FireflyException(sprintf('[c] Cannot deal with type "%s"', $type));
|
||||
}
|
||||
$setType = $setTypes[$type];
|
||||
|
||||
$this->transactions = [];
|
||||
$set = $this->getSingleGenericPeriodByType($start, $end, $type);
|
||||
$return['total_transactions'] += $set['count'];
|
||||
$return[$setType] = $set;
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above, but for lists that involve transactions without a budget.
|
||||
*
|
||||
@@ -263,60 +254,18 @@ trait PeriodOverview
|
||||
*/
|
||||
protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$range = Navigation::getViewRange(true);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('transactions-period-entries');
|
||||
$cache->addProperty($transactionType);
|
||||
if ($cache->has()) {
|
||||
return $cache->get();
|
||||
}
|
||||
$this->periodStatisticRepo = app(PeriodStatisticRepositoryInterface::class);
|
||||
$range = Navigation::getViewRange(true);
|
||||
[$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
|
||||
|
||||
/** @var array $dates */
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$spent = [];
|
||||
$earned = [];
|
||||
$transferred = [];
|
||||
// collect all journals in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes($types)->setRange($start, $end);
|
||||
$genericSet = $collector->getExtractedJournals();
|
||||
$loops = 0;
|
||||
$dates = Navigation::blockPeriods($start, $end, $range);
|
||||
$entries = [];
|
||||
$this->statistics = $this->periodStatisticRepo->allInRangeForPrefix('all_', $start, $end);
|
||||
Log::debug(sprintf('Collected %d statistics', $this->statistics->count()));
|
||||
|
||||
foreach ($dates as $currentDate) {
|
||||
$title = Navigation::periodShow($currentDate['end'], $currentDate['period']);
|
||||
|
||||
if ($loops < 10) {
|
||||
// set to correct array
|
||||
if ('expenses' === $transactionType || 'withdrawal' === $transactionType) {
|
||||
$spent = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
if ('revenue' === $transactionType || 'deposit' === $transactionType) {
|
||||
$earned = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
if ('transfer' === $transactionType || 'transfers' === $transactionType) {
|
||||
$transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
}
|
||||
$entries[] = [
|
||||
'title' => $title,
|
||||
'route' => route('transactions.index', [
|
||||
$transactionType,
|
||||
$currentDate['start']->format('Y-m-d'),
|
||||
$currentDate['end']->format('Y-m-d'),
|
||||
]),
|
||||
'total_transactions' => count($spent) + count($earned) + count($transferred),
|
||||
'spent' => $this->groupByCurrency($spent),
|
||||
'earned' => $this->groupByCurrency($earned),
|
||||
'transferred' => $this->groupByCurrency($transferred),
|
||||
];
|
||||
++$loops;
|
||||
$entries[] = $this->getGenericPeriod($transactionType, $currentDate['period'], $currentDate['start'], $currentDate['end']);
|
||||
}
|
||||
|
||||
return $entries;
|
||||
@@ -363,10 +312,11 @@ trait PeriodOverview
|
||||
|
||||
return new Collection();
|
||||
}
|
||||
Log::debug(sprintf('Now in filterStatistics("%s")', $type));
|
||||
|
||||
return $this->statistics->filter(
|
||||
static fn (PeriodStatistic $statistic): bool => $statistic->start->eq($start) && $statistic->end->eq($end) && $statistic->type === $type
|
||||
);
|
||||
return $this->statistics->filter(static function (PeriodStatistic $statistic) use ($start, $end, $type): bool {
|
||||
return $statistic->start->isSameSecond($start) && $statistic->end->isSameSecond($end) && $statistic->type === $type;
|
||||
});
|
||||
}
|
||||
|
||||
private function filterTransactionsByType(TransactionTypeEnum $type, Carbon $start, Carbon $end): array
|
||||
@@ -428,21 +378,63 @@ trait PeriodOverview
|
||||
return [$start, $end];
|
||||
}
|
||||
|
||||
private function getSingleGenericPeriodByType(Carbon $start, Carbon $end, string $type): array
|
||||
{
|
||||
$filterType = sprintf('all_%s', $type);
|
||||
$statistics = $this->filterStatistics($start, $end, $filterType);
|
||||
$types = config(sprintf('firefly.transactionTypesByType.%s', $type));
|
||||
// nothing found, regenerate them.
|
||||
if (0 === $statistics->count()) {
|
||||
if (0 === count($this->transactions)) {
|
||||
// get collection!
|
||||
// collect all journals in this period (regardless of type)
|
||||
$collector = app(GroupCollectorInterface::class);
|
||||
$collector->setTypes($types)->setRange($start, $end);
|
||||
$this->transactions = $collector->getExtractedJournals();
|
||||
Log::debug(sprintf('Going to group %d found journal(s)', count($types)));
|
||||
}
|
||||
|
||||
$grouped = $this->groupByCurrency($this->filterJournalsByDate($this->transactions, $start, $end));
|
||||
$this->saveGroupedForPrefix('all', $start, $end, $type, $grouped);
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
$grouped = ['count' => 0];
|
||||
|
||||
/** @var PeriodStatistic $statistic */
|
||||
foreach ($statistics as $statistic) {
|
||||
$id = (int) $statistic->transaction_currency_id;
|
||||
$currency = Amount::getTransactionCurrencyById($id);
|
||||
$grouped[$id] = [
|
||||
'amount' => (string) $statistic->amount,
|
||||
'count' => (int) $statistic->count,
|
||||
'currency_id' => $currency->id,
|
||||
'currency_name' => $currency->name,
|
||||
'currency_code' => $currency->code,
|
||||
'currency_symbol' => $currency->symbol,
|
||||
'currency_decimal_places' => $currency->decimal_places,
|
||||
];
|
||||
$grouped['count'] += (int) $statistic->count;
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
private function getSingleModelPeriodByType(Model $model, Carbon $start, Carbon $end, string $type): array
|
||||
{
|
||||
Log::debug(sprintf(
|
||||
'Now in getSingleModelPeriodByType(%s #%d, %s %s, %s)',
|
||||
$model::class,
|
||||
$model->id,
|
||||
$start->format('Y-m-d'),
|
||||
$end->format('Y-m-d'),
|
||||
$start->format('Y-m-d H:i:s.u'),
|
||||
$end->format('Y-m-d H:i:s.u'),
|
||||
$type
|
||||
));
|
||||
$statistics = $this->filterStatistics($start, $end, $type);
|
||||
|
||||
// nothing found, regenerate them.
|
||||
if (0 === $statistics->count()) {
|
||||
Log::debug(sprintf('Found nothing in this period for type "%s"', $type));
|
||||
Log::debug(sprintf('Found nothing between %s and %s for type "%s"', $start->format('Y-m-d H:i:s.u'), $end->format('Y-m-d H:i:s.u'), $type));
|
||||
if (0 === count($this->transactions)) {
|
||||
switch ($model::class) {
|
||||
default:
|
||||
@@ -467,7 +459,7 @@ trait PeriodOverview
|
||||
|
||||
switch ($type) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot deal with category period type %s', $type));
|
||||
throw new FireflyException(sprintf('Cannot deal with type %s', $type));
|
||||
|
||||
case 'spent':
|
||||
$result = $this->filterTransactionsByType(TransactionTypeEnum::WITHDRAWAL, $start, $end);
|
||||
@@ -529,7 +521,7 @@ trait PeriodOverview
|
||||
|
||||
switch ($model) {
|
||||
default:
|
||||
throw new FireflyException(sprintf('Cannot deal with model of type "%s"', $model));
|
||||
throw new FireflyException(sprintf('[b] Cannot deal with model of type "%s"', $model));
|
||||
|
||||
case 'budget':
|
||||
// get all expenses without a budget.
|
||||
|
||||
@@ -53,6 +53,22 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private readonly bool $convertToPrimary; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
@@ -66,6 +82,22 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private array $ids = [];
|
||||
|
||||
@@ -53,6 +53,22 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private Carbon $end;
|
||||
|
||||
@@ -55,6 +55,22 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $accounts = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
@@ -68,6 +84,22 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $amounts = [];
|
||||
private Collection $collection;
|
||||
private array $currencies = [];
|
||||
|
||||
@@ -50,6 +50,22 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $accountIds = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
@@ -63,6 +79,22 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private Collection $collection;
|
||||
private array $currencies = [];
|
||||
private array $groupIds = [];
|
||||
|
||||
@@ -59,6 +59,22 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private readonly bool $convertToPrimary;
|
||||
private ?Carbon $end = null;
|
||||
private array $mappedObjects = [];
|
||||
|
||||
@@ -79,6 +79,38 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
// @phpstan-ignore-line
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||
|
||||
@@ -55,6 +55,22 @@ class WebhookEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $ids = []; // @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
@@ -68,6 +84,22 @@ class WebhookEnrichment implements EnrichmentInterface
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
// @phpstan-ignore-line
|
||||
private array $responses = [];
|
||||
private array $triggers = [];
|
||||
private array $webhookDeliveries = [];
|
||||
|
||||
@@ -51,8 +51,8 @@ class ObjectGroupTransformer extends AbstractTransformer
|
||||
|
||||
return [
|
||||
'id' => (string) $objectGroup->id,
|
||||
'created_at' => $objectGroup->created_at?->toAtomString(),
|
||||
'updated_at' => $objectGroup->updated_at?->toAtomString(),
|
||||
'created_at' => $objectGroup->created_at->toAtomString(),
|
||||
'updated_at' => $objectGroup->updated_at->toAtomString(),
|
||||
'title' => $objectGroup->title,
|
||||
'order' => $objectGroup->order,
|
||||
'links' => [['rel' => 'self', 'uri' => '/object_groups/'.$objectGroup->id]],
|
||||
|
||||
@@ -66,8 +66,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' => $amount,
|
||||
'pc_amount' => $primaryAmount,
|
||||
|
||||
|
||||
@@ -32,11 +32,9 @@ use FireflyIII\Http\Middleware\IsAdmin;
|
||||
use FireflyIII\Http\Middleware\Range;
|
||||
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
|
||||
use FireflyIII\Http\Middleware\SecureHeaders;
|
||||
use FireflyIII\Http\Middleware\StartFireflySession;
|
||||
use FireflyIII\Http\Middleware\TrustProxies;
|
||||
use FireflyIII\Http\Middleware\StartFireflyIIISession;
|
||||
use FireflyIII\Http\Middleware\VerifyCsrfToken;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Contracts\Http\Kernel;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
@@ -47,7 +45,6 @@ use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
|
||||
use Illuminate\Foundation\Http\Middleware\TrimStrings;
|
||||
use Illuminate\Http\Middleware\HandleCors;
|
||||
use Illuminate\Http\Middleware\ValidatePostSize;
|
||||
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use Laravel\Passport\Http\Middleware\CreateFreshApiToken;
|
||||
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
|
||||
@@ -92,115 +89,99 @@ if (!function_exists('stringIsEqual')) {
|
||||
$app = Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web : __DIR__ . '/../routes/web.php',
|
||||
api : __DIR__ . '/../routes/api.php',
|
||||
commands: __DIR__ . '/../routes/console.php',
|
||||
health : '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware): void {
|
||||
|
||||
// overrule the standard middleware
|
||||
$middleware->use(
|
||||
[
|
||||
InvokeDeferredCallbacks::class,
|
||||
\Illuminate\Http\Middleware\TrustProxies::class, // use the DEFAULT middleware for this.
|
||||
HandleCors::class,
|
||||
PreventRequestsDuringMaintenance::class,
|
||||
ValidatePostSize::class,
|
||||
TrimStrings::class,
|
||||
ConvertEmptyStringsToNull::class,
|
||||
SecureHeaders::class,
|
||||
TrustProxies::class,
|
||||
SecureHeaders::class, // is a Firefly III specific middleware class.
|
||||
]
|
||||
);
|
||||
|
||||
// overrule the web group
|
||||
// append and extend the default "web" middleware
|
||||
// to include our own custom "StartFireflyIIISession" class.
|
||||
// this class in turns contains a better "previous URL" feature.
|
||||
// See https://laravel.com/docs/12.x/middleware for the default list.
|
||||
$middleware->group('web',
|
||||
[
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
StartFireflyIIISession::class, // this is different.
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
SubstituteBindings::class,
|
||||
Binder::class, // this is also different.
|
||||
CreateFreshApiToken::class,
|
||||
]
|
||||
);
|
||||
// new group?
|
||||
$middleware->appendToGroup('binders-only',
|
||||
[
|
||||
Installer::class,
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
Binder::class,
|
||||
]);
|
||||
|
||||
//
|
||||
$middleware->appendToGroup('user-not-logged-in', [
|
||||
Installer::class,
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
Binder::class,
|
||||
RedirectIfAuthenticated::class,
|
||||
]);
|
||||
// the default API group only contains "substitute bindings" middleware
|
||||
// so here we replace the entire API group and add more sensible stuff.
|
||||
$middleware->group('api',
|
||||
[
|
||||
AcceptHeaders::class,
|
||||
// EnsureFrontendRequestsAreStateful::class,
|
||||
'auth:api',
|
||||
Binder::class,
|
||||
]
|
||||
);
|
||||
$middleware->appendToGroup('api_basic', [AcceptHeaders::class, Binder::class]);
|
||||
|
||||
// more
|
||||
$middleware->appendToGroup('user-logged-in-no-2fa', [
|
||||
Installer::class,
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
Binder::class,
|
||||
Authenticate::class,
|
||||
]);
|
||||
|
||||
// simple auth
|
||||
// "simple auth" means the user must be logged in and present,
|
||||
// but does not have to be 2FA authenticated. This is so all users
|
||||
// can always log out, for example.
|
||||
$middleware->appendToGroup('user-simple-auth', [
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
Binder::class,
|
||||
Authenticate::class,
|
||||
]);
|
||||
|
||||
// user full auth
|
||||
// This middleware is added for all routes where the user MUST have full authentication.
|
||||
// this includes 2FA etc.
|
||||
// incidentally, this group also includes the range middleware and the message thing.
|
||||
$middleware->appendToGroup('user-full-auth', [
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
Authenticate::class,
|
||||
MFAMiddleware::class,
|
||||
Range::class,
|
||||
Binder::class,
|
||||
InterestingMessage::class,
|
||||
CreateFreshApiToken::class,
|
||||
]);
|
||||
|
||||
// admin
|
||||
// This middleware is added to ensure that the user is not only logged in and
|
||||
// authenticated (with MFA and everything), but also admin.
|
||||
$middleware->appendToGroup('admin', [
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
StartFireflySession::class,
|
||||
ShareErrorsFromSession::class,
|
||||
VerifyCsrfToken::class,
|
||||
Authenticate::class,
|
||||
// AuthenticateTwoFactor::class,
|
||||
MFAMiddleware::class,
|
||||
IsAdmin::class,
|
||||
Range::class,
|
||||
Binder::class,
|
||||
CreateFreshApiToken::class,
|
||||
InterestingMessage::class,
|
||||
]);
|
||||
|
||||
// api
|
||||
$middleware->appendToGroup('api', [AcceptHeaders::class, EnsureFrontendRequestsAreStateful::class, 'auth:api,sanctum', Binder::class]);
|
||||
// api basic,
|
||||
$middleware->appendToGroup('api_basic', [AcceptHeaders::class, Binder::class]);
|
||||
// if the user is not logged in, this group applies.
|
||||
// on top of everything else of course.
|
||||
$middleware->appendToGroup('user-not-logged-in', [
|
||||
Installer::class,
|
||||
RedirectIfAuthenticated::class,
|
||||
]);
|
||||
|
||||
// the "binders only" group does not need or ask for authentication
|
||||
// it just makes sure strings from routes are bound to objects if possible.
|
||||
$middleware->group('binders-only',
|
||||
[
|
||||
Installer::class,
|
||||
EncryptCookies::class,
|
||||
AddQueuedCookiesToResponse::class,
|
||||
Binder::class,
|
||||
]);
|
||||
|
||||
// $middleware->priority([StartFireflyIIISession::class, ShareErrorsFromSession::class, Authenticate::class, Binder::class, Authorize::class]);
|
||||
})
|
||||
->withEvents(discover: [
|
||||
__DIR__ . '/../app/Listeners',
|
||||
@@ -225,16 +206,6 @@ $app = Application::configure(basePath: dirname(__DIR__))
|
||||
|
|
||||
*/
|
||||
|
||||
$app->singleton(
|
||||
Kernel::class,
|
||||
FireflyIII\Http\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
Illuminate\Contracts\Console\Kernel::class,
|
||||
FireflyIII\Console\Kernel::class
|
||||
);
|
||||
|
||||
$app->singleton(
|
||||
ExceptionHandler::class,
|
||||
Handler::class
|
||||
|
||||
71
bootstrap/providers.php
Normal file
71
bootstrap/providers.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*
|
||||
* providers.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use FireflyIII\Providers\AccountServiceProvider;
|
||||
use FireflyIII\Providers\AdminServiceProvider;
|
||||
use FireflyIII\Providers\AppServiceProvider;
|
||||
use FireflyIII\Providers\AttachmentServiceProvider;
|
||||
use FireflyIII\Providers\BillServiceProvider;
|
||||
use FireflyIII\Providers\BudgetServiceProvider;
|
||||
use FireflyIII\Providers\CategoryServiceProvider;
|
||||
use FireflyIII\Providers\CurrencyServiceProvider;
|
||||
use FireflyIII\Providers\FireflyServiceProvider;
|
||||
use FireflyIII\Providers\JournalServiceProvider;
|
||||
use FireflyIII\Providers\PiggyBankServiceProvider;
|
||||
use FireflyIII\Providers\RecurringServiceProvider;
|
||||
use FireflyIII\Providers\RouteServiceProvider;
|
||||
use FireflyIII\Providers\RuleGroupServiceProvider;
|
||||
use FireflyIII\Providers\RuleServiceProvider;
|
||||
use FireflyIII\Providers\SearchServiceProvider;
|
||||
use FireflyIII\Providers\TagServiceProvider;
|
||||
use TwigBridge\ServiceProvider;
|
||||
|
||||
return [
|
||||
// Package Service Providers...
|
||||
|
||||
// Application Service Providers...
|
||||
AppServiceProvider::class,
|
||||
FireflyIII\Providers\AuthServiceProvider::class,
|
||||
// FireflyIII\Providers\BroadcastServiceProvider::class,
|
||||
// EventServiceProvider::class,
|
||||
RouteServiceProvider::class,
|
||||
|
||||
// own stuff:
|
||||
PragmaRX\Google2FALaravel\ServiceProvider::class,
|
||||
ServiceProvider::class,
|
||||
|
||||
// More service providers.
|
||||
AccountServiceProvider::class,
|
||||
AttachmentServiceProvider::class,
|
||||
BillServiceProvider::class,
|
||||
BudgetServiceProvider::class,
|
||||
CategoryServiceProvider::class,
|
||||
CurrencyServiceProvider::class,
|
||||
FireflyServiceProvider::class,
|
||||
JournalServiceProvider::class,
|
||||
PiggyBankServiceProvider::class,
|
||||
RuleServiceProvider::class,
|
||||
RuleGroupServiceProvider::class,
|
||||
SearchServiceProvider::class,
|
||||
TagServiceProvider::class,
|
||||
AdminServiceProvider::class,
|
||||
RecurringServiceProvider::class,
|
||||
];
|
||||
49
changelog.md
49
changelog.md
@@ -3,6 +3,55 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## v6.4.21
|
||||
|
||||
### Added
|
||||
- The ability to undo the recording of a database migration, which may help with database issues. [See the docs](https://docs.firefly-iii.org/references/faq/firefly-iii/using/#i-get-errors-about-missing-tables-how-do-i-fix-this)
|
||||
- Added debug logs to file permission checks.
|
||||
|
||||
### Fixed
|
||||
- View range issue for subscription overview
|
||||
- Amount log entries were recorded for the transaction group, not the journal
|
||||
- Subscriptions were not being renamed in rules when their names were changed
|
||||
- [Issue 11688](https://github.com/firefly-iii/firefly-iii/issues/11688) (Token endpoints returning 401 unauthorized) reported by @molnarti
|
||||
- [Issue 11694](https://github.com/firefly-iii/firefly-iii/issues/11694) (Foreign currency amount is always positive in transfers) reported by @SledgehammerPL
|
||||
- [Issue 11684](https://github.com/firefly-iii/firefly-iii/issues/11684) (Transaction summary duplicated after more than 10 rows) reported by @jkmf
|
||||
- [Issue 11700](https://github.com/firefly-iii/firefly-iii/issues/11700) (Duplicate entry for key 'tag_transaction_journal_tag_id_transaction_journal_id_unique') reported by @beatbesmer
|
||||
- [Issue 11702](https://github.com/firefly-iii/firefly-iii/issues/11702) (Can't enable displaying primary currency when using Postgres) reported by @absdjfh
|
||||
- [Issue 11710](https://github.com/firefly-iii/firefly-iii/issues/11710) (Firefly throws error on startup and when trying to use importer) reported by @avee87
|
||||
|
||||
## v6.4.20
|
||||
|
||||
### Added
|
||||
- The ability to undo the recording of a database migration, which may help with database issues. [See the docs](https://docs.firefly-iii.org/references/faq/firefly-iii/using/#i-get-errors-about-missing-tables-how-do-i-fix-this)
|
||||
- Added debug logs to file permission checks.
|
||||
|
||||
### Fixed
|
||||
- View range issue for subscription overview
|
||||
- Amount log entries were recorded for the transaction group, not the journal
|
||||
- Subscriptions were not being renamed in rules when their names were changed
|
||||
- [Issue 11688](https://github.com/firefly-iii/firefly-iii/issues/11688) (Token endpoints returning 401 unauthorized) reported by @molnarti
|
||||
- [Issue 11694](https://github.com/firefly-iii/firefly-iii/issues/11694) (Foreign currency amount is always positive in transfers) reported by @SledgehammerPL
|
||||
- [Issue 11684](https://github.com/firefly-iii/firefly-iii/issues/11684) (Transaction summary duplicated after more than 10 rows) reported by @jkmf
|
||||
- [Issue 11700](https://github.com/firefly-iii/firefly-iii/issues/11700) (Duplicate entry for key 'tag_transaction_journal_tag_id_transaction_journal_id_unique') reported by @beatbesmer
|
||||
- [Issue 11702](https://github.com/firefly-iii/firefly-iii/issues/11702) (Can't enable displaying primary currency when using Postgres) reported by @absdjfh
|
||||
|
||||
## v6.4.19
|
||||
|
||||
### Added
|
||||
- The ability to undo the recording of a database migration, which may help with database issues. [See the docs](https://docs.firefly-iii.org/references/faq/firefly-iii/using/#i-get-errors-about-missing-tables-how-do-i-fix-this)
|
||||
- Added debug logs to file permission checks
|
||||
|
||||
### Fixed
|
||||
- View range issue for subscription overview
|
||||
- Amount log entries were recorded for the transaction group, not the journal
|
||||
- Subscriptions were not being renamed in rules when their names were changed
|
||||
- [Issue 11688](https://github.com/firefly-iii/firefly-iii/issues/11688) (Token endpoints returning 401 unauthorized) reported by @molnarti
|
||||
- [Issue 11694](https://github.com/firefly-iii/firefly-iii/issues/11694) (Foreign currency amount is always positive in transfers) reported by @SledgehammerPL
|
||||
- [Issue 11684](https://github.com/firefly-iii/firefly-iii/issues/11684) (Transaction summary duplicated after more than 10 rows) reported by @jkmf
|
||||
- [Issue 11700](https://github.com/firefly-iii/firefly-iii/issues/11700) (Duplicate entry for key 'tag_transaction_journal_tag_id_transaction_journal_id_unique') reported by @beatbesmer
|
||||
- [Issue 11702](https://github.com/firefly-iii/firefly-iii/issues/11702) (Can't enable displaying primary currency when using Postgres) reported by @absdjfh
|
||||
|
||||
## v6.4.18
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -34,9 +34,6 @@
|
||||
"transfers",
|
||||
"management"
|
||||
],
|
||||
"platform": {
|
||||
"php": "8.4"
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"homepage": "https://github.com/firefly-iii/firefly-iii",
|
||||
"type": "project",
|
||||
@@ -93,7 +90,6 @@
|
||||
"laravel-notification-channels/pushover": "^4.0",
|
||||
"laravel/framework": "^12",
|
||||
"laravel/passport": "^12.0",
|
||||
"laravel/sanctum": "^4.1",
|
||||
"laravel/slack-notification-channel": "^3.3",
|
||||
"laravel/ui": "^4.2",
|
||||
"league/commonmark": "^2",
|
||||
|
||||
175
composer.lock
generated
175
composer.lock
generated
@@ -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": "c4e7dd2df7bae96ea6e4df82530411b9",
|
||||
"content-hash": "6c4181d945517372c00358f3828806bc",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -2233,69 +2233,6 @@
|
||||
},
|
||||
"time": "2026-02-06T12:17:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/sanctum",
|
||||
"version": "v4.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laravel/sanctum.git",
|
||||
"reference": "e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laravel/sanctum/zipball/e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76",
|
||||
"reference": "e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"illuminate/console": "^11.0|^12.0|^13.0",
|
||||
"illuminate/contracts": "^11.0|^12.0|^13.0",
|
||||
"illuminate/database": "^11.0|^12.0|^13.0",
|
||||
"illuminate/support": "^11.0|^12.0|^13.0",
|
||||
"php": "^8.2",
|
||||
"symfony/console": "^7.0|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.6",
|
||||
"orchestra/testbench": "^9.15|^10.8|^11.0",
|
||||
"phpstan/phpstan": "^1.10"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Laravel\\Sanctum\\SanctumServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laravel\\Sanctum\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Taylor Otwell",
|
||||
"email": "taylor@laravel.com"
|
||||
}
|
||||
],
|
||||
"description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.",
|
||||
"keywords": [
|
||||
"auth",
|
||||
"laravel",
|
||||
"sanctum"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/laravel/sanctum/issues",
|
||||
"source": "https://github.com/laravel/sanctum"
|
||||
},
|
||||
"time": "2026-02-07T17:19:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/serializable-closure",
|
||||
"version": "v2.0.9",
|
||||
@@ -3894,16 +3831,16 @@
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v4.1.2",
|
||||
"version": "v4.1.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5"
|
||||
"reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/f76b5dc3d6c6d3043c8d937df2698515b99cbaf5",
|
||||
"reference": "f76b5dc3d6c6d3043c8d937df2698515b99cbaf5",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/bb3ea637e3d131d72acc033cfc2746ee893349fe",
|
||||
"reference": "bb3ea637e3d131d72acc033cfc2746ee893349fe",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3915,8 +3852,10 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"jetbrains/phpstorm-attributes": "^1.2",
|
||||
"nette/phpstan-rules": "^1.0",
|
||||
"nette/tester": "^2.5",
|
||||
"phpstan/phpstan": "^2.0@stable",
|
||||
"phpstan/extension-installer": "^1.4@stable",
|
||||
"phpstan/phpstan": "^2.1@stable",
|
||||
"tracy/tracy": "^2.9"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -3977,9 +3916,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v4.1.2"
|
||||
"source": "https://github.com/nette/utils/tree/v4.1.3"
|
||||
},
|
||||
"time": "2026-02-03T17:21:09+00:00"
|
||||
"time": "2026-02-13T03:05:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nunomaduro/collision",
|
||||
@@ -5120,16 +5059,16 @@
|
||||
},
|
||||
{
|
||||
"name": "predis/predis",
|
||||
"version": "v3.3.0",
|
||||
"version": "v3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/predis/predis.git",
|
||||
"reference": "153097374b39a2f737fe700ebcd725642526cdec"
|
||||
"reference": "1183f5732e6b10efd33f64984a96726eaecb59aa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/153097374b39a2f737fe700ebcd725642526cdec",
|
||||
"reference": "153097374b39a2f737fe700ebcd725642526cdec",
|
||||
"url": "https://api.github.com/repos/predis/predis/zipball/1183f5732e6b10efd33f64984a96726eaecb59aa",
|
||||
"reference": "1183f5732e6b10efd33f64984a96726eaecb59aa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5171,7 +5110,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/predis/predis/issues",
|
||||
"source": "https://github.com/predis/predis/tree/v3.3.0"
|
||||
"source": "https://github.com/predis/predis/tree/v3.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5179,7 +5118,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-24T17:48:50+00:00"
|
||||
"time": "2026-02-11T17:30:28+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
@@ -9646,16 +9585,16 @@
|
||||
},
|
||||
{
|
||||
"name": "thecodingmachine/safe",
|
||||
"version": "v3.3.0",
|
||||
"version": "v3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thecodingmachine/safe.git",
|
||||
"reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236"
|
||||
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thecodingmachine/safe/zipball/2cdd579eeaa2e78e51c7509b50cc9fb89a956236",
|
||||
"reference": "2cdd579eeaa2e78e51c7509b50cc9fb89a956236",
|
||||
"url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -9765,7 +9704,7 @@
|
||||
"description": "PHP core functions that throw exceptions instead of returning FALSE on error",
|
||||
"support": {
|
||||
"issues": "https://github.com/thecodingmachine/safe/issues",
|
||||
"source": "https://github.com/thecodingmachine/safe/tree/v3.3.0"
|
||||
"source": "https://github.com/thecodingmachine/safe/tree/v3.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -9776,12 +9715,16 @@
|
||||
"url": "https://github.com/shish",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/silasjoisten",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/staabm",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-05-14T06:15:44+00:00"
|
||||
"time": "2026-02-04T18:08:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
@@ -10530,16 +10473,16 @@
|
||||
},
|
||||
{
|
||||
"name": "fruitcake/laravel-debugbar",
|
||||
"version": "v4.0.7",
|
||||
"version": "v4.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/fruitcake/laravel-debugbar.git",
|
||||
"reference": "a9cc62c81cd0bda4ca7410229487638d7df786be"
|
||||
"reference": "ad7a5b11c11bf7773c9acd04d0fe0d79a229b1c7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/a9cc62c81cd0bda4ca7410229487638d7df786be",
|
||||
"reference": "a9cc62c81cd0bda4ca7410229487638d7df786be",
|
||||
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/ad7a5b11c11bf7773c9acd04d0fe0d79a229b1c7",
|
||||
"reference": "ad7a5b11c11bf7773c9acd04d0fe0d79a229b1c7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10616,7 +10559,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
|
||||
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.0.7"
|
||||
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.0.8"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10628,7 +10571,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-06T20:53:50+00:00"
|
||||
"time": "2026-02-14T13:26:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
@@ -11198,16 +11141,16 @@
|
||||
},
|
||||
{
|
||||
"name": "php-debugbar/php-debugbar",
|
||||
"version": "v3.3.1",
|
||||
"version": "v3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-debugbar/php-debugbar.git",
|
||||
"reference": "afdaa2e56aca9d56b5bb2bad041bd2f6002017cf"
|
||||
"reference": "e50d470344b62a033a76d3d10a803b04c8e3be69"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/afdaa2e56aca9d56b5bb2bad041bd2f6002017cf",
|
||||
"reference": "afdaa2e56aca9d56b5bb2bad041bd2f6002017cf",
|
||||
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/e50d470344b62a033a76d3d10a803b04c8e3be69",
|
||||
"reference": "e50d470344b62a033a76d3d10a803b04c8e3be69",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11284,7 +11227,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
|
||||
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.3.1"
|
||||
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -11296,7 +11239,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-06T21:09:38+00:00"
|
||||
"time": "2026-02-14T14:10:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-debugbar/symfony-bridge",
|
||||
@@ -11414,11 +11357,11 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.38",
|
||||
"version": "2.1.39",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/dfaf1f530e1663aa167bc3e52197adb221582629",
|
||||
"reference": "dfaf1f530e1663aa167bc3e52197adb221582629",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224",
|
||||
"reference": "c6f73a2af4cbcd99c931d0fb8f08548cc0fa8224",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11463,25 +11406,25 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-30T17:12:46+00:00"
|
||||
"time": "2026-02-11T14:48:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
|
||||
"reference": "468e02c9176891cc901143da118f09dc9505fc2f"
|
||||
"reference": "6b5571001a7f04fa0422254c30a0017ec2f2cacc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f",
|
||||
"reference": "468e02c9176891cc901143da118f09dc9505fc2f",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/6b5571001a7f04fa0422254c30a0017ec2f2cacc",
|
||||
"reference": "6b5571001a7f04fa0422254c30a0017ec2f2cacc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"phpstan/phpstan": "^2.1.15"
|
||||
"phpstan/phpstan": "^2.1.39"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
@@ -11506,29 +11449,32 @@
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
|
||||
"keywords": [
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3"
|
||||
"source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.4"
|
||||
},
|
||||
"time": "2025-05-14T10:56:57+00:00"
|
||||
"time": "2026-02-09T13:21:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "2.0.8",
|
||||
"version": "2.0.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "1ed9e626a37f7067b594422411539aa807190573"
|
||||
"reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1ed9e626a37f7067b594422411539aa807190573",
|
||||
"reference": "1ed9e626a37f7067b594422411539aa807190573",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f",
|
||||
"reference": "1aba28b697c1e3b6bbec8a1725f8b11b6d3e5a5f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"phpstan/phpstan": "^2.1.29"
|
||||
"phpstan/phpstan": "^2.1.39"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
@@ -11554,11 +11500,14 @@
|
||||
"MIT"
|
||||
],
|
||||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"keywords": [
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.8"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.10"
|
||||
},
|
||||
"time": "2026-01-27T08:10:25+00:00"
|
||||
"time": "2026-02-11T14:17:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
||||
@@ -22,59 +22,18 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use FireflyIII\Providers\AccountServiceProvider;
|
||||
use FireflyIII\Providers\AdminServiceProvider;
|
||||
use FireflyIII\Providers\AppServiceProvider;
|
||||
use FireflyIII\Providers\AttachmentServiceProvider;
|
||||
use FireflyIII\Providers\BillServiceProvider;
|
||||
use FireflyIII\Providers\BudgetServiceProvider;
|
||||
use FireflyIII\Providers\CategoryServiceProvider;
|
||||
use FireflyIII\Providers\CurrencyServiceProvider;
|
||||
use FireflyIII\Providers\EventServiceProvider;
|
||||
use FireflyIII\Providers\FireflyServiceProvider;
|
||||
use FireflyIII\Providers\JournalServiceProvider;
|
||||
use FireflyIII\Providers\PiggyBankServiceProvider;
|
||||
use FireflyIII\Providers\RecurringServiceProvider;
|
||||
use FireflyIII\Providers\RouteServiceProvider;
|
||||
use FireflyIII\Providers\RuleGroupServiceProvider;
|
||||
use FireflyIII\Providers\RuleServiceProvider;
|
||||
use FireflyIII\Providers\SearchServiceProvider;
|
||||
use FireflyIII\Providers\SessionServiceProvider;
|
||||
use FireflyIII\Providers\TagServiceProvider;
|
||||
use FireflyIII\Support\Facades\AccountForm;
|
||||
use FireflyIII\Support\Facades\CurrencyForm;
|
||||
use FireflyIII\Support\Facades\ExpandedForm;
|
||||
use FireflyIII\Support\Facades\PiggyBankForm;
|
||||
use FireflyIII\Support\Facades\RuleForm;
|
||||
use Illuminate\Auth\AuthServiceProvider;
|
||||
use Illuminate\Auth\Passwords\PasswordResetServiceProvider;
|
||||
use Illuminate\Broadcasting\BroadcastServiceProvider;
|
||||
use Illuminate\Bus\BusServiceProvider;
|
||||
use Illuminate\Cache\CacheServiceProvider;
|
||||
use Illuminate\Cookie\CookieServiceProvider;
|
||||
use Illuminate\Database\DatabaseServiceProvider;
|
||||
use Illuminate\Encryption\EncryptionServiceProvider;
|
||||
use Illuminate\Filesystem\FilesystemServiceProvider;
|
||||
use Illuminate\Foundation\Providers\ConsoleSupportServiceProvider;
|
||||
use Illuminate\Foundation\Providers\FoundationServiceProvider;
|
||||
use Illuminate\Hashing\HashServiceProvider;
|
||||
use Illuminate\Mail\MailServiceProvider;
|
||||
use Illuminate\Notifications\NotificationServiceProvider;
|
||||
use Illuminate\Pagination\PaginationServiceProvider;
|
||||
use Illuminate\Pipeline\PipelineServiceProvider;
|
||||
use Illuminate\Queue\QueueServiceProvider;
|
||||
use Illuminate\Redis\RedisServiceProvider;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Lang;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Translation\TranslationServiceProvider;
|
||||
use Illuminate\Validation\ValidationServiceProvider;
|
||||
use Illuminate\View\ViewServiceProvider;
|
||||
use Spatie\Html\Facades\Html;
|
||||
use TwigBridge\ServiceProvider;
|
||||
|
||||
return [
|
||||
'name' => envNonEmpty('APP_NAME', 'Firefly III'),
|
||||
@@ -86,61 +45,6 @@ return [
|
||||
'fallback_locale' => 'en_US',
|
||||
'key' => env('APP_KEY'),
|
||||
'cipher' => 'AES-256-CBC',
|
||||
'providers' => [
|
||||
// Laravel Framework Service Providers...
|
||||
AuthServiceProvider::class,
|
||||
BroadcastServiceProvider::class,
|
||||
BusServiceProvider::class,
|
||||
CacheServiceProvider::class,
|
||||
ConsoleSupportServiceProvider::class,
|
||||
CookieServiceProvider::class,
|
||||
DatabaseServiceProvider::class,
|
||||
EncryptionServiceProvider::class,
|
||||
FilesystemServiceProvider::class,
|
||||
FoundationServiceProvider::class,
|
||||
HashServiceProvider::class,
|
||||
MailServiceProvider::class,
|
||||
NotificationServiceProvider::class,
|
||||
PaginationServiceProvider::class,
|
||||
PipelineServiceProvider::class,
|
||||
QueueServiceProvider::class,
|
||||
RedisServiceProvider::class,
|
||||
PasswordResetServiceProvider::class,
|
||||
SessionServiceProvider::class,
|
||||
TranslationServiceProvider::class,
|
||||
ValidationServiceProvider::class,
|
||||
ViewServiceProvider::class,
|
||||
|
||||
// Package Service Providers...
|
||||
|
||||
// Application Service Providers...
|
||||
AppServiceProvider::class,
|
||||
FireflyIII\Providers\AuthServiceProvider::class,
|
||||
// FireflyIII\Providers\BroadcastServiceProvider::class,
|
||||
// EventServiceProvider::class,
|
||||
RouteServiceProvider::class,
|
||||
|
||||
// own stuff:
|
||||
PragmaRX\Google2FALaravel\ServiceProvider::class,
|
||||
ServiceProvider::class,
|
||||
|
||||
// More service providers.
|
||||
AccountServiceProvider::class,
|
||||
AttachmentServiceProvider::class,
|
||||
BillServiceProvider::class,
|
||||
BudgetServiceProvider::class,
|
||||
CategoryServiceProvider::class,
|
||||
CurrencyServiceProvider::class,
|
||||
FireflyServiceProvider::class,
|
||||
JournalServiceProvider::class,
|
||||
PiggyBankServiceProvider::class,
|
||||
RuleServiceProvider::class,
|
||||
RuleGroupServiceProvider::class,
|
||||
SearchServiceProvider::class,
|
||||
TagServiceProvider::class,
|
||||
AdminServiceProvider::class,
|
||||
RecurringServiceProvider::class,
|
||||
],
|
||||
'aliases' => [
|
||||
'Auth' => Auth::class,
|
||||
'Route' => Route::class,
|
||||
|
||||
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2026-02-10',
|
||||
'build_time' => 1770751756,
|
||||
'version' => 'develop/2026-02-15',
|
||||
'build_time' => 1771170494,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 28, // field is no longer used.
|
||||
|
||||
|
||||
86
package-lock.json
generated
86
package-lock.json
generated
@@ -3814,9 +3814,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ajv-formats/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -4240,6 +4240,22 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/body-parser/node_modules/qs": {
|
||||
"version": "6.14.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
|
||||
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/bonjour-service": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
|
||||
@@ -4578,9 +4594,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001769",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz",
|
||||
"integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==",
|
||||
"version": "1.0.30001770",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz",
|
||||
"integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@@ -6191,6 +6207,22 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/express/node_modules/qs": {
|
||||
"version": "6.14.2",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz",
|
||||
"integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"side-channel": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -7118,9 +7150,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "25.8.4",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.4.tgz",
|
||||
"integrity": "sha512-a9A0MnUjKvzjEN/26ZY1okpra9kA8MEwzYEz1BNm+IyxUKPRH6ihf0p7vj8YvULwZHKHl3zkJ6KOt4hewxBecQ==",
|
||||
"version": "25.8.7",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.8.7.tgz",
|
||||
"integrity": "sha512-ttxxc5+67S/0hhoeVdEgc1lRklZhdfcUSEPp1//uUG2NB88X3667gRsDar+ZWQFdysnOsnb32bcoMsa4mtzhkQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
@@ -9717,9 +9749,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.14.1",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
|
||||
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
|
||||
"version": "6.15.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.0.tgz",
|
||||
"integrity": "sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
@@ -11033,9 +11065,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11801,9 +11833,9 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.105.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.1.tgz",
|
||||
"integrity": "sha512-Gdj3X74CLJJ8zy4URmK42W7wTZUJrqL+z8nyGEr4dTN0kb3nVs+ZvjbTOqRYPD7qX4tUmwyHL9Q9K6T1seW6Yw==",
|
||||
"version": "5.105.2",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz",
|
||||
"integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -11922,9 +11954,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-middleware/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -12039,9 +12071,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack-dev-server/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -12159,9 +12191,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webpack/node_modules/ajv": {
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
||||
"version": "8.18.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
|
||||
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
"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.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") has been updated.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> er blevet gemt.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") er blevet opdateret.",
|
||||
"transaction_updated_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> (\"{title}\") has been updated.",
|
||||
"transaction_new_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID}<\/a> has been stored.",
|
||||
"transaction_journal_information": "Transaction information",
|
||||
@@ -31,7 +31,7 @@
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"no_budget_pointer": "Det ser ud til, at du ikke har oprettet budgetter endnu. Du burde oprette nogle p\u00e5 <a href=\"\/budgets\">budgetsiden<\/a>. Budgetter kan hj\u00e6lpe dig med at holde styr p\u00e5 udgifter.",
|
||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
||||
"no_bill_pointer": "Det ser ikke ud til, at du har nogle budgetter endnu. Du burde oprette nogle p\u00e5 <a href=\"\/budgets\">budgetsiden<\/a>. Budgetter kan hj\u00e6lpe dig med at holde styr p\u00e5 udgifter.",
|
||||
"source_account": "Kildekonto",
|
||||
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
||||
"destination_account": "Destinationskonto",
|
||||
@@ -107,42 +107,42 @@
|
||||
"multi_account_warning_withdrawal": "Husk, at kildekontoen for efterf\u00f8lgende opdelinger vil blive overstyret af hvad der er defineret i den f\u00f8rste opdeling af tilbagetr\u00e6kningen.",
|
||||
"multi_account_warning_deposit": "Husk, at destinationskontoen for efterf\u00f8lgende opdelinger vil blive tilsidesat af hvad der er defineret i den f\u00f8rste opsplitning af depositummet.",
|
||||
"multi_account_warning_transfer": "Husk p\u00e5, at kilden + destination konto for efterf\u00f8lgende opdelinger vil blive overstyret af hvad der er defineret i den f\u00f8rste opdeling af overf\u00f8rslen.",
|
||||
"webhook_trigger_ANY": "After any event",
|
||||
"webhook_trigger_ANY": "Efter enhver begivenhed",
|
||||
"webhook_trigger_STORE_TRANSACTION": "Efter oprettelse af transaktion",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Efter opdatering af transaktion",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Efter sletning af transaktion",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_trigger_STORE_BUDGET": "Efter budgetoprettelse",
|
||||
"webhook_trigger_UPDATE_BUDGET": "Efter budgetopdatering",
|
||||
"webhook_trigger_DESTROY_BUDGET": "Efter sletning af budget",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "Efter budgetteret bel\u00f8b \u00e6ndring",
|
||||
"webhook_response_TRANSACTIONS": "Transaktionsdetaljer",
|
||||
"webhook_response_RELEVANT": "Relevant details",
|
||||
"webhook_response_RELEVANT": "Relevante oplysninger",
|
||||
"webhook_response_ACCOUNTS": "Kontodetaljer",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_response_NONE": "Ingen detaljer",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Handlinger",
|
||||
"meta_data": "Meta data",
|
||||
"webhook_messages": "Webhook-besked",
|
||||
"inactive": "Inactive",
|
||||
"no_webhook_messages": "Der er ingen webhook-beskeder",
|
||||
"inspect": "Inspect",
|
||||
"inspect": "Unders\u00f8g",
|
||||
"create_new_webhook": "Opret ny webhook",
|
||||
"webhooks": "Webhooks",
|
||||
"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_trigger_form_help": "Indik\u00e9r p\u00e5 hvilken begivenhed webhook vil udl\u00f8se",
|
||||
"webhook_response_form_help": "Angiv, hvad webhook skal indsende til URL.",
|
||||
"webhook_delivery_form_help": "Hvilket format webhook skal levere data i.",
|
||||
"webhook_active_form_help": "Webhooken skal v\u00e6re aktiv, ellers vil den ikke blive kaldt.",
|
||||
"edit_webhook_js": "Rediger webhook \"{title}\"",
|
||||
"webhook_was_triggered": "The webhook was triggered on the indicated transaction. Please wait for results to appear.",
|
||||
"webhook_was_triggered": "Webhooken blev udl\u00f8st p\u00e5 den angivne transaktion. Vent venligst p\u00e5 at resultaterne vises.",
|
||||
"view_message": "Vis besked",
|
||||
"view_attempts": "Vis mislykkede fors\u00f8g",
|
||||
"message_content_title": "Webhook-beskedindhold",
|
||||
"message_content_help": "This is the content of the message that was sent (or tried) using this webhook.",
|
||||
"message_content_help": "Dette er indholdet af den besked, der blev sendt (eller fors\u00f8gt) ved hj\u00e6lp af denne webhook.",
|
||||
"attempt_content_title": "Webhook-fors\u00f8g",
|
||||
"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.",
|
||||
"attempt_content_help": "Disse er alle de mislykkede fors\u00f8g p\u00e5 at sende denne webhook-meddelelse til den konfigurerede URL. Efter et stykke tid vil Firefly III stoppe med at fors\u00f8ge.",
|
||||
"no_attempts": "Der er ingen mislykkede fors\u00f8g. Det er en god ting!",
|
||||
"webhook_attempt_at": "Attempt at {moment}",
|
||||
"logs": "Logs",
|
||||
"webhook_attempt_at": "Fors\u00f8g p\u00e5 {moment}",
|
||||
"logs": "Logfiler",
|
||||
"response": "Svar",
|
||||
"visit_webhook_url": "Bes\u00f8g webhook-URL",
|
||||
"reset_webhook_secret": "Nulstil webhook-hemmelighed",
|
||||
|
||||
@@ -107,18 +107,18 @@
|
||||
"multi_account_warning_withdrawal": "Tenga en cuenta que la cuenta de origen de las divisiones posteriores ser\u00e1 anulada por lo que se defina en la primera divisi\u00f3n del gasto.",
|
||||
"multi_account_warning_deposit": "Tenga en cuenta que la cuenta de destino de las divisiones posteriores ser\u00e1 anulada por lo que se defina en la primera divisi\u00f3n del retiro.",
|
||||
"multi_account_warning_transfer": "Tenga en cuenta que la cuenta de origen + destino de divisiones posteriores ser\u00e1 anulada por lo que se defina en la primera divisi\u00f3n de la transferencia.",
|
||||
"webhook_trigger_ANY": "After any event",
|
||||
"webhook_trigger_ANY": "Despu\u00e9s de cualquier evento",
|
||||
"webhook_trigger_STORE_TRANSACTION": "Despu\u00e9s de crear la transacci\u00f3n",
|
||||
"webhook_trigger_UPDATE_TRANSACTION": "Despu\u00e9s de actualizar la transacci\u00f3n",
|
||||
"webhook_trigger_DESTROY_TRANSACTION": "Despu\u00e9s de eliminar la transacci\u00f3n",
|
||||
"webhook_trigger_STORE_BUDGET": "After budget creation",
|
||||
"webhook_trigger_STORE_BUDGET": "Despu\u00e9s de crear un presupuesto",
|
||||
"webhook_trigger_UPDATE_BUDGET": "After budget update",
|
||||
"webhook_trigger_DESTROY_BUDGET": "After budget delete",
|
||||
"webhook_trigger_STORE_UPDATE_BUDGET_LIMIT": "After budgeted amount change",
|
||||
"webhook_response_TRANSACTIONS": "Detalles de la transacci\u00f3n",
|
||||
"webhook_response_RELEVANT": "Relevant details",
|
||||
"webhook_response_ACCOUNTS": "Detalles de la cuenta",
|
||||
"webhook_response_NONE": "No details",
|
||||
"webhook_response_NONE": "Sin detalles",
|
||||
"webhook_delivery_JSON": "JSON",
|
||||
"actions": "Acciones",
|
||||
"meta_data": "Meta Datos",
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
"destination_account_reconciliation": "\uc870\uc815 \uac70\ub798\uc758 \ubaa9\uc801\uc9c0 \uacc4\uc815\uc740 \ud3b8\uc9d1\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
|
||||
"source_account_reconciliation": "\uc870\uc815 \uac70\ub798\uc758 \ucd9c\ubc1c\uc9c0 \uacc4\uc815\uc740 \ud3b8\uc9d1\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
|
||||
"budget": "\uc608\uc0b0",
|
||||
"bill": "Subscription",
|
||||
"bill": "\uad6c\ub3c5",
|
||||
"you_create_withdrawal": "\ucd9c\uae08\uc744 \uc0dd\uc131\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4.",
|
||||
"you_create_transfer": "\uc804\uc1a1\uc744 \uc0dd\uc131\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4.",
|
||||
"you_create_deposit": "\uc785\uae08\uc744 \uc0dd\uc131\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4.",
|
||||
|
||||
@@ -184,11 +184,14 @@
|
||||
{{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_decimal_places, false) }}
|
||||
{% endif %}
|
||||
{% if transaction.source_account_id != account.id %}
|
||||
{{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_decimal_places, false) }}
|
||||
{{ formatAmountBySymbol(transaction.amount*-1, transaction.currency_symbol, transaction.currency_decimal_places, false) }}
|
||||
{% endif %}
|
||||
|
||||
{# foreign amount of transfer #}
|
||||
{% if null != transaction.foreign_amount %}
|
||||
{% if null != transaction.foreign_amount and transaction.source_account_id == account.id %}
|
||||
({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places, false) }})
|
||||
{% endif %}
|
||||
{% if null != transaction.foreign_amount and transaction.source_account_id != account.id %}
|
||||
({{ formatAmountBySymbol(transaction.foreign_amount*-1, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places, false) }})
|
||||
{% endif %}
|
||||
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use FireflyIII\Http\Middleware\AcceptHeaders;
|
||||
use FireflyIII\Http\Middleware\Binder;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
use function Safe\define;
|
||||
@@ -38,6 +41,19 @@ if (!defined('DATEFORMAT')) {
|
||||
define('DATEFORMAT', '(19|20)[0-9]{2}-?[0-9]{2}-?[0-9]{2}');
|
||||
}
|
||||
|
||||
// API route for cron
|
||||
Route::group(
|
||||
[
|
||||
'namespace' => 'FireflyIII\Api\V1\Controllers\System',
|
||||
'prefix' => 'v1',
|
||||
'as' => 'api.v1.cron.',
|
||||
'middleware' => [Binder::class, AcceptHeaders::class],
|
||||
],
|
||||
static function (): void {
|
||||
Route::get('cron/{cliToken}', ['uses' => 'CronController@cron', 'as' => 'index'])->withoutMiddleware(['api']);
|
||||
}
|
||||
);
|
||||
|
||||
// Autocomplete controllers
|
||||
Route::group(
|
||||
[
|
||||
|
||||
@@ -73,24 +73,24 @@ Route::group(
|
||||
}
|
||||
);
|
||||
|
||||
Route::group(
|
||||
['middleware' => 'binders-only', 'namespace' => 'FireflyIII\Http\Controllers\System', 'as' => 'cron.', 'prefix' => 'cron'],
|
||||
static function (): void {
|
||||
Route::get('run/{cliToken}', ['uses' => 'CronController@cron', 'as' => 'cron']);
|
||||
}
|
||||
);
|
||||
// Route::group(
|
||||
// ['middleware' => 'binders-only', 'namespace' => 'FireflyIII\Http\Controllers\System', 'as' => 'cron.', 'prefix' => 'cron'],
|
||||
// static function (): void {
|
||||
// Route::get('run/{cliToken}', ['uses' => 'CronController@cron', 'as' => 'cron']);
|
||||
// }
|
||||
// );
|
||||
|
||||
Route::group(
|
||||
['middleware' => 'binders-only', 'namespace' => 'FireflyIII\Http\Controllers\System'],
|
||||
['middleware' => ['binders-only'], 'namespace' => 'FireflyIII\Http\Controllers\System'],
|
||||
static function (): void {
|
||||
// Route::get('offline', static fn () => view('errors.offline'));
|
||||
Route::get('health', ['uses' => 'HealthcheckController@check', 'as' => 'healthcheck']);
|
||||
Route::get('health', ['uses' => 'HealthcheckController@check', 'as' => 'healthcheck'])->withoutMiddleware(['web']);
|
||||
}
|
||||
);
|
||||
|
||||
// These routes only work when the user is NOT logged in.
|
||||
Route::group(
|
||||
['middleware' => 'user-not-logged-in', 'namespace' => 'FireflyIII\Http\Controllers'],
|
||||
['middleware' => ['user-not-logged-in'], 'namespace' => 'FireflyIII\Http\Controllers'],
|
||||
static function (): void {
|
||||
// Authentication Routes...
|
||||
Route::get('login', ['uses' => 'Auth\LoginController@showLoginForm', 'as' => 'login']);
|
||||
@@ -128,7 +128,7 @@ Route::group(
|
||||
|
||||
// For the two factor routes, the user must be logged in, but NOT 2FA. Account confirmation does not matter here.
|
||||
Route::group(
|
||||
['middleware' => 'user-logged-in-no-2fa', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'FireflyIII\Http\Controllers\Auth'],
|
||||
['middleware' => 'user-simple-auth', 'prefix' => 'two-factor', 'as' => 'two-factor.', 'namespace' => 'FireflyIII\Http\Controllers\Auth'],
|
||||
static function (): void {
|
||||
Route::post('submit', ['uses' => 'TwoFactorController@submitMFA', 'as' => 'submit']);
|
||||
Route::get('lost', ['uses' => 'TwoFactorController@lostTwoFactor', 'as' => 'lost']); // can be removed when v2 is live.
|
||||
|
||||
Reference in New Issue
Block a user