mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-30 18:41:08 +00:00
Display audit logs
This commit is contained in:
@@ -23,6 +23,7 @@ namespace FireflyIII\Handlers\Events;
|
|||||||
|
|
||||||
use FireflyIII\Events\TriggeredAuditLog;
|
use FireflyIII\Events\TriggeredAuditLog;
|
||||||
use FireflyIII\Models\AuditLogEntry;
|
use FireflyIII\Models\AuditLogEntry;
|
||||||
|
use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface;
|
||||||
|
|
||||||
class AuditEventHandler
|
class AuditEventHandler
|
||||||
{
|
{
|
||||||
@@ -33,13 +34,16 @@ class AuditEventHandler
|
|||||||
*/
|
*/
|
||||||
public function storeAuditEvent(TriggeredAuditLog $event)
|
public function storeAuditEvent(TriggeredAuditLog $event)
|
||||||
{
|
{
|
||||||
$auditLogEntry = new AuditLogEntry;
|
$array = [
|
||||||
$auditLogEntry->auditable()->associate($event->auditable);
|
'auditable' => $event->auditable,
|
||||||
$auditLogEntry->changer()->associate($event->changer);
|
'changer' => $event->changer,
|
||||||
$auditLogEntry->action = $event->field;
|
'action' => $event->field,
|
||||||
$auditLogEntry->before = $event->before;
|
'before' => $event->before,
|
||||||
$auditLogEntry->after = $event->after;
|
'after' => $event->after,
|
||||||
$auditLogEntry->save();
|
];
|
||||||
|
/** @var ALERepositoryInterface $repository */
|
||||||
|
$repository = app(ALERepositoryInterface::class);
|
||||||
|
$repository->store($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -27,12 +27,12 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\TransactionGroup;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface;
|
||||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
|
|
||||||
@@ -43,6 +43,7 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
|||||||
class ShowController extends Controller
|
class ShowController extends Controller
|
||||||
{
|
{
|
||||||
private TransactionGroupRepositoryInterface $repository;
|
private TransactionGroupRepositoryInterface $repository;
|
||||||
|
private ALERepositoryInterface $ALERepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ShowController constructor.
|
* ShowController constructor.
|
||||||
@@ -55,6 +56,7 @@ class ShowController extends Controller
|
|||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
$this->repository = app(TransactionGroupRepositoryInterface::class);
|
$this->repository = app(TransactionGroupRepositoryInterface::class);
|
||||||
|
$this->ALERepository = app(ALERepositoryInterface::class);
|
||||||
|
|
||||||
app('view')->share('title', (string) trans('firefly.transactions'));
|
app('view')->share('title', (string) trans('firefly.transactions'));
|
||||||
app('view')->share('mainTitleIcon', 'fa-exchange');
|
app('view')->share('mainTitleIcon', 'fa-exchange');
|
||||||
@@ -108,10 +110,17 @@ class ShowController extends Controller
|
|||||||
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects($groupArray['transactions'][$index]['transaction_journal_id']);
|
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects($groupArray['transactions'][$index]['transaction_journal_id']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get audit log entries:
|
||||||
|
$logEntries = [];
|
||||||
|
foreach($transactionGroup->transactionJournals as $journal) {
|
||||||
|
$logEntries[$journal->id] = $this->ALERepository->getForObject($journal);
|
||||||
|
}
|
||||||
|
|
||||||
$events = $this->repository->getPiggyEvents($transactionGroup);
|
$events = $this->repository->getPiggyEvents($transactionGroup);
|
||||||
$attachments = $this->repository->getAttachments($transactionGroup);
|
$attachments = $this->repository->getAttachments($transactionGroup);
|
||||||
$links = $this->repository->getLinks($transactionGroup);
|
$links = $this->repository->getLinks($transactionGroup);
|
||||||
|
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'transactions.show',
|
'transactions.show',
|
||||||
compact(
|
compact(
|
||||||
@@ -119,6 +128,7 @@ class ShowController extends Controller
|
|||||||
'amounts',
|
'amounts',
|
||||||
'first',
|
'first',
|
||||||
'type',
|
'type',
|
||||||
|
'logEntries',
|
||||||
'subTitle',
|
'subTitle',
|
||||||
'splits',
|
'splits',
|
||||||
'groupArray',
|
'groupArray',
|
||||||
|
@@ -40,6 +40,8 @@ use FireflyIII\Helpers\Report\ReportHelper;
|
|||||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||||
use FireflyIII\Helpers\Webhook\Sha3SignatureGenerator;
|
use FireflyIII\Helpers\Webhook\Sha3SignatureGenerator;
|
||||||
use FireflyIII\Helpers\Webhook\SignatureGeneratorInterface;
|
use FireflyIII\Helpers\Webhook\SignatureGeneratorInterface;
|
||||||
|
use FireflyIII\Repositories\AuditLogEntry\ALERepository;
|
||||||
|
use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface;
|
||||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepository;
|
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepository;
|
||||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
||||||
use FireflyIII\Repositories\TransactionType\TransactionTypeRepository;
|
use FireflyIII\Repositories\TransactionType\TransactionTypeRepository;
|
||||||
@@ -171,6 +173,8 @@ class FireflyServiceProvider extends ServiceProvider
|
|||||||
$this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class);
|
$this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class);
|
||||||
|
|
||||||
$this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class);
|
$this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class);
|
||||||
|
$this->app->bind(ALERepositoryInterface::class, ALERepository::class);
|
||||||
|
|
||||||
$this->app->bind(
|
$this->app->bind(
|
||||||
ObjectGroupRepositoryInterface::class,
|
ObjectGroupRepositoryInterface::class,
|
||||||
static function (Application $app) {
|
static function (Application $app) {
|
||||||
|
56
app/Repositories/AuditLogEntry/ALERepository.php
Normal file
56
app/Repositories/AuditLogEntry/ALERepository.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* ALERepository.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\Repositories\AuditLogEntry;
|
||||||
|
|
||||||
|
use FireflyIII\Models\AuditLogEntry;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ALERepository
|
||||||
|
*/
|
||||||
|
class ALERepository implements ALERepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function store(array $data): AuditLogEntry
|
||||||
|
{
|
||||||
|
$auditLogEntry = new AuditLogEntry;
|
||||||
|
|
||||||
|
$auditLogEntry->auditable()->associate($data['auditable']);
|
||||||
|
$auditLogEntry->changer()->associate($data['changer']);
|
||||||
|
$auditLogEntry->action = $data['field'];
|
||||||
|
$auditLogEntry->before = $data['before'];
|
||||||
|
$auditLogEntry->after = $data['after'];
|
||||||
|
$auditLogEntry->save();
|
||||||
|
return $auditLogEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getForObject(Model $model): Collection
|
||||||
|
{
|
||||||
|
return AuditLogEntry::where('auditable_id', $model->id)->where('auditable_type', get_class($model))->get();
|
||||||
|
}
|
||||||
|
}
|
44
app/Repositories/AuditLogEntry/ALERepositoryInterface.php
Normal file
44
app/Repositories/AuditLogEntry/ALERepositoryInterface.php
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* ALERepositoryInterface.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\Repositories\AuditLogEntry;
|
||||||
|
|
||||||
|
use FireflyIII\Models\AuditLogEntry;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface ALERepositoryInterface
|
||||||
|
*/
|
||||||
|
interface ALERepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @return AuditLogEntry
|
||||||
|
*/
|
||||||
|
public function store(array $data): AuditLogEntry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Model $model
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
public function getForObject(Model $model): Collection;
|
||||||
|
}
|
@@ -55,7 +55,7 @@ class AppendDescription implements ActionInterface
|
|||||||
// event for audit log entry
|
// event for audit log entry
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'update_description', null, $description));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'update_description', $journal['description'], $description));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ class ClearBudget implements ActionInterface
|
|||||||
|
|
||||||
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();
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'remove_budget', $budget->name, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_budget', $budget->name, null));
|
||||||
|
|
||||||
Log::debug(sprintf('RuleAction ClearBudget removed all budgets from journal #%d.', $journal['transaction_journal_id']));
|
Log::debug(sprintf('RuleAction ClearBudget removed all budgets from journal #%d.', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
|
@@ -60,7 +60,7 @@ class ClearCategory implements ActionInterface
|
|||||||
|
|
||||||
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();
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'removed_category', $category->name, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_category', $category->name, null));
|
||||||
|
|
||||||
Log::debug(sprintf('RuleAction ClearCategory removed all categories from journal #%d.', $journal['transaction_journal_id']));
|
Log::debug(sprintf('RuleAction ClearCategory removed all categories from journal #%d.', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
|
@@ -64,7 +64,7 @@ class ClearNotes implements ActionInterface
|
|||||||
->delete();
|
->delete();
|
||||||
Log::debug(sprintf('RuleAction ClearNotes removed all notes from journal #%d.', $journal['transaction_journal_id']));
|
Log::debug(sprintf('RuleAction ClearNotes removed all notes from journal #%d.', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'remove_notes', $before, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_notes', $before, null));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -75,13 +75,13 @@ class ConvertToDeposit implements ActionInterface
|
|||||||
if (TransactionType::WITHDRAWAL === $type) {
|
if (TransactionType::WITHDRAWAL === $type) {
|
||||||
Log::debug('Going to transform a withdrawal to a deposit.');
|
Log::debug('Going to transform a withdrawal to a deposit.');
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::WITHDRAWAL, TransactionType::DEPOSIT));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::DEPOSIT));
|
||||||
|
|
||||||
return $this->convertWithdrawalArray($journal);
|
return $this->convertWithdrawalArray($journal);
|
||||||
}
|
}
|
||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::TRANSFER, TransactionType::DEPOSIT));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::DEPOSIT));
|
||||||
Log::debug('Going to transform a transfer to a deposit.');
|
Log::debug('Going to transform a transfer to a deposit.');
|
||||||
|
|
||||||
return $this->convertTransferArray($journal);
|
return $this->convertTransferArray($journal);
|
||||||
|
@@ -92,7 +92,7 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
if (TransactionType::WITHDRAWAL === $type) {
|
if (TransactionType::WITHDRAWAL === $type) {
|
||||||
Log::debug('Going to transform a withdrawal to a transfer.');
|
Log::debug('Going to transform a withdrawal to a transfer.');
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER));
|
||||||
|
|
||||||
return $this->convertWithdrawalArray($journal, $asset);
|
return $this->convertWithdrawalArray($journal, $asset);
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ class ConvertToTransfer implements ActionInterface
|
|||||||
Log::debug('Going to transform a deposit to a transfer.');
|
Log::debug('Going to transform a deposit to a transfer.');
|
||||||
|
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER));
|
||||||
|
|
||||||
return $this->convertDepositArray($journal, $asset);
|
return $this->convertDepositArray($journal, $asset);
|
||||||
}
|
}
|
||||||
|
@@ -73,14 +73,14 @@ class ConvertToWithdrawal implements ActionInterface
|
|||||||
if (TransactionType::DEPOSIT === $type) {
|
if (TransactionType::DEPOSIT === $type) {
|
||||||
Log::debug('Going to transform a deposit to a withdrawal.');
|
Log::debug('Going to transform a deposit to a withdrawal.');
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::DEPOSIT, TransactionType::WITHDRAWAL));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::WITHDRAWAL));
|
||||||
|
|
||||||
return $this->convertDepositArray($journal);
|
return $this->convertDepositArray($journal);
|
||||||
}
|
}
|
||||||
if (TransactionType::TRANSFER === $type) {
|
if (TransactionType::TRANSFER === $type) {
|
||||||
Log::debug('Going to transform a transfer to a withdrawal.');
|
Log::debug('Going to transform a transfer to a withdrawal.');
|
||||||
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $object, 'change_transaction_type', TransactionType::TRANSFER, TransactionType::WITHDRAWAL));
|
event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::WITHDRAWAL));
|
||||||
|
|
||||||
return $this->convertTransferArray($journal);
|
return $this->convertTransferArray($journal);
|
||||||
}
|
}
|
||||||
|
@@ -63,6 +63,14 @@ class LinkToBill implements ActionInterface
|
|||||||
$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) {
|
||||||
|
$count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id'])
|
||||||
|
->where('bill_id', $bill->id)->count();
|
||||||
|
if (0 !== $count) {
|
||||||
|
Log::error(sprintf('RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.', $journal['transaction_journal_id'], $billName));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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]);
|
||||||
@@ -71,7 +79,7 @@ class LinkToBill implements ActionInterface
|
|||||||
);
|
);
|
||||||
|
|
||||||
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'change_bill', null, $bill->id));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'set_bill', null, $bill->name));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -74,7 +74,7 @@ class MoveNotesToDescription implements ActionInterface
|
|||||||
$note->delete();
|
$note->delete();
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'update_description', $before, $journal->description));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'update_description', $before, $journal->description));
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'remove_notes', $beforeNote, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_notes', $beforeNote, null));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -50,14 +50,19 @@ class RemoveAllTags implements ActionInterface
|
|||||||
*/
|
*/
|
||||||
public function actOnArray(array $journal): bool
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('RuleAction ClearCategory removed all tags from journal %d.', $journal['transaction_journal_id']));
|
|
||||||
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->delete();
|
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->delete();
|
||||||
|
$count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->count();
|
||||||
|
if (0 === $count) {
|
||||||
|
Log::debug(sprintf('RuleAction RemoveAllTags, journal #%d has no tags.', $journal['transaction_journal_id']));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('RuleAction RemoveAllTags removed all tags from journal %d.', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
|
|
||||||
// audit log
|
// audit log
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'remove_all_tags', null, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_all_tags', null, null));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,11 @@ class RemoveTag implements ActionInterface
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
$count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->count();
|
||||||
|
if(0 === $count) {
|
||||||
|
Log::debug(sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag is linked.', $name, $journal['transaction_journal_id']));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal['transaction_journal_id']));
|
Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal['transaction_journal_id']));
|
||||||
DB::table('tag_transaction_journal')
|
DB::table('tag_transaction_journal')
|
||||||
@@ -71,7 +76,7 @@ class RemoveTag implements ActionInterface
|
|||||||
|
|
||||||
/** @var TransactionJournal $journal */
|
/** @var TransactionJournal $journal */
|
||||||
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
$journal = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']);
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journal, 'remove_tag', $tag->tag, null));
|
event(new TriggeredAuditLog($this->action->rule, $journal, 'clear_tag', $tag->tag, null));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ use FireflyIII\Events\TriggeredAuditLog;
|
|||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@@ -61,6 +62,7 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
|
|
||||||
// refresh the transaction type.
|
// refresh the transaction type.
|
||||||
$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']);
|
||||||
$type = TransactionType::find((int) $journalObj->transaction_type_id);
|
$type = TransactionType::find((int) $journalObj->transaction_type_id);
|
||||||
$journal['transaction_type_type'] = $type->type;
|
$journal['transaction_type_type'] = $type->type;
|
||||||
@@ -91,7 +93,7 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
Log::debug('Piggy bank account is linked to source, so remove amount.');
|
Log::debug('Piggy bank account is linked to source, so remove amount.');
|
||||||
$this->removeAmount($journal, $piggyBank, $destination->amount);
|
$this->removeAmount($journal, $piggyBank, $destination->amount);
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journalObj, 'remove_from_piggy', null, ['amount' => $destination->amount, 'piggy' => $piggyBank->name]));
|
event(new TriggeredAuditLog($this->action->rule, $journalObj, 'remove_from_piggy', null, ['currency_symbol' => $journalObj->transactionCurrency->symbol, 'decimal_places' => $journalObj->transactionCurrency->decimal_places, 'amount' => $destination->amount, 'piggy' => $piggyBank->name]));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -99,7 +101,7 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
Log::debug('Piggy bank account is linked to source, so add amount.');
|
Log::debug('Piggy bank account is linked to source, so add amount.');
|
||||||
$this->addAmount($journal, $piggyBank, $destination->amount);
|
$this->addAmount($journal, $piggyBank, $destination->amount);
|
||||||
|
|
||||||
event(new TriggeredAuditLog($this->action->rule, $journalObj, 'add_to_piggy', null, ['amount' => $destination->amount, 'piggy' => $piggyBank->name]));
|
event(new TriggeredAuditLog($this->action->rule, $journalObj, 'add_to_piggy', null, ['currency_symbol' => $journalObj->transactionCurrency->symbol, 'decimal_places' => $journalObj->transactionCurrency->decimal_places, 'amount' => $destination->amount, 'piggy' => $piggyBank->name]));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -2539,4 +2539,25 @@ return [
|
|||||||
// other stuff
|
// other stuff
|
||||||
'placeholder' => '[Placeholder]',
|
'placeholder' => '[Placeholder]',
|
||||||
|
|
||||||
|
// audit log entries
|
||||||
|
'audit_log_entries' => 'Audit log entries',
|
||||||
|
'ale_action_log_add' => 'Add :amount to piggy bank ":name"',
|
||||||
|
'ale_action_log_remove' => 'Remove :amount from piggy bank ":name"',
|
||||||
|
'ale_action_clear_budget' => 'Removed from budget',
|
||||||
|
'ale_action_clear_category' => 'Removed from category',
|
||||||
|
'ale_action_clear_notes' => 'Removed notes',
|
||||||
|
'ale_action_clear_tag' => 'Cleared tag',
|
||||||
|
'ale_action_clear_all_tags' => 'Cleared all tags',
|
||||||
|
'ale_action_set_bill' => 'Linked to bill',
|
||||||
|
'ale_action_set_budget' => 'Set budget',
|
||||||
|
'ale_action_set_category' => 'Set category',
|
||||||
|
'ale_action_set_source' => 'Set source account',
|
||||||
|
'ale_action_set_destination' => 'Set destination account',
|
||||||
|
'ale_action_update_transaction_type' => 'Changed transaction type',
|
||||||
|
'ale_action_update_notes' => 'Changed notes',
|
||||||
|
'ale_action_update_description' => 'Changed description',
|
||||||
|
'ale_action_add_to_piggy' => 'Piggy bank',
|
||||||
|
'ale_action_remove_from_piggy' => 'Piggy bank',
|
||||||
|
'ale_action_add_tag' => 'Added tag',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
89
resources/views/list/ale.twig
Normal file
89
resources/views/list/ale.twig
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<table class="table">
|
||||||
|
{% for logEntry in logEntries %}
|
||||||
|
<tr>
|
||||||
|
<td style="width:20%;">
|
||||||
|
{# link to object: #}
|
||||||
|
{% if 'FireflyIII\\Models\\Rule' == logEntry.changer_type %}
|
||||||
|
<a href="{{ route('rules.edit', [logEntry.changer_id] ) }}">
|
||||||
|
{% endif %}
|
||||||
|
{{ logEntry.changer_type|replace({"FireflyIII\\Models\\": ""}) }}
|
||||||
|
#{{ logEntry.changer_id }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td style="width:30%;">
|
||||||
|
{{ trans('firefly.ale_action_'~logEntry.action) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{# display depends on action #}
|
||||||
|
{% if 'add_tag' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'clear_budget' == logEntry.action %}
|
||||||
|
<code><s>{{ logEntry.before }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'clear_category' == logEntry.action %}
|
||||||
|
<code><s>{{ logEntry.before }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'clear_tag' == logEntry.action %}
|
||||||
|
<code><s>{{ logEntry.before }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'clear_notes' == logEntry.action %}
|
||||||
|
{% if logEntry.before|length > 25 %}
|
||||||
|
<code><s>{{ logEntry.before|slice(0,25) }}...</s></code>
|
||||||
|
{% else %}
|
||||||
|
<code><s>{{ logEntry.before }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'set_bill' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'set_budget' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'set_category' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'set_source' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'set_destination' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'update_transaction_type' == logEntry.action %}
|
||||||
|
{{ trans('firefly.'~logEntry.before) }} → {{ trans('firefly.'~logEntry.after) }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'update_notes' == logEntry.action %}
|
||||||
|
{% if logEntry.before|length > 25 %}
|
||||||
|
<code><s>{{ logEntry.before|slice(0,25) }}...</s></code>
|
||||||
|
{% else %}
|
||||||
|
<code><s>{{ logEntry.before }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
→
|
||||||
|
{% if logEntry.after|length > 25 %}
|
||||||
|
<code>{{ logEntry.after|slice(0,25) }}...</code>
|
||||||
|
{% else %}
|
||||||
|
<code>{{ logEntry.after }}</code>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if 'update_description' == logEntry.action %}
|
||||||
|
<code>{{ logEntry.before }}</code>
|
||||||
|
→
|
||||||
|
<code><s>{{ logEntry.after }}</s></code>
|
||||||
|
{% endif %}
|
||||||
|
{% if 'add_to_piggy' == logEntry.action %}
|
||||||
|
{{ trans('firefly.ale_action_log_add', {amount: formatAmountBySymbol(logEntry.after.amount, logEntry.after.currency_symbol, logEntry.after.decimal_places, true), name: logEntry.after.name})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if 'remove_from_piggy' == logEntry.action %}
|
||||||
|
{{ trans('firefly.ale_action_log_remove', {amount: formatAmountBySymbol(logEntry.after.amount, logEntry.after.currency_symbol, logEntry.after.decimal_places, true), name: logEntry.after.name})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
@@ -46,7 +46,7 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ trans('list.type') }}</td>
|
<td style="width:40%;">{{ trans('list.type') }}</td>
|
||||||
<td>{{ first.transactiontype.type|_ }}</td>
|
<td>{{ first.transactiontype.type|_ }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{% if first.transactiontype.type != 'Withdrawal' or splits == 1 %}
|
{% if first.transactiontype.type != 'Withdrawal' or splits == 1 %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td style="width:40%;">
|
||||||
{{ trans_choice('firefly.source_accounts', accounts['source']|length ) }}
|
{{ trans_choice('firefly.source_accounts', accounts['source']|length ) }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -270,13 +270,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if null != journal.budget_id and first.transactiontype.type == 'Withdrawal' %}
|
{% if null != journal.budget_id and first.transactiontype.type == 'Withdrawal' %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ 'budget'|_ }}</td>
|
<td style="width:40%;">{{ 'budget'|_ }}</td>
|
||||||
<td><a href="{{ route('budgets.show', [journal.budget_id]) }}">{{ journal.budget_name }}</a></td>
|
<td><a href="{{ route('budgets.show', [journal.budget_id]) }}">{{ journal.budget_name }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if null != journal.bill_id and first.transactiontype.type == 'Withdrawal' %}
|
{% if null != journal.bill_id and first.transactiontype.type == 'Withdrawal' %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ 'bill'|_ }}</td>
|
<td style="width:40%;">{{ 'bill'|_ }}</td>
|
||||||
<td><a href="{{ route('bills.show', [journal.bill_id]) }}">{{ journal.bill_name }}</a></td>
|
<td><a href="{{ route('bills.show', [journal.bill_id]) }}">{{ journal.bill_name }}</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -284,7 +284,7 @@
|
|||||||
{% for dateField in ['interest_date','book_date','process_date','due_date','payment_date','invoice_date'] %}
|
{% for dateField in ['interest_date','book_date','process_date','due_date','payment_date','invoice_date'] %}
|
||||||
{% if journalHasMeta(journal.transaction_journal_id, dateField) %}
|
{% if journalHasMeta(journal.transaction_journal_id, dateField) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ trans('list.'~dateField) }}</td>
|
<td style="width:40%;">{{ trans('list.'~dateField) }}</td>
|
||||||
<td>{{ journalGetMetaDate(journal.transaction_journal_id, dateField).isoFormat(monthAndDayFormat) }}</td>
|
<td>{{ journalGetMetaDate(journal.transaction_journal_id, dateField).isoFormat(monthAndDayFormat) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
{% if journalHasMeta(journal.transaction_journal_id, metaField) %}
|
{% if journalHasMeta(journal.transaction_journal_id, metaField) %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ trans('list.'~metaField) }}</td>
|
<td>{{ trans('list.'~metaField) }}</td>
|
||||||
<td>
|
<td style="width:40%;">
|
||||||
{% if 'external_url' == metaField %}
|
{% if 'external_url' == metaField %}
|
||||||
{% set url = journalGetMetaField(journal.transaction_journal_id, metaField) %}
|
{% set url = journalGetMetaField(journal.transaction_journal_id, metaField) %}
|
||||||
<a href="{{ url }}" rel="noopener noreferrer nofollow" target="_blank">
|
<a href="{{ url }}" rel="noopener noreferrer nofollow" target="_blank">
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if null != journal.notes and '' != journal.notes %}
|
{% if null != journal.notes and '' != journal.notes %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ trans('list.notes') }}</td>
|
<td style="width:40%;">{{ trans('list.notes') }}</td>
|
||||||
<td class="markdown">{{ journal.notes|default('')|markdown }}</td>
|
<td class="markdown">{{ journal.notes|default('')|markdown }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -323,13 +323,13 @@
|
|||||||
{% set recurringTotal = '∞' %}
|
{% set recurringTotal = '∞' %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ trans('list.recurring_transaction') }}</td>
|
<td style="width:40%;">{{ trans('list.recurring_transaction') }}</td>
|
||||||
<td>{{ trans('firefly.recurring_info', {total: recurringTotal, count: journalGetMetaField(journal.transaction_journal_id, 'recurring_count') }) }}</td>
|
<td>{{ trans('firefly.recurring_info', {total: recurringTotal, count: journalGetMetaField(journal.transaction_journal_id, 'recurring_count') }) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if journal.tags|length > 0 %}
|
{% if journal.tags|length > 0 %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ 'tags'|_ }}</td>
|
<td style="width:40%;">{{ 'tags'|_ }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% for tag in journal.tags %}
|
{% for tag in journal.tags %}
|
||||||
<h4 style="display: inline;"><a class="label label-success" href="{{ route('tags.show', tag.id) }}">
|
<h4 style="display: inline;"><a class="label label-success" href="{{ route('tags.show', tag.id) }}">
|
||||||
@@ -416,6 +416,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if logEntries[journal.transaction_journal_id]|length > 0 %}
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">
|
||||||
|
{{ 'audit_log_entries'|_ }}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body no-padding">
|
||||||
|
{% include 'list.ale' with {logEntries: logEntries[journal.transaction_journal_id]} %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user