🤖 Auto commit for release 'develop' on 2026-03-01

This commit is contained in:
JC5
2026-03-01 08:08:15 +01:00
parent 6bae8ab70a
commit bb51baaa38
15 changed files with 133 additions and 132 deletions

View File

@@ -2687,8 +2687,5 @@
"php": ">=8.5.0"
},
"platform-dev": {},
"platform-overrides": {
"php": "8.5"
},
"plugin-api-version": "2.9.0"
}

View File

@@ -4,6 +4,7 @@ Over time, many people have contributed to Firefly III. Their efforts are not al
Please find below all the people who contributed to the Firefly III code. Their names are mentioned in the year of their first contribution.
## 2026
- Matthew Grove
- Cinnamon Pyro
- R1DEN
- RiDEN

View File

@@ -128,16 +128,16 @@ class ListController extends Controller
*/
public function transactions(ListRequest $request, Account $account): JsonResponse
{
['limit' => $limit, 'page' => $page, 'start' => $start, 'end' => $end, 'type' => $type] = $request->attributes->all();
$types = $this->mapTransactionTypes($type ?? 'default');
$manager = $this->getManager();
['limit' => $limit, 'page' => $page, 'start' => $start, 'end' => $end, 'type' => $type] = $request->attributes->all();
$types = $this->mapTransactionTypes($type ?? 'default');
$manager = $this->getManager();
/** @var User $admin */
$admin = auth()->user();
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector = app(GroupCollectorInterface::class);
$collector->setUser($admin)->setAccounts(new Collection()->push($account))->withAPIInformation()->setLimit($limit)->setPage($page)->setTypes($types);
if (null !== $start) {
$collector->setStart($start);
@@ -146,18 +146,18 @@ class ListController extends Controller
$collector->setEnd($end);
}
$paginator = $collector->getPaginatedGroups();
$paginator = $collector->getPaginatedGroups();
$paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams());
// enrich
$enrichment = new TransactionGroupEnrichment();
$enrichment = new TransactionGroupEnrichment();
$enrichment->setUser($admin);
$transactions = $enrichment->enrich($paginator->getCollection());
$transactions = $enrichment->enrich($paginator->getCollection());
/** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class);
$transformer = app(TransactionGroupTransformer::class);
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource = new FractalCollection($transactions, $transformer, 'transactions');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -92,7 +92,7 @@ class UpdateController extends Controller
$flags->applyRules = $applyRules;
$flags->fireWebhooks = $fireWebhooks;
$flags->recalculateCredit = $runRecalculations;
$flags->batchSubmission = $data['batch_submission'] ?? false;
$flags->batchSubmission = $data['batch_submission'] ?? false;
event(new UpdatedSingleTransactionGroup($flags, $objects));
event(new WebhookMessagesRequestSending());

View File

@@ -54,17 +54,20 @@ class BatchController extends Controller
public function finishBatch(Request $request): JsonResponse
{
Log::debug('Now in finishBatch.');
$journals = $this->repository->getUncompletedJournals();
$journals = $this->repository->getUncompletedJournals();
if (0 === count($journals)) {
Log::debug('Counted zero journals, return.');
return response()->json([], 204);
}
Log::debug(sprintf('Counted %d journals.', count($journals)));
/** @var TransactionJournal $first */
$first = $journals->first();
$group = $first?->transactionGroup;
$first = $journals->first();
$group = $first?->transactionGroup;
if (null === $group) {
Log::debug('First group is NULL.');
return response()->json([], 204);
}
$flags = new TransactionGroupEventFlags();

View File

