Allow unreconcile and expand API to block reconciled transactions.

This commit is contained in:
James Cole
2023-10-22 18:44:30 +02:00
parent a86a582d0f
commit 2c34bd36a5
50 changed files with 1267 additions and 1046 deletions

View File

@@ -417,15 +417,22 @@ class UpdateRequest extends FormRequest
// all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator);
// user wants to update a reconciled transaction.
// source, destination, amount + foreign_amount cannot be changed
// and must be omitted from the request.
$this->preventUpdateReconciled($validator, $transactionGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// a catch when users submit splits with no source or destination info at all.
$this->preventNoAccountInfo($validator, );
// see method:
//$this->preventNoAccountInfo($validator, );
// validate that the currency fits the source and/or destination account.
// validate all account info
$this->validateAccountInformationUpdate($validator, $transactionGroup);
}
);
}

View File

@@ -25,8 +25,11 @@ namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
@@ -36,8 +39,11 @@ use Illuminate\View\View;
*/
class EditController extends Controller
{
private JournalRepositoryInterface $repository;
/**
* EditController constructor.
* IndexController constructor.
*
*/
@@ -45,17 +51,30 @@ class EditController extends Controller
{
parent::__construct();
// some useful repositories:
// translations:
$this->middleware(
static function ($request, $next) {
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.transactions'));
app('view')->share('mainTitleIcon', 'fa-exchange');
$this->repository = app(JournalRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param TransactionJournal $journal
*
* @return JsonResponse
*/
public function unreconcile(TransactionJournal $journal): JsonResponse
{
$this->repository->unreconcileById($journal->id);
return response()->json([], 204);
}
/**
* @param TransactionGroup $transactionGroup
*

View File

@@ -46,7 +46,7 @@ use Illuminate\Support\Collection;
class JournalRepository implements JournalRepositoryInterface
{
/** @var User */
private $user;
private User $user;
/**
* @param TransactionGroup $transactionGroup
@@ -334,4 +334,14 @@ class JournalRepository implements JournalRepositoryInterface
return $journal;
}
/**
* @inheritDoc
*/
public function unreconcileById(int $journalId): void
{
/** @var TransactionJournal $journal */
$journal = $this->user->transactionJournals()->find($journalId);
$journal?->transactions()->update(['reconciled' => false]);
}
}

View File

@@ -133,6 +133,13 @@ interface JournalRepositoryInterface
*/
public function reconcileById(int $journalId): void;
/**
* TODO Maybe to account repository? Do this wen reconcile is API only.
*
* @param int $journalId
*/
public function unreconcileById(int $journalId): void;
/**
* Search in journal descriptions.
*

View File

@@ -25,7 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\Validation;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
@@ -37,6 +39,50 @@ use Illuminate\Validation\Validator;
trait GroupValidation
{
/**
* @param Validator $validator
* @param TransactionGroup $transactionGroup
*
* @return void
*/
protected function preventUpdateReconciled(Validator $validator, TransactionGroup $transactionGroup): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
$count = Transaction
::leftJoin('transaction_journals', 'transaction_journals.id', 'transactions.transaction_journal_id')
->leftJoin('transaction_groups', 'transaction_groups.id', 'transaction_journals.transaction_group_id')
->where('transaction_journals.transaction_group_id', $transactionGroup->id)
->where('transactions.reconciled', 1)->where('transactions.amount', '<', 0)->count(['transactions.id']);
if (0 === $count) {
app('log')->debug(sprintf('Transaction is not reconciled, done with %s', __METHOD__));
return;
}
$data = $validator->getData();
$forbidden = ['amount','foreign_amount','currency_code','currency_id','foreign_currency_code','foreign_currency_id',
'source_id','source_name','source_number','source_iban',
'destination_id','destination_name','destination_number','destination_iban',
];
foreach($data['transactions'] as $index => $row) {
foreach($forbidden as $key) {
if(array_key_exists($key, $row)) {
$validator->errors()->add(
sprintf('transactions.%d.%s', $index, $key),
(string)trans('validation.reconciled_forbidden_field', ['field' => $key])
);
}
}
}
app('log')->debug(sprintf('Done with %s', __METHOD__));
}
/**
* A catch when users submit splits with no source or destination info at all.
*
* TODO This should prevent errors down the road but I'm not yet sure what I'm validating here
* TODO so I disabled this on 2023-10-22 to see if it causes any issues.
*
* @param Validator $validator
*
* @throws FireflyException

View File

@@ -376,6 +376,11 @@ trait TransactionValidation
public function validateAccountInformationUpdate(Validator $validator, TransactionGroup $transactionGroup): void
{
Log::debug('Now in validateAccountInformationUpdate()');
if ($validator->errors()->count() > 0) {
Log::debug('Validator already has errors, so return.');
return;
}
$transactions = $this->getTransactionsArray($validator);
/**
@@ -699,6 +704,11 @@ trait TransactionValidation
*/
private function validateEqualAccountsForUpdate(Validator $validator, TransactionGroup $transactionGroup): void
{
if ($validator->errors()->count() > 0) {
Log::debug('Validator already has errors, so return.');
return;
}
Log::debug('Now in validateEqualAccountsForUpdate()');
$transactions = $this->getTransactionsArray($validator);