Compare commits

...

41 Commits

Author SHA1 Message Date
github-actions[bot]
3adf3d2fdb Merge pull request #10906 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-09-13 18:38:12 +02:00
github-actions[bot]
0923d5a23e Merge pull request #10905 from firefly-iii/release-1757781480
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:38:07 +02:00
JC5
76b8cdc385 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:38:00 +02:00
James Cole
0a27da83eb Merge branch 'main' into develop
# Conflicts:
#	.github/workflows/release.yml
2025-09-13 18:33:47 +02:00
github-actions[bot]
17d6e2be85 Merge pull request #10903 from firefly-iii/release-1757781134
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:32:20 +02:00
JC5
7381f3eba9 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:32:14 +02:00
James Cole
7f2ef1b8e1 Should not be necessary, but OK/ 2025-09-13 18:28:26 +02:00
github-actions[bot]
9dccae2402 Merge pull request #10901 from firefly-iii/release-1757780827
🤖 Automatically merge the PR into the develop branch.
2025-09-13 18:27:17 +02:00
JC5
073afd5b6e 🤖 Auto commit for release 'v6.4.0' on 2025-09-13 2025-09-13 18:27:07 +02:00
James Cole
4167d85be2 Expand changelog. 2025-09-13 07:30:50 +02:00
James Cole
ee28d1307d Fix #10871 2025-09-13 07:30:30 +02:00
James Cole
7562215666 Add some extra explanation. 2025-09-13 07:24:03 +02:00
github-actions[bot]
0203b918e9 Merge pull request #10899 from firefly-iii/release-1757740712
🤖 Automatically merge the PR into the develop branch.
2025-09-13 07:18:41 +02:00
JC5
ae7c664418 🤖 Auto commit for release 'develop' on 2025-09-13 2025-09-13 07:18:32 +02:00
James Cole
f13e0991fb Fix #10898 2025-09-13 07:13:30 +02:00
James Cole
deae94b658 Set user ID from object, fix #10891 2025-09-11 19:37:34 +02:00
James Cole
c38c752520 Fix #10888 2025-09-10 20:42:15 +02:00
James Cole
28e7df2527 Small php fixes. 2025-09-10 16:16:31 +02:00
James Cole
cb0b42e44b Replace method calls. 2025-09-10 16:07:19 +02:00
James Cole
a3674c4dfe No need to use the exception either. 2025-09-10 07:03:41 +02:00
James Cole
27480561ee Catch random exception because why not. 2025-09-10 07:03:23 +02:00
github-actions[bot]
6ea7152423 Merge pull request #10886 from firefly-iii/release-1757480185
🤖 Automatically merge the PR into the develop branch.
2025-09-10 06:56:34 +02:00
JC5
dab95f7a86 🤖 Auto commit for release 'develop' on 2025-09-10 2025-09-10 06:56:25 +02:00
James Cole
adf34805a8 Shiny release PR. 2025-09-10 06:52:51 +02:00
James Cole
93e926465f Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-09-10 06:51:11 +02:00
github-actions[bot]
5b0be91f93 Merge pull request #10885 from firefly-iii/release-1757479782
🤖 Automatically merge the PR into the develop branch.
2025-09-10 06:49:50 +02:00
JC5
01e7b604da 🤖 Auto commit for release 'develop' on 2025-09-10 2025-09-10 06:49:42 +02:00
James Cole
974a550d22 Merge branch 'main' into develop 2025-09-10 06:44:16 +02:00
James Cole
58d175444b Fix #10883 2025-09-10 06:43:24 +02:00
James Cole
29d8861e96 Merge pull request #10882 from firefly-iii/dependabot/npm_and_yarn/npm_and_yarn-f5c1666f0c 2025-09-10 06:02:57 +02:00
dependabot[bot]
eb832c750f Bump vite in the npm_and_yarn group across 1 directory
Bumps the npm_and_yarn group with 1 update in the / directory: [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite).


Updates `vite` from 7.1.2 to 7.1.5
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.1.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.1.5
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-09 20:59:51 +00:00
James Cole
134770644a Fix amounts in transaction. 2025-09-09 17:14:53 +02:00
James Cole
a9f21c9371 Extra text in the PR. 2025-09-09 15:53:25 +02:00
github-actions[bot]
781947beeb Merge pull request #10879 from firefly-iii/release-1757425805
🤖 Automatically merge the PR into the develop branch.
2025-09-09 15:50:18 +02:00
JC5
9760cd2f97 🤖 Auto commit for release 'develop' on 2025-09-09 2025-09-09 15:50:06 +02:00
James Cole
d317e9ec32 Update changelog. 2025-09-09 15:41:19 +02:00
James Cole
534f7fcadb Merge branch 'main' into develop 2025-09-09 15:36:55 +02:00
James Cole
fb3f7a1d4b Merge pull request #10874 from firefly-iii/dependabot/github_actions/actions/stale-10
Bump actions/stale from 9 to 10
2025-09-08 11:41:37 +02:00
James Cole
bf2c3e3561 Merge pull request #10873 from firefly-iii/dependabot/github_actions/actions/github-script-8
Bump actions/github-script from 7 to 8
2025-09-08 11:41:12 +02:00
dependabot[bot]
0990b1f0b4 Bump actions/stale from 9 to 10
Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/stale/compare/v9...v10)

---
updated-dependencies:
- dependency-name: actions/stale
  dependency-version: '10'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 03:08:14 +00:00
dependabot[bot]
c1922670c8 Bump actions/github-script from 7 to 8
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 03:08:10 +00:00
83 changed files with 321 additions and 290 deletions

View File

@@ -402,16 +402,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.87.1",
"version": "v3.87.2",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "2f5170365e2a422d0c5421f9c8818b2c078105f6"
"reference": "da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/2f5170365e2a422d0c5421f9c8818b2c078105f6",
"reference": "2f5170365e2a422d0c5421f9c8818b2c078105f6",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992",
"reference": "da5f0a7858c79b56fc0b8c36d3efcfe5f37f0992",
"shasum": ""
},
"require": {
@@ -494,7 +494,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.87.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.87.2"
},
"funding": [
{
@@ -502,7 +502,7 @@
"type": "github"
}
],
"time": "2025-09-02T15:27:36+00:00"
"time": "2025-09-10T09:51:40+00:00"
},
{
"name": "psr/container",

View File

@@ -314,8 +314,9 @@ DEMO_USERNAME=
DEMO_PASSWORD=
#
# Disable or enable the running balance column data
# Please disable this. It's a very experimental feature.
# Disable or enable the running balance column data.
# If you enable this, please also run "php artisan firefly-iii:correct-database"
# This will take some time the first run.
#
USE_RUNNING_BALANCE=false

View File

@@ -15,7 +15,7 @@ jobs:
timeout-minutes: 10
steps:
- name: Prune cancelled/skipped runs
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
@@ -45,7 +45,7 @@ jobs:
}
- name: Prune runs older than 3 days
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |

View File

@@ -250,7 +250,7 @@ jobs:
fi
echo "Merge all changes from $BRANCH_NAME back into '$MERGE_INTO' using a PR"
PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 Created by GitHub action')
PR_URL=$(gh pr create -B $MERGE_INTO -H $BRANCH_NAME --title "🤖 Automatic PR to merge all changes into the '$MERGE_INTO' branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`')
echo "PR URL is '$PR_URL'"
IFS='/' read -ra parts <<< "$PR_URL"
PR_NR=$(printf %s\\n "${parts[@]:(-1)}")
@@ -272,7 +272,7 @@ jobs:
echo "Also merge everything into main since this is a release."
echo 'create PR'
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body "🤖 Created by GitHub action")
PR_URL=$(gh pr create -B main -H develop --title "🤖 Automatic PR to merge all changes into the main branch." --body '🤖 This PR was created automatically by a GitHub action to merge the changed files into this branch. It will be merged automatically. `Share and enjoy`')
echo "PR URL is '$PR_URL'"
IFS='/' read -ra parts <<< "$PR_URL"

View File

@@ -15,7 +15,7 @@ jobs:
actions: write
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: |

View File

@@ -31,9 +31,7 @@ use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\AccountBalanceGrouped;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;

View File

@@ -114,7 +114,7 @@ class BudgetController extends Controller
// get all limits:
$limits = $this->blRepository->getBudgetLimits($budget, $start, $end);
$rows = [];
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
$spent = $this->opsRepository->listExpenses($start, $end, null, new Collection()->push($budget));
$expenses = $this->processExpenses($budget->id, $spent, $start, $end);
$converter = new ExchangeRateConverter();
$currencies = [$this->primaryCurrency->id => $this->primaryCurrency];
@@ -208,7 +208,7 @@ class BudgetController extends Controller
// */
// private function noBudgetLimits(Budget $budget, Carbon $start, Carbon $end): array
// {
// $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection([$budget]));
// $spent = $this->opsRepository->listExpenses($start, $end, null, new Collection()->push($budget));
//
// return $this->processExpenses($budget->id, $spent, $start, $end);
// }
@@ -290,7 +290,7 @@ class BudgetController extends Controller
// Log::debug(sprintf('Created new ExchangeRateConverter in %s', __METHOD__));
// $end = clone $limit->end_date;
// $end->endOfDay();
// $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection([$budget]));
// $spent = $this->opsRepository->listExpenses($limit->start_date, $end, null, new Collection()->push($budget));
// $limitCurrencyId = $limit->transaction_currency_id;
//
// /** @var array $entry */

View File

