diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php new file mode 100644 index 0000000000..36c788973e --- /dev/null +++ b/app/Http/Controllers/BudgetController.php @@ -0,0 +1,76 @@ +startOfMonth()); + Log::debug('Budget: '. $budget->id); + Log::debug('Budget (full) ' . print_r($budget->toArray(),true)); + Log::debug('Amount:' . $amount); + Log::debug('Date: ' . $date); + $limitRepetition = $repository->updateLimitAmount($budget, $date, $amount); + + return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]); + + } + + /** + * @return mixed + */ + public function index(BudgetRepositoryInterface $repository) + { + $budgets = Auth::user()->budgets()->get(); + + // loop the budgets: + $budgets->each( + function (Budget $budget) use ($repository) { + $date = Session::get('start', Carbon::now()->startOfMonth()); + $budget->spent = $repository->spentInMonth($budget, $date); + $budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); + } + ); + + $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); + $spent = $budgets->sum('spent'); + $amount = Preferences::get('budgetIncomeTotal' . $date, 1000)->data; + $overspent = $spent > $amount; + $spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100); + $budgetMax = Preferences::get('budgetMaximum', 1000); + $budgetMaximum = $budgetMax->data; + + return View::make('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount')); + } + +} diff --git a/app/Http/breadcrumbs.php b/app/Http/breadcrumbs.php new file mode 100644 index 0000000000..126c478c30 --- /dev/null +++ b/app/Http/breadcrumbs.php @@ -0,0 +1,369 @@ +push('Home', route('index')); + } +); + +// accounts +Breadcrumbs::register( + 'accounts.index', function (Generator $breadcrumbs, $what) { + $breadcrumbs->parent('home'); + $breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what)); +} +); +Breadcrumbs::register( + 'accounts.show', function (Generator $breadcrumbs, \Account $account) { + switch ($account->accountType->type) { + default: + throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"'); + break; + case 'Default account': + case 'Asset account': + $what = 'asset'; + break; + case 'Cash account': + $what = 'cash'; + break; + case 'Expense account': + case 'Beneficiary account': + $what = 'expense'; + break; + case 'Revenue account': + $what = 'revenue'; + break; + } + $breadcrumbs->parent('accounts.index', $what); + $breadcrumbs->push(e($account->name), route('accounts.show', $account->id)); +} +); +Breadcrumbs::register( + 'accounts.delete', function (Generator $breadcrumbs, \Account $account) { + $breadcrumbs->parent('accounts.show', $account); + $breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id)); +} +); + +Breadcrumbs::register( + 'accounts.edit', function (Generator $breadcrumbs, \Account $account) { + $breadcrumbs->parent('accounts.show', $account); + $breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id)); +} +); + +// budgets. +Breadcrumbs::register( + 'budgets.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Budgets', route('budgets.index')); +} +); +Breadcrumbs::register( + 'budgets.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('budgets.index'); + $breadcrumbs->push('Create new budget', route('budgets.create')); +} +); + +Breadcrumbs::register( + 'budgets.edit', function (Generator $breadcrumbs, Budget $budget) { + $breadcrumbs->parent('budgets.show', $budget); + $breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id)); +} +); +Breadcrumbs::register( + 'budgets.delete', function (Generator $breadcrumbs, Budget $budget) { + $breadcrumbs->parent('budgets.show', $budget); + $breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id)); +} +); + +Breadcrumbs::register( + 'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) { + $breadcrumbs->parent('budgets.index'); + $breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id)); + if (!is_null($repetition)) { + $breadcrumbs->push( + DateKit::periodShow($repetition->startdate, $repetition->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id) + ); + } +} +); + +// categories +Breadcrumbs::register( + 'categories.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Categories', route('categories.index')); +} +); +Breadcrumbs::register( + 'categories.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('categories.index'); + $breadcrumbs->push('Create new category', route('categories.create')); +} +); + +Breadcrumbs::register( + 'categories.edit', function (Generator $breadcrumbs, Category $category) { + $breadcrumbs->parent('categories.show', $category); + $breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id)); +} +); +Breadcrumbs::register( + 'categories.delete', function (Generator $breadcrumbs, Category $category) { + $breadcrumbs->parent('categories.show', $category); + $breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id)); +} +); + +Breadcrumbs::register( + 'categories.show', function (Generator $breadcrumbs, Category $category) { + $breadcrumbs->parent('categories.index'); + $breadcrumbs->push(e($category->name), route('categories.show', $category->id)); + +} +); + + +// piggy banks +Breadcrumbs::register( + 'piggyBanks.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Piggy banks', route('piggyBanks.index')); +} +); +Breadcrumbs::register( + 'piggyBanks.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('piggyBanks.index'); + $breadcrumbs->push('Create new piggy bank', route('piggyBanks.create')); +} +); + +Breadcrumbs::register( + 'piggyBanks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.show', $piggyBank); + $breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggyBanks.edit', $piggyBank->id)); +} +); +Breadcrumbs::register( + 'piggyBanks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.show', $piggyBank); + $breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggyBanks.delete', $piggyBank->id)); +} +); + +Breadcrumbs::register( + 'piggyBanks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.index'); + $breadcrumbs->push(e($piggyBank->name), route('piggyBanks.show', $piggyBank->id)); + +} +); + +// preferences +Breadcrumbs::register( + 'preferences', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Preferences', route('preferences')); + +} +); + +// profile +Breadcrumbs::register( + 'profile', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Profile', route('profile')); + +} +); +Breadcrumbs::register( + 'change-password', function (Generator $breadcrumbs) { + $breadcrumbs->parent('profile'); + $breadcrumbs->push('Change your password', route('change-password')); + +} +); + +// bills +Breadcrumbs::register( + 'bills.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Bills', route('bills.index')); +} +); +Breadcrumbs::register( + 'bills.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('bills.index'); + $breadcrumbs->push('Create new bill', route('bills.create')); +} +); + +Breadcrumbs::register( + 'bills.edit', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.show', $bill); + $breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id)); +} +); +Breadcrumbs::register( + 'bills.delete', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.show', $bill); + $breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id)); +} +); + +Breadcrumbs::register( + 'bills.show', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.index'); + $breadcrumbs->push(e($bill->name), route('bills.show', $bill->id)); + +} +); + +// reminders +Breadcrumbs::register( + 'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id)); + +} +); + +// repeated expenses +Breadcrumbs::register( + 'repeated.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Repeated expenses', route('repeated.index')); +} +); +Breadcrumbs::register( + 'repeated.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('repeated.index'); + $breadcrumbs->push('Create new repeated expense', route('repeated.create')); +} +); + +Breadcrumbs::register( + 'repeated.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.show', $piggyBank); + $breadcrumbs->push('Edit ' . e($piggyBank->name), route('repeated.edit', $piggyBank->id)); +} +); +Breadcrumbs::register( + 'repeated.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.show', $piggyBank); + $breadcrumbs->push('Delete ' . e($piggyBank->name), route('repeated.delete', $piggyBank->id)); +} +); + +Breadcrumbs::register( + 'repeated.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.index'); + $breadcrumbs->push(e($piggyBank->name), route('repeated.show', $piggyBank->id)); + +} +); + +// reports +Breadcrumbs::register( + 'reports.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Reports', route('reports.index')); +} +); + +Breadcrumbs::register( + 'reports.year', function (Generator $breadcrumbs, Carbon $date) { + $breadcrumbs->parent('reports.index'); + $breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y'))); +} +); + +Breadcrumbs::register( + 'reports.month', function (Generator $breadcrumbs, Carbon $date) { + $breadcrumbs->parent('reports.index'); + $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date)); +} +); + +Breadcrumbs::register( + 'reports.budget', function (Generator $breadcrumbs, Carbon $date) { + $breadcrumbs->parent('reports.index'); + $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date)); +} +); + +// search +Breadcrumbs::register( + 'search', function (Generator $breadcrumbs, $query) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); +} +); + +// transactions +Breadcrumbs::register( + 'transactions.index', function (Generator $breadcrumbs, $what) { + $breadcrumbs->parent('home'); + + switch ($what) { + case 'expenses': + case 'withdrawal': + $subTitle = 'Expenses'; + break; + case 'revenue': + case 'deposit': + $subTitle = 'Revenue, income and deposits'; + break; + case 'transfer': + case 'transfers': + $subTitle = 'Transfers'; + break; + case 'opening balance': + $subTitle = 'Opening balances'; + break; + default: + throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs'); + } + + $breadcrumbs->push($subTitle, route('transactions.index', $what)); +} +); +Breadcrumbs::register( + 'transactions.create', function (Generator $breadcrumbs, $what) { + $breadcrumbs->parent('transactions.index', $what); + $breadcrumbs->push('Create new ' .e($what), route('transactions.create', $what)); +} +); + +Breadcrumbs::register( + 'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) { + $breadcrumbs->parent('transactions.show', $journal); + $breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id)); +} +); +Breadcrumbs::register( + 'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) { + $breadcrumbs->parent('transactions.show', $journal); + $breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id)); +} +); + +Breadcrumbs::register( + 'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) { + + $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); + $breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id)); + +} +); diff --git a/app/Http/routes.php b/app/Http/routes.php index ef3ed610f6..f9c83d1a45 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,5 +1,7 @@ where('user_id', Auth::user()->id)->first(); + } + + return null; +} +); + +Route::bind( + 'budget', function ($value, $route) { + if (Auth::check()) { + return Budget:: + where('id', $value)->where('user_id', Auth::user()->id)->first(); + } + + return null; +} +); + /** * Home Controller @@ -57,12 +81,17 @@ Route::group( * Budget Controller */ Route::get('/budgets', ['uses' => 'BudgetController@index', 'as' => 'budgets.index']); - //Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']); # extra. - //Route::get('/budgets/create', ['uses' => 'BudgetController@create', 'as' => 'budgets.create']); - //Route::get('/budgets/edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']); - //Route::get('/budgets/delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']); + Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']); # extra. + Route::get('/budgets/create', ['uses' => 'BudgetController@create', 'as' => 'budgets.create']); + Route::get('/budgets/edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']); + Route::get('/budgets/delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']); Route::get('/budgets/show/{budget}/{limitrepetition?}', ['uses' => 'BudgetController@show', 'as' => 'budgets.show']); - //Route::get('/budgets/list/noBudget', ['uses' => 'BudgetController@noBudget', 'as' => 'budgets.noBudget']); + Route::get('/budgets/list/noBudget', ['uses' => 'BudgetController@noBudget', 'as' => 'budgets.noBudget']); + Route::post('/budgets/income', ['uses' => 'BudgetController@postUpdateIncome', 'as' => 'budgets.postIncome']); + Route::post('/budgets/store', ['uses' => 'BudgetController@store', 'as' => 'budgets.store']); + Route::post('/budgets/update/{budget}', ['uses' => 'BudgetController@update', 'as' => 'budgets.update']); + Route::post('/budgets/destroy/{budget}', ['uses' => 'BudgetController@destroy', 'as' => 'budgets.destroy']); + Route::post('budgets/amount/{budget}', ['uses' => 'BudgetController@amount']); /** * Category Controller diff --git a/app/Models/Budget.php b/app/Models/Budget.php index c5eca8b87b..f915f41f04 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -34,7 +34,7 @@ class Budget extends Model */ public function limitrepetitions() { - return $this->hasManyThrough('FireflyIII\Models\LimitRepetition', 'BudgetLimit', 'budget_id'); + return $this->hasManyThrough('FireflyIII\Models\LimitRepetition', 'FireflyIII\Models\BudgetLimit', 'budget_id'); } /** diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 21995a8501..c1665ce53c 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,10 +2,16 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; +use FireflyIII\Models\BudgetLimit; +use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\Facades\Navigation; use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; + + /** * Class EventServiceProvider * @@ -61,6 +67,46 @@ class EventServiceProvider extends ServiceProvider } ); + BudgetLimit::saved(function(BudgetLimit $budgetLimit) { + + $end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0); + $end->subDay(); + + $set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->get(); + /* + * Create new LimitRepetition: + */ + if ($set->count() == 0) { + + $repetition = new LimitRepetition; + $repetition->startdate = $budgetLimit->startdate; + $repetition->enddate = $end; + $repetition->amount = $budgetLimit->amount; + $repetition->budgetLimit()->associate($budgetLimit); + + try { + $repetition->save(); + } catch (QueryException $e) { + \Log::error('Trying to save new LimitRepetition failed!'); + \Log::error($e->getMessage()); + } + } else { + if ($set->count() == 1) { + /* + * Update existing one. + */ + $repetition = $set->first(); + $repetition->amount = $budgetLimit->amount; + $repetition->save(); + + } + } + }); + + + + + } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index ce53c188a1..cbfeb35313 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -58,6 +58,7 @@ class FireflyServiceProvider extends ServiceProvider // preferences $this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository'); + $this->app->bind('FireflyIII\Repositories\Budget\BudgetRepositoryInterface', 'FireflyIII\Repositories\Budget\BudgetRepository'); $this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository'); } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php new file mode 100644 index 0000000000..135417e2bd --- /dev/null +++ b/app/Repositories/Budget/BudgetRepository.php @@ -0,0 +1,66 @@ +startOfMonth(); + $end->endOfMonth(); + $sum = floatval($budget->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1; + + return $sum; + } + + /** + * @param Budget $budget + * @param Carbon $date + * @param $amount + * + * @return LimitRepetition|null + */ + public function updateLimitAmount(Budget $budget, Carbon $date, $amount) + { + /** @var BudgetLimit $limit */ + $limit = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); + if (!$limit) { + // create one! + $limit = new BudgetLimit; + $limit->budget()->associate($budget); + $limit->startdate = $date; + $limit->amount = $amount; + $limit->repeat_freq = 'monthly'; + $limit->repeats = 0; + $limit->save(); + } else { + if ($amount > 0) { + $limit->amount = $amount; + $limit->save(); + } else { + $limit->delete(); + } + } + return $limit; + + + } +} \ No newline at end of file diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php new file mode 100644 index 0000000000..9314d4a22f --- /dev/null +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -0,0 +1,31 @@ + 'addDays', + 'weekly' => 'addWeeks', + 'week' => 'addWeeks', + 'month' => 'addMonths', + 'monthly' => 'addMonths', + 'quarter' => 'addMonths', + 'quarterly' => 'addMonths', + 'half-year' => 'addMonths', + 'year' => 'addYears', + 'yearly' => 'addYears', + ]; + $modifierMap = [ + 'quarter' => 3, + 'quarterly' => 3, + 'half-year' => 6, + ]; + if (!isset($functionMap[$repeatFreq])) { + throw new FireflyException('Cannot do addPeriod for $repeat_freq "' . $repeatFreq . '"'); + } + if (isset($modifierMap[$repeatFreq])) { + $add = $add * $modifierMap[$repeatFreq]; + } + $function = $functionMap[$repeatFreq]; + $date->$function($add); + + return $date; + } + } \ No newline at end of file diff --git a/composer.json b/composer.json index 3e09c253c6..2a358c2e1c 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ }, "require": { "laravel/framework": "5.0.*", - "davejamesmiller/laravel-breadcrumbs": "@stable", + "davejamesmiller/laravel-breadcrumbs": "~3.0", "grumpydictator/gchart": "dev-master", "michelf/php-markdown": "@stable", "watson/validating": "dev-master", diff --git a/composer.lock b/composer.lock index 1047058260..bc29b0d420 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "13cdbee2532896d10d1b3d8833f72d74", + "hash": "6399deca7bccfb38eaa5df996618bc4d", "packages": [ { "name": "barryvdh/laravel-ide-helper", @@ -187,32 +187,33 @@ }, { "name": "davejamesmiller/laravel-breadcrumbs", - "version": "2.3.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/davejamesmiller/laravel-breadcrumbs.git", - "reference": "cfcdc58ceaa8bbafa403828b8d1279d65f62799f" + "reference": "5a5d5d1b1f5780359604f7fde11bbf810ff3e9e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/davejamesmiller/laravel-breadcrumbs/zipball/cfcdc58ceaa8bbafa403828b8d1279d65f62799f", - "reference": "cfcdc58ceaa8bbafa403828b8d1279d65f62799f", + "url": "https://api.github.com/repos/davejamesmiller/laravel-breadcrumbs/zipball/5a5d5d1b1f5780359604f7fde11bbf810ff3e9e4", + "reference": "5a5d5d1b1f5780359604f7fde11bbf810ff3e9e4", "shasum": "" }, "require": { - "illuminate/support": "4.*|5.*", - "illuminate/view": "4.*|5.*", - "php": ">=5.3.0" + "illuminate/support": "5.*", + "illuminate/view": "5.*", + "php": ">=5.4.0" }, "require-dev": { - "mockery/mockery": "~0.9.0", - "phpunit/phpunit": "4.0.*", - "satooshi/php-coveralls": "~0.6.0" + "mockery/mockery": "0.9.*", + "orchestra/testbench": "3.0.*", + "phpunit/phpunit": "4.*", + "satooshi/php-coveralls": "0.6.*" }, "type": "library", "autoload": { - "psr-0": { - "DaveJamesMiller\\Breadcrumbs": "src/" + "psr-4": { + "DaveJamesMiller\\Breadcrumbs\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -231,7 +232,7 @@ "keywords": [ "laravel" ], - "time": "2014-10-26 22:36:05" + "time": "2015-02-08 21:44:39" }, { "name": "dnoegel/php-xdg-base-dir", @@ -4802,7 +4803,6 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "davejamesmiller/laravel-breadcrumbs": 0, "grumpydictator/gchart": 20, "michelf/php-markdown": 0, "watson/validating": 20, diff --git a/config/app.php b/config/app.php index 3c67782ca7..686a08138c 100644 --- a/config/app.php +++ b/config/app.php @@ -138,6 +138,7 @@ return [ 'Illuminate\Html\HtmlServiceProvider', 'Barryvdh\Debugbar\ServiceProvider', 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', + 'DaveJamesMiller\Breadcrumbs\ServiceProvider', /* * Application Service Providers... @@ -198,6 +199,8 @@ return [ 'View' => 'Illuminate\Support\Facades\View', 'Form' => 'Illuminate\Html\FormFacade', 'Html' => 'Illuminate\Html\HtmlFacade', + 'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade', + 'Preferences' => 'FireflyIII\Support\Facades\Preferences', 'Navigation' => 'FireflyIII\Support\Facades\Navigation', 'Amount' => 'FireflyIII\Support\Facades\Amount', diff --git a/public/js/budgets.js b/public/js/budgets.js new file mode 100644 index 0000000000..b4820c206d --- /dev/null +++ b/public/js/budgets.js @@ -0,0 +1,153 @@ +$(function () { + updateRanges(); + //$('input[type="range"]').change(updateSingleRange); + $('input[type="range"]').on('input', updateSingleRange); + //$('input[type="number"]').on('change', updateSingleRange); + $('input[type="number"]').on('input', updateSingleRange); + $('.updateIncome').on('click', updateIncome); + + + if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') { + googleColumnChart('chart/budget/' + budgetID + '/spending', 'budgetOverview'); + } + if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') { + googleLineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview'); + } + +}); + + +function updateSingleRange(e) { + // get some values: + var input = $(e.target); + var id = input.data('id'); + var value = parseInt(input.val()); + var spent = parseFloat($('#spent-' + id).data('value')); + + // update small display: + if (value > 0) { + // show the input: + $('#budget-info-' + id + ' span').show(); + $('#budget-info-' + id + ' input').show(); + + // update the text: + $('#budget-description-' + id).text('Budgeted: '); + } else { + // hide the input: + $('#budget-info-' + id + ' span').hide(); + $('#budget-info-' + id + ' input').hide(); + + // update the text: + $('#budget-description-' + id).html('No budget'); + } + + // update the range display text: + $('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2)); + + // send a post to Firefly to update the amount: + $.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) { + // update the link if relevant: + $('#budget-link-' + id).attr('href', 'budgets/show/' + id + '/' + data.repetition); + }); + if (input.attr('type') == 'number') { + // update the range-input: + $('#budget-range-' + id).val(value); + } else { + // update the number-input: + $('#budget-info-' + id + ' input').val(value); + } + + // update or hide the bar, whichever is necessary. + updateTotal(); + return value; +} + +function updateTotal() { + var sum = 0; + $('input[type="range"]').each(function (i, v) { + // get some values: + sum += parseInt($(v).val()); + }); + + /** + * Update total sum: + */ + var totalAmount = parseInt($('#totalAmount').data('value')); + var pct; + if (sum <= totalAmount) { + pct = sum / totalAmount * 100; + $('#progress-bar-default').css('width', pct + '%'); + $('#progress-bar-warning').css('width', '0'); + $('#progress-bar-danger').css('width', '0'); + $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger'); + } else { + // we gaan er X overheen, + + pct = totalAmount / sum * 100; + var danger = 100 - pct; + var err = 100 - danger; + $('#progress-bar-default').css('width', 0); + $('#progress-bar-warning').css('width', err + '%'); + $('#progress-bar-danger').css('width', danger + '%'); + $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success'); + } + +} + +function updateIncome(e) { + $('#monthlyBudgetModal').empty().load('budgets/income').modal('show'); + + return false; +} + +function updateRanges() { + /** + * Update all ranges. + */ + var sum = 0; + $('input[type="range"]').each(function (i, v) { + // get some values: + var input = $(v); + var id = input.data('id'); + var value = parseInt(input.val()); + + // calculate sum: + sum += value + + // update small display: + $('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2)); + + // update progress bar (if relevant) + var barHolder = $('#budget-progress-' + id); + var spent = parseFloat(barHolder.data('spent')); + + // send a post to Firefly to update the amount: + $.post('budgets/amount/' + id, {amount: value, _token: token}).success(function (data) { + }); + + }); + + /** + * Update total sum: + */ + var totalAmount = parseInt($('#totalAmount').data('value')); + if (sum <= totalAmount) { + var pct = sum / totalAmount * 100; + $('#progress-bar-default').css('width', pct + '%'); + $('#progress-bar-warning').css('width', '0'); + $('#progress-bar-danger').css('width', '0'); + $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-success').removeClass('text-danger'); + } else { + // we gaan er X overheen, + + var pct = totalAmount / sum * 100; + var danger = 100 - pct; + var err = 100 - danger; + $('#progress-bar-default').css('width', 0); + $('#progress-bar-warning').css('width', err + '%'); + $('#progress-bar-danger').css('width', danger + '%'); + $('#budgetedAmount').text('\u20AC ' + sum.toFixed(2)).addClass('text-danger').removeClass('text-success'); + } + + +} \ No newline at end of file diff --git a/resources/views/accounts/create.blade.php b/resources/views/accounts/create.blade.php index 68dc3ff298..e6ae51dd37 100644 --- a/resources/views/accounts/create.blade.php +++ b/resources/views/accounts/create.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) --}} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) !!} {!! Form::open(['class' => 'form-horizontal','id' => 'store','route' => 'accounts.store']) !!} {!! Form::hidden('what',$what) !!} diff --git a/resources/views/accounts/delete.blade.php b/resources/views/accounts/delete.blade.php index 675d6682bc..d32bc352f1 100644 --- a/resources/views/accounts/delete.blade.php +++ b/resources/views/accounts/delete.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) --}} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) !!} {!! Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('accounts.destroy',$account->id)]) !!}
diff --git a/resources/views/accounts/edit.blade.php b/resources/views/accounts/edit.blade.php index 0b296380ba..d714a0dc86 100644 --- a/resources/views/accounts/edit.blade.php +++ b/resources/views/accounts/edit.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) --}} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) !!} {!! Form::model($account, ['class' => 'form-horizontal','id' => 'update','url' => route('accounts.update',$account->id)]) !!}
diff --git a/resources/views/accounts/index.blade.php b/resources/views/accounts/index.blade.php index 628fc76b41..c0f34287a8 100644 --- a/resources/views/accounts/index.blade.php +++ b/resources/views/accounts/index.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) --}} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) !!}
diff --git a/resources/views/accounts/show.blade.php b/resources/views/accounts/show.blade.php index 0ace1f4916..2fbd79614d 100644 --- a/resources/views/accounts/show.blade.php +++ b/resources/views/accounts/show.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) --}} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) !!}
diff --git a/resources/views/budgets/create.blade.php b/resources/views/budgets/create.blade.php new file mode 100644 index 0000000000..6ba3bcf297 --- /dev/null +++ b/resources/views/budgets/create.blade.php @@ -0,0 +1,42 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) !!} +{{Form::open(['class' => 'form-horizontal','id' => 'store','url' => route('budgets.store')])}} +
+
+
+
+ Mandatory fields +
+
+ {{Form::ffText('name')}} +
+
+

