Compare commits

...

16 Commits

Author SHA1 Message Date
github-actions[bot]
b6e9db7339 Merge pull request #11857 from firefly-iii/release-1772515618
🤖 Automatically merge the PR into the develop branch.
2026-03-03 06:27:04 +01:00
JC5
374fdbe1d4 🤖 Auto commit for release 'develop' on 2026-03-03 2026-03-03 06:26:58 +01:00
James Cole
e0b05b63ec Fix config issue 2026-03-03 06:21:01 +01:00
github-actions[bot]
342ca61fb6 Merge pull request #11856 from firefly-iii/release-1772514544
🤖 Automatically merge the PR into the develop branch.
2026-03-03 06:09:12 +01:00
JC5
e9d21faf08 🤖 Auto commit for release 'develop' on 2026-03-03 2026-03-03 06:09:04 +01:00
github-actions[bot]
847800f81f Merge pull request #11851 from firefly-iii/release-1772469975
🤖 Automatically merge the PR into the develop branch.
2026-03-02 17:46:23 +01:00
JC5
b1e6f6b264 🤖 Auto commit for release 'develop' on 2026-03-02 2026-03-02 17:46:15 +01:00
github-actions[bot]
91d282c9cf Merge pull request #11850 from firefly-iii/release-1772423452
🤖 Automatically merge the PR into the develop branch.
2026-03-02 04:51:03 +01:00
JC5
c53ed44ea3 🤖 Auto commit for release 'develop' on 2026-03-02 2026-03-02 04:50:53 +01:00
James Cole
70b12354e8 Fix https://github.com/firefly-iii/firefly-iii/issues/11847 2026-03-01 20:11:33 +01:00
James Cole
6e8d204f00 Fix rule actions checking for renamed accounts. 2026-03-01 19:55:48 +01:00
github-actions[bot]
f1578b2c90 Merge pull request #11843 from firefly-iii/release-1772371014
🤖 Automatically merge the PR into the develop branch.
2026-03-01 14:17:01 +01:00
JC5
90e4ca78a4 🤖 Auto commit for release 'develop' on 2026-03-01 2026-03-01 14:16:55 +01:00
James Cole
aae855ed16 Fix range as reported by @dakennguyen 2026-03-01 14:12:38 +01:00
James Cole
2056ba5e08 Fix range. 2026-03-01 14:12:11 +01:00
James Cole
2cd7983f51 Fix https://github.com/firefly-iii/firefly-iii/issues/11842 2026-03-01 12:48:21 +01:00
10 changed files with 80 additions and 30 deletions

View File

@@ -77,10 +77,18 @@ class ConfigurationController extends Controller
$staticData = $this->getStaticConfiguration();
$return = [];
foreach ($dynamicData as $key => $value) {
$return[] = ['title' => sprintf('configuration.%s', $key), 'value' => $value, 'editable' => true];
$return[] = [
'title' => sprintf('configuration.%s', $key),
'value' => $value,
'editable' => true,
];
}
foreach ($staticData as $key => $value) {
$return[] = ['title' => $key, 'value' => $value, 'editable' => false];
$return[] = [
'title' => $key,
'value' => $value,
'editable' => false,
];
}
return response()->api($return);
@@ -95,18 +103,30 @@ class ConfigurationController extends Controller
$dynamic = $this->getDynamicConfiguration();
$shortKey = str_replace('configuration.', '', $configKey);
if (str_starts_with($configKey, 'configuration.')) {
$data = ['title' => $configKey, 'value' => $dynamic[$shortKey], 'editable' => true];
$data = [
'title' => $configKey,
'value' => $dynamic[$shortKey],
'editable' => true,
];
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
}
if (str_starts_with($configKey, 'webhook.')) {
$data = ['title' => $configKey, 'value' => $this->getWebhookConfiguration($configKey), 'editable' => false];
$data = [
'title' => $configKey,
'value' => $this->getWebhookConfiguration($configKey),
'editable' => false,
];
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
}
// fallback
$data = ['title' => $configKey, 'value' => config($shortKey), 'editable' => false];
$data = [
'title' => $configKey,
'value' => config($shortKey),
'editable' => false,
];
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
}
@@ -134,7 +154,11 @@ class ConfigurationController extends Controller
// get updated config:
$newConfig = $this->getDynamicConfiguration();
$data = ['title' => $name, 'value' => $newConfig[$shortName], 'editable' => true];
$data = [
'title' => $name,
'value' => $newConfig[$shortName],
'editable' => true,
];
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
}
@@ -146,16 +170,30 @@ class ConfigurationController extends Controller
*/
private function getDynamicConfiguration(): array
{
$isDemoSite = FireflyConfig::get('is_demo_site');
$updateCheck = FireflyConfig::get('permission_update_check');
$lastCheck = FireflyConfig::get('last_update_check');
$singleUser = FireflyConfig::get('single_user_mode');
$isDemoSite = FireflyConfig::get('is_demo_site', false);
$updateCheck = FireflyConfig::get('permission_update_check', -1);
$singleUser = FireflyConfig::get('single_user_mode', true);
$lastCheck = FireflyConfig::get('last_update_check', 1);
$enableExchangeRates = FireflyConfig::get('enable_exchange_rates', config('cer.enabled'));
$useRunningBalance = FireflyConfig::get('use_running_balance', true);
$enableExternalMap = FireflyConfig::get('enable_external_map', false);
$enableExternalRates = FireflyConfig::get('enable_external_rates', false);
$allowWebhooks = FireflyConfig::get('allow_webhooks', false);
$enableBatchProcessing = FireflyConfig::get('enable_batch_processing', false);
$validUrlProtocols = FireflyConfig::get('valid_url_protocols', 'http,https');
return [
'is_demo_site' => $isDemoSite?->data,
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
'single_user_mode' => $singleUser?->data,
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
'enable_exchange_rates' => $enableExchangeRates?->data,
'use_running_balance' => $useRunningBalance?->data,
'enable_external_map' => $enableExternalMap?->data,
'enable_external_rates' => $enableExternalRates?->data,
'allow_webhooks' => $allowWebhooks?->data,
'enable_batch_processing' => $enableBatchProcessing?->data,
'valid_url_protocols' => $validUrlProtocols?->data ?? 'http,https',
];
}

