Compare commits

..

6 Commits

Author SHA1 Message Date
github-actions[bot]
80823cdfe3 Merge pull request #11784 from firefly-iii/release-1771741207
🤖 Automatically merge the PR into the develop branch.
2026-02-22 07:20:14 +01:00
JC5
defaef171e 🤖 Auto commit for release 'develop' on 2026-02-22 2026-02-22 07:20:07 +01:00
James Cole
81f6f22efb Introduce undocumented count endpoint. 2026-02-22 07:05:30 +01:00
github-actions[bot]
4ad2508675 Merge pull request #11781 from firefly-iii/release-1771701858
🤖 Automatically merge the PR into the develop branch.
2026-02-21 20:24:25 +01:00
JC5
35f997be45 🤖 Auto commit for release 'develop' on 2026-02-21 2026-02-21 20:24:18 +01:00
James Cole
ad3fec1458 Clean up templates. 2026-02-21 20:18:04 +01:00
11 changed files with 188 additions and 23 deletions

View File

@@ -4,9 +4,9 @@ body:
- type: checkboxes
attributes:
label: Support guidelines
description: Please read the support guidelines before proceeding.
description: Thank you for reading the support guidelines before proceeding.
options:
- label: I've read the <!-- MZ2udTpin6FL --> [support guidelines](https://github.com/firefly-iii/firefly-iii/blob/main/.github/support.md)
- label: I'm smart and I read the <!-- MZ2udTpin6FL --> [support guidelines](https://github.com/firefly-iii/firefly-iii/blob/main/.github/support.md)
required: true
- type: checkboxes
@@ -29,7 +29,7 @@ body:
attributes:
label: Debug information
description: Please provide the table from the /debug page. Do not add backticks or quotes.
placeholder: The output from the /debug page
placeholder: The output from the /debug page or "N/A"
validations:
required: true

View File

@@ -1,14 +1,14 @@
<!--
Thank you for submitting new code to Firefly III, or any of the related projects. Please read the following rules carefully.
- Please do not submit solutions for problems that are not already reported in an issue.
- Unfortunately, Firefly III can't be your learning experience. If you're new to all of this, please open an issue first.
- Please do not open PRs to "discuss" possible solutions or to "get feedback" on your code. I simply don't have time for that.
- Pull requests for the MAIN branch will be closed.
- DO NOT include translated strings in your PR.
- PRs (or parts thereof) that only fix issues inside code comments will not be accepted.
Please TALK TO ME FIRST before you open a PR.
If it feels necessary to open an issue first, please do so, before you open a PR.
1. If you fix a problem that has no ticket, talk to me FIRST.
2. If you introduce new financial solutions or concepts, talk to me FIRST.
3. If your PR is more than 25 lines, talk to me FIRST.
4. If you used AI to write your PR, talk to me FIRST.
5. If you fix spelling or code comments, talk to me FIRST.
Wanna talk to me? Open a GitHub Issue, Discussion, or send me an email: james@firefly-iii.org
See also: https://docs.firefly-iii.org/explanation/support/#contributing-code
@@ -16,7 +16,7 @@ See also: https://docs.firefly-iii.org/explanation/support/#contributing-code
@JC5
This PR fixes issue # (if relevant).
This PR fixes issue # <!-- mandatory field! -->.
Changes in this pull request:

View File

