mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Fix issues where rule action would use old data.
This commit is contained in:
parent
ccaadd1f52
commit
d1c87e1c21
@ -22,8 +22,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
use FireflyIII\Models\RuleAction;
|
|
||||||
use DB;
|
use DB;
|
||||||
|
use FireflyIII\Models\RuleAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AppendDescription.
|
* Class AppendDescription.
|
||||||
@ -49,6 +49,7 @@ class AppendDescription implements ActionInterface
|
|||||||
{
|
{
|
||||||
$description = sprintf('%s%s', $journal['description'], $this->action->action_value);
|
$description = sprintf('%s%s', $journal['description'], $this->action->action_value);
|
||||||
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);
|
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,19 +52,20 @@ class AppendNotes implements ActionInterface
|
|||||||
{
|
{
|
||||||
$dbNote = Note
|
$dbNote = Note
|
||||||
::
|
::
|
||||||
where('noteable_id', (int) $journal['transaction_journal_id'])
|
where('noteable_id', (int)$journal['transaction_journal_id'])
|
||||||
->where('noteable_type', TransactionJournal::class)
|
->where('noteable_type', TransactionJournal::class)
|
||||||
->first(['notes.*']);
|
->first(['notes.*']);
|
||||||
if (null === $dbNote) {
|
if (null === $dbNote) {
|
||||||
$dbNote = new Note;
|
$dbNote = new Note;
|
||||||
$dbNote->noteable_id = (int) $journal['transaction_journal_id'];
|
$dbNote->noteable_id = (int)$journal['transaction_journal_id'];
|
||||||
$dbNote->noteable_type = TransactionJournal::class;
|
$dbNote->noteable_type = TransactionJournal::class;
|
||||||
$dbNote->text = '';
|
$dbNote->text = '';
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('RuleAction AppendNotes appended "%s" to "%s".', $this->action->action_value, $dbNote->text));
|
Log::debug(sprintf('RuleAction AppendNotes appended "%s" to "%s".', $this->action->action_value, $dbNote->text));
|
||||||
$text = sprintf('%s%s', $dbNote->text, $this->action->action_value);
|
$text = sprintf('%s%s', $dbNote->text, $this->action->action_value);
|
||||||
$dbNote->text = $text;
|
$dbNote->text = $text;
|
||||||
$dbNote->save();
|
$dbNote->save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
/**
|
/**
|
||||||
* Class ClearBudget.
|
* Class ClearBudget.
|
||||||
*/
|
*/
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
use DB;
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use Log;
|
use Log;
|
||||||
|
@ -22,10 +22,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
/**
|
/**
|
||||||
* Class ClearNotes.
|
* Class ClearNotes.
|
||||||
*/
|
*/
|
||||||
@ -46,10 +47,11 @@ class ClearNotes implements ActionInterface
|
|||||||
public function actOnArray(array $journal): bool
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
DB::table('notes')
|
DB::table('notes')
|
||||||
->where('noteable_id', $journal['transaction_journal_id'])
|
->where('noteable_id', $journal['transaction_journal_id'])
|
||||||
->where('noteable_type', TransactionJournal::class)
|
->where('noteable_type', TransactionJournal::class)
|
||||||
->delete();
|
->delete();
|
||||||
Log::debug(sprintf('RuleAction ClearNotes removed all notes.'));
|
Log::debug(sprintf('RuleAction ClearNotes removed all notes.'));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,46 +52,31 @@ class ConvertToDeposit implements ActionInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input is a transfer from A to B.
|
* @inheritDoc
|
||||||
* Output is a deposit from C to B.
|
|
||||||
*
|
|
||||||
* @param array $journal
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
private function convertTransferArray(array $journal): bool
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
$user = User::find($journal['user_id']);
|
Log::debug(sprintf('Convert journal #%d to deposit.', $journal['transaction_journal_id']));
|
||||||
// find or create revenue account.
|
$type = $journal['transaction_type_type'];
|
||||||
/** @var AccountFactory $factory */
|
if (TransactionType::DEPOSIT === $type) {
|
||||||
$factory = app(AccountFactory::class);
|
Log::error(sprintf('Journal #%d is already a deposit (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
|
||||||
$factory->setUser($user);
|
|
||||||
|
|
||||||
// get the action value, or use the original source name in case the action value is empty:
|
return false;
|
||||||
// this becomes a new or existing revenue account.
|
}
|
||||||
$revenueName = '' === $this->action->action_value ? $journal['source_account_name'] : $this->action->action_value;
|
|
||||||
$revenue = $factory->findOrCreate($revenueName, AccountType::REVENUE);
|
|
||||||
|
|
||||||
Log::debug(sprintf('ConvertToDeposit. Action value is "%s", revenue name is "%s"', $this->action->action_value, $journal['source_account_name']));
|
if (TransactionType::WITHDRAWAL === $type) {
|
||||||
unset($source);
|
Log::debug('Going to transform a withdrawal to a deposit.');
|
||||||
|
|
||||||
// update source transaction(s) to be revenue account
|
return $this->convertWithdrawalArray($journal);
|
||||||
DB::table('transactions')
|
}
|
||||||
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
if (TransactionType::TRANSFER === $type) {
|
||||||
->where('amount', '<', 0)
|
Log::debug('Going to transform a transfer to a deposit.');
|
||||||
->update(['account_id' => $revenue->id]);
|
|
||||||
|
|
||||||
// change transaction type of journal:
|
return $this->convertTransferArray($journal);
|
||||||
$newType = TransactionType::whereType(TransactionType::DEPOSIT)->first();
|
}
|
||||||
|
|
||||||
DB::table('transaction_journals')
|
return false;
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
|
||||||
->update(['transaction_type_id' => $newType->id]);
|
|
||||||
|
|
||||||
Log::debug('Converted transfer to deposit.');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -143,29 +128,45 @@ class ConvertToDeposit implements ActionInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* Input is a transfer from A to B.
|
||||||
|
* Output is a deposit from C to B.
|
||||||
|
*
|
||||||
|
* @param array $journal
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function actOnArray(array $journal): bool
|
private function convertTransferArray(array $journal): bool
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Convert journal #%d to deposit.', $journal['transaction_journal_id']));
|
$user = User::find($journal['user_id']);
|
||||||
$type = $journal['transaction_type_type'];
|
// find or create revenue account.
|
||||||
if (TransactionType::DEPOSIT === $type) {
|
/** @var AccountFactory $factory */
|
||||||
Log::error(sprintf('Journal #%d is already a deposit (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
|
$factory = app(AccountFactory::class);
|
||||||
|
$factory->setUser($user);
|
||||||
|
|
||||||
return false;
|
// get the action value, or use the original source name in case the action value is empty:
|
||||||
}
|
// this becomes a new or existing revenue account.
|
||||||
|
$revenueName = '' === $this->action->action_value ? $journal['source_account_name'] : $this->action->action_value;
|
||||||
|
$revenue = $factory->findOrCreate($revenueName, AccountType::REVENUE);
|
||||||
|
|
||||||
if (TransactionType::WITHDRAWAL === $type) {
|
Log::debug(sprintf('ConvertToDeposit. Action value is "%s", revenue name is "%s"', $this->action->action_value, $journal['source_account_name']));
|
||||||
Log::debug('Going to transform a withdrawal to a deposit.');
|
unset($source);
|
||||||
|
|
||||||
return $this->convertWithdrawalArray($journal);
|
// update source transaction(s) to be revenue account
|
||||||
}
|
DB::table('transactions')
|
||||||
if (TransactionType::TRANSFER === $type) {
|
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
||||||
Log::debug('Going to transform a transfer to a deposit.');
|
->where('amount', '<', 0)
|
||||||
|
->update(['account_id' => $revenue->id]);
|
||||||
|
|
||||||
return $this->convertTransferArray($journal);
|
// change transaction type of journal:
|
||||||
}
|
$newType = TransactionType::whereType(TransactionType::DEPOSIT)->first();
|
||||||
return false;
|
|
||||||
|
DB::table('transaction_journals')
|
||||||
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
|
->update(['transaction_type_id' => $newType->id]);
|
||||||
|
|
||||||
|
Log::debug('Converted transfer to deposit.');
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,14 +24,15 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -56,10 +57,12 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
*/
|
*/
|
||||||
public function actOnArray(array $journal): bool
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
$type = $journal['transaction_type_type'];
|
$type = $journal['transaction_type_type'];
|
||||||
$user = User::find($journal['user_id']);
|
$user = User::find($journal['user_id']);
|
||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
Log::error(sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
|
Log::error(
|
||||||
|
sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -70,7 +73,12 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
$repository->setUser($user);
|
$repository->setUser($user);
|
||||||
$asset = $repository->findByName($this->action->action_value, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
|
$asset = $repository->findByName($this->action->action_value, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]);
|
||||||
if (null === $asset) {
|
if (null === $asset) {
|
||||||
Log::error(sprintf('Journal #%d cannot be converted because no asset with name "%s" exists (rule #%d).', $journal['transaction_journal_id'], $this->action->action_value, $this->action->rule_id));
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Journal #%d cannot be converted because no asset with name "%s" exists (rule #%d).', $journal['transaction_journal_id'],
|
||||||
|
$this->action->action_value, $this->action->rule_id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -88,49 +96,25 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
return false; // @codeCoverageIgnore
|
return false; // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A deposit is from Revenue to Asset.
|
|
||||||
* We replace the Revenue with another asset.
|
|
||||||
* @param array $journal
|
|
||||||
* @param Account $asset
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function convertDepositArray(array $journal, Account $asset): bool
|
|
||||||
{
|
|
||||||
if ($journal['destination_account_id'] === $asset->id) {
|
|
||||||
Log::error(vsprintf('Journal #%d has already has "%s" as a destination asset. ConvertToTransfer failed. (rule #%d).', [$journal['transaction_journal_id'], $asset->name, $this->action->rule_id]));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// update source transaction:
|
|
||||||
DB::table('transactions')
|
|
||||||
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
|
||||||
->where('amount', '<', 0)
|
|
||||||
->update(['account_id' => $asset->id]);
|
|
||||||
|
|
||||||
// change transaction type of journal:
|
|
||||||
$newType = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
|
||||||
|
|
||||||
DB::table('transaction_journals')
|
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
|
||||||
->update(['transaction_type_id' => $newType->id]);
|
|
||||||
|
|
||||||
Log::debug('Converted deposit to transfer.');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A withdrawal is from Asset to Expense.
|
* A withdrawal is from Asset to Expense.
|
||||||
* We replace the Expense with another asset.
|
* We replace the Expense with another asset.
|
||||||
|
*
|
||||||
* @param array $journal
|
* @param array $journal
|
||||||
* @param Account $asset
|
* @param Account $asset
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private function convertWithdrawalArray(array $journal, Account $asset): bool
|
private function convertWithdrawalArray(array $journal, Account $asset): bool
|
||||||
{
|
{
|
||||||
if ($journal['source_account_id'] === $asset->id) {
|
if ($journal['source_account_id'] === $asset->id) {
|
||||||
Log::error(vsprintf('Journal #%d has already has "%s" as a source asset. ConvertToTransfer failed. (rule #%d).', [$journal['transaction_journal_id'], $asset->name, $this->action->rule_id]));
|
Log::error(
|
||||||
|
vsprintf(
|
||||||
|
'Journal #%d has already has "%s" as a source asset. ConvertToTransfer failed. (rule #%d).',
|
||||||
|
[$journal['transaction_journal_id'], $asset->name, $this->action->rule_id]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +125,7 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
->update(['account_id' => $asset->id]);
|
->update(['account_id' => $asset->id]);
|
||||||
|
|
||||||
// change transaction type of journal:
|
// change transaction type of journal:
|
||||||
$newType = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
$newType = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
||||||
|
|
||||||
DB::table('transaction_journals')
|
DB::table('transaction_journals')
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
@ -152,4 +136,44 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A deposit is from Revenue to Asset.
|
||||||
|
* We replace the Revenue with another asset.
|
||||||
|
*
|
||||||
|
* @param array $journal
|
||||||
|
* @param Account $asset
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function convertDepositArray(array $journal, Account $asset): bool
|
||||||
|
{
|
||||||
|
if ($journal['destination_account_id'] === $asset->id) {
|
||||||
|
Log::error(
|
||||||
|
vsprintf(
|
||||||
|
'Journal #%d has already has "%s" as a destination asset. ConvertToTransfer failed. (rule #%d).',
|
||||||
|
[$journal['transaction_journal_id'], $asset->name, $this->action->rule_id]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update source transaction:
|
||||||
|
DB::table('transactions')
|
||||||
|
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
||||||
|
->where('amount', '<', 0)
|
||||||
|
->update(['account_id' => $asset->id]);
|
||||||
|
|
||||||
|
// change transaction type of journal:
|
||||||
|
$newType = TransactionType::whereType(TransactionType::TRANSFER)->first();
|
||||||
|
|
||||||
|
DB::table('transaction_journals')
|
||||||
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
|
->update(['transaction_type_id' => $newType->id]);
|
||||||
|
|
||||||
|
Log::debug('Converted deposit to transfer.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Factory\AccountFactory;
|
use FireflyIII\Factory\AccountFactory;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
@ -31,7 +32,6 @@ use FireflyIII\Models\RuleAction;
|
|||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -51,11 +51,76 @@ class ConvertToWithdrawal implements ActionInterface
|
|||||||
$this->action = $action;
|
$this->action = $action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function actOnArray(array $journal): bool
|
||||||
|
{
|
||||||
|
$type = $journal['transaction_type_type'];
|
||||||
|
if (TransactionType::WITHDRAWAL === $type) {
|
||||||
|
Log::error(sprintf('Journal #%d is already a withdrawal (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TransactionType::DEPOSIT === $type) {
|
||||||
|
Log::debug('Going to transform a deposit to a withdrawal.');
|
||||||
|
|
||||||
|
return $this->convertDepositArray($journal);
|
||||||
|
}
|
||||||
|
if (TransactionType::TRANSFER === $type) {
|
||||||
|
Log::debug('Going to transform a transfer to a withdrawal.');
|
||||||
|
|
||||||
|
return $this->convertTransferArray($journal);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
private function convertDepositArray(array $journal): bool
|
||||||
|
{
|
||||||
|
$user = User::find($journal['user_id']);
|
||||||
|
/** @var AccountFactory $factory */
|
||||||
|
$factory = app(AccountFactory::class);
|
||||||
|
$factory->setUser($user);
|
||||||
|
|
||||||
|
$expenseName = '' === $this->action->action_value ? $journal['source_account_name'] : $this->action->action_value;
|
||||||
|
$expense = $factory->findOrCreate($expenseName, AccountType::EXPENSE);
|
||||||
|
$destinationId = $journal['destination_account_id'];
|
||||||
|
|
||||||
|
|
||||||
|
Log::debug(sprintf('ConvertToWithdrawal. Action value is "%s", expense name is "%s"', $this->action->action_value, $expenseName));
|
||||||
|
|
||||||
|
// update source transaction(s) to be the original destination account
|
||||||
|
DB::table('transactions')
|
||||||
|
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
||||||
|
->where('amount', '<', 0)
|
||||||
|
->update(['account_id' => $destinationId]);
|
||||||
|
|
||||||
|
// update destination transaction(s) to be new expense account.
|
||||||
|
DB::table('transactions')
|
||||||
|
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
||||||
|
->where('amount', '>', 0)
|
||||||
|
->update(['account_id' => $expense->id]);
|
||||||
|
|
||||||
|
// change transaction type of journal:
|
||||||
|
$newType = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
||||||
|
DB::table('transaction_journals')
|
||||||
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
|
->update(['transaction_type_id' => $newType->id]);
|
||||||
|
|
||||||
|
Log::debug('Converted deposit to withdrawal.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Input is a transfer from A to B.
|
* Input is a transfer from A to B.
|
||||||
* Output is a withdrawal from A to C.
|
* Output is a withdrawal from A to C.
|
||||||
*
|
*
|
||||||
* @param array $journal
|
* @param array $journal
|
||||||
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
@ -82,7 +147,7 @@ class ConvertToWithdrawal implements ActionInterface
|
|||||||
->update(['account_id' => $expense->id]);
|
->update(['account_id' => $expense->id]);
|
||||||
|
|
||||||
// change transaction type of journal:
|
// change transaction type of journal:
|
||||||
$newType = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
$newType = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
||||||
DB::table('transaction_journals')
|
DB::table('transaction_journals')
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
->update(['transaction_type_id' => $newType->id]);
|
->update(['transaction_type_id' => $newType->id]);
|
||||||
@ -91,67 +156,4 @@ class ConvertToWithdrawal implements ActionInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function actOnArray(array $journal): bool
|
|
||||||
{
|
|
||||||
$type = $journal['transaction_type_type'];
|
|
||||||
if (TransactionType::WITHDRAWAL === $type) {
|
|
||||||
Log::error(sprintf('Journal #%d is already a withdrawal (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TransactionType::DEPOSIT === $type) {
|
|
||||||
Log::debug('Going to transform a deposit to a withdrawal.');
|
|
||||||
|
|
||||||
return $this->convertDepositArray($journal);
|
|
||||||
}
|
|
||||||
if (TransactionType::TRANSFER === $type) {
|
|
||||||
Log::debug('Going to transform a transfer to a withdrawal.');
|
|
||||||
|
|
||||||
return $this->convertTransferArray($journal);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // @codeCoverageIgnore
|
|
||||||
}
|
|
||||||
|
|
||||||
private function convertDepositArray(array $journal): bool
|
|
||||||
{
|
|
||||||
$user = User::find($journal['user_id']);
|
|
||||||
/** @var AccountFactory $factory */
|
|
||||||
$factory = app(AccountFactory::class);
|
|
||||||
$factory->setUser($user);
|
|
||||||
|
|
||||||
$expenseName = '' === $this->action->action_value ? $journal['source_account_name'] : $this->action->action_value;
|
|
||||||
$expense = $factory->findOrCreate($expenseName, AccountType::EXPENSE);
|
|
||||||
$destinationId = $journal['destination_account_id'];
|
|
||||||
|
|
||||||
|
|
||||||
Log::debug(sprintf('ConvertToWithdrawal. Action value is "%s", expense name is "%s"', $this->action->action_value, $expenseName));
|
|
||||||
|
|
||||||
// update source transaction(s) to be the original destination account
|
|
||||||
DB::table('transactions')
|
|
||||||
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
|
||||||
->where('amount', '<', 0)
|
|
||||||
->update(['account_id' => $destinationId]);
|
|
||||||
|
|
||||||
// update destination transaction(s) to be new expense account.
|
|
||||||
DB::table('transactions')
|
|
||||||
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
|
||||||
->where('amount', '>', 0)
|
|
||||||
->update(['account_id' => $expense->id]);
|
|
||||||
|
|
||||||
// change transaction type of journal:
|
|
||||||
$newType = TransactionType::whereType(TransactionType::WITHDRAWAL)->first();
|
|
||||||
DB::table('transaction_journals')
|
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
|
||||||
->update(['transaction_type_id' => $newType->id]);
|
|
||||||
|
|
||||||
Log::debug('Converted deposit to withdrawal.');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,9 @@ class DeleteTransaction implements ActionInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('RuleAction DeleteTransaction DELETED transaction journal #%d ("%s").', $journal['transaction_journal_id'], $journal['description']));
|
Log::debug(
|
||||||
|
sprintf('RuleAction DeleteTransaction DELETED transaction journal #%d ("%s").', $journal['transaction_journal_id'], $journal['description'])
|
||||||
|
);
|
||||||
|
|
||||||
// trigger delete factory:
|
// trigger delete factory:
|
||||||
$journal = TransactionJournal::find($journal['transaction_group_id']);
|
$journal = TransactionJournal::find($journal['transaction_group_id']);
|
||||||
|
@ -58,19 +58,26 @@ class LinkToBill implements ActionInterface
|
|||||||
/** @var BillRepositoryInterface $repository */
|
/** @var BillRepositoryInterface $repository */
|
||||||
$repository = app(BillRepositoryInterface::class);
|
$repository = app(BillRepositoryInterface::class);
|
||||||
$repository->setUser($user);
|
$repository->setUser($user);
|
||||||
$billName = (string) $this->action->action_value;
|
$billName = (string)$this->action->action_value;
|
||||||
$bill = $repository->findByName($billName);
|
$bill = $repository->findByName($billName);
|
||||||
|
|
||||||
if (null !== $bill && $journal['transaction_type_type'] === TransactionType::WITHDRAWAL) {
|
if (null !== $bill && $journal['transaction_type_type'] === TransactionType::WITHDRAWAL) {
|
||||||
DB::table('transaction_journals')
|
DB::table('transaction_journals')
|
||||||
->where('id', '=', $journal['transaction_journal_id'])
|
->where('id', '=', $journal['transaction_journal_id'])
|
||||||
->update(['bill_id' => $bill->id]);
|
->update(['bill_id' => $bill->id]);
|
||||||
Log::debug(sprintf('RuleAction LinkToBill set the bill of journal #%d to bill #%d ("%s").', $journal['transaction_journal_id'], $bill->id, $bill->name));
|
Log::debug(
|
||||||
|
sprintf('RuleAction LinkToBill set the bill of journal #%d to bill #%d ("%s").', $journal['transaction_journal_id'], $bill->id, $bill->name)
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::error(sprintf('RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": no such bill found or not a withdrawal.', $journal['transaction_journal_id'], $billName));
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": no such bill found or not a withdrawal.',
|
||||||
|
$journal['transaction_journal_id'], $billName
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -22,8 +22,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
use FireflyIII\Models\RuleAction;
|
|
||||||
use DB;
|
use DB;
|
||||||
|
use FireflyIII\Models\RuleAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PrependDescription.
|
* Class PrependDescription.
|
||||||
@ -50,6 +50,7 @@ class PrependDescription implements ActionInterface
|
|||||||
{
|
{
|
||||||
$description = sprintf('%s%s', $this->action->action_value, $journal['description']);
|
$description = sprintf('%s%s', $this->action->action_value, $journal['description']);
|
||||||
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);
|
DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,19 +52,20 @@ class PrependNotes implements ActionInterface
|
|||||||
{
|
{
|
||||||
$dbNote = Note
|
$dbNote = Note
|
||||||
::
|
::
|
||||||
where('noteable_id', (int) $journal['transaction_journal_id'])
|
where('noteable_id', (int)$journal['transaction_journal_id'])
|
||||||
->where('noteable_type', TransactionJournal::class)
|
->where('noteable_type', TransactionJournal::class)
|
||||||
->first(['notes.*']);
|
->first(['notes.*']);
|
||||||
if (null === $dbNote) {
|
if (null === $dbNote) {
|
||||||
$dbNote = new Note;
|
$dbNote = new Note;
|
||||||
$dbNote->noteable_id = (int) $journal['transaction_journal_id'];
|
$dbNote->noteable_id = (int)$journal['transaction_journal_id'];
|
||||||
$dbNote->noteable_type = TransactionJournal::class;
|
$dbNote->noteable_type = TransactionJournal::class;
|
||||||
$dbNote->text = '';
|
$dbNote->text = '';
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('RuleAction PrependNotes prepended "%s" to "%s".', $this->action->action_value, $dbNote->text));
|
Log::debug(sprintf('RuleAction PrependNotes prepended "%s" to "%s".', $this->action->action_value, $dbNote->text));
|
||||||
$text = sprintf('%s%s', $this->action->action_value, $dbNote->text);
|
$text = sprintf('%s%s', $this->action->action_value, $dbNote->text);
|
||||||
$dbNote->text = $text;
|
$dbNote->text = $text;
|
||||||
$dbNote->save();
|
$dbNote->save();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,9 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,10 +22,10 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RemoveTag.
|
* Class RemoveTag.
|
||||||
|
@ -22,11 +22,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SetBudget.
|
* Class SetBudget.
|
||||||
@ -55,7 +55,12 @@ class SetBudget implements ActionInterface
|
|||||||
|
|
||||||
$budget = $user->budgets()->where('name', $search)->first();
|
$budget = $user->budgets()->where('name', $search)->first();
|
||||||
if (null === $budget) {
|
if (null === $budget) {
|
||||||
Log::debug(sprintf('RuleAction SetBudget could not set budget of journal #%d to "%s" because no such budget exists.', $journal['transaction_journal_id'], $search));
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'RuleAction SetBudget could not set budget of journal #%d to "%s" because no such budget exists.', $journal['transaction_journal_id'],
|
||||||
|
$search
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -73,7 +78,9 @@ class SetBudget implements ActionInterface
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('RuleAction SetBudget set the budget of journal #%d to budget #%d ("%s").', $journal['transaction_journal_id'], $budget->id, $budget->name));
|
Log::debug(
|
||||||
|
sprintf('RuleAction SetBudget set the budget of journal #%d to budget #%d ("%s").', $journal['transaction_journal_id'], $budget->id, $budget->name)
|
||||||
|
);
|
||||||
|
|
||||||
DB::table('budget_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete();
|
DB::table('budget_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete();
|
||||||
DB::table('budget_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'budget_id' => $budget->id]);
|
DB::table('budget_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'budget_id' => $budget->id]);
|
||||||
|
@ -22,11 +22,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\TransactionRules\Actions;
|
namespace FireflyIII\TransactionRules\Actions;
|
||||||
|
|
||||||
|
use DB;
|
||||||
use FireflyIII\Factory\CategoryFactory;
|
use FireflyIII\Factory\CategoryFactory;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Log;
|
use Log;
|
||||||
use DB;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SetCategory.
|
* Class SetCategory.
|
||||||
@ -52,8 +52,9 @@ class SetCategory implements ActionInterface
|
|||||||
{
|
{
|
||||||
$user = User::find($journal['user_id']);
|
$user = User::find($journal['user_id']);
|
||||||
$search = $this->action->action_value;
|
$search = $this->action->action_value;
|
||||||
if(null === $user) {
|
if (null === $user) {
|
||||||
Log::error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal);
|
Log::error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,12 +63,22 @@ class SetCategory implements ActionInterface
|
|||||||
$factory->setUser($user);
|
$factory->setUser($user);
|
||||||
$category = $factory->findOrCreate(null, $search);
|
$category = $factory->findOrCreate(null, $search);
|
||||||
if (null === $category) {
|
if (null === $category) {
|
||||||
Log::debug(sprintf('RuleAction SetCategory could not set category of journal #%d to "%s" because no such category exists.', $journal['transaction_journal_id'], $search));
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'RuleAction SetCategory could not set category of journal #%d to "%s" because no such category exists.', $journal['transaction_journal_id'],
|
||||||
|
$search
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('RuleAction SetCategory set the category of journal #%d to category #%d ("%s").', $journal['transaction_journal_id'], $category->id, $category->name));
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'RuleAction SetCategory set the category of journal #%d to category #%d ("%s").', $journal['transaction_journal_id'], $category->id,
|
||||||
|
$category->name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
DB::table('category_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete();
|
DB::table('category_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete();
|
||||||
DB::table('category_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'category_id' => $category->id]);
|
DB::table('category_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'category_id' => $category->id]);
|
||||||
|
@ -60,6 +60,7 @@ class SetDescription implements ActionInterface
|
|||||||
$this->action->action_value
|
$this->action->action_value
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,27 +48,6 @@ class SetDestinationAccount implements ActionInterface
|
|||||||
$this->action = $action;
|
$this->action = $action;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Account|null
|
|
||||||
*/
|
|
||||||
private function findExpenseAccount(): ?Account
|
|
||||||
{
|
|
||||||
$account = $this->repository->findByName($this->action->action_value, [AccountType::EXPENSE]);
|
|
||||||
if (null === $account) {
|
|
||||||
$data = [
|
|
||||||
'name' => $this->action->action_value,
|
|
||||||
'account_type' => 'expense',
|
|
||||||
'account_type_id' => null,
|
|
||||||
'virtual_balance' => 0,
|
|
||||||
'active' => true,
|
|
||||||
'iban' => null,
|
|
||||||
];
|
|
||||||
$account = $this->repository->store($data);
|
|
||||||
}
|
|
||||||
Log::debug(sprintf('Found or created expense account #%d ("%s")', $account->id, $account->name));
|
|
||||||
return $account;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
@ -82,7 +61,11 @@ class SetDestinationAccount implements ActionInterface
|
|||||||
// it depends on the type what kind of destination account is expected.
|
// it depends on the type what kind of destination account is expected.
|
||||||
$expectedTypes = config(sprintf('firefly.source_dests.%s.%s', $type, $journal['source_account_type']));
|
$expectedTypes = config(sprintf('firefly.source_dests.%s.%s', $type, $journal['source_account_type']));
|
||||||
if (null === $expectedTypes) {
|
if (null === $expectedTypes) {
|
||||||
Log::error(sprintf('Configuration line "%s" is unexpectedly empty. Stopped.', sprintf('firefly.source_dests.%s.%s', $type, $journal['source_account_type'])));
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Configuration line "%s" is unexpectedly empty. Stopped.', sprintf('firefly.source_dests.%s.%s', $type, $journal['source_account_type'])
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -106,6 +89,7 @@ class SetDestinationAccount implements ActionInterface
|
|||||||
$expense = $this->findExpenseAccount();
|
$expense = $this->findExpenseAccount();
|
||||||
if (null === $expense) {
|
if (null === $expense) {
|
||||||
Log::error('Could not create expense account.');
|
Log::error('Could not create expense account.');
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
DB::table('transactions')
|
DB::table('transactions')
|
||||||
@ -122,10 +106,33 @@ class SetDestinationAccount implements ActionInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $types
|
* @param array $types
|
||||||
|
*
|
||||||
* @return Account|null
|
* @return Account|null
|
||||||
*/
|
*/
|
||||||
private function findAccount(array $types): ?Account
|
private function findAccount(array $types): ?Account
|
||||||
{
|
{
|
||||||
return $this->repository->findByName($this->action->action_value, $types);
|
return $this->repository->findByName($this->action->action_value, $types);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Account|null
|
||||||
|
*/
|
||||||
|
private function findExpenseAccount(): ?Account
|
||||||
|
{
|
||||||
|
$account = $this->repository->findByName($this->action->action_value, [AccountType::EXPENSE]);
|
||||||
|
if (null === $account) {
|
||||||
|
$data = [
|
||||||
|
'name' => $this->action->action_value,
|
||||||
|
'account_type' => 'expense',
|
||||||
|
'account_type_id' => null,
|
||||||
|
'virtual_balance' => 0,
|
||||||
|
'active' => true,
|
||||||
|
'iban' => null,
|
||||||
|
];
|
||||||
|
$account = $this->repository->store($data);
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Found or created expense account #%d ("%s")', $account->id, $account->name));
|
||||||
|
|
||||||
|
return $account;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@ namespace FireflyIII\TransactionRules\Actions;
|
|||||||
use DB;
|
use DB;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@ -48,6 +50,74 @@ class SetSourceAccount implements ActionInterface
|
|||||||
$this->action = $action;
|
$this->action = $action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function actOnArray(array $journal): bool
|
||||||
|
{
|
||||||
|
$user = User::find($journal['user_id']);
|
||||||
|
$type = $journal['transaction_type_type'];
|
||||||
|
/** @var TransactionJournal $journal */
|
||||||
|
$journal = TransactionJournal::find((int)$journal['transaction_journal_id']);
|
||||||
|
/** @var AccountRepositoryInterface repository */
|
||||||
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($user);
|
||||||
|
|
||||||
|
// if this is a transfer or a withdrawal, the new source account must be an asset account or a default account, and it MUST exist:
|
||||||
|
$newAccount = $this->findAssetAccount($type);
|
||||||
|
if ((TransactionType::WITHDRAWAL === $type || TransactionType::TRANSFER === $type) && null === $newAccount) {
|
||||||
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'Cannot change source account of journal #%d because no asset account with name "%s" exists.', $journal['transaction_journal_id'],
|
||||||
|
$this->action->action_value
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// new source account must be different from the current destination:
|
||||||
|
$destinationId = (int)$journal['destination_account_id'];
|
||||||
|
/** @var Transaction $source */
|
||||||
|
$source = $journal->transactions()->where('amount', '>', 0)->first();
|
||||||
|
if (null !== $source) {
|
||||||
|
$destinationId = $source->account ? (int)$source->account->id : $destinationId;
|
||||||
|
}
|
||||||
|
if (TransactionType::TRANSFER === $type && null !== $newAccount && (int)$newAccount->id === $destinationId) {
|
||||||
|
Log::error(
|
||||||
|
sprintf(
|
||||||
|
'New source account ID #%d and current destination account ID #%d are the same. Do nothing.', $newAccount->id,
|
||||||
|
$destinationId
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if this is a deposit, the new source account must be a revenue account and may be created:
|
||||||
|
if (TransactionType::DEPOSIT === $type) {
|
||||||
|
$newAccount = $this->findRevenueAccount();
|
||||||
|
}
|
||||||
|
if (null === $newAccount) {
|
||||||
|
Log::error('New account is NULL');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(sprintf('New source account is #%d ("%s").', $newAccount->id, $newAccount->name));
|
||||||
|
|
||||||
|
// update source transaction with new source account:
|
||||||
|
// get source transaction:
|
||||||
|
DB::table('transactions')
|
||||||
|
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
||||||
|
->where('amount', '<', 0)
|
||||||
|
->update(['account_id' => $newAccount->id]);
|
||||||
|
|
||||||
|
Log::debug(sprintf('Updated journal #%d and gave it new source account ID.', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param string $type
|
||||||
*
|
*
|
||||||
@ -83,47 +153,7 @@ class SetSourceAccount implements ActionInterface
|
|||||||
$account = $this->repository->store($data);
|
$account = $this->repository->store($data);
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Found or created revenue account #%d ("%s")', $account->id, $account->name));
|
Log::debug(sprintf('Found or created revenue account #%d ("%s")', $account->id, $account->name));
|
||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritDoc
|
|
||||||
*/
|
|
||||||
public function actOnArray(array $journal): bool
|
|
||||||
{
|
|
||||||
$user = User::find($journal['user_id']);
|
|
||||||
$type = $journal['transaction_type_type'];
|
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
|
||||||
$this->repository->setUser($user);
|
|
||||||
|
|
||||||
// if this is a transfer or a withdrawal, the new source account must be an asset account or a default account, and it MUST exist:
|
|
||||||
$newAccount = $this->findAssetAccount($type);
|
|
||||||
if ((TransactionType::WITHDRAWAL === $type || TransactionType::TRANSFER === $type) && null === $newAccount) {
|
|
||||||
Log::error(sprintf('Cannot change source account of journal #%d because no asset account with name "%s" exists.', $journal['transaction_journal_id'], $this->action->action_value));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this is a deposit, the new source account must be a revenue account and may be created:
|
|
||||||
if (TransactionType::DEPOSIT === $type) {
|
|
||||||
$newAccount = $this->findRevenueAccount();
|
|
||||||
}
|
|
||||||
if (null === $newAccount) {
|
|
||||||
Log::error('New account is NULL');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::debug(sprintf('New source account is #%d ("%s").', $newAccount->id, $newAccount->name));
|
|
||||||
|
|
||||||
// update source transaction with new source account:
|
|
||||||
// get source transaction:
|
|
||||||
DB::table('transactions')
|
|
||||||
->where('transaction_journal_id', '=', $journal['transaction_journal_id'])
|
|
||||||
->where('amount', '<', 0)
|
|
||||||
->update(['account_id' => $newAccount->id]);
|
|
||||||
|
|
||||||
Log::debug(sprintf('Updated journal #%d and gave it new source account ID.', $journal['transaction_journal_id']));
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -54,42 +54,49 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $journalArray
|
* @inheritDoc
|
||||||
* @param PiggyBank $piggyBank
|
|
||||||
* @param string $amount
|
|
||||||
*/
|
*/
|
||||||
private function addAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
$user = User::find($journalArray['user_id']);
|
Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
|
||||||
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
if (TransactionType::TRANSFER !== $journal['transaction_type_type']) {
|
||||||
$repository = app(PiggyBankRepositoryInterface::class);
|
Log::info(sprintf('Journal #%d is a "%s" so skip this action.', $journal['transaction_journal_id'], $journal['transaction_type_type']));
|
||||||
$repository->setUser($journal->user);
|
|
||||||
|
|
||||||
// how much can we add to the piggy bank?
|
return false;
|
||||||
$toAdd = bcsub($piggyBank->targetamount, $repository->getCurrentAmount($piggyBank));
|
}
|
||||||
Log::debug(sprintf('Max amount to add to piggy bank is %s, amount is %s', $toAdd, $amount));
|
$user = User::find($journal['user_id']);
|
||||||
|
|
||||||
// update amount to fit:
|
$piggyBank = $this->findPiggybank($user);
|
||||||
$amount = -1 === bccomp($amount, $toAdd) ? $amount : $toAdd;
|
if (null === $piggyBank) {
|
||||||
Log::debug(sprintf('Amount is now %s', $amount));
|
Log::info(
|
||||||
|
sprintf('No piggy bank names "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id)
|
||||||
|
);
|
||||||
|
|
||||||
// if amount is zero, stop.
|
return false;
|
||||||
if (0 === bccomp('0', $amount)) {
|
|
||||||
Log::warning('Amount left is zero, stop.');
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we can add amount:
|
Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name));
|
||||||
if (false === $repository->canAddAmount($piggyBank, $amount)) {
|
|
||||||
Log::warning(sprintf('Cannot add %s to piggy bank.', $amount));
|
|
||||||
|
|
||||||
return;
|
/** @var Transaction $source */
|
||||||
|
$source = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '<', 0)->first();
|
||||||
|
/** @var Transaction $destination */
|
||||||
|
$destination = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '>', 0)->first();
|
||||||
|
|
||||||
|
if ((int)$source->account_id === (int)$piggyBank->account_id) {
|
||||||
|
Log::debug('Piggy bank account is linked to source, so remove amount.');
|
||||||
|
$this->removeAmount($journal, $piggyBank, $destination->amount);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Will now add %s to piggy bank.', $amount));
|
if ((int)$destination->account_id === (int)$piggyBank->account_id) {
|
||||||
|
Log::debug('Piggy bank account is linked to source, so add amount.');
|
||||||
|
$this->addAmount($journal, $piggyBank, $destination->amount);
|
||||||
|
|
||||||
$repository->addAmount($piggyBank, $amount);
|
return true;
|
||||||
$repository->createEventWithJournal($piggyBank, app('steam')->positive($amount), $journal);
|
}
|
||||||
|
Log::info('Piggy bank is not linked to source or destination, so no action will be taken.');
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,8 +116,8 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
*/
|
*/
|
||||||
private function removeAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
private function removeAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
||||||
{
|
{
|
||||||
$user = User::find($journalArray['user_id']);
|
$user = User::find($journalArray['user_id']);
|
||||||
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
||||||
$repository = app(PiggyBankRepositoryInterface::class);
|
$repository = app(PiggyBankRepositoryInterface::class);
|
||||||
$repository->setUser($journal->user);
|
$repository->setUser($journal->user);
|
||||||
|
|
||||||
@ -141,46 +148,41 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @param array $journalArray
|
||||||
|
* @param PiggyBank $piggyBank
|
||||||
|
* @param string $amount
|
||||||
*/
|
*/
|
||||||
public function actOnArray(array $journal): bool
|
private function addAmount(array $journalArray, PiggyBank $piggyBank, string $amount): void
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
|
$user = User::find($journalArray['user_id']);
|
||||||
if (TransactionType::TRANSFER !== $journal['transaction_type_type']) {
|
$journal = $user->transactionJournals()->find($journalArray['transaction_journal_id']);
|
||||||
Log::info(sprintf('Journal #%d is a "%s" so skip this action.', $journal['transaction_journal_id'], $journal['transaction_type_type']));
|
$repository = app(PiggyBankRepositoryInterface::class);
|
||||||
|
$repository->setUser($journal->user);
|
||||||
|
|
||||||
return false;
|
// how much can we add to the piggy bank?
|
||||||
}
|
$toAdd = bcsub($piggyBank->targetamount, $repository->getCurrentAmount($piggyBank));
|
||||||
$user = User::find($journal['user_id']);
|
Log::debug(sprintf('Max amount to add to piggy bank is %s, amount is %s', $toAdd, $amount));
|
||||||
|
|
||||||
$piggyBank = $this->findPiggybank($user);
|
// update amount to fit:
|
||||||
if (null === $piggyBank) {
|
$amount = -1 === bccomp($amount, $toAdd) ? $amount : $toAdd;
|
||||||
Log::info(sprintf('No piggy bank names "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id));
|
Log::debug(sprintf('Amount is now %s', $amount));
|
||||||
|
|
||||||
return false;
|
// if amount is zero, stop.
|
||||||
|
if (0 === bccomp('0', $amount)) {
|
||||||
|
Log::warning('Amount left is zero, stop.');
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name));
|
// make sure we can add amount:
|
||||||
|
if (false === $repository->canAddAmount($piggyBank, $amount)) {
|
||||||
|
Log::warning(sprintf('Cannot add %s to piggy bank.', $amount));
|
||||||
|
|
||||||
/** @var Transaction $source */
|
return;
|
||||||
$source = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '<', 0)->first();
|
|
||||||
/** @var Transaction $destination */
|
|
||||||
$destination = Transaction::where('transaction_journal_id', $journal['transaction_journal_id'])->where('amount', '>', 0)->first();
|
|
||||||
|
|
||||||
if ((int) $source->account_id === (int) $piggyBank->account_id) {
|
|
||||||
Log::debug('Piggy bank account is linked to source, so remove amount.');
|
|
||||||
$this->removeAmount($journal, $piggyBank, $destination->amount);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if ((int) $destination->account_id === (int) $piggyBank->account_id) {
|
Log::debug(sprintf('Will now add %s to piggy bank.', $amount));
|
||||||
Log::debug('Piggy bank account is linked to source, so add amount.');
|
|
||||||
$this->addAmount($journal, $piggyBank, $destination->amount);
|
|
||||||
|
|
||||||
return true;
|
$repository->addAmount($piggyBank, $amount);
|
||||||
}
|
$repository->createEventWithJournal($piggyBank, app('steam')->positive($amount), $journal);
|
||||||
Log::info('Piggy bank is not linked to source or destination, so no action will be taken.');
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -223,7 +223,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
Log::debug(sprintf('Now in findStrictRule(#%d)', $rule->id ?? 0));
|
||||||
$searchArray = [];
|
$searchArray = [];
|
||||||
/** @var RuleTrigger $ruleTrigger */
|
/** @var RuleTrigger $ruleTrigger */
|
||||||
foreach ($rule->ruleTriggers as $ruleTrigger) {
|
foreach ($rule->ruleTriggers()->where('active',1)->get() as $ruleTrigger) {
|
||||||
// if needs no context, value is different:
|
// if needs no context, value is different:
|
||||||
$needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
$needsContext = config(sprintf('firefly.search.operators.%s.needs_context', $ruleTrigger->trigger_type)) ?? true;
|
||||||
if (false === $needsContext) {
|
if (false === $needsContext) {
|
||||||
@ -370,7 +370,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
{
|
{
|
||||||
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id']));
|
||||||
/** @var RuleAction $ruleAction */
|
/** @var RuleAction $ruleAction */
|
||||||
foreach ($rule->ruleActions as $ruleAction) {
|
foreach ($rule->ruleActions()->where('active',1)->get() as $ruleAction) {
|
||||||
$break = $this->processRuleAction($ruleAction, $transaction);
|
$break = $this->processRuleAction($ruleAction, $transaction);
|
||||||
if (true === $break) {
|
if (true === $break) {
|
||||||
break;
|
break;
|
||||||
@ -448,7 +448,7 @@ class SearchRuleEngine implements RuleEngineInterface
|
|||||||
$total = new Collection;
|
$total = new Collection;
|
||||||
$count = 0;
|
$count = 0;
|
||||||
/** @var RuleTrigger $ruleTrigger */
|
/** @var RuleTrigger $ruleTrigger */
|
||||||
foreach ($rule->ruleTriggers as $ruleTrigger) {
|
foreach ($rule->ruleTriggers()->where('active',1)->get() as $ruleTrigger) {
|
||||||
if ('user_action' === $ruleTrigger->trigger_type) {
|
if ('user_action' === $ruleTrigger->trigger_type) {
|
||||||
Log::debug('Skip trigger type.');
|
Log::debug('Skip trigger type.');
|
||||||
continue;
|
continue;
|
||||||
|
Loading…
Reference in New Issue
Block a user