diff --git a/app/assets/javascripts/firefly/piggybanks.js b/app/assets/javascripts/firefly/piggybanks.js index 598b6480bd..56f02c9fbf 100644 --- a/app/assets/javascripts/firefly/piggybanks.js +++ b/app/assets/javascripts/firefly/piggybanks.js @@ -15,24 +15,21 @@ function inputRange(e) { var target = $(e.target); var piggyBankId = target.attr('name').substring(6); var accountId = target.data('account'); - var value = parseFloat(target.val()); + var amount = parseFloat(target.val()); + - var leftInAccount = leftInAccounts(accountId); - if(leftInAccount <= 0) { - value = parseFloat($('#piggy_'+piggyBankId+'_amount').val()); - target.val(parseFloat(value)); - } - var valueId = 'piggy_' + piggyBankId + '_amount'; - $('#' + valueId).val(value.toFixed(2)); // -// // new percentage for amount in piggy bank, formatted. + // new percentage for amount in piggy bank, formatted. var pctId = 'piggy_' + piggyBankId + '_pct'; - percentage = Math.round((value / parseFloat(target.attr('max'))) * 100) + '%'; //Math.round((value / parseFloat(target.attr('total'))) * 100) + '%'; + percentage = Math.round((amount / parseFloat(target.attr('max'))) * 100) + '%'; //Math.round((value / parseFloat(target.attr('total'))) * 100) + '%'; $('#' + pctId).text(percentage); - // update the bar accordingly. + // new value for number input: + var valueId = 'piggy_' + piggyBankId + '_amount'; + $('#' + valueId).val(amount.toFixed(2)); + leftInAccounts(accountId); return true; } @@ -42,27 +39,27 @@ function inputNumber(e) { var amount = parseFloat(target.val()); var piggyBankId = target.data('piggy'); var accountId = target.data('account'); - var leftInAccount = leftInAccounts(accountId); - if(leftInAccount <= 0) { - amount = parseFloat($('#piggy_'+piggyBankId+'_amount').val()); - } else { - // do something! - } + + // update amount in range input: target.val(amount); - console.log('SERVER'); $('input[name="piggy_'+piggyBankId+'"]').val(amount); + console.log('SERVER: ' + amount); $.post('piggybanks/updateAmount/' + piggyBankId, {amount: amount}); + + leftInAccounts(accountId); } function updateAmount(e) { + + // update amount on server: var target = $(e.target); var piggyBankId = target.attr('name').substring(6); var accountId = target.data('account'); - var value = target.val(); - console.log('SERVER'); - $.post('piggybanks/updateAmount/' + piggyBankId, {amount: value}); + var amount = target.val(); + console.log('SERVER: ' + amount); + $.post('piggybanks/updateAmount/' + piggyBankId, {amount: amount}); } @@ -80,7 +77,11 @@ function leftInAccounts(accountId) { } }); var left = total - inPiggies; - console.log('LEFT: ' + left); + + // set amount left: + leftFormatted = '€ ' + left.toFixed(2); + $('#account_'+accountId+'_left').text(leftFormatted); + // return amount left: return left; diff --git a/app/controllers/CategoryController.php b/app/controllers/CategoryController.php index b098fbefca..14c0465076 100644 --- a/app/controllers/CategoryController.php +++ b/app/controllers/CategoryController.php @@ -1,7 +1,7 @@ _repository->get(); + return View::make('categories.index')->with('categories', $categories); } @@ -57,7 +59,7 @@ class CategoryController extends BaseController $journals = $this->_category->journalsInRange($category, $start, $end); - return View::make('categories.show')->with('category', $category)->with('journals',$journals); + return View::make('categories.show')->with('category', $category)->with('journals', $journals); } public function store() @@ -69,9 +71,11 @@ class CategoryController extends BaseController if (Input::get('create') == '1') { return Redirect::route('categories.create'); } + return Redirect::route('categories.index'); } else { Session::flash('error', 'Could not save the new category!'); + return Redirect::route('categories.create')->withInput(); } } diff --git a/app/controllers/ChartController.php b/app/controllers/ChartController.php index 0c776e55ab..150992a659 100644 --- a/app/controllers/ChartController.php +++ b/app/controllers/ChartController.php @@ -35,8 +35,8 @@ class ChartController extends BaseController $end = Session::get('end'); \Log::debug('Draw home account chart.'); - \Log::debug('From: '.$start.' ('.$start->timezone.')'); - \Log::debug('Until: '.$end); + \Log::debug('From: ' . $start . ' (' . $start->timezone . ')'); + \Log::debug('Until: ' . $end); if (is_null($account)) { // get, depending on preferences: @@ -116,7 +116,9 @@ class ChartController extends BaseController } - public function categoryShowChart(Category $category) { + + public function categoryShowChart(Category $category) + { $start = Session::get('start'); $end = Session::get('end'); $range = Session::get('range'); @@ -124,11 +126,11 @@ class ChartController extends BaseController $serie = $this->_chart->categoryShowChart($category, $range, $start, $end); $data = [ 'chart_title' => $category->name, - 'subtitle' => 'View more', - 'series' => $serie + 'subtitle' => 'View more', + 'series' => $serie ]; - return Response::json($data); + return Response::json($data); } diff --git a/app/controllers/LimitController.php b/app/controllers/LimitController.php index 8898c74ece..2d85bd8b3c 100644 --- a/app/controllers/LimitController.php +++ b/app/controllers/LimitController.php @@ -33,9 +33,9 @@ class LimitController extends BaseController { $periods = \Config::get('firefly.periods_to_text'); $prefilled = [ - 'startdate' => Input::get('startdate') ? : date('Y-m-d'), + 'startdate' => Input::get('startdate') ? : date('Y-m-d'), 'repeat_freq' => Input::get('repeat_freq') ? : 'monthly', - 'budget_id' => $budget ? $budget->id : null + 'budget_id' => $budget ? $budget->id : null ]; $budgets = $this->_budgets->getAsSelectList(); diff --git a/app/controllers/PiggybankController.php b/app/controllers/PiggybankController.php index 860f46f41e..71c9f7e045 100644 --- a/app/controllers/PiggybankController.php +++ b/app/controllers/PiggybankController.php @@ -27,19 +27,24 @@ class PiggybankController extends BaseController return View::make('piggybanks.create')->with('accounts', $accounts); } - public function delete() + public function delete(Piggybank $piggyBank) { + return View::make('piggybanks.delete')->with('piggybank', $piggyBank); } - public function destroy() + public function destroy(Piggybank $piggyBank) { + $piggyBank->delete(); + Session::flash('success', 'Piggy bank deleted.'); + + return Redirect::route('piggybanks.index'); } - public function edit() + public function edit(Piggybank $piggyBank) { - } - public function updateAmount(Piggybank $piggybank) { - $this->_repository->updateAmount($piggybank,Input::get('amount')); + $accounts = $this->_accounts->getActiveDefaultAsSelectList(); + + return View::make('piggybanks.edit')->with('piggybank', $piggyBank)->with('accounts', $accounts); } public function index() @@ -55,8 +60,10 @@ class PiggybankController extends BaseController if (!isset($accounts[$id])) { $account->balance = $account->balance(); $account->left = $account->balance - $piggyBank->amount; + $account->total = $piggyBank->target; } else { $account->left -= $piggyBank->amount; + $account->total += $piggyBank->target; } $accounts[$id] = $account; @@ -80,7 +87,12 @@ class PiggybankController extends BaseController return Redirect::route('piggybanks.create')->withInput(); } else { - Session::flash('success', 'New piggy bank created!'); + Session::flash('success', 'New piggy bank "' . $piggyBank->name . '" created!'); + + + if (Input::get('create') == '1') { + return Redirect::route('piggybanks.create')->withInput(); + } return Redirect::route('piggybanks.index'); } @@ -89,5 +101,15 @@ class PiggybankController extends BaseController public function update() { + + $piggyBank = $this->_repository->update(Input::all()); + Session::flash('success', 'Piggy bank "' . $piggyBank->name . '" updated.'); + + return Redirect::route('piggybanks.index'); + } + + public function updateAmount(Piggybank $piggybank) + { + $this->_repository->updateAmount($piggybank, Input::get('amount')); } } \ No newline at end of file diff --git a/app/controllers/RecurringControlle.php b/app/controllers/RecurringController.php similarity index 86% rename from app/controllers/RecurringControlle.php rename to app/controllers/RecurringController.php index 10b48a027e..a45bfb0b00 100644 --- a/app/controllers/RecurringControlle.php +++ b/app/controllers/RecurringController.php @@ -1,6 +1,7 @@ _accounts = $accounts; - $this->_budgets = $budgets; - $this->_categories = $categories; - $this->_journal = $journal; - - + $this->_repository = $repository; View::share('menu', 'home'); } /** - * @param $what + * @param string $what * - * @return $this|\Illuminate\View\View + * @return \Illuminate\View\View */ - public function create($what) + public function create($what = 'deposit') { // get accounts with names and id's. - $accounts = $this->_accounts->getActiveDefaultAsSelectList(); - $budgets = $this->_budgets->getAsSelectList(); + /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ + $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + $accounts = $accountRepository->getActiveDefaultAsSelectList(); + + // get budgets as a select list. + /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */ + $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); + $budgets = $budgetRepository->getAsSelectList(); $budgets[0] = '(no budget)'; @@ -52,63 +44,78 @@ class TransactionController extends BaseController ); } + public function delete(TransactionJournal $transactionJournal) + { + return View::make('transactions.delete')->with('journal', $transactionJournal); + + + } + + public function destroy(TransactionJournal $transactionJournal) + { + $transactionJournal->delete(); + + return Redirect::route('transactions.index'); + + } + /** * @param $journalId * * @return $this|\Illuminate\View\View */ - public function edit($journalId) + public function edit(TransactionJournal $journal) { - // get journal: - $journal = $this->_journal->find($journalId); + // type is useful for display: + $what = strtolower($journal->transactiontype->type); - if ($journal) { - // type is useful for display: - $what = strtolower($journal->transactiontype->type); + // some lists prefilled: + // get accounts with names and id's. + /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ + $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + $accounts = $accountRepository->getActiveDefaultAsSelectList(); - // some lists prefilled: - $budgets = $this->_budgets->getAsSelectList(); - $budgets[0] = '(no budget)'; - $accounts = $this->_accounts->getActiveDefaultAsSelectList(); + // get budgets as a select list. + /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */ + $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); + $budgets = $budgetRepository->getAsSelectList(); + $budgets[0] = '(no budget)'; - // data to properly display form: - $data = [ - 'date' => $journal->date->format('Y-m-d'), - 'category' => '', - 'budget_id' => 0 - ]; - $category = $journal->categories()->first(); - if (!is_null($category)) { - $data['category'] = $category->name; - } - switch ($journal->transactiontype->type) { - case 'Withdrawal': - $data['account_id'] = $journal->transactions[0]->account->id; - $data['beneficiary'] = $journal->transactions[1]->account->name; - $data['amount'] = floatval($journal->transactions[1]->amount); - $budget = $journal->budgets()->first(); - if (!is_null($budget)) { - $data['budget_id'] = $budget->id; - } - break; - case 'Deposit': - $data['account_id'] = $journal->transactions[1]->account->id; - $data['beneficiary'] = $journal->transactions[0]->account->name; - $data['amount'] = floatval($journal->transactions[1]->amount); - break; - case 'Transfer': - $data['account_from_id'] = $journal->transactions[1]->account->id; - $data['account_to_id'] = $journal->transactions[0]->account->id; - $data['amount'] = floatval($journal->transactions[1]->amount); - break; - } - - return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with( - 'what', $what - )->with('budgets', $budgets)->with('data', $data); + // data to properly display form: + $data = [ + 'date' => $journal->date->format('Y-m-d'), + 'category' => '', + 'budget_id' => 0 + ]; + $category = $journal->categories()->first(); + if (!is_null($category)) { + $data['category'] = $category->name; + } + switch ($journal->transactiontype->type) { + case 'Withdrawal': + $data['account_id'] = $journal->transactions[0]->account->id; + $data['beneficiary'] = $journal->transactions[1]->account->name; + $data['amount'] = floatval($journal->transactions[1]->amount); + $budget = $journal->budgets()->first(); + if (!is_null($budget)) { + $data['budget_id'] = $budget->id; + } + break; + case 'Deposit': + $data['account_id'] = $journal->transactions[1]->account->id; + $data['beneficiary'] = $journal->transactions[0]->account->name; + $data['amount'] = floatval($journal->transactions[1]->amount); + break; + case 'Transfer': + $data['account_from_id'] = $journal->transactions[1]->account->id; + $data['account_to_id'] = $journal->transactions[0]->account->id; + $data['amount'] = floatval($journal->transactions[1]->amount); + break; } - return View::make('error')->with('message', 'Invalid journal'); + return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with( + 'what', $what + )->with('budgets', $budgets)->with('data', $data); } /** @@ -116,9 +123,9 @@ class TransactionController extends BaseController */ public function index() { - $transactions = $this->_journal->paginate(25); + $journals = $this->_repository->paginate(25); - return View::make('transactions.index')->with('transactions', $transactions); + return View::make('transactions.index')->with('journals', $journals); } /** @@ -128,12 +135,12 @@ class TransactionController extends BaseController */ public function show($journalId) { - $journal = $this->_journal->find($journalId); - if ($journal) { - return View::make('transactions.show')->with('journal', $journal); - } - - return View::make('error')->with('message', 'Invalid journal'); +// $journal = $this->_journal->find($journalId); +// if ($journal) { +// return View::make('transactions.show')->with('journal', $journal); +// } +// +// return View::make('error')->with('message', 'Invalid journal'); } /** @@ -143,137 +150,37 @@ class TransactionController extends BaseController */ public function store($what) { - // $fromAccount and $toAccount are found - // depending on the $what - - $fromAccount = null; - $toAccount = null; - - switch ($what) { - case 'withdrawal': - $fromAccount = $this->_accounts->find(intval(Input::get('account_id'))); - $toAccount = $this->_accounts->createOrFindBeneficiary(Input::get('beneficiary')); - break; - case 'deposit': - $fromAccount = $this->_accounts->createOrFindBeneficiary(Input::get('beneficiary')); - $toAccount = $this->_accounts->find(intval(Input::get('account_id'))); - break; - case 'transfer': - $fromAccount = $this->_accounts->find(intval(Input::get('account_from_id'))); - $toAccount = $this->_accounts->find(intval(Input::get('account_to_id'))); - break; - } - // fall back to cash if necessary: - $fromAccount = is_null($fromAccount) ? $fromAccount = $this->_accounts->getCashAccount() : $fromAccount; - $toAccount = is_null($toAccount) ? $toAccount = $this->_accounts->getCashAccount() : $toAccount; - - // create or find category: - $category = $this->_categories->createOrFind(Input::get('category')); - - // find budget: - $budget = $this->_budgets->find(intval(Input::get('budget_id'))); - - // find amount & description: - $description = trim(Input::get('description')); - $amount = floatval(Input::get('amount')); - $date = new \Carbon\Carbon(Input::get('date')); - - // create journal - /** @var \TransactionJournal $journal */ - try { - $journal = $this->_journal->createSimpleJournal($fromAccount, $toAccount, $description, $amount, $date); - } catch (\Firefly\Exception\FireflyException $e) { - return Redirect::route('transactions.create', $what)->withInput(); - } - - // attach bud/cat (?) - if (!is_null($budget)) { - $journal->budgets()->save($budget); - } - if (!is_null($category)) { - $journal->categories()->save($category); - } - - Session::flash('success', 'Transaction "' . $description . '" saved'); - - if (Input::get('create') == '1') { - return Redirect::route('transactions.create', $what)->withInput(); + $transactionJournal = $this->_repository->store($what, Input::all()); + if ($transactionJournal->id) { + Session::flash('success', 'Transaction "' . $transactionJournal->description . '" saved!'); + if (Input::get('create') == '1') { + return Redirect::route('transactions.create', [$what])->withInput(); + } else { + return Redirect::route('transactions.index'); + } } else { - return Redirect::route('index'); + Session::flash('error', 'Could not save transaction: ' . $transactionJournal->errors()->first()); + + return Redirect::route('transactions.create', [$what])->withInput()->withErrors( + $transactionJournal->errors() + ); } } - public function update($journalId) + public function update(TransactionJournal $journal) { + $journal = $this->_repository->update($journal, Input::all()); + if ($journal->validate()) { + // has been saved, return to index: + Session::flash('success', 'Transaction updated!'); - // get journal: - $journal = $this->_journal->find($journalId); + return Redirect::route('transactions.index'); + } else { + Session::flash('error', 'Could not update transaction: ' . $journal->errors()->first()); - if ($journal) { - // update basics first: - $journal->description = Input::get('description'); - $journal->date = Input::get('date'); - $amount = floatval(Input::get('amount')); - - // remove previous category, if any: - if (!is_null($journal->categories()->first())) { - $journal->categories()->detach($journal->categories()->first()->id); - } - // remove previous budget, if any: - if (!is_null($journal->budgets()->first())) { - $journal->budgets()->detach($journal->budgets()->first()->id); - } - - // get the category: - $category = $this->_categories->findByName(Input::get('category')); - if (!is_null($category)) { - $journal->categories()->attach($category); - } - // update the amounts: - $journal->transactions[0]->amount = $amount * -1; - $journal->transactions[1]->amount = $amount; - - // switch on type to properly change things: - switch ($journal->transactiontype->type) { - case 'Withdrawal': - // means transaction[0] is the users account. - $account = $this->_accounts->find(Input::get('account_id')); - $beneficiary = $this->_accounts->findByName(Input::get('beneficiary')); - $journal->transactions[0]->account()->associate($account); - $journal->transactions[1]->account()->associate($beneficiary); - - - // do budget: - $budget = $this->_budgets->find(Input::get('budget_id')); - $journal->budgets()->attach($budget); - - break; - case 'Deposit': - // means transaction[0] is the beneficiary. - $account = $this->_accounts->find(Input::get('account_id')); - $beneficiary = $this->_accounts->findByName(Input::get('beneficiary')); - $journal->transactions[0]->account()->associate($beneficiary); - $journal->transactions[1]->account()->associate($account); - break; - case 'Transfer': - // means transaction[0] is account that sent the money (from). - $fromAccount = $this->_accounts->find(Input::get('account_from_id')); - $toAccount = $this->_accounts->find(Input::get('account_to_id')); - $journal->transactions[0]->account()->associate($fromAccount); - $journal->transactions[1]->account()->associate($toAccount); - break; - default: - throw new \Firefly\Exception\FireflyException('Cannot edit this!'); - break; - } - - $journal->transactions[0]->save(); - $journal->transactions[1]->save(); - $journal->save(); - - return Redirect::route('transactions.edit', $journal->id); + return Redirect::route('transactions.edit', $journal->id)->withInput()->withErrors($journal->errors()); } diff --git a/app/lib/Firefly/Helper/Controllers/Category.php b/app/lib/Firefly/Helper/Controllers/Category.php index 1f31dd9c04..0b3444ce87 100644 --- a/app/lib/Firefly/Helper/Controllers/Category.php +++ b/app/lib/Firefly/Helper/Controllers/Category.php @@ -15,10 +15,9 @@ class Category implements CategoryInterface { public function journalsInRange(\Category $category, Carbon $start, Carbon $end) { - return $category->transactionjournals()-> - with(['transactions','transactions.account','transactiontype','components'])-> - - orderBy('date','DESC')->orderBy('id','DESC')->before($end)->after($start)->get(); + return $category->transactionjournals()->with( + ['transactions', 'transactions.account', 'transactiontype', 'components'] + )->orderBy('date', 'DESC')->orderBy('id', 'DESC')->before($end)->after($start)->get(); } } \ No newline at end of file diff --git a/app/lib/Firefly/Helper/Controllers/CategoryInterface.php b/app/lib/Firefly/Helper/Controllers/CategoryInterface.php index 621c6a6600..f858f301b9 100644 --- a/app/lib/Firefly/Helper/Controllers/CategoryInterface.php +++ b/app/lib/Firefly/Helper/Controllers/CategoryInterface.php @@ -11,7 +11,8 @@ namespace Firefly\Helper\Controllers; use Carbon\Carbon; -interface CategoryInterface { +interface CategoryInterface +{ public function journalsInRange(\Category $category, Carbon $start, Carbon $end); diff --git a/app/lib/Firefly/Helper/Controllers/Chart.php b/app/lib/Firefly/Helper/Controllers/Chart.php index dc9015c029..62290d58cd 100644 --- a/app/lib/Firefly/Helper/Controllers/Chart.php +++ b/app/lib/Firefly/Helper/Controllers/Chart.php @@ -21,7 +21,9 @@ class Chart implements ChartInterface $return = ['name' => $account->name, 'id' => $account->id, 'data' => []]; while ($current <= $end) { - \Log::debug('Now at day: ' . $current . '('.$current->timestamp.'), ('.($current->timestamp * 1000).') '); + \Log::debug( + 'Now at day: ' . $current . '(' . $current->timestamp . '), (' . ($current->timestamp * 1000) . ') ' + ); if ($current > $today) { $return['data'][] = [$current->timestamp * 1000, $account->predict(clone $current)]; } else { @@ -38,7 +40,7 @@ class Chart implements ChartInterface { $result = [ 'rows' => [], - 'sum' => 0 + 'sum' => 0 ]; if ($account) { // get journals in range: @@ -219,7 +221,6 @@ class Chart implements ChartInterface } - // now format the current range: $title = ''; switch ($range) { @@ -240,7 +241,7 @@ class Chart implements ChartInterface $title = $beginning->format('M Y') . ' - ' . $currentEnd->format('M Y'); break; case 'custom': - $title = $beginning->format('d-m-Y').' - '.$currentEnd->format('d-m-Y'); + $title = $beginning->format('d-m-Y') . ' - ' . $currentEnd->format('d-m-Y'); break; case 'yearly': // return $this->startdate->format('Y'); @@ -257,7 +258,10 @@ class Chart implements ChartInterface ) ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') ->where('transaction_types.type', 'Withdrawal') - ->leftJoin('component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin( + 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', + 'transaction_journals.id' + ) ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id') ->where('components.id', '=', $category->id) //->leftJoin() @@ -306,6 +310,7 @@ class Chart implements ChartInterface } } + return $data; diff --git a/app/lib/Firefly/Storage/Category/CategoryRepositoryInterface.php b/app/lib/Firefly/Storage/Category/CategoryRepositoryInterface.php index f6ab03d581..ca422ca541 100644 --- a/app/lib/Firefly/Storage/Category/CategoryRepositoryInterface.php +++ b/app/lib/Firefly/Storage/Category/CategoryRepositoryInterface.php @@ -14,6 +14,7 @@ interface CategoryRepositoryInterface * @return mixed */ public function get(); + public function find($categoryId); /** diff --git a/app/lib/Firefly/Storage/Category/EloquentCategoryRepository.php b/app/lib/Firefly/Storage/Category/EloquentCategoryRepository.php index c703200dbd..0ab79e6a43 100644 --- a/app/lib/Firefly/Storage/Category/EloquentCategoryRepository.php +++ b/app/lib/Firefly/Storage/Category/EloquentCategoryRepository.php @@ -66,6 +66,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface $category->user()->associate(\Auth::user()); $category->save(); + return $category; } diff --git a/app/lib/Firefly/Storage/Piggybank/EloquentPiggybankRepository.php b/app/lib/Firefly/Storage/Piggybank/EloquentPiggybankRepository.php index 946c6f35f1..efcca6ae9b 100644 --- a/app/lib/Firefly/Storage/Piggybank/EloquentPiggybankRepository.php +++ b/app/lib/Firefly/Storage/Piggybank/EloquentPiggybankRepository.php @@ -23,7 +23,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface { return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where( 'accounts.user_id', \Auth::user()->id - )->where('piggybanks.id', $piggyBankId)->first('piggybanks.*'); + )->where('piggybanks.id', $piggyBankId)->first(['piggybanks.*']); } public function get() @@ -32,13 +32,6 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface 'accounts.user_id', \Auth::user()->id )->get(['piggybanks.*']); } - public function updateAmount(\Piggybank $piggyBank, $amount) { - $piggyBank->amount = floatval($amount); - if($piggyBank->validate()) { - $piggyBank->save(); - } - - } public function store($data) { @@ -62,4 +55,31 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface return $piggyBank; } + + public function update($data) + { + $piggyBank = $this->find($data['id']); + if ($piggyBank) { + $accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + $account = $accounts->find($data['account_id']); + // update piggybank accordingly: + $piggyBank->name = $data['name']; + $piggyBank->target = floatval($data['target']); + $piggyBank->account()->associate($account); + if ($piggyBank->validate()) { + $piggyBank->save(); + } + } + + return $piggyBank; + } + + public function updateAmount(\Piggybank $piggyBank, $amount) + { + $piggyBank->amount = floatval($amount); + if ($piggyBank->validate()) { + $piggyBank->save(); + } + + } } \ No newline at end of file diff --git a/app/lib/Firefly/Storage/Piggybank/PiggybankRepositoryInterface.php b/app/lib/Firefly/Storage/Piggybank/PiggybankRepositoryInterface.php index 57535460dc..995dacaf43 100644 --- a/app/lib/Firefly/Storage/Piggybank/PiggybankRepositoryInterface.php +++ b/app/lib/Firefly/Storage/Piggybank/PiggybankRepositoryInterface.php @@ -12,9 +12,15 @@ interface PiggybankRepositoryInterface { public function find($piggyBankId); + public function count(); + public function store($data); + public function get(); public function updateAmount(\Piggybank $piggyBank, $amount); + + public function update($data); + } \ No newline at end of file diff --git a/app/lib/Firefly/Storage/StorageServiceProvider.php b/app/lib/Firefly/Storage/StorageServiceProvider.php index 3d3145aa46..420e57ce8c 100644 --- a/app/lib/Firefly/Storage/StorageServiceProvider.php +++ b/app/lib/Firefly/Storage/StorageServiceProvider.php @@ -32,8 +32,6 @@ class StorageServiceProvider extends ServiceProvider ); - - $this->app->bind( 'Firefly\Storage\Account\AccountRepositoryInterface', 'Firefly\Storage\Account\EloquentAccountRepository' diff --git a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php index 5e37cf683e..fc04b223fb 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php +++ b/app/lib/Firefly/Storage/TransactionJournal/EloquentTransactionJournalRepository.php @@ -14,26 +14,6 @@ use Firefly\Exception\FireflyException; class EloquentTransactionJournalRepository implements TransactionJournalRepositoryInterface { - /** - * @param $journalId - * - * @return mixed - */ - public function find($journalId) - { - return \Auth::user()->transactionjournals()->with( - ['transactions' => function ($q) { - return $q->orderBy('amount', 'ASC'); - }, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account', - 'transactions.account.accounttype'] - ) - ->where('id', $journalId)->first(); - } - /* - - * - */ - /** * * We're building this thinking the money goes from A to B. @@ -66,20 +46,24 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito public function createSimpleJournal(\Account $from, \Account $toAccount, $description, $amount, Carbon $date) { \Log::debug('Creating tranaction "' . $description . '".'); + $journal = new \TransactionJournal; $amountFrom = $amount * -1; $amountTo = $amount; if (round(floatval($amount), 2) == 0.00) { \Log::error('Transaction will never save: amount = 0'); - \Session::flash('error', 'The amount should not be empty or zero.'); - throw new FireflyException('Could not figure out transaction type.'); + $journal->errors()->add('amount', 'Amount must not be zero.'); + + return $journal; } // same account: if ($from->id == $toAccount->id) { \Log::error('Accounts cannot be equal'); - \Session::flash('error', 'Select two different accounts.'); - throw new FireflyException('Select two different accounts.'); + $journal->errors()->add('account_id', 'Must be different accounts.'); + $journal->errors()->add('account_from_id', 'Must be different accounts.'); + + return $journal; } // account types for both: @@ -129,18 +113,15 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito } // new journal: - $journal = new \TransactionJournal(); + $journal->transactionType()->associate($journalType); $journal->transactionCurrency()->associate($currency); $journal->user()->associate(\Auth::user()); $journal->completed = false; $journal->description = $description; $journal->date = $date; - if (!$journal->save()) { - \Log::error('Cannot create valid journal.'); - \Log::error('Errors: ' . print_r($journal->errors()->all(), true)); - \Session::flash('error', 'Could not create journal: ' . $journal->errors()->first()); - throw new FireflyException('Cannot create valid journal.'); + if (!$journal->validate()) { + return $journal; } $journal->save(); @@ -150,7 +131,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito $fromTransaction->transactionJournal()->associate($journal); $fromTransaction->description = null; $fromTransaction->amount = $amountFrom; - if (!$fromTransaction->save()) { + if (!$fromTransaction->validate()) { \Log::error('Cannot create valid transaction (from) for journal #' . $journal->id); \Log::error('Errors: ' . print_r($fromTransaction->errors()->all(), true)); throw new FireflyException('Cannot create valid transaction (from).'); @@ -162,7 +143,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito $toTransaction->transactionJournal()->associate($journal); $toTransaction->description = null; $toTransaction->amount = $amountTo; - if (!$toTransaction->save()) { + if (!$toTransaction->validate()) { \Log::error('Cannot create valid transaction (to) for journal #' . $journal->id); \Log::error('Errors: ' . print_r($toTransaction->errors()->all(), true)); throw new FireflyException('Cannot create valid transaction (to).'); @@ -174,6 +155,26 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito return $journal; } + /* + + * + */ + + /** + * @param $journalId + * + * @return mixed + */ + public function find($journalId) + { + return \Auth::user()->transactionjournals()->with( + ['transactions' => function ($q) { + return $q->orderBy('amount', 'ASC'); + }, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account', + 'transactions.account.accounttype'] + ) + ->where('id', $journalId)->first(); + } /** * @@ -183,6 +184,35 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito } + /** + * @param \Account $account + * @param Carbon $date + * + * @return mixed + */ + public function getByAccountAndDate(\Account $account, Carbon $date) + { + $accountID = $account->id; + $query = \Auth::user()->transactionjournals()->with( + [ + 'transactions', + 'transactions.account', + 'transactioncurrency', + 'transactiontype' + ] + ) + ->distinct() + ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->where('transactions.account_id', $accountID) + ->where('transaction_journals.date', $date->format('Y-m-d')) + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.id', 'DESC') + ->get(['transaction_journals.*']); + + return $query; + } + /** * @param \Account $account * @param int $count @@ -214,6 +244,17 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito return $query; } + /** + * @param Carbon $start + * @param Carbon $end + * + * @return mixed + */ + public function getByDateRange(Carbon $start, Carbon $end) + { + die('no impl'); + } + /** * @param int $count * @@ -234,50 +275,154 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito ) ->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.id', 'DESC') - ->take($count) ->paginate($count); return $query; } - /** - * @param Carbon $start - * @param Carbon $end - * - * @return mixed - */ - public function getByDateRange(Carbon $start, Carbon $end) + public function store($what, $data) { - die('no impl'); + // $fromAccount and $toAccount are found + // depending on the $what + + $fromAccount = null; + $toAccount = null; + + /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ + $accountRepository = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + + /** @var \Firefly\Storage\Category\CategoryRepositoryInterface $catRepository */ + $catRepository = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface'); + + /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budRepository */ + $budRepository = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); + + + switch ($what) { + case 'withdrawal': + $fromAccount = $accountRepository->find(intval($data['account_id'])); + $toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']); + break; + case 'deposit': + $fromAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']); + $toAccount = $accountRepository->find(intval($data['account_id'])); + break; + case 'transfer': + $fromAccount = $accountRepository->find(intval($data['account_from_id'])); + $toAccount = $accountRepository->find(intval($data['account_to_id'])); + break; + } + // fall back to cash if necessary: + $fromAccount = is_null($fromAccount) ? $fromAccount = $accountRepository->getCashAccount() : $fromAccount; + $toAccount = is_null($toAccount) ? $toAccount = $accountRepository->getCashAccount() : $toAccount; + + // create or find category: + $category = isset($data['category']) ? $catRepository->createOrFind($data['category']) : null; + + // find budget: + $budget = isset($data['budget_id']) ? $budRepository->find(intval($data['budget_id'])) : null; +// +// // find amount & description: + $description = trim($data['description']); + $amount = floatval($data['amount']); + $date = new \Carbon\Carbon($data['date']); + + // try to create a journal: + $transactionJournal = $this->createSimpleJournal($fromAccount, $toAccount, $description, $amount, $date); + if (!$transactionJournal->id || $transactionJournal->completed == 0) { + return $transactionJournal; + } + + // attach: + if (!is_null($budget)) { + $transactionJournal->budgets()->save($budget); + } + if (!is_null($category)) { + $transactionJournal->categories()->save($category); + } + + return $transactionJournal; } - /** - * @param \Account $account - * @param Carbon $date - * - * @return mixed - */ - public function getByAccountAndDate(\Account $account, Carbon $date) + public function update(\TransactionJournal $journal, $data) { - $accountID = $account->id; - $query = \Auth::user()->transactionjournals()->with( - [ - 'transactions', - 'transactions.account', - 'transactioncurrency', - 'transactiontype' - ] - ) - ->distinct() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') - ->where('transactions.account_id', $accountID) - ->where('transaction_journals.date', $date->format('Y-m-d')) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.id', 'DESC') - ->get(['transaction_journals.*']); + /** @var \Firefly\Storage\Category\CategoryRepositoryInterface $catRepository */ + $catRepository = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface'); + + /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */ + $budRepository = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface'); + + /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */ + $accountRepository = \App::make('Firefly\Storage\Account\AccountRepositoryInterface'); + + + // update basics first: + $journal->description = $data['description']; + $journal->date = $data['date']; + $amount = floatval($data['amount']); + + // remove previous category, if any: + if (!is_null($journal->categories()->first())) { + $journal->categories()->detach($journal->categories()->first()->id); + } + // remove previous budget, if any: + if (!is_null($journal->budgets()->first())) { + $journal->budgets()->detach($journal->budgets()->first()->id); + } + + + $category = isset($data['category']) ? $catRepository->findByName($data['category']) : null; + if (!is_null($category)) { + $journal->categories()->attach($category); + } + // update the amounts: + /** @var \Transaction $transaction */ + $transactions = $journal->transactions()->orderBy('amount', 'ASC')->get(); + $transactions[0]->amount = $amount; + $transactions[1]->amount = $amount; + + // switch on type to properly change things: + switch ($journal->transactiontype->type) { + case 'Withdrawal': + // means transaction[0] is the users account. + $account = $accountRepository->find($data['account_id']); + $beneficiary = $accountRepository->findByName($data['beneficiary']); + $transactions[0]->account()->associate($account); + $transactions[1]->account()->associate($beneficiary); + + // do budget: + $budget = $budRepository->find($data['budget_id']); + $journal->budgets()->attach($budget); + + break; + case 'Deposit': + // means transaction[0] is the beneficiary. + $account = $accountRepository->find($data['account_id']); + $beneficiary = $accountRepository->findByName($data['beneficiary']); + $journal->transactions[0]->account()->associate($beneficiary); + $journal->transactions[1]->account()->associate($account); + break; + case 'Transfer': + // means transaction[0] is account that sent the money (from). + $fromAccount = $accountRepository->find($data['account_from_id']); + $toAccount = $accountRepository->find($data['account_to_id']); + $journal->transactions[0]->account()->associate($fromAccount); + $journal->transactions[1]->account()->associate($toAccount); + break; + default: + throw new \Firefly\Exception\FireflyException('Cannot edit this!'); + break; + } + + $transactions[0]->save(); + $transactions[1]->save(); + if ($journal->validate()) { + $journal->save(); + } + + return $journal; + - return $query; } diff --git a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php index 6bf727d259..71ccee399d 100644 --- a/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php +++ b/app/lib/Firefly/Storage/TransactionJournal/TransactionJournalRepositoryInterface.php @@ -27,6 +27,10 @@ interface TransactionJournalRepositoryInterface */ public function get(); + public function store($what, $data); + + public function update(\TransactionJournal $journal, $data); + /** * @param $journalId * diff --git a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php index b7b05a154d..4af5f62e5f 100644 --- a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php +++ b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php @@ -46,14 +46,14 @@ class EloquentLimitTrigger if ($limit->repeats == 0) { $limit->createRepetition($limit->startdate); } - if($limit->repeats == 1) { + if ($limit->repeats == 1) { $start = $limit->startdate; $end = new Carbon; // repeat for period: $current = clone $start; - \Log::debug('Create repeating limit for #'.$limit->id.' starting on ' . $current); - while($current <= $end) { + \Log::debug('Create repeating limit for #' . $limit->id . ' starting on ' . $current); + while ($current <= $end) { \Log::debug('Current is now: ' . $current); $limit->createRepetition(clone $current); // switch period, add time: @@ -128,10 +128,10 @@ class EloquentLimitTrigger // } // // } - } - } + } + } // // diff --git a/app/models/Piggybank.php b/app/models/Piggybank.php index f1b4291d7c..2afb4908a3 100644 --- a/app/models/Piggybank.php +++ b/app/models/Piggybank.php @@ -1,6 +1,29 @@ belongsTo('Account'); } + public function getDates() + { + return array('created_at', 'updated_at', 'targetdate'); + } + } \ No newline at end of file diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php index fb5d474bdd..4afdac6c13 100644 --- a/app/models/TransactionJournal.php +++ b/app/models/TransactionJournal.php @@ -47,6 +47,14 @@ use LaravelBook\Ardent\Ardent; * 'Budget[] $budgets * @property-read \Illuminate\Database\Eloquent\Collection|\ * 'Category[] $categories + * @property-read \Illuminate\Database\Eloquent\Collection|\ + * 'Budget[] $budgets + * @property-read \Illuminate\Database\Eloquent\Collection|\ + * 'Category[] $categories + * @property-read \Illuminate\Database\Eloquent\Collection|\ + * 'Budget[] $budgets + * @property-read \Illuminate\Database\Eloquent\Collection|\ + * 'Category[] $categories */ class TransactionJournal extends Ardent { diff --git a/app/models/User.php b/app/models/User.php index 72ea913144..1250c2710f 100644 --- a/app/models/User.php +++ b/app/models/User.php @@ -32,6 +32,7 @@ use LaravelBook\Ardent\Ardent; * @method static \Illuminate\Database\Query\Builder|\User whereRememberToken($value) * @method static \Illuminate\Database\Query\Builder|\User whereMigrated($value) * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals + * @property-read \Illuminate\Database\Eloquent\Collection|\Piggybank[] $piggybanks */ class User extends Ardent implements UserInterface, RemindableInterface { @@ -72,7 +73,8 @@ class User extends Ardent implements UserInterface, RemindableInterface return $this->hasMany('Account'); } - public function piggybanks() { + public function piggybanks() + { return $this->hasMany('Piggybank'); } diff --git a/app/routes.php b/app/routes.php index f4f8fe4ccb..ea47f032c5 100644 --- a/app/routes.php +++ b/app/routes.php @@ -30,6 +30,16 @@ Route::bind('category', function($value, $route) return null; }); +Route::bind('tj', function($value, $route) + { + if(Auth::check()) { + return TransactionJournal:: + where('id', $value)-> + where('user_id',Auth::user()->id)->first(); + } + return null; + }); + Route::bind('limit', function($value, $route) { if(Auth::check()) { @@ -78,6 +88,8 @@ Route::group(['before' => 'auth'], function () { // piggy bank controller Route::get('/piggybanks',['uses' => 'PiggybankController@index','as' => 'piggybanks.index']); Route::get('/piggybanks/create', ['uses' => 'PiggybankController@create','as' => 'piggybanks.create']); + Route::get('/piggybanks/edit/{piggybank}', ['uses' => 'PiggybankController@edit','as' => 'piggybanks.edit']); + Route::get('/piggybanks/delete/{piggybank}', ['uses' => 'PiggybankController@delete','as' => 'piggybanks.delete']); Route::post('/piggybanks/updateAmount/{piggybank}',['uses' => 'PiggybankController@updateAmount','as' => 'piggybanks.updateAmount']); @@ -119,10 +131,11 @@ Route::group(['before' => 'auth'], function () { // transaction controller: Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(['what' => 'withdrawal|deposit|transfer']); - Route::get('/transaction/show/{id}',['uses' => 'TransactionController@show','as' => 'transactions.show']); - Route::get('/transaction/edit/{id}',['uses' => 'TransactionController@edit','as' => 'transactions.edit']); - Route::get('/transaction/delete/{id}',['uses' => 'TransactionController@delete','as' => 'transactions.delete']); + Route::get('/transaction/show/{tj}',['uses' => 'TransactionController@show','as' => 'transactions.show']); + Route::get('/transaction/edit/{tj}',['uses' => 'TransactionController@edit','as' => 'transactions.edit']); + Route::get('/transaction/delete/{tj}',['uses' => 'TransactionController@delete','as' => 'transactions.delete']); Route::get('/transactions/index',['uses' => 'TransactionController@index','as' => 'transactions.index']); + // migration controller Route::get('/migrate', ['uses' => 'MigrationController@index', 'as' => 'migrate']); @@ -149,7 +162,8 @@ Route::group(['before' => 'csrf|auth'], function () { // piggy bank controller Route::post('/piggybanks/store',['uses' => 'PiggybankController@store','as' => 'piggybanks.store']); - + Route::post('/piggybanks/update', ['uses' => 'PiggybankController@update','as' => 'piggybanks.update']); + Route::post('/piggybanks/destroy/{piggybank}', ['uses' => 'PiggybankController@destroy','as' => 'piggybanks.destroy']); @@ -169,7 +183,8 @@ Route::group(['before' => 'csrf|auth'], function () { // transaction controller: Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store']) ->where(['what' => 'withdrawal|deposit|transfer']); - Route::post('/transaction/update/{id}',['uses' => 'TransactionController@update','as' => 'transactions.update']); + Route::post('/transaction/update/{tj}',['uses' => 'TransactionController@update','as' => 'transactions.update']); + Route::post('/transaction/destroy/{tj}',['uses' => 'TransactionController@destroy','as' => 'transactions.destroy']); } ); diff --git a/app/views/lists/transactions.blade.php b/app/views/lists/transactions.blade.php index 49bdca4665..b41db9db0d 100644 --- a/app/views/lists/transactions.blade.php +++ b/app/views/lists/transactions.blade.php @@ -28,10 +28,10 @@
Remember that deleting something is permanent.
+ +Use piggy banks to make saving money easier
++ Saving money is hard. Piggy banks allow you to group money + from an account together. If you also set a target (and a target date) you + can save towards your goals. +
+{{$errors->first('name')}}
+ @else + For example: new bike, new camera + @endif +{{$errors->first('target')}}
+ @else + How much money do you need to save? + @endif +{{$errors->first('account_id')}}
+ @else + Indicate on which account you've got your savings. + @endif +{{$errors->first('targetdate')}}
+ @else + + If you want to, set a target date. This will inform you how much money you should save to + get to the target amount. + + @endif ++ Target date: {{$piggybank->targetdate->format('jS F Y')}} +
+ @endif@@ -56,6 +63,12 @@ | {{$piggybank->pct}} | ++ + |
{{$errors->first('account_from_id')}}
+ @endif{{$errors->first('account_to_id')}}
+ @endif{{$errors->first('amount')}}
+ @endifRemember that deleting something is permanent.
+ ++ This form allows you to delete the transaction labelled "{{{$journal->description}}}". +
++ Are you sure? +
+ +