mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 01:32:38 +00:00
Implemented chore period intervals to have more flexible schedules (closes #312)
This commit is contained in:
parent
554ac104f8
commit
28b23fd313
@ -4,5 +4,8 @@
|
|||||||
### Recipe fixes
|
### Recipe fixes
|
||||||
- Fixed that recipes were displayed without ingredients if the total recipe count was > 100
|
- 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
|
### 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))
|
- 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))
|
||||||
|
@ -1546,3 +1546,15 @@ msgstr ""
|
|||||||
|
|
||||||
msgid "Are you sure to remove the included recipe \"%s\"?"
|
msgid "Are you sure to remove the included recipe \"%s\"?"
|
||||||
msgstr ""
|
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
47
migrations/0094.sql
Normal 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;
|
@ -118,6 +118,7 @@ $('.input-group-chore-period-type').on('change', function(e)
|
|||||||
{
|
{
|
||||||
var periodType = $('#period_type').val();
|
var periodType = $('#period_type').val();
|
||||||
var periodDays = $('#period_days').val();
|
var periodDays = $('#period_days').val();
|
||||||
|
var periodInterval = $('#period_interval').val();
|
||||||
|
|
||||||
$(".period-type-input").addClass("d-none");
|
$(".period-type-input").addClass("d-none");
|
||||||
$(".period-type-" + periodType).removeClass("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')
|
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-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')
|
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'));
|
$('#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(","));
|
$("#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')
|
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("min", "1");
|
||||||
$("#period_days").attr("max", "31");
|
$("#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"));
|
$("#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');
|
Grocy.FrontendHelpers.ValidateForm('chore-form');
|
||||||
|
@ -86,6 +86,18 @@
|
|||||||
|
|
||||||
<input type="hidden" id="period_config" name="period_config" value="@if($mode == 'edit'){{ $chore->period_config }}@endif">
|
<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)
|
@if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="assignment_type">{{ $__t('Assignment type') }} <span id="chore-assignment-type-info" class="small text-muted"></span></label>
|
<label for="assignment_type">{{ $__t('Assignment type') }} <span id="chore-assignment-type-info" class="small text-muted"></span></label>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user