mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-13 16:00:13 +00:00
Compare commits
28 Commits
develop-20
...
develop
Author | SHA1 | Date | |
---|---|---|---|
|
4f0e978687 | ||
|
e1cf9f7a79 | ||
|
7ce055a22c | ||
|
7bd915930c | ||
|
75aa2d99fd | ||
|
f52bc0e242 | ||
|
55cf924794 | ||
|
df3e4a6554 | ||
|
7c4ada458e | ||
|
2a4a98dd10 | ||
|
a3bf845851 | ||
|
78e832cdba | ||
|
d47e4c4f24 | ||
|
056329291f | ||
|
977946064d | ||
|
1870345ddf | ||
|
6980717075 | ||
|
1fe0aebacb | ||
|
cbf7aef0c1 | ||
|
8c3e6c0189 | ||
|
cf7ee79c1c | ||
|
7e344e4332 | ||
|
0a55e9fb4e | ||
|
ed2e0e86dc | ||
|
9d1fb2cd6a | ||
|
57617b750f | ||
|
f6411fdc5a | ||
|
02e24fc919 |
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers\Models\Account;
|
namespace FireflyIII\Api\V1\Controllers\Models\Account;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
|
use FireflyIII\Api\V1\Requests\PaginationRequest;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
@@ -69,22 +70,25 @@ class ListController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attachments(Account $account): JsonResponse
|
public function attachments(Account $account, PaginationRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
$pageSize = $this->parameters->get('limit');
|
[
|
||||||
|
'limit' => $limit,
|
||||||
|
'offset' => $offset,
|
||||||
|
'page' => $page,
|
||||||
|
] = $request->attributes->all();
|
||||||
$collection = $this->repository->getAttachments($account);
|
$collection = $this->repository->getAttachments($account);
|
||||||
|
|
||||||
$count = $collection->count();
|
$count = $collection->count();
|
||||||
$attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
$attachments = $collection->slice($offset, $limit);
|
||||||
|
|
||||||
// make paginator:
|
// make paginator:
|
||||||
$paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($attachments, $count, $limit, $page);
|
||||||
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams());
|
$paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams());
|
||||||
|
|
||||||
/** @var AttachmentTransformer $transformer */
|
/** @var AttachmentTransformer $transformer */
|
||||||
$transformer = app(AttachmentTransformer::class);
|
$transformer = app(AttachmentTransformer::class);
|
||||||
$transformer->setParameters($this->parameters);
|
|
||||||
|
|
||||||
$resource = new FractalCollection($attachments, $transformer, 'attachments');
|
$resource = new FractalCollection($attachments, $transformer, 'attachments');
|
||||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||||
|
@@ -128,23 +128,25 @@ class ShowController extends Controller
|
|||||||
// get list of accounts. Count it and split it.
|
// get list of accounts. Count it and split it.
|
||||||
$this->repository->resetAccountOrder();
|
$this->repository->resetAccountOrder();
|
||||||
$account->refresh();
|
$account->refresh();
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
[$start, $end, $date] = $request->attributes->all();
|
['start' => $start,
|
||||||
|
'end' => $end,
|
||||||
|
'date' => $date,] = $request->attributes->all();
|
||||||
|
|
||||||
// enrich
|
// enrich
|
||||||
/** @var User $admin */
|
/** @var User $admin */
|
||||||
$admin = auth()->user();
|
$admin = auth()->user();
|
||||||
$enrichment = new AccountEnrichment();
|
$enrichment = new AccountEnrichment();
|
||||||
$enrichment->setDate($date);
|
$enrichment->setDate($date);
|
||||||
$enrichment->setStart($start);
|
$enrichment->setStart($start);
|
||||||
$enrichment->setEnd($end);
|
$enrichment->setEnd($end);
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$account = $enrichment->enrichSingle($account);
|
$account = $enrichment->enrichSingle($account);
|
||||||
|
|
||||||
|
|
||||||
/** @var AccountTransformer $transformer */
|
/** @var AccountTransformer $transformer */
|
||||||
$transformer = app(AccountTransformer::class);
|
$transformer = app(AccountTransformer::class);
|
||||||
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
|
$resource = new Item($account, $transformer, self::RESOURCE_KEY);
|
||||||
|
|
||||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -30,8 +30,8 @@ class DateRangeRequest extends ApiRequest
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'start' => sprintf('date|after:1970-01-02|before:2038-01-17|before:end|required_with:end|', $this->required),
|
'start' => sprintf('date|after:1970-01-02|before:2038-01-17|before:end|required_with:end|%s', $this->required),
|
||||||
'end' => sprintf('date|after:1970-01-02|before:2038-01-17|after:start|required_with:start|', $this->required),
|
'end' => sprintf('date|after:1970-01-02|before:2038-01-17|after:start|required_with:start|%s', $this->required),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,7 +39,11 @@ class DateRangeRequest extends ApiRequest
|
|||||||
{
|
{
|
||||||
$validator->after(
|
$validator->after(
|
||||||
function (Validator $validator): void {
|
function (Validator $validator): void {
|
||||||
if (!$validator->valid()) {
|
if ($validator->failed()) {
|
||||||
|
// set null values
|
||||||
|
$this->attributes->set('start', null);
|
||||||
|
$this->attributes->set('end', null);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$start = $this->getCarbonDate('start')?->startOfDay();
|
$start = $this->getCarbonDate('start')?->startOfDay();
|
||||||
|
@@ -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,7 +39,7 @@ class DateRequest extends ApiRequest
|
|||||||
{
|
{
|
||||||
$validator->after(
|
$validator->after(
|
||||||
function (Validator $validator): void {
|
function (Validator $validator): void {
|
||||||
if (!$validator->valid()) {
|
if ($validator->failed()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$date = $this->getCarbonDate('date')?->endOfDay();
|
$date = $this->getCarbonDate('date')?->endOfDay();
|
||||||
@@ -46,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'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -47,7 +47,7 @@ class PaginationRequest extends ApiRequest
|
|||||||
public function rules(): array
|
public function rules(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'sort' => ['nullable', new IsValidSortInstruction($this->sortClass)],
|
'sort' => ['nullable', new IsValidSortInstruction((string)$this->sortClass)],
|
||||||
'limit' => 'numeric|min:1|max:131337',
|
'limit' => 'numeric|min:1|max:131337',
|
||||||
'page' => 'numeric|min:1|max:131337',
|
'page' => 'numeric|min:1|max:131337',
|
||||||
];
|
];
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
39
app/Api/V1/Requests/Summary/BasicRequest.php
Normal file
39
app/Api/V1/Requests/Summary/BasicRequest.php
Normal 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,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -84,8 +84,10 @@ class AttachmentFactory
|
|||||||
return $attachment;
|
return $attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUser(User $user): void
|
public function setUser(User $user): static
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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);
|
||||||
|
@@ -38,6 +38,11 @@ class IsValidSortInstruction implements ValidationRule
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if ('' === $value) {
|
||||||
|
// don't validate.
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
|
$validParameters = config(sprintf('firefly.allowed_sort_parameters.%s', $shortClass));
|
||||||
if (!is_array($validParameters)) {
|
if (!is_array($validParameters)) {
|
||||||
$fail('validation.no_sort_instructions')->translate(['object' => $shortClass]);
|
$fail('validation.no_sort_instructions')->translate(['object' => $shortClass]);
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
24
composer.lock
generated
24
composer.lock
generated
@@ -10549,16 +10549,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "driftingly/rector-laravel",
|
"name": "driftingly/rector-laravel",
|
||||||
"version": "2.0.7",
|
"version": "2.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/driftingly/rector-laravel.git",
|
"url": "https://github.com/driftingly/rector-laravel.git",
|
||||||
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e"
|
"reference": "efb636a08dfddfa2a3f4527b1dd970a898a075a4"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/625dc02cee08d47ecf0ac86de2f02a55026cf34e",
|
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/efb636a08dfddfa2a3f4527b1dd970a898a075a4",
|
||||||
"reference": "625dc02cee08d47ecf0ac86de2f02a55026cf34e",
|
"reference": "efb636a08dfddfa2a3f4527b1dd970a898a075a4",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -10578,9 +10578,9 @@
|
|||||||
"description": "Rector upgrades rules for Laravel Framework",
|
"description": "Rector upgrades rules for Laravel Framework",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/driftingly/rector-laravel/issues",
|
"issues": "https://github.com/driftingly/rector-laravel/issues",
|
||||||
"source": "https://github.com/driftingly/rector-laravel/tree/2.0.7"
|
"source": "https://github.com/driftingly/rector-laravel/tree/2.1.0"
|
||||||
},
|
},
|
||||||
"time": "2025-08-19T20:49:47+00:00"
|
"time": "2025-10-12T21:51:39+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "fakerphp/faker",
|
"name": "fakerphp/faker",
|
||||||
@@ -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",
|
||||||
|
@@ -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-10',
|
'version' => 'develop/2025-10-13',
|
||||||
'build_time' => 1760115185,
|
'build_time' => 1760325798,
|
||||||
'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.
|
||||||
|
|
||||||
|
24
database/factories/AccountFactory.php
Normal file
24
database/factories/AccountFactory.php
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
18
package-lock.json
generated
18
package-lock.json
generated
@@ -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": [
|
||||||
{
|
{
|
||||||
@@ -5820,9 +5820,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/envinfo": {
|
"node_modules/envinfo": {
|
||||||
"version": "7.17.0",
|
"version": "7.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.18.0.tgz",
|
||||||
"integrity": "sha512-GpfViocsFM7viwClFgxK26OtjMlKN67GCR5v6ASFkotxtpBWd9d+vNy+AH7F2E1TUkMDZ8P/dDPZX71/NG8xnQ==",
|
"integrity": "sha512-02QGCLRW+Jb8PC270ic02lat+N57iBaWsvHjcJViqp6UVupRB+Vsg7brYPTqEFXvsdTql3KnSczv5ModZFpl8Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
87
tests/integration/Api/Models/Account/ListControllerTest.php
Normal file
87
tests/integration/Api/Models/Account/ListControllerTest.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?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\Factory\AttachmentFactory;
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\integration\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @covers \FireflyIII\Api\V1\Controllers\Models\Account\ListController
|
||||||
|
*/
|
||||||
|
final class ListControllerTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
private User $user;
|
||||||
|
private Account $account;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->user = $this->createAuthenticatedUser();
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
|
$this->account = Account::factory()->for($this->user)->withType(AccountTypeEnum::ASSET)->create();
|
||||||
|
app(AttachmentFactory::class)->setUser($this->user)->create([
|
||||||
|
'filename' => 'test 1',
|
||||||
|
'title' => 'test 1',
|
||||||
|
'attachable_type' => Account::class,
|
||||||
|
'attachable_id' => $this->account->id,
|
||||||
|
]);
|
||||||
|
app(AttachmentFactory::class)->setUser($this->user)->create([
|
||||||
|
'filename' => 'test 2',
|
||||||
|
'title' => 'test 2',
|
||||||
|
'attachable_type' => Account::class,
|
||||||
|
'attachable_id' => $this->account->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndex(): void
|
||||||
|
{
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
$response = $this->getJson(route('api.v1.accounts.attachments', ['account' => $this->account->id]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
$response->assertJson([
|
||||||
|
'meta' => ['pagination' => ['total' => 2, 'total_pages' => 1]],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexCanChangePageSize(): void
|
||||||
|
{
|
||||||
|
$this->actingAs($this->user);
|
||||||
|
$response = $this->getJson(route('api.v1.accounts.attachments', ['account' => $this->account->id, 'limit' => 1]));
|
||||||
|
$response->assertStatus(200);
|
||||||
|
$response->assertJson([
|
||||||
|
'meta' => ['pagination' => ['total' => 2, 'total_pages' => 2]],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
89
tests/integration/Api/Models/Account/ShowControllerTest.php
Normal file
89
tests/integration/Api/Models/Account/ShowControllerTest.php
Normal 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]],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user