Compare commits

...

11 Commits

Author SHA1 Message Date
github-actions[bot]
ad5a8a2934 Merge pull request #11656 from firefly-iii/release-1770398774
🤖 Automatically merge the PR into the develop branch.
2026-02-06 18:26:25 +01:00
JC5
e37ef69491 🤖 Auto commit for release 'develop' on 2026-02-06 2026-02-06 18:26:14 +01:00
James Cole
df8a406c58 Fix issue with email change. 2026-02-06 18:12:52 +01:00
James Cole
88d3e01065 Add events for opening balance. 2026-02-06 18:10:41 +01:00
James Cole
7a1c32f1aa Expand changelog. 2026-02-06 15:58:45 +01:00
James Cole
54df0d44f7 Clean up events 2026-02-06 15:47:34 +01:00
James Cole
1f7775032b Fix budgeted amounts. 2026-02-06 15:38:32 +01:00
github-actions[bot]
8cfe1e8047 Merge pull request #11655 from firefly-iii/release-1770383285
🤖 Automatically merge the PR into the develop branch.
2026-02-06 14:08:15 +01:00
JC5
f0be634829 🤖 Auto commit for release 'develop' on 2026-02-06 2026-02-06 14:08:05 +01:00
James Cole
485e1138f8 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2026-02-06 14:03:26 +01:00
James Cole
9abf08b3be Fix view range. 2026-02-06 14:02:37 +01:00
26 changed files with 190 additions and 118 deletions

View File

@@ -1,50 +0,0 @@
<?php
declare(strict_types=1);
/*
* TriggeredStoredTransactionGroup.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\Events\Model\TransactionGroup;
use FireflyIII\Events\Event;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\TransactionGroup;
use Illuminate\Queue\SerializesModels;
/**
* @deprecated
*/
class TriggeredStoredTransactionGroup extends Event
{
use SerializesModels;
public ?RuleGroup $ruleGroup = null;
/**
* Create a new event instance.
*/
public function __construct(
public TransactionGroup $transactionGroup,
?RuleGroup $ruleGroup = null
) {
$this->ruleGroup = $ruleGroup;
}
}

View File

@@ -29,6 +29,7 @@ use FireflyIII\Models\Bill;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
use FireflyIII\Support\Facades\Navigation;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer;
use FireflyIII\User;
@@ -75,6 +76,16 @@ class IndexController extends Controller
$this->repository->correctTransfers();
$start = session('start');
$end = session('end');
$viewRange = Preferences::get('viewRange', '1M')->data;
// give the end some extra space when the user has last7, last30 or last90.
if ('last7' === $viewRange || 'last30' === $viewRange) {
$end->addDays(30);
}
if ('last90') {
$end->addDays(90);
}
$collection = $this->repository->getBills();
$total = $collection->count();

View File

@@ -152,7 +152,7 @@ class ProfileController extends Controller
}
$repository->unblockUser($user);
// also remove the "remote_guard_alt_email" preference.
Preferences::delete('remote_guard_alt_email');
Preferences::deleteForUser($user, 'remote_guard_alt_email');
// return to log in.
session()->flash('success', (string) trans('firefly.login_with_new_email'));

View File