@@ -25,11 +25,15 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Search;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Search\CountRequest;
use FireflyIII\Api\V1\Requests\Search\TransactionSearchRequest;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Support\Search\SearchInterface;
use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
@@ -38,6 +42,51 @@ use League\Fractal\Resource\Collection;
*/
class TransactionController extends Controller
{
private JournalRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(function ($request, $next) {
/** @var User $admin */
$admin = auth()->user();
$this->repository = app(JournalRepositoryInterface::class);
$this->repository->setUser($admin);
return $next($request);
});
}
public function count(CountRequest $request, SearchInterface $searcher): JsonResponse
{
$count = 0;
$includeDeleted = $request->attributes->get('include_deleted', false);
$externalId = (string) $request->attributes->get('external_identifier');
$internalRef = (string) $request->attributes->get('internal_reference');
$notes = (string) $request->attributes->get('notes');
$description = (string) $request->attributes->get('description');
Log::debug(sprintf('Include deleted? %s', var_export($includeDeleted, true)));
if ('' !== $externalId) {
$count += $this->repository->countByMeta('external_identifier', $externalId, $includeDeleted);
Log::debug(sprintf('Search for transactions with external_identifier "%s", count is now %d', $externalId, $count));
}
if ('' !== $internalRef) {
$count += $this->repository->countByMeta('internal_reference', $internalRef, $includeDeleted);
Log::debug(sprintf('Search for transactions with internal_reference "%s", count is now %d', $internalRef, $count));
}
if ('' !== $notes) {
$count += $this->repository->countByNotes($notes, $includeDeleted);
Log::debug(sprintf('Search for transactions with notes LIKE "%s", count is now %d', $notes, $count));
}
if ('' !== $description) {
$count += $this->repository->countByDescription($description, $includeDeleted);
Log::debug(sprintf('Search for transactions with description "%s", count is now %d', $description, $count));
}
return response()->json(['count' => $count]);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/search/searchTransactions

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
/*
* SearchRequest.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\Api\V1\Requests\Search;
use FireflyIII\Api\V1\Requests\AggregateFormRequest;
use FireflyIII\Rules\IsBoolean;
use Illuminate\Contracts\Validation\Validator;
use Override;
class CountRequest extends AggregateFormRequest
{
public function rules(): array
{
return [
'notes' => 'string|min:1|max:255',
'external_identifier' => 'string|min:1|max:255',
'description' => 'string|min:1|max:255',
'internal_reference' => 'string|min:1|max:255',
'include_deleted' => new IsBoolean(),
];
}
public function withValidator(Validator $validator): void
{
$validator->after(function (Validator $validator): void {
if ($validator->failed()) {
return;
}
$this->attributes->set('include_deleted', $this->convertBoolean($this->input('include_deleted', 'false')));
$this->attributes->set('notes', $this->convertString('notes'));
$this->attributes->set('external_identifier', $this->convertString('external_identifier'));
$this->attributes->set('description', $this->convertString('description'));
$this->attributes->set('internal_reference', $this->convertString('internal_reference'));
});
}
#[Override]
protected function getRequests(): array
{
return [];
}
}

View File

@@ -48,6 +48,47 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
{
use UserGroupTrait;
#[Override]
public function countByDescription(string $value, bool $includeDeleted): int
{
$search = $this->user->transactionJournals()->where('description', $value);
if ($includeDeleted) {
$search->withTrashed();
}
return $search->count();
}
#[Override]
public function countByMeta(string $field, string $value, bool $includeDeleted): int
{
$search = TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id')
->where('name', $field)
->where('data', json_encode($value))
->where('transaction_journals.user_id', $this->user->id)
;
if ($includeDeleted) {
$search->withTrashed();
}
return $search->count();
}
#[Override]
public function countByNotes(string $value, bool $includeDeleted): int
{
$search = Note::where('noteable_type', TransactionJournal::class)
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'notes.noteable_id')
->where('transaction_journals.user_id', $this->user->id)
->where('text', 'LIKE', sprintf('%%%s%%', $value))
;
if ($includeDeleted) {
$search->withTrashed();
}
return $search->count();
}
public function destroyGroup(TransactionGroup $transactionGroup): void
{
/** @var TransactionGroupDestroyService $service */

View File

@@ -47,6 +47,12 @@ use Illuminate\Support\Collection;
*/
interface JournalRepositoryInterface
{
public function countByDescription(string $value, bool $includeDeleted): int;
public function countByMeta(string $field, string $value, bool $includeDeleted): int;
public function countByNotes(string $value, bool $includeDeleted): int;
/**
* Deletes a transaction group.
*/

View File

@@ -182,6 +182,10 @@ class ExportDataGenerator
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
public function __construct()
{
$this->accounts = new Collection();

View File

@@ -14,15 +14,15 @@ And yes, despite my goal not to change things, some very clever users (that's yo
- Support for PHP 8.5
### Changed
- #11776
- [PR 11776](https://github.com/firefly-iii/firefly-iii/pull/11776) (Convert to primary currency for charts) reported by @dakennguyen
- The update check now contacts GitHub directly.
### Removed
- Support for PHP 8.4 and earlier
### Fixed
- #11685
- #11778
- [Discussion 11685](https://github.com/orgs/firefly-iii/discussions/11685) (Yearly budget best practices) started by @molnarti
- [Issue 11778](https://github.com/firefly-iii/firefly-iii/issues/11778) (API update rule trigger only accepts "store-journal") reported by @jhns-de
- Test notification was broken for system owners.
## v6.4.23 - 2026-02-20

View File

@@ -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-21',
'build_time' => 1771686731,
'version' => 'develop/2026-02-22',
'build_time' => 1771741082,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

12
package-lock.json generated
View File

@@ -4597,9 +4597,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001770",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz",
"integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==",
"version": "1.0.30001772",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001772.tgz",
"integrity": "sha512-mIwLZICj+ntVTw4BT2zfp+yu/AqV6GMKfJVJMx3MwPxs+uk/uj2GLl2dH8LQbjiLDX66amCga5nKFyDgRR43kg==",
"dev": true,
"funding": [
{
@@ -8328,9 +8328,9 @@
"license": "MIT"
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz",
"integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==",
"dev": true,
"license": "ISC",
"dependencies": {

View File

@@ -699,6 +699,7 @@ Route::group(
],
static function (): void {
Route::get('transactions', ['uses' => 'TransactionController@search', 'as' => 'transactions']);
Route::get('transactions/count', ['uses' => 'TransactionController@count', 'as' => 'count']);
Route::get('accounts', ['uses' => 'AccountController@search', 'as' => 'accounts']);
}
);