Code cleanup.

This commit is contained in:
James Cole
2023-12-20 19:35:52 +01:00
parent c4f6366642
commit 64ec0cf62e
997 changed files with 12908 additions and 28136 deletions

View File

@@ -28,18 +28,12 @@ use Carbon\Carbon;
use FireflyIII\Events\NewVersionAvailable;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use JsonException;
/**
* Class UpdateRequest
*/
class UpdateRequest implements UpdateRequestInterface
{
/**
* @param string $channel
*
* @return array
*/
public function getUpdateInformation(string $channel): array
{
app('log')->debug(sprintf('Now in getUpdateInformation(%s)', $channel));
@@ -62,11 +56,6 @@ class UpdateRequest implements UpdateRequestInterface
return $this->parseResult($updateInfo);
}
/**
* @param string $channel
*
* @return array
*/
private function contactServer(string $channel): array
{
app('log')->debug(sprintf('Now in contactServer(%s)', $channel));
@@ -80,6 +69,7 @@ class UpdateRequest implements UpdateRequestInterface
$url = config('firefly.update_endpoint');
app('log')->debug(sprintf('Going to call %s', $url));
try {
$client = new Client();
$options = [
@@ -106,9 +96,10 @@ class UpdateRequest implements UpdateRequestInterface
return $return;
}
$body = (string)$res->getBody();
try {
$json = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
} catch (\JsonException $e) {
app('log')->error('Body is not valid JSON');
app('log')->error($body);
$return['message'] = 'Invalid JSON :(';
@@ -137,11 +128,6 @@ class UpdateRequest implements UpdateRequestInterface
return $return;
}
/**
* @param array $information
*
* @return array
*/
private function parseResult(array $information): array
{
app('log')->debug('Now in parseResult()', $information);

View File

@@ -29,10 +29,5 @@ namespace FireflyIII\Services\FireflyIIIOrg\Update;
*/
interface UpdateRequestInterface
{
/**
* @param string $channel
*
* @return array
*/
public function getUpdateInformation(string $channel): array;
}

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\RecurrenceTransaction;
@@ -31,19 +30,12 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Database\Eloquent\Builder;
use stdClass;
/**
* Class AccountDestroyService
*/
class AccountDestroyService
{
/**
* @param Account $account
* @param Account|null $moveTo
*
* @return void
*/
public function destroy(Account $account, ?Account $moveTo): void
{
// find and delete opening balance journal + opposing account
@@ -69,25 +61,55 @@ class AccountDestroyService
$account->delete();
}
/**
* @param Account $account
*/
public function moveTransactions(Account $account, Account $moveTo): void
{
app('log')->debug(sprintf('Move from account #%d to #%d', $account->id, $moveTo->id));
\DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
$collection = Transaction::groupBy('transaction_journal_id', 'account_id')
->where('account_id', $moveTo->id)
->get(['transaction_journal_id', 'account_id', \DB::raw('count(*) as the_count')]) // @phpstan-ignore-line
;
if (0 === $collection->count()) {
return;
}
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
$user = $account->user;
/** @var \stdClass $row */
foreach ($collection as $row) {
if ((int)$row->the_count > 1) {
$journalId = $row->transaction_journal_id;
$journal = $user->transactionJournals()->find($journalId);
if (null !== $journal) {
app('log')->debug(sprintf('Deleted journal #%d because it has the same source as destination.', $journal->id));
$service->destroy($journal);
}
}
}
}
private function destroyOpeningBalance(Account $account): void
{
app('log')->debug(sprintf('Searching for opening balance for account #%d "%s"', $account->id, $account->name));
$set = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionType::OPENING_BALANCE)
->get(['transactions.transaction_journal_id']);
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionType::OPENING_BALANCE)
->get(['transactions.transaction_journal_id'])
;
if ($set->count() > 0) {
$journalId = $set->first()->transaction_journal_id;
app('log')->debug(sprintf('Found opening balance journal with ID #%d', $journalId));
// get transactions with this journal (should be just one):
$transactions = Transaction::where('transaction_journal_id', $journalId)
->where('account_id', '!=', $account->id)
->get();
->where('account_id', '!=', $account->id)
->get()
;
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
app('log')->debug(sprintf('Found transaction with ID #%d', $transaction->id));
@@ -107,72 +129,32 @@ class AccountDestroyService
}
}
/**
* @param Account $account
* @param Account $moveTo
*/
public function moveTransactions(Account $account, Account $moveTo): void
{
app('log')->debug(sprintf('Move from account #%d to #%d', $account->id, $moveTo->id));
DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]);
$collection = Transaction::groupBy('transaction_journal_id', 'account_id')
->where('account_id', $moveTo->id)
->get(['transaction_journal_id', 'account_id', DB::raw('count(*) as the_count')]); // @phpstan-ignore-line
if (0 === $collection->count()) {
return;
}
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
$user = $account->user;
/** @var stdClass $row */
foreach ($collection as $row) {
if ((int)$row->the_count > 1) {
$journalId = $row->transaction_journal_id;
$journal = $user->transactionJournals()->find($journalId);
if (null !== $journal) {
app('log')->debug(sprintf('Deleted journal #%d because it has the same source as destination.', $journal->id));
$service->destroy($journal);
}
}
}
}
/**
* @param Account $account
* @param Account $moveTo
*/
private function updateRecurrences(Account $account, Account $moveTo): void
{
DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]);
DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]);
\DB::table('recurrences_transactions')->where('source_id', $account->id)->update(['source_id' => $moveTo->id]);
\DB::table('recurrences_transactions')->where('destination_id', $account->id)->update(['destination_id' => $moveTo->id]);
}
/**
* @param Account $account
*/
private function destroyJournals(Account $account): void
{
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
app('log')->debug('Now trigger account delete response #' . $account->id);
app('log')->debug('Now trigger account delete response #'.$account->id);
/** @var Transaction $transaction */
foreach ($account->transactions()->get() as $transaction) {
app('log')->debug('Now at transaction #' . $transaction->id);
/** @var TransactionJournal|null $journal */
app('log')->debug('Now at transaction #'.$transaction->id);
/** @var null|TransactionJournal $journal */
$journal = $transaction->transactionJournal()->first();
if (null !== $journal) {
app('log')->debug('Call for deletion of journal #' . $journal->id);
app('log')->debug('Call for deletion of journal #'.$journal->id);
$service->destroy($journal);
}
}
}
/**
* @param Account $account
*/
private function destroyRecurrences(Account $account): void
{
$recurrences = RecurrenceTransaction::where(

View File

@@ -30,9 +30,6 @@ use FireflyIII\Models\Bill;
*/
class BillDestroyService
{
/**
* @param Bill $bill
*/
public function destroy(Bill $bill): void
{
$bill->delete();

View File

@@ -23,19 +23,13 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use DB;
use FireflyIII\Models\Budget;
/**
* Class BudgetDestroyService
*
*/
class BudgetDestroyService
{
/**
* @param Budget $budget
*/
public function destroy(Budget $budget): void
{
$budget->delete();
@@ -46,10 +40,10 @@ class BudgetDestroyService
}
// also delete all relations between categories and transaction journals:
DB::table('budget_transaction_journal')->where('budget_id', $budget->id)->delete();
\DB::table('budget_transaction_journal')->where('budget_id', $budget->id)->delete();
// also delete all relations between categories and transactions:
DB::table('budget_transaction')->where('budget_id', $budget->id)->delete();
\DB::table('budget_transaction')->where('budget_id', $budget->id)->delete();
// also delete all budget limits
foreach ($budget->budgetlimits()->get() as $limit) {

View File

@@ -23,30 +23,24 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use DB;
use FireflyIII\Models\Category;
/**
* Class CategoryDestroyService
*
*/
class CategoryDestroyService
{
/**
* @param Category $category
*/
public function destroy(Category $category): void
{
$category->delete();
// also delete all relations between categories and transaction journals:
DB::table('category_transaction_journal')->where('category_id', $category->id)->delete();
\DB::table('category_transaction_journal')->where('category_id', $category->id)->delete();
// also delete all relations between categories and transactions:
DB::table('category_transaction')->where('category_id', $category->id)->delete();
\DB::table('category_transaction')->where('category_id', $category->id)->delete();
// delete references to category from recurring transactions.
DB::table('rt_meta')->where('name', 'category_id')->where('value', $category->id)->delete();
\DB::table('rt_meta')->where('name', 'category_id')->where('value', $category->id)->delete();
}
}

View File

@@ -27,14 +27,9 @@ use FireflyIII\Models\TransactionCurrency;
/**
* Class CurrencyDestroyService
*
*/
class CurrencyDestroyService
{
/**
* @param TransactionCurrency $currency
*/
public function destroy(TransactionCurrency $currency): void
{
$currency->delete();

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use DB;
use FireflyIII\Models\Attachment;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
@@ -35,12 +34,10 @@ use FireflyIII\Models\TransactionJournalMeta;
*/
class JournalDestroyService
{
/**
* @param TransactionJournal $journal
*/
public function destroy(TransactionJournal $journal): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
app('log')->debug(sprintf('Will now delete transaction #%d', $transaction->id));
@@ -61,16 +58,19 @@ class JournalDestroyService
}
// delete all from 'budget_transaction_journal'
DB::table('budget_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete();
\DB::table('budget_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete()
;
// delete all from 'category_transaction_journal'
DB::table('category_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete();
\DB::table('category_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete()
;
// delete all from 'tag_transaction_journal'
DB::table('tag_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete();
\DB::table('tag_transaction_journal')
->where('transaction_journal_id', $journal->id)->delete()
;
// delete all links:
TransactionJournalLink::where('source_id', $journal->id)->delete();

View File

@@ -33,8 +33,6 @@ class RecurrenceDestroyService
{
/**
* Delete recurrence by ID
*
* @param int $recurrenceId
*/
public function destroyById(int $recurrenceId): void
{
@@ -47,14 +45,12 @@ class RecurrenceDestroyService
/**
* Delete recurrence.
*
* @param Recurrence $recurrence
*
*/
public function destroy(Recurrence $recurrence): void
{
// delete all meta data
$recurrence->recurrenceMeta()->delete();
// delete all transactions.
/** @var RecurrenceTransaction $transaction */
foreach ($recurrence->recurrenceTransactions as $transaction) {

View File

@@ -28,17 +28,13 @@ use FireflyIII\Models\TransactionGroup;
/**
* Class TransactionGroupDestroyService
*
*/
class TransactionGroupDestroyService
{
/**
* @param TransactionGroup $transactionGroup
*/
public function destroy(TransactionGroup $transactionGroup): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
foreach ($transactionGroup->transactionJournals as $journal) {

View File

@@ -38,22 +38,14 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService;
use JsonException;
use Validator;
/**
* Trait AccountServiceTrait
*
*/
trait AccountServiceTrait
{
protected AccountRepositoryInterface $accountRepository;
/**
* @param null|string $iban
*
* @return null|string
*/
public function filterIban(?string $iban): ?string
{
if (null === $iban) {
@@ -61,23 +53,18 @@ trait AccountServiceTrait
}
$data = ['iban' => $iban];
$rules = ['iban' => 'required|iban'];
$validator = Validator::make($data, $rules);
$validator = \Validator::make($data, $rules);
if ($validator->fails()) {
app('log')->info(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban));
return null;
}
return app('steam')->filterSpaces($iban);
}
/**
* Returns true if the data in the array is submitted but empty.
*
* @param array $data
*
* @return bool
*/
public function isEmptyOBData(array $data): bool
{
@@ -102,15 +89,11 @@ trait AccountServiceTrait
* Update metadata for account. Depends on type which fields are valid.
*
* TODO this method treats expense accounts and liabilities the same way (tries to save interest)
*
* @param Account $account
* @param array $data
*
*/
public function updateMetaData(Account $account, array $data): void
{
$fields = $this->validFields;
if ($account->accountType->type === AccountType::ASSET) {
if (AccountType::ASSET === $account->accountType->type) {
$fields = $this->validAssetFields;
}
@@ -119,7 +102,7 @@ trait AccountServiceTrait
$list = config('firefly.valid_currency_account_types');
if (!in_array($type, $list, true)) {
$pos = array_search('currency_id', $fields, true);
if ($pos !== false) {
if (false !== $pos) {
unset($fields[$pos]);
}
}
@@ -133,13 +116,14 @@ trait AccountServiceTrait
}
// only asset account may have a role:
if ($account->accountType->type !== AccountType::ASSET) {
if (AccountType::ASSET !== $account->accountType->type) {
$data['account_role'] = '';
}
if ($account->accountType->type === AccountType::ASSET && 'ccAsset' === $data['account_role']) {
if (AccountType::ASSET === $account->accountType->type && 'ccAsset' === $data['account_role']) {
$fields = $this->validCCFields;
}
/** @var AccountMetaFactory $factory */
$factory = app(AccountMetaFactory::class);
foreach ($fields as $field) {
@@ -162,12 +146,6 @@ trait AccountServiceTrait
}
}
/**
* @param Account $account
* @param string $note
*
* @return bool
*/
public function updateNote(Account $account, string $note): bool
{
$dbNote = $account->notes()->first();
@@ -190,10 +168,6 @@ trait AccountServiceTrait
/**
* Verify if array contains valid data to possibly store or update the opening balance.
*
* @param array $data
*
* @return bool
*/
public function validOBData(array $data): bool
{
@@ -213,12 +187,9 @@ trait AccountServiceTrait
}
/**
* @param Account $account
* @param array $data
*
* @return TransactionGroup
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*
* @deprecated
*/
protected function createOBGroup(Account $account, array $data): TransactionGroup
@@ -250,6 +221,7 @@ trait AccountServiceTrait
// amount is 0
if (0 === bccomp($amount, '0')) {
app('log')->debug('Amount is zero, so will not make an OB group.');
throw new FireflyException('Amount for new opening balance was unexpectedly 0.');
}
@@ -303,6 +275,7 @@ trait AccountServiceTrait
} catch (DuplicateTransactionException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
@@ -311,8 +284,6 @@ trait AccountServiceTrait
/**
* Delete TransactionGroup with liability credit in it.
*
* @param Account $account
*/
protected function deleteCreditTransaction(Account $account): void
{
@@ -321,6 +292,7 @@ trait AccountServiceTrait
if (null !== $creditGroup) {
app('log')->debug('Credit journal found, delete journal.');
/** @var TransactionGroupDestroyService $service */
$service = app(TransactionGroupDestroyService::class);
$service->destroy($creditGroup);
@@ -329,10 +301,6 @@ trait AccountServiceTrait
/**
* Returns the credit transaction group, or NULL if it does not exist.
*
* @param Account $account
*
* @return TransactionGroup|null
*/
protected function getCreditTransaction(Account $account): ?TransactionGroup
{
@@ -343,8 +311,6 @@ trait AccountServiceTrait
/**
* Delete TransactionGroup with opening balance in it.
*
* @param Account $account
*/
protected function deleteOBGroup(Account $account): void
{
@@ -354,6 +320,7 @@ trait AccountServiceTrait
// opening balance data? update it!
if (null !== $openingBalanceGroup) {
app('log')->debug('Opening balance journal found, delete journal.');
/** @var TransactionGroupDestroyService $service */
$service = app(TransactionGroupDestroyService::class);
$service->destroy($openingBalanceGroup);
@@ -362,10 +329,6 @@ trait AccountServiceTrait
/**
* Returns the opening balance group, or NULL if it does not exist.
*
* @param Account $account
*
* @return TransactionGroup|null
*/
protected function getOBGroup(Account $account): ?TransactionGroup
{
@@ -373,19 +336,16 @@ trait AccountServiceTrait
}
/**
* @param int $currencyId
* @param string $currencyCode
*
* @return TransactionCurrency
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency
{
// find currency, or use default currency instead.
/** @var TransactionCurrencyFactory $factory */
$factory = app(TransactionCurrencyFactory::class);
/** @var TransactionCurrency|null $currency */
/** @var null|TransactionCurrency $currency */
$currency = $factory->find($currencyId, $currencyCode);
if (null === $currency) {
@@ -401,15 +361,8 @@ trait AccountServiceTrait
/**
* Create the opposing "credit liability" transaction for credit liabilities.
*
*
* @param Account $account
* @param string $direction
* @param string $openingBalance
* @param Carbon $openingBalanceDate
*
* @return TransactionGroup
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function updateCreditTransaction(Account $account, string $direction, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup
{
@@ -417,6 +370,7 @@ trait AccountServiceTrait
if (0 === bccomp($openingBalance, '0')) {
app('log')->debug('Amount is zero, so will not update liability credit/debit group.');
throw new FireflyException('Amount for update liability credit/debit was unexpectedly 0.');
}
// if direction is "debit" (i owe this debt), amount is negative.
@@ -464,13 +418,8 @@ trait AccountServiceTrait
}
/**
* @param Account $account
* @param string $openingBalance
* @param Carbon $openingBalanceDate
*
* @return TransactionGroup
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function createCreditTransaction(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup
{
@@ -478,6 +427,7 @@ trait AccountServiceTrait
if (0 === bccomp($openingBalance, '0')) {
app('log')->debug('Amount is zero, so will not make an liability credit group.');
throw new FireflyException('Amount for new liability credit was unexpectedly 0.');
}
@@ -552,80 +502,19 @@ trait AccountServiceTrait
} catch (DuplicateTransactionException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
return $group;
}
/**
* TODO refactor to "getfirstjournal"
*
* @param TransactionGroup $group
*
* @return TransactionJournal
* @throws FireflyException
*/
private function getObJournal(TransactionGroup $group): TransactionJournal
{
/** @var TransactionJournal|null $journal */
$journal = $group->transactionJournals()->first();
if (null === $journal) {
throw new FireflyException(sprintf('Group #%d has no OB journal', $group->id));
}
return $journal;
}
/**
* TODO Rename to getOpposingTransaction
*
* @param TransactionJournal $journal
* @param Account $account
*
* @return Transaction
* @throws FireflyException
*/
private function getOBTransaction(TransactionJournal $journal, Account $account): Transaction
{
/** @var Transaction|null $transaction */
$transaction = $journal->transactions()->where('account_id', '!=', $account->id)->first();
if (null === $transaction) {
throw new FireflyException(sprintf('Could not get OB transaction for journal #%d', $journal->id));
}
return $transaction;
}
/**
* @param TransactionJournal $journal
* @param Account $account
*
* @return Transaction
* @throws FireflyException
*/
private function getNotOBTransaction(TransactionJournal $journal, Account $account): Transaction
{
/** @var Transaction|null $transaction */
$transaction = $journal->transactions()->where('account_id', $account->id)->first();
if (null === $transaction) {
throw new FireflyException(sprintf('Could not get non-OB transaction for journal #%d', $journal->id));
}
return $transaction;
}
/**
* Update or create the opening balance group.
* Since opening balance and date can still be empty strings, it may fail.
*
* @param Account $account
* @param string $openingBalance
* @param Carbon $openingBalanceDate
*
* @return TransactionGroup
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function updateOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup
{
@@ -650,7 +539,6 @@ trait AccountServiceTrait
$journal->date = $openingBalanceDate;
$journal->transactionCurrency()->associate($currency);
// if amount is negative:
if (1 === bccomp('0', $openingBalance)) {
app('log')->debug('Amount is negative.');
@@ -682,13 +570,8 @@ trait AccountServiceTrait
}
/**
* @param Account $account
* @param string $openingBalance
* @param Carbon $openingBalanceDate
*
* @return TransactionGroup
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function createOBGroupV2(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup
{
@@ -718,6 +601,7 @@ trait AccountServiceTrait
// amount is 0
if (0 === bccomp($openingBalance, '0')) {
app('log')->debug('Amount is zero, so will not make an OB group.');
throw new FireflyException('Amount for new opening balance was unexpectedly 0.');
}
@@ -771,9 +655,56 @@ trait AccountServiceTrait
} catch (DuplicateTransactionException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
throw new FireflyException($e->getMessage(), 0, $e);
}
return $group;
}
/**
* TODO refactor to "getfirstjournal"
*
* @throws FireflyException
*/
private function getObJournal(TransactionGroup $group): TransactionJournal
{
/** @var null|TransactionJournal $journal */
$journal = $group->transactionJournals()->first();
if (null === $journal) {
throw new FireflyException(sprintf('Group #%d has no OB journal', $group->id));
}
return $journal;
}
/**
* TODO Rename to getOpposingTransaction
*
* @throws FireflyException
*/
private function getOBTransaction(TransactionJournal $journal, Account $account): Transaction
{
/** @var null|Transaction $transaction */
$transaction = $journal->transactions()->where('account_id', '!=', $account->id)->first();
if (null === $transaction) {
throw new FireflyException(sprintf('Could not get OB transaction for journal #%d', $journal->id));
}
return $transaction;
}
/**
* @throws FireflyException
*/
private function getNotOBTransaction(TransactionJournal $journal, Account $account): Transaction
{
/** @var null|Transaction $transaction */
$transaction = $journal->transactions()->where('account_id', $account->id)->first();
if (null === $transaction) {
throw new FireflyException(sprintf('Could not get non-OB transaction for journal #%d', $journal->id));
}
return $transaction;
}
}

View File

@@ -29,16 +29,9 @@ use FireflyIII\Models\RuleAction;
/**
* Trait BillServiceTrait
*
*/
trait BillServiceTrait
{
/**
* @param Bill $bill
* @param string $oldName
* @param string $newName
*/
public function updateBillActions(Bill $bill, string $oldName, string $newName): void
{
if ($oldName === $newName) {
@@ -46,8 +39,9 @@ trait BillServiceTrait
}
$ruleIds = $bill->user->rules()->get(['id'])->pluck('id')->toArray();
$set = RuleAction::whereIn('rule_id', $ruleIds)
->where('action_type', 'link_to_bill')
->where('action_value', $oldName)->get();
->where('action_type', 'link_to_bill')
->where('action_value', $oldName)->get()
;
/** @var RuleAction $ruleAction */
foreach ($set as $ruleAction) {
@@ -57,12 +51,6 @@ trait BillServiceTrait
}
}
/**
* @param Bill $bill
* @param string $note
*
* @return bool
*/
public function updateNote(Bill $bill, string $note): bool
{
if ('' === $note) {

View File

@@ -53,9 +53,6 @@ class CreditRecalculateService
$this->work = [];
}
/**
*
*/
public function recalculate(): void
{
if (true !== config('firefly.feature_flags.handle_debts')) {
@@ -74,9 +71,16 @@ class CreditRecalculateService
$this->processWork();
}
/**
*
*/
public function setAccount(?Account $account): void
{
$this->account = $account;
}
public function setGroup(TransactionGroup $group): void
{
$this->group = $group;
}
private function processGroup(): void
{
/** @var TransactionJournal $journal */
@@ -91,8 +95,6 @@ class CreditRecalculateService
}
/**
* @param TransactionJournal $journal
*
* @throws FireflyException
*/
private function findByJournal(TransactionJournal $journal): void
@@ -111,9 +113,6 @@ class CreditRecalculateService
}
/**
* @param TransactionJournal $journal
*
* @return Account
* @throws FireflyException
*/
private function getSourceAccount(TransactionJournal $journal): Account
@@ -122,20 +121,17 @@ class CreditRecalculateService
}
/**
* @param TransactionJournal $journal
* @param string $direction
*
* @return Account
* @throws FireflyException
*/
private function getAccountByDirection(TransactionJournal $journal, string $direction): Account
{
/** @var Transaction|null $transaction */
/** @var null|Transaction $transaction */
$transaction = $journal->transactions()->where('amount', $direction, '0')->first();
if (null === $transaction) {
throw new FireflyException(sprintf('Cannot find "%s"-transaction of journal #%d', $direction, $journal->id));
}
/** @var Account|null $foundAccount */
/** @var null|Account $foundAccount */
$foundAccount = $transaction->account;
if (null === $foundAccount) {
throw new FireflyException(sprintf('Cannot find "%s"-account of transaction #%d of journal #%d', $direction, $transaction->id, $journal->id));
@@ -145,9 +141,6 @@ class CreditRecalculateService
}
/**
* @param TransactionJournal $journal
*
* @return Account
* @throws FireflyException
*/
private function getDestinationAccount(TransactionJournal $journal): Account
@@ -155,9 +148,6 @@ class CreditRecalculateService
return $this->getAccountByDirection($journal, '>');
}
/**
*
*/
private function processAccount(): void
{
$valid = config('firefly.valid_liabilities');
@@ -166,9 +156,6 @@ class CreditRecalculateService
}
}
/**
*
*/
private function processWork(): void
{
$this->repository = app(AccountRepositoryInterface::class);
@@ -177,9 +164,6 @@ class CreditRecalculateService
}
}
/**
* @param Account $account
*/
private function processWorkAccount(Account $account): void
{
app('log')->debug(sprintf('Now processing account #%d ("%s")', $account->id, $account->name));
@@ -210,11 +194,13 @@ class CreditRecalculateService
// now loop all transactions (except opening balance and credit thing)
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->orderBy('transaction_journals.date', 'ASC')
->get(['transactions.*']);
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->orderBy('transaction_journals.date', 'ASC')
->get(['transactions.*'])
;
$total = $transactions->count();
app('log')->debug(sprintf('Found %d transaction(s) to process.', $total));
/** @var Transaction $transaction */
foreach ($transactions as $index => $transaction) {
app('log')->debug(sprintf('[%d/%d] Processing transaction.', $index + 1, $total));
@@ -226,16 +212,12 @@ class CreditRecalculateService
/**
* If account direction is "debit" ("I owe this amount") the opening balance must always be AWAY from the account:
*
* @param Account $account
* @param TransactionJournal $openingBalance
*
* @return void
*/
private function validateOpeningBalance(Account $account, TransactionJournal $openingBalance)
{
/** @var Transaction $source */
$source = $openingBalance->transactions()->where('amount', '<', 0)->first();
/** @var Transaction $dest */
$dest = $openingBalance->transactions()->where('amount', '>', 0)->first();
if ($source->account_id !== $account->id) {
@@ -255,19 +237,12 @@ class CreditRecalculateService
}
$source->save();
$dest->save();
return;
}
app('log')->debug('Opening balance is valid');
}
/**
* @param Account $account
* @param string $direction
* @param Transaction $transaction
* @param string $leftOfDebt
*
* @return string
*/
private function processTransaction(Account $account, string $direction, Transaction $transaction, string $leftOfDebt): string
{
$journal = $transaction->transactionJournal;
@@ -275,20 +250,23 @@ class CreditRecalculateService
$accountCurrency = $this->repository->getAccountCurrency($account);
$decimals = $accountCurrency->decimal_places;
$type = $journal->transactionType->type;
/** @var Transaction $destTransaction */
$destTransaction = $journal->transactions()->where('amount', '>', '0')->first();
/** @var Transaction $sourceTransaction */
$sourceTransaction = $journal->transactions()->where('amount', '<', '0')->first();
app('log')->debug(sprintf('Left of debt is: %s', app('steam')->bcround($leftOfDebt, $decimals)));
if ('' === $direction) {
app('log')->warning('Direction is empty, so do nothing.');
return $leftOfDebt;
}
if (TransactionType::LIABILITY_CREDIT === $type || TransactionType::OPENING_BALANCE === $type) {
app('log')->warning(sprintf('Transaction type is "%s", so do nothing.', $type));
return $leftOfDebt;
}
@@ -305,7 +283,7 @@ class CreditRecalculateService
// if it's a credit ("I am owed"), this increases the amount due,
// because we're lending person X more money
if (
$type === TransactionType::WITHDRAWAL
TransactionType::WITHDRAWAL === $type
&& $account->id === $transaction->account_id
&& 1 === bccomp($usedAmount, '0')
&& 'credit' === $direction
@@ -313,6 +291,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 1 (withdrawal into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
@@ -321,7 +300,7 @@ class CreditRecalculateService
// if it's a credit ("I am owed"), this decreases the amount due,
// because we're sending money away from the loan (like loan forgiveness)
if (
$type === TransactionType::WITHDRAWAL
TransactionType::WITHDRAWAL === $type
&& $account->id === $sourceTransaction->account_id
&& -1 === bccomp($usedAmount, '0')
&& 'credit' === $direction
@@ -329,6 +308,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcsub($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 2 (withdrawal away from liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
@@ -337,7 +317,7 @@ class CreditRecalculateService
// if it's a credit ("I am owed") this decreases the amount due.
// because the person is paying us back.
if (
$type === TransactionType::DEPOSIT
TransactionType::DEPOSIT === $type
&& $account->id === $transaction->account_id
&& -1 === bccomp($usedAmount, '0')
&& 'credit' === $direction
@@ -345,6 +325,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcsub($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 3 (deposit away from liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
@@ -353,7 +334,7 @@ class CreditRecalculateService
// if it's a credit ("I am owed") this increases the amount due.
// because the person is having to pay more money.
if (
$type === TransactionType::DEPOSIT
TransactionType::DEPOSIT === $type
&& $account->id === $destTransaction->account_id
&& 1 === bccomp($usedAmount, '0')
&& 'credit' === $direction
@@ -361,13 +342,14 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 4 (deposit into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
// case 5: transfer into loan (from other loan).
// if it's a credit ("I am owed") this increases the amount due,
// because the person has to pay more back.
if (
$type === TransactionType::TRANSFER
TransactionType::TRANSFER === $type
&& $account->id === $destTransaction->account_id
&& 1 === bccomp($usedAmount, '0')
&& 'credit' === $direction
@@ -375,6 +357,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 5 (transfer into credit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
// Case 6
@@ -382,7 +365,7 @@ class CreditRecalculateService
// if it's a debit ("I owe this amount"), this decreases the amount due,
// because we're paying off the debt
if (
$type === TransactionType::WITHDRAWAL
TransactionType::WITHDRAWAL === $type
&& $account->id === $transaction->account_id
&& 1 === bccomp($usedAmount, '0')
&& 'debit' === $direction
@@ -390,6 +373,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcsub($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 6 (withdrawal into debit liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
// case 7
@@ -397,7 +381,7 @@ class CreditRecalculateService
// if it's a credit ("I am owed") this increases the amount due.
// because we are borrowing more money.
if (
$type === TransactionType::DEPOSIT
TransactionType::DEPOSIT === $type
&& $account->id === $transaction->account_id
&& -1 === bccomp($usedAmount, '0')
&& 'debit' === $direction
@@ -405,6 +389,7 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 7 (deposit away from liability): %s - %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
// case 8
@@ -412,7 +397,7 @@ class CreditRecalculateService
// if it's a debit ("I owe this amount") this increase the amount due.
// because we are paying interest.
if (
$type === TransactionType::WITHDRAWAL
TransactionType::WITHDRAWAL === $type
&& $account->id === $transaction->account_id
&& -1 === bccomp($usedAmount, '0')
&& 'debit' === $direction
@@ -420,15 +405,16 @@ class CreditRecalculateService
$usedAmount = app('steam')->positive($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case 8 (withdrawal away from liability): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
// in any other case, remove amount from left of debt.
if (in_array($type, [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER], true)) {
$usedAmount = app('steam')->negative($usedAmount);
$result = bcadd($leftOfDebt, $usedAmount);
app('log')->debug(sprintf('Case X (all other cases): %s + %s = %s', app('steam')->bcround($leftOfDebt, $decimals), app('steam')->bcround($usedAmount, $decimals), app('steam')->bcround($result, $decimals)));
return $result;
}
@@ -436,20 +422,4 @@ class CreditRecalculateService
return $leftOfDebt;
}
/**
* @param Account|null $account
*/
public function setAccount(?Account $account): void
{
$this->account = $account;
}
/**
* @param TransactionGroup $group
*/
public function setGroup(TransactionGroup $group): void
{
$this->group = $group;
}
}

View File

@@ -38,7 +38,6 @@ use FireflyIII\Support\NullArrayObject;
/**
* Trait JournalServiceTrait
*
*/
trait JournalServiceTrait
{
@@ -48,11 +47,6 @@ trait JournalServiceTrait
private TagFactory $tagFactory;
/**
* @param string $transactionType
* @param string $direction
* @param array $data
*
* @return Account|null
* @throws FireflyException
*/
protected function getAccount(string $transactionType, string $direction, array $data): ?Account
@@ -89,7 +83,6 @@ trait JournalServiceTrait
// the account that Firefly III creates must be "creatable", aka select the one we can create from the list just in case
$creatableType = $this->getCreatableType($expectedTypes[$transactionType]);
// if the result is NULL but the ID is set, an account could exist of the wrong type.
// that data can be used to create a new account of the right type.
if (null === $result && null !== $data['id'] && null !== $creatableType) {
@@ -113,15 +106,128 @@ trait JournalServiceTrait
app('log')->debug('If cant be created, return cash account.');
$result = $this->getCashAccount($result, $data, $expectedTypes[$transactionType]);
}
return $result;
}
/**
* @param array $data
* @param array $types
*
* @return Account|null
* @throws FireflyException
*/
protected function getAmount(string $amount): string
{
if ('' === $amount) {
throw new FireflyException(sprintf('The amount cannot be an empty string: "%s"', $amount));
}
app('log')->debug(sprintf('Now in getAmount("%s")', $amount));
if (0 === bccomp('0', $amount)) {
throw new FireflyException(sprintf('The amount seems to be zero: "%s"', $amount));
}
return $amount;
}
protected function getForeignAmount(?string $amount): ?string
{
if (null === $amount) {
app('log')->debug('No foreign amount info in array. Return NULL');
return null;
}
if ('' === $amount) {
app('log')->debug('Foreign amount is empty string, return NULL.');
return null;
}
if (0 === bccomp('0', $amount)) {
app('log')->debug('Foreign amount is 0.0, return NULL.');
return null;
}
app('log')->debug(sprintf('Foreign amount is %s', $amount));
return $amount;
}
protected function storeBudget(TransactionJournal $journal, NullArrayObject $data): void
{
if (TransactionType::WITHDRAWAL !== $journal->transactionType->type) {
$journal->budgets()->sync([]);
return;
}
$budget = $this->budgetRepository->findBudget($data['budget_id'], $data['budget_name']);
if (null !== $budget) {
app('log')->debug(sprintf('Link budget #%d to journal #%d', $budget->id, $journal->id));
$journal->budgets()->sync([$budget->id]);
return;
}
// if the budget is NULL, sync empty.
$journal->budgets()->sync([]);
}
protected function storeCategory(TransactionJournal $journal, NullArrayObject $data): void
{
$category = $this->categoryRepository->findCategory($data['category_id'], $data['category_name']);
if (null !== $category) {
app('log')->debug(sprintf('Link category #%d to journal #%d', $category->id, $journal->id));
$journal->categories()->sync([$category->id]);
return;
}
// if the category is NULL, sync empty.
$journal->categories()->sync([]);
}
protected function storeNotes(TransactionJournal $journal, ?string $notes): void
{
$notes = (string)$notes;
$note = $journal->notes()->first();
if ('' !== $notes) {
if (null === $note) {
$note = new Note();
$note->noteable()->associate($journal);
}
$note->text = $notes;
$note->save();
app('log')->debug(sprintf('Stored notes for journal #%d', $journal->id));
return;
}
// try to delete existing notes.
$note?->delete();
}
/**
* Link tags to journal.
*/
protected function storeTags(TransactionJournal $journal, ?array $tags): void
{
app('log')->debug('Now in storeTags()', $tags ?? []);
$this->tagFactory->setUser($journal->user);
$set = [];
if (!is_array($tags)) {
app('log')->debug('Tags is not an array, break.');
return;
}
app('log')->debug('Start of loop.');
foreach ($tags as $string) {
$string = (string)$string;
app('log')->debug(sprintf('Now at tag "%s"', $string));
if ('' !== $string) {
$tag = $this->tagFactory->findOrCreate($string);
if (null !== $tag) {
$set[] = $tag->id;
}
}
}
$set = array_unique($set);
app('log')->debug('End of loop.');
app('log')->debug(sprintf('Total nr. of tags: %d', count($tags)), $tags);
$journal->tags()->sync($set);
}
private function findAccountById(array $data, array $types): ?Account
{
// first attempt, find by ID.
@@ -131,34 +237,32 @@ trait JournalServiceTrait
app('log')->debug(
sprintf('Found "account_id" object: #%d, "%s" of type %s (1)', $search->id, $search->name, $search->accountType->type)
);
return $search;
}
if (null !== $search && 0 === count($types)) {
app('log')->debug(
sprintf('Found "account_id" object: #%d, "%s" of type %s (2)', $search->id, $search->name, $search->accountType->type)
);
return $search;
}
}
app('log')->debug(sprintf('Found no account by ID #%d of types', $data['id']), $types);
return null;
}
/**
* @param Account|null $account
* @param array $data
* @param array $types
*
* @return Account|null
*/
private function findAccountByIban(?Account $account, array $data, array $types): ?Account
{
if (null !== $account) {
app('log')->debug(sprintf('Already have account #%d ("%s"), return that.', $account->id, $account->name));
return $account;
}
if (null === $data['iban'] || '' === $data['iban']) {
app('log')->debug('IBAN is empty, will not search for IBAN.');
return null;
}
// find by preferred type.
@@ -172,24 +276,20 @@ trait JournalServiceTrait
return $source;
}
app('log')->debug(sprintf('Found no account with IBAN "%s" of expected types', $data['iban']), $types);
return null;
}
/**
* @param Account|null $account
* @param array $data
* @param array $types
*
* @return Account|null
*/
private function findAccountByNumber(?Account $account, array $data, array $types): ?Account
{
if (null !== $account) {
app('log')->debug(sprintf('Already have account #%d ("%s"), return that.', $account->id, $account->name));
return $account;
}
if (null === $data['number'] || '' === $data['number']) {
app('log')->debug('Account number is empty, will not search for account number.');
return null;
}
// find by preferred type.
@@ -205,24 +305,20 @@ trait JournalServiceTrait
}
app('log')->debug(sprintf('Found no account with account number "%s" of expected types', $data['number']), $types);
return null;
}
/**
* @param Account|null $account
* @param array $data
* @param array $types
*
* @return Account|null
*/
private function findAccountByName(?Account $account, array $data, array $types): ?Account
{
if (null !== $account) {
app('log')->debug(sprintf('Already have account #%d ("%s"), return that.', $account->id, $account->name));
return $account;
}
if (null === $data['name'] || '' === $data['name']) {
app('log')->debug('Account name is empty, will not search for account name.');
return null;
}
@@ -238,34 +334,28 @@ trait JournalServiceTrait
return $source;
}
app('log')->debug(sprintf('Found no account with account name "%s" of expected types', $data['name']), $types);
return null;
}
/**
* @param array $types
*
* @return null|string
*/
private function getCreatableType(array $types): ?string
{
$result = null;
$list = config('firefly.dynamic_creation_allowed');
/** @var string $type */
foreach ($types as $type) {
if (true === in_array($type, $list, true)) {
$result = $type;
break;
}
}
return $result;
}
/**
* @param Account|null $account
* @param array $data
* @param string $preferredType
*
* @return Account|null
* @throws FireflyException
*/
private function createAccount(?Account $account, array $data, string $preferredType): ?Account
@@ -300,9 +390,10 @@ trait JournalServiceTrait
// if name is still NULL, return NULL.
if ('' === (string)$data['name']) {
app('log')->debug('Account name is still NULL, return NULL.');
return null;
}
//$data['name'] = $data['name'] ?? '(no name)';
// $data['name'] = $data['name'] ?? '(no name)';
$account = $this->accountRepository->store(
[
@@ -333,13 +424,6 @@ trait JournalServiceTrait
return $account;
}
/**
* @param Account|null $account
* @param array $data
* @param array $types
*
* @return Account|null
*/
private function getCashAccount(?Account $account, array $data, array $types): ?Account
{
// return cash account.
@@ -348,155 +432,7 @@ trait JournalServiceTrait
$account = $this->accountRepository->getCashAccount();
}
app('log')->debug('Cannot return cash account, return input instead.');
return $account;
}
/**
* @param string $amount
*
* @return string
* @throws FireflyException
*/
protected function getAmount(string $amount): string
{
if ('' === $amount) {
throw new FireflyException(sprintf('The amount cannot be an empty string: "%s"', $amount));
}
app('log')->debug(sprintf('Now in getAmount("%s")', $amount));
if (0 === bccomp('0', $amount)) {
throw new FireflyException(sprintf('The amount seems to be zero: "%s"', $amount));
}
return $amount;
}
/**
* @param string|null $amount
*
* @return string|null
*/
protected function getForeignAmount(?string $amount): ?string
{
if (null === $amount) {
app('log')->debug('No foreign amount info in array. Return NULL');
return null;
}
if ('' === $amount) {
app('log')->debug('Foreign amount is empty string, return NULL.');
return null;
}
if (0 === bccomp('0', $amount)) {
app('log')->debug('Foreign amount is 0.0, return NULL.');
return null;
}
app('log')->debug(sprintf('Foreign amount is %s', $amount));
return $amount;
}
/**
* @param TransactionJournal $journal
* @param NullArrayObject $data
*
*/
protected function storeBudget(TransactionJournal $journal, NullArrayObject $data): void
{
if (TransactionType::WITHDRAWAL !== $journal->transactionType->type) {
$journal->budgets()->sync([]);
return;
}
$budget = $this->budgetRepository->findBudget($data['budget_id'], $data['budget_name']);
if (null !== $budget) {
app('log')->debug(sprintf('Link budget #%d to journal #%d', $budget->id, $journal->id));
$journal->budgets()->sync([$budget->id]);
return;
}
// if the budget is NULL, sync empty.
$journal->budgets()->sync([]);
}
/**
* @param TransactionJournal $journal
* @param NullArrayObject $data
*
*/
protected function storeCategory(TransactionJournal $journal, NullArrayObject $data): void
{
$category = $this->categoryRepository->findCategory($data['category_id'], $data['category_name']);
if (null !== $category) {
app('log')->debug(sprintf('Link category #%d to journal #%d', $category->id, $journal->id));
$journal->categories()->sync([$category->id]);
return;
}
// if the category is NULL, sync empty.
$journal->categories()->sync([]);
}
/**
* @param TransactionJournal $journal
* @param string|null $notes
*
*/
protected function storeNotes(TransactionJournal $journal, ?string $notes): void
{
$notes = (string)$notes;
$note = $journal->notes()->first();
if ('' !== $notes) {
if (null === $note) {
$note = new Note();
$note->noteable()->associate($journal);
}
$note->text = $notes;
$note->save();
app('log')->debug(sprintf('Stored notes for journal #%d', $journal->id));
return;
}
// try to delete existing notes.
$note?->delete();
}
/**
* Link tags to journal.
*
* @param TransactionJournal $journal
* @param array|null $tags
*
*/
protected function storeTags(TransactionJournal $journal, ?array $tags): void
{
app('log')->debug('Now in storeTags()', $tags ?? []);
$this->tagFactory->setUser($journal->user);
$set = [];
if (!is_array($tags)) {
app('log')->debug('Tags is not an array, break.');
return;
}
app('log')->debug('Start of loop.');
foreach ($tags as $string) {
$string = (string)$string;
app('log')->debug(sprintf('Now at tag "%s"', $string));
if ('' !== $string) {
$tag = $this->tagFactory->findOrCreate($string);
if (null !== $tag) {
$set[] = $tag->id;
}
}
}
$set = array_unique($set);
app('log')->debug('End of loop.');
app('log')->debug(sprintf('Total nr. of tags: %d', count($tags)), $tags);
$journal->tags()->sync($set);
}
}

View File

@@ -32,12 +32,6 @@ use Illuminate\Database\Eloquent\Model;
*/
trait LocationServiceTrait
{
/**
* @param Model $model
* @param array $data
*
* @return Location|null
*/
protected function storeNewLocation(Model $model, array $data): ?Location
{
$data['store_location'] ??= false;

View File

@@ -40,20 +40,12 @@ use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RecurrenceTransactionMeta;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Validation\AccountValidator;
use JsonException;
/**
* Trait RecurringTransactionTrait
*
*/
trait RecurringTransactionTrait
{
/**
* @param Recurrence $recurrence
* @param string $note
*
* @return bool
*/
public function updateNote(Recurrence $recurrence, string $note): bool
{
if ('' === $note) {
@@ -75,10 +67,6 @@ trait RecurringTransactionTrait
return true;
}
/**
* @param Recurrence $recurrence
* @param array $repetitions
*/
protected function createRepetitions(Recurrence $recurrence, array $repetitions): void
{
/** @var array $array */
@@ -98,11 +86,8 @@ trait RecurringTransactionTrait
/**
* Store transactions of a recurring transactions. It's complex but readable.
*
* @param Recurrence $recurrence
* @param array $transactions
*
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
protected function createTransactions(Recurrence $recurrence, array $transactions): void
{
@@ -179,18 +164,14 @@ trait RecurringTransactionTrait
}
/**
* @param array $expectedTypes
* @param int|null $accountId
* @param string|null $accountName
*
* @return Account
* @throws JsonException
* @throws \JsonException
*/
protected function findAccount(array $expectedTypes, ?int $accountId, ?string $accountName): Account
{
$result = null;
$accountId = (int)$accountId;
$accountName = (string)$accountName;
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($this->user);
@@ -209,9 +190,11 @@ trait RecurringTransactionTrait
// maybe we can create it? Try to avoid LOAN and other asset types.
$cannotCreate = [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD];
/** @var AccountFactory $factory */
$factory = app(AccountFactory::class);
$factory->setUser($this->user);
/** @var string $expectedType */
foreach ($expectedTypes as $expectedType) {
if (in_array($expectedType, $cannotCreate, true)) {
@@ -229,10 +212,61 @@ trait RecurringTransactionTrait
return $result ?? $repository->getCashAccount();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $budgetId
*/
protected function updatePiggyBank(RecurrenceTransaction $transaction, int $piggyId): void
{
/** @var PiggyBankFactory $factory */
$factory = app(PiggyBankFactory::class);
$factory->setUser($transaction->recurrence->user);
$piggyBank = $factory->find($piggyId, null);
if (null !== $piggyBank) {
/** @var null|RecurrenceMeta $entry */
$entry = $transaction->recurrenceTransactionMeta()->where('name', 'piggy_bank_id')->first();
if (null === $entry) {
$entry = RecurrenceTransactionMeta::create(['rt_id' => $transaction->id, 'name' => 'piggy_bank_id', 'value' => $piggyBank->id]);
}
$entry->value = $piggyBank->id;
$entry->save();
}
if (null === $piggyBank) {
// delete if present
$transaction->recurrenceTransactionMeta()->where('name', 'piggy_bank_id')->delete();
}
}
protected function updateTags(RecurrenceTransaction $transaction, array $tags): void
{
if (0 !== count($tags)) {
/** @var null|RecurrenceMeta $entry */
$entry = $transaction->recurrenceTransactionMeta()->where('name', 'tags')->first();
if (null === $entry) {
$entry = RecurrenceTransactionMeta::create(['rt_id' => $transaction->id, 'name' => 'tags', 'value' => json_encode($tags)]);
}
$entry->value = json_encode($tags);
$entry->save();
}
if (0 === count($tags)) {
// delete if present
$transaction->recurrenceTransactionMeta()->where('name', 'tags')->delete();
}
}
protected function deleteRepetitions(Recurrence $recurrence): void
{
$recurrence->recurrenceRepetitions()->delete();
}
protected function deleteTransactions(Recurrence $recurrence): void
{
app('log')->debug('deleteTransactions()');
/** @var RecurrenceTransaction $transaction */
foreach ($recurrence->recurrenceTransactions as $transaction) {
$transaction->recurrenceTransactionMeta()->delete();
$transaction->delete();
}
}
private function setBudget(RecurrenceTransaction $transaction, int $budgetId): void
{
$budgetFactory = app(BudgetFactory::class);
@@ -252,10 +286,6 @@ trait RecurringTransactionTrait
$meta->save();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $billId
*/
private function setBill(RecurrenceTransaction $transaction, int $billId): void
{
$billFactory = app(BillFactory::class);
@@ -275,10 +305,6 @@ trait RecurringTransactionTrait
$meta->save();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $categoryId
*/
private function setCategory(RecurrenceTransaction $transaction, int $categoryId): void
{
$categoryFactory = app(CategoryFactory::class);
@@ -301,76 +327,4 @@ trait RecurringTransactionTrait
$meta->value = $category->id;
$meta->save();
}
/**
* @param RecurrenceTransaction $transaction
* @param int $piggyId
*/
protected function updatePiggyBank(RecurrenceTransaction $transaction, int $piggyId): void
{
/** @var PiggyBankFactory $factory */
$factory = app(PiggyBankFactory::class);
$factory->setUser($transaction->recurrence->user);
$piggyBank = $factory->find($piggyId, null);
if (null !== $piggyBank) {
/** @var RecurrenceMeta|null $entry */
$entry = $transaction->recurrenceTransactionMeta()->where('name', 'piggy_bank_id')->first();
if (null === $entry) {
$entry = RecurrenceTransactionMeta::create(['rt_id' => $transaction->id, 'name' => 'piggy_bank_id', 'value' => $piggyBank->id]);
}
$entry->value = $piggyBank->id;
$entry->save();
}
if (null === $piggyBank) {
// delete if present
$transaction->recurrenceTransactionMeta()->where('name', 'piggy_bank_id')->delete();
}
}
/**
* @param RecurrenceTransaction $transaction
* @param array $tags
*/
protected function updateTags(RecurrenceTransaction $transaction, array $tags): void
{
if (0 !== count($tags)) {
/** @var RecurrenceMeta|null $entry */
$entry = $transaction->recurrenceTransactionMeta()->where('name', 'tags')->first();
if (null === $entry) {
$entry = RecurrenceTransactionMeta::create(['rt_id' => $transaction->id, 'name' => 'tags', 'value' => json_encode($tags)]);
}
$entry->value = json_encode($tags);
$entry->save();
}
if (0 === count($tags)) {
// delete if present
$transaction->recurrenceTransactionMeta()->where('name', 'tags')->delete();
}
}
/**
* @param Recurrence $recurrence
*
*/
protected function deleteRepetitions(Recurrence $recurrence): void
{
$recurrence->recurrenceRepetitions()->delete();
}
/**
* @param Recurrence $recurrence
*
*/
protected function deleteTransactions(Recurrence $recurrence): void
{
app('log')->debug('deleteTransactions()');
/** @var RecurrenceTransaction $transaction */
foreach ($recurrence->recurrenceTransactions as $transaction) {
$transaction->recurrenceTransactionMeta()->delete();
$transaction->delete();
}
}
}

View File

@@ -29,7 +29,6 @@ use FireflyIII\Models\TransactionType;
/**
* Trait TransactionTypeTrait
*
*/
trait TransactionTypeTrait
{
@@ -37,9 +36,6 @@ trait TransactionTypeTrait
* Get the transaction type. Since this is mandatory, will throw an exception when nothing comes up. Will always
* use TransactionType repository.
*
* @param string $type
*
* @return TransactionType
* @throws FireflyException
*/
protected function findTransactionType(string $type): TransactionType
@@ -48,6 +44,7 @@ trait TransactionTypeTrait
$transactionType = $factory->find($type);
if (null === $transactionType) {
app('log')->error(sprintf('Could not find transaction type for "%s"', $type));
throw new FireflyException(sprintf('Could not find transaction type for "%s"', $type));
}

View File

@@ -31,7 +31,6 @@ use FireflyIII\Models\Location;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Services\Internal\Support\AccountServiceTrait;
use FireflyIII\User;
use JsonException;
/**
* Class AccountUpdateService
@@ -63,12 +62,8 @@ class AccountUpdateService
/**
* Update account data.
*
* @param Account $account
* @param array $data
*
* @return Account
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
public function update(Account $account, array $data): Account
{
@@ -110,20 +105,60 @@ class AccountUpdateService
return $account;
}
/**
* @param User $user
*/
public function setUser(User $user): void
{
$this->user = $user;
}
/**
* @param Account $account
* @param array $data
*
* @return Account
*/
public function updateAccountOrder(Account $account, array $data): Account
{
// skip if no order info
if (!array_key_exists('order', $data) || $data['order'] === $account->order) {
app('log')->debug(sprintf('Account order will not be touched because its not set or already at %d.', $account->order));
return $account;
}
// skip if not of orderable type.
$type = $account->accountType->type;
if (!in_array($type, [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], true)) {
app('log')->debug('Will not change order of this account.');
return $account;
}
// get account type ID's because a join and an update is hard:
$oldOrder = $account->order;
$newOrder = $data['order'];
app('log')->debug(sprintf('Order is set to be updated from %s to %s', $oldOrder, $newOrder));
$list = $this->getTypeIds([AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT]);
if (AccountType::ASSET === $type) {
$list = $this->getTypeIds([AccountType::ASSET]);
}
if ($newOrder > $oldOrder) {
$this->user->accounts()->where('accounts.order', '<=', $newOrder)->where('accounts.order', '>', $oldOrder)
->where('accounts.id', '!=', $account->id)
->whereIn('accounts.account_type_id', $list)
->decrement('order')
;
$account->order = $newOrder;
app('log')->debug(sprintf('Order of account #%d ("%s") is now %d', $account->id, $account->name, $newOrder));
$account->save();
return $account;
}
$this->user->accounts()->where('accounts.order', '>=', $newOrder)->where('accounts.order', '<', $oldOrder)
->where('accounts.id', '!=', $account->id)
->whereIn('accounts.account_type_id', $list)
->increment('order')
;
$account->order = $newOrder;
app('log')->debug(sprintf('Order of account #%d ("%s") is now %d', $account->id, $account->name, $newOrder));
$account->save();
return $account;
}
private function updateAccount(Account $account, array $data): Account
{
// update the account itself:
@@ -138,7 +173,7 @@ class AccountUpdateService
}
// set liability, but account must already be a liability.
//$liabilityType = $data['liability_type'] ?? '';
// $liabilityType = $data['liability_type'] ?? '';
if ($this->isLiability($account) && array_key_exists('liability_type', $data)) {
$type = $this->getAccountType($data['liability_type']);
$account->account_type_id = $type->id;
@@ -163,11 +198,6 @@ class AccountUpdateService
return $account;
}
/**
* @param Account $account
*
* @return bool
*/
private function isLiability(Account $account): bool
{
$type = $account->accountType->type;
@@ -175,77 +205,15 @@ class AccountUpdateService
return in_array($type, [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], true);
}
/**
* @param string $type
*
* @return AccountType
*/
private function getAccountType(string $type): AccountType
{
return AccountType::whereType(ucfirst($type))->first();
}
/**
* @param Account $account
* @param array $data
*
* @return Account
*/
public function updateAccountOrder(Account $account, array $data): Account
{
// skip if no order info
if (!array_key_exists('order', $data) || $data['order'] === $account->order) {
app('log')->debug(sprintf('Account order will not be touched because its not set or already at %d.', $account->order));
return $account;
}
// skip if not of orderable type.
$type = $account->accountType->type;
if (!in_array($type, [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], true)) {
app('log')->debug('Will not change order of this account.');
return $account;
}
// get account type ID's because a join and an update is hard:
$oldOrder = $account->order;
$newOrder = $data['order'];
app('log')->debug(sprintf('Order is set to be updated from %s to %s', $oldOrder, $newOrder));
$list = $this->getTypeIds([AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT]);
if ($type === AccountType::ASSET) {
$list = $this->getTypeIds([AccountType::ASSET]);
}
if ($newOrder > $oldOrder) {
$this->user->accounts()->where('accounts.order', '<=', $newOrder)->where('accounts.order', '>', $oldOrder)
->where('accounts.id', '!=', $account->id)
->whereIn('accounts.account_type_id', $list)
->decrement('order');
$account->order = $newOrder;
app('log')->debug(sprintf('Order of account #%d ("%s") is now %d', $account->id, $account->name, $newOrder));
$account->save();
return $account;
}
$this->user->accounts()->where('accounts.order', '>=', $newOrder)->where('accounts.order', '<', $oldOrder)
->where('accounts.id', '!=', $account->id)
->whereIn('accounts.account_type_id', $list)
->increment('order');
$account->order = $newOrder;
app('log')->debug(sprintf('Order of account #%d ("%s") is now %d', $account->id, $account->name, $newOrder));
$account->save();
return $account;
}
/**
* @param array $array
*
* @return array
*/
private function getTypeIds(array $array): array
{
$return = [];
/** @var string $type */
foreach ($array as $type) {
/** @var AccountType $type */
@@ -256,10 +224,6 @@ class AccountUpdateService
return $return;
}
/**
* @param Account $account
* @param array $data
*/
private function updateLocation(Account $account, array $data): void
{
$updateLocation = $data['update_location'] ?? false;
@@ -287,9 +251,6 @@ class AccountUpdateService
}
/**
* @param Account $account
* @param array $data
*
* @throws FireflyException
*/
private function updateOpeningBalance(Account $account, array $data): void
@@ -323,8 +284,6 @@ class AccountUpdateService
}
/**
* @param Account $account
*
* @throws FireflyException
*/
private function updatePreferences(Account $account): void

View File

@@ -33,7 +33,6 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
use FireflyIII\Services\Internal\Support\BillServiceTrait;
use FireflyIII\User;
use Illuminate\Support\Collection;
use JsonException;
/**
* Class BillUpdateService
@@ -46,12 +45,8 @@ class BillUpdateService
protected User $user;
/**
* @param Bill $bill
* @param array $data
*
* @return Bill
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
public function update(Bill $bill, array $data): Bill
{
@@ -135,12 +130,6 @@ class BillUpdateService
return $bill;
}
/**
* @param Bill $bill
* @param array $data
*
* @return Bill
*/
private function updateBillProperties(Bill $bill, array $data): Bill
{
if (array_key_exists('name', $data) && '' !== (string)$data['name']) {
@@ -179,37 +168,30 @@ class BillUpdateService
return $bill;
}
/**
* @param Bill $bill
* @param int $oldOrder
* @param int $newOrder
*/
private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void
{
if ($newOrder > $oldOrder) {
$this->user->bills()->where('order', '<=', $newOrder)->where('order', '>', $oldOrder)
->where('bills.id', '!=', $bill->id)
->decrement('bills.order');
->where('bills.id', '!=', $bill->id)
->decrement('bills.order')
;
$bill->order = $newOrder;
$bill->save();
}
if ($newOrder < $oldOrder) {
$this->user->bills()->where('order', '>=', $newOrder)->where('order', '<', $oldOrder)
->where('bills.id', '!=', $bill->id)
->increment('bills.order');
->where('bills.id', '!=', $bill->id)
->increment('bills.order')
;
$bill->order = $newOrder;
$bill->save();
}
}
/**
* @param Bill $bill
* @param array $oldData
* @param array $newData
*/
private function updateBillTriggers(Bill $bill, array $oldData, array $newData): void
{
app('log')->debug(sprintf('Now in updateBillTriggers(%d, "%s")', $bill->id, $bill->name));
/** @var BillRepositoryInterface $repository */
$repository = app(BillRepositoryInterface::class);
$repository->setUser($bill->user);
@@ -232,18 +214,13 @@ class BillUpdateService
}
if ($oldData[$field] === $newData[$field]) {
app('log')->debug(sprintf('Field %s is unchanged ("%s"), continue.', $field, $oldData[$field]));
continue;
}
$this->updateRules($rules, $ruleTriggerKey, $oldData[$field], $newData[$field]);
}
}
/**
* @param Collection $rules
* @param string $key
* @param string $oldValue
* @param string $newValue
*/
private function updateRules(Collection $rules, string $key, string $oldValue, string $newValue): void
{
/** @var Rule $rule */
@@ -253,6 +230,7 @@ class BillUpdateService
app('log')->debug(sprintf('Updated rule trigger #%d from value "%s" to value "%s"', $trigger->id, $oldValue, $newValue));
$trigger->trigger_value = $newValue;
$trigger->save();
continue;
}
if (null !== $trigger && $trigger->trigger_value !== $oldValue && in_array($key, ['amount_more', 'amount_less'], true)
@@ -264,12 +242,6 @@ class BillUpdateService
}
}
/**
* @param Rule $rule
* @param string $key
*
* @return RuleTrigger|null
*/
private function getRuleTrigger(Rule $rule, string $key): ?RuleTrigger
{
return $rule->ruleTriggers()->where('trigger_type', $key)->first();

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Services\Internal\Update;
use Exception;
use FireflyIII\Models\Category;
use FireflyIII\Models\Note;
use FireflyIII\Models\RecurrenceTransactionMeta;
@@ -33,8 +32,6 @@ use FireflyIII\User;
/**
* Class CategoryUpdateService
*
*/
class CategoryUpdateService
{
@@ -61,11 +58,7 @@ class CategoryUpdateService
}
/**
* @param Category $category
* @param array $data
*
* @return Category
* @throws Exception
* @throws \Exception
*/
public function update(Category $category, array $data): Category
{
@@ -84,19 +77,17 @@ class CategoryUpdateService
return $category;
}
/**
* @param string $oldName
* @param string $newName
*/
private function updateRuleTriggers(string $oldName, string $newName): void
{
$types = ['category_is',];
$types = ['category_is'];
$triggers = RuleTrigger::leftJoin('rules', 'rules.id', '=', 'rule_triggers.rule_id')
->where('rules.user_id', $this->user->id)
->whereIn('rule_triggers.trigger_type', $types)
->where('rule_triggers.trigger_value', $oldName)
->get(['rule_triggers.*']);
->where('rules.user_id', $this->user->id)
->whereIn('rule_triggers.trigger_type', $types)
->where('rule_triggers.trigger_value', $oldName)
->get(['rule_triggers.*'])
;
app('log')->debug(sprintf('Found %d triggers to update.', $triggers->count()));
/** @var RuleTrigger $trigger */
foreach ($triggers as $trigger) {
$trigger->trigger_value = $newName;
@@ -105,19 +96,17 @@ class CategoryUpdateService
}
}
/**
* @param string $oldName
* @param string $newName
*/
private function updateRuleActions(string $oldName, string $newName): void
{
$types = ['set_category',];
$types = ['set_category'];
$actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id')
->where('rules.user_id', $this->user->id)
->whereIn('rule_actions.action_type', $types)
->where('rule_actions.action_value', $oldName)
->get(['rule_actions.*']);
->where('rules.user_id', $this->user->id)
->whereIn('rule_actions.action_type', $types)
->where('rule_actions.action_value', $oldName)
->get(['rule_actions.*'])
;
app('log')->debug(sprintf('Found %d actions to update.', $actions->count()));
/** @var RuleAction $action */
foreach ($actions as $action) {
$action->action_value = $newName;
@@ -126,25 +115,19 @@ class CategoryUpdateService
}
}
/**
* @param string $oldName
* @param string $newName
*/
private function updateRecurrences(string $oldName, string $newName): void
{
RecurrenceTransactionMeta::leftJoin('recurrences_transactions', 'rt_meta.rt_id', '=', 'recurrences_transactions.id')
->leftJoin('recurrences', 'recurrences.id', '=', 'recurrences_transactions.recurrence_id')
->where('recurrences.user_id', $this->user->id)
->where('rt_meta.name', 'category_name')
->where('rt_meta.value', $oldName)
->update(['rt_meta.value' => $newName]);
->leftJoin('recurrences', 'recurrences.id', '=', 'recurrences_transactions.recurrence_id')
->where('recurrences.user_id', $this->user->id)
->where('rt_meta.name', 'category_name')
->where('rt_meta.value', $oldName)
->update(['rt_meta.value' => $newName])
;
}
/**
* @param Category $category
* @param array $data
*
* @throws Exception
* @throws \Exception
*/
private function updateNotes(Category $category, array $data): void
{

View File

@@ -27,17 +27,9 @@ use FireflyIII\Models\TransactionCurrency;
/**
* Class CurrencyUpdateService
*
*/
class CurrencyUpdateService
{
/**
* @param TransactionCurrency $currency
* @param array $data
*
* @return TransactionCurrency
*/
public function update(TransactionCurrency $currency, array $data): TransactionCurrency
{
if (array_key_exists('code', $data) && '' !== (string)$data['code']) {

View File

@@ -39,11 +39,6 @@ use FireflyIII\Models\TransactionJournalMeta;
*/
class GroupCloneService
{
/**
* @param TransactionGroup $group
*
* @return TransactionGroup
*/
public function cloneGroup(TransactionGroup $group): TransactionGroup
{
$newGroup = $group->replicate();
@@ -55,11 +50,6 @@ class GroupCloneService
return $newGroup;
}
/**
* @param TransactionJournal $journal
* @param TransactionGroup $newGroup
* @param int $originalGroup
*/
private function cloneJournal(TransactionJournal $journal, TransactionGroup $newGroup, int $originalGroup): void
{
$newJournal = $journal->replicate();
@@ -83,6 +73,7 @@ class GroupCloneService
foreach ($journal->transactionJournalMeta as $meta) {
$this->cloneMeta($meta, $newJournal);
}
// clone category
/** @var Category $category */
foreach ($journal->categories as $category) {
@@ -105,7 +96,7 @@ class GroupCloneService
// add relation.
// TODO clone ALL linked piggy banks
/** @var PiggyBankEvent|null $event */
/** @var null|PiggyBankEvent $event */
$event = $journal->piggyBankEvents()->first();
if (null !== $event) {
$piggyBank = $event->piggyBank;
@@ -114,10 +105,6 @@ class GroupCloneService
}
}
/**
* @param Transaction $transaction
* @param TransactionJournal $newJournal
*/
private function cloneTransaction(Transaction $transaction, TransactionJournal $newJournal): void
{
$newTransaction = $transaction->replicate();
@@ -126,11 +113,6 @@ class GroupCloneService
$newTransaction->save();
}
/**
* @param Note $note
* @param TransactionJournal $newJournal
* @param int $oldGroupId
*/
private function cloneNote(Note $note, TransactionJournal $newJournal, int $oldGroupId): void
{
$newNote = $note->replicate();
@@ -142,10 +124,6 @@ class GroupCloneService
$newNote->save();
}
/**
* @param TransactionJournalMeta $meta
* @param TransactionJournal $newJournal
*/
private function cloneMeta(TransactionJournalMeta $meta, TransactionJournal $newJournal): void
{
$newMeta = $meta->replicate();

View File

@@ -30,7 +30,6 @@ use FireflyIII\Factory\TransactionJournalFactory;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use JsonException;
/**
* Class GroupUpdateService
@@ -40,18 +39,15 @@ class GroupUpdateService
/**
* Update a transaction group.
*
* @param TransactionGroup $transactionGroup
* @param array $data
*
* @return TransactionGroup
* @throws DuplicateTransactionException
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
public function update(TransactionGroup $transactionGroup, array $data): TransactionGroup
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
app('log')->debug('Now in group update service', $data);
/** @var array $transactions */
$transactions = $data['transactions'] ?? [];
// update group name.
@@ -71,7 +67,6 @@ class GroupUpdateService
);
}
if (0 === count($transactions)) {
app('log')->debug('No transactions submitted, do nothing.');
@@ -112,6 +107,7 @@ class GroupUpdateService
foreach ($result as $deletedId) {
/** @var TransactionJournal $journal */
$journal = $transactionGroup->transactionJournals()->find((int)$deletedId);
/** @var JournalDestroyService $service */
$service = app(JournalDestroyService::class);
$service->destroy($journal);
@@ -126,17 +122,12 @@ class GroupUpdateService
/**
* Update single journal.
*
* @param TransactionGroup $transactionGroup
* @param TransactionJournal $journal
* @param array $data
*/
private function updateTransactionJournal(
TransactionGroup $transactionGroup,
TransactionJournal $journal,
array $data
): void
{
): void {
app('log')->debug(sprintf('Now in %s', __METHOD__));
if (0 === count($data)) {
return;
@@ -144,6 +135,7 @@ class GroupUpdateService
if (1 === count($data) && array_key_exists('transaction_journal_id', $data)) {
return;
}
/** @var JournalUpdateService $updateService */
$updateService = app(JournalUpdateService::class);
$updateService->setTransactionGroup($transactionGroup);
@@ -153,27 +145,25 @@ class GroupUpdateService
}
/**
* @param TransactionGroup $transactionGroup
* @param array $transactions
*
* @return array
* @throws DuplicateTransactionException
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
private function updateTransactions(TransactionGroup $transactionGroup, array $transactions): array
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
// updated or created transaction journals:
$updated = [];
/**
* @var int $index
* @var array $transaction
*/
foreach ($transactions as $index => $transaction) {
app('log')->debug(sprintf('Now at #%d of %d', ($index + 1), count($transactions)), $transaction);
app('log')->debug(sprintf('Now at #%d of %d', $index + 1, count($transactions)), $transaction);
$journalId = (int)($transaction['transaction_journal_id'] ?? 0);
/** @var TransactionJournal|null $journal */
/** @var null|TransactionJournal $journal */
$journal = $transactionGroup->transactionJournals()->find($journalId);
if (null === $journal) {
app('log')->debug('This entry has no existing journal: make a new split.');
@@ -181,7 +171,8 @@ class GroupUpdateService
// by plucking it from another journal in the group:
if (!array_key_exists('type', $transaction)) {
app('log')->debug('No transaction type is indicated.');
/** @var TransactionJournal|null $randomJournal */
/** @var null|TransactionJournal $randomJournal */
$randomJournal = $transactionGroup->transactionJournals()->inRandomOrder()->with(
['transactionType']
)->first();
@@ -212,14 +203,9 @@ class GroupUpdateService
}
/**
* @param TransactionGroup $transactionGroup
* @param array $data
*
* @return TransactionJournal|null
*
* @throws DuplicateTransactionException
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
private function createTransactionJournal(TransactionGroup $transactionGroup, array $data): ?TransactionJournal
{
@@ -228,14 +214,17 @@ class GroupUpdateService
$data,
],
];
/** @var TransactionJournalFactory $factory */
$factory = app(TransactionJournalFactory::class);
$factory->setUser($transactionGroup->user);
try {
$collection = $factory->create($submission);
} catch (FireflyException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
throw new FireflyException(
sprintf('Could not create new transaction journal: %s', $e->getMessage()),
0,

View File

@@ -99,20 +99,14 @@ class JournalUpdateService
'external_url',
];
$this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date',
'invoice_date',];
'invoice_date', ];
}
/**
* @param array $data
*/
public function setData(array $data): void
{
$this->data = $data;
}
/**
* @param TransactionGroup $transactionGroup
*/
public function setTransactionGroup(TransactionGroup $transactionGroup): void
{
$this->transactionGroup = $transactionGroup;
@@ -127,23 +121,16 @@ class JournalUpdateService
$this->sourceTransaction = null;
}
/**
* @param TransactionJournal $transactionJournal
*/
public function setTransactionJournal(TransactionJournal $transactionJournal): void
{
$this->transactionJournal = $transactionJournal;
}
/**
*
*/
public function update(): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
app('log')->debug(sprintf('Now in JournalUpdateService for journal #%d.', $this->transactionJournal->id));
$this->data['reconciled'] = array_key_exists('reconciled', $this->data) ? $this->data['reconciled'] : false;
// can we update account data using the new type?
@@ -181,17 +168,11 @@ class JournalUpdateService
$this->transactionJournal->refresh();
}
/**
* @return bool
*/
private function hasValidAccounts(): bool
{
return $this->hasValidSourceAccount() && $this->hasValidDestinationAccount();
}
/**
* @return bool
*/
private function hasValidSourceAccount(): bool
{
app('log')->debug('Now in hasValidSourceAccount().');
@@ -225,11 +206,6 @@ class JournalUpdateService
return $result;
}
/**
* @param array $fields
*
* @return bool
*/
private function hasFields(array $fields): bool
{
foreach ($fields as $field) {
@@ -241,9 +217,6 @@ class JournalUpdateService
return false;
}
/**
* @return Account
*/
private function getOriginalSourceAccount(): Account
{
if (null === $this->sourceAccount) {
@@ -254,9 +227,6 @@ class JournalUpdateService
return $this->sourceAccount;
}
/**
* @return Transaction
*/
private function getSourceTransaction(): Transaction
{
if (null === $this->sourceTransaction) {
@@ -277,8 +247,6 @@ class JournalUpdateService
*
* If the array contains key 'type' and the value is correct, this is returned. Otherwise, the original type is
* returned.
*
* @return string
*/
private function getExpectedType(): string
{
@@ -290,9 +258,6 @@ class JournalUpdateService
return $this->transactionJournal->transactionType->type;
}
/**
* @return bool
*/
private function hasValidDestinationAccount(): bool
{
app('log')->debug('Now in hasValidDestinationAccount().');
@@ -332,9 +297,6 @@ class JournalUpdateService
return $result;
}
/**
* @return Account
*/
private function getOriginalDestinationAccount(): Account
{
if (null === $this->destinationAccount) {
@@ -347,8 +309,6 @@ class JournalUpdateService
/**
* Get destination transaction.
*
* @return Transaction
*/
private function getDestinationTransaction(): Transaction
{
@@ -361,8 +321,6 @@ class JournalUpdateService
/**
* Does a validation and returns the source account. This method will break if the source isn't really valid.
*
* @return Account
*/
private function getValidSourceAccount(): Account
{
@@ -381,6 +339,7 @@ class JournalUpdateService
];
$expectedType = $this->getExpectedType();
try {
$result = $this->getAccount($expectedType, 'source', $sourceInfo);
} catch (FireflyException $e) {
@@ -426,8 +385,6 @@ class JournalUpdateService
/**
* Does a validation and returns the destination account. This method will break if the dest isn't really valid.
*
* @return Account
*/
private function getValidDestinationAccount(): Account
{
@@ -448,6 +405,7 @@ class JournalUpdateService
// make new account validator.
$expectedType = $this->getExpectedType();
app('log')->debug(sprintf('Expected type (new or unchanged) is %s', $expectedType));
try {
$result = $this->getAccount($expectedType, 'destination', $destInfo);
} catch (FireflyException $e) {
@@ -513,8 +471,6 @@ class JournalUpdateService
/**
* Update journal generic field. Cannot be set to NULL.
*
* @param string $fieldName
*/
private function updateField(string $fieldName): void
{
@@ -526,7 +482,7 @@ class JournalUpdateService
// update timezone.
$value->setTimezone(config('app.timezone'));
}
if (!($value instanceof Carbon)) {
if (!$value instanceof Carbon) {
$value = new Carbon($value);
}
// do some parsing.
@@ -537,19 +493,16 @@ class JournalUpdateService
$this->transactionJournal->user,
$this->transactionJournal,
sprintf('update_%s', $fieldName),
$this->transactionJournal->$fieldName, // @phpstan-ignore-line
$this->transactionJournal->{$fieldName}, // @phpstan-ignore-line
$value
)
);
$this->transactionJournal->$fieldName = $value;// @phpstan-ignore-line
$this->transactionJournal->{$fieldName} = $value; // @phpstan-ignore-line
app('log')->debug(sprintf('Updated %s', $fieldName));
}
}
/**
*
*/
private function updateCategory(): void
{
// update category
@@ -560,9 +513,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateBudget(): void
{
// update budget
@@ -576,9 +526,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateTags(): void
{
if ($this->hasFields(['tags'])) {
@@ -588,9 +535,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateReconciled(): void
{
if (array_key_exists('reconciled', $this->data) && is_bool($this->data['reconciled'])) {
@@ -598,9 +542,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateNotes(): void
{
// update notes.
@@ -610,9 +551,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateMeta(): void
{
// update meta fields.
@@ -629,9 +567,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateMetaFields(): void
{
/** @var TransactionJournalMetaFactory $factory */
@@ -651,9 +586,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateMetaDateFields(): void
{
/** @var TransactionJournalMetaFactory $factory */
@@ -679,9 +611,6 @@ class JournalUpdateService
}
}
/**
*
*/
private function updateCurrency(): void
{
// update transactions.
@@ -709,9 +638,6 @@ class JournalUpdateService
app('log')->debug(sprintf('Updated currency to #%d (%s)', $currency->id, $currency->code));
}
/**
*
*/
private function updateAmount(): void
{
app('log')->debug(sprintf('Now in %s', __METHOD__));
@@ -721,6 +647,7 @@ class JournalUpdateService
$value = $this->data['amount'] ?? '';
app('log')->debug(sprintf('Amount is now "%s"', $value));
try {
$amount = $this->getAmount($value);
} catch (FireflyException $e) {
@@ -740,9 +667,6 @@ class JournalUpdateService
app('log')->debug(sprintf('Updated amount to "%s"', $amount));
}
/**
*
*/
private function updateForeignAmount(): void
{
// amount, foreign currency.

View File

@@ -32,12 +32,9 @@ use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Services\Internal\Support\RecurringTransactionTrait;
use FireflyIII\Services\Internal\Support\TransactionTypeTrait;
use FireflyIII\User;
use JsonException;
/**
* Class RecurrenceUpdateService
*
*/
class RecurrenceUpdateService
{
@@ -51,10 +48,6 @@ class RecurrenceUpdateService
*
* TODO if the user updates the type, the accounts must be validated again.
*
* @param Recurrence $recurrence
* @param array $data
*
* @return Recurrence
* @throws FireflyException
*/
public function update(Recurrence $recurrence, array $data): Recurrence
@@ -111,10 +104,6 @@ class RecurrenceUpdateService
return $recurrence;
}
/**
* @param Recurrence $recurrence
* @param string $text
*/
private function setNoteText(Recurrence $recurrence, string $text): void
{
$dbNote = $recurrence->notes()->first();
@@ -132,10 +121,6 @@ class RecurrenceUpdateService
}
/**
*
* @param Recurrence $recurrence
* @param array $repetitions
*
* @throws FireflyException
*/
private function updateRepetitions(Recurrence $recurrence, array $repetitions): void
@@ -168,25 +153,20 @@ class RecurrenceUpdateService
];
foreach ($fields as $field => $column) {
if (array_key_exists($field, $current)) {
$match->$column = $current[$field];
$match->{$column} = $current[$field];
$match->save();
}
}
}
}
/**
* @param Recurrence $recurrence
* @param array $data
*
* @return RecurrenceRepetition|null
*/
private function matchRepetition(Recurrence $recurrence, array $data): ?RecurrenceRepetition
{
$originalCount = $recurrence->recurrenceRepetitions()->count();
if (1 === $originalCount) {
app('log')->debug('Return the first one');
/** @var RecurrenceRepetition|null */
// @var RecurrenceRepetition|null
return $recurrence->recurrenceRepetitions()->first();
}
// find it:
@@ -203,18 +183,16 @@ class RecurrenceUpdateService
$query->where($column, $data[$field]);
}
}
/** @var RecurrenceRepetition|null */
// @var RecurrenceRepetition|null
return $query->first();
}
/**
* TODO this method is very complex.
*
* @param Recurrence $recurrence
* @param array $transactions
*
* @throws FireflyException
* @throws JsonException
* @throws \JsonException
*/
private function updateTransactions(Recurrence $recurrence, array $transactions): void
{
@@ -224,13 +202,12 @@ class RecurrenceUpdateService
if (0 === count($transactions)) {
// won't drop transactions, rather avoid.
app('log')->warning('No transactions to update, too scared to continue!');
return;
}
$combinations = [];
$originalTransactions = $recurrence->recurrenceTransactions()->get()->toArray();
/**
* First, make sure to loop all existing transactions and match them to a counterpart in the submitted transactions array.
*/
// First, make sure to loop all existing transactions and match them to a counterpart in the submitted transactions array.
foreach ($originalTransactions as $i => $originalTransaction) {
foreach ($transactions as $ii => $submittedTransaction) {
if (array_key_exists('id', $submittedTransaction) && (int)$originalTransaction['id'] === (int)$submittedTransaction['id']) {
@@ -239,14 +216,11 @@ class RecurrenceUpdateService
'original' => $originalTransaction,
'submitted' => $submittedTransaction,
];
unset($originalTransactions[$i]);
unset($transactions[$ii]);
unset($originalTransactions[$i], $transactions[$ii]);
}
}
}
/**
* If one left of both we can match those as well and presto.
*/
// If one left of both we can match those as well and presto.
if (1 === count($originalTransactions) && 1 === count($transactions)) {
$first = array_shift($originalTransactions);
app('log')->debug(sprintf('One left of each, link them (ID is #%d)', $first['id']));
@@ -271,16 +245,11 @@ class RecurrenceUpdateService
$this->createTransactions($recurrence, $transactions);
}
/**
* @param Recurrence $recurrence
* @param array $combination
*
* @return void
*/
private function updateCombination(Recurrence $recurrence, array $combination): void
{
$original = $combination['original'];
$submitted = $combination['submitted'];
/** @var RecurrenceTransaction $transaction */
$transaction = $recurrence->recurrenceTransactions()->find($original['id']);
app('log')->debug(sprintf('Now in updateCombination(#%d)', $original['id']));
@@ -327,7 +296,7 @@ class RecurrenceUpdateService
];
foreach ($fields as $field => $column) {
if (array_key_exists($field, $submitted)) {
$transaction->$column = $submitted[$field];
$transaction->{$column} = $submitted[$field];
$transaction->save();
}
}
@@ -359,12 +328,6 @@ class RecurrenceUpdateService
}
}
/**
* @param Recurrence $recurrence
* @param int $transactionId
*
* @return void
*/
private function deleteTransaction(Recurrence $recurrence, int $transactionId): void
{
app('log')->debug(sprintf('Will delete transaction #%d in recurrence #%d.', $transactionId, $recurrence->id));

View File

@@ -29,17 +29,11 @@ use GuzzleHttp\Exception\RequestException;
/**
* Class PwndVerifierV2.
*
*/
class PwndVerifierV2 implements Verifier
{
/**
* Verify the given password against (some) service.
*
* @param string $password
*
* @return bool
*/
public function validPassword(string $password): bool
{
@@ -62,7 +56,7 @@ class PwndVerifierV2 implements Verifier
try {
$client = new Client();
$res = $client->request('GET', $url, $opt);
} catch (GuzzleException | RequestException $e) {
} catch (GuzzleException|RequestException $e) {
app('log')->error(sprintf('Could not verify password security: %s', $e->getMessage()));
return true;

View File

@@ -30,10 +30,6 @@ interface Verifier
{
/**
* Verify the given password against (some) service.
*
* @param string $password
*
* @return bool
*/
public function validPassword(string $password): bool;
}

View File

@@ -30,7 +30,6 @@ use FireflyIII\Models\WebhookMessage;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use JsonException;
/**
* Class StandardWebhookSender
@@ -40,17 +39,11 @@ class StandardWebhookSender implements WebhookSenderInterface
private WebhookMessage $message;
private int $version = 1;
/**
* @inheritDoc
*/
public function getVersion(): int
{
return $this->version;
}
/**
* @inheritDoc
*/
public function send(): void
{
// have the signature generator generate a signature. If it fails, the error thrown will
@@ -58,6 +51,7 @@ class StandardWebhookSender implements WebhookSenderInterface
$signatureGenerator = app(SignatureGeneratorInterface::class);
$this->message->sent = true;
$this->message->save();
try {
$signature = $signatureGenerator->generate($this->message);
} catch (FireflyException $e) {
@@ -80,7 +74,7 @@ class StandardWebhookSender implements WebhookSenderInterface
try {
$json = json_encode($this->message->message, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
} catch (\JsonException $e) {
app('log')->error('Did not send message because of a JSON error.');
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
@@ -107,14 +101,14 @@ class StandardWebhookSender implements WebhookSenderInterface
],
];
$client = new Client();
try {
$res = $client->request('POST', $this->message->webhook->url, $options);
} catch (RequestException | ConnectException $e) {
} catch (ConnectException|RequestException $e) {
app('log')->error('The webhook could NOT be submitted but Firefly III caught the error below.');
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
$logs = sprintf("%s\n%s", $e->getMessage(), $e->getTraceAsString());
$this->message->errored = true;
@@ -143,9 +137,6 @@ class StandardWebhookSender implements WebhookSenderInterface
app('log')->debug(sprintf('Response body: %s', $res->getBody()));
}
/**
* @inheritDoc
*/
public function setMessage(WebhookMessage $message): void
{
$this->message = $message;

View File

@@ -30,18 +30,9 @@ use FireflyIII\Models\WebhookMessage;
*/
interface WebhookSenderInterface
{
/**
* @return int
*/
public function getVersion(): int;
/**
*
*/
public function send(): void;
/**
* @param WebhookMessage $message
*/
public function setMessage(WebhookMessage $message): void;
}