diff --git a/app/Crud/Account/AccountCrud.php b/app/Crud/Account/AccountCrud.php deleted file mode 100644 index 1e83d004f4..0000000000 --- a/app/Crud/Account/AccountCrud.php +++ /dev/null @@ -1,407 +0,0 @@ -user = $user; - } - - /** - * WILL BE REMOVED. - * - * @param string $name - * @param array $types - * - * @return Account - */ - public function findByName(string $name, array $types): Account - { - $query = $this->user->accounts(); - - if (count($types) > 0) { - $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); - $query->whereIn('account_types.type', $types); - - } - Log::debug(sprintf('Searching for account named %s of the following type(s)', $name), ['types' => $types]); - - $accounts = $query->get(['accounts.*']); - /** @var Account $account */ - foreach ($accounts as $account) { - if ($account->name === $name) { - Log::debug(sprintf('Found #%d (%s) with type id %d', $account->id, $account->name, $account->account_type_id)); - - return $account; - } - } - Log::debug('Found nothing.'); - - return new Account; - } - - /** - * @param array $data - * - * @return Account - */ - public function store(array $data): Account - { - $newAccount = $this->storeAccount($data); - $this->updateMetadata($newAccount, $data); - - if ($this->validOpeningBalanceData($data)) { - $this->updateInitialBalance($newAccount, $data); - - return $newAccount; - } - $this->deleteInitialBalance($newAccount); - - return $newAccount; - - } - - /** - * @param Account $account - * @param array $data - * - * @return Account - */ - public function update(Account $account, array $data): Account - { - // update the account: - $account->name = $data['name']; - $account->active = $data['active'] == '1' ? true : false; - $account->virtual_balance = $data['virtualBalance']; - $account->iban = $data['iban']; - $account->save(); - - $this->updateMetadata($account, $data); - $this->updateInitialBalance($account, $data); - - return $account; - } - - /** - * @param Account $account - */ - protected function deleteInitialBalance(Account $account) - { - $journal = $this->openingBalanceTransaction($account); - if (!is_null($journal->id)) { - $journal->delete(); - } - - } - - /** - * @param Account $account - * - * @return TransactionJournal|null - */ - protected function openingBalanceTransaction(Account $account): TransactionJournal - { - $journal = TransactionJournal - ::sortCorrectly() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); - if (is_null($journal)) { - Log::debug('Could not find a opening balance journal, return empty one.'); - - return new TransactionJournal; - } - Log::debug(sprintf('Found opening balance: journal #%d.', $journal->id)); - - return $journal; - } - - /** - * @param array $data - * - * @return Account - * @throws FireflyException - */ - protected function storeAccount(array $data): Account - { - $data['accountType'] = $data['accountType'] ?? 'invalid'; - $type = config('firefly.accountTypeByIdentifier.' . $data['accountType']); - $accountType = AccountType::whereType($type)->first(); - - // verify account type - if (is_null($accountType)) { - throw new FireflyException(sprintf('Account type "%s" is invalid. Cannot create account.', $data['accountType'])); - } - - // account may exist already: - $existingAccount = $this->findByName($data['name'], [$data['accountType']]); - if (!is_null($existingAccount->id)) { - throw new FireflyException(sprintf('There already is an account named "%s" of type "%s".', $data['name'], $data['accountType'])); - } - - // create it: - $newAccount = new Account( - [ - 'user_id' => $data['user'], - 'account_type_id' => $accountType->id, - 'name' => $data['name'], - 'virtual_balance' => $data['virtualBalance'], - 'active' => $data['active'] === true ? true : false, - 'iban' => $data['iban'], - ] - ); - $newAccount->save(); - // verify its creation: - if (is_null($newAccount->id)) { - Log::error( - sprintf('Could not create account "%s" (%d error(s))', $data['name'], $newAccount->getErrors()->count()), $newAccount->getErrors()->toArray() - ); - throw new FireflyException(sprintf('Tried to create account named "%s" but failed. The logs have more details.', $data['name'])); - } - - return $newAccount; - } - - /** - * @param Account $account - * @param array $data - * - * @return TransactionJournal - */ - protected function storeInitialBalance(Account $account, array $data): TransactionJournal - { - $amount = $data['openingBalance']; - $user = $data['user']; - $name = $data['name']; - $opposing = $this->storeOpposingAccount($amount, $user, $name); - $transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first(); - $journal = TransactionJournal::create( - [ - 'user_id' => $data['user'], - 'transaction_type_id' => $transactionType->id, - 'transaction_currency_id' => $data['openingBalanceCurrency'], - 'description' => 'Initial balance for "' . $account->name . '"', - 'completed' => true, - 'date' => $data['openingBalanceDate'], - 'encrypted' => true, - ] - ); - Log::debug(sprintf('Created new opening balance journal: #%d', $journal->id)); - - $firstAccount = $account; - $secondAccount = $opposing; - $firstAmount = $amount; - $secondAmount = $amount * -1; - - if ($data['openingBalance'] < 0) { - $firstAccount = $opposing; - $secondAccount = $account; - $firstAmount = $amount * -1; - $secondAmount = $amount; - } - - $one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]); - $one->save();// first transaction: from - $two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]); - $two->save(); // second transaction: to - - Log::debug(sprintf('Stored two transactions, #%d and #%d', $one->id, $two->id)); - - return $journal; - } - - /** - * @param float $amount - * @param int $user - * @param string $name - * - * @return Account - */ - protected function storeOpposingAccount(float $amount, int $user, string $name):Account - { - $type = $amount < 0 ? 'expense' : 'revenue'; - $opposingData = [ - 'user' => $user, - 'accountType' => $type, - 'name' => $name . ' initial balance', - 'active' => false, - 'iban' => '', - 'virtualBalance' => 0, - ]; - Log::debug('Going to create an opening balance opposing account'); - - return $this->storeAccount($opposingData); - } - - /** - * @param Account $account - * @param array $data - * - * @return bool - */ - protected function updateInitialBalance(Account $account, array $data): bool - { - $openingBalance = $this->openingBalanceTransaction($account); - - // no opening balance journal? create it: - if (is_null($openingBalance->id)) { - Log::debug('No opening balance journal yet, create journal.'); - $this->storeInitialBalance($account, $data); - - return true; - } - // opening balance data? update it! - if (!is_null($openingBalance->id)) { - $date = $data['openingBalanceDate']; - $amount = $data['openingBalance']; - - Log::debug('Opening balance journal found, update journal.'); - - $this->updateOpeningBalanceJournal($account, $openingBalance, $date, $amount); - - return true; - } - - return true; - } - - /** - * @param Account $account - * @param array $data - * - */ - protected function updateMetadata(Account $account, array $data) - { - foreach ($this->validFields as $field) { - /** @var AccountMeta $entry */ - $entry = $account->accountMeta()->where('name', $field)->first(); - - // if $data has field and $entry is null, create new one: - if (isset($data[$field]) && is_null($entry)) { - Log::debug( - sprintf( - 'Created meta-field "%s":"%s" for account #%d ("%s") ', - $field, $data[$field], $account->id, $account->name - ) - ); - AccountMeta::create( - [ - 'account_id' => $account->id, - 'name' => $field, - 'data' => $data[$field], - ] - ); - } - - // if $data has field and $entry is not null, update $entry: - if (isset($data[$field]) && !is_null($entry)) { - $entry->data = $data[$field]; - $entry->save(); - Log::debug( - sprintf( - 'Updated meta-field "%s":"%s" for account #%d ("%s") ', - $field, $data[$field], $account->id, $account->name - ) - ); - } - } - - } - - /** - * @param Account $account - * @param TransactionJournal $journal - * @param Carbon $date - * @param float $amount - * - * @return bool - */ - protected function updateOpeningBalanceJournal(Account $account, TransactionJournal $journal, Carbon $date, float $amount): bool - { - // update date: - $journal->date = $date; - $journal->save(); - // update transactions: - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - if ($account->id == $transaction->account_id) { - $transaction->amount = $amount; - $transaction->save(); - } - if ($account->id != $transaction->account_id) { - $transaction->amount = $amount * -1; - $transaction->save(); - } - } - Log::debug('Updated opening balance journal.'); - - return true; - - } - - /** - * @param array $data - * - * @return bool - */ - protected function validOpeningBalanceData(array $data): bool - { - if (isset($data['openingBalance']) - && isset($data['openingBalanceDate']) - && isset($data['openingBalanceCurrency']) - && bccomp(strval($data['openingBalance']), '0') !== 0 - ) { - Log::debug('Array has valid opening balance data.'); - - return true; - } - Log::debug('Array does not have valid opening balance data.'); - - return false; - } -} diff --git a/app/Crud/Account/AccountCrudInterface.php b/app/Crud/Account/AccountCrudInterface.php deleted file mode 100644 index 6dfcd6e713..0000000000 --- a/app/Crud/Account/AccountCrudInterface.php +++ /dev/null @@ -1,53 +0,0 @@ - trim($request->input('name')), @@ -314,7 +314,7 @@ class AccountController extends Controller ]; - $account = $crud->store($accountData); + $account = $repository->store($accountData); Session::flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name]))); Preferences::mark(); @@ -338,13 +338,13 @@ class AccountController extends Controller } /** - * @param AccountFormRequest $request - * @param AccountCrudInterface $crud - * @param Account $account + * @param AccountFormRequest $request + * @param ARI $repository + * @param Account $account * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function update(AccountFormRequest $request, AccountCrudInterface $crud, Account $account) + public function update(AccountFormRequest $request, ARI $repository, Account $account) { $accountData = [ @@ -361,7 +361,7 @@ class AccountController extends Controller 'ccType' => $request->input('ccType'), 'ccMonthlyPaymentDate' => $request->input('ccMonthlyPaymentDate'), ]; - $crud->update($account, $accountData); + $repository->update($account, $accountData); Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name]))); Preferences::mark(); diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php index d799d14c39..832be8d57a 100644 --- a/app/Http/Controllers/ExportController.php +++ b/app/Http/Controllers/ExportController.php @@ -121,7 +121,6 @@ class ExportController extends Controller * @param EJRI $jobs * * @return string - * @internal param AccountCrudInterface $crud * */ public function postIndex(ExportFormRequest $request, AccountRepositoryInterface $repository, EJRI $jobs) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 39918cdbd8..65465a8e9f 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -101,7 +101,6 @@ class JsonController extends Controller * @param AccountRepositoryInterface $repository * * @return \Illuminate\Http\JsonResponse - * @internal param AccountCrudInterface $crud * * @internal param ARI $accountRepository */ diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index 1bcbc91bac..c15d3ce88c 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers; use Carbon\Carbon; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Http\Requests\NewUserFormRequest; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Preferences; @@ -60,27 +59,27 @@ class NewUserController extends Controller } /** - * @param NewUserFormRequest $request - * @param AccountCrudInterface $crud + * @param NewUserFormRequest $request + * @param AccountRepositoryInterface $repository * - * @return \Illuminate\Http\RedirectResponse + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function submit(NewUserFormRequest $request, AccountCrudInterface $crud) + public function submit(NewUserFormRequest $request, AccountRepositoryInterface $repository) { $count = 1; // create normal asset account: - $this->createAssetAccount($request, $crud); + $this->createAssetAccount($request, $repository); // create savings account if (strlen($request->get('savings_balance')) > 0) { - $this->createSavingsAccount($request, $crud); + $this->createSavingsAccount($request, $repository); $count++; } // create credit card. if (strlen($request->get('credit_card_limit')) > 0) { - $this->storeCreditCard($request, $crud); + $this->storeCreditCard($request, $repository); $count++; } $message = strval(trans('firefly.stored_new_accounts_new_user')); @@ -95,12 +94,12 @@ class NewUserController extends Controller } /** - * @param NewUserFormRequest $request - * @param AccountCrudInterface $crud + * @param NewUserFormRequest $request + * @param AccountRepositoryInterface $repository * * @return bool */ - private function createAssetAccount(NewUserFormRequest $request, AccountCrudInterface $crud): bool + private function createAssetAccount(NewUserFormRequest $request, AccountRepositoryInterface $repository): bool { $assetAccount = [ 'name' => $request->get('bank_name'), @@ -115,18 +114,18 @@ class NewUserController extends Controller 'openingBalanceCurrency' => intval($request->input('amount_currency_id_bank_balance')), ]; - $crud->store($assetAccount); + $repository->store($assetAccount); return true; } /** - * @param NewUserFormRequest $request - * @param AccountCrudInterface $crud + * @param NewUserFormRequest $request + * @param AccountRepositoryInterface $repository * * @return bool */ - private function createSavingsAccount(NewUserFormRequest $request, AccountCrudInterface $crud): bool + private function createSavingsAccount(NewUserFormRequest $request, AccountRepositoryInterface $repository): bool { $savingsAccount = [ 'name' => $request->get('bank_name') . ' savings account', @@ -140,18 +139,18 @@ class NewUserController extends Controller 'openingBalanceDate' => new Carbon, 'openingBalanceCurrency' => intval($request->input('amount_currency_id_savings_balance')), ]; - $crud->store($savingsAccount); + $repository->store($savingsAccount); return true; } /** - * @param NewUserFormRequest $request - * @param AccountCrudInterface $crud + * @param NewUserFormRequest $request + * @param AccountRepositoryInterface $repository * * @return bool */ - private function storeCreditCard(NewUserFormRequest $request, AccountCrudInterface $crud): bool + private function storeCreditCard(NewUserFormRequest $request, AccountRepositoryInterface $repository): bool { $creditAccount = [ 'name' => 'Credit card', @@ -167,7 +166,7 @@ class NewUserController extends Controller 'ccType' => 'monthlyFull', 'ccMonthlyPaymentDate' => Carbon::now()->year . '-01-01', ]; - $crud->store($creditAccount); + $repository->store($creditAccount); return true; } diff --git a/app/Import/Converter/AssetAccountIban.php b/app/Import/Converter/AssetAccountIban.php index 96bf71779c..9ed749a781 100644 --- a/app/Import/Converter/AssetAccountIban.php +++ b/app/Import/Converter/AssetAccountIban.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -43,9 +42,6 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -71,7 +67,7 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface } - $account = $crud->store( + $account = $repository->store( ['name' => 'Asset account with IBAN ' . $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0, 'active' => true, 'openingBalance' => 0] ); diff --git a/app/Import/Converter/AssetAccountName.php b/app/Import/Converter/AssetAccountName.php index 6ad981c067..4785ae16d2 100644 --- a/app/Import/Converter/AssetAccountName.php +++ b/app/Import/Converter/AssetAccountName.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -43,9 +42,6 @@ class AssetAccountName extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -70,7 +66,7 @@ class AssetAccountName extends BasicConverter implements ConverterInterface } - $account = $crud->store( + $account = $repository->store( ['name' => $value, 'iban' => null, 'openingBalance' => 0, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0, 'active' => true] ); diff --git a/app/Import/Converter/AssetAccountNumber.php b/app/Import/Converter/AssetAccountNumber.php index 647e18f7a6..5c71bf57f1 100644 --- a/app/Import/Converter/AssetAccountNumber.php +++ b/app/Import/Converter/AssetAccountNumber.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -41,9 +40,6 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -78,7 +74,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface } - $account = $crud->store( + $account = $repository->store( ['name' => $accountName, 'openingBalance' => 0, 'iban' => null, 'user' => $this->user->id, 'accountType' => 'asset', 'virtualBalance' => 0, 'accountNumber' => $value, 'active' => true] diff --git a/app/Import/Converter/OpposingAccountIban.php b/app/Import/Converter/OpposingAccountIban.php index 6d46b2662b..b1f8dc63e7 100644 --- a/app/Import/Converter/OpposingAccountIban.php +++ b/app/Import/Converter/OpposingAccountIban.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Log; @@ -42,9 +41,6 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -73,7 +69,7 @@ class OpposingAccountIban extends BasicConverter implements ConverterInterface return $account; } - $account = $crud->store( + $account = $repository->store( ['name' => $value, 'iban' => $value, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true, 'openingBalance' => 0] ); diff --git a/app/Import/Converter/OpposingAccountName.php b/app/Import/Converter/OpposingAccountName.php index f869a22e06..4516873a25 100644 --- a/app/Import/Converter/OpposingAccountName.php +++ b/app/Import/Converter/OpposingAccountName.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Log; @@ -42,9 +41,6 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -73,7 +69,7 @@ class OpposingAccountName extends BasicConverter implements ConverterInterface return $account; } - $account = $crud->store( + $account = $repository->store( ['name' => $value, 'iban' => null, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'active' => true, 'openingBalance' => 0, ] diff --git a/app/Import/Converter/OpposingAccountNumber.php b/app/Import/Converter/OpposingAccountNumber.php index 725813a0b2..86df680223 100644 --- a/app/Import/Converter/OpposingAccountNumber.php +++ b/app/Import/Converter/OpposingAccountNumber.php @@ -13,7 +13,6 @@ declare(strict_types = 1); namespace FireflyIII\Import\Converter; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -43,9 +42,6 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface return new Account; } - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -81,7 +77,7 @@ class OpposingAccountNumber extends BasicConverter implements ConverterInterface } - $account = $crud->store( + $account = $repository->store( ['name' => $accountName, 'openingBalance' => 0, 'iban' => null, 'user' => $this->user->id, 'accountType' => 'import', 'virtualBalance' => 0, 'accountNumber' => $value, 'active' => true] diff --git a/app/Import/ImportValidator.php b/app/Import/ImportValidator.php index 8045fa38e2..20705ca605 100644 --- a/app/Import/ImportValidator.php +++ b/app/Import/ImportValidator.php @@ -14,7 +14,6 @@ declare(strict_types = 1); namespace FireflyIII\Import; use Carbon\Carbon; -use FireflyIII\Crud\Account\AccountCrudInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\ImportJob; @@ -176,8 +175,6 @@ class ImportValidator return $account; } // find it first by new type: - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -186,7 +183,7 @@ class ImportValidator if (is_null($result->id)) { // can convert account: Log::debug(sprintf('No account named %s of type %s, create new account.', $account->name, $type)); - $result = $crud->store( + $result = $repository->store( [ 'user' => $this->user->id, 'accountType' => config('firefly.shortNamesByFullName.' . $type), @@ -216,16 +213,13 @@ class ImportValidator private function fallbackExpenseAccount(): Account { - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); $name = 'Unknown expense account'; $result = $repository->findByName($name, [AccountType::EXPENSE]); if (is_null($result->id)) { - $result = $crud->store( + $result = $repository->store( ['name' => $name, 'iban' => null, 'openingBalance' => 0, 'user' => $this->user->id, 'accountType' => 'expense', 'virtualBalance' => 0, 'active' => true] ); @@ -240,9 +234,6 @@ class ImportValidator private function fallbackRevenueAccount(): Account { - /** @var AccountCrudInterface $crud */ - $crud = app(AccountCrudInterface::class, [$this->user]); - /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class, [$this->user]); @@ -251,7 +242,7 @@ class ImportValidator if (is_null($result->id)) { - $result = $crud->store( + $result = $repository->store( ['name' => $name, 'iban' => null, 'openingBalance' => 0, 'user' => $this->user->id, 'accountType' => 'revenue', 'virtualBalance' => 0, 'active' => true] ); diff --git a/app/Providers/CrudServiceProvider.php b/app/Providers/CrudServiceProvider.php index 8a18f117d1..93acfa1412 100644 --- a/app/Providers/CrudServiceProvider.php +++ b/app/Providers/CrudServiceProvider.php @@ -42,26 +42,6 @@ class CrudServiceProvider extends ServiceProvider public function register() { $this->registerJournal(); - $this->registerAccount(); - } - - private function registerAccount() - { - - $this->app->bind( - 'FireflyIII\Crud\Account\AccountCrudInterface', - function (Application $app, array $arguments) { - - if (!isset($arguments[0]) && auth()->check()) { - return app('FireflyIII\Crud\Account\AccountCrud', [auth()->user()]); - } - if (!isset($arguments[0]) && !$app->auth->check()) { - throw new FireflyException('There is no user present.'); - } - - return app('FireflyIII\Crud\Account\AccountCrud', $arguments); - } - ); } private function registerJournal() diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index afed9ef68d..ee8ce84c15 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -16,8 +16,13 @@ namespace FireflyIII\Repositories\Account; use Carbon\Carbon; use DB; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; +use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Support\Collection; use Log; @@ -34,6 +39,8 @@ class AccountRepository implements AccountRepositoryInterface /** @var User */ private $user; + /** @var array */ + private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber']; /** * AttachmentRepository constructor. @@ -277,4 +284,325 @@ class AccountRepository implements AccountRepositoryInterface return $first; } + /** + * @param array $data + * + * @return Account + */ + public function store(array $data): Account + { + $newAccount = $this->storeAccount($data); + $this->updateMetadata($newAccount, $data); + + if ($this->validOpeningBalanceData($data)) { + $this->updateInitialBalance($newAccount, $data); + + return $newAccount; + } + $this->deleteInitialBalance($newAccount); + + return $newAccount; + + } + + /** + * @param Account $account + * @param array $data + * + * @return Account + */ + public function update(Account $account, array $data): Account + { + // update the account: + $account->name = $data['name']; + $account->active = $data['active'] == '1' ? true : false; + $account->virtual_balance = $data['virtualBalance']; + $account->iban = $data['iban']; + $account->save(); + + $this->updateMetadata($account, $data); + $this->updateInitialBalance($account, $data); + + return $account; + } + + /** + * @param Account $account + */ + protected function deleteInitialBalance(Account $account) + { + $journal = $this->openingBalanceTransaction($account); + if (!is_null($journal->id)) { + $journal->delete(); + } + + } + + /** + * @param Account $account + * + * @return TransactionJournal|null + */ + protected function openingBalanceTransaction(Account $account): TransactionJournal + { + $journal = TransactionJournal + ::sortCorrectly() + ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); + if (is_null($journal)) { + Log::debug('Could not find a opening balance journal, return empty one.'); + + return new TransactionJournal; + } + Log::debug(sprintf('Found opening balance: journal #%d.', $journal->id)); + + return $journal; + } + + /** + * @param array $data + * + * @return Account + * @throws FireflyException + */ + protected function storeAccount(array $data): Account + { + $data['accountType'] = $data['accountType'] ?? 'invalid'; + $type = config('firefly.accountTypeByIdentifier.' . $data['accountType']); + $accountType = AccountType::whereType($type)->first(); + + // verify account type + if (is_null($accountType)) { + throw new FireflyException(sprintf('Account type "%s" is invalid. Cannot create account.', $data['accountType'])); + } + + // account may exist already: + $existingAccount = $this->findByName($data['name'], [$data['accountType']]); + if (!is_null($existingAccount->id)) { + throw new FireflyException(sprintf('There already is an account named "%s" of type "%s".', $data['name'], $data['accountType'])); + } + + // create it: + $newAccount = new Account( + [ + 'user_id' => $data['user'], + 'account_type_id' => $accountType->id, + 'name' => $data['name'], + 'virtual_balance' => $data['virtualBalance'], + 'active' => $data['active'] === true ? true : false, + 'iban' => $data['iban'], + ] + ); + $newAccount->save(); + // verify its creation: + if (is_null($newAccount->id)) { + Log::error( + sprintf('Could not create account "%s" (%d error(s))', $data['name'], $newAccount->getErrors()->count()), $newAccount->getErrors()->toArray() + ); + throw new FireflyException(sprintf('Tried to create account named "%s" but failed. The logs have more details.', $data['name'])); + } + + return $newAccount; + } + + /** + * @param Account $account + * @param array $data + * + * @return TransactionJournal + */ + protected function storeInitialBalance(Account $account, array $data): TransactionJournal + { + $amount = $data['openingBalance']; + $user = $data['user']; + $name = $data['name']; + $opposing = $this->storeOpposingAccount($amount, $user, $name); + $transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first(); + $journal = TransactionJournal::create( + [ + 'user_id' => $data['user'], + 'transaction_type_id' => $transactionType->id, + 'transaction_currency_id' => $data['openingBalanceCurrency'], + 'description' => 'Initial balance for "' . $account->name . '"', + 'completed' => true, + 'date' => $data['openingBalanceDate'], + 'encrypted' => true, + ] + ); + Log::debug(sprintf('Created new opening balance journal: #%d', $journal->id)); + + $firstAccount = $account; + $secondAccount = $opposing; + $firstAmount = $amount; + $secondAmount = $amount * -1; + + if ($data['openingBalance'] < 0) { + $firstAccount = $opposing; + $secondAccount = $account; + $firstAmount = $amount * -1; + $secondAmount = $amount; + } + + $one = new Transaction(['account_id' => $firstAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $firstAmount]); + $one->save();// first transaction: from + $two = new Transaction(['account_id' => $secondAccount->id, 'transaction_journal_id' => $journal->id, 'amount' => $secondAmount]); + $two->save(); // second transaction: to + + Log::debug(sprintf('Stored two transactions, #%d and #%d', $one->id, $two->id)); + + return $journal; + } + + /** + * @param float $amount + * @param int $user + * @param string $name + * + * @return Account + */ + protected function storeOpposingAccount(float $amount, int $user, string $name):Account + { + $type = $amount < 0 ? 'expense' : 'revenue'; + $opposingData = [ + 'user' => $user, + 'accountType' => $type, + 'name' => $name . ' initial balance', + 'active' => false, + 'iban' => '', + 'virtualBalance' => 0, + ]; + Log::debug('Going to create an opening balance opposing account'); + + return $this->storeAccount($opposingData); + } + + /** + * @param Account $account + * @param array $data + * + * @return bool + */ + protected function updateInitialBalance(Account $account, array $data): bool + { + $openingBalance = $this->openingBalanceTransaction($account); + + // no opening balance journal? create it: + if (is_null($openingBalance->id)) { + Log::debug('No opening balance journal yet, create journal.'); + $this->storeInitialBalance($account, $data); + + return true; + } + // opening balance data? update it! + if (!is_null($openingBalance->id)) { + $date = $data['openingBalanceDate']; + $amount = $data['openingBalance']; + + Log::debug('Opening balance journal found, update journal.'); + + $this->updateOpeningBalanceJournal($account, $openingBalance, $date, $amount); + + return true; + } + + return true; + } + + /** + * @param Account $account + * @param array $data + * + */ + protected function updateMetadata(Account $account, array $data) + { + foreach ($this->validFields as $field) { + /** @var AccountMeta $entry */ + $entry = $account->accountMeta()->where('name', $field)->first(); + + // if $data has field and $entry is null, create new one: + if (isset($data[$field]) && is_null($entry)) { + Log::debug( + sprintf( + 'Created meta-field "%s":"%s" for account #%d ("%s") ', + $field, $data[$field], $account->id, $account->name + ) + ); + AccountMeta::create( + [ + 'account_id' => $account->id, + 'name' => $field, + 'data' => $data[$field], + ] + ); + } + + // if $data has field and $entry is not null, update $entry: + if (isset($data[$field]) && !is_null($entry)) { + $entry->data = $data[$field]; + $entry->save(); + Log::debug( + sprintf( + 'Updated meta-field "%s":"%s" for account #%d ("%s") ', + $field, $data[$field], $account->id, $account->name + ) + ); + } + } + + } + + /** + * @param Account $account + * @param TransactionJournal $journal + * @param Carbon $date + * @param float $amount + * + * @return bool + */ + protected function updateOpeningBalanceJournal(Account $account, TransactionJournal $journal, Carbon $date, float $amount): bool + { + // update date: + $journal->date = $date; + $journal->save(); + // update transactions: + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + if ($account->id == $transaction->account_id) { + $transaction->amount = $amount; + $transaction->save(); + } + if ($account->id != $transaction->account_id) { + $transaction->amount = $amount * -1; + $transaction->save(); + } + } + Log::debug('Updated opening balance journal.'); + + return true; + + } + + /** + * @param array $data + * + * @return bool + */ + protected function validOpeningBalanceData(array $data): bool + { + if (isset($data['openingBalance']) + && isset($data['openingBalanceDate']) + && isset($data['openingBalanceCurrency']) + && bccomp(strval($data['openingBalance']), '0') !== 0 + ) { + Log::debug('Array has valid opening balance data.'); + + return true; + } + Log::debug('Array does not have valid opening balance data.'); + + return false; + } + } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 21d8c7a163..ab7b1f5dc9 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -105,4 +105,11 @@ interface AccountRepositoryInterface */ public function oldestJournalDate(Account $account): Carbon; + /** + * @param array $data + * + * @return Account + */ + public function store(array $data) : Account; + }