mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -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\Recurrence;
|
||||||
use FireflyIII\Models\RecurrenceRepetition;
|
use FireflyIII\Models\RecurrenceRepetition;
|
||||||
use FireflyIII\Models\RecurrenceTransaction;
|
use FireflyIII\Models\RecurrenceTransaction;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
@ -32,8 +30,6 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
private $journalRepository;
|
private $journalRepository;
|
||||||
/** @var RecurringRepositoryInterface */
|
/** @var RecurringRepositoryInterface */
|
||||||
private $repository;
|
private $repository;
|
||||||
/** @var UserRepositoryInterface */
|
|
||||||
private $userRepository;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new job instance.
|
* Create a new job instance.
|
||||||
@ -46,14 +42,11 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
$this->date = $date;
|
$this->date = $date;
|
||||||
$this->repository = app(RecurringRepositoryInterface::class);
|
$this->repository = app(RecurringRepositoryInterface::class);
|
||||||
$this->journalRepository = app(JournalRepositoryInterface::class);
|
$this->journalRepository = app(JournalRepositoryInterface::class);
|
||||||
$this->userRepository = app(UserRepositoryInterface::class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the job.
|
* Execute the job.
|
||||||
*
|
*
|
||||||
* TODO check number of repetitions.
|
|
||||||
*
|
|
||||||
* @throws \FireflyIII\Exceptions\FireflyException
|
* @throws \FireflyIII\Exceptions\FireflyException
|
||||||
*/
|
*/
|
||||||
public function handle(): void
|
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')));
|
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.
|
// create transaction array and send to factory.
|
||||||
$array = [
|
$array = [
|
||||||
'type' => $recurrence->transactionType->type,
|
'type' => $recurrence->transactionType->type,
|
||||||
@ -212,7 +212,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
'piggy_bank_name' => null,
|
'piggy_bank_name' => null,
|
||||||
'bill_id' => null,
|
'bill_id' => null,
|
||||||
'bill_name' => null,
|
'bill_name' => null,
|
||||||
'recurrence_id' => $recurrence->id,
|
'recurrence_id' => (int)$recurrence->id,
|
||||||
|
|
||||||
// transaction data:
|
// transaction data:
|
||||||
'transactions' => $this->getTransactionData($recurrence),
|
'transactions' => $this->getTransactionData($recurrence),
|
||||||
@ -315,6 +315,14 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
return false;
|
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
|
// is no longer running
|
||||||
if ($this->repeatUntilHasPassed($recurrence)) {
|
if ($this->repeatUntilHasPassed($recurrence)) {
|
||||||
Log::info(
|
Log::info(
|
||||||
|
@ -72,6 +72,7 @@ class Recurrence extends Model
|
|||||||
'updated_at' => 'datetime',
|
'updated_at' => 'datetime',
|
||||||
'deleted_at' => 'datetime',
|
'deleted_at' => 'datetime',
|
||||||
'title' => 'string',
|
'title' => 'string',
|
||||||
|
'id' => 'int',
|
||||||
'description' => 'string',
|
'description' => 'string',
|
||||||
'first_date' => 'date',
|
'first_date' => 'date',
|
||||||
'repeat_until' => 'date',
|
'repeat_until' => 'date',
|
||||||
|
@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceMeta;
|
|||||||
use FireflyIII\Models\RecurrenceRepetition;
|
use FireflyIII\Models\RecurrenceRepetition;
|
||||||
use FireflyIII\Models\RecurrenceTransaction;
|
use FireflyIII\Models\RecurrenceTransaction;
|
||||||
use FireflyIII\Models\RecurrenceTransactionMeta;
|
use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||||
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Services\Internal\Destroy\RecurrenceDestroyService;
|
use FireflyIII\Services\Internal\Destroy\RecurrenceDestroyService;
|
||||||
use FireflyIII\Services\Internal\Update\RecurrenceUpdateService;
|
use FireflyIII\Services\Internal\Update\RecurrenceUpdateService;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@ -129,6 +130,34 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
return $return === '' ? null : $return;
|
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.
|
* Get the notes.
|
||||||
*
|
*
|
||||||
@ -398,6 +427,8 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// filter out all the weekend days:
|
||||||
|
$return = $this->filterWeekends($repetition, $return);
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@ -512,12 +543,16 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
foreach ($dates as $date) {
|
foreach ($dates as $date) {
|
||||||
$isWeekend = $date->isWeekend();
|
$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) {
|
if ($isWeekend && $repetition->weekend === RecurrenceRepetition::WEEKEND_TO_FRIDAY) {
|
||||||
$clone = clone $date;
|
$clone = clone $date;
|
||||||
$clone->subDays(7 - $date->dayOfWeekIso);
|
$clone->addDays(5 - $date->dayOfWeekIso);
|
||||||
$return[] = $clone;
|
$return[] = clone $clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
// postpone to Monday?
|
// postpone to Monday?
|
||||||
@ -526,10 +561,12 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
$clone->addDays(8 - $date->dayOfWeekIso);
|
$clone->addDays(8 - $date->dayOfWeekIso);
|
||||||
$return[] = $clone;
|
$return[] = $clone;
|
||||||
}
|
}
|
||||||
// otherwise, ignore the date!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter unique dates?
|
// filter unique dates
|
||||||
|
$collection = new Collection($return);
|
||||||
|
$filtered = $collection->unique();
|
||||||
|
$return = $filtered->toArray();
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,17 @@ interface RecurringRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function getCategory(RecurrenceTransaction $recurrenceTransaction): ?string;
|
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.
|
* Get the notes.
|
||||||
*
|
*
|
||||||
|
@ -137,6 +137,7 @@ class RecurrenceTransformer extends TransformerAbstract
|
|||||||
'repetition_type' => $repetition->repetition_type,
|
'repetition_type' => $repetition->repetition_type,
|
||||||
'repetition_moment' => $repetition->repetition_moment,
|
'repetition_moment' => $repetition->repetition_moment,
|
||||||
'repetition_skip' => (int)$repetition->repetition_skip,
|
'repetition_skip' => (int)$repetition->repetition_skip,
|
||||||
|
'weekend' => (int)$repetition->weekend,
|
||||||
'description' => $this->repository->repetitionDescription($repetition),
|
'description' => $this->repository->repetitionDescription($repetition),
|
||||||
'occurrences' => [],
|
'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 += '&end_date=' + $('#ffInput_repeat_until').val();
|
||||||
newEventsUri += '&reps=' + $('#ffInput_repetitions').val();
|
newEventsUri += '&reps=' + $('#ffInput_repetitions').val();
|
||||||
newEventsUri += '&first_date=' + $('#ffInput_first_date').val();
|
newEventsUri += '&first_date=' + $('#ffInput_first_date').val();
|
||||||
|
newEventsUri += '&weekend=' + $('#ffInput_weekend').val();
|
||||||
|
|
||||||
// remove all event sources from calendar:
|
// remove all event sources from calendar:
|
||||||
calendar.fullCalendar('removeEventSources');
|
calendar.fullCalendar('removeEventSources');
|
||||||
|
@ -20,8 +20,8 @@
|
|||||||
{{ ExpandedForm.date('first_date',null, {helpText: trans('firefly.help_first_date')}) }}
|
{{ ExpandedForm.date('first_date',null, {helpText: trans('firefly.help_first_date')}) }}
|
||||||
{{ ExpandedForm.select('repetition_type', [], null, {helpText: trans('firefly.change_date_other_options')}) }}
|
{{ ExpandedForm.select('repetition_type', [], null, {helpText: trans('firefly.change_date_other_options')}) }}
|
||||||
{{ ExpandedForm.number('skip', 0) }}
|
{{ ExpandedForm.number('skip', 0) }}
|
||||||
{{ ExpandedForm.select('repetition_end', repetitionEnds) }}
|
|
||||||
{{ ExpandedForm.select('weekend', weekendResponses, null, {helpText: trans('firefly.help_weekend')}) }}
|
{{ ExpandedForm.select('weekend', weekendResponses, null, {helpText: trans('firefly.help_weekend')}) }}
|
||||||
|
{{ ExpandedForm.select('repetition_end', repetitionEnds) }}
|
||||||
{{ ExpandedForm.date('repeat_until',null) }}
|
{{ ExpandedForm.date('repeat_until',null) }}
|
||||||
{{ ExpandedForm.number('repetitions',null) }}
|
{{ ExpandedForm.number('repetitions',null) }}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user