mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-29 06:34:37 +00:00 
			
		
		
		
	Improve account CRUD and tests.
This commit is contained in:
		| @@ -51,11 +51,13 @@ class RenameAccountMeta extends Command | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $start = microtime(true); | ||||
|         // @codeCoverageIgnoreStart | ||||
|         if ($this->isExecuted() && true !== $this->option('force')) { | ||||
|             $this->warn('This command has already been executed.'); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         // @codeCoverageIgnoreEnd | ||||
|         $array = [ | ||||
|             'accountRole'          => 'account_role', | ||||
|             'ccType'               => 'cc_type', | ||||
|   | ||||
| @@ -27,7 +27,6 @@ namespace FireflyIII\Factory; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Services\Internal\Support\AccountServiceTrait; | ||||
| use FireflyIII\User; | ||||
| @@ -40,12 +39,13 @@ use Log; | ||||
|  */ | ||||
| class AccountFactory | ||||
| { | ||||
|     use AccountServiceTrait; | ||||
|  | ||||
|     /** @var AccountRepositoryInterface */ | ||||
|     protected $accountRepository; | ||||
|     /** @var User */ | ||||
|     private $user; | ||||
|  | ||||
|     use AccountServiceTrait; | ||||
|     /** @var array */ | ||||
|     private $canHaveVirtual; | ||||
|  | ||||
| @@ -223,27 +223,5 @@ class AccountFactory | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $currencyId | ||||
|      * @param string $currencyCode | ||||
|      * @return TransactionCurrency | ||||
|      */ | ||||
|     protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency | ||||
|     { | ||||
|         // find currency, or use default currency instead. | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory = app(TransactionCurrencyFactory::class); | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         $currency = $factory->find($currencyId, $currencyCode); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             // use default currency: | ||||
|             $currency = app('amount')->getDefaultCurrencyByUser($this->user); | ||||
|         } | ||||
|         $currency->enabled = true; | ||||
|         $currency->save(); | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -121,6 +121,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|             'source.foreign_amount as foreign_amount', | ||||
|             'source.foreign_currency_id as foreign_currency_id', | ||||
|             'foreign_currency.code as foreign_currency_code', | ||||
|             'foreign_currency.name as foreign_currency_name', | ||||
|             'foreign_currency.symbol as foreign_currency_symbol', | ||||
|             'foreign_currency.decimal_places as foreign_currency_decimal_places', | ||||
|  | ||||
| @@ -590,6 +591,7 @@ class GroupCollector implements GroupCollectorInterface | ||||
|  | ||||
|     /** | ||||
|      * Return the sum of all journals. | ||||
|      * TODO ignores the currency. | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Http\Requests\AccountFormRequest; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Controllers\ModelInformation; | ||||
| use Illuminate\Http\Request; | ||||
| use Log; | ||||
|  | ||||
| @@ -37,11 +38,13 @@ use Log; | ||||
|  */ | ||||
| class CreateController extends Controller | ||||
| { | ||||
|     use ModelInformation; | ||||
|     /** @var AccountRepositoryInterface The account repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * CreateController constructor. | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -122,11 +125,9 @@ class CreateController extends Controller | ||||
|  | ||||
|         // update preferences if necessary: | ||||
|         $frontPage = app('preferences')->get('frontPageAccounts', [])->data; | ||||
|         if (AccountType::ASSET === $account->accountType->type && count($frontPage) > 0) { | ||||
|             // @codeCoverageIgnoreStart | ||||
|         if (AccountType::ASSET === $account->accountType->type) { | ||||
|             $frontPage[] = $account->id; | ||||
|             app('preferences')->set('frontPageAccounts', $frontPage); | ||||
|             // @codeCoverageIgnoreEnd | ||||
|         } | ||||
|         // redirect to previous URL. | ||||
|         $redirect = redirect($this->getPreviousUri('accounts.create.uri')); | ||||
| @@ -140,40 +141,6 @@ class CreateController extends Controller | ||||
|         return $redirect; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getRoles(): array | ||||
|     { | ||||
|         $roles = []; | ||||
|         foreach (config('firefly.accountRoles') as $role) { | ||||
|             $roles[$role] = (string)trans(sprintf('firefly.account_role_%s', $role)); | ||||
|         } | ||||
|  | ||||
|         return $roles; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function getLiabilityTypes(): array | ||||
|     { | ||||
|  | ||||
|         // types of liability: | ||||
|         $debt     = $this->repository->getAccountTypeByType(AccountType::DEBT); | ||||
|         $loan     = $this->repository->getAccountTypeByType(AccountType::LOAN); | ||||
|         $mortgage = $this->repository->getAccountTypeByType(AccountType::MORTGAGE); | ||||
|         /** @noinspection NullPointerExceptionInspection */ | ||||
|         $liabilityTypes = [ | ||||
|             $debt->id     => (string)trans(sprintf('firefly.account_type_%s', AccountType::DEBT)), | ||||
|             $loan->id     => (string)trans(sprintf('firefly.account_type_%s', AccountType::LOAN)), | ||||
|             $mortgage->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::MORTGAGE)), | ||||
|         ]; | ||||
|         asort($liabilityTypes); | ||||
|  | ||||
|         return $liabilityTypes; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,7 @@ class DeleteController extends Controller | ||||
|  | ||||
|     /** | ||||
|      * DeleteController constructor. | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -66,16 +67,16 @@ class DeleteController extends Controller | ||||
|      */ | ||||
|     public function delete(Account $account) | ||||
|     { | ||||
|         $typeName    = config('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $subTitle    = (string)trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]); | ||||
|         $typeName    = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); | ||||
|         $subTitle    = (string)trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]); | ||||
|         $accountList = app('expandedform')->makeSelectListWithEmpty($this->repository->getAccountsByType([$account->accountType->type])); | ||||
|         $what        = $typeName; | ||||
|         $objectType  = $typeName; | ||||
|         unset($accountList[$account->id]); | ||||
|  | ||||
|         // put previous url in session | ||||
|         $this->rememberPreviousUri('accounts.delete.uri'); | ||||
|  | ||||
|         return view('accounts.delete', compact('account', 'subTitle', 'accountList', 'what')); | ||||
|         return view('accounts.delete', compact('account', 'subTitle', 'accountList', 'objectType')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -89,13 +90,13 @@ class DeleteController extends Controller | ||||
|     public function destroy(Request $request, Account $account) | ||||
|     { | ||||
|         $type     = $account->accountType->type; | ||||
|         $typeName = config('firefly.shortNamesByFullName.' . $type); | ||||
|         $typeName = config(sprintf('firefly.shortNamesByFullName.%s', $type)); | ||||
|         $name     = $account->name; | ||||
|         $moveTo   = $this->repository->findNull((int)$request->get('move_account_before_delete')); | ||||
|  | ||||
|         $this->repository->destroy($account, $moveTo); | ||||
|  | ||||
|         $request->session()->flash('success', (string)trans('firefly.' . $typeName . '_deleted', ['name' => $name])); | ||||
|         $request->session()->flash('success', (string)trans(sprintf('firefly.%s_deleted', $typeName), ['name' => $name])); | ||||
|         app('preferences')->mark(); | ||||
|  | ||||
|         return redirect($this->getPreviousUri('accounts.delete.uri')); | ||||
|   | ||||
| @@ -27,9 +27,9 @@ namespace FireflyIII\Http\Controllers\Account; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Http\Requests\AccountFormRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Support\Http\Controllers\ModelInformation; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| /** | ||||
| @@ -38,6 +38,7 @@ use Illuminate\Http\Request; | ||||
|  */ | ||||
| class EditController extends Controller | ||||
| { | ||||
|     use ModelInformation; | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $currencyRepos; | ||||
|     /** @var AccountRepositoryInterface The account repository */ | ||||
| @@ -78,24 +79,11 @@ class EditController extends Controller | ||||
|      */ | ||||
|     public function edit(Request $request, Account $account, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $what         = config('firefly.shortNamesByFullName')[$account->accountType->type]; | ||||
|         $subTitle     = (string)trans('firefly.edit_' . $what . '_account', ['name' => $account->name]); | ||||
|         $subTitleIcon = config('firefly.subIconsByIdentifier.' . $what); | ||||
|         $roles        = []; | ||||
|         foreach (config('firefly.accountRoles') as $role) { | ||||
|             $roles[$role] = (string)trans('firefly.account_role_' . $role); | ||||
|         } | ||||
|  | ||||
|         // types of liability: | ||||
|         $debt           = $this->repository->getAccountTypeByType(AccountType::DEBT); | ||||
|         $loan           = $this->repository->getAccountTypeByType(AccountType::LOAN); | ||||
|         $mortgage       = $this->repository->getAccountTypeByType(AccountType::MORTGAGE); | ||||
|         $liabilityTypes = [ | ||||
|             $debt->id     => (string)trans('firefly.account_type_' . AccountType::DEBT), | ||||
|             $loan->id     => (string)trans('firefly.account_type_' . AccountType::LOAN), | ||||
|             $mortgage->id => (string)trans('firefly.account_type_' . AccountType::MORTGAGE), | ||||
|         ]; | ||||
|         asort($liabilityTypes); | ||||
|         $objectType     = config('firefly.shortNamesByFullName')[$account->accountType->type]; | ||||
|         $subTitle       = (string)trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]); | ||||
|         $subTitleIcon   = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); | ||||
|         $roles          = $this->getRoles(); | ||||
|         $liabilityTypes = $this->getLiabilityTypes(); | ||||
|  | ||||
|         // interest calculation periods: | ||||
|         $interestPeriods = [ | ||||
| @@ -146,7 +134,7 @@ class EditController extends Controller | ||||
|         $request->session()->flash('preFilled', $preFilled); | ||||
|  | ||||
|         return view( | ||||
|             'accounts.edit', compact('account', 'currency', 'subTitle', 'subTitleIcon', 'what', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods') | ||||
|             'accounts.edit', compact('account', 'currency', 'subTitle', 'subTitleIcon', 'objectType', 'roles', 'preFilled', 'liabilityTypes', 'interestPeriods') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -43,6 +43,7 @@ class IndexController extends Controller | ||||
|  | ||||
|     /** | ||||
|      * IndexController constructor. | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
| @@ -65,16 +66,16 @@ class IndexController extends Controller | ||||
|      * Show list of accounts. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param string  $what | ||||
|      * @param string $objectType | ||||
|      * | ||||
|      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View | ||||
|      */ | ||||
|     public function index(Request $request, string $what) | ||||
|     public function index(Request $request, string $objectType) | ||||
|     { | ||||
|         $what         = $what ?? 'asset'; | ||||
|         $subTitle     = (string)trans('firefly.' . $what . '_accounts'); | ||||
|         $subTitleIcon = config('firefly.subIconsByIdentifier.' . $what); | ||||
|         $types        = config('firefly.accountTypesByIdentifier.' . $what); | ||||
|         $objectType   = $objectType ?? 'asset'; | ||||
|         $subTitle     = (string)trans(sprintf('firefly.%s_accounts', $objectType)); | ||||
|         $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); | ||||
|         $types        = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); | ||||
|         $collection   = $this->repository->getAccountsByType($types); | ||||
|         $total        = $collection->count(); | ||||
|         $page         = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); | ||||
| @@ -99,16 +100,16 @@ class IndexController extends Controller | ||||
|                 $account->endBalance        = $this->isInArray($endBalances, $account->id); | ||||
|                 $account->difference        = bcsub($account->endBalance, $account->startBalance); | ||||
|                 $account->interest          = round($this->repository->getMetaValue($account, 'interest'), 6); | ||||
|                 $account->interestPeriod    = (string)trans('firefly.interest_calc_' . $this->repository->getMetaValue($account, 'interest_period')); | ||||
|                 $account->accountTypeString = (string)trans('firefly.account_type_' . $account->accountType->type); | ||||
|                 $account->interestPeriod    = (string)trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))); | ||||
|                 $account->accountTypeString = (string)trans(sprintf('firefly.account_type_%s', $account->accountType->type)); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         // make paginator: | ||||
|         $accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page); | ||||
|         $accounts->setPath(route('accounts.index', [$what])); | ||||
|         $accounts->setPath(route('accounts.index', [$objectType])); | ||||
|  | ||||
|         return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'page', 'accounts')); | ||||
|         return view('accounts.index', compact('objectType', 'subTitleIcon', 'subTitle', 'page', 'accounts')); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -111,8 +111,7 @@ class AccountFormRequest extends Request | ||||
|             'interest_period'                    => 'in:daily,monthly,yearly', | ||||
|         ]; | ||||
|  | ||||
|         // TODO verify if this will work. | ||||
|         if ('liabilities' === $this->get('what')) { | ||||
|         if ('liabilities' === $this->get('objectType')) { | ||||
|             $rules['opening_balance']      = ['numeric', 'required']; | ||||
|             $rules['opening_balance_date'] = 'date|required'; | ||||
|         } | ||||
|   | ||||
| @@ -26,11 +26,15 @@ namespace FireflyIII\Services\Internal\Support; | ||||
| use Exception; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Factory\AccountMetaFactory; | ||||
| use FireflyIII\Factory\TransactionCurrencyFactory; | ||||
| use FireflyIII\Factory\TransactionGroupFactory; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Note; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; | ||||
| use Log; | ||||
| @@ -75,6 +79,32 @@ trait AccountServiceTrait | ||||
|         return $iban; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update meta data 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 | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function updateMetaData(Account $account, array $data): void | ||||
|     { | ||||
|         $fields = $this->validFields; | ||||
|  | ||||
|         if ($account->accountType->type === AccountType::ASSET) { | ||||
|             $fields = $this->validAssetFields; | ||||
|         } | ||||
|         if ($account->accountType->type === AccountType::ASSET && 'ccAsset' === $data['account_role']) { | ||||
|             $fields = $this->validCCFields; | ||||
|         } | ||||
|         /** @var AccountMetaFactory $factory */ | ||||
|         $factory = app(AccountMetaFactory::class); | ||||
|         foreach ($fields as $field) { | ||||
|             $factory->crud($account, $field, (string)($data[$field] ?? '')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| //    /** | ||||
| //     * @param User $user | ||||
| //     * @param string $name | ||||
| @@ -126,29 +156,34 @@ trait AccountServiceTrait | ||||
| //    } | ||||
|  | ||||
|     /** | ||||
|      * Update meta data 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 | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @param string $note | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function updateMetaData(Account $account, array $data): void | ||||
|     public function updateNote(Account $account, string $note): bool | ||||
|     { | ||||
|         $fields = $this->validFields; | ||||
|         if ('' === $note) { | ||||
|             $dbNote = $account->notes()->first(); | ||||
|             if (null !== $dbNote) { | ||||
|                 try { | ||||
|                     $dbNote->delete(); | ||||
|                 } catch (Exception $e) { | ||||
|                     Log::debug($e->getMessage()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         if ($account->accountType->type === AccountType::ASSET) { | ||||
|             $fields = $this->validAssetFields; | ||||
|             return true; | ||||
|         } | ||||
|         if ($account->accountType->type === AccountType::ASSET && 'ccAsset' === $data['account_role']) { | ||||
|             $fields = $this->validCCFields; | ||||
|         } | ||||
|         /** @var AccountMetaFactory $factory */ | ||||
|         $factory = app(AccountMetaFactory::class); | ||||
|         foreach ($fields as $field) { | ||||
|             $factory->crud($account, $field, (string)($data[$field] ?? '')); | ||||
|         $dbNote = $account->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             $dbNote = new Note; | ||||
|             $dbNote->noteable()->associate($account); | ||||
|         } | ||||
|         $dbNote->text = trim($note); | ||||
|         $dbNote->save(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| //    /** | ||||
| @@ -262,37 +297,6 @@ trait AccountServiceTrait | ||||
| //        return $journal; | ||||
| //    } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string $note | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function updateNote(Account $account, string $note): bool | ||||
|     { | ||||
|         if ('' === $note) { | ||||
|             $dbNote = $account->notes()->first(); | ||||
|             if (null !== $dbNote) { | ||||
|                 try { | ||||
|                     $dbNote->delete(); | ||||
|                 } catch (Exception $e) { | ||||
|                     Log::debug($e->getMessage()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|         $dbNote = $account->notes()->first(); | ||||
|         if (null === $dbNote) { | ||||
|             $dbNote = new Note; | ||||
|             $dbNote->noteable()->associate($account); | ||||
|         } | ||||
|         $dbNote->text = trim($note); | ||||
|         $dbNote->save(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Verify if array contains valid data to possibly store or update the opening balance. | ||||
|      * | ||||
| @@ -313,6 +317,29 @@ trait AccountServiceTrait | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $currencyId | ||||
|      * @param string $currencyCode | ||||
|      * @return TransactionCurrency | ||||
|      */ | ||||
|     protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency | ||||
|     { | ||||
|         // find currency, or use default currency instead. | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory = app(TransactionCurrencyFactory::class); | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         $currency = $factory->find($currencyId, $currencyCode); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             // use default currency: | ||||
|             $currency = app('amount')->getDefaultCurrencyByUser($this->user); | ||||
|         } | ||||
|         $currency->enabled = true; | ||||
|         $currency->save(); | ||||
|  | ||||
|         return $currency; | ||||
|     } | ||||
|  | ||||
| //    /** | ||||
| //     * @param Account            $account | ||||
| //     * @param TransactionJournal $journal | ||||
| @@ -446,6 +473,7 @@ trait AccountServiceTrait | ||||
|             Log::error($e->getMessage()); | ||||
|             Log::error($e->getTraceAsString()); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return $group; | ||||
| @@ -462,12 +490,46 @@ trait AccountServiceTrait | ||||
|      */ | ||||
|     protected function updateOBGroup(Account $account, array $data): ?TransactionGroup | ||||
|     { | ||||
|         if (null === $this->getOBGroup($account)) { | ||||
|         $obGroup = $this->getOBGroup($account); | ||||
|         if (null === $obGroup) { | ||||
|             return $this->createOBGroup($account, $data); | ||||
|         } | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal                          = $obGroup->transactionJournals()->first(); | ||||
|         $journal->date                    = $data['opening_balance_date'] ?? $journal->date; | ||||
|         $journal->transaction_currency_id = $data['currency_id']; | ||||
|  | ||||
|         // edit in this method | ||||
|         die('cannot handle edit'); | ||||
|         /** @var Transaction $obTransaction */ | ||||
|         $obTransaction = $journal->transactions()->where('account_id', '!=', $account->id)->first(); | ||||
|         /** @var Transaction $accountTransaction */ | ||||
|         $accountTransaction = $journal->transactions()->where('account_id', $account->id)->first(); | ||||
|  | ||||
|         // if amount is negative: | ||||
|         if (1 === bccomp('0', $data['opening_balance'])) { | ||||
|             // account transaction loses money: | ||||
|             $accountTransaction->amount                  = app('steam')->negative($data['opening_balance']); | ||||
|             $accountTransaction->transaction_currency_id = $data['currency_id']; | ||||
|  | ||||
|             // OB account transaction gains money | ||||
|             $obTransaction->amount                  = app('steam')->positive($data['opening_balance']); | ||||
|             $obTransaction->transaction_currency_id = $data['currency_id']; | ||||
|         } | ||||
|         if (-1 === bccomp('0', $data['opening_balance'])) { | ||||
|             // account gains money: | ||||
|             $accountTransaction->amount                  = app('steam')->positive($data['opening_balance']); | ||||
|             $accountTransaction->transaction_currency_id = $data['currency_id']; | ||||
|  | ||||
|             // OB account loses money: | ||||
|             $obTransaction->amount                  = app('steam')->negative($data['opening_balance']); | ||||
|             $obTransaction->transaction_currency_id = $data['currency_id']; | ||||
|         } | ||||
|         // save both | ||||
|         $accountTransaction->save(); | ||||
|         $obTransaction->save(); | ||||
|         $journal->save(); | ||||
|         $obGroup->refresh(); | ||||
|  | ||||
|         return $obGroup; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -25,7 +25,9 @@ namespace FireflyIII\Services\Internal\Update; | ||||
|  | ||||
| use FireflyIII\Factory\TransactionCurrencyFactory; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Services\Internal\Support\AccountServiceTrait; | ||||
| use Log; | ||||
|  | ||||
| @@ -36,6 +38,11 @@ class AccountUpdateService | ||||
| { | ||||
|     use AccountServiceTrait; | ||||
|  | ||||
|     /** @var array */ | ||||
|     private $canHaveVirtual; | ||||
|     /** @var AccountRepositoryInterface */ | ||||
|     protected $accountRepository; | ||||
|  | ||||
|     /** | ||||
|      * Constructor. | ||||
|      */ | ||||
| @@ -44,6 +51,9 @@ class AccountUpdateService | ||||
|         if ('testing' === config('app.env')) { | ||||
|             Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this))); | ||||
|         } | ||||
|         // TODO move to configuration. | ||||
|         $this->canHaveVirtual    = [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD]; | ||||
|         $this->accountRepository = app(AccountRepositoryInterface::class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -53,12 +63,11 @@ class AccountUpdateService | ||||
|      * @param array   $data | ||||
|      * | ||||
|      * @return Account | ||||
|      * @throws \FireflyIII\Exceptions\FireflyException | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function update(Account $account, array $data): Account | ||||
|     { | ||||
|         $this->accountRepository->setUser($account->user); | ||||
|  | ||||
|         // update the account itself: | ||||
|         $account->name            = $data['name']; | ||||
|         $account->active          = $data['active']; | ||||
| @@ -69,32 +78,26 @@ class AccountUpdateService | ||||
|         if (isset($data['currency_id']) && 0 === $data['currency_id']) { | ||||
|             unset($data['currency_id']); | ||||
|         } | ||||
|         // find currency, or use default currency instead. | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory = app(TransactionCurrencyFactory::class); | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         $currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             // use default currency: | ||||
|             $currency = app('amount')->getDefaultCurrencyByUser($account->user); | ||||
|         } | ||||
|         $currency->enabled = true; | ||||
|         $currency->save(); | ||||
|         // find currency, or use default currency instead. | ||||
|         $currency = $this->getCurrency((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)); | ||||
|         unset($data['currency_code']); | ||||
|         $data['currency_id'] = $currency->id; | ||||
|  | ||||
|  | ||||
|         // update all meta data: | ||||
|         $this->updateMetaData($account, $data); | ||||
|  | ||||
|         // has valid initial balance (IB) data? | ||||
|         if ($this->validOBData($data)) { | ||||
|             // then do update! | ||||
|             $this->updateIB($account, $data); | ||||
|         } | ||||
|  | ||||
|         // if not, delete it when exist. | ||||
|         if (!$this->validOBData($data)) { | ||||
|             $this->deleteIB($account); | ||||
|         $type = $account->accountType; | ||||
|         // if it can have a virtual balance, it can also have an opening balance. | ||||
|         if (in_array($type->type, $this->canHaveVirtual, true)) { | ||||
|             if ($this->validOBData($data)) { | ||||
|                 $this->updateOBGroup($account, $data); | ||||
|             } | ||||
|             if (!$this->validOBData($data)) { | ||||
|                 $this->deleteOBGroup($account); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // update note: | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|     {{ Form.model(account, {'class' : 'form-horizontal','id' : 'update','url' : route('accounts.update',account.id) } ) }} | ||||
|  | ||||
|     <input type="hidden" name="id" value="{{ account.id }}"/> | ||||
|     <input type="hidden" name="what" value="{{ what }}"/> | ||||
|     <input type="hidden" name="objectType" value="{{ objectType }}"/> | ||||
|  | ||||
|     <div class="row"> | ||||
|         <div class="col-lg-6 col-md-6 col-sm-12 col-xs-12"> | ||||
| @@ -18,11 +18,11 @@ | ||||
|                 </div> | ||||
|                 <div class="box-body"> | ||||
|                     {{ ExpandedForm.text('name') }} | ||||
|                     {% if account.accountType.type == 'Default account' or account.accountType.type == 'Asset account' or what == 'liabilities' %} | ||||
|                     {% if account.accountType.type == 'Default account' or account.accountType.type == 'Asset account' or objectType == 'liabilities' %} | ||||
|                         {{ ExpandedForm.currencyList('currency_id', null, {helpText:'account_default_currency'|_}) }} | ||||
|                     {% endif %} | ||||
|  | ||||
|                     {% if what == 'liabilities' %} | ||||
|                     {% if objectType == 'liabilities' %} | ||||
|                         {{ ExpandedForm.select('liability_type_id', liabilityTypes) }} | ||||
|                         {{ ExpandedForm.amountNoCurrency('opening_balance', null, {label:'debt_start_amount'|_, helpText: 'debt_start_amount_help'|_}) }} | ||||
|                         {{ ExpandedForm.date('opening_balance_date', null, {label:'debt_start_date'|_}) }} | ||||
| @@ -90,7 +90,7 @@ | ||||
|                 </div> | ||||
|                 <div class="box-footer"> | ||||
|                     <button type="submit" class="btn pull-right btn-success"> | ||||
|                         {{ ('update_' ~ what ~ '_account')|_ }} | ||||
|                         {{ ('update_' ~ objectType ~ '_account')|_ }} | ||||
|                     </button> | ||||
|                 </div> | ||||
|             </div> | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| {% extends "./layout/default" %} | ||||
|  | ||||
| {% block breadcrumbs %} | ||||
|     {{ Breadcrumbs.render(Route.getCurrentRoute.getName, what) }} | ||||
|     {{ Breadcrumbs.render(Route.getCurrentRoute.getName, objectType) }} | ||||
| {% endblock %} | ||||
|  | ||||
| {% block content %} | ||||
|     {% if accounts.count > 0 %} | ||||
|         <div class="row"> | ||||
|             <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|                 <div class="box" id="account-index-{{ what }}"> | ||||
|                 <div class="box" id="account-index-{{ objectType }}"> | ||||
|                     <div class="box-header with-border"> | ||||
|                         <h3 class="box-title"> | ||||
|                             {{ subTitle }} | ||||
| @@ -17,8 +17,8 @@ | ||||
|                             <div class="btn-group"> | ||||
|                                 <button class="btn btn-box-tool dropdown-toggle" data-toggle="dropdown"><i class="fa fa-ellipsis-v"></i></button> | ||||
|                                 <ul class="dropdown-menu" role="menu"> | ||||
|                                     <li><a href="{{ route('accounts.create', what) }}"><i | ||||
|                                                     class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ what ~ '_account')|_ }} | ||||
|                                     <li><a href="{{ route('accounts.create', objectType) }}"><i | ||||
|                                                     class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ objectType ~ '_account')|_ }} | ||||
|                                         </a></li> | ||||
|                                 </ul> | ||||
|                             </div> | ||||
| @@ -29,20 +29,20 @@ | ||||
|  | ||||
|                     <div class="box-body table-responsive no-padding"> | ||||
|                         <div style="padding:8px;"> | ||||
|                             <a href="{{ route('accounts.create', what) }}" class="btn btn-success"><i class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ what ~ '_account')|_ }}</a> | ||||
|                             <a href="{{ route('accounts.create', objectType) }}" class="btn btn-success"><i class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ objectType ~ '_account')|_ }}</a> | ||||
|                         </div> | ||||
|  | ||||
|                         {% include 'list.accounts' %} | ||||
|                     </div> | ||||
|                     <div class="box-footer"> | ||||
|                         <a href="{{ route('accounts.create', what) }}" class="btn btn-success"><i class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ what ~ '_account')|_ }}</a> | ||||
|                         <a href="{{ route('accounts.create', objectType) }}" class="btn btn-success"><i class="fa fa-plus fa-fw"></i> {{ ('make_new_' ~ objectType ~ '_account')|_ }}</a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     {% endif %} | ||||
|     {% if accounts.count == 0 and page == 1 %} | ||||
|         {% include 'partials.empty' with {what: what, type: 'accounts',route: route('accounts.create', [what])} %} | ||||
|         {% include 'partials.empty' with {objectType: objectType, type: 'accounts',route: route('accounts.create', [objectType])} %} | ||||
|     {% endif %} | ||||
| {% endblock %} | ||||
|  | ||||
| @@ -52,7 +52,7 @@ | ||||
|  | ||||
| {% block scripts %} | ||||
|     <script type="text/javascript"> | ||||
|         var what = '{{ what|escape }}'; | ||||
|         var objectType = '{{ objectType|escape }}'; | ||||
|     </script> | ||||
|     <script type="text/javascript" src="v1/js/lib/bootstrap-sortable.js?v={{ FF_VERSION }}"></script> | ||||
| {% endblock %} | ||||
|   | ||||
| @@ -6,10 +6,10 @@ | ||||
|     <tr> | ||||
|         <th class="hidden-sm hidden-xs" data-defaultsort="disabled"> </th> | ||||
|         <th data-defaultsign="az">{{ trans('list.name') }}</th> | ||||
|         {% if what == 'asset' %} | ||||
|         {% if objectType == 'asset' %} | ||||
|             <th data-defaultsign="az" class="hidden-sm hidden-xs hidden-md">{{ trans('list.role') }}</th> | ||||
|         {% endif %} | ||||
|         {% if what == 'liabilities' %} | ||||
|         {% if objectType == 'liabilities' %} | ||||
|             <th data-defaultsign="az">{{ trans('list.liability_type') }}</th> | ||||
|             <th data-defaultsign="_19">{{ trans('list.interest') }} ({{ trans('list.interest_period') }})</th> | ||||
|         {% endif %} | ||||
| @@ -17,7 +17,7 @@ | ||||
|         <th data-defaultsign="_19">{{ trans('list.currentBalance') }}</th> | ||||
|         <th class="hidden-sm hidden-xs">{{ trans('list.active') }}</th> | ||||
|         {# hide last activity to make room for other stuff #} | ||||
|         {% if what != 'liabilities' %} | ||||
|         {% if objectType != 'liabilities' %} | ||||
|             <th data-defaultsign="month" class="hidden-sm hidden-xs hidden-md">{{ trans('list.lastActivity') }}</th> | ||||
|         {% endif %} | ||||
|         <th data-defaultsign="_19" style="width:15%;" | ||||
| @@ -30,7 +30,7 @@ | ||||
|             <td class="hidden-sm hidden-xs"> | ||||
|                 <div class="btn-group btn-group-xs edit_tr_buttons"><a class="btn btn-default btn-xs" title="{{ 'edit'|_ }}" | ||||
|                                                                        href="{{ route('accounts.edit',account.id) }}"><i | ||||
|                                 class="fa fa-fw fa-pencil"></i></a>{% if what == 'asset' %}<a class="btn btn-default btn-xs" | ||||
|                                 class="fa fa-fw fa-pencil"></i></a>{% if objectType == 'asset' %}<a class="btn btn-default btn-xs" | ||||
|                                                                                               title="{{ 'reconcile_this_account'|_ }}" | ||||
|                                                                                               href="{{ route('accounts.reconcile',account.id) }}"><i | ||||
|                                 class="fa fa-fw fa-check"></i></a>{% endif %}<a class="btn btn-danger btn-xs" title="{{ 'delete'|_ }}" | ||||
| @@ -38,7 +38,7 @@ | ||||
|                                 class="fa fa-fw fa-trash-o"></i></a></div> | ||||
|             </td> | ||||
|             <td data-value="{{ account.name }}"><a href="{{ route('accounts.show',account.id) }}">{{ account.name }}</a></td> | ||||
|             {% if what == "asset" %} | ||||
|             {% if objectType == "asset" %} | ||||
|                 <td class="hidden-sm hidden-xs hidden-md"> | ||||
|                     {% for entry in account.accountmeta %} | ||||
|                         {% if entry.name == 'account_role' %} | ||||
| @@ -47,7 +47,7 @@ | ||||
|                     {% endfor %} | ||||
|                 </td> | ||||
|             {% endif %} | ||||
|             {% if what == 'liabilities' %} | ||||
|             {% if objectType == 'liabilities' %} | ||||
|                 <td>{{ account.accountTypeString }}</td> | ||||
|             <td data-value="{{ account.interest }}"> | ||||
|                 {{ account.interest }}% ({{ account.interestPeriod|lower }}) | ||||
| @@ -67,7 +67,7 @@ | ||||
|                 {% endif %} | ||||
|             </td> | ||||
|             {# hide last activity to make room for other stuff #} | ||||
|             {% if what != 'liabilities' %} | ||||
|             {% if objectType != 'liabilities' %} | ||||
|                 {% if account.lastActivityDate %} | ||||
|                     <td class="hidden-sm hidden-xs hidden-md" data-value="{{ account.lastActivityDate.format('Y-m-d H-i-s') }} "> | ||||
|                         {{ account.lastActivityDate.formatLocalized(monthAndDayFormat) }} | ||||
|   | ||||
| @@ -24,8 +24,9 @@ declare(strict_types=1); | ||||
| namespace Tests\Feature\Controllers\Account; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
| use Amount; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| @@ -39,7 +40,10 @@ use Tests\TestCase; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class CreateControllerTest | ||||
|  * Class CreateControllerTest. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class CreateControllerTest extends TestCase | ||||
| { | ||||
| @@ -63,12 +67,24 @@ class CreateControllerTest extends TestCase | ||||
|         $accountRepos = $this->mock(AccountRepositoryInterface::class); | ||||
|         $repository   = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $userRepos    = $this->mock(UserRepositoryInterface::class); | ||||
|         $euro         = $this->getEuro(); | ||||
|         $repository->shouldReceive('get')->andReturn(new Collection); | ||||
|  | ||||
|         // used for session range. | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         // mock hasRole for user repository: | ||||
|         $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true)->atLeast()->once(); | ||||
|  | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         // mock default calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|         $this->mockIntroPreference('shown_demo_accounts_create_asset'); | ||||
|  | ||||
|         // mock default calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         // get all types: | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Debt'])->andReturn(AccountType::find(11))->once(); | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Loan'])->andReturn(AccountType::find(9))->once(); | ||||
| @@ -91,23 +107,40 @@ class CreateControllerTest extends TestCase | ||||
|         // mock stuff | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|  | ||||
|         $repository->shouldReceive('store')->once()->andReturn(factory(Account::class)->make()); | ||||
|         $asset        = $this->getRandomAsset(); | ||||
|         $euro         = $this->getEuro(); | ||||
|         $repository->shouldReceive('store')->once()->andReturn($asset); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         // change the preference: | ||||
|         Preferences::setForUser($this->user(), 'frontPageAccounts', [1]); | ||||
|         // mock default calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         $this->session(['accounts.create.uri' => 'http://localhost']); | ||||
|         // change the preference: | ||||
|         $emptyPref       = new Preference; | ||||
|         $emptyPref->data = []; | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['frontPageAccounts', []])->andReturn($emptyPref); | ||||
|         Preferences::shouldReceive('set')->atLeast()->once()->withArgs(['frontPageAccounts', [$asset->id]]); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|  | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once()->withNoArgs(); | ||||
|  | ||||
|         // mock default calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|  | ||||
|  | ||||
|         $this->session(['accounts.create.uri' => 'http://localhost/x']); | ||||
|         $this->be($this->user()); | ||||
|         $data = [ | ||||
|             'name' => 'new account ' . $this->randomInt(), | ||||
|             'what' => 'asset', | ||||
|             'name'       => 'new account ' . $this->randomInt(), | ||||
|             'objectType' => 'asset', | ||||
|         ]; | ||||
|  | ||||
|         $response = $this->post(route('accounts.store', ['asset']), $data); | ||||
|         $response->assertStatus(302); | ||||
|         $response->assertSessionHas('success'); | ||||
|         $response->assertRedirect('http://localhost/x'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -120,21 +153,44 @@ class CreateControllerTest extends TestCase | ||||
|         // mock stuff | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|         $asset        = $this->getRandomAsset(); | ||||
|         $euro         = $this->getEuro(); | ||||
|  | ||||
|         $repository->shouldReceive('store')->once()->andReturn(factory(Account::class)->make()); | ||||
|         $repository->shouldReceive('store')->once()->andReturn($asset); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         // change the preference: | ||||
|         $emptyPref       = new Preference; | ||||
|         $emptyPref->data = []; | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['frontPageAccounts', []])->andReturn($emptyPref); | ||||
|         Preferences::shouldReceive('set')->atLeast()->once()->withArgs(['frontPageAccounts', [$asset->id]]); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|  | ||||
|         // mock default calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|         //$this->mockIntroPreference('shown_demo_accounts_create_asset'); | ||||
|  | ||||
|         // mock default calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|  | ||||
|  | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once()->withNoArgs(); | ||||
|  | ||||
|         $this->session(['accounts.create.uri' => 'http://localhost']); | ||||
|         $this->be($this->user()); | ||||
|         $data = [ | ||||
|             'name'           => 'new account ' . $this->randomInt(), | ||||
|             'what'           => 'asset', | ||||
|             'objectType'     => 'asset', | ||||
|             'create_another' => 1, | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|         $response = $this->post(route('accounts.store', ['asset']), $data); | ||||
|         $response->assertStatus(302); | ||||
|         $response->assertSessionHas('success'); | ||||
|         $response->assertRedirect('http://localhost/accounts/create/asset'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -147,21 +203,36 @@ class CreateControllerTest extends TestCase | ||||
|         // mock stuff | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|  | ||||
|         $repository->shouldReceive('store')->once()->andReturn(factory(Account::class)->make()); | ||||
|         $liability    = $this->getRandomLoan(); | ||||
|         $loan         = AccountType::where('type', AccountType::LOAN)->first(); | ||||
|         $euro         = $this->getEuro(); | ||||
|         $repository->shouldReceive('store')->once()->andReturn($liability); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         // change the preference: | ||||
|         Preferences::setForUser($this->user(), 'frontPageAccounts', [1]); | ||||
|         $emptyPref       = new Preference; | ||||
|         $emptyPref->data = []; | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['frontPageAccounts', []])->andReturn($emptyPref); | ||||
|  | ||||
|         // mock default calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|         //$this->mockIntroPreference('shown_demo_accounts_create_asset'); | ||||
|  | ||||
|         // mock default calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once()->withNoArgs(); | ||||
|  | ||||
|         $this->session(['accounts.create.uri' => 'http://localhost']); | ||||
|         $this->be($this->user()); | ||||
|         $data = [ | ||||
|             'name'               => 'new liability account ' . $this->randomInt(), | ||||
|             'what'               => 'liabilities', | ||||
|             'liability_type_id'  => AccountType::where('type', AccountType::LOAN)->first()->id, | ||||
|             'openingBalance'     => '100', | ||||
|             'openingBalanceDate' => '2018-01-01', | ||||
|             'name'                 => 'new liability account ' . $this->randomInt(), | ||||
|             'objectType'           => 'liabilities', | ||||
|             'liability_type_id'    => $loan->id, | ||||
|             'opening_balance'      => '-100', | ||||
|             'opening_balance_date' => '2018-01-01', | ||||
|         ]; | ||||
|  | ||||
|         $response = $this->post(route('accounts.store', ['liabilities']), $data); | ||||
|   | ||||
| @@ -24,6 +24,7 @@ declare(strict_types=1); | ||||
| namespace Tests\Feature\Controllers\Account; | ||||
|  | ||||
|  | ||||
| use Amount; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| @@ -33,10 +34,15 @@ use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Mockery; | ||||
| use Tests\TestCase; | ||||
| use Preferences; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class DeleteControllerTest | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class DeleteControllerTest extends TestCase | ||||
| { | ||||
| @@ -59,15 +65,25 @@ class DeleteControllerTest extends TestCase | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|         $userRepos    = $this->mock(UserRepositoryInterface::class); | ||||
|         $asset        = $this->getRandomAsset(); | ||||
|         $repository->shouldReceive('getAccountsByType')->withArgs([[AccountType::ASSET]])->andReturn(new Collection); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         // mock hasRole for user repository: | ||||
|         $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true)->atLeast()->once(); | ||||
|  | ||||
|         // mock Amount | ||||
|         $euro         = $this->getEuro(); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         $this->be($this->user()); | ||||
|         $account  = $this->user()->accounts()->where('account_type_id', 3)->whereNull('deleted_at')->first(); | ||||
|         $response = $this->get(route('accounts.delete', [$account->id])); | ||||
|         $response = $this->get(route('accounts.delete', [$asset->id])); | ||||
|         $response->assertStatus(200); | ||||
|         // has bread crumb | ||||
|         $response->assertSee('<ol class="breadcrumb">'); | ||||
| @@ -82,15 +98,27 @@ class DeleteControllerTest extends TestCase | ||||
|         // mock stuff | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|         $asset        = $this->getRandomAsset(); | ||||
|         $euro         = $this->getEuro(); | ||||
|         $repository->shouldReceive('findNull')->withArgs([0])->once()->andReturn(null); | ||||
|         $repository->shouldReceive('destroy')->andReturn(true); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once(); | ||||
|  | ||||
|         // mock Amount | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         $this->session(['accounts.delete.uri' => 'http://localhost/accounts/show/1']); | ||||
|         $account = $this->user()->accounts()->where('account_type_id', 3)->whereNull('deleted_at')->first(); | ||||
|  | ||||
|         $this->be($this->user()); | ||||
|         $response = $this->post(route('accounts.destroy', [$account->id])); | ||||
|         $response = $this->post(route('accounts.destroy', [$asset->id])); | ||||
|         $response->assertStatus(302); | ||||
|         $response->assertSessionHas('success'); | ||||
|     } | ||||
|   | ||||
| @@ -35,11 +35,15 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Mockery; | ||||
| use Preferences; | ||||
| use Tests\TestCase; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class EditControllerTest | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class EditControllerTest extends TestCase | ||||
| { | ||||
| @@ -54,6 +58,7 @@ class EditControllerTest extends TestCase | ||||
|  | ||||
|     /** | ||||
|      * @covers \FireflyIII\Http\Controllers\Account\EditController | ||||
|      * @covers \FireflyIII\Http\Requests\AccountFormRequest | ||||
|      */ | ||||
|     public function testEdit(): void | ||||
|     { | ||||
| @@ -61,36 +66,47 @@ class EditControllerTest extends TestCase | ||||
|         $repository   = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $accountRepos = $this->mock(AccountRepositoryInterface::class); | ||||
|         $userRepos    = $this->mock(UserRepositoryInterface::class); | ||||
|         $asset        = $this->getRandomAsset(); | ||||
|         $euro         = $this->getEuro(); | ||||
|  | ||||
|         $repository->shouldReceive('findNull')->withArgs([1])->andReturn(TransactionCurrency::find(1))->atLeast()->once(); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         // mock preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         $repository->shouldReceive('findNull')->withArgs([1])->andReturn($euro)->atLeast()->once(); | ||||
|  | ||||
|         // mock hasRole for user repository: | ||||
|         $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true)->atLeast()->once(); | ||||
|  | ||||
|         $repository->shouldReceive('get')->andReturn(new Collection); | ||||
|         $repository->shouldReceive('get')->andReturn(new Collection)->atLeast()->once(); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|         $accountRepos->shouldReceive('getNoteText')->andReturn('Some text')->once(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceAmount')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceDate')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountNumber'])->andReturn('123'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('defaultAsset'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccType'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccMonthlyPaymentDate'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly'); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceAmount')->andReturnNull()->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceDate')->andReturnNull()->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_number'])->andReturn('123')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_role'])->andReturn('defaultAsset')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_type'])->andReturn('')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_monthly_payment_date'])->andReturn('')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1')->atLeast()->once(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly')->atLeast()->once(); | ||||
|  | ||||
|         // get all types: | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Debt'])->andReturn(AccountType::find(11))->once(); | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Loan'])->andReturn(AccountType::find(9))->once(); | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Mortgage'])->andReturn(AccountType::find(12))->once(); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         //$this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         $this->be($this->user()); | ||||
|         $account  = $this->user()->accounts()->where('account_type_id', 3)->whereNull('deleted_at')->first(); | ||||
|         $response = $this->get(route('accounts.edit', [$account->id])); | ||||
|         $response = $this->get(route('accounts.edit', [$asset->id])); | ||||
|         $response->assertStatus(200); | ||||
|         // has bread crumb | ||||
|         $response->assertSee('<ol class="breadcrumb">'); | ||||
| @@ -99,6 +115,7 @@ class EditControllerTest extends TestCase | ||||
|  | ||||
|     /** | ||||
|      * @covers \FireflyIII\Http\Controllers\Account\EditController | ||||
|      * @covers \FireflyIII\Http\Requests\AccountFormRequest | ||||
|      */ | ||||
|     public function testEditLiability(): void | ||||
|     { | ||||
| @@ -106,22 +123,23 @@ class EditControllerTest extends TestCase | ||||
|         $repository   = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $accountRepos = $this->mock(AccountRepositoryInterface::class); | ||||
|         $userRepos    = $this->mock(UserRepositoryInterface::class); | ||||
|  | ||||
|         $euro         = $this->getEuro(); | ||||
|         $loan         = $this->getRandomLoan(); | ||||
|         // mock hasRole for user repository: | ||||
|         $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true)->atLeast()->once(); | ||||
|  | ||||
|         $repository->shouldReceive('findNull')->once()->andReturn(TransactionCurrency::find(1)); | ||||
|         $repository->shouldReceive('findNull')->once()->andReturn($euro); | ||||
|         $repository->shouldReceive('get')->andReturn(new Collection); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|         $accountRepos->shouldReceive('getNoteText')->andReturn('Some text')->once(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceAmount')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceDate')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountNumber'])->andReturn('123'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('defaultAsset'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccType'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_number'])->andReturn('123'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_role'])->andReturn('defaultAsset'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_type'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccMonthlyPaymentDate'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_monthly_payment_date'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly'); | ||||
| @@ -131,10 +149,19 @@ class EditControllerTest extends TestCase | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Loan'])->andReturn(AccountType::find(9))->once(); | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Mortgage'])->andReturn(AccountType::find(12))->once(); | ||||
|  | ||||
|         // mock Amount | ||||
|         $euro = $this->getEuro(); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|  | ||||
|         $this->be($this->user()); | ||||
|         $account  = $this->user()->accounts()->where('account_type_id', 12)->whereNull('deleted_at')->first(); | ||||
|         $response = $this->get(route('accounts.edit', [$account->id])); | ||||
|         $response = $this->get(route('accounts.edit', [$loan->id])); | ||||
|         $response->assertStatus(200); | ||||
|         // has bread crumb | ||||
|         $response->assertSee('<ol class="breadcrumb">'); | ||||
| @@ -143,6 +170,7 @@ class EditControllerTest extends TestCase | ||||
|  | ||||
|     /** | ||||
|      * @covers \FireflyIII\Http\Controllers\Account\EditController | ||||
|      * @covers \FireflyIII\Http\Requests\AccountFormRequest | ||||
|      */ | ||||
|     public function testEditNull(): void | ||||
|     { | ||||
| @@ -163,15 +191,21 @@ class EditControllerTest extends TestCase | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceAmount')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getOpeningBalanceDate')->andReturnNull(); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountNumber'])->andReturn('123'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountRole'])->andReturn('defaultAsset'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccType'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'ccMonthlyPaymentDate'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_number'])->andReturn('123'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_role'])->andReturn('defaultAsset'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_type'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'cc_monthly_payment_date'])->andReturn(''); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'include_net_worth'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'BIC'])->andReturn('BIC'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); | ||||
|         $accountRepos->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly'); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         // get all types: | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Debt'])->andReturn(AccountType::find(11))->once(); | ||||
|         $accountRepos->shouldReceive('getAccountTypeByType')->withArgs(['Loan'])->andReturn(AccountType::find(9))->once(); | ||||
| @@ -195,13 +229,18 @@ class EditControllerTest extends TestCase | ||||
|     public function testUpdate(): void | ||||
|     { | ||||
|         // mock stuff | ||||
|         $journalRepos  = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository    = $this->mock(AccountRepositoryInterface::class); | ||||
|         $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|         $this->mock(CurrencyRepositoryInterface::class); | ||||
|  | ||||
|         $repository->shouldReceive('update')->once(); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
|  | ||||
|         $euro = $this->getEuro(); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once(); | ||||
|  | ||||
|         $this->session(['accounts.edit.uri' => 'http://localhost/javascript/account']); | ||||
|         $this->be($this->user()); | ||||
|         $data = [ | ||||
| @@ -210,6 +249,12 @@ class EditControllerTest extends TestCase | ||||
|             'what'   => 'asset', | ||||
|         ]; | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         $response = $this->post(route('accounts.update', [1]), $data); | ||||
|         $response->assertStatus(302); | ||||
|         $response->assertSessionHas('success'); | ||||
| @@ -223,9 +268,9 @@ class EditControllerTest extends TestCase | ||||
|     public function testUpdateAgain(): void | ||||
|     { | ||||
|         // mock stuff | ||||
|         $journalRepos  = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository    = $this->mock(AccountRepositoryInterface::class); | ||||
|         $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $journalRepos = $this->mock(JournalRepositoryInterface::class); | ||||
|         $repository   = $this->mock(AccountRepositoryInterface::class); | ||||
|         $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $repository->shouldReceive('update')->once(); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|  | ||||
| @@ -238,6 +283,16 @@ class EditControllerTest extends TestCase | ||||
|             'return_to_edit' => '1', | ||||
|         ]; | ||||
|  | ||||
|         $euro = $this->getEuro(); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|         Preferences::shouldReceive('mark')->atLeast()->once(); | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         $response = $this->post(route('accounts.update', [1]), $data); | ||||
|         $response->assertStatus(302); | ||||
|         $response->assertSessionHas('success'); | ||||
|   | ||||
| @@ -22,8 +22,8 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace Tests\Feature\Controllers\Account; | ||||
|  | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use Amount; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| @@ -32,13 +32,14 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Mockery; | ||||
| use Preferences; | ||||
| use Steam; | ||||
| use Tests\TestCase; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class IndexControllerTest | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.TooManyPublicMethods) | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| @@ -64,26 +65,40 @@ class IndexControllerTest extends TestCase | ||||
|     public function testIndex(string $range): void | ||||
|     { | ||||
|         // mock stuff | ||||
|         $account       = factory(Account::class)->make(); | ||||
|         $account       = $this->getRandomAsset(); | ||||
|         $repository    = $this->mock(AccountRepositoryInterface::class); | ||||
|         $journalRepos  = $this->mock(JournalRepositoryInterface::class); | ||||
|         $currencyRepos = $this->mock(CurrencyRepositoryInterface::class); | ||||
|         $userRepos     = $this->mock(UserRepositoryInterface::class); | ||||
|  | ||||
|         $euro          = $this->getEuro(); | ||||
|         // mock hasRole for user repository: | ||||
|         $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->andReturn(true)->atLeast()->once(); | ||||
|  | ||||
|         $repository->shouldReceive('getAccountsByType')->andReturn(new Collection([$account])); | ||||
|         $repository->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'currency_id'])->andReturn('1'); | ||||
|         $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); | ||||
|         $currencyRepos->shouldReceive('findNull')->withArgs([1])->andReturn(TransactionCurrency::find(1)); | ||||
|         $currencyRepos->shouldReceive('findNull')->withArgs([1])->andReturn($euro); | ||||
|         Steam::shouldReceive('balancesByAccounts')->andReturn([$account->id => '100']); | ||||
|         Steam::shouldReceive('getLastActivities')->andReturn([]); | ||||
|  | ||||
|  | ||||
|         // mock calls to Preferences: | ||||
|         $this->mockDefaultPreferences(); | ||||
|  | ||||
|         // mock calls to Configuration: | ||||
|         $this->mockDefaultConfiguration(); | ||||
|  | ||||
|         // list size | ||||
|         $pref       = new Preference; | ||||
|         $pref->data = 50; | ||||
|         Preferences::shouldReceive('get')->withArgs(['listPageSize', 50])->atLeast()->once()->andReturn($pref); | ||||
|  | ||||
|         Amount::shouldReceive('formatAnything')->andReturn('123'); | ||||
|         Amount::shouldReceive('getDefaultCurrency')->atLeast()->once()->andReturn($euro); | ||||
|  | ||||
|         $repository->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest'])->andReturn('1'); | ||||
|         $repository->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'interest_period'])->andReturn('monthly'); | ||||
|  | ||||
|         $repository->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'accountNumber'])->andReturn('123'); | ||||
|         $repository->shouldReceive('getMetaValue')->withArgs([Mockery::any(), 'account_number'])->andReturn('123'); | ||||
|  | ||||
|         $this->be($this->user()); | ||||
|         $this->changeDateRange($this->user(), $range); | ||||
|   | ||||
| @@ -27,11 +27,13 @@ use Carbon\Carbon; | ||||
| use Closure; | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyConfig; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Configuration; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionGroup; | ||||
| @@ -42,6 +44,7 @@ use FireflyIII\User; | ||||
| use Illuminate\Foundation\Testing\TestCase as BaseTestCase; | ||||
| use Log; | ||||
| use Mockery; | ||||
| use Preferences; | ||||
| use RuntimeException; | ||||
|  | ||||
| /** | ||||
| @@ -51,6 +54,56 @@ use RuntimeException; | ||||
|  */ | ||||
| abstract class TestCase extends BaseTestCase | ||||
| { | ||||
|     /** | ||||
|      * Mock the Preferences call that checks if the user has seen the introduction popups already. | ||||
|      * | ||||
|      * @param string $key | ||||
|      */ | ||||
|     public function mockIntroPreference(string $key): void | ||||
|     { | ||||
|         $true       = new Preference; | ||||
|         $true->data = true; | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs([$key, false])->andReturn($true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Mock the call that checks for the users last activity (for caching). | ||||
|      */ | ||||
|     public function mockLastActivity(): void | ||||
|     { | ||||
|         Preferences::shouldReceive('lastActivity')->withNoArgs()->atLeast()->once()->andReturn('md512345'); | ||||
|     } | ||||
|  | ||||
|     public function mockDefaultConfiguration(): void | ||||
|     { | ||||
|  | ||||
|         $falseConfig       = new Configuration; | ||||
|         $falseConfig->data = false; | ||||
|  | ||||
|         FireflyConfig::shouldReceive('get')->withArgs(['is_demo_site', false])->once()->andReturn($falseConfig); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Mock default preferences. | ||||
|      */ | ||||
|     public function mockDefaultPreferences(): void | ||||
|     { | ||||
|         $false       = new Preference; | ||||
|         $false->data = false; | ||||
|         $view        = new Preference; | ||||
|         $view->data  = '1M'; | ||||
|         $lang        = new Preference; | ||||
|         $lang->data  = 'en_US'; | ||||
|         $list        = new Preference; | ||||
|         $list->data  = 50; | ||||
|  | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['twoFactorAuthEnabled', false])->andReturn($false); | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['twoFactorAuthSecret'])->andReturnNull(); | ||||
|         Preferences::shouldReceive('get')->withArgs(['viewRange', Mockery::any()])->andReturn($view); | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['language', 'en_US'])->andReturn($lang); | ||||
|         Preferences::shouldReceive('get')->atLeast()->once()->withArgs(['list-length', 10])->andReturn($list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user