Work on piggy banks [skip ci]

This commit is contained in:
James Cole 2014-07-31 22:01:52 +02:00
parent 50cfcb8905
commit 706d853b04
12 changed files with 394 additions and 2 deletions

View File

@ -0,0 +1,26 @@
$(function () {
$('input[type="range"]').on('input',inputAmount);
$('input[type="range"]').on('change',changeAmount);
});
function inputAmount(e) {
var target = $(e.target);
var piggyBankId = target.attr('name').substring(6);
var value = target.val();
valueFormatted = '€ ' + (Math.round(value * 100) / 100).toFixed(2);;
console.log(piggyBankId + ': ' + value);
var valueId = 'piggy_'+piggyBankId+'_amount';
$('#' + valueId).text(valueFormatted);
return true;
}
function changeAmount(e) {
console.log('Change!');
}

View File

@ -0,0 +1,13 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear in whatever order it
// gets included (e.g. say you have require_tree . then the code will appear after all the directories
// but before any files alphabetically greater than 'application.js'
//
// The available directives right now are require, require_directory, and require_tree
//
//= require firefly/piggybanks

View File

@ -1,7 +1,30 @@
<?php
class PiggybankController extends BaseController {
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
use Firefly\Storage\Piggybank\PiggybankRepositoryInterface as PRI;
/**
* Class PiggybankController
*/
class PiggybankController extends BaseController
{
protected $_repository;
protected $_accounts;
public function __construct(PRI $repository, ARI $accounts)
{
$this->_repository = $repository;
$this->_accounts = $accounts;
View::share('menu', 'home');
}
public function create()
{
$accounts = $this->_accounts->getActiveDefaultAsSelectList();
return View::make('piggybanks.create')->with('accounts', $accounts);
}
public function delete()
@ -18,6 +41,25 @@ class PiggybankController extends BaseController {
public function index()
{
$count = $this->_repository->count();
$piggybanks = $this->_repository->get();
$accounts = [];
// get accounts:
foreach($piggybanks as $piggyBank) {
$account = $piggyBank->account;
$id = $account->id;
if(!isset($accounts[$id])) {
$account->balance = $account->balance();
$account->left = $account->balance;
} else {
$account->left -= $piggyBank->amount;
}
$accounts[$id] = $account;
}
return View::make('piggybanks.index')->with('count', $count)->with('accounts',$accounts)->with('piggybanks',$piggybanks);
}
public function show()
@ -26,6 +68,15 @@ class PiggybankController extends BaseController {
public function store()
{
$piggyBank = $this->_repository->store(Input::all());
if(!$piggyBank->id) {
Session::flash('error','Could not save piggy bank: ' . $piggyBank->errors()->first());
return Redirect::route('piggybanks.create')->withInput();
} else {
Session::flash('success','New piggy bank created!');
return Redirect::route('piggybanks.index');
}
}
public function update()

View File

@ -0,0 +1,58 @@
<?php
namespace Firefly\Storage\Piggybank;
/**
* Class EloquentLimitRepository
*
* @package Firefly\Storage\Limit
*/
class EloquentPiggybankRepository implements PiggybankRepositoryInterface
{
public function count()
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
)->count();
}
public function find($piggyBankId)
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
)->where('piggybanks.id', $piggyBankId)->first('piggybanks.*');
}
public function get()
{
return \Piggybank::with('account')->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
)->get(['piggybanks.*']);
}
public function store($data)
{
var_dump($data);
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$account = isset($data['account_id']) ? $accounts->find($data['account_id']) : null;
$piggyBank = new \Piggybank;
$piggyBank->account()->associate($account);
$piggyBank->targetdate
= isset($data['targetdate']) && strlen($data['targetdate']) > 0 ? $data['targetdate'] : null;
$piggyBank->name = isset($data['name']) ? $data['name'] : null;
$piggyBank->amount = 0;
$piggyBank->target = floatval($data['target']);
$piggyBank->order = 1;
if ($piggyBank->validate()) {
$piggyBank->save();
}
return $piggyBank;
}
}

View File

