mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	New charts + tests.
This commit is contained in:
		| @@ -1,17 +1,19 @@ | ||||
| <?php | ||||
|  | ||||
| use Carbon\Carbon as Carbon; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use Firefly\Helper\Toolkit\Toolkit as tk; | ||||
| use Firefly\Storage\Account\AccountRepositoryInterface as ARI; | ||||
| use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI; | ||||
|  | ||||
| class ChartController extends BaseController | ||||
| { | ||||
|  | ||||
|     protected $accounts; | ||||
|     protected $journals; | ||||
|  | ||||
|     public function __construct(ARI $accounts) | ||||
|     public function __construct(ARI $accounts, TJRI $journals) | ||||
|     { | ||||
|         $this->accounts = $accounts; | ||||
|         $this->journals = $journals; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -19,7 +21,7 @@ class ChartController extends BaseController | ||||
|      */ | ||||
|     public function homeAccount($account = null) | ||||
|     { | ||||
|         list($start,$end) = tk::getDateRange(); | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|         $current = clone $start; | ||||
|  | ||||
|         // chart | ||||
| @@ -27,7 +29,6 @@ class ChartController extends BaseController | ||||
|         $chart->addColumn('Day of the month', 'date'); | ||||
|  | ||||
|  | ||||
|  | ||||
|         if (is_null($account)) { | ||||
|             // get accounts: | ||||
|             $accounts = $this->accounts->getActiveDefault(); | ||||
| @@ -61,7 +62,68 @@ class ChartController extends BaseController | ||||
|  | ||||
|         $chart->generate(); | ||||
|         return $chart->getData(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all budgets used in transaction(journals) this period: | ||||
|      */ | ||||
|     public function homeBudgets() | ||||
|     { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|  | ||||
|         $result = $this->journals->homeBudgetChart($start, $end); | ||||
|  | ||||
|         // create a chart: | ||||
|         $chart = App::make('gchart'); | ||||
|         $chart->addColumn('Budget', 'string'); | ||||
|         $chart->addColumn('Amount', 'number'); | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $chart->addRow($name, $amount); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all categories used in transaction(journals) this period. | ||||
|      */ | ||||
|     public function homeCategories() | ||||
|     { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|  | ||||
|         $result = $this->journals->homeCategoryChart($start, $end); | ||||
|  | ||||
|         // create a chart: | ||||
|         $chart = App::make('gchart'); | ||||
|         $chart->addColumn('Category', 'string'); | ||||
|         $chart->addColumn('Amount', 'number'); | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $chart->addRow($name, $amount); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * get all beneficiaries used in transaction(journals) this period. | ||||
|      */ | ||||
|     public function homeBeneficiaries() | ||||
|     { | ||||
|         list($start, $end) = tk::getDateRange(); | ||||
|  | ||||
|         $result = $this->journals->homeBeneficiaryChart($start, $end); | ||||
|  | ||||
|         // create a chart: | ||||
|         $chart = App::make('gchart'); | ||||
|         $chart->addColumn('Beneficiary', 'string'); | ||||
|         $chart->addColumn('Amount', 'number'); | ||||
|         foreach ($result as $name => $amount) { | ||||
|             $chart->addRow($name, $amount); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
| }  | ||||
| @@ -135,6 +135,99 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public function homeBudgetChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         return $this->homeComponentChart($start, $end, 'Budget'); | ||||
|     } | ||||
|  | ||||
|     public function homeComponentChart(\Carbon\Carbon $start, \Carbon\Carbon $end, $chartType) | ||||
|     { | ||||
|  | ||||
|         // lets make this simple. | ||||
|         $types = []; | ||||
|         foreach (\TransactionType::whereIn('type', ['Deposit', 'Withdrawal'])->get() as $t) { | ||||
|             $types[] = $t->id; | ||||
|         } | ||||
|         unset($t); | ||||
|  | ||||
|         // get all journals, partly filtered: | ||||
|         $journals = \TransactionJournal:: | ||||
|             with( | ||||
|                 ['components'         => function ($q) use ($chartType) { | ||||
|                         $q->where('class', $chartType); | ||||
|                     }, 'transactions' => function ($q) { | ||||
|                         $q->where('amount', '>', 0); | ||||
|                     }] | ||||
|             ) | ||||
|             ->after($start)->before($end) | ||||
|             ->whereIn('transaction_type_id', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|         unset($types); | ||||
|  | ||||
|  | ||||
|         foreach ($journals as $journal) { | ||||
|             // has to be one: | ||||
|             $transaction = $journal->transactions[0]; | ||||
|             $amount = floatval($transaction->amount); | ||||
|  | ||||
|  | ||||
|             // MIGHT be one: | ||||
|             $budget = isset($journal->components[0]) ? $journal->components[0] : null; | ||||
|             if (!is_null($budget)) { | ||||
|                 $name = $budget->name; | ||||
|             } else { | ||||
|                 $name = '(no budget)'; | ||||
|             } | ||||
|             $result[$name] = isset($result[$name]) ? $result[$name] + $amount : $amount; | ||||
|  | ||||
|         } | ||||
|         unset($journal, $transaction, $budget, $name, $amount); | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     public function homeCategoryChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         return $this->homeComponentChart($start, $end, 'Category'); | ||||
|     } | ||||
|  | ||||
|     public function homeBeneficiaryChart(\Carbon\Carbon $start, \Carbon\Carbon $end) | ||||
|     { | ||||
|         $result = []; | ||||
|  | ||||
|         // lets make this simple. | ||||
|         $types = []; | ||||
|         foreach (\TransactionType::whereIn('type', ['Deposit', 'Withdrawal'])->get() as $t) { | ||||
|             $types[] = $t->id; | ||||
|         } | ||||
|         unset($t); | ||||
|  | ||||
|         // account type we want to see: | ||||
|         $accountType = \AccountType::where('description', 'Beneficiary account')->first(); | ||||
|         $accountTypeID = $accountType->id; | ||||
|  | ||||
|         // get all journals, partly filtered: | ||||
|         $journals = \TransactionJournal:: | ||||
|             with( | ||||
|                 ['transactions', 'transactions.account' => function ($q) use ($accountTypeID) { | ||||
|                         $q->where('account_type_id', $accountTypeID); | ||||
|                     }] | ||||
|             ) | ||||
|             ->after($start)->before($end) | ||||
|             ->whereIn('transaction_type_id', $types) | ||||
|             ->get(['transaction_journals.*']); | ||||
|         foreach ($journals as $journal) { | ||||
|             foreach ($journal->transactions as $t) { | ||||
|                 if (!is_null($t->account)) { | ||||
|                     $name = $t->account->name; | ||||
|                     $amount = floatval($t->amount) < 0 ? floatval($t->amount) * -1 : floatval($t->amount); | ||||
|  | ||||
|                     $result[$name] = isset($result[$name]) ? $result[$name]+$amount : $amount; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     public function getByAccount(\Account $account, $count = 25) | ||||
|     { | ||||
|         $accountID = $account->id; | ||||
|   | ||||
| @@ -11,4 +11,10 @@ interface TransactionJournalRepositoryInterface | ||||
|  | ||||
|     public function getByAccount(\Account $account, $count = 25); | ||||
|  | ||||
|     public function homeBudgetChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|     public function homeCategoryChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|     public function homeBeneficiaryChart(\Carbon\Carbon $start, \Carbon\Carbon $end); | ||||
|  | ||||
|     public function homeComponentChart(\Carbon\Carbon $start, \Carbon\Carbon $end, $chartType); | ||||
|  | ||||
| } | ||||
| @@ -48,4 +48,11 @@ class TransactionJournal extends Elegant | ||||
|         return array('created_at', 'updated_at', 'date'); | ||||
|     } | ||||
|  | ||||
|     public function scopeAfter($query, \Carbon\Carbon $date) { | ||||
|         return $query->where('date','>=',$date->format('Y-m-d')); | ||||
|     } | ||||
|     public function scopeBefore($query, \Carbon\Carbon $date) { | ||||
|         return $query->where('date','<=',$date->format('Y-m-d')); | ||||
|     } | ||||
|  | ||||
| }  | ||||
| @@ -7,6 +7,9 @@ Route::group(['before' => 'auth'], function () { | ||||
|  | ||||
|         // chart controller | ||||
|         Route::get('/chart/home/account/{account?}', ['uses' => 'ChartController@homeAccount', 'as' => 'chart.home']); | ||||
|         Route::get('/chart/home/budgets', ['uses' => 'ChartController@homeBudgets', 'as' => 'chart.budgets']); | ||||
|         Route::get('/chart/home/beneficiaries', ['uses' => 'ChartController@homeBeneficiaries', 'as' => 'chart.beneficiaries']); | ||||
|         Route::get('/chart/home/categories', ['uses' => 'ChartController@homeCategories', 'as' => 'chart.categories']); | ||||
|  | ||||
|         // preferences controller | ||||
|         Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']); | ||||
|   | ||||
| @@ -132,4 +132,94 @@ class ChartControllerTest extends TestCase | ||||
|         $this->assertResponseOk(); | ||||
|         $this->assertViewHas('message'); | ||||
|     } | ||||
|  | ||||
|     public function testhomeBudgets() | ||||
|     { | ||||
|         // mock preference: | ||||
|         $pref = $this->mock('Preference'); | ||||
|         $pref->shouldReceive('getAttribute', 'data')->andReturn('week'); | ||||
|  | ||||
|         $start = new \Carbon\Carbon; | ||||
|         $end = new \Carbon\Carbon; | ||||
|  | ||||
|         // mock transaction journal | ||||
|         $tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); | ||||
|         $tj->shouldReceive('homeBudgetChart')->andReturn(['entry' => 30]); | ||||
|  | ||||
|         // mock toolkit: | ||||
|         $toolkit = $this->mock('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|         $toolkit->shouldReceive('getDateRange')->andReturn([$start, $end]); | ||||
|  | ||||
|  | ||||
|         // mock preferences helper: | ||||
|         $preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|         $preferences->shouldReceive('get')->with('viewRange', 'week')->once()->andReturn($pref); | ||||
|  | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/chart/home/budgets'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testhomeCategories() | ||||
|     { | ||||
|         // mock preference: | ||||
|         $pref = $this->mock('Preference'); | ||||
|         $pref->shouldReceive('getAttribute', 'data')->andReturn('week'); | ||||
|  | ||||
|         $start = new \Carbon\Carbon; | ||||
|         $end = new \Carbon\Carbon; | ||||
|  | ||||
|         // mock transaction journal | ||||
|         $tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); | ||||
|         $tj->shouldReceive('homeCategoryChart')->andReturn(['entry' => 30]); | ||||
|  | ||||
|         // mock toolkit: | ||||
|         $toolkit = $this->mock('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|         $toolkit->shouldReceive('getDateRange')->andReturn([$start, $end]); | ||||
|  | ||||
|  | ||||
|         // mock preferences helper: | ||||
|         $preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|         $preferences->shouldReceive('get')->with('viewRange', 'week')->once()->andReturn($pref); | ||||
|  | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/chart/home/categories'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
|  | ||||
|     public function testhomeBeneficiaries() | ||||
|     { | ||||
|         // mock preference: | ||||
|         $pref = $this->mock('Preference'); | ||||
|         $pref->shouldReceive('getAttribute', 'data')->andReturn('week'); | ||||
|  | ||||
|         $start = new \Carbon\Carbon; | ||||
|         $end = new \Carbon\Carbon; | ||||
|  | ||||
|         // mock transaction journal | ||||
|         $tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'); | ||||
|         $tj->shouldReceive('homeBeneficiaryChart')->andReturn(['entry' => 30]); | ||||
|  | ||||
|         // mock toolkit: | ||||
|         $toolkit = $this->mock('Firefly\Helper\Toolkit\ToolkitInterface'); | ||||
|         $toolkit->shouldReceive('getDateRange')->andReturn([$start, $end]); | ||||
|  | ||||
|  | ||||
|         // mock preferences helper: | ||||
|         $preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface'); | ||||
|         $preferences->shouldReceive('get')->with('viewRange', 'week')->once()->andReturn($pref); | ||||
|  | ||||
|  | ||||
|         // call | ||||
|         $this->call('GET', '/chart/home/beneficiaries'); | ||||
|  | ||||
|         // test | ||||
|         $this->assertResponseOk(); | ||||
|     } | ||||
| } | ||||
| @@ -81,14 +81,18 @@ | ||||
|     <div class="row"> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <h4>Beneficiaries</h4> | ||||
|             <div id="beneficiaryChart"></div> | ||||
|         </div> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <h4>Categories</h4> | ||||
|             <div id="categoryChart"></div> | ||||
|         </div> | ||||
|         <div class="col-lg-4 col-sm-6 col-md-6"> | ||||
|             <h4>Budgets</h4> | ||||
|             <div id="budgetChart"></div> | ||||
|         </div> | ||||
|     </div> | ||||
|     <br /><br /><br /><br /><br /> | ||||
|  | ||||
|  | ||||
| @endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user