mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-11-26 19:00:22 -06:00
make sure recurrence can skip weekends.
This commit is contained in:
parent
49de4f2200
commit
7ba11a57a8
@ -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(
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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' => [],
|
||||
];
|
||||
|
1
public/js/ff/recurring/edit.js
vendored
1
public/js/ff/recurring/edit.js
vendored
@ -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');
|
||||
|
@ -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) }}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user