firefly-iii/app/models/RecurringTransaction.php
2014-12-20 15:00:53 +01:00

121 lines
3.7 KiB
PHP

<?php
use Carbon\Carbon;
use Watson\Validating\ValidatingTrait;
use \Illuminate\Database\Eloquent\Model as Eloquent;
/**
* Class RecurringTransaction
*/
class RecurringTransaction extends Eloquent
{
use ValidatingTrait;
protected $rules
= [
'user_id' => 'required|exists:users,id',
'name' => 'required|between:1,255|min:1',
'match' => 'required',
'amount_max' => 'required|between:0,65536',
'amount_min' => 'required|between:0,65536',
'date' => 'required|date',
'active' => 'between:0,1',
'automatch' => 'between:0,1',
'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly',
'skip' => 'required|between:0,31',];
protected $fillable = ['user_id', 'name', 'match', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', 'active', 'automatch'];
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'date'];
}
/**
* TODO remove this method in favour of something in the FireflyIII libraries.
*
* @return null
*/
public function lastFoundMatch()
{
$last = $this->transactionjournals()->orderBy('date', 'DESC')->first();
if ($last) {
return $last->date;
}
return null;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactionjournals()
{
return $this->hasMany('TransactionJournal');
}
/**
* TODO remove this method in favour of something in the FireflyIII libraries.
*
* Find the next expected match based on the set journals and the date stuff from the recurring
* transaction.
*/
public function nextExpectedMatch()
{
/*
* The date Firefly tries to find. If this stays null, it's "unknown".
*/
$finalDate = null;
if ($this->active == 0) {
return $finalDate;
}
/*
* $today is the start of the next period, to make sure FF3 won't miss anything
* when the current period has a transaction journal.
*/
$today = DateKit::addPeriod(new Carbon, $this->repeat_freq, 0);
/*
* FF3 loops from the $start of the recurring transaction, and to make sure
* $skip works, it adds one (for modulo).
*/
$skip = $this->skip + 1;
$start = DateKit::startOfPeriod(new Carbon, $this->repeat_freq);
/*
* go back exactly one month/week/etc because FF3 does not care about 'next'
* recurring transactions if they're too far into the past.
*/
// echo 'Repeat freq is: ' . $recurringTransaction->repeat_freq . '<br />';
// echo 'Start: ' . $start . ' <br />';
$counter = 0;
while ($start <= $today) {
if (($counter % $skip) == 0) {
// do something.
$end = DateKit::endOfPeriod(clone $start, $this->repeat_freq);
$journalCount = $this->transactionjournals()->before($end)->after($start)->count();
if ($journalCount == 0) {
$finalDate = clone $start;
break;
}
}
// add period for next round!
$start = DateKit::addPeriod($start, $this->repeat_freq, 0);
$counter++;
}
return $finalDate;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
}