@@ -232,8 +232,6 @@ abstract class Controller extends BaseController
$baseUrl = sprintf('%s/api/v1', request()->getSchemeAndHttpHost());
$manager->setSerializer(new JsonApiSerializer($baseUrl));
// $transformer->collectMetaData(new Collection([$object]));
$resource = new Item($object, $transformer, $key);
return $manager->createData($resource)->toArray();

View File

@@ -76,7 +76,7 @@ class BudgetController extends Controller
/** @var Budget $budget */
foreach ($budgets as $budget) {
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection([$budget]));
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection()->push($budget));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumExpenses($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumIncome($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumIncome($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -76,7 +76,7 @@ class CategoryController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$expenses = $this->opsRepository->sumTransfers($start, $end, $assetAccounts, new Collection([$category]));
$expenses = $this->opsRepository->sumTransfers($start, $end, $assetAccounts, new Collection()->push($category));
/** @var array $expense */
foreach ($expenses as $expense) {

View File

@@ -152,7 +152,7 @@ class ListController extends Controller
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($admin)->setAccounts(new Collection([$account]))
$collector->setUser($admin)->setAccounts(new Collection()->push($account))
->withAPIInformation()->setLimit($pageSize)->setPage($this->parameters->get('page'))->setTypes($types)
;

View File

@@ -75,7 +75,7 @@ class TriggerController extends Controller
/** @var RuleEngineInterface $ruleEngine */
$ruleEngine = app(RuleEngineInterface::class);
$ruleEngine->setRules(new Collection([$rule]));
$ruleEngine->setRules(new Collection()->push($rule));
// overrule the rule(s) if necessary.
if (array_key_exists('start', $parameters) && null !== $parameters['start']) {
@@ -129,7 +129,7 @@ class TriggerController extends Controller
/** @var RuleEngineInterface $ruleEngine */
$ruleEngine = app(RuleEngineInterface::class);
$ruleEngine->setRules(new Collection([$rule]));
$ruleEngine->setRules(new Collection()->push($rule));
// overrule the rule(s) if necessary.
if (array_key_exists('start', $parameters) && null !== $parameters['start']) {

View File

@@ -133,7 +133,6 @@ class ConfigurationController extends Controller
*/
public function show(string $configKey): JsonResponse
{
$data = [];
$dynamic = $this->getDynamicConfiguration();
$shortKey = str_replace('configuration.', '', $configKey);
if (str_starts_with($configKey, 'configuration.')) {

View File

@@ -165,9 +165,9 @@ class ShowController extends Controller
// tell the generator which trigger it should look for
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
// tell the generator which objects to process
$engine->setObjects(new Collection([$group]));
$engine->setObjects(new Collection()->push($group));
// set the webhook to trigger
$engine->setWebhooks(new Collection([$webhook]));
$engine->setWebhooks(new Collection()->push($webhook));
// tell the generator to generate the messages
$engine->generateMessages();

View File

@@ -58,8 +58,8 @@ class StoreByCurrenciesRequest extends FormRequest
$data = $validator->getData();
foreach ($data as $date => $rate) {
try {
$date = Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidFormatException $e) {
Carbon::createFromFormat('Y-m-d', $date);
} catch (InvalidFormatException) {
$validator->errors()->add('date', trans('validation.date', ['attribute' => 'date']));
return;

View File

@@ -88,7 +88,7 @@ class StoreByDateRequest extends FormRequest
}
try {
$to = Amount::getTransactionCurrencyByCode((string)$key);
Amount::getTransactionCurrencyByCode((string)$key);
} catch (FireflyException) {
$validator->errors()->add(sprintf('rates.%s', $key), trans('validation.invalid_currency_code', ['code' => $key]));
}

View File

@@ -57,8 +57,6 @@ class CorrectsPiggyBanks extends Command
$event->transaction_journal_id = null;
$event->save();
++$count;
continue;
}
}
if (0 !== $count) {

View File

@@ -71,7 +71,6 @@ class RestoresOAuthKeys extends Command
$this->storeKeysInDB();
$this->friendlyInfo('Stored OAuth keys in database.');
return;
}
}

View File

@@ -515,7 +515,7 @@ class ForcesDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = (float) 10 ** $currency->decimal_places;
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct));
@@ -546,7 +546,7 @@ class ForcesDecimalSize extends Command
continue;
}
// fix $field by rounding it down correctly.
$pow = (float) 10 ** $currency->decimal_places;
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$this->friendlyWarning(
sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Console\Commands\System;
use Carbon\Carbon;
use FireflyIII\Support\System\GeneratesInstallationId;
use Illuminate\Console\Command;
use Random\RandomException;
class OutputsInstructions extends Command
{
@@ -266,7 +267,11 @@ class OutputsInstructions extends Command
];
}
$random = random_int(0, count($lines) - 1);
try {
$random = random_int(0, count($lines) - 1);
} catch (RandomException) {
$random = 0;
}
if ($addQuotes) {
$this->line(sprintf(' "%s"', $lines[$random]));

View File

@@ -157,7 +157,6 @@ class UpgradesLiabilitiesEight extends Command
$service = new TransactionGroupDestroyService();
$service->destroy($group);
return;
}
}

View File

@@ -128,10 +128,6 @@ class GracefulNotFoundHandler extends ExceptionHandler
return redirect(route('categories.index'));
case 'rules.edit':
$request->session()->reflash();
return redirect(route('rules.index'));
case 'rule-groups.edit':
$request->session()->reflash();

View File

@@ -270,7 +270,7 @@ class TransactionJournalFactory
$negative = $transactionFactory->createNegative((string) $row['amount'], (string) $row['foreign_amount']);
} catch (FireflyException $e) {
Log::error(sprintf('Exception creating negative transaction: %s', $e->getMessage()));
$this->forceDeleteOnError(new Collection([$journal]));
$this->forceDeleteOnError(new Collection()->push($journal));
throw new FireflyException($e->getMessage(), 0, $e);
}
@@ -305,7 +305,7 @@ class TransactionJournalFactory
} catch (FireflyException $e) {
Log::error(sprintf('Exception creating positive transaction: %s', $e->getMessage()));
$this->forceTrDelete($negative);
$this->forceDeleteOnError(new Collection([$journal]));
$this->forceDeleteOnError(new Collection()->push($journal));
throw new FireflyException($e->getMessage(), 0, $e);
}

View File

@@ -132,7 +132,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end)->withAccountInformation()
$collector->setAccounts(new Collection()->push($account))->setRange($this->start, $this->end)->withAccountInformation()
->withBudgetInformation()->withCategoryInformation()->withBillInformation()->withNotes()
;
$journals = $collector->getExtractedJournals();

View File

@@ -52,7 +52,7 @@ class DestroyedGroupEventHandler
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser($user);
$engine->setObjects(new Collection([$group]));
$engine->setObjects(new Collection()->push($group));
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION);
$engine->generateMessages();
Log::debug(sprintf('send event RequestedSendWebhookMessages from %s', __METHOD__));

View File

@@ -116,7 +116,7 @@ class StoredGroupEventHandler
// tell the generator which trigger it should look for
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION);
// tell the generator which objects to process
$engine->setObjects(new Collection([$group]));
$engine->setObjects(new Collection()->push($group));
// tell the generator to generate the messages
$engine->generateMessages();

View File

@@ -163,7 +163,7 @@ class UpdatedGroupEventHandler
/** @var MessageGeneratorInterface $engine */
$engine = app(MessageGeneratorInterface::class);
$engine->setUser($user);
$engine->setObjects(new Collection([$group]));
$engine->setObjects(new Collection()->push($group));
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION);
$engine->generateMessages();

View File

