Optimized chore on-time tracking (closes #2385)

This commit is contained in:
Bernd Bestel 2025-01-14 20:39:07 +01:00
parent 9cac3b2311
commit 97dbd7bf08
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
7 changed files with 51 additions and 17 deletions

View File

@ -42,7 +42,11 @@
### Chores
- Added a new option "Swap track next schedule / track now buttons" (stock settings / top right corner settings menu) to swap the "Track next chore schedule" and "Track chore execution now" buttons/menu items on the chores overview page (defaults to disabled, so no changed behavior when not configured)
- Added the possibility to see if a scheduled schedule chore was tracked/done on time or not:
- When tracking chores, the "Next estimated tracking date" (so the current scheduled time) is now also stored in the corresponding chore journal entry and displayed in new column "Scheduled tracking time" on the chores journal page
- When the "Tracked time" is later than the "Scheduled tracking time", the corresponding chore journal entry is now highlighted in red on the chores journal page
- Added a new column "Time of tracking" on the chores journal page (displays the time when the tracking actually happened, hidden by default)
- Added a new option "Swap track next schedule / track now buttons" (chores settings / top right corner settings menu) to swap the "Track next chore schedule" / "Track chore execution now" buttons/menu items on the chores overview page (defaults to disabled, so no changed behavior when not configured)
### Calendar

View File

@ -2440,3 +2440,9 @@ msgstr ""
msgid "Swap track next schedule / track now buttons"
msgstr ""
msgid "Scheduled tracking time"
msgstr ""
msgid "Time of tracking"
msgstr ""

10
migrations/0244.sql Normal file
View File

@ -0,0 +1,10 @@
ALTER TABLE chores_log
ADD scheduled_execution_time DATETIME;
DELETE FROM user_settings
WHERE key IN (
'datatables_state_chores-journal-table',
'datatables_rowGroup_chores-journal-table',
'datatables_state_products-table',
'datatables_rowGroup_products-table'
);

View File

@ -2,7 +2,8 @@
'order': [[2, 'desc']],
'columnDefs': [
{ 'orderable': false, 'targets': 0 },
{ 'searchable': false, "targets": 0 }
{ 'searchable': false, "targets": 0 },
{ 'visible': false, 'targets': 4 }
].concat($.fn.dataTable.defaults.columnDefs)
});
$('#chores-journal-table tbody').removeClass("d-none");

View File

@ -187,11 +187,13 @@ class ChoresService extends BaseService
}
}
$scheduledExecutionTime = $this->getDatabase()->chores_current()->where('chore_id = :1', $chore->id)->fetch()->next_estimated_execution_time;
$logRow = $this->getDatabase()->chores_log()->createRow([
'chore_id' => $choreId,
'tracked_time' => $trackedTime,
'done_by_user_id' => $doneBy,
'skipped' => BoolToInt($skipped)
'skipped' => BoolToInt($skipped),
'scheduled_execution_time' => $scheduledExecutionTime
]);
$logRow->save();
$lastInsertId = $this->getDatabase()->lastInsertId();

View File

@ -13,17 +13,18 @@
<div class="row">
<div class="col-lg-6 col-12">
<h4 ">{{ $__t('Batteries overview') }}</h4>
@include('components.numberpicker', array(
'id' => 'batteries_due_soon_days',
'additionalAttributes' => 'data-setting-key="batteries_due_soon_days"',
'label' => 'Due soon days',
'min' => 0,
'additionalCssClasses' => 'user-setting-control',
'hint' => $__t('Set to 0 to hide due soon filters/highlighting')
))
'additionalAttributes' => 'data-setting-key=" batteries_due_soon_days"', 'label'=> 'Due soon days',
'min' => 0,
'additionalCssClasses' => 'user-setting-control',
'hint' => $__t('Set to 0 to hide due soon filters/highlighting')
))
<a href="{{ $U('/batteriesoverview') }}"
class="btn btn-success">{{ $__t('OK') }}</a>
<a href="{{ $U('/batteriesoverview') }}"
class="btn btn-success">{{ $__t('OK') }}</a>
</div>
</div>
@stop

View File

@ -91,9 +91,9 @@
</th>
<th class="allow-grouping">{{ $__t('Chore') }}</th>
<th>{{ $__t('Tracked time') }}</th>
@if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
<th class="allow-grouping">{{ $__t('Done by') }}</th>
@endif
<th>{{ $__t('Scheduled tracking time') }}</th>
<th>{{ $__t('Time of tracking') }}</th>
<th class="allow-grouping @if(!GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) d-none @endif">{{ $__t('Done by') }}</th>
@include('components.userfields_thead', array(
'userfields' => $userfields
@ -103,7 +103,7 @@
<tbody class="d-none">
@foreach($choresLog as $choreLogEntry)
<tr id="chore-execution-{{ $choreLogEntry->id }}-row"
class="@if($choreLogEntry->undone == 1) text-muted @endif @if($choreLogEntry->skipped == 1) font-italic @endif">
class="@if($choreLogEntry->undone == 1) text-muted @endif @if($choreLogEntry->skipped == 1) font-italic @endif @if (!empty($choreLogEntry->scheduled_execution_time) && $choreLogEntry->skipped == 0 && $choreLogEntry->tracked_time > $choreLogEntry->scheduled_execution_time) table-danger @endif">
<td class="fit-content border-right">
<a class="btn btn-secondary btn-xs undo-chore-execution-button permission-CHORE_UNDO_EXECUTION @if($choreLogEntry->undone == 1) disabled @endif"
href="#"
@ -131,15 +131,25 @@
<span class="text-muted">{{ $__t('Skipped') }}</span>
@endif
</td>
@if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
<td>
@if (!empty($choreLogEntry->scheduled_execution_time))
<span>{{ $choreLogEntry->scheduled_execution_time }}</span>
<time class="timeago timeago-contextual @if(FindObjectInArrayByPropertyValue($chores, 'id', $choreLogEntry->chore_id)->track_date_only == 1) timeago-date-only @endif"
datetime="{{ $choreLogEntry->scheduled_execution_time }}"></time>
@endif
</td>
<td>
<span>{{ $choreLogEntry->row_created_timestamp }}</span>
<time class="timeago timeago-contextual"
datetime="{{ $choreLogEntry->row_created_timestamp }}"></time>
</td>
<td class="@if(!GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) d-none @endif">
@if ($choreLogEntry->done_by_user_id !== null && !empty($choreLogEntry->done_by_user_id))
{{ GetUserDisplayName(FindObjectInArrayByPropertyValue($users, 'id', $choreLogEntry->done_by_user_id)) }}
@else
{{ $__t('Unknown') }}
@endif
</td>
@endif
@include('components.userfields_tbody', array(
'userfields' => $userfields,