Removed single table inheritance.

This commit is contained in:
James Cole 2014-12-17 20:47:46 +01:00
parent de7db8db78
commit 9d4c4be468
8 changed files with 361 additions and 76 deletions

View File

@ -9,7 +9,7 @@ install:
script:
- php vendor/bin/codecept build
- php vendor/bin/codecept run --coverage --coverage-xml -vvv
- php vendor/bin/codecept run --coverage --coverage-xml
after_script:
- php vendor/bin/coveralls

View File

@ -1,6 +1,7 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint;
/**
@ -10,7 +11,6 @@ use Illuminate\Database\Schema\Blueprint;
*/
class ChangesForV321 extends Migration
{
/**
* Reverse the migrations.
*
@ -18,24 +18,163 @@ class ChangesForV321 extends Migration
*/
public function down()
{
// rename tables back to original name.
/*
* Undo updates to budget_limits table.
*/
$this->undoBudgetLimits();
$this->undoPiggyBankEvents();
$this->undoMoveBudgets();
$this->undoMoveCategories();
$this->undoCreateBudgetTables();
$this->undoCreateCategoryTables();
$this->undoRenameInLimitRepetitions();
$this->undoUpdateTransactionTable();
$this->undoDropCompRecurTable();
$this->undoDropCompTransTable();
}
public function undoBudgetLimits()
{
Schema::table(
'budget_limits', function (Blueprint $table) {
$table->dropForeign('bid_foreign');
$table->dropColumn('budget_id');
}
);
Schema::rename('budget_limits', 'limits');
}
public function undoPiggyBankEvents()
{
Schema::rename('piggy_bank_events', 'piggybank_events');
// rename column in "limit_repetitions" back to the original name
}
public function undoMoveBudgets()
{
Budget::get()->each(
function (Budget $budget) {
$entry = [
'user_id' => $budget->user_id,
'name' => $budget->name,
'class' => 'Budget'
];
$component = Component::firstOrCreate($entry);
Log::debug('Migrated budget back #' . $component->id . ': ' . $component->name);
// create entry in component_transaction_journal
$connections = DB::table('budget_transaction_journal')->where('budget_id', $budget->id)->get();
foreach ($connections as $connection) {
try {
DB::table('component_transaction_journal')->insert(
[
'component_id' => $component->id,
'transaction_journal_id' => $connection->transaction_journal_id
]
);
} catch (QueryException $e) {
}
}
}
);
}
public function undoMoveCategories()
{
Category::get()->each(
function (Category $category) {
$entry = [
'user_id' => $category->user_id,
'name' => $category->name,
'class' => 'Category'
];
$component = Component::firstOrCreate($entry);
Log::debug('Migrated category back #' . $component->id . ': ' . $component->name);
// create entry in component_transaction_journal
$connections = DB::table('category_transaction_journal')->where('category_id', $category->id)->get();
foreach ($connections as $connection) {
try {
DB::table('component_transaction_journal')->insert(
[
'component_id' => $component->id,
'transaction_journal_id' => $connection->transaction_journal_id
]
);
} catch (QueryException $e) {
}
}
}
);
}
public function undoCreateBudgetTables()
{
Schema::drop('budget_transaction_journal');
Schema::drop('budgets');
}
public function undoCreateCategoryTables()
{
Schema::drop('category_transaction_journal');
Schema::drop('categories');
}
public function undoRenameInLimitRepetitions()
{
Schema::table(
'limit_repetitions', function (Blueprint $table) {
$table->renameColumn('budget_limit_id', 'limit_id');
}
);
}
// create column in "transactions"
// create foreign key in "transactions"
// TODO skipped because not supported in SQLite
public function undoUpdateTransactionTable()
{
Schema::table(
'transactions', function (Blueprint $table) {
#$table->integer('piggybank_id')->nullable()->unsigned();
#$table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('set null');
$table->integer('piggybank_id')->nullable()->unsigned();
$table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('set null');
}
);
}
public function undoDropCompRecurTable()
{
Schema::create(
'component_recurring_transaction', function (Blueprint $table) {
$table->increments('id');
$table->integer('component_id')->unsigned();
$table->integer('recurring_transaction_id')->unsigned();
$table->boolean('optional');
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
$table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('cascade');
$table->unique(['component_id', 'recurring_transaction_id'], 'cid_rtid_unique');
}
);
}
public function undoDropCompTransTable()
{
Schema::create(
'component_transaction', function (Blueprint $table) {
$table->increments('id');
$table->integer('component_id')->unsigned();
$table->integer('transaction_id')->unsigned();
$table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
$table->foreign('transaction_id')->references('id')->on('transactions')->onDelete('cascade');
$table->unique(['component_id', 'transaction_id']);
}
);
}
@ -47,29 +186,166 @@ class ChangesForV321 extends Migration
*/
public function up()
{
// rename tables.
Schema::rename('limits', 'budget_limits');
Schema::rename('piggybank_events', 'piggy_bank_events');
$this->doCreateBudgetTables();
$this->doRenameInLimitRepetitions();
$this->doBudgetLimits();
$this->doPiggyBankEvents();
$this->doCreateCategoryTables();
$this->doUpdateTransactionTable();
$this->doDropCompRecurTable();
$this->doDropCompTransTable();
$this->doMoveBudgets();
$this->doMoveCategories();
// rename column in "limit_repetitions"
}
public function doCreateBudgetTables()
{
Schema::create(
'budgets', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->string('name', 50);
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unique(['user_id', 'name']);
}
);
Schema::create(
'budget_transaction_journal', function (Blueprint $table) {
$table->increments('id');
$table->integer('budget_id')->unsigned();
$table->integer('transaction_journal_id')->unsigned();
$table->foreign('budget_id')->references('id')->on('budgets')->onDelete('cascade');
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
$table->unique(['budget_id', 'transaction_journal_id'], 'bid_tjid_unique');
}
);
}
public function doRenameInLimitRepetitions()
{
Schema::table(
'limit_repetitions', function (Blueprint $table) {
$table->renameColumn('limit_id', 'budget_limit_id');
}
);
}
// drop foreign key in "transactions"
// drop column in "transactions"
// TODO skipped because not supported in SQLite
public function doBudgetLimits()
{
Schema::rename('limits', 'budget_limits');
Schema::table(
'transactions', function (Blueprint $table) {
#$table->dropForeign('transactions_piggybank_id_foreign');
#$table->dropIndex('transactions_piggybank_id_foreign');
#$table->dropColumn('piggybank_id');
'budget_limits', function (Blueprint $table) {
$table->integer('budget_id')->unsigned()->after('updated_at');
$table->foreign('budget_id', 'bid_foreign')->references('id')->on('budgets')->onDelete('cascade');
}
);
}
public function doPiggyBankEvents()
{
Schema::rename('piggybank_events', 'piggy_bank_events');
}
public function doCreateCategoryTables()
{
Schema::create(
'categories', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->string('name', 50);
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unique(['user_id', 'name']);
}
);
Schema::create(
'category_transaction_journal', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->integer('transaction_journal_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
$table->unique(['category_id', 'transaction_journal_id'], 'catid_tjid_unique');
}
);
}
public function doUpdateTransactionTable()
{
Schema::table(
'transactions', function (Blueprint $table) {
$table->dropForeign('transactions_piggybank_id_foreign');
#$table->dropIndex('transactions_piggybank_id_foreign');
$table->dropColumn('piggybank_id');
}
);
}
public function doDropCompRecurTable()
{
Schema::drop('component_recurring_transaction');
}
public function doDropCompTransTable()
{
Schema::drop('component_transaction');
}
public function doMoveBudgets()
{
Component::where('class', 'Budget')->get()->each(
function (Component $c) {
$entry = [
'user_id' => $c->user_id,
'name' => $c->name
];
$budget = Budget::firstOrCreate($entry);
Log::debug('Migrated budget #' . $budget->id . ': ' . $budget->name);
// create entry in budget_transaction_journal
$connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get();
foreach ($connections as $connection) {
DB::table('budget_transaction_journal')->insert(
[
'budget_id' => $budget->id,
'transaction_journal_id' => $connection->transaction_journal_id
]
);
}
}
);
}
public function doMoveCategories()
{
Component::where('class', 'Category')->get()->each(
function (Component $c) {
$entry = [
'user_id' => $c->user_id,
'name' => $c->name
];
$category = Category::firstOrCreate($entry);
Log::debug('Migrated category #' . $category->id . ': ' . $category->name);
// create entry in category_transaction_journal
$connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get();
foreach ($connections as $connection) {
DB::table('category_transaction_journal')->insert(
[
'category_id' => $category->id,
'transaction_journal_id' => $connection->transaction_journal_id
]
);
}
}
);
}
}

