mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	First attempt at an import/migration procedure.
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
|  | ||||
| return [ | ||||
|     'verify_mail' => true, | ||||
|     'verify_mail' => false, | ||||
|     'verify_reset' => true, | ||||
|     'allow_register' => true | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon as Carbon; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
|  | ||||
| class HomeController extends BaseController { | ||||
| @@ -10,6 +10,7 @@ class HomeController extends BaseController { | ||||
|  | ||||
| 	public function index() | ||||
| 	{ | ||||
| 		return View::make('index'); | ||||
|         $count = $this->accounts->count(); | ||||
| 		return View::make('index')->with('count',$count); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -19,6 +19,7 @@ class CreateTransactionJournalsTable extends Migration { | ||||
|             $table->integer('transaction_type_id')->unsigned(); | ||||
|             $table->integer('transaction_currency_id')->unsigned(); | ||||
|             $table->string('description',255)->nullable(); | ||||
|             $table->boolean('completed'); | ||||
|             $table->date('date'); | ||||
|  | ||||
|             // connect transaction journals to transaction types | ||||
|   | ||||
| @@ -9,6 +9,7 @@ interface AccountRepositoryInterface | ||||
|  | ||||
|     public function count(); | ||||
|  | ||||
|     public function store(); | ||||
|     public function store($data); | ||||
|     public function storeWithInitialBalance($data,\Carbon\Carbon $date, $amount = 0); | ||||
|  | ||||
| }  | ||||
| @@ -11,53 +11,51 @@ class EloquentAccountRepository implements AccountRepositoryInterface | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     public function count() { | ||||
|     public function count() | ||||
|     { | ||||
|         return \Auth::user()->accounts()->count(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function store() { | ||||
|     public function storeWithInitialBalance($data, \Carbon\Carbon $date, $amount = 0) | ||||
|     { | ||||
|  | ||||
|         $account = $this->store($data); | ||||
|  | ||||
|         $initialBalanceAT = \AccountType::where('description', 'Initial balance account')->first(); | ||||
|         $initial = new \Account; | ||||
|         $initial->accountType()->associate($initialBalanceAT); | ||||
|         $initial->user()->associate(\Auth::user()); | ||||
|         $initial->name = $data['name'] . ' initial balance'; | ||||
|         $initial->active = 0; | ||||
|         $initial->save(); | ||||
|  | ||||
|         // create new transaction journal (and transactions): | ||||
|         /** @var \Firefly\Storage\TransactionJournal\TransactionJournalInterface $transactionJournal */ | ||||
|         $transactionJournal = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalInterface'); | ||||
|         $transactionJournal->createSimpleJournal( | ||||
|             $initial, $account, 'Initial Balance for ' . $data['name'], $amount, $date | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         $default = \AccountType::where('description','Default account')->first(); | ||||
|         $balanceAT = \AccountType::where('description','Initial balance account')->first(); | ||||
|         return $account; | ||||
|  | ||||
|         $account = new \Account; | ||||
|         $account->active = true; | ||||
|  | ||||
|         $account->user()->associate(\Auth::user()); | ||||
|         $account->name = \Input::get('name'); | ||||
|         $account->accountType()->associate($default); | ||||
|  | ||||
|         if(!$account->isValid()) { | ||||
|             \Log::error('Could not create account: ' . $account->validator->messages()->first()); | ||||
|             $this->validator = $account->validator; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         $account->save(); | ||||
|  | ||||
|         $balance = floatval(\Input::get('openingbalance')); | ||||
|         if($balance != 0.00) { | ||||
|             // create account | ||||
|             $initial = new \Account; | ||||
|             $account->active = false; | ||||
|  | ||||
|             $account->user()->associate(\Auth::user()); | ||||
|             $account->name = \Input::get('name').' initial balance'; | ||||
|             $account->accountType()->associate($balanceAT); | ||||
|             $account->save(); | ||||
|  | ||||
|             // create journal (access helper!) | ||||
|  | ||||
|  | ||||
|             // create journal | ||||
|  | ||||
|             // create transaction | ||||
|  | ||||
|             // create | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function store($data) | ||||
|     { | ||||
|         $defaultAT = \AccountType::where('description', 'Default account')->first(); | ||||
|  | ||||
|         $at = isset($data['account_type']) ? $data['account_type'] : $defaultAT; | ||||
|  | ||||
|         $account = new \Account; | ||||
|         $account->accountType()->associate($at); | ||||
|         $account->user()->associate(\Auth::user()); | ||||
|         $account->name = $data['name']; | ||||
|         $account->active = isset($data['active']) ? $data['active'] : 1; | ||||
|         $account->save(); | ||||
|         return $account; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -20,6 +20,10 @@ class StorageServiceProvider extends ServiceProvider | ||||
|             'Firefly\Storage\Account\AccountRepositoryInterface', | ||||
|             'Firefly\Storage\Account\EloquentAccountRepository' | ||||
|         ); | ||||
|         $this->app->bind( | ||||
|             'Firefly\Storage\TransactionJournal\TransactionJournalInterface', | ||||
|             'Firefly\Storage\TransactionJournal\EloquentTransactionJournalRepository' | ||||
|         ); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,114 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 03/07/14 | ||||
|  * Time: 15:24 | ||||
|  */ | ||||
|  | ||||
| namespace Firefly\Storage\TransactionJournal; | ||||
|  | ||||
|  | ||||
| class EloquentTransactionJournalRepository implements TransactionJournalInterface | ||||
| { | ||||
|  | ||||
|     public function createSimpleJournal(\Account $from, \Account $to, $description, $amount, \Carbon\Carbon $date) | ||||
|     { | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * We're building this thinking the money goes from A to B. | ||||
|          * If the amount is negative however, the money still goes | ||||
|          * from A to B but the balances are reversed. | ||||
|          * | ||||
|          * Aka: | ||||
|          * | ||||
|          * Amount = 200 | ||||
|          * A loses 200 (-200).  * -1 | ||||
|          * B gains 200 (200).    * 1 | ||||
|          * | ||||
|          * Final balance: -200 for A, 200 for B. | ||||
|          * | ||||
|          * When the amount is negative: | ||||
|          * | ||||
|          * Amount = -200 | ||||
|          * A gains 200 (200). * -1 | ||||
|          * B loses 200 (-200). * 1 | ||||
|          * | ||||
|          */ | ||||
|  | ||||
|         // amounts: | ||||
|         $amountFrom = $amount * -1; | ||||
|         $amountTo = $amount; | ||||
|  | ||||
|         // account types for both: | ||||
|         $toAT = $to->accountType->description; | ||||
|         $fromAT = $from->accountType->description; | ||||
|  | ||||
|  | ||||
|         switch (true) { | ||||
|             // is withdrawal from one of your own accounts: | ||||
|             case ($fromAT == 'Default account'): | ||||
|                 $journalType = \TransactionType::where('type', 'Withdrawal')->first(); | ||||
|                 break; | ||||
|             // both are yours: | ||||
|             case ($fromAT == 'Default account' && $toAT == 'Default account'): | ||||
|                 // determin transaction type. If both accounts are new, it's an initial | ||||
|                 // balance transfer. | ||||
|                 $journalType = \TransactionType::where('type', 'Transfer')->first(); | ||||
|                 break; | ||||
|             case ($from->transactions()->count() == 0 && $to->transactions()->count() == 0): | ||||
|                 $journalType = \TransactionType::where('type', 'Opening balance')->first(); | ||||
|                 break; | ||||
|             default: | ||||
|                 // is deposit into one of your own accounts: | ||||
|             case ($toAT == 'Default account'): | ||||
|                 $journalType = \TransactionType::where('type', 'Deposit')->first(); | ||||
|                 break; | ||||
|         } | ||||
|         // always the same currency: | ||||
|         $currency = \TransactionCurrency::where('code', 'EUR')->first(); | ||||
|  | ||||
|         // new journal: | ||||
|         $journal = new \TransactionJournal(); | ||||
|         $journal->transactionType()->associate($journalType); | ||||
|         $journal->transactionCurrency()->associate($currency); | ||||
|         $journal->completed = false; | ||||
|         $journal->description = $description; | ||||
|         $journal->date = $date; | ||||
|         if (!$journal->isValid()) { | ||||
|             return false; | ||||
|         } | ||||
|         $journal->save(); | ||||
|  | ||||
|         // create transactions: | ||||
|         $fromTransaction = new \Transaction; | ||||
|         $fromTransaction->account()->associate($from); | ||||
|         $fromTransaction->transactionJournal()->associate($journal); | ||||
|         $fromTransaction->description = null; | ||||
|         $fromTransaction->amount = $amountFrom; | ||||
|         if (!$fromTransaction->isValid()) { | ||||
|             return false; | ||||
|         } | ||||
|         $fromTransaction->save(); | ||||
|  | ||||
|         $toTransaction = new \Transaction; | ||||
|         $toTransaction->account()->associate($to); | ||||
|         $toTransaction->transactionJournal()->associate($journal); | ||||
|         $toTransaction->description = null; | ||||
|         $toTransaction->amount = $amountTo; | ||||
|         if (!$toTransaction->isValid()) { | ||||
|             return false; | ||||
|         } | ||||
|         $toTransaction->save(); | ||||
|  | ||||
|         $journal->completed = true; | ||||
|         $journal->save(); | ||||
|         return; | ||||
|  | ||||
|  | ||||
|  | ||||
|         echo 'saved!'; | ||||
|  | ||||
|     } | ||||
| }  | ||||
| @@ -0,0 +1,16 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 03/07/14 | ||||
|  * Time: 15:22 | ||||
|  */ | ||||
|  | ||||
| namespace Firefly\Storage\TransactionJournal; | ||||
|  | ||||
|  | ||||
| interface TransactionJournalInterface { | ||||
|  | ||||
|     public function createSimpleJournal(\Account $from, \Account $to, $description, $amount, \Carbon\Carbon $date); | ||||
|  | ||||
| }  | ||||
| @@ -1,8 +1,16 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| class Transaction extends Eloquent | ||||
| class Transaction extends Elegant | ||||
| { | ||||
|     public static $rules | ||||
|         = [ | ||||
|             'account_id'             => 'numeric|required|exists:accounts,id', | ||||
|             'transaction_journal_id' => 'numeric|required|exists:transaction_journals,id', | ||||
|             'description'            => 'between:1,255', | ||||
|             'amount'                 => 'required|between:-65536,65536', | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|     public function account() | ||||
|     { | ||||
|   | ||||
| @@ -1,17 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
|  | ||||
| class TransactionJournal extends Eloquent { | ||||
| class TransactionJournal extends Elegant | ||||
| { | ||||
|  | ||||
|     public function transactionType() { | ||||
|     public static $rules | ||||
|         = [ | ||||
|             'transaction_type_id'     => 'required|exists:transaction_types,id', | ||||
|             'transaction_currency_id' => 'required|exists:transaction_currencies,id', | ||||
|             'description'             => 'between:1,255', | ||||
|             'date'                    => 'date', | ||||
|         ]; | ||||
|  | ||||
|     public function transactionType() | ||||
|     { | ||||
|         return $this->belongsTo('TransactionType'); | ||||
|     } | ||||
|     public function transactionCurrency() { | ||||
|  | ||||
|     public function transactionCurrency() | ||||
|     { | ||||
|         return $this->belongsTo('TransactionCurrency'); | ||||
|     } | ||||
|  | ||||
|     public function transactions() { | ||||
|     public function transactions() | ||||
|     { | ||||
|         return $this->hasMany('Transaction'); | ||||
|     } | ||||
|  | ||||
|     public function getDates() | ||||
|     { | ||||
|         return array('created_at', 'updated_at', 'date'); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| @@ -17,4 +17,8 @@ Route::post('/remindme',['uses' => 'UserController@postRemindme','before' => 'cs | ||||
| // profile (after login / logout) | ||||
| Route::get('/profile',['uses' => 'ProfileController@index','as' => 'profile','before' => 'auth']); | ||||
| Route::get('/profile/change-password',['uses' => 'ProfileController@changePassword','as' => 'change-password','before' => 'auth']); | ||||
| Route::post('/profile/change-password',['uses' => 'ProfileController@postChangePassword','before' => 'csrf|auth']); | ||||
| Route::post('/profile/change-password',['uses' => 'ProfileController@postChangePassword','before' => 'csrf|auth']); | ||||
|  | ||||
| // migrate controller: | ||||
| Route::get('/migrate',['uses' => 'MigrationController@index','as' => 'migrate','before' => 'auth']); | ||||
| Route::post('/migrate',['uses' => 'MigrationController@postIndex','before' => 'csrf|auth']); | ||||
| @@ -2,11 +2,41 @@ | ||||
| @section('content') | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <h1>Firefly<br/> | ||||
|         <h1>Firefly | ||||
|             @if($count > 0) | ||||
|             <br/> | ||||
|             <small>What's playing?</small> | ||||
|             @endif | ||||
|         </h1> | ||||
|     </div> | ||||
| </div> | ||||
| @if($count == 0) | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <p class="lead">Welcome to Firefly III.</p> | ||||
|         <p> | ||||
|             To get get started, choose below: | ||||
|         </p> | ||||
|     </div> | ||||
| </div> | ||||
| <div class="row"> | ||||
|     <div class="col-lg-6 col-md-6 col-sm-12"> | ||||
|         <h2><a href="{{route('migrate')}}">Migrate from Firefly II</a></h2> | ||||
|         <p> | ||||
|             Use this option if you have a JSON file from your current Firefly II installation. | ||||
|         </p> | ||||
|     </div> | ||||
|     <div class="col-lg-6 col-md-6 col-sm-12"> | ||||
|         <h2><a href="#">Start from scratch</a></h2> | ||||
|         <p> | ||||
|             Use this option if you are new to Firefly (III). | ||||
|         </p> | ||||
|     </div> | ||||
| @else | ||||
|  | ||||
|  | ||||
| @endif | ||||
|  | ||||
| @stop | ||||
| @section('scripts') | ||||
| @stop | ||||
| @@ -3,50 +3,25 @@ | ||||
| <div class="row"> | ||||
|     <div class="col-lg-8 col-md-8 col-sm-12"> | ||||
|         <h1>Firefly<br/> | ||||
|             <small>Migration instructions</small> | ||||
|             <small>Migration</small> | ||||
|         </h1> | ||||
|         <ol> | ||||
|             <li>Open <code>app/config/database.php</code></li> | ||||
|             <li>Fill in the <code>old-firefly</code> connection records.</li> | ||||
|             <li>Refresh this page.</li> | ||||
|             <li>Upload <code>firefly-export-****-**-**.json</code></li> | ||||
|             <li>Wait..</li> | ||||
|             <li>Done!</li> | ||||
|         </ol> | ||||
|  | ||||
|         <p> | ||||
|             It should look something like this: | ||||
|         </p> | ||||
| <pre> | ||||
| return [ | ||||
|     'fetch'       => PDO::FETCH_CLASS, | ||||
|     'default'     => 'mysql', | ||||
|     'connections' => [ | ||||
|         'mysql'  => [ | ||||
|             'driver'    => 'mysql', | ||||
|             'host'      => 'localhost', | ||||
|             'database'  => '(current database)', | ||||
|             'username'  => '', | ||||
|             'password'  => '', | ||||
|             'charset'   => 'utf8', | ||||
|             'collation' => 'utf8_unicode_ci', | ||||
|             'prefix'    => '', | ||||
|         ], | ||||
|         <strong> | ||||
|         'old-firefly'  => [ | ||||
|             'driver'    => 'mysql', | ||||
|             'host'      => 'localhost', | ||||
|             'database'  => '(previous database)', | ||||
|             'username'  => '', | ||||
|             'password'  => '', | ||||
|             'charset'   => 'utf8', | ||||
|             'collation' => 'utf8_unicode_ci', | ||||
|             'prefix'    => '', | ||||
|         ],</strong> | ||||
|     ], | ||||
| </pre> | ||||
|         <p> | ||||
|             This page will disappear when the connection is valid. | ||||
|         </p> | ||||
|         <p> | ||||
|             Current error: <code>{{$error or ''}}</code> | ||||
|               | ||||
|         </p> | ||||
|         {{Form::open(['files' => true])}} | ||||
|             <div class="form-group"> | ||||
|                 <label for="exportFile">Export file</label> | ||||
|                 <input name="exportFile" type="file" id="exportFile"> | ||||
|                 <p class="help-block">Upload the export file here.</p> | ||||
|             </div> | ||||
|             <button type="submit" class="btn btn-info">Import</button> | ||||
|         {{Form::close()}} | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user