Compare commits

...

14 Commits

Author SHA1 Message Date
github-actions[bot]
75aa2d99fd Merge pull request #11055 from firefly-iii/release-1760278017
🤖 Automatically merge the PR into the develop branch.
2025-10-12 16:07:07 +02:00
JC5
f52bc0e242 🤖 Auto commit for release 'develop' on 2025-10-12 2025-10-12 16:06:57 +02:00
James Cole
55cf924794 Another fix for #11054 2025-10-12 16:02:14 +02:00
James Cole
df3e4a6554 Fix #11054 2025-10-12 12:25:21 +02:00
James Cole
7c4ada458e Merge pull request #11052 from ctrl-f5/fix/incorrect-validator-function
correct validator function to check for errors + `Account\ShowControllerTest`
2025-10-12 06:47:19 +02:00
Nicky De Maeyer
2a4a98dd10 use the correct validator function to check for errors, add a test for ShowController 2025-10-11 23:02:54 +02:00
github-actions[bot]
a3bf845851 Merge pull request #11051 from firefly-iii/release-1760189013
🤖 Automatically merge the PR into the develop branch.
2025-10-11 15:23:39 +02:00
JC5
78e832cdba 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 15:23:33 +02:00
James Cole
d47e4c4f24 Fix #11050 2025-10-11 15:17:51 +02:00
github-actions[bot]
056329291f Merge pull request #11049 from firefly-iii/release-1760159506
🤖 Automatically merge the PR into the develop branch.
2025-10-11 07:11:57 +02:00
JC5
977946064d 🤖 Auto commit for release 'develop' on 2025-10-11 2025-10-11 07:11:46 +02:00
James Cole
1870345ddf Add new request in style of aggregated requests, fix issue with missing field. 2025-10-11 07:05:32 +02:00
James Cole
6980717075 Set version in more places. 2025-10-11 06:47:55 +02:00
James Cole
1fe0aebacb Validate version using build_time. 2025-10-11 06:45:16 +02:00
19 changed files with 280 additions and 74 deletions

View File

@@ -27,7 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Summary;
use Carbon\Carbon; use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\DateRangeRequest; use FireflyIII\Api\V1\Requests\Summary\BasicRequest;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -88,34 +88,25 @@ class BasicController extends Controller
); );
} }
/** public function basic(BasicRequest $request): JsonResponse
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/summary/getBasicSummary
*
* @throws Exception
*/
public function basic(DateRangeRequest $request): JsonResponse
{ {
// parameters for boxes: // parameters for boxes:
$dates = $request->attributes->all(); ['start' => $start, 'end' => $end, 'code' => $code] = $request->attributes->all();
$start = $dates['start'];
$end = $dates['end'];
$code = $request->get('currency_code');
// balance information: // balance information:
$balanceData = $this->getBalanceInformation($start, $end); $balanceData = $this->getBalanceInformation($start, $end);
$billData = $this->getSubscriptionInformation($start, $end); $billData = $this->getSubscriptionInformation($start, $end);
$spentData = $this->getLeftToSpendInfo($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end);
$netWorthData = $this->getNetWorthInfo($end); $netWorthData = $this->getNetWorthInfo($end);
// $balanceData = []; // $balanceData = [];
// $billData = []; // $billData = [];
// $spentData = []; // $spentData = [];
// $netWorthData = []; // $netWorthData = [];
$total = array_merge($balanceData, $billData, $spentData, $netWorthData); $total = array_merge($balanceData, $billData, $spentData, $netWorthData);
// give new keys // give new keys
$return = []; $return = [];
foreach ($total as $entry) { foreach ($total as $entry) {
if (null === $code || ($code === $entry['currency_code'])) { if ('' === $code || ($code === $entry['currency_code'])) {
$return[$entry['key']] = $entry; $return[$entry['key']] = $entry;
} }
} }

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Api\V1\Requests;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use RuntimeException; use RuntimeException;
@@ -43,12 +44,14 @@ abstract class AggregateFormRequest extends ApiRequest
parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content); parent::initialize($query, $request, $attributes, $cookies, $files, $server, $content);
// instantiate all subrequests and share current requests' bags with them // instantiate all subrequests and share current requests' bags with them
Log::debug('Initializing AggregateFormRequest.');
foreach ($this->getRequests() as $config) { foreach ($this->getRequests() as $config) {
$requestClass = is_array($config) ? array_shift($config) : $config; $requestClass = is_array($config) ? array_shift($config) : $config;
if (!is_a($requestClass, Request::class, true)) { if (!is_a($requestClass, Request::class, true)) {
throw new RuntimeException('getRequests() must return class-strings of subclasses of Request'); throw new RuntimeException('getRequests() must return class-strings of subclasses of Request');
} }
Log::debug(sprintf('Initializing subrequest %s', $requestClass));
$instance = $this->requests[] = new $requestClass(); $instance = $this->requests[] = new $requestClass();
$instance->request = $this->request; $instance->request = $this->request;
@@ -63,6 +66,7 @@ abstract class AggregateFormRequest extends ApiRequest
$instance->handleConfig(is_array($config) ? $config : []); $instance->handleConfig(is_array($config) ? $config : []);
} }
} }
Log::debug('Done initializing AggregateFormRequest.');
} }
public function rules(): array public function rules(): array
@@ -85,6 +89,7 @@ abstract class AggregateFormRequest extends ApiRequest
// register all subrequests' validators // register all subrequests' validators
foreach ($this->requests as $request) { foreach ($this->requests as $request) {
if (method_exists($request, 'withValidator')) { if (method_exists($request, 'withValidator')) {
Log::debug(sprintf('Process withValidator from class %s', get_class($request)));
$request->withValidator($validator); $request->withValidator($validator);
} }
} }

