From 4cec0a9f979c7e72163db0668b2aa76eeed9e043 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 22 Oct 2023 07:51:26 +0200 Subject: [PATCH] Refactor repository and some commands for upgrading --- .../Commands/Upgrade/AccountCurrencies.php | 15 +- .../Upgrade/UpgradeCurrencyPreferences.php | 153 ++++++++++++++++++ .../Commands/Upgrade/UpgradeSkeleton.php.stub | 1 + .../Currency/CurrencyRepository.php | 81 ++++++++-- .../Currency/CurrencyRepositoryInterface.php | 14 ++ .../Internal/Update/CurrencyUpdateService.php | 7 +- 6 files changed, 243 insertions(+), 28 deletions(-) create mode 100644 app/Console/Commands/Upgrade/UpgradeCurrencyPreferences.php diff --git a/app/Console/Commands/Upgrade/AccountCurrencies.php b/app/Console/Commands/Upgrade/AccountCurrencies.php index 73b6ffdf62..c470b70a1d 100644 --- a/app/Console/Commands/Upgrade/AccountCurrencies.php +++ b/app/Console/Commands/Upgrade/AccountCurrencies.php @@ -129,20 +129,7 @@ class AccountCurrencies extends Command $accounts = $this->accountRepos->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); // get user's currency preference: - $defaultCurrencyCode = app('preferences')->getForUser($user, 'currencyPreference', $systemCurrencyCode)->data; - if (!is_string($defaultCurrencyCode)) { - $defaultCurrencyCode = $systemCurrencyCode; - } - - /** @var TransactionCurrency|null $defaultCurrency */ - $defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first(); - - if (null === $defaultCurrency) { - Log::error(sprintf('Users currency pref "%s" does not exist!', $defaultCurrencyCode)); - $this->friendlyError(sprintf('User has a preference for "%s", but this currency does not exist.', $defaultCurrencyCode)); - - return; - } + $defaultCurrency = app('amount')->getDefaultCurrencyByUser($user); /** @var Account $account */ foreach ($accounts as $account) { diff --git a/app/Console/Commands/Upgrade/UpgradeCurrencyPreferences.php b/app/Console/Commands/Upgrade/UpgradeCurrencyPreferences.php new file mode 100644 index 0000000000..29c21063f6 --- /dev/null +++ b/app/Console/Commands/Upgrade/UpgradeCurrencyPreferences.php @@ -0,0 +1,153 @@ +isExecuted() && true !== $this->option('force')) { + $this->friendlyInfo('This command has already been executed.'); + + return 0; + } + $this->runUpgrade(); + + $this->friendlyPositive('Currency preferences migrated.'); + + //$this->markAsExecuted(); + + 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 User $user + * + * @return string + */ + private function getPreference(User $user): string + { + $preference = Preference::where('user_id', $user->id)->where('name', 'currencyPreference')->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']); + + if (null !== $preference) { + return (string)$preference->data; + } + return 'EUR'; + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } + + private function runUpgrade(): void + { + $groups = UserGroup::get(); + /** @var UserGroup $group */ + foreach ($groups as $group) { + $this->upgradeGroupPreferences($group); + } + + $users = User::get(); + /** @var User $user */ + foreach ($users as $user) { + $this->upgradeUserPreferences($user); + } + } + + /** + * @param User $user + * + * @return void + */ + private function upgradeUserPreferences(User $user): void + { + $currencies = TransactionCurrency::get(); + $enabled = new Collection(); + /** @var TransactionCurrency $currency */ + foreach ($currencies as $currency) { + if ($currency->enabled) { + $enabled->push($currency); + } + } + $user->currencies()->sync($enabled->pluck('id')->toArray()); + + // set the default currency for the user and for the group: + $preference = $this->getPreference($user); + $defaultCurrency = TransactionCurrency::where('code', $preference)->first(); + if (null === $currency) { + // get EUR + $defaultCurrency = TransactionCurrency::where('code', 'EUR')->first(); + } + $user->currencies()->updateExistingPivot($defaultCurrency->id, ['user_default' => true]); + $user->userGroup->currencies()->updateExistingPivot($defaultCurrency->id, ['group_default' => true]); + } + + /** + * @param UserGroup $group + * + * @return void + */ + private function upgradeGroupPreferences(UserGroup $group) + { + $currencies = TransactionCurrency::get(); + $enabled = new Collection(); + /** @var TransactionCurrency $currency */ + foreach ($currencies as $currency) { + if ($currency->enabled) { + $enabled->push($currency); + } + } + $group->currencies()->sync($enabled->pluck('id')->toArray()); + } +} diff --git a/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub b/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub index 4ba6803d78..a5fd3aab50 100644 --- a/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub +++ b/app/Console/Commands/Upgrade/UpgradeSkeleton.php.stub @@ -10,6 +10,7 @@ use Illuminate\Console\Command; */ class UpgradeSkeleton extends Command { + use ShowsFriendlyMessages; public const CONFIG_NAME = '480_some_name'; /** * The console command description. diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 591b4ae146..39684f8a41 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -140,8 +140,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface } // is the default currency for the user or the system - $defaultCode = app('preferences')->getForUser($this->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data; - if ($currency->code === $defaultCode) { + $count = $this->user->currencies()->where('transaction_currencies.id', $currency->id)->wherePivot('user_default', 1)->count(); + if ($count > 0) { Log::info('Is the default currency of the user, return true.'); return 'current_default'; @@ -226,6 +226,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface */ public function disable(TransactionCurrency $currency): void { + $this->user->currencies()->detach($currency->id); $currency->enabled = false; $currency->save(); } @@ -236,15 +237,13 @@ class CurrencyRepository implements CurrencyRepositoryInterface public function ensureMinimalEnabledCurrencies(): void { // if no currencies are enabled, enable the first one in the DB (usually the EUR) - if (0 === $this->get()->count()) { - /** @var TransactionCurrency $first */ - $first = $this->getAll()->first(); - if (null === $first) { + if (0 === $this->user->currencies()->count()) { + $euro = app('amount')->getSystemCurrency(); + if (null === $euro) { throw new FireflyException('No currencies found. You broke Firefly III'); } - Log::channel('audit')->info(sprintf('Auto-enabled currency %s.', $first->code)); - $this->enable($first); - app('preferences')->set('currencyPreference', $first->code); + Log::channel('audit')->info(sprintf('Auto-enabled currency %s.', $euro->code)); + $this->enable($euro); app('preferences')->mark(); } } @@ -255,7 +254,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface */ public function enable(TransactionCurrency $currency): void { - $currency->enabled = true; + $this->user->currencies()->syncWithoutDetaching([$currency->id]); + $currency->enabled = false; $currency->save(); } @@ -462,6 +462,14 @@ class CurrencyRepository implements CurrencyRepositoryInterface return null; } + /** + * @inheritDoc + */ + public function getUserCurrencies(User $user): Collection + { + return $user->currencies()->get(); + } + /** * @inheritDoc */ @@ -527,6 +535,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface */ public function store(array $data): TransactionCurrency { + throw new FireflyException(sprintf('Method "%s" needs a refactor.', __METHOD__)); /** @var TransactionCurrencyFactory $factory */ $factory = app(TransactionCurrencyFactory::class); $result = $factory->create($data); @@ -546,9 +555,61 @@ class CurrencyRepository implements CurrencyRepositoryInterface */ public function update(TransactionCurrency $currency, array $data): TransactionCurrency { + app('log')->debug('Now in update()'); + // can be true, false, null + $enabled = array_key_exists('enabled', $data) ? $data['enabled'] : null; + // can be true, false, but method only responds to "true". + $default = array_key_exists('default', $data) ? $data['default'] : false; + + // remove illegal combo's: + if (false === $enabled && true === $default) { + $enabled = true; + } + if (false === $default) { + app('log')->warning(sprintf('Set default=false will NOT do anything for currency %s', $currency->code)); + } + + // update currency with current user specific settings + $currency->refreshForUser($this->user); + + // currency is enabled, must be disabled. + if (false === $enabled) { + app('log')->debug(sprintf('Disabled currency %s for user #%d', $currency->code, $this->user->id)); + $this->user->currencies()->detach($currency->id); + } + // currency must be enabled + if (true === $enabled) { + app('log')->debug(sprintf('Enabled currency %s for user #%d', $currency->code, $this->user->id)); + $this->user->currencies()->detach($currency->id); + $this->user->currencies()->syncWithoutDetaching([$currency->id => ['user_default' => false]]); + } + + // currency must be made default. + if (true === $default) { + app('log')->debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->user->id)); + $this->user->currencies()->detach($currency->id); + foreach ($this->user->currencies()->get() as $item) { + $this->user->currencies()->updateExistingPivot($item->id, ['user_default' => false]); + } + $this->user->currencies()->syncWithoutDetaching([$currency->id => ['user_default' => true]]); + } + /** @var CurrencyUpdateService $service */ $service = app(CurrencyUpdateService::class); return $service->update($currency, $data); } + + /** + * @inheritDoc + */ + public function makeDefault(TransactionCurrency $currency): void + { + app('log')->debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->user->id)); + $this->user->currencies()->detach($currency->id); + foreach ($this->user->currencies()->get() as $item) { + $this->user->currencies()->updateExistingPivot($item->id, ['user_default' => false]); + } + $this->user->currencies()->syncWithoutDetaching([$currency->id => ['user_default' => true]]); + } } diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 3ef07f66f4..ff8c1c8d1d 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -204,6 +204,20 @@ interface CurrencyRepositoryInterface */ public function getExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): ?CurrencyExchangeRate; + /** + * @param TransactionCurrency $currency + * + * @return void + */ + public function makeDefault(TransactionCurrency $currency): void; + + /** + * @param User $user + * + * @return Collection + */ + public function getUserCurrencies(User $user): Collection; + /** * @param TransactionCurrency $currency * diff --git a/app/Services/Internal/Update/CurrencyUpdateService.php b/app/Services/Internal/Update/CurrencyUpdateService.php index c01444e4e8..01fe1692f6 100644 --- a/app/Services/Internal/Update/CurrencyUpdateService.php +++ b/app/Services/Internal/Update/CurrencyUpdateService.php @@ -52,14 +52,13 @@ class CurrencyUpdateService $currency->name = e($data['name']); } - if (array_key_exists('enabled', $data) && is_bool($data['enabled'])) { - $currency->enabled = (bool)$data['enabled']; - } + $currency->enabled = false; if (array_key_exists('decimal_places', $data) && is_int($data['decimal_places'])) { $currency->decimal_places = (int)$data['decimal_places']; } - + unset($currency->userEnabled); + unset($currency->userDefault); $currency->save(); return $currency;