@@ -26,16 +26,15 @@ namespace FireflyIII\Http\Controllers\RuleGroup;
use Carbon\Carbon;
use Exception;
use FireflyIII\Events\Model\TransactionGroup\TriggeredStoredTransactionGroup;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
@@ -45,6 +44,7 @@ use Illuminate\View\View;
class ExecutionController extends Controller
{
private readonly AccountRepositoryInterface $repository;
private readonly RuleGroupRepositoryInterface $ruleGroupRepository;
/**
* ExecutionController constructor.
@@ -52,11 +52,13 @@ class ExecutionController extends Controller
public function __construct()
{
parent::__construct();
$this->repository = app(AccountRepositoryInterface::class);
$this->repository = app(AccountRepositoryInterface::class);
$this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$this->middleware(function ($request, $next) {
app('view')->share('title', (string) trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->repository->setUser(auth()->user());
$this->ruleGroupRepository->setUser(auth()->user());
return $next($request);
});
@@ -70,44 +72,37 @@ class ExecutionController extends Controller
public function execute(SelectTransactionsRequest $request, RuleGroup $ruleGroup): RedirectResponse
{
Log::debug(sprintf('You have selected rule group #%d', $ruleGroup->id));
// Get parameters specified by the user
$accounts = $request->get('accounts');
$set = new Collection();
if (is_array($accounts)) {
$set = $this->repository->getAccountsById($accounts);
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
if (count($set) > 0) {
$collector->setAccounts($set);
}
// start code
/** @var User $user */
$user = auth()->user();
$accounts = implode(',', $request->get('accounts'));
// create new rule engine:
$newRuleEngine = app(RuleEngineInterface::class);
$newRuleEngine->setUser($user);
// add date operators.
if (null !== $request->get('start')) {
$startDate = new Carbon($request->get('start'));
$collector->setStart($startDate);
$newRuleEngine->addOperator(['type' => 'date_after', 'value' => $startDate->format('Y-m-d')]);
}
if (null !== $request->get('end')) {
$endDate = new Carbon($request->get('end'));
$collector->setEnd($endDate);
$newRuleEngine->addOperator(['type' => 'date_before', 'value' => $endDate->format('Y-m-d')]);
}
$final = $collector->getGroups();
$ids = $final->pluck('id')->toArray();
Log::debug(sprintf('Found %d groups collected from %d account(s)', $final->count(), $set->count()));
foreach (array_chunk($ids, 1337) as $setOfIds) {
Log::debug(sprintf('Now processing %d groups', count($setOfIds)));
$groups = TransactionGroup::whereIn('id', $setOfIds)->get();
/** @var TransactionGroup $group */
foreach ($groups as $group) {
Log::debug(sprintf('Processing group #%d.', $group->id));
event(new TriggeredStoredTransactionGroup($group, $ruleGroup));
}
}
// add extra operators:
$newRuleEngine->addOperator(['type' => 'account_id', 'value' => $accounts]);
// set rules:
$rules = $this->ruleGroupRepository->getActiveRules($ruleGroup);
$newRuleEngine->setRules($rules);
$newRuleEngine->fire();
$resultCount = $newRuleEngine->getResults();
// Tell the user that the job is queued
session()->flash('success', (string) trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title]));
session()->flash('success', trans_choice('firefly.applied_rule_group_selection', $resultCount, ['title' => $ruleGroup->title]));
return redirect()->route('rules.index');
}

View File

