diff --git a/app/Handlers/Events/StoredJournalEventHandler.php b/app/Handlers/Events/StoredJournalEventHandler.php index 7a880fc699..6d266d0dda 100644 --- a/app/Handlers/Events/StoredJournalEventHandler.php +++ b/app/Handlers/Events/StoredJournalEventHandler.php @@ -42,6 +42,10 @@ class StoredJournalEventHandler /** * StoredJournalEventHandler constructor. + * + * @param PRI $repository + * @param JRI $journalRepository + * @param RGRI $ruleGroupRepository */ public function __construct(PRI $repository, JRI $journalRepository, RGRI $ruleGroupRepository) { diff --git a/app/Handlers/Events/UpdatedJournalEventHandler.php b/app/Handlers/Events/UpdatedJournalEventHandler.php index 1cdadd6da8..e4ea75a008 100644 --- a/app/Handlers/Events/UpdatedJournalEventHandler.php +++ b/app/Handlers/Events/UpdatedJournalEventHandler.php @@ -35,6 +35,8 @@ class UpdatedJournalEventHandler /** * StoredJournalEventHandler constructor. + * + * @param RuleGroupRepositoryInterface $ruleGroupRepository */ public function __construct(RuleGroupRepositoryInterface $ruleGroupRepository) { diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 4449e17b01..0313f57040 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -142,10 +142,9 @@ class JsonController extends Controller } /** - * @param AccountTaskerInterface $accountTasker - * @param AccountRepositoryInterface $repository - * * @return \Illuminate\Http\JsonResponse + * @internal param AccountTaskerInterface $accountTasker + * @internal param AccountRepositoryInterface $repository * */ public function boxIn() @@ -178,10 +177,10 @@ class JsonController extends Controller } /** - * @param AccountTaskerInterface $accountTasker - * @param AccountRepositoryInterface $repository - * * @return \Symfony\Component\HttpFoundation\Response + * @internal param AccountTaskerInterface $accountTasker + * @internal param AccountRepositoryInterface $repository + * */ public function boxOut() { diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index b0205f36af..0551bfafe8 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -23,6 +23,7 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use Illuminate\Support\Collection; use Preferences; use Session; @@ -203,11 +204,10 @@ class MassController extends Controller * * @return mixed */ - public function update(MassEditJournalRequest $request, JournalRepositoryInterface $repository) + public function update(MassEditJournalRequest $request, JournalRepositoryInterface $repository, JournalUpdateInterface $updater) { $journalIds = $request->get('journals'); $count = 0; - if (is_array($journalIds)) { foreach ($journalIds as $journalId) { $journal = $repository->find(intval($journalId)); @@ -251,7 +251,7 @@ class MassController extends Controller 'tags' => $tags, ]; // call repository update function. - $repository->update($journal, $data); + $updater->update($journal, $data); $count++; } diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index 89de28d7d2..bdd4de6a21 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -27,6 +27,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use Log; use Preferences; @@ -366,11 +367,12 @@ class SingleController extends Controller /** * @param JournalFormRequest $request * @param JournalRepositoryInterface $repository + * @param JournalUpdateInterface $updater * @param TransactionJournal $journal * * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal) + public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, JournalUpdateInterface $updater, TransactionJournal $journal) { // @codeCoverageIgnoreStart if ($this->isOpeningBalance($journal)) { @@ -379,7 +381,7 @@ class SingleController extends Controller // @codeCoverageIgnoreEnd $data = $request->getJournalData(); - $journal = $repository->update($journal, $data); + $journal = $updater->update($journal, $data); /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; $this->attachments->saveAttachmentsForModel($journal, $files); diff --git a/app/Http/Controllers/Transaction/SplitController.php b/app/Http/Controllers/Transaction/SplitController.php index e6668bc43e..2514574fe1 100644 --- a/app/Http/Controllers/Transaction/SplitController.php +++ b/app/Http/Controllers/Transaction/SplitController.php @@ -25,6 +25,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use Illuminate\Http\Request; use Log; use Preferences; @@ -124,18 +125,19 @@ class SplitController extends Controller /** * @param Request $request * @param JournalRepositoryInterface $repository + * @param JournalUpdateInterface $updater * @param TransactionJournal $journal * * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function update(Request $request, JournalRepositoryInterface $repository, TransactionJournal $journal) + public function update(Request $request, JournalRepositoryInterface $repository, JournalUpdateInterface $updater, TransactionJournal $journal) { if ($this->isOpeningBalance($journal)) { return $this->redirectToAccount($journal); } $data = $this->arrayFromInput($request); - $journal = $repository->updateSplitJournal($journal, $data); + $journal = $updater->updateSplitJournal($journal, $data); /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; // save attachments: diff --git a/app/Mail/RegisteredUser.php b/app/Mail/RegisteredUser.php index f48ddfe6d5..924aa883de 100644 --- a/app/Mail/RegisteredUser.php +++ b/app/Mail/RegisteredUser.php @@ -17,7 +17,8 @@ class RegisteredUser extends Mailable /** * Create a new message instance. * - * @return void + * @param string $address + * @param string $ip */ public function __construct(string $address, string $ip) { diff --git a/app/Providers/JournalServiceProvider.php b/app/Providers/JournalServiceProvider.php index 42ff742255..7c65845e93 100644 --- a/app/Providers/JournalServiceProvider.php +++ b/app/Providers/JournalServiceProvider.php @@ -20,6 +20,8 @@ use FireflyIII\Repositories\Journal\JournalRepository; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalTasker; use FireflyIII\Repositories\Journal\JournalTaskerInterface; +use FireflyIII\Repositories\Journal\JournalUpdate; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use Illuminate\Foundation\Application; use Illuminate\Support\ServiceProvider; @@ -50,8 +52,12 @@ class JournalServiceProvider extends ServiceProvider $this->registerRepository(); $this->registerTasker(); $this->registerCollector(); + $this->registerUpdater(); } + /** + * + */ private function registerCollector() { $this->app->bind( @@ -69,6 +75,9 @@ class JournalServiceProvider extends ServiceProvider ); } + /** + * + */ private function registerRepository() { $this->app->bind( @@ -86,6 +95,29 @@ class JournalServiceProvider extends ServiceProvider ); } + /** + * + */ + private function registerUpdater() + { + $this->app->bind( + JournalUpdateInterface::class, + function (Application $app) { + /** @var JournalUpdateInterface $tasker */ + $update = app(JournalUpdate::class); + + if ($app->auth->check()) { + $update->setUser(auth()->user()); + } + + return $update; + } + ); + } + + /** + * + */ private function registerTasker() { $this->app->bind( diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 9a28be284b..85746ec174 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -13,12 +13,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; -use DB; -use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; -use FireflyIII\Models\Budget; -use FireflyIII\Models\Category; use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; @@ -40,10 +35,7 @@ class JournalRepository implements JournalRepositoryInterface /** @var User */ private $user; /** @var array */ - private $validMetaFields - = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', 'internal_reference', 'notes', 'foreign_amount', - 'foreign_currency_id', - ]; + private $validMetaFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', 'internal_reference', 'notes']; /** * @param TransactionJournal $journal @@ -179,8 +171,8 @@ class JournalRepository implements JournalRepositoryInterface // find transaction type. /** @var TransactionType $transactionType */ $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); - $accounts = $this->storeAccounts($transactionType, $data); - $data = $this->verifyNativeAmount($data, $accounts); + $accounts = JournalSupport::storeAccounts($this->user, $transactionType, $data); + $data = JournalSupport::verifyNativeAmount($data, $accounts); $amount = strval($data['amount']); $journal = new TransactionJournal( [ @@ -195,8 +187,8 @@ class JournalRepository implements JournalRepositoryInterface $journal->save(); // store stuff: - $this->storeCategoryWithJournal($journal, $data['category']); - $this->storeBudgetWithJournal($journal, $data['budget_id']); + JournalSupport::storeCategoryWithJournal($journal, $data['category']); + JournalSupport::storeBudgetWithJournal($journal, $data['budget_id']); // store two transactions: $one = [ @@ -211,7 +203,7 @@ class JournalRepository implements JournalRepositoryInterface 'budget' => null, 'identifier' => 0, ]; - $this->storeTransaction($one); + JournalSupport::storeTransaction($one); $two = [ 'journal' => $journal, @@ -226,7 +218,7 @@ class JournalRepository implements JournalRepositoryInterface 'identifier' => 0, ]; - $this->storeTransaction($two); + JournalSupport::storeTransaction($two); // store tags @@ -249,152 +241,6 @@ class JournalRepository implements JournalRepositoryInterface } - /** - * @param TransactionJournal $journal - * @param array $data - * - * @return TransactionJournal - */ - public function update(TransactionJournal $journal, array $data): TransactionJournal - { - - // update actual journal: - $journal->description = $data['description']; - $journal->date = $data['date']; - $accounts = $this->storeAccounts($journal->transactionType, $data); - $data = $this->verifyNativeAmount($data, $accounts); - $data['amount'] = strval($data['amount']); - $data['foreign_amount'] = is_null($data['foreign_amount']) ? null : strval($data['foreign_amount']); - - var_dump($data); - - // unlink all categories, recreate them: - $journal->categories()->detach(); - $journal->budgets()->detach(); - - $this->storeCategoryWithJournal($journal, $data['category']); - $this->storeBudgetWithJournal($journal, $data['budget_id']); - - // negative because source loses money. - $this->updateSourceTransaction($journal, $accounts['source'], $data); - - // positive because destination gets money. - $this->updateDestinationTransaction($journal, $accounts['destination'], $data); - - $journal->save(); - - // update tags: - if (isset($data['tags']) && is_array($data['tags'])) { - $this->updateTags($journal, $data['tags']); - } - - // update meta fields: - $result = $journal->save(); - if ($result) { - foreach ($data as $key => $value) { - if (in_array($key, $this->validMetaFields)) { - $journal->setMeta($key, $value); - continue; - } - Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); - } - - return $journal; - } - - return $journal; - } - - /** - * Same as above but for transaction journal with multiple transactions. - * - * @param TransactionJournal $journal - * @param array $data - * - * @return TransactionJournal - */ - public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal - { - // update actual journal: - $journal->description = $data['journal_description']; - $journal->date = $data['date']; - $journal->save(); - Log::debug(sprintf('Updated split journal #%d', $journal->id)); - - // unlink all categories: - $journal->categories()->detach(); - $journal->budgets()->detach(); - - // update meta fields: - $result = $journal->save(); - if ($result) { - foreach ($data as $key => $value) { - if (in_array($key, $this->validMetaFields)) { - $journal->setMeta($key, $value); - continue; - } - Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); - } - } - - - // update tags: - if (isset($data['tags']) && is_array($data['tags'])) { - $this->updateTags($journal, $data['tags']); - } - - // delete original transactions, and recreate them. - $journal->transactions()->delete(); - - // store each transaction. - $identifier = 0; - Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions']))); - - foreach ($data['transactions'] as $transaction) { - Log::debug(sprintf('Split journal update split transaction %d', $identifier)); - $transaction = $this->appendTransactionData($transaction, $data); - $this->storeSplitTransaction($journal, $transaction, $identifier); - $identifier++; - } - - $journal->save(); - - return $journal; - } - - /** - * When the user edits a split journal, each line is missing crucial data: - * - * - Withdrawal lines are missing the source account ID - * - Deposit lines are missing the destination account ID - * - Transfers are missing both. - * - * We need to append the array. - * - * @param array $transaction - * @param array $data - * - * @return array - */ - private function appendTransactionData(array $transaction, array $data): array - { - switch ($data['what']) { - case strtolower(TransactionType::TRANSFER): - case strtolower(TransactionType::WITHDRAWAL): - $transaction['source_account_id'] = intval($data['journal_source_account_id']); - break; - } - - switch ($data['what']) { - case strtolower(TransactionType::TRANSFER): - case strtolower(TransactionType::DEPOSIT): - $transaction['destination_account_id'] = intval($data['journal_destination_account_id']); - break; - } - - return $transaction; - } - /** * * * Remember: a balancingAct takes at most one expense and one transfer. @@ -422,433 +268,4 @@ class JournalRepository implements JournalRepositoryInterface return true; } - - /** - * @param TransactionType $type - * @param array $data - * - * @return array - * @throws FireflyException - */ - private function storeAccounts(TransactionType $type, array $data): array - { - $accounts = [ - 'source' => null, - 'destination' => null, - ]; - - Log::debug(sprintf('Going to store accounts for type %s', $type->type)); - switch ($type->type) { - case TransactionType::WITHDRAWAL: - $accounts = $this->storeWithdrawalAccounts($data); - break; - - case TransactionType::DEPOSIT: - $accounts = $this->storeDepositAccounts($data); - - break; - case TransactionType::TRANSFER: - $accounts['source'] = Account::where('user_id', $this->user->id)->where('id', $data['source_account_id'])->first(); - $accounts['destination'] = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(); - break; - default: - throw new FireflyException(sprintf('Did not recognise transaction type "%s".', $type->type)); - } - - if (is_null($accounts['source'])) { - Log::error('"source"-account is null, so we cannot continue!', ['data' => $data]); - throw new FireflyException('"source"-account is null, so we cannot continue!'); - } - - if (is_null($accounts['destination'])) { - Log::error('"destination"-account is null, so we cannot continue!', ['data' => $data]); - throw new FireflyException('"destination"-account is null, so we cannot continue!'); - - } - - - return $accounts; - } - - /** - * @param TransactionJournal $journal - * @param int $budgetId - */ - private function storeBudgetWithJournal(TransactionJournal $journal, int $budgetId) - { - if (intval($budgetId) > 0 && $journal->transactionType->type === TransactionType::WITHDRAWAL) { - /** @var \FireflyIII\Models\Budget $budget */ - $budget = Budget::find($budgetId); - $journal->budgets()->save($budget); - } - } - - /** - * @param Transaction $transaction - * @param int $budgetId - */ - private function storeBudgetWithTransaction(Transaction $transaction, int $budgetId) - { - if (intval($budgetId) > 0 && $transaction->transactionJournal->transactionType->type !== TransactionType::TRANSFER) { - /** @var \FireflyIII\Models\Budget $budget */ - $budget = Budget::find($budgetId); - $transaction->budgets()->save($budget); - } - } - - /** - * @param TransactionJournal $journal - * @param string $category - */ - private function storeCategoryWithJournal(TransactionJournal $journal, string $category) - { - if (strlen($category) > 0) { - $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); - $journal->categories()->save($category); - } - } - - /** - * @param Transaction $transaction - * @param string $category - */ - private function storeCategoryWithTransaction(Transaction $transaction, string $category) - { - if (strlen($category) > 0) { - $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $transaction->transactionJournal->user_id]); - $transaction->categories()->save($category); - } - } - - /** - * @param array $data - * - * @return array - */ - private function storeDepositAccounts(array $data): array - { - Log::debug('Now in storeDepositAccounts().'); - $destinationAccount = Account::where('user_id', $this->user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']); - - Log::debug(sprintf('Destination account is #%d ("%s")', $destinationAccount->id, $destinationAccount->name)); - - if (strlen($data['source_account_name']) > 0) { - $sourceType = AccountType::where('type', 'Revenue account')->first(); - $sourceAccount = Account::firstOrCreateEncrypted( - ['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1] - ); - - Log::debug(sprintf('source account name is "%s", account is %d', $data['source_account_name'], $sourceAccount->id)); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - - Log::debug('source_account_name is empty, so default to cash account!'); - - $sourceType = AccountType::where('type', AccountType::CASH)->first(); - $sourceAccount = Account::firstOrCreateEncrypted( - ['user_id' => $this->user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1] - ); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - - /** - * @param TransactionJournal $journal - * @param array $transaction - * @param int $identifier - * - * @return Collection - */ - private function storeSplitTransaction(TransactionJournal $journal, array $transaction, int $identifier): Collection - { - // store source and destination accounts (depends on type) - $accounts = $this->storeAccounts($journal->transactionType, $transaction); - - // store transaction one way: - $amount = bcmul(strval($transaction['amount']), '-1'); - $foreignAmount = is_null($transaction['foreign_amount']) ? null : bcmul(strval($transaction['foreign_amount']), '-1'); - $one = $this->storeTransaction( - [ - 'journal' => $journal, - 'account' => $accounts['source'], - 'amount' => $amount, - 'transaction_currency_id' => $transaction['transaction_currency_id'], - 'foreign_amount' => $foreignAmount, - 'foreign_currency_id' => $transaction['foreign_currency_id'], - 'description' => $transaction['description'], - 'category' => null, - 'budget' => null, - 'identifier' => $identifier, - ] - ); - $this->storeCategoryWithTransaction($one, $transaction['category']); - $this->storeBudgetWithTransaction($one, $transaction['budget_id']); - - // and the other way: - $amount = strval($transaction['amount']); - $foreignAmount = is_null($transaction['foreign_amount']) ? null : strval($transaction['foreign_amount']); - $two = $this->storeTransaction( - [ - 'journal' => $journal, - 'account' => $accounts['destination'], - 'amount' => $amount, - 'transaction_currency_id' => $transaction['transaction_currency_id'], - 'foreign_amount' => $foreignAmount, - 'foreign_currency_id' => $transaction['foreign_currency_id'], - 'description' => $transaction['description'], - 'category' => null, - 'budget' => null, - 'identifier' => $identifier, - ] - ); - $this->storeCategoryWithTransaction($two, $transaction['category']); - $this->storeBudgetWithTransaction($two, $transaction['budget_id']); - - return new Collection([$one, $two]); - } - - /** - * @param array $data - * - * @return Transaction - */ - private function storeTransaction(array $data): Transaction - { - $fields = [ - 'transaction_journal_id' => $data['journal']->id, - 'account_id' => $data['account']->id, - 'amount' => $data['amount'], - 'foreign_amount' => $data['foreign_amount'], - 'transaction_currency_id' => $data['transaction_currency_id'], - 'foreign_currency_id' => $data['foreign_currency_id'], - 'description' => $data['description'], - 'identifier' => $data['identifier'], - ]; - - - if (is_null($data['foreign_currency_id'])) { - unset($fields['foreign_currency_id']); - } - if (is_null($data['foreign_amount'])) { - unset($fields['foreign_amount']); - } - - /** @var Transaction $transaction */ - $transaction = Transaction::create($fields); - - Log::debug(sprintf('Transaction stored with ID: %s', $transaction->id)); - - if (!is_null($data['category'])) { - $transaction->categories()->save($data['category']); - } - - if (!is_null($data['budget'])) { - $transaction->categories()->save($data['budget']); - } - - return $transaction; - - } - - /** - * @param array $data - * - * @return array - */ - private function storeWithdrawalAccounts(array $data): array - { - Log::debug('Now in storeWithdrawalAccounts().'); - $sourceAccount = Account::where('user_id', $this->user->id)->where('id', $data['source_account_id'])->first(['accounts.*']); - - Log::debug(sprintf('Source account is #%d ("%s")', $sourceAccount->id, $sourceAccount->name)); - - if (strlen($data['destination_account_name']) > 0) { - $destinationType = AccountType::where('type', AccountType::EXPENSE)->first(); - $destinationAccount = Account::firstOrCreateEncrypted( - [ - 'user_id' => $this->user->id, - 'account_type_id' => $destinationType->id, - 'name' => $data['destination_account_name'], - 'active' => 1, - ] - ); - - Log::debug(sprintf('destination account name is "%s", account is %d', $data['destination_account_name'], $destinationAccount->id)); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - Log::debug('destination_account_name is empty, so default to cash account!'); - $destinationType = AccountType::where('type', AccountType::CASH)->first(); - $destinationAccount = Account::firstOrCreateEncrypted( - ['user_id' => $this->user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1] - ); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - - - } - - /** - * @param TransactionJournal $journal - * @param Account $account - * @param array $data - * - * @throws FireflyException - */ - private function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data) - { - $set = $journal->transactions()->where('amount', '>', 0)->get(); - if ($set->count() != 1) { - throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); - } - /** @var Transaction $transaction */ - $transaction = $set->first(); - $transaction->amount = app('steam')->positive($data['amount']); - $transaction->transaction_currency_id = $data['currency_id']; - $transaction->foreign_amount = is_null($data['foreign_amount']) ? null : app('steam')->positive($data['foreign_amount']); - $transaction->foreign_currency_id = $data['foreign_currency_id']; - - $transaction->account_id = $account->id; - $transaction->save(); - - } - - /** - * @param TransactionJournal $journal - * @param Account $account - * @param array $data - * - * @throws FireflyException - */ - private function updateSourceTransaction(TransactionJournal $journal, Account $account, array $data) - { - // should be one: - $set = $journal->transactions()->where('amount', '<', 0)->get(); - if ($set->count() != 1) { - throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); - } - /** @var Transaction $transaction */ - $transaction = $set->first(); - $transaction->amount = bcmul(app('steam')->positive($data['amount']), '-1'); - $transaction->transaction_currency_id = $data['currency_id']; - $transaction->foreign_amount = is_null($data['foreign_amount']) ? null : bcmul(app('steam')->positive($data['foreign_amount']), '-1'); - $transaction->foreign_currency_id = $data['foreign_currency_id']; - $transaction->save(); - } - - /** - * @param TransactionJournal $journal - * @param array $array - * - * @return bool - */ - private function updateTags(TransactionJournal $journal, array $array): bool - { - // create tag repository - /** @var TagRepositoryInterface $tagRepository */ - $tagRepository = app(TagRepositoryInterface::class); - - - // find or create all tags: - $tags = []; - $ids = []; - foreach ($array as $name) { - if (strlen(trim($name)) > 0) { - $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); - $tags[] = $tag; - $ids[] = $tag->id; - } - } - - // delete all tags connected to journal not in this array: - if (count($ids) > 0) { - DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); - } - // if count is zero, delete them all: - if (count($ids) == 0) { - DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); - } - - // connect each tag to journal (if not yet connected): - /** @var Tag $tag */ - foreach ($tags as $tag) { - Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); - $tagRepository->connect($journal, $tag); - } - - return true; - } - - /** - * This method checks the data array and the given accounts to verify that the native amount, currency - * and possible the foreign currency and amount are properly saved. - * - * @param array $data - * @param array $accounts - * - * @return array - * @throws FireflyException - */ - private function verifyNativeAmount(array $data, array $accounts): array - { - /** @var TransactionType $transactionType */ - $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); - $submittedCurrencyId = $data['currency_id']; - $data['foreign_amount'] = null; - $data['foreign_currency_id'] = null; - - // which account to check for what the native currency is? - $check = 'source'; - if ($transactionType->type === TransactionType::DEPOSIT) { - $check = 'destination'; - } - switch ($transactionType->type) { - case TransactionType::DEPOSIT: - case TransactionType::WITHDRAWAL: - // continue: - $nativeCurrencyId = intval($accounts[$check]->getMeta('currency_id')); - - // does not match? Then user has submitted amount in a foreign currency: - if ($nativeCurrencyId !== $submittedCurrencyId) { - // store amount and submitted currency in "foreign currency" fields: - $data['foreign_amount'] = $data['amount']; - $data['foreign_currency_id'] = $submittedCurrencyId; - - // overrule the amount and currency ID fields to be the original again: - $data['amount'] = strval($data['native_amount']); - $data['currency_id'] = $nativeCurrencyId; - } - break; - case TransactionType::TRANSFER: - $sourceCurrencyId = intval($accounts['source']->getMeta('currency_id')); - $destinationCurrencyId = intval($accounts['destination']->getMeta('currency_id')); - $data['amount'] = strval($data['source_amount']); - $data['currency_id'] = intval($accounts['source']->getMeta('currency_id')); - - if ($sourceCurrencyId !== $destinationCurrencyId) { - // accounts have different id's, save this info: - $data['foreign_amount'] = strval($data['destination_amount']); - $data['foreign_currency_id'] = $destinationCurrencyId; - } - - break; - default: - throw new FireflyException(sprintf('Cannot handle %s in verifyNativeAmount()', $transactionType->type)); - } - - return $data; - } } diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 028f2d52d7..a25ee4fa23 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -95,20 +95,4 @@ interface JournalRepositoryInterface */ public function store(array $data): TransactionJournal; - /** - * @param TransactionJournal $journal - * @param array $data - * - * @return TransactionJournal - */ - public function update(TransactionJournal $journal, array $data): TransactionJournal; - - /** - * @param TransactionJournal $journal - * @param array $data - * - * @return TransactionJournal - */ - public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal; - } diff --git a/app/Repositories/Journal/JournalSupport.php b/app/Repositories/Journal/JournalSupport.php new file mode 100644 index 0000000000..cb930ccf18 --- /dev/null +++ b/app/Repositories/Journal/JournalSupport.php @@ -0,0 +1,361 @@ + null, + 'destination' => null, + ]; + + Log::debug(sprintf('Going to store accounts for type %s', $type->type)); + switch ($type->type) { + case TransactionType::WITHDRAWAL: + $accounts = self::storeWithdrawalAccounts($user, $data); + break; + + case TransactionType::DEPOSIT: + $accounts = self::storeDepositAccounts($user, $data); + + break; + case TransactionType::TRANSFER: + $accounts['source'] = Account::where('user_id', $user->id)->where('id', $data['source_account_id'])->first(); + $accounts['destination'] = Account::where('user_id', $user->id)->where('id', $data['destination_account_id'])->first(); + break; + default: + throw new FireflyException(sprintf('Did not recognise transaction type "%s".', $type->type)); + } + + if (is_null($accounts['source'])) { + Log::error('"source"-account is null, so we cannot continue!', ['data' => $data]); + throw new FireflyException('"source"-account is null, so we cannot continue!'); + } + + if (is_null($accounts['destination'])) { + Log::error('"destination"-account is null, so we cannot continue!', ['data' => $data]); + throw new FireflyException('"destination"-account is null, so we cannot continue!'); + + } + + + return $accounts; + } + + /** + * @param TransactionJournal $journal + * @param int $budgetId + */ + public static function storeBudgetWithJournal(TransactionJournal $journal, int $budgetId) + { + if (intval($budgetId) > 0 && $journal->transactionType->type === TransactionType::WITHDRAWAL) { + /** @var \FireflyIII\Models\Budget $budget */ + $budget = Budget::find($budgetId); + $journal->budgets()->save($budget); + } + } + + /** + * @param Transaction $transaction + * @param int $budgetId + */ + public static function storeBudgetWithTransaction(Transaction $transaction, int $budgetId) + { + if (intval($budgetId) > 0 && $transaction->transactionJournal->transactionType->type !== TransactionType::TRANSFER) { + /** @var \FireflyIII\Models\Budget $budget */ + $budget = Budget::find($budgetId); + $transaction->budgets()->save($budget); + } + } + + /** + * @param TransactionJournal $journal + * @param string $category + */ + public static function storeCategoryWithJournal(TransactionJournal $journal, string $category) + { + if (strlen($category) > 0) { + $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); + $journal->categories()->save($category); + } + } + + /** + * @param Transaction $transaction + * @param string $category + */ + public static function storeCategoryWithTransaction(Transaction $transaction, string $category) + { + if (strlen($category) > 0) { + $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $transaction->transactionJournal->user_id]); + $transaction->categories()->save($category); + } + } + + /** + * @param User $user + * @param array $data + * + * @return array + */ + public static function storeDepositAccounts(User $user, array $data): array + { + Log::debug('Now in storeDepositAccounts().'); + $destinationAccount = Account::where('user_id', $user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']); + + Log::debug(sprintf('Destination account is #%d ("%s")', $destinationAccount->id, $destinationAccount->name)); + + if (strlen($data['source_account_name']) > 0) { + $sourceType = AccountType::where('type', 'Revenue account')->first(); + $sourceAccount = Account::firstOrCreateEncrypted( + ['user_id' => $user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name'], 'active' => 1] + ); + + Log::debug(sprintf('source account name is "%s", account is %d', $data['source_account_name'], $sourceAccount->id)); + + return [ + 'source' => $sourceAccount, + 'destination' => $destinationAccount, + ]; + } + + Log::debug('source_account_name is empty, so default to cash account!'); + + $sourceType = AccountType::where('type', AccountType::CASH)->first(); + $sourceAccount = Account::firstOrCreateEncrypted( + ['user_id' => $user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account', 'active' => 1] + ); + + return [ + 'source' => $sourceAccount, + 'destination' => $destinationAccount, + ]; + } + + /** + * @param User $user + * @param array $data + * + * @return array + */ + public static function storeWithdrawalAccounts(User $user, array $data): array + { + Log::debug('Now in storeWithdrawalAccounts().'); + $sourceAccount = Account::where('user_id', $user->id)->where('id', $data['source_account_id'])->first(['accounts.*']); + + Log::debug(sprintf('Source account is #%d ("%s")', $sourceAccount->id, $sourceAccount->name)); + + if (strlen($data['destination_account_name']) > 0) { + $destinationType = AccountType::where('type', AccountType::EXPENSE)->first(); + $destinationAccount = Account::firstOrCreateEncrypted( + [ + 'user_id' => $user->id, + 'account_type_id' => $destinationType->id, + 'name' => $data['destination_account_name'], + 'active' => 1, + ] + ); + + Log::debug(sprintf('destination account name is "%s", account is %d', $data['destination_account_name'], $destinationAccount->id)); + + return [ + 'source' => $sourceAccount, + 'destination' => $destinationAccount, + ]; + } + Log::debug('destination_account_name is empty, so default to cash account!'); + $destinationType = AccountType::where('type', AccountType::CASH)->first(); + $destinationAccount = Account::firstOrCreateEncrypted( + ['user_id' => $user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account', 'active' => 1] + ); + + return [ + 'source' => $sourceAccount, + 'destination' => $destinationAccount, + ]; + } + + /** + * @param TransactionJournal $journal + * @param array $array + * + * @return bool + */ + public static function updateTags(TransactionJournal $journal, array $array): bool + { + // create tag repository + /** @var TagRepositoryInterface $tagRepository */ + $tagRepository = app(TagRepositoryInterface::class); + + + // find or create all tags: + $tags = []; + $ids = []; + foreach ($array as $name) { + if (strlen(trim($name)) > 0) { + $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); + $tags[] = $tag; + $ids[] = $tag->id; + } + } + + // delete all tags connected to journal not in this array: + if (count($ids) > 0) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); + } + // if count is zero, delete them all: + if (count($ids) == 0) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); + } + + // connect each tag to journal (if not yet connected): + /** @var Tag $tag */ + foreach ($tags as $tag) { + Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); + $tagRepository->connect($journal, $tag); + } + + return true; + } + + /** + * This method checks the data array and the given accounts to verify that the native amount, currency + * and possible the foreign currency and amount are properly saved. + * + * @param array $data + * @param array $accounts + * + * @return array + * @throws FireflyException + */ + public static function verifyNativeAmount(array $data, array $accounts): array + { + /** @var TransactionType $transactionType */ + $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); + $submittedCurrencyId = $data['currency_id']; + $data['foreign_amount'] = null; + $data['foreign_currency_id'] = null; + + // which account to check for what the native currency is? + $check = 'source'; + if ($transactionType->type === TransactionType::DEPOSIT) { + $check = 'destination'; + } + switch ($transactionType->type) { + case TransactionType::DEPOSIT: + case TransactionType::WITHDRAWAL: + // continue: + $nativeCurrencyId = intval($accounts[$check]->getMeta('currency_id')); + + // does not match? Then user has submitted amount in a foreign currency: + if ($nativeCurrencyId !== $submittedCurrencyId) { + // store amount and submitted currency in "foreign currency" fields: + $data['foreign_amount'] = $data['amount']; + $data['foreign_currency_id'] = $submittedCurrencyId; + + // overrule the amount and currency ID fields to be the original again: + $data['amount'] = strval($data['native_amount']); + $data['currency_id'] = $nativeCurrencyId; + } + break; + case TransactionType::TRANSFER: + $sourceCurrencyId = intval($accounts['source']->getMeta('currency_id')); + $destinationCurrencyId = intval($accounts['destination']->getMeta('currency_id')); + $data['amount'] = strval($data['source_amount']); + $data['currency_id'] = intval($accounts['source']->getMeta('currency_id')); + + if ($sourceCurrencyId !== $destinationCurrencyId) { + // accounts have different id's, save this info: + $data['foreign_amount'] = strval($data['destination_amount']); + $data['foreign_currency_id'] = $destinationCurrencyId; + } + + break; + default: + throw new FireflyException(sprintf('Cannot handle %s in verifyNativeAmount()', $transactionType->type)); + } + + return $data; + } + + /** + * @param array $data + * + * @return Transaction + */ + public static function storeTransaction(array $data): Transaction + { + $fields = [ + 'transaction_journal_id' => $data['journal']->id, + 'account_id' => $data['account']->id, + 'amount' => $data['amount'], + 'foreign_amount' => $data['foreign_amount'], + 'transaction_currency_id' => $data['transaction_currency_id'], + 'foreign_currency_id' => $data['foreign_currency_id'], + 'description' => $data['description'], + 'identifier' => $data['identifier'], + ]; + + + if (is_null($data['foreign_currency_id'])) { + unset($fields['foreign_currency_id']); + } + if (is_null($data['foreign_amount'])) { + unset($fields['foreign_amount']); + } + + /** @var Transaction $transaction */ + $transaction = Transaction::create($fields); + + Log::debug(sprintf('Transaction stored with ID: %s', $transaction->id)); + + if (!is_null($data['category'])) { + $transaction->categories()->save($data['category']); + } + + if (!is_null($data['budget'])) { + $transaction->categories()->save($data['budget']); + } + + return $transaction; + + } +} \ No newline at end of file diff --git a/app/Repositories/Journal/JournalUpdate.php b/app/Repositories/Journal/JournalUpdate.php new file mode 100644 index 0000000000..0be4ac53a5 --- /dev/null +++ b/app/Repositories/Journal/JournalUpdate.php @@ -0,0 +1,290 @@ +user = $user; + } + + /** + * @param TransactionJournal $journal + * @param array $data + * + * @return TransactionJournal + */ + public function update(TransactionJournal $journal, array $data): TransactionJournal + { + + // update actual journal: + $journal->description = $data['description']; + $journal->date = $data['date']; + $accounts = JournalSupport::storeAccounts($this->user, $journal->transactionType, $data); + $data = JournalSupport::verifyNativeAmount($data, $accounts); + $data['amount'] = strval($data['amount']); + $data['foreign_amount'] = is_null($data['foreign_amount']) ? null : strval($data['foreign_amount']); + + // unlink all categories, recreate them: + $journal->categories()->detach(); + $journal->budgets()->detach(); + + JournalSupport::storeCategoryWithJournal($journal, $data['category']); + JournalSupport::storeBudgetWithJournal($journal, $data['budget_id']); + + // negative because source loses money. + $this->updateSourceTransaction($journal, $accounts['source'], $data); + + // positive because destination gets money. + $this->updateDestinationTransaction($journal, $accounts['destination'], $data); + + $journal->save(); + + // update tags: + if (isset($data['tags']) && is_array($data['tags'])) { + JournalSupport::updateTags($journal, $data['tags']); + } + + // update meta fields: + $result = $journal->save(); + if ($result) { + foreach ($data as $key => $value) { + if (in_array($key, $this->validMetaFields)) { + $journal->setMeta($key, $value); + continue; + } + Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); + } + + return $journal; + } + + return $journal; + } + + /** + * Same as above but for transaction journal with multiple transactions. + * + * @param TransactionJournal $journal + * @param array $data + * + * @return TransactionJournal + */ + public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal + { + // update actual journal: + $journal->description = $data['journal_description']; + $journal->date = $data['date']; + $journal->save(); + Log::debug(sprintf('Updated split journal #%d', $journal->id)); + + // unlink all categories: + $journal->categories()->detach(); + $journal->budgets()->detach(); + + // update meta fields: + $result = $journal->save(); + if ($result) { + foreach ($data as $key => $value) { + if (in_array($key, $this->validMetaFields)) { + $journal->setMeta($key, $value); + continue; + } + Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); + } + } + + + // update tags: + if (isset($data['tags']) && is_array($data['tags'])) { + JournalSupport::updateTags($journal, $data['tags']); + } + + // delete original transactions, and recreate them. + $journal->transactions()->delete(); + + // store each transaction. + $identifier = 0; + Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions']))); + + foreach ($data['transactions'] as $transaction) { + Log::debug(sprintf('Split journal update split transaction %d', $identifier)); + $transaction = $this->appendTransactionData($transaction, $data); + $this->storeSplitTransaction($journal, $transaction, $identifier); + $identifier++; + } + + $journal->save(); + + return $journal; + } + + /** + * When the user edits a split journal, each line is missing crucial data: + * + * - Withdrawal lines are missing the source account ID + * - Deposit lines are missing the destination account ID + * - Transfers are missing both. + * + * We need to append the array. + * + * @param array $transaction + * @param array $data + * + * @return array + */ + private function appendTransactionData(array $transaction, array $data): array + { + switch ($data['what']) { + case strtolower(TransactionType::TRANSFER): + case strtolower(TransactionType::WITHDRAWAL): + $transaction['source_account_id'] = intval($data['journal_source_account_id']); + break; + } + + switch ($data['what']) { + case strtolower(TransactionType::TRANSFER): + case strtolower(TransactionType::DEPOSIT): + $transaction['destination_account_id'] = intval($data['journal_destination_account_id']); + break; + } + + return $transaction; + } + + /** + * @param TransactionJournal $journal + * @param array $transaction + * @param int $identifier + * + * @return Collection + */ + private function storeSplitTransaction(TransactionJournal $journal, array $transaction, int $identifier): Collection + { + // store source and destination accounts (depends on type) + $accounts = JournalSupport::storeAccounts($this->user, $journal->transactionType, $transaction); + + // store transaction one way: + $amount = bcmul(strval($transaction['amount']), '-1'); + $foreignAmount = is_null($transaction['foreign_amount']) ? null : bcmul(strval($transaction['foreign_amount']), '-1'); + $one = JournalSupport::storeTransaction( + [ + 'journal' => $journal, + 'account' => $accounts['source'], + 'amount' => $amount, + 'transaction_currency_id' => $transaction['transaction_currency_id'], + 'foreign_amount' => $foreignAmount, + 'foreign_currency_id' => $transaction['foreign_currency_id'], + 'description' => $transaction['description'], + 'category' => null, + 'budget' => null, + 'identifier' => $identifier, + ] + ); + JournalSupport::storeCategoryWithTransaction($one, $transaction['category']); + JournalSupport::storeBudgetWithTransaction($one, $transaction['budget_id']); + + // and the other way: + $amount = strval($transaction['amount']); + $foreignAmount = is_null($transaction['foreign_amount']) ? null : strval($transaction['foreign_amount']); + $two = JournalSupport::storeTransaction( + [ + 'journal' => $journal, + 'account' => $accounts['destination'], + 'amount' => $amount, + 'transaction_currency_id' => $transaction['transaction_currency_id'], + 'foreign_amount' => $foreignAmount, + 'foreign_currency_id' => $transaction['foreign_currency_id'], + 'description' => $transaction['description'], + 'category' => null, + 'budget' => null, + 'identifier' => $identifier, + ] + ); + JournalSupport::storeCategoryWithTransaction($two, $transaction['category']); + JournalSupport::storeBudgetWithTransaction($two, $transaction['budget_id']); + + return new Collection([$one, $two]); + } + + /** + * @param TransactionJournal $journal + * @param Account $account + * @param array $data + * + * @throws FireflyException + */ + private function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data) + { + $set = $journal->transactions()->where('amount', '>', 0)->get(); + if ($set->count() != 1) { + throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); + } + /** @var Transaction $transaction */ + $transaction = $set->first(); + $transaction->amount = app('steam')->positive($data['amount']); + $transaction->transaction_currency_id = $data['currency_id']; + $transaction->foreign_amount = is_null($data['foreign_amount']) ? null : app('steam')->positive($data['foreign_amount']); + $transaction->foreign_currency_id = $data['foreign_currency_id']; + + $transaction->account_id = $account->id; + $transaction->save(); + + } + + /** + * @param TransactionJournal $journal + * @param Account $account + * @param array $data + * + * @throws FireflyException + */ + private function updateSourceTransaction(TransactionJournal $journal, Account $account, array $data) + { + // should be one: + $set = $journal->transactions()->where('amount', '<', 0)->get(); + if ($set->count() != 1) { + throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); + } + /** @var Transaction $transaction */ + $transaction = $set->first(); + $transaction->amount = bcmul(app('steam')->positive($data['amount']), '-1'); + $transaction->transaction_currency_id = $data['currency_id']; + $transaction->foreign_amount = is_null($data['foreign_amount']) ? null : bcmul(app('steam')->positive($data['foreign_amount']), '-1'); + $transaction->foreign_currency_id = $data['foreign_currency_id']; + $transaction->save(); + } + +} \ No newline at end of file diff --git a/app/Repositories/Journal/JournalUpdateInterface.php b/app/Repositories/Journal/JournalUpdateInterface.php new file mode 100644 index 0000000000..21f6f80c85 --- /dev/null +++ b/app/Repositories/Journal/JournalUpdateInterface.php @@ -0,0 +1,44 @@ +first(); // mock stuff $repository = $this->mock(JournalRepositoryInterface::class); + $updater = $this->mock(JournalUpdateInterface::class); $repository->shouldReceive('first')->once()->andReturn(new TransactionJournal); - $repository->shouldReceive('update')->once(); + $updater->shouldReceive('update')->once(); $repository->shouldReceive('find')->once()->andReturn($deposit); diff --git a/tests/Feature/Controllers/Transaction/SingleControllerTest.php b/tests/Feature/Controllers/Transaction/SingleControllerTest.php index 56bd1041bf..b396a961db 100644 --- a/tests/Feature/Controllers/Transaction/SingleControllerTest.php +++ b/tests/Feature/Controllers/Transaction/SingleControllerTest.php @@ -23,6 +23,7 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; @@ -269,6 +270,7 @@ class SingleControllerTest extends TestCase // mock $this->expectsEvents(UpdatedTransactionJournal::class); + $updater = $this->mock(JournalUpdateInterface::class); $repository = $this->mock(JournalRepositoryInterface::class); $journal = new TransactionJournal(); @@ -278,7 +280,7 @@ class SingleControllerTest extends TestCase $journal->transactionType()->associate($type); - $repository->shouldReceive('update')->andReturn($journal); + $updater->shouldReceive('update')->andReturn($journal); $repository->shouldReceive('first')->times(2)->andReturn(new TransactionJournal); $this->session(['transactions.edit.uri' => 'http://localhost']); diff --git a/tests/Feature/Controllers/Transaction/SplitControllerTest.php b/tests/Feature/Controllers/Transaction/SplitControllerTest.php index 578802bc8c..c6cf00eb07 100644 --- a/tests/Feature/Controllers/Transaction/SplitControllerTest.php +++ b/tests/Feature/Controllers/Transaction/SplitControllerTest.php @@ -21,6 +21,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface; +use FireflyIII\Repositories\Journal\JournalUpdateInterface; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; use Tests\TestCase; @@ -134,7 +135,8 @@ class SplitControllerTest extends TestCase // mock stuff $repository = $this->mock(JournalRepositoryInterface::class); - $repository->shouldReceive('updateSplitJournal')->andReturn($deposit); + $updater = $this->mock(JournalUpdateInterface::class); + $updater->shouldReceive('updateSplitJournal')->andReturn($deposit); $repository->shouldReceive('first')->times(2)->andReturn(new TransactionJournal); $attachmentRepos = $this->mock(AttachmentHelperInterface::class); $attachmentRepos->shouldReceive('saveAttachmentsForModel');