@@ -94,7 +94,7 @@ trait AttachmentCollection
static function (EloquentBuilder $q1): void { // @phpstan-ignore-line
$q1->where('attachments.attachable_type', TransactionJournal::class);
// $q1->where('attachments.uploaded', true);
$q1->whereNull('attachments.deleted_at');
// $q1->whereNull('attachments.deleted_at');
$q1->orWhereNull('attachments.attachable_type');
}
)
@@ -107,6 +107,7 @@ trait AttachmentCollection
$this->fields[] = 'attachments.id as attachment_id';
$this->fields[] = 'attachments.filename as attachment_filename';
$this->fields[] = 'attachments.title as attachment_title';
$this->fields[] = 'attachments.deleted_at as attachment_deleted_at';
$this->fields[] = 'attachments.uploaded as attachment_uploaded';
$this->joinAttachmentTables();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Collector\Extensions;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
@@ -597,16 +598,16 @@ trait MetaCollection
$foundTagCount = 0;
foreach ($object['transactions'] as $transaction) {
$transactionTagCount = count($transaction['tags']);
app('log')->debug(sprintf('Transaction #%d has %d tag(s)', $transaction['transaction_journal_id'], $transactionTagCount));
Log::debug(sprintf('Transaction #%d has %d tag(s)', $transaction['transaction_journal_id'], $transactionTagCount));
if ($transactionTagCount < $expectedTagCount) {
app('log')->debug(sprintf('Transaction has %d tag(s), we expect %d tag(s), return false.', $transactionTagCount, $expectedTagCount));
Log::debug(sprintf('Transaction has %d tag(s), we expect %d tag(s), return false.', $transactionTagCount, $expectedTagCount));
return false;
}
foreach ($transaction['tags'] as $tag) {
Log::debug(sprintf('"%s" versus', strtolower((string) $tag['name'])), $list);
if (in_array(strtolower((string) $tag['name']), $list, true)) {
app('log')->debug(sprintf('Transaction has tag "%s" so count++.', $tag['name']));
Log::debug(sprintf('Transaction has tag "%s" so count++.', $tag['name']));
++$foundTagCount;
$journalId = $transaction['transaction_journal_id'];
// #8377 prevent adding a transaction twice when multiple tag searches find this transaction
@@ -761,7 +762,7 @@ trait MetaCollection
public function setTag(Tag $tag): GroupCollectorInterface
{
$this->withTagInformation();
$this->setTags(new Collection([$tag]));
$this->setTags(new Collection()->push($tag));
return $this;
}
@@ -775,6 +776,9 @@ trait MetaCollection
$this->withTagInformation();
$this->query->whereNotNull('tag_transaction_journal.tag_id');
// Added this while fixing #10898, not sure why a post filter was ever necessary.
$this->query->whereIn('tag_transaction_journal.tag_id', $tags->pluck('id')->toArray());
// this method adds a "postFilter" to the collector.
$list = $tags->pluck('tag')->toArray();
$list = array_map('strtolower', $list);
@@ -784,13 +788,13 @@ trait MetaCollection
foreach ($transaction['tags'] as $tag) {
Log::debug(sprintf('"%s" versus', strtolower((string) $tag['name'])), $list);
if (in_array(strtolower((string) $tag['name']), $list, true)) {
app('log')->debug(sprintf('Transaction has tag "%s" so return true.', $tag['name']));
Log::debug(sprintf('Transaction has tag "%s" so return true.', $tag['name']));
return true;
}
}
}
app('log')->debug('Transaction has no tags from the list, so return false.');
Log::debug('Transaction has no tags from the list, so return false.');
return false;
};
@@ -812,11 +816,11 @@ trait MetaCollection
$filter = static function (array $object) use ($list): bool {
Log::debug(sprintf('Now in setWithoutSpecificTags(%s) filter', implode(', ', $list)));
foreach ($object['transactions'] as $transaction) {
app('log')->debug(sprintf('Transaction has %d tag(s)', count($transaction['tags'])));
Log::debug(sprintf('Transaction has %d tag(s)', count($transaction['tags'])));
foreach ($transaction['tags'] as $tag) {
Log::debug(sprintf('"%s" versus', strtolower((string) $tag['name'])), $list);
if (in_array(strtolower((string) $tag['name']), $list, true)) {
app('log')->debug(sprintf('Transaction has tag "%s", but should not have it, return false.', $tag['name']));
Log::debug(sprintf('Transaction has tag "%s", but should not have it, return false.', $tag['name']));
return false;
}
@@ -919,6 +923,8 @@ trait MetaCollection
{
$this->withCategoryInformation();
$this->query->whereNull('category_transaction_journal.category_id');
// better fix for #10507
$this->query->whereNotIn('transaction_types.type', [TransactionTypeEnum::OPENING_BALANCE->value]);
return $this;
}

View File

@@ -560,7 +560,7 @@ class GroupCollector implements GroupCollectorInterface
}
$groups = $this->parseSums($groups);
return new Collection($groups);
return new Collection()->push(...$groups);
}
/**
@@ -631,10 +631,11 @@ class GroupCollector implements GroupCollectorInterface
}
// also merge attachments:
if (array_key_exists('attachment_id', $result)) {
if (array_key_exists('attachment_id', $result) && null !== $result['attachment_id']) {
$uploaded = 1 === (int)$result['attachment_uploaded'];
$attachmentId = (int)$augumentedJournal['attachment_id'];
if (0 !== $attachmentId && $uploaded) {
$deleted = null !== $result['attachment_deleted_at'];
if (0 !== $attachmentId && $uploaded && !$deleted) {
$result['attachments'][$attachmentId] = [
'id' => $attachmentId,
'filename' => $augumentedJournal['attachment_filename'],
@@ -659,7 +660,7 @@ class GroupCollector implements GroupCollectorInterface
private function convertToInteger(array $array): array
{
foreach ($this->integerFields as $field) {
$array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null;
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (int)$array[$field] : null;
}
return $array;
@@ -1095,9 +1096,6 @@ class GroupCollector implements GroupCollectorInterface
->whereNull('transaction_groups.deleted_at')
->whereNull('transaction_journals.deleted_at')
->whereNull('source.deleted_at')
// #10507 ignore opening balance.
->where('transaction_types.type', '!=', TransactionTypeEnum::OPENING_BALANCE->value)
->whereNotNull('transaction_groups.id')
->whereNull('destination.deleted_at')
->orderBy('transaction_journals.date', 'DESC')

View File

@@ -31,7 +31,6 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam;
@@ -49,7 +48,6 @@ use Illuminate\Support\Facades\Log;
class NetWorth implements NetWorthInterface
{
private AccountRepositoryInterface $accountRepository;
private CurrencyRepositoryInterface $currencyRepos;
private User $user; // @phpstan-ignore-line
private ?UserGroup $userGroup = null;
@@ -131,8 +129,6 @@ class NetWorth implements NetWorthInterface
$this->accountRepository = app(AccountRepositoryInterface::class);
$this->accountRepository->setUserGroup($userGroup);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->currencyRepos->setUserGroup($this->userGroup);
}
#[Deprecated]

View File

@@ -45,7 +45,7 @@ class PopupReport implements PopupReportInterface
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))
$collector->setAccounts(new Collection()->push($account))
->withAccountInformation()
->withBudgetInformation()
->withCategoryInformation()
@@ -72,7 +72,7 @@ class PopupReport implements PopupReportInterface
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setAccounts(new Collection([$account]))
->setAccounts(new Collection()->push($account))
->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
->withAccountInformation()
->withCategoryInformation()
@@ -191,7 +191,7 @@ class PopupReport implements PopupReportInterface
// $set = $attributes['accounts'] ?? new Collection;
// $set->push($account);
$collector->setDestinationAccounts(new Collection([$account]))
$collector->setDestinationAccounts(new Collection()->push($account))
->setRange($attributes['startDate'], $attributes['endDate'])
->withAccountInformation()
->withBudgetInformation()
@@ -218,7 +218,7 @@ class PopupReport implements PopupReportInterface
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setSourceAccounts(new Collection([$account]))
->setSourceAccounts(new Collection()->push($account))
->setDestinationAccounts($attributes['accounts'])
->setRange($attributes['startDate'], $attributes['endDate'])
->setTypes([TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::TRANSFER->value])

View File

@@ -86,7 +86,7 @@ class CreateController extends Controller
'latitude' => $hasOldInput ? old('location_latitude') : config('firefly.default_location.latitude'),
'longitude' => $hasOldInput ? old('location_longitude') : config('firefly.default_location.longitude'),
'zoom_level' => $hasOldInput ? old('location_zoom_level') : config('firefly.default_location.zoom_level'),
'has_location' => $hasOldInput ? 'true' === old('location_has_location') : false,
'has_location' => $hasOldInput && 'true' === old('location_has_location'),
],
];
$liabilityDirections = [
@@ -106,7 +106,7 @@ class CreateController extends Controller
'preFilled',
[
'currency_id' => $this->primaryCurrency->id,
'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : true,
'include_net_worth' => !$hasOldInput || (bool)$request->old('include_net_worth'),
]
);
// issue #8321

View File

@@ -143,7 +143,7 @@ class ShowController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setAccounts(new Collection([$account]))
->setAccounts(new Collection()->push($account))
->setLimit($pageSize)
->setPage($page)
->withAttachmentInformation()
@@ -221,7 +221,7 @@ class ShowController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation();
$collector->setAccounts(new Collection()->push($account))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation();
// this search will not include transaction groups where this asset account (or liability)
// is just part of ONE of the journals. To force this:

View File

@@ -203,7 +203,7 @@ class BudgetLimitController extends Controller
if ($request->expectsJson()) {
$array = $limit->toArray();
// add some extra metadata:
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $currency);
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
$array['left_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount']));
$array['amount_formatted'] = app('amount')->formatAnything($limit->transactionCurrency, $limit['amount']);
@@ -264,7 +264,7 @@ class BudgetLimitController extends Controller
$limit->start_date,
$limit->end_date,
null,
new Collection([$budgetLimit->budget]),
new Collection()->push($budgetLimit->budget),
$budgetLimit->transactionCurrency
);
$daysLeft = $this->activeDaysLeft($limit->start_date, $limit->end_date);

View File

@@ -235,7 +235,7 @@ class IndexController extends Controller
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$current]), $currency, false);
$spentArr = $this->opsRepository->sumExpenses($start, $end, null, new Collection()->push($current), $currency, false);
if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['currency_id'] = $currency->id;

View File

@@ -235,7 +235,7 @@ class AccountController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))
$collector->setAccounts(new Collection()->push($account))
->setRange($start, $end)
->withBudgetInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
;
@@ -322,7 +322,7 @@ class AccountController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
$collector->setAccounts(new Collection()->push($account))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
$journals = $collector->getExtractedJournals();
$result = [];
$chartData = [];
@@ -429,7 +429,7 @@ class AccountController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::DEPOSIT->value]);
$collector->setAccounts(new Collection()->push($account))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionTypeEnum::DEPOSIT->value]);
$journals = $collector->getExtractedJournals();
$result = [];
$chartData = [];

View File

@@ -100,7 +100,7 @@ class BudgetController extends Controller
return response()->json($cache->get());
}
$step = $this->calculateStep($start, $end); // depending on diff, do something with range of chart.
$collection = new Collection([$budget]);
$collection = new Collection()->push($budget);
$chartData = [];
$loopStart = clone $start;
$loopStart = Navigation::startOfPeriod($loopStart, $step);
@@ -169,7 +169,7 @@ class BudgetController extends Controller
$locale = app('steam')->getLocale();
$entries = [];
$amount = $budgetLimit->amount ?? '0';
$budgetCollection = new Collection([$budget]);
$budgetCollection = new Collection()->push($budget);
$currency = $budgetLimit->transactionCurrency;
if ($this->convertToPrimary) {
$amount = $budgetLimit->native_amount ?? $amount;
@@ -535,7 +535,7 @@ class BudgetController extends Controller
}
// get spent amount in this period for this currency.
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection([$budget]), $currency);
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
$amount = app('steam')->positive($sum[$currency->id]['sum'] ?? '0');
$chartData[0]['entries'][$title] = app('steam')->bcround($amount, $currency->decimal_places);

View File

@@ -163,7 +163,7 @@ class BudgetReportController extends Controller
public function mainChart(Collection $accounts, Budget $budget, Carbon $start, Carbon $end): JsonResponse
{
$chartData = [];
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection([$budget]));
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($budget));
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
// loop expenses.

View File

@@ -174,7 +174,7 @@ class CategoryController extends Controller
$opsRepository = app(OperationsRepositoryInterface::class);
$categoryId = $category->id;
// this gives us all currencies
$collection = new Collection([$category]);
$collection = new Collection()->push($category);
$expenses = $opsRepository->listExpenses($start, $end, $accounts, $collection);
$income = $opsRepository->listIncome($start, $end, $accounts, $collection);
}

View File

@@ -208,8 +208,8 @@ class CategoryReportController extends Controller
public function mainChart(Collection $accounts, Category $category, Carbon $start, Carbon $end): JsonResponse
{
$chartData = [];
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection([$category]));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection([$category]));
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($category));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($category));
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
// loop expenses.
foreach ($spent as $currency) {

View File

@@ -150,7 +150,7 @@ class DoubleReportController extends Controller
{
$chartData = [];
$opposing = $this->repository->expandWithDoubles(new Collection([$account]));
$opposing = $this->repository->expandWithDoubles(new Collection()->push($account));
$accounts = $accounts->merge($opposing);
$spent = $this->opsRepository->listExpenses($start, $end, $accounts);
$earned = $this->opsRepository->listIncome($start, $end, $accounts);

View File

@@ -212,8 +212,8 @@ class TagReportController extends Controller
public function mainChart(Collection $accounts, Tag $tag, Carbon $start, Carbon $end): JsonResponse
{
$chartData = [];
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection([$tag]));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection([$tag]));
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($tag));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($tag));
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
// loop expenses.

View File

@@ -170,7 +170,7 @@ class HomeController extends Controller
foreach ($accounts as $account) {
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->withAccountInformation()->setRange($start, $end)->setLimit(10)->setPage(1);
$collector->setAccounts(new Collection()->push($account))->withAccountInformation()->setRange($start, $end)->setLimit(10)->setPage(1);
$set = $collector->getExtractedJournals();
$transactions[] = ['transactions' => $set, 'account' => $account];
}

View File

@@ -171,7 +171,7 @@ class BoxController extends Controller
$filtered = $allAccounts->filter(
static function (Account $account) use ($accountRepository) {
$includeNetWorth = $accountRepository->getMetaValue($account, 'include_net_worth');
$result = null === $includeNetWorth ? true : '1' === $includeNetWorth;
$result = null === $includeNetWorth || '1' === $includeNetWorth;
if (false === $result) {
app('log')->debug(sprintf('Will not include "%s" in net worth charts.', $account->name));
}

View File

@@ -217,7 +217,7 @@ class ReconcileController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))
$collector->setAccounts(new Collection()->push($account))
->setRange($selectionStart, $selectionEnd)
->withBudgetInformation()->withCategoryInformation()->withAccountInformation()
;

View File

@@ -74,7 +74,7 @@ class TriggerController extends Controller
/** @var CreateRecurringTransactions $job */
$job = app(CreateRecurringTransactions::class);
$job->setRecurrences(new Collection([$recurrence]));
$job->setRecurrences(new Collection()->push($recurrence));
$job->setDate($date);
$job->setForce(false);
$job->handle();

View File

@@ -291,7 +291,7 @@ class BudgetController extends Controller
$cache->addProperty('budget-period-report');
$cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) {
// return $cache->get();
return $cache->get();
}
$periods = Navigation::listOfPeriods($start, $end);

View File

@@ -152,7 +152,7 @@ class SelectController extends Controller
$newRuleEngine = app(RuleEngineInterface::class);
// set rules:
$newRuleEngine->setRules(new Collection([$rule]));
$newRuleEngine->setRules(new Collection()->push($rule));
$newRuleEngine->setRefreshTriggers(false);
$collection = $newRuleEngine->find();
$collection = $collection->slice(0, 20);
@@ -196,7 +196,7 @@ class SelectController extends Controller
$newRuleEngine = app(RuleEngineInterface::class);
// set rules:
$newRuleEngine->setRules(new Collection([$rule]));
$newRuleEngine->setRules(new Collection()->push($rule));
$collection = $newRuleEngine->find();
$collection = $collection->slice(0, 20);

View File

@@ -78,7 +78,7 @@ class ExecutionController extends Controller
// set rules:
// #10427, file rule group and not the set of rules.
$collection = new Collection([$ruleGroup]);
$collection = new Collection()->push($ruleGroup);
$newRuleEngine->setRuleGroups($collection);
$newRuleEngine->fire();

View File

@@ -250,10 +250,7 @@ class TagController extends Controller
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation()
->setTag($tag)->withBudgetInformation()->withCategoryInformation()
->withAttachmentInformation()
;
$collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation()->setTag($tag)->withBudgetInformation()->withCategoryInformation()->withAttachmentInformation();
$groups = $collector->getPaginatedGroups();
$groups->setPath($path);
$sums = $this->repository->sumsOfTag($tag, $start, $end);

View File

@@ -269,7 +269,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection([$autoBudget->budget]), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
@@ -329,7 +329,7 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection([$autoBudget->budget]), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));

