diff --git a/app/controllers/RecurringController.php b/app/controllers/RecurringController.php index a45bfb0b00..5b01dae6f3 100644 --- a/app/controllers/RecurringController.php +++ b/app/controllers/RecurringController.php @@ -1,7 +1,15 @@ _repository = $repository; + View::share('menu', 'home'); + } public function create() { } @@ -20,6 +28,8 @@ class RecurringController extends BaseController public function index() { + $list = $this->_repository->get(); + return View::make('recurring.index'); } public function show() diff --git a/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php b/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php index 9193cb8cf9..931c60b43c 100644 --- a/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php +++ b/app/database/migrations/2014_07_05_143244_create_recurring_transactions_table.php @@ -18,10 +18,15 @@ class CreateRecurringTransactionsTable extends Migration { $table->timestamps(); $table->integer('user_id')->unsigned(); $table->string('name',50); + $table->string('match',255); $table->decimal('amount_max',10,2); $table->decimal('amount_min',10,2); + $table->date('date'); $table->boolean('active'); + + $table->boolean('automatch'); $table->enum('repeat_freq', ['daily', 'weekly','monthly','quarterly','half-year','yearly']); + $table->smallInteger('skip')->unsigned(); $table->unique(['user_id','name']); diff --git a/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php b/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php index b16dfccda3..e5781b6f6d 100644 --- a/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php +++ b/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php @@ -17,6 +17,7 @@ class RecurringTransactionsToComponents extends Migration { $table->increments('id'); $table->integer('component_id')->unsigned(); $table->integer('recurring_transaction_id')->unsigned(); + $table->boolean('optional'); // link components with component_id $table->foreign('component_id') diff --git a/app/lib/Firefly/Storage/RecurringTransaction/EloquentRecurringTransactionRepository.php b/app/lib/Firefly/Storage/RecurringTransaction/EloquentRecurringTransactionRepository.php new file mode 100644 index 0000000000..3348a3c6db --- /dev/null +++ b/app/lib/Firefly/Storage/RecurringTransaction/EloquentRecurringTransactionRepository.php @@ -0,0 +1,15 @@ +recurringtransactions()->get(); + } + +} \ No newline at end of file diff --git a/app/lib/Firefly/Storage/RecurringTransaction/RecurringTransactionRepositoryInterface.php b/app/lib/Firefly/Storage/RecurringTransaction/RecurringTransactionRepositoryInterface.php new file mode 100644 index 0000000000..2706c62172 --- /dev/null +++ b/app/lib/Firefly/Storage/RecurringTransaction/RecurringTransactionRepositoryInterface.php @@ -0,0 +1,13 @@ +app->bind( + 'Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface', + 'Firefly\Storage\RecurringTransaction\EloquentRecurringTransactionRepository' + ); + $this->app->bind( 'Firefly\Storage\Account\AccountRepositoryInterface', diff --git a/app/models/RecurringTransaction.php b/app/models/RecurringTransaction.php new file mode 100644 index 0000000000..e60938e722 --- /dev/null +++ b/app/models/RecurringTransaction.php @@ -0,0 +1,33 @@ + 'required|exists:users,id', + 'name' => 'required|between:1,255', + 'match' => 'required', + 'amount_max' => 'required|between:0,65536', + 'amount_min' => 'required|between:0,65536', + 'date' => 'required|date', + 'active' => 'required|between:0,1', + 'automatch' => 'required|between:0,1', + 'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly', + 'skip' => 'required|between:0,31', + ]; + + public static $factory + = [ + 'user_id' => 'factory|User', + 'name' => 'string', + 'data' => 'string' + ]; + + public function user() + { + return $this->belongsTo('User'); + } + +} \ No newline at end of file diff --git a/app/models/User.php b/app/models/User.php index 3788c1759a..6db3d59a04 100644 --- a/app/models/User.php +++ b/app/models/User.php @@ -73,6 +73,11 @@ class User extends Ardent implements UserInterface, RemindableInterface return $this->hasMany('Account'); } + public function recurringtransactions() + { + return $this->hasMany('RecurringTransaction'); + } + public function piggybanks() { return $this->hasMany('Piggybank'); diff --git a/app/routes.php b/app/routes.php index c82f4fadb9..d843ce83e3 100644 --- a/app/routes.php +++ b/app/routes.php @@ -110,10 +110,14 @@ Route::group(['before' => 'auth'], function () { Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']); Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); + // JSON controller: + Route::get('/json/beneficiaries', ['uses' => 'JsonController@beneficiaries', 'as' => 'json.beneficiaries']); + Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']); - - // Categories controller: - + // limit controller: + Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); + Route::get('/budgets/limits/delete/{limit}',['uses' => 'LimitController@delete','as' => 'budgets.limits.delete']); + Route::get('/budgets/limits/edit/{limit}',['uses' => 'LimitController@edit','as' => 'budgets.limits.edit']); // piggy bank controller Route::get('/piggybanks',['uses' => 'PiggybankController@index','as' => 'piggybanks.index']); @@ -126,26 +130,12 @@ Route::group(['before' => 'auth'], function () { // preferences controller Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']); - // user controller - Route::get('/logout', ['uses' => 'UserController@logout', 'as' => 'logout']); - //profile controller Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']); Route::get('/profile/change-password',['uses' => 'ProfileController@changePassword', 'as' => 'change-password']); - - - - - // limit controller: - Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); - Route::get('/budgets/limits/delete/{limit}',['uses' => 'LimitController@delete','as' => 'budgets.limits.delete']); - Route::get('/budgets/limits/edit/{limit}',['uses' => 'LimitController@edit','as' => 'budgets.limits.edit']); - - // JSON controller: - Route::get('/json/beneficiaries', ['uses' => 'JsonController@beneficiaries', 'as' => 'json.beneficiaries']); - Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']); - + // recurring transactions controller + Route::get('/recurring',['uses' => 'RecurringController@index', 'as' => 'recurring.index']); // transaction controller: Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(['what' => 'withdrawal|deposit|transfer']); @@ -154,6 +144,9 @@ Route::group(['before' => 'auth'], function () { Route::get('/transaction/delete/{tj}',['uses' => 'TransactionController@delete','as' => 'transactions.delete']); Route::get('/transactions/index',['uses' => 'TransactionController@index','as' => 'transactions.index']); + // user controller + Route::get('/logout', ['uses' => 'UserController@logout', 'as' => 'logout']); + // migration controller Route::get('/migrate', ['uses' => 'MigrationController@index', 'as' => 'migrate']); @@ -177,43 +170,39 @@ Route::group(['before' => 'csrf|auth'], function () { Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']); Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']); - // profile controller - Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword']); + // limit controller: + Route::post('/budgets/limits/store/{budget?}', ['uses' => 'LimitController@store', 'as' => 'budgets.limits.store']); + Route::post('/budgets/limits/destroy/{id?}',['uses' => 'LimitController@destroy','as' => 'budgets.limits.destroy']); + Route::post('/budgets/limits/update/{id?}',['uses' => 'LimitController@update','as' => 'budgets.limits.update']); - - - - // migration controller - Route::post('/migrate', ['uses' => 'MigrationController@postIndex']); - // piggy bank controller Route::post('/piggybanks/store',['uses' => 'PiggybankController@store','as' => 'piggybanks.store']); Route::post('/piggybanks/update', ['uses' => 'PiggybankController@update','as' => 'piggybanks.update']); Route::post('/piggybanks/destroy/{piggybank}', ['uses' => 'PiggybankController@destroy','as' => 'piggybanks.destroy']); - - // preferences controller Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']); - - // limit controller: - Route::post('/budgets/limits/store/{budget?}', ['uses' => 'LimitController@store', 'as' => 'budgets.limits.store']); - Route::post('/budgets/limits/destroy/{id?}',['uses' => 'LimitController@destroy','as' => 'budgets.limits.destroy']); - Route::post('/budgets/limits/update/{id?}',['uses' => 'LimitController@update','as' => 'budgets.limits.update']); + // profile controller + Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword']); // transaction controller: - Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store']) - ->where(['what' => 'withdrawal|deposit|transfer']); + Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store'])->where(['what' => 'withdrawal|deposit|transfer']); Route::post('/transaction/update/{tj}',['uses' => 'TransactionController@update','as' => 'transactions.update']); Route::post('/transaction/destroy/{tj}',['uses' => 'TransactionController@destroy','as' => 'transactions.destroy']); + // migration controller + Route::post('/migrate', ['uses' => 'MigrationController@postIndex']); + } ); // guest routes: Route::group(['before' => 'guest'], function () { + // dev import route: + Route::get('/dev',['uses' => 'MigrationController@dev']); + // user controller Route::get('/login', ['uses' => 'UserController@login', 'as' => 'login']); Route::get('/register', ['uses' => 'UserController@register', 'as' => 'register']); @@ -221,9 +210,7 @@ Route::group(['before' => 'guest'], function () { Route::get('/reset/{reset}', ['uses' => 'UserController@reset', 'as' => 'reset']); Route::get('/remindme', ['uses' => 'UserController@remindme', 'as' => 'remindme']); - // dev import route: - Route::get('/dev',['uses' => 'MigrationController@dev']); - Route::get('/limit',['uses' => 'MigrationController@limit']); + } ); diff --git a/app/views/partials/menu/home.blade.php b/app/views/partials/menu/home.blade.php index 20c320b05b..00cf09a3e9 100644 --- a/app/views/partials/menu/home.blade.php +++ b/app/views/partials/menu/home.blade.php @@ -27,6 +27,7 @@ $r = Route::current()->getName();
We all have bills to pay. Firefly can help you organize those bills into recurring transactions, + which are exactly what the name suggests. Firefly can match new (and existing) transactions to such a recurring transaction + and help you organize these expenses into manageable groups. The front page of Firefly will show you which recurring + transactions you have missed, which are yet to come and which have been paid.
+ +Name | +Matches on | +Amount between | +Expected every | +Next expected match | +Automatch | +Active | +
---|