Skip to content

fix(events): populate TaskIsExpired on calendar + stream paths so mobile overdue list survives refresh#1007

Merged
renemadsen merged 1 commit into
stablefrom
fix/mobile-overdue-taskisexpired-clobber
Jun 15, 2026
Merged

fix(events): populate TaskIsExpired on calendar + stream paths so mobile overdue list survives refresh#1007
renemadsen merged 1 commit into
stablefrom
fix/mobile-overdue-taskisexpired-clobber

Conversation

@renemadsen

Copy link
Copy Markdown
Member

Problem

Customer-reported: overdue "red tasks" visible in the Angular web calendar do not appear in the flutter-eform mobile overdue list.

Root cause

The mobile overdue list (ListTaskTracker) and calendar (ListEvents/StreamEventChanges) share one client Drift cache keyed by (eventId, planDayKey, complianceId). Only ListTaskTracker set task_is_expired=true. The calendar/stream paths never computed the flag, so it serialized as proto3-default false, and re-upserting the same current-week rows clobbered the tracker's true. The overdue list briefly populated then collapsed to empty.

Fix

  • GetTasksForWeek now computes CalendarTaskResponseModel.TaskIsExpired on every emit phase (recurrence-expansion, orphan-anchor, moved-in, compliance), mirroring GetTaskTrackerList.
  • EventsGrpcService.ListEvents and LoadEventsAsync forward TaskIsExpired on the Event message.
  • Extracted the shared expiry predicate (retracted Removed && Status==77, or past-due effectiveDate < today && Status != 100, else date-only) into a single ComputeTaskIsExpired helper, removing 3 duplicated copies.

Verification

  • gRPC: ListEvents past-due rows now return task_is_expired=true (was false); ListTaskTracker unchanged at 11/23 expired (no regression). Re-confirmed after each rebuild.
  • On device: reproduced the empty list, then confirmed the overdue list holds at 11 after the fix (no collapse to 0).
  • Dual review (code-review + code-simplifier) clean; no behavior change on the admin web path.

🤖 Generated with Claude Code

…ile overdue list survives refresh

The mobile overdue ("red tasks") list and the calendar share one client
Drift cache keyed by (eventId, planDayKey, complianceId). Only
ListTaskTracker set task_is_expired=true; ListEvents and StreamEventChanges
re-upserted the same current-week rows with task_is_expired=false (the flag
was never computed on those paths, so it defaulted to proto3 false),
clobbering the tracker's value. The overdue list populated briefly and then
collapsed to empty.

GetTasksForWeek now computes CalendarTaskResponseModel.TaskIsExpired on all
emit phases (recurrence-expansion, orphan-anchor, moved-in, compliance),
and ListEvents + LoadEventsAsync forward it, so all paths agree. The shared
expiry predicate (previously duplicated in GetTaskTrackerList) is extracted
into a single ComputeTaskIsExpired helper.

Verified over gRPC: ListEvents past-due rows now return task_is_expired=true;
ListTaskTracker unchanged (11/23 expired). Reproduced on device and confirmed
the overdue list now holds instead of collapsing to 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 15, 2026 16:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a mobile/web calendar consistency issue by ensuring the backend computes and propagates TaskIsExpired on the calendar/week and event-stream gRPC paths, preventing the mobile Drift cache from being overwritten with proto3-default false values.

Changes:

  • Computes CalendarTaskResponseModel.TaskIsExpired throughout GetTasksForWeek, and centralizes the predicate into ComputeTaskIsExpired.
  • Forwards TaskIsExpired into the gRPC Event message in EventsGrpcService for ListEvents and the stream’s load path.
  • Updates model documentation to reflect that both task-tracker and calendar-week paths populate the field.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Services/GrpcServices/EventsGrpcService.cs Adds TaskIsExpired to Event projection for list + stream load paths.
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Services/BackendConfigurationCalendarService/BackendConfigurationCalendarService.cs Computes TaskIsExpired across week-view emit phases and factors out shared predicate.
eFormAPI/Plugins/BackendConfiguration.Pn/BackendConfiguration.Pn/Infrastructure/Models/Calendar/CalendarTaskResponseModel.cs Updates XML doc to reflect TaskIsExpired is now populated by both service paths.

Comment on lines +269 to +275
.ToDictionary(g => g.Key, g =>
{
var first = g.First();
var sc = first.MicrotingSdkCaseId > 0 ? sdkCasesById.GetValueOrDefault(first.MicrotingSdkCaseId) : null;
var expired = ComputeTaskIsExpired(sc, first.Deadline, dateTimeNow);
return (ComplianceId: first.Id, SdkCaseId: first.MicrotingSdkCaseId, TaskIsExpired: expired);
});
Comment on lines +989 to +993
var compSdkCase = compliance.MicrotingSdkCaseId > 0
? weekComplianceCasesById.GetValueOrDefault(compliance.MicrotingSdkCaseId)
: null;
var compTaskIsExpired = ComputeTaskIsExpired(compSdkCase, effectiveTaskDate, dateTimeNow);

@renemadsen renemadsen merged commit 3513dc0 into stable Jun 15, 2026
27 checks passed
@renemadsen renemadsen deleted the fix/mobile-overdue-taskisexpired-clobber branch June 15, 2026 17:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants