diff --git a/app/controllers/ChartController.php b/app/controllers/ChartController.php index b0d8ec7458..af43fe323a 100644 --- a/app/controllers/ChartController.php +++ b/app/controllers/ChartController.php @@ -1,17 +1,19 @@ 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()); } } \ No newline at end of file diff --git a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php index 6beb5f255f..9fa1dc839c 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php +++ b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php @@ -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; diff --git a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php index 350c189388..d7cc4aa5d5 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php +++ b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php @@ -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); + } \ No newline at end of file diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php index a99ce4e022..8b6ff79e8d 100644 --- a/app/models/TransactionJournal.php +++ b/app/models/TransactionJournal.php @@ -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')); + } + } \ No newline at end of file diff --git a/app/routes.php b/app/routes.php index 0e369b101f..b09ff0416e 100644 --- a/app/routes.php +++ b/app/routes.php @@ -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']); diff --git a/app/tests/controllers/ChartControllerTest.php b/app/tests/controllers/ChartControllerTest.php index 47afa74fbb..57bab4bad0 100644 --- a/app/tests/controllers/ChartControllerTest.php +++ b/app/tests/controllers/ChartControllerTest.php @@ -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(); + } } \ No newline at end of file diff --git a/app/views/index.blade.php b/app/views/index.blade.php index 6bf48df680..69e6f4bebc 100644 --- a/app/views/index.blade.php +++ b/app/views/index.blade.php @@ -81,14 +81,18 @@