mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	New stuff! [skip ci]
This commit is contained in:
		
							
								
								
									
										16
									
								
								app/assets/javascripts/accounts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								app/assets/javascripts/accounts.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| // This is a manifest file that'll be compiled into application.js, which will include all the files | ||||
| // listed below. | ||||
| // | ||||
| // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, | ||||
| // can be referenced here using a relative path. | ||||
| // | ||||
| // It's not advisable to add code directly here, but if you do, it'll appear in whatever order it  | ||||
| // gets included (e.g. say you have require_tree . then the code will appear after all the directories  | ||||
| // but before any files alphabetically greater than 'application.js'  | ||||
| // | ||||
| // The available directives right now are require, require_directory, and require_tree | ||||
| // | ||||
| //= require highslide/highslide-full.min | ||||
| //= require highslide/highslide.config | ||||
| //= require_tree highcharts | ||||
| //= require firefly/accounts | ||||
							
								
								
									
										95
									
								
								app/assets/javascripts/firefly/accounts.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								app/assets/javascripts/firefly/accounts.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| $(function () { | ||||
| if($('#chart').length == 1) { | ||||
|     /** | ||||
|      * get data from controller for home charts: | ||||
|      */ | ||||
|     $.getJSON('chart/home/account/' + accountID).success(function (data) { | ||||
|         var options = { | ||||
|             chart: { | ||||
|                 renderTo: 'chart', | ||||
|                 type: 'line' | ||||
|             }, | ||||
|  | ||||
|             series: data, | ||||
|             title: { | ||||
|                 text: 'BETTER TITLE HERE' | ||||
|             }, | ||||
|             yAxis: { | ||||
|                 formatter: function () { | ||||
|                     return '$' + Highcharts.numberFormat(this.y, 0); | ||||
|                 } | ||||
|             }, | ||||
|             subtitle: { | ||||
|                 text: '<a href="#">View more</a>', | ||||
|                 useHTML: true | ||||
|             }, | ||||
|  | ||||
|             xAxis: { | ||||
|                 floor: 0, | ||||
|                 type: 'datetime', | ||||
|                 dateTimeLabelFormats: { | ||||
|                     day: '%e %b', | ||||
|                     year: '%b' | ||||
|                 }, | ||||
|                 title: { | ||||
|                     text: 'Date' | ||||
|                 } | ||||
|             }, | ||||
|             tooltip: { | ||||
|                 shared: true, | ||||
|                 crosshairs: false, | ||||
|                 formatter: function () { | ||||
|                     var str = '<span style="font-size:80%;">' + Highcharts.dateFormat("%A, %e %B", this.x) + '</span><br />'; | ||||
|                     for (x in this.points) { | ||||
|                         var point = this.points[x]; | ||||
|                         var colour = point.point.pointAttr[''].fill; | ||||
|                         str += '<span style="color:' + colour + '">' + point.series.name + '</span>: € ' + Highcharts.numberFormat(point.y, 2) + '<br />'; | ||||
|                     } | ||||
|                     //console.log(); | ||||
|                     return str; | ||||
|                     return '<span style="font-size:80%;">' + this.series.name + ' on ' + Highcharts.dateFormat("%e %B", this.x) + ':</span><br /> € ' + Highcharts.numberFormat(this.y, 2); | ||||
|                 } | ||||
|             }, | ||||
|             plotOptions: { | ||||
|                 line: { | ||||
|                     shadow: true | ||||
|                 }, | ||||
|                 series: { | ||||
|                     cursor: 'pointer', | ||||
|                     negativeColor: '#FF0000', | ||||
|                     threshold: 0, | ||||
|                     lineWidth: 1, | ||||
|                     marker: { | ||||
|                         radius: 2 | ||||
|                     }, | ||||
|                     point: { | ||||
|                         events: { | ||||
|                             click: function (e) { | ||||
|                                 hs.htmlExpand(null, { | ||||
|                                         src: 'chart/home/info/' + this.series.name + '/' + Highcharts.dateFormat("%d/%m/%Y", this.x), | ||||
|                                         pageOrigin: { | ||||
|                                             x: e.pageX, | ||||
|                                             y: e.pageY | ||||
|                                         }, | ||||
|                                         objectType: 'ajax', | ||||
|                                         headingText: '<a href="#">' + this.series.name + '</a>', | ||||
|                                         width: 250 | ||||
|                                     } | ||||
|                                 ) | ||||
|                                 ; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             credits: { | ||||
|                 enabled: false | ||||
|             } | ||||
|         }; | ||||
|         $('#chart').highcharts(options); | ||||
|     }); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| }); | ||||
							
								
								
									
										13
									
								
								app/assets/stylesheets/accounts.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/assets/stylesheets/accounts.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /** | ||||
|  * This is a manifest file that'll be compiled into application.css, which will include all the files | ||||
|  * listed below. | ||||
|  * | ||||
|  * Any Css/Less files within this directory, lib/assets/javascripts, vendor/assets/javascripts, | ||||
|  * can be referenced here using a relative path. | ||||
|  * | ||||
|  * It's not advisable to add code directly here, but if you do, it'll appear in whatever order it  | ||||
|  * gets included (e.g. say you have require_tree . then the code will appear after all the directories  | ||||
|  * but before any files alphabetically greater than 'application.css'  | ||||
|  * | ||||
|  *= require highslide/highslide | ||||
|  */ | ||||
| @@ -51,13 +51,11 @@ class AccountController extends \BaseController | ||||
|         $result = $this->_repository->destroy(Input::get('id')); | ||||
|         if ($result === true) { | ||||
|             Session::flash('success', 'The account was deleted.'); | ||||
|  | ||||
|             return Redirect::route('accounts.index'); | ||||
|         } else { | ||||
|             Session::flash('danger', 'Could not delete the account. Check the logs to be sure.'); | ||||
|  | ||||
|             return Redirect::route('accounts.index'); | ||||
|             Session::flash('error', 'Could not delete the account. Check the logs to be sure.'); | ||||
|         } | ||||
|         return Redirect::route('accounts.index'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| @@ -93,7 +91,9 @@ class AccountController extends \BaseController | ||||
|      */ | ||||
|     public function show(Account $account) | ||||
|     { | ||||
|         return View::make('accounts.show')->with('account', $account); | ||||
|         $show = $this->_accounts->show($account, 40); | ||||
|  | ||||
|         return View::make('accounts.show')->with('account', $account)->with('show',$show); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| use Firefly\Helper\Controllers\BudgetInterface as BI; | ||||
| use Firefly\Storage\Budget\BudgetRepositoryInterface as BRI; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| /** | ||||
|  * Class BudgetController | ||||
|  */ | ||||
| @@ -9,16 +10,40 @@ class BudgetController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $_budgets; | ||||
|     protected $_repository; | ||||
|  | ||||
|     /** | ||||
|      * @param BRI $budgets | ||||
|      */ | ||||
|     public function __construct(BRI $budgets) | ||||
|     public function __construct(BI $budgets, BRI $repository) | ||||
|     { | ||||
|         $this->_budgets = $budgets; | ||||
|         $this->_repository = $repository; | ||||
|         View::share('menu', 'budgets'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|  | ||||
|         return View::make('budgets.create')->with('periods', $periods); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function indexByBudget() | ||||
|     { | ||||
|         $budgets = $this->_repository->get(); | ||||
|         $today = new Carbon; | ||||
|  | ||||
|         return View::make('budgets.indexByBudget')->with('budgets', $budgets)->with('today', $today); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      * @throws Firefly\Exception\FireflyException | ||||
| @@ -26,76 +51,12 @@ class BudgetController extends BaseController | ||||
|     public function indexByDate() | ||||
|     { | ||||
|         // get a list of dates by getting all repetitions: | ||||
|         $budgets = $this->_budgets->get(); | ||||
|         $reps = []; | ||||
|         foreach ($budgets as $budget) { | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 $dateFormats = \Config::get('firefly.date_formats_by_period.' . $limit->repeat_freq); | ||||
|                 if (is_null($dateFormats)) { | ||||
|                     throw new \Firefly\Exception\FireflyException('No date formats for ' . $limit->repeat_freq); | ||||
|                 } | ||||
|         $set = $this->_repository->get(); | ||||
|         $budgets = $this->_budgets->organizeByDate($set); | ||||
|  | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|                     $periodOrder = $rep->startdate->format($dateFormats['group_date']); | ||||
|                     $period = $rep->startdate->format($dateFormats['display_date']); | ||||
|                     $reps[$periodOrder] = isset($reps[$periodOrder]) ? $reps[$periodOrder] : ['date' => $period]; | ||||
|         return View::make('budgets.indexByDate')->with('budgets', $budgets); | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // put all the budgets under their respective date: | ||||
|         foreach ($budgets as $budget) { | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 $dateFormats = \Config::get('firefly.date_formats_by_period.' . $limit->repeat_freq); | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|  | ||||
|                     $month = $rep->startdate->format($dateFormats['group_date']); | ||||
|                     $reps[$month]['limitrepetitions'][] = $rep; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         krsort($reps); | ||||
|  | ||||
|         return View::make('budgets.indexByDate')->with('reps', $reps); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function indexByBudget() | ||||
|     { | ||||
|         $budgets = $this->_budgets->get(); | ||||
|         $today = new \Carbon\Carbon; | ||||
|         return View::make('budgets.indexByBudget')->with('budgets', $budgets)->with('today', $today); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this|\Illuminate\View\View | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         $periods = \Config::get('firefly.periods_to_text'); | ||||
|         return View::make('budgets.create')->with('periods', $periods); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|  | ||||
|         $data = [ | ||||
|             'name'        => Input::get('name'), | ||||
|             'amount'      => floatval(Input::get('amount')), | ||||
|             'repeat_freq' => Input::get('period'), | ||||
|             'repeats'     => intval(Input::get('repeats')) | ||||
|         ]; | ||||
|  | ||||
|         $this->_budgets->store($data); | ||||
|         Session::flash('success', 'Budget created!'); | ||||
|         return Redirect::route('budgets.index'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -146,5 +107,24 @@ class BudgetController extends BaseController | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function store() | ||||
|     { | ||||
|  | ||||
|         $data = [ | ||||
|             'name'        => Input::get('name'), | ||||
|             'amount'      => floatval(Input::get('amount')), | ||||
|             'repeat_freq' => Input::get('period'), | ||||
|             'repeats'     => intval(Input::get('repeats')) | ||||
|         ]; | ||||
|  | ||||
|         $this->_budgets->store($data); | ||||
|         Session::flash('success', 'Budget created!'); | ||||
|  | ||||
|         return Redirect::route('budgets.index'); | ||||
|     } | ||||
|  | ||||
|  | ||||
| }  | ||||
| @@ -41,6 +41,7 @@ class Account implements AccountInterface | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $list; | ||||
|  | ||||
|     } | ||||
| @@ -53,6 +54,7 @@ class Account implements AccountInterface | ||||
|     public function openingBalanceTransaction(\Account $account) | ||||
|     { | ||||
|         $transactionType = \TransactionType::where('type', 'Opening balance')->first(); | ||||
|  | ||||
|         return \TransactionJournal:: | ||||
|             with( | ||||
|                 ['transactions' => function ($q) { | ||||
| @@ -63,4 +65,118 @@ class Account implements AccountInterface | ||||
|             ->where('transactions.account_id', $account->id)->first(['transaction_journals.*']); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param \Account $account | ||||
|      * @param          $perPage | ||||
|      * | ||||
|      * @return mixed|void | ||||
|      */ | ||||
|     public function show(\Account $account, $perPage) | ||||
|     { | ||||
|         $start = \Session::get('start'); | ||||
|         $end = \Session::get('end'); | ||||
|         $stats = [ | ||||
|             'budgets'    => [], | ||||
|             'categories' => [], | ||||
|             'accounts'   => [] | ||||
|         ]; | ||||
|         $items = []; | ||||
|  | ||||
|  | ||||
|         // build a query: | ||||
|         $query = \TransactionJournal::with( | ||||
|             ['transactions'                        => function ($q) { | ||||
|                     $q->orderBy('amount', 'ASC'); | ||||
|                 }, 'transactiontype', 'components' => function ($q) { | ||||
|                     $q->orderBy('class'); | ||||
|                 }, 'transactions.account.accounttype'] | ||||
|         )->orderBy('date', 'DESC')->leftJoin( | ||||
|                 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|             )->where('transactions.account_id', $account->id)->where('date', '>=', $start->format('Y-m-d'))->where( | ||||
|                 'date', '<=', $end->format('Y-m-d') | ||||
|             )->orderBy('transaction_journals.id', 'DESC'); | ||||
|  | ||||
|  | ||||
|         // build paginator: | ||||
|         $totalItems = $query->count(); | ||||
|         $page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1; | ||||
|         $skip = ($page - 1) * $perPage; | ||||
|         $result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']); | ||||
|         // in the mean time, build list of categories, budgets and other accounts: | ||||
|  | ||||
|         /** @var $item \TransactionJournal */ | ||||
|         foreach ($result as $item) { | ||||
|             $items[] = $item; | ||||
|             foreach ($item->components as $component) { | ||||
|                 if ($component->class == 'Budget') { | ||||
|                     $stats['budgets'][$component->id] = $component; | ||||
|                 } | ||||
|                 if ($component->class == 'Category') { | ||||
|                     $stats['categories'][$component->id] = $component; | ||||
|                 } | ||||
|             } | ||||
|             $fromAccount = $item->transactions[0]->account; | ||||
|             $toAccount = $item->transactions[1]->account; | ||||
|             $stats['accounts'][$fromAccount->id] = $fromAccount; | ||||
|             $stats['accounts'][$toAccount->id] = $toAccount; | ||||
|         } | ||||
|         unset($result, $page); | ||||
|         $paginator = \Paginator::make($items, $totalItems, $perPage); | ||||
|  | ||||
|         // statistics | ||||
|         $stats['period']['in'] = floatval( | ||||
|             \Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin( | ||||
|                     'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                 )->leftJoin( | ||||
|                     'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' | ||||
|                 )->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where( | ||||
|                     'transaction_journals.date', '>=', $start->format('Y-m-d') | ||||
|                 )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount') | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         $stats['period']['out'] = floatval( | ||||
|             \Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin( | ||||
|                     'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                 )->leftJoin( | ||||
|                     'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' | ||||
|                 )->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where( | ||||
|                     'transaction_journals.date', '>=', $start->format('Y-m-d') | ||||
|                 )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount') | ||||
|         ); | ||||
|         $stats['period']['diff'] = $stats['period']['in'] + $stats['period']['out']; | ||||
|  | ||||
|         $stats['period']['t_in'] = floatval( | ||||
|             \Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin( | ||||
|                     'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                 )->leftJoin( | ||||
|                     'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' | ||||
|                 )->where('transaction_types.type', 'Transfer')->where( | ||||
|                     'transaction_journals.date', '>=', $start->format('Y-m-d') | ||||
|                 )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount') | ||||
|         ); | ||||
|  | ||||
|         $stats['period']['t_out'] = floatval( | ||||
|             \Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin( | ||||
|                     'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|                 )->leftJoin( | ||||
|                     'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' | ||||
|                 )->where('transaction_types.type', 'Transfer')->where( | ||||
|                     'transaction_journals.date', '>=', $start->format('Y-m-d') | ||||
|                 )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount') | ||||
|         ); | ||||
|  | ||||
|         $stats['period']['t_diff'] = $stats['period']['t_in'] + $stats['period']['t_out']; | ||||
|  | ||||
|  | ||||
|         $return = [ | ||||
|             'journals'   => $paginator, | ||||
|             'statistics' => $stats | ||||
|         ]; | ||||
|  | ||||
|         return $return; | ||||
|  | ||||
|  | ||||
|     } | ||||
| }  | ||||
| @@ -28,4 +28,12 @@ interface AccountInterface | ||||
|      */ | ||||
|     public function openingBalanceTransaction(\Account $account); | ||||
|  | ||||
|     /** | ||||
|      * @param \Account $account | ||||
|      * @param          $perPage | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function show(\Account $account, $perPage); | ||||
|  | ||||
| }  | ||||
							
								
								
									
										61
									
								
								app/lib/Firefly/Helper/Controllers/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								app/lib/Firefly/Helper/Controllers/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 27/07/14 | ||||
|  * Time: 16:28 | ||||
|  */ | ||||
|  | ||||
| namespace Firefly\Helper\Controllers; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package Firefly\Helper\Controllers | ||||
|  */ | ||||
| class Budget implements BudgetInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * | ||||
|      * @return mixed|void | ||||
|      */ | ||||
|     public function organizeByDate(Collection $budgets) | ||||
|     { | ||||
|         $return = []; | ||||
|  | ||||
|         foreach ($budgets as $budget) { | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 $dateFormats = \Config::get('firefly.date_formats_by_period.' . $limit->repeat_freq); | ||||
|                 if (is_null($dateFormats)) { | ||||
|                     throw new \Firefly\Exception\FireflyException('No date formats for ' . $limit->repeat_freq); | ||||
|                 } | ||||
|  | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|                     $periodOrder = $rep->startdate->format($dateFormats['group_date']); | ||||
|                     $period = $rep->startdate->format($dateFormats['display_date']); | ||||
|                     $return[$periodOrder] = isset($return[$periodOrder]) ? $return[$periodOrder] : ['date' => $period]; | ||||
|  | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // put all the budgets under their respective date: | ||||
|         foreach ($budgets as $budget) { | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 $dateFormats = \Config::get('firefly.date_formats_by_period.' . $limit->repeat_freq); | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|                     $rep->left = $rep->left(); | ||||
|  | ||||
|                     $month = $rep->startdate->format($dateFormats['group_date']); | ||||
|                     $return[$month]['limitrepetitions'][] = $rep; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         krsort($return); | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
| }  | ||||
							
								
								
									
										18
									
								
								app/lib/Firefly/Helper/Controllers/BudgetInterface.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								app/lib/Firefly/Helper/Controllers/BudgetInterface.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <?php | ||||
| namespace Firefly\Helper\Controllers; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
| /** | ||||
|  * Interface BudgetInterface | ||||
|  * | ||||
|  * @package Firefly\Helper\Controllers | ||||
|  */ | ||||
| interface BudgetInterface { | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $budgets | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function organizeByDate(Collection $budgets); | ||||
|  | ||||
| }  | ||||
| @@ -23,6 +23,11 @@ class HelperServiceProvider extends ServiceProvider | ||||
|             'Firefly\Helper\Controllers\Account' | ||||
|         ); | ||||
|  | ||||
|         $this->app->bind( | ||||
|             'Firefly\Helper\Controllers\BudgetInterface', | ||||
|             'Firefly\Helper\Controllers\Budget' | ||||
|         ); | ||||
|  | ||||
|         // mail: | ||||
|         $this->app->bind( | ||||
|             'Firefly\Helper\Email\EmailHelperInterface', | ||||
|   | ||||
| @@ -12,6 +12,40 @@ use Carbon\Carbon; | ||||
| class EloquentBudgetRepository implements BudgetRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @param $budgetId | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function find($budgetId) | ||||
|     { | ||||
|  | ||||
|         return \Auth::user()->budgets()->find($budgetId); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function get() | ||||
|     { | ||||
|         $set = \Auth::user()->budgets()->with( | ||||
|             ['limits'                        => function ($q) { | ||||
|                     $q->orderBy('limits.startdate', 'ASC'); | ||||
|                 }, 'limits.limitrepetitions' => function ($q) { | ||||
|                     $q->orderBy('limit_repetitions.startdate', 'ASC'); | ||||
|                 }] | ||||
|         )->orderBy('name', 'ASC')->get(); | ||||
|         foreach ($set as $budget) { | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|                     $rep->left = $rep->left(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array|mixed | ||||
|      */ | ||||
| @@ -24,6 +58,7 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface | ||||
|         foreach ($list as $entry) { | ||||
|             $return[intval($entry->id)] = $entry->name; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
| @@ -69,6 +104,7 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface | ||||
|                 $budget->count += count($limit->limitrepetitions); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
| @@ -123,30 +159,4 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface | ||||
|         return $budget; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function get() | ||||
|     { | ||||
|         return \Auth::user()->budgets()->with( | ||||
|             ['limits'                        => function ($q) { | ||||
|                     $q->orderBy('limits.startdate', 'ASC'); | ||||
|                 }, 'limits.limitrepetitions' => function ($q) { | ||||
|                     $q->orderBy('limit_repetitions.startdate', 'ASC'); | ||||
|                 }] | ||||
|         )->orderBy('name', 'ASC')->get(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $budgetId | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function find($budgetId) | ||||
|     { | ||||
|  | ||||
|         return \Auth::user()->budgets()->find($budgetId); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| @@ -100,7 +100,7 @@ class EloquentLimitRepository implements LimitRepositoryInterface | ||||
|      */ | ||||
|     public function getTJByBudgetAndDateRange(\Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $result = $budget->transactionjournals()->after($start)->before($end)->get(); | ||||
|         $result = $budget->transactionjournals()->with('transactions')->after($start)->before($end)->get(); | ||||
|  | ||||
|         return $result; | ||||
|  | ||||
|   | ||||
| @@ -37,6 +37,7 @@ class LimitRepetition extends Ardent | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         return [ | ||||
|             'limit_id'  => 'factory|Limit', | ||||
|             'startdate' => $start, | ||||
| @@ -45,11 +46,6 @@ class LimitRepetition extends Ardent | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     public function limit() | ||||
|     { | ||||
|         return $this->belongsTo('Limit'); | ||||
|     } | ||||
|  | ||||
|     public function getDates() | ||||
|     { | ||||
|         return ['created_at', 'updated_at', 'startdate', 'enddate']; | ||||
| @@ -60,10 +56,6 @@ class LimitRepetition extends Ardent | ||||
|      */ | ||||
|     public function left() | ||||
|     { | ||||
|         $key = 'limit-rep-left-' . $this->id; | ||||
|         if (Cache::has($key)) { | ||||
|             return Cache::get($key); | ||||
|         } | ||||
|         $left = floatval($this->amount); | ||||
|  | ||||
|         // budget: | ||||
| @@ -80,11 +72,14 @@ class LimitRepetition extends Ardent | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         Cache::forever($key, $left); | ||||
|  | ||||
|  | ||||
|         return $left; | ||||
|     } | ||||
|  | ||||
|     public function limit() | ||||
|     { | ||||
|         return $this->belongsTo('Limit'); | ||||
|     } | ||||
|  | ||||
|  | ||||
| }  | ||||
| @@ -3,8 +3,23 @@ | ||||
| // models: | ||||
| Route::bind('account', function($value, $route) | ||||
|     { | ||||
|         return Account::where('id', $value)->where('user_id',Auth::user()->id)->first(); | ||||
|         if(Auth::check()) { | ||||
|             return Account:: | ||||
|                 where('id', $value)-> | ||||
|                 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; | ||||
|     }); | ||||
|  | ||||
|  | ||||
|  | ||||
| // protected routes: | ||||
| @@ -15,7 +30,7 @@ Route::group(['before' => 'auth'], function () { | ||||
|         Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); | ||||
|  | ||||
|         // chart controller | ||||
|         Route::get('/chart/home/account/{account?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']); | ||||
|         Route::get('/chart/home/account/{accountname?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']); | ||||
|         Route::get('/chart/home/categories', ['uses' => 'ChartController@homeCategories', 'as' => 'chart.categories']); | ||||
|         Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']); | ||||
|         Route::get('/chart/home/info/{accountname}/{day}/{month}/{year}', ['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']); | ||||
| @@ -42,7 +57,9 @@ Route::group(['before' => 'auth'], function () { | ||||
|         Route::get('/budget/create',['uses' => 'BudgetController@create', 'as' => 'budgets.create']); | ||||
|         Route::get('/budgets',['uses' => 'BudgetController@indexByDate','as' => 'budgets.index']); | ||||
|         Route::get('/budgets/budget',['uses' => 'BudgetController@indexByBudget','as' => 'budgets.index.budget']); | ||||
|         Route::get('/budget/show/{id}',['uses' => 'BudgetController@show', 'as' => 'budgets.show']); | ||||
|         Route::get('/budget/show/{budget}',['uses' => 'BudgetController@show', 'as' => 'budgets.show']); | ||||
|         Route::get('/budget/edit/{budget}',['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']); | ||||
|         Route::get('/budget/delete/{budget}',['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']); | ||||
|  | ||||
|         // limit controller: | ||||
|         Route::get('/budgets/limits/create/{id?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']); | ||||
|   | ||||
| @@ -1,102 +1,210 @@ | ||||
| <?php | ||||
|  | ||||
| use Mockery as m; | ||||
| use \League\FactoryMuffin\Facade\FactoryMuffin as f; | ||||
| use Illuminate\Database\Eloquent\Collection; | ||||
|  | ||||
| class AccountControllerTest extends TestCase | ||||
| { | ||||
|     protected $_repository; | ||||
|     protected $_user; | ||||
|     protected $_accounts; | ||||
|     public function setUp() | ||||
|     { | ||||
|         parent::setUp(); | ||||
|         Artisan::call('migrate'); | ||||
|         Artisan::call('db:seed'); | ||||
|     } | ||||
|  | ||||
|     public function testIndex() | ||||
|     { | ||||
|         // mock account type(s): | ||||
|         $personal = $this->mock('AccountType'); | ||||
|         $personal->shouldReceive('getAttribute', 'description')->andReturn('Default account'); | ||||
|  | ||||
|         $bene = $this->mock('AccountType'); | ||||
|         $bene->shouldReceive('getAttribute', 'description')->andReturn('Beneficiary account'); | ||||
|  | ||||
|         $initial = $this->mock('AccountType'); | ||||
|         $initial->shouldReceive('getAttribute', 'description')->andReturn('Initial balance account'); | ||||
|  | ||||
|         $cash = $this->mock('AccountType'); | ||||
|         $cash->shouldReceive('getAttribute', 'description')->andReturn('Cash account'); | ||||
|  | ||||
|  | ||||
|         // mock account(s) | ||||
|         $one = $this->mock('Account'); | ||||
|         $one->shouldReceive('getAttribute')->andReturn($personal); | ||||
|  | ||||
|         $two = $this->mock('Account'); | ||||
|         $two->shouldReceive('getAttribute')->andReturn($bene); | ||||
|  | ||||
|         $three = $this->mock('Account'); | ||||
|         $three->shouldReceive('getAttribute')->andReturn($initial); | ||||
|  | ||||
|         $four = $this->mock('Account'); | ||||
|         $four->shouldReceive('getAttribute')->andReturn($cash); | ||||
|         $c = new \Illuminate\Database\Eloquent\Collection([$one, $two, $three, $four]); | ||||
|  | ||||
|         // mock account repository: | ||||
|         $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $accounts->shouldReceive('get')->andReturn($c); | ||||
|  | ||||
|  | ||||
|         $list = [ | ||||
|             'personal'      => [$one], | ||||
|             'beneficiaries' => [$two], | ||||
|             'initial'       => [$three], | ||||
|             'cash'          => [$four] | ||||
|         ]; | ||||
|  | ||||
|         // mock: | ||||
|         View::shouldReceive('share'); | ||||
|         View::shouldReceive('make')->with('accounts.index')->once()->andReturn(\Mockery::self()) | ||||
|             ->shouldReceive('with')->once()->with('accounts', $list)->andReturn(\Mockery::self()) | ||||
|             ->shouldReceive('with')->once()->with('total', 4)->andReturn(\Mockery::self()); | ||||
|  | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/accounts'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|         $this->_repository = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $this->_accounts = $this->mock('Firefly\Helper\Controllers\AccountInterface'); | ||||
|         $this->_user = m::mock('User','Eloquent'); | ||||
|         $this->app->instance('User', $this->_user); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function testCreate() | ||||
|     { | ||||
|         // mock: | ||||
|         View::shouldReceive('share'); | ||||
|         View::shouldReceive('make')->with('accounts.create'); | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/accounts/create'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testShow() | ||||
|     { | ||||
|         // mock account repository: | ||||
|         $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
|         $accounts->shouldReceive('get')->with(1)->andReturn([]); | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/accounts/1'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public function tearDown() | ||||
|     { | ||||
|         Mockery::close(); | ||||
|     } | ||||
|  | ||||
|     public function testCreate() | ||||
|     { | ||||
|         $this->action('GET', 'AccountController@create'); | ||||
|         $this->assertResponseOk(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function testDelete() | ||||
|     { | ||||
|  | ||||
|         $account = f::create('Account'); | ||||
|         Auth::shouldReceive('user')->andReturn($this->_user); | ||||
|         Auth::shouldReceive('check')->andReturn(true); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($account->email); | ||||
|  | ||||
|         $this->action('GET', 'AccountController@delete',$account->id); | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testDestroy() | ||||
|     { | ||||
|         $account = f::create('Account'); | ||||
|         Auth::shouldReceive('user')->andReturn($this->_user); | ||||
|         $this->_repository->shouldReceive('destroy')->once()->with("")->andReturn(true); | ||||
|         $this->action('POST', 'AccountController@destroy',$account->id); | ||||
|         $this->assertRedirectedToRoute('accounts.index'); | ||||
|         $this->assertSessionHas('success'); | ||||
|     } | ||||
|  | ||||
|     public function testDestroyFails() | ||||
|     { | ||||
|         $account = f::create('Account'); | ||||
|         $this->_repository->shouldReceive('destroy')->once()->with("")->andReturn(false); | ||||
|         $this->action('POST', 'AccountController@destroy',$account->id); | ||||
|         $this->assertRedirectedToRoute('accounts.index'); | ||||
|         $this->assertSessionHas('error'); | ||||
|     } | ||||
|  | ||||
|     public function testEdit() | ||||
|     { | ||||
|         $account = f::create('Account'); | ||||
|  | ||||
|         Auth::shouldReceive('user')->andReturn($this->_user); | ||||
|         Auth::shouldReceive('check')->andReturn(true); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($account->email); | ||||
|         $this->_accounts->shouldReceive('openingBalanceTransaction')->once()->andReturn(null); | ||||
|  | ||||
|         $this->action('GET', 'AccountController@edit',$account->id); | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testIndex() | ||||
|     { | ||||
|         $account = f::create('Account'); | ||||
|         $collection = new Collection(); | ||||
|         $collection->add($account); | ||||
|  | ||||
|         $list = [ | ||||
|             'personal'      => [], | ||||
|             'beneficiaries' => [], | ||||
|             'initial'       => [], | ||||
|             'cash'          => [] | ||||
|         ]; | ||||
|  | ||||
|         $this->_repository->shouldReceive('get')->with()->once()->andReturn($collection); | ||||
|         $this->_accounts->shouldReceive('index')->with($collection)->once()->andReturn($list); | ||||
|         $this->action('GET', 'AccountController@index'); | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testShow() | ||||
|     { | ||||
|         $account = f::create('Account'); | ||||
|  | ||||
|         Auth::shouldReceive('user')->andReturn($this->_user); | ||||
|         Auth::shouldReceive('check')->andReturn(true); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id); | ||||
|         $this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($account->email); | ||||
|         $this->_accounts->shouldReceive('paginate')->with($account,40)->once()->andReturn(); | ||||
|  | ||||
|         $this->action('GET', 'AccountController@show',$account->id); | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testStore() | ||||
|     { | ||||
| //        $this->action('POST', 'AccountController@store'); | ||||
| //        $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|  | ||||
| // | ||||
| //    public function testIndex() | ||||
| //    { | ||||
| ////        // mock account type(s): | ||||
| ////        $personal = $this->mock('AccountType'); | ||||
| ////        $personal->shouldReceive('getAttribute', 'description')->andReturn('Default account'); | ||||
| //// | ||||
| ////        $bene = $this->mock('AccountType'); | ||||
| ////        $bene->shouldReceive('getAttribute', 'description')->andReturn('Beneficiary account'); | ||||
| //// | ||||
| ////        $initial = $this->mock('AccountType'); | ||||
| ////        $initial->shouldReceive('getAttribute', 'description')->andReturn('Initial balance account'); | ||||
| //// | ||||
| ////        $cash = $this->mock('AccountType'); | ||||
| ////        $cash->shouldReceive('getAttribute', 'description')->andReturn('Cash account'); | ||||
| //// | ||||
| //// | ||||
| ////        // mock account(s) | ||||
| ////        $one = $this->mock('Account'); | ||||
| ////        $one->shouldReceive('getAttribute')->andReturn($personal); | ||||
| //// | ||||
| ////        $two = $this->mock('Account'); | ||||
| ////        $two->shouldReceive('getAttribute')->andReturn($bene); | ||||
| //// | ||||
| ////        $three = $this->mock('Account'); | ||||
| ////        $three->shouldReceive('getAttribute')->andReturn($initial); | ||||
| //// | ||||
| ////        $four = $this->mock('Account'); | ||||
| ////        $four->shouldReceive('getAttribute')->andReturn($cash); | ||||
| ////        $c = new \Illuminate\Database\Eloquent\Collection([$one, $two, $three, $four]); | ||||
| //// | ||||
| ////        // mock account repository: | ||||
| ////        $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
| ////        $accounts->shouldReceive('get')->andReturn($c); | ||||
| //// | ||||
| //// | ||||
| ////        $list = [ | ||||
| ////            'personal'      => [$one], | ||||
| ////            'beneficiaries' => [$two], | ||||
| ////            'initial'       => [$three], | ||||
| ////            'cash'          => [$four] | ||||
| ////        ]; | ||||
| //// | ||||
| ////        // mock: | ||||
| ////        View::shouldReceive('share'); | ||||
| ////        View::shouldReceive('make')->with('accounts.index')->once()->andReturn(\Mockery::self()) | ||||
| ////            ->shouldReceive('with')->once()->with('accounts', $list)->andReturn(\Mockery::self()) | ||||
| ////            ->shouldReceive('with')->once()->with('total', 4)->andReturn(\Mockery::self()); | ||||
| //// | ||||
| // | ||||
| //        // call | ||||
| //        $this->call('GET', '/accounts'); | ||||
| // | ||||
| //        // test | ||||
| //        $this->assertResponseOk(); | ||||
| // | ||||
| //    } | ||||
| //// | ||||
| ////    public function testCreate() | ||||
| ////    { | ||||
| ////        // mock: | ||||
| ////        View::shouldReceive('share'); | ||||
| ////        View::shouldReceive('make')->with('accounts.create'); | ||||
| //// | ||||
| ////        // call | ||||
| ////        $this->call('GET', '/accounts/create'); | ||||
| //// | ||||
| ////        // test | ||||
| ////        $this->assertResponseOk(); | ||||
| ////    } | ||||
| //// | ||||
| ////    public function testShow() | ||||
| ////    { | ||||
| ////        // mock account repository: | ||||
| ////        $accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface'); | ||||
| ////        $accounts->shouldReceive('get')->with(1)->andReturn([]); | ||||
| //// | ||||
| ////        // call | ||||
| ////        $this->call('GET', '/accounts/1'); | ||||
| //// | ||||
| ////        // test | ||||
| ////        $this->assertResponseOk(); | ||||
| ////    } | ||||
| //// | ||||
|  | ||||
|     public function testUpdate() | ||||
|     { | ||||
|     } | ||||
| } | ||||
| @@ -47,9 +47,4 @@ | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @stop | ||||
| @section('scripts') | ||||
|     <script src="https://www.google.com/jsapi"></script> | ||||
| <!--    <script src="assets/javascript/charts.js"></script>--> | ||||
| <!--    <script src="assets/javascript/index.js"></script>--> | ||||
| @stop | ||||
| @@ -18,18 +18,96 @@ | ||||
|  | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <h4>Transactions</h4> | ||||
|         <h4>Summary <small>For selected account and period</small></h4> | ||||
|  | ||||
|     </div> | ||||
| </div> | ||||
| <div class="row"> | ||||
|     <div class="col-lg-6 col-md-6 col-sm-12"> | ||||
|  | ||||
|         <table class="table table-striped table-condensed"> | ||||
|             <tr> | ||||
|                 <th></th> | ||||
|                 <th>Expense / income</th> | ||||
|                 <th>Transfers</th> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>Out</td> | ||||
|                 <td> | ||||
|                     {{mf($show['statistics']['period']['out'])}} | ||||
|                     <a href="#transactions-thisaccount-this-period-expensesonly"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     {{mf($show['statistics']['period']['t_out'])}} | ||||
|                     <a href="#transactions-thisaccount-this-period-transfers-out-only"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>In</td> | ||||
|                 <td> | ||||
|                     {{mf($show['statistics']['period']['in'])}} | ||||
|                     <a href="#transactions-thisaccount-this-period-incomeonly"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     {{mf($show['statistics']['period']['t_in'])}} | ||||
|                     <a href="#transactions-thisaccount-this-period-transfers-in-only"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>Difference</td> | ||||
|                 <td>{{mf($show['statistics']['period']['diff'])}}</td> | ||||
|                 <td>{{mf($show['statistics']['period']['t_diff'])}}</td> | ||||
|             </tr> | ||||
|             </table> | ||||
|     </div> | ||||
|     <div class="col-lg-6 col-md-6 col-sm-12"> | ||||
|         <table class="table table-striped table-condensed"> | ||||
|             <tr> | ||||
|                 <td style="width:30%;">Related accounts</td> | ||||
|                 <td> | ||||
|                     @foreach($show['statistics']['accounts'] as $acct) | ||||
|                     <a href="{{route('accounts.show',$acct->id)}}" class="btn btn-default btn-xs">{{{$acct->name}}}</a> | ||||
|                     @endforeach | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>Related categories</td> | ||||
|                 <td> | ||||
|                     @foreach($show['statistics']['categories'] as $cat) | ||||
|                     <a href="#category-overview" class="btn btn-default btn-xs">{{{$cat->name}}}</a> | ||||
|                     @endforeach | ||||
|                 </td> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <td>Related budgets</td> | ||||
|                 <td> | ||||
|                     @foreach($show['statistics']['budgets'] as $bud) | ||||
|                     <a href="#budget-overview" class="btn btn-default btn-xs">{{{$bud->name}}}</a> | ||||
|                     @endforeach | ||||
|                 </td> | ||||
|             </tr> | ||||
|         </table> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|  | ||||
|  | ||||
|         <h4>Transactions <small> For selected account and period</small></h4> | ||||
|         @include('paginated.transactions',['journals' => $show['journals']]) | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @stop | ||||
|  | ||||
| @section('styles') | ||||
| <?php echo stylesheet_link_tag('accounts'); ?> | ||||
| @stop | ||||
|  | ||||
| @section('scripts') | ||||
| <script type="text/javascript"> | ||||
|     var accountID = {{$account->id}}; | ||||
| </script> | ||||
| <script src="assets/javascript/highcharts.js"></script> | ||||
| <script src="assets/javascript/highcharts-more.js"></script> | ||||
| <script src="assets/javascript/highslide-full.min.js"></script> | ||||
| <script src="assets/javascript/highslide.config.js"></script> | ||||
| <script src="assets/javascript/accounts.js"></script> | ||||
| <?php echo javascript_include_tag('accounts'); ?> | ||||
| @stop | ||||
| @@ -3,18 +3,29 @@ | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <h1>Firefly | ||||
|             <small>Budgets and limits</small> | ||||
|             <small>Budgets and envelopes</small> | ||||
|         </h1> | ||||
|         <p class="lead">Use budgets to organize and limit your expenses.</p> | ||||
|  | ||||
|         <p class="text-info"> | ||||
|             These are your budgets and if set, their "limits". Firefly uses an "<a | ||||
|                 href="http://en.wikipedia.org/wiki/Envelope_System" class="text-success">envelope system</a>" for your | ||||
|             budgets, | ||||
|             which means that for each period of time (for example a month) a virtual "envelope" can be created | ||||
|             containing a certain amount of money. Money spent within a budget is removed from the envelope. | ||||
|             Budgets are groups of expenses that reappear every [period]*. Examples could be "groceries", "bills" or | ||||
|             "drinks with friends". The table below lists all of the budgets you have, if any. | ||||
|             <a href="http://dictionary.reference.com/browse/budget">By definition</a>, budgets are an estimated amount | ||||
|             of money, ie. € 400,-. Such an estimation can change over time but <em>should</em> always be set. Budgets | ||||
|             without an actual budget are fairly pointless. | ||||
|         </p> | ||||
|         <p> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.index')}}"><span class="glyphicon glyphicon-th"></span> Group by date</a> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.limits.create')}}"><span class="glyphicon glyphicon-plus-sign"></span> Create a limit</a> | ||||
|         <p class="text-info"> | ||||
|             Use this page to create or change budgets and the estimated amount of money you think is wise. Pages further ahead | ||||
|             will explain what an "envelope" is in the context of budgeting. | ||||
|         </p> | ||||
|         <p class="text-info"> | ||||
|             * <small>Every month, week, year, etc.</small> | ||||
|         </p> | ||||
|  | ||||
|         <div class="btn-group"> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.index')}}"><span class="glyphicon glyphicon-th"></span> Group budgets by date</a> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.limits.create')}}"><span class="glyphicon glyphicon-plus-sign"></span> Create a new envelope</a> | ||||
|         </div> | ||||
|         </p> | ||||
|     </div> | ||||
| </div> | ||||
| @@ -24,7 +35,7 @@ | ||||
|             <tr> | ||||
|                 <th>Budget</th> | ||||
|                 <th>Current envelope(s)</th> | ||||
|                 <th> </th> | ||||
|                 <th>Update budget</th> | ||||
|             </tr> | ||||
|             @foreach($budgets as $budget) | ||||
|             <tr> | ||||
| @@ -50,14 +61,14 @@ | ||||
|                                 {{mf($rep->amount,false)}}</span> | ||||
|                         </div> | ||||
|                         <div class="col-sm-2"> | ||||
|                             @if($rep->left() < 0) | ||||
|                             @if($rep->left < 0) | ||||
|                             <span class="label label-danger"> | ||||
|                                 <span class="glyphicon glyphicon-envelope"></span> | ||||
|                                 {{mf($rep->left(),false)}}</span> | ||||
|                                 {{mf($rep->left,false)}}</span> | ||||
|                             @else | ||||
|                             <span class="label label-success"> | ||||
|                                 <span class="glyphicon glyphicon-envelope"></span> | ||||
|                                 {{mf($rep->left(),false)}}</span> | ||||
|                                 {{mf($rep->left,false)}}</span> | ||||
|                             @endif | ||||
|                         </div> | ||||
|                         <div class="col-sm-3"> | ||||
| @@ -75,10 +86,12 @@ | ||||
|                         </div> | ||||
|                         @endif | ||||
|                         <div class="col-sm-2 @if($limit->repeats == 0) col-sm-offset-2 @endif"> | ||||
|                             <a href="#" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span></a> | ||||
|                             @if($limit->repeats == 0 || ($limit->repeats == 1 && $index == 0)) | ||||
|                             <a href="#" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></a> | ||||
|                             @endif | ||||
|                             <div class="btn-group btn-group-xs"> | ||||
|                                 <a href="#" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span></a> | ||||
|                                 @if($limit->repeats == 0 || ($limit->repeats == 1 && $index == 0)) | ||||
|                                 <a href="#" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></a> | ||||
|                                 @endif | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                     @endforeach | ||||
|   | ||||
| @@ -3,64 +3,82 @@ | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <h1>Firefly | ||||
|             <small>Budgets and limits</small> | ||||
|             <small>Budgets and envelopes</small> | ||||
|         </h1> | ||||
|         <p class="lead">Use budgets to organize and limit your expenses.</p> | ||||
|  | ||||
|         <p class="text-info"> | ||||
|             These are your budgets and if set, their "limits". Firefly uses an "<a | ||||
|                 href="http://en.wikipedia.org/wiki/Envelope_System" class="text-success">envelope system</a>" for your | ||||
|             budgets, | ||||
|             which means that for each period of time (for example a month) a virtual "envelope" can be created | ||||
|             containing a certain amount of money. Money spent within a budget is removed from the envelope. | ||||
|             Budgets are groups of expenses that reappear every [period]*. Examples could be "groceries", "bills" or | ||||
|             "drinks with friends". The table below lists all of the budgets you have, if any. | ||||
|             <a href="http://dictionary.reference.com/browse/budget">By definition</a>, budgets are an estimated amount | ||||
|             of money, ie. € 400,-. Such an estimation can change over time but <em>should</em> always be set. Budgets | ||||
|             without an actual budget are fairly pointless. | ||||
|         </p> | ||||
|         <p class="text-info"> | ||||
|             Use this page to create or change budgets and the estimated amount of money you think is wise. Pages further ahead | ||||
|             will explain what an "envelope" is in the context of budgeting. | ||||
|         </p> | ||||
|         <p class="text-info"> | ||||
|             * <small>Every month, week, year, etc.</small> | ||||
|         </p> | ||||
|         <p> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.index.budget')}}"><span class="glyphicon glyphicon-indent-left"></span> Group by budget</a> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.limits.create')}}"><span class="glyphicon glyphicon-plus-sign"></span> Create a limit</a> | ||||
|             <a class="btn btn-default" href ="{{route('budgets.limits.create')}}"><span class="glyphicon glyphicon-plus-sign"></span> Create an envelope</a> | ||||
|         </p> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @foreach($reps as $date => $data) | ||||
| <!-- count = zero! --> | ||||
|  | ||||
| @foreach($budgets as $date => $entry) | ||||
| <div class="row"> | ||||
|     <div class="col-lg-12 col-md-12 col-sm-12"> | ||||
|         <h3>{{$data['date']}}</h3> | ||||
|         <h3><a href="#transactions-in-this-period">{{$entry['date']}}</a> | ||||
|              <a class="btn btn-default btn-xs" href ="{{route('budgets.limits.create')}}#date-and-budget-selected"><span class="glyphicon glyphicon-plus-sign"></span> Create an envelope for {{$entry['date']}}</a> | ||||
|             </h3> | ||||
|         <table class="table table-bordered table-striped"> | ||||
|             <tr> | ||||
|                 <th style="width:45%;">Budget</th> | ||||
|                 <th colspan="2" style="width:45%;">Budget</th> | ||||
|                 <th style="width:15%;">Envelope</th> | ||||
|                 <th style="width:15%;">Left</th> | ||||
|                 <th> </th> | ||||
|             </tr> | ||||
|             @foreach($data['limitrepetitions'] as $index => $rep) | ||||
|             @foreach($entry['limitrepetitions'] as $index => $repetition) | ||||
|             <tr> | ||||
|                 <td> | ||||
|                     <a href="{{route('budgets.show',$rep->limit->budget->id)}}">{{{$rep->limit->budget->name}}}</a> | ||||
|  | ||||
|                     <div class="btn-group"> | ||||
|                         <a title="Edit budget {{{$repetition->limit->budget->name}}}" href="{{route('budgets.edit',$repetition->limit->budget->id)}}" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span></a> | ||||
|                         <a title="Delete budget {{{$repetition->limit->budget->name}}}" href="{{route('budgets.delete',$repetition->limit->budget->id)}}" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></a> | ||||
|                     </div> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <a href="{{route('budgets.show',$repetition->limit->budget->id)}}#transactions-in-this-period"> | ||||
|                         {{{$repetition->limit->budget->name}}} | ||||
|                     </a> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <span class="label label-primary"> | ||||
|                         <span class="glyphicon glyphicon-envelope"></span> {{mf($rep->amount,false)}}</span> | ||||
|                         <span class="glyphicon glyphicon-envelope"></span> {{mf($repetition->amount,false)}}</span> | ||||
|                 </td> | ||||
|                 <td> | ||||
|                 @if($rep->left() < 0) | ||||
|                 @if($repetition->left < 0) | ||||
|                             <span class="label label-danger"> | ||||
|                                 <span class="glyphicon glyphicon-envelope"></span> | ||||
|                                 {{mf($rep->left(),false)}}</span> | ||||
|                                 {{mf($repetition->left,false)}}</span> | ||||
|                 @else | ||||
|                             <span class="label label-success"> | ||||
|                                 <span class="glyphicon glyphicon-envelope"></span> | ||||
|                                 {{mf($rep->left(),false)}}</span> | ||||
|                                 {{mf($repetition->left,false)}}</span> | ||||
|                 @endif | ||||
|                 </td> | ||||
|                 <td> | ||||
|                     <div class="btn-group"> | ||||
|                         <a href="{{route('budgets.limits.edit',$rep->limit->id)}}" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span></a> | ||||
|                         <a href="{{route('budgets.limits.delete',$rep->limit->id)}}" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></a> | ||||
|                         <a title="Edit envelope for {{{$repetition->limit->budget->name}}} in {{$entry['date']}}" href="{{route('budgets.limits.edit',$repetition->limit->id)}}" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span></a> | ||||
|                         <a title="Delete envelope for {{{$repetition->limit->budget->name}}} in {{$entry['date']}}" href="{{route('budgets.limits.delete',$repetition->limit->id)}}" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></a> | ||||
|                     </div> | ||||
|                     @if($rep->limit->repeats == 1) | ||||
|                     @if($repetition->limit->repeats == 1) | ||||
|                         <span class="label label-warning">auto repeats</span> | ||||
|                     @endif | ||||
|                     <a href="{{route('budgets.limits.create',$rep->limit->budget->id)}}" class="btn btn-default btn-xs"><span | ||||
|                             class="glyphicon-plus-sign glyphicon"></span> Add another limit</a> | ||||
|                 </td> | ||||
|             </tr> | ||||
| @endforeach | ||||
|   | ||||
| @@ -56,7 +56,7 @@ | ||||
|         @foreach($set as $data) | ||||
|         <div class="col-lg-{{$split}} col-md-{{$split}}"> | ||||
|             <h4> | ||||
|                 <a href="{{route('accounts.show',$data[1]->id)}}?range={{Config::get('firefly.range_to_text.'.Session::get('range'))}}&startdate={{Session::get('start')->format('Y-m-d')}}">{{{$data[1]->name}}}</a> | ||||
|                 <a href="{{route('accounts.show',$data[1]->id)}}">{{{$data[1]->name}}}</a> | ||||
|             </h4> | ||||
|  | ||||
|             @include('transactions.journals-small',['transactions' => $data[0],'account' => $data[1]]) | ||||
|   | ||||
							
								
								
									
										71
									
								
								app/views/paginated/transactions.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/views/paginated/transactions.blade.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| <table class="table table-striped table-condensed"> | ||||
|     <tr> | ||||
|         <th colspan="2"></th> | ||||
|         <th>Date</th> | ||||
|         <th>Description</th> | ||||
|         <th>Amount (€)</th> | ||||
|         <th>From</th> | ||||
|         <th>To</th> | ||||
|         <th></th> | ||||
|     </tr> | ||||
|     @foreach($journals as $journal) | ||||
|     <tr> | ||||
|         <td> | ||||
|             @if($journal->transactiontype->type == 'Withdrawal') | ||||
|                 <span class="glyphicon glyphicon-arrow-left" title="Withdrawal"></span> | ||||
|             @endif | ||||
|             @if($journal->transactiontype->type == 'Deposit') | ||||
|                 <span class="glyphicon glyphicon-arrow-right" title="Deposit"></span> | ||||
|             @endif | ||||
|             @if($journal->transactiontype->type == 'Transfer') | ||||
|                 <span class="glyphicon glyphicon-resize-full" title="Transfer"></span> | ||||
|             @endif | ||||
|             @if($journal->transactiontype->type == 'Opening balance') | ||||
|                 <span class="glyphicon glyphicon-ban-circle" title="Opening balance"></span> | ||||
|             @endif | ||||
|         </td> | ||||
|         <td> | ||||
|             @foreach($journal->components as $component) | ||||
|             @if($component->class == 'Budget') | ||||
|             <a href="#budget-overview"><span class="glyphicon glyphicon-tasks" title="Budget: {{{$component->name}}}"></span></a> | ||||
|             @endif | ||||
|             @if($component->class == 'Category') | ||||
|             <a href="#category-overview"><span class="glyphicon glyphicon-tag" title="Category: {{{$component->name}}}"></span></a> | ||||
|             @endif | ||||
|             @endforeach | ||||
|         </td> | ||||
|         <td> | ||||
|             {{$journal->date->format('d F Y')}} | ||||
|         </td> | ||||
|         <td><a href="{{route('transactions.show',$journal->id)}}" title="{{{$journal->description}}}">{{{$journal->description}}}</a></td> | ||||
|         <td> | ||||
|             @if($journal->transactiontype->type == 'Withdrawal') | ||||
|                 <span class="text-danger">{{mf($journal->transactions[1]->amount,false)}}</span> | ||||
|             @endif | ||||
|             @if($journal->transactiontype->type == 'Deposit') | ||||
|                 <span class="text-success">{{mf($journal->transactions[1]->amount,false)}}</span> | ||||
|             @endif | ||||
|             @if($journal->transactiontype->type == 'Transfer') | ||||
|                 <span class="text-info">{{mf($journal->transactions[1]->amount,false)}}</span> | ||||
|             @endif | ||||
|         </td> | ||||
|         <td> | ||||
|             <a href="{{route('accounts.show',$journal->transactions[0]->account_id)}}">{{{$journal->transactions[0]->account->name}}}</a> | ||||
|         </td> | ||||
|         <td> | ||||
|             <a href="{{route('accounts.show',$journal->transactions[1]->account_id)}}">{{{$journal->transactions[1]->account->name}}}</a> | ||||
|         </td> | ||||
|         <td> | ||||
|             <div class="btn-group btn-group-xs"> | ||||
|                 <a href="{{route('transactions.edit',$journal->id)}}" class="btn btn-default"> | ||||
|                     <span class="glyphicon glyphicon-pencil"></span> | ||||
|                     <a href="{{route('transactions.delete',$journal->id)}}" class="btn btn-danger"> | ||||
|                         <span class="glyphicon glyphicon-trash"></span> | ||||
|                     </a> | ||||
|             </div> | ||||
|         </td> | ||||
|     </tr> | ||||
|     @endforeach | ||||
| </table> | ||||
|  | ||||
| {{$journals->links()}} | ||||
		Reference in New Issue
	
	Block a user