Unify piggy bank events. Does not save a link to the journal (yet)

This commit is contained in:
James Cole
2022-12-11 07:17:59 +01:00
parent f33f9c797b
commit 44af5473a8
13 changed files with 237 additions and 172 deletions

View File

@@ -0,0 +1,58 @@
<?php
/*
* ChangedPiggyBankAmount.php
* Copyright (c) 2022 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\Events;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
/**
* Class ChangedPiggyBankAmount
*/
class ChangedPiggyBankAmount extends Event
{
use SerializesModels;
public PiggyBank $piggyBank;
public ?TransactionJournal $transactionJournal;
public ?TransactionGroup $transactionGroup;
public string $amount;
/**
* Create a new event instance.
*
* @param PiggyBank $piggyBank
* @param string $amount
* @param TransactionJournal|null $transactionJournal
* @param TransactionGroup|null $transactionGroup
*/
public function __construct(PiggyBank $piggyBank, string $amount, ?TransactionJournal $transactionJournal, ?TransactionGroup $transactionGroup)
{
Log::debug(sprintf('Created piggy bank event for piggy bank #%d with amount %s', $piggyBank->id, $amount));
$this->piggyBank = $piggyBank;
$this->transactionJournal = $transactionJournal;
$this->transactionGroup = $transactionGroup;
$this->amount = $amount;
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Factory; namespace FireflyIII\Factory;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
@@ -40,22 +41,20 @@ class PiggyBankEventFactory
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* @param PiggyBank|null $piggyBank * @param PiggyBank|null $piggyBank
*
* @return PiggyBankEvent|null
*/ */
public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): ?PiggyBankEvent public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): void
{ {
Log::debug(sprintf('Now in PiggyBankEventCreate for a %s', $journal->transactionType->type)); Log::debug(sprintf('Now in PiggyBankEventCreate for a %s', $journal->transactionType->type));
if (null === $piggyBank) { if (null === $piggyBank) {
Log::debug('Piggy bank is null'); Log::debug('Piggy bank is null');
return null; return;
} }
if (TransactionType::TRANSFER !== $journal->transactionType->type) { if (TransactionType::TRANSFER !== $journal->transactionType->type) {
Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id)); Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id));
return null; return;
} }
/** @var PiggyBankRepositoryInterface $piggyRepos */ /** @var PiggyBankRepositoryInterface $piggyRepos */
@@ -66,20 +65,17 @@ class PiggyBankEventFactory
if (null === $repetition) { if (null === $repetition) {
Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d'))); Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d')));
return null; return;
} }
Log::debug('Found repetition'); Log::debug('Found repetition');
$amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal); $amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal);
if (0 === bccomp($amount, '0')) { if (0 === bccomp($amount, '0')) {
Log::debug('Amount is zero, will not create event.'); Log::debug('Amount is zero, will not create event.');
return null; return;
} }
// amount can be negative.
$piggyRepos->addAmountToRepetition($repetition, $amount); $piggyRepos->addAmountToRepetition($repetition, $amount);
$event = $piggyRepos->createEventWithJournal($piggyBank, $amount, $journal);
Log::debug(sprintf('Created piggy bank event #%d', $event->id));
return $event;
} }
} }

View File

@@ -306,10 +306,8 @@ class TransactionJournalFactory
unset($dataRow['import_hash_v2'], $dataRow['original_source']); unset($dataRow['import_hash_v2'], $dataRow['original_source']);
$json = json_encode($dataRow, JSON_THROW_ON_ERROR); $json = json_encode($dataRow, JSON_THROW_ON_ERROR);
if (false === $json) { if (false === $json) {
$json = json_encode((string)microtime(), JSON_THROW_ON_ERROR); $json = json_encode((string)microtime(), JSON_THROW_ON_ERROR);
Log::error(sprintf('Could not hash the original row! %s', json_last_error_msg()), $dataRow); Log::error(sprintf('Could not hash the original row! %s', json_last_error_msg()), $dataRow);
} }
$hash = hash('sha256', $json); $hash = hash('sha256', $json);
Log::debug(sprintf('The hash is: %s', $hash), $dataRow); Log::debug(sprintf('The hash is: %s', $hash), $dataRow);

