mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Fix issue with liability upgrades.
This commit is contained in:
parent
4917f40abf
commit
c976149bf1
62
app/Console/Commands/Correction/TriggerCreditCalculation.php
Normal file
62
app/Console/Commands/Correction/TriggerCreditCalculation.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\Correction;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CorrectionSkeleton
|
||||||
|
* TODO DONT FORGET TO ADD THIS TO THE DOCKER BUILD
|
||||||
|
*/
|
||||||
|
class TriggerCreditCalculation extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Triggers the credit recalculation service for liabilities.';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:trigger-credit-recalculation';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$this->processAccounts();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processAccounts(): void
|
||||||
|
{
|
||||||
|
$accounts = Account::leftJoin('account_types', 'accounts.account_type_id', 'account_types.id')
|
||||||
|
->whereIn('account_types.type', config('firefly.valid_liabilities'))
|
||||||
|
->get(['accounts.*']);
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
Log::debug(sprintf('Processing account #%d ("%s")', $account->id, $account->name));
|
||||||
|
$this->processAccount($account);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $account
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function processAccount(Account $account): void
|
||||||
|
{
|
||||||
|
/** @var CreditRecalculateService $object */
|
||||||
|
$object = app(CreditRecalculateService::class);
|
||||||
|
$object->setAccount($account);
|
||||||
|
$object->recalculate();
|
||||||
|
}
|
||||||
|
}
|
@ -145,10 +145,13 @@ class UpgradeLiabilities extends Command
|
|||||||
$this->correctOpeningBalance($account, $openingBalance);
|
$this->correctOpeningBalance($account, $openingBalance);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add liability direction property
|
// add liability direction property (if it does not yet exist!)
|
||||||
/** @var AccountMetaFactory $factory */
|
$value = $repository->getMetaValue($account, 'liability_direction');
|
||||||
$factory = app(AccountMetaFactory::class);
|
if (null === $value) {
|
||||||
$factory->crud($account, 'liability_direction', 'debit');
|
/** @var AccountMetaFactory $factory */
|
||||||
|
$factory = app(AccountMetaFactory::class);
|
||||||
|
$factory->crud($account, 'liability_direction', 'debit');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
208
app/Console/Commands/Upgrade/UpgradeLiabilitiesEight.php
Normal file
208
app/Console/Commands/Upgrade/UpgradeLiabilitiesEight.php
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UpgradeLiabilities.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\Upgrade;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\Account;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\TransactionType;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService;
|
||||||
|
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UpgradeLiabilitiesEight
|
||||||
|
*/
|
||||||
|
class UpgradeLiabilitiesEight extends Command
|
||||||
|
{
|
||||||
|
public const CONFIG_NAME = '580_upgrade_liabilities';
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Upgrade liabilities to new 5.8.0 structure.';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:liabilities-580 {--F|force : Force the execution of this command.}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$start = microtime(true);
|
||||||
|
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||||
|
$this->warn('This command has already been executed.');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$this->upgradeLiabilities();
|
||||||
|
|
||||||
|
// TODO uncomment me
|
||||||
|
//$this->markAsExecuted();
|
||||||
|
|
||||||
|
$end = round(microtime(true) - $start, 2);
|
||||||
|
$this->info(sprintf('Upgraded liabilities for 5.8.0 in %s seconds.', $end));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
private function isExecuted(): bool
|
||||||
|
{
|
||||||
|
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
||||||
|
if (null !== $configVar) {
|
||||||
|
return (bool)$configVar->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
$service = app(CreditRecalculateService::class);
|
||||||
|
$service->setAccount($account);
|
||||||
|
$service->recalculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 ("%s")', $account->id, $account->name));
|
||||||
|
|
||||||
|
$direction = $repository->getMetaValue($account, 'liability_direction');
|
||||||
|
if ('debit' === $direction && $this->hasBadOpening($account)) {
|
||||||
|
$this->deleteCreditTransaction($account);
|
||||||
|
$this->line(sprintf('Fixed correct bad opening for liability #%d ("%s")', $account->id, $account->name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $account
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function deleteCreditTransaction(Account $account): void
|
||||||
|
{
|
||||||
|
$liabilityType = TransactionType::whereType(TransactionType::LIABILITY_CREDIT)->first();
|
||||||
|
$liabilityJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->where('transactions.account_id', $account->id)
|
||||||
|
->where('transaction_journals.transaction_type_id', $liabilityType->id)
|
||||||
|
->first(['transaction_journals.*']);
|
||||||
|
if (null !== $liabilityJournal) {
|
||||||
|
$group = $liabilityJournal->transactionGroup;
|
||||||
|
$service = new TransactionGroupDestroyService();
|
||||||
|
$service->destroy($group);
|
||||||
|
Log::debug(sprintf('Deleted liability credit group #%d', $group->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function markAsExecuted(): void
|
||||||
|
{
|
||||||
|
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Account $account
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function hasBadOpening(Account $account): bool
|
||||||
|
{
|
||||||
|
$openingBalanceType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first();
|
||||||
|
$liabilityType = TransactionType::whereType(TransactionType::LIABILITY_CREDIT)->first();
|
||||||
|
$openingJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->where('transactions.account_id', $account->id)
|
||||||
|
->where('transaction_journals.transaction_type_id', $openingBalanceType->id)
|
||||||
|
->first(['transaction_journals.*']);
|
||||||
|
if (null === $openingJournal) {
|
||||||
|
Log::debug('Account has no opening balance and can be skipped.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$liabilityJournal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
|
->where('transactions.account_id', $account->id)
|
||||||
|
->where('transaction_journals.transaction_type_id', $liabilityType->id)
|
||||||
|
->first(['transaction_journals.*']);
|
||||||
|
if (null === $liabilityJournal) {
|
||||||
|
Log::debug('Account has no liability credit and can be skipped.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$openingJournal->date->isSameDay($liabilityJournal->date)) {
|
||||||
|
Log::debug('Account has opening/credit not on the same day.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -39,8 +39,7 @@ use Log;
|
|||||||
*/
|
*/
|
||||||
class AccountTasker implements AccountTaskerInterface
|
class AccountTasker implements AccountTaskerInterface
|
||||||
{
|
{
|
||||||
/** @var User */
|
private User $user;
|
||||||
private $user;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
|
@ -95,8 +95,8 @@ class AccountUpdateService
|
|||||||
// update opening balance.
|
// update opening balance.
|
||||||
$this->updateOpeningBalance($account, $data);
|
$this->updateOpeningBalance($account, $data);
|
||||||
|
|
||||||
// update opening balance.
|
// Since 5.8.0, delete liability credit transactions, if any:
|
||||||
$this->updateCreditLiability($account, $data);
|
$this->deleteCreditTransaction($account);
|
||||||
|
|
||||||
// update note:
|
// update note:
|
||||||
if (array_key_exists('notes', $data) && null !== $data['notes']) {
|
if (array_key_exists('notes', $data) && null !== $data['notes']) {
|
||||||
@ -305,6 +305,10 @@ class AccountUpdateService
|
|||||||
$this->deleteOBGroup($account);
|
$this->deleteOBGroup($account);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// if cannot have an opening balance, delete it.
|
||||||
|
if(!in_array($type->type, $this->canHaveOpeningBalance, true)) {
|
||||||
|
$this->deleteOBGroup($account);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,6 +316,7 @@ class AccountUpdateService
|
|||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
* @deprecated In Firefly III v5.8.0 and onwards, credit transactions for liabilities are no longer created.
|
||||||
*/
|
*/
|
||||||
private function updateCreditLiability(Account $account, array $data): void
|
private function updateCreditLiability(Account $account, array $data): void
|
||||||
{
|
{
|
||||||
|
@ -875,7 +875,7 @@ return [
|
|||||||
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
|
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
|
||||||
],
|
],
|
||||||
'can_have_virtual_amounts' => [AccountType::ASSET],
|
'can_have_virtual_amounts' => [AccountType::ASSET],
|
||||||
'can_have_opening_balance' => [AccountType::ASSET],
|
'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||||
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||||
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
|
||||||
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
|
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],
|
||||||
|
Loading…
Reference in New Issue
Block a user