mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-15 16:57:09 +00:00
Various extensions to recurring transactions.
This commit is contained in:
@@ -64,15 +64,5 @@ class Kernel extends ConsoleKernel
|
|||||||
{
|
{
|
||||||
// create recurring transactions.
|
// create recurring transactions.
|
||||||
$schedule->job(new CreateRecurringTransactions(new Carbon))->daily();
|
$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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ namespace FireflyIII\Http\Controllers\Recurring;
|
|||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Http\Requests\RecurrenceFormRequest;
|
use FireflyIII\Http\Requests\RecurrenceFormRequest;
|
||||||
|
use FireflyIII\Models\RecurrenceRepetition;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@@ -89,10 +90,17 @@ class CreateController extends Controller
|
|||||||
'until_date' => trans('firefly.repeat_until_date'),
|
'until_date' => trans('firefly.repeat_until_date'),
|
||||||
'times' => trans('firefly.repeat_times'),
|
'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:
|
// flash some data:
|
||||||
$hasOldInput = null !== $request->old('_token');
|
$hasOldInput = null !== $request->old('_token');
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
'first_date' => $tomorrow->format('Y-m-d'),
|
'first_date' => $tomorrow->format('Y-m-d'),
|
||||||
'transaction_type' => $hasOldInput ? $request->old('transaction_type') : 'withdrawal',
|
'transaction_type' => $hasOldInput ? $request->old('transaction_type') : 'withdrawal',
|
||||||
'active' => $hasOldInput ? (bool)$request->old('active') : true,
|
'active' => $hasOldInput ? (bool)$request->old('active') : true,
|
||||||
@@ -100,7 +108,9 @@ class CreateController extends Controller
|
|||||||
];
|
];
|
||||||
$request->session()->flash('preFilled', $preFilled);
|
$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')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -110,6 +110,7 @@ class IndexController extends Controller
|
|||||||
$repetition->repetition_type = $repetitionType;
|
$repetition->repetition_type = $repetitionType;
|
||||||
$repetition->repetition_moment = $repetitionMoment;
|
$repetition->repetition_moment = $repetitionMoment;
|
||||||
$repetition->repetition_skip = (int)$request->get('skip');
|
$repetition->repetition_skip = (int)$request->get('skip');
|
||||||
|
$repetition->weekend = (int)$request->get('weekend');
|
||||||
|
|
||||||
$actualEnd = clone $end;
|
$actualEnd = clone $end;
|
||||||
switch ($endsAt) {
|
switch ($endsAt) {
|
||||||
@@ -222,8 +223,9 @@ class IndexController extends Controller
|
|||||||
'daily' => ['label' => trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')],
|
'daily' => ['label' => trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')],
|
||||||
$weekly => ['label' => trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]), 'selected' => 0 === strpos($preSelected, 'weekly')],
|
$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')],
|
$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')],
|
$ndom => ['label' => trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]),
|
||||||
$yearly => ['label' => trans('firefly.recurring_yearly', ['date' => $yearlyDate]),'selected' => 0 === strpos($preSelected, 'yearly')],
|
'selected' => 0 === strpos($preSelected, 'ndom')],
|
||||||
|
$yearly => ['label' => trans('firefly.recurring_yearly', ['date' => $yearlyDate]), 'selected' => 0 === strpos($preSelected, 'yearly')],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
Log::debug('Now running report thing.');
|
Log::debug('Now running report thing.');
|
||||||
// will now send email to users.
|
// will now send email to users.
|
||||||
foreach ($result as $userId => $journals) {
|
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();
|
$journals = TransactionJournal::where('user_id', $userId)->inRandomOrder()->take(1)->get();
|
||||||
event(new RequestedReportOnJournals($userId, $journals));
|
event(new RequestedReportOnJournals($userId, $journals));
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
* @property string $repetition_type
|
* @property string $repetition_type
|
||||||
* @property string $repetition_moment
|
* @property string $repetition_moment
|
||||||
* @property int $repetition_skip
|
* @property int $repetition_skip
|
||||||
|
* @property int $weekend
|
||||||
* @property \Carbon\Carbon $created_at
|
* @property \Carbon\Carbon $created_at
|
||||||
* @property \Carbon\Carbon $deleted_at
|
* @property \Carbon\Carbon $deleted_at
|
||||||
* @property \Carbon\Carbon $updated_at
|
* @property \Carbon\Carbon $updated_at
|
||||||
@@ -41,10 +42,18 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
*/
|
*/
|
||||||
class RecurrenceRepetition extends Model
|
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;
|
use SoftDeletes;
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $casts
|
protected $casts
|
||||||
= [
|
= [
|
||||||
'created_at' => 'datetime',
|
'created_at' => 'datetime',
|
||||||
'updated_at' => 'datetime',
|
'updated_at' => 'datetime',
|
||||||
'deleted_at' => 'datetime',
|
'deleted_at' => 'datetime',
|
||||||
@@ -52,7 +61,7 @@ class RecurrenceRepetition extends Model
|
|||||||
'repetition_moment' => 'string',
|
'repetition_moment' => 'string',
|
||||||
'repetition_skip' => 'int',
|
'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 */
|
/** @var string */
|
||||||
protected $table = 'recurrences_repetitions';
|
protected $table = 'recurrences_repetitions';
|
||||||
|
|
||||||
|
@@ -262,6 +262,8 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// filter out all the weekend days:
|
||||||
|
$return = $this->filterWeekends($repetition, $return);
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -492,4 +494,43 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
|
|
||||||
return $service->update($recurrence, $data);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -92,6 +92,7 @@ class ChangesForV475 extends Migration
|
|||||||
$table->string('repetition_type', 50);
|
$table->string('repetition_type', 50);
|
||||||
$table->string('repetition_moment', 50);
|
$table->string('repetition_moment', 50);
|
||||||
$table->smallInteger('repetition_skip', false, true);
|
$table->smallInteger('repetition_skip', false, true);
|
||||||
|
$table->smallInteger('weekend', false, true);
|
||||||
|
|
||||||
$table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade');
|
$table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade');
|
||||||
}
|
}
|
||||||
|
1
public/js/ff/recurring/create.js
vendored
1
public/js/ff/recurring/create.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');
|
||||||
|
@@ -1261,5 +1261,11 @@ return [
|
|||||||
'updated_recurrence' => 'Updated recurring transaction ":title"',
|
'updated_recurrence' => 'Updated recurring transaction ":title"',
|
||||||
'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.',
|
'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.',
|
||||||
'delete_recurring' => 'Delete recurring transaction ":title"',
|
'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',
|
'recurrence_deleted' => 'Recurring transaction ":title" deleted',
|
||||||
];
|
];
|
||||||
|
@@ -236,5 +236,6 @@ return [
|
|||||||
'repetition_end' => 'Repetition ends',
|
'repetition_end' => 'Repetition ends',
|
||||||
'repetitions' => 'Repetitions',
|
'repetitions' => 'Repetitions',
|
||||||
'calendar' => 'Calendar',
|
'calendar' => 'Calendar',
|
||||||
|
'weekend' => 'Weekend',
|
||||||
|
|
||||||
];
|
];
|
||||||
|
@@ -105,6 +105,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('recurring.create') }}">
|
||||||
|
<i class="menu-icon fa fa-paint-brush bg-teal"></i>
|
||||||
|
|
||||||
|
<div class="menu-info">
|
||||||
|
<h4 class="control-sidebar-subheading">{{ 'new_recurring_transaction'|_ }}</h4>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
{{ 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('repetition_end', repetitionEnds) }}
|
||||||
|
{{ ExpandedForm.select('weekend', weekendResponses, null, {helpText: trans('firefly.help_weekend')}) }}
|
||||||
{{ ExpandedForm.date('repeat_until',null) }}
|
{{ ExpandedForm.date('repeat_until',null) }}
|
||||||
{{ ExpandedForm.number('repetitions',null) }}
|
{{ ExpandedForm.number('repetitions',null) }}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user