mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-01 04:59:25 -06:00
121 lines
3.7 KiB
PHP
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');
|
|
}
|
|
}
|