mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-04 03:43:07 +00:00
Added the ability to manually add or remove money from piggy banks (issue #6) [skip ci]
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Firefly\Exception\FireflyException;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
use Firefly\Storage\Piggybank\PiggybankRepositoryInterface as PRI;
|
||||
|
||||
@@ -24,6 +24,20 @@ class PiggybankController extends BaseController
|
||||
$this->_accounts = $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Piggybank $piggyBank
|
||||
*/
|
||||
public function addMoney(Piggybank $piggyBank)
|
||||
{
|
||||
$what = 'add';
|
||||
$maxAdd = $this->_repository->leftOnAccount($piggyBank->account);
|
||||
$maxRemove = null;
|
||||
|
||||
return View::make('piggybanks.modifyAmount')->with('what', $what)->with('maxAdd', $maxAdd)->with(
|
||||
'maxRemove', $maxRemove
|
||||
)->with('piggybank', $piggyBank);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
@@ -46,7 +60,6 @@ class PiggybankController extends BaseController
|
||||
return View::make('piggybanks.create-repeated')->with('accounts', $accounts)->with('periods', $periods);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Piggybank $piggyBank
|
||||
*
|
||||
@@ -101,11 +114,57 @@ class PiggybankController extends BaseController
|
||||
$countNonRepeating = $this->_repository->countNonrepeating();
|
||||
|
||||
$piggybanks = $this->_repository->get();
|
||||
|
||||
return View::make('piggybanks.index')->with('piggybanks', $piggybanks)
|
||||
->with('countRepeating', $countRepeating)
|
||||
->with('countNonRepeating', $countNonRepeating);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Piggybank $piggyBank
|
||||
*/
|
||||
public function modMoney(Piggybank $piggyBank)
|
||||
{
|
||||
var_dump(Input::all());
|
||||
$amount = floatval(Input::get('amount'));
|
||||
switch (Input::get('what')) {
|
||||
default:
|
||||
throw new FireflyException('No such action');
|
||||
break;
|
||||
case 'add':
|
||||
$maxAdd = $this->_repository->leftOnAccount($piggyBank->account);
|
||||
if ($amount <= min($maxAdd, $piggyBank->targetamount)) {
|
||||
Session::flash('success','Amount updated!');
|
||||
$this->_repository->modifyAmount($piggyBank, $amount);
|
||||
} else {
|
||||
Session::flash('warning','Could not!');
|
||||
}
|
||||
break;
|
||||
case 'remove':
|
||||
$maxRemove = $piggyBank->currentRelevantRep()->currentamount;
|
||||
if($amount <= $maxRemove) {
|
||||
$this->_repository->modifyAmount($piggyBank, ($amount * -1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Redirect::route('piggybanks.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Piggybank $piggyBank
|
||||
*/
|
||||
public function removeMoney(Piggybank $piggyBank)
|
||||
{
|
||||
$what = 'remove';
|
||||
$maxAdd = $this->_repository->leftOnAccount($piggyBank->account);
|
||||
$maxRemove = $piggyBank->currentRelevantRep()->currentamount;
|
||||
|
||||
return View::make('piggybanks.modifyAmount')->with('what', $what)->with('maxAdd', $maxAdd)->with(
|
||||
'maxRemove', $maxRemove
|
||||
)->with('piggybank', $piggyBank);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
@@ -69,7 +69,51 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return \Auth::user()->piggybanks()->with(['account', 'piggybankrepetitions'])->get();
|
||||
$piggies = \Auth::user()->piggybanks()->with(['account', 'piggybankrepetitions'])->get();
|
||||
|
||||
foreach($piggies as $pig) {
|
||||
$pig->leftInAccount = $this->leftOnAccount($pig->account);
|
||||
}
|
||||
return $piggies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Account $account
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function leftOnAccount(\Account $account)
|
||||
{
|
||||
$balance = $account->balance();
|
||||
/** @var \Piggybank $p */
|
||||
foreach ($account->piggybanks()->get() as $p) {
|
||||
$balance -= $p->currentRelevantRep()->currentamount;
|
||||
}
|
||||
|
||||
return $balance;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \Piggybank $piggyBank
|
||||
* @param $amount
|
||||
*
|
||||
* @return bool|mixed
|
||||
*/
|
||||
public function modifyAmount(\Piggybank $piggyBank, $amount)
|
||||
{
|
||||
$rep = $piggyBank->currentRelevantRep();
|
||||
\Log::debug('Amount before: ' . $rep->currentamount);
|
||||
$rep->currentamount += $amount;
|
||||
\Log::debug('Amount after: ' . $rep->currentamount);
|
||||
\Log::debug('validates: ' . $rep->validate());
|
||||
\Log::debug(print_r($rep->toArray(),true));
|
||||
$rep->save();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,18 +226,4 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Piggybank $piggyBank
|
||||
* @param $amount
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
public function updateAmount(\Piggybank $piggyBank, $amount)
|
||||
{
|
||||
$piggyBank->amount = floatval($amount);
|
||||
if ($piggyBank->validate()) {
|
||||
$piggyBank->save();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -45,6 +45,23 @@ interface PiggybankRepositoryInterface
|
||||
*/
|
||||
public function get();
|
||||
|
||||
/**
|
||||
* Will tell you how much money is left on this account.
|
||||
*
|
||||
* @param \Account $account
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function leftOnAccount(\Account $account);
|
||||
|
||||
/**
|
||||
* @param \Piggybank $piggyBank
|
||||
* @param $amount
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function modifyAmount(\Piggybank $piggyBank, $amount);
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
*
|
||||
@@ -60,12 +77,5 @@ interface PiggybankRepositoryInterface
|
||||
*/
|
||||
public function update(\Piggybank $piggy, $data);
|
||||
|
||||
/**
|
||||
* @param \Piggybank $piggyBank
|
||||
* @param $amount
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateAmount(\Piggybank $piggyBank, $amount);
|
||||
|
||||
}
|
@@ -52,12 +52,15 @@ class EloquentPiggybankTrigger
|
||||
$reps = $piggy->piggybankrepetitions()->get();
|
||||
/** @var \PiggybankRepetition $rep */
|
||||
foreach ($reps as $rep) {
|
||||
$sum = \Transaction::where('piggybank_id', $piggy->id)->leftJoin(
|
||||
if ($rep->currentamount == 0) {
|
||||
$sum = \Transaction::where('piggybank_id', $piggy->id)->leftJoin(
|
||||
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
|
||||
)->where('transaction_journals.date', '>=', $rep->startdate->format('Y-m-d'))->where(
|
||||
'transaction_journals.date', '<=', $rep->targetdate->format('Y-m-d')
|
||||
)->sum('transactions.amount');
|
||||
$rep->currentamount = floatval($sum);
|
||||
'transaction_journals.date', '<=', $rep->targetdate->format('Y-m-d')
|
||||
)->sum('transactions.amount');
|
||||
|
||||
$rep->currentamount = floatval($sum);
|
||||
}
|
||||
$rep->save();
|
||||
|
||||
|
||||
|
@@ -92,6 +92,14 @@ class Account extends Ardent
|
||||
return $this->hasMany('Transaction');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function piggybanks()
|
||||
{
|
||||
return $this->hasMany('Piggybank');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Carbon\Carbon $date
|
||||
*
|
||||
|
@@ -177,6 +177,8 @@ class Piggybank extends Ardent
|
||||
|
||||
/**
|
||||
* Grabs the PiggyBankRepetition that's currently relevant / active
|
||||
*
|
||||
* @returns \PiggybankRepetition
|
||||
*/
|
||||
public function currentRelevantRep() {
|
||||
return $this->piggybankrepetitions()
|
||||
|
@@ -137,6 +137,10 @@ Route::group(['before' => 'auth'], function () {
|
||||
Route::get('/piggybanks',['uses' => 'PiggybankController@index','as' => 'piggybanks.index']);
|
||||
Route::get('/piggybanks/create/piggybank', ['uses' => 'PiggybankController@createPiggybank','as' => 'piggybanks.create.piggybank']);
|
||||
Route::get('/piggybanks/create/repeated', ['uses' => 'PiggybankController@createRepeated','as' => 'piggybanks.create.repeated']);
|
||||
|
||||
Route::get('/piggybanks/addMoney/{piggybank}', ['uses' => 'PiggybankController@addMoney','as' => 'piggybanks.amount.add']);
|
||||
Route::get('/piggybanks/removeMoney/{piggybank}', ['uses' => 'PiggybankController@removeMoney','as' => 'piggybanks.amount.remove']);
|
||||
|
||||
Route::get('/piggybanks/show/{piggybank}', ['uses' => 'PiggybankController@show','as' => 'piggybanks.show']);
|
||||
Route::get('/piggybanks/edit/{piggybank}', ['uses' => 'PiggybankController@edit','as' => 'piggybanks.edit']);
|
||||
Route::get('/piggybanks/delete/{piggybank}', ['uses' => 'PiggybankController@delete','as' => 'piggybanks.delete']);
|
||||
@@ -204,6 +208,8 @@ Route::group(['before' => 'csrf|auth'], function () {
|
||||
Route::post('/piggybanks/store/repeated',['uses' => 'PiggybankController@storeRepeated','as' => 'piggybanks.store.repeated']);
|
||||
Route::post('/piggybanks/update/{piggybank}', ['uses' => 'PiggybankController@update','as' => 'piggybanks.update']);
|
||||
Route::post('/piggybanks/destroy/{piggybank}', ['uses' => 'PiggybankController@destroy','as' => 'piggybanks.destroy']);
|
||||
Route::post('/piggybanks/mod/{piggybank}', ['uses' => 'PiggybankController@modMoney','as' => 'piggybanks.modMoney']);
|
||||
|
||||
|
||||
// preferences controller
|
||||
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']);
|
||||
|
@@ -66,9 +66,17 @@
|
||||
@endif
|
||||
|
||||
</p>
|
||||
<div class="btn-group-xs btn-group">
|
||||
<div class="btn-group-sm btn-group">
|
||||
<a href="{{route('piggybanks.edit',$piggyBank->id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></span></a>
|
||||
@if($piggyBank->leftInAccount > 0)
|
||||
<a data-toggle="modal" href="{{route('piggybanks.amount.add',$piggyBank->id)}}" data-target="#modal" class="btn btn-default"><span class="glyphicon glyphicon-plus-sign"></span> Add money</a>
|
||||
@endif
|
||||
@if($piggyBank->currentRelevantRep()->currentamount > 0)
|
||||
<a data-toggle="modal" href="{{route('piggybanks.amount.remove',$piggyBank->id)}}" data-target="#modal" class="btn btn-default"><span class="glyphicon glyphicon-minus-sign"></span> Remove money</a>
|
||||
@endif
|
||||
<a href="{{route('piggybanks.delete',$piggyBank->id)}}" class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span></a>
|
||||
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -114,9 +122,16 @@
|
||||
|
||||
|
||||
</p>
|
||||
<div class="btn-group-xs btn-group">
|
||||
<a href="{{route('piggybanks.edit',$repeated->id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></span></a>
|
||||
<a href="{{route('piggybanks.delete',$repeated->id)}}" class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span></a>
|
||||
<div class="btn-group btn-group-sm">
|
||||
<a href="{{route('piggybanks.edit',$piggyBank->id)}}" class="btn btn-default"><span class="glyphicon glyphicon-pencil"></span></a>
|
||||
@if($piggyBank->leftInAccount > 0)
|
||||
<a data-toggle="modal" href="{{route('piggybanks.amount.add',$piggyBank->id)}}" data-target="#modal" class="btn btn-default"><span class="glyphicon glyphicon-plus-sign"></span> Add money</a>
|
||||
@endif
|
||||
@if($piggyBank->currentRelevantRep()->currentamount > 0)
|
||||
<a data-toggle="modal" href="{{route('piggybanks.amount.remove',$piggyBank->id)}}" data-target="#modal" class="btn btn-default"><span class="glyphicon glyphicon-minus-sign"></span> Remove money</a>
|
||||
@endif
|
||||
<a href="{{route('piggybanks.delete',$piggyBank->id)}}" class="btn btn-danger"><span class="glyphicon glyphicon-trash"></span></a>
|
||||
|
||||
</div>
|
||||
</td></tr>
|
||||
@endif
|
||||
@@ -125,6 +140,18 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL -->
|
||||
<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
<?php echo javascript_include_tag('piggybanks'); ?>
|
||||
|
62
app/views/piggybanks/modifyAmount.blade.php
Normal file
62
app/views/piggybanks/modifyAmount.blade.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
|
||||
<h4 class="modal-title" id="myModalLabel">
|
||||
@if($what == 'add')
|
||||
Add money to "{{{$piggybank->name}}}"
|
||||
@else
|
||||
Remove money from "{{{$piggybank->name}}}"
|
||||
@endif
|
||||
</h4>
|
||||
</div>
|
||||
<form style="display: inline;" action="{{route('piggybanks.modMoney',$piggybank->id)}}" method="POST">
|
||||
<input type="hidden" name="what" value="{{$what}}" />
|
||||
{{Form::token()}}
|
||||
<div class="modal-body">
|
||||
<p class="text-info">
|
||||
@if($what == 'add')
|
||||
Usually you would add money to this
|
||||
@if($piggybank->repeated == 1)
|
||||
repeated expense
|
||||
@else
|
||||
piggy bank
|
||||
@endif
|
||||
by transferring it from one of your accounts to "{{{$piggybank->account->name}}}". However,
|
||||
since there is still {{mf($maxAdd)}} on that account not locked in any piggy bank or repeated expense,
|
||||
you can also add it manually.
|
||||
|
||||
@else
|
||||
|
||||
If you need the money in this
|
||||
@if($piggybank->repeated == 1)
|
||||
repeated expense
|
||||
@else
|
||||
piggy bank
|
||||
@endif
|
||||
for something else, you can opt to remove it using this form. Since there is {{mf($maxRemove)}} in this
|
||||
@if($piggybank->repeated == 1)
|
||||
repeated expense
|
||||
@else
|
||||
piggy bank
|
||||
@endif
|
||||
that is the maximum amount of money you can remove using this form.
|
||||
@endif
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label for="amount">Amount to {{$what}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">€</div>
|
||||
@if($what == 'add')
|
||||
<input type="number" step="any" max="{{min($maxAdd,$piggybank->targetamount)}}" min="0.01" class="form-control" id="amount" name="amount">
|
||||
@else
|
||||
<input type="number" step="any" max="{{$maxRemove}}" min="0.01" class="form-control" id="amount" name="amount">
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<input type="submit" class="btn btn-primary" value="Submit" name="submit" />
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -5,6 +5,12 @@
|
||||
<h1>Firefly
|
||||
<small>Piggy bank "{{{$piggyBank->name}}}"</small>
|
||||
</h1>
|
||||
<p>
|
||||
<a href="{{route('accounts.show',$piggyBank->account_id)}}">{{{$piggyBank->account->name}}}</a> has
|
||||
a balance of {{mf($piggyBank->account->balance())}}.
|
||||
Of that {{mf($piggyBank->account->balance())}}, you have {{mf(0)}} not yet locked up in other piggy banks.
|
||||
You can add {{mf(max(0,1))}} to this piggy bank.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
Reference in New Issue
Block a user