View File

@@ -39,6 +39,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use function Safe\json_decode;
@@ -74,7 +75,7 @@ class DownloadExchangeRates implements ShouldQueue
$newDate = clone $date;
$newDate->startOfDay();
$this->date = $newDate;
app('log')->debug(sprintf('Created new DownloadExchangeRates("%s")', $this->date->format('Y-m-d')));
Log::debug(sprintf('Created new DownloadExchangeRates("%s")', $this->date->format('Y-m-d')));
}
}
@@ -83,7 +84,7 @@ class DownloadExchangeRates implements ShouldQueue
*/
public function handle(): void
{
app('log')->debug('Now in handle()');
Log::debug('Now in handle()');
$currencies = $this->repository->getCompleteSet();
/** @var TransactionCurrency $currency */
@@ -97,7 +98,7 @@ class DownloadExchangeRates implements ShouldQueue
*/
private function downloadRates(TransactionCurrency $currency): void
{
app('log')->debug(sprintf('Now downloading new exchange rates for currency %s.', $currency->code));
Log::debug(sprintf('Now downloading new exchange rates for currency %s.', $currency->code));
$base = sprintf('%s/%s/%s', (string) config('cer.url'), $this->date->year, $this->date->isoWeek);
$client = new Client();
$url = sprintf('%s/%s.json', $base, $currency->code);
@@ -105,20 +106,20 @@ class DownloadExchangeRates implements ShouldQueue
try {
$res = $client->get($url);
} catch (ConnectException|RequestException $e) {
app('log')->warning(sprintf('Trying to grab "%s" resulted in error "%s".', $url, $e->getMessage()));
Log::warning(sprintf('Trying to grab "%s" resulted in error "%s".', $url, $e->getMessage()));
return;
}
$statusCode = $res->getStatusCode();
if (200 !== $statusCode) {
app('log')->warning(sprintf('Trying to grab "%s" resulted in status code %d.', $url, $statusCode));
Log::warning(sprintf('Trying to grab "%s" resulted in status code %d.', $url, $statusCode));
return;
}
$body = (string) $res->getBody();
$json = json_decode($body, true);
if (false === $json || null === $json) {
app('log')->warning(sprintf('Trying to grab "%s" resulted in bad JSON.', $url));
Log::warning(sprintf('Trying to grab "%s" resulted in bad JSON.', $url));
return;
}
@@ -134,11 +135,11 @@ class DownloadExchangeRates implements ShouldQueue
foreach ($rates as $code => $rate) {
$to = $this->getCurrency($code);
if (!$to instanceof TransactionCurrency) {
app('log')->debug(sprintf('Currency %s is not in use, do not save rate.', $code));
Log::debug(sprintf('Currency %s is not in use, do not save rate.', $code));
continue;
}
app('log')->debug(sprintf('Currency %s is in use.', $code));
Log::debug(sprintf('Currency %s is in use.', $code));
$this->saveRate($currency, $to, $date, $rate);
}
}
@@ -147,25 +148,25 @@ class DownloadExchangeRates implements ShouldQueue
{
// if we have it already, don't bother searching for it again.
if (array_key_exists($code, $this->active)) {
app('log')->debug(sprintf('Already know what the result is of searching for %s', $code));
Log::debug(sprintf('Already know what the result is of searching for %s', $code));
return $this->active[$code];
}
// find it in the database.
$currency = $this->repository->findByCode($code);
if (!$currency instanceof TransactionCurrency) {
app('log')->debug(sprintf('Did not find currency %s.', $code));
Log::debug(sprintf('Did not find currency %s.', $code));
$this->active[$code] = null;
return null;
}
if (false === $currency->enabled) {
app('log')->debug(sprintf('Currency %s is not enabled.', $code));
Log::debug(sprintf('Currency %s is not enabled.', $code));
$this->active[$code] = null;
return null;
}
app('log')->debug(sprintf('Currency %s is enabled.', $code));
Log::debug(sprintf('Currency %s is enabled.', $code));
$this->active[$code] = $currency;
return $currency;
@@ -177,7 +178,7 @@ class DownloadExchangeRates implements ShouldQueue
$this->repository->setUser($user);
$existing = $this->repository->getExchangeRate($from, $to, $date);
if (!$existing instanceof CurrencyExchangeRate) {
app('log')->debug(sprintf('Saved rate from %s to %s for user #%d.', $from->code, $to->code, $user->id));
Log::debug(sprintf('Saved rate from %s to %s for user #%d.', $from->code, $to->code, $user->id));
$this->repository->setExchangeRate($from, $to, $date, $rate);
}
}

View File

@@ -209,7 +209,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface, U
#[Deprecated]
public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget
{
/** @var null|AvailableBudget */
/** @var null|AvailableBudget $availableBudget */
$availableBudget = $this->user->availableBudgets()
->where('transaction_currency_id', $currency->id)
->where('start_date', $start->format('Y-m-d'))

View File

@@ -373,7 +373,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
return CurrencyExchangeRate::create(
[
'user_id' => $this->user->id,
'user_group_id' => $this->user->user_group_id,
'user_group_id' => $this->userGroup->id,
'from_currency_id' => $fromCurrency->id,
'to_currency_id' => $toCurrency->id,
'date' => $date,

View File

@@ -34,15 +34,11 @@ use Closure;
*/
class IsDuplicateTransaction implements ValidationRule
{
private string $value;
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
$this->value = $value;
$fail($this->value);
$fail($value);
}
}

View File

@@ -227,7 +227,6 @@ class CreditRecalculateService
$source->save();
$dest->save();
return;
}
// Log::debug('Opening balance is valid');
}

View File

@@ -70,7 +70,7 @@ class Calculator
}
self::$intervalMap = new SplObjectStorage();
foreach (Periodicity::cases() as $interval) {
$periodicityClass = __NAMESPACE__."\\Periodicity\\{$interval->name}";
$periodicityClass = sprintf('%s\Periodicity\%s', __NAMESPACE__, $interval->name);
self::$intervals[] = $interval->name;
self::$intervalMap->attach($interval, new $periodicityClass());
}

