diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index d328d92b5e..2eb257341e 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -5,9 +5,12 @@ use FireflyIII\Http\Requests; use FireflyIII\Http\Requests\CategoryFormRequest; use FireflyIII\Models\Category; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; +use Illuminate\Pagination\LengthAwarePaginator; use Redirect; use Session; use View; +use Input; + /** * Class CategoryController @@ -17,6 +20,9 @@ use View; class CategoryController extends Controller { + /** + * + */ public function __construct() { View::share('title', 'Categories'); @@ -31,6 +37,24 @@ class CategoryController extends Controller return view('categories.create')->with('subTitle', 'Create a new category'); } + /** + * @param Category $category + * + * @return $this + */ + public function show(Category $category, CategoryRepositoryInterface $repository) + { + $hideCategory = true; // used in list. + $page = intval(Input::get('page')); + $offset = $page > 0 ? $page * 50 : 0; + $set = $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)->orderBy('date', 'DESC')->get(['transaction_journals.*']); + $count = $category->transactionJournals()->count(); + + $journals = new LengthAwarePaginator($set, $count, 50, $page); + + return view('categories.show', compact('category', 'journals', 'hideCategory')); + } + /** * @param Category $category * diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 59ccc9fdff..8eafd0d496 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -12,6 +12,7 @@ use FireflyIII\Models\Bill; use FireflyIII\Models\Budget; use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\Category; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use Grumpydictator\Gchart\GChart; use Illuminate\Database\Query\Builder as QueryBuilder; @@ -30,6 +31,49 @@ class GoogleChartController extends Controller { + /** + * + * @param Category $category + * @param $year + * + * @return \Illuminate\Http\JsonResponse + */ + public function categoriesAndSpending(Category $category, $year, GChart $chart) + { + try { + new Carbon('01-01-' . $year); + } catch (Exception $e) { + return view('error')->with('message', 'Invalid year.'); + } + + $chart->addColumn('Month', 'date'); + $chart->addColumn('Budgeted', 'number'); + $chart->addColumn('Spent', 'number'); + + $start = new Carbon('01-01-' . $year); + $end = clone $start; + $end->endOfYear(); + while ($start <= $end) { + + $currentEnd = clone $start; + $currentEnd->endOfMonth(); + $spent = floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; + $budgeted = null; + + $chart->addRow(clone $start, $budgeted, $spent); + + $start->addMonth(); + } + + + $chart->generate(); + + return Response::json($chart->getData()); + + + } + + /** * @param Account $account * @param string $view diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php new file mode 100644 index 0000000000..f4583a826f --- /dev/null +++ b/app/Http/Controllers/JsonController.php @@ -0,0 +1,68 @@ +categories()->orderBy('name','ASC')->get(); + $return = []; + foreach ($list as $entry) { + $return[] = $entry->name; + } + + return Response::json($return); + + + } + + /** + * Returns a JSON list of all beneficiaries. + * + * @return \Illuminate\Http\JsonResponse + */ + public function expenseAccounts() + { + $list = Auth::user()->accounts()->accountTypeIn(['Expense account', 'Beneficiary account'])->get(); + $return = []; + foreach ($list as $entry) { + $return[] = $entry->name; + } + + return Response::json($return); + + } + + /** + * @return \Illuminate\Http\JsonResponse + */ + public function revenueAccounts() + { + $list = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->get(); + $return = []; + foreach ($list as $entry) { + $return[] = $entry->name; + } + + return Response::json($return); + + } + +} diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index 81d40fb137..556bf8f294 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -64,7 +64,7 @@ class PiggyBankController extends Controller { } } - return View::make('piggy-banks.index', compact('piggyBanks', 'accounts')); + return view('piggy-banks.index', compact('piggyBanks', 'accounts')); } } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 39c1d205e1..817a0514ee 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -102,7 +102,7 @@ class ReportController extends Controller * End getBudgetsForMonth DONE */ - return View::make('reports.budget', compact('subTitle', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly')); + return view('reports.budget', compact('subTitle', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly')); } @@ -239,7 +239,7 @@ class ReportController extends Controller */ - return View::make( + return view( 'reports.month', compact( 'income', 'expenses', 'budgets', 'accounts', 'categories', @@ -258,7 +258,7 @@ class ReportController extends Controller try { new Carbon('01-01-' . $year); } catch (Exception $e) { - return View::make('error')->with('message', 'Invalid date.'); + return view('error')->with('message', 'Invalid date.'); } $date = new Carbon('01-01-' . $year); $end = clone $date; @@ -273,7 +273,7 @@ class ReportController extends Controller //$groupedExpenses = $helper-> expensesGroupedByAccount($date, $end, 15); - return View::make( + return view( 'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon') ); } diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 2ee5dc4458..1757e9de8b 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -1,14 +1,17 @@ accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get() + Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get(['accounts.*']) ); $budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); $budgets[0] = '(no budget)'; @@ -98,7 +101,34 @@ class TransactionController extends Controller $journals = new LengthAwarePaginator($set, $count, 50, $page); $journals->setPath('transactions/' . $what); - return View::make('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); + return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals')); + + } + + public function store(JournalFormRequest $request, JournalRepositoryInterface $repository) + { + + $journalData = [ + 'what' => $request->get('what'), + 'description' => $request->get('description'), + 'account_id' => intval($request->get('account_id')), + 'account_from_id' => intval($request->get('account_from_id')), + 'account_to_id' => intval($request->get('account_to_id')), + 'expense_account' => $request->get('expense_account'), + 'revenue_account' => $request->get('revenue_account'), + 'amount' => floatval($request->get('amount')), + 'user' => Auth::user()->id, + 'amount_currency_id' => intval($request->get('amount_currency_id')), + 'date' => new Carbon($request->get('date')), + 'budget_id' => intval($request->get('budget_id')), + 'category' => $request->get('category'), + ]; + + $journal = $repository->store($journalData); + + Session::flash('success', 'New transaction "' . $journal->description . '" stored!'); + + return Redirect::route('transactions.index', $request->input('what')); } diff --git a/app/Http/Requests/JournalFormRequest.php b/app/Http/Requests/JournalFormRequest.php new file mode 100644 index 0000000000..aefaefb972 --- /dev/null +++ b/app/Http/Requests/JournalFormRequest.php @@ -0,0 +1,72 @@ + 'required|min:1,max:255', + 'what' => 'required|in:withdrawal,deposit,transfer|exists:transaction_types,type', + 'amount' => 'numeric|required|min:0.01', + 'date' => 'required|date', + 'amount_currency_id' => 'required|exists:transaction_currencies,id', + + ]; + + switch ($what) { + case 'withdrawal': + $rules['account_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; + $rules['expense_account'] = 'between:1,255'; + $rules['category'] = 'between:1,255'; + if (intval(Input::get('budget_id')) != 0) { + $rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets'; + } + + + break; + case 'deposit': + $rules['category'] = 'between:1,255'; + $rules['account_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; + $rules['revenue_account'] = 'between:1,255'; + break; + case 'transfer': + $rules['account_from_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:account_to_id'; + $rules['account_to_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:account_from_id'; + $rules['category'] = 'between:1,255'; + break; + default: + die('Cannot handle ' . $what); + break; + } + + return $rules; + + + } +} \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index 7dc48170bf..9301cc0ec8 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -151,11 +151,17 @@ Route::group( Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']); Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending']); Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); + Route::get('/chart/category/{category}/spending/{year}', ['uses' => 'GoogleChartController@categoriesAndSpending']); Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']); Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']); //Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']); + // JSON controller + 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']); + /** * Piggy Bank Controller diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 4be2636774..5e7cefbcb9 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -2,6 +2,14 @@ namespace FireflyIII\Repositories\Journal; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; + /** * Class JournalRepository * @@ -10,4 +18,97 @@ namespace FireflyIII\Repositories\Journal; class JournalRepository implements JournalRepositoryInterface { + /** + * @param array $data + * + * @return TransactionJournal + */ + public function store(array $data) + { + // find transaction type. + $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); + + // store actual journal. + $journal = new TransactionJournal( + [ + 'user_id' => $data['user'], + 'transaction_type_id' => $transactionType->id, + 'transaction_currency_id' => $data['amount_currency_id'], + 'description' => $data['description'], + 'completed' => 0, + 'date' => $data['date'], + ] + ); + $journal->save(); + + + // store or get category + if (strlen($data['category']) > 0) { + $category = Category::firstOrCreate(['name' => $data['category'], 'user_id' => $data['user']]); + $journal->categories()->save($category); + } + + // store or get budget + if (intval($data['budget_id']) > 0) { + $budget = Budget::find($data['budget_id']); + $journal->budgets()->save($budget); + } + + // store accounts (depends on type) + switch ($transactionType->type) { + case 'Withdrawal': + + $from = Account::find($data['account_id']); + + if (strlen($data['expense_account']) > 0) { + $toType = AccountType::where('type', 'Expense account')->first(); + $to = Account::firstOrCreate( + ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1] + ); + } else { + $toType = AccountType::where('type', 'Cash account')->first(); + $to = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]); + } + break; + + case 'Deposit': + $to = Account::find($data['account_id']); + + if (strlen($data['revenue_account']) > 0) { + $fromType = AccountType::where('type', 'Revenue account')->first(); + $from = Account::firstOrCreate( + ['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1] + ); + } else { + $toType = AccountType::where('type', 'Cash account')->first(); + $from = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]); + } + + break; + case 'Transfer': + $from = Account::find($data['account_from_id']); + $to = Account::find($data['account_to_id']); + break; + } + + // store accompanying transactions. + Transaction::create( // first transaction. + [ + 'account_id' => $from->id, + 'transaction_journal_id' => $journal->id, + 'amount' => $data['amount'] * -1 + ] + ); + Transaction::create( // second transaction. + [ + 'account_id' => $to->id, + 'transaction_journal_id' => $journal->id, + 'amount' => $data['amount'] + ] + ); + + return $journal; + + + } } \ No newline at end of file diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index ae19f6f052..65106022eb 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -1,13 +1,8 @@ where('user_id', Auth::user()->id)->where('id', $value)->count(); + if ($count == 1) { + return true; + } + + return false; + + } + /** * @param $attribute * @param $value diff --git a/resources/views/categories/show.blade.php b/resources/views/categories/show.blade.php index bdfefd3e52..fd17e123e8 100644 --- a/resources/views/categories/show.blade.php +++ b/resources/views/categories/show.blade.php @@ -1,6 +1,6 @@ @extends('layouts.default') @section('content') -{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $category) }} +{!! Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $category) !!}
@@ -60,17 +61,17 @@