@@ -212,8 +212,12 @@ class ShowController extends Controller
];
$amounts[$foreignSymbol]['amount'] = bcadd($amounts[$foreignSymbol]['amount'], (string) $transaction['foreign_amount']);
}
// add primary currency amount
if (null !== $transaction['pc_amount'] && $transaction['currency_id'] !== $this->primaryCurrency->id) {
// add primary currency amount, but only if it is not the foreign amount or the current one.
if (
null !== $transaction['pc_amount']
&& $transaction['currency_id'] !== $this->primaryCurrency->id
&& $transaction['foreign_currency_code'] !== $this->primaryCurrency->code
) {
// same for foreign currency:
$primarySymbol = $this->primaryCurrency->symbol;
$amounts[$primarySymbol] ??= [

View File

@@ -35,10 +35,10 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Override;
use Spatie\Period\Boundaries;
use Spatie\Period\Period;
use Spatie\Period\Precision;
use Override;
/**
* Class AvailableBudgetRepository

View File

@@ -91,7 +91,14 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface, UserGroup
/** @var BudgetLimit $budgetLimit */
foreach ($set as $budgetLimit) {
$result = bcadd((string) $budgetLimit->amount, $result);
if ($budgetLimit->start_date->isSameDay($start) && $budgetLimit->end_date->isSameDay($end)) {
$result = bcadd((string) $budgetLimit->amount, $result);
continue;
}
$period = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
$amountPerDay = $this->getDailyAmount($budgetLimit);
$result = bcadd($result, bcmul((string) $period->length(), $amountPerDay));
}
return $result;

View File

@@ -144,7 +144,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface, UserGroupInte
public function getActiveRules(RuleGroup $group): Collection
{
return $group->rules()->where('rules.active', true)->get(['rules.*']);
return $group->rules()->where('rules.active', true)->orderBy('rules.order', 'ASC')->get(['rules.*']);
}
public function getActiveStoreRules(RuleGroup $group): Collection

View File

@@ -27,6 +27,10 @@ namespace FireflyIII\Services\Internal\Support;
use Carbon\Carbon;
use Deprecated;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Events\Model\TransactionGroup\CreatedSingleTransactionGroup;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventFlags;
use FireflyIII\Events\Model\TransactionGroup\TransactionGroupEventObjects;
use FireflyIII\Events\Model\TransactionGroup\UpdatedSingleTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountMetaFactory;
@@ -384,15 +388,15 @@ trait AccountServiceTrait
protected function createOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup
{
Log::debug('Now going to create an OB group.');
$language = Preferences::getForUser($account->user, 'language', 'en_US')->data;
$language = Preferences::getForUser($account->user, 'language', 'en_US')->data;
if (is_array($language)) {
$language = 'en_US';
}
$language = (string) $language;
$sourceId = null;
$sourceName = null;
$destId = null;
$destName = null;
$language = (string) $language;
$sourceId = null;
$sourceName = null;
$destId = null;
$destName = null;
// amount is positive.
if (1 === bccomp($openingBalance, '0')) {
@@ -414,16 +418,16 @@ trait AccountServiceTrait
}
// make amount positive, regardless:
$amount = Steam::positive($openingBalance);
$amount = Steam::positive($openingBalance);
// get or grab currency:
$currency = $this->accountRepository->getAccountCurrency($account);
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
}
// submit to factory:
$submission = [
$submission = [
'group_title' => null,
'user' => $account->user,
'user_group' => $account->user->userGroup,
@@ -455,7 +459,7 @@ trait AccountServiceTrait
Log::debug('Going for submission in createOBGroupV2', $submission);
/** @var TransactionGroupFactory $factory */
$factory = app(TransactionGroupFactory::class);
$factory = app(TransactionGroupFactory::class);
$factory->setUser($account->user);
try {
@@ -466,6 +470,13 @@ trait AccountServiceTrait
throw new FireflyException($e->getMessage(), 0, $e);
}
Preferences::mark();
$objects = TransactionGroupEventObjects::collectFromTransactionGroup($group);
$flags = new TransactionGroupEventFlags();
$flags->applyRules = false;
$flags->fireWebhooks = false;
$flags->batchSubmission = false;
event(new CreatedSingleTransactionGroup($flags, $objects));
return $group;
}
@@ -610,23 +621,23 @@ trait AccountServiceTrait
{
Log::debug(sprintf('Now in %s', __METHOD__));
// create if not exists:
$obGroup = $this->getOBGroup($account);
$obGroup = $this->getOBGroup($account);
if (null === $obGroup) {
return $this->createOBGroupV2($account, $openingBalance, $openingBalanceDate);
}
Log::debug('Update OB group');
// if exists, update:
$currency = $this->accountRepository->getAccountCurrency($account);
$currency = $this->accountRepository->getAccountCurrency($account);
if (null === $currency) {
$currency = Amount::getPrimaryCurrencyByUserGroup($account->user->userGroup);
}
// simply grab the first journal and change it:
$journal = $this->getObJournal($obGroup);
$obTransaction = $this->getOBTransaction($journal, $account);
$accountTransaction = $this->getNotOBTransaction($journal, $account);
$journal->date = $openingBalanceDate;
$journal = $this->getObJournal($obGroup);
$obTransaction = $this->getOBTransaction($journal, $account);
$accountTransaction = $this->getNotOBTransaction($journal, $account);
$journal->date = $openingBalanceDate;
$journal->transactionCurrency()->associate($currency);
// if amount is negative:
@@ -656,6 +667,13 @@ trait AccountServiceTrait
$journal->save();
$obGroup->refresh();
$objects = TransactionGroupEventObjects::collectFromTransactionGroup($obGroup);
$flags = new TransactionGroupEventFlags();
$flags->applyRules = false;
$flags->fireWebhooks = false;
$flags->batchSubmission = false;
event(new UpdatedSingleTransactionGroup($flags, $objects));
return $obGroup;
}

View File

@@ -37,6 +37,8 @@ class Calculator
private static ?SplObjectStorage $intervalMap = null; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private static array $intervals = [];
public function isAvailablePeriodicity(Periodicity $periodicity): bool

View File

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

View File

@@ -82,10 +82,16 @@ trait PeriodOverview
protected PeriodStatisticRepositoryInterface $periodStatisticRepo;
private Collection $statistics; // temp data holder
// temp data holder
// temp data holder
// temp data holder
private array $transactions; // temp data holder
// temp data holder
// temp data holder
// temp data holder
/**
* This method returns "period entries", so nov-2015, dec-2015, etc. (this depends on the users session range)
* and for each period, the amount of money spent and earned. This is a complex operation which is cached for

View File

@@ -42,8 +42,12 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
{
private Collection $collection; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private readonly bool $convertToPrimary; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $currencies = [];
private array $currencyIds = [];
private array $ids = [];

View File

@@ -42,6 +42,8 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private Collection $collection;
private readonly bool $convertToPrimary; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $currencies = [];
private array $currencyIds = [];
private Carbon $end;

View File

@@ -44,8 +44,12 @@ class PiggyBankEnrichment implements EnrichmentInterface
{
private array $accountIds = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $accounts = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $amounts = [];
private Collection $collection;
private array $currencies = [];

View File

@@ -39,8 +39,12 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
{
private array $accountCurrencies = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $accountIds = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private Collection $collection;
private array $currencies = [];
private array $groupIds = [];

View File

@@ -48,6 +48,8 @@ class SubscriptionEnrichment implements EnrichmentInterface
private BillDateCalculator $calculator;
private Collection $collection; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private readonly bool $convertToPrimary;
private ?Carbon $end = null;
private array $mappedObjects = [];

View File

@@ -57,6 +57,10 @@ class TransactionGroupEnrichment implements EnrichmentInterface
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
public function __construct()
{
$this->dateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];

View File

@@ -44,8 +44,12 @@ class WebhookEnrichment implements EnrichmentInterface
private Collection $collection;
private array $deliveries = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $ids = []; // @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
// @phpstan-ignore-line
private array $responses = [];
private array $triggers = [];
private array $webhookDeliveries = [];

View File

@@ -75,6 +75,17 @@ class Preferences
return true;
}
public function deleteForUser(User $user, string $name): bool
{
$fullName = sprintf('preference%s%s', auth()->user()->id, $name);
if (Cache::has($fullName)) {
Cache::forget($fullName);
}
Preference::where('user_id', $user->id)->where('name', $name)->delete();
return true;
}
/**
* Find by name, has no user ID in it, because the method is called from an unauthenticated route any way.
*/

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## v6.4.17 - 2026-02-06
### Added
- Batch processing. Firefly III now has a setting (under `/settings`) that allows you to send `"batch_processing": true` with new transactions over the API. If this setting is enabled and the value is `true`, Firefly III will not fire rules, webhooks or other events untill you either send `false` with a transaction OR use the [API end point](https://api-docs.firefly-iii.org/) `/v1/api/batch/finish`. This should speed up (large) data imports. It's a little experimental, use at your own risk.
### Changed
- A lot of code in Firefly III is code responding to changes made by other code. These lines of code are called events, listeners, observers, handlers, etc. They were a bit of a mess and I cleaned them all up. This should greatly improve the reliability of debt amounts and running balance consistency. Bugs are always possible, let me know.
### Deprecated
- PHP 8.4 is still on my list to be disabled, beware.
### Fixed
- [PR 11589](https://github.com/firefly-iii/firefly-iii/pull/11589) (apply user-selected light/dark mode to form elements (checkboxes, date picker) #8613 #7620) reported by @mateuszkulapl
- [Issue 11541](https://github.com/firefly-iii/firefly-iii/issues/11541) (Display running balance fails for transactions between accounts with different currencies) reported by @SledgehammerPL
- [Issue 11544](https://github.com/firefly-iii/firefly-iii/issues/11544) (Clean up events and handlers) reported by @JC5
- [Issue 11546](https://github.com/firefly-iii/firefly-iii/issues/11546) (Wrong invitation expiry time) reported by @GunoH
- [Discussion 11431](https://github.com/orgs/firefly-iii/discussions/11431) (Settings don't get saved) started by @PVTejas
- [Issue 11399](https://github.com/firefly-iii/firefly-iii/issues/11399) (Unusual behavior in audit logs (multi-currency)) reported by @jgmm81
- [PR 11569](https://github.com/firefly-iii/firefly-iii/pull/11569) (Fix layout overflow issues with long content in v1 and v2 layouts) reported by @gian21391
- [Issue 11563](https://github.com/firefly-iii/firefly-iii/issues/11563) (Tag Report/Insight API Endpoint for Tags Non Functional) reported by @Unsantae
- [PR 11589](https://github.com/firefly-iii/firefly-iii/pull/11589) (apply user-selected light/dark mode to form elements (checkboxes, date picker) #8613 #7620) reported by @mateuszkulapl
- [Issue 11601](https://github.com/firefly-iii/firefly-iii/issues/11601) (Only ungrouped piggy banks are listed when creating a transaction) reported by @jgmm81
- [Issue 11614](https://github.com/firefly-iii/firefly-iii/issues/11614) (Add New Taiwan Dollar to Currency Seeder) reported by @nick322
- [Issue 11620](https://github.com/firefly-iii/firefly-iii/issues/11620) (Add database indexes to improve reporting query performance) reported by @Zakmaf
- [PR 11632](https://github.com/firefly-iii/firefly-iii/pull/11632) (fix v2 layout dashboard transactions load) reported by @mateuszkulapl
- Confirming your new email address would result in an error.
### Security
- Initial release.
### API
- [API end point](https://api-docs.firefly-iii.org/) `/v1/api/batch/finish`.
## v6.4.16 - 2026-01-18
> [!WARNING]

14
composer.lock generated
View File

@@ -12014,21 +12014,21 @@
},
{
"name": "rector/rector",
"version": "2.3.5",
"version": "2.3.6",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "9442f4037de6a5347ae157fe8e6c7cda9d909070"
"reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/9442f4037de6a5347ae157fe8e6c7cda9d909070",
"reference": "9442f4037de6a5347ae157fe8e6c7cda9d909070",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/ca9ebb81d280cd362ea39474dabd42679e32ca6b",
"reference": "ca9ebb81d280cd362ea39474dabd42679e32ca6b",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"phpstan/phpstan": "^2.1.36"
"phpstan/phpstan": "^2.1.38"
},
"conflict": {
"rector/rector-doctrine": "*",
@@ -12062,7 +12062,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.3.5"
"source": "https://github.com/rectorphp/rector/tree/2.3.6"
},
"funding": [
{
@@ -12070,7 +12070,7 @@
"type": "github"
}
],
"time": "2026-01-28T15:22:48+00:00"
"time": "2026-02-06T14:25:06+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -79,7 +79,7 @@ return [
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-02-06',
'build_time' => 1770382386,
'build_time' => 1770398635,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

View File

@@ -825,7 +825,7 @@ return [
'execute' => 'Execute',
'apply_rule_group_selection' => 'Apply rule group ":title" to a selection of your transactions',
'apply_rule_group_selection_intro' => 'Rule groups like ":title" are normally only applied to new or updated transactions, but you can tell Firefly III to run all the rules in this group on a selection of your existing transactions. This can be useful when you have updated a group of rules and you need the changes to be applied to all of your other transactions.',
'applied_rule_group_selection' => 'Rule group ":title" has been applied to your selection.',
'applied_rule_group_selection' => '{0} No transactions in your selection were changed by the rules in rule group ":title".|[1] One transaction in your selection was changed by the rules in rule group ":title".|[2,*] :count transactions in your selection were changed by the rules in rule group ":title".',
'rule_run_after_creation' => 'If you check this box, you get the opportunity to run the rule after it has been created.',
'rule_run_after_edit' => 'If you check this box, you get the opportunity to run the rule after it has been updated.',

View File

@@ -260,8 +260,8 @@
{% if null != transaction.foreign_amount %}
({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }})
{% endif %}
{# primary currency amount of withdrawal #}
{% if convertToPrimary and 0 != transaction.pc_amount %}
{# primary currency amount of withdrawal, if not in foreign currency #}
{% if convertToPrimary and 0 != transaction.pc_amount and primaryCurrency.id != transaction.foreign_currency_id %}
({{ formatAmountBySymbol(transaction.pc_amount, primaryCurrency.symbol, primaryCurrency.decimal_places) }})
{% endif %}
{% endif %}
@@ -304,9 +304,9 @@
{% endif %}
{% elseif transaction.transaction_type_type == 'Opening balance' %}
{% if account.id == transaction.source_account_id %}
<span title="Opening balance, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% elseif account.id == transaction.destination_account_id %}
<span title="Opening balance, src">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% elseif account.id == transaction.destination_account_id %}
<span title="Opening balance, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
{% else %}
-
{% endif %}

View File

@@ -315,8 +315,8 @@
</span>
{% endif %}
<!-- do primary currency amount -->
{% if null != journal.pc_amount and primaryCurrency.id != journal.currency_id %}
<!-- do primary currency amount, if foreign amount is not the same. -->
{% if null != journal.pc_amount and primaryCurrency.id != journal.currency_id and primaryCurrency.id != journal.foreign_currency_id %}
{% if first.transaction_type_type == 'Withdrawal' %}
({{ formatAmountBySymbol(journal.pc_amount, primaryCurrency.symbol, primaryCurrency.decimal_places) }})
{% elseif first.transaction_type_type == 'Deposit' %}