@ -0,0 +1,18 @@
<?php
namespace Firefly\Storage\Piggybank;
/**
* Interface LimitRepositoryInterface
*
* @package Firefly\Storage\Limit
*/
interface PiggybankRepositoryInterface
{
public function find($piggyBankId);
public function count();
public function store($data);
public function get();
}

View File

@ -26,6 +26,11 @@ class StorageServiceProvider extends ServiceProvider
'Firefly\Storage\Transaction\EloquentTransactionRepository'
);
$this->app->bind(
'Firefly\Storage\Piggybank\PiggybankRepositoryInterface',
'Firefly\Storage\Piggybank\EloquentPiggybankRepository'
);

21
app/models/Piggybank.php Normal file
View File

@ -0,0 +1,21 @@
<?php
use LaravelBook\Ardent\Ardent as Ardent;
class Piggybank extends Ardent
{
public static $rules
= [
'name' => 'required|between:1,255',
'account_id' => 'required|exists:accounts,id',
'targetdate' => 'date',
'amount' => 'required|min:0',
'target' => 'required|min:1',
'order' => 'required:min:1',
];
public function account()
{
return $this->belongsTo('Account');
}
}

View File

@ -72,6 +72,10 @@ class User extends Ardent implements UserInterface, RemindableInterface
return $this->hasMany('Account');
}
public function piggybanks() {
return $this->hasMany('Piggybank');
}
public function preferences()
{
return $this->hasMany('Preference');

View File

@ -64,6 +64,10 @@ Route::group(['before' => 'auth'], function () {
Route::get('/categories/edit/{category}',['uses' => 'CategoryController@edit','as' => 'categories.edit']);
Route::get('/categories/delete/{category}',['uses' => 'CategoryController@delete','as' => 'categories.delete']);
// piggy bank controller
Route::get('/piggybanks',['uses' => 'PiggybankController@index','as' => 'piggybanks.index']);
Route::get('/piggybanks/create', ['uses' => 'PiggybankController@create','as' => 'piggybanks.create']);
// preferences controller
Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']);
@ -90,6 +94,7 @@ Route::group(['before' => 'auth'], function () {
Route::get('/budgets/edit/{budget}',['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']);
Route::get('/budgets/delete/{budget}',['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']);
// limit controller:
Route::get('/budgets/limits/create/{budget?}',['uses' => 'LimitController@create','as' => 'budgets.limits.create']);
Route::get('/budgets/limits/delete/{limit}',['uses' => 'LimitController@delete','as' => 'budgets.limits.delete']);
@ -130,6 +135,11 @@ Route::group(['before' => 'csrf|auth'], function () {
// migration controller
Route::post('/migrate', ['uses' => 'MigrationController@postIndex']);
// piggy bank controller
Route::post('/piggybanks/store',['uses' => 'PiggybankController@store','as' => 'piggybanks.store']);
// preferences controller
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']);

View File

@ -29,7 +29,7 @@ $r = Route::current()->getName();
<li><a href="{{route('transactions.index')}}"><span class="glyphicon glyphicon-list-alt"></span> Transactions</a></li>
<li class="divider"></li>
<li><a href="#"><span class="glyphicon glyphicon-save"></span> Piggy banks</a></li>
<li><a href="{{route('piggybanks.index')}}"><span class="glyphicon glyphicon-save"></span> Piggy banks</a></li>
</ul>
</li>
</ul>

View File

@ -0,0 +1,116 @@
@extends('layouts.default')
@section('content')
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h1>Firefly
<small>Create a new piggy bank</small>
</h1>
<p class="lead">Create piggy banks to make saving money easier</p>
<p class="text-info">
Saving money is <em>hard</em>. 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.
</p>
</div>
</div>
{{Form::open(['class' => 'form-horizontal','url' => route('piggybanks.store')])}}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<h4>Mandatory fields</h4>
<div class="form-group">
<label for="name" class="col-sm-4 control-label">Name</label>
<div class="col-sm-8">
<input type="text" name="name" class="form-control" id="name" value="{{Input::old('name')}}" placeholder="Name">
@if($errors->has('name'))
<p class="text-danger">{{$errors->first('name')}}</p>
@else
<span class="help-block">For example: new bike, new camera</span>
@endif
</div>
</div>
<div class="form-group">
{{ Form::label('target', 'Target amount', ['class' => 'col-sm-4 control-label'])}}
<div class="col-sm-8">
<div class="input-group">
<span class="input-group-addon">&euro;</span>
{{Form::input('number','target', Input::old('target'), ['step' => 'any', 'min' => '1', 'class' => 'form-control'])}}
</div>
@if($errors->has('target'))
<p class="text-danger">{{$errors->first('target')}}</p>
@else
<span class="help-block">How much money do you need to save?</span>
@endif
</div>
</div>
<div class="form-group">
<label for="account_id" class="col-sm-4 control-label">
Saving account
</label>
<div class="col-sm-8">
{{Form::select('account_id',$accounts,Input::old('account_id') ?: Input::get('account'),['class' => 'form-control'])}}
@if($errors->has('account_id'))
<p class="text-danger">{{$errors->first('account_id')}}</p>
@else
<span class="help-block">Indicate on which account you've got your savings.</span>
@endif
</div>
</div>
</div>
<div class="col-lg-6 col-md-12 col-sm-6">
<h4>Optional fields</h4>
<div class="form-group">
{{ Form::label('targetdate', 'Target date', ['class' => 'col-sm-4 control-label'])}}
<div class="col-sm-8">
{{ Form::input('date','targetdate', Input::old('targetdate') ?: '', ['class'
=> 'form-control']) }}
@if($errors->has('targetdate'))
<p class="text-danger">{{$errors->first('targetdate')}}</p>
@else
<span class="help-block">
If you want to, set a target date. This will inform you how much money you should save to
get to the target amount.
</span>
@endif
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-6">
<!-- add another after this one? -->
<div class="form-group">
<label for="create" class="col-sm-4 control-label">&nbsp;</label>
<div class="col-sm-8">
<div class="checkbox">
<label>
{{Form::checkbox('create',1,Input::old('create') == '1')}}
Create another (return to this form)
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-default btn-success">Create the piggy bank</button>
</div>
</div>
</div>
</div>
{{Form::close()}}
@stop

View File

@ -0,0 +1,70 @@
@extends('layouts.default')
@section('content')
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h1>Firefly
<small>Piggy banks</small>
</h1>
<p class="lead">Set targets and save money</p>
<p class="text-info">
Saving money is <em>hard</em>. 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.
</p>
@if($count == 0)
<p>
<a href="{{route('piggybanks.create')}}" class="btn btn-success">Create new piggy bank</a>
</p>
@endif
</div>
</div>
@if($count > 0)
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<h4>Accounts used for piggy banks</h4>
<table class="table table-striped">
<tr>
<th>Account</th>
<th>Current balance</th>
<th>Left for (other) piggy banks</th>
</tr>
@foreach($accounts as $account)
<tr>
<td>{{{$account->name}}}</td>
<td>{{mf($account->balance())}}</td>
<td>{{mf($account->left)}}</td>
</tr>
@endforeach
</table>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-6 col-sm-12">
<h3>Piggy banks</h3>
@foreach($piggybanks as $piggybank)
<h4>{{{$piggybank->name}}} <small>{{mf($piggybank->target)}}</small></h4>
<table class="table table-bordered">
<tr>
<td style="width:10%;"><span id="piggy_{{$piggybank->id}}_amount">{{mf($piggybank->amount,false)}}</span></td>
<td><input type="range" name="piggy_{{$piggybank->id}}" min="1" max="{{$piggybank->target}}" step="any" value="{{$piggybank->amount}}" /></td>
<td>Y</td>
</tr>
</table>
@endforeach
<p>
<a href="{{route('piggybanks.create')}}" class="btn btn-success">Create new piggy bank</a>
</p>
</div>
</div>
@endif
@stop
@section('scripts')
<?php echo javascript_include_tag('piggybanks'); ?>
@stop