View File

@@ -114,7 +114,7 @@ class FrontpageChartGenerator
*/
private function noBudgetLimits(array $data, Budget $budget): array
{
$spent = $this->opsRepository->sumExpenses($this->start, $this->end, null, new Collection([$budget]));
$spent = $this->opsRepository->sumExpenses($this->start, $this->end, null, new Collection()->push($budget));
/** @var array $entry */
foreach ($spent as $entry) {
@@ -158,7 +158,7 @@ class FrontpageChartGenerator
Log::debug(sprintf('Processing limit #%d with %s %s', $limit->id, $limit->transactionCurrency->code, $limit->amount));
}
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection([$budget]), $currency);
$spent = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
Log::debug(sprintf('Spent array has %d entries.', count($spent)));
/** @var array $entry */

View File

@@ -40,7 +40,7 @@ class WholePeriodChartGenerator
public function generate(Category $category, Carbon $start, Carbon $end): array
{
$collection = new Collection([$category]);
$collection = new Collection()->push($category);
/** @var OperationsRepositoryInterface $opsRepository */
$opsRepository = app(OperationsRepositoryInterface::class);

View File

@@ -191,7 +191,7 @@ trait AugumentData
$set = $blRepository->getBudgetLimits($budget, $start, $end);
$budgetCollection = new Collection([$budget]);
$budgetCollection = new Collection()->push($budget);
// merge sets based on a key, in case of convert to primary currency
$limits = new Collection();

View File

@@ -90,7 +90,7 @@ class AccountEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): Account|array
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -73,7 +73,7 @@ class BudgetEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();
@@ -167,7 +167,7 @@ class BudgetEnrichment implements EnrichmentInterface
$opsRepository->setUser($this->user);
$opsRepository->setUserGroup($this->userGroup);
// $spent = $this->beautify();
// $set = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]))
// $set = $this->opsRepository->sumExpenses($start, $end, null, new Collection()->push($budget))
$expenses = $opsRepository->collectExpenses($this->start, $this->end, null, $this->collection, null);
foreach ($this->collection as $item) {
$id = (int)$item->id;

View File

@@ -47,7 +47,6 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private array $notes = [];
private Carbon $start;
private Carbon $end;
private Collection $budgets;
private array $expenses = [];
private array $pcExpenses = [];
private array $currencyIds = [];
@@ -146,12 +145,12 @@ class BudgetLimitEnrichment implements EnrichmentInterface
private function collectBudgets(): void
{
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
$this->budgets = Budget::whereIn('id', $budgetIds)->get();
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
$budgets = Budget::whereIn('id', $budgetIds)->get();
$repository = app(OperationsRepository::class);
$repository = app(OperationsRepository::class);
$repository->setUser($this->user);
$expenses = $repository->collectExpenses($this->start, $this->end, null, $this->budgets, null);
$expenses = $repository->collectExpenses($this->start, $this->end, null, $budgets, null);
/** @var BudgetLimit $budgetLimit */
foreach ($this->collection as $budgetLimit) {

View File

@@ -65,7 +65,7 @@ class CategoryEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -80,7 +80,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -69,7 +69,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -101,7 +101,7 @@ class RecurringEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();
@@ -162,15 +162,14 @@ class RecurringEnrichment implements EnrichmentInterface
foreach ($set as $carbon) {
$occurrences[] = $carbon->toAtomString();
}
$this->repetitions[$id][$repId] = [
'id' => (string)$repId,
'created_at' => $repetition->created_at->toAtomString(),
'updated_at' => $repetition->updated_at->toAtomString(),
'type' => $repetition->repetition_type,
'moment' => (string)$repetition->moment,
'skip' => (int)$repetition->skip,
'weekend' => RecurrenceRepetitionWeekend::from((int)$repetition->weekend),
'moment' => (string)$repetition->repetition_moment,
'skip' => (int)$repetition->repetition_skip,
'weekend' => RecurrenceRepetitionWeekend::from((int)$repetition->weekend)->value,
'description' => $this->getRepetitionDescription($repetition),
'occurrences' => $occurrences,
];

View File

@@ -145,7 +145,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -68,7 +68,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
{
Log::debug(__METHOD__);
if (is_array($model)) {
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -70,7 +70,7 @@ class WebhookEnrichment implements EnrichmentInterface
public function enrichSingle(array|Model $model): array|Model
{
Log::debug(__METHOD__);
$collection = new Collection([$model]);
$collection = new Collection()->push($model);
$collection = $this->enrich($collection);
return $collection->first();

View File

@@ -206,7 +206,7 @@ class AccountBalanceCalculator
foreach ($transactionJournal->transactions as $transaction) {
$set[$transaction->account_id] = $transaction->account;
}
$accounts = new Collection($set);
$accounts = new Collection()->push(...$set);
$object->optimizedCalculation($accounts, $transactionJournal->date);
}
}

View File

@@ -188,7 +188,7 @@ class BudgetReportGenerator
$limitId = $limit->id;
$limitCurrency = $limit->transactionCurrency ?? $this->currency;
$currencyId = $limitCurrency->id;
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget]));
$expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection()->push($budget));
$spent = $expenses[$currencyId]['sum'] ?? '0';
$left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent);
$overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0';

View File

