diff --git a/app/controllers/PiggybankController.php b/app/controllers/PiggybankController.php index e1bca56ab6..f7395fd13f 100644 --- a/app/controllers/PiggybankController.php +++ b/app/controllers/PiggybankController.php @@ -230,7 +230,7 @@ class PiggybankController extends BaseController public function show(Piggybank $piggybank) { - $events = $piggybank->piggybankevents()->orderBy('date', 'DESC')->get(); + $events = $piggybank->piggybankevents()->orderBy('date', 'DESC')->orderBy('id','DESC')->get(); /* * Number of reminders: diff --git a/app/controllers/TransactionController.php b/app/controllers/TransactionController.php index 5e8b103649..77b47374ae 100644 --- a/app/controllers/TransactionController.php +++ b/app/controllers/TransactionController.php @@ -100,10 +100,16 @@ class TransactionController extends BaseController { $type = $transactionJournal->transactionType->type; + /* + * Trigger creation of new piggy bank event + */ + Event::fire('piggybank.destroyTransfer', [$transactionJournal]); + /** @var \FireflyIII\Database\TransactionJournal $repository */ $repository = App::make('FireflyIII\Database\TransactionJournal'); $repository->destroy($transactionJournal); + switch ($type) { case 'Withdrawal': return Redirect::route('transactions.index', 'withdrawal'); @@ -126,6 +132,9 @@ class TransactionController extends BaseController */ public function edit(TransactionJournal $journal) { + /* + * TODO the piggybank id must be filled in when relevant. + */ /* * All the repositories we need: */ @@ -199,9 +208,17 @@ class TransactionController extends BaseController $prefilled['amount'] = floatval($journal->transactions[1]->amount); break; case 'transfer': - $prefilled['account_from_id'] = $journal->transactions[1]->account->id; - $prefilled['account_to_id'] = $journal->transactions[0]->account->id; - $prefilled['amount'] = floatval($journal->transactions[1]->amount); + if (floatval($journal->transactions[0]->amount) < 0) { + // zero = from account. + $prefilled['account_from_id'] = $journal->transactions[0]->account->id; + $prefilled['account_to_id'] = $journal->transactions[1]->account->id; + $prefilled['amount'] = floatval($journal->transactions[1]->amount); + } else { + // one = from account + $prefilled['account_from_id'] = $journal->transactions[1]->account->id; + $prefilled['account_to_id'] = $journal->transactions[0]->account->id; + $prefilled['amount'] = floatval($journal->transactions[0]->amount); + } break; } @@ -248,7 +265,7 @@ class TransactionController extends BaseController break; } - return View::make('transactions.index', compact('subTitle', 'subTitleIcon','journals'))->with('what', $what); + return View::make('transactions.index', compact('subTitle', 'subTitleIcon', 'journals'))->with('what', $what); } @@ -295,9 +312,17 @@ class TransactionController extends BaseController return Redirect::route('transactions.create', $what)->withInput()->withErrors($messages['errors']); } // store! - $repository->store($data); + $journal = $repository->store($data); Session::flash('success', 'New transaction stored!'); + /* + * Trigger a search for the related (if selected) + * piggy bank and store an event. + */ + if (!is_null(Input::get('piggybank_id')) && intval(Input::get('piggybank_id')) > 0) { + Event::fire('piggybank.createTransfer', [$journal, intval(Input::get('piggybank_id'))]); + } + if ($data['post_submit_action'] == 'create_another') { return Redirect::route('transactions.create', $what)->withInput(); } else { @@ -339,6 +364,7 @@ class TransactionController extends BaseController // has been saved, return to index: Session::flash('success', 'Transaction updated!'); // Event::fire('journals.update', [$journal]); + Event::fire('piggybank.updateTransfer', [$journal]); if (Input::get('post_submit_action') == 'return_to_edit') { return Redirect::route('transactions.edit', $journal->id)->withInput(); diff --git a/app/database/migrations/2014_11_15_112449_extend_piggybank_events.php b/app/database/migrations/2014_11_15_112449_extend_piggybank_events.php new file mode 100644 index 0000000000..c92d1f0343 --- /dev/null +++ b/app/database/migrations/2014_11_15_112449_extend_piggybank_events.php @@ -0,0 +1,33 @@ +integer('transaction_journal_id')->unsigned()->nullable(); + $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('set null'); + } + ); + } + +} diff --git a/app/lib/FireflyIII/Database/Piggybank.php b/app/lib/FireflyIII/Database/Piggybank.php index b54c2c9710..491ff71ba2 100644 --- a/app/lib/FireflyIII/Database/Piggybank.php +++ b/app/lib/FireflyIII/Database/Piggybank.php @@ -2,6 +2,7 @@ namespace FireflyIII\Database; use Carbon\Carbon; +use Firefly\Exception\FireflyException; use FireflyIII\Database\Ifaces\CommonDatabaseCalls; use FireflyIII\Database\Ifaces\CUD; use FireflyIII\Database\Ifaces\PiggybankInterface; @@ -196,8 +197,10 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface */ public function find($id) { - // TODO: Implement find() method. - throw new NotImplementedException; + return \Piggybank:: + leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id') + ->where('piggybanks.id','=',$id) + ->where('accounts.user_id', $this->getUser()->id)->first(['piggybanks.*']); } /** @@ -234,6 +237,18 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface throw new NotImplementedException; } + public function findRepetitionByDate(\Piggybank $piggybank, Carbon $date) + { + $reps = $piggybank->piggybankrepetitions()->get(); + if ($reps->count() == 1) { + return $reps->first(); + } + if ($reps->count() == 0) { + throw new FireflyException('Should always find a piggy bank repetition.'); + } + throw new NotImplementedException; + } + /** * @param \Account $account * diff --git a/app/lib/FireflyIII/Database/TransactionJournal.php b/app/lib/FireflyIII/Database/TransactionJournal.php index 2367a18ad0..0f4a145a06 100644 --- a/app/lib/FireflyIII/Database/TransactionJournal.php +++ b/app/lib/FireflyIII/Database/TransactionJournal.php @@ -164,7 +164,6 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData */ public function update(Ardent $model, array $data) { - var_dump($data); /** @var \FireflyIII\Database\TransactionType $typeRepository */ $typeRepository = \App::make('FireflyIII\Database\TransactionType'); diff --git a/app/lib/FireflyIII/Event/Piggybank.php b/app/lib/FireflyIII/Event/Piggybank.php index 0a2da1922b..d946cc3bd8 100644 --- a/app/lib/FireflyIII/Event/Piggybank.php +++ b/app/lib/FireflyIII/Event/Piggybank.php @@ -6,19 +6,21 @@ namespace FireflyIII\Event; use Carbon\Carbon; use Illuminate\Events\Dispatcher; -class Piggybank { +class Piggybank +{ /** * @param \Piggybank $piggybank * @param float $amount */ - public function addMoney(\Piggybank $piggybank, $amount = 0.0) { - if($amount > 0) { + public function addMoney(\Piggybank $piggybank, $amount = 0.0) + { + if ($amount > 0) { $event = new \PiggybankEvent; $event->piggybank()->associate($piggybank); $event->amount = floatval($amount); - $event->date = new Carbon; - if(!$event->validate()) { + $event->date = new Carbon; + if (!$event->validate()) { var_dump($event->errors()); exit(); } @@ -26,18 +28,130 @@ class Piggybank { } } + /** + * @param \TransactionJournal $journal + * @param int $piggybankId + */ + public function createTransfer(\TransactionJournal $journal, $piggybankId = 0) + { + /** @var \FireflyIII\Database\Piggybank $repository */ + $repository = \App::make('FireflyIII\Database\Piggybank'); + + /** @var \Piggybank $piggyBank */ + $piggyBank = $repository->find($piggybankId); + + /** @var \PiggybankRepetition $repetition */ + $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); + + \Log::debug( + 'Connecting transfer "' . $journal->description . '" (#' . $journal->id . ') to piggy bank "' . $piggyBank->name . '" (#' . $piggyBank->id . ').' + ); + + // some variables to double check the connection. + $start = $piggyBank->startdate; + $end = $piggyBank->targetdate; + $amount = floatval($piggyBank->targetamount); + $leftToSave = $amount - floatval($repetition->currentamount); + $relevantTransaction = null; + /** @var \Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if ($transaction->account_id == $piggyBank->account_id) { + $relevantTransaction = $transaction; + } + } + if (is_null($relevantTransaction)) { + return; + } + \Log::debug('Relevant transaction is #' . $relevantTransaction->id . ' with amount ' . $relevantTransaction->amount); + + // if FF3 should save this connection depends on some variables: + if ($start && $end && $journal->date >= $start && $journal->date <= $end) { + if ($relevantTransaction->amount < 0) { // amount removed from account, so removed from piggy bank. + \Log::debug('Remove from piggy bank.'); + $continue = ($relevantTransaction->amount * -1 <= floatval($repetition->currentamount)); + \Log::debug( + 'relevantTransaction.amount *-1 = ' . ($relevantTransaction->amount * -1) . ' >= current = ' . floatval($repetition->currentamount) + ); + } else { // amount added + \Log::debug('Add from piggy bank.'); + $continue = $relevantTransaction->amount <= $leftToSave; + } + if ($continue) { + \Log::debug('Update repetition.'); + $repetition->currentamount += floatval($relevantTransaction->amount); + $repetition->save(); + + $event = new \PiggybankEvent; + $event->piggybank()->associate($piggyBank); + $event->transactionjournal()->associate($journal); + $event->amount = floatval($relevantTransaction->amount); + $event->date = new Carbon; + if (!$event->validate()) { + var_dump($event->errors()); + exit(); + } + $event->save(); + } + } + } + + public function destroyTransfer(\TransactionJournal $journal) + { + if ($journal->piggybankevents()->count() > 0) { + + /** @var \FireflyIII\Database\Piggybank $repository */ + $repository = \App::make('FireflyIII\Database\Piggybank'); + + /** @var \Piggybank $piggyBank */ + $piggyBank = $journal->piggybankevents()->first()->piggybank()->first(); + + /** @var \PiggybankRepetition $repetition */ + $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); + + $relevantTransaction = null; + /** @var \Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if ($transaction->account_id == $piggyBank->account_id) { + $relevantTransaction = $transaction; + } + } + if (is_null($relevantTransaction)) { + return; + } + + $repetition->currentamount += floatval($relevantTransaction->amount * -1); + $repetition->save(); + + + $event = new \PiggybankEvent; + $event->piggybank()->associate($piggyBank); + $event->amount = floatval($relevantTransaction->amount * -1); + $event->date = new Carbon; + if (!$event->validate()) { + var_dump($event->errors()); + exit(); + } + $event->save(); + } + } + + /* + * + */ + /** * @param \Piggybank $piggybank * @param float $amount */ - public function removeMoney(\Piggybank $piggybank, $amount = 0.0) { + public function removeMoney(\Piggybank $piggybank, $amount = 0.0) + { $amount = $amount * -1; - if($amount < 0) { + if ($amount < 0) { $event = new \PiggybankEvent; $event->piggybank()->associate($piggybank); $event->amount = floatval($amount); - $event->date = new Carbon; - if(!$event->validate()) { + $event->date = new Carbon; + if (!$event->validate()) { var_dump($event->errors()); exit(); } @@ -52,5 +166,58 @@ class Piggybank { { $events->listen('piggybank.addMoney', 'FireflyIII\Event\Piggybank@addMoney'); $events->listen('piggybank.removeMoney', 'FireflyIII\Event\Piggybank@removeMoney'); + $events->listen('piggybank.createTransfer', 'FireflyIII\Event\Piggybank@createTransfer'); + $events->listen('piggybank.destroyTransfer', 'FireflyIII\Event\Piggybank@destroyTransfer'); + $events->listen('piggybank.updateTransfer', 'FireflyIII\Event\Piggybank@updateTransfer'); + } + + public function updateTransfer(\TransactionJournal $journal) + { + + if ($journal->piggybankevents()->count() > 0) { + + $event = $journal->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->first(); + $eventSum = floatval($journal->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->sum('amount')); + + /** @var \FireflyIII\Database\Piggybank $repository */ + $repository = \App::make('FireflyIII\Database\Piggybank'); + + /** @var \Piggybank $piggyBank */ + $piggyBank = $journal->piggybankevents()->first()->piggybank()->first(); + + /** @var \PiggybankRepetition $repetition */ + $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); + + $relevantTransaction = null; + /** @var \Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + if ($transaction->account_id == $piggyBank->account_id) { + $relevantTransaction = $transaction; + } + } + if (is_null($relevantTransaction)) { + return; + } + + $diff = floatval($relevantTransaction->amount) - floatval($eventSum); + /* + * Create an event to remove /add the difference from the piggy + */ + $repetition->currentamount += $diff; + $repetition->save(); + + + $event = new \PiggybankEvent; + $event->piggybank()->associate($piggyBank); + $event->transactionJournal()->associate($journal); + $event->amount = $diff; + $event->date = new Carbon; + if (!$event->validate()) { + var_dump($event->errors()); + exit(); + } + $event->save(); + } + } } \ No newline at end of file diff --git a/app/models/PiggybankEvent.php b/app/models/PiggybankEvent.php index ceb3c1bf91..b33a8567cc 100644 --- a/app/models/PiggybankEvent.php +++ b/app/models/PiggybankEvent.php @@ -41,4 +41,12 @@ class PiggybankEvent extends Ardent return $this->belongsTo('Piggybank'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function transactionJournal() + { + return $this->belongsTo('TransactionJournal'); + } + } \ No newline at end of file diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php index 94eb8318e6..b996cb2d69 100644 --- a/app/models/TransactionJournal.php +++ b/app/models/TransactionJournal.php @@ -138,6 +138,14 @@ class TransactionJournal extends Ardent return $query->where('date', '>=', $date->format('Y-m-d')); } + /** + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function piggybankevents() + { + return $this->hasMany('PiggybankEvent'); + } + /** * @param $query * @param Carbon $date diff --git a/app/routes.php b/app/routes.php index 0f39b634aa..1400d74167 100644 --- a/app/routes.php +++ b/app/routes.php @@ -154,6 +154,7 @@ Route::group( Route::get('/chart/sankey/{account}/in', ['uses' => 'GoogleChartController@accountSankeyInChart']); Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']); Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']); + Route::get('/chart/recurring/{recurring}', ['uses' => 'GoogleChartController@recurringOverview']); Route::get('/chart/reports/budgets/{year}', ['uses' => 'GoogleChartController@budgetsReportChart']); Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); diff --git a/app/views/list/piggybank-events.blade.php b/app/views/list/piggybank-events.blade.php index 0493b986c7..dfba52ee4f 100644 --- a/app/views/list/piggybank-events.blade.php +++ b/app/views/list/piggybank-events.blade.php @@ -5,7 +5,14 @@ @foreach($events as $event)