+ +

+ +
+
+ +
+
+ Options +
+
+ {{Form::ffOptionsList('create','budget')}} +
+
+ +
+ +
+ + + +{{Form::close()}} + + +@stop diff --git a/resources/views/budgets/delete.blade.php b/resources/views/budgets/delete.blade.php new file mode 100644 index 0000000000..7b85429f1a --- /dev/null +++ b/resources/views/budgets/delete.blade.php @@ -0,0 +1,37 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget) !!} +{{Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('budgets.destroy',$budget->id)])}} +
+
+
+
+ Delete budget "{{{$budget->name}}}" +
+
+

+ Are you sure? +

+ +

+ + Cancel +

+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ + +{{Form::close()}} +@stop diff --git a/resources/views/budgets/edit.blade.php b/resources/views/budgets/edit.blade.php new file mode 100644 index 0000000000..0a124bad78 --- /dev/null +++ b/resources/views/budgets/edit.blade.php @@ -0,0 +1,42 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget) !!} +
+
+

Use budgets to organize and limit your expenses.

+
+
+ +{{Form::model($budget, ['class' => 'form-horizontal','id' => 'update','url' => route('budgets.update',$budget->id)])}} +
+
+
+
+ Mandatory fields +
+
+ {{Form::ffText('name')}} +
+
+