@@ -28,6 +28,7 @@ use Carbon\Carbon;
use FireflyIII\Enums\RecurrenceRepetitionWeekend;
use FireflyIII\Models\RecurrenceRepetition;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
/**
* Trait FiltersWeekends
@@ -39,9 +40,9 @@ trait FiltersWeekends
*/
protected function filterWeekends(RecurrenceRepetition $repetition, array $dates): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
Log::debug(sprintf('Now in %s', __METHOD__));
if (RecurrenceRepetitionWeekend::WEEKEND_DO_NOTHING->value === $repetition->weekend) {
app('log')->debug('Repetition will not be filtered on weekend days.');
Log::debug('Repetition will not be filtered on weekend days.');
return $dates;
}
@@ -53,7 +54,7 @@ trait FiltersWeekends
if (!$isWeekend) {
$return[] = clone $date;
// app('log')->debug(sprintf('Date is %s, not a weekend date.', $date->format('D d M Y')));
// Log::debug(sprintf('Date is %s, not a weekend date.', $date->format('D d M Y')));
continue;
}
@@ -61,7 +62,7 @@ trait FiltersWeekends
if (RecurrenceRepetitionWeekend::WEEKEND_TO_FRIDAY->value === $repetition->weekend) {
$clone = clone $date;
$clone->addDays(5 - $date->dayOfWeekIso);
app('log')->debug(
Log::debug(
sprintf('Date is %s, and this is in the weekend, so corrected to %s (Friday).', $date->format('D d M Y'), $clone->format('D d M Y'))
);
$return[] = clone $clone;
@@ -73,23 +74,22 @@ trait FiltersWeekends
if (RecurrenceRepetitionWeekend::WEEKEND_TO_MONDAY->value === $repetition->weekend) {
$clone = clone $date;
$clone->addDays(8 - $date->dayOfWeekIso);
app('log')->debug(
Log::debug(
sprintf('Date is %s, and this is in the weekend, so corrected to %s (Monday).', $date->format('D d M Y'), $clone->format('D d M Y'))
);
$return[] = $clone;
continue;
}
// app('log')->debug(sprintf('Date is %s, removed from final result', $date->format('D d M Y')));
// Log::debug(sprintf('Date is %s, removed from final result', $date->format('D d M Y')));
}
// filter unique dates
app('log')->debug(sprintf('Count before filtering: %d', count($dates)));
$collection = new Collection($return);
Log::debug(sprintf('Count before filtering: %d', count($dates)));
$collection = new Collection()->push(...$return);
$filtered = $collection->unique();
$return = $filtered->toArray();
app('log')->debug(sprintf('Count after filtering: %d', count($return)));
Log::debug(sprintf('Count after filtering: %d', count($return)));
return $return;
}

View File

@@ -450,7 +450,7 @@ class OperatorQuerySearch implements SearchInterface
case 'source_account_id':
$account = $this->accountRepository->find((int) $value);
if (null !== $account) {
$this->collector->setSourceAccounts(new Collection([$account]));
$this->collector->setSourceAccounts(new Collection()->push($account));
}
if (null === $account) {
// since the source does not exist, cannot return results:
@@ -463,7 +463,7 @@ class OperatorQuerySearch implements SearchInterface
case '-source_account_id':
$account = $this->accountRepository->find((int) $value);
if (null !== $account) {
$this->collector->excludeSourceAccounts(new Collection([$account]));
$this->collector->excludeSourceAccounts(new Collection()->push($account));
}
if (null === $account) {
// since the source does not exist, cannot return results:
@@ -580,7 +580,7 @@ class OperatorQuerySearch implements SearchInterface
case 'destination_account_id':
$account = $this->accountRepository->find((int) $value);
if (null !== $account) {
$this->collector->setDestinationAccounts(new Collection([$account]));
$this->collector->setDestinationAccounts(new Collection()->push($account));
}
if (null === $account) {
Log::warning('Call to findNothing() because dest account does not exist (destination_account_id).');
@@ -592,7 +592,7 @@ class OperatorQuerySearch implements SearchInterface
case '-destination_account_id':
$account = $this->accountRepository->find((int) $value);
if (null !== $account) {
$this->collector->excludeDestinationAccounts(new Collection([$account]));
$this->collector->excludeDestinationAccounts(new Collection()->push($account));
}
if (null === $account) {
Log::warning('Call to findNothing() because dest account does not exist (-destination_account_id).');
@@ -652,37 +652,37 @@ class OperatorQuerySearch implements SearchInterface
//
case 'source_is_cash':
$account = $this->getCashAccount();
$this->collector->setSourceAccounts(new Collection([$account]));
$this->collector->setSourceAccounts(new Collection()->push($account));
break;
case '-source_is_cash':
$account = $this->getCashAccount();
$this->collector->excludeSourceAccounts(new Collection([$account]));
$this->collector->excludeSourceAccounts(new Collection()->push($account));
break;
case 'destination_is_cash':
$account = $this->getCashAccount();
$this->collector->setDestinationAccounts(new Collection([$account]));
$this->collector->setDestinationAccounts(new Collection()->push($account));
break;
case '-destination_is_cash':
$account = $this->getCashAccount();
$this->collector->excludeDestinationAccounts(new Collection([$account]));
$this->collector->excludeDestinationAccounts(new Collection()->push($account));
break;
case 'account_is_cash':
$account = $this->getCashAccount();
$this->collector->setAccounts(new Collection([$account]));
$this->collector->setAccounts(new Collection()->push($account));
break;
case '-account_is_cash':
$account = $this->getCashAccount();
$this->collector->excludeAccounts(new Collection([$account]));
$this->collector->excludeAccounts(new Collection()->push($account));
break;
@@ -1070,7 +1070,7 @@ class OperatorQuerySearch implements SearchInterface
case '-bill_is':
$bill = $this->billRepository->findByName($value);
if (null !== $bill) {
$this->collector->excludeBills(new Collection([$bill]));
$this->collector->excludeBills(new Collection()->push($bill));
break;
}

View File

@@ -3,17 +3,13 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.4.0 - 2025-09-01
## 6.4.0 - 2025-09-19
### Added
- [Issue 5532](https://github.com/firefly-iii/firefly-iii/issues/5532) (Asset prices and exchange rates) reported by @svozniuk
- [Discussion 10725](https://github.com/orgs/firefly-iii/discussions/10725) (New webhook triggers) started by @Billos. See the [documentation](https://docs.firefly-iii.org/how-to/firefly-iii/features/webhooks/).
### Changed
- Initial release.
### Fixed
- [Issue 10790](https://github.com/firefly-iii/firefly-iii/issues/10790) (Undefined variable $occurrences) reported by @senna1992
@@ -22,12 +18,22 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- [Issue 10799](https://github.com/firefly-iii/firefly-iii/issues/10799) (Budget - "Left (per day)" not showing the correct value) reported by @GensHaze
- [Issue 10802](https://github.com/firefly-iii/firefly-iii/issues/10802) (Crash when trying to update a budget limit) reported by @Billos
- [Issue 10803](https://github.com/firefly-iii/firefly-iii/issues/10803) (Issue in /v1/budget-limits spent attribute) reported by @Billos
- [Issue 10804](https://github.com/firefly-iii/firefly-iii/issues/10804) (No notes information included in the "List all accounts" API call) reported by @gpampuro
- [Issue 10808](https://github.com/firefly-iii/firefly-iii/issues/10808) (cron job Error: Undefined variable $preference) reported by @MexerSam
- [Issue 10813](https://github.com/firefly-iii/firefly-iii/issues/10813) (Error "Argument #2 ($symbol) must be of type string" while try open subscriptions section) reported by @mrResident
- [Issue 10814](https://github.com/firefly-iii/firefly-iii/issues/10814) (Deposit show negative amounts & red numbers in detail view) reported by @dreautall
- [Issue 10819](https://github.com/firefly-iii/firefly-iii/issues/10819) (Internal Server Error when trying to open piggy banks) reported by @noantiq
- [Issue 10820](https://github.com/firefly-iii/firefly-iii/issues/10820) (Unable to search date 1970-01-01 to apply rule.) reported by @Kage1
- [Issue 10824](https://github.com/firefly-iii/firefly-iii/issues/10824) (Converting withdrawal to transfer to account in different currency doesn't allow setting correct currencies) reported by @avee87
- [Issue 10833](https://github.com/firefly-iii/firefly-iii/issues/10833) (Can't open transaction after assigning a tag to it) reported by @zynexiz
- [Issue 10837](https://github.com/firefly-iii/firefly-iii/issues/10837) (Internal Server Erorr when viewing or editing Recurring transaction) reported by @Tommy78649
- [Discussion 10846](https://github.com/orgs/firefly-iii/discussions/10846) (Add support for WebP format in attachments) started by @Idestius
- [Issue 10853](https://github.com/firefly-iii/firefly-iii/issues/10853) (Failed to Send Discord Notification) reported by @pimonteiro
- [Issue 10854](https://github.com/firefly-iii/firefly-iii/issues/10854) (string / null in budget causes budget page to not render) reported by @4e868df3
- [Issue 10871](https://github.com/firefly-iii/firefly-iii/issues/10871) (Transactions disappear after deleting attachment) reported by @dvmfa90
- [Discussion 10883](https://github.com/orgs/firefly-iii/discussions/10883) (Initial balance for account is missing from exported CSV) started by @ajaskiewiczpl
- [Issue 10888](https://github.com/firefly-iii/firefly-iii/issues/10888) (Recurring transation forgets repetition type, skip and weekend action) reported by @mansellrace
- [Discussion 10891](https://github.com/orgs/firefly-iii/discussions/10891) (User group id is null when downloading new exchange rates) started by @dakennguyen
- [Issue 10898](https://github.com/firefly-iii/firefly-iii/issues/10898) (Paperclip icon appears for transactions without attachments in Tag view) reported by @empeig
### API

112
composer.lock generated
View File

@@ -1811,16 +1811,16 @@
},
{
"name": "laravel-notification-channels/pushover",
"version": "4.1.1",
"version": "4.1.2",
"source": {
"type": "git",
"url": "https://github.com/laravel-notification-channels/pushover.git",
"reference": "68697f85a01c5f10168ad0ab05b14ef3e244cec4"
"reference": "53be939273e79e832a417d5863c1d443f0b3c665"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel-notification-channels/pushover/zipball/68697f85a01c5f10168ad0ab05b14ef3e244cec4",
"reference": "68697f85a01c5f10168ad0ab05b14ef3e244cec4",
"url": "https://api.github.com/repos/laravel-notification-channels/pushover/zipball/53be939273e79e832a417d5863c1d443f0b3c665",
"reference": "53be939273e79e832a417d5863c1d443f0b3c665",
"shasum": ""
},
"require": {
@@ -1872,9 +1872,9 @@
"homepage": "https://github.com/laravel-notification-channels/pushover",
"support": {
"issues": "https://github.com/laravel-notification-channels/pushover/issues",
"source": "https://github.com/laravel-notification-channels/pushover/tree/4.1.1"
"source": "https://github.com/laravel-notification-channels/pushover/tree/4.1.2"
},
"time": "2025-03-01T09:05:11+00:00"
"time": "2025-09-09T09:14:17+00:00"
},
{
"name": "laravel/framework",
@@ -2811,16 +2811,16 @@
},
{
"name": "league/csv",
"version": "9.24.1",
"version": "9.25.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/csv.git",
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8"
"reference": "f856f532866369fb1debe4e7c5a1db185f40ef86"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/e0221a3f16aa2a823047d59fab5809d552e29bc8",
"reference": "e0221a3f16aa2a823047d59fab5809d552e29bc8",
"url": "https://api.github.com/repos/thephpleague/csv/zipball/f856f532866369fb1debe4e7c5a1db185f40ef86",
"reference": "f856f532866369fb1debe4e7c5a1db185f40ef86",
"shasum": ""
},
"require": {
@@ -2836,7 +2836,7 @@
"phpstan/phpstan-deprecation-rules": "^1.2.1",
"phpstan/phpstan-phpunit": "^1.4.2",
"phpstan/phpstan-strict-rules": "^1.6.2",
"phpunit/phpunit": "^10.5.16 || ^11.5.22",
"phpunit/phpunit": "^10.5.16 || ^11.5.22 || ^12.3.6",
"symfony/var-dumper": "^6.4.8 || ^7.3.0"
},
"suggest": {
@@ -2898,7 +2898,7 @@
"type": "github"
}
],
"time": "2025-06-25T14:53:51+00:00"
"time": "2025-09-11T08:29:08+00:00"
},
{
"name": "league/event",
@@ -10738,16 +10738,16 @@
},
{
"name": "larastan/larastan",
"version": "v3.6.1",
"version": "v3.7.1",
"source": {
"type": "git",
"url": "https://github.com/larastan/larastan.git",
"reference": "3c223047e374befd1b64959784685d6ecccf66aa"
"reference": "2e653fd19585a825e283b42f38378b21ae481cc7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larastan/larastan/zipball/3c223047e374befd1b64959784685d6ecccf66aa",
"reference": "3c223047e374befd1b64959784685d6ecccf66aa",
"url": "https://api.github.com/repos/larastan/larastan/zipball/2e653fd19585a825e283b42f38378b21ae481cc7",
"reference": "2e653fd19585a825e283b42f38378b21ae481cc7",
"shasum": ""
},
"require": {
@@ -10761,7 +10761,7 @@
"illuminate/pipeline": "^11.44.2 || ^12.4.1",
"illuminate/support": "^11.44.2 || ^12.4.1",
"php": "^8.2",
"phpstan/phpstan": "^2.1.11"
"phpstan/phpstan": "^2.1.23"
},
"require-dev": {
"doctrine/coding-standard": "^13",
@@ -10815,7 +10815,7 @@
],
"support": {
"issues": "https://github.com/larastan/larastan/issues",
"source": "https://github.com/larastan/larastan/tree/v3.6.1"
"source": "https://github.com/larastan/larastan/tree/v3.7.1"
},
"funding": [
{
@@ -10823,7 +10823,7 @@
"type": "github"
}
],
"time": "2025-08-25T07:24:56+00:00"
"time": "2025-09-10T19:42:11+00:00"
},
{
"name": "laravel-json-api/testing",
@@ -11332,16 +11332,16 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.22",
"version": "2.1.25",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4"
"reference": "4087d28bd252895874e174d65e26b2c202ed893a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/41600c8379eb5aee63e9413fe9e97273e25d57e4",
"reference": "41600c8379eb5aee63e9413fe9e97273e25d57e4",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/4087d28bd252895874e174d65e26b2c202ed893a",
"reference": "4087d28bd252895874e174d65e26b2c202ed893a",
"shasum": ""
},
"require": {
@@ -11386,7 +11386,7 @@
"type": "github"
}
],
"time": "2025-08-04T19:17:37+00:00"
"time": "2025-09-12T14:26:42+00:00"
},
{
"name": "phpstan/phpstan-deprecation-rules",
@@ -11485,16 +11485,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "12.3.6",
"version": "12.3.7",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "da2cdaff87220fa641e7652364281b736e4347e0"
"reference": "bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/da2cdaff87220fa641e7652364281b736e4347e0",
"reference": "da2cdaff87220fa641e7652364281b736e4347e0",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9",
"reference": "bbede0f5593dad37af3be6a6f8e6ae1885e8a0a9",
"shasum": ""
},
"require": {
@@ -11550,7 +11550,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.6"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.7"
},
"funding": [
{
@@ -11570,7 +11570,7 @@
"type": "tidelift"
}
],
"time": "2025-09-02T05:23:14+00:00"
"time": "2025-09-10T09:59:06+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -11819,16 +11819,16 @@
},
{
"name": "phpunit/phpunit",
"version": "12.3.8",
"version": "12.3.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "9d68c1b41fc21aac106c71cde4669fe7b99fca10"
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9d68c1b41fc21aac106c71cde4669fe7b99fca10",
"reference": "9d68c1b41fc21aac106c71cde4669fe7b99fca10",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0d401d0df2e3c1703be425ecdc2d04f5c095938d",
"reference": "0d401d0df2e3c1703be425ecdc2d04f5c095938d",
"shasum": ""
},
"require": {
@@ -11842,7 +11842,7 @@
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.3",
"phpunit/php-code-coverage": "^12.3.6",
"phpunit/php-code-coverage": "^12.3.7",
"phpunit/php-file-iterator": "^6.0.0",
"phpunit/php-invoker": "^6.0.0",
"phpunit/php-text-template": "^5.0.0",
@@ -11896,7 +11896,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.8"
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.10"
},
"funding": [
{
@@ -11920,20 +11920,20 @@
"type": "tidelift"
}
],
"time": "2025-09-03T06:25:17+00:00"
"time": "2025-09-11T10:35:19+00:00"
},
{
"name": "rector/rector",
"version": "2.1.6",
"version": "2.1.7",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "729aabc0ec66e700ef164e26454a1357f222a2f3"
"reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/729aabc0ec66e700ef164e26454a1357f222a2f3",
"reference": "729aabc0ec66e700ef164e26454a1357f222a2f3",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/c34cc07c4698f007a20dc5c99ff820089ae413ce",
"reference": "c34cc07c4698f007a20dc5c99ff820089ae413ce",
"shasum": ""
},
"require": {
@@ -11972,7 +11972,7 @@
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.1.6"
"source": "https://github.com/rectorphp/rector/tree/2.1.7"
},
"funding": [
{
@@ -11980,20 +11980,20 @@
"type": "github"
}
],
"time": "2025-09-05T15:43:08+00:00"
"time": "2025-09-10T11:13:58+00:00"
},
{
"name": "sebastian/cli-parser",
"version": "4.0.0",
"version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c"
"reference": "8fd93be538992d556aaa45c74570129448a42084"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/6d584c727d9114bcdc14c86711cd1cad51778e7c",
"reference": "6d584c727d9114bcdc14c86711cd1cad51778e7c",
"url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/8fd93be538992d556aaa45c74570129448a42084",
"reference": "8fd93be538992d556aaa45c74570129448a42084",
"shasum": ""
},
"require": {
@@ -12005,7 +12005,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "4.0-dev"
"dev-main": "4.1-dev"
}
},
"autoload": {
@@ -12029,15 +12029,27 @@
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
"security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.0.0"
"source": "https://github.com/sebastianbergmann/cli-parser/tree/4.1.0"
},
"funding": [
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
},
{
"url": "https://liberapay.com/sebastianbergmann",
"type": "liberapay"
},
{
"url": "https://thanks.dev/u/gh/sebastianbergmann",
"type": "thanks_dev"
},
{
"url": "https://tidelift.com/funding/github/packagist/sebastian/cli-parser",
"type": "tidelift"
}
],
"time": "2025-02-07T04:53:50+00:00"
"time": "2025-09-13T14:16:18+00:00"
},
{
"name": "sebastian/comparator",

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-09-08',
'build_time' => 1757313229,
'version' => '6.4.0',
'build_time' => 1757781366,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 26,

89
package-lock.json generated
View File

@@ -2207,9 +2207,9 @@
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.30",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
"version": "0.3.31",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
"integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3159,9 +3159,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.3.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz",
"integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==",
"version": "24.3.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.3.tgz",
"integrity": "sha512-GKBNHjoNw3Kra1Qg5UXttsY5kiWMEfoHq2TmXb+b1rcm6N7B3wTrFYIf/oSZ1xNQ+hVVijgLkiDZh7jRRsh+Gw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3949,9 +3949,9 @@
}
},
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz",
"integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4060,6 +4060,16 @@
],
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.3.tgz",
"integrity": "sha512-mcE+Wr2CAhHNWxXN/DdTI+n4gsPc5QpXpWnyCQWiQYIYZX+ZMJ8juXZgjRa/0/YPJo/NSsgW15/YgmI4nbysYw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.js"
}
},
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
@@ -4337,9 +4347,9 @@
}
},
"node_modules/browserslist": {
"version": "4.25.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz",
"integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==",
"version": "4.26.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.0.tgz",
"integrity": "sha512-P9go2WrP9FiPwLv3zqRD/Uoxo0RSHjzFCiQz7d4vbmwNqQFo9T9WCeP/Qn5EbcKQY6DBbkxEXNcpJOmncNrb7A==",
"dev": true,
"funding": [
{
@@ -4357,9 +4367,10 @@
],
"license": "MIT",
"dependencies": {
"caniuse-lite": "^1.0.30001737",
"electron-to-chromium": "^1.5.211",
"node-releases": "^2.0.19",
"baseline-browser-mapping": "^2.8.2",
"caniuse-lite": "^1.0.30001741",
"electron-to-chromium": "^1.5.218",
"node-releases": "^2.0.21",
"update-browserslist-db": "^1.1.3"
},
"bin": {
@@ -5711,9 +5722,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.214",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.214.tgz",
"integrity": "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q==",
"version": "1.5.218",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.218.tgz",
"integrity": "sha512-uwwdN0TUHs8u6iRgN8vKeWZMRll4gBkz+QMqdS7DDe49uiK68/UX92lFb61oiFPrpYZNeZIqa4bA7O6Aiasnzg==",
"dev": true,
"license": "ISC"
},
@@ -7969,9 +7980,9 @@
}
},
"node_modules/magic-string": {
"version": "0.30.18",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz",
"integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==",
"version": "0.30.19",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
"integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -8439,9 +8450,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.20.tgz",
"integrity": "sha512-7gK6zSXEH6neM212JgfYFXe+GmZQM+fia5SsusuBIUgnPheLFBmIPhtFoAQRj8/7wASYQnbDlHPVwY0BefoFgA==",
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz",
"integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==",
"dev": true,
"license": "MIT"
},
@@ -9923,9 +9934,9 @@
"license": "MIT"
},
"node_modules/regenerate-unicode-properties": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz",
"integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==",
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
"integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9936,18 +9947,18 @@
}
},
"node_modules/regexpu-core": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz",
"integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.3.1.tgz",
"integrity": "sha512-DzcswPr252wEr7Qz8AyAVbfyBDKLoYp6eRA1We2Fa9qirRFSdtkP5sHr3yglDKy2BbA0fd2T+j/CUSKes3FeVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"regenerate": "^1.4.2",
"regenerate-unicode-properties": "^10.2.0",
"regenerate-unicode-properties": "^10.2.2",
"regjsgen": "^0.8.0",
"regjsparser": "^0.12.0",
"unicode-match-property-ecmascript": "^2.0.0",
"unicode-match-property-value-ecmascript": "^2.1.0"
"unicode-match-property-value-ecmascript": "^2.2.1"
},
"engines": {
"node": ">=4"
@@ -11377,9 +11388,9 @@
}
},
"node_modules/unicode-match-property-value-ecmascript": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz",
"integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==",
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
"integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -11543,9 +11554,9 @@
}
},
"node_modules/vite": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz",
"integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==",
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz",
"integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11554,7 +11565,7 @@
"picomatch": "^4.0.3",
"postcss": "^8.5.6",
"rollup": "^4.43.0",
"tinyglobby": "^0.2.14"
"tinyglobby": "^0.2.15"
},
"bin": {
"vite": "bin/vite.js"

View File

@@ -87,11 +87,16 @@ let show = function () {
if (this.entries.hasOwnProperty(i)) {
const currencyCode = this.entries[i].currency_code;
const foreignCurrencyCode = this.entries[i].foreign_currency_code;
const primaryCurrencyCode = this.entries[i].primary_currency_code;
if (undefined === this.amounts[currencyCode]) {
this.amounts[currencyCode] = 0;
this.amounts[currencyCode] += parseFloat(this.entries[i].amount);
}
if (undefined === this.amounts[primaryCurrencyCode]) {
this.amounts[primaryCurrencyCode] = 0;
this.amounts[primaryCurrencyCode] += parseFloat(this.entries[i].pc_amount);
}
if (null !== foreignCurrencyCode && '' !== foreignCurrencyCode && undefined === this.amounts[foreignCurrencyCode]) {
this.amounts[foreignCurrencyCode] = 0;
this.amounts[foreignCurrencyCode] += parseFloat(this.entries[i].foreign_amount);

View File

@@ -17,23 +17,23 @@
<tbody>
<tr>
<th style="width:10%;">
<template x-if="'Withdrawal' === groupProperties.transactionType">
<template x-if="'withdrawal' === groupProperties.transactionType">
<em class="fa fa-solid fa-arrow-left"
:title="groupProperties.transactionTypeTranslated"></em>
</template>
<template x-if="'Deposit' === groupProperties.transactionType">
<template x-if="'deposit' === groupProperties.transactionType">
<em class="fa-solid fa-arrow-right"
:title="groupProperties.transactionTypeTranslated"></em>
</template>
<template x-if="'Transfer' === groupProperties.transactionType">
<template x-if="'transfer' === groupProperties.transactionType">
<em class="fa-solid fa-rotate"
:title="groupProperties.transactionTypeTranslated"></em>
</template>
<template
x-if="'Transfer' !== groupProperties.transactionType && 'Deposit' !== groupProperties.transactionType && 'Withdrawal' !== groupProperties.transactionType">
<span>TODO missing ICON</span>
x-if="'transfer' !== groupProperties.transactionType && 'deposit' !== groupProperties.transactionType && 'withdrawal' !== groupProperties.transactionType">
<span x-text="groupProperties.transactionType"></span>
</template>
</th>
<td><span class="group_title" :data-group="groupProperties.id" x-text="groupProperties.title"></span></td>
@@ -53,6 +53,18 @@
<a class="btn btn-danger" :href="'./transactions/delete/' + groupProperties.id">
<em class="fa-solid fa-trash"></em> {{ __('firefly.delete') }}
</a>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
{{ __('firefly.actions') }}
</button>
<ul class="dropdown-menu">
<li x-show="'withdrawal' !== groupProperties.transactionType"><a class="dropdown-item" href="{{ route('transactions.convert.index', ['withdrawal', $transactionGroup['id']]) }}">{{ __('firefly.convert_to_withdrawal') }}</a></li>
<li x-show="'deposit' !== groupProperties.transactionType"><a class="dropdown-item" href="{{ route('transactions.convert.index', ['deposit', $transactionGroup['id']]) }}">{{ __('firefly.convert_to_deposit') }}</a></li>
<li x-show="'transfer' !== groupProperties.transactionType"><a class="dropdown-item" href="{{ route('transactions.convert.index', ['transfer', $transactionGroup['id']]) }}">{{ __('firefly.convert_to_transfer') }}</a></li>
<li><a class="dropdown-item" href="#">{{ __('firefly.clone') }}</a></li>
<li><a class="dropdown-item" href="#">{{ __('firefly.clone_and_edit') }}</a></li>
</ul>
</div>
</div>
</div>
</div>
@@ -70,25 +82,25 @@
<em class="fa-solid fa-money-bill-wave" title="{{ __('firefly.amount') }}"></em>
</th>
<td>
<template x-if="'Withdrawal' === groupProperties.transactionType">
<template x-if="'withdrawal' === groupProperties.transactionType">
<template x-for="(amount, code) in amounts">
<span class="text-danger" x-text="formatMoney(amount*-1, code)"></span>
</template>
</template>
<template x-if="'Deposit' === groupProperties.transactionType">
<template x-if="'deposit' === groupProperties.transactionType">
<template x-for="(amount, code) in amounts">
<span class="text-success" x-text="formatMoney(amount, code)"></span>
</template>
</template>
<template x-if="'Transfer' === groupProperties.transactionType">
<template x-if="'transfer' === groupProperties.transactionType">
<template x-for="(amount, code) in amounts">
<span class="text-info" x-text="formatMoney(amount, code)"></span>
</template>
</template>
<template
x-if="'Transfer' !== groupProperties.transactionType && 'Deposit' !== groupProperties.transactionType && 'Withdrawal' !== groupProperties.transactionType">
x-if="'transfer' !== groupProperties.transactionType && 'deposit' !== groupProperties.transactionType && 'withdrawal' !== groupProperties.transactionType">
<span>TODO PARSE MISSING AMOUNT</span>
</template>
</td>
@@ -164,33 +176,33 @@
:title="entry.source_account.name"
x-text="entry.source_account.name"></a>
&rarr;
<template x-if="'Withdrawal' === groupProperties.transactionType">
<template x-if="'withdrawal' === groupProperties.transactionType">
<span class="text-danger"
x-text="formatMoney(entry.amount*-1, entry.currency_code)"></span>
</template>
<template x-if="'Deposit' === groupProperties.transactionType">
<template x-if="'deposit' === groupProperties.transactionType">
<span class="text-success"
x-text="formatMoney(entry.amount, entry.currency_code)"></span>
</template>
<template x-if="'Transfer' === groupProperties.transactionType">
<template x-if="'transfer' === groupProperties.transactionType">
<span class="text-info"
x-text="formatMoney(entry.amount, entry.currency_code)"></span>
</template>
<template
x-if="null !== entry.foreign_currency_code && 'Withdrawal' === groupProperties.transactionType">
x-if="null !== entry.foreign_currency_code && '' !== entry.foreign_currency_code && 'withdrawal' === groupProperties.transactionType">
<span class="text-muted"
x-text="formatMoney(entry.foreign_amount*-1, entry.foreign_currency_code)"></span>
x-text="formatMoney(entry.foreign_amount*-1, entry.foreign_currency_code) + 'y'"></span>
</template>
<template
x-if="null !== entry.foreign_currency_code && 'Withdrawal' !== groupProperties.transactionType">
x-if="null !== entry.foreign_currency_code && '' !== entry.foreign_currency_code && 'withdrawal' !== groupProperties.transactionType">
<span class="text-muted"
x-text="formatMoney(entry.foreign_amount, entry.foreign_currency_code)"></span>
x-text="formatMoney(entry.foreign_amount, entry.foreign_currency_code) + 'x'"></span>
</template>
<template
x-if="'Transfer' !== groupProperties.transactionType && 'Deposit' !== groupProperties.transactionType && 'Withdrawal' !== groupProperties.transactionType">
x-if="'transfer' !== groupProperties.transactionType && 'deposit' !== groupProperties.transactionType && 'withdrawal' !== groupProperties.transactionType">
<span>TODO PARSE MISSING AMOUNT</span>
</template>
&rarr;