diff --git a/app/Console/Commands/Upgrade/UpgradeLiabilities.php b/app/Console/Commands/Upgrade/UpgradeLiabilities.php new file mode 100644 index 0000000000..55bfa8670f --- /dev/null +++ b/app/Console/Commands/Upgrade/UpgradeLiabilities.php @@ -0,0 +1,175 @@ +isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + $this->upgradeLiabilities(); + + //$this->markAsExecuted(); + + $end = round(microtime(true) - $start, 2); + $this->info(sprintf('in %s seconds.', $end)); + + return 0; + } + + /** + * @return bool + */ + private function isExecuted(): bool + { + $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); + if (null !== $configVar) { + return (bool)$configVar->data; + } + + return false; + } + + /** + * @param Account $account + * @param TransactionJournal $openingBalance + */ + private function correctOpeningBalance(Account $account, TransactionJournal $openingBalance): void + { + $source = $this->getSourceTransaction($openingBalance); + $destination = $this->getDestinationTransaction($openingBalance); + if (null === $source || null === $destination) { + return; + } + // source MUST be the liability. + if ((int)$destination->account_id === (int)$account->id) { + Log::debug(sprintf('Must switch around, because account #%d is the destination.', $destination->account_id)); + // so if not, switch things around: + $sourceAccountId = (int)$source->account_id; + $source->account_id = $destination->account_id; + $destination->account_id = $sourceAccountId; + $source->save(); + $destination->save(); + Log::debug(sprintf('Source transaction #%d now has account #%d', $source->id, $source->account_id)); + Log::debug(sprintf('Dest transaction #%d now has account #%d', $destination->id, $destination->account_id)); + } + } + + /** + * @param TransactionJournal $journal + * + * @return Transaction + */ + private function getSourceTransaction(TransactionJournal $journal): ?Transaction + { + return $journal->transactions()->where('amount', '<', 0)->first(); + } + + /** + * @param TransactionJournal $journal + * + * @return Transaction + */ + private function getDestinationTransaction(TransactionJournal $journal): ?Transaction + { + return $journal->transactions()->where('amount', '>', 0)->first(); + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } + + /** + * + */ + private function upgradeLiabilities(): void + { + Log::debug('Upgrading liabilities.'); + $users = User::get(); + /** @var User $user */ + foreach ($users as $user) { + $this->upgradeForUser($user); + } + } + + /** + * @param User $user + */ + private function upgradeForUser(User $user): void + { + Log::debug(sprintf('Upgrading liabilities for user #%d', $user->id)); + $accounts = $user->accounts() + ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') + ->whereIn('account_types.type', config('firefly.valid_liabilities')) + ->get(['accounts.*']); + /** @var Account $account */ + foreach ($accounts as $account) { + $this->upgradeLiability($account); + } + } + + /** + * @param Account $account + */ + private function upgradeLiability(Account $account): void + { + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setUser($account->user); + Log::debug(sprintf('Upgrade liability #%d', $account->id)); + + // get opening balance, and correct if necessary. + $openingBalance = $repository->getOpeningBalance($account); + if (null !== $openingBalance) { + // correct if necessary + $this->correctOpeningBalance($account, $openingBalance); + } + + // add liability direction property + /** @var AccountMetaFactory $factory */ + $factory = app(AccountMetaFactory::class); + $factory->crud($account, 'liability_direction', 'debit'); + } + +}