make sure recurrence can skip weekends.

This commit is contained in:
James Cole 2018-06-26 21:17:50 +02:00
parent 49de4f2200
commit 7ba11a57a8
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
7 changed files with 73 additions and 14 deletions

View File

@ -7,10 +7,8 @@ use FireflyIII\Events\RequestedReportOnJournals;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@ -32,8 +30,6 @@ class CreateRecurringTransactions implements ShouldQueue
private $journalRepository;
/** @var RecurringRepositoryInterface */
private $repository;
/** @var UserRepositoryInterface */
private $userRepository;
/**
* Create a new job instance.
@ -46,14 +42,11 @@ class CreateRecurringTransactions implements ShouldQueue
$this->date = $date;
$this->repository = app(RecurringRepositoryInterface::class);
$this->journalRepository = app(JournalRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
}
/**
* Execute the job.
*
* TODO check number of repetitions.
*
* @throws \FireflyIII\Exceptions\FireflyException
*/
public function handle(): void
@ -198,6 +191,13 @@ class CreateRecurringTransactions implements ShouldQueue
}
Log::debug(sprintf('%s IS today (%s)', $date->format('Y-m-d'), $this->date->format('Y-m-d')));
// count created journals on THIS day.
$created = $this->repository->getJournals($recurrence, $date, $date);
if ($created->count() > 0) {
Log::info(sprintf('Already created %d journal(s) for date %s', $created->count(), $date->format('Y-m-d')));
continue;
}
// create transaction array and send to factory.
$array = [
'type' => $recurrence->transactionType->type,
@ -212,7 +212,7 @@ class CreateRecurringTransactions implements ShouldQueue
'piggy_bank_name' => null,
'bill_id' => null,
'bill_name' => null,
'recurrence_id' => $recurrence->id,
'recurrence_id' => (int)$recurrence->id,
// transaction data:
'transactions' => $this->getTransactionData($recurrence),
@ -315,6 +315,14 @@ class CreateRecurringTransactions implements ShouldQueue
return false;
}
// has repeated X times.
$journals = $this->repository->getJournals($recurrence, null, null);
if ($recurrence->repetitions !== 0 && $journals->count() >= $recurrence->repetitions) {
Log::info(sprintf('Recurrence #%d has run %d times, so will run no longer.', $recurrence->id, $recurrence->repetitions));
return false;
}
// is no longer running
if ($this->repeatUntilHasPassed($recurrence)) {
Log::info(

View File

@ -72,6 +72,7 @@ class Recurrence extends Model
'updated_at' => 'datetime',
'deleted_at' => 'datetime',
'title' => 'string',
'id' => 'int',
'description' => 'string',
'first_date' => 'date',
'repeat_until' => 'date',

View File

@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceMeta;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RecurrenceTransactionMeta;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Services\Internal\Destroy\RecurrenceDestroyService;
use FireflyIII\Services\Internal\Update\RecurrenceUpdateService;
use FireflyIII\User;
@ -129,6 +130,34 @@ class RecurringRepository implements RecurringRepositoryInterface
return $return === '' ? null : $return;
}
/**
* Returns the journals created for this recurrence, possibly limited by time.
*
* @param Recurrence $recurrence
* @param Carbon|null $start
* @param Carbon|null $end
*
* @return Collection
*/
public function getJournals(Recurrence $recurrence, Carbon $start = null, Carbon $end = null): Collection
{
$query = TransactionJournal
::leftJoin('journal_meta', 'journal_meta.transaction_journal_id', '=', 'transaction_journals.id')
->where('transaction_journals.user_id', $recurrence->user_id)
->whereNull('transaction_journals.deleted_at')
->where('journal_meta.name', 'recurrence_id')
->where('journal_meta.data', '"' . $recurrence->id . '"');
if (null !== $start) {
$query->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'));
}
if (null !== $end) {
$query->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'));
}
$result = $query->get(['transaction_journals.*']);
return $result;
}
/**
* Get the notes.
*
@ -398,6 +427,8 @@ class RecurringRepository implements RecurringRepositoryInterface
}
break;
}
// filter out all the weekend days:
$return = $this->filterWeekends($repetition, $return);
return $return;
}
@ -512,12 +543,16 @@ class RecurringRepository implements RecurringRepositoryInterface
/** @var Carbon $date */
foreach ($dates as $date) {
$isWeekend = $date->isWeekend();
if (!$isWeekend) {
$return[] = clone $date;
continue;
}
// set back to Friday?
// is weekend and must set back to Friday?
if ($isWeekend && $repetition->weekend === RecurrenceRepetition::WEEKEND_TO_FRIDAY) {
$clone = clone $date;
$clone->subDays(7 - $date->dayOfWeekIso);
$return[] = $clone;
$clone->addDays(5 - $date->dayOfWeekIso);
$return[] = clone $clone;
}
// postpone to Monday?
@ -526,10 +561,12 @@ class RecurringRepository implements RecurringRepositoryInterface
$clone->addDays(8 - $date->dayOfWeekIso);
$return[] = $clone;
}
// otherwise, ignore the date!
}
// filter unique dates?
// filter unique dates
$collection = new Collection($return);
$filtered = $collection->unique();
$return = $filtered->toArray();
return $return;
}

View File

@ -78,6 +78,17 @@ interface RecurringRepositoryInterface
*/
public function getCategory(RecurrenceTransaction $recurrenceTransaction): ?string;
/**
* Returns the journals created for this recurrence, possibly limited by time.
*
* @param Recurrence $recurrence
* @param Carbon|null $start
* @param Carbon|null $end
*
* @return Collection
*/
public function getJournals(Recurrence $recurrence, Carbon $start = null, Carbon $end = null): Collection;
/**
* Get the notes.
*

View File

@ -137,6 +137,7 @@ class RecurrenceTransformer extends TransformerAbstract
'repetition_type' => $repetition->repetition_type,
'repetition_moment' => $repetition->repetition_moment,
'repetition_skip' => (int)$repetition->repetition_skip,
'weekend' => (int)$repetition->weekend,
'description' => $this->repository->repetitionDescription($repetition),
'occurrences' => [],
];

View File

@ -67,6 +67,7 @@ function showRepCalendar() {
newEventsUri += '&end_date=' + $('#ffInput_repeat_until').val();
newEventsUri += '&reps=' + $('#ffInput_repetitions').val();
newEventsUri += '&first_date=' + $('#ffInput_first_date').val();
newEventsUri += '&weekend=' + $('#ffInput_weekend').val();
// remove all event sources from calendar:
calendar.fullCalendar('removeEventSources');

View File

@ -20,8 +20,8 @@
{{ ExpandedForm.date('first_date',null, {helpText: trans('firefly.help_first_date')}) }}
{{ ExpandedForm.select('repetition_type', [], null, {helpText: trans('firefly.change_date_other_options')}) }}
{{ ExpandedForm.number('skip', 0) }}
{{ ExpandedForm.select('repetition_end', repetitionEnds) }}
{{ ExpandedForm.select('weekend', weekendResponses, null, {helpText: trans('firefly.help_weekend')}) }}
{{ ExpandedForm.select('repetition_end', repetitionEnds) }}
{{ ExpandedForm.date('repeat_until',null) }}
{{ ExpandedForm.number('repetitions',null) }}