+ +

+
+
+ +
+
+ Options +
+
+ {{Form::ffOptionsList('update','budget')}} +
+
+
+
+{{Form::close()}} + + +@stop diff --git a/resources/views/budgets/income.blade.php b/resources/views/budgets/income.blade.php new file mode 100644 index 0000000000..713c61a20c --- /dev/null +++ b/resources/views/budgets/income.blade.php @@ -0,0 +1,21 @@ +
+{{Form::token()}} + +
diff --git a/resources/views/budgets/index.blade.php b/resources/views/budgets/index.blade.php new file mode 100644 index 0000000000..871f071189 --- /dev/null +++ b/resources/views/budgets/index.blade.php @@ -0,0 +1,158 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) !!} +
+
+
+
+ {{Session::get('start', \Carbon\Carbon::now()->startOfMonth())->format('F Y')}} +
+
+
+
+ Budgeted: {{Amount::format(300)}} +
+
+ Income {{Session::get('start', \Carbon\Carbon::now()->startOfMonth())->format('F Y')}}: + {!! Amount::format($amount) !!} +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Spent: {!! Amount::format($spent) !!} +
+
+
+
+
+ @if($overspent) +
+
+ @else +
+ @endif +
+
+
+ +
+
+
+
+ + @include('partials.date_nav') + + +
+
+ +
+@foreach($budgets as $budget) +
+
+
+ @if(isset($budget->currentRep)) + {{{$budget->name}}} + @else + {{{$budget->name}}} + @endif + + + +
+
+ + +
+
+ +
+
+ +

