diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index 1e46d3ddde..ad4d63f700 100644 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -11,6 +11,9 @@ class HomeController extends BaseController { public function index() { $count = $this->accounts->count(); + + // build the home screen: + return View::make('index')->with('count',$count); } } \ No newline at end of file diff --git a/app/controllers/MigrationController.php b/app/controllers/MigrationController.php index 8e205e94ca..490e9e3c68 100644 --- a/app/controllers/MigrationController.php +++ b/app/controllers/MigrationController.php @@ -19,6 +19,7 @@ class MigrationController extends BaseController public function postIndex() { + // @codeCoverageIgnoreStart if (Input::hasFile('exportFile')) { // get content: @@ -31,487 +32,10 @@ class MigrationController extends BaseController return View::make('error')->with('message', 'Invalid JSON content.'); } $this->migration->migrate(); - return 'busy!'; - } - - // then, start migrating! - - -// -// -// // map old and new id's. -// $map = [ -// 'accounts' => [], -// 'beneficiaries' => [], -// ]; -// -// // get the account types we need -// $beneficiaryAT = AccountType::where('description', 'Beneficiary account')->first(); -// -// // save all accounts: -// foreach ($JSON->accounts as $entry) { -// // create account: -// if ($entry->openingbalance == 0) { -// $account = $this->accounts->store(['name' => $entry->name]); -// } else { -// $account = $this->accounts->storeWithInitialBalance( -// ['name' => $entry->name], -// new Carbon($entry->openingbalancedate), -// floatval($entry->openingbalance) -// ); -// } -// $map['accounts'][$entry->id] = $account->id; -// } -// unset($entry); -// -// // save all components: -// foreach ($JSON->components as $entry) { -// switch ($entry->type->type) { -// case 'beneficiary': -// // create new account for beneficiary: -// $account = $this->accounts->store(['name' => $entry->name]); -// $map['beneficiaries'][$entry->id] = $account; -// break; -// case 'category': -// // create new component for category: -//// $account = $this->accounts->store(['name' => $entry->name]); -//// $map['beneficiaries'][$entry->id] = $account; -// break; -// } -// } -// unset($JSON->accounts); -// -// -// var_dump($JSON); -// var_dump($map); -// -// exit; -// } -// - return View::make('error')->with('message', 'No file found.'); - } - - /* - public function index() - { - // check if database connection is present. - $configValue = Config::get('database.connections.old-firefly'); - if (is_null($configValue)) { - return View::make('migrate.index'); - } - - // try to connect to it: - $error = ''; - try { - DB::connection('old-firefly')->select('SELECT * from `users`;'); - } catch (PDOException $e) { - $error = $e->getMessage(); - return View::make('migrate.index')->with('error', $error); - } - - return Redirect::route('migrate.upload'); - - - } - - public function selectUser() - { - $oldUsers = []; - try { - $oldUsers = DB::connection('old-firefly')->select('SELECT * from `users`;'); - } catch (PDOException $e) { - $error = $e->getMessage(); - return View::make('migrate.index')->with('error', $error); - } - - return View::make('migrate.select-user')->with('oldUsers', $oldUsers); - } - - public function postSelectUser() - { - $userID = Input::get('user'); - $count = DB::connection('old-firefly')->table('users')->where('id', $userID)->count(); - if ($count == 1) { - return Redirect::route('migrate.migrate', $userID); + return Redirect::route('index'); } else { - return View::make('error')->with('message', 'No such user!'); + return View::make('error')->with('message', 'No file selected'); } + // @codeCoverageIgnoreEnd } - public function migrate($userID) - { - // import the data. - $user = Auth::user(); - $previousUser = DB::connection('old-firefly')->table('users')->where('id', $userID)->first(); - - - // current user already migrated? - if ($user->migrated) { - return View::make('error')->with('message', 'This user has already been migrated.'); - } - - // a map to keep the connections intact: - $map = [ - 'accounts' => [], - 'beneficiaries' => [], - 'categories' => [], - 'budgets' => [], - ]; - - // messages to show in result screen: - $messages = []; - - // grab account types: - $defaultAT = AccountType::where('description', 'Default account')->first(); - $initialBalanceAT = AccountType::where('description', 'Initial balance account')->first(); - $beneficiaryAT = AccountType::where('description', 'Beneficiary account')->first(); - - // grab transaction types: - $initialBalanceTT = TransactionType::where('type', 'Opening balance')->first(); - $depositTT = TransactionType::where('type', 'Deposit')->first(); - $withdrawalTT = TransactionType::where('type', 'Withdrawal')->first(); - $transferTT = TransactionType::where('type', 'Transfer')->first(); - - // grab currency: - $currency = TransactionCurrency::where('code', 'EUR')->first(); - - // grab component types: - $categoryType = ComponentType::where('type', 'category')->first(); - $budgetType = ComponentType::where('type', 'budget')->first(); - - // create a special cash account for this user: - $cashAccount = new Account; - $cashAccount->name = 'Cash account'; - $cashAccount->active = true; - $cashAccount->accountType()->associate($beneficiaryAT); - $cashAccount->user()->associate($user); - $cashAccount->save(); - $messages[] = 'Created "cash" account.'; - - // get the old accounts: - $accounts = DB::connection('old-firefly')->table('accounts')->where('user_id', $previousUser->id)->get(); - foreach ($accounts as $account) { - - // already had one? - $existing = Account::where('name', $account->name)->where('account_type_id', $defaultAT->id)->where( - 'user_id', $previousUser->id - )->first(); - - if (!is_null($existing)) { - $map['accounts'][$account->id] = $existing; - $messages[] = 'Skipped creating account ' . $account->name . ' because it already exists.'; - continue; - } - unset($existing); - // create account: - $current = new Account; - $current->name = $account->name; - $current->active = true; - $current->accountType()->associate($defaultAT); - $current->user()->associate($user); - $current->save(); - - // map and information - $map['accounts'][$account->id] = $current; - $messages[] = 'Account "' . $current->name . '" recreated.'; - - // recreate opening balance, if relevant: - if (floatval($account->openingbalance) != 0) { - - // now create another account, and create the first transfer indicating - $initial = new Account; - $initial->name = $account->name . ' initial balance'; - $initial->accountType()->associate($initialBalanceAT); - $initial->active = 1; - $initial->user()->associate($user); - $initial->save(); - - // create a journal, and two transfers: - $journal = new TransactionJournal; - $journal->transactionType()->associate($initialBalanceTT); - $journal->transactionCurrency()->associate($currency); - $journal->description = $account->name . ' opening balance'; - $journal->date = $account->openingbalancedate; - $journal->save(); - - // coming from a virtual account is: - $credit = new Transaction; - $credit->account()->associate($current); - $credit->transactionJournal()->associate($journal); - $credit->description = null; - $credit->amount = $account->openingbalance; - $credit->save(); - - // transfer into this new account - $debet = new Transaction; - $debet->account()->associate($initial); - $debet->transactionJournal()->associate($journal); - $debet->description = null; - $debet->amount = $account->openingbalance * -1; - $debet->save(); - $messages[] - = 'Saved initial balance for ' . $current->name . ' (' . mf($account->openingbalance, true) . ')'; - unset($initial, $journal, $credit, $debet); - } - unset($current); - } - - // save all old components - $components = DB::connection('old-firefly')->table('components')->leftJoin( - 'types', 'types.id', '=', 'components.type_id' - )->where('user_id', $previousUser->id)->get(['components.*', 'types.type']); - - foreach ($components as $component) { - $id = $component->id; - switch ($component->type) { - case 'beneficiary': - if (!isset($map['beneficiaries'][$id])) { - // if it exists, skip: - $existing = Account::where('name', $component->name)->where('user_id', $user->id)->where( - 'account_type_id', $beneficiaryAT->id - )->first(); - if (!is_null($existing)) { - $map['beneficiaries'][$id] = $existing; - $messages[] - = 'Skipped creating beneficiary "' . $component->name . '" because it already exists.'; - unset($existing); - continue; - } - - - // new account for this beneficiary - $beneficiary = new Account; - $beneficiary->name = $component->name; - $beneficiary->accountType()->associate($beneficiaryAT); - $beneficiary->user()->associate($user); - $beneficiary->active = 1; - $beneficiary->save(); - $map['beneficiaries'][$id] = $beneficiary; - $messages[] = 'Recreated beneficiary "' . $beneficiary->name . '".'; - unset($beneficiary); - } - break; - case 'category': - // if it exists, skip: - $existing = Component::where('name', $component->name)->where('user_id', $user->id)->where( - 'component_type_id', $categoryType->id - )->first(); - if (!is_null($existing)) { - $map['categories'][$id] = $existing; - $messages[] = 'Skipped creating category "' . $component->name . '" because it already exists.'; - unset($existing); - continue; - } - - // new component for this category: - $category = new Component; - $category->componentType()->associate($categoryType); - $category->name = $component->name; - $category->user()->associate($user); - $category->save(); - $map['categories'][$id] = $category; - $messages[] = 'Recreated category "' . $category->name . '".'; - unset($category); - break; - case 'budget': - // if it exists, skip: - $existing = Component::where('name', $component->name)->where('user_id', $user->id)->where( - 'component_type_id', $budgetType->id - )->first(); - if (!is_null($existing)) { - $map['budgets'][$id] = $existing; - $messages[] = 'Skipped creating budget "' . $component->name . '" because it already exists.'; - unset($existing); - continue; - } - - // new component for this budget: - $budget = new Component; - $budget->componentType()->associate($budgetType); - $budget->user()->associate($user); - $budget->name = $component->name; - $budget->save(); - $map['budgets'][$id] = $budget; - $messages[] = 'Recreated budget "' . $budget->name . '".'; - unset($budget); - break; - } - } - - // grab all old transactions: - $transactions = DB::connection('old-firefly')->table('transactions')->where('user_id', $user->id)->orderBy( - 'date' - ) - ->get(); - - foreach ($transactions as $transaction) { - $accountID = $transaction->account_id; - - // grab the components for this transaction - $components = DB::connection('old-firefly')->table('component_transaction') - ->leftJoin('components', 'components.id', '=', 'component_transaction.component_id') - ->leftJoin('types', 'types.id', '=', 'components.type_id') - ->where('transaction_id', $transaction->id) - ->get(['components.id', 'types.type']); - - $beneficiary = null; - $budget = null; - $category = null; - - // loop components, get the right id's: - foreach ($components as $component) { - $id = $component->id; - switch ($component->type) { - case 'beneficiary': - $beneficiary = $map['beneficiaries'][$id]; - break; - case 'budget': - $budget = $map['budgets'][$id]; - break; - case 'category': - $category = $map['categories'][$id]; - break; - } - } - // get a fall back for empty beneficiaries: - if (is_null($beneficiary)) { - $beneficiary = $cashAccount; - } - - // create the transaction journal: - $journal = new TransactionJournal; - if ($transaction->amount < 0) { - $journal->transactionType()->associate($withdrawalTT); - } else { - $journal->transactionType()->associate($depositTT); - } - $journal->transactionCurrency()->associate($currency); - $journal->description = $transaction->description; - $journal->date = $transaction->date; - $journal->save(); - - // create two transactions: - - if ($transaction->amount < 0) { - // credit the beneficiary - $credit = new Transaction; - $credit->account()->associate($beneficiary); - $credit->transactionJournal()->associate($journal); - $credit->description = null; - $credit->amount = floatval($transaction->amount) * -1; - $credit->save(); - // add budget / category: - if (!is_null($budget)) { - $credit->components()->attach($budget); - } - if (!is_null($category)) { - $credit->components()->attach($category); - } - - // debet ourselves: - $debet = new Transaction; - $debet->account()->associate($map['accounts'][$accountID]); - $debet->transactionJournal()->associate($journal); - $debet->description = null; - $debet->amount = floatval($transaction->amount); - $debet->save(); - if (!is_null($budget)) { - $debet->components()->attach($budget); - } - if (!is_null($category)) { - $debet->components()->attach($category); - } - $messages[] - = 'Recreated expense "' . $transaction->description . '" (' . mf($transaction->amount, true) . ')'; - - } else { - $credit = new Transaction; - $credit->account()->associate($map['accounts'][$accountID]); - $credit->transactionJournal()->associate($journal); - $credit->description = null; - $credit->amount = floatval($transaction->amount); - $credit->save(); - if (!is_null($budget)) { - $credit->components()->attach($budget); - } - if (!is_null($category)) { - $credit->components()->attach($category); - } - - // from whoever! - $debet = new Transaction; - $debet->account()->associate($beneficiary); - $debet->transactionJournal()->associate($journal); - $debet->description = null; - $debet->amount = floatval($transaction->amount) * -1; - $debet->save(); - if (!is_null($budget)) { - $debet->components()->attach($budget); - } - if (!is_null($category)) { - $debet->components()->attach($category); - } - $messages[] - = 'Recreated income "' . $transaction->description . '" (' . mf($transaction->amount, true) . ')'; - - } - - - } - unset($transaction); - - // recreate the transfers: - $transfers = DB::connection('old-firefly')->table('transfers')->where('user_id', $user->id)->get(); - foreach ($transfers as $transfer) { - - // if it exists already, we don't need to recreate it: - $existingJournal = TransactionJournal::where('description', $transfer->description)->where( - 'date', $transfer->date - )->where('transaction_type_id', $transferTT->id)->first(); - if (!is_null($existingJournal)) { - // grab transaction from journal to make sure: - $firstTransaction = $existingJournal->transactions()->first(); - if ($firstTransaction->amount == $transfer->amount - || $firstTransaction->amount == $transfer->amount * -1 - ) { - // probably the same: - $messages[] = 'Skipped transfer "' . $transfer->description . '" because it already exists.'; - unset($existingJournal, $firstTransaction); - continue; - } - } - - - $fromID = $transfer->accountfrom_id; - $toID = $transfer->accountto_id; - // create a journak: - $journal = new TransactionJournal; - $journal->transactionType()->associate($transferTT); - $journal->transactionCurrency()->associate($currency); - $journal->description = $transfer->description; - $journal->date = $transfer->date; - $journal->save(); - - // from account (debet) to another account (credit) - $debet = new Transaction; - $debet->account()->associate($map['accounts'][$fromID]); - $debet->transactionJournal()->associate($journal); - $debet->description = null; - $debet->amount = floatval($transfer->amount * -1); - $debet->save(); - - // to another account! - $credit = new Transaction; - $credit->account()->associate($map['accounts'][$toID]); - $credit->transactionJournal()->associate($journal); - $credit->description = null; - $credit->amount = floatval($transfer->amount); - $credit->save(); - $messages[] = 'Recreated transfer "' . $transfer->description . '" (' . mf($transfer->amount) . ')'; - } - $user->migrated = true; - $user->save(); - - return View::make('migrate.result')->with('messages', $messages); - } - */ } \ No newline at end of file diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index 0e7d7d813c..752560b138 100644 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -26,6 +26,17 @@ class UserController extends BaseController */ public function login() { +// $user = User::find(1); +// Auth::login($user); +// /** @var Firefly\Helper\Migration\MigrationHelperInterface $migration */ +// $migration = App::make('Firefly\Helper\Migration\MigrationHelperInterface'); +// $file = '/Library/WebServer/Documents/projects/firefly-iii/app/storage/firefly-export-2014-07-03.json'; +// $migration->loadFile($file); +// if($migration->validFile()) { +// $migration->migrate(); +// } + + return View::make('user.login'); } diff --git a/app/database/migrations/2014_06_27_163817_create_components_table.php b/app/database/migrations/2014_06_27_163817_create_components_table.php index c22acbb31d..2b1a473d12 100644 --- a/app/database/migrations/2014_06_27_163817_create_components_table.php +++ b/app/database/migrations/2014_06_27_163817_create_components_table.php @@ -18,18 +18,13 @@ class CreateComponentsTable extends Migration { $table->timestamps(); $table->string('name',50); $table->integer('user_id')->unsigned(); - $table->integer('component_type_id')->unsigned(); + $table->string('class',20); // connect components to users $table->foreign('user_id') ->references('id')->on('users') ->onDelete('cascade'); - - // connect components to component types - $table->foreign('component_type_id') - ->references('id')->on('component_types') - ->onDelete('cascade'); - }); + }); } /** diff --git a/app/database/migrations/2014_07_05_100651_create_piggybanks_table.php b/app/database/migrations/2014_07_05_100651_create_piggybanks_table.php new file mode 100644 index 0000000000..4d3ae7bd35 --- /dev/null +++ b/app/database/migrations/2014_07_05_100651_create_piggybanks_table.php @@ -0,0 +1,46 @@ +increments('id'); + $table->timestamps(); + $table->integer('account_id')->unsigned(); + $table->date('targetdate')->nullable(); + $table->string('name', 500); + $table->decimal('amount', 10, 2); + $table->decimal('target', 10, 2)->nullable(); + $table->integer('order')->unsigned(); + + // connect account to piggybank. + $table->foreign('account_id') + ->references('id')->on('accounts') + ->onDelete('cascade'); + + } + ); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('piggybanks'); + } + +} diff --git a/app/database/migrations/2014_06_27_163734_create_component_types_table.php b/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php similarity index 64% rename from app/database/migrations/2014_06_27_163734_create_component_types_table.php rename to app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php index d7b66ca46b..0a344e985b 100644 --- a/app/database/migrations/2014_06_27_163734_create_component_types_table.php +++ b/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php @@ -3,7 +3,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; -class CreateComponentTypesTable extends Migration { +class CreateRecurringTransactionsTable extends Migration { /** * Run the migrations. @@ -12,11 +12,10 @@ class CreateComponentTypesTable extends Migration { */ public function up() { - Schema::create('component_types', function(Blueprint $table) + Schema::create('recurringtransactions', function(Blueprint $table) { $table->increments('id'); $table->timestamps(); - $table->string('type',50); }); } @@ -27,7 +26,7 @@ class CreateComponentTypesTable extends Migration { */ public function down() { - Schema::drop('component_types'); + Schema::drop('recurringtransactions'); } } diff --git a/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php b/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php new file mode 100644 index 0000000000..df9b0ff525 --- /dev/null +++ b/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php @@ -0,0 +1,43 @@ +increments('id'); + $table->integer('component_id')->unsigned(); + $table->integer('transaction_journal_id')->unsigned(); + + // link components with component_id + $table->foreign('component_id') + ->references('id')->on('components') + ->onDelete('cascade'); + + // link transaction journals with transaction_journal_id + $table->foreign('transaction_journal_id') + ->references('id')->on('transaction_journals') + ->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('component_transaction_journal'); + } + +} diff --git a/app/database/seeds/ComponentTypeSeeder.php b/app/database/seeds/ComponentTypeSeeder.php deleted file mode 100644 index 58dd2f7139..0000000000 --- a/app/database/seeds/ComponentTypeSeeder.php +++ /dev/null @@ -1,16 +0,0 @@ -delete(); - - ComponentType::create(['type' => 'category']); - ComponentType::create(['type' => 'budget']); - } - -} \ No newline at end of file diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php index e4af46af43..bc31d0998e 100644 --- a/app/database/seeds/DatabaseSeeder.php +++ b/app/database/seeds/DatabaseSeeder.php @@ -15,7 +15,6 @@ class DatabaseSeeder extends Seeder $this->call('AccountTypeSeeder'); $this->call('TransactionCurrencySeeder'); $this->call('TransactionTypeSeeder'); - $this->call('ComponentTypeSeeder'); $this->call('DefaultUserSeeder'); } diff --git a/app/lib/Firefly/Database/SingleTableInheritanceEntity.php b/app/lib/Firefly/Database/SingleTableInheritanceEntity.php new file mode 100644 index 0000000000..244710539f --- /dev/null +++ b/app/lib/Firefly/Database/SingleTableInheritanceEntity.php @@ -0,0 +1,78 @@ +mapData((array)$attributes)->newInstance(array(), true); + $instance->setRawAttributes((array)$attributes, true); + return $instance; + } + + // if no subclass is defined, function as normal + + public function mapData(array $attributes) + { + if (!$this->subclassField) { + return $this->newInstance(); + } + + return new $attributes[$this->subclassField]; + } + + // instead of using $this->newInstance(), call + // newInstance() on the object from mapData + + public function newQuery($excludeDeleted = true) + { + // If using Laravel 4.0.x then use the following commented version of this command + // $builder = new Builder($this->newBaseQueryBuilder()); + // newEloquentBuilder() was added in 4.1 + $builder = $this->newEloquentBuilder($this->newBaseQueryBuilder()); + + // Once we have the query builders, we will set the model instances so the + // builder can easily access any information it may need from the model + // while it is constructing and executing various queries against it. + $builder->setModel($this)->with($this->with); + + if ($excludeDeleted && $this->softDelete) { + $builder->whereNull($this->getQualifiedDeletedAtColumn()); + } + + if ($this->subclassField && $this->isSubclass()) { + $builder->where($this->subclassField, '=', get_class($this)); + } + + return $builder; + } + + public function isSubclass() + { + return $this->isSubclass; + } + + // ensure that the subclass field is assigned on save + + public function save(array $options = array()) + { + if ($this->subclassField) { + $this->attributes[$this->subclassField] = get_class($this); + } + return parent::save($options); + } +} \ No newline at end of file diff --git a/app/lib/Firefly/Helper/Migration/MigrationHelper.php b/app/lib/Firefly/Helper/Migration/MigrationHelper.php index 3336485f16..368ccf8cdc 100644 --- a/app/lib/Firefly/Helper/Migration/MigrationHelper.php +++ b/app/lib/Firefly/Helper/Migration/MigrationHelper.php @@ -49,9 +49,18 @@ class MigrationHelper implements MigrationHelperInterface \DB::beginTransaction(); try { + // create cash account: + $this->_createCashAccount(); + $this->_importAccounts(); $this->_importComponents(); - $this->_importPiggybanks(); + //$this->_importPiggybanks(); + + // create transactions: + $this->_importTransactions(); + + // create transfers: + $this->_importTransfers(); } catch (\Firefly\Exception\FireflyException $e) { @@ -66,6 +75,15 @@ class MigrationHelper implements MigrationHelperInterface return true; } + protected function _createCashAccount() + { + $cashAT = \AccountType::where('description', 'Cash account')->first(); + /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */ + $accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + $cash = $accounts->store(['name' => 'Cash account', 'account_type' => $cashAT, 'active' => false]); + $this->map['cash'] = $cash; + } + protected function _importAccounts() { @@ -83,7 +101,7 @@ class MigrationHelper implements MigrationHelperInterface floatval($entry->openingbalance) ); } - $this->map['accounts'][$entry->id] = $account->id; + $this->map['accounts'][$entry->id] = $account; \Log::info('Imported account "' . $entry->name . '" with balance ' . $entry->openingbalance); } } @@ -91,38 +109,25 @@ class MigrationHelper implements MigrationHelperInterface protected function _importComponents() { $beneficiaryAT = \AccountType::where('description', 'Beneficiary account')->first(); - $budgetType = \ComponentType::where('type', 'budget')->first(); - $categoryType = \ComponentType::where('type', 'category')->first(); foreach ($this->JSON->components as $entry) { switch ($entry->type->type) { case 'beneficiary': $beneficiary = $this->_importBeneficiary($entry, $beneficiaryAT); - $this->map['accounts'][$entry->id] = $beneficiary->id; + $this->map['accounts'][$entry->id] = $beneficiary; break; case 'category': - $component = $this->_importComponent($entry, $categoryType); - $this->map['components'][$entry->id] = $component->id; + $component = $this->_importCategory($entry); + $this->map['categories'][$entry->id] = $component; break; case 'budget': - $component = $this->_importComponent($entry, $budgetType); - $this->map['components'][$entry->id] = $component->id; + $component = $this->_importBudget($entry); + $this->map['budgets'][$entry->id] = $component; break; } } } - protected function _importPiggybanks() { - - /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */ - $accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); - - // get type for piggy: - $piggyAT = \AccountType::where('description', 'Piggy bank')->first(); - foreach($this->JSON->piggybanks as $piggyBank) { - } - } - protected function _importBeneficiary($component, \AccountType $beneficiaryAT) { /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */ @@ -135,10 +140,98 @@ class MigrationHelper implements MigrationHelperInterface ); } - protected function _importComponent($component, \ComponentType $type) + protected function _importCategory($component) { /** @var \Firefly\Storage\Component\ComponentRepositoryInterface $components */ $components = \App::make('Firefly\Storage\Component\ComponentRepositoryInterface'); - return $components->store(['name' => $component->name, 'component_type' => $type]); + return $components->store(['name' => $component->name, 'class' => 'Category']); + } + + protected function _importBudget($component) + { + /** @var \Firefly\Storage\Component\ComponentRepositoryInterface $components */ + $components = \App::make('Firefly\Storage\Component\ComponentRepositoryInterface'); + return $components->store(['name' => $component->name, 'class' => 'Budget']); + } + + protected function _importTransactions() + { + + /** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $journals */ + $journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); + + // loop component_transaction to find beneficiaries, categories and budgets: + $beneficiaries = []; + $categories = []; + $budgets = []; + foreach ($this->JSON->component_transaction as $entry) { + // beneficiaries + if (isset($this->map['accounts'][$entry->component_id])) { + $beneficiaries[$entry->transaction_id] = $this->map['accounts'][$entry->component_id]; + } + + // categories + if (isset($this->map['categories'][$entry->component_id])) { + $categories[$entry->transaction_id] = $this->map['categories'][$entry->component_id]; + } + + // budgets: + if (isset($this->map['budgets'][$entry->component_id])) { + $budgets[$entry->transaction_id] = $this->map['budgets'][$entry->component_id]; + } + } + + foreach ($this->JSON->transactions as $entry) { + $id = $entry->id; + + // to properly save the amount, do it times -1: + $amount = $entry->amount * -1; + + /** @var \Account $fromAccount */ + $fromAccount = isset($this->map['accounts'][$entry->account_id]) + ? $this->map['accounts'][$entry->account_id] : false; + + /** @var \Account $toAccount */ + $toAccount = isset($beneficiaries[$entry->id]) ? $beneficiaries[$entry->id] : $this->map['cash']; + + $date = new \Carbon\Carbon($entry->date); + $journal = $journals->createSimpleJournal($fromAccount, $toAccount, $entry->description, $amount, $date); + + // save budgets and categories, on the journal + if(isset($budgets[$entry->id])) { + $budget = $budgets[$entry->id]; + $journal->budgets()->save($budget); + } + if(isset($categories[$entry->id])) { + $category = $categories[$entry->id]; + $journal->categories()->save($category); + } + + } + } + + protected function _importTransfers() + { + /** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $journals */ + $journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); + + foreach ($this->JSON->transfers as $entry) { + $id = $entry->id; + + // to properly save the amount, do it times 1 (?): + $amount = $entry->amount * -1; + + /** @var \Account $fromAccount */ + $fromAccount = isset($this->map['accounts'][$entry->accountfrom_id]) + ? $this->map['accounts'][$entry->accountto_id] : false; + + /** @var \Account $toAccount */ + $toAccount = isset($this->map['accounts'][$entry->accountto_id]) + ? $this->map['accounts'][$entry->accountfrom_id] : false; + + $date = new \Carbon\Carbon($entry->date); + $journals->createSimpleJournal($fromAccount, $toAccount, $entry->description, $amount, $date); + + } } } \ No newline at end of file diff --git a/app/lib/Firefly/Storage/Account/AccountRepositoryInterface.php b/app/lib/Firefly/Storage/Account/AccountRepositoryInterface.php index 61aefb607c..27ebff7eb8 100644 --- a/app/lib/Firefly/Storage/Account/AccountRepositoryInterface.php +++ b/app/lib/Firefly/Storage/Account/AccountRepositoryInterface.php @@ -9,6 +9,8 @@ interface AccountRepositoryInterface public function count(); + public function get(); + public function store($data); public function storeWithInitialBalance($data,\Carbon\Carbon $date, $amount = 0); diff --git a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php index 81e5ee3d60..2a7a2ca5e1 100644 --- a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php +++ b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php @@ -13,6 +13,10 @@ class EloquentAccountRepository implements AccountRepositoryInterface { } + public function get() { + return \Auth::user()->accounts()->get(); + } + public function count() { return \Auth::user()->accounts()->count(); diff --git a/app/lib/Firefly/Storage/Component/EloquentComponentRepository.php b/app/lib/Firefly/Storage/Component/EloquentComponentRepository.php index 58f980a1b5..138af1f028 100644 --- a/app/lib/Firefly/Storage/Component/EloquentComponentRepository.php +++ b/app/lib/Firefly/Storage/Component/EloquentComponentRepository.php @@ -20,18 +20,26 @@ class EloquentComponentRepository implements ComponentRepositoryInterface public function store($data) { - if (!isset($data['component_type'])) { - throw new \Firefly\Exception\FireflyException('No component type present.'); + if (!isset($data['class'])) { + throw new \Firefly\Exception\FireflyException('No class type present.'); + } + switch ($data['class']) { + case 'Budget': + $component = new \Budget; + break; + case 'Category': + $component = new \Category; + break; + } - $component = new \Component; - $component->componentType()->associate($data['component_type']); $component->name = $data['name']; $component->user()->associate(\Auth::user()); try { $component->save(); } catch (\Illuminate\Database\QueryException $e) { \Log::error('DB ERROR: ' . $e->getMessage()); - throw new \Firefly\Exception\FireflyException('Could not save component ' . $data['name']); + throw new \Firefly\Exception\FireflyException('Could not save component ' . $data['name'] . ' of type' + . $data['class']); } return $component; diff --git a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php index 515cb5ad38..3311d5f9b0 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php +++ b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php @@ -15,7 +15,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito public function createSimpleJournal(\Account $from, \Account $to, $description, $amount, \Carbon\Carbon $date) { - + \Log::debug('Creating tranaction "'.$description.'".'); /* * We're building this thinking the money goes from A to B. * If the amount is negative however, the money still goes @@ -67,6 +67,10 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito $journalType = \TransactionType::where('type', 'Deposit')->first(); break; } + + // some debug information: + \Log::debug($journalType->type.': AccountFrom "'.$from->name.'" will gain/lose '.$amountFrom.' and AccountTo "'.$to->name.'" will gain/lose '.$amountTo); + if (is_null($journalType)) { \Log::error('Could not figure out transacion type!'); throw new \Firefly\Exception\FireflyException('Could not figure out transaction type.'); @@ -122,10 +126,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito $journal->completed = true; $journal->save(); - return; - - - echo 'saved!'; - + return $journal; } } \ No newline at end of file diff --git a/app/models/Budget.php b/app/models/Budget.php new file mode 100644 index 0000000000..7e0cfb5cd1 --- /dev/null +++ b/app/models/Budget.php @@ -0,0 +1,14 @@ + 'exists:users,id|required', @@ -11,15 +15,14 @@ class Component extends Elegant ]; - public function componentType() - { - return $this->belongsTo('ComponentType'); - } - public function transactions() { return $this->belongsToMany('Transaction'); } + public function transactionjournals() + { + return $this->belongsToMany('TransactionJournal'); + } public function user() { diff --git a/app/models/ComponentType.php b/app/models/ComponentType.php deleted file mode 100644 index 4e2e49a8d0..0000000000 --- a/app/models/ComponentType.php +++ /dev/null @@ -1,11 +0,0 @@ -hasMany('Component'); - } - -} \ No newline at end of file diff --git a/app/models/Transaction.php b/app/models/Transaction.php index 06aa3732b1..54e1df081d 100644 --- a/app/models/Transaction.php +++ b/app/models/Transaction.php @@ -26,4 +26,13 @@ class Transaction extends Elegant { return $this->belongsToMany('Component'); } + + public function budgets() + { + return $this->belongsToMany('Budget'); + } + public function categories() + { + return $this->belongsToMany('Category'); + } } \ No newline at end of file diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php index 099fd09a9b..a99ce4e022 100644 --- a/app/models/TransactionJournal.php +++ b/app/models/TransactionJournal.php @@ -28,6 +28,21 @@ class TransactionJournal extends Elegant return $this->hasMany('Transaction'); } + public function components() + { + return $this->belongsToMany('Component'); + } + + public function budgets() + { + return $this->belongsToMany('Budget','component_transaction_journal','transaction_journal_id','component_id'); + } + + public function categories() + { + return $this->belongsToMany('Category','component_transaction_journal','transaction_journal_id','component_id'); + } + public function getDates() { return array('created_at', 'updated_at', 'date'); diff --git a/app/routes.php b/app/routes.php index ed721149db..169583074f 100644 --- a/app/routes.php +++ b/app/routes.php @@ -15,10 +15,13 @@ Route::group(['before' => 'auth'], function () { // migration controller Route::get('/migrate', ['uses' => 'MigrationController@index', 'as' => 'migrate']); + + // account controller: + Route::get('/accounts/create', ['uses' => 'AccountController@create', 'as' => 'accounts.create']); } ); -// protected + csrf routes +// protected + csrf routes (POST) Route::group(['before' => 'csrf|auth'], function () { // profile controller Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword']); @@ -26,6 +29,9 @@ Route::group(['before' => 'csrf|auth'], function () { // migration controller Route::post('/migrate', ['uses' => 'MigrationController@postIndex']); + // account controller: + Route::get('/accounts/store', ['uses' => 'AccountController@store', 'as' => 'accounts.store']); + } ); diff --git a/app/tests/controllers/AccountControllerTest.php b/app/tests/controllers/AccountControllerTest.php new file mode 100644 index 0000000000..2272fbd225 --- /dev/null +++ b/app/tests/controllers/AccountControllerTest.php @@ -0,0 +1,19 @@ +with('accounts.create'); + + // call + $this->call('GET', '/accounts/create'); + + // test + $this->assertResponseOk(); + } +} \ No newline at end of file diff --git a/app/tests/controllers/MigrationControllerTest.php b/app/tests/controllers/MigrationControllerTest.php new file mode 100644 index 0000000000..41fe0bbac3 --- /dev/null +++ b/app/tests/controllers/MigrationControllerTest.php @@ -0,0 +1,21 @@ +with('migrate.index'); + + // call + $this->call('GET', '/migrate'); + + // test + $this->assertResponseOk(); + } +} \ No newline at end of file diff --git a/app/tests/controllers/UserControllerTest.php b/app/tests/controllers/UserControllerTest.php index 5d80be2ed7..bed7d1fc54 100644 --- a/app/tests/controllers/UserControllerTest.php +++ b/app/tests/controllers/UserControllerTest.php @@ -211,34 +211,6 @@ class UserControllerTest extends TestCase } - public function testVerification() - { - - $repository = $this->mock('Firefly\Storage\User\UserRepositoryInterface'); - $email = $this->mock('Firefly\Helper\Email\EmailHelper'); - - $repository->shouldReceive('findByVerification')->once()->andReturn(new User); - $email->shouldReceive('sendPasswordMail')->once()->andReturn(true); - - // test - $crawler = $this->client->request('GET', '/verify/blabla'); - $this->assertTrue($this->client->getResponse()->isOk()); - $this->assertCount(1, $crawler->filter('h1:contains("Password sent")')); - - } - - public function testVerificationFails() - { - $repository = $this->mock('Firefly\Storage\User\UserRepositoryInterface'); - $repository->shouldReceive('findByVerification')->once()->andReturn(null); - - // test - $crawler = $this->client->request('GET', '/verify/blabla'); - $this->assertTrue($this->client->getResponse()->isOk()); - $this->assertCount(1, $crawler->filter('h1:contains("Error")')); - $this->assertViewHas('message'); - } - public function testReset() { diff --git a/app/views/accounts/create-first-time.blade.php b/app/views/accounts/create.blade.php similarity index 100% rename from app/views/accounts/create-first-time.blade.php rename to app/views/accounts/create.blade.php