diff --git a/app/Console/Commands/Upgrade/BudgetLimitCurrency.php b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php new file mode 100644 index 0000000000..db85f1cfb5 --- /dev/null +++ b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php @@ -0,0 +1,109 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Upgrade; + + +use FireflyIII\Models\Budget; +use FireflyIII\Models\BudgetLimit; +use Illuminate\Console\Command; + +/** + * Class BudgetLimitCurrency + */ +class BudgetLimitCurrency extends Command +{ + public const CONFIG_NAME = '4780_bl_currency'; + /** + * The console command description. + * + * @var string + */ + protected $description = 'Give budget limits a currency'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:bl-currency {--F|force : Force the execution of this command.}'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle(): int + { + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + + $budgetLimits = BudgetLimit::get(); + /** @var BudgetLimit $budgetLimit */ + foreach ($budgetLimits as $budgetLimit) { + if (null === $budgetLimit->transaction_currency_id) { + /** @var Budget $budget */ + $budget = $budgetLimit->budget; + if (null !== $budget) { + $user = $budget->user; + if (null !== $user) { + $currency = app('amount')->getDefaultCurrencyByUser($user); + $budgetLimit->transaction_currency_id = $currency->id; + $budgetLimit->save(); + $this->line( + sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name) + ); + } + } + } + } + + $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; // @codeCoverageIgnore + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } +} \ No newline at end of file diff --git a/app/Console/Commands/Upgrade/CCLiabilities.php b/app/Console/Commands/Upgrade/CCLiabilities.php new file mode 100644 index 0000000000..373bac1ce7 --- /dev/null +++ b/app/Console/Commands/Upgrade/CCLiabilities.php @@ -0,0 +1,106 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Upgrade; + + +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use Illuminate\Console\Command; +use Illuminate\Support\Collection; + +/** + * Class CCLiabilities + */ +class CCLiabilities extends Command +{ + + + public const CONFIG_NAME = '4780_cc_liabilities'; + /** + * The console command description. + * + * @var string + */ + protected $description = 'Convert old credit card liabilities.'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:cc-liabilities {--F|force : Force the execution of this command.}'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle(): int + { + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + $ccType = AccountType::where('type', AccountType::CREDITCARD)->first(); + $debtType = AccountType::where('type', AccountType::DEBT)->first(); + if (null === $ccType || null === $debtType) { + return 0; + } + /** @var Collection $accounts */ + $accounts = Account::where('account_type_id', $ccType->id)->get(); + foreach ($accounts as $account) { + $account->account_type_id = $debtType->id; + $account->save(); + $this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id)); + } + if ($accounts->count() > 0) { + $this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards'); + } + $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; // @codeCoverageIgnore + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } +} \ No newline at end of file diff --git a/app/Console/Commands/UpgradeDatabaseX.php b/app/Console/Commands/Upgrade/JournalCurrencies.php similarity index 52% rename from app/Console/Commands/UpgradeDatabaseX.php rename to app/Console/Commands/Upgrade/JournalCurrencies.php index ac5bcc4114..48903d0301 100644 --- a/app/Console/Commands/UpgradeDatabaseX.php +++ b/app/Console/Commands/Upgrade/JournalCurrencies.php @@ -1,8 +1,7 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ -/** @noinspection PhpStaticAsDynamicMethodCallInspection */ -/** @noinspection PhpDynamicAsStaticMethodCallInspection */ - declare(strict_types=1); -namespace FireflyIII\Console\Commands; +namespace FireflyIII\Console\Commands\Upgrade; -use Crypt; -use DB; -use Exception; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; -use FireflyIII\Models\Attachment; -use FireflyIII\Models\Bill; -use FireflyIII\Models\Budget; -use FireflyIII\Models\BudgetLimit; -use FireflyIII\Models\Note; -use FireflyIII\Models\Preference; -use FireflyIII\Models\Rule; -use FireflyIII\Models\RuleAction; -use FireflyIII\Models\RuleGroup; -use FireflyIII\Models\RuleTrigger; use FireflyIII\Models\Transaction; -use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; -use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\User; use Illuminate\Console\Command; -use Illuminate\Contracts\Encryption\DecryptException; -use Illuminate\Database\QueryException; use Illuminate\Support\Collection; use Log; -use Schema; -use UnexpectedValueException; /** - * Class UpgradeDatabase. - * - * Upgrade user database. - * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * - * @codeCoverageIgnore + * Class JournalCurrencies */ -class UpgradeDatabaseX extends Command +class JournalCurrencies extends Command { + + public const CONFIG_NAME = '4780_journal_currencies'; /** * The console command description. * * @var string */ - protected $description = 'Will run various commands to update database records.'; + protected $description = 'Update all transaction and journal currencies.'; /** * The name and signature of the console command. * * @var string */ - protected $signature = 'firefly:upgrade-databaseX'; + protected $signature = 'firefly-iii:journal-currencies {--F|force : Force the execution of this command.}'; /** * Execute the console command. + * + * @return int */ public function handle(): int { - $this->updateAccountCurrencies(); - $this->createNewTypes(); - $this->line('Updating currency information..'); + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + $this->updateTransferCurrencies(); $this->updateOtherCurrencies(); - $this->line('Done updating currency information..'); - $this->migrateNotes(); - $this->migrateAttachmentData(); - $this->migrateBillsToRules(); - $this->budgetLimitCurrency(); - $this->removeCCLiabilities(); - - $this->info('Firefly III database is up to date.'); + $this->markAsExecuted(); return 0; } - /** - * @param string $value - * - * @return string - */ - private function tryDecrypt(string $value): string - { - try { - $value = Crypt::decrypt($value); - } catch (DecryptException $e) { - Log::debug(sprintf('Could not decrypt. %s', $e->getMessage())); - } - - return $value; - } - - /** - * Since it is one routine these warnings make sense and should be supressed. - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function migrateBillsToRules(): void - { - foreach (User::get() as $user) { - /** @var Preference $lang */ - $lang = app('preferences')->getForUser($user, 'language', 'en_US'); - $groupName = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data); - $ruleGroup = $user->ruleGroups()->where('title', $groupName)->first(); - $currencyPreference = app('preferences')->getForUser($user, 'currencyPreference', config('firefly.default_currency', 'EUR')); - - if (null === $currencyPreference) { - $this->error('User has no currency preference. Impossible.'); - - return; - } - $currencyCode = $this->tryDecrypt($currencyPreference->data); - - // try json decrypt just in case. - if (\strlen($currencyCode) > 3) { - $currencyCode = json_decode($currencyCode) ?? 'EUR'; - } - - $currency = TransactionCurrency::where('code', $currencyCode)->first(); - if (null === $currency) { - $this->line('Fall back to default currency in migrateBillsToRules().'); - $currency = app('amount')->getDefaultCurrencyByUser($user); - } - - if (null === $ruleGroup) { - $array = RuleGroup::get(['order'])->pluck('order')->toArray(); - $order = \count($array) > 0 ? max($array) + 1 : 1; - $ruleGroup = RuleGroup::create( - [ - 'user_id' => $user->id, - 'title' => (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data), - 'description' => (string)trans('firefly.rulegroup_for_bills_description', [], $lang->data), - 'order' => $order, - 'active' => 1, - ] - ); - } - - // loop bills. - $order = 1; - /** @var Collection $collection */ - $collection = $user->bills()->get(); - /** @var Bill $bill */ - foreach ($collection as $bill) { - if ('MIGRATED_TO_RULES' !== $bill->match) { - $rule = Rule::create( - [ - 'user_id' => $user->id, - 'rule_group_id' => $ruleGroup->id, - 'title' => (string)trans('firefly.rule_for_bill_title', ['name' => $bill->name], $lang->data), - 'description' => (string)trans('firefly.rule_for_bill_description', ['name' => $bill->name], $lang->data), - 'order' => $order, - 'active' => $bill->active, - 'stop_processing' => 1, - ] - ); - // add default trigger - RuleTrigger::create( - [ - 'rule_id' => $rule->id, - 'trigger_type' => 'user_action', - 'trigger_value' => 'store-journal', - 'active' => 1, - 'stop_processing' => 0, - 'order' => 1, - ] - ); - // add trigger for description - $match = implode(' ', explode(',', $bill->match)); - RuleTrigger::create( - [ - 'rule_id' => $rule->id, - 'trigger_type' => 'description_contains', - 'trigger_value' => $match, - 'active' => 1, - 'stop_processing' => 0, - 'order' => 2, - ] - ); - if ($bill->amount_max !== $bill->amount_min) { - // add triggers for amounts: - RuleTrigger::create( - [ - 'rule_id' => $rule->id, - 'trigger_type' => 'amount_less', - 'trigger_value' => round($bill->amount_max, $currency->decimal_places), - 'active' => 1, - 'stop_processing' => 0, - 'order' => 3, - ] - ); - RuleTrigger::create( - [ - 'rule_id' => $rule->id, - 'trigger_type' => 'amount_more', - 'trigger_value' => round((float)$bill->amount_min, $currency->decimal_places), - 'active' => 1, - 'stop_processing' => 0, - 'order' => 4, - ] - ); - } - if ($bill->amount_max === $bill->amount_min) { - RuleTrigger::create( - [ - 'rule_id' => $rule->id, - 'trigger_type' => 'amount_exactly', - 'trigger_value' => round((float)$bill->amount_min, $currency->decimal_places), - 'active' => 1, - 'stop_processing' => 0, - 'order' => 3, - ] - ); - } - - // create action - RuleAction::create( - [ - 'rule_id' => $rule->id, - 'action_type' => 'link_to_bill', - 'action_value' => $bill->name, - 'order' => 1, - 'active' => 1, - 'stop_processing' => 0, - ] - ); - - $order++; - $bill->match = 'MIGRATED_TO_RULES'; - $bill->save(); - $this->line(sprintf('Updated bill #%d ("%s") so it will use rules.', $bill->id, $bill->name)); - } - - // give bills a currency when they dont have one. - if (null === $bill->transaction_currency_id) { - $this->line(sprintf('Gave bill #%d ("%s") a currency (%s).', $bill->id, $bill->name, $currency->name)); - $bill->transactionCurrency()->associate($currency); - $bill->save(); - } - } - } - } - - - - /** * This routine verifies that withdrawals, deposits and opening balances have the correct currency settings for * the accounts they are linked to. @@ -376,126 +172,24 @@ class UpgradeDatabaseX extends Command } /** - * + * @return bool */ - private function budgetLimitCurrency(): void + private function isExecuted(): bool { - $budgetLimits = BudgetLimit::get(); - /** @var BudgetLimit $budgetLimit */ - foreach ($budgetLimits as $budgetLimit) { - if (null === $budgetLimit->transaction_currency_id) { - /** @var Budget $budget */ - $budget = $budgetLimit->budget; - if (null !== $budget) { - $user = $budget->user; - if (null !== $user) { - $currency = app('amount')->getDefaultCurrencyByUser($user); - $budgetLimit->transaction_currency_id = $currency->id; - $budgetLimit->save(); - $this->line( - sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name) - ); - } - } - } + $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); + if (null !== $configVar) { + return (bool)$configVar->data; } + + return false; // @codeCoverageIgnore } /** * */ - private function createNewTypes(): void + private function markAsExecuted(): void { - // create transaction type "Reconciliation". - $type = TransactionType::where('type', TransactionType::RECONCILIATION)->first(); - if (null === $type) { - TransactionType::create(['type' => TransactionType::RECONCILIATION]); - } - $account = AccountType::where('type', AccountType::RECONCILIATION)->first(); - if (null === $account) { - AccountType::create(['type' => AccountType::RECONCILIATION]); - } - } - - /** - * Move the description of each attachment (when not NULL) to the notes or to a new note object - * for all attachments. - */ - private function migrateAttachmentData(): void - { - $attachments = Attachment::get(); - - /** @var Attachment $att */ - foreach ($attachments as $att) { - - // move description: - $description = (string)$att->description; - if ('' !== $description) { - // find or create note: - $note = $att->notes()->first(); - if (null === $note) { - $note = new Note; - $note->noteable()->associate($att); - } - $note->text = $description; - $note->save(); - - // clear description: - $att->description = ''; - $att->save(); - - Log::debug(sprintf('Migrated attachment #%s description to note #%d', $att->id, $note->id)); - } - } - } - - /** - * Move all the journal_meta notes to their note object counter parts. - */ - private function migrateNotes(): void - { - /** @noinspection PhpUndefinedMethodInspection */ - $set = TransactionJournalMeta::whereName('notes')->get(); - /** @var TransactionJournalMeta $meta */ - foreach ($set as $meta) { - $journal = $meta->transactionJournal; - $note = $journal->notes()->first(); - if (null === $note) { - $note = new Note(); - $note->noteable()->associate($journal); - } - - $note->text = $meta->data; - $note->save(); - Log::debug(sprintf('Migrated meta note #%d to Note #%d', $meta->id, $note->id)); - try { - $meta->delete(); - } catch (Exception $e) { - Log::error(sprintf('Could not delete old meta entry #%d: %s', $meta->id, $e->getMessage())); - } - } - } - - /** - * - */ - private function removeCCLiabilities(): void - { - $ccType = AccountType::where('type', AccountType::CREDITCARD)->first(); - $debtType = AccountType::where('type', AccountType::DEBT)->first(); - if (null === $ccType || null === $debtType) { - return; - } - /** @var Collection $accounts */ - $accounts = Account::where('account_type_id', $ccType->id)->get(); - foreach ($accounts as $account) { - $account->account_type_id = $debtType->id; - $account->save(); - $this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id)); - } - if ($accounts->count() > 0) { - $this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards'); - } + app('fireflyconfig')->set(self::CONFIG_NAME, true); } /** @@ -533,8 +227,6 @@ class UpgradeDatabaseX extends Command } - - /** * This method makes sure that the tranaction uses the same currency as the source account does. * If not, the currency is updated to include a reference to its original currency as the "foreign" currency. @@ -677,5 +369,4 @@ class UpgradeDatabaseX extends Command } } - -} +} \ No newline at end of file diff --git a/app/Console/Commands/Upgrade/MigrateAttachments.php b/app/Console/Commands/Upgrade/MigrateAttachments.php new file mode 100644 index 0000000000..39860d421b --- /dev/null +++ b/app/Console/Commands/Upgrade/MigrateAttachments.php @@ -0,0 +1,114 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Upgrade; + + +use FireflyIII\Models\Attachment; +use FireflyIII\Models\Note; +use Illuminate\Console\Command; +use Log; + +/** + * Class MigrateAttachments + */ +class MigrateAttachments extends Command +{ + public const CONFIG_NAME = '4780_migrate_attachments'; + /** + * The console command description. + * + * @var string + */ + protected $description = 'Migrates attachment meta-data.'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:migrate-attachments {--F|force : Force the execution of this command.}'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle(): int + { + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + $attachments = Attachment::get(); + + /** @var Attachment $att */ + foreach ($attachments as $att) { + + // move description: + $description = (string)$att->description; + if ('' !== $description) { + // find or create note: + $note = $att->notes()->first(); + if (null === $note) { + $note = new Note; + $note->noteable()->associate($att); + } + $note->text = $description; + $note->save(); + + // clear description: + $att->description = ''; + $att->save(); + + Log::debug(sprintf('Migrated attachment #%s description to note #%d', $att->id, $note->id)); + } + } + + $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; // @codeCoverageIgnore + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } +} \ No newline at end of file diff --git a/app/Console/Commands/Upgrade/MigrateNotes.php b/app/Console/Commands/Upgrade/MigrateNotes.php new file mode 100644 index 0000000000..2c78de9a57 --- /dev/null +++ b/app/Console/Commands/Upgrade/MigrateNotes.php @@ -0,0 +1,112 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Upgrade; + + +use Exception; +use FireflyIII\Models\Note; +use FireflyIII\Models\TransactionJournalMeta; +use Illuminate\Console\Command; +use Log; + +/** + * Class MigrateNotes + */ +class MigrateNotes extends Command +{ + public const CONFIG_NAME = '4780_migrate_notes'; + /** + * The console command description. + * + * @var string + */ + protected $description = 'Migrate notes'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:migrate-notes {--F|force : Force the execution of this command.}'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle(): int + { + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + + /** @noinspection PhpUndefinedMethodInspection */ + $set = TransactionJournalMeta::whereName('notes')->get(); + /** @var TransactionJournalMeta $meta */ + foreach ($set as $meta) { + $journal = $meta->transactionJournal; + $note = $journal->notes()->first(); + if (null === $note) { + $note = new Note(); + $note->noteable()->associate($journal); + } + + $note->text = $meta->data; + $note->save(); + Log::debug(sprintf('Migrated meta note #%d to Note #%d', $meta->id, $note->id)); + try { + $meta->delete(); + } catch (Exception $e) { + Log::error(sprintf('Could not delete old meta entry #%d: %s', $meta->id, $e->getMessage())); + } + } + + $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; // @codeCoverageIgnore + } + + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } +} \ No newline at end of file diff --git a/app/Console/Commands/Upgrade/MigrateToRules.php b/app/Console/Commands/Upgrade/MigrateToRules.php new file mode 100644 index 0000000000..8756d268fe --- /dev/null +++ b/app/Console/Commands/Upgrade/MigrateToRules.php @@ -0,0 +1,257 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Upgrade; + + +use Crypt; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Preference; +use FireflyIII\Models\Rule; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\RuleGroup; +use FireflyIII\Models\RuleTrigger; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\User; +use Illuminate\Console\Command; +use Illuminate\Contracts\Encryption\DecryptException; +use Illuminate\Support\Collection; +use Log; + +/** + * Class MigrateToRules + */ +class MigrateToRules extends Command +{ + public const CONFIG_NAME = '4780_bills_to_rules'; + /** + * The console command description. + * + * @var string + */ + protected $description = 'Migrate bills to rules.'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:bills-to-rules {--F|force : Force the execution of this command.}'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle(): int + { + if ($this->isExecuted() && true !== $this->option('force')) { + $this->warn('This command has already been executed.'); + + return 0; + } + + foreach (User::get() as $user) { + /** @var Preference $lang */ + $lang = app('preferences')->getForUser($user, 'language', 'en_US'); + $groupName = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data); + $ruleGroup = $user->ruleGroups()->where('title', $groupName)->first(); + $currencyPreference = app('preferences')->getForUser($user, 'currencyPreference', config('firefly.default_currency', 'EUR')); + + if (null === $currencyPreference) { + $this->error('User has no currency preference. Impossible.'); + + return 1; + } + $currencyCode = $this->tryDecrypt($currencyPreference->data); + + // try json decrypt just in case. + if (\strlen($currencyCode) > 3) { + $currencyCode = json_decode($currencyCode) ?? 'EUR'; + } + + $currency = TransactionCurrency::where('code', $currencyCode)->first(); + if (null === $currency) { + $this->line('Fall back to default currency in migrateBillsToRules().'); + $currency = app('amount')->getDefaultCurrencyByUser($user); + } + + if (null === $ruleGroup) { + $array = RuleGroup::get(['order'])->pluck('order')->toArray(); + $order = \count($array) > 0 ? max($array) + 1 : 1; + $ruleGroup = RuleGroup::create( + [ + 'user_id' => $user->id, + 'title' => (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data), + 'description' => (string)trans('firefly.rulegroup_for_bills_description', [], $lang->data), + 'order' => $order, + 'active' => 1, + ] + ); + } + + // loop bills. + $order = 1; + /** @var Collection $collection */ + $collection = $user->bills()->get(); + /** @var Bill $bill */ + foreach ($collection as $bill) { + if ('MIGRATED_TO_RULES' !== $bill->match) { + $rule = Rule::create( + [ + 'user_id' => $user->id, + 'rule_group_id' => $ruleGroup->id, + 'title' => (string)trans('firefly.rule_for_bill_title', ['name' => $bill->name], $lang->data), + 'description' => (string)trans('firefly.rule_for_bill_description', ['name' => $bill->name], $lang->data), + 'order' => $order, + 'active' => $bill->active, + 'stop_processing' => 1, + ] + ); + // add default trigger + RuleTrigger::create( + [ + 'rule_id' => $rule->id, + 'trigger_type' => 'user_action', + 'trigger_value' => 'store-journal', + 'active' => 1, + 'stop_processing' => 0, + 'order' => 1, + ] + ); + // add trigger for description + $match = implode(' ', explode(',', $bill->match)); + RuleTrigger::create( + [ + 'rule_id' => $rule->id, + 'trigger_type' => 'description_contains', + 'trigger_value' => $match, + 'active' => 1, + 'stop_processing' => 0, + 'order' => 2, + ] + ); + if ($bill->amount_max !== $bill->amount_min) { + // add triggers for amounts: + RuleTrigger::create( + [ + 'rule_id' => $rule->id, + 'trigger_type' => 'amount_less', + 'trigger_value' => round($bill->amount_max, $currency->decimal_places), + 'active' => 1, + 'stop_processing' => 0, + 'order' => 3, + ] + ); + RuleTrigger::create( + [ + 'rule_id' => $rule->id, + 'trigger_type' => 'amount_more', + 'trigger_value' => round((float)$bill->amount_min, $currency->decimal_places), + 'active' => 1, + 'stop_processing' => 0, + 'order' => 4, + ] + ); + } + if ($bill->amount_max === $bill->amount_min) { + RuleTrigger::create( + [ + 'rule_id' => $rule->id, + 'trigger_type' => 'amount_exactly', + 'trigger_value' => round((float)$bill->amount_min, $currency->decimal_places), + 'active' => 1, + 'stop_processing' => 0, + 'order' => 3, + ] + ); + } + + // create action + RuleAction::create( + [ + 'rule_id' => $rule->id, + 'action_type' => 'link_to_bill', + 'action_value' => $bill->name, + 'order' => 1, + 'active' => 1, + 'stop_processing' => 0, + ] + ); + + $order++; + $bill->match = 'MIGRATED_TO_RULES'; + $bill->save(); + $this->line(sprintf('Updated bill #%d ("%s") so it will use rules.', $bill->id, $bill->name)); + } + + // give bills a currency when they dont have one. + if (null === $bill->transaction_currency_id) { + $this->line(sprintf('Gave bill #%d ("%s") a currency (%s).', $bill->id, $bill->name, $currency->name)); + $bill->transactionCurrency()->associate($currency); + $bill->save(); + } + } + } + + $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; // @codeCoverageIgnore + } + + /** + * + */ + private function markAsExecuted(): void + { + app('fireflyconfig')->set(self::CONFIG_NAME, true); + } + + /** + * @param string $value + * + * @return string + */ + private function tryDecrypt(string $value): string + { + try { + $value = Crypt::decrypt($value); + } catch (DecryptException $e) { + Log::debug(sprintf('Could not decrypt. %s', $e->getMessage())); + } + + return $value; + } +} \ No newline at end of file diff --git a/app/Console/Commands/Upgrade/UpgradeDatabase.php b/app/Console/Commands/Upgrade/UpgradeDatabase.php index d1dd3b52fc..d5a8c082e6 100644 --- a/app/Console/Commands/Upgrade/UpgradeDatabase.php +++ b/app/Console/Commands/Upgrade/UpgradeDatabase.php @@ -62,6 +62,12 @@ class UpgradeDatabase extends Command $commands = [ 'firefly-iii:transaction-identifiers', 'firefly-iii:account-currencies', + 'firefly-iii:journal-currencies', + 'firefly-iii:migrate-notes', + 'firefly-iii:migrate-attachments', + 'firefly-iii:bills-to-rules', + 'firefly-iii:bl-currency', + 'firefly-iii:cc-liabilities', 'firefly-iii:migrate-to-groups', 'firefly-iii:back-to-journals', ];