diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f9fba1df4b..a9d5b137c3 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -64,15 +64,5 @@ class Kernel extends ConsoleKernel { // create recurring transactions. $schedule->job(new CreateRecurringTransactions(new Carbon))->daily(); - - // send test email. - $schedule->call( - function () { - $ipAddress = '127.0.0.1'; - /** @var User $user */ - $user = User::find(1); - event(new AdminRequestedTestMessage($user, $ipAddress)); - } - )->daily(); } } diff --git a/app/Http/Controllers/Recurring/CreateController.php b/app/Http/Controllers/Recurring/CreateController.php index 3a75c998fc..817f6f73dd 100644 --- a/app/Http/Controllers/Recurring/CreateController.php +++ b/app/Http/Controllers/Recurring/CreateController.php @@ -27,6 +27,7 @@ namespace FireflyIII\Http\Controllers\Recurring; use Carbon\Carbon; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RecurrenceFormRequest; +use FireflyIII\Models\RecurrenceRepetition; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use Illuminate\Http\Request; @@ -89,10 +90,17 @@ class CreateController extends Controller 'until_date' => trans('firefly.repeat_until_date'), 'times' => trans('firefly.repeat_times'), ]; + // what to do in the weekend? + $weekendResponses = [ + RecurrenceRepetition::WEEKEND_DO_NOTHING => trans('firefly.do_nothing'), + RecurrenceRepetition::WEEKEND_SKIP_CREATION => trans('firefly.skip_transaction'), + RecurrenceRepetition::WEEKEND_TO_FRIDAY => trans('firefly.jump_to_friday'), + RecurrenceRepetition::WEEKEND_TO_MONDAY => trans('firefly.jump_to_monday'), + ]; // flash some data: $hasOldInput = null !== $request->old('_token'); - $preFilled = [ + $preFilled = [ 'first_date' => $tomorrow->format('Y-m-d'), 'transaction_type' => $hasOldInput ? $request->old('transaction_type') : 'withdrawal', 'active' => $hasOldInput ? (bool)$request->old('active') : true, @@ -100,7 +108,9 @@ class CreateController extends Controller ]; $request->session()->flash('preFilled', $preFilled); - return view('recurring.create', compact('tomorrow', 'oldRepetitionType', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets')); + return view( + 'recurring.create', compact('tomorrow', 'oldRepetitionType', 'weekendResponses', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets') + ); } /** diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index b7e2884a58..69f5847d95 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -110,6 +110,7 @@ class IndexController extends Controller $repetition->repetition_type = $repetitionType; $repetition->repetition_moment = $repetitionMoment; $repetition->repetition_skip = (int)$request->get('skip'); + $repetition->weekend = (int)$request->get('weekend'); $actualEnd = clone $end; switch ($endsAt) { @@ -222,8 +223,9 @@ class IndexController extends Controller 'daily' => ['label' => trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')], $weekly => ['label' => trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]), 'selected' => 0 === strpos($preSelected, 'weekly')], $monthly => ['label' => trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]), 'selected' => 0 === strpos($preSelected, 'monthly')], - $ndom => ['label' => trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]),'selected' => 0 === strpos($preSelected, 'ndom')], - $yearly => ['label' => trans('firefly.recurring_yearly', ['date' => $yearlyDate]),'selected' => 0 === strpos($preSelected, 'yearly')], + $ndom => ['label' => trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]), + 'selected' => 0 === strpos($preSelected, 'ndom')], + $yearly => ['label' => trans('firefly.recurring_yearly', ['date' => $yearlyDate]), 'selected' => 0 === strpos($preSelected, 'yearly')], ]; } diff --git a/app/Jobs/CreateRecurringTransactions.php b/app/Jobs/CreateRecurringTransactions.php index 45cfe72936..5c378811d4 100644 --- a/app/Jobs/CreateRecurringTransactions.php +++ b/app/Jobs/CreateRecurringTransactions.php @@ -89,7 +89,7 @@ class CreateRecurringTransactions implements ShouldQueue Log::debug('Now running report thing.'); // will now send email to users. foreach ($result as $userId => $journals) { - // random bunch to make mail. + //// random bunch to make mail. $journals = TransactionJournal::where('user_id', $userId)->inRandomOrder()->take(1)->get(); event(new RequestedReportOnJournals($userId, $journals)); } diff --git a/app/Models/RecurrenceRepetition.php b/app/Models/RecurrenceRepetition.php index 48f3eb93ff..6164e38b99 100644 --- a/app/Models/RecurrenceRepetition.php +++ b/app/Models/RecurrenceRepetition.php @@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property string $repetition_type * @property string $repetition_moment * @property int $repetition_skip + * @property int $weekend * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $deleted_at * @property \Carbon\Carbon $updated_at @@ -41,10 +42,18 @@ use Illuminate\Database\Eloquent\SoftDeletes; */ class RecurrenceRepetition extends Model { + /** @var int */ + public const WEEKEND_DO_NOTHING = 1; + /** @var int */ + public const WEEKEND_SKIP_CREATION = 2; + /** @var int */ + public const WEEKEND_TO_FRIDAY = 3; + /** @var int */ + public const WEEKEND_TO_MONDAY = 4; use SoftDeletes; /** @var array */ protected $casts - = [ + = [ 'created_at' => 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', @@ -52,7 +61,7 @@ class RecurrenceRepetition extends Model 'repetition_moment' => 'string', 'repetition_skip' => 'int', ]; - protected $fillable = ['recurrence_id', 'repetition_type', 'repetition_moment', 'repetition_skip']; + protected $fillable = ['recurrence_id', 'weekend', 'repetition_type', 'repetition_moment', 'repetition_skip']; /** @var string */ protected $table = 'recurrences_repetitions'; diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php index 18418c9034..024f3fb14a 100644 --- a/app/Repositories/Recurring/RecurringRepository.php +++ b/app/Repositories/Recurring/RecurringRepository.php @@ -262,6 +262,8 @@ class RecurringRepository implements RecurringRepositoryInterface } break; } + // filter out all the weekend days: + $return = $this->filterWeekends($repetition, $return); return $return; } @@ -492,4 +494,43 @@ class RecurringRepository implements RecurringRepositoryInterface return $service->update($recurrence, $data); } + + /** + * Filters out all weekend entries, if necessary. + * + * @param RecurrenceRepetition $repetition + * @param array $dates + * + * @return array + */ + protected function filterWeekends(RecurrenceRepetition $repetition, array $dates): array + { + if ($repetition->weekend === RecurrenceRepetition::WEEKEND_DO_NOTHING) { + return $dates; + } + $return = []; + /** @var Carbon $date */ + foreach ($dates as $date) { + $isWeekend = $date->isWeekend(); + + // set back to Friday? + if ($isWeekend && $repetition->weekend === RecurrenceRepetition::WEEKEND_TO_FRIDAY) { + $clone = clone $date; + $clone->subDays(7 - $date->dayOfWeekIso); + $return[] = $clone; + } + + // postpone to Monday? + if ($isWeekend && $repetition->weekend === RecurrenceRepetition::WEEKEND_TO_MONDAY) { + $clone = clone $date; + $clone->addDays(8 - $date->dayOfWeekIso); + $return[] = $clone; + } + // otherwise, ignore the date! + } + + // filter unique dates? + + return $return; + } } \ No newline at end of file diff --git a/database/migrations/2018_06_08_200526_changes_for_v475.php b/database/migrations/2018_06_08_200526_changes_for_v475.php index db5cfbebe7..366ea260f9 100644 --- a/database/migrations/2018_06_08_200526_changes_for_v475.php +++ b/database/migrations/2018_06_08_200526_changes_for_v475.php @@ -92,6 +92,7 @@ class ChangesForV475 extends Migration $table->string('repetition_type', 50); $table->string('repetition_moment', 50); $table->smallInteger('repetition_skip', false, true); + $table->smallInteger('weekend', false, true); $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); } diff --git a/public/js/ff/recurring/create.js b/public/js/ff/recurring/create.js index d8cbe8912f..7e1deebfff 100644 --- a/public/js/ff/recurring/create.js +++ b/public/js/ff/recurring/create.js @@ -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'); diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 72856519f1..cbe8f38983 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -1261,5 +1261,11 @@ return [ 'updated_recurrence' => 'Updated recurring transaction ":title"', 'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.', 'delete_recurring' => 'Delete recurring transaction ":title"', + 'new_recurring_transaction' => 'New recurring transaction', + 'help_weekend' => 'What should Firefly III do when the recurring transaction falls on a Saturday or Sunday?', + 'do_nothing' => 'Just create the transaction', + 'skip_transaction' => 'Skip the occurence', + 'jump_to_friday' => 'Create the transaction on the previous Friday instead', + 'jump_to_monday' => 'Create the transaction on the next Monday instead', 'recurrence_deleted' => 'Recurring transaction ":title" deleted', ]; diff --git a/resources/lang/en_US/form.php b/resources/lang/en_US/form.php index a54447545a..773f713fa0 100644 --- a/resources/lang/en_US/form.php +++ b/resources/lang/en_US/form.php @@ -236,5 +236,6 @@ return [ 'repetition_end' => 'Repetition ends', 'repetitions' => 'Repetitions', 'calendar' => 'Calendar', + 'weekend' => 'Weekend', ]; diff --git a/resources/views/partials/control-bar.twig b/resources/views/partials/control-bar.twig index aa96baa72b..e1d19a1beb 100644 --- a/resources/views/partials/control-bar.twig +++ b/resources/views/partials/control-bar.twig @@ -105,6 +105,15 @@ +
  • + + + + + +
  • diff --git a/resources/views/recurring/create.twig b/resources/views/recurring/create.twig index d9f4e3572f..c165ad7dc7 100644 --- a/resources/views/recurring/create.twig +++ b/resources/views/recurring/create.twig @@ -21,6 +21,7 @@ {{ 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.date('repeat_until',null) }} {{ ExpandedForm.number('repetitions',null) }}