View File

@@ -39,9 +39,11 @@ class DateRangeRequest extends ApiRequest
{ {
$validator->after( $validator->after(
function (Validator $validator): void { function (Validator $validator): void {
$this->attributes->set('start', null); if ($validator->failed()) {
$this->attributes->set('end', null); // set null values
if (!$validator->valid()) { $this->attributes->set('start', null);
$this->attributes->set('end', null);
return; return;
} }
$start = $this->getCarbonDate('start')?->startOfDay(); $start = $this->getCarbonDate('start')?->startOfDay();

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests; namespace FireflyIII\Api\V1\Requests;
use Carbon\Carbon;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
class DateRequest extends ApiRequest class DateRequest extends ApiRequest
@@ -38,8 +39,7 @@ class DateRequest extends ApiRequest
{ {
$validator->after( $validator->after(
function (Validator $validator): void { function (Validator $validator): void {
$this->attributes->set('date', null); if ($validator->failed()) {
if (!$validator->valid()) {
return; return;
} }
$date = $this->getCarbonDate('date')?->endOfDay(); $date = $this->getCarbonDate('date')?->endOfDay();
@@ -47,7 +47,7 @@ class DateRequest extends ApiRequest
// if we also have a range, date must be in that range // if we also have a range, date must be in that range
$start = $this->attributes->get('start'); $start = $this->attributes->get('start');
$end = $this->attributes->get('end'); $end = $this->attributes->get('end');
if ($date && $start && $end && !$date->between($start, $end)) { if ($date instanceof Carbon && $start instanceof Carbon && $end instanceof Carbon && !$date->between($start, $end)) {
$validator->errors()->add('date', (string)trans('validation.between_date')); $validator->errors()->add('date', (string)trans('validation.between_date'));
} }

View File

@@ -42,7 +42,7 @@ class AccountTypeApiRequest extends ApiRequest
{ {
$validator->after( $validator->after(
function (Validator $validator): void { function (Validator $validator): void {
if (!$validator->valid()) { if ($validator->failed()) {
return; return;
} }

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* CurrencyCodeRequest.php
* Copyright (c) 2025 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\Api\V1\Requests\Models\TransactionCurrency;
use FireflyIII\Api\V1\Requests\ApiRequest;
use Illuminate\Validation\Validator;
class CurrencyCodeRequest extends ApiRequest
{
public function rules(): array
{
return [
'code' => sprintf('exists:transaction_currencies,code|%s', $this->required),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(
function (Validator $validator): void {
if (!$validator->valid()) {
return;
}
$code = $this->convertString('code', '');
$this->attributes->set('code', $code);
}
);
}
}

View File

@@ -57,7 +57,7 @@ class PaginationRequest extends ApiRequest
{ {
$validator->after( $validator->after(
function (Validator $validator): void { function (Validator $validator): void {
if (!$validator->valid()) { if ($validator->failed()) {
return; return;
} }

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
/*
* BasicRequest.php
* Copyright (c) 2025 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\Api\V1\Requests\Summary;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Api\V1\Requests\DateRangeRequest;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\CurrencyCodeRequest;
class BasicRequest extends AggregateFormRequest
{
protected function getRequests(): array
{
return [
[DateRangeRequest::class, 'required'],
CurrencyCodeRequest::class,
];
}
}

View File

@@ -46,7 +46,7 @@ class SetsLatestVersion extends Command
return 0; return 0;
} }
FireflyConfig::set('ff3_version', config('firefly.version')); FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
$this->friendlyInfo('Updated version.'); $this->friendlyInfo('Updated version.');
return 0; return 0;

View File

@@ -87,7 +87,7 @@ class UpgradesDatabase extends Command
$this->call($command, $args); $this->call($command, $args);
} }
// index will set FF3 version. // index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version')); FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return 0; return 0;
} }

View File

@@ -221,10 +221,26 @@ class TransactionJournalFactory
]; ];
Log::debug('Source info:', $sourceInfo); Log::debug('Source info:', $sourceInfo);
Log::debug('Destination info:', $destInfo); Log::debug('Destination info:', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo); $destinationAccount = null;
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount); $sourceAccount = null;
if (TransactionTypeEnum::DEPOSIT->value === $type->type) {
Log::debug('Transaction type is deposit, start with destination first.');
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo, $destinationAccount);
}
if (TransactionTypeEnum::DEPOSIT->value !== $type->type) {
Log::debug('Transaction type is not deposit, start with source first.');
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo, $sourceAccount);
}
Log::debug('Done with getAccount(2x)'); Log::debug('Done with getAccount(2x)');
// there is a safety catch here. If either account is NULL, they will be replaced with the cash account.
if (null === $destinationAccount) {
Log::warning('Destination account is NULL, will replace with cash account.');
$destinationAccount = $this->accountRepository->getCashAccount();
}
// this is the moment for a reconciliation sanity check (again). // this is the moment for a reconciliation sanity check (again).
if (TransactionTypeEnum::RECONCILIATION->value === $type->type) { if (TransactionTypeEnum::RECONCILIATION->value === $type->type) {

View File

@@ -34,6 +34,7 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use phpseclib3\Crypt\RSA; use phpseclib3\Crypt\RSA;
@@ -81,8 +82,10 @@ class InstallController extends Controller
public function index() public function index()
{ {
app('view')->share('FF_VERSION', config('firefly.version')); app('view')->share('FF_VERSION', config('firefly.version'));
// index will set FF3 version. // index will set FF3 version.
FireflyConfig::set('ff3_version', (string) config('firefly.version')); FireflyConfig::set('ff3_version', (string) config('firefly.version'));
FireflyConfig::set('ff3_build_time', (int) config('firefly.build_time'));
return view('install.index'); return view('install.index');
} }
@@ -98,18 +101,18 @@ class InstallController extends Controller
'errorMessage' => null, 'errorMessage' => null,
]; ];
app('log')->debug(sprintf('Will now run commands. Request index is %d', $requestIndex)); Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex));
$indexes = array_keys($this->upgradeCommands); $indexes = array_keys($this->upgradeCommands);
if (array_key_exists($requestIndex, $indexes)) { if (array_key_exists($requestIndex, $indexes)) {
$command = $indexes[$requestIndex]; $command = $indexes[$requestIndex];
$parameters = $this->upgradeCommands[$command]; $parameters = $this->upgradeCommands[$command];
app('log')->debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters); Log::debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters);
try { try {
$result = $this->executeCommand($command, $parameters); $result = $this->executeCommand($command, $parameters);
} catch (FireflyException $e) { } catch (FireflyException $e) {
app('log')->error($e->getMessage()); Log::error($e->getMessage());
app('log')->error($e->getTraceAsString()); Log::error($e->getTraceAsString());
if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) { if (str_contains($e->getMessage(), 'open_basedir restriction in effect')) {
$this->lastError = self::BASEDIR_ERROR; $this->lastError = self::BASEDIR_ERROR;
} }
@@ -134,7 +137,7 @@ class InstallController extends Controller
*/ */
private function executeCommand(string $command, array $args): bool private function executeCommand(string $command, array $args): bool
{ {
app('log')->debug(sprintf('Will now call command %s with args.', $command), $args); Log::debug(sprintf('Will now call command %s with args.', $command), $args);
try { try {
if ('generate-keys' === $command) { if ('generate-keys' === $command) {
@@ -142,7 +145,7 @@ class InstallController extends Controller
} }
if ('generate-keys' !== $command) { if ('generate-keys' !== $command) {
Artisan::call($command, $args); Artisan::call($command, $args);
app('log')->debug(Artisan::output()); Log::debug(Artisan::output());
} }
} catch (Exception $e) { // intentional generic exception } catch (Exception $e) { // intentional generic exception
throw new FireflyException($e->getMessage(), 0, $e); throw new FireflyException($e->getMessage(), 0, $e);

View File

@@ -88,6 +88,7 @@ trait JournalServiceTrait
// the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case // the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case
$creatableType = $this->getCreatableType($expectedTypes[$transactionType]); $creatableType = $this->getCreatableType($expectedTypes[$transactionType]);
Log::debug(sprintf('Creatable type is "%s"', $creatableType), $expectedTypes[$transactionType]);
// if the result is NULL but the ID is set, an account could exist of the wrong type. // if the result is NULL but the ID is set, an account could exist of the wrong type.
// that data can be used to create a new account of the right type. // that data can be used to create a new account of the right type.
@@ -227,9 +228,11 @@ trait JournalServiceTrait
} }
// find by preferred type. // find by preferred type.
Log::debug('Find by preferred type.');
$result = $this->accountRepository->findByName($data['name'], [$types[0]]); $result = $this->accountRepository->findByName($data['name'], [$types[0]]);
// or any expected type. // or any expected type.
Log::debug('Find by any expected type.');
$result ??= $this->accountRepository->findByName($data['name'], $types); $result ??= $this->accountRepository->findByName($data['name'], $types);
if (null !== $result) { if (null !== $result) {

View File

@@ -67,32 +67,16 @@ trait IsOldVersion
protected function isOldVersionInstalled(): bool protected function isOldVersionInstalled(): bool
{ {
// version compare thing. // version compare thing.
$configVersion = (string)config('firefly.version'); $configBuildTime = (int)config('firefly.build_time');
$dbVersion = (string)FireflyConfig::getFresh('ff3_version', '1.0')->data; $dbBuildTime = (int)FireflyConfig::getFresh('ff3_build_time', 123)->data;
$compare = 0; $configTime = Carbon::createFromTimestamp($configBuildTime, config('app.timezone'));
// compare develop to develop $dbTime = Carbon::createFromTimestamp($dbBuildTime, config('app.timezone'));
if (str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) { if ($dbBuildTime < $configBuildTime) {
$compare = $this->compareDevelopVersions($configVersion, $dbVersion); Log::warning(sprintf('Your database was last managed by an older version of Firefly III (I see %s, I expect %s). Redirect to migrate routine.', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
}
// user has develop installed, goes to normal version.
if (!str_starts_with($configVersion, 'develop') && str_starts_with($dbVersion, 'develop')) {
return true;
}
// user has normal, goes to develop version.
if (str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
return true;
}
// compare normal with normal.
if (!str_starts_with($configVersion, 'develop') && !str_starts_with($dbVersion, 'develop')) {
$compare = version_compare($configVersion, $dbVersion);
}
if (-1 === $compare) {
Log::warning(sprintf('The current configured Firefly III version (%s) is older than the required version (%s). Redirect to migrate routine.', $dbVersion, $configVersion));
return true; return true;
} }
Log::debug(sprintf('Your database is up to date (I see %s, I expect %s).', $dbTime->format('Y-m-d H:i:s'), $configTime->format('Y-m-d H:i:s')));
return false; return false;
} }

12
composer.lock generated
View File

@@ -11920,16 +11920,16 @@
}, },
{ {
"name": "rector/rector", "name": "rector/rector",
"version": "2.2.2", "version": "2.2.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/rectorphp/rector.git", "url": "https://github.com/rectorphp/rector.git",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed" "reference": "d27f976a332a87b5d03553c2e6f04adbe5da034f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/5b353f7457b9a0c63fc91ef340f5d119a40991ed", "url": "https://api.github.com/repos/rectorphp/rector/zipball/d27f976a332a87b5d03553c2e6f04adbe5da034f",
"reference": "5b353f7457b9a0c63fc91ef340f5d119a40991ed", "reference": "d27f976a332a87b5d03553c2e6f04adbe5da034f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11968,7 +11968,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/rectorphp/rector/issues", "issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.2" "source": "https://github.com/rectorphp/rector/tree/2.2.3"
}, },
"funding": [ "funding": [
{ {
@@ -11976,7 +11976,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2025-10-09T19:50:20+00:00" "time": "2025-10-11T21:50:23+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false), 'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => 'develop/2025-10-11', 'version' => 'develop/2025-10-12',
'build_time' => 1760157052, 'build_time' => 1760277899,
'api_version' => '2.1.0', // field is no longer used. 'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used. 'db_version' => 28, // field is no longer used.

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace Database\Factories;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\AccountType;
use Illuminate\Database\Eloquent\Factories\Factory;
class AccountFactory extends Factory
{
public function definition(): array
{
return [
'name' => $this->faker->name(),
'active' => true,
];
}
public function withType(AccountTypeEnum $type): static
{
return $this->for(AccountType::where('type', $type->value)->first());
}
}

12
package-lock.json generated
View File

@@ -3173,9 +3173,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.7.1", "version": "24.7.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.1.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.7.2.tgz",
"integrity": "sha512-CmyhGZanP88uuC5GpWU9q+fI61j2SkhO3UGMUdfYRE6Bcy0ccyzn1Rqj9YAB/ZY4kOXmNf0ocah5GtphmLMP6Q==", "integrity": "sha512-/NbVmcGTP+lj5oa4yiYxxeBjRivKQ5Ns1eSZeB99ExsEQ6rX5XYU1Zy/gGxY/ilqtD4Etx9mKyrPxZRetiahhA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -4521,9 +4521,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001749", "version": "1.0.30001750",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001749.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001750.tgz",
"integrity": "sha512-0rw2fJOmLfnzCRbkm8EyHL8SvI2Apu5UbnQuTsJ0ClgrH8hcwFooJ1s5R0EP8o8aVrFu8++ae29Kt9/gZAZp/Q==", "integrity": "sha512-cuom0g5sdX6rw00qOoLNSFCJ9/mYIsuSOA+yzpDw8eopiFqcVwQvZHqov0vmEighRxX++cfC0Vg1G+1Iy/mSpQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {

View File

@@ -0,0 +1,89 @@
<?php
/*
* AccountControllerTest.php
* Copyright (c) 2025 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 Tests\integration\Api\Models\Account;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Account;
use FireflyIII\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\integration\TestCase;
/**
* @internal
*
* @covers \FireflyIII\Api\V1\Controllers\Models\Account\ShowController
*/
final class ShowControllerTest extends TestCase
{
use RefreshDatabase;
private User $user;
protected function setUp(): void
{
parent::setUp();
$this->user = $this->createAuthenticatedUser();
$this->actingAs($this->user);
Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::REVENUE)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::EXPENSE)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::DEBT)->create();
Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
}
public function testIndex(): void
{
$this->actingAs($this->user);
$response = $this->getJson(route('api.v1.accounts.index'));
$response->assertStatus(200);
$response->assertJson([
'meta' => ['pagination' => ['total' => 5]],
]);
}
public function testIndexFailsOnUnknownAccountType(): void
{
$this->actingAs($this->user);
$response = $this->getJson(route('api.v1.accounts.index').'?type=foobar');
$response->assertStatus(422);
$response->assertJson(['errors' => ['type' => ['The selected type is invalid.']]]);
}
public function testIndexCanFilterOnAccountType(): void
{
$this->actingAs($this->user);
$response = $this->getJson(route('api.v1.accounts.index').'?type=asset');
$response->assertStatus(200);
$response->assertJson([
'data' => [
['attributes' => ['type' => 'asset']],
['attributes' => ['type' => 'asset']],
],
'meta' => ['pagination' => ['total' => 2]],
]);
}
}