+ @if($budget->currentRep) + + @else + + @endif +

+ +

+ + + @if($budget->currentRep) + + Budgeted: + + + @if($budget->currentRep->amount > $budget->spent) + {{Amount::getCurrencySymbol()}} + @else + {{Amount::getCurrencySymbol()}} + @endif + + @else + No budget + + + + @endif + +

+

+ Spent: {!! Amount::format($budget->spent) !!} +

+
+
+
+@endforeach +
+
+
+ Create budget +
+ +
+
+ + + + + +@stop +@section('scripts') + + + +@stop diff --git a/resources/views/budgets/noBudget.blade.php b/resources/views/budgets/noBudget.blade.php new file mode 100644 index 0000000000..cda701ca37 --- /dev/null +++ b/resources/views/budgets/noBudget.blade.php @@ -0,0 +1,24 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) !!} +
+
+ + @include('partials.date_nav') +
+
+
+
+
+
+ {{{$subTitle}}} +
+
+ @include('list.journals-full',['journals' => $list]) +
+
+
+
+ + +@stop diff --git a/resources/views/budgets/show.blade.php b/resources/views/budgets/show.blade.php new file mode 100644 index 0000000000..ae119ef7ce --- /dev/null +++ b/resources/views/budgets/show.blade.php @@ -0,0 +1,91 @@ +@extends('layouts.default') +@section('content') +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget, $repetition) !!} +
+
+
+
+ Overview +
+
+
+
+
+ +
+
+ Transactions +
+ @include('list.journals-full') +
+
+
+ @foreach($limits as $limit) + @foreach($limit->limitrepetitions as $rep) +
+ +
+
+
+ Amount: {{Amount::format($rep->amount)}} +
+
+ Spent: {{Amount::format($rep->spentInRepetition())}} +
+
+
+
+ spentInRepetition() > $rep->amount; + ?> + @if($overspent) + amount / $rep->spentInRepetition()*100; + ?> +
+
+
+
+ @else + spentInRepetition() / $rep->amount*100; + ?> +
+
+
+
+ @endif +
+
+
+
+ @endforeach + @endforeach + + +
+
+ +@stop +@section('scripts') + + + + +{{HTML::script('assets/javascript/firefly/gcharts.options.js')}} +{{HTML::script('assets/javascript/firefly/gcharts.js')}} +{{HTML::script('assets/javascript/firefly/budgets.js')}} + +@stop diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index 3a212eb533..7ec53cefe4 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{-- Breadcrumbs::renderIfExists() --}} +{!! Breadcrumbs::renderIfExists() !!} @if($count == 0)
diff --git a/resources/views/partials/date_nav.blade.php b/resources/views/partials/date_nav.blade.php index 1230471443..71046d2a48 100644 --- a/resources/views/partials/date_nav.blade.php +++ b/resources/views/partials/date_nav.blade.php @@ -1,7 +1,7 @@
- {{{\Session::get('period')}}} + {{{Session::get('period')}}}
@@ -21,8 +21,8 @@
diff --git a/tasks.txt b/tasks.txt new file mode 100644 index 0000000000..bd9c044afc --- /dev/null +++ b/tasks.txt @@ -0,0 +1,2 @@ +- replace \Session with Session +- find all event::fire's, and see if they fire in new ff as well. \ No newline at end of file