Now with the added capability of adding money to a piggy bank from a transfer. Also various fixes (see issue #6). [skip ci]

This commit is contained in:
James Cole
2014-08-16 12:13:50 +02:00
parent 7c57ce8504
commit d645a38aec
13 changed files with 239 additions and 211 deletions

View File

@@ -6,6 +6,7 @@ use Firefly\Storage\Piggybank\PiggybankRepositoryInterface as PRI;
/** /**
* Class PiggybankController * Class PiggybankController
*
*/ */
class PiggybankController extends BaseController class PiggybankController extends BaseController
{ {
@@ -63,7 +64,6 @@ class PiggybankController extends BaseController
*/ */
public function destroy(Piggybank $piggyBank) public function destroy(Piggybank $piggyBank)
{ {
// TODO move to repository.
$this->_repository->destroy($piggyBank); $this->_repository->destroy($piggyBank);
Event::fire('piggybanks.change'); Event::fire('piggybanks.change');
Session::flash('success', 'Piggy bank deleted.'); Session::flash('success', 'Piggy bank deleted.');
@@ -96,9 +96,9 @@ class PiggybankController extends BaseController
*/ */
public function index() public function index()
{ {
Event::fire('piggybanks.change');
$countRepeating = $this->_repository->countRepeating(); $countRepeating = $this->_repository->countRepeating();
$countNonRepeating = $this->_repository->countNonrepeating(); $countNonRepeating = $this->_repository->countNonrepeating();
Event::fire('piggybanks.change'); // TODO remove
$piggybanks = $this->_repository->get(); $piggybanks = $this->_repository->get();
return View::make('piggybanks.index')->with('piggybanks', $piggybanks) return View::make('piggybanks.index')->with('piggybanks', $piggybanks)
@@ -111,7 +111,6 @@ class PiggybankController extends BaseController
*/ */
public function show(Piggybank $piggyBank) public function show(Piggybank $piggyBank)
{ {
Event::fire('piggybanks.change'); // TODO remove
return View::make('piggybanks.show')->with('piggyBank', $piggyBank); return View::make('piggybanks.show')->with('piggyBank', $piggyBank);
} }
@@ -159,7 +158,7 @@ class PiggybankController extends BaseController
$data['order'] = 0; $data['order'] = 0;
$piggyBank = $this->_repository->store($data); $piggyBank = $this->_repository->store($data);
if ($piggyBank->validate()) { if ($piggyBank->id) {
Session::flash('success', 'New piggy bank "' . $piggyBank->name . '" created!'); Session::flash('success', 'New piggy bank "' . $piggyBank->name . '" created!');
Event::fire('piggybanks.change'); Event::fire('piggybanks.change');

View File

@@ -37,10 +37,15 @@ class TransactionController extends BaseController
$budgets = $budgetRepository->getAsSelectList(); $budgets = $budgetRepository->getAsSelectList();
$budgets[0] = '(no budget)'; $budgets[0] = '(no budget)';
// get the number of piggy banks.
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
$piggyRepository = App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
$piggies = $piggyRepository->get();
return View::make('transactions.create')->with('accounts', $accounts)->with('budgets', $budgets)->with( return View::make('transactions.create')->with('accounts', $accounts)->with('budgets', $budgets)->with(
'what', $what 'what', $what
); )->with('piggies',$piggies);
} }
/** /**

View File

@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateTransactionsTable extends Migration class CreateTransactionsTable extends Migration
{ {
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('transactions');
}
/** /**
* Run the migrations. * Run the migrations.
* *
@@ -23,6 +33,7 @@ class CreateTransactionsTable extends Migration
$table->increments('id'); $table->increments('id');
$table->timestamps(); $table->timestamps();
$table->integer('account_id')->unsigned(); $table->integer('account_id')->unsigned();
$table->integer('piggybank_id')->nullable()->unsigned();
$table->integer('transaction_journal_id')->unsigned(); $table->integer('transaction_journal_id')->unsigned();
$table->string('description', 255)->nullable(); $table->string('description', 255)->nullable();
$table->decimal('amount', 10, 2); $table->decimal('amount', 10, 2);
@@ -32,6 +43,11 @@ class CreateTransactionsTable extends Migration
->references('id')->on('transaction_journals') ->references('id')->on('transaction_journals')
->onDelete('cascade'); ->onDelete('cascade');
// connect piggy banks
$table->foreign('piggybank_id')
->references('id')->on('piggybanks')
->onDelete('set null');
// connect account id: // connect account id:
$table->foreign('account_id') $table->foreign('account_id')
->references('id')->on('accounts') ->references('id')->on('accounts')
@@ -41,14 +57,4 @@ class CreateTransactionsTable extends Migration
); );
} }
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('transactions');
}
} }

View File

@@ -1,43 +1,45 @@
<?php <?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreatePiggyInstance extends Migration { class CreatePiggyInstance extends Migration
{
/** /**
* Run the migrations. * Run the migrations.
* *
* @return void * @return void
*/ */
public function up() public function up()
{ {
Schema::create('piggybank_repetitions', function(Blueprint $table) Schema::create(
{ 'piggybank_repetitions', function (Blueprint $table) {
$table->increments('id'); $table->increments('id');
$table->timestamps(); $table->timestamps();
$table->integer('piggybank_id')->unsigned(); $table->integer('piggybank_id')->unsigned();
$table->date('startdate')->nullable(); $table->date('startdate')->nullable();
$table->date('targetdate')->nullable(); $table->date('targetdate')->nullable();
$table->decimal('currentamount',10,2); $table->decimal('currentamount', 10, 2);
$table->unique(['piggybank_id','startdate','targetdate']); $table->unique(['piggybank_id', 'startdate', 'targetdate']);
// connect instance to piggybank. // connect instance to piggybank.
$table->foreign('piggybank_id') $table->foreign('piggybank_id')
->references('id')->on('piggybanks') ->references('id')->on('piggybanks')
->onDelete('cascade'); ->onDelete('cascade');
}); }
} );
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
* @return void * @return void
*/ */
public function down() public function down()
{ {
Schema::drop('piggybank_repetitions'); Schema::drop('piggybank_repetitions');
} }
} }

View File

@@ -114,6 +114,8 @@ class Chart implements ChartInterface
$q->where('startdate', $start->format('Y-m-d')); $q->where('startdate', $start->format('Y-m-d'));
}] }]
)->orderBy('name', 'ASC')->get(); )->orderBy('name', 'ASC')->get();
$limitInPeriod = '';
$spentInPeriod = '';
foreach ($budgets as $budget) { foreach ($budgets as $budget) {
$budget->count = 0; $budget->count = 0;

View File

@@ -16,6 +16,9 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
*/ */
public function createOrFind($name) public function createOrFind($name)
{ {
if(strlen($name) == 0) {
return null;
}
$category = $this->findByName($name); $category = $this->findByName($name);
if (!$category) { if (!$category) {
return $this->store(['name' => $name]); return $this->store(['name' => $name]);
@@ -55,7 +58,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
*/ */
public function findByName($name) public function findByName($name)
{ {
if ($name == '') { if ($name == '' || strlen($name) == 0) {
return null; return null;
} }

View File

@@ -163,20 +163,15 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
$piggy->startdate $piggy->startdate
= isset($data['startdate']) && strlen($data['startdate']) > 0 ? new Carbon($data['startdate']) : null; = isset($data['startdate']) && strlen($data['startdate']) > 0 ? new Carbon($data['startdate']) : null;
// everything we can update for NON repeating piggy banks: foreach ($piggy->piggybankrepetitions()->get() as $rep) {
if ($piggy->repeats == 0) { $rep->delete();
// if non-repeating there is only one PiggyBank instance and we can delete it safely. }
// it will be recreated.
$piggy->piggybankrepetitions()->first()->delete();
} else {
// we can delete all of them, because reasons
foreach ($piggy->piggybankrepetitions()->get() as $rep) {
$rep->delete();
}
if ($piggy->repeats == 1) {
$piggy->rep_every = intval($data['rep_every']); $piggy->rep_every = intval($data['rep_every']);
$piggy->rep_length = $data['rep_length']; $piggy->rep_length = $data['rep_length'];
} }
if ($piggy->validate()) { if ($piggy->validate()) {
// check the things we check for new piggies // check the things we check for new piggies
$piggy->save(); $piggy->save();

View File

@@ -34,8 +34,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
* A gains 200 (200). * -1 * A gains 200 (200). * -1
* B loses 200 (-200). * 1 * B loses 200 (-200). * 1
* *
* @param \Account $from * @param \Account $from
* @param \Account $toAccount * @param \Account $toAccount
* @param $description * @param $description
* @param $amount * @param $amount
* @param \Carbon\Carbon $date * @param \Carbon\Carbon $date
@@ -287,6 +287,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
case 'transfer': case 'transfer':
$fromAccount = $accountRepository->find(intval($data['account_from_id'])); $fromAccount = $accountRepository->find(intval($data['account_from_id']));
$toAccount = $accountRepository->find(intval($data['account_to_id'])); $toAccount = $accountRepository->find(intval($data['account_to_id']));
break; break;
} }
// fall back to cash if necessary: // fall back to cash if necessary:
@@ -310,6 +312,39 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
return $transactionJournal; return $transactionJournal;
} }
// here we're done and we have transactions in the journal:
// do something with the piggy bank:
if ($what == 'transfer') {
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
$piggyRepository = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
if (isset($data['piggybank_id'])) {
/** @var \Piggybank $piggyBank */
$piggyBank = $piggyRepository->find(intval($data['piggybank_id']));
if ($piggyBank) {
if ($toAccount->id == $piggyBank->account_id) {
// find the transaction connected to the $toAccount:
/** @var \Transaction $transaction */
$transaction
= $transactionJournal->transactions()->where('account_id', $toAccount->id)->first();
// connect the piggy to it:
$transaction->piggybank()->associate($piggyBank);
$transaction->save();
} else {
\Session::flash(
'warning',
'Piggy bank "' . e($piggyBank->name) . '" is not set to draw money from account "' . e(
$toAccount->name
) . '", so the money isn\'t added to the piggy bank.'
);
}
}
}
}
// attach: // attach:
if (!is_null($budget)) { if (!is_null($budget)) {
$transactionJournal->budgets()->save($budget); $transactionJournal->budgets()->save($budget);
@@ -390,10 +425,13 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
break; break;
case 'Transfer': case 'Transfer':
// means transaction[0] is account that sent the money (from). // means transaction[0] is account that sent the money (from).
/** @var \Account $fromAccount */
$fromAccount = $accountRepository->find($data['account_from_id']); $fromAccount = $accountRepository->find($data['account_from_id']);
/** @var \Account $toAccount */
$toAccount = $accountRepository->find($data['account_to_id']); $toAccount = $accountRepository->find($data['account_to_id']);
$journal->transactions[0]->account()->associate($fromAccount); $journal->transactions[0]->account()->associate($fromAccount);
$journal->transactions[1]->account()->associate($toAccount); $journal->transactions[1]->account()->associate($toAccount);
break; break;
default: default:
throw new FireflyException('Cannot edit this!'); throw new FireflyException('Cannot edit this!');

View File

@@ -45,6 +45,24 @@ class EloquentPiggybankTrigger
} catch (QueryException $e) { } catch (QueryException $e) {
} }
} }
// whatever we did here, we now have all repetitions for this
// piggy bank, and we can find transactions that fall within
// that repetition (to fix the "saved amount".
$reps = $piggy->piggybankrepetitions()->get();
/** @var \PiggybankRepetition $rep */
foreach ($reps as $rep) {
$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);
$rep->save();
}
} }
unset($piggy, $piggybanks, $rep); unset($piggy, $piggybanks, $rep);
@@ -59,14 +77,8 @@ class EloquentPiggybankTrigger
$rep->targetdate = $repeated->targetdate; $rep->targetdate = $repeated->targetdate;
$rep->currentamount = 0; $rep->currentamount = 0;
try { try {
\Log::debug(
'Creating initial rep ('.$repeated->name.') (from ' . ($rep->startdate ? $rep->startdate->format('d-m-Y')
: 'NULL') . ' to '
. ($rep->targetdate ? $rep->targetdate->format('d-m-Y') : 'NULL') . ')'
);
$rep->save(); $rep->save();
} catch (QueryException $e) { } catch (QueryException $e) {
\Log::error('FAILED initital repetition.');
} }
unset($rep); unset($rep);
@@ -109,6 +121,19 @@ class EloquentPiggybankTrigger
} }
} }
} }
$reps = $repeated->piggybankrepetitions()->get();
/** @var \PiggybankRepetition $rep */
foreach ($reps as $rep) {
$sum = \Transaction::where('piggybank_id', $repeated->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);
$rep->save();
}
} }
} }
} }

