diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index 59f47f5aa0..2d1cb6e6f4 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -87,403 +87,4 @@ class SingleController extends Controller ); } - /** - * CLone a transaction. - * - * @param TransactionJournal $journal - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function cloneTransaction(TransactionJournal $journal) - { - $source = $this->repository->getJournalSourceAccounts($journal)->first(); - $destination = $this->repository->getJournalDestinationAccounts($journal)->first(); - $budgetId = $this->repository->getJournalBudgetId($journal); - $categoryName = $this->repository->getJournalCategoryName($journal); - $tags = implode(',', $this->repository->getTags($journal)); - /** @var Transaction $transaction */ - $transaction = $journal->transactions()->first(); - $amount = app('steam')->positive($transaction->amount); - $foreignAmount = null === $transaction->foreign_amount ? null : app('steam')->positive($transaction->foreign_amount); - - // make sure previous URI is correct: - session()->put('transactions.create.fromStore', true); - session()->put('transactions.create.uri', app('url')->previous()); - - $preFilled = [ - 'description' => $journal->description, - 'source_id' => $source->id, - 'source_name' => $source->name, - 'destination_id' => $destination->id, - 'destination_name' => $destination->name, - 'amount' => $amount, - 'source_amount' => $amount, - 'destination_amount' => $foreignAmount, - 'foreign_amount' => $foreignAmount, - 'native_amount' => $foreignAmount, - 'amount_currency_id_amount' => $transaction->foreign_currency_id ?? 0, - 'date' => (new Carbon())->format('Y-m-d'), - 'budget_id' => $budgetId, - 'category' => $categoryName, - 'tags' => $tags, - 'interest_date' => $this->repository->getMetaField($journal, 'interest_date'), - 'book_date' => $this->repository->getMetaField($journal, 'book_date'), - 'process_date' => $this->repository->getMetaField($journal, 'process_date'), - 'due_date' => $this->repository->getMetaField($journal, 'due_date'), - 'payment_date' => $this->repository->getMetaField($journal, 'payment_date'), - 'invoice_date' => $this->repository->getMetaField($journal, 'invoice_date'), - 'internal_reference' => $this->repository->getMetaField($journal, 'internal_reference'), - 'notes' => $this->repository->getNoteText($journal), - ]; - - session()->flash('preFilled', $preFilled); - - return redirect(route('transactions.create', [strtolower($journal->transactionType->type)])); - } - - /** - * Create a new journal. - * - * @param Request $request - * @param string|null $what - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function create(Request $request, string $what = null) - { - $what = strtolower($what ?? TransactionType::DEPOSIT); - $what = (string)($request->old('what') ?? $what); - $budgets = app('expandedform')->makeSelectListWithEmpty($this->budgets->getActiveBudgets()); - $preFilled = session()->has('preFilled') ? session('preFilled') : []; - $subTitle = (string)trans('form.add_new_' . $what); - $subTitleIcon = 'fa-plus'; - $optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; - $source = (int)$request->get('source'); - - // grab old currency ID from old data: - $currencyID = (int)$request->old('amount_currency_id_amount'); - $preFilled['amount_currency_id_amount'] = $currencyID; - - if (('withdrawal' === $what || 'transfer' === $what) && $source > 0) { - $preFilled['source_id'] = $source; - } - if ('deposit' === $what && $source > 0) { - $preFilled['destination_id'] = $source; - } - - session()->put('preFilled', $preFilled); - - // put previous url in session if not redirect from store (not "create another"). - if (true !== session('transactions.create.fromStore')) { - $this->rememberPreviousUri('transactions.create.uri'); - } - session()->forget('transactions.create.fromStore'); - - return view( - 'transactions.single.create', - compact('subTitleIcon', 'budgets', 'what', 'subTitle', 'optionalFields', 'preFilled') - ); - } - - /** - * Show a special JSONified view of a transaction, for easier debug purposes. - * - * @param TransactionJournal $journal - * - * @codeCoverageIgnore - * @return JsonResponse - */ - public function debugShow(TransactionJournal $journal): JsonResponse - { - $array = $journal->toArray(); - $array['transactions'] = []; - $array['meta'] = []; - - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - $array['transactions'][] = $transaction->toArray(); - } - /** @var TransactionJournalMeta $meta */ - foreach ($journal->transactionJournalMeta as $meta) { - $array['meta'][] = $meta->toArray(); - } - - return response()->json($array); - } - - /** - * Shows the form that allows a user to delete a transaction journal. - * - * @param TransactionJournal $journal - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View - */ - public function delete(TransactionJournal $journal) - { - Log::debug(sprintf('Start of delete view for journal #%d', $journal->id)); - // Covered by another controller's tests - // @codeCoverageIgnoreStart - if ($this->isOpeningBalance($journal)) { - return $this->redirectToAccount($journal); - } - // @codeCoverageIgnoreEnd - - $what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type); - $subTitle = (string)trans('firefly.delete_' . $what, ['description' => $journal->description]); - - // put previous url in session - Log::debug('Will try to remember previous URI'); - $this->rememberPreviousUri('transactions.delete.uri'); - - return view('transactions.single.delete', compact('journal', 'subTitle', 'what')); - } - - /** - * Actually destroys the journal. - * - * @param TransactionJournal $transactionJournal - * - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy(TransactionJournal $transactionJournal): RedirectResponse - { - // @codeCoverageIgnoreStart - if ($this->isOpeningBalance($transactionJournal)) { - return $this->redirectToAccount($transactionJournal); - } - // @codeCoverageIgnoreEnd - $type = $this->repository->getTransactionType($transactionJournal); - session()->flash('success', (string)trans('firefly.deleted_' . strtolower($type), ['description' => $transactionJournal->description])); - - $this->repository->destroy($transactionJournal); - - app('preferences')->mark(); - - return redirect($this->getPreviousUri('transactions.delete.uri')); - } - - /** - * Edit a journal. - * - * @param TransactionJournal $journal - * - * @param JournalRepositoryInterface $repository - * - * @return mixed - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository) - { - $transactionType = $repository->getTransactionType($journal); - - // redirect to account: - if ($transactionType === TransactionType::OPENING_BALANCE) { - return $this->redirectToAccount($journal); - } - // redirect to reconcile edit: - if ($transactionType === TransactionType::RECONCILIATION) { - return redirect(route('accounts.reconcile.edit', [$journal->id])); - } - - $what = strtolower($transactionType); - $budgetList = app('expandedform')->makeSelectListWithEmpty($this->budgets->getBudgets()); - - // view related code - $subTitle = (string)trans('breadcrumbs.edit_journal', ['description' => $journal->description]); - - // journal related code - $sourceAccounts = $repository->getJournalSourceAccounts($journal); - $destinationAccounts = $repository->getJournalDestinationAccounts($journal); - $optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; - $pTransaction = $repository->getFirstPosTransaction($journal); - $foreignCurrency = $pTransaction->foreignCurrency ?? $pTransaction->transactionCurrency; - $preFilled = [ - 'date' => $repository->getJournalDate($journal, null), // $journal->dateAsString() - 'interest_date' => $repository->getJournalDate($journal, 'interest_date'), - 'book_date' => $repository->getJournalDate($journal, 'book_date'), - 'process_date' => $repository->getJournalDate($journal, 'process_date'), - 'category' => $repository->getJournalCategoryName($journal), - 'budget_id' => $repository->getJournalBudgetId($journal), - 'tags' => implode(',', $repository->getTags($journal)), - 'source_id' => $sourceAccounts->first()->id, - 'source_name' => $sourceAccounts->first()->edit_name, - 'destination_id' => $destinationAccounts->first()->id, - 'destination_name' => $destinationAccounts->first()->edit_name, - 'bill_id' => $journal->bill_id, - 'bill_name' => null === $journal->bill_id ? null : $journal->bill->name, - - // new custom fields: - 'due_date' => $repository->getJournalDate($journal, 'due_date'), - 'payment_date' => $repository->getJournalDate($journal, 'payment_date'), - 'invoice_date' => $repository->getJournalDate($journal, 'invoice_date'), - 'interal_reference' => $repository->getMetaField($journal, 'internal_reference'), - 'notes' => $repository->getNoteText($journal), - - // amount fields - 'amount' => $pTransaction->amount, - 'source_amount' => $pTransaction->amount, - 'native_amount' => $pTransaction->amount, - 'destination_amount' => $pTransaction->foreign_amount, - 'currency' => $pTransaction->transactionCurrency, - 'source_currency' => $pTransaction->transactionCurrency, - 'native_currency' => $pTransaction->transactionCurrency, - 'foreign_currency' => $foreignCurrency, - 'destination_currency' => $foreignCurrency, - ]; - - // amounts for withdrawals and deposits: - // amount, native_amount, source_amount, destination_amount - if (null !== $pTransaction->foreign_amount && ($journal->isWithdrawal() || $journal->isDeposit())) { - $preFilled['amount'] = $pTransaction->foreign_amount; - $preFilled['currency'] = $pTransaction->foreignCurrency; - } - - session()->flash('preFilled', $preFilled); - - // put previous url in session if not redirect from store (not "return_to_edit"). - if (true !== session('transactions.edit.fromUpdate')) { - $this->rememberPreviousUri('transactions.edit.uri'); - } - session()->forget('transactions.edit.fromUpdate'); - - return view( - 'transactions.single.edit', - compact('journal', 'optionalFields', 'what', 'budgetList', 'subTitle') - )->with('data', $preFilled); - } - - /** - * Stores a new journal. - * - * @param JournalFormRequest $request - * @param JournalRepositoryInterface $repository - * - * @return RedirectResponse - * @throws \FireflyIII\Exceptions\FireflyException - * - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function store(JournalFormRequest $request, JournalRepositoryInterface $repository): RedirectResponse - { - $doSplit = 1 === (int)$request->get('split_journal'); - $createAnother = 1 === (int)$request->get('create_another'); - $data = $request->getJournalData(); - $group = $repository->store($data); - - throw new FireflyException('Needs refactor'); - if (null === $journal->id) { - // error! - Log::error('Could not store transaction journal.'); - session()->flash('error', (string)trans('firefly.unknown_journal_error')); - - return redirect(route('transactions.create', [$request->input('what')]))->withInput(); - } - - /** @var array $files */ - $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($journal, $files); - - // store the journal only, flash the rest. - Log::debug(sprintf('Count of error messages is %d', $this->attachments->getErrors()->count())); - if (count($this->attachments->getErrors()->get('attachments')) > 0) { - session()->flash('error', $this->attachments->getErrors()->get('attachments')); - } - // flash messages - if (count($this->attachments->getMessages()->get('attachments')) > 0) { - session()->flash('info', $this->attachments->getMessages()->get('attachments')); - } - - event(new StoredTransactionGroup($group)); - - session()->flash('success_uri', route('transactions.show', [$journal->id])); - session()->flash('success', (string)trans('firefly.stored_journal', ['description' => $journal->description])); - app('preferences')->mark(); - - // @codeCoverageIgnoreStart - if (true === $createAnother) { - session()->put('transactions.create.fromStore', true); - - return redirect(route('transactions.create', [$request->input('what')]))->withInput(); - } - - if (true === $doSplit) { - return redirect(route('transactions.split.edit', [$journal->id])); - } - - // @codeCoverageIgnoreEnd - - return redirect($this->getPreviousUri('transactions.create.uri')); - } - - /** - * Update a journal. - * - * @param JournalFormRequest $request - * @param JournalRepositoryInterface $repository - * @param TransactionJournal $journal - * - * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal) - { - // @codeCoverageIgnoreStart - if ($this->isOpeningBalance($journal)) { - return $this->redirectToAccount($journal); - } - // @codeCoverageIgnoreEnd - - $data = $request->getJournalData(); - - // keep current bill: - $data['bill_id'] = $journal->bill_id; - - // remove it if no checkbox: - if (!$request->boolean('keep_bill_id')) { - $data['bill_id'] = null; - } - throw new FireflyException('Needs refactor'); - - $journal = $repository->update($journal, $data); - /** @var array $files */ - $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($journal, $files); - - // @codeCoverageIgnoreStart - if (count($this->attachments->getErrors()->get('attachments')) > 0) { - session()->flash('error', $this->attachments->getErrors()->get('attachments')); - } - if (count($this->attachments->getMessages()->get('attachments')) > 0) { - session()->flash('info', $this->attachments->getMessages()->get('attachments')); - } - // @codeCoverageIgnoreEnd - - event(new UpdatedTransactionGroup($group)); - // update, get events by date and sort DESC - - $type = strtolower($this->repository->getTransactionType($journal)); - session()->flash('success', (string)trans('firefly.updated_' . $type, ['description' => $data['description']])); - app('preferences')->mark(); - - // @codeCoverageIgnoreStart - if (1 === (int)$request->get('return_to_edit')) { - session()->put('transactions.edit.fromUpdate', true); - - return redirect(route('transactions.edit', [$journal->id]))->withInput(['return_to_edit' => 1]); - } - // @codeCoverageIgnoreEnd - - // redirect to previous URL. - return redirect($this->getPreviousUri('transactions.edit.uri')); - } } diff --git a/tests/Feature/Controllers/Transaction/IndexControllerTest.php b/tests/Feature/Controllers/Transaction/IndexControllerTest.php index 634b4881bd..b08f6a4ec8 100644 --- a/tests/Feature/Controllers/Transaction/IndexControllerTest.php +++ b/tests/Feature/Controllers/Transaction/IndexControllerTest.php @@ -99,15 +99,11 @@ class IndexControllerTest extends TestCase $userRepos = $this->mock(UserRepositoryInterface::class); $collector = $this->mock(GroupCollectorInterface::class); - // generic set for the info blocks: - $groupArray = [$this->getRandomWithdrawalAsArray()]; - // role? $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true); // make paginator. $paginator = new LengthAwarePaginator([$group], 1, 40, 1); - //Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('10'); $collector->shouldReceive('setTypes')->atLeast()->once()->andReturnSelf(); $collector->shouldReceive('setRange')->atLeast()->once()->andReturnSelf(); @@ -117,13 +113,10 @@ class IndexControllerTest extends TestCase $collector->shouldReceive('withCategoryInformation')->atLeast()->once()->andReturnSelf(); $collector->shouldReceive('withAccountInformation')->atLeast()->once()->andReturnSelf(); $collector->shouldReceive('getPaginatedGroups')->atLeast()->once()->andReturn($paginator); - //$collector->shouldReceive('getExtractedJournals')->atLeast()->once()->andReturn($groupArray); - $pref = new Preference; $pref->data = 50; Preferences::shouldReceive('get')->withArgs(['listPageSize', 50])->atLeast()->once()->andReturn($pref); - //Preferences::shouldReceive('lastActivity')->atLeast()->once()->andReturn('md512345'); $this->be($this->user()); $response = $this->get(route('transactions.index.all', ['withdrawal'])); diff --git a/tests/Feature/Controllers/Transaction/ShowControllerTest.php b/tests/Feature/Controllers/Transaction/ShowControllerTest.php new file mode 100644 index 0000000000..324fd08a2d --- /dev/null +++ b/tests/Feature/Controllers/Transaction/ShowControllerTest.php @@ -0,0 +1,85 @@ +. + */ + +namespace Tests\Feature\Controllers\Transaction; + + +use Amount; +use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Transformers\TransactionGroupTransformer; +use Log; +use Mockery; +use Tests\TestCase; + +/** + * Class ShowControllerTest + */ +class ShowControllerTest extends TestCase +{ + /** + * + */ + public function setUp(): void + { + parent::setUp(); + Log::info(sprintf('Now in %s.', get_class($this))); + } + + /** + * @covers \FireflyIII\Http\Controllers\Transaction\ShowController + */ + public function testShow(): void + { + $this->mockDefaultSession(); + + // values + $withdrawal = $this->getRandomWithdrawalGroup(); + $array = $this->getRandomWithdrawalGroupAsArray(); + + $array[0]['transactions'][0]['foreign_amount'] = '10'; + $array[0]['transactions'][0]['foreign_currency_symbol'] = 'x'; + $array[0]['transactions'][0]['foreign_currency_decimal_places'] = 2; + + $groupRepository = $this->mock(TransactionGroupRepositoryInterface::class); + $userRepos = $this->mock(UserRepositoryInterface::class); + $transformer = $this->mock(TransactionGroupTransformer::class); + + // mock for transformer: + $transformer->shouldReceive('setParameters')->atLeast()->once(); + $transformer->shouldReceive('transformObject')->atLeast()->once()->andReturn($array[0]); + + // mock for repos + $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true); + $groupRepository->shouldReceive('getPiggyEvents')->atLeast()->once()->andReturn([]); + $groupRepository->shouldReceive('getAttachments')->atLeast()->once()->andReturn([]); + $groupRepository->shouldReceive('getLinks')->atLeast()->once()->andReturn([]); + + Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('x'); + + + $this->be($this->user()); + $response = $this->get(route('transactions.show', [$withdrawal->id])); + $response->assertStatus(200); + // has bread crumb + $response->assertSee('