View File

@ -8,7 +8,7 @@ class DefaultUserSeeder extends Seeder
public function run()
{
DB::table('users')->delete();
if (App::environment() == 'testing') {
if (App::environment() == 'testing' || App::environment() == 'homestead') {
User::create(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null]);
User::create(['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null]);

View File

@ -10,7 +10,7 @@ class TestContentSeeder extends Seeder
public function run()
{
if (App::environment() == 'testing') {
if (App::environment() == 'testing' || App::environment() == 'homestead') {
$assetType = AccountType::whereType('Asset account')->first();
$expenseType = AccountType::whereType('Expense account')->first();
@ -40,6 +40,14 @@ class TestContentSeeder extends Seeder
$lunch = Category::create(['user_id' => $user->id, 'name' => 'Lunch']);
$house = Category::create(['user_id' => $user->id, 'name' => 'House']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 1', 'class' => 'Budget']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 2', 'class' => 'Budget']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 3', 'class' => 'Budget']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 4', 'class' => 'Category']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 5', 'class' => 'Category']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 6', 'class' => 'Category']);
Component::create(['user_id' => $user->id, 'name' => 'Some Component 7', 'class' => 'Category']);
// create some expense accounts.
$ah = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Albert Heijn', 'active' => 1]);
$plus = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'PLUS', 'active' => 1]);

View File

@ -5,18 +5,17 @@ use Illuminate\Database\Eloquent\SoftDeletingTrait;
/**
* Class Budget
*/
class Budget extends Component
class Budget extends Eloquent
{
protected $isSubclass = true;
use SoftDeletingTrait;
protected $fillable = ['name', 'user_id'];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
*/
public function limitrepetitions()
{
return $this->hasManyThrough('LimitRepetition', 'BudgetLimit', 'component_id');
return $this->hasManyThrough('LimitRepetition', 'BudgetLimit', 'budget_id');
}
/**
@ -24,8 +23,23 @@ class Budget extends Component
*/
public function budgetlimits()
{
return $this->hasMany('BudgetLimit', 'component_id');
return $this->hasMany('BudgetLimit', 'budget_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('TransactionJournal', 'budget_transaction_journal', 'budget_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
}

View File

@ -1,14 +1,27 @@
<?php
use Illuminate\Database\Eloquent\SoftDeletingTrait;
/**
* Class Category
*/
class Category extends Component
class Category extends Eloquent
{
use SoftDeletingTrait;
protected $fillable = ['name', 'user_id'];
// @codingStandardsIgnoreStart
protected $isSubclass = true;
// @codingStandardsIgnoreEnd
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('TransactionJournal', 'budget_transaction_journal', 'budget_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
}

View File

@ -7,7 +7,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Class Component
*/
class Component extends SingleTableInheritanceEntity
class Component extends Eloquent
{
public static $rules
@ -17,48 +17,22 @@ class Component extends SingleTableInheritanceEntity
'class' => 'required',
];
protected $dates = ['deleted_at', 'created_at', 'updated_at'];
protected $fillable = ['name', 'user_id'];
protected $subclassField = 'class';
protected $fillable = ['name', 'user_id','class'];
protected $table = 'components';
use ValidatingTrait;
/**
* TODO remove this method in favour of something in the FireflyIII libraries.
*
* @return Carbon
*/
public function lastActionDate()
{
$transaction = $this->transactionjournals()->orderBy('updated_at', 'DESC')->first();
if (is_null($transaction)) {
return null;
}
return $transaction->date;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
{
return $this->belongsToMany('TransactionJournal', 'component_transaction_journal', 'component_id');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactions()
{
return $this->belongsToMany('Transaction');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
// /**
// * remove this method in favour of something in the FireflyIII libraries.
// *
// * @return Carbon
// */
// public function lastActionDate()
// {
// $transaction = $this->transactionjournals()->orderBy('updated_at', 'DESC')->first();
// if (is_null($transaction)) {
// return null;
// }
//
// return $transaction->date;
// }
}

View File

@ -28,7 +28,7 @@ class TransactionJournal extends Eloquent
public function budgets()
{
return $this->belongsToMany(
'Budget', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
'Budget', 'budget_transaction_journal', 'transaction_journal_id', 'budget_id'
);
}
@ -38,7 +38,7 @@ class TransactionJournal extends Eloquent
public function categories()
{
return $this->belongsToMany(
'Category', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
'Category', 'category_transaction_journal', 'transaction_journal_id', 'category_id'
);
}