View File

@@ -0,0 +1,55 @@
<?php
/*
* PiggyBankEventHandler.php
* Copyright (c) 2022 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\Handlers\Events;
use Carbon\Carbon;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Models\PiggyBankEvent;
/**
* Class PiggyBankEventHandler
*/
class PiggyBankEventHandler
{
/**
* @param ChangedPiggyBankAmount $event
* @return void
*/
public function changePiggyAmount(ChangedPiggyBankAmount $event): void
{
// find journal if group is present.
$journal = $event->transactionJournal;
if (null !== $event->transactionGroup) {
$journal = $event->transactionGroup->transactionJournals()->first();
}
$date = $journal?->date ?? Carbon::now();
PiggyBankEvent::create(
[
'piggy_bank_id' => $event->piggyBank->id,
'transaction_journal_id' => $journal?->id,
'date' => $date->format('Y-m-d'),
'amount' => $event->amount,
]
);
}
}

View File

@@ -129,7 +129,6 @@ class AmountController extends Controller
} }
if ($this->piggyRepos->canAddAmount($piggyBank, $amount)) { if ($this->piggyRepos->canAddAmount($piggyBank, $amount)) {
$this->piggyRepos->addAmount($piggyBank, $amount); $this->piggyRepos->addAmount($piggyBank, $amount);
$this->piggyRepos->createEvent($piggyBank, $amount);
session()->flash( session()->flash(
'success', 'success',
(string) trans( (string) trans(

View File

@@ -25,6 +25,7 @@ namespace FireflyIII\Providers;
use Exception; use Exception;
use FireflyIII\Events\ActuallyLoggedIn; use FireflyIII\Events\ActuallyLoggedIn;
use FireflyIII\Events\AdminRequestedTestMessage; use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\DetectedNewIPAddress; use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RegisteredUser;
@@ -140,6 +141,11 @@ class EventServiceProvider extends ServiceProvider
WarnUserAboutBill::class => [ WarnUserAboutBill::class => [
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill', 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
], ],
// piggy bank related events:
ChangedPiggyBankAmount::class => [
'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount',
],
]; ];
/** /**

View File

@@ -24,17 +24,15 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\PiggyBank; namespace FireflyIII\Repositories\PiggyBank;
use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Note; use FireflyIII\Models\Note;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Log; use Illuminate\Support\Facades\Log;
/** /**
* Trait ModifiesPiggyBanks * Trait ModifiesPiggyBanks
@@ -59,8 +57,8 @@ trait ModifiesPiggyBanks
$repetition->currentamount = bcadd($currentAmount, $amount); $repetition->currentamount = bcadd($currentAmount, $amount);
$repetition->save(); $repetition->save();
// create event Log::debug('addAmount: Trigger change for positive amount.');
//$this->createEvent($piggyBank, $amount); event(new ChangedPiggyBankAmount($piggyBank, $amount, null, null));
return true; return true;
} }
@@ -69,15 +67,19 @@ trait ModifiesPiggyBanks
* @param PiggyBankRepetition $repetition * @param PiggyBankRepetition $repetition
* @param string $amount * @param string $amount
* *
* @return string * @return void
*/ */
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): string public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): void
{ {
$newAmount = bcadd($repetition->currentamount, $amount); Log::debug(sprintf('addAmountToRepetition: %s', $amount));
$repetition->currentamount = $newAmount; if (-1 === bccomp($amount, '0')) {
$repetition->save(); Log::debug('Remove amount.');
$this->removeAmount($repetition->piggyBank, bcmul($amount, '-1'));
return $newAmount; }
if (1 === bccomp($amount, '0')) {
Log::debug('Add amount.');
$this->addAmount($repetition->piggyBank, $amount);
}
} }
/** /**
@@ -127,24 +129,6 @@ trait ModifiesPiggyBanks
return bccomp($amount, $savedSoFar) <= 0; return bccomp($amount, $savedSoFar) <= 0;
} }
/**
* @param PiggyBank $piggyBank
* @param string $amount
* @param TransactionJournal $journal
*
* @return PiggyBankEvent
*/
public function createEventWithJournal(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): PiggyBankEvent
{
return PiggyBankEvent::create(
[
'piggy_bank_id' => $piggyBank->id,
'transaction_journal_id' => $journal->id,
'date' => $journal->date->format('Y-m-d'),
'amount' => $amount]
);
}
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
@@ -174,27 +158,12 @@ trait ModifiesPiggyBanks
$repetition->currentamount = bcsub($repetition->currentamount, $amount); $repetition->currentamount = bcsub($repetition->currentamount, $amount);
$repetition->save(); $repetition->save();
// create event Log::debug('addAmount: Trigger change for negative amount.');
$this->createEvent($piggyBank, bcmul($amount, '-1')); event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), null, null));
return true; return true;
} }
/**
* @param PiggyBank $piggyBank
* @param string $amount
*
* @return PiggyBankEvent
*/
public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent
{
if (0 === bccomp('0', $amount)) {
return new PiggyBankEvent;
}
return PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
@@ -225,8 +194,14 @@ trait ModifiesPiggyBanks
$repetition->currentamount = $amount; $repetition->currentamount = $amount;
$repetition->save(); $repetition->save();
// create event if (-1 === bccomp($difference, '0')) {
$this->createEvent($piggyBank, $difference); Log::debug('addAmount: Trigger change for negative amount.');
event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), null, null));
}
if (1 === bccomp($difference, '0')) {
Log::debug('addAmount: Trigger change for positive amount.');
event(new ChangedPiggyBankAmount($piggyBank, $amount, null, null));
}
return $piggyBank; return $piggyBank;
} }
@@ -242,7 +217,6 @@ trait ModifiesPiggyBanks
} }
return $piggyBank; return $piggyBank;
} }
/** /**
@@ -295,7 +269,6 @@ trait ModifiesPiggyBanks
$piggyBank->objectGroups()->sync([$objectGroup->id]); $piggyBank->objectGroups()->sync([$objectGroup->id]);
$piggyBank->save(); $piggyBank->save();
} }
} }
// try also with ID // try also with ID
$objectGroupId = (int)($data['object_group_id'] ?? 0); $objectGroupId = (int)($data['object_group_id'] ?? 0);
@@ -410,8 +383,10 @@ trait ModifiesPiggyBanks
// remove money from the rep. // remove money from the rep.
$repetition = $this->getRepetition($piggyBank); $repetition = $this->getRepetition($piggyBank);
if (null !== $repetition && $repetition->currentamount > $piggyBank->targetamount && 0.0 !== (float)$piggyBank->targetamount) { if (null !== $repetition && $repetition->currentamount > $piggyBank->targetamount && 0.0 !== (float)$piggyBank->targetamount) {
$diff = bcsub($piggyBank->targetamount, $repetition->currentamount); $difference = bcsub($piggyBank->targetamount, $repetition->currentamount);
$this->createEvent($piggyBank, $diff);
// an amount will be removed, create "negative" event:
event(new ChangedPiggyBankAmount($piggyBank, $difference, null, null));
$repetition->currentamount = $piggyBank->targetamount; $repetition->currentamount = $piggyBank->targetamount;
$repetition->save(); $repetition->save();
@@ -475,7 +450,6 @@ trait ModifiesPiggyBanks
} }
if (array_key_exists('startdate', $data)) { if (array_key_exists('startdate', $data)) {
$piggyBank->startdate = $data['startdate']; $piggyBank->startdate = $data['startdate'];
} }
$piggyBank->save(); $piggyBank->save();

View File

@@ -47,10 +47,8 @@ interface PiggyBankRepositoryInterface
/** /**
* @param PiggyBankRepetition $repetition * @param PiggyBankRepetition $repetition
* @param string $amount * @param string $amount
*
* @return string
*/ */
public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): string; public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount): void;
/** /**
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
@@ -68,25 +66,6 @@ interface PiggyBankRepositoryInterface
*/ */
public function canRemoveAmount(PiggyBank $piggyBank, string $amount): bool; public function canRemoveAmount(PiggyBank $piggyBank, string $amount): bool;
/**
* Create a new event.
*
* @param PiggyBank $piggyBank
* @param string $amount
*
* @return PiggyBankEvent
*/
public function createEvent(PiggyBank $piggyBank, string $amount): PiggyBankEvent;
/**
* @param PiggyBank $piggyBank
* @param string $amount
* @param TransactionJournal $journal
*
* @return PiggyBankEvent
*/
public function createEventWithJournal(PiggyBank $piggyBank, string $amount, TransactionJournal $journal): PiggyBankEvent;
/** /**
* Destroy piggy bank. * Destroy piggy bank.
* *

View File

@@ -83,6 +83,7 @@ class JournalDestroyService
$journal->notes()->delete(); $journal->notes()->delete();
// update events // update events
// TODO move to repository
$journal->piggyBankEvents()->update(['transaction_journal_id' => null]); $journal->piggyBankEvents()->update(['transaction_journal_id' => null]);
$journal->delete(); $journal->delete();

View File

@@ -105,7 +105,7 @@ class GroupCloneService
// add note saying "cloned". // add note saying "cloned".
// add relation. // add relation.
// clone linked piggy banks // TODO clone ALL linked piggy banks
/** @var PiggyBankEvent $event */ /** @var PiggyBankEvent $event */
$event = $journal->piggyBankEvents()->first(); $event = $journal->piggyBankEvents()->first();
if(null !== $event) { if(null !== $event) {

View File

@@ -152,7 +152,6 @@ class UpdatePiggybank implements ActionInterface
Log::debug(sprintf('Will now remove %s from piggy bank.', $amount)); Log::debug(sprintf('Will now remove %s from piggy bank.', $amount));
$repository->removeAmount($piggyBank, $amount); $repository->removeAmount($piggyBank, $amount);
$repository->createEventWithJournal($piggyBank, app('steam')->negative($amount), $journal);
} }
/** /**
@@ -191,6 +190,5 @@ class UpdatePiggybank implements ActionInterface
Log::debug(sprintf('Will now add %s to piggy bank.', $amount)); Log::debug(sprintf('Will now add %s to piggy bank.', $amount));
$repository->addAmount($piggyBank, $amount); $repository->addAmount($piggyBank, $amount);
$repository->createEventWithJournal($piggyBank, app('steam')->positive($amount), $journal);
} }
} }

View File

@@ -1851,6 +1851,7 @@ return [
'no_tags' => '(no tags)', 'no_tags' => '(no tags)',
// piggy banks: // piggy banks:
'event_history' => 'Event history',
'add_money_to_piggy' => 'Add money to piggy bank ":name"', 'add_money_to_piggy' => 'Add money to piggy bank ":name"',
'piggy_bank' => 'Piggy bank', 'piggy_bank' => 'Piggy bank',
'new_piggy_bank' => 'New piggy bank', 'new_piggy_bank' => 'New piggy bank',

View File

@@ -98,7 +98,7 @@
</div> </div>
<div class="box"> <div class="box">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">{{ 'transactions'|_ }}</h3> <h3 class="box-title">{{ 'event_history'|_ }}</h3>
</div> </div>
<div class="box-body no-padding" id="piggyEvents"> <div class="box-body no-padding" id="piggyEvents">
{% include 'list/piggy-bank-events' %} {% include 'list/piggy-bank-events' %}