mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-03-06 16:01:29 +00:00
Compare commits
1 Commits
develop-20
...
JC5-patch-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4405b2ac8f |
10
.env.example
10
.env.example
@@ -14,15 +14,7 @@ SITE_OWNER=mail@example.com
|
||||
# Change it to a string of exactly 32 chars or use something like `php artisan key:generate` to generate it.
|
||||
# If you use Docker or similar, you can set this variable from a file by using APP_KEY_FILE
|
||||
#
|
||||
# Try to avoid special characters like #, < and > in your app key. This string does not need full entropy
|
||||
# When in doubt, follow the link below and pick one.
|
||||
#
|
||||
# https://www.random.org/strings/?num=5&len=32&digits=on&upperalpha=on&loweralpha=on&unique=on&format=html&rnd=new
|
||||
#
|
||||
# If you are a fancy linux nerd like me, use this command:
|
||||
#
|
||||
# head /dev/urandom | LC_ALL=C tr -dc 'A-Za-z0-9' | head -c 32 && echo
|
||||
#
|
||||
# Avoid the "#" character in your APP_KEY, it may break things.
|
||||
#
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ github.event.inputs.phpversion }}
|
||||
php-version: ${{ github.event.inputs.phpversion || '8.4' }}
|
||||
extensions: mbstring, intl, zip, bcmath
|
||||
- name: Switch and pull
|
||||
run: |
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace FireflyIII\Console\Commands\Correction;
|
||||
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||
use FireflyIII\Support\System\OAuthKeys;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class RestoresOAuthKeys extends Command
|
||||
{
|
||||
@@ -41,9 +40,7 @@ class RestoresOAuthKeys extends Command
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
Log::debug('Restore OAuth Keys command.');
|
||||
$this->restoreOAuthKeys();
|
||||
Log::debug('Done with OAuth Keys command.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
35
app/Events/Model/Account/Updated.php
Normal file
35
app/Events/Model/Account/Updated.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Updated.php
|
||||
* Copyright (c) 2024 james@firefly-iii.org.
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\Account;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class Updated
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public Account $account) {}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* SubscriptionNeedsExtensionOrRenewal.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* WarnUserAboutBill.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -22,15 +24,18 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\Subscription;
|
||||
namespace FireflyIII\Events\Model\Bill;
|
||||
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\Bill;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionNeedsExtensionOrRenewal extends Event
|
||||
/**
|
||||
* Class WarnUserAboutBill.
|
||||
*/
|
||||
class WarnUserAboutBill extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public Bill $subscription, public string $field, public int $diff) {}
|
||||
public function __construct(public Bill $bill, public string $field, public int $diff) {}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* SubscriptionIsOverdueForPayment.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* WarnUserAboutOverdueSubscriptions.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -21,15 +21,18 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Events\Model\Subscription;
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\Bill;
|
||||
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionsAreOverdueForPayment extends Event
|
||||
class WarnUserAboutOverdueSubscriptions extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public User $user, public array $overdue) {}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ use Illuminate\Support\Facades\Log;
|
||||
/**
|
||||
* Class ChangedAmount
|
||||
*/
|
||||
class PiggyBankAmountIsChanged extends Event
|
||||
class ChangedAmount extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* PiggyBankNameIsChanged.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* ChangedName.php
|
||||
* Copyright (c) 2025 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -21,16 +21,15 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Event;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Needs to be an event because system needs old value as well as the new value.
|
||||
*/
|
||||
class PiggyBankNameIsChanged extends Event
|
||||
class ChangedName extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
@@ -23,7 +23,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankAmountIsChanged;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\ObjectGroup;
|
||||
@@ -305,7 +305,7 @@ class PiggyBankFactory
|
||||
if (0 !== bccomp($oldSavedAmount, $newSavedAmount)) {
|
||||
Log::debug('Amount changed, will create event for it.');
|
||||
// create event for difference.
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, bcsub($newSavedAmount, $oldSavedAmount), null, null));
|
||||
event(new ChangedAmount($piggyBank, bcsub($newSavedAmount, $oldSavedAmount), null, null));
|
||||
}
|
||||
}
|
||||
if (0 === count($toBeLinked)) {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* NotifiesAboutOverdueSubscription.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* BillEventHandler.php
|
||||
* Copyright (c) 2022 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -21,27 +20,35 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\Subscription;
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\Model\Subscription\SubscriptionsAreOverdueForPayment;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Notifications\User\BillReminder;
|
||||
use FireflyIII\Notifications\User\SubscriptionsOverdueReminder;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class NotifiesAboutOverdueSubscriptions implements ShouldQueue
|
||||
use function Safe\json_encode;
|
||||
|
||||
/**
|
||||
* Class BillEventHandler
|
||||
*/
|
||||
class BillEventHandler
|
||||
{
|
||||
public function handle(SubscriptionsAreOverdueForPayment $event): void
|
||||
public function warnAboutOverdueSubscriptions(WarnUserAboutOverdueSubscriptions $event): void
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
// make sure user does not get the warning twice.
|
||||
$overdue = $event->overdue;
|
||||
$user = $event->user;
|
||||
$toBeWarned = [];
|
||||
Log::debug(sprintf('%d subscriptions to warn about.', count($overdue)));
|
||||
Log::debug(sprintf('%d bills to warn about.', count($overdue)));
|
||||
foreach ($overdue as $item) {
|
||||
/** @var Bill $bill */
|
||||
$bill = $item['bill'];
|
||||
@@ -55,12 +62,12 @@ class NotifiesAboutOverdueSubscriptions implements ShouldQueue
|
||||
$toBeWarned[] = $item;
|
||||
}
|
||||
unset($bill);
|
||||
Log::debug(sprintf('Now %d subscription(s) to warn about.', count($toBeWarned)));
|
||||
Log::debug(sprintf('Now %d bills to warn about.', count($toBeWarned)));
|
||||
|
||||
/** @var bool $sendNotification */
|
||||
$sendNotification = Preferences::getForUser($user, 'notification_bill_reminder', true)->data;
|
||||
if (false === $sendNotification) {
|
||||
Log::debug('User has disabled subscription reminders.');
|
||||
Log::debug('User has disabled bill reminders.');
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -98,4 +105,39 @@ class NotifiesAboutOverdueSubscriptions implements ShouldQueue
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function warnAboutBill(WarnUserAboutBill $event): void
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
|
||||
$bill = $event->bill;
|
||||
|
||||
/** @var bool $preference */
|
||||
$preference = Preferences::getForUser($bill->user, 'notification_bill_reminder', true)->data;
|
||||
|
||||
if (true === $preference) {
|
||||
Log::debug('Bill reminder is true!');
|
||||
|
||||
try {
|
||||
Notification::send($bill->user, new BillReminder($bill, $event->field, $event->diff));
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
if (str_contains($message, 'Bcc')) {
|
||||
Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (str_contains($message, 'RFC 2822')) {
|
||||
Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('User has disabled bill reminders.');
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* CreatesPiggyBankEventForChangedAmount.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* PiggyBankEventHandler.php
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -21,17 +20,43 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\PiggyBank;
|
||||
declare(strict_types=1);
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankAmountIsChanged;
|
||||
namespace FireflyIII\Handlers\Events\Model;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CreatesPiggyBankEventForChangedAmount implements ShouldQueue
|
||||
/**
|
||||
* Class PiggyBankEventHandler
|
||||
*/
|
||||
class PiggyBankEventHandler
|
||||
{
|
||||
public function handle(PiggyBankAmountIsChanged $event): void
|
||||
public function changedPiggyBankName(ChangedName $event): void
|
||||
{
|
||||
// loop all accounts, collect all user's rules.
|
||||
/** @var Account $account */
|
||||
foreach ($event->piggyBank->accounts as $account) {
|
||||
/** @var Rule $rule */
|
||||
foreach ($account->user->rules as $rule) {
|
||||
/** @var RuleAction $ruleAction */
|
||||
foreach ($rule->ruleActions()->where('action_type', 'update_piggy')->get() as $ruleAction) {
|
||||
if ($event->oldName === $ruleAction->action_value) {
|
||||
$ruleAction->action_value = $event->newName;
|
||||
$ruleAction->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function changePiggyAmount(ChangedAmount $event): void
|
||||
{
|
||||
// find journal if group is present.
|
||||
$journal = $event->transactionJournal;
|
||||
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* NotifiesUserAboutFailedRuleAction.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
* RuleHandler.php
|
||||
* Copyright (c) 2023 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
@@ -21,20 +20,24 @@ declare(strict_types=1);
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\Rule;
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events\Model;
|
||||
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
|
||||
use FireflyIII\Notifications\User\RuleActionFailed;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class NotifiesUserAboutFailedRuleAction implements ShouldQueue
|
||||
/**
|
||||
* Class RuleHandler
|
||||
*/
|
||||
class RuleHandler
|
||||
{
|
||||
public function handle(RuleActionFailedOnArray|RuleActionFailedOnObject $event): void
|
||||
public function ruleActionFailedOnArray(RuleActionFailedOnArray $event): void
|
||||
{
|
||||
$ruleAction = $event->ruleAction;
|
||||
$rule = $ruleAction->rule;
|
||||
@@ -49,12 +52,9 @@ class NotifiesUserAboutFailedRuleAction implements ShouldQueue
|
||||
$error = $event->error;
|
||||
$user = $ruleAction->rule->user;
|
||||
|
||||
$groupId = is_array($journal) ? $journal['transaction_group_id'] : $journal->transaction_group_id;
|
||||
$groupTitle = is_array($journal) ? ($journal['description'] ?? '') : ($journal->description ?? '');
|
||||
|
||||
|
||||
$mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $groupId, 'error' => $error]);
|
||||
$groupLink = route('transactions.show', [$groupId]);
|
||||
$mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal['transaction_group_id'], 'error' => $error]);
|
||||
$groupTitle = $journal['description'] ?? '';
|
||||
$groupLink = route('transactions.show', [$journal['transaction_group_id']]);
|
||||
$ruleTitle = $rule->title;
|
||||
$ruleLink = route('rules.edit', [$rule->id]);
|
||||
$params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink];
|
||||
@@ -65,4 +65,33 @@ class NotifiesUserAboutFailedRuleAction implements ShouldQueue
|
||||
Log::error(sprintf('[a] Error sending notification that the rule action failed: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public function ruleActionFailedOnObject(RuleActionFailedOnObject $event): void
|
||||
{
|
||||
$ruleAction = $event->ruleAction;
|
||||
$rule = $ruleAction->rule;
|
||||
|
||||
/** @var bool $preference */
|
||||
$preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data;
|
||||
if (false === $preference) {
|
||||
return;
|
||||
}
|
||||
Log::debug('Now in ruleActionFailedOnObject');
|
||||
$journal = $event->journal;
|
||||
$error = $event->error;
|
||||
$user = $ruleAction->rule->user;
|
||||
|
||||
$mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal->transaction_group_id, 'error' => $error]);
|
||||
$groupTitle = $journal->description ?? '';
|
||||
$groupLink = route('transactions.show', [$journal->transaction_group_id]);
|
||||
$ruleTitle = $rule->title;
|
||||
$ruleLink = route('rules.edit', [$rule->id]);
|
||||
$params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink];
|
||||
|
||||
try {
|
||||
Notification::send($user, new RuleActionFailed($params));
|
||||
} catch (ClientException $e) {
|
||||
Log::error(sprintf('[b] Error sending notification that the rule action failed: %s', $e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Jobs;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\Model\Subscription\SubscriptionNeedsExtensionOrRenewal;
|
||||
use FireflyIII\Events\Model\Subscription\SubscriptionsAreOverdueForPayment;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
|
||||
@@ -143,7 +143,7 @@ class WarnAboutBills implements ShouldQueue
|
||||
{
|
||||
$diff = $this->getDiff($bill, $field);
|
||||
Log::debug('Will now send warning!');
|
||||
event(new SubscriptionNeedsExtensionOrRenewal($bill, $field, $diff));
|
||||
event(new WarnUserAboutBill($bill, $field, $diff));
|
||||
}
|
||||
|
||||
public function setDate(Carbon $date): void
|
||||
@@ -197,8 +197,8 @@ class WarnAboutBills implements ShouldQueue
|
||||
private function sendOverdueAlerts(User $user, array $overdue): void
|
||||
{
|
||||
if (count($overdue) > 0) {
|
||||
Log::debug(sprintf('Will now send warning about overdue subscription(s) for user #%d.', $user->id));
|
||||
event(new SubscriptionsAreOverdueForPayment($user, $overdue));
|
||||
Log::debug(sprintf('Will now send warning about overdue bill for user #%d.', $user->id));
|
||||
event(new WarnUserAboutOverdueSubscriptions($user, $overdue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* UpdatesRulesForChangedPiggyBankName.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankNameIsChanged;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Rule;
|
||||
use FireflyIII\Models\RuleAction;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
|
||||
class UpdatesRulesForChangedPiggyBankName implements ShouldQueue
|
||||
{
|
||||
public function handle(PiggyBankNameIsChanged $event): void
|
||||
{
|
||||
// loop all accounts, collect all user's rules.
|
||||
/** @var Account $account */
|
||||
foreach ($event->piggyBank->accounts as $account) {
|
||||
/** @var Rule $rule */
|
||||
foreach ($account->user->rules as $rule) {
|
||||
/** @var RuleAction $ruleAction */
|
||||
foreach ($rule->ruleActions()->where('action_type', 'update_piggy')->get() as $ruleAction) {
|
||||
if ($event->oldName === $ruleAction->action_value) {
|
||||
$ruleAction->action_value = $event->newName;
|
||||
$ruleAction->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
* NotifiesAboutExtensionOrRenewal.php
|
||||
* Copyright (c) 2026 james@firefly-iii.org
|
||||
*
|
||||
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Listeners\Model\Subscription;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\Model\Subscription\SubscriptionNeedsExtensionOrRenewal;
|
||||
use FireflyIII\Notifications\User\BillReminder;
|
||||
use FireflyIII\Support\Facades\Preferences;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class NotifiesAboutExtensionOrRenewal implements ShouldQueue
|
||||
{
|
||||
public function handle(SubscriptionNeedsExtensionOrRenewal $event): void
|
||||
{
|
||||
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||
$subscription = $event->subscription;
|
||||
|
||||
/** @var bool $preference */
|
||||
$preference = Preferences::getForUser($subscription->user, 'notification_bill_reminder', true)->data;
|
||||
|
||||
if (true === $preference) {
|
||||
Log::debug('Subscription reminder is true!');
|
||||
|
||||
try {
|
||||
Notification::send($subscription->user, new BillReminder($subscription, $event->field, $event->diff));
|
||||
} catch (Exception $e) {
|
||||
$message = $e->getMessage();
|
||||
if (str_contains($message, 'Bcc')) {
|
||||
Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
|
||||
|
||||
return;
|
||||
}
|
||||
if (str_contains($message, 'RFC 2822')) {
|
||||
Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
|
||||
|
||||
return;
|
||||
}
|
||||
Log::error($e->getMessage());
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
Log::debug('User has disabled subscription reminders.');
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,12 @@ use FireflyIII\Events\ActuallyLoggedIn;
|
||||
use FireflyIII\Events\Admin\InvitationCreated;
|
||||
use FireflyIII\Events\DestroyedTransactionGroup;
|
||||
use FireflyIII\Events\DetectedNewIPAddress;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
|
||||
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
|
||||
use FireflyIII\Events\Model\TransactionGroup\TriggeredStoredTransactionGroup;
|
||||
use FireflyIII\Events\NewVersionAvailable;
|
||||
use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
|
||||
@@ -67,145 +73,145 @@ class EventServiceProvider extends ServiceProvider
|
||||
protected $listen
|
||||
= [
|
||||
// is a User related event.
|
||||
RegisteredUser::class => [
|
||||
RegisteredUser::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationMail',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendAdminRegistrationNotification',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@attachUserRole',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@createGroupMembership',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@createExchangeRates',
|
||||
],
|
||||
UserAttemptedLogin::class => [
|
||||
UserAttemptedLogin::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendLoginAttemptNotification',
|
||||
],
|
||||
// is a User related event.
|
||||
Login::class => [
|
||||
Login::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@checkSingleUserIsAdmin',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@demoUserBackToEnglish',
|
||||
],
|
||||
ActuallyLoggedIn::class => [
|
||||
ActuallyLoggedIn::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@storeUserIPAddress',
|
||||
],
|
||||
DetectedNewIPAddress::class => [
|
||||
DetectedNewIPAddress::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@notifyNewIPAddress',
|
||||
],
|
||||
RequestedVersionCheckStatus::class => [
|
||||
RequestedVersionCheckStatus::class => [
|
||||
'FireflyIII\Handlers\Events\VersionCheckEventHandler@checkForUpdates',
|
||||
],
|
||||
RequestedReportOnJournals::class => [
|
||||
RequestedReportOnJournals::class => [
|
||||
'FireflyIII\Handlers\Events\AutomationHandler@reportJournals',
|
||||
],
|
||||
|
||||
// is a User related event.
|
||||
RequestedNewPassword::class => [
|
||||
RequestedNewPassword::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendNewPassword',
|
||||
],
|
||||
UserTestNotificationChannel::class => [
|
||||
UserTestNotificationChannel::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendTestNotification',
|
||||
],
|
||||
// is a User related event.
|
||||
UserChangedEmail::class => [
|
||||
UserChangedEmail::class => [
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendEmailChangeConfirmMail',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendEmailChangeUndoMail',
|
||||
],
|
||||
// admin related
|
||||
OwnerTestNotificationChannel::class => [
|
||||
OwnerTestNotificationChannel::class => [
|
||||
'FireflyIII\Handlers\Events\AdminEventHandler@sendTestNotification',
|
||||
],
|
||||
NewVersionAvailable::class => [
|
||||
NewVersionAvailable::class => [
|
||||
'FireflyIII\Handlers\Events\AdminEventHandler@sendNewVersion',
|
||||
],
|
||||
InvitationCreated::class => [
|
||||
InvitationCreated::class => [
|
||||
'FireflyIII\Handlers\Events\AdminEventHandler@sendInvitationNotification',
|
||||
'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationInvite',
|
||||
],
|
||||
UnknownUserAttemptedLogin::class => [
|
||||
UnknownUserAttemptedLogin::class => [
|
||||
'FireflyIII\Handlers\Events\AdminEventHandler@sendLoginAttemptNotification',
|
||||
],
|
||||
|
||||
// is a Transaction Journal related event.
|
||||
StoredTransactionGroup::class => [
|
||||
StoredTransactionGroup::class => [
|
||||
'FireflyIII\Handlers\Events\StoredGroupEventHandler@runAllHandlers',
|
||||
],
|
||||
TriggeredStoredTransactionGroup::class => [
|
||||
TriggeredStoredTransactionGroup::class => [
|
||||
'FireflyIII\Handlers\Events\StoredGroupEventHandler@triggerRulesManually',
|
||||
],
|
||||
// is a Transaction Journal related event.
|
||||
UpdatedTransactionGroup::class => [
|
||||
UpdatedTransactionGroup::class => [
|
||||
'FireflyIII\Handlers\Events\UpdatedGroupEventHandler@runAllHandlers',
|
||||
],
|
||||
DestroyedTransactionGroup::class => [
|
||||
DestroyedTransactionGroup::class => [
|
||||
'FireflyIII\Handlers\Events\DestroyedGroupEventHandler@runAllHandlers',
|
||||
],
|
||||
// API related events:
|
||||
AccessTokenCreated::class => [
|
||||
AccessTokenCreated::class => [
|
||||
'FireflyIII\Handlers\Events\APIEventHandler@accessTokenCreated',
|
||||
],
|
||||
|
||||
// Webhook related event:
|
||||
RequestedSendWebhookMessages::class => [
|
||||
RequestedSendWebhookMessages::class => [
|
||||
'FireflyIII\Handlers\Events\WebhookEventHandler@sendWebhookMessages',
|
||||
],
|
||||
|
||||
// account related events:
|
||||
StoredAccount::class => [
|
||||
StoredAccount::class => [
|
||||
'FireflyIII\Handlers\Events\StoredAccountEventHandler@recalculateCredit',
|
||||
],
|
||||
UpdatedAccount::class => [
|
||||
UpdatedAccount::class => [
|
||||
'FireflyIII\Handlers\Events\UpdatedAccountEventHandler@recalculateCredit',
|
||||
],
|
||||
|
||||
// subscription related events:
|
||||
// SubscriptionNeedsExtensionOrRenewal::class => [
|
||||
// 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
|
||||
// ],
|
||||
// WarnUserAboutOverdueSubscriptions::class => [
|
||||
// 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutOverdueSubscriptions',
|
||||
// ],
|
||||
// bill related events:
|
||||
WarnUserAboutBill::class => [
|
||||
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
|
||||
],
|
||||
WarnUserAboutOverdueSubscriptions::class => [
|
||||
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutOverdueSubscriptions',
|
||||
],
|
||||
|
||||
// audit log events:
|
||||
TriggeredAuditLog::class => [
|
||||
TriggeredAuditLog::class => [
|
||||
'FireflyIII\Handlers\Events\AuditEventHandler@storeAuditEvent',
|
||||
],
|
||||
// piggy bank related events:
|
||||
// PiggyBankAmountIsChanged::class => [
|
||||
// 'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
||||
// ],
|
||||
// ChangedName::class => [
|
||||
// 'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||
// ],
|
||||
ChangedAmount::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
||||
],
|
||||
ChangedName::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||
],
|
||||
|
||||
// rule actions
|
||||
// RuleActionFailedOnArray::class => [
|
||||
// 'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray',
|
||||
// ],
|
||||
// RuleActionFailedOnObject::class => [
|
||||
// 'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnObject',
|
||||
// ],
|
||||
RuleActionFailedOnArray::class => [
|
||||
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray',
|
||||
],
|
||||
RuleActionFailedOnObject::class => [
|
||||
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnObject',
|
||||
],
|
||||
|
||||
// security related
|
||||
EnabledMFA::class => [
|
||||
EnabledMFA::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFAEnabledMail',
|
||||
],
|
||||
DisabledMFA::class => [
|
||||
DisabledMFA::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFADisabledMail',
|
||||
],
|
||||
MFANewBackupCodes::class => [
|
||||
MFANewBackupCodes::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendNewMFABackupCodesMail',
|
||||
],
|
||||
MFAUsedBackupCode::class => [
|
||||
MFAUsedBackupCode::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendUsedBackupCodeMail',
|
||||
],
|
||||
MFABackupFewLeft::class => [
|
||||
MFABackupFewLeft::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupFewLeftMail',
|
||||
],
|
||||
MFABackupNoLeft::class => [
|
||||
MFABackupNoLeft::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendBackupNoLeftMail',
|
||||
],
|
||||
MFAManyFailedAttempts::class => [
|
||||
MFAManyFailedAttempts::class => [
|
||||
'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFAFailedAttemptsMail',
|
||||
],
|
||||
// preferences
|
||||
UserGroupChangedPrimaryCurrency::class => [
|
||||
UserGroupChangedPrimaryCurrency::class => [
|
||||
'FireflyIII\Handlers\Events\PreferencesEventHandler@resetPrimaryCurrencyAmounts',
|
||||
],
|
||||
];
|
||||
|
||||
@@ -25,8 +25,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankAmountIsChanged;
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankNameIsChanged;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\PiggyBankFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -68,7 +68,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcsub((string)$currentAmount, $amount);
|
||||
$pivot->current_amount = bcsub((string) $currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
@@ -82,7 +82,7 @@ trait ModifiesPiggyBanks
|
||||
$pivot->save();
|
||||
|
||||
Log::debug('ChangedAmount: removeAmount [a]: Trigger change for negative amount.');
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, bcmul($amount, '-1'), $journal, null));
|
||||
event(new ChangedAmount($piggyBank, bcmul($amount, '-1'), $journal, null));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -91,7 +91,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcadd((string)$currentAmount, $amount);
|
||||
$pivot->current_amount = bcadd((string) $currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
@@ -105,7 +105,7 @@ trait ModifiesPiggyBanks
|
||||
$pivot->save();
|
||||
|
||||
Log::debug('ChangedAmount: addAmount [b]: Trigger change for positive amount.');
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, $amount, $journal, null));
|
||||
event(new ChangedAmount($piggyBank, $amount, $journal, null));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -123,13 +123,13 @@ trait ModifiesPiggyBanks
|
||||
|
||||
|
||||
if (0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||
$leftToSave = bcsub($piggyBank->target_amount, (string)$savedSoFar);
|
||||
$maxAmount = 1 === bccomp((string)$leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||
$leftToSave = bcsub($piggyBank->target_amount, (string) $savedSoFar);
|
||||
$maxAmount = 1 === bccomp((string) $leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
||||
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
||||
}
|
||||
|
||||
$compare = bccomp($amount, (string)$maxAmount);
|
||||
$compare = bccomp($amount, (string) $maxAmount);
|
||||
$result = $compare <= 0;
|
||||
|
||||
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
|
||||
@@ -141,7 +141,7 @@ trait ModifiesPiggyBanks
|
||||
{
|
||||
$savedSoFar = $this->getCurrentAmount($piggyBank, $account);
|
||||
|
||||
return bccomp($amount, (string)$savedSoFar) <= 0;
|
||||
return bccomp($amount, (string) $savedSoFar) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,11 +178,11 @@ trait ModifiesPiggyBanks
|
||||
|
||||
if (-1 === bccomp($difference, '0')) {
|
||||
Log::debug('ChangedAmount: addAmount [c]: Trigger change for negative amount.');
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, $difference, null, null));
|
||||
event(new ChangedAmount($piggyBank, $difference, null, null));
|
||||
}
|
||||
if (1 === bccomp($difference, '0')) {
|
||||
Log::debug('ChangedAmount: addAmount [d]: Trigger change for positive amount.');
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, $difference, null, null));
|
||||
event(new ChangedAmount($piggyBank, $difference, null, null));
|
||||
}
|
||||
|
||||
return $piggyBank;
|
||||
@@ -234,9 +234,9 @@ trait ModifiesPiggyBanks
|
||||
// if the piggy bank is now smaller than the sum of the money saved,
|
||||
// remove money from all accounts until the piggy bank is the right amount.
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank);
|
||||
if (1 === bccomp((string)$currentAmount, (string)$piggyBank->target_amount) && 0 !== bccomp((string)$piggyBank->target_amount, '0')) {
|
||||
if (1 === bccomp((string) $currentAmount, (string)$piggyBank->target_amount) && 0 !== bccomp((string)$piggyBank->target_amount, '0')) {
|
||||
Log::debug(sprintf('Current amount is %s, target amount is %s', $currentAmount, $piggyBank->target_amount));
|
||||
$difference = bcsub((string)$piggyBank->target_amount, (string)$currentAmount);
|
||||
$difference = bcsub((string)$piggyBank->target_amount, (string) $currentAmount);
|
||||
|
||||
// an amount will be removed, create "negative" event:
|
||||
// Log::debug(sprintf('ChangedAmount: is triggered with difference "%s"', $difference));
|
||||
@@ -283,7 +283,7 @@ trait ModifiesPiggyBanks
|
||||
private function updateProperties(PiggyBank $piggyBank, array $data): PiggyBank
|
||||
{
|
||||
if (array_key_exists('name', $data) && '' !== $data['name']) {
|
||||
event(new PiggyBankNameIsChanged($piggyBank, $piggyBank->name, $data['name']));
|
||||
event(new ChangedName($piggyBank, $piggyBank->name, $data['name']));
|
||||
$piggyBank->name = $data['name'];
|
||||
}
|
||||
if (array_key_exists('transaction_currency_id', $data) && is_int($data['transaction_currency_id'])) {
|
||||
|
||||
@@ -24,7 +24,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Events\Model\PiggyBank\PiggyBankAmountIsChanged;
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\PiggyBankFactory;
|
||||
use FireflyIII\Models\Account;
|
||||
@@ -448,7 +448,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
|
||||
$piggyBank->piggyBankEvents()->delete();
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
if (0 !== bccomp('0', (string) $account->pivot->current_amount)) {
|
||||
event(new PiggyBankAmountIsChanged($piggyBank, $account->pivot->current_amount, null, null));
|
||||
event(new ChangedAmount($piggyBank, $account->pivot->current_amount, null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ class UserRepository implements UserRepositoryInterface
|
||||
if (!$user instanceof User) {
|
||||
throw new FireflyException('User is not a User object.');
|
||||
}
|
||||
$now = now(config('app.timezone'));
|
||||
$now = today(config('app.timezone'));
|
||||
$now->addDays(2);
|
||||
$invitee = new InvitedUser();
|
||||
$invitee->user()->associate($user);
|
||||
|
||||
@@ -32,7 +32,6 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use FireflyIII\Support\Facades\Steam;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
@@ -98,9 +97,10 @@ class AccountBalanceCalculator
|
||||
|
||||
return '0';
|
||||
}
|
||||
Log::debug(sprintf('getLatestBalance: notBefore date is "%s", calculating', $notBefore->format('Y-m-d')));
|
||||
$query = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transactions.transaction_currency_id', $currencyId)
|
||||
->where('transaction_journals.transaction_currency_id', $currencyId)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
// this order is the same as GroupCollector
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
@@ -110,32 +110,21 @@ class AccountBalanceCalculator
|
||||
->orderBy('transactions.amount', 'DESC')
|
||||
->where('transactions.account_id', $accountId)
|
||||
;
|
||||
$notBefore->startOfDay();
|
||||
$query->where('transaction_journals.date', '<', $notBefore);
|
||||
|
||||
$first = $query->first(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount', 'transactions.balance_after']);
|
||||
|
||||
if (null === $first) {
|
||||
Log::debug(sprintf('Found no transactions for currency #%d and account #%d, return 0.', $currencyId, $accountId));
|
||||
|
||||
return '0';
|
||||
}
|
||||
|
||||
|
||||
$balance = (string)($first->balance_after ?? '0');
|
||||
Log::debug(sprintf('getLatestBalance: found balance: %s in transaction #%d on moment %s', Steam::bcround($balance, 2), $first->id ?? 0, $notBefore->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('getLatestBalance: found balance: %s in transaction #%d', $balance, $first->id ?? 0));
|
||||
|
||||
return $balance;
|
||||
}
|
||||
|
||||
private function optimizedCalculation(Collection $accounts, ?Carbon $notBefore = null): void
|
||||
{
|
||||
if ($notBefore instanceof Carbon) {
|
||||
$notBefore->startOfDay();
|
||||
}
|
||||
|
||||
Log::debug(sprintf('start of optimizedCalculation with date "%s"', $notBefore?->format('Y-m-d H:i:s')));
|
||||
Log::debug('start of optimizedCalculation');
|
||||
if ($accounts->count() > 0) {
|
||||
Log::debug(sprintf('Limited to %d account(s): %s', $accounts->count(), implode(', ', $accounts->pluck('id')->toArray())));
|
||||
Log::debug(sprintf('Limited to %d account(s)', $accounts->count()));
|
||||
}
|
||||
// collect all transactions and the change they make.
|
||||
$balances = [];
|
||||
@@ -154,18 +143,18 @@ class AccountBalanceCalculator
|
||||
$query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
|
||||
}
|
||||
if ($notBefore instanceof Carbon) {
|
||||
$notBefore->startOfDay();
|
||||
$query->where('transaction_journals.date', '>=', $notBefore);
|
||||
}
|
||||
|
||||
$set = $query->get(['transactions.id', 'transactions.balance_dirty', 'transactions.transaction_currency_id', 'transaction_journals.date', 'transactions.account_id', 'transactions.amount']);
|
||||
Log::debug(sprintf('Found %d transaction(s)', $set->count()));
|
||||
Log::debug(sprintf('Counted %d transaction(s)', $set->count()));
|
||||
|
||||
// the balance value is an array.
|
||||
// first entry is the balance, second is the date.
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
Log::debug(sprintf('Processing transaction #%d with currency #%d and amount %s', $entry->id, $entry->transaction_currency_id, Steam::bcround($entry->amount)));
|
||||
// start with empty array:
|
||||
$balances[$entry->account_id] ??= [];
|
||||
$balances[$entry->account_id][$entry->transaction_currency_id] ??= [$this->getLatestBalance($entry->account_id, $entry->transaction_currency_id, $notBefore), null];
|
||||
@@ -173,9 +162,6 @@ class AccountBalanceCalculator
|
||||
// before and after are easy:
|
||||
$before = $balances[$entry->account_id][$entry->transaction_currency_id][0];
|
||||
$after = bcadd($before, (string)$entry->amount);
|
||||
|
||||
Log::debug(sprintf('Before:%s, after:%s', Steam::bcround($before, 2), Steam::bcround($after, 2)));
|
||||
|
||||
if (true === $entry->balance_dirty || $accounts->count() > 0) {
|
||||
// update the transaction:
|
||||
$entry->balance_before = $before;
|
||||
|
||||
@@ -24,12 +24,12 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Support\System;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Laravel\Passport\Console\KeysCommand;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
@@ -48,27 +48,16 @@ class OAuthKeys
|
||||
|
||||
public static function generateKeys(): void
|
||||
{
|
||||
Log::debug('Will now run generateKeys()');
|
||||
Artisan::registerCommand(new KeysCommand());
|
||||
Artisan::call('firefly-iii:laravel-passport-keys');
|
||||
Log::debug('Done with generateKeys()');
|
||||
}
|
||||
|
||||
public static function hasKeyFiles(): bool
|
||||
{
|
||||
Log::debug('hasKeyFiles()');
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
$privateExists = file_exists($private);
|
||||
$publicExists = file_exists($public);
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
|
||||
Log::debug(sprintf('Private key file at "%s" exists? %s', $private, var_export($privateExists, true)));
|
||||
Log::debug(sprintf('Public key file at "%s" exists ? %s', $public, var_export($publicExists, true)));
|
||||
|
||||
$result = file_exists($private) && file_exists($public);
|
||||
Log::debug(sprintf('Method will return %s', var_export($result, true)));
|
||||
|
||||
return $result;
|
||||
return file_exists($private) && file_exists($public);
|
||||
}
|
||||
|
||||
public static function keysInDatabase(): bool
|
||||
@@ -76,36 +65,17 @@ class OAuthKeys
|
||||
$privateKey = '';
|
||||
$publicKey = '';
|
||||
// better check if keys are in the database:
|
||||
$hasPrivate = FireflyConfig::has(self::PRIVATE_KEY);
|
||||
$hasPublic = FireflyConfig::has(self::PUBLIC_KEY);
|
||||
|
||||
Log::debug(sprintf('keysInDatabase: hasPrivate:%s, hasPublic:%s', var_export($hasPrivate, true), var_export($hasPublic, true)));
|
||||
|
||||
if ($hasPrivate && $hasPublic) {
|
||||
if (FireflyConfig::has(self::PRIVATE_KEY) && FireflyConfig::has(self::PUBLIC_KEY)) {
|
||||
try {
|
||||
$privateKey = trim((string)FireflyConfig::get(self::PRIVATE_KEY)?->data);
|
||||
$publicKey = trim((string)FireflyConfig::get(self::PUBLIC_KEY)?->data);
|
||||
$privateKey = (string)FireflyConfig::get(self::PRIVATE_KEY)?->data;
|
||||
$publicKey = (string)FireflyConfig::get(self::PUBLIC_KEY)?->data;
|
||||
} catch (ContainerExceptionInterface|FireflyException|NotFoundExceptionInterface $e) {
|
||||
Log::error(sprintf('Could not validate keysInDatabase(): %s', $e->getMessage()));
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
if ('' === $privateKey) {
|
||||
Log::warning('Private key in DB is unexpectedly an empty string.');
|
||||
}
|
||||
if ('' === $publicKey) {
|
||||
Log::warning('Public key in DB is unexpectedly an empty string.');
|
||||
}
|
||||
if ('' !== $privateKey) {
|
||||
Log::debug(sprintf('SHA2 hash of private key in DB: %s', hash('sha256', $privateKey)));
|
||||
}
|
||||
if ('' !== $publicKey) {
|
||||
Log::debug(sprintf('SHA2 hash of public key in DB : %s', hash('sha256', $publicKey)));
|
||||
}
|
||||
$return = '' !== $privateKey && '' !== $publicKey;
|
||||
Log::debug(sprintf('keysInDatabase will return %s', var_export($return, true)));
|
||||
|
||||
return $return;
|
||||
return '' !== $privateKey && '' !== $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,20 +86,12 @@ class OAuthKeys
|
||||
*/
|
||||
public static function restoreKeysFromDB(): bool
|
||||
{
|
||||
Log::debug('restoreKeysFromDB()');
|
||||
$privateKey = (string)FireflyConfig::get(self::PRIVATE_KEY)?->data;
|
||||
$publicKey = (string)FireflyConfig::get(self::PUBLIC_KEY)?->data;
|
||||
|
||||
if ('' === $privateKey) {
|
||||
Log::warning('Private key is not in the database.');
|
||||
}
|
||||
if ('' === $publicKey) {
|
||||
Log::warning('Public key is not in the database.');
|
||||
}
|
||||
|
||||
try {
|
||||
$privateContent = trim(Crypt::decrypt($privateKey));
|
||||
$publicContent = trim(Crypt::decrypt($publicKey));
|
||||
$privateContent = Crypt::decrypt($privateKey);
|
||||
$publicContent = Crypt::decrypt($publicKey);
|
||||
} catch (DecryptException $e) {
|
||||
Log::error('Could not decrypt pub/private keypair.');
|
||||
Log::error($e->getMessage());
|
||||
@@ -137,7 +99,6 @@ class OAuthKeys
|
||||
// delete config vars from DB:
|
||||
FireflyConfig::delete(self::PRIVATE_KEY);
|
||||
FireflyConfig::delete(self::PUBLIC_KEY);
|
||||
Log::debug('Done with generateKeysFromDB(), return FALSE');
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -146,24 +107,15 @@ class OAuthKeys
|
||||
file_put_contents($private, $privateContent);
|
||||
file_put_contents($public, $publicContent);
|
||||
|
||||
Log::debug(sprintf('Will store private key with hash "%s" in file "%s"', hash('sha256', $privateContent), $private));
|
||||
Log::debug(sprintf('Will store public key with hash "%s" in file "%s"', hash('sha256', $publicContent), $public));
|
||||
Log::debug('Done with generateKeysFromDB()');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function storeKeysInDB(): void
|
||||
{
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
$privateContent = file_get_contents($private);
|
||||
$publicContent = file_get_contents($public);
|
||||
FireflyConfig::set(self::PRIVATE_KEY, Crypt::encrypt($privateContent));
|
||||
FireflyConfig::set(self::PUBLIC_KEY, Crypt::encrypt($publicContent));
|
||||
|
||||
Log::debug(sprintf('Will store the content of file "%s" as "%s" in the database (hash: %s)', $private, self::PRIVATE_KEY, hash('sha256', $privateContent)));
|
||||
Log::debug(sprintf('Will store the content of file "%s" as "%s" in the database (hash: %s)', $public, self::PUBLIC_KEY, hash('sha256', $publicContent)));
|
||||
$private = storage_path('oauth-private.key');
|
||||
$public = storage_path('oauth-public.key');
|
||||
FireflyConfig::set(self::PRIVATE_KEY, Crypt::encrypt(file_get_contents($private)));
|
||||
FireflyConfig::set(self::PUBLIC_KEY, Crypt::encrypt(file_get_contents($public)));
|
||||
}
|
||||
|
||||
public static function verifyKeysRoutine(): void
|
||||
|
||||
12
composer.lock
generated
12
composer.lock
generated
@@ -10706,16 +10706,16 @@
|
||||
},
|
||||
{
|
||||
"name": "larastan/larastan",
|
||||
"version": "v3.9.0",
|
||||
"version": "v3.8.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/larastan/larastan.git",
|
||||
"reference": "82c18890d0d5b012bc39a3432531e5b6cd1b4b3a"
|
||||
"reference": "ff3725291bc4c7e6032b5a54776e3e5104c86db9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/82c18890d0d5b012bc39a3432531e5b6cd1b4b3a",
|
||||
"reference": "82c18890d0d5b012bc39a3432531e5b6cd1b4b3a",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/ff3725291bc4c7e6032b5a54776e3e5104c86db9",
|
||||
"reference": "ff3725291bc4c7e6032b5a54776e3e5104c86db9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10784,7 +10784,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/larastan/larastan/issues",
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.9.0"
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.8.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -10792,7 +10792,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-01-17T23:00:37+00:00"
|
||||
"time": "2025-12-11T16:37:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel-json-api/testing",
|
||||
|
||||
@@ -78,8 +78,8 @@ return [
|
||||
'running_balance_column' => (bool)envNonEmpty('USE_RUNNING_BALANCE', true), // this is only the default value, is not used.
|
||||
// see cer.php for exchange rates feature flag.
|
||||
],
|
||||
'version' => 'develop/2026-01-19',
|
||||
'build_time' => 1768805645,
|
||||
'version' => '6.4.16',
|
||||
'build_time' => 1768636333,
|
||||
'api_version' => '2.1.0', // field is no longer used.
|
||||
'db_version' => 28, // field is no longer used.
|
||||
|
||||
|
||||
54
package-lock.json
generated
54
package-lock.json
generated
@@ -3350,42 +3350,42 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-core": {
|
||||
"version": "3.5.27",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.27.tgz",
|
||||
"integrity": "sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz",
|
||||
"integrity": "sha512-vXyI5GMfuoBCnv5ucIT7jhHKl55Y477yxP6fc4eUswjP8FG3FFVFd41eNDArR+Uk3QKn2Z85NavjaxLxOC19/w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/shared": "3.5.27",
|
||||
"@vue/shared": "3.5.26",
|
||||
"entities": "^7.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"source-map-js": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-dom": {
|
||||
"version": "3.5.27",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.27.tgz",
|
||||
"integrity": "sha512-oAFea8dZgCtVVVTEC7fv3T5CbZW9BxpFzGGxC79xakTr6ooeEqmRuvQydIiDAkglZEAd09LgVf1RoDnL54fu5w==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.26.tgz",
|
||||
"integrity": "sha512-y1Tcd3eXs834QjswshSilCBnKGeQjQXB6PqFn/1nxcQw4pmG42G8lwz+FZPAZAby6gZeHSt/8LMPfZ4Rb+Bd/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-core": "3.5.27",
|
||||
"@vue/shared": "3.5.27"
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-sfc": {
|
||||
"version": "3.5.27",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.27.tgz",
|
||||
"integrity": "sha512-sHZu9QyDPeDmN/MRoshhggVOWE5WlGFStKFwu8G52swATgSny27hJRWteKDSUUzUH+wp+bmeNbhJnEAel/auUQ==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.26.tgz",
|
||||
"integrity": "sha512-egp69qDTSEZcf4bGOSsprUr4xI73wfrY5oRs6GSgXFTiHrWj4Y3X5Ydtip9QMqiCMCPVwLglB9GBxXtTadJ3mA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.28.5",
|
||||
"@vue/compiler-core": "3.5.27",
|
||||
"@vue/compiler-dom": "3.5.27",
|
||||
"@vue/compiler-ssr": "3.5.27",
|
||||
"@vue/shared": "3.5.27",
|
||||
"@vue/compiler-core": "3.5.26",
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/compiler-ssr": "3.5.26",
|
||||
"@vue/shared": "3.5.26",
|
||||
"estree-walker": "^2.0.2",
|
||||
"magic-string": "^0.30.21",
|
||||
"postcss": "^8.5.6",
|
||||
@@ -3393,14 +3393,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/compiler-ssr": {
|
||||
"version": "3.5.27",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.27.tgz",
|
||||
"integrity": "sha512-Sj7h+JHt512fV1cTxKlYhg7qxBvack+BGncSpH+8vnN+KN95iPIcqB5rsbblX40XorP+ilO7VIKlkuu3Xq2vjw==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.26.tgz",
|
||||
"integrity": "sha512-lZT9/Y0nSIRUPVvapFJEVDbEXruZh2IYHMk2zTtEgJSlP5gVOqeWXH54xDKAaFS4rTnDeDBQUYDtxKyoW9FwDw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.27",
|
||||
"@vue/shared": "3.5.27"
|
||||
"@vue/compiler-dom": "3.5.26",
|
||||
"@vue/shared": "3.5.26"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/component-compiler-utils": {
|
||||
@@ -3482,9 +3482,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.5.27",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.27.tgz",
|
||||
"integrity": "sha512-dXr/3CgqXsJkZ0n9F3I4elY8wM9jMJpP3pvRG52r6m0tu/MsAFIe6JpXVGeNMd/D9F4hQynWT8Rfuj0bdm9kFQ==",
|
||||
"version": "3.5.26",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.26.tgz",
|
||||
"integrity": "sha512-7Z6/y3uFI5PRoKeorTOSXKcDj0MSasfNNltcslbFrPpcw6aXRUALq4IfJlaTRspiWIUOEZbrpM+iQGmCOiWe4A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
@@ -4564,9 +4564,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001765",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz",
|
||||
"integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==",
|
||||
"version": "1.0.30001764",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz",
|
||||
"integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
||||
@@ -121,10 +121,8 @@ export default {
|
||||
let srcType = this.source.type ? this.source.type.toLowerCase() : 'invalid';
|
||||
let tType = this.transactionType ? this.transactionType.toLowerCase() : 'invalid';
|
||||
let liabilities = ['loan', 'debt', 'mortgage'];
|
||||
let asset = ['asset account'];
|
||||
let sourceIsLiability = liabilities.indexOf(srcType) !== -1;
|
||||
let destIsLiability = liabilities.indexOf(destType) !== -1;
|
||||
let destIsAsset =asset.indexOf(destType) !== -1;
|
||||
|
||||
|
||||
// console.log(srcType + ' (source) is a liability: ' + sourceIsLiability);
|
||||
@@ -133,15 +131,18 @@ export default {
|
||||
if (tType === 'transfer' || destIsLiability || sourceIsLiability) {
|
||||
console.log('Source or dest is a liability.')
|
||||
console.log('Source is liability OR dest is liability, OR transfer. Lock list on currency of destination.');
|
||||
console.log(this.destination.type);
|
||||
// console.log('Length of currencies is ' + this.currencies.length);
|
||||
// console.log(this.currencies);
|
||||
this.liability = true;
|
||||
// lock dropdown list on currencyID of destination UNLESS dest is not liab
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (parseInt(this.currencies[key].id) === parseInt(this.destination.currency_id) || (!destIsLiability && 'transfer' !== tType)) {
|
||||
console.log('Enable currency: ' + this.currencies[key].attributes.code + '.');
|
||||
if (
|
||||
parseInt(this.currencies[key].id) === parseInt(this.destination.currency_id) || !destIsLiability
|
||||
) {
|
||||
console.log('Enable currency!!');
|
||||
console.log(this.currencies[key]);
|
||||
// console.log(this.destination);
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"firefly": {
|
||||
"administrations_page_title": "Administrasi keuangan",
|
||||
"administrations_index_menu": "Administrasi keuangan",
|
||||
"administrations_page_title": "Financial administrations",
|
||||
"administrations_index_menu": "Financial administrations",
|
||||
"expires_at": "Expires at",
|
||||
"temp_administrations_introduction": "Firefly III segera akan memiliki kemampuan untuk mengelola beberapa administrasi keuangan. Saat ini, Anda hanya memiliki satu. Anda dapat mengatur judul administrasi ini serta mata uang utamanya. Pengaturan ini menggantikan pengaturan sebelumnya di mana Anda menetapkan \u201cmata uang default\u201d. Sekarang, pengaturan ini terkait langsung dengan masing-masing administrasi keuangan dan dapat berbeda untuk setiap administrasi.",
|
||||
"temp_administrations_introduction": "Firefly III will soon get the ability to manage multiple financial administrations. Right now, you only have the one. You can set the title of this administration and its primary currency. This replaces the previous setting where you would set your \"default currency\". This setting is now tied to the financial administration and can be different per administration.",
|
||||
"administration_currency_form_help": "It may take a long time for the page to load if you change the primary currency because transaction may need to be converted to your (new) primary currency.",
|
||||
"administrations_page_edit_sub_title_js": "Edit administrasi keuangan \u201c{title}\u201d",
|
||||
"administrations_page_edit_sub_title_js": "Edit financial administration \"{title}\"",
|
||||
"table": "Meja",
|
||||
"welcome_back": "Apa yang sedang dimainkan?",
|
||||
"flash_error": "Kesalahan!",
|
||||
@@ -20,7 +20,7 @@
|
||||
"split": "Pisah",
|
||||
"single_split": "Pisah",
|
||||
"not_enough_currencies": "Not enough currencies",
|
||||
"not_enough_currencies_enabled": "Jika Anda hanya mengaktifkan satu mata uang, tidak perlu menambahkan nilai tukar.",
|
||||
"not_enough_currencies_enabled": "If you have just one currency enabled, there is no need to add exchange rates.",
|
||||
"transaction_stored_link": "<a href=\"transactions\/show\/{ID}\">Transaction #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_stored_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID} (\"{title}\")<\/a> has been stored.",
|
||||
"webhook_updated_link": "<a href=\"webhooks\/show\/{ID}\">Webhook #{ID}<\/a> (\"{title}\") has been updated.",
|
||||
@@ -31,7 +31,7 @@
|
||||
"apply_rules_checkbox": "Apply rules",
|
||||
"fire_webhooks_checkbox": "Fire webhooks",
|
||||
"no_budget_pointer": "Anda tampaknya belum memiliki anggaran. Anda harus membuat beberapa di halaman-<a href=\"budgets\">anggaran<\/a>. Anggaran dapat membantu anda melacak pengeluaran.",
|
||||
"no_bill_pointer": "Sepertinya Anda belum memiliki langganan. Buat beberapa di halaman <a href=\"subscriptions\">Langganan<\/a>. Langganan dapat membantu Anda melacak pengeluaran.",
|
||||
"no_bill_pointer": "You seem to have no subscription yet. You should create some on the <a href=\"subscriptions\">subscription<\/a>-page. Subscriptions can help you keep track of expenses.",
|
||||
"source_account": "Akun sumber",
|
||||
"hidden_fields_preferences": "You can enable more transaction options in your <a href=\"preferences\">preferences<\/a>.",
|
||||
"destination_account": "Akun tujuan",
|
||||
@@ -50,7 +50,7 @@
|
||||
"category": "Kategori",
|
||||
"attachments": "Lampiran",
|
||||
"notes": "Notes",
|
||||
"external_url": "URL eksternal",
|
||||
"external_url": "URL luar",
|
||||
"update_transaction": "Update transaction",
|
||||
"after_update_create_another": "After updating, return here to continue editing.",
|
||||
"store_as_new": "Store as a new transaction instead of updating.",
|
||||
@@ -59,7 +59,7 @@
|
||||
"no_piggy_bank": "(tidak ada celengan)",
|
||||
"description": "Deskripsi",
|
||||
"split_transaction_title_help": "If you create a split transaction, there must be a global description for all splits of the transaction.",
|
||||
"destination_account_reconciliation": "Anda tidak dapat mengubah rekening tujuan pada transaksi rekonsiliasi.",
|
||||
"destination_account_reconciliation": "You can't edit the destination account of a reconciliation transaction.",
|
||||
"source_account_reconciliation": "Anda tidak dapat mengedit akun sumber dari transaksi rekonsiliasi.",
|
||||
"budget": "Anggaran",
|
||||
"bill": "Subscription",
|
||||
@@ -146,14 +146,14 @@
|
||||
"response": "Tanggapan",
|
||||
"visit_webhook_url": "Visit webhook URL",
|
||||
"reset_webhook_secret": "Reset webhook secret",
|
||||
"header_exchange_rates": "Nilai tukar",
|
||||
"exchange_rates_intro": "Firefly III mendukung pengunduhan dan penggunaan nilai tukar. Baca selengkapnya di <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">dokumentasi<\/a>.",
|
||||
"exchange_rates_from_to": "Antara {from} dan {to} (dan sebaliknya)",
|
||||
"exchange_rates_intro_rates": "Firefly III menggunakan nilai tukar berikut. Nilai tukar terbalik akan dihitung secara otomatis jika tidak tersedia. Jika tidak ada nilai tukar untuk tanggal transaksi, Firefly III akan mencari nilai tukar sebelumnya. Jika tetap tidak ditemukan, nilai tukar \u201c1\u201d akan digunakan.",
|
||||
"header_exchange_rates_rates": "Nilai tukar",
|
||||
"header_exchange_rates_table": "Tabel dengan nilai tukar",
|
||||
"header_exchange_rates": "Exchange rates",
|
||||
"exchange_rates_intro": "Firefly III supports downloading and using exchange rates. Read more about this in <a href=\"https:\/\/docs.firefly-iii.org\/explanation\/financial-concepts\/exchange-rates\/\">the documentation<\/a>.",
|
||||
"exchange_rates_from_to": "Between {from} and {to} (and the other way around)",
|
||||
"exchange_rates_intro_rates": "Firefly III uses the following exchange rates. The inverse is automatically calculated when it is not provided. If no exchange rate exists for the date of the transaction, Firefly III will go back in time to find one. If none are present, the rate \"1\" will be used.",
|
||||
"header_exchange_rates_rates": "Exchange rates",
|
||||
"header_exchange_rates_table": "Table with exchange rates",
|
||||
"help_rate_form": "On this day, how many {to} will you get for one {from}?",
|
||||
"add_new_rate": "Tambahkan nilai tukar baru",
|
||||
"add_new_rate": "Add a new exchange rate",
|
||||
"save_new_rate": "Save new rate"
|
||||
},
|
||||
"form": {
|
||||
|
||||
@@ -314,12 +314,7 @@
|
||||
{% if account.id == transaction.source_account_id %}
|
||||
<span title="Transfer, source">{{ formatAmountBySymbol(transaction.source_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
|
||||
{% else %}
|
||||
{% if null == transaction.foreign_currency_id %}
|
||||
<span title="Transfer, dest, normal currency">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
|
||||
{% endif %}
|
||||
{% if null != transaction.foreign_currency_id %}
|
||||
<span title="Transfer, dest, foreign currency">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}</span>
|
||||
{% endif %}
|
||||
<span title="Transfer, dest">{{ formatAmountBySymbol(transaction.destination_balance_after, transaction.currency_symbol, transaction.currency_decimal_places) }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user