mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-18 02:03:40 +00:00
🤖 Auto commit for release 'develop' on 2025-06-03
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events\Model\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Event;
|
||||
@@ -10,7 +12,5 @@ class ChangedName extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
public function __construct(public PiggyBank $piggyBank, public string $oldName, public string $newName)
|
||||
{
|
||||
}
|
||||
public function __construct(public PiggyBank $piggyBank, public string $oldName, public string $newName) {}
|
||||
}
|
||||
|
@@ -37,16 +37,16 @@ use FireflyIII\Models\PiggyBankEvent;
|
||||
*/
|
||||
class PiggyBankEventHandler
|
||||
{
|
||||
|
||||
public function changedPiggyBankName(ChangedName $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) {
|
||||
foreach ($event->piggyBank->accounts as $account) {
|
||||
/** @var Rule $rule */
|
||||
foreach($account->user->rules as $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) {
|
||||
foreach ($rule->ruleActions()->where('action_type', 'update_piggy')->get() as $ruleAction) {
|
||||
if ($event->oldName === $ruleAction->action_value) {
|
||||
$ruleAction->action_value = $event->newName;
|
||||
$ruleAction->save();
|
||||
}
|
||||
@@ -54,6 +54,7 @@ class PiggyBankEventHandler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function changePiggyAmount(ChangedAmount $event): void
|
||||
{
|
||||
// find journal if group is present.
|
||||
|
@@ -78,17 +78,19 @@ class AmountController extends Controller
|
||||
$leftToSave = bcsub($piggyBank->target_amount, $totalSaved);
|
||||
$maxAmount = 0 === bccomp($piggyBank->target_amount, '0') ? $leftOnAccount : min($leftOnAccount, $leftToSave);
|
||||
|
||||
Log::debug(sprintf('Account "%s", left on account "%s", saved so far "%s", left to save "%s", max amount "%s".',
|
||||
Log::debug(sprintf(
|
||||
'Account "%s", left on account "%s", saved so far "%s", left to save "%s", max amount "%s".',
|
||||
$account->name,
|
||||
$leftOnAccount,
|
||||
$totalSaved,
|
||||
$leftToSave,
|
||||
$maxAmount,));
|
||||
$maxAmount,
|
||||
));
|
||||
|
||||
$accounts[] = [
|
||||
'account' => $account,
|
||||
'left_on_account' => $leftOnAccount,
|
||||
'total_saved' => $totalSaved,
|
||||
'total_saved' => $totalSaved,
|
||||
'left_to_save' => $leftToSave,
|
||||
'max_amount' => $maxAmount,
|
||||
];
|
||||
@@ -107,9 +109,9 @@ class AmountController extends Controller
|
||||
public function addMobile(PiggyBank $piggyBank)
|
||||
{
|
||||
/** @var Carbon $date */
|
||||
$date = session('end', today(config('app.timezone')));
|
||||
$accounts = [];
|
||||
$total = '0';
|
||||
$date = session('end', today(config('app.timezone')));
|
||||
$accounts = [];
|
||||
$total = '0';
|
||||
$totalSaved = $this->piggyRepos->getCurrentAmount($piggyBank);
|
||||
foreach ($piggyBank->accounts as $account) {
|
||||
$leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, $account, $date);
|
||||
@@ -118,7 +120,7 @@ class AmountController extends Controller
|
||||
$accounts[] = [
|
||||
'account' => $account,
|
||||
'left_on_account' => $leftOnAccount,
|
||||
'total_saved' => $totalSaved,
|
||||
'total_saved' => $totalSaved,
|
||||
'left_to_save' => $leftToSave,
|
||||
'max_amount' => $maxAmount,
|
||||
];
|
||||
|
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
@@ -211,7 +211,7 @@ class EventServiceProvider extends ServiceProvider
|
||||
ChangedAmount::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changePiggyAmount',
|
||||
],
|
||||
ChangedName::class => [
|
||||
ChangedName::class => [
|
||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||
],
|
||||
|
||||
|
@@ -65,15 +65,15 @@ trait ModifiesPiggyBanks
|
||||
|
||||
public function removeAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcsub((string)$currentAmount, $amount);
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcsub((string)$currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
$userCurrency = app('amount')->getNativeCurrencyByUserGroup($this->user->userGroup);
|
||||
$userCurrency = app('amount')->getNativeCurrencyByUserGroup($this->user->userGroup);
|
||||
if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
$converter = new ExchangeRateConverter();
|
||||
$converter->setIgnoreSettings(true);
|
||||
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
|
||||
}
|
||||
@@ -88,15 +88,15 @@ trait ModifiesPiggyBanks
|
||||
|
||||
public function addAmount(PiggyBank $piggyBank, Account $account, string $amount, ?TransactionJournal $journal = null): bool
|
||||
{
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcadd((string)$currentAmount, $amount);
|
||||
$currentAmount = $this->getCurrentAmount($piggyBank, $account);
|
||||
$pivot = $piggyBank->accounts()->where('accounts.id', $account->id)->first()->pivot;
|
||||
$pivot->current_amount = bcadd((string)$currentAmount, $amount);
|
||||
$pivot->native_current_amount = null;
|
||||
|
||||
// also update native_current_amount.
|
||||
$userCurrency = app('amount')->getNativeCurrencyByUserGroup($this->user->userGroup);
|
||||
$userCurrency = app('amount')->getNativeCurrencyByUserGroup($this->user->userGroup);
|
||||
if ($userCurrency->id !== $piggyBank->transaction_currency_id) {
|
||||
$converter = new ExchangeRateConverter();
|
||||
$converter = new ExchangeRateConverter();
|
||||
$converter->setIgnoreSettings(true);
|
||||
$pivot->native_current_amount = $converter->convert($piggyBank->transactionCurrency, $userCurrency, today(), $pivot->current_amount);
|
||||
}
|
||||
@@ -112,10 +112,10 @@ trait ModifiesPiggyBanks
|
||||
public function canAddAmount(PiggyBank $piggyBank, Account $account, string $amount): bool
|
||||
{
|
||||
Log::debug('Now in canAddAmount');
|
||||
$today = today(config('app.timezone'))->endOfDay();
|
||||
$today = today(config('app.timezone'))->endOfDay();
|
||||
$leftOnAccount = $this->leftOnAccount($piggyBank, $account, $today);
|
||||
$savedSoFar = $this->getCurrentAmount($piggyBank);
|
||||
$maxAmount = $leftOnAccount;
|
||||
$savedSoFar = $this->getCurrentAmount($piggyBank);
|
||||
$maxAmount = $leftOnAccount;
|
||||
|
||||
Log::debug(sprintf('Left on account: %s on %s', $leftOnAccount, $today->format('Y-m-d H:i:s')));
|
||||
Log::debug(sprintf('Saved so far: %s', $savedSoFar));
|
||||
@@ -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;
|
||||
$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);
|
||||
$result = $compare <= 0;
|
||||
$compare = bccomp($amount, (string)$maxAmount);
|
||||
$result = $compare <= 0;
|
||||
|
||||
Log::debug(sprintf('Compare <= 0? %d, so canAddAmount is %s', $compare, var_export($result, true)));
|
||||
|
||||
@@ -163,15 +163,15 @@ trait ModifiesPiggyBanks
|
||||
|
||||
public function setCurrentAmount(PiggyBank $piggyBank, string $amount): PiggyBank
|
||||
{
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
if (null === $repetition) {
|
||||
return $piggyBank;
|
||||
}
|
||||
$max = $piggyBank->target_amount;
|
||||
$max = $piggyBank->target_amount;
|
||||
if (1 === bccomp($amount, $max) && 0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||
$amount = $max;
|
||||
}
|
||||
$difference = bcsub($amount, (string)$repetition->current_amount);
|
||||
$difference = bcsub($amount, (string)$repetition->current_amount);
|
||||
$repetition->current_amount = $amount;
|
||||
$repetition->save();
|
||||
|
||||
@@ -202,7 +202,7 @@ trait ModifiesPiggyBanks
|
||||
*/
|
||||
public function store(array $data): PiggyBank
|
||||
{
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory->user = $this->user;
|
||||
|
||||
return $factory->store($data);
|
||||
@@ -210,20 +210,20 @@ trait ModifiesPiggyBanks
|
||||
|
||||
public function update(PiggyBank $piggyBank, array $data): PiggyBank
|
||||
{
|
||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||
$piggyBank = $this->updateProperties($piggyBank, $data);
|
||||
if (array_key_exists('notes', $data)) {
|
||||
$this->updateNote($piggyBank, (string)$data['notes']);
|
||||
}
|
||||
|
||||
// update the order of the piggy bank:
|
||||
$oldOrder = $piggyBank->order;
|
||||
$newOrder = (int)($data['order'] ?? $oldOrder);
|
||||
$oldOrder = $piggyBank->order;
|
||||
$newOrder = (int)($data['order'] ?? $oldOrder);
|
||||
if ($oldOrder !== $newOrder) {
|
||||
$this->setOrder($piggyBank, $newOrder);
|
||||
}
|
||||
|
||||
// update the accounts
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory->user = $this->user;
|
||||
|
||||
// the piggy bank currency is set or updated FIRST, if it exists.
|
||||
@@ -300,11 +300,11 @@ trait ModifiesPiggyBanks
|
||||
$piggyBank->target_amount = '0';
|
||||
}
|
||||
if (array_key_exists('target_date', $data) && '' !== $data['target_date']) {
|
||||
$piggyBank->target_date = $data['target_date'];
|
||||
$piggyBank->target_date = $data['target_date'];
|
||||
$piggyBank->target_date_tz = $data['target_date']?->format('e');
|
||||
}
|
||||
if (array_key_exists('start_date', $data)) {
|
||||
$piggyBank->start_date = $data['start_date'];
|
||||
$piggyBank->start_date = $data['start_date'];
|
||||
$piggyBank->start_date_tz = $data['target_date']?->format('e');
|
||||
}
|
||||
$piggyBank->save();
|
||||
@@ -320,7 +320,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
return;
|
||||
}
|
||||
$dbNote = $piggyBank->notes()->first();
|
||||
$dbNote = $piggyBank->notes()->first();
|
||||
if (null === $dbNote) {
|
||||
$dbNote = new Note();
|
||||
$dbNote->noteable()->associate($piggyBank);
|
||||
@@ -331,7 +331,7 @@ trait ModifiesPiggyBanks
|
||||
|
||||
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
|
||||
{
|
||||
$oldOrder = $piggyBank->order;
|
||||
$oldOrder = $piggyBank->order;
|
||||
// Log::debug(sprintf('Will move piggy bank #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
|
||||
if ($newOrder > $oldOrder) {
|
||||
PiggyBank::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
|
||||
@@ -339,7 +339,8 @@ trait ModifiesPiggyBanks
|
||||
->where('accounts.user_id', $this->user->id)
|
||||
->where('piggy_banks.order', '<=', $newOrder)->where('piggy_banks.order', '>', $oldOrder)
|
||||
->where('piggy_banks.id', '!=', $piggyBank->id)
|
||||
->distinct()->decrement('piggy_banks.order');
|
||||
->distinct()->decrement('piggy_banks.order')
|
||||
;
|
||||
|
||||
$piggyBank->order = $newOrder;
|
||||
Log::debug(sprintf('[1] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
|
||||
@@ -352,7 +353,8 @@ trait ModifiesPiggyBanks
|
||||
->where('accounts.user_id', $this->user->id)
|
||||
->where('piggy_banks.order', '>=', $newOrder)->where('piggy_banks.order', '<', $oldOrder)
|
||||
->where('piggy_banks.id', '!=', $piggyBank->id)
|
||||
->distinct()->increment('piggy_banks.order');
|
||||
->distinct()->increment('piggy_banks.order')
|
||||
;
|
||||
|
||||
$piggyBank->order = $newOrder;
|
||||
Log::debug(sprintf('[2] Order of piggy #%d ("%s") from %d to %d', $piggyBank->id, $piggyBank->name, $oldOrder, $newOrder));
|
||||
@@ -373,7 +375,7 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
// if this account contains less than the amount, remove the current amount, update the amount and continue.
|
||||
$this->removeAmount($piggyBank, $account, $current);
|
||||
$amount = bcsub($amount, (string)$current);
|
||||
$amount = bcsub($amount, (string)$current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ class ExchangeRateConverter
|
||||
return '1';
|
||||
}
|
||||
if ($from->id === $to->id) {
|
||||
// Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
// Log::debug('ExchangeRateConverter: From and to are the same, return "1".');
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
@@ -40,9 +40,7 @@ class UpdatePiggyBank implements ActionInterface
|
||||
/**
|
||||
* TriggerInterface constructor.
|
||||
*/
|
||||
public function __construct(private readonly RuleAction $action)
|
||||
{
|
||||
}
|
||||
public function __construct(private readonly RuleAction $action) {}
|
||||
|
||||
public function actOnArray(array $journal): bool
|
||||
{
|
||||
@@ -52,12 +50,12 @@ class UpdatePiggyBank implements ActionInterface
|
||||
|
||||
// refresh the transaction type.
|
||||
/** @var User $user */
|
||||
$user = User::find($journal['user_id']);
|
||||
$user = User::find($journal['user_id']);
|
||||
|
||||
/** @var TransactionJournal $journalObj */
|
||||
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
|
||||
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
|
||||
|
||||
$piggyBank = $this->findPiggyBank($user, $actionValue);
|
||||
$piggyBank = $this->findPiggyBank($user, $actionValue);
|
||||
if (!$piggyBank instanceof PiggyBank) {
|
||||
Log::info(
|
||||
sprintf('No piggy bank named "%s", cant execute action #%d of rule #%d', $actionValue, $this->action->id, $this->action->rule_id)
|
||||
@@ -74,6 +72,7 @@ class UpdatePiggyBank implements ActionInterface
|
||||
Log::info(sprintf('Piggy bank #%d ("%s") already has an event for transaction journal #%d, so no action will be taken.', $piggyBank->id, $piggyBank->name, $journalObj->id));
|
||||
|
||||
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $actionValue])));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -81,7 +80,7 @@ class UpdatePiggyBank implements ActionInterface
|
||||
/** @var Transaction $destination */
|
||||
$destination = $journalObj->transactions()->where('amount', '>', 0)->first();
|
||||
|
||||
$accounts = $this->getAccounts($journalObj);
|
||||
$accounts = $this->getAccounts($journalObj);
|
||||
Log::debug(sprintf('Source account is #%d: "%s"', $accounts['source']->id, $accounts['source']->name));
|
||||
Log::debug(sprintf('Destination account is #%d: "%s"', $accounts['destination']->id, $accounts['source']->name));
|
||||
|
||||
@@ -97,9 +96,9 @@ class UpdatePiggyBank implements ActionInterface
|
||||
null,
|
||||
[
|
||||
'currency_symbol' => $journalObj->transactionCurrency->symbol,
|
||||
'decimal_places' => $journalObj->transactionCurrency->decimal_places,
|
||||
'amount' => $destination->amount,
|
||||
'piggy' => $piggyBank->name,
|
||||
'decimal_places' => $journalObj->transactionCurrency->decimal_places,
|
||||
'amount' => $destination->amount,
|
||||
'piggy' => $piggyBank->name,
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -120,10 +119,10 @@ class UpdatePiggyBank implements ActionInterface
|
||||
null,
|
||||
[
|
||||
'currency_symbol' => $journalObj->transactionCurrency->symbol,
|
||||
'decimal_places' => $journalObj->transactionCurrency->decimal_places,
|
||||
'amount' => $destination->amount,
|
||||
'piggy' => $piggyBank->name,
|
||||
'piggy_id' => $piggyBank->id,
|
||||
'decimal_places' => $journalObj->transactionCurrency->decimal_places,
|
||||
'amount' => $destination->amount,
|
||||
'piggy' => $piggyBank->name,
|
||||
'piggy_id' => $piggyBank->id,
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -154,7 +153,7 @@ class UpdatePiggyBank implements ActionInterface
|
||||
private function getAccounts(TransactionJournal $journal): array
|
||||
{
|
||||
return [
|
||||
'source' => $journal->transactions()->where('amount', '<', '0')->first()?->account,
|
||||
'source' => $journal->transactions()->where('amount', '<', '0')->first()?->account,
|
||||
'destination' => $journal->transactions()->where('amount', '>', '0')->first()?->account,
|
||||
];
|
||||
}
|
||||
@@ -180,11 +179,11 @@ class UpdatePiggyBank implements ActionInterface
|
||||
$repository->setUser($journal->user);
|
||||
|
||||
// how much can we remove from this piggy bank?
|
||||
$toRemove = $repository->getCurrentAmount($piggyBank, $account);
|
||||
$toRemove = $repository->getCurrentAmount($piggyBank, $account);
|
||||
Log::debug(sprintf('Amount is %s, max to remove is %s', $amount, $toRemove));
|
||||
|
||||
// if $amount is bigger than $toRemove, shrink it.
|
||||
$amount = -1 === bccomp($amount, $toRemove) ? $amount : $toRemove;
|
||||
$amount = -1 === bccomp($amount, $toRemove) ? $amount : $toRemove;
|
||||
Log::debug(sprintf('Amount is now %s', $amount));
|
||||
|
||||
// if amount is zero, stop.
|
||||
@@ -213,7 +212,7 @@ class UpdatePiggyBank implements ActionInterface
|
||||
|
||||
// how much can we add to the piggy bank?
|
||||
if (0 !== bccomp($piggyBank->target_amount, '0')) {
|
||||
$toAdd = bcsub($piggyBank->target_amount, $repository->getCurrentAmount($piggyBank, $account));
|
||||
$toAdd = bcsub($piggyBank->target_amount, $repository->getCurrentAmount($piggyBank, $account));
|
||||
Log::debug(sprintf('Max amount to add to piggy bank is %s, amount is %s', $toAdd, $amount));
|
||||
|
||||
// update amount to fit:
|
||||
|
Reference in New Issue
Block a user