Implemented chore period intervals to have more flexible schedules (closes #312)

This commit is contained in:
Bernd Bestel 2019-10-04 11:14:11 +02:00
parent 554ac104f8
commit 28b23fd313
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
5 changed files with 78 additions and 0 deletions

View File

@ -4,5 +4,8 @@
### Recipe fixes
- Fixed that recipes were displayed without ingredients if the total recipe count was > 100
### Chores improvements
- Added a "period interval" option per chore to have more flexible schedules (possible for the daily/weekly/monthly schedules, means "schedule this chore only every x days/weeks/months" to have for example biweekly schedules)
### General & other improvements
- New Input shorthands for date fields to increase/decrease the date by 1 month/year (shift + arrow keys, see the full list [here](https://github.com/grocy/grocy#input-shorthands-for-date-fields))

View File

@ -1546,3 +1546,15 @@ msgstr ""
msgid "Are you sure to remove the included recipe \"%s\"?"
msgstr ""
msgid "Period interval"
msgstr ""
msgid "This means the next execution of this chore should only be scheduled every %s days"
msgstr ""
msgid "This means the next execution of this chore should only be scheduled every %s weeks"
msgstr ""
msgid "This means the next execution of this chore should only be scheduled every %s months"
msgstr ""

47
migrations/0094.sql Normal file
View File

@ -0,0 +1,47 @@
ALTER TABLE chores
ADD period_interval INTEGER NOT NULL DEFAULT 1 CHECK(period_interval > 0);
DROP VIEW chores_current;
CREATE VIEW chores_current
AS
SELECT
x.chore_id,
x.last_tracked_time,
CASE WHEN x.rollover = 1 AND DATETIME('now', 'localtime') > x.next_estimated_execution_time THEN
DATETIME(STRFTIME('%Y-%m-%d', DATETIME('now', 'localtime')) || ' ' || STRFTIME('%H:%M:%S', x.next_estimated_execution_time))
ELSE
x.next_estimated_execution_time
END AS next_estimated_execution_time,
x.track_date_only,
x.next_execution_assigned_to_user_id
FROM (
SELECT
h.id AS chore_id,
MAX(l.tracked_time) AS last_tracked_time,
CASE h.period_type
WHEN 'manually' THEN '2999-12-31 23:59:59'
WHEN 'dynamic-regular' THEN DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_days AS TEXT) || ' day')
WHEN 'daily' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' day')
WHEN 'weekly' THEN
CASE
WHEN period_config LIKE '%sunday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 0')
WHEN period_config LIKE '%monday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 1')
WHEN period_config LIKE '%tuesday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 2')
WHEN period_config LIKE '%wednesday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 3')
WHEN period_config LIKE '%thursday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 4')
WHEN period_config LIKE '%friday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 5')
WHEN period_config LIKE '%saturday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', '+' || CAST((h.period_interval - 1) * 7 AS TEXT) || ' days', 'weekday 6')
END
WHEN 'monthly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+' || CAST(h.period_interval AS TEXT) || ' month', 'start of month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
END AS next_estimated_execution_time,
h.track_date_only,
h.rollover,
h.next_execution_assigned_to_user_id
FROM chores h
LEFT JOIN chores_log l
ON h.id = l.chore_id
AND l.undone = 0
GROUP BY h.id, h.period_days
) x;

View File

@ -118,6 +118,7 @@ $('.input-group-chore-period-type').on('change', function(e)
{
var periodType = $('#period_type').val();
var periodDays = $('#period_days').val();
var periodInterval = $('#period_interval').val();
$(".period-type-input").addClass("d-none");
$(".period-type-" + periodType).removeClass("d-none");
@ -139,11 +140,13 @@ $('.input-group-chore-period-type').on('change', function(e)
else if (periodType === 'daily')
{
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled 1 day after the last execution'));
$('#chore-period-interval-info').text(__t('This means the next execution of this chore should only be scheduled every %s days', periodInterval.toString()));
}
else if (periodType === 'weekly')
{
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled 1 day after the last execution, but only for the weekdays selected below'));
$("#period_config").val($(".period-type-weekly input:checkbox:checked").map(function () { return this.value; }).get().join(","));
$('#chore-period-interval-info').text(__t('This means the next execution of this chore should only be scheduled every %s weeks', periodInterval.toString()));
}
else if (periodType === 'monthly')
{
@ -152,6 +155,7 @@ $('.input-group-chore-period-type').on('change', function(e)
$("#period_days").attr("min", "1");
$("#period_days").attr("max", "31");
$("#period_days").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", "31"));
$('#chore-period-interval-info').text(__t('This means the next execution of this chore should only be scheduled every %s months', periodInterval.toString()));
}
Grocy.FrontendHelpers.ValidateForm('chore-form');

View File

@ -86,6 +86,18 @@
<input type="hidden" id="period_config" name="period_config" value="@if($mode == 'edit'){{ $chore->period_config }}@endif">
@php if($mode == 'edit') { $value = $chore->period_interval; } else { $value = 1; } @endphp
@include('components.numberpicker', array(
'id' => 'period_interval',
'label' => 'Period interval',
'value' => $value,
'min' => '1',
'additionalCssClasses' => 'input-group-chore-period-type',
'invalidFeedback' => $__t('This cannot be lower than %s', '1'),
'additionalGroupCssClasses' => 'period-type-input period-type-daily period-type-weekly period-type-monthly',
'hintId' => 'chore-period-interval-info'
))
@if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
<div class="form-group">
<label for="assignment_type">{{ $__t('Assignment type') }} <span id="chore-assignment-type-info" class="small text-muted"></span></label>