@@ -30,7 +30,9 @@ class UserRequestedBatchProcessing extends Event
{
public TransactionGroupEventObjects $objects;
public function __construct(public TransactionGroupEventFlags $flags) {
public function __construct(
public TransactionGroupEventFlags $flags
) {
$this->objects = new TransactionGroupEventObjects();
}
}

View File

@@ -102,8 +102,8 @@ class CategoryReportController extends Controller
/** @var array $category */
foreach ($currency['categories'] as $category) {
foreach ($category['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$title = sprintf('%s (%s)', $category['name'], $journalData['currency_name']);
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$title = sprintf('%s (%s)', $category['name'], $journalData['currency_name']);
$result[$title] ??= [
'amount' => '0',
'currency_symbol' => $journalData['currency_symbol'],
@@ -129,8 +129,8 @@ class CategoryReportController extends Controller
/** @var array $category */
foreach ($currency['categories'] as $category) {
foreach ($category['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$title = sprintf('%s (%s)', $category['name'], $journalData['currency_name']);
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$title = sprintf('%s (%s)', $category['name'], $journalData['currency_name']);
$result[$title] ??= [
'amount' => '0',
'currency_symbol' => $journalData['currency_symbol'],
@@ -213,9 +213,9 @@ class CategoryReportController extends Controller
// add things to chart Data for each currency:
foreach ($currency['categories'] as $currentCategory) {
foreach ($currentCategory['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-spent', $journalData['currency_id']);
$chartData[$spentKey] ??= [
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-spent', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf(
'%s (%s)',
(string) trans('firefly.spent_in_specific_category', ['category' => $category->name]),
@@ -227,7 +227,7 @@ class CategoryReportController extends Controller
'currency_id' => $journalData['currency_id'],
'entries' => $this->makeEntries($start, $end),
];
$key = $journal['date']->isoFormat($format);
$key = $journal['date']->isoFormat($format);
$chartData[$spentKey]['entries'][$key] ??= '0';
$chartData[$spentKey]['entries'][$key] = bcadd($chartData[$spentKey]['entries'][$key], $journalData['amount']);
}
@@ -239,9 +239,9 @@ class CategoryReportController extends Controller
// add things to chart Data for each currency:
foreach ($currency['categories'] as $currentCategory) {
foreach ($currentCategory['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-earned', $journalData['currency_id']);
$chartData[$spentKey] ??= [
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-earned', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf(
'%s (%s)',
(string) trans('firefly.earned_in_specific_category', ['category' => $category->name]),
@@ -253,7 +253,7 @@ class CategoryReportController extends Controller
'currency_id' => $journalData['currency_id'],
'entries' => $this->makeEntries($start, $end),
];
$key = $journal['date']->isoFormat($format);
$key = $journal['date']->isoFormat($format);
$chartData[$spentKey]['entries'][$key] ??= '0';
$chartData[$spentKey]['entries'][$key] = bcadd($chartData[$spentKey]['entries'][$key], $journalData['amount']);
}
@@ -340,5 +340,4 @@ class CategoryReportController extends Controller
return $return;
}
}

View File

@@ -178,14 +178,14 @@ class ReportController extends Controller
// loop. group by currency and by period.
/** @var array $journal */
foreach ($journals as $journal) {
$period = $journal['date']->format($format);
$journalData = $this->resolveJournalAmountAndCurrency($journal, $journal);
$currencyId = $journalData['currency_id'];
$currencySymbol = $journalData['currency_symbol'];
$currencyCode = $journalData['currency_code'];
$currencyName = $journalData['currency_name'];
$currencyDecimalPlaces = $journalData['currency_decimal_places'];
$amount = $journalData['amount'];
$period = $journal['date']->format($format);
$journalData = $this->resolveJournalAmountAndCurrency($journal, $journal);
$currencyId = $journalData['currency_id'];
$currencySymbol = $journalData['currency_symbol'];
$currencyCode = $journalData['currency_code'];
$currencyName = $journalData['currency_name'];
$currencyDecimalPlaces = $journalData['currency_decimal_places'];
$amount = $journalData['amount'];
$data[$currencyId] ??= [
'currency_id' => $currencyId,
@@ -196,7 +196,7 @@ class ReportController extends Controller
];
$data[$currencyId][$period] ??= ['period' => $period, 'spent' => '0', 'earned' => '0'];
// in our outgoing?
$key = 'spent';
$key = 'spent';
// deposit = incoming
// transfer or reconcile or opening balance, and these accounts are the destination.

View File

@@ -215,17 +215,21 @@ class TagReportController extends Controller
// add things to chart Data for each currency:
foreach ($currency['tags'] as $currentTag) {
foreach ($currentTag['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-spent', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf('%s (%s)', (string) trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]), $journalData['currency_name']),
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-spent', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf(
'%s (%s)',
(string) trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]),
$journalData['currency_name']
),
'type' => 'bar',
'currency_symbol' => $journalData['currency_symbol'],
'currency_code' => $journalData['currency_code'],
'currency_id' => $journalData['currency_id'],
'entries' => $this->makeEntries($start, $end),
];
$key = $journal['date']->isoFormat($format);
$key = $journal['date']->isoFormat($format);
$chartData[$spentKey]['entries'][$key] ??= '0';
$chartData[$spentKey]['entries'][$key] = bcadd($chartData[$spentKey]['entries'][$key], $journalData['amount']);
}
@@ -237,17 +241,21 @@ class TagReportController extends Controller
// add things to chart Data for each currency:
foreach ($currency['tags'] as $currentTag) {
foreach ($currentTag['transaction_journals'] as $journal) {
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-earned', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf('%s (%s)', (string) trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]), $journalData['currency_name']),
$journalData = $this->resolveJournalAmountAndCurrency($journal, $currency);
$spentKey = sprintf('%d-earned', $journalData['currency_id']);
$chartData[$spentKey] ??= [
'label' => sprintf(
'%s (%s)',
(string) trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]),
$journalData['currency_name']
),
'type' => 'bar',
'currency_symbol' => $journalData['currency_symbol'],
'currency_code' => $journalData['currency_code'],
'currency_id' => $journalData['currency_id'],
'entries' => $this->makeEntries($start, $end),
];
$key = $journal['date']->isoFormat($format);
$key = $journal['date']->isoFormat($format);
$chartData[$spentKey]['entries'][$key] ??= '0';
$chartData[$spentKey]['entries'][$key] = bcadd($chartData[$spentKey]['entries'][$key], $journalData['amount']);
}
@@ -386,5 +394,4 @@ class TagReportController extends Controller
return $return;
}
}

View File

@@ -55,7 +55,7 @@ trait SupportsGroupProcessingTrait
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
$newRuleEngine->setRuleGroups($groups);
foreach($array as $journalId) {
foreach ($array as $journalId) {
$newRuleEngine->removeOperator('journal_id');
$newRuleEngine->addOperator(['type' => 'journal_id', 'value' => $journalId]);
$newRuleEngine->fire();

View File

@@ -42,11 +42,7 @@ trait ResolvesJournalAmountAndCurrency
$currencyDecimalPlaces = (int) ($journal['currency_decimal_places'] ?? $currency['currency_decimal_places'] ?? 2);
$amount = (string) $journal['amount'];
if (
$this->convertToPrimary
&& null !== $this->primaryCurrency
&& $currencyId !== $this->primaryCurrency->id
) {
if ($this->convertToPrimary && null !== $this->primaryCurrency && $currencyId !== $this->primaryCurrency->id) {
$currencyId = $this->primaryCurrency->id;
$currencyName = $this->primaryCurrency->name;
$currencySymbol = $this->primaryCurrency->symbol;
@@ -54,8 +50,7 @@ trait ResolvesJournalAmountAndCurrency
$currencyDecimalPlaces = $this->primaryCurrency->decimal_places;
$amount = (int) ($journal['foreign_currency_id'] ?? 0) === $this->primaryCurrency->id
? (string) ($journal['foreign_amount'] ?? '0')
: (string) ($journal['pc_amount'] ?? '0')
;
: (string) ($journal['pc_amount'] ?? '0');
}
return [

View File

@@ -37,9 +37,6 @@ interface RuleEngineInterface
*/
public function addOperator(array $operator): void;
public function removeOperator(string $type): void;
/**
* Find all transactions only, dont apply anything.
*/
@@ -55,6 +52,8 @@ interface RuleEngineInterface
*/
public function getResults(): int;
public function removeOperator(string $type): void;
public function setRefreshTriggers(bool $refreshTriggers): void;
/**

View File

@@ -38,6 +38,7 @@ use FireflyIII\TransactionRules\Factory\ActionFactory;
use FireflyIII\User;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Override;
/**
* Class SearchRuleEngine
@@ -46,12 +47,12 @@ class SearchRuleEngine implements RuleEngineInterface
{
private readonly Collection $groups;
private array $operators = [];
private array $operators = [];
// always collect the triggers from the database, unless indicated otherwise.
private bool $refreshTriggers = true;
private array $resultCount = [];
private bool $refreshTriggers = true;
private array $resultCount = [];
private readonly Collection $rules;
private User $user;
private User $user;
public function __construct()
{
@@ -70,7 +71,7 @@ class SearchRuleEngine implements RuleEngineInterface
Log::debug('SearchRuleEngine::find()');
$collection = new Collection();
foreach ($this->rules as $rule) {
$found = new Collection();
$found = new Collection();
if (true === $rule->strict) {
$found = $this->findStrictRule($rule);
}
@@ -79,7 +80,7 @@ class SearchRuleEngine implements RuleEngineInterface
}
$collection = $collection->merge($found);
}
$result = $collection->unique();
$result = $collection->unique();
Log::debug(sprintf('SearchRuleEngine::find() returns %d unique transactions.', $result->count()));
return $result;
@@ -102,9 +103,9 @@ class SearchRuleEngine implements RuleEngineInterface
$result = $this->fireRule($rule);
if ($result && true === $rule->stop_processing) {
Log::debug(sprintf(
'Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.',
$rule->id
));
'Rule #%d has triggered and executed, but calls to stop processing. Since not in the context of a group, do not stop.',
$rule->id
));
}
if (false === $result && true === $rule->stop_processing) {
Log::debug(sprintf('Rule #%d has triggered and changed nothing, but calls to stop processing. Do not stop.', $rule->id));
@@ -134,6 +135,21 @@ class SearchRuleEngine implements RuleEngineInterface
return count($this->resultCount);
}
#[Override]
public function removeOperator(string $type): void
{
$new = [];
foreach ($this->operators as $operator) {
if ($type === $operator['type']) {
Log::debug(sprintf('Removing operator "%s"', $type));
continue;
}
$new[] = $operator;
}
$this->operators = $new;
}
public function setRefreshTriggers(bool $refreshTriggers): void
{
$this->refreshTriggers = $refreshTriggers;
@@ -170,9 +186,10 @@ class SearchRuleEngine implements RuleEngineInterface
private function addNotes(array $transaction): array
{
$transaction['notes'] = '';
$dbNote = Note::where('noteable_id', (int)$transaction['transaction_journal_id'])
->where('noteable_type', TransactionJournal::class)
->first(['notes.*']);
$dbNote = Note::where('noteable_id', (int) $transaction['transaction_journal_id'])
->where('noteable_type', TransactionJournal::class)
->first(['notes.*'])
;
if (null !== $dbNote) {
$transaction['notes'] = $dbNote->text;
}
@@ -201,12 +218,12 @@ class SearchRuleEngine implements RuleEngineInterface
/** @var RuleTrigger $ruleTrigger */
foreach ($triggers as $ruleTrigger) {
Log::debug(sprintf(
'Now at rule trigger #%d: %s:"%s" (%s).',
$ruleTrigger->id,
$ruleTrigger->trigger_type,
$ruleTrigger->trigger_value,
var_export($ruleTrigger->stop_processing, true)
));
'Now at rule trigger #%d: %s:"%s" (%s).',
$ruleTrigger->id,
$ruleTrigger->trigger_type,
$ruleTrigger->trigger_value,
var_export($ruleTrigger->stop_processing, true)
));
if (false === $ruleTrigger->active) {
Log::debug('Trigger is not active, continue.');
@@ -244,10 +261,10 @@ class SearchRuleEngine implements RuleEngineInterface
$searchEngine->parseQuery(sprintf('%s:%s', $type, $value));
}
$result = $searchEngine->searchTransactions();
$collection = $result->getCollection();
$result = $searchEngine->searchTransactions();
$collection = $result->getCollection();
Log::debug(sprintf('Found in this run, %d transactions', $collection->count()));
$total = $total->merge($collection);
$total = $total->merge($collection);
Log::debug(sprintf('Total collection is now %d transactions', $total->count()));
++$count;
// if trigger says stop processing, do so.
@@ -261,7 +278,7 @@ class SearchRuleEngine implements RuleEngineInterface
Log::debug(sprintf('Done running %d trigger(s)', $count));
// make collection unique
$unique = $total->unique(static function (array $group): string {
$unique = $total->unique(static function (array $group): string {
$str = '';
foreach ($group['transactions'] as $transaction) {
$str = sprintf('%s%d', $str, $transaction['transaction_journal_id']);
@@ -283,8 +300,8 @@ class SearchRuleEngine implements RuleEngineInterface
private function findStrictRule(Rule $rule): Collection
{
Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
$searchArray = [];
$triggers = [];
$searchArray = [];
$triggers = [];
if ($this->refreshTriggers) {
$triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get();
}
@@ -298,12 +315,12 @@ class SearchRuleEngine implements RuleEngineInterface
continue;
}
$contextSearch = $ruleTrigger->trigger_type;
if (str_starts_with((string)$ruleTrigger->trigger_type, '-')) {
$contextSearch = substr((string)$ruleTrigger->trigger_type, 1);
if (str_starts_with((string) $ruleTrigger->trigger_type, '-')) {
$contextSearch = substr((string) $ruleTrigger->trigger_type, 1);
}
// if the trigger needs no context, value is different:
$needsContext = (bool)(config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true);
$needsContext = (bool) (config(sprintf('search.operators.%s.needs_context', $contextSearch)) ?? true);
if (false === $needsContext) {
Log::debug(sprintf('SearchRuleEngine:: add a rule trigger (no context): %s:true', $ruleTrigger->trigger_type));
$searchArray[$ruleTrigger->trigger_type][] = 'true';
@@ -319,7 +336,7 @@ class SearchRuleEngine implements RuleEngineInterface
Log::debug(sprintf('SearchRuleEngine:: add local added operator: %s:"%s"', $operator['type'], $operator['value']));
$searchArray[$operator['type']][] = sprintf('"%s"', $operator['value']);
}
$date = today(config('app.timezone'));
$date = today(config('app.timezone'));
if ($this->hasSpecificJournalTrigger($searchArray)) {
$date = $this->setDateFromJournalTrigger($searchArray);
}
@@ -340,7 +357,7 @@ class SearchRuleEngine implements RuleEngineInterface
}
}
$result = $searchEngine->searchTransactions();
$result = $searchEngine->searchTransactions();
return $result->getCollection();
}
@@ -357,11 +374,7 @@ class SearchRuleEngine implements RuleEngineInterface
}
if (!$group->relationLoaded('rules')) {
Log::debug('Group rules have NOT been pre-loaded, load them NOW.');
$rules = $group
->rules()
->orderBy('rules.order', 'ASC')
->where('rules.active', true)
->get(['rules.*']);
$rules = $group->rules()->orderBy('rules.order', 'ASC')->where('rules.active', true)->get(['rules.*']);
}
Log::debug(sprintf('Going to fire group #%d with %d rule(s)', $group->id, $rules->count()));
@@ -429,7 +442,7 @@ class SearchRuleEngine implements RuleEngineInterface
$this->processResults($rule, $collection);
$result = $collection->count() > 0;
$result = $collection->count() > 0;
if ($result) {
Log::debug(sprintf('SearchRuleEngine:: Done. Rule #%d was triggered (on %d transaction(s)).', $rule->id, $collection->count()));
@@ -455,7 +468,7 @@ class SearchRuleEngine implements RuleEngineInterface
Log::debug('Found a journal_id trigger with 1 journal, true.');
$journalTrigger = true;
}
if ('journal_id' === $triggerName && is_string($values) && !str_contains($values,',')) {
if ('journal_id' === $triggerName && is_string($values) && !str_contains($values, ',')) {
Log::debug('Found a journal_id trigger with 1 journal, true.');
$journalTrigger = true;
}
@@ -464,7 +477,7 @@ class SearchRuleEngine implements RuleEngineInterface
$dateTrigger = true;
}
}
$result = $journalTrigger && $dateTrigger;
$result = $journalTrigger && $dateTrigger;
Log::debug(sprintf('Result of hasSpecificJournalTrigger is %s.', var_export($result, true)));
return $result;
@@ -496,11 +509,11 @@ class SearchRuleEngine implements RuleEngineInterface
if ($result) {
$this->resultCount[$journalId] = array_key_exists($journalId, $this->resultCount) ? $this->resultCount[$journalId]++ : 1;
Log::debug(sprintf(
'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.',
$ruleAction->action_type,
$transaction['transaction_journal_id'] ?? 0,
count($this->resultCount)
));
'Action "%s" on journal #%d was executed, so count a result. Updated transaction journal count is now %d.',
$ruleAction->action_type,
$transaction['transaction_journal_id'] ?? 0,
count($this->resultCount)
));
}
if (false === $result) {
Log::debug(sprintf('Action "%s" reports NO changes were made.', $ruleAction->action_type));
@@ -558,14 +571,14 @@ class SearchRuleEngine implements RuleEngineInterface
$journalId = 0;
foreach ($array as $triggerName => $values) {
if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) {
$journalId = (int)trim($values[0] ?? '"0"', '"'); // follows format "123".
$journalId = (int) trim($values[0] ?? '"0"', '"'); // follows format "123".
Log::debug(sprintf('Found journal ID #%d', $journalId));
}
}
if (0 !== $journalId) {
$repository = app(JournalRepositoryInterface::class);
$repository->setUser($this->user);
$journal = $repository->find($journalId);
$journal = $repository->find($journalId);
if (null !== $journal) {
$date = $journal->date;
Log::debug(sprintf('Found journal #%d with date %s.', $journal->id, $journal->date->format('Y-m-d')));
@@ -577,19 +590,4 @@ class SearchRuleEngine implements RuleEngineInterface
return today(config('app.timezone'));
}
#[\Override]
public function removeOperator(string $type): void
{
$new = [];
foreach ($this->operators as $operator) {
if ($type === $operator['type']) {
Log::debug(sprintf('Removing operator "%s"', $type));
continue;
}
$new[] = $operator;
}
$this->operators = $new;
}
}

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-28',
'build_time' => 1772261249,
'version' => 'develop/2026-03-01',
'build_time' => 1772348761,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

18
package-lock.json generated
View File

@@ -3246,9 +3246,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "25.3.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.2.tgz",
"integrity": "sha512-RpV6r/ij22zRRdyBPcxDeKAzH43phWVKEjL2iksqo1Vz3CuBUrgmPpPhALKiRfU7OMCmeeO9vECBMsV0hMTG8Q==",
"version": "25.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz",
"integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4597,9 +4597,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001774",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001774.tgz",
"integrity": "sha512-DDdwPGz99nmIEv216hKSgLD+D4ikHQHjBC/seF98N9CPqRX4M5mSxT9eTV6oyisnJcuzxtZy4n17yKKQYmYQOA==",
"version": "1.0.30001775",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001775.tgz",
"integrity": "sha512-s3Qv7Lht9zbVKE9XoTyRG6wVDCKdtOFIjBGg3+Yhn6JaytuNKPIjBMTMIY1AnOH3seL5mvF+x33oGAyK3hVt3A==",
"dev": true,
"funding": [
{
@@ -5859,9 +5859,9 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.19.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz",
"integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==",
"version": "5.20.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz",
"integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==",
"dev": true,
"license": "MIT",
"dependencies": {