mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-18 02:03:40 +00:00
Compare commits
41 Commits
develop-20
...
v6.4.0
Author | SHA1 | Date | |
---|---|---|---|
|
3adf3d2fdb | ||
|
0923d5a23e | ||
|
76b8cdc385 | ||
|
0a27da83eb | ||
|
17d6e2be85 | ||
|
7381f3eba9 | ||
|
7f2ef1b8e1 | ||
|
9dccae2402 | ||
|
073afd5b6e | ||
|
4167d85be2 | ||
|
ee28d1307d | ||
|
7562215666 | ||
|
0203b918e9 | ||
|
ae7c664418 | ||
|
f13e0991fb | ||
|
deae94b658 | ||
|
c38c752520 | ||
|
28e7df2527 | ||
|
cb0b42e44b | ||
|
a3674c4dfe | ||
|
27480561ee | ||
|
6ea7152423 | ||
|
dab95f7a86 | ||
|
adf34805a8 | ||
|
93e926465f | ||
|
5b0be91f93 | ||
|
01e7b604da | ||
|
974a550d22 | ||
|
58d175444b | ||
|
29d8861e96 | ||
|
eb832c750f | ||
|
134770644a | ||
|
a9f21c9371 | ||
|
781947beeb | ||
|
9760cd2f97 | ||
|
d317e9ec32 | ||
|
534f7fcadb | ||
|
fb3f7a1d4b | ||
|
bf2c3e3561 | ||
|
0990b1f0b4 | ||
|
c1922670c8 |
12
.ci/php-cs-fixer/composer.lock
generated
12
.ci/php-cs-fixer/composer.lock
generated
@@ -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",
|
||||
|
@@ -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
|
||||
|
||||
|
4
.github/workflows/cleanup.yml
vendored
4
.github/workflows/cleanup.yml
vendored
@@ -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: |
|
||||
|
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -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"
|
||||
|
2
.github/workflows/stale.yml
vendored
2
.github/workflows/stale.yml
vendored
@@ -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: |
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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();
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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)
|
||||
;
|
||||
|
||||
|
@@ -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']) {
|
||||
|
@@ -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.')) {
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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]));
|
||||
}
|
||||
|
@@ -57,8 +57,6 @@ class CorrectsPiggyBanks extends Command
|
||||
$event->transaction_journal_id = null;
|
||||
$event->save();
|
||||
++$count;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (0 !== $count) {
|
||||
|
@@ -71,7 +71,6 @@ class RestoresOAuthKeys extends Command
|
||||
$this->storeKeysInDB();
|
||||
$this->friendlyInfo('Stored OAuth keys in database.');
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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]));
|
||||
|
||||
|
@@ -157,7 +157,6 @@ class UpgradesLiabilitiesEight extends Command
|
||||
$service = new TransactionGroupDestroyService();
|
||||
$service->destroy($group);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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();
|
||||
|
@@ -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__));
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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')
|
||||
|
@@ -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]
|
||||
|
@@ -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])
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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 = [];
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
|
@@ -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.
|
||||
|
@@ -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];
|
||||
}
|
||||
|
@@ -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));
|
||||
}
|
||||
|
@@ -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()
|
||||
;
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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'))
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -227,7 +227,6 @@ class CreditRecalculateService
|
||||
$source->save();
|
||||
$dest->save();
|
||||
|
||||
return;
|
||||
}
|
||||
// Log::debug('Opening balance is valid');
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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;
|
||||
|
@@ -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) {
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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,
|
||||
];
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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';
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
18
changelog.md
18
changelog.md
@@ -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
112
composer.lock
generated
@@ -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",
|
||||
|
@@ -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
89
package-lock.json
generated
@@ -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"
|
||||
|
@@ -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);
|
||||
|
@@ -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>
|
||||
→
|
||||
<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>
|
||||
→
|
||||
|
Reference in New Issue
Block a user