mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Refactor upgrade and verify commands.
This commit is contained in:
parent
a89be86ca4
commit
1b0be2a47e
81
app/Console/Commands/Correction/CorrectDatabase.php
Normal file
81
app/Console/Commands/Correction/CorrectDatabase.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* CorrectDatabase.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
|
||||
use Artisan;
|
||||
use Illuminate\Console\Command;
|
||||
use Schema;
|
||||
|
||||
/**
|
||||
* Class CorrectDatabase
|
||||
*/
|
||||
class CorrectDatabase extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Will correct the integrity of your database, of necessary.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:correct-database';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('users')) {
|
||||
return 1;
|
||||
}
|
||||
$commands = [
|
||||
'firefly-iii:fix-piggies',
|
||||
'firefly-iii:create-link-types',
|
||||
'firefly-iii:create-access-tokens',
|
||||
'firefly-iii:remove-bills',
|
||||
'firefly-iii:enable-currencies',
|
||||
'firefly-iii:fix-transfer-budgets',
|
||||
'firefly-iii:fix-uneven-amount',
|
||||
'firefly-iii:delete-zero-amount',
|
||||
'firefly-iii:delete-orphaned-transactions',
|
||||
'firefly-iii:delete-empty-journals',
|
||||
'firefly-iii:delete-empty-groups',
|
||||
'firefly-iii:fix-account-types',
|
||||
];
|
||||
foreach ($commands as $command) {
|
||||
$this->line(sprintf('Now executing %s', $command));
|
||||
Artisan::call($command);
|
||||
$result = Artisan::output();
|
||||
echo $result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
57
app/Console/Commands/Correction/CorrectionSkeleton.php.stub
Normal file
57
app/Console/Commands/Correction/CorrectionSkeleton.php.stub
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* VerifySkeleton.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class CorrectionSkeleton
|
||||
*/
|
||||
class CorrectionSkeleton extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'DESCRIPTION HERE';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:CORR_COMMAND';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
//
|
||||
$this->warn('Congrats, you found the skeleton command. Boo!');
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
72
app/Console/Commands/Correction/CreateAccessTokens.php
Normal file
72
app/Console/Commands/Correction/CreateAccessTokens.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateAccessTokens.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class CreateAccessTokens
|
||||
*/
|
||||
class CreateAccessTokens extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Creates user access tokens.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:create-access-tokens';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$count = 0;
|
||||
$users = User::get();
|
||||
/** @var User $user */
|
||||
foreach ($users as $user) {
|
||||
$pref = app('preferences')->getForUser($user, 'access_token', null);
|
||||
if (null === $pref) {
|
||||
$token = $user->generateAccessToken();
|
||||
app('preferences')->setForUser($user, 'access_token', $token);
|
||||
$this->line(sprintf('Generated access token for user %s', $user->email));
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All access tokens OK!');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
79
app/Console/Commands/Correction/CreateLinkTypes.php
Normal file
79
app/Console/Commands/Correction/CreateLinkTypes.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* CreateLinkTypes.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\LinkType;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class CreateLinkTypes. Created all link types in case a migration hasn't fired.
|
||||
*/
|
||||
class CreateLinkTypes extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Creates all link types.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:create-link-types';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
//
|
||||
$count = 0;
|
||||
$set = [
|
||||
'Related' => ['relates to', 'relates to'],
|
||||
'Refund' => ['(partially) refunds', 'is (partially) refunded by'],
|
||||
'Paid' => ['(partially) pays for', 'is (partially) paid for by'],
|
||||
'Reimbursement' => ['(partially) reimburses', 'is (partially) reimbursed by'],
|
||||
];
|
||||
foreach ($set as $name => $values) {
|
||||
$link = LinkType::where('name', $name)->where('outward', $values[0])->where('inward', $values[1])->first();
|
||||
if (null === $link) {
|
||||
$link = new LinkType;
|
||||
$link->name = $name;
|
||||
$link->outward = $values[0];
|
||||
$link->inward = $values[1];
|
||||
++$count;
|
||||
$this->line(sprintf('Created missing link type "%s"', $name));
|
||||
}
|
||||
$link->editable = false;
|
||||
$link->save();
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All link types OK!');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
68
app/Console/Commands/Correction/DeleteEmptyGroups.php
Normal file
68
app/Console/Commands/Correction/DeleteEmptyGroups.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteEmptyGroups.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class DeleteEmptyGroups
|
||||
*/
|
||||
class DeleteEmptyGroups extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Delete empty transaction groups.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:delete-empty-groups';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @throws Exception;
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
//
|
||||
$groups = array_unique(TransactionJournal::get(['transaction_group_id'])->pluck('transaction_group_id')->toArray());
|
||||
$count = TransactionGroup::whereNull('deleted_at')->whereNotIn('id', $groups)->count();
|
||||
if (0 === $count) {
|
||||
$this->info('No empty groups.');
|
||||
}
|
||||
if ($count > 0) {
|
||||
$this->info(sprintf('Deleted %d empty groups.', $count));
|
||||
TransactionGroup::whereNull('deleted_at')->whereNotIn('id', $groups)->delete();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
115
app/Console/Commands/Correction/DeleteEmptyJournals.php
Normal file
115
app/Console/Commands/Correction/DeleteEmptyJournals.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteEmptyJournals.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class DeleteEmptyJournals
|
||||
*/
|
||||
class DeleteEmptyJournals extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Delete empty and uneven transaction journals.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:delete-empty-journals';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->deleteUnevenJournals();
|
||||
$this->deleteEmptyJournals();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function deleteEmptyJournals(): void
|
||||
{
|
||||
|
||||
$count = 0;
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
->get(['transaction_journals.id']);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
TransactionJournal::find($entry->id)->delete();
|
||||
$this->info(sprintf('Deleted empty transaction #%d', $entry->id));
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No empty transactions.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete transactions and their journals if they have an uneven number of transactions.
|
||||
*/
|
||||
private function deleteUnevenJournals(): void
|
||||
{
|
||||
/**
|
||||
* select count(transactions.transaction_journal_id) as the_count, transactions.transaction_journal_id from transactions
|
||||
*
|
||||
* where transactions.deleted_at is null
|
||||
*
|
||||
* group by transactions.transaction_journal_id
|
||||
* having the_count in ()
|
||||
*/
|
||||
|
||||
$set = Transaction
|
||||
::whereNull('deleted_at')
|
||||
->having('the_count', '!=', '2')
|
||||
->groupBy('transactions.transaction_journal_id')
|
||||
->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']);
|
||||
$total = 0;
|
||||
foreach ($set as $row) {
|
||||
$count = (int)$row->the_count;
|
||||
if (1 === $count % 2) {
|
||||
// uneven number, delete journal and transactions:
|
||||
TransactionJournal::find((int)$row->transaction_journal_id)->delete();
|
||||
Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete();
|
||||
$this->info(sprintf('Deleted transaction #%d because it had an uneven number of transactions.', $row->transaction_journal_id));
|
||||
$total++;
|
||||
}
|
||||
}
|
||||
if (0 === $total) {
|
||||
$this->info('No uneven transactions.');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
126
app/Console/Commands/Correction/DeleteOrphanedTransactions.php
Normal file
126
app/Console/Commands/Correction/DeleteOrphanedTransactions.php
Normal file
@ -0,0 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteOrphanedTransactions.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use Exception;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Deletes transactions where the journal has been deleted.
|
||||
*/
|
||||
class DeleteOrphanedTransactions extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Deletes orphaned transactions.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:delete-orphaned-transactions';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->deleteOrphanedTransactions();
|
||||
$this->deleteFromOrphanedAccounts();
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function deleteFromOrphanedAccounts(): void
|
||||
{
|
||||
$set
|
||||
= Transaction
|
||||
::leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
|
||||
->whereNotNull('accounts.deleted_at')
|
||||
->get(['transactions.*']);
|
||||
$count = 0;
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
// delete journals
|
||||
$journal = TransactionJournal::find((int)$transaction->transaction_journal_id);
|
||||
if ($journal) {
|
||||
$journal->delete();
|
||||
}
|
||||
Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete();
|
||||
$this->line(
|
||||
sprintf('Deleted transaction #%d because account #%d was already deleted.', $transaction->transaction_journal_id, $transaction->account_id)
|
||||
);
|
||||
$count++;
|
||||
}
|
||||
if(0===$count) {
|
||||
$this->info('No orphaned accounts.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
private function deleteOrphanedTransactions(): void
|
||||
{
|
||||
$count = 0;
|
||||
$set = Transaction
|
||||
::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNotNull('transaction_journals.deleted_at')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNotNull('transactions.id')
|
||||
->get(
|
||||
[
|
||||
'transaction_journals.id as journal_id',
|
||||
'transactions.id as transaction_id',
|
||||
]
|
||||
);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$transaction = Transaction::find((int)$entry->transaction_id);
|
||||
$transaction->delete();
|
||||
$this->info(
|
||||
sprintf(
|
||||
'Transaction #%d (part of deleted journal #%d) has been deleted as well.',
|
||||
$entry->transaction_id,
|
||||
$entry->journal_id
|
||||
)
|
||||
);
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No orphaned transactions.');
|
||||
}
|
||||
}
|
||||
}
|
71
app/Console/Commands/Correction/DeleteZeroAmount.php
Normal file
71
app/Console/Commands/Correction/DeleteZeroAmount.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* DeleteZeroAmount.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class DeleteZeroAmount
|
||||
*/
|
||||
class DeleteZeroAmount extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Delete transactions with zero amount.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:delete-zero-amount';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* @throws Exception
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$set = Transaction::where('amount', 0)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
|
||||
$set = array_unique($set);
|
||||
/** @var Collection $journals */
|
||||
$journals = TransactionJournal::whereIn('id', $set)->get();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$this->info(sprintf('Deleted transaction #%d because the amount is zero (0.00).', $journal->id));
|
||||
$journal->delete();
|
||||
Transaction::where('transaction_journal_id', $journal->id)->delete();
|
||||
}
|
||||
if (0 === $journals->count()) {
|
||||
$this->info('No zero-amount transactions.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
96
app/Console/Commands/Correction/EnableCurrencies.php
Normal file
96
app/Console/Commands/Correction/EnableCurrencies.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* EnableCurrencies.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class EnableCurrencies
|
||||
*/
|
||||
class EnableCurrencies extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Enables all currencies in use.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:enable-currencies';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$found = [];
|
||||
// get all meta entries
|
||||
/** @var Collection $meta */
|
||||
$meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']);
|
||||
foreach ($meta as $entry) {
|
||||
$found[] = (int)$entry->data;
|
||||
}
|
||||
|
||||
// get all from journals:
|
||||
/** @var Collection $journals */
|
||||
$journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($journals as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
// get all from transactions
|
||||
/** @var Collection $transactions */
|
||||
$transactions = Transaction::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($transactions as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
// get all from budget limits
|
||||
/** @var Collection $limits */
|
||||
$limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($limits as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
$found = array_unique($found);
|
||||
$this->info(sprintf('%d different currencies are currently in use.', count($found)));
|
||||
$disabled = TransactionCurrency::whereIn('id', $found)->where('enabled', false)->count();
|
||||
if ($disabled > 0) {
|
||||
$this->info(sprintf('%d were still disabled. This has been corrected.', $disabled));
|
||||
}
|
||||
TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
113
app/Console/Commands/Correction/FixAccountTypes.php
Normal file
113
app/Console/Commands/Correction/FixAccountTypes.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* FixAccountTypes.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class FixAccountTypes
|
||||
*/
|
||||
class FixAccountTypes extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Make sure all journals have the correct from/to account types.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:fix-account-types';
|
||||
/** @var array */
|
||||
private $expected;
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->expected = config('firefly.source_dests');
|
||||
$journals = TransactionJournal::get();
|
||||
foreach ($journals as $journal) {
|
||||
$this->inspectJournal($journal);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function getDestinationAccount(TransactionJournal $journal): Account
|
||||
{
|
||||
return $journal->transactions()->where('amount', '>', 0)->first()->account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
private function getSourceAccount(TransactionJournal $journal): Account
|
||||
{
|
||||
return $journal->transactions()->where('amount', '<', 0)->first()->account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
private function inspectJournal(TransactionJournal $journal): void
|
||||
{
|
||||
$count = $journal->transactions()->count();
|
||||
if (2 !== $count) {
|
||||
$this->info(sprintf('Cannot inspect journal #%d because it does not have 2 transactions, but %d', $journal->id, $count));
|
||||
|
||||
return;
|
||||
}
|
||||
$type = $journal->transactionType->type;
|
||||
$sourceAccount = $this->getSourceAccount($journal);
|
||||
$sourceAccountType = $sourceAccount->accountType->type;
|
||||
$destinationAccount = $this->getDestinationAccount($journal);
|
||||
$destinationAccountType = $destinationAccount->accountType->type;
|
||||
if (!isset($this->expected[$type])) {
|
||||
$this->info(sprintf('No source/destination info for transaction type %s.', $type));
|
||||
|
||||
return;
|
||||
}
|
||||
if (!isset($this->expected[$type][$sourceAccountType])) {
|
||||
$this->info(sprintf('The source of %s #%d cannot be of type "%s".', $type, $journal->id, $sourceAccountType));
|
||||
$this->info(sprintf('The destination of %s #%d probably cannot be of type "%s".', $type, $journal->id, $destinationAccountType));
|
||||
|
||||
// TODO think of a way to fix the problem.
|
||||
return;
|
||||
}
|
||||
$expectedTypes = $this->expected[$type][$sourceAccountType];
|
||||
if (!\in_array($destinationAccountType, $expectedTypes, true)) {
|
||||
$this->info(sprintf('The destination of %s #%d cannot be of type "%s".', $type, $journal->id, $destinationAccountType));
|
||||
// TODO think of a way to fix the problem.
|
||||
}
|
||||
}
|
||||
}
|
82
app/Console/Commands/Correction/FixPiggies.php
Normal file
82
app/Console/Commands/Correction/FixPiggies.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* FixPiggies.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Report (and fix) piggy banks. Make sure there are only transfers linked to piggy bank events.
|
||||
*
|
||||
* Class FixPiggies
|
||||
*/
|
||||
class FixPiggies extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fixes common issues with piggy banks.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:fix-piggies';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
|
||||
$set->each(
|
||||
function (PiggyBankEvent $event) {
|
||||
if (null === $event->transaction_journal_id) {
|
||||
return true;
|
||||
}
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->transactionJournal()->first();
|
||||
if (null === $journal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$type = $journal->transactionType->type;
|
||||
if (TransactionType::TRANSFER !== $type) {
|
||||
$event->transaction_journal_id = null;
|
||||
$event->save();
|
||||
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
$this->line(sprintf('Verified the content of %d piggy bank events.', $set->count()));
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
99
app/Console/Commands/Correction/FixUnevenAmount.php
Normal file
99
app/Console/Commands/Correction/FixUnevenAmount.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* FixUnevenAmount.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use DB;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Console\Command;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class FixUnevenAmount
|
||||
*/
|
||||
class FixUnevenAmount extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fix journals with uneven amounts.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:fix-uneven-amount';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
|
||||
$count = 0;
|
||||
// get invalid journals
|
||||
$journals = DB::table('transactions')
|
||||
->groupBy('transaction_journal_id')
|
||||
->whereNull('deleted_at')
|
||||
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($journals as $entry) {
|
||||
if (0 !== bccomp((string)$entry->the_sum, '0')) {
|
||||
$this->fixJournal((int)$entry->transaction_journal_id);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('Amount integrity OK!');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $param
|
||||
*/
|
||||
private function fixJournal(int $param): void
|
||||
{
|
||||
// one of the transactions is bad.
|
||||
$journal = TransactionJournal::find($param);
|
||||
if (!$journal) {
|
||||
return;
|
||||
}
|
||||
/** @var Transaction $source */
|
||||
$source = $journal->transactions()->where('amount', '<', 0)->first();
|
||||
$amount = bcmul('-1', (string)$source->amount);
|
||||
|
||||
// fix amount of destination:
|
||||
/** @var Transaction $destination */
|
||||
$destination = $journal->transactions()->where('amount', '>', 0)->first();
|
||||
$destination->amount = $amount;
|
||||
$destination->save();
|
||||
|
||||
$this->line(sprintf('Corrected amount in transaction #%d', $param));
|
||||
|
||||
}
|
||||
}
|
71
app/Console/Commands/Correction/RemoveBills.php
Normal file
71
app/Console/Commands/Correction/RemoveBills.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* RemoveBills.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class RemoveBills
|
||||
*/
|
||||
class RemoveBills extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Remove bills from transactions that shouldn\'t have one.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:remove-bills';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
/** @var TransactionType $withdrawal */
|
||||
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journals = TransactionJournal::whereNotNull('bill_id')->where('transaction_type_id', '!=', $withdrawal->id)->get();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$this->line(sprintf('Transaction journal #%d should not be linked to bill #%d.', $journal->id, $journal->bill_id));
|
||||
$journal->bill_id = null;
|
||||
$journal->save();
|
||||
}
|
||||
if (0 === $journals->count()) {
|
||||
$this->info('All transactions have correct bill information.');
|
||||
}
|
||||
if ($journals->count() > 0) {
|
||||
$this->info('Fixed all transactions so they have correct bill information.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
71
app/Console/Commands/Correction/TransferBudgets.php
Normal file
71
app/Console/Commands/Correction/TransferBudgets.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* TransferBudgets.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Correction;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class TransferBudgets
|
||||
*/
|
||||
class TransferBudgets extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Removes budgets from transfers.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:fix-transfer-budgets';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$set = TransactionJournal::distinct()
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||
->whereNotIn('transaction_types.type', [TransactionType::WITHDRAWAL])
|
||||
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*']);
|
||||
$count = 0;
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->info(sprintf('Transaction #%d is a %s, so has no longer a budget.', $entry->id, $entry->transactionType->type));
|
||||
$entry->budgets()->sync([]);
|
||||
$count++;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No invalid budget/journal entries.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
191
app/Console/Commands/Integrity/ReportEmptyObjects.php
Normal file
191
app/Console/Commands/Integrity/ReportEmptyObjects.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
* ReportEmptyObjects.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Console\Command;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class ReportEmptyObjects
|
||||
*/
|
||||
class ReportEmptyObjects extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Reports on empty database objects.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:report-empty-objects';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->reportEmptyBudgets();
|
||||
$this->reportEmptyCategories();
|
||||
$this->reportEmptyTags();
|
||||
$this->reportAccounts();
|
||||
$this->reportBudgetLimits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Reports on budgets with no budget limits (which makes them pointless).
|
||||
*/
|
||||
private function reportBudgetLimits(): void
|
||||
{
|
||||
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.encrypted', 'budgets.user_id', 'users.email'])
|
||||
->whereNull('budget_limits.id')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'budgets.encrypted', 'users.email']);
|
||||
|
||||
/** @var Budget $entry */
|
||||
foreach ($set as $entry) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$entry->name
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports on accounts with no transactions.
|
||||
*/
|
||||
private function reportAccounts(): void
|
||||
{
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
|
||||
->whereNull('transactions.account_id')
|
||||
->get(
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
|
||||
);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$name = $entry->name;
|
||||
$line = 'User #%d (%s) has account #%d ("%s") which has no transactions.';
|
||||
$line = sprintf($line, $entry->user_id, $entry->email, $entry->id, $name);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on budgets with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyBudgets(): void
|
||||
{
|
||||
$set = Budget::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('budget_transaction_journal.budget_id')
|
||||
->whereNull('budgets.deleted_at')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has budget #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on categories with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyCategories(): void
|
||||
{
|
||||
$set = Category::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||
->leftJoin('users', 'categories.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('category_transaction_journal.category_id')
|
||||
->whereNull('categories.deleted_at')
|
||||
->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has category #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function reportEmptyTags(): void
|
||||
{
|
||||
$set = Tag::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')
|
||||
->leftJoin('users', 'tags.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('tag_transaction_journal.tag_id')
|
||||
->whereNull('tags.deleted_at')
|
||||
->get(['tags.id', 'tags.tag', 'tags.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->tag;
|
||||
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has tag #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
108
app/Console/Commands/Integrity/ReportIntegrity.php
Normal file
108
app/Console/Commands/Integrity/ReportIntegrity.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* ReportIntegrity.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Schema;
|
||||
use Artisan;
|
||||
|
||||
/**
|
||||
* Class ReportIntegrity
|
||||
*/
|
||||
class ReportIntegrity extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Will report on the integrity of your database.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:report-integrity';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('users')) {
|
||||
return 1;
|
||||
}
|
||||
$commands = [
|
||||
'firefly-iii:report-empty-objects',
|
||||
'firefly-iii:report-sum',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
// 'firefly-iii:',
|
||||
];
|
||||
foreach ($commands as $command) {
|
||||
$this->line(sprintf('Now executing %s', $command));
|
||||
Artisan::call($command);
|
||||
$result = Artisan::output();
|
||||
echo $result;
|
||||
}
|
||||
|
||||
// $this->reportEmptyBudgets();
|
||||
// $this->reportEmptyCategories();
|
||||
// $this->reportObject('tag');
|
||||
// $this->reportAccounts();
|
||||
// $this->reportBudgetLimits();
|
||||
// $this->reportSum();
|
||||
// $this->reportJournals();
|
||||
// $this->reportTransactions();
|
||||
// $this->reportDeletedAccounts();
|
||||
// $this->reportNoTransactions();
|
||||
// $this->reportTransfersBudgets();
|
||||
// $this->reportIncorrectJournals();
|
||||
// $this->repairPiggyBanks();
|
||||
// $this->createLinkTypes();
|
||||
// $this->createAccessTokens();
|
||||
// $this->fixDoubleAmounts(); // is a report function!
|
||||
// $this->fixBadMeta();
|
||||
// $this->removeBills();
|
||||
// $this->enableCurrencies();
|
||||
// $this->reportZeroAmount();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
56
app/Console/Commands/Integrity/ReportSkeleton.php.stub
Normal file
56
app/Console/Commands/Integrity/ReportSkeleton.php.stub
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* VerifySkeleton.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class ReportSkeleton
|
||||
*/
|
||||
class ReportSkeleton extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'DESCRIPTION HERE';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:INT_COMMAND';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
//
|
||||
$this->warn('Congrats, you found the skeleton command. Boo!');
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
78
app/Console/Commands/Integrity/ReportSum.php
Normal file
78
app/Console/Commands/Integrity/ReportSum.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* ReportSum.php
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands\Integrity;
|
||||
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
/**
|
||||
* Class ReportSkeleton
|
||||
*/
|
||||
class ReportSum extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Report on the total sum of transactions. Must be 0.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:report-sum';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
$this->reportSum();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reports for each user when the sum of their transactions is not zero.
|
||||
*/
|
||||
private function reportSum(): void
|
||||
{
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
|
||||
/** @var User $user */
|
||||
foreach ($userRepository->all() as $user) {
|
||||
$sum = (string)$user->transactions()->sum('amount');
|
||||
if (0 !== bccomp($sum, '0')) {
|
||||
$this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!');
|
||||
}
|
||||
if (0 === bccomp($sum, '0')) {
|
||||
$this->info(sprintf('Amount integrity OK for user #%d', $user->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -206,6 +206,7 @@ class JournalCurrencies extends Command
|
||||
$accountRepos->setUser($transaction->account->user);
|
||||
$currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id'));
|
||||
$journal = $transaction->transactionJournal;
|
||||
$currencyCode = $journal->transactionCurrency->code ?? '(nothing)';
|
||||
|
||||
if (null === $currency) {
|
||||
return;
|
||||
@ -218,7 +219,7 @@ class JournalCurrencies extends Command
|
||||
$journal->id,
|
||||
$journal->description,
|
||||
$currency->code,
|
||||
$journal->transactionCurrency->code
|
||||
$currencyCode
|
||||
)
|
||||
);
|
||||
$journal->transaction_currency_id = $currency->id;
|
||||
|
@ -24,6 +24,7 @@ namespace FireflyIII\Console\Commands\Upgrade;
|
||||
use Exception;
|
||||
use FireflyIII\Factory\TransactionJournalFactory;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
|
||||
@ -93,7 +94,8 @@ class MigrateToGroups extends Command
|
||||
}
|
||||
|
||||
Log::debug('---- start group migration ----');
|
||||
$this->makeGroups();
|
||||
$this->makeGroupsFromSplitJournals();
|
||||
$this->makeGroupsFromAll();
|
||||
Log::debug('---- end group migration ----');
|
||||
|
||||
$this->markAsMigrated();
|
||||
@ -101,6 +103,19 @@ class MigrateToGroups extends Command
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
private function giveGroup(TransactionJournal $journal): void
|
||||
{
|
||||
$group = new TransactionGroup;
|
||||
$group->title = null;
|
||||
$group->user_id = $journal->user_id;
|
||||
$group->save();
|
||||
$journal->transaction_group_id = $group->id;
|
||||
$journal->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
@ -114,12 +129,50 @@ class MigrateToGroups extends Command
|
||||
return false; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives all journals without a group a group.
|
||||
*/
|
||||
private function makeGroupsFromAll(): void
|
||||
{
|
||||
$orphanedJournals = $this->journalRepository->getJournalsWithoutGroup();
|
||||
if ($orphanedJournals->count() > 0) {
|
||||
Log::debug(sprintf('Going to convert %d transactions. Please hold..', $orphanedJournals->count()));
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($orphanedJournals as $journal) {
|
||||
$this->giveGroup($journal);
|
||||
}
|
||||
}
|
||||
if (0 === $orphanedJournals->count()) {
|
||||
$this->info('No need to convert transactions.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function makeGroupsFromSplitJournals(): void
|
||||
{
|
||||
$splitJournals = $this->journalRepository->getSplitJournals();
|
||||
|
||||
if ($splitJournals->count() > 0) {
|
||||
$this->info(sprintf('Going to convert %d split transaction(s). Please hold..', $splitJournals->count()));
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($splitJournals as $journal) {
|
||||
$this->makeMultiGroup($journal);
|
||||
}
|
||||
}
|
||||
if (0 === $splitJournals->count()) {
|
||||
$this->info('Found no split transactions. Nothing to do.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function makeGroup(TransactionJournal $journal): void
|
||||
private function makeMultiGroup(TransactionJournal $journal): void
|
||||
{
|
||||
// double check transaction count.
|
||||
if ($journal->transactions->count() <= 2) {
|
||||
@ -204,33 +257,13 @@ class MigrateToGroups extends Command
|
||||
Log::debug('Done calling transaction journal factory');
|
||||
|
||||
// delete the old transaction journal.
|
||||
//$this->service->destroy($journal);
|
||||
$this->service->destroy($journal);
|
||||
|
||||
// report on result:
|
||||
Log::debug(sprintf('Migrated journal #%d into these journals: %s', $journal->id, implode(', ', $result->pluck('id')->toArray())));
|
||||
$this->line(sprintf('Migrated journal #%d into these journals: %s', $journal->id, implode(', ', $result->pluck('id')->toArray())));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
private function makeGroups(): void
|
||||
{
|
||||
$splitJournals = $this->journalRepository->getSplitJournals();
|
||||
|
||||
if ($splitJournals->count() > 0) {
|
||||
$this->info(sprintf('Going to un-split %d transaction(s). This could take some time.', $splitJournals->count()));
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($splitJournals as $journal) {
|
||||
$this->makeGroup($journal);
|
||||
}
|
||||
}
|
||||
if (0 === $splitJournals->count()) {
|
||||
$this->info('Found no split journals. Nothing to do.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@ -34,7 +34,7 @@ class UpgradeDatabase extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Executes all upgrade commands.';
|
||||
protected $description = 'Upgrades the database to the latest version.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
|
@ -40,7 +40,7 @@ class UpgradeSkeleton extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly-iii:SKELETON {--F|force : Force the execution of this command.}';
|
||||
protected $signature = 'firefly-iii:UPGRSKELETON {--F|force : Force the execution of this command.}';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
@ -1,714 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* VerifyDatabase.php
|
||||
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @noinspection PhpDynamicAsStaticMethodCallInspection */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use DB;
|
||||
use Exception;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Schema;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class VerifyDatabase.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
class VerifyDatabase extends Command
|
||||
{
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Will verify your database.';
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'firefly:verify';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): int
|
||||
{
|
||||
// if table does not exist, return false
|
||||
if (!Schema::hasTable('users')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$this->reportEmptyBudgets();
|
||||
$this->reportEmptyCategories();
|
||||
$this->reportObject('tag');
|
||||
$this->reportAccounts();
|
||||
$this->reportBudgetLimits();
|
||||
$this->reportSum();
|
||||
$this->reportJournals();
|
||||
$this->reportTransactions();
|
||||
$this->reportDeletedAccounts();
|
||||
$this->reportNoTransactions();
|
||||
$this->reportTransfersBudgets();
|
||||
$this->reportIncorrectJournals();
|
||||
$this->repairPiggyBanks();
|
||||
$this->createLinkTypes();
|
||||
$this->createAccessTokens();
|
||||
$this->fixDoubleAmounts();
|
||||
$this->fixBadMeta();
|
||||
$this->removeBills();
|
||||
$this->enableCurrencies();
|
||||
$this->reportZeroAmount();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create user access tokens, if not present already.
|
||||
*/
|
||||
private function createAccessTokens(): void
|
||||
{
|
||||
$count = 0;
|
||||
$users = User::get();
|
||||
/** @var User $user */
|
||||
foreach ($users as $user) {
|
||||
$pref = app('preferences')->getForUser($user, 'access_token', null);
|
||||
if (null === $pref) {
|
||||
$token = $user->generateAccessToken();
|
||||
app('preferences')->setForUser($user, 'access_token', $token);
|
||||
$this->line(sprintf('Generated access token for user %s', $user->email));
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All access tokens OK!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default link types if necessary.
|
||||
*/
|
||||
private function createLinkTypes(): void
|
||||
{
|
||||
$count = 0;
|
||||
$set = [
|
||||
'Related' => ['relates to', 'relates to'],
|
||||
'Refund' => ['(partially) refunds', 'is (partially) refunded by'],
|
||||
'Paid' => ['(partially) pays for', 'is (partially) paid for by'],
|
||||
'Reimbursement' => ['(partially) reimburses', 'is (partially) reimbursed by'],
|
||||
];
|
||||
foreach ($set as $name => $values) {
|
||||
$link = LinkType::where('name', $name)->where('outward', $values[0])->where('inward', $values[1])->first();
|
||||
if (null === $link) {
|
||||
$link = new LinkType;
|
||||
$link->name = $name;
|
||||
$link->outward = $values[0];
|
||||
$link->inward = $values[1];
|
||||
++$count;
|
||||
}
|
||||
$link->editable = false;
|
||||
$link->save();
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All link types OK!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Will make sure that all currencies in use are actually enabled.
|
||||
*/
|
||||
private function enableCurrencies(): void
|
||||
{
|
||||
$found = [];
|
||||
// get all meta entries
|
||||
/** @var Collection $meta */
|
||||
$meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']);
|
||||
foreach ($meta as $entry) {
|
||||
$found[] = (int)$entry->data;
|
||||
}
|
||||
|
||||
// get all from journals:
|
||||
/** @var Collection $journals */
|
||||
$journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($journals as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
// get all from transactions
|
||||
/** @var Collection $transactions */
|
||||
$transactions = Transaction::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($transactions as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
// get all from budget limits
|
||||
/** @var Collection $limits */
|
||||
$limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']);
|
||||
foreach ($limits as $entry) {
|
||||
$found[] = (int)$entry->transaction_currency_id;
|
||||
}
|
||||
|
||||
$found = array_unique($found);
|
||||
TransactionCurrency::whereIn('id', $found)->update(['enabled' => true]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the situation where the matching transactions of a journal somehow have non-matching categories or budgets.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
private function fixBadMeta(): void
|
||||
{
|
||||
// categories
|
||||
$set = Transaction
|
||||
::leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->get(['transactions.id', 'transaction_journal_id', 'identifier', 'category_transaction.category_id', 'category_transaction.id as ct_id']);
|
||||
$results = [];
|
||||
foreach ($set as $obj) {
|
||||
$key = $obj->transaction_journal_id . '-' . $obj->identifier;
|
||||
$category = (int)$obj->category_id;
|
||||
|
||||
// value exists and is not category:
|
||||
if (isset($results[$key]) && $results[$key] !== $category) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d referred to the wrong category. Was category #%d but is fixed to be category #%d.', $obj->transaction_journal_id,
|
||||
$category, $results[$key]
|
||||
)
|
||||
);
|
||||
DB::table('category_transaction')->where('id', $obj->ct_id)->update(['category_id' => $results[$key]]);
|
||||
|
||||
}
|
||||
|
||||
// value does not exist:
|
||||
if ($category > 0 && !isset($results[$key])) {
|
||||
$results[$key] = $category;
|
||||
}
|
||||
}
|
||||
|
||||
// budgets
|
||||
$set = Transaction
|
||||
::leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id')
|
||||
->whereNull('transactions.deleted_at')
|
||||
->get(['transactions.id', 'transaction_journal_id', 'identifier', 'budget_transaction.budget_id', 'budget_transaction.id as ct_id']);
|
||||
$results = [];
|
||||
foreach ($set as $obj) {
|
||||
$key = $obj->transaction_journal_id . '-' . $obj->identifier;
|
||||
$budget = (int)$obj->budget_id;
|
||||
|
||||
// value exists and is not budget:
|
||||
if (isset($results[$key]) && $results[$key] !== $budget) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d referred to the wrong budget. Was budget #%d but is fixed to be budget #%d.', $obj->transaction_journal_id, $budget,
|
||||
$results[$key]
|
||||
)
|
||||
);
|
||||
DB::table('budget_transaction')->where('id', $obj->ct_id)->update(['budget_id' => $results[$key]]);
|
||||
|
||||
}
|
||||
|
||||
// value does not exist:
|
||||
if ($budget > 0 && !isset($results[$key])) {
|
||||
$results[$key] = $budget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes sure amounts are stored correctly.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
private function fixDoubleAmounts(): void
|
||||
{
|
||||
$count = 0;
|
||||
// get invalid journals
|
||||
$errored = [];
|
||||
$journals = DB::table('transactions')
|
||||
->groupBy('transaction_journal_id')
|
||||
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($journals as $entry) {
|
||||
if (0 !== bccomp((string)$entry->the_sum, '0')) {
|
||||
$errored[] = $entry->transaction_journal_id;
|
||||
}
|
||||
}
|
||||
foreach ($errored as $journalId) {
|
||||
// select and update:
|
||||
$res = Transaction::whereNull('deleted_at')->where('transaction_journal_id', $journalId)->groupBy('amount')->get([DB::raw('MIN(id) as first_id')]);
|
||||
$ids = $res->pluck('first_id')->toArray();
|
||||
DB::table('transactions')->whereIn('id', $ids)->update(['amount' => DB::raw('amount * -1')]);
|
||||
++$count;
|
||||
// report about it
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = TransactionJournal::find($journalId);
|
||||
if (null === $journal) {
|
||||
continue;
|
||||
}
|
||||
if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d was stored incorrectly. One of your asset accounts may show the wrong balance. Please visit /transactions/show/%d to verify the opening balance.',
|
||||
$journalId, $journalId
|
||||
)
|
||||
);
|
||||
}
|
||||
if (TransactionType::OPENING_BALANCE !== $journal->transactionType->type) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d was stored incorrectly. Could be that the transaction shows the wrong amount. Please visit /transactions/show/%d to verify the opening balance.',
|
||||
$journalId, $journalId
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('Amount integrity OK!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes bills from journals that should not have bills.
|
||||
*/
|
||||
private function removeBills(): void
|
||||
{
|
||||
/** @var TransactionType $withdrawal */
|
||||
$withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first();
|
||||
$journals = TransactionJournal::whereNotNull('bill_id')
|
||||
->where('transaction_type_id', '!=', $withdrawal->id)->get();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$this->line(sprintf('Transaction journal #%d should not be linked to bill #%d.', $journal->id, $journal->bill_id));
|
||||
$journal->bill_id = null;
|
||||
$journal->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Eeport (and fix) piggy banks. Make sure there are only transfers linked to piggy bank events.
|
||||
*/
|
||||
private function repairPiggyBanks(): void
|
||||
{
|
||||
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
|
||||
$set->each(
|
||||
function (PiggyBankEvent $event) {
|
||||
if (null === $event->transaction_journal_id) {
|
||||
return true;
|
||||
}
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->transactionJournal()->first();
|
||||
if (null === $journal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$type = $journal->transactionType->type;
|
||||
if (TransactionType::TRANSFER !== $type) {
|
||||
$event->transaction_journal_id = null;
|
||||
$event->save();
|
||||
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports on accounts with no transactions.
|
||||
*/
|
||||
private function reportAccounts(): void
|
||||
{
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('users', 'accounts.user_id', '=', 'users.id')
|
||||
->groupBy(['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email'])
|
||||
->whereNull('transactions.account_id')
|
||||
->get(
|
||||
['accounts.id', 'accounts.encrypted', 'accounts.name', 'accounts.user_id', 'users.email']
|
||||
);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$name = $entry->name;
|
||||
$line = 'User #%d (%s) has account #%d ("%s") which has no transactions.';
|
||||
$line = sprintf($line, $entry->user_id, $entry->email, $entry->id, $name);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports on budgets with no budget limits (which makes them pointless).
|
||||
*/
|
||||
private function reportBudgetLimits(): void
|
||||
{
|
||||
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->groupBy(['budgets.id', 'budgets.name', 'budgets.encrypted', 'budgets.user_id', 'users.email'])
|
||||
->whereNull('budget_limits.id')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'budgets.encrypted', 'users.email']);
|
||||
|
||||
/** @var Budget $entry */
|
||||
foreach ($set as $entry) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has budget #%d ("%s") which has no budget limits.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$entry->name
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports on deleted accounts that still have not deleted transactions or journals attached to them.
|
||||
*/
|
||||
private function reportDeletedAccounts(): void
|
||||
{
|
||||
$set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->whereNotNull('accounts.deleted_at')
|
||||
->whereNotNull('transactions.id')
|
||||
->where(
|
||||
function (Builder $q) {
|
||||
$q->whereNull('transactions.deleted_at');
|
||||
$q->orWhereNull('transaction_journals.deleted_at');
|
||||
}
|
||||
)
|
||||
->get(
|
||||
['accounts.id as account_id', 'accounts.deleted_at as account_deleted_at', 'transactions.id as transaction_id',
|
||||
'transactions.deleted_at as transaction_deleted_at', 'transaction_journals.id as journal_id',
|
||||
'transaction_journals.deleted_at as journal_deleted_at',]
|
||||
);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$date = $entry->transaction_deleted_at ?? $entry->journal_deleted_at;
|
||||
$this->error(
|
||||
'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on budgets with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyBudgets(): void
|
||||
{
|
||||
$set = Budget::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('budget_transaction_journal.budget_id')
|
||||
->whereNull('budgets.deleted_at')
|
||||
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
|
||||
// also count the transactions:
|
||||
$countTransactions = DB::table('budget_transaction')->where('budget_id', $entry->id)->count();
|
||||
|
||||
if (0 === $countTransactions) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has budget #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on categories with no transactions or journals.
|
||||
*/
|
||||
private function reportEmptyCategories(): void
|
||||
{
|
||||
$set = Category::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||
->leftJoin('users', 'categories.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull('category_transaction_journal.category_id')
|
||||
->whereNull('categories.deleted_at')
|
||||
->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
|
||||
// also count the transactions:
|
||||
$countTransactions = DB::table('category_transaction')->where('category_id', $entry->id)->count();
|
||||
|
||||
if (0 === $countTransactions) {
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has category #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on journals with bad account types linked to them.
|
||||
*/
|
||||
private function reportIncorrectJournals(): void
|
||||
{
|
||||
$configuration = [
|
||||
// a withdrawal can not have revenue account:
|
||||
TransactionType::WITHDRAWAL => [AccountType::REVENUE],
|
||||
// deposit cannot have an expense account:
|
||||
TransactionType::DEPOSIT => [AccountType::EXPENSE],
|
||||
// transfer cannot have either:
|
||||
TransactionType::TRANSFER => [AccountType::EXPENSE, AccountType::REVENUE],
|
||||
];
|
||||
foreach ($configuration as $transactionType => $accountTypes) {
|
||||
$set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin('account_types', 'account_types.id', 'accounts.account_type_id')
|
||||
->leftJoin('users', 'users.id', '=', 'transaction_journals.user_id')
|
||||
->where('transaction_types.type', $transactionType)
|
||||
->whereIn('account_types.type', $accountTypes)
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->get(
|
||||
['transaction_journals.id', 'transaction_journals.user_id', 'users.email', 'account_types.type as a_type',
|
||||
'transaction_types.type',]
|
||||
);
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction journal #%d (user #%d, %s) is of type "%s" but ' .
|
||||
'is linked to a "%s". The transaction journal should be recreated.',
|
||||
$entry->id,
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$entry->type,
|
||||
$entry->a_type
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Any deleted transaction journals that have transactions that are NOT deleted:.
|
||||
*/
|
||||
private function reportJournals(): void
|
||||
{
|
||||
$count = 0;
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNotNull('transaction_journals.deleted_at')// USE THIS
|
||||
->whereNull('transactions.deleted_at')
|
||||
->whereNotNull('transactions.id')
|
||||
->get(
|
||||
[
|
||||
'transaction_journals.id as journal_id',
|
||||
'transaction_journals.description',
|
||||
'transaction_journals.deleted_at as journal_deleted',
|
||||
'transactions.id as transaction_id',
|
||||
'transactions.deleted_at as transaction_deleted_at',]
|
||||
);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
|
||||
);
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No orphaned transactions!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on journals without transactions.
|
||||
*/
|
||||
private function reportNoTransactions(): void
|
||||
{
|
||||
$count = 0;
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
->get(['transaction_journals.id']);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
|
||||
);
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No orphaned journals!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on things with no linked journals.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
private function reportObject(string $name): void
|
||||
{
|
||||
$plural = str_plural($name);
|
||||
$class = sprintf('FireflyIII\Models\%s', ucfirst($name));
|
||||
$field = 'tag' === $name ? 'tag' : 'name';
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id')
|
||||
->leftJoin('users', $plural . '.user_id', '=', 'users.id')
|
||||
->distinct()
|
||||
->whereNull($name . '_transaction_journal.' . $name . '_id')
|
||||
->whereNull($plural . '.deleted_at')
|
||||
->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']);
|
||||
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$objName = $entry->name;
|
||||
|
||||
$line = sprintf(
|
||||
'User #%d (%s) has %s #%d ("%s") which has no transactions.',
|
||||
$entry->user_id,
|
||||
$entry->email,
|
||||
$name,
|
||||
$entry->id,
|
||||
$objName
|
||||
);
|
||||
$this->line($line);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports for each user when the sum of their transactions is not zero.
|
||||
*/
|
||||
private function reportSum(): void
|
||||
{
|
||||
/** @var UserRepositoryInterface $userRepository */
|
||||
$userRepository = app(UserRepositoryInterface::class);
|
||||
|
||||
/** @var User $user */
|
||||
foreach ($userRepository->all() as $user) {
|
||||
$sum = (string)$user->transactions()->sum('amount');
|
||||
if (0 !== bccomp($sum, '0')) {
|
||||
$this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!');
|
||||
}
|
||||
if (0 === bccomp($sum, '0')) {
|
||||
$this->info(sprintf('Amount integrity OK for user #%d', $user->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports on deleted transactions that are connected to a not deleted journal.
|
||||
*/
|
||||
private function reportTransactions(): void
|
||||
{
|
||||
$set = Transaction::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNotNull('transactions.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->get(
|
||||
['transactions.id as transaction_id', 'transactions.deleted_at as transaction_deleted', 'transaction_journals.id as journal_id',
|
||||
'transaction_journals.deleted_at',]
|
||||
);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
'Error: Transaction journal #' . $entry->journal_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called "transaction_journals" and change the "deleted_at" field to: "' . $entry->transaction_deleted . '"'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report on transfers that have budgets.
|
||||
*/
|
||||
private function reportTransfersBudgets(): void
|
||||
{
|
||||
$set = TransactionJournal::distinct()
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('budget_transaction_journal', 'transaction_journals.id', '=', 'budget_transaction_journal.transaction_journal_id')
|
||||
->whereIn('transaction_types.type', [TransactionType::TRANSFER, TransactionType::DEPOSIT])
|
||||
->whereNotNull('budget_transaction_journal.budget_id')->get(['transaction_journals.*']);
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($set as $entry) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Error: Transaction journal #%d is a %s, but has a budget. Edit it without changing anything, so the budget will be removed.',
|
||||
$entry->id,
|
||||
$entry->transactionType->type
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect all journals with empty amount.
|
||||
*/
|
||||
private function reportZeroAmount(): void
|
||||
{
|
||||
$set = Transaction::where('amount', 0)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray();
|
||||
$set = array_unique($set);
|
||||
/** @var Collection $journals */
|
||||
$journals = TransactionJournal::whereIn('id', $set)->get();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$message = sprintf(
|
||||
'Transaction "%s" (#%d), owned by user %s, has amount zero (0.00). It should be deleted.', $journal->description,
|
||||
$journal->id, $journal->user->email
|
||||
);
|
||||
$this->error($message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -154,26 +154,8 @@ class TransactionFactory
|
||||
Log::debug(sprintf('Now in getAccount(%s)', $direction));
|
||||
Log::debug(sprintf('Parameters: ((account), %s, %s)', var_export($sourceId, true), var_export($sourceName, true)));
|
||||
// expected type of source account, in order of preference
|
||||
$array = [
|
||||
'source' => [
|
||||
TransactionType::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionType::DEPOSIT => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE,
|
||||
AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION],
|
||||
TransactionType::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionType::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionType::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
],
|
||||
'destination' => [
|
||||
TransactionType::WITHDRAWAL => [AccountType::EXPENSE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionType::DEPOSIT => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionType::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionType::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionType::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
],
|
||||
];
|
||||
/** @var array $array */
|
||||
$array = config('firefly.expected_source_types');
|
||||
$expectedTypes = $array[$direction];
|
||||
unset($array);
|
||||
|
||||
@ -295,38 +277,7 @@ class TransactionFactory
|
||||
public function makeDramaOverAccountTypes(Account $source, Account $destination): void
|
||||
{
|
||||
// if the source is X, then Y is allowed as destination.
|
||||
$combinations = [
|
||||
TransactionType::WITHDRAWAL => [
|
||||
AccountType::ASSET => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::CASH],
|
||||
AccountType::LOAN => [AccountType::EXPENSE],
|
||||
AccountType::DEBT => [AccountType::EXPENSE],
|
||||
AccountType::MORTGAGE => [AccountType::EXPENSE],
|
||||
],
|
||||
TransactionType::DEPOSIT => [
|
||||
AccountType::REVENUE => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::CASH => [AccountType::ASSET],
|
||||
AccountType::LOAN => [AccountType::ASSET],
|
||||
AccountType::DEBT => [AccountType::ASSET],
|
||||
AccountType::MORTGAGE => [AccountType::ASSET],
|
||||
],
|
||||
TransactionType::TRANSFER => [
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::LOAN => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::DEBT => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::MORTGAGE => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
],
|
||||
TransactionType::OPENING_BALANCE => [
|
||||
AccountType::ASSET => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::LOAN => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::DEBT => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::MORTGAGE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
],
|
||||
TransactionType::RECONCILIATION => [
|
||||
AccountType::RECONCILIATION => [AccountType::ASSET],
|
||||
AccountType::ASSET => [AccountType::RECONCILIATION],
|
||||
],
|
||||
];
|
||||
$combinations = config('firefly.source_dests');
|
||||
$sourceType = $source->accountType->type;
|
||||
$destType = $destination->accountType->type;
|
||||
$journalType = $this->journal->transactionType->type;
|
||||
|
@ -129,7 +129,9 @@ class TransactionJournalFactory
|
||||
Log::debug(sprintf('Now creating journal %d/%d', $index + 1, \count($transactions)));
|
||||
/** Get basic fields */
|
||||
|
||||
$currency = $this->currencyRepository->findCurrency($transaction['currency'], (int)$transaction['currency_id'], $transaction['currency_code']);
|
||||
$currency = $this->currencyRepository->findCurrency(
|
||||
$transaction['currency'], (int)$transaction['currency_id'], $transaction['currency_code']
|
||||
);
|
||||
$foreignCurrency = $this->findForeignCurrency($transaction);
|
||||
|
||||
$bill = $this->billRepository->findBill($transaction['bill'], (int)$transaction['bill_id'], $transaction['bill_name']);
|
||||
@ -189,9 +191,8 @@ class TransactionJournalFactory
|
||||
|
||||
$collection->push($journal);
|
||||
}
|
||||
if ($collection->count() > 1) {
|
||||
$this->storeGroup($collection, $data['group_title']);
|
||||
}
|
||||
|
||||
$this->storeGroup($collection, $data['group_title']);
|
||||
|
||||
return $collection;
|
||||
|
||||
|
@ -26,6 +26,7 @@ use FireflyIII\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@ -103,11 +104,11 @@ class TransactionGroup extends Model
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return BelongsToMany
|
||||
* @return HasMany
|
||||
*/
|
||||
public function transactionJournals(): BelongsToMany
|
||||
public function transactionJournals(): HasMany
|
||||
{
|
||||
return $this->belongsToMany(TransactionJournal::class,'group_journals');
|
||||
return $this->hasMany(TransactionJournal::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -39,43 +39,45 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
/**
|
||||
* Class TransactionJournal.
|
||||
*
|
||||
* @property User $user
|
||||
* @property int $bill_id
|
||||
* @property Collection $categories
|
||||
* @property bool $completed
|
||||
* @property string $description
|
||||
* @property int $transaction_type_id
|
||||
* @property int transaction_currency_id
|
||||
* @property TransactionCurrency $transactionCurrency
|
||||
* @property Collection $tags
|
||||
* @property int user_id
|
||||
* @property Collection transactions
|
||||
* @property int transaction_count
|
||||
* @property Carbon interest_date
|
||||
* @property Carbon book_date
|
||||
* @property Carbon process_date
|
||||
* @property bool encrypted
|
||||
* @property int order
|
||||
* @property int budget_id
|
||||
* @property string period_marker
|
||||
* @property Carbon $date
|
||||
* @property string $transaction_type_type
|
||||
* @property int $id
|
||||
* @property TransactionType $transactionType
|
||||
* @property Collection budgets
|
||||
* @property Bill $bill
|
||||
* @property Collection transactionJournalMeta
|
||||
* @property User $user
|
||||
* @property int $bill_id
|
||||
* @property Collection $categories
|
||||
* @property bool $completed
|
||||
* @property string $description
|
||||
* @property int $transaction_type_id
|
||||
* @property int transaction_currency_id
|
||||
* @property TransactionCurrency $transactionCurrency
|
||||
* @property Collection $tags
|
||||
* @property int user_id
|
||||
* @property Collection transactions
|
||||
* @property int transaction_count
|
||||
* @property Carbon interest_date
|
||||
* @property Carbon book_date
|
||||
* @property Carbon process_date
|
||||
* @property bool encrypted
|
||||
* @property int order
|
||||
* @property int budget_id
|
||||
* @property string period_marker
|
||||
* @property Carbon $date
|
||||
* @property string $transaction_type_type
|
||||
* @property int $id
|
||||
* @property TransactionType $transactionType
|
||||
* @property Collection budgets
|
||||
* @property Bill $bill
|
||||
* @property Collection transactionJournalMeta
|
||||
* @property TransactionGroup transactionGroup
|
||||
* @property int transaction_group_id
|
||||
* @SuppressWarnings (PHPMD.TooManyPublicMethods)
|
||||
* @SuppressWarnings (PHPMD.CouplingBetweenObjects)
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property int $tag_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Note[] $notes
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||
* @property int $tag_count
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Note[] $notes
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournalLink[] $sourceJournalLinks
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $transactionGroups
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $transactionGroups
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\TransactionJournal after(\Carbon\Carbon $date)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\Models\TransactionJournal before(\Carbon\Carbon $date)
|
||||
* @method static bool|null forceDelete()
|
||||
@ -362,11 +364,11 @@ class TransactionJournal extends Model
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* @return BelongsToMany
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function transactionGroups(): BelongsToMany
|
||||
public function transactionGroup(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(TransactionGroup::class,'group_journals');
|
||||
return $this->belongsTo(TransactionGroup::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -482,6 +482,16 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
return $amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all journals without a group, used in an upgrade routine.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsWithoutGroup(): Collection
|
||||
{
|
||||
return TransactionJournal::whereNull('transaction_group_id')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournalLink $link
|
||||
*
|
||||
|
@ -39,7 +39,6 @@ use Illuminate\Support\MessageBag;
|
||||
*/
|
||||
interface JournalRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param TransactionType $type
|
||||
@ -57,9 +56,6 @@ interface JournalRepositoryInterface
|
||||
*/
|
||||
public function countTransactions(TransactionJournal $journal): int;
|
||||
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* Deletes a journal.
|
||||
*
|
||||
@ -69,6 +65,9 @@ interface JournalRepositoryInterface
|
||||
*/
|
||||
public function destroy(TransactionJournal $journal): bool;
|
||||
|
||||
|
||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||
|
||||
/**
|
||||
* Find a journal by its hash.
|
||||
*
|
||||
@ -205,6 +204,13 @@ interface JournalRepositoryInterface
|
||||
*/
|
||||
public function getJournalTotal(TransactionJournal $journal): string;
|
||||
|
||||
/**
|
||||
* Return all journals without a group, used in an upgrade routine.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsWithoutGroup(): Collection;
|
||||
|
||||
/**
|
||||
* @param TransactionJournalLink $link
|
||||
*
|
||||
|
@ -24,6 +24,8 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
use FireflyIII\Export\Exporter\CsvExporter;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\TransactionType as TransactionTypeModel;
|
||||
use FireflyIII\Services\Currency\FixerIOv2;
|
||||
use FireflyIII\Services\Currency\RatesApiIOv1;
|
||||
use FireflyIII\TransactionRules\Actions\AddTag;
|
||||
@ -278,7 +280,6 @@ return [
|
||||
'zh_CN' => ['name_locale' => 'Chinese Simplified', 'name_english' => 'Chinese Simplified'], // 99%
|
||||
|
||||
|
||||
|
||||
//'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'], // 71%
|
||||
'nb_NO' => ['name_locale' => 'Norsk', 'name_english' => 'Norwegian'],
|
||||
//'ca_ES' => ['name_locale' => 'Catalan', 'name_english' => 'Catalan'], // 0%
|
||||
@ -474,17 +475,73 @@ return [
|
||||
],
|
||||
|
||||
|
||||
'test-triggers' => [
|
||||
'test-triggers' => [
|
||||
'limit' => 10,
|
||||
'range' => 200,
|
||||
],
|
||||
'default_currency' => 'EUR',
|
||||
'default_language' => 'en_US',
|
||||
'search_modifiers' => ['amount_is', 'amount', 'amount_max', 'amount_min', 'amount_less', 'amount_more', 'source', 'destination', 'category',
|
||||
'budget', 'bill', 'type', 'date', 'date_before', 'date_after', 'on', 'before', 'after'],
|
||||
'default_currency' => 'EUR',
|
||||
'default_language' => 'en_US',
|
||||
'search_modifiers' => ['amount_is', 'amount', 'amount_max', 'amount_min', 'amount_less', 'amount_more', 'source', 'destination', 'category',
|
||||
'budget', 'bill', 'type', 'date', 'date_before', 'date_after', 'on', 'before', 'after'],
|
||||
// tag notes has_attachments
|
||||
'cer_providers' => [
|
||||
'cer_providers' => [
|
||||
'fixer' => FixerIOv2::class,
|
||||
'ratesapi' => RatesApiIOv1::class,
|
||||
],
|
||||
|
||||
// expected source types for each transaction type, in order of preference.
|
||||
'expected_source_types' => [
|
||||
'source' => [
|
||||
TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionTypeModel::DEPOSIT => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE,
|
||||
AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION],
|
||||
TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
],
|
||||
'destination' => [
|
||||
TransactionTypeModel::WITHDRAWAL => [AccountType::EXPENSE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionTypeModel::DEPOSIT => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
],
|
||||
],
|
||||
|
||||
// allowed source / destination accounts.
|
||||
'source_dests' => [
|
||||
TransactionTypeModel::WITHDRAWAL => [
|
||||
AccountType::ASSET => [AccountType::EXPENSE, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::CASH],
|
||||
AccountType::LOAN => [AccountType::EXPENSE],
|
||||
AccountType::DEBT => [AccountType::EXPENSE],
|
||||
AccountType::MORTGAGE => [AccountType::EXPENSE],
|
||||
],
|
||||
TransactionTypeModel::DEPOSIT => [
|
||||
AccountType::REVENUE => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::CASH => [AccountType::ASSET],
|
||||
AccountType::LOAN => [AccountType::ASSET],
|
||||
AccountType::DEBT => [AccountType::ASSET],
|
||||
AccountType::MORTGAGE => [AccountType::ASSET],
|
||||
],
|
||||
TransactionTypeModel::TRANSFER => [
|
||||
AccountType::ASSET => [AccountType::ASSET],
|
||||
AccountType::LOAN => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::DEBT => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
AccountType::MORTGAGE => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
],
|
||||
TransactionTypeModel::OPENING_BALANCE => [
|
||||
AccountType::ASSET => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::LOAN => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::DEBT => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::MORTGAGE => [AccountType::INITIAL_BALANCE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
|
||||
],
|
||||
TransactionTypeModel::RECONCILIATION => [
|
||||
AccountType::RECONCILIATION => [AccountType::ASSET],
|
||||
AccountType::ASSET => [AccountType::RECONCILIATION],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class ChangesForV480 extends Migration
|
||||
{
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
|
||||
}
|
||||
}
|
54
database/migrations/2019_03_22_183214_changes_for_v480.php
Normal file
54
database/migrations/2019_03_22_183214_changes_for_v480.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
/**
|
||||
* Class ChangesForV480
|
||||
*/
|
||||
class ChangesForV480 extends Migration
|
||||
{
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table(
|
||||
'transaction_journals',
|
||||
function (Blueprint $table) {
|
||||
// drop transaction_group_id + foreign key.
|
||||
// cannot drop foreign keys in SQLite:
|
||||
if ('sqlite' !== config('database.default')) {
|
||||
$table->dropForeign('transaction_journals_transaction_group_id_foreign');
|
||||
}
|
||||
$table->dropColumn('transaction_group_id');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
|
||||
Schema::table(
|
||||
'transaction_journals',
|
||||
function (Blueprint $table) {
|
||||
|
||||
$table->integer('transaction_currency_id', false, true)->nullable()->change();
|
||||
|
||||
// add column "group_id" after "transaction_type_id"
|
||||
$table->integer('transaction_group_id', false, true)
|
||||
->nullable()->default(null)->after('transaction_type_id');
|
||||
|
||||
// add foreign key for "transaction_group_id"
|
||||
$table->foreign('transaction_group_id')->references('id')->on('transaction_groups')->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user