View File

@@ -52,22 +52,6 @@ class Transaction extends Ardent
return $this->belongsTo('Account'); return $this->belongsTo('Account');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionJournal()
{
return $this->belongsTo('TransactionJournal');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function components()
{
return $this->belongsToMany('Component');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/ */
@@ -83,4 +67,28 @@ class Transaction extends Ardent
{ {
return $this->belongsToMany('Category', 'component_transaction', 'transaction_id', 'component_id'); return $this->belongsToMany('Category', 'component_transaction', 'transaction_id', 'component_id');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function components()
{
return $this->belongsToMany('Component');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function piggybank()
{
return $this->belongsTo('Piggybank');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionJournal()
{
return $this->belongsTo('TransactionJournal');
}
} }

View File

@@ -3,91 +3,6 @@
use LaravelBook\Ardent\Ardent; use LaravelBook\Ardent\Ardent;
/**
* TransactionJournal
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $transaction_type_id
* @property integer $transaction_currency_id
* @property string $description
* @property boolean $completed
* @property \Carbon\Carbon $date
* @property-read \TransactionType $transactionType
* @property-read \TransactionCurrency $transactionCurrency
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereTransactionCurrencyId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value)
* @method static \TransactionJournal after($date)
* @method static \TransactionJournal before($date)
* @property integer $user_id
* @property-read \User $user
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUserId($value)
* @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
* @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
* @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
* @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
* @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
* @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 class TransactionJournal extends Ardent
{ {
@@ -117,49 +32,6 @@ class TransactionJournal extends Ardent
]; ];
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionType()
{
return $this->belongsTo('TransactionType');
}
/**
* User
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionCurrency()
{
return $this->belongsTo('TransactionCurrency');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('Transaction');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function components()
{
return $this->belongsToMany('Component');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/ */
@@ -180,6 +52,14 @@ class TransactionJournal extends Ardent
); );
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function components()
{
return $this->belongsToMany('Component');
}
/** /**
* @return array * @return array
*/ */
@@ -210,4 +90,38 @@ class TransactionJournal extends Ardent
return $query->where('date', '<=', $date->format('Y-m-d')); return $query->where('date', '<=', $date->format('Y-m-d'));
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionCurrency()
{
return $this->belongsTo('TransactionCurrency');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionType()
{
return $this->belongsTo('TransactionType');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('Transaction');
}
/**
* User
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
} }

View File

@@ -175,6 +175,37 @@
</div> </div>
</div> </div>
<!-- RELATE THIS TRANSFER TO A PIGGY BANK -->
@if($what == 'transfer' && count($piggies) > 0)
<div class="form-group">
<label for="piggybank_id" class="col-sm-4 control-label">
Piggy bank
</label>
<div class="col-sm-8">
<select name="piggybank_id" class="form-control">
<option value="0" label="(no piggy bank)">(no piggy bank)</option>
@foreach($piggies as $piggy)
@if($piggy->id == Input::old('piggybank_id'))
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}" selected="selected ">{{{$piggy->name}}}</option>
@else
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}">{{{$piggy->name}}}</option>
@endif
@endforeach
</select>
@if($errors->has('piggybank_id'))
<p class="text-danger">{{$errors->first('piggybank_id')}}</p>
@else
<span class="help-block">
You can directly add the amount you're transferring
to one of your piggy banks, provided they are related to the account your
transferring <em>to</em>.
</span>
@endif
</div>
</div>
@endif
</div> </div>
</div> </div>