View File

@@ -778,9 +778,10 @@ class GroupCollector implements GroupCollectorInterface
{
$newArray = $newJournal->toArray();
if (array_key_exists('attachment_id', $newArray)) {
$attachmentId = (int) $newJournal['attachment_id'];
$existingJournal['attachments'][$attachmentId] = ['id' => $attachmentId];
$attachmentId = (int) $newJournal['attachment_id'];
if (0 !== $attachmentId) {
$existingJournal['attachments'][$attachmentId] = ['id' => $attachmentId];
}
}
return $existingJournal;

View File

@@ -151,9 +151,8 @@ class ReportController extends Controller
$cache->addProperty($end);
$cache->addProperty($this->convertToPrimary);
if ($cache->has()) {
// return response()->json($cache->get());
// return response()->json($cache->get());
}
Log::debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray());
Log::debug(sprintf('Period: %s to %s', $start->toW3cString(), $end->toW3cString()));
$format = Navigation::preferredCarbonFormat($start, $end);
@@ -247,10 +246,6 @@ class ReportController extends Controller
if ('1Y' === $preferredRange) {
$currentEnd = Navigation::endOfPeriod($currentEnd, $preferredRange);
}
// 2026-03-01 similar fix for monthly ranges.
if ('1M' === $preferredRange) {
$currentEnd = Navigation::endOfPeriod($currentEnd, $preferredRange);
}
Log::debug(sprintf('Start of sub-loop, current end is %s', $currentEnd->toW3cString()));
while ($currentStart <= $currentEnd) {
Log::debug(sprintf('Current start: %s', $currentStart->toW3cString()));

View File

@@ -246,12 +246,17 @@ class TagController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
// collect transaction journal IDs in repository,
// this makes the collector faster and more accurate.
$journalIds = $this->repository->getJournalIds($tag);
$collector
->setRange($start, $end)
->setLimit($pageSize)
->setPage($page)
->setJournalIds($journalIds)
->withAccountInformation()
->setTag($tag)
// ->setTag($tag)
->withBudgetInformation()
->withCategoryInformation()
->withAttachmentInformation()
@@ -296,6 +301,10 @@ class TagController extends Controller
$path = route('tags.show', [$tag->id, 'all']);
$location = $this->repository->getLocation($tag);
// collect transaction journal IDs in repository,
// this makes the collector faster and more accurate.
$journalIds = $this->repository->getJournalIds($tag);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
@@ -303,7 +312,7 @@ class TagController extends Controller
->setLimit($pageSize)
->setPage($page)
->withAccountInformation()
->setTag($tag)
->setJournalIds($journalIds)
->withBudgetInformation()
->withCategoryInformation()
->withAttachmentInformation()

View File

@@ -51,7 +51,7 @@ class UpdatesAccountInformation implements ShouldQueue
private function correctRuleActions(Account $account, array $oldData, Rule $rule): void
{
$fields = ['set_source_account', 'set_destination_account'];
$fields = ['set_source_account', 'set_destination_account', 'convert_withdrawal', 'convert_deposit', 'convert_transfer'];
Log::debug(sprintf('Check if rule #%d actions reference account #%d "%s"', $rule->id, $account->id, $account->name));
$fixed = 0;

View File

@@ -135,6 +135,12 @@ class TagRepository implements TagRepositoryInterface, UserGroupInterface
});
}
#[Override]
public function getJournalIds(Tag $tag): array
{
return $tag->transactionJournals->pluck('id')->toArray();
}
public function getLocation(Tag $tag): ?Location
{
/** @var null|Location */

View File

@@ -71,6 +71,8 @@ interface TagRepositoryInterface
public function getAttachments(Tag $tag): Collection;
public function getJournalIds(Tag $tag): array;
/**
* Return location, or NULL.
*/

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

6
package-lock.json generated
View File

@@ -9005,9 +9005,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.6",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
"version": "8.5.8",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
"dev": true,
"funding": [
{

View File

@@ -724,12 +724,11 @@ Route::group(
'namespace' => 'FireflyIII\Api\V1\Controllers\System',
'prefix' => 'v1/configuration',
'as' => 'api.v1.configuration.',
'middleware' => ['api-admin'],
],
static function (): void {
Route::get('', ['uses' => 'ConfigurationController@index', 'as' => 'index']);
Route::get('{eitherConfigKey}', ['uses' => 'ConfigurationController@show', 'as' => 'show']);
Route::put('{dynamicConfigKey}', ['uses' => 'ConfigurationController@update', 'as' => 'update']);
Route::get('{eitherConfigKey}', ['uses' => 'ConfigurationController@show', 'as' => 'show']);
}
);
// Users API routes: