From c907cb4cf1da51d868f48256706d487d14cf8e0c Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 6 Apr 2015 09:15:59 +0200 Subject: [PATCH 01/66] General cleanup and new (incomplete) tests. --- .../Controllers/GoogleChartController.php | 156 +++++------------- app/Http/routes.php | 3 +- app/Repositories/Bill/BillRepository.php | 35 +++- .../Bill/BillRepositoryInterface.php | 9 +- app/Repositories/Budget/BudgetRepository.php | 96 +++++++++-- .../Budget/BudgetRepositoryInterface.php | 109 +++++++----- .../Category/CategoryRepository.php | 33 ++++ .../Category/CategoryRepositoryInterface.php | 8 + .../controllers/GoogleChartControllerTest.php | 107 ++++++++++++ 9 files changed, 385 insertions(+), 171 deletions(-) create mode 100644 tests/controllers/GoogleChartControllerTest.php diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 0c0ce8138b..9285487ab0 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -17,11 +17,11 @@ use FireflyIII\Models\PiggyBank; use FireflyIII\Models\Preference; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use Grumpydictator\Gchart\GChart; -use Illuminate\Database\Query\Builder as QueryBuilder; -use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; use Navigation; use Preferences; @@ -46,9 +46,8 @@ class GoogleChartController extends Controller */ public function accountBalanceChart(Account $account, GChart $chart) { - $accountName = iconv('UTF-8', 'ASCII//TRANSLIT', $account->name); $chart->addColumn('Day of month', 'date'); - $chart->addColumn('Balance for ' . $accountName, 'number'); + $chart->addColumn('Balance for ' . $account->name, 'number'); $chart->addCertainty(1); $start = Session::get('start', Carbon::now()->startOfMonth()); @@ -73,19 +72,15 @@ class GoogleChartController extends Controller * * @return \Symfony\Component\HttpFoundation\Response */ - public function allAccountsBalanceChart(GChart $chart) + public function allAccountsBalanceChart(GChart $chart, AccountRepositoryInterface $repository) { $chart->addColumn('Day of the month', 'date'); $frontPage = Preferences::get('frontPageAccounts', []); $start = Session::get('start', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth()); + $accounts = $repository->getFrontpageAccounts($frontPage); - if ($frontPage->data == []) { - $accounts = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']); - } else { - $accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']); - } $index = 1; /** @var Account $account */ foreach ($accounts as $account) { @@ -108,7 +103,7 @@ class GoogleChartController extends Controller $current->addDay(); } $chart->generate(); - //header('Content-Type: application/json; charset=utf-8'); + return Response::json($chart->getData()); } @@ -120,22 +115,16 @@ class GoogleChartController extends Controller */ public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository) { - try { - new Carbon('01-01-' . $year); - } catch (Exception $e) { - return view('error')->with('message', 'Invalid year.'); - } - $budgets = Auth::user()->budgets()->get(); - $budgets->sortBy('name'); + $budgets = $repository->getBudgets(); $chart->addColumn('Month', 'date'); foreach ($budgets as $budget) { $chart->addColumn($budget->name, 'number'); } + $start = Carbon::createFromDate(intval($year), 1, 1); $end = clone $start; $end->endOfYear(); - while ($start <= $end) { $row = [clone $start]; foreach ($budgets as $budget) { @@ -146,7 +135,6 @@ class GoogleChartController extends Controller $start->addMonth(); } - $chart->generate(); return Response::json($chart->getData()); @@ -158,73 +146,44 @@ class GoogleChartController extends Controller * * @return \Symfony\Component\HttpFoundation\Response */ - public function allBudgetsHomeChart(GChart $chart) + public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository) { $chart->addColumn('Budget', 'string'); $chart->addColumn('Budgeted', 'number'); $chart->addColumn('Spent', 'number'); - $budgets = Auth::user()->budgets()->orderBy('name', 'DESC')->get(); - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); + $budgets = $repository->getBudgets(); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); + $allEntries = new Collection; - /** @var Budget $budget */ foreach ($budgets as $budget) { - - /** @var Collection $repetitions */ - $repetitions = LimitRepetition:: - leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') - ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) - ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) - ->where('budget_limits.budget_id', $budget->id) - ->get(['limit_repetitions.*']); - - // no results? search entire range for expenses and list those. + $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); if ($repetitions->count() == 0) { - $expenses = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; - if ($expenses > 0) { - $chart->addRow($budget->name, 0, $expenses); - } - } else { - // add with foreach: - /** @var LimitRepetition $repetition */ - foreach ($repetitions as $repetition) { - - $expenses - = - floatval($budget->transactionjournals()->before($repetition->enddate)->after($repetition->startdate)->lessThan(0)->sum('amount')) * -1; - if ($expenses > 0) { - $chart->addRow($budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses); - } - } + $expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end); + $allEntries->push([$budget->name, 0, $expenses]); + continue; + } + /** @var LimitRepetition $repetition */ + foreach ($repetitions as $repetition) { + $expenses = $repository->sumBudgetExpensesInPeriod($budget, $repetition->startdate, $repetition->enddate); + $allEntries->push([$budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses]); + } + } + + $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end); + $allEntries->push(['(no budget)', 0, $noBudgetExpenses]); + + foreach ($allEntries as $entry) { + if ($entry[2] > 0) { + $chart->addRow($entry[0], $entry[1], $entry[2]); } - - } - $noBudgetSet = Auth::user() - ->transactionjournals() - ->whereNotIn( - 'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) { - $query - ->select('transaction_journals.id') - ->from('transaction_journals') - ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) - ->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')) - ->whereNotNull('budget_transaction_journal.budget_id'); - } - ) - ->before($end) - ->after($start) - ->lessThan(0) - ->transactionTypes(['Withdrawal']) - ->get(); - $sum = $noBudgetSet->sum('amount') * -1; - $chart->addRow('No budget', 0, $sum); $chart->generate(); return Response::json($chart->getData()); + } /** @@ -232,34 +191,14 @@ class GoogleChartController extends Controller * * @return \Symfony\Component\HttpFoundation\Response */ - public function allCategoriesHomeChart(GChart $chart) + public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository) { $chart->addColumn('Category', 'string'); $chart->addColumn('Spent', 'number'); - // query! $start = Session::get('start', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth()); - $set = TransactionJournal:: - where('transaction_journals.user_id', Auth::user()->id) - ->leftJoin( - 'transactions', - function (JoinClause $join) { - $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); - } - ) - ->leftJoin( - 'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' - ) - ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') - ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') - ->before($end) - ->where('categories.user_id', Auth::user()->id) - ->after($start) - ->where('transaction_types.type', 'Withdrawal') - ->groupBy('categories.id') - ->orderBy('sum', 'DESC') - ->get(['categories.id', 'categories.encrypted', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); + $set = $repository->getCategoriesAndExpenses($start, $end); foreach ($set as $entry) { $isEncrypted = intval($entry->encrypted) == 1 ? true : false; @@ -275,11 +214,12 @@ class GoogleChartController extends Controller } /** - * @param Bill $bill + * @param Bill $bill + * @param GChart $chart * - * @return \Illuminate\Http\JsonResponse + * @return \Symfony\Component\HttpFoundation\Response */ - public function billOverview(Bill $bill, GChart $chart) + public function billOverview(Bill $bill, GChart $chart, BillRepositoryInterface $repository) { $chart->addColumn('Date', 'date'); @@ -288,24 +228,10 @@ class GoogleChartController extends Controller $chart->addColumn('Recorded bill entry', 'number'); // get first transaction or today for start: - $first = $bill->transactionjournals()->orderBy('date', 'ASC')->first(); - if ($first) { - $start = $first->date; - } else { - $start = new Carbon; - } - - $results = $bill->transactionjournals()->after($start)->get(); + $results = $repository->getJournals($bill); /** @var TransactionJournal $result */ foreach ($results as $result) { - $amount = 0; - /** @var Transaction $tr */ - foreach ($result->transactions()->get() as $tr) { - if (floatval($tr->amount) > 0) { - $amount = floatval($tr->amount); - } - } - $chart->addRow(clone $result->date, $bill->amount_max, $bill->amount_min, $amount); + $chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount)); } $chart->generate(); @@ -330,7 +256,7 @@ class GoogleChartController extends Controller $start = Session::get('start', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth()); - $bills = Auth::user()->bills()->where('active', 1)->get(); + $bills = $repository->getActiveBills(); /** @var Bill $bill */ foreach ($bills as $bill) { diff --git a/app/Http/routes.php b/app/Http/routes.php index 3b6a5bc63f..890337b1cd 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -170,7 +170,6 @@ Route::group( Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']); Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']); Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']); - Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']); Route::post('/bills/update/{bill}', ['uses' => 'BillController@update', 'as' => 'bills.update']); Route::post('/bills/destroy/{bill}', ['uses' => 'BillController@destroy', 'as' => 'bills.destroy']); @@ -226,7 +225,7 @@ Route::group( Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']); Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']); Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']); - Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending']); + Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending'])->where(['year' => '[0-9]+']); Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']); Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']); diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 049634ac40..837713d87b 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -7,6 +7,7 @@ use Carbon\Carbon; use FireflyIII\Models\Bill; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; use Log; use Navigation; @@ -33,7 +34,15 @@ class BillRepository implements BillRepositoryInterface */ public function getBills() { - return Auth::user()->bills()->orderBy('name', 'ASC')->get(); + /** @var Collection $set */ + $set = Auth::user()->bills()->orderBy('name', 'ASC')->get(); + $set->sort( + function (Bill $bill) { + return $bill->name; + } + ); + + return $set; } /** @@ -44,10 +53,16 @@ class BillRepository implements BillRepositoryInterface public function getJournals(Bill $bill) { return $bill->transactionjournals()->withRelevantData() + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.amount', '>', 0); + } + ) ->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.order', 'ASC') ->orderBy('transaction_journals.id', 'DESC') - ->get(); + ->get(['transaction_journals.*', 'transactions.amount']); } /** @@ -307,4 +322,20 @@ class BillRepository implements BillRepositoryInterface return $bill; } + + /** + * @return Collection + */ + public function getActiveBills() + { + /** @var Collection $set */ + $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get(); + $set->sort( + function (Bill $bill) { + return $bill->name; + } + ); + + return $set; + } } diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 134d275f00..a0fbe7eac9 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -22,6 +22,11 @@ interface BillRepositoryInterface */ public function destroy(Bill $bill); + /** + * @return Collection + */ + public function getActiveBills(); + /** * @return Collection */ @@ -32,14 +37,14 @@ interface BillRepositoryInterface * * @return Collection */ - public function getPossiblyRelatedJournals(Bill $bill); + public function getJournals(Bill $bill); /** * @param Bill $bill * * @return Collection */ - public function getJournals(Bill $bill); + public function getPossiblyRelatedJournals(Bill $bill); /** * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 5d614286bd..1fa943c0cd 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -9,6 +9,7 @@ use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\LimitRepetition; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; +use Illuminate\Database\Query\Builder as QueryBuilder; /** * Class BudgetRepository @@ -60,7 +61,49 @@ class BudgetRepository implements BudgetRepositoryInterface */ public function getActiveBudgets() { - return Auth::user()->budgets()->where('active', 1)->get(); + $budgets = Auth::user()->budgets()->where('active', 1)->get(); + $budgets->sortBy('name'); + + return $budgets; + } + + /** + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end) + { + /** @var Collection $repetitions */ + return LimitRepetition:: + leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') + ->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00')) + ->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00')) + ->where('budget_limits.budget_id', $budget->id) + ->get(['limit_repetitions.*']); + } + + /** + * @param Budget $budget + * + * @return Collection + */ + public function getBudgetLimits(Budget $budget) + { + return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); + } + + /** + * @return Collection + */ + public function getBudgets() + { + $budgets = Auth::user()->budgets()->get(); + $budgets->sortBy('name'); + + return $budgets; } /** @@ -135,6 +178,35 @@ class BudgetRepository implements BudgetRepositoryInterface ->get(['transaction_journals.*']); } + /** + * @param Carbon $start + * @param Carbon $end + * + * @return mixed + */ + public function getWithoutBudgetSum(Carbon $start, Carbon $end) + { + $noBudgetSet = Auth::user() + ->transactionjournals() + ->whereNotIn( + 'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) { + $query + ->select('transaction_journals.id') + ->from('transaction_journals') + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')) + ->whereNotNull('budget_transaction_journal.budget_id'); + } + ) + ->before($end) + ->after($start) + ->lessThan(0) + ->transactionTypes(['Withdrawal']) + ->get(); + return floatval($noBudgetSet->sum('amount')) * -1; + } + /** * @param Budget $budget * @param Carbon $date @@ -169,6 +241,18 @@ class BudgetRepository implements BudgetRepositoryInterface return $newBudget; } + /** + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return float + */ + public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end) + { + return floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; + } + /** * @param Budget $budget * @param array $data @@ -224,14 +308,4 @@ class BudgetRepository implements BudgetRepositoryInterface } - - /** - * @param Budget $budget - * - * @return Collection - */ - public function getBudgetLimits(Budget $budget) - { - return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); - } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 38cdc43532..c1d8e1c230 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -14,6 +14,11 @@ use Illuminate\Support\Collection; */ interface BudgetRepositoryInterface { + /** + * @return void + */ + public function cleanupBudgets(); + /** * @param Budget $budget * @@ -26,31 +31,14 @@ interface BudgetRepositoryInterface */ public function getActiveBudgets(); - /** - * @return Collection - */ - public function getInactiveBudgets(); - - /** - * @return void - */ - public function cleanupBudgets(); - /** * @param Budget $budget - * @param Carbon $date - * - * @return float - */ - public function spentInMonth(Budget $budget, Carbon $date); - - /** * @param Carbon $start * @param Carbon $end * * @return Collection */ - public function getWithoutBudget(Carbon $start, Carbon $end); + public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end); /** * @param Budget $budget @@ -59,6 +47,11 @@ interface BudgetRepositoryInterface */ public function getBudgetLimits(Budget $budget); + /** + * @return Collection + */ + public function getBudgets(); + /** * @param Budget $budget * @param Carbon $date @@ -68,28 +61,9 @@ interface BudgetRepositoryInterface public function getCurrentRepetition(Budget $budget, Carbon $date); /** - * @param Budget $budget - * @param Carbon $date - * @param $amount - * - * @return mixed + * @return Collection */ - public function updateLimitAmount(Budget $budget, Carbon $date, $amount); - - /** - * @param array $data - * - * @return Budget - */ - public function store(array $data); - - /** - * @param Budget $budget - * @param array $data - * - * @return Budget - */ - public function update(Budget $budget, array $data); + public function getInactiveBudgets(); /** * Returns all the transaction journals for a limit, possibly limited by a limit repetition. @@ -102,4 +76,61 @@ interface BudgetRepositoryInterface */ public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50); + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutBudget(Carbon $start, Carbon $end); + + /** + * @param Carbon $start + * @param Carbon $end + * + * @return mixed + */ + public function getWithoutBudgetSum(Carbon $start, Carbon $end); + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function spentInMonth(Budget $budget, Carbon $date); + + /** + * @param array $data + * + * @return Budget + */ + public function store(array $data); + + /** + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return float + */ + public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end); + + /** + * @param Budget $budget + * @param array $data + * + * @return Budget + */ + public function update(Budget $budget, array $data); + + /** + * @param Budget $budget + * @param Carbon $date + * @param $amount + * + * @return mixed + */ + public function updateLimitAmount(Budget $budget, Carbon $date, $amount); + } diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 3b8710a3f4..75f04b5ad7 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -4,7 +4,10 @@ namespace FireflyIII\Repositories\Category; use Auth; use Carbon\Carbon; +use DB; use FireflyIII\Models\Category; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; /** @@ -46,6 +49,36 @@ class CategoryRepository implements CategoryRepositoryInterface return Auth::user()->categories()->orderBy('name', 'ASC')->get(); } + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getCategoriesAndExpenses($start, $end) + { + return TransactionJournal:: + where('transaction_journals.user_id', Auth::user()->id) + ->leftJoin( + 'transactions', + function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); + } + ) + ->leftJoin( + 'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' + ) + ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->before($end) + ->where('categories.user_id', Auth::user()->id) + ->after($start) + ->where('transaction_types.type', 'Withdrawal') + ->groupBy('categories.id') + ->orderBy('sum', 'DESC') + ->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); + } + /** * @param Category $category * @param int $page diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index 33ba5cc1d1..7faa595b60 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -32,6 +32,14 @@ interface CategoryRepositoryInterface */ public function getCategories(); + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getCategoriesAndExpenses($start, $end); + /** * @param Category $category * @param int $page diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php new file mode 100644 index 0000000000..03e1c5fe9f --- /dev/null +++ b/tests/controllers/GoogleChartControllerTest.php @@ -0,0 +1,107 @@ +markTestIncomplete(); + } + + public function testAllAccountsBalanceChart() + { + $this->markTestIncomplete(); + } + + public function testAllBudgetsAndSpending() + { + $this->markTestIncomplete(); + } + + public function testAllBudgetsHomeChart() + { + $this->markTestIncomplete(); + } + + public function testAllCategoriesHomeChart() + { + $this->markTestIncomplete(); + } + + public function testBillOverview() + { + $this->markTestIncomplete(); + } + + public function testBillsOverview() + { + $this->markTestIncomplete(); + } + + public function testBudgetLimitSpending() + { + $this->markTestIncomplete(); + } + + public function testBudgetsAndSpending() + { + $this->markTestIncomplete(); + } + + public function testCategoryOverviewChart() + { + $this->markTestIncomplete(); + } + + public function testCategoryPeriodChart() + { + $this->markTestIncomplete(); + } + + public function testPiggyBankHistory() + { + $this->markTestIncomplete(); + } + + public function testYearInExp() + { + $this->markTestIncomplete(); + } + + public function testYearInExpSum() + { + $this->markTestIncomplete(); + } + +} \ No newline at end of file From b2674971f10f2969560abed5537a50bb8027235f Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 6 Apr 2015 09:20:45 +0200 Subject: [PATCH 02/66] Updated composer.lock. --- composer.lock | 109 ++++++++++++++++++++++++++------------------------ 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/composer.lock b/composer.lock index 889d37ed8f..ed45ccf657 100644 --- a/composer.lock +++ b/composer.lock @@ -677,16 +677,16 @@ }, { "name": "grumpydictator/gchart", - "version": "1.0.8", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/JC5/gchart.git", - "reference": "24d06101cfda7ff336ecb10f7f0cb0d6004cb83c" + "reference": "920a0494a0697472bf81c0111b6825c516099e59" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JC5/gchart/zipball/24d06101cfda7ff336ecb10f7f0cb0d6004cb83c", - "reference": "24d06101cfda7ff336ecb10f7f0cb0d6004cb83c", + "url": "https://api.github.com/repos/JC5/gchart/zipball/920a0494a0697472bf81c0111b6825c516099e59", + "reference": "920a0494a0697472bf81c0111b6825c516099e59", "shasum": "" }, "require": { @@ -709,7 +709,7 @@ } ], "description": "GChart is a small package that allows you to easily generate data for the Google Charts API.", - "time": "2015-02-20 20:07:26" + "time": "2015-04-05 19:17:17" }, { "name": "illuminate/html", @@ -945,16 +945,16 @@ }, { "name": "laravel/framework", - "version": "v5.0.26", + "version": "v5.0.27", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "8e53c33e144f94032cc6ecbfee0be2a96ed63be0" + "reference": "4d6330118a295086ce9ff8eed2200d5b67f17688" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/8e53c33e144f94032cc6ecbfee0be2a96ed63be0", - "reference": "8e53c33e144f94032cc6ecbfee0be2a96ed63be0", + "url": "https://api.github.com/repos/laravel/framework/zipball/4d6330118a295086ce9ff8eed2200d5b67f17688", + "reference": "4d6330118a295086ce9ff8eed2200d5b67f17688", "shasum": "" }, "require": { @@ -1067,7 +1067,7 @@ "framework", "laravel" ], - "time": "2015-04-03 02:58:05" + "time": "2015-04-04 01:34:57" }, { "name": "league/commonmark", @@ -1377,16 +1377,16 @@ }, { "name": "nikic/php-parser", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dba7524b3724f25b947cd26a580787c55c8a6f9b" + "reference": "08f97eb4efa029e2fafb6d8c98b71731bf0cf621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dba7524b3724f25b947cd26a580787c55c8a6f9b", - "reference": "dba7524b3724f25b947cd26a580787c55c8a6f9b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/08f97eb4efa029e2fafb6d8c98b71731bf0cf621", + "reference": "08f97eb4efa029e2fafb6d8c98b71731bf0cf621", "shasum": "" }, "require": { @@ -1418,7 +1418,7 @@ "parser", "php" ], - "time": "2015-03-24 19:10:28" + "time": "2015-04-03 14:33:59" }, { "name": "psr/log", @@ -3225,31 +3225,33 @@ }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", + "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -3266,7 +3268,7 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2015-04-02 05:19:05" }, { "name": "phpunit/php-text-template", @@ -3407,16 +3409,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.5.1", + "version": "4.6.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4" + "reference": "08b2aacdd8433abbba468f995d6d64b76a7a62ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4", - "reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/08b2aacdd8433abbba468f995d6d64b76a7a62ec", + "reference": "08b2aacdd8433abbba468f995d6d64b76a7a62ec", "shasum": "" }, "require": { @@ -3428,17 +3430,17 @@ "php": ">=5.3.3", "phpspec/prophecy": "~1.3,>=1.3.1", "phpunit/php-code-coverage": "~2.0,>=2.0.11", - "phpunit/php-file-iterator": "~1.3.2", + "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0.2", + "phpunit/php-timer": "~1.0", "phpunit/phpunit-mock-objects": "~2.3", "sebastian/comparator": "~1.1", - "sebastian/diff": "~1.1", + "sebastian/diff": "~1.2", "sebastian/environment": "~1.2", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", - "symfony/yaml": "~2.0" + "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" @@ -3449,12 +3451,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.5.x-dev" + "dev-master": "4.6.x-dev" } }, "autoload": { "classmap": [ "src/" + ], + "files": [ + "src/Framework/Assert/Functions.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3475,7 +3480,7 @@ "testing", "xunit" ], - "time": "2015-03-29 09:24:05" + "time": "2015-04-03 13:46:59" }, { "name": "phpunit/phpunit-mock-objects", @@ -3666,16 +3671,16 @@ }, { "name": "sebastian/diff", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "5843509fed39dee4b356a306401e9dd1a931fec7" + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7", - "reference": "5843509fed39dee4b356a306401e9dd1a931fec7", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", + "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", "shasum": "" }, "require": { @@ -3687,7 +3692,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.3-dev" } }, "autoload": { @@ -3714,32 +3719,32 @@ "keywords": [ "diff" ], - "time": "2014-08-15 10:29:00" + "time": "2015-02-22 15:13:53" }, { "name": "sebastian/environment", - "version": "1.2.1", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7" + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7", - "reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", + "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { - "phpunit/phpunit": "~4.3" + "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { @@ -3764,7 +3769,7 @@ "environment", "hhvm" ], - "time": "2014-10-25 08:00:45" + "time": "2015-01-01 10:01:08" }, { "name": "sebastian/exporter", @@ -3938,16 +3943,16 @@ }, { "name": "sebastian/version", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", - "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", "shasum": "" }, "type": "library", @@ -3969,7 +3974,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2014-12-15 14:25:24" + "time": "2015-02-24 06:35:25" }, { "name": "symfony/class-loader", From 701efb943df2f9782ee2b5adacc7905312d31e44 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 10:14:10 +0200 Subject: [PATCH 03/66] Lots of new tests. --- .../Controllers/GoogleChartController.php | 100 +++++------- app/Models/TransactionJournal.php | 13 ++ .../Account/AccountRepository.php | 52 ++++++- .../Account/AccountRepositoryInterface.php | 16 ++ app/Repositories/Bill/BillRepository.php | 71 +++++++-- .../Bill/BillRepositoryInterface.php | 24 +++ app/Repositories/Budget/BudgetRepository.php | 11 ++ .../Budget/BudgetRepositoryInterface.php | 8 + .../controllers/GoogleChartControllerTest.php | 146 +++++++++++++++++- 9 files changed, 355 insertions(+), 86 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 9285487ab0..e3117a6616 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -1,8 +1,6 @@ addColumn('Name', 'string'); $chart->addColumn('Amount', 'number'); - - $paid = ['items' => [], 'amount' => 0]; - $unpaid = ['items' => [], 'amount' => 0]; $start = Session::get('start', Carbon::now()->startOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth()); - - $bills = $repository->getActiveBills(); + $bills = $repository->getActiveBills(); + $paid = new Collection; // journals. + $unpaid = new Collection; // bills /** @var Bill $bill */ foreach ($bills as $bill) { @@ -264,71 +260,55 @@ class GoogleChartController extends Controller foreach ($ranges as $range) { // paid a bill in this range? - $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); - if ($count == 0) { - $unpaid['items'][] = $bill->name . ' (' . $range['start']->format('jS M Y') . ')'; - $unpaid['amount'] += ($bill->amount_max + $bill->amount_min / 2); - + $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); + if ($journals->count() == 0) { + $unpaid->push([$bill, $range['start']]); } else { - $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); - $paid['items'][] = $journal->description; - $amount = 0; - foreach ($journal->transactions as $t) { - if (floatval($t->amount) > 0) { - $amount = floatval($t->amount); - } - } - $paid['amount'] += $amount; + $paid = $paid->merge($journals); } } } - /** - * Find credit card accounts and possibly unpaid credit card bills. - */ - $creditCards = Auth::user()->accounts() - ->hasMetaValue('accountRole', 'ccAsset') - ->hasMetaValue('ccType', 'monthlyFull') - ->get( - [ - 'accounts.*', - 'ccType.data as ccType', - 'accountRole.data as accountRole' - ] - ); - // if the balance is not zero, the monthly payment is still underway. - /** @var Account $creditCard */ + $creditCards = $accounts->getCreditCards(); foreach ($creditCards as $creditCard) { $balance = Steam::balance($creditCard, null, true); $date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); if ($balance < 0) { - // unpaid! - $unpaid['amount'] += $balance * -1; - $unpaid['items'][] = $creditCard->name . ' (expected ' . Amount::format(($balance * -1), false) . ') on the ' . $date->format('jS') . ')'; + // unpaid! create a fake bill that matches the amount. + $description = $creditCard->name; + $amount = $balance * -1; + $fakeBill = $repository->createFakeBill($description, $date, $amount); + $unpaid->push([$fakeBill, $date]); } if ($balance == 0) { - // find a transfer TO the credit card which should account for + // find transfer(s) TO the credit card which should account for // anything paid. If not, the CC is not yet used. - $transactions = $creditCard->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->before($end)->after($start)->get(); - if ($transactions->count() > 0) { - /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $journal = $transaction->transactionJournal; - if ($journal->transactionType->type == 'Transfer') { - $paid['amount'] += floatval($transaction->amount); - $paid['items'][] = $creditCard->name . - ' (paid ' . Amount::format((floatval($transaction->amount)), false) . - ' on the ' . $journal->date->format('jS') . ')'; - } - } - } + $journals = $accounts->getTransfersInRange($creditCard, $start, $end); + $paid = $paid->merge($journals); } } - $chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']); - $chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']); + // loop paid and create single entry: + $paidDescriptions = []; + $paidAmount = 0; + $unpaidDescriptions = []; + $unpaidAmount = 0; + + /** @var TransactionJournal $entry */ + foreach ($paid as $entry) { + $paidDescriptions[] = $entry->description; + $paidAmount += floatval($entry->amount); + } + + // loop unpaid: + /** @var Bill $entry */ + foreach ($unpaid as $entry) { + $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; + $unpaidAmount += ($bill->amount_max + $bill->amount_min / 2); + } + + $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); + $chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount); $chart->generate(); return Response::json($chart->getData()); @@ -341,7 +321,7 @@ class GoogleChartController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart) + public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart, BudgetRepositoryInterface $repository) { $start = clone $repetition->startdate; $end = $repetition->enddate; @@ -356,7 +336,7 @@ class GoogleChartController extends Controller /* * Sum of expenses on this day: */ - $sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount')); + $sum = $repository->expensesOnDay($budget, $start); $amount += $sum; $chart->addRow(clone $start, $amount); $start->addDay(); diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index 2745f8379f..d9af19b51e 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -55,6 +55,19 @@ class TransactionJournal extends Model return $this->belongsToMany('FireflyIII\Models\Category'); } + /** + * @return float + */ + public function getAmountAttribute() + { + /** @var Transaction $t */ + foreach ($this->transactions as $t) { + if ($t->amount > 0) { + return floatval($t->amount); + } + } + } + /** * @return array */ diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index b09f53bdae..50807a32b9 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -66,13 +66,33 @@ class AccountRepository implements AccountRepositoryInterface )->accountTypeIn($types)->orderBy('accounts.name', 'ASC'); if ($page == -1) { - return $query->get(['accounts.*']); + $result = $query->get(['accounts.*']); } else { $size = 50; $offset = ($page - 1) * $size; - return $query->take($size)->offset($offset)->get(['accounts.*']); + $result = $query->take($size)->offset($offset)->get(['accounts.*']); } + + return $result; + } + + + /** + * @return Collection + */ + public function getCreditCards() + { + return Auth::user()->accounts() + ->hasMetaValue('accountRole', 'ccAsset') + ->hasMetaValue('ccType', 'monthlyFull') + ->get( + [ + 'accounts.*', + 'ccType.data as ccType', + 'accountRole.data as accountRole' + ] + ); } /** @@ -219,6 +239,34 @@ class AccountRepository implements AccountRepositoryInterface return $accounts; } + /** + * Get all transfers TO this account in this range. + * + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getTransfersInRange(Account $account, Carbon $start, Carbon $end) + { + return TransactionJournal::whereIn( + 'id', function ($q) use ($account, $start, $end) { + $q->select('transaction_journals.id') + ->from('transactions') + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->where('transactions.account_id', $account->id) + ->where('transaction_journals.user_id', Auth::user()->id) + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->where('transactions.amount', '>', 0) + ->where('transaction_types.type', 'Transfer'); + + } + )->get(); + } + /** * @param Account $account * diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index d064db673a..280cf41a21 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -46,6 +46,22 @@ interface AccountRepositoryInterface */ public function getFirstTransaction(TransactionJournal $journal, Account $account); + /** + * @return Collection + */ + public function getCreditCards(); + + /** + * Get all transfers TO this account in this range. + * + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getTransfersInRange(Account $account, Carbon $start, Carbon $end); + /** * @param Preference $preference * diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 837713d87b..9b7ae4e492 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -19,6 +19,31 @@ use Navigation; */ class BillRepository implements BillRepositoryInterface { + /** + * Create a fake bill to help the chart controller. + * + * @param string $description + * @param Carbon $date + * @param float $amount + * + * @return Bill + */ + public function createFakeBill($description, Carbon $date, $amount) + { + $bill = new Bill; + $bill->name = $description; + $bill->match = $description; + $bill->amount_min = $amount; + $bill->amount_max = $amount; + $bill->date = $date; + $bill->repeat_freq = 'monthly'; + $bill->skip = 0; + $bill->automatch = false; + $bill->active = false; + + return $bill; + } + /** * @param Bill $bill * @@ -29,6 +54,22 @@ class BillRepository implements BillRepositoryInterface return $bill->delete(); } + /** + * @return Collection + */ + public function getActiveBills() + { + /** @var Collection $set */ + $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get(); + $set->sort( + function (Bill $bill) { + return $bill->name; + } + ); + + return $set; + } + /** * @return Collection */ @@ -65,6 +106,20 @@ class BillRepository implements BillRepositoryInterface ->get(['transaction_journals.*', 'transactions.amount']); } + /** + * Get all journals that were recorded on this bill between these dates. + * + * @param Bill $bill + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end) + { + return $bill->transactionjournals()->before($end)->after($start)->get(); + } + /** * @param Bill $bill * @@ -322,20 +377,4 @@ class BillRepository implements BillRepositoryInterface return $bill; } - - /** - * @return Collection - */ - public function getActiveBills() - { - /** @var Collection $set */ - $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get(); - $set->sort( - function (Bill $bill) { - return $bill->name; - } - ); - - return $set; - } } diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index a0fbe7eac9..5e6041710b 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -15,6 +15,17 @@ use Illuminate\Support\Collection; interface BillRepositoryInterface { + /** + * Create a fake bill to help the chart controller. + * + * @param string $description + * @param Carbon $date + * @param float $amount + * + * @return Bill + */ + public function createFakeBill($description, Carbon $date, $amount); + /** * @param Bill $bill * @@ -39,6 +50,17 @@ interface BillRepositoryInterface */ public function getJournals(Bill $bill); + /** + * Get all journals that were recorded on this bill between these dates. + * + * @param Bill $bill + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end); + /** * @param Bill $bill * @@ -66,6 +88,8 @@ interface BillRepositoryInterface */ public function lastFoundMatch(Bill $bill); + + /** * @param Bill $bill * diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 1fa943c0cd..21838900e4 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -308,4 +308,15 @@ class BudgetRepository implements BudgetRepositoryInterface } + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function expensesOnDay(Budget $budget, Carbon $date) + { + return floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($date)->sum('amount')); + } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index c1d8e1c230..eb61d7370d 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -107,6 +107,14 @@ interface BudgetRepositoryInterface */ public function store(array $data); + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function expensesOnDay(Budget $budget, Carbon $date); + /** * @param Budget $budget * @param Carbon $start diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php index 03e1c5fe9f..5637734821 100644 --- a/tests/controllers/GoogleChartControllerTest.php +++ b/tests/controllers/GoogleChartControllerTest.php @@ -1,5 +1,10 @@ markTestIncomplete(); + $account = FactoryMuffin::create('FireflyIII\Models\Account'); + $this->be($account->user); + + // mock stuff: + Steam::shouldReceive('balance')->andReturn(0); + + $this->call('GET', '/chart/account/' . $account->id); + $this->assertResponseOk(); } public function testAllAccountsBalanceChart() { - $this->markTestIncomplete(); + $account = FactoryMuffin::create('FireflyIII\Models\Account'); + $this->be($account->user); + $collection = new Collection; + $collection->push($account); + + //mock stuff: + Preferences::shouldReceive('get')->andReturn(new Preference); + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getFrontpageAccounts')->andReturn($collection); + + $this->call('GET', '/chart/home/account'); + $this->assertResponseOk(); + + } public function testAllBudgetsAndSpending() { - $this->markTestIncomplete(); + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $collection = new Collection; + $collection->push($budget); + + // mock stuff: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('getBudgets')->andReturn($collection); + $repository->shouldReceive('spentInMonth')->andReturn(rand(1, 100)); + + $this->call('GET', '/chart/budgets/spending/2015'); + $this->assertResponseOk(); } public function testAllBudgetsHomeChart() { - $this->markTestIncomplete(); + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $budget1 = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $start = Carbon::now()->startOfMonth(); + $end = Carbon::now()->endOfMonth(); + + $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); + $repetitions = new Collection; + $repetitions->push($repetition); + $emptyRepetitions = new Collection; + + $collection = new Collection; + $collection->push($budget); + $collection->push($budget1); + + // mock stuff: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('getBudgets')->andReturn($collection); + $repository->shouldReceive('getBudgetLimitRepetitions')->once()->andReturn($repetitions, $emptyRepetitions); + $repository->shouldReceive('sumBudgetExpensesInPeriod')->andReturn(12); + $repository->shouldReceive('getWithoutBudgetSum')->andReturn(0); + + $this->call('GET', '/chart/home/budgets'); + $this->assertResponseOk(); } public function testAllCategoriesHomeChart() { - $this->markTestIncomplete(); + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + + $this->be($category->user); + $category->save(); + $category->sum = 100; + $collection = new Collection; + $collection->push($category); + + // mock stuff: + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('getCategoriesAndExpenses')->andReturn($collection); + Crypt::shouldReceive('decrypt')->andReturn('Hello!'); + Crypt::shouldReceive('encrypt')->andReturn('Hello!'); + + + $this->call('GET', '/chart/home/categories'); + $this->assertResponseOk(); } public function testBillOverview() { - $this->markTestIncomplete(); + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $collection = new Collection; + $collection->push($journal); + $this->be($bill->user); + + // mock! + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $repository->shouldReceive('getJournals')->andReturn($collection); + + + // call! + $this->call('GET', '/chart/bills/' . $bill->id); + $this->assertResponseOk(); } public function testBillsOverview() { - $this->markTestIncomplete(); + $bill1 = FactoryMuffin::create('FireflyIII\Models\Bill'); + $bill2 = FactoryMuffin::create('FireflyIII\Models\Bill'); + $journal1 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journal2 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $card1 = FactoryMuffin::create('FireflyIII\Models\Account'); + $card2 = FactoryMuffin::create('FireflyIII\Models\Account'); + $fake = FactoryMuffin::create('FireflyIII\Models\Bill'); + + + $bills = new Collection([$bill1, $bill2]); + $journals = new Collection([$journal1, $journal2]); + $cards = new Collection([$card1, $card2]); + $emptyCollection = new Collection; + $ranges = [['start' => new Carbon, 'end' => new Carbon]]; + $this->be($bill1->user); + + // mock! + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $accounts = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + + // calls: + $repository->shouldReceive('getActiveBills')->andReturn($bills); + $repository->shouldReceive('getRanges')->andReturn($ranges); + $repository->shouldReceive('getJournalsInRange')->andReturn($journals, $emptyCollection); + $accounts->shouldReceive('getCreditCards')->andReturn($cards); + $accounts->shouldReceive('getTransfersInRange')->andReturn($journals, $emptyCollection); + $repository->shouldReceive('createFakeBill')->andReturn($fake); + Steam::shouldReceive('balance')->andReturn(-1, 0); + + $this->call('GET', '/chart/home/bills'); + $this->assertResponseOk(); } public function testBudgetLimitSpending() { - $this->markTestIncomplete(); + $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); + $budget = $repetition->budgetlimit->budget; + $this->be($budget->user); + ///chart/budget/{budget}/{limitrepetition} + + // mock! + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('expensesOnDay')->andReturn(rand(1, 1000)); + + $this->call('GET', '/chart/budget/' . $budget->id . '/' . $repetition->id); + $this->assertResponseOk(); + } public function testBudgetsAndSpending() From 192db4bb6ef236d800b3c8cdee9c5f7398e6c0cf Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 10:14:20 +0200 Subject: [PATCH 04/66] Accidentally included JS twice. --- resources/views/accounts/show.blade.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/views/accounts/show.blade.php b/resources/views/accounts/show.blade.php index 8cf88a34b4..412014e342 100644 --- a/resources/views/accounts/show.blade.php +++ b/resources/views/accounts/show.blade.php @@ -55,8 +55,6 @@ - - @stop From 1932bf277adde848d4aec3cbbfc7f96e646f06f8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 17:51:22 +0200 Subject: [PATCH 05/66] More tests --- .../Controllers/GoogleChartController.php | 74 ++++++------------ app/Repositories/Budget/BudgetRepository.php | 75 +++++++++++++++--- .../Budget/BudgetRepositoryInterface.php | 38 +++++++-- .../Category/CategoryRepository.php | 40 ++++++++++ .../Category/CategoryRepositoryInterface.php | 24 ++++++ .../PiggyBank/PiggyBankRepository.php | 10 +++ .../PiggyBankRepositoryInterface.php | 7 ++ .../controllers/GoogleChartControllerTest.php | 78 +++++++++++++++++-- tests/factories/all.php | 14 ++++ 9 files changed, 282 insertions(+), 78 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index e3117a6616..37566986b9 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -1,6 +1,5 @@ addColumn('Month', 'date'); $chart->addColumn('Budgeted', 'number'); $chart->addColumn('Spent', 'number'); - if ($year == 0) { - // grab the first budgetlimit ever: - $firstLimit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first(); - if ($firstLimit) { - $start = new Carbon($firstLimit->startdate); - } else { - $start = Carbon::now()->startOfYear(); - } - // grab the last budget limit ever: - $lastLimit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first(); - if ($lastLimit) { - $end = new Carbon($lastLimit->startdate); - } else { - $end = Carbon::now()->endOfYear(); - } + if ($year == 0) { + $start = $repository->getFirstBudgetLimitDate($budget); + $end = $repository->getLastBudgetLimitDate($budget); } else { $start = Carbon::createFromDate(intval($year), 1, 1); $end = clone $start; @@ -386,19 +371,8 @@ class GoogleChartController extends Controller } while ($start <= $end) { - $spent = $repository->spentInMonth($budget, $start); - $repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') - ->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00')) - ->where('budget_limits.budget_id', $budget->id) - ->first(['limit_repetitions.*']); - - if ($repetition) { - $budgeted = floatval($repetition->amount); - \Log::debug('Found a repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name . '!'); - } else { - \Log::debug('No repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name); - $budgeted = null; - } + $spent = $repository->spentInMonth($budget, $start); + $budgeted = $repository->getLimitAmountOnDate($budget, $start); $chart->addRow(clone $start, $budgeted, $spent); $start->addMonth(); } @@ -416,12 +390,11 @@ class GoogleChartController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function categoryOverviewChart(Category $category, GChart $chart) + public function categoryOverviewChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository) { // oldest transaction in category: - /** @var TransactionJournal $first */ - $first = $category->transactionjournals()->orderBy('date', 'ASC')->first(); - $start = $first->date; + $start = $repository->getFirstActivityDate($category); + /** @var Preference $range */ $range = Preferences::get('viewRange', '1M'); // jump to start of week / month / year / etc (TODO). @@ -434,13 +407,12 @@ class GoogleChartController extends Controller while ($start <= $end) { $currentEnd = Navigation::endOfPeriod($start, $range->data); - $spent = floatval($category->transactionjournals()->before($currentEnd)->after($start)->lessThan(0)->sum('amount')) * -1; + $spent = $repository->spentInPeriodSum($category, $start, $currentEnd); $chart->addRow(clone $start, $spent); $start = Navigation::addPeriod($start, $range->data, 0); } - $chart->generate(); return Response::json($chart->getData()); @@ -454,17 +426,15 @@ class GoogleChartController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function categoryPeriodChart(Category $category, GChart $chart) + public function categoryPeriodChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository) { - // oldest transaction in category: - /** @var TransactionJournal $first */ - $start = clone Session::get('start'); + $start = clone Session::get('start', Carbon::now()->startOfMonth()); $chart->addColumn('Period', 'date'); $chart->addColumn('Spent', 'number'); - $end = Session::get('end'); + $end = Session::get('end', Carbon::now()->endOfMonth()); while ($start <= $end) { - $spent = floatval($category->transactionjournals()->onDate($start)->lessThan(0)->sum('amount')) * -1; + $spent = $repository->spentOnDaySum($category, $start); $chart->addRow(clone $start, $spent); $start->addDay(); } @@ -482,13 +452,13 @@ class GoogleChartController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart) + public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart, PiggyBankRepositoryInterface $repository) { $chart->addColumn('Date', 'date'); $chart->addColumn('Balance', 'number'); /** @var Collection $set */ - $set = DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); + $set = $repository->getEventSummarySet($piggyBank); $sum = 0; foreach ($set as $entry) { diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 21838900e4..a7b80cbf24 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -7,9 +7,9 @@ use Carbon\Carbon; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\LimitRepetition; +use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; -use Illuminate\Database\Query\Builder as QueryBuilder; /** * Class BudgetRepository @@ -56,6 +56,17 @@ class BudgetRepository implements BudgetRepositoryInterface return true; } + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function expensesOnDay(Budget $budget, Carbon $date) + { + return floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($date)->sum('amount')); + } + /** * @return Collection */ @@ -117,6 +128,21 @@ class BudgetRepository implements BudgetRepositoryInterface return $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); } + /** + * @param Budget $budget + * + * @return Carbon + */ + public function getFirstBudgetLimitDate(Budget $budget) + { + $limit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first(); + if ($limit) { + return $limit->startdate; + } + + return Carbon::now()->startOfYear(); + } + /** * @return Collection */ @@ -158,6 +184,41 @@ class BudgetRepository implements BudgetRepositoryInterface return new LengthAwarePaginator($set, $count, $take, $offset); } + /** + * @param Budget $budget + * + * @return Carbon + */ + public function getLastBudgetLimitDate(Budget $budget) + { + $limit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first(); + if ($limit) { + return $limit->startdate; + } + + return Carbon::now()->startOfYear(); + } + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float|null + */ + public function getLimitAmountOnDate(Budget $budget, Carbon $date) + { + $repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') + ->where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00')) + ->where('budget_limits.budget_id', $budget->id) + ->first(['limit_repetitions.*']); + + if ($repetition) { + return floatval($repetition->amount); + } + + return null; + } + /** * @param Carbon $start * @param Carbon $end @@ -204,6 +265,7 @@ class BudgetRepository implements BudgetRepositoryInterface ->lessThan(0) ->transactionTypes(['Withdrawal']) ->get(); + return floatval($noBudgetSet->sum('amount')) * -1; } @@ -308,15 +370,4 @@ class BudgetRepository implements BudgetRepositoryInterface } - - /** - * @param Budget $budget - * @param Carbon $date - * - * @return float - */ - public function expensesOnDay(Budget $budget, Carbon $date) - { - return floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($date)->sum('amount')); - } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index eb61d7370d..d2c0cd0bed 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -26,6 +26,14 @@ interface BudgetRepositoryInterface */ public function destroy(Budget $budget); + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function expensesOnDay(Budget $budget, Carbon $date); + /** * @return Collection */ @@ -60,6 +68,13 @@ interface BudgetRepositoryInterface */ public function getCurrentRepetition(Budget $budget, Carbon $date); + /** + * @param Budget $budget + * + * @return Carbon + */ + public function getFirstBudgetLimitDate(Budget $budget); + /** * @return Collection */ @@ -76,6 +91,21 @@ interface BudgetRepositoryInterface */ public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50); + /** + * @param Budget $budget + * + * @return Carbon + */ + public function getLastBudgetLimitDate(Budget $budget); + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return float + */ + public function getLimitAmountOnDate(Budget $budget, Carbon $date); + /** * @param Carbon $start * @param Carbon $end @@ -107,14 +137,6 @@ interface BudgetRepositoryInterface */ public function store(array $data); - /** - * @param Budget $budget - * @param Carbon $date - * - * @return float - */ - public function expensesOnDay(Budget $budget, Carbon $date); - /** * @param Budget $budget * @param Carbon $start diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 75f04b5ad7..1266d71b50 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -79,6 +79,23 @@ class CategoryRepository implements CategoryRepositoryInterface ->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); } + /** + * @param Category $category + * + * @return Carbon + */ + public function getFirstActivityDate(Category $category) + { + /** @var TransactionJournal $first */ + $first = $category->transactionjournals()->orderBy('date', 'ASC')->first(); + if ($first) { + return $first->date; + } + + return new Carbon; + + } + /** * @param Category $category * @param int $page @@ -138,6 +155,18 @@ class CategoryRepository implements CategoryRepositoryInterface ->get(['transaction_journals.*']); } + /** + * @param Category $category + * @param Carbon $start + * @param Carbon $end + * + * @return float + */ + public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end) + { + return floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; + } + /** * @param array $data * @@ -170,4 +199,15 @@ class CategoryRepository implements CategoryRepositoryInterface return $category; } + + /** + * @param Category $category + * @param Carbon $date + * + * @return float + */ + public function spentOnDaySum(Category $category, Carbon $date) + { + return floatval($category->transactionjournals()->onDate($date)->lessThan(0)->sum('amount')) * -1; + } } diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index 7faa595b60..5b29845daf 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -40,6 +40,13 @@ interface CategoryRepositoryInterface */ public function getCategoriesAndExpenses($start, $end); + /** + * @param Category $category + * + * @return Carbon + */ + public function getFirstActivityDate(Category $category); + /** * @param Category $category * @param int $page @@ -63,6 +70,23 @@ interface CategoryRepositoryInterface */ public function getWithoutCategory(Carbon $start, Carbon $end); + /** + * @param Category $category + * @param Carbon $start + * @param Carbon $end + * + * @return float + */ + public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end); + + /** + * @param Category $category + * @param Carbon $date + * + * @return float + */ + public function spentOnDaySum(Category $category, Carbon $date); + /** * @param array $data * diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index fb381ba1c1..0c95d0ab2f 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -86,6 +86,16 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $part; } + /** + * @param PiggyBank $piggyBank + * + * @return Collection + */ + public function getEventSummarySet(PiggyBank $piggyBank) + { + return DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); + } + /** * Set all piggy banks to order 0. * diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index 13afce327d..4bfe3d8cab 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -35,6 +35,13 @@ interface PiggyBankRepositoryInterface */ public function createPiggyBankPart(array $data); + /** + * @param PiggyBank $piggyBank + * + * @return Collection + */ + public function getEventSummarySet(PiggyBank $piggyBank); + /** * Set all piggy banks to order 0. * diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php index 5637734821..612b2d71f5 100644 --- a/tests/controllers/GoogleChartControllerTest.php +++ b/tests/controllers/GoogleChartControllerTest.php @@ -190,8 +190,10 @@ class GoogleChartControllerTest extends TestCase public function testBudgetLimitSpending() { - $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); - $budget = $repetition->budgetlimit->budget; + $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); + $repetition->startdate = Carbon::now()->startOfMonth(); + $repetition->enddate = Carbon::now()->endOfMonth(); + $budget = $repetition->budgetlimit->budget; $this->be($budget->user); ///chart/budget/{budget}/{limitrepetition} @@ -206,22 +208,86 @@ class GoogleChartControllerTest extends TestCase public function testBudgetsAndSpending() { - $this->markTestIncomplete(); + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('spentInMonth')->andReturn(100); + $repository->shouldReceive('getLimitAmountOnDate')->andReturn(100); + $repository->shouldReceive('getFirstBudgetLimitDate')->andReturn(Carbon::now()->startOfMonth()); + $repository->shouldReceive('getLastBudgetLimitDate')->andReturn(Carbon::now()->endOfYear()); + + // /chart/budget/{budget}/spending/{year?} + $this->call('GET', '/chart/budget/' . $budget->id . '/spending/0'); + $this->assertResponseOk(); + } + + public function testBudgetsAndSpendingWithYear() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('spentInMonth')->andReturn(100); + $repository->shouldReceive('getLimitAmountOnDate')->andReturn(100); + + // /chart/budget/{budget}/spending/{year?} + $this->call('GET', '/chart/budget/' . $budget->id . '/spending/2015'); + $this->assertResponseOk(); } public function testCategoryOverviewChart() { - $this->markTestIncomplete(); + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $pref = FactoryMuffin::create('FireflyIII\Models\Preference'); + $this->be($category->user); + $start = new Carbon(); + $start->subDay(); + $end = new Carbon; + $end->addWeek(); + + // mock! + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('getFirstActivityDate')->andReturn($start); + $repository->shouldReceive('spentInPeriodSum')->andReturn(rand(1, 100)); + Preferences::shouldReceive('get')->andReturn($pref); + + Navigation::shouldReceive('startOfPeriod')->andReturn($start); + Navigation::shouldReceive('endOfPeriod')->andReturn($start); + Navigation::shouldReceive('addPeriod')->andReturn($end); + + $this->call('GET', '/chart/category/' . $category->id . '/overview'); + $this->assertResponseOk(); } public function testCategoryPeriodChart() { - $this->markTestIncomplete(); + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + + // mock! + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('spentOnDaySum')->andReturn(rand(1, 100)); + + $this->call('GET', '/chart/category/' . $category->id . '/period'); + $this->assertResponseOk(); } public function testPiggyBankHistory() { - $this->markTestIncomplete(); + $piggyBank = FactoryMuffin::create('FireflyIII\Models\PiggyBank'); + $this->be($piggyBank->account->user); + + $obj = new stdClass; + $obj->sum = 12; + $obj->date = new Carbon; + $collection = new Collection([$obj]); + + $repository = $this->mock('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface'); + $repository->shouldReceive('getEventSummarySet')->andReturn($collection); + + $this->call('GET', '/chart/piggy-history/' . $piggyBank->id); + $this->assertResponseOk(); } public function testYearInExp() diff --git a/tests/factories/all.php b/tests/factories/all.php index d551718cdb..16d2b9ee74 100644 --- a/tests/factories/all.php +++ b/tests/factories/all.php @@ -160,6 +160,20 @@ FactoryMuffin::define( ] ); +FactoryMuffin::define( + 'FireflyIII\Models\PiggyBank', + [ + 'account_id' => 'factory|FireflyIII\Models\Account', + 'name' => 'sentence', + 'targetamount' => 'integer', + 'startdate' => 'date', + 'targetdate' => 'date', + 'reminder_skip' => 0, + 'remind_me' => 0, + 'order' => 0, + ] +); + FactoryMuffin::define( 'FireflyIII\Models\TransactionType', [ From bf354275b337e70cd15aa488ff5183632dee099c Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 18:25:21 +0200 Subject: [PATCH 06/66] Some general cleaning up. --- app/Helpers/Report/ReportQuery.php | 1 - .../Controllers/GoogleChartController.php | 14 +------ app/Http/Controllers/HelpController.php | 6 +-- app/Http/Controllers/JsonController.php | 5 +++ .../Account/AccountRepository.php | 1 - .../Currency/CurrencyRepository.php | 2 +- .../Currency/CurrencyRepositoryInterface.php | 2 +- .../2014_12_13_190730_changes_for_v321.php | 2 - resources/views/form/help.blade.php | 2 +- .../controllers/GoogleChartControllerTest.php | 39 ++++++++++++++++++- 10 files changed, 50 insertions(+), 24 deletions(-) diff --git a/app/Helpers/Report/ReportQuery.php b/app/Helpers/Report/ReportQuery.php index 1e00357743..93a48a0633 100644 --- a/app/Helpers/Report/ReportQuery.php +++ b/app/Helpers/Report/ReportQuery.php @@ -254,7 +254,6 @@ class ReportQuery implements ReportQueryInterface $data->each( function (Model $object) { -// $object->description = intval($object->encrypted); $object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; } ); diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 37566986b9..b24dd68ae6 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -2,8 +2,6 @@ use Carbon\Carbon; use Crypt; -use DB; -use Exception; use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; @@ -480,11 +478,7 @@ class GoogleChartController extends Controller */ public function yearInExp($year, GChart $chart, ReportQueryInterface $query) { - try { - $start = new Carbon('01-01-' . $year); - } catch (Exception $e) { - return view('error')->with('message', 'Invalid year.'); - } + $start = new Carbon('01-01-' . $year); $chart->addColumn('Month', 'date'); $chart->addColumn('Income', 'number'); $chart->addColumn('Expenses', 'number'); @@ -532,11 +526,7 @@ class GoogleChartController extends Controller */ public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query) { - try { - $start = new Carbon('01-01-' . $year); - } catch (Exception $e) { - return view('error')->with('message', 'Invalid year.'); - } + $start = new Carbon('01-01-' . $year); $chart->addColumn('Summary', 'string'); $chart->addColumn('Income', 'number'); $chart->addColumn('Expenses', 'number'); diff --git a/app/Http/Controllers/HelpController.php b/app/Http/Controllers/HelpController.php index 5c03c30456..f8041286f7 100644 --- a/app/Http/Controllers/HelpController.php +++ b/app/Http/Controllers/HelpController.php @@ -5,7 +5,7 @@ use ErrorException; use League\CommonMark\CommonMarkConverter; use Response; use Route; - +use Log; /** * Class HelpController * @@ -27,7 +27,7 @@ class HelpController extends Controller ]; if (!Route::has($route)) { - \Log::error('No such route: ' . $route); + Log::error('No such route: ' . $route); return Response::json($content); } @@ -75,7 +75,7 @@ class HelpController extends Controller try { $content['text'] = file_get_contents($uri); } catch (ErrorException $e) { - \Log::error(trim($e->getMessage())); + Log::error(trim($e->getMessage())); } if (strlen(trim($content['text'])) == 0) { $content['text'] = '

There is no help for this route.

'; diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 322e34c97a..fb69b046d9 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -239,6 +239,11 @@ class JsonController extends Controller return Response::json(['value' => $pref->data]); } + /** + * @param $what + * + * @return \Symfony\Component\HttpFoundation\Response + */ public function transactionJournals($what) { $descriptions = []; diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 50807a32b9..46e837d9e9 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -509,7 +509,6 @@ class AccountRepository implements AccountRepositoryInterface protected function updateMetadata(Account $account, array $data) { $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType']; - $updated = false; foreach ($validFields as $field) { $entry = $account->accountMeta()->where('name', $field)->first(); diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index bffdc88c94..d7991b6098 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -81,4 +81,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface return $currency; } -} \ No newline at end of file +} diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index cfb72467ba..2514d08aba 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -49,4 +49,4 @@ interface CurrencyRepositoryInterface */ public function update(TransactionCurrency $currency, array $data); -} \ No newline at end of file +} diff --git a/database/migrations/2014_12_13_190730_changes_for_v321.php b/database/migrations/2014_12_13_190730_changes_for_v321.php index b381e774ab..5a0524d322 100644 --- a/database/migrations/2014_12_13_190730_changes_for_v321.php +++ b/database/migrations/2014_12_13_190730_changes_for_v321.php @@ -426,7 +426,6 @@ class ChangesForV321 extends Migration public function moveComponentIdToBudgetId() { - //Log::debug('Now in moveComponentIdToBudgetId()'); BudgetLimit::get()->each( function (BudgetLimit $bl) { Log::debug('Now at budgetLimit #' . $bl->id . ' with component_id: ' . $bl->component_id); @@ -447,7 +446,6 @@ class ChangesForV321 extends Migration } } ); - //Log::debug('Done with moveComponentIdToBudgetId()'); } diff --git a/resources/views/form/help.blade.php b/resources/views/form/help.blade.php index ce06cb2e49..9b6375c241 100644 --- a/resources/views/form/help.blade.php +++ b/resources/views/form/help.blade.php @@ -1,3 +1,3 @@ @if(isset($options['helpText']))

{{$options['helpText']}}

-@endif \ No newline at end of file +@endif diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php index 612b2d71f5..23ce5ccc8e 100644 --- a/tests/controllers/GoogleChartControllerTest.php +++ b/tests/controllers/GoogleChartControllerTest.php @@ -292,12 +292,47 @@ class GoogleChartControllerTest extends TestCase public function testYearInExp() { - $this->markTestIncomplete(); + $user = FactoryMuffin::create('FireflyIII\User'); + $preference = FactoryMuffin::create('FireflyIII\Models\Preference'); + $journal1 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journal2 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journals = new Collection([$journal1, $journal2]); + $this->be($user); + + + // mock! + $repository = $this->mock('FireflyIII\Helpers\Report\ReportQueryInterface'); + + // expect! + $repository->shouldReceive('incomeByPeriod')->andReturn($journals); + $repository->shouldReceive('journalsByExpenseAccount')->andReturn($journals); + Preferences::shouldReceive('get')->withArgs(['showSharedReports',false])->once()->andReturn($preference); + + + $this->call('GET', '/chart/reports/income-expenses/2015'); + $this->assertResponseOk(); } public function testYearInExpSum() { - $this->markTestIncomplete(); + $user = FactoryMuffin::create('FireflyIII\User'); + $preference = FactoryMuffin::create('FireflyIII\Models\Preference'); + $journal1 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journal2 = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journals = new Collection([$journal1, $journal2]); + $this->be($user); + + + // mock! + $repository = $this->mock('FireflyIII\Helpers\Report\ReportQueryInterface'); + + // expect! + $repository->shouldReceive('incomeByPeriod')->andReturn($journals); + $repository->shouldReceive('journalsByExpenseAccount')->andReturn($journals); + Preferences::shouldReceive('get')->withArgs(['showSharedReports',false])->once()->andReturn($preference); + + + $this->call('GET', '/chart/reports/income-expenses-sum/2015'); } } \ No newline at end of file From 0d336727e8f2643fd5be79f796767e19cea9dd72 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 18:26:14 +0200 Subject: [PATCH 07/66] Automated code cleanup. --- app/Http/Controllers/AccountController.php | 4 +--- app/Http/Controllers/BillController.php | 2 +- app/Http/Controllers/HelpController.php | 3 ++- app/Http/Controllers/HomeController.php | 11 +++++++---- app/Http/Controllers/JsonController.php | 1 - app/Http/Controllers/PiggyBankController.php | 6 ++++-- app/Http/Controllers/ReportController.php | 3 +-- app/Http/Middleware/PiggyBanks.php | 6 +----- app/Http/Requests/BudgetFormRequest.php | 2 +- app/Http/Requests/CategoryFormRequest.php | 2 +- app/Http/Requests/PiggyBankFormRequest.php | 4 +--- app/Models/Account.php | 1 + app/Models/Category.php | 4 +++- app/Models/PiggyBank.php | 4 +++- app/Models/Reminder.php | 6 ++++-- app/Models/Transaction.php | 5 +++-- app/Providers/EventServiceProvider.php | 15 +++++++++------ app/Repositories/Bill/BillRepositoryInterface.php | 1 - .../Journal/JournalRepositoryInterface.php | 3 ++- app/Validation/FireflyValidator.php | 6 +++--- 20 files changed, 48 insertions(+), 41 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index afacfa1b23..a0be3ef501 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -1,6 +1,5 @@ setPath('accounts/show/' . $account->id); - return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle')); } @@ -192,7 +190,7 @@ class AccountController extends Controller ]; $account = $repository->store($accountData); - Session::flash('success', 'New account "' . $account->name . '" stored!'); + Session::flash('success', 'New account "' . $account->name . '" stored!'); if (intval(Input::get('create_another')) === 1) { return Redirect::route('accounts.create', $request->input('what'))->withInput(); diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index 6a78a4718f..f269af2954 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -173,7 +173,7 @@ class BillController extends Controller */ public function show(Bill $bill, BillRepositoryInterface $repository) { - $journals = $repository->getJournals($bill); + $journals = $repository->getJournals($bill); $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); $hideBill = true; diff --git a/app/Http/Controllers/HelpController.php b/app/Http/Controllers/HelpController.php index f8041286f7..09e99e2b4b 100644 --- a/app/Http/Controllers/HelpController.php +++ b/app/Http/Controllers/HelpController.php @@ -3,9 +3,10 @@ use Cache; use ErrorException; use League\CommonMark\CommonMarkConverter; +use Log; use Response; use Route; -use Log; + /** * Class HelpController * diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 2f029fde65..202cb7ea18 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -2,12 +2,13 @@ use Auth; use Carbon\Carbon; +use Config; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Input; use Preferences; -use Session; use Redirect; -use Config; +use Session; + /** * Class HomeController * @@ -31,8 +32,10 @@ class HomeController extends Controller Session::put('end', $end); } - public function flush() { + public function flush() + { Session::clear(); + return Redirect::route('index'); } @@ -42,7 +45,7 @@ class HomeController extends Controller public function index(AccountRepositoryInterface $repository) { - $types = Config::get('firefly.accountTypesByIdentifier.asset'); + $types = Config::get('firefly.accountTypesByIdentifier.asset'); $count = $repository->countAccounts($types); $title = 'Firefly'; $subTitle = 'What\'s playing?'; diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index fb69b046d9..f620da02fd 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -2,7 +2,6 @@ use Amount; use Auth; -use Carbon\Carbon; use DB; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index 51349c6371..d219359656 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -16,8 +16,8 @@ use Input; use Redirect; use Session; use Steam; -use View; use URL; +use View; /** * Class PiggyBankController @@ -170,7 +170,7 @@ class PiggyBankController extends Controller if (!isset($accounts[$account->id])) { $accounts[$account->id] = [ 'name' => $account->name, - 'balance' => Steam::balance($account,null,true), + 'balance' => Steam::balance($account, null, true), 'leftForPiggyBanks' => $repository->leftOnAccount($account), 'sumOfSaved' => $piggyBank->savedSoFar, 'sumOfTargets' => floatval($piggyBank->targetamount), @@ -326,6 +326,7 @@ class PiggyBankController extends Controller if (intval(Input::get('create_another')) === 1) { Session::put('piggy-banks.create.fromStore', true); + return Redirect::route('piggy-banks.create')->withInput(); } @@ -360,6 +361,7 @@ class PiggyBankController extends Controller if (intval(Input::get('return_to_edit')) === 1) { Session::put('piggy-banks.edit.fromUpdate', true); + return Redirect::route('piggy-banks.edit', $piggyBank->id); } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 20f24d4d6b..ad6d3e5889 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -11,7 +11,6 @@ use Preferences; use Session; use Steam; use View; -use Crypt; /** * Class ReportController @@ -246,7 +245,7 @@ class ReportController extends Controller /** * Start getExpenseGroupedForMonth DONE */ - $set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports); + $set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports); $expenses = Steam::makeArray($set); $expenses = Steam::sortArray($expenses); diff --git a/app/Http/Middleware/PiggyBanks.php b/app/Http/Middleware/PiggyBanks.php index 0854d338a8..8c00cf2376 100644 --- a/app/Http/Middleware/PiggyBanks.php +++ b/app/Http/Middleware/PiggyBanks.php @@ -3,17 +3,13 @@ namespace FireflyIII\Http\Middleware; -use Carbon\Carbon; +use App; use Closure; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBankRepetition; use Illuminate\Contracts\Auth\Guard; -use Illuminate\Database\Query\JoinClause; use Illuminate\Http\Request; use Illuminate\Support\Collection; -use Navigation; -use Session; -use App; /** * Class PiggyBanks diff --git a/app/Http/Requests/BudgetFormRequest.php b/app/Http/Requests/BudgetFormRequest.php index 57cd60d20f..452acc42e2 100644 --- a/app/Http/Requests/BudgetFormRequest.php +++ b/app/Http/Requests/BudgetFormRequest.php @@ -30,7 +30,7 @@ class BudgetFormRequest extends Request $nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted'; if (Budget::find(Input::get('id'))) { - $nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted,'.intval(Input::get('id')); + $nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted,' . intval(Input::get('id')); } return [ diff --git a/app/Http/Requests/CategoryFormRequest.php b/app/Http/Requests/CategoryFormRequest.php index 4a074750bd..7c02b57152 100644 --- a/app/Http/Requests/CategoryFormRequest.php +++ b/app/Http/Requests/CategoryFormRequest.php @@ -30,7 +30,7 @@ class CategoryFormRequest extends Request $nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted'; if (Category::find(Input::get('id'))) { - $nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted,'.intval(Input::get('id')); + $nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted,' . intval(Input::get('id')); } return [ diff --git a/app/Http/Requests/PiggyBankFormRequest.php b/app/Http/Requests/PiggyBankFormRequest.php index 2e950b8019..86b9d3ec23 100644 --- a/app/Http/Requests/PiggyBankFormRequest.php +++ b/app/Http/Requests/PiggyBankFormRequest.php @@ -3,9 +3,7 @@ namespace FireflyIII\Http\Requests; use Auth; -use Carbon\Carbon; use Input; -use Navigation; /** * Class PiggyBankFormRequest @@ -32,7 +30,7 @@ class PiggyBankFormRequest extends Request $nameRule = 'required|between:1,255|uniquePiggyBankForUser'; $targetDateRule = 'date'; if (intval(Input::get('id'))) { - $nameRule = 'required|between:1,255|uniquePiggyBankForUser:'.intval(Input::get('id')); + $nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . intval(Input::get('id')); } diff --git a/app/Models/Account.php b/app/Models/Account.php index e95240cdbb..d0c0d7c6cd 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -54,6 +54,7 @@ class Account extends Model App::abort(500, 'Could not create new account with data: ' . json_encode($fields)); } + return $account; } diff --git a/app/Models/Category.php b/app/Models/Category.php index 539f889378..91674b7f87 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -1,8 +1,9 @@ attributes['name'] = Crypt::encrypt($value); $this->attributes['encrypted'] = true; } + /** * @param $value * diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index c81ef28b71..4b952c1258 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -1,8 +1,9 @@ attributes['name'] = Crypt::encrypt($value); $this->attributes['encrypted'] = true; } + /** * @param $value * diff --git a/app/Models/Reminder.php b/app/Models/Reminder.php index 62c053d765..b8a62a2383 100644 --- a/app/Models/Reminder.php +++ b/app/Models/Reminder.php @@ -1,9 +1,10 @@ encrypted) == 1) { return json_decode(Crypt::decrypt($value)); } + return json_decode($value); } @@ -90,7 +92,7 @@ class Reminder extends Model public function setMetadataAttribute($value) { $this->attributes['encrypted'] = true; - $this->attributes['metadata'] = Crypt::encrypt(json_encode($value)); + $this->attributes['metadata'] = Crypt::encrypt(json_encode($value)); } /** diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index ab1e04c0be..85f8e74e17 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -1,10 +1,11 @@ reminders()->get(); - /** @var Reminder $reminder */ - foreach($reminders as $reminder) { - $reminder->delete(); + PiggyBank::deleting( + function (PiggyBank $piggyBank) { + $reminders = $piggyBank->reminders()->get(); + /** @var Reminder $reminder */ + foreach ($reminders as $reminder) { + $reminder->delete(); + } } - }); + ); Account::deleted( diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 5e6041710b..a6d5c5ea1e 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -89,7 +89,6 @@ interface BillRepositoryInterface public function lastFoundMatch(Bill $bill); - /** * @param Bill $bill * diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 2bd13b2870..cbe44671a5 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -2,8 +2,8 @@ namespace FireflyIII\Repositories\Journal; -use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; use Illuminate\Support\Collection; /** @@ -48,6 +48,7 @@ interface JournalRepositoryInterface /** * Get users first transaction journal + * * @return TransactionJournal */ public function first(); diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index 3ba63000ab..3dec04fa7e 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -223,10 +223,10 @@ class FireflyValidator extends Validator } $set = $query->get(['piggy_banks.*']); - foreach($set as $entry) { + foreach ($set as $entry) { $isEncrypted = intval($entry->encrypted) == 1 ? true : false; - $checkValue = $isEncrypted ? Crypt::decrypt($entry->name) : $entry->name; - if($checkValue == $value) { + $checkValue = $isEncrypted ? Crypt::decrypt($entry->name) : $entry->name; + if ($checkValue == $value) { return false; } } From f10f5d30bfbb5ba58fd9db0e771d62b2963df7d9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 18:48:34 +0200 Subject: [PATCH 08/66] Mock previously unmocked calls. --- .../Account/AccountRepository.php | 2 +- .../Account/AccountRepositoryInterface.php | 3 +- tests/controllers/AccountControllerTest.php | 11 +++- tests/controllers/BillControllerTest.php | 3 + tests/controllers/BudgetControllerTest.php | 5 +- tests/controllers/CategoryControllerTest.php | 58 ++++++++++++++----- tests/factories/all.php | 10 +++- 7 files changed, 69 insertions(+), 23 deletions(-) diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 46e837d9e9..ff4474635c 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -155,7 +155,7 @@ class AccountRepository implements AccountRepositoryInterface * @param Account $account * @param int $page * - * @return mixed + * @return LengthAwarePaginator */ public function getJournals(Account $account, $page) { diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 280cf41a21..7040e9ff9b 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -7,6 +7,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Preference; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; /** @@ -82,7 +83,7 @@ interface AccountRepositoryInterface * @param Account $account * @param string $range * - * @return mixed + * @return LengthAwarePaginator */ public function getJournals(Account $account, $page); diff --git a/tests/controllers/AccountControllerTest.php b/tests/controllers/AccountControllerTest.php index be21d77d87..63af83b215 100644 --- a/tests/controllers/AccountControllerTest.php +++ b/tests/controllers/AccountControllerTest.php @@ -4,6 +4,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Preference; use FireflyIII\Models\TransactionCurrency; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use League\FactoryMuffin\Facade as FactoryMuffin; @@ -95,12 +96,15 @@ class AccountControllerTest extends TestCase $account = FactoryMuffin::create('FireflyIII\Models\Account'); $this->be($account->user); - $this->assertCount(1, DB::table('accounts')->where('id', $account->id)->whereNull('deleted_at')->get()); + + // mock: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('destroy')->andReturn(true); // post it! $this->call('POST', '/accounts/destroy/' . $account->id, ['_token' => 'replaceme']); $this->assertSessionHas('success'); - $this->assertCount(0, DB::table('accounts')->where('id', $account->id)->whereNull('deleted_at')->get()); + $this->assertResponseStatus(302); } public function testEdit() @@ -167,7 +171,10 @@ class AccountControllerTest extends TestCase // an account: $this->be($this->account->user); + // mock! Amount::shouldReceive('getCurrencyCode')->once()->andReturn('A'); + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getJournals')->andReturn(new LengthAwarePaginator([],0,10)); // get edit page: $this->call('GET', '/accounts/show/' . $this->account->id); diff --git a/tests/controllers/BillControllerTest.php b/tests/controllers/BillControllerTest.php index aa24ff040d..eab8b1c0f6 100644 --- a/tests/controllers/BillControllerTest.php +++ b/tests/controllers/BillControllerTest.php @@ -93,6 +93,9 @@ class BillControllerTest extends TestCase $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); $this->be($bill->user); + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $repository->shouldReceive('destroy')->andReturn(true); + $this->call('POST', '/bills/destroy/' . $bill->id, ['_token' => 'replaceMe']); $this->assertSessionHas('success', 'The bill was deleted.'); diff --git a/tests/controllers/BudgetControllerTest.php b/tests/controllers/BudgetControllerTest.php index 0a89b99076..50ea295ca7 100644 --- a/tests/controllers/BudgetControllerTest.php +++ b/tests/controllers/BudgetControllerTest.php @@ -78,12 +78,13 @@ class BudgetControllerTest extends TestCase $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); $this->be($budget->user); - $this->assertCount(1, DB::table('budgets')->where('id', $budget->id)->get()); + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('destroy')->andReturn(true); $this->call('POST', '/budgets/destroy/' . $budget->id, ['_token' => 'replaceme']); $this->assertSessionHas('success', 'The budget "' . e($budget->name) . '" was deleted.'); - $this->assertCount(0, DB::table('budgets')->wherenull('deleted_at')->where('id', $budget->id)->get()); + } public function testEdit() diff --git a/tests/controllers/CategoryControllerTest.php b/tests/controllers/CategoryControllerTest.php index 33119cc388..0a13d671d6 100644 --- a/tests/controllers/CategoryControllerTest.php +++ b/tests/controllers/CategoryControllerTest.php @@ -146,12 +146,18 @@ class CategoryControllerTest extends TestCase public function testStore() { - $category = FactoryMuffin::create('FireflyIII\Models\Category'); - $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); - - $repository->shouldReceive('store')->andReturn($category); + // create + $category = FactoryMuffin::create('FireflyIII\Models\Category'); $this->be($category->user); + // mock + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CategoryFormRequest'); + + // expect + $repository->shouldReceive('store')->andReturn($category); + $request->shouldReceive('input')->andReturn(''); + $this->call('POST', '/categories/store', ['_token' => 'replaceMe', 'name' => 'Bla bla #' . rand(1, 1000)]); $this->assertResponseStatus(302); $this->assertSessionHas('success', 'New category "' . $category->name . '" stored!'); @@ -160,12 +166,19 @@ class CategoryControllerTest extends TestCase // public function testStoreAndRedirect() { - $category = FactoryMuffin::create('FireflyIII\Models\Category'); - $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); - - $repository->shouldReceive('store')->andReturn($category); + // create + $category = FactoryMuffin::create('FireflyIII\Models\Category'); $this->be($category->user); + // mock: + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CategoryFormRequest'); + + // fake: + $repository->shouldReceive('store')->andReturn($category); + $request->shouldReceive('input')->andReturn(''); + + $this->call('POST', '/categories/store', ['_token' => 'replaceMe', 'create_another' => 1, 'name' => 'Bla bla #' . rand(1, 1000)]); $this->assertResponseStatus(302); $this->assertSessionHas('success', 'New category "' . $category->name . '" stored!'); @@ -173,12 +186,18 @@ class CategoryControllerTest extends TestCase public function testUpdate() { - $category = FactoryMuffin::create('FireflyIII\Models\Category'); - $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); - - $repository->shouldReceive('update')->andReturn($category); + // create + $category = FactoryMuffin::create('FireflyIII\Models\Category'); $this->be($category->user); + // mock + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CategoryFormRequest'); + + // expect + $repository->shouldReceive('update')->andReturn($category); + $request->shouldReceive('input')->andReturn(''); + $this->call('POST', '/categories/update/' . $category->id, ['_token' => 'replaceMe', 'name' => 'Bla bla #' . rand(1, 1000)]); $this->assertResponseStatus(302); $this->assertSessionHas('success', 'Category "' . $category->name . '" updated.'); @@ -186,12 +205,19 @@ class CategoryControllerTest extends TestCase public function testUpdateAndRedirect() { - $category = FactoryMuffin::create('FireflyIII\Models\Category'); - $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); - - $repository->shouldReceive('update')->andReturn($category); + // create + $category = FactoryMuffin::create('FireflyIII\Models\Category'); $this->be($category->user); + // mock + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CategoryFormRequest'); + + // expect + $request->shouldReceive('input')->andReturn(''); + $repository->shouldReceive('update')->andReturn($category); + + $this->call('POST', '/categories/update/' . $category->id, ['_token' => 'replaceMe', 'return_to_edit' => 1, 'name' => 'Bla bla #' . rand(1, 1000)]); $this->assertResponseStatus(302); $this->assertSessionHas('success', 'Category "' . $category->name . '" updated.'); diff --git a/tests/factories/all.php b/tests/factories/all.php index 16d2b9ee74..0a6d507a1a 100644 --- a/tests/factories/all.php +++ b/tests/factories/all.php @@ -177,7 +177,15 @@ FactoryMuffin::define( FactoryMuffin::define( 'FireflyIII\Models\TransactionType', [ - 'type' => 'word', + 'type' => function () { + $types = ['Withdrawal', 'Deposit', 'Transfer']; + $count = DB::table('transaction_types')->count(); + if ($count < 3) { + return $types[$count]; + } else { + return RandomString::generateRandomString(10); + } + } ] ); From 05670cf39363be70a3360d9cee6b91ad57f31c76 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 18:52:15 +0200 Subject: [PATCH 09/66] Optimize test code. --- tests/TestCase.php | 21 +++++------ tests/controllers/AccountControllerTest.php | 2 +- .../controllers/GoogleChartControllerTest.php | 4 +-- tests/controllers/HomeControllerTest.php | 36 +++++++++---------- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 9ceb86ea36..336e5f2a9a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -22,16 +22,6 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase return $app; } - /** - * This method is called before the first test of this test class is run. - * - * @since Method available since Release 3.4.0 - */ - public static function setUpBeforeClass() - { - parent::setUpBeforeClass(); - } - /** * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. @@ -44,7 +34,15 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase } - + /** + * This method is called before the first test of this test class is run. + * + * @since Method available since Release 3.4.0 + */ + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + } /** * @param string $class @@ -61,5 +59,4 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase } - } diff --git a/tests/controllers/AccountControllerTest.php b/tests/controllers/AccountControllerTest.php index 63af83b215..58b908c640 100644 --- a/tests/controllers/AccountControllerTest.php +++ b/tests/controllers/AccountControllerTest.php @@ -174,7 +174,7 @@ class AccountControllerTest extends TestCase // mock! Amount::shouldReceive('getCurrencyCode')->once()->andReturn('A'); $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); - $repository->shouldReceive('getJournals')->andReturn(new LengthAwarePaginator([],0,10)); + $repository->shouldReceive('getJournals')->andReturn(new LengthAwarePaginator([], 0, 10)); // get edit page: $this->call('GET', '/accounts/show/' . $this->account->id); diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php index 23ce5ccc8e..3600a2eebb 100644 --- a/tests/controllers/GoogleChartControllerTest.php +++ b/tests/controllers/GoogleChartControllerTest.php @@ -306,7 +306,7 @@ class GoogleChartControllerTest extends TestCase // expect! $repository->shouldReceive('incomeByPeriod')->andReturn($journals); $repository->shouldReceive('journalsByExpenseAccount')->andReturn($journals); - Preferences::shouldReceive('get')->withArgs(['showSharedReports',false])->once()->andReturn($preference); + Preferences::shouldReceive('get')->withArgs(['showSharedReports', false])->once()->andReturn($preference); $this->call('GET', '/chart/reports/income-expenses/2015'); @@ -329,7 +329,7 @@ class GoogleChartControllerTest extends TestCase // expect! $repository->shouldReceive('incomeByPeriod')->andReturn($journals); $repository->shouldReceive('journalsByExpenseAccount')->andReturn($journals); - Preferences::shouldReceive('get')->withArgs(['showSharedReports',false])->once()->andReturn($preference); + Preferences::shouldReceive('get')->withArgs(['showSharedReports', false])->once()->andReturn($preference); $this->call('GET', '/chart/reports/income-expenses-sum/2015'); diff --git a/tests/controllers/HomeControllerTest.php b/tests/controllers/HomeControllerTest.php index e49ea0fcfc..3e98aa6f64 100644 --- a/tests/controllers/HomeControllerTest.php +++ b/tests/controllers/HomeControllerTest.php @@ -25,23 +25,6 @@ class HomeControllerTest extends TestCase parent::tearDown(); } - /** - * @covers FireflyIII\Http\Controllers\HomeController::dateRange - */ - public function testDateRangeWarning() - { - $start = '2014-03-01'; - $end = '2015-03-31'; - $this->be(new FireflyIII\User); - $this->call('POST', '/daterange', ['end' => $end, 'start' => $start,'_token' => 'replaceme']); - $this->assertResponseOk(); - - $this->assertSessionHas('start'); - $this->assertSessionHas('end'); - $this->assertSessionHas('warning'); - - } - /** * @covers FireflyIII\Http\Controllers\HomeController::dateRange */ @@ -52,7 +35,7 @@ class HomeControllerTest extends TestCase $this->be(new FireflyIII\User); - $this->call('POST', '/daterange', ['end' => $end, 'start' => $start,'_token' => 'replaceme']); + $this->call('POST', '/daterange', ['end' => $end, 'start' => $start, '_token' => 'replaceme']); $this->assertResponseOk(); $this->assertSessionHas('start'); @@ -60,6 +43,23 @@ class HomeControllerTest extends TestCase } + /** + * @covers FireflyIII\Http\Controllers\HomeController::dateRange + */ + public function testDateRangeWarning() + { + $start = '2014-03-01'; + $end = '2015-03-31'; + $this->be(new FireflyIII\User); + $this->call('POST', '/daterange', ['end' => $end, 'start' => $start, '_token' => 'replaceme']); + $this->assertResponseOk(); + + $this->assertSessionHas('start'); + $this->assertSessionHas('end'); + $this->assertSessionHas('warning'); + + } + /** * @covers FireflyIII\Http\Controllers\HomeController::index */ From ff5ecf61829f2f99e9d30f9eed3a613fddc108e8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 19:58:49 +0200 Subject: [PATCH 10/66] More tests. --- app/Helpers/Help/Help.php | 85 ++++++++++++++++ app/Helpers/Help/HelpInterface.php | 46 +++++++++ app/Http/Controllers/HelpController.php | 54 ++--------- app/Providers/FireflyServiceProvider.php | 1 + .../controllers/GoogleChartControllerTest.php | 1 + tests/controllers/HelpControllerTest.php | 96 +++++++++++++++++++ 6 files changed, 237 insertions(+), 46 deletions(-) create mode 100644 app/Helpers/Help/Help.php create mode 100644 app/Helpers/Help/HelpInterface.php create mode 100644 tests/controllers/HelpControllerTest.php diff --git a/app/Helpers/Help/Help.php b/app/Helpers/Help/Help.php new file mode 100644 index 0000000000..f7bf4a7690 --- /dev/null +++ b/app/Helpers/Help/Help.php @@ -0,0 +1,85 @@ + '

There is no help for this route!

', + 'title' => $route, + ]; + try { + $content['text'] = file_get_contents($uri); + } catch (ErrorException $e) { + Log::error(trim($e->getMessage())); + } + if (strlen(trim($content['text'])) == 0) { + $content['text'] = '

There is no help for this route.

'; + } + $converter = new CommonMarkConverter(); + $content['text'] = $converter->convertToHtml($content['text']); + + return $content; + + } + + /** + * @return boolean + */ + public function hasRoute($route) + { + return Route::has($route); + } + + /** + * @param $title + * @param array $content + * + * @return void + */ + public function putInCache($route, array $content) + { + Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. + Cache::put('help.' . $route . '.title', $content['title'], 10080); + } + + /** + * @param $route + * + * @return bool + */ + public function inCache($route) + { + return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); + } +} \ No newline at end of file diff --git a/app/Helpers/Help/HelpInterface.php b/app/Helpers/Help/HelpInterface.php new file mode 100644 index 0000000000..c550a9faf5 --- /dev/null +++ b/app/Helpers/Help/HelpInterface.php @@ -0,0 +1,46 @@ + '

There is no help for this route!

', 'title' => 'Help', ]; - if (!Route::has($route)) { + if (!$help->hasRoute($route)) { Log::error('No such route: ' . $route); return Response::json($content); } - if ($this->inCache($route)) { + if ($help->inCache($route)) { $content = [ - 'text' => Cache::get('help.' . $route . '.text'), - 'title' => Cache::get('help.' . $route . '.title'), + 'text' => $help->getFromCache('help.' . $route . '.text'), + 'title' => $help->getFromCache('help.' . $route . '.title'), ]; return Response::json($content); } - $content = $this->getFromGithub($route); + $content = $help->getFromGithub($route); - - Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week. - Cache::put('help.' . $route . '.title', $content['title'], 10080); + $help->putInCache($route, $content); return Response::json($content); } - /** - * @param $route - * - * @return bool - */ - protected function inCache($route) - { - return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text'); - } - - /** - * @param $route - * - * @return array - */ - protected function getFromGithub($route) - { - $uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; - $content = [ - 'text' => '

There is no help for this route!

', - 'title' => $route, - ]; - try { - $content['text'] = file_get_contents($uri); - } catch (ErrorException $e) { - Log::error(trim($e->getMessage())); - } - if (strlen(trim($content['text'])) == 0) { - $content['text'] = '

There is no help for this route.

'; - } - $converter = new CommonMarkConverter(); - $content['text'] = $converter->convertToHtml($content['text']); - - return $content; - - - } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 113a25c433..a00ffc289e 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -66,6 +66,7 @@ class FireflyServiceProvider extends ServiceProvider $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); + $this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help'); $this->app->bind('FireflyIII\Helpers\Reminders\ReminderHelperInterface', 'FireflyIII\Helpers\Reminders\ReminderHelper'); $this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper'); $this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery'); diff --git a/tests/controllers/GoogleChartControllerTest.php b/tests/controllers/GoogleChartControllerTest.php index 3600a2eebb..d6cf2bf489 100644 --- a/tests/controllers/GoogleChartControllerTest.php +++ b/tests/controllers/GoogleChartControllerTest.php @@ -193,6 +193,7 @@ class GoogleChartControllerTest extends TestCase $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); $repetition->startdate = Carbon::now()->startOfMonth(); $repetition->enddate = Carbon::now()->endOfMonth(); + $repetition->save(); $budget = $repetition->budgetlimit->budget; $this->be($budget->user); ///chart/budget/{budget}/{limitrepetition} diff --git a/tests/controllers/HelpControllerTest.php b/tests/controllers/HelpControllerTest.php new file mode 100644 index 0000000000..1bacdbdcb0 --- /dev/null +++ b/tests/controllers/HelpControllerTest.php @@ -0,0 +1,96 @@ +be($user); + // mock some stuff. + $interface = $this->mock('FireflyIII\Helpers\Help\HelpInterface'); + $interface->shouldReceive('hasRoute')->once()->with('accounts.index')->andReturn(true); + $interface->shouldReceive('getFromCache')->once()->with('help.accounts.index.title')->andReturn('Title.'); + $interface->shouldReceive('getFromCache')->once()->with('help.accounts.index.text')->andReturn('Text'); + $interface->shouldReceive('inCache')->andReturn(true); + + + $this->call('GET', '/help/accounts.index'); + $this->assertResponseOk(); + } + + /** + * Everything present and accounted for, but not cached + */ + public function testGetHelpTextNoCache() + { + // login + $user = FactoryMuffin::create('FireflyIII\User'); + $content = ['title' => 'Bla', 'text' => 'Bla']; + + $this->be($user); + // mock some stuff. + $interface = $this->mock('FireflyIII\Helpers\Help\HelpInterface'); + $interface->shouldReceive('hasRoute')->once()->with('accounts.index')->andReturn(true); + $interface->shouldReceive('getFromGithub')->once()->with('accounts.index')->andReturn($content); + $interface->shouldReceive('putInCache')->once()->withArgs(['accounts.index', $content]); + $interface->shouldReceive('inCache')->once()->andReturn(false); + + + $this->call('GET', '/help/accounts.index'); + $this->assertResponseOk(); + } + + /** + * No such route. + */ + public function testGetHelpTextNoRoute() + { + // login + $user = FactoryMuffin::create('FireflyIII\User'); + $content = ['title' => 'Bla', 'text' => 'Bla']; + + $this->be($user); + // mock some stuff. + $interface = $this->mock('FireflyIII\Helpers\Help\HelpInterface'); + $interface->shouldReceive('hasRoute')->once()->with('accounts.index')->andReturn(false); + + + $this->call('GET', '/help/accounts.index'); + $this->assertResponseOk(); + } +} \ No newline at end of file From 8f9b1b866b9e79fd2bf122518b82f98e250a4fb8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Tue, 7 Apr 2015 20:54:43 +0200 Subject: [PATCH 11/66] Included full home controller tests. --- app/Http/Controllers/HomeController.php | 5 +- .../Account/AccountRepository.php | 7 ++ .../Account/AccountRepositoryInterface.php | 5 ++ tests/controllers/HelpControllerTest.php | 4 +- tests/controllers/HomeControllerTest.php | 64 +++++++++++++------ 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 202cb7ea18..1824d01039 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -32,6 +32,9 @@ class HomeController extends Controller Session::put('end', $end); } + /** + * @return \Illuminate\Http\RedirectResponse + */ public function flush() { Session::clear(); @@ -58,7 +61,7 @@ class HomeController extends Controller $savings = $repository->getSavingsAccounts(); // check if all books are correct. - $sum = floatval(Auth::user()->transactions()->sum('amount')); + $sum = $repository->sumOfEverything(); if ($sum != 0) { Session::flash( 'error', 'Your transactions are unbalanced. This means a' diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index ff4474635c..50e4004f15 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -151,6 +151,13 @@ class AccountRepository implements AccountRepositoryInterface ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']); } + /** + * @return float + */ + public function sumOfEverything() { + return floatval(Auth::user()->transactions()->sum('amount')); + } + /** * @param Account $account * @param int $page diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 7040e9ff9b..a8dad3c2eb 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -94,6 +94,11 @@ interface AccountRepositoryInterface */ public function getLastActivity(Account $account); + /** + * @return float + */ + public function sumOfEverything(); + /** * Get savings accounts and the balance difference in the period. * diff --git a/tests/controllers/HelpControllerTest.php b/tests/controllers/HelpControllerTest.php index 1bacdbdcb0..849fb45180 100644 --- a/tests/controllers/HelpControllerTest.php +++ b/tests/controllers/HelpControllerTest.php @@ -2,6 +2,9 @@ use League\FactoryMuffin\Facade as FactoryMuffin; +/** + * Class HelpControllerTest + */ class HelpControllerTest extends TestCase { /** @@ -82,7 +85,6 @@ class HelpControllerTest extends TestCase { // login $user = FactoryMuffin::create('FireflyIII\User'); - $content = ['title' => 'Bla', 'text' => 'Bla']; $this->be($user); // mock some stuff. diff --git a/tests/controllers/HomeControllerTest.php b/tests/controllers/HomeControllerTest.php index 3e98aa6f64..aff74fa2e2 100644 --- a/tests/controllers/HomeControllerTest.php +++ b/tests/controllers/HomeControllerTest.php @@ -1,7 +1,10 @@ be(new FireflyIII\User); + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); $this->call('POST', '/daterange', ['end' => $end, 'start' => $start, '_token' => 'replaceme']); @@ -43,6 +46,7 @@ class HomeControllerTest extends TestCase } + /** * @covers FireflyIII\Http\Controllers\HomeController::dateRange */ @@ -50,37 +54,61 @@ class HomeControllerTest extends TestCase { $start = '2014-03-01'; $end = '2015-03-31'; - $this->be(new FireflyIII\User); + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $this->call('POST', '/daterange', ['end' => $end, 'start' => $start, '_token' => 'replaceme']); $this->assertResponseOk(); $this->assertSessionHas('start'); $this->assertSessionHas('end'); $this->assertSessionHas('warning'); + } + + /** + * + */ + public function testFlush() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + $this->call('GET', '/flush'); + $this->assertResponseStatus(302); } /** * @covers FireflyIII\Http\Controllers\HomeController::index */ - public function testIndexLoggedIn() + public function testIndex() { - $this->be(new FireflyIII\User); - Amount::shouldReceive('getCurrencyCode')->andReturn('EUR'); + $user = FactoryMuffin::create('FireflyIII\User'); + $preference = FactoryMuffin::create('FireflyIII\Models\Preference'); + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $journals = new Collection([$journal]); + $account = FactoryMuffin::create('FireflyIII\Models\Account'); + $accounts = new Collection([$account]); + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); - $response = $this->call('GET', '/'); + $this->be($user); + + // mock ALL THE THINGS! + $repository->shouldReceive('countAccounts')->once()->andReturn(3); + Preferences::shouldReceive('get')->once()->withArgs(['frontPageAccounts', []])->andReturn($preference); + $repository->shouldReceive('getFrontpageAccounts')->once()->with($preference)->andReturn($accounts); + $repository->shouldReceive('getSavingsAccounts')->once()->andReturn($accounts); + $repository->shouldReceive('sumOfEverything')->once()->andReturn(1); + $repository->shouldReceive('getFrontpageTransactions')->once()->andReturn($journals); + + + Amount::shouldReceive('getCurrencyCode')->andReturn('EUR'); + Amount::shouldReceive('format')->andReturn('xxx'); + Amount::shouldReceive('formatJournal')->with($journal)->andReturn('xxx'); + + $this->call('GET', '/'); $this->assertResponseOk(); } - /** - * @covers FireflyIII\Http\Controllers\HomeController::index - */ - public function testIndexNoLogin() - { - $response = $this->call('GET', '/'); - $this->assertRedirectedTo('auth/login'); - - } - } From c587081fe4eac5e9e3724f699ff7b2e78408053b Mon Sep 17 00:00:00 2001 From: Balazs Varkonyi Date: Thu, 9 Apr 2015 11:52:35 +0200 Subject: [PATCH 12/66] Add savings total for savings widget on dashboard --- app/Http/Controllers/HomeController.php | 8 +++++++- resources/views/index.blade.php | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 1824d01039..d9acb90548 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -8,6 +8,7 @@ use Input; use Preferences; use Redirect; use Session; +use Steam; /** * Class HomeController @@ -60,6 +61,11 @@ class HomeController extends Controller $accounts = $repository->getFrontpageAccounts($frontPage); $savings = $repository->getSavingsAccounts(); + $savingsTotal = 0; + foreach ($savings as $savingAccount) { + $savingsTotal += Steam::balance($savingAccount); + } + // check if all books are correct. $sum = $repository->sumOfEverything(); if ($sum != 0) { @@ -77,7 +83,7 @@ class HomeController extends Controller } } - return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions')); + return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal')); } diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index 7773963ef2..cc4a001e1b 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -55,6 +55,7 @@
Savings + {!! Amount::format($savingsTotal) !!}
@if(count($savings) == 0) From 339c3525056d5e19c9865b8433e6d841ee96ac6c Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 17:46:47 +0200 Subject: [PATCH 13/66] Fixed a bug where categories would be created even though they already existed. --- app/Models/Category.php | 35 ++++++++++++++++++- .../Journal/JournalRepository.php | 4 +-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/app/Models/Category.php b/app/Models/Category.php index 91674b7f87..60a8198571 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -3,7 +3,7 @@ use Crypt; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; - +use App; /** * Class Category * @@ -31,6 +31,39 @@ class Category extends Model return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id'); } + /** + * @param array $fields + * + * @return Account|null + */ + public static function firstOrCreateEncrypted(array $fields) + { + // everything but the name: + $query = Category::orderBy('id'); + foreach ($fields as $name => $value) { + if ($name != 'name') { + $query->where($name, $value); + } + } + $set = $query->get(['categories.*']); + /** @var Category $category */ + foreach ($set as $category) { + if ($category->name == $fields['name']) { + return $category; + } + } + // create it! + $category = Category::create($fields); + if (is_null($category->id)) { + // could not create account: + App::abort(500, 'Could not create new category with data: ' . json_encode($fields)); + + } + + return $category; + + } + /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index fdda6ae3d4..eb1c8db19d 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -140,7 +140,7 @@ class JournalRepository implements JournalRepositoryInterface // store or get category if (strlen($data['category']) > 0) { - $category = Category::firstOrCreate(['name' => $data['category'], 'user_id' => $data['user']]); + $category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]); $journal->categories()->save($category); } @@ -193,7 +193,7 @@ class JournalRepository implements JournalRepositoryInterface // unlink all categories, recreate them: $journal->categories()->detach(); if (strlen($data['category']) > 0) { - $category = Category::firstOrCreate(['name' => $data['category'], 'user_id' => $data['user']]); + $category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]); $journal->categories()->save($category); } From 9c8ba668737963d2c1a22c05d94c6b93dab0a6cd Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 17:54:24 +0200 Subject: [PATCH 14/66] Order categories by name. --- .../Category/CategoryRepository.php | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 1266d71b50..9fe14b1bbb 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -46,7 +46,15 @@ class CategoryRepository implements CategoryRepositoryInterface */ public function getCategories() { - return Auth::user()->categories()->orderBy('name', 'ASC')->get(); + /** @var Collection $set */ + $set = Auth::user()->categories()->orderBy('name', 'ASC')->get(); + $set->sortBy( + function (Category $category) { + return $category->name; + } + ); + + return $set; } /** @@ -167,6 +175,17 @@ class CategoryRepository implements CategoryRepositoryInterface return floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; } + /** + * @param Category $category + * @param Carbon $date + * + * @return float + */ + public function spentOnDaySum(Category $category, Carbon $date) + { + return floatval($category->transactionjournals()->onDate($date)->lessThan(0)->sum('amount')) * -1; + } + /** * @param array $data * @@ -199,15 +218,4 @@ class CategoryRepository implements CategoryRepositoryInterface return $category; } - - /** - * @param Category $category - * @param Carbon $date - * - * @return float - */ - public function spentOnDaySum(Category $category, Carbon $date) - { - return floatval($category->transactionjournals()->onDate($date)->lessThan(0)->sum('amount')) * -1; - } } From 950c4045b05b0bed833a468039c34aeea5158ef6 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 19:10:24 +0200 Subject: [PATCH 15/66] Fix total savings to accurately reflect end of current period. --- app/Http/Controllers/HomeController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index d9acb90548..e02c69bddb 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -63,7 +63,7 @@ class HomeController extends Controller $savingsTotal = 0; foreach ($savings as $savingAccount) { - $savingsTotal += Steam::balance($savingAccount); + $savingsTotal += Steam::balance($savingAccount, $end); } // check if all books are correct. From 5124ce03029e26d9f7390c56fa8e9507c9c7bc13 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 20:52:47 +0200 Subject: [PATCH 16/66] Fixed a bug where getAmountAttribute would interfere with queries that contained a "amount"-field. --- app/Http/Controllers/JsonController.php | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index f620da02fd..e8229bfa84 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -40,9 +40,9 @@ class JsonController extends Controller ->after($start) ->transactionTypes(['Deposit']) ->where('transactions.amount', '>', 0) - ->first([DB::Raw('SUM(transactions.amount) as `amount`')]); + ->first([DB::Raw('SUM(transactions.amount) as `totalAmount`')]); if (!is_null($in)) { - $amount = floatval($in->amount); + $amount = floatval($in->totalAmount); } break; @@ -50,13 +50,13 @@ class JsonController extends Controller $box = Input::get('box'); $in = Auth::user()->transactionjournals() ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->before($end) - ->after($start) + //->before($end) + // ->after($start) ->transactionTypes(['Withdrawal']) ->where('transactions.amount', '>', 0) - ->first([DB::Raw('SUM(transactions.amount) as `amount`')]); + ->first([DB::Raw('SUM(transactions.amount) as `totalAmount`')]); if (!is_null($in)) { - $amount = floatval($in->amount); + $amount = floatval($in->totalAmount); } break; @@ -115,14 +115,8 @@ class JsonController extends Controller // paid a bill in this range? $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); if ($count != 0) { - $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); - $currentAmount = 0; - foreach ($journal->transactions as $t) { - if (floatval($t->amount) > 0) { - $currentAmount = floatval($t->amount); - } - } - $amount += $currentAmount; + $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); + $amount += $journal->amount; } } From 587b94153d3d82e19ded1489259872e01be649e5 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 20:58:57 +0200 Subject: [PATCH 17/66] Removed some foreach() routines that are no longer necessary now that getAmountAttribute() exists. --- app/Handlers/Events/ConnectJournalToPiggyBank.php | 9 +-------- app/Handlers/Events/UpdateJournalConnection.php | 13 ++----------- app/Http/Controllers/RelatedController.php | 12 ------------ app/Http/Controllers/TransactionController.php | 8 +------- 4 files changed, 4 insertions(+), 38 deletions(-) diff --git a/app/Handlers/Events/ConnectJournalToPiggyBank.php b/app/Handlers/Events/ConnectJournalToPiggyBank.php index 7280ccc3c6..81152e3d97 100644 --- a/app/Handlers/Events/ConnectJournalToPiggyBank.php +++ b/app/Handlers/Events/ConnectJournalToPiggyBank.php @@ -51,14 +51,7 @@ class ConnectJournalToPiggyBank return; } Log::debug('Found a piggy bank'); - $amount = 0; - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - if ($transaction->account_id === $piggyBank->account_id) { - // this transaction is the relevant one. - $amount = floatval($transaction->amount); - } - } + $amount = $journal->amount; Log::debug('Amount: ' . $amount); if ($amount == 0) { return; diff --git a/app/Handlers/Events/UpdateJournalConnection.php b/app/Handlers/Events/UpdateJournalConnection.php index 38b7a503e7..ad79e70551 100644 --- a/app/Handlers/Events/UpdateJournalConnection.php +++ b/app/Handlers/Events/UpdateJournalConnection.php @@ -45,17 +45,8 @@ class UpdateJournalConnection if (is_null($repetition)) { return; } - $amount = 0; - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - if ($transaction->account_id === $piggyBank->account_id) { - // this transaction is the relevant one. - $amount = floatval($transaction->amount); - } - } - - // update current repetition: - $diff = $amount - $event->amount; + $amount = $journal->amount; + $diff = $amount - $event->amount;// update current repetition $repetition->currentamount += $diff; $repetition->save(); diff --git a/app/Http/Controllers/RelatedController.php b/app/Http/Controllers/RelatedController.php index 5bdebaae3a..d8d914a3ec 100644 --- a/app/Http/Controllers/RelatedController.php +++ b/app/Http/Controllers/RelatedController.php @@ -40,19 +40,7 @@ class RelatedController extends Controller $unique = array_unique($ids); $journals = new Collection; if (count($unique) > 0) { - $journals = Auth::user()->transactionjournals()->whereIn('id', $unique)->get(); - $journals->each( - function (TransactionJournal $journal) { - /** @var Transaction $t */ - foreach ($journal->transactions()->get() as $t) { - if ($t->amount > 0) { - $journal->amount = $t->amount; - } - } - - } - ); } $parent = $journal; diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 4d850ef7bb..5a3bbfa628 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -149,13 +149,7 @@ class TransactionController extends Controller $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id; } - $preFilled['amount'] = 0; - /** @var Transaction $t */ - foreach ($transactions as $t) { - if (floatval($t->amount) > 0) { - $preFilled['amount'] = floatval($t->amount); - } - } + $preFilled['amount'] = $journal->amount; $preFilled['account_id'] = $repository->getAssetAccount($journal); $preFilled['expense_account'] = $transactions[0]->account->name; $preFilled['revenue_account'] = $transactions[1]->account->name; From 0224d1d59bf416eab2403cbf4036e9c4591925fa Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:01:08 +0200 Subject: [PATCH 18/66] Accidentally commented out date limits in query. --- app/Http/Controllers/JsonController.php | 4 ++-- app/Repositories/Bill/BillRepository.php | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index e8229bfa84..e248d9aeec 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -50,8 +50,8 @@ class JsonController extends Controller $box = Input::get('box'); $in = Auth::user()->transactionjournals() ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - //->before($end) - // ->after($start) + ->before($end) + ->after($start) ->transactionTypes(['Withdrawal']) ->where('transactions.amount', '>', 0) ->first([DB::Raw('SUM(transactions.amount) as `totalAmount`')]); diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 9b7ae4e492..c6b7bacb05 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -4,6 +4,8 @@ namespace FireflyIII\Repositories\Bill; use Auth; use Carbon\Carbon; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; use FireflyIII\Models\Bill; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; From 37f40d86376cd83639bcac552a0f77c23f486864 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:14:15 +0200 Subject: [PATCH 19/66] Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. --- app/Helpers/Report/ReportHelper.php | 16 +++++++-------- app/Helpers/Report/ReportQuery.php | 24 +++++++++++------------ app/Http/Controllers/ReportController.php | 2 +- app/Support/Steam.php | 20 ++++++++++--------- resources/views/reports/budget.blade.php | 20 +++++++++---------- 5 files changed, 42 insertions(+), 40 deletions(-) diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index e1252e55c1..b968994367 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -60,15 +60,15 @@ class ReportHelper implements ReportHelperInterface $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); } ) - ->get(['budgets.*', 'budget_limits.amount as amount']); + ->get(['budgets.*', 'budget_limits.amount as queryAmount']); - $budgets = Steam::makeArray($set); - $amountSet = $query->journalsByBudget($start, $end, $showSharedReports); - $amounts = Steam::makeArray($amountSet); - $budgets = Steam::mergeArrays($budgets, $amounts); - $budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0; - $budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0; - $budgets[0]['name'] = 'No budget'; + $budgets = Steam::makeArray($set); + $amountSet = $query->journalsByBudget($start, $end, $showSharedReports); + $amounts = Steam::makeArray($amountSet); + $budgets = Steam::mergeArrays($budgets, $amounts); + $budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0; + $budgets[0]['queryAmount'] = isset($budgets[0]['queryAmount']) ? $budgets[0]['queryAmount'] : 0.0; + $budgets[0]['name'] = 'No budget'; // find transactions to shared asset accounts, which are without a budget by default: // which is only relevant when shared asset accounts are hidden. diff --git a/app/Helpers/Report/ReportQuery.php b/app/Helpers/Report/ReportQuery.php index 93a48a0633..8b8f2728ee 100644 --- a/app/Helpers/Report/ReportQuery.php +++ b/app/Helpers/Report/ReportQuery.php @@ -96,7 +96,7 @@ class ReportQuery implements ReportQueryInterface ->get( [ 'transaction_journals.*', - 'transactions.amount' + 'transactions.amount as queryAmount' ] ); @@ -178,7 +178,7 @@ class ReportQuery implements ReportQueryInterface { $query = $this->queryJournalsNoBudget($account, $start, $end); - return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `amount`')]); + return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]); } @@ -196,7 +196,7 @@ class ReportQuery implements ReportQueryInterface { $query = $this->queryJournalsNoBudget($account, $start, $end); - return $query->get(['budgets.name', 'transactions.amount', 'transaction_journals.*']); + return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']); } /** @@ -244,7 +244,7 @@ class ReportQuery implements ReportQueryInterface 'transaction_journals.description', 'transaction_journals.encrypted', 'transaction_types.type', - DB::Raw('SUM(`t_to`.`amount`) as `amount`'), + DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'), 'transaction_journals.date', 't_from.account_id as account_id', 'ac_from.name as name', @@ -334,9 +334,9 @@ class ReportQuery implements ReportQueryInterface ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) ->where('transaction_types.type', 'Withdrawal') ->groupBy('categories.id') - ->orderBy('amount'); + ->orderBy('queryAmount'); - $data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]); + $data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]); // decrypt data: $data->each( function (Model $object) { @@ -389,9 +389,9 @@ class ReportQuery implements ReportQueryInterface $query->before($end)->after($start) ->where('transaction_journals.user_id', Auth::user()->id) ->groupBy('t_to.account_id') - ->orderBy('amount', 'DESC'); + ->orderBy('queryAmount', 'DESC'); - $data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `amount`')]); + $data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `queryAmount`')]); // decrypt $data->each( @@ -440,10 +440,10 @@ class ReportQuery implements ReportQueryInterface $query->where('transaction_types.type', 'Deposit'); } - $query->groupBy('t_from.account_id')->orderBy('amount'); + $query->groupBy('t_from.account_id')->orderBy('queryAmount'); $data = $query->get( - ['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `amount`')] + ['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `queryAmount`')] ); // decrypt $data->each( @@ -488,7 +488,7 @@ class ReportQuery implements ReportQueryInterface ->where('transaction_journals.user_id', Auth::user()->id) ->get( ['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name', - 'transactions.amount'] + 'transactions.amount as queryAmount'] ); } @@ -533,7 +533,7 @@ class ReportQuery implements ReportQueryInterface [ 'categories.id', 'categories.name as name', - DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`') + DB::Raw('SUM(`transactions`.`amount`) * -1 AS `queryAmount`') ] ); } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index ad6d3e5889..9c82e2f7cc 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -81,7 +81,7 @@ class ReportController extends Controller $id = intval($budget->id); $data = $budget->toArray(); $array[$id] = $data; - if (floatval($data['amount']) != 0) { + if (floatval($data['queryAmount']) != 0) { $hide = false; } } diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 5bd043eefe..77c5dc1d16 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -103,14 +103,16 @@ class Steam $id = intval($entry->id); if (isset($array[$id])) { $array[$id]['amount'] += floatval($entry->amount); + $array[$id]['queryAmount'] += floatval($entry->queryAmount); $array[$id]['spent'] += floatval($entry->spent); $array[$id]['encrypted'] = intval($entry->encrypted); } else { $array[$id] = [ - 'amount' => floatval($entry->amount), - 'spent' => floatval($entry->spent), - 'encrypted' => intval($entry->encrypted), - 'name' => $entry->name + 'amount' => floatval($entry->amount), + 'queryAmount' => floatval($entry->queryAmount), + 'spent' => floatval($entry->spent), + 'encrypted' => intval($entry->encrypted), + 'name' => $entry->name ]; } } @@ -131,7 +133,7 @@ class Steam foreach ($two as $id => $value) { // $otherId also exists in $one: if (isset($one[$id])) { - $one[$id]['amount'] += $value['amount']; + $one[$id]['queryAmount'] += $value['queryAmount']; $one[$id]['spent'] += $value['spent']; } else { $one[$id] = $value; @@ -170,11 +172,11 @@ class Steam { uasort( $array, function ($left, $right) { - if ($left['amount'] == $right['amount']) { + if ($left['queryAmount'] == $right['queryAmount']) { return 0; } - return ($left['amount'] < $right['amount']) ? 1 : -1; + return ($left['queryAmount'] < $right['queryAmount']) ? 1 : -1; } ); @@ -193,11 +195,11 @@ class Steam { uasort( $array, function ($left, $right) { - if ($left['amount'] == $right['amount']) { + if ($left['queryAmount'] == $right['queryAmount']) { return 0; } - return ($left['amount'] < $right['amount']) ? -1 : 1; + return ($left['queryAmount'] < $right['queryAmount']) ? -1 : 1; } ); diff --git a/resources/views/reports/budget.blade.php b/resources/views/reports/budget.blade.php index bc41bba2fe..c986e47c20 100644 --- a/resources/views/reports/budget.blade.php +++ b/resources/views/reports/budget.blade.php @@ -75,7 +75,7 @@ @foreach($budgets as $id => $budget) {{{$budget['name']}}} - {!! Amount::format($budget['amount']) !!} + {!! Amount::format($budget['queryAmount']) !!} @foreach($accounts as $account) @if($account->hide === false) @@ -83,23 +83,23 @@ @if($id == 0) - {!! Amount::format($account->budgetInformation[$id]['amount']) !!} + {!! Amount::format($account->budgetInformation[$id]['queryAmount']) !!} @else - {!! Amount::format($account->budgetInformation[$id]['amount']) !!} + {!! Amount::format($account->budgetInformation[$id]['queryAmount']) !!} @endif budgetInformation[$id]['amount']); - $accountSums[$account->id] += floatval($account->budgetInformation[$id]['amount']); + $spent += floatval($account->budgetInformation[$id]['queryAmount']); + $accountSums[$account->id] += floatval($account->budgetInformation[$id]['queryAmount']); ?> @else {!! Amount::format(0) !!} @endif @endif @endforeach - {!! Amount::format($budget['amount'] + $budget['spent']) !!} - {!! Amount::format($budget['amount'] + $spent) !!} + {!! Amount::format($budget['queryAmount'] + $budget['spent']) !!} + {!! Amount::format($budget['queryAmount'] + $spent) !!} @endforeach @@ -122,10 +122,10 @@ @if($account->hide === false) @if(isset($account->budgetInformation[0])) - @if($account->budgetInformation[0]['amount'] + $account->balancedAmount != 0.0) - {!! Amount::format($account->budgetInformation[0]['amount'] + $account->balancedAmount) !!} + @if($account->budgetInformation[0]['queryAmount'] + $account->balancedAmount != 0.0) + {!! Amount::format($account->budgetInformation[0]['queryAmount'] + $account->balancedAmount) !!} @else - {!! Amount::format($account->budgetInformation[0]['amount'] + $account->balancedAmount) !!} + {!! Amount::format($account->budgetInformation[0]['queryAmount'] + $account->balancedAmount) !!} @endif @else From 1d67d2250a2f6107b08a68ad8d0a395144b8b650 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:16:35 +0200 Subject: [PATCH 20/66] Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. --- resources/views/reports/month.blade.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/views/reports/month.blade.php b/resources/views/reports/month.blade.php index dfcf5ce912..1f257f4b30 100644 --- a/resources/views/reports/month.blade.php +++ b/resources/views/reports/month.blade.php @@ -64,7 +64,7 @@ @foreach($expenses as $id => $expense) @if($id > 0) @@ -72,7 +72,7 @@ @else {{{$expense['name']}}} @endif - {!! Amount::format($expense['amount']) !!} + {!! Amount::format($expense['queryAmount']) !!} @endforeach @@ -133,11 +133,11 @@ @foreach($budgets as $id => $budget) - @if($budget['amount'] != 0 || $budget['spent'] != 0) + @if($budget['queryAmount'] != 0 || $budget['spent'] != 0) @if($id > 0) @@ -174,7 +174,7 @@ @foreach($categories as $id => $category) - + @if($id > 0) @@ -183,7 +183,7 @@ {{{$category['name']}}} @endif - {!! Amount::format($category['amount'],false) !!} + {!! Amount::format($category['queryAmount'],false) !!} @endforeach From 38516528216f10ddd6fb7544b5a6e077f3370abb Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:18:18 +0200 Subject: [PATCH 21/66] Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. --- app/Support/Steam.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Support/Steam.php b/app/Support/Steam.php index 77c5dc1d16..591bba1db5 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -67,8 +67,8 @@ class Steam public function limitArray(array $array, $limit = 10) { $others = [ - 'name' => 'Others', - 'amount' => 0 + 'name' => 'Others', + 'queryAmount' => 0 ]; $return = []; $count = 0; @@ -76,7 +76,7 @@ class Steam if ($count < ($limit - 1)) { $return[$id] = $entry; } else { - $others['amount'] += $entry['amount']; + $others['queryAmount'] += $entry['queryAmount']; } $count++; From 7abeece3f047574242c726f854a3e9c2afec22d7 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:27:35 +0200 Subject: [PATCH 22/66] Simplified the "out"-box. --- app/Http/Controllers/JsonController.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index e248d9aeec..7961927374 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -3,6 +3,7 @@ use Amount; use Auth; use DB; +use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; use FireflyIII\Models\Transaction; @@ -25,7 +26,7 @@ class JsonController extends Controller /** * */ - public function box(BillRepositoryInterface $repository) + public function box(BillRepositoryInterface $repository, ReportQueryInterface $reportQuery) { $amount = 0; $start = Session::get('start'); @@ -34,17 +35,12 @@ class JsonController extends Controller switch (Input::get('box')) { case 'in': $box = Input::get('box'); - $in = Auth::user()->transactionjournals() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->before($end) - ->after($start) - ->transactionTypes(['Deposit']) - ->where('transactions.amount', '>', 0) - ->first([DB::Raw('SUM(transactions.amount) as `totalAmount`')]); - if (!is_null($in)) { - $amount = floatval($in->totalAmount); - } + $set = $reportQuery->journalsByExpenseAccount($start, $end, true); + + foreach ($set as $entry) { + $amount += $set->queryAmount; + } break; case 'out': $box = Input::get('box'); From 2432af7883e9d605b213968b98cab2fdb88c66ab Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:29:58 +0200 Subject: [PATCH 23/66] Simplified the in and out-box. --- app/Http/Controllers/JsonController.php | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 7961927374..8917194049 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -2,7 +2,6 @@ use Amount; use Auth; -use DB; use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; @@ -37,22 +36,16 @@ class JsonController extends Controller $box = Input::get('box'); $set = $reportQuery->journalsByExpenseAccount($start, $end, true); - foreach ($set as $entry) { - $amount += $set->queryAmount; + $amount += $entry->queryAmount; } break; case 'out': $box = Input::get('box'); - $in = Auth::user()->transactionjournals() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->before($end) - ->after($start) - ->transactionTypes(['Withdrawal']) - ->where('transactions.amount', '>', 0) - ->first([DB::Raw('SUM(transactions.amount) as `totalAmount`')]); - if (!is_null($in)) { - $amount = floatval($in->totalAmount); + $set = $reportQuery->incomeByPeriod($start, $end, true); + + foreach ($set as $entry) { + $amount += $entry->queryAmount; } break; From 490997157e4497c5e8d3ed72a231c966f35ce9dc Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:30:35 +0200 Subject: [PATCH 24/66] Switched two queries around. --- app/Http/Controllers/JsonController.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 8917194049..d8e10850bb 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -34,7 +34,8 @@ class JsonController extends Controller switch (Input::get('box')) { case 'in': $box = Input::get('box'); - $set = $reportQuery->journalsByExpenseAccount($start, $end, true); + $set = $reportQuery->incomeByPeriod($start, $end, true); + foreach ($set as $entry) { $amount += $entry->queryAmount; @@ -42,7 +43,7 @@ class JsonController extends Controller break; case 'out': $box = Input::get('box'); - $set = $reportQuery->incomeByPeriod($start, $end, true); + $set = $reportQuery->journalsByExpenseAccount($start, $end, true); foreach ($set as $entry) { $amount += $entry->queryAmount; From d3f642551d4acf340dd12c462c52995b5a776e63 Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 9 Apr 2015 21:36:58 +0200 Subject: [PATCH 25/66] Fixed a small bug in the bill-chart and simplified yet another Json box. --- .../Controllers/GoogleChartController.php | 2 +- app/Http/Controllers/JsonController.php | 47 +++++++++---------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index b24dd68ae6..e5455e5598 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -302,7 +302,7 @@ class GoogleChartController extends Controller /** @var Bill $entry */ foreach ($unpaid as $entry) { $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; - $unpaidAmount += ($bill->amount_max + $bill->amount_min / 2); + $unpaidAmount += ($entry[0]->amount_max + $entry[0]->amount_min / 2); } $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index d8e10850bb..e82a3a1dbf 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -2,12 +2,15 @@ use Amount; use Auth; +use Carbon\Carbon; use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Models\Account; use FireflyIII\Models\Bill; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use Illuminate\Support\Collection; use Input; use Preferences; use Response; @@ -25,7 +28,7 @@ class JsonController extends Controller /** * */ - public function box(BillRepositoryInterface $repository, ReportQueryInterface $reportQuery) + public function box(BillRepositoryInterface $repository, ReportQueryInterface $reportQuery, AccountRepositoryInterface $accountRepository) { $amount = 0; $start = Session::get('start'); @@ -51,8 +54,9 @@ class JsonController extends Controller break; case 'bills-unpaid': - $box = 'bills-unpaid'; - $bills = Auth::user()->bills()->where('active', 1)->get(); + $box = 'bills-unpaid'; + $bills = $repository->getActiveBills(); + $unpaid = new Collection; // bills /** @var Bill $bill */ foreach ($bills as $bill) { @@ -60,36 +64,31 @@ class JsonController extends Controller foreach ($ranges as $range) { // paid a bill in this range? - $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); - if ($count == 0) { - $amount += floatval($bill->amount_max + $bill->amount_min / 2); + $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); + if ($journals->count() == 0) { + $unpaid->push([$bill, $range['start']]); } - } } - /** - * Find credit card accounts and possibly unpaid credit card bills. - */ - $creditCards = Auth::user()->accounts() - ->hasMetaValue('accountRole', 'ccAsset') - ->hasMetaValue('ccType', 'monthlyFull') - ->get( - [ - 'accounts.*', - 'ccType.data as ccType', - 'accountRole.data as accountRole' - ] - ); - // if the balance is not zero, the monthly payment is still underway. - /** @var Account $creditCard */ + $creditCards = $accountRepository->getCreditCards(); foreach ($creditCards as $creditCard) { $balance = Steam::balance($creditCard, null, true); + $date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); if ($balance < 0) { - // unpaid! - $amount += $balance * -1; + // unpaid! create a fake bill that matches the amount. + $description = $creditCard->name; + $amount = $balance * -1; + $fakeBill = $repository->createFakeBill($description, $date, $amount); + $unpaid->push([$fakeBill, $date]); } } + // loop unpaid: + /** @var Bill $entry */ + foreach ($unpaid as $entry) { + $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; + $amount += ($entry[0]->amount_max + $entry[0]->amount_min / 2); + } break; case 'bills-paid': From 2ef7a019453d1d457f6cd03b5e6d755951aa00fe Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 10 Apr 2015 06:52:36 +0200 Subject: [PATCH 26/66] Fixed a bug where the bill chart and boxes would inaccurately reflect the amount of bills yet to pay. --- app/Http/Controllers/GoogleChartController.php | 2 +- app/Http/Controllers/JsonController.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index e5455e5598..59f22335a0 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -302,7 +302,7 @@ class GoogleChartController extends Controller /** @var Bill $entry */ foreach ($unpaid as $entry) { $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; - $unpaidAmount += ($entry[0]->amount_max + $entry[0]->amount_min / 2); + $unpaidAmount += ($entry[0]->amount_max + $entry[0]->amount_min) / 2; } $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index e82a3a1dbf..7c59728f5b 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -70,6 +70,7 @@ class JsonController extends Controller } } } + unset($bill, $range, $ranges); $creditCards = $accountRepository->getCreditCards(); foreach ($creditCards as $creditCard) { @@ -86,8 +87,7 @@ class JsonController extends Controller // loop unpaid: /** @var Bill $entry */ foreach ($unpaid as $entry) { - $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; - $amount += ($entry[0]->amount_max + $entry[0]->amount_min / 2); + $amount += ($entry[0]->amount_max + $entry[0]->amount_min) / 2; } break; From 06f2e34bb5ad51c88b5d6443f464958c2738c55c Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 10 Apr 2015 06:57:39 +0200 Subject: [PATCH 27/66] Renamed the amount variable so it stops interfering with another variable --- app/Http/Controllers/JsonController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 7c59728f5b..effcee45e5 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -79,8 +79,8 @@ class JsonController extends Controller if ($balance < 0) { // unpaid! create a fake bill that matches the amount. $description = $creditCard->name; - $amount = $balance * -1; - $fakeBill = $repository->createFakeBill($description, $date, $amount); + $fakeAmount = $balance * -1; + $fakeBill = $repository->createFakeBill($description, $date, $fakeAmount); $unpaid->push([$fakeBill, $date]); } } From db5d94d95634886e66b8fb62a254f39e42248ede Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 10 Apr 2015 07:19:45 +0200 Subject: [PATCH 28/66] Added temporary debug entries. --- app/Http/Controllers/JsonController.php | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index effcee45e5..1e257eba0d 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -16,6 +16,7 @@ use Preferences; use Response; use Session; use Steam; +use Log; /** * Class JsonController @@ -38,8 +39,6 @@ class JsonController extends Controller case 'in': $box = Input::get('box'); $set = $reportQuery->incomeByPeriod($start, $end, true); - - foreach ($set as $entry) { $amount += $entry->queryAmount; } @@ -57,6 +56,7 @@ class JsonController extends Controller $box = 'bills-unpaid'; $bills = $repository->getActiveBills(); $unpaid = new Collection; // bills + Log::debug('UnpaidBox: Unpaid box'); /** @var Bill $bill */ foreach ($bills as $bill) { @@ -85,16 +85,22 @@ class JsonController extends Controller } } // loop unpaid: + /** @var Bill $entry */ foreach ($unpaid as $entry) { - $amount += ($entry[0]->amount_max + $entry[0]->amount_min) / 2; + $current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; + $amount += $current; + Log::debug('UnpaidBox: '.$entry[0]->name.': '.$current); + Log::debug('UnpaidBox: Total is now: ' . $amount); } + Log::debug('UnpaidBox: Total is final: ' . $amount); break; case 'bills-paid': $box = 'bills-paid'; // these two functions are the same as the chart TODO $bills = Auth::user()->bills()->where('active', 1)->get(); + Log::debug('PaidBox: Paid box'); /** @var Bill $bill */ foreach ($bills as $bill) { @@ -106,11 +112,15 @@ class JsonController extends Controller if ($count != 0) { $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); $amount += $journal->amount; + Log::debug('PaidBox: Journal for bill "'.$bill->name.'": ' . $journal->amount); + Log::debug('PaidBox: Total is now: ' . $amount); } } } + + Log::debug('PaidBox: Doing ccs now.'); /** * Find credit card accounts and possibly unpaid credit card bills. */ @@ -129,6 +139,7 @@ class JsonController extends Controller foreach ($creditCards as $creditCard) { $balance = Steam::balance($creditCard, null, true); if ($balance == 0) { + Log::debug('PaidBox: Balance for '.$creditCard->name.' is zero.'); // find a transfer TO the credit card which should account for // anything paid. If not, the CC is not yet used. $transactions = $creditCard->transactions() @@ -139,14 +150,19 @@ class JsonController extends Controller foreach ($transactions as $transaction) { $journal = $transaction->transactionJournal; if ($journal->transactionType->type == 'Transfer') { + Log::debug('PaidBox: Found the transfer! Amount: ' . floatval($transaction->amount)); $amount += floatval($transaction->amount); + Log::debug('PaidBox: Total is now: ' . $amount); } } } } } + Log::debug('PaidBox: Total is: ' . $amount); + break; } + return Response::json(['box' => $box, 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); } From 4a95bdd8ba6dc8a8c31ba6b0bac4a1c5a2f592c3 Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 10 Apr 2015 07:25:24 +0200 Subject: [PATCH 29/66] Added temporary debug to google chart. --- app/Http/Controllers/GoogleChartController.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 59f22335a0..12586522f4 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -19,6 +19,7 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use Grumpydictator\Gchart\GChart; use Illuminate\Support\Collection; +use Log; use Navigation; use Preferences; use Response; @@ -277,6 +278,7 @@ class GoogleChartController extends Controller $description = $creditCard->name; $amount = $balance * -1; $fakeBill = $repository->createFakeBill($description, $date, $amount); + unset($description, $amount); $unpaid->push([$fakeBill, $date]); } if ($balance == 0) { @@ -294,16 +296,26 @@ class GoogleChartController extends Controller /** @var TransactionJournal $entry */ foreach ($paid as $entry) { + $paidDescriptions[] = $entry->description; $paidAmount += floatval($entry->amount); + Log::debug('PaidChart: ' . $entry->description . ' with amount ' . floatval($entry->amount)); + Log::debug('PaidChart: total amount is now: ' . $paidAmount); } + Log::debug('PaidChart: total amount final: ' . $paidAmount); // loop unpaid: /** @var Bill $entry */ foreach ($unpaid as $entry) { - $unpaidDescriptions[] = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; - $unpaidAmount += ($entry[0]->amount_max + $entry[0]->amount_min) / 2; + $description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; + $amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; + $unpaidDescriptions[] = $description; + $unpaidAmount += $amount; + Log::debug('UnpaidChart: ' . $description . ' with amount ' . $amount); + Log::debug('UnpaidChart: total is now: ' . $unpaidAmount); + unset($amount, $description); } + Log::debug('UnpaidChart: total is final: ' . $unpaidAmount); $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); $chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount); From d8d92f147fb37306cd7ed366454e811a6c9cf9da Mon Sep 17 00:00:00 2001 From: James Cole Date: Fri, 10 Apr 2015 07:29:36 +0200 Subject: [PATCH 30/66] Removed logging, found bug. --- app/Http/Controllers/GoogleChartController.php | 7 ------- app/Http/Controllers/JsonController.php | 16 ++-------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 12586522f4..f8fe729133 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -19,7 +19,6 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use Grumpydictator\Gchart\GChart; use Illuminate\Support\Collection; -use Log; use Navigation; use Preferences; use Response; @@ -299,10 +298,7 @@ class GoogleChartController extends Controller $paidDescriptions[] = $entry->description; $paidAmount += floatval($entry->amount); - Log::debug('PaidChart: ' . $entry->description . ' with amount ' . floatval($entry->amount)); - Log::debug('PaidChart: total amount is now: ' . $paidAmount); } - Log::debug('PaidChart: total amount final: ' . $paidAmount); // loop unpaid: /** @var Bill $entry */ @@ -311,11 +307,8 @@ class GoogleChartController extends Controller $amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; $unpaidDescriptions[] = $description; $unpaidAmount += $amount; - Log::debug('UnpaidChart: ' . $description . ' with amount ' . $amount); - Log::debug('UnpaidChart: total is now: ' . $unpaidAmount); unset($amount, $description); } - Log::debug('UnpaidChart: total is final: ' . $unpaidAmount); $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); $chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount); diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 1e257eba0d..31bc8ea34c 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -16,7 +16,6 @@ use Preferences; use Response; use Session; use Steam; -use Log; /** * Class JsonController @@ -56,7 +55,6 @@ class JsonController extends Controller $box = 'bills-unpaid'; $bills = $repository->getActiveBills(); $unpaid = new Collection; // bills - Log::debug('UnpaidBox: Unpaid box'); /** @var Bill $bill */ foreach ($bills as $bill) { @@ -90,17 +88,13 @@ class JsonController extends Controller foreach ($unpaid as $entry) { $current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; $amount += $current; - Log::debug('UnpaidBox: '.$entry[0]->name.': '.$current); - Log::debug('UnpaidBox: Total is now: ' . $amount); } - Log::debug('UnpaidBox: Total is final: ' . $amount); break; case 'bills-paid': $box = 'bills-paid'; // these two functions are the same as the chart TODO $bills = Auth::user()->bills()->where('active', 1)->get(); - Log::debug('PaidBox: Paid box'); /** @var Bill $bill */ foreach ($bills as $bill) { @@ -110,17 +104,15 @@ class JsonController extends Controller // paid a bill in this range? $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); if ($count != 0) { + // TODO this only gets the first match, may be more than one. $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); $amount += $journal->amount; - Log::debug('PaidBox: Journal for bill "'.$bill->name.'": ' . $journal->amount); - Log::debug('PaidBox: Total is now: ' . $amount); } } } - Log::debug('PaidBox: Doing ccs now.'); /** * Find credit card accounts and possibly unpaid credit card bills. */ @@ -139,7 +131,6 @@ class JsonController extends Controller foreach ($creditCards as $creditCard) { $balance = Steam::balance($creditCard, null, true); if ($balance == 0) { - Log::debug('PaidBox: Balance for '.$creditCard->name.' is zero.'); // find a transfer TO the credit card which should account for // anything paid. If not, the CC is not yet used. $transactions = $creditCard->transactions() @@ -150,16 +141,13 @@ class JsonController extends Controller foreach ($transactions as $transaction) { $journal = $transaction->transactionJournal; if ($journal->transactionType->type == 'Transfer') { - Log::debug('PaidBox: Found the transfer! Amount: ' . floatval($transaction->amount)); $amount += floatval($transaction->amount); - Log::debug('PaidBox: Total is now: ' . $amount); } } } } } - Log::debug('PaidBox: Total is: ' . $amount); - break; + break; } From 1802bb967a239af2223152611c8eaa8291701313 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 07:24:07 +0200 Subject: [PATCH 31/66] Moved JSON money boxes to individual functions. --- app/Http/Controllers/JsonController.php | 254 +++++++++++++----------- app/Http/routes.php | 5 +- public/js/index.js | 6 +- 3 files changed, 145 insertions(+), 120 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 31bc8ea34c..c093515637 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -11,7 +11,6 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use Illuminate\Support\Collection; -use Input; use Preferences; use Response; use Session; @@ -25,133 +24,156 @@ use Steam; class JsonController extends Controller { + /** + * @param BillRepositoryInterface $repository * + * @return \Symfony\Component\HttpFoundation\Response */ - public function box(BillRepositoryInterface $repository, ReportQueryInterface $reportQuery, AccountRepositoryInterface $accountRepository) + public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) { - $amount = 0; $start = Session::get('start'); $end = Session::get('end'); - $box = 'empty'; - switch (Input::get('box')) { - case 'in': - $box = Input::get('box'); - $set = $reportQuery->incomeByPeriod($start, $end, true); - foreach ($set as $entry) { - $amount += $entry->queryAmount; - } - break; - case 'out': - $box = Input::get('box'); - $set = $reportQuery->journalsByExpenseAccount($start, $end, true); + $amount = 0; - foreach ($set as $entry) { - $amount += $entry->queryAmount; + // these two functions are the same as the chart TODO + $bills = Auth::user()->bills()->where('active', 1)->get(); + + /** @var Bill $bill */ + foreach ($bills as $bill) { + $ranges = $repository->getRanges($bill, $start, $end); + + foreach ($ranges as $range) { + // paid a bill in this range? + $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); + if ($count != 0) { + // TODO this only gets the first match, may be more than one. + $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); + $amount += $journal->amount; } - break; - case 'bills-unpaid': - $box = 'bills-unpaid'; - $bills = $repository->getActiveBills(); - $unpaid = new Collection; // bills - - /** @var Bill $bill */ - foreach ($bills as $bill) { - $ranges = $repository->getRanges($bill, $start, $end); - - foreach ($ranges as $range) { - // paid a bill in this range? - $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); - if ($journals->count() == 0) { - $unpaid->push([$bill, $range['start']]); - } - } - } - unset($bill, $range, $ranges); - - $creditCards = $accountRepository->getCreditCards(); - foreach ($creditCards as $creditCard) { - $balance = Steam::balance($creditCard, null, true); - $date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); - if ($balance < 0) { - // unpaid! create a fake bill that matches the amount. - $description = $creditCard->name; - $fakeAmount = $balance * -1; - $fakeBill = $repository->createFakeBill($description, $date, $fakeAmount); - $unpaid->push([$fakeBill, $date]); - } - } - // loop unpaid: - - /** @var Bill $entry */ - foreach ($unpaid as $entry) { - $current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; - $amount += $current; - } - - break; - case 'bills-paid': - $box = 'bills-paid'; - // these two functions are the same as the chart TODO - $bills = Auth::user()->bills()->where('active', 1)->get(); - - /** @var Bill $bill */ - foreach ($bills as $bill) { - $ranges = $repository->getRanges($bill, $start, $end); - - foreach ($ranges as $range) { - // paid a bill in this range? - $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); - if ($count != 0) { - // TODO this only gets the first match, may be more than one. - $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); - $amount += $journal->amount; - } - - } - } - - - /** - * Find credit card accounts and possibly unpaid credit card bills. - */ - $creditCards = Auth::user()->accounts() - ->hasMetaValue('accountRole', 'ccAsset') - ->hasMetaValue('ccType', 'monthlyFull') - ->get( - [ - 'accounts.*', - 'ccType.data as ccType', - 'accountRole.data as accountRole' - ] - ); - // if the balance is not zero, the monthly payment is still underway. - /** @var Account $creditCard */ - foreach ($creditCards as $creditCard) { - $balance = Steam::balance($creditCard, null, true); - if ($balance == 0) { - // find a transfer TO the credit card which should account for - // anything paid. If not, the CC is not yet used. - $transactions = $creditCard->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->before($end)->after($start)->get(); - if ($transactions->count() > 0) { - /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $journal = $transaction->transactionJournal; - if ($journal->transactionType->type == 'Transfer') { - $amount += floatval($transaction->amount); - } - } - } - } - } - break; + } } - return Response::json(['box' => $box, 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); + /** + * Find credit card accounts and possibly unpaid credit card bills. + */ + $creditCards = $accountRepository->getCreditCards(); + // if the balance is not zero, the monthly payment is still underway. + /** @var Account $creditCard */ + foreach ($creditCards as $creditCard) { + $balance = Steam::balance($creditCard, null, true); + if ($balance == 0) { + // find a transfer TO the credit card which should account for + // anything paid. If not, the CC is not yet used. + $transactions = $creditCard->transactions() + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->before($end)->after($start)->get(); + if ($transactions->count() > 0) { + /** @var Transaction $transaction */ + foreach ($transactions as $transaction) { + $journal = $transaction->transactionJournal; + if ($journal->transactionType->type == 'Transfer') { + $amount += floatval($transaction->amount); + } + } + } + } + } + + return Response::json(['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); + } + + /** + * @param BillRepositoryInterface $repository + * @param AccountRepositoryInterface $accountRepository + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) + { + $start = Session::get('start'); + $end = Session::get('end'); + $amount = 0; + + $bills = $repository->getActiveBills(); + $unpaid = new Collection; // bills + + /** @var Bill $bill */ + foreach ($bills as $bill) { + $ranges = $repository->getRanges($bill, $start, $end); + + foreach ($ranges as $range) { + // paid a bill in this range? + $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); + if ($journals->count() == 0) { + $unpaid->push([$bill, $range['start']]); + } + } + } + unset($bill, $range, $ranges); + + $creditCards = $accountRepository->getCreditCards(); + foreach ($creditCards as $creditCard) { + $balance = Steam::balance($creditCard, null, true); + $date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); + if ($balance < 0) { + // unpaid! create a fake bill that matches the amount. + $description = $creditCard->name; + $fakeAmount = $balance * -1; + $fakeBill = $repository->createFakeBill($description, $date, $fakeAmount); + $unpaid->push([$fakeBill, $date]); + } + } + // loop unpaid: + + /** @var Bill $entry */ + foreach ($unpaid as $entry) { + $current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; + $amount += $current; + } + + return Response::json(['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); + } + + /** + * @param ReportQueryInterface $reportQuery + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function boxIn(ReportQueryInterface $reportQuery) + { + $start = Session::get('start'); + $end = Session::get('end'); + $amount = 0; + + $set = $reportQuery->incomeByPeriod($start, $end, true); + foreach ($set as $entry) { + $amount += $entry->queryAmount; + } + + return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); + } + + /** + * @param ReportQueryInterface $reportQuery + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function boxOut(ReportQueryInterface $reportQuery) + { + $start = Session::get('start'); + $end = Session::get('end'); + $amount = 0; + + $set = $reportQuery->journalsByExpenseAccount($start, $end, true); + + foreach ($set as $entry) { + $amount += $entry->queryAmount; + } + + return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); } /** diff --git a/app/Http/routes.php b/app/Http/routes.php index 890337b1cd..274cc21d5a 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -245,7 +245,10 @@ Route::group( Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']); Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']); Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']); - Route::get('/json/box', ['uses' => 'JsonController@box', 'as' => 'json.box']); + Route::get('/json/box/in', ['uses' => 'JsonController@boxIn', 'as' => 'json.box.in']); + Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']); + Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']); + Route::get('/json/box/bills-paid', ['uses' => 'JsonController@boxBillsPaid', 'as' => 'json.box.unpaid']); Route::get('/json/show-shared-reports', 'JsonController@showSharedReports'); Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals'); Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports'); diff --git a/public/js/index.js b/public/js/index.js index bc4148eac5..89639a78ed 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -10,11 +10,11 @@ function drawChart() { } function getBoxAmounts() { - var boxes = ['in', 'out','bills-unpaid','bills-paid']; + var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid']; for (x in boxes) { var box = boxes[x]; - $.getJSON('/json/box', {box: box}).success(function (data) { - if(data.amount_raw != 0) { + $.getJSON('/json/box/' + box).success(function (data) { + if (data.amount_raw != 0) { $('#box-' + data.box).html(data.amount); } }).fail(function () { From 5c06b45eb16cace747db8d7d4230d45a9ce56e4e Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 07:32:11 +0200 Subject: [PATCH 32/66] Code cleanup. --- app/Http/Controllers/JsonController.php | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index c093515637..02b529df7d 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -37,7 +37,7 @@ class JsonController extends Controller $amount = 0; // these two functions are the same as the chart TODO - $bills = Auth::user()->bills()->where('active', 1)->get(); + $bills = $repository->getActiveBills(); /** @var Bill $bill */ foreach ($bills as $bill) { @@ -45,15 +45,14 @@ class JsonController extends Controller foreach ($ranges as $range) { // paid a bill in this range? - $count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count(); - if ($count != 0) { - // TODO this only gets the first match, may be more than one. - $journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first(); + $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); + foreach ($journals as $journal) { $amount += $journal->amount; } } } + unset($journals, $journal); /** @@ -67,17 +66,11 @@ class JsonController extends Controller if ($balance == 0) { // find a transfer TO the credit card which should account for // anything paid. If not, the CC is not yet used. - $transactions = $creditCard->transactions() - ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->before($end)->after($start)->get(); - if ($transactions->count() > 0) { - /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $journal = $transaction->transactionJournal; - if ($journal->transactionType->type == 'Transfer') { - $amount += floatval($transaction->amount); - } - } + $journals = $accountRepository->getTransfersInRange($creditCard, $start, $end); + foreach ($journals as $journal) { + $amount += floatval($journal->amount); + + } } } From f6999f355b854e9f6e737be9f502e559dfd18601 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 12:27:56 +0200 Subject: [PATCH 33/66] Some foreach loop cleaning up. --- app/Http/Controllers/JsonController.php | 41 ++++-------------------- app/Repositories/Bill/BillRepository.php | 14 ++------ 2 files changed, 9 insertions(+), 46 deletions(-) diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 02b529df7d..2ec220a00d 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -45,15 +45,10 @@ class JsonController extends Controller foreach ($ranges as $range) { // paid a bill in this range? - $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); - foreach ($journals as $journal) { - $amount += $journal->amount; - } - + $amount += $repository->getJournalsInRange($bill, $range['start'], $range['end'])->sum('amount'); } } - unset($journals, $journal); - + unset($ranges, $bill, $range, $bills); /** * Find credit card accounts and possibly unpaid credit card bills. @@ -66,12 +61,7 @@ class JsonController extends Controller if ($balance == 0) { // find a transfer TO the credit card which should account for // anything paid. If not, the CC is not yet used. - $journals = $accountRepository->getTransfersInRange($creditCard, $start, $end); - foreach ($journals as $journal) { - $amount += floatval($journal->amount); - - - } + $amount += $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount'); } } @@ -86,26 +76,22 @@ class JsonController extends Controller */ public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) { - $start = Session::get('start'); - $end = Session::get('end'); $amount = 0; - $bills = $repository->getActiveBills(); $unpaid = new Collection; // bills /** @var Bill $bill */ foreach ($bills as $bill) { - $ranges = $repository->getRanges($bill, $start, $end); + $ranges = $repository->getRanges($bill, clone Session::get('start'), clone Session::get('end')); foreach ($ranges as $range) { - // paid a bill in this range? $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); if ($journals->count() == 0) { $unpaid->push([$bill, $range['start']]); } } } - unset($bill, $range, $ranges); + unset($bill, $bills, $range, $ranges); $creditCards = $accountRepository->getCreditCards(); foreach ($creditCards as $creditCard) { @@ -119,8 +105,6 @@ class JsonController extends Controller $unpaid->push([$fakeBill, $date]); } } - // loop unpaid: - /** @var Bill $entry */ foreach ($unpaid as $entry) { $current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; @@ -139,12 +123,7 @@ class JsonController extends Controller { $start = Session::get('start'); $end = Session::get('end'); - $amount = 0; - - $set = $reportQuery->incomeByPeriod($start, $end, true); - foreach ($set as $entry) { - $amount += $entry->queryAmount; - } + $amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount'); return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); } @@ -158,13 +137,7 @@ class JsonController extends Controller { $start = Session::get('start'); $end = Session::get('end'); - $amount = 0; - - $set = $reportQuery->journalsByExpenseAccount($start, $end, true); - - foreach ($set as $entry) { - $amount += $entry->queryAmount; - } + $amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount'); return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); } diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index c6b7bacb05..611e438dbe 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -62,12 +62,7 @@ class BillRepository implements BillRepositoryInterface public function getActiveBills() { /** @var Collection $set */ - $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get(); - $set->sort( - function (Bill $bill) { - return $bill->name; - } - ); + $set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get()->sortBy('name'); return $set; } @@ -78,12 +73,7 @@ class BillRepository implements BillRepositoryInterface public function getBills() { /** @var Collection $set */ - $set = Auth::user()->bills()->orderBy('name', 'ASC')->get(); - $set->sort( - function (Bill $bill) { - return $bill->name; - } - ); + $set = Auth::user()->bills()->orderBy('name', 'ASC')->get()->sortBy('name'); return $set; } From 3e01daa172948c941c3087073c6affcd338ff817 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 12:36:17 +0200 Subject: [PATCH 34/66] Query & loop optimizations. --- app/Helpers/Report/ReportHelper.php | 6 +-- app/Helpers/Report/ReportQuery.php | 10 +---- app/Helpers/Report/ReportQueryInterface.php | 2 +- .../Controllers/GoogleChartController.php | 43 ++++++------------- 4 files changed, 17 insertions(+), 44 deletions(-) diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index b968994367..40bd302e40 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -73,10 +73,8 @@ class ReportHelper implements ReportHelperInterface // find transactions to shared asset accounts, which are without a budget by default: // which is only relevant when shared asset accounts are hidden. if ($showSharedReports === false) { - $transfers = $query->sharedExpenses($start, $end); - foreach ($transfers as $transfer) { - $budgets[0]['spent'] += floatval($transfer->amount) * -1; - } + $transfers = $query->sharedExpenses($start, $end)->sum('queryAmount'); + $budgets[0]['spent'] += floatval($transfers) * -1; } return $budgets; diff --git a/app/Helpers/Report/ReportQuery.php b/app/Helpers/Report/ReportQuery.php index 8b8f2728ee..f2ab84ea62 100644 --- a/app/Helpers/Report/ReportQuery.php +++ b/app/Helpers/Report/ReportQuery.php @@ -111,17 +111,11 @@ class ReportQuery implements ReportQueryInterface * @param Carbon $start * @param Carbon $end * - * @return Collection + * @return float */ public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end) { - $set = $this->balancedTransactionsList($account, $start, $end); - $sum = 0; - foreach ($set as $entry) { - $sum += floatval($entry->amount); - } - - return $sum; + return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount')); } /** diff --git a/app/Helpers/Report/ReportQueryInterface.php b/app/Helpers/Report/ReportQueryInterface.php index c92a46ad06..47a7857707 100644 --- a/app/Helpers/Report/ReportQueryInterface.php +++ b/app/Helpers/Report/ReportQueryInterface.php @@ -43,7 +43,7 @@ interface ReportQueryInterface * @param Carbon $start * @param Carbon $end * - * @return Collection + * @return float */ public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end); diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index f8fe729133..8b09f1aa0c 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -80,8 +80,7 @@ class GoogleChartController extends Controller $index = 1; /** @var Account $account */ foreach ($accounts as $account) { - $accountName = $account->name; - $chart->addColumn('Balance for ' . $accountName, 'number'); + $chart->addColumn('Balance for ' . $account->name, 'number'); $chart->addCertainty($index); $index++; } @@ -251,6 +250,11 @@ class GoogleChartController extends Controller $bills = $repository->getActiveBills(); $paid = new Collection; // journals. $unpaid = new Collection; // bills + // loop paid and create single entry: + $paidDescriptions = []; + $paidAmount = 0; + $unpaidDescriptions = []; + $unpaidAmount = 0; /** @var Bill $bill */ foreach ($bills as $bill) { @@ -287,11 +291,7 @@ class GoogleChartController extends Controller $paid = $paid->merge($journals); } } - // loop paid and create single entry: - $paidDescriptions = []; - $paidAmount = 0; - $unpaidDescriptions = []; - $unpaidAmount = 0; + /** @var TransactionJournal $entry */ foreach ($paid as $entry) { @@ -498,19 +498,9 @@ class GoogleChartController extends Controller while ($start < $end) { $currentEnd = clone $start; $currentEnd->endOfMonth(); - // total income: - $income = $query->incomeByPeriod($start, $currentEnd, $showSharedReports); - $incomeSum = 0; - foreach ($income as $entry) { - $incomeSum += floatval($entry->amount); - } - - // total expenses: - $expense = $query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports); - $expenseSum = 0; - foreach ($expense as $entry) { - $expenseSum += floatval($entry->amount); - } + // total income && total expenses: + $incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount')); + $expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount')); $chart->addRow(clone $start, $incomeSum, $expenseSum); $start->addMonth(); @@ -549,18 +539,9 @@ class GoogleChartController extends Controller $currentEnd = clone $start; $currentEnd->endOfMonth(); // total income: - $incomeResult = $query->incomeByPeriod($start, $currentEnd, $showSharedReports); - $incomeSum = 0; - foreach ($incomeResult as $entry) { - $incomeSum += floatval($entry->amount); - } - + $incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount')); // total expenses: - $expenseResult = $query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports); - $expenseSum = 0; - foreach ($expenseResult as $entry) { - $expenseSum += floatval($entry->amount); - } + $expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount')); $income += $incomeSum; $expense += $expenseSum; From df8976eabe195a0dc70a0de047f1b465b6b382ce Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 12:40:47 +0200 Subject: [PATCH 35/66] Journals that no longer match a bill will be removed. --- app/Repositories/Bill/BillRepository.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 611e438dbe..df997ba2c0 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -315,6 +315,12 @@ class BillRepository implements BillRepositoryInterface Log::debug('TOTAL match is true!'); $journal->bill()->associate($bill); $journal->save(); + } else { + if ((!$wordMatch || !$amountMatch) && $bill->id == $journal->bill_id) { + // if no match, but bill used to match, remove it: + $journal->bill_id = null; + $journal->save(); + } } } From 13890e32a144e4cd99f1bd9481398b4f8889867f Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 12:50:56 +0200 Subject: [PATCH 36/66] Fixed a view and a botched include. --- app/Providers/EventServiceProvider.php | 4 ++-- resources/views/reports/month.blade.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 3247c6ae2b..e19c145043 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -1,6 +1,7 @@ {{{$budget['name']}}} @endif - {!! Amount::format($budget['amount']) !!} + {!! Amount::format($budget['queryAmount']) !!} {!! Amount::format($budget['spent'],false) !!} {!! Amount::format($budget['amount'] + $budget['spent']) !!} From ca3d59dc333dad7b8e9488e7d6a68f89159e6b9d Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 12:51:58 +0200 Subject: [PATCH 37/66] Another fix. --- resources/views/reports/month.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/reports/month.blade.php b/resources/views/reports/month.blade.php index 2343be2fe8..a7a9504352 100644 --- a/resources/views/reports/month.blade.php +++ b/resources/views/reports/month.blade.php @@ -148,7 +148,7 @@ {!! Amount::format($budget['queryAmount']) !!} {!! Amount::format($budget['spent'],false) !!} - {!! Amount::format($budget['amount'] + $budget['spent']) !!} + {!! Amount::format($budget['queryAmount'] + $budget['spent']) !!} @endif @endforeach From 505aee22bb5e8972c492d4e4399a91579ff21ce1 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 14:53:22 +0200 Subject: [PATCH 38/66] Sortable categories. --- public/css/bootstrap-sortable.css | 100 ++++++++++ public/js/bootstrap-sortable.js | 209 +++++++++++++++++++++ resources/views/categories/index.blade.php | 5 + resources/views/list/categories.blade.php | 28 +-- 4 files changed, 331 insertions(+), 11 deletions(-) create mode 100644 public/css/bootstrap-sortable.css create mode 100644 public/js/bootstrap-sortable.js diff --git a/public/css/bootstrap-sortable.css b/public/css/bootstrap-sortable.css new file mode 100644 index 0000000000..7991cd2a78 --- /dev/null +++ b/public/css/bootstrap-sortable.css @@ -0,0 +1,100 @@ +table.sortable span.sign { + display: block; + position: absolute; + top: 50%; + right: 5px; + font-size: 12px; + margin-top: -10px; + color: #bfbfc1; +} + +table.sortable th:after { + display: block; + position: absolute; + top: 50%; + right: 5px; + font-size: 12px; + margin-top: -10px; + color: #bfbfc1; +} + +table.sortable th.arrow:after { + content: ''; +} + +table.sortable span.arrow, span.reversed, th.arrow.down:after, th.reversedarrow.down:after, th.arrow.up:after, th.reversedarrow.up:after { + border-style: solid; + border-width: 5px; + font-size: 0; + border-color: #ccc transparent transparent transparent; + line-height: 0; + height: 0; + width: 0; + margin-top: -2px; +} + + table.sortable span.arrow.up, th.arrow.up:after { + border-color: transparent transparent #ccc transparent; + margin-top: -7px; + } + +table.sortable span.reversed, th.reversedarrow.down:after { + border-color: transparent transparent #ccc transparent; + margin-top: -7px; +} + + table.sortable span.reversed.up, th.reversedarrow.up:after { + border-color: #ccc transparent transparent transparent; + margin-top: -2px; + } + +table.sortable span.az:before, th.az.down:after { + content: "a .. z"; +} + +table.sortable span.az.up:before, th.az.up:after { + content: "z .. a"; +} + +table.sortable th.az.nosort:after, th.AZ.nosort:after, th._19.nosort:after, th.month.nosort:after { + content: ".."; +} + +table.sortable span.AZ:before, th.AZ.down:after { + content: "A .. Z"; +} + +table.sortable span.AZ.up:before, th.AZ.up:after { + content: "Z .. A"; +} + +table.sortable span._19:before, th._19.down:after { + content: "1 .. 9"; +} + +table.sortable span._19.up:before, th._19.up:after { + content: "9 .. 1"; +} + +table.sortable span.month:before, th.month.down:after { + content: "jan .. dec"; +} + +table.sortable span.month.up:before, th.month.up:after { + content: "dec .. jan"; +} + +table.sortable thead th:not([data-defaultsort=disabled]) { + cursor: pointer; + position: relative; + top: 0; + left: 0; +} + +table.sortable thead th:hover:not([data-defaultsort=disabled]) { + background: #efefef; +} + +table.sortable thead th div.mozilla { + position: relative; +} diff --git a/public/js/bootstrap-sortable.js b/public/js/bootstrap-sortable.js new file mode 100644 index 0000000000..48bfb151be --- /dev/null +++ b/public/js/bootstrap-sortable.js @@ -0,0 +1,209 @@ +/** + * TinySort is a small script that sorts HTML elements. It sorts by text- or attribute value, or by that of one of it's children. + * @summary A nodeElement sorting script. + * @version 2.2.0 + * @license MIT/GPL + * @author Ron Valstar + * @copyright Ron Valstar + * @namespace tinysort + */ +!function (a, b) { "use strict"; function c() { return b } "function" == typeof define && define.amd ? define("tinysort", c) : a.tinysort = b }(this, function () { "use strict"; function a(a, f) { function j() { 0 === arguments.length ? s({}) : d(arguments, function (a) { s(c(a) ? { selector: a } : a) }), p = D.length } function s(a) { var b = !!a.selector, c = b && ":" === a.selector[0], d = e(a || {}, r); D.push(e({ hasSelector: b, hasAttr: !(d.attr === i || "" === d.attr), hasData: d.data !== i, hasFilter: c, sortReturnNumber: "asc" === d.order ? 1 : -1 }, d)) } function t() { d(a, function (a, b) { y ? y !== a.parentNode && (E = !1) : y = a.parentNode; var c = D[0], d = c.hasFilter, e = c.selector, f = !e || d && a.matchesSelector(e) || e && a.querySelector(e), g = f ? B : C, h = { elm: a, pos: b, posn: g.length }; A.push(h), g.push(h) }), x = B.slice(0) } function u() { B.sort(v) } function v(a, e) { var f = 0; for (0 !== q && (q = 0) ; 0 === f && p > q;) { var i = D[q], j = i.ignoreDashes ? n : m; if (d(o, function (a) { var b = a.prepare; b && b(i) }), i.sortFunction) f = i.sortFunction(a, e); else if ("rand" == i.order) f = Math.random() < .5 ? 1 : -1; else { var k = h, r = b(a, i), s = b(e, i), t = "" === r || r === g, u = "" === s || s === g; if (r === s) f = 0; else if (i.emptyEnd && (t || u)) f = t && u ? 0 : t ? 1 : -1; else { if (!i.forceStrings) { var v = c(r) ? r && r.match(j) : h, w = c(s) ? s && s.match(j) : h; if (v && w) { var x = r.substr(0, r.length - v[0].length), y = s.substr(0, s.length - w[0].length); x == y && (k = !h, r = l(v[0]), s = l(w[0])) } } f = r === g || s === g ? 0 : s > r ? -1 : r > s ? 1 : 0 } } d(o, function (a) { var b = a.sort; b && (f = b(i, k, r, s, f)) }), f *= i.sortReturnNumber, 0 === f && q++ } return 0 === f && (f = a.pos > e.pos ? 1 : -1), f } function w() { var a = B.length === A.length; E && a ? F ? B.forEach(function (a, b) { a.elm.style.order = b }) : (B.forEach(function (a) { z.appendChild(a.elm) }), y.appendChild(z)) : (B.forEach(function (a) { var b = a.elm, c = k.createElement("div"); a.ghost = c, b.parentNode.insertBefore(c, b) }), B.forEach(function (a, b) { var c = x[b].ghost; c.parentNode.insertBefore(a.elm, c), c.parentNode.removeChild(c) })) } c(a) && (a = k.querySelectorAll(a)), 0 === a.length && console.warn("No elements to sort"); var x, y, z = k.createDocumentFragment(), A = [], B = [], C = [], D = [], E = !0, F = a.length && (f === g || f.useFlex !== !1) && -1 !== getComputedStyle(a[0].parentNode, null).display.indexOf("flex"); return j.apply(i, Array.prototype.slice.call(arguments, 1)), t(), u(), w(), B.map(function (a) { return a.elm }) } function b(a, b) { var d, e = a.elm; return b.selector && (b.hasFilter ? e.matchesSelector(b.selector) || (e = i) : e = e.querySelector(b.selector)), b.hasAttr ? d = e.getAttribute(b.attr) : b.useVal ? d = e.value || e.getAttribute("value") : b.hasData ? d = e.getAttribute("data-" + b.data) : e && (d = e.textContent), c(d) && (b.cases || (d = d.toLowerCase()), d = d.replace(/\s+/g, " ")), d } function c(a) { return "string" == typeof a } function d(a, b) { for (var c, d = a.length, e = d; e--;) c = d - e - 1, b(a[c], c) } function e(a, b, c) { for (var d in b) (c || a[d] === g) && (a[d] = b[d]); return a } function f(a, b, c) { o.push({ prepare: a, sort: b, sortBy: c }) } var g, h = !1, i = null, j = window, k = j.document, l = parseFloat, m = /(-?\d+\.?\d*)\s*$/g, n = /(\d+\.?\d*)\s*$/g, o = [], p = 0, q = 0, r = { selector: i, order: "asc", attr: i, data: i, useVal: h, place: "start", returns: h, cases: h, forceStrings: h, ignoreDashes: h, sortFunction: i, useFlex: h, emptyEnd: h }; return j.Element && function (a) { a.matchesSelector = a.matchesSelector || a.mozMatchesSelector || a.msMatchesSelector || a.oMatchesSelector || a.webkitMatchesSelector || function (a) { for (var b = this, c = (b.parentNode || b.document).querySelectorAll(a), d = -1; c[++d] && c[d] != b;); return !!c[d] } }(Element.prototype), e(f, { loop: d }), e(a, { plugin: f, defaults: r }) }()); + +(function ($) { + + var $document = $(document), + signClass, + sortEngine; + + $.bootstrapSortable = function (applyLast, sign, customSort) { + + // Check if moment.js is available + var momentJsAvailable = (typeof moment !== 'undefined'); + + // Set class based on sign parameter + signClass = !sign ? "arrow" : sign; + + // Set sorting algorithm + if (customSort == 'default') + customSort = defaultSortEngine; + sortEngine = customSort || sortEngine || defaultSortEngine; + + // Set attributes needed for sorting + $('table.sortable').each(function () { + var $this = $(this); + applyLast = (applyLast === true); + $this.find('span.sign').remove(); + + // Add placeholder cells for colspans + $this.find('thead [colspan]').each(function () { + var colspan = parseFloat($(this).attr('colspan')); + for (var i = 1; i < colspan; i++) { + $(this).after(''); + } + }); + + // Add placeholder cells for rowspans + $this.find('thead [rowspan]').each(function () { + var $cell = $(this); + var rowspan = parseFloat($cell.attr('rowspan')); + for (var i = 1; i < rowspan; i++) { + var parentRow = $cell.parent('tr'); + var nextRow = parentRow.next('tr'); + var index = parentRow.children().index($cell); + nextRow.children().eq(index).before(''); + } + }); + + // Set indexes to header cells + $this.find('thead tr').each(function (rowIndex) { + $(this).find('th').each(function (columnIndex) { + var $this = $(this); + $this.addClass('nosort').removeClass('up down'); + $this.attr('data-sortcolumn', columnIndex); + $this.attr('data-sortkey', columnIndex + '-' + rowIndex); + }); + }); + + // Cleanup placeholder cells + $this.find('thead .rowspan-compensate, .colspan-compensate').remove(); + + // Initialize sorting values + $this.find('td').each(function () { + var $this = $(this); + if ($this.attr('data-dateformat') !== undefined && momentJsAvailable) { + $this.attr('data-value', moment($this.text(), $this.attr('data-dateformat')).format('YYYY/MM/DD/HH/mm/ss')); + } + else { + $this.attr('data-value') === undefined && $this.attr('data-value', $this.text()); + } + }); + + var context = lookupSortContext($this), + bsSort = context.bsSort; + + $this.find('thead th[data-defaultsort!="disabled"]').each(function (index) { + var $this = $(this); + var $sortTable = $this.closest('table.sortable'); + $this.data('sortTable', $sortTable); + var sortKey = $this.attr('data-sortkey'); + var thisLastSort = applyLast ? context.lastSort : -1; + bsSort[sortKey] = applyLast ? bsSort[sortKey] : $this.attr('data-defaultsort'); + if (bsSort[sortKey] !== undefined && (applyLast === (sortKey === thisLastSort))) { + bsSort[sortKey] = bsSort[sortKey] === 'asc' ? 'desc' : 'asc'; + doSort($this, $sortTable); + } + }); + $this.trigger('sorted'); + }); + }; + + // Add click event to table header + $document.on('click', 'table.sortable thead th[data-defaultsort!="disabled"]', function (e) { + var $this = $(this), $table = $this.data('sortTable') || $this.closest('table.sortable'); + $table.trigger('before-sort'); + doSort($this, $table); + $table.trigger('sorted'); + }); + + // Look up sorting data appropriate for the specified table (jQuery element). + // This allows multiple tables on one page without collisions. + function lookupSortContext($table) { + var context = $table.data("bootstrap-sortable-context"); + if (context === undefined) { + context = { bsSort: [], lastSort: undefined }; + $table.find('thead th[data-defaultsort!="disabled"]').each(function (index) { + var $this = $(this); + var sortKey = $this.attr('data-sortkey'); + context.bsSort[sortKey] = $this.attr('data-defaultsort'); + if (context.bsSort[sortKey] !== undefined) { + context.lastSort = sortKey; + } + }); + $table.data("bootstrap-sortable-context", context); + } + return context; + } + + function defaultSortEngine(rows, sortingParams) { + tinysort(rows, sortingParams); + } + + // Sorting mechanism separated + function doSort($this, $table) { + var sortColumn = parseFloat($this.attr('data-sortcolumn')), + context = lookupSortContext($table), + bsSort = context.bsSort; + + var colspan = $this.attr('colspan'); + if (colspan) { + var mainSort = parseFloat($this.data('mainsort')) || 0; + var rowIndex = parseFloat($this.data('sortkey').split('-').pop()); + + // If there is one more row in header, delve deeper + if ($table.find('thead tr').length - 1 > rowIndex) { + doSort($table.find('[data-sortkey="' + (sortColumn + mainSort) + '-' + (rowIndex + 1) + '"]'), $table); + return; + } + // Otherwise, just adjust the sortColumn + sortColumn = sortColumn + mainSort; + } + + var localSignClass = $this.attr('data-defaultsign') || signClass; + + // update arrow icon + $table.find('th').each(function () { + $(this).removeClass('up').removeClass('down').addClass('nosort'); + }); + + if ($.browser.mozilla) { + var moz_arrow = $table.find('div.mozilla'); + if (moz_arrow !== undefined) { + moz_arrow.find('.sign').remove(); + moz_arrow.parent().html(moz_arrow.html()); + } + $this.wrapInner('
'); + $this.children().eq(0).append(''); + } + else { + $table.find('span.sign').remove(); + $this.append(''); + } + + // sort direction + var sortKey = $this.attr('data-sortkey'); + var initialDirection = $this.attr('data-firstsort') !== 'desc' ? 'desc' : 'asc'; + + context.lastSort = sortKey; + bsSort[sortKey] = (bsSort[sortKey] || initialDirection) === 'asc' ? 'desc' : 'asc'; + if (bsSort[sortKey] === 'desc') { + $this.find('span.sign').addClass('up'); + $this.addClass('up').removeClass('down nosort'); + } else { + $this.addClass('down').removeClass('up nosort'); + } + + // sort rows + var rows = $table.children('tbody').children('tr'); + sortEngine(rows, { selector: 'td:nth-child(' + (sortColumn + 1) + ')', order: bsSort[sortKey], data: 'value' }); + + // add class to sorted column cells + $table.find('td.sorted, th.sorted').removeClass('sorted'); + rows.find('td:eq(' + sortColumn + ')').addClass('sorted'); + $this.addClass('sorted'); + } + + // jQuery 1.9 removed this object + if (!$.browser) { + $.browser = { chrome: false, mozilla: false, opera: false, msie: false, safari: false }; + var ua = navigator.userAgent; + $.each($.browser, function (c) { + $.browser[c] = ((new RegExp(c, 'i').test(ua))) ? true : false; + if ($.browser.mozilla && c === 'mozilla') { $.browser.mozilla = ((new RegExp('firefox', 'i').test(ua))) ? true : false; } + if ($.browser.chrome && c === 'safari') { $.browser.safari = false; } + }); + } + + // Initialise on DOM ready + $($.bootstrapSortable); + +}(jQuery)); diff --git a/resources/views/categories/index.blade.php b/resources/views/categories/index.blade.php index fbb537b6c0..ca6dfff078 100644 --- a/resources/views/categories/index.blade.php +++ b/resources/views/categories/index.blade.php @@ -27,6 +27,10 @@
@stop +@section('styles') + +@stop + @section('scripts') + @stop diff --git a/resources/views/list/categories.blade.php b/resources/views/list/categories.blade.php index c9fb5d2f4b..7fc193c5ff 100644 --- a/resources/views/list/categories.blade.php +++ b/resources/views/list/categories.blade.php @@ -1,9 +1,12 @@ - - - - - - +
 NameLast activity
+ + + + + + + + @@ -20,13 +23,16 @@ - + @else + + + @endif @endforeach +
 NameLast activity
  Without a category {{{$category->name}}} - @if($category->lastActivity) + @if($category->lastActivity) + {{$category->lastActivity->format('jS F Y')}} - @else + Never - @endif -
From 651a4fd3ccb2207efa7b61847001c6928e05181c Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:01:42 +0200 Subject: [PATCH 39/66] Sortable accounts. --- app/Http/Controllers/AccountController.php | 13 ++----- app/Http/Controllers/BillController.php | 2 +- .../Account/AccountRepository.php | 16 ++------- .../Account/AccountRepositoryInterface.php | 3 +- resources/views/accounts/index.blade.php | 10 ++++-- resources/views/list/accounts.blade.php | 35 ++++++++++--------- 6 files changed, 32 insertions(+), 47 deletions(-) diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index a0be3ef501..e5e2e8a919 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -7,7 +7,6 @@ use FireflyIII\Http\Requests; use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use Illuminate\Pagination\LengthAwarePaginator; use Input; use Redirect; use Session; @@ -123,18 +122,14 @@ class AccountController extends Controller $subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what); $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); $types = Config::get('firefly.accountTypesByIdentifier.' . $what); - $size = 50; - $page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page')); - $set = $repository->getAccounts($types, $page); - $total = $repository->countAccounts($types); - + $accounts = $repository->getAccounts($types); // last activity: /** * HERE WE ARE */ $start = clone Session::get('start', Carbon::now()->startOfMonth()); $start->subDay(); - $set->each( + $accounts->each( function (Account $account) use ($start, $repository) { $account->lastActivityDate = $repository->getLastActivity($account); $account->startBalance = Steam::balance($account, $start); @@ -142,10 +137,6 @@ class AccountController extends Controller } ); - $accounts = new LengthAwarePaginator($set, $total, $size, $page); - $accounts->setPath(route('accounts.index', $what)); - - return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts')); } diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index f269af2954..d605b3d0ba 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -45,7 +45,7 @@ class BillController extends Controller $expense = null; // get users expense accounts: - $accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'), -1); + $accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense')); foreach ($matches as $match) { $match = strtolower($match); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 50e4004f15..ba5a88fea7 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -53,26 +53,16 @@ class AccountRepository implements AccountRepositoryInterface /** * @param array $types - * @param int $page * * @return Collection */ - public function getAccounts(array $types, $page) + public function getAccounts(array $types) { - $query = Auth::user()->accounts()->with( + $result = Auth::user()->accounts()->with( ['accountmeta' => function (HasMany $query) { $query->where('name', 'accountRole'); }] - )->accountTypeIn($types)->orderBy('accounts.name', 'ASC'); - - if ($page == -1) { - $result = $query->get(['accounts.*']); - } else { - $size = 50; - $offset = ($page - 1) * $size; - - $result = $query->take($size)->offset($offset)->get(['accounts.*']); - } + )->accountTypeIn($types)->orderBy('accounts.name', 'ASC')->get(['accounts.*'])->sortBy('name'); return $result; } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index a8dad3c2eb..0d533a0970 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -33,11 +33,10 @@ interface AccountRepositoryInterface /** * @param array $types - * @param int $page * * @return mixed */ - public function getAccounts(array $types, $page); + public function getAccounts(array $types); /** * @param TransactionJournal $journal diff --git a/resources/views/accounts/index.blade.php b/resources/views/accounts/index.blade.php index 09cdafce86..8f52cbd9ca 100644 --- a/resources/views/accounts/index.blade.php +++ b/resources/views/accounts/index.blade.php @@ -22,13 +22,16 @@ -
- @include('list.accounts') -
+ @include('list.accounts') @stop + +@section('styles') + +@stop + @section('scripts') + @stop diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 11f60e0eea..2755b01252 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -1,18 +1,18 @@ -@if(is_object($accounts) && method_exists($accounts, 'render')) - {!! $accounts->render() !!} -@endif - +
+ - + @if(isset($what) && $what == 'asset') @endif - + + + @foreach($accounts as $account) @endif - - + - @else - Never + @endif - - @endforeach -
   NameRoleCurrent balance ActiveLast activityLast activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}}
@@ -31,29 +31,30 @@ @endforeach {!! Amount::format(Steam::balance($account)) !!} + + {!! Amount::format($balance) !!} @if($account->active) @else @endif @if($account->lastActivityDate) - {{{$account->lastActivityDate->format('j F Y')}}} + + {{{$account->lastActivityDate->format('j F Y')}}} + + Never + + {!! Amount::format($account->endBalance - $account->startBalance) !!}
-@if(is_object($accounts) && method_exists($accounts, 'render')) - {!! $accounts->render() !!} -@endif + + \ No newline at end of file From 714c13bdbfc22bd440f8550babdd690fd9fea6d9 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:04:16 +0200 Subject: [PATCH 40/66] Include moment.js --- resources/views/accounts/index.blade.php | 1 + resources/views/categories/index.blade.php | 1 + 2 files changed, 2 insertions(+) diff --git a/resources/views/accounts/index.blade.php b/resources/views/accounts/index.blade.php index 8f52cbd9ca..fe7572c707 100644 --- a/resources/views/accounts/index.blade.php +++ b/resources/views/accounts/index.blade.php @@ -42,6 +42,7 @@ + @stop diff --git a/resources/views/categories/index.blade.php b/resources/views/categories/index.blade.php index ca6dfff078..e0d009f93a 100644 --- a/resources/views/categories/index.blade.php +++ b/resources/views/categories/index.blade.php @@ -39,6 +39,7 @@ + @stop From b53aaf7ddef9bfda736960599630d8c9aee48a7e Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:06:10 +0200 Subject: [PATCH 41/66] Fixed sort format. --- resources/views/list/accounts.blade.php | 2 +- resources/views/list/categories.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 2755b01252..8bb374c635 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} diff --git a/resources/views/list/categories.blade.php b/resources/views/list/categories.blade.php index 7fc193c5ff..3190591d56 100644 --- a/resources/views/list/categories.blade.php +++ b/resources/views/list/categories.blade.php @@ -3,7 +3,7 @@   Name - Last activity + Last activity From 967b0b493b72096c0f9c4bca170719432db83758 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:07:42 +0200 Subject: [PATCH 42/66] Switched dates around. --- resources/views/list/accounts.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 8bb374c635..e0d01916c3 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} @@ -41,7 +41,7 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else From 1ee741460da6c0c4439c79571975e4265e270318 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:09:48 +0200 Subject: [PATCH 43/66] Updated empty entries as well. --- resources/views/list/accounts.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index e0d01916c3..1e6ba40b00 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -45,7 +45,7 @@ {{{$account->lastActivityDate->format('j F Y')}}} @else - + Never @endif From 7b6723e9a29fb718fc6bb1a3696110fbd346d90e Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:10:29 +0200 Subject: [PATCH 44/66] Update date format. --- resources/views/list/accounts.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 1e6ba40b00..a3bf9c542a 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} From d3bbb6fb1f07d3143df80bb7210123d0f793b465 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:11:19 +0200 Subject: [PATCH 45/66] Removed date value. --- resources/views/list/accounts.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index a3bf9c542a..b8eaff6bc2 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} @@ -41,7 +41,7 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else From 2a72cce3b749566deb88d0f74c1b4dd37f72e1d3 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 15:11:45 +0200 Subject: [PATCH 46/66] Included date format. --- resources/views/list/accounts.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index b8eaff6bc2..87b7065433 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -41,7 +41,7 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else From 8d9561d7a5487c16d535f6cbcbe4ed7afe28433c Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 18:45:01 +0200 Subject: [PATCH 47/66] Removed data-value. --- resources/views/list/accounts.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 87b7065433..1842783530 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -41,11 +41,11 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else - + Never @endif From c43439bb68e94b0a414ddc99402b0c88c9717d85 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 18:47:37 +0200 Subject: [PATCH 48/66] Test for date. --- resources/views/list/accounts.blade.php | 4 ++-- resources/views/list/categories.blade.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 1842783530..1942217ab8 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} @@ -41,7 +41,7 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else diff --git a/resources/views/list/categories.blade.php b/resources/views/list/categories.blade.php index 3190591d56..717214af0d 100644 --- a/resources/views/list/categories.blade.php +++ b/resources/views/list/categories.blade.php @@ -3,7 +3,7 @@   Name - Last activity + Last activity @@ -24,7 +24,7 @@ {{{$category->name}}} @if($category->lastActivity) - + {{$category->lastActivity->format('jS F Y')}} @else From 38b27fec92d16c6ab448b4b1662f99ea869fa219 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 18:49:57 +0200 Subject: [PATCH 49/66] Without moment.js --- resources/views/accounts/index.blade.php | 1 - resources/views/categories/index.blade.php | 1 - resources/views/list/accounts.blade.php | 2 +- resources/views/list/categories.blade.php | 2 +- 4 files changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/views/accounts/index.blade.php b/resources/views/accounts/index.blade.php index fe7572c707..8f52cbd9ca 100644 --- a/resources/views/accounts/index.blade.php +++ b/resources/views/accounts/index.blade.php @@ -42,7 +42,6 @@ - @stop diff --git a/resources/views/categories/index.blade.php b/resources/views/categories/index.blade.php index e0d009f93a..ca6dfff078 100644 --- a/resources/views/categories/index.blade.php +++ b/resources/views/categories/index.blade.php @@ -39,7 +39,6 @@ - @stop diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 1942217ab8..7ff9b5fc7c 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -8,7 +8,7 @@ @endif Current balance Active - Last activity + Last activity Balance difference between {{Session::get('start')->format('jS F Y')}} and {{Session::get('end')->format('jS F Y')}} diff --git a/resources/views/list/categories.blade.php b/resources/views/list/categories.blade.php index 717214af0d..b7c1bd1c2d 100644 --- a/resources/views/list/categories.blade.php +++ b/resources/views/list/categories.blade.php @@ -3,7 +3,7 @@   Name - Last activity + Last activity From 6157d82a0b7bcc7ecf7b45a4964e369bad424db5 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 18:52:03 +0200 Subject: [PATCH 50/66] time format --- resources/views/list/accounts.blade.php | 4 ++-- resources/views/list/categories.blade.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/views/list/accounts.blade.php b/resources/views/list/accounts.blade.php index 7ff9b5fc7c..12431be966 100644 --- a/resources/views/list/accounts.blade.php +++ b/resources/views/list/accounts.blade.php @@ -41,11 +41,11 @@ @endif @if($account->lastActivityDate) - + {{{$account->lastActivityDate->format('j F Y')}}} @else - + Never @endif diff --git a/resources/views/list/categories.blade.php b/resources/views/list/categories.blade.php index b7c1bd1c2d..2c5b166c43 100644 --- a/resources/views/list/categories.blade.php +++ b/resources/views/list/categories.blade.php @@ -24,11 +24,11 @@ {{{$category->name}}} @if($category->lastActivity) - + {{$category->lastActivity->format('jS F Y')}} @else - + Never @endif From c37e9a446776b8b6b1339342eb55dbeeeb6b73e1 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 11 Apr 2015 19:59:41 +0200 Subject: [PATCH 51/66] Covered the JSON controller. --- app/Http/Controllers/JsonController.php | 40 ++-- .../Journal/JournalRepository.php | 21 +- .../Journal/JournalRepositoryInterface.php | 29 ++- tests/controllers/JsonControllerTest.php | 206 ++++++++++++++++++ 4 files changed, 270 insertions(+), 26 deletions(-) create mode 100644 tests/controllers/JsonControllerTest.php diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 2ec220a00d..abbc81b0b4 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -10,6 +10,8 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Repositories\Category\CategoryRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Support\Collection; use Preferences; use Response; @@ -32,8 +34,8 @@ class JsonController extends Controller */ public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) { - $start = Session::get('start'); - $end = Session::get('end'); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); $amount = 0; // these two functions are the same as the chart TODO @@ -77,12 +79,14 @@ class JsonController extends Controller public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) { $amount = 0; + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); $bills = $repository->getActiveBills(); $unpaid = new Collection; // bills /** @var Bill $bill */ foreach ($bills as $bill) { - $ranges = $repository->getRanges($bill, clone Session::get('start'), clone Session::get('end')); + $ranges = $repository->getRanges($bill, $start, $end); foreach ($ranges as $range) { $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); @@ -121,8 +125,8 @@ class JsonController extends Controller */ public function boxIn(ReportQueryInterface $reportQuery) { - $start = Session::get('start'); - $end = Session::get('end'); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); $amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount'); return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); @@ -135,8 +139,8 @@ class JsonController extends Controller */ public function boxOut(ReportQueryInterface $reportQuery) { - $start = Session::get('start'); - $end = Session::get('end'); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); $amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount'); return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); @@ -147,13 +151,14 @@ class JsonController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function categories() + public function categories(CategoryRepositoryInterface $repository) { - $list = Auth::user()->categories()->orderBy('name', 'ASC')->get(); + $list = $repository->getCategories(); $return = []; foreach ($list as $entry) { $return[] = $entry->name; } + sort($return); return Response::json($return); } @@ -163,9 +168,9 @@ class JsonController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function expenseAccounts() + public function expenseAccounts(AccountRepositoryInterface $accountRepository) { - $list = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Expense account', 'Beneficiary account'])->get(); + $list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']); $return = []; foreach ($list as $entry) { $return[] = $entry->name; @@ -178,9 +183,9 @@ class JsonController extends Controller /** * @return \Illuminate\Http\JsonResponse */ - public function revenueAccounts() + public function revenueAccounts(AccountRepositoryInterface $accountRepository) { - $list = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']); + $list = $accountRepository->getAccounts(['Revenue account']); $return = []; foreach ($list as $entry) { $return[] = $entry->name; @@ -218,13 +223,12 @@ class JsonController extends Controller * * @return \Symfony\Component\HttpFoundation\Response */ - public function transactionJournals($what) + public function transactionJournals($what, JournalRepositoryInterface $repository) { $descriptions = []; - $dbType = TransactionType::whereType($what)->first(); - $journals = Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id) - ->orderBy('id', 'DESC')->take(50) - ->get(); + $dbType = $repository->getTransactionType($what); + + $journals = $repository->getJournalsOfType($dbType); foreach ($journals as $j) { $descriptions[] = $j->description; } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index eb1c8db19d..f8732d7867 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -62,6 +62,26 @@ class JournalRepository implements JournalRepositoryInterface return $journal->transactions()->first()->account_id; } + /** + * @param TransactionType $dbType + * + * @return Collection + */ + public function getJournalsOfType(TransactionType $dbType) + { + return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get(); + } + + /** + * @param $type + * + * @return TransactionType + */ + public function getTransactionType($type) + { + return TransactionType::whereType($type)->first(); + } + /** * @param string $query * @param TransactionJournal $journal @@ -289,5 +309,4 @@ class JournalRepository implements JournalRepositoryInterface return [$from, $to]; } - } diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index cbe44671a5..02febb7b96 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -4,6 +4,7 @@ namespace FireflyIII\Repositories\Journal; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; use Illuminate\Support\Collection; /** @@ -13,6 +14,13 @@ use Illuminate\Support\Collection; */ interface JournalRepositoryInterface { + /** + * Get users first transaction journal + * + * @return TransactionJournal + */ + public function first(); + /** * * Get the account_id, which is the asset account that paid for the transaction. @@ -23,6 +31,13 @@ interface JournalRepositoryInterface */ public function getAssetAccount(TransactionJournal $journal); + /** + * @param TransactionType $dbType + * + * @return Collection + */ + public function getJournalsOfType(TransactionType $dbType); + /** * @param string $query * @param TransactionJournal $journal @@ -31,6 +46,13 @@ interface JournalRepositoryInterface */ public function searchRelated($query, TransactionJournal $journal); + + /** + * @param $type + * + * @return TransactionType + */ + public function getTransactionType($type); /** * @param array $data * @@ -45,11 +67,4 @@ interface JournalRepositoryInterface * @return mixed */ public function update(TransactionJournal $journal, array $data); - - /** - * Get users first transaction journal - * - * @return TransactionJournal - */ - public function first(); } diff --git a/tests/controllers/JsonControllerTest.php b/tests/controllers/JsonControllerTest.php new file mode 100644 index 0000000000..4a902079f6 --- /dev/null +++ b/tests/controllers/JsonControllerTest.php @@ -0,0 +1,206 @@ + new Carbon, 'end' => new Carbon]]; + $this->be($bill->user); + + $bills = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $accounts = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + + // mock! + $bills->shouldReceive('getActiveBills')->andReturn($collection); + $bills->shouldReceive('getRanges')->andReturn($ranges); + $bills->shouldReceive('getJournalsInRange')->andReturn(new Collection); + $accounts->shouldReceive('getCreditCards')->andReturn($ccs); + $accounts->shouldReceive('getTransfersInRange')->andReturn(new Collection); + Amount::shouldReceive('format')->andReturn('xx'); + Steam::shouldReceive('balance')->andReturn(0); + + + $this->call('GET', '/json/box/bills-paid'); + $this->assertResponseOk(); + + } + + public function testBoxBillsUnpaid() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $cc = FactoryMuffin::create('FireflyIII\Models\Account'); + $ccs = new Collection([$cc]); + $collection = new Collection([$bill]); + $ranges = [['start' => new Carbon, 'end' => new Carbon]]; + $this->be($bill->user); + + $bills = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $accounts = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + + // mock! + $bills->shouldReceive('getActiveBills')->andReturn($collection); + $bills->shouldReceive('getRanges')->andReturn($ranges); + $bills->shouldReceive('getJournalsInRange')->andReturn(new Collection); + $bills->shouldReceive('createFakeBill')->andReturn($bill); + $accounts->shouldReceive('getCreditCards')->andReturn($ccs); + Amount::shouldReceive('format')->andReturn('xx'); + Steam::shouldReceive('balance')->andReturn(-1); + + $this->call('GET', '/json/box/bills-unpaid'); + $this->assertResponseOk(); + } + + public function testBoxIn() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Helpers\Report\ReportQueryInterface'); + $repository->shouldReceive('incomeByPeriod')->andReturn(new Collection); + Amount::shouldReceive('format')->andReturn('xx'); + + $this->call('GET', '/json/box/in'); + $this->assertResponseOk(); + } + + public function testBoxOut() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Helpers\Report\ReportQueryInterface'); + $repository->shouldReceive('journalsByExpenseAccount')->andReturn(new Collection); + Amount::shouldReceive('format')->andReturn('xx'); + + $this->call('GET', '/json/box/out'); + $this->assertResponseOk(); + } + + public function testCategories() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + $categories = new Collection([$category]); + + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('getCategories')->andReturn($categories); + + $this->call('GET', '/json/categories'); + $this->assertResponseOk(); + } + + public function testExpenseAccounts() + { + $account = FactoryMuffin::create('FireflyIII\Models\Account'); + $this->be($account->user); + $accounts = new Collection([$account]); + + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getAccounts')->with(['Expense account', 'Beneficiary account'])->andReturn($accounts); + + $this->call('GET', '/json/expense-accounts'); + $this->assertResponseOk(); + } + + public function testRevenueAccounts() + { + $account = FactoryMuffin::create('FireflyIII\Models\Account'); + $this->be($account->user); + $accounts = new Collection([$account]); + + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getAccounts')->with(['Revenue account'])->andReturn($accounts); + + $this->call('GET', '/json/revenue-accounts'); + $this->assertResponseOk(); + } + + public function testSetSharedReports() + { + $pref = FactoryMuffin::create('FireflyIII\Models\Preference'); + $pref->data = false; + $pref->save(); + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + Preferences::shouldReceive('get')->withArgs(['showSharedReports', false])->andReturn($pref); + Preferences::shouldReceive('set')->withArgs(['showSharedReports', true]); + + $this->call('GET', '/json/show-shared-reports/set'); + $this->assertResponseOk(); + } + + + public function testShowSharedReports() + { + $pref = FactoryMuffin::create('FireflyIII\Models\Preference'); + $pref->data = false; + $pref->save(); + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + Preferences::shouldReceive('get')->withArgs(['showSharedReports', false])->andReturn($pref); + + + $this->call('GET', '/json/show-shared-reports'); + $this->assertResponseOk(); + } + + public function testTransactionJournals() + { + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $type = FactoryMuffin::create('FireflyIII\Models\TransactionType'); + $collection = new Collection([$journal]); + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Journal\JournalRepositoryInterface'); + $repository->shouldReceive('getTransactionType')->with('withdrawal')->andReturn($type); + $repository->shouldReceive('getJournalsOfType')->with($type)->andReturn($collection); + + + $this->call('GET', '/json/transaction-journals/withdrawal'); + $this->assertResponseOk(); + } + +} \ No newline at end of file From a3423f03212a669c9f61c6a2cfcf15dcfe5c9dae Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 12 Apr 2015 10:19:37 +0200 Subject: [PATCH 52/66] Add the correct path to category overview. --- app/Http/Controllers/CategoryController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 105959bc54..09b7b1370d 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -136,6 +136,7 @@ class CategoryController extends Controller $set = $repository->getJournals($category, $page); $count = $repository->countJournals($category); $journals = new LengthAwarePaginator($set, $count, 50, $page); + $journals->setPath('categories/show/' . $category->id); return view('categories.show', compact('category', 'journals', 'hideCategory')); } From 7a9f5ebdd161b3c0e573e480af05577153d737a6 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 12 Apr 2015 10:22:15 +0200 Subject: [PATCH 53/66] Added "what" variable. --- resources/views/transactions/edit.blade.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/resources/views/transactions/edit.blade.php b/resources/views/transactions/edit.blade.php index 884582ff36..e955d470f2 100644 --- a/resources/views/transactions/edit.blade.php +++ b/resources/views/transactions/edit.blade.php @@ -91,6 +91,9 @@ @stop @section('scripts') + @stop From 9fd8d8915d946340afb91a97f3eb91f644a1aad2 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 12 Apr 2015 10:53:53 +0200 Subject: [PATCH 54/66] amount > queryAmount --- resources/views/reports/year.blade.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/views/reports/year.blade.php b/resources/views/reports/year.blade.php index 3879321d21..31191257ce 100644 --- a/resources/views/reports/year.blade.php +++ b/resources/views/reports/year.blade.php @@ -92,7 +92,7 @@ $incomeSum = 0; $expenseSum = 0; foreach($groupedIncomes as $income) { - $incomeSum += floatval($income->amount); + $incomeSum += floatval($income->queryAmount); } foreach($groupedExpenses as $exp) { $expenseSum += floatval($exp['amount']); @@ -127,11 +127,11 @@ @foreach($groupedIncomes as $income) amount)*-1; + $sum += floatval($income->queryAmount)*-1; ?> {{{$income->name}}} - {!! Amount::format(floatval($income->amount)*-1) !!} + {!! Amount::format(floatval($income->queryAmount)*-1) !!} @endforeach From 721fa04e3c2c2589ea1a62ab6aec9957f545704b Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 13 Apr 2015 20:43:58 +0200 Subject: [PATCH 55/66] Added home screen information about piggy banks. --- app/Http/Controllers/HomeController.php | 31 ++-- .../Account/AccountRepository.php | 61 ++++++- .../Account/AccountRepositoryInterface.php | 8 + .../PiggyBank/PiggyBankRepository.php | 3 + .../PiggyBankRepositoryInterface.php | 1 - resources/views/index.blade.php | 149 +++++++++++------- tests/controllers/HomeControllerTest.php | 1 + 7 files changed, 178 insertions(+), 76 deletions(-) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index e02c69bddb..d7728b61b1 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -1,6 +1,5 @@ countAccounts($types); - $title = 'Firefly'; - $subTitle = 'What\'s playing?'; - $mainTitleIcon = 'fa-fire'; - $transactions = []; - $frontPage = Preferences::get('frontPageAccounts', []); - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->endOfMonth()); - $accounts = $repository->getFrontpageAccounts($frontPage); - $savings = $repository->getSavingsAccounts(); + $types = Config::get('firefly.accountTypesByIdentifier.asset'); + $count = $repository->countAccounts($types); + $title = 'Firefly'; + $subTitle = 'What\'s playing?'; + $mainTitleIcon = 'fa-fire'; + $transactions = []; + $frontPage = Preferences::get('frontPageAccounts', []); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->endOfMonth()); + $accounts = $repository->getFrontpageAccounts($frontPage); + $savings = $repository->getSavingsAccounts(); + $piggyBankAccounts = $repository->getPiggyBankAccounts(); - $savingsTotal = 0; + + $savingsTotal = 0; foreach ($savings as $savingAccount) { $savingsTotal += Steam::balance($savingAccount, $end); } @@ -83,7 +86,7 @@ class HomeController extends Controller } } - return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal')); + return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal','piggyBankAccounts')); } diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index ba5a88fea7..5dd2fe9772 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -6,6 +6,7 @@ use App; use Auth; use Carbon\Carbon; use Config; +use DB; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; @@ -141,13 +142,6 @@ class AccountRepository implements AccountRepositoryInterface ->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']); } - /** - * @return float - */ - public function sumOfEverything() { - return floatval(Auth::user()->transactions()->sum('amount')); - } - /** * @param Account $account * @param int $page @@ -194,6 +188,51 @@ class AccountRepository implements AccountRepositoryInterface return null; } + /** + * Get the accounts of a user that have piggy banks connected to them. + * + * @return Collection + */ + public function getPiggyBankAccounts() + { + $ids = []; + $start = clone Session::get('start', new Carbon); + $end = clone Session::get('end', new Carbon); + $accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']); + $accounts = new Collection; + + foreach ($accountIds as $id) { + $ids[] = intval($id->account_id); + } + + $ids = array_unique($ids); + if (count($ids) > 0) { + $accounts = Auth::user()->accounts()->whereIn('id', $ids)->get(); + } + + $accounts->each( + function (Account $account) use ($start, $end) { + $account->startBalance = Steam::balance($account, $start); + $account->endBalance = Steam::balance($account, $end); + $account->piggyBalance = 0; + /** @var PiggyBank $piggyBank */ + foreach ($account->piggyBanks as $piggyBank) { + $account->piggyBalance += $piggyBank->currentRelevantRep()->currentamount; + } + // sum of piggy bank amounts on this account: + // diff between endBalance and piggyBalance. + // then, percentage. + $difference = $account->endBalance - $account->piggyBalance; + $account->difference = $difference; + $account->percentage = $difference != 0 ? round((($difference / $account->endBalance) * 100)) : 100; + + } + ); + + return $accounts; + + } + /** * Get savings accounts and the balance difference in the period. * @@ -324,6 +363,14 @@ class AccountRepository implements AccountRepositoryInterface } + /** + * @return float + */ + public function sumOfEverything() + { + return floatval(Auth::user()->transactions()->sum('amount')); + } + /** * @param Account $account * @param array $data diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 0d533a0970..0a80c40691 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -51,6 +51,14 @@ interface AccountRepositoryInterface */ public function getCreditCards(); + /** + * Get the accounts of a user that have piggy banks connected to them. + * + * @return Collection + */ + public function getPiggyBankAccounts(); + + /** * Get all transfers TO this account in this range. * diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 0c95d0ab2f..ecabb40237 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -17,6 +17,7 @@ use Navigation; class PiggyBankRepository implements PiggyBankRepositoryInterface { + /** * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * @@ -96,6 +97,8 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); } + + /** * Set all piggy banks to order 0. * diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index 4bfe3d8cab..bc445cad87 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -14,7 +14,6 @@ use Illuminate\Support\Collection; interface PiggyBankRepositoryInterface { - /** * @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind. * diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php index cc4a001e1b..013e4a4a15 100644 --- a/resources/views/index.blade.php +++ b/resources/views/index.blade.php @@ -52,63 +52,104 @@
-
-
- Savings - {!! Amount::format($savingsTotal) !!} -
-
- @if(count($savings) == 0) -

Mark your asset accounts as "Savings account" to fill this panel.

- @else - @foreach($savings as $account) - -
- -
{!! Amount::format($account->startBalance) !!}
- -
- @if($account->difference < 0) - -
-
- @if($account->percentage <= 50) - {{Amount::format($account->difference,false)}} - @endif -
-
- @if($account->percentage > 50) - {{Amount::format($account->difference,false)}} - @endif -
-
- @else - -
-
- @if($account->percentage > 50) - {{Amount::format($account->difference,false)}} - @endif -
-
- @if($account->percentage <= 50) - {{Amount::format($account->difference,false)}} - @endif -
-
+ + +
+
+ Savings + {!! Amount::format($savingsTotal) !!} +
+
+ @if(count($savings) == 0) +

Mark your asset accounts as "Savings account" to fill this panel.

+ @else + @foreach($savings as $account) + +
+ +
{!! Amount::format($account->startBalance) !!}
+ +
+ @if($account->difference < 0) + +
+
+ @if($account->percentage <= 50) + {{Amount::format($account->difference,false)}} + @endif +
+
+ @if($account->percentage > 50) + {{Amount::format($account->difference,false)}} + @endif +
+
+ @else + +
+
+ @if($account->percentage > 50) + {{Amount::format($account->difference,false)}} + @endif +
+
+ @if($account->percentage <= 50) + {{Amount::format($account->difference,false)}} + @endif +
+
+ @endif + +
+ +
{!! Amount::format($account->endBalance) !!}
+
+ @endforeach + @endif +
+
+ + +
+
+ Piggy banks +
+
+ @if($piggyBankAccounts->count() == 0) +

Create piggy banks to fill this panel.

+ @else + @foreach($piggyBankAccounts as $account) + +
+ +
{!! Amount::format($account->startBalance) !!}
+ +
+ +
+
+ @if($account->percentage <= 50) + {{Amount::format($account->piggyBalance,false)}} divided @endif -
- -
{!! Amount::format($account->endBalance) !!}
+
+ @if($account->percentage > 50) + {{Amount::format($account->difference,false)}} left to divide + @endif
- @endforeach - @endif -
-
- +
+
+ +
{!! Amount::format($account->piggyBalance) !!}
+
+ @endforeach + @endif +
+
diff --git a/tests/controllers/HomeControllerTest.php b/tests/controllers/HomeControllerTest.php index aff74fa2e2..d9491bac8c 100644 --- a/tests/controllers/HomeControllerTest.php +++ b/tests/controllers/HomeControllerTest.php @@ -98,6 +98,7 @@ class HomeControllerTest extends TestCase Preferences::shouldReceive('get')->once()->withArgs(['frontPageAccounts', []])->andReturn($preference); $repository->shouldReceive('getFrontpageAccounts')->once()->with($preference)->andReturn($accounts); $repository->shouldReceive('getSavingsAccounts')->once()->andReturn($accounts); + $repository->shouldReceive('getPiggyBankAccounts')->once()->andReturn($accounts); $repository->shouldReceive('sumOfEverything')->once()->andReturn(1); $repository->shouldReceive('getFrontpageTransactions')->once()->andReturn($journals); From edbda32a84c0435b578939e9de4e47c7ebc99e6d Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 13 Apr 2015 21:13:05 +0200 Subject: [PATCH 56/66] Fix balance. --- app/Repositories/Account/AccountRepository.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 5dd2fe9772..2d3bd4c388 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -212,8 +212,8 @@ class AccountRepository implements AccountRepositoryInterface $accounts->each( function (Account $account) use ($start, $end) { - $account->startBalance = Steam::balance($account, $start); - $account->endBalance = Steam::balance($account, $end); + $account->startBalance = Steam::balance($account, $start, true); + $account->endBalance = Steam::balance($account, $end, true); $account->piggyBalance = 0; /** @var PiggyBank $piggyBank */ foreach ($account->piggyBanks as $piggyBank) { From e774ebd0a32fe60f74474cb11ad70b904671fc8b Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 18 Apr 2015 16:04:21 +0200 Subject: [PATCH 57/66] Possible bug in account create thing. [skip ci] --- app/Models/Account.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/Models/Account.php b/app/Models/Account.php index d0c0d7c6cd..2712aef197 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -51,7 +51,8 @@ class Account extends Model $account = Account::create($fields); if (is_null($account->id)) { // could not create account: - App::abort(500, 'Could not create new account with data: ' . json_encode($fields)); + App::abort(500, 'Could not create new account with data: ' . json_encode($fields).' because ' . json_encode($account->getErrors())); + } From 0656ccbdd9147b0c432737cd591840376540b83f Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 13:57:43 +0200 Subject: [PATCH 58/66] Fixed a bug where the query would include deleted transactions. --- app/Models/LimitRepetition.php | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/app/Models/LimitRepetition.php b/app/Models/LimitRepetition.php index 927d33b1f9..129e0a4901 100644 --- a/app/Models/LimitRepetition.php +++ b/app/Models/LimitRepetition.php @@ -1,5 +1,7 @@ leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id') - ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') - ->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d')) - ->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d')) - ->where('transactions.amount', '>', 0) - ->where('limit_repetitions.id', '=', $this->id) - ->sum('transactions.amount'); + $sum = DB::table('transactions') + ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id') + ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') + ->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d')) + ->where('transaction_journals.user_id', Auth::user()->id) + ->whereNull('transactions.deleted_at') + ->where('transactions.amount', '>', 0) + ->where('limit_repetitions.id', '=', $this->id) + ->sum('transactions.amount'); return floatval($sum); } From 52d23b6ef53f35d472f9de5638d545c874d4f93b Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 14:19:25 +0200 Subject: [PATCH 59/66] Referred to an id which turned out to be a index. --- resources/views/reports/year.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/reports/year.blade.php b/resources/views/reports/year.blade.php index 31191257ce..fd65f34a3c 100644 --- a/resources/views/reports/year.blade.php +++ b/resources/views/reports/year.blade.php @@ -149,9 +149,9 @@
- @foreach($groupedExpenses as $id => $expense) + @foreach($groupedExpenses as $expense) - + From 6d1978fd9a75a4078ce155c66514edaf847ba617 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 14:27:08 +0200 Subject: [PATCH 60/66] Showed the wrong value. --- resources/views/reports/year.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/reports/year.blade.php b/resources/views/reports/year.blade.php index fd65f34a3c..30d3c12756 100644 --- a/resources/views/reports/year.blade.php +++ b/resources/views/reports/year.blade.php @@ -152,9 +152,9 @@ @foreach($groupedExpenses as $expense) - + - + @endforeach From 91c6deeb1fc621c07943aa7636bc2801e45a75bf Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 14:28:17 +0200 Subject: [PATCH 61/66] Renamed another field. --- resources/views/reports/year.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/reports/year.blade.php b/resources/views/reports/year.blade.php index 30d3c12756..f29b2fa8be 100644 --- a/resources/views/reports/year.blade.php +++ b/resources/views/reports/year.blade.php @@ -95,7 +95,7 @@ $incomeSum += floatval($income->queryAmount); } foreach($groupedExpenses as $exp) { - $expenseSum += floatval($exp['amount']); + $expenseSum += floatval($exp['queryAmount']); } $incomeSum = floatval($incomeSum*-1); From 412d6d4fd7aa031aacabcbfcebb5aace231055f6 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 17:43:04 +0200 Subject: [PATCH 62/66] Small CSS fix for piggy banks [skip ci] --- public/css/firefly.css | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/public/css/firefly.css b/public/css/firefly.css index 195d5a4043..422c9bed10 100644 --- a/public/css/firefly.css +++ b/public/css/firefly.css @@ -1,3 +1,8 @@ #daterange {cursor:pointer;} .google-chart-error {height:30px;background:url('/images/error.png') no-repeat center center;} -.handle {cursor:move;} \ No newline at end of file +.handle {cursor:move;} + +.ui-sortable-placeholder { + display: inline-block; + height: 1px; +} \ No newline at end of file From 875cbf66af5dae7e393defa3796de1bc109ac103 Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 19 Apr 2015 19:10:53 +0200 Subject: [PATCH 63/66] 1 should be 0 --- app/Repositories/Budget/BudgetRepository.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index a7b80cbf24..82ceed96cf 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -148,7 +148,7 @@ class BudgetRepository implements BudgetRepositoryInterface */ public function getInactiveBudgets() { - return Auth::user()->budgets()->where('active', 1)->get(); + return Auth::user()->budgets()->where('active', 0)->get(); } /** From 4b9b207d92af753b22bce00dd1b8d14b480bc925 Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 20 Apr 2015 17:59:04 +0200 Subject: [PATCH 64/66] Removed development references. --- config/app.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/config/app.php b/config/app.php index 23d8fa9af1..fe7ad89606 100644 --- a/config/app.php +++ b/config/app.php @@ -136,8 +136,6 @@ return [ 'Illuminate\Validation\ValidationServiceProvider', 'Illuminate\View\ViewServiceProvider', 'Illuminate\Html\HtmlServiceProvider', - 'Barryvdh\Debugbar\ServiceProvider', - 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', 'DaveJamesMiller\Breadcrumbs\ServiceProvider', /* From f47ba6c9779f9968ecf2e02b7d8e0f714e0d80e8 Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 20 Apr 2015 18:06:21 +0200 Subject: [PATCH 65/66] Update example file. --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 6e6fd0fa1a..ce0218faf1 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ -APP_ENV=local -APP_DEBUG=true +APP_ENV=production +APP_DEBUG=false APP_KEY=SomeRandomString DB_CONNECTION=mysql From daf859b97732f0428a3b5d6ce14dc467a7641604 Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 20 Apr 2015 18:06:37 +0200 Subject: [PATCH 66/66] Updated read me. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 493b3745d3..352f3728fb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Firefly III (v3.3.7) +Firefly III (v3.3.8) =========== [![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
{{{$expense['name']}}}{{{$expense['name']}}} {!! Amount::format(floatval($expense['amount'])*-1) !!}
{{{$expense['name']}}}{!! Amount::format(floatval($expense['amount'])*-1) !!}{!! Amount::format(floatval($expense['queryAmount'])*-1) !!}
Sum