Almost half the shifts had no end time
7,277 of 17,312 field shifts in thirty days never ended, so the attendance export showed blank hours. The job that closed them had been off for nine months.
You export last month’s attendance for the field team and the End Time column is blank on nearly every other row. Hours Logged is blank with it. The staff started their day; the report cannot say when they stopped. You ask two reasonable questions: does an unfinished day stop somebody starting the next one, and would a reminder on their phone help?
In the thirty days we measured, 7,277 of 17,312 shifts had never been ended, 42 per cent. At the worst depot it was 80 per cent; others sat at 74, 63 and 46. On production, 57,842 shift rows had no end at all. Whatever the report said about hours, it was not true.
What was actually going on
The system had a nightly job that closed any shift still open. Its last closure was dated 12 November 2025. In the file that registers the scheduled jobs, the line that starts it had been commented out, while the other three jobs beside it were still running. Nine months, nothing closed, nothing alerted.
Worse, the export could not even show the closures the job had made before it died. The export compared the closer’s name against “system” in lower case; the data held “System” with a capital. So 60,999 rows the job had closed rendered blank too.
Your first question had a clean answer: no. Starting a shift looks only at today, and there is no rule in the database that forbids a second open shift. One employee had left four consecutive days open and started fresh on each following working day. So the start of every day was recorded, and only the end was missing. The disabled job had not damaged the thing you most wanted to know, which is who turned up.
The old rows, though, can never be closed. Ending a shift also looks only at today.
Measuring before designing
Before a line of the reminder was written, we measured the working week from production, and two assumptions broke.
Saturday is a full working day: 624 shifts on an average Saturday against 43 on a Sunday. A reminder that ran Monday to Friday would have silently skipped about 624 people every week. And seven in the evening, the first time proposed, is too early. A quarter of shifts end by 19:29, half by 20:30, three-quarters by 21:32. A reminder at seven would have interrupted most people who were still legitimately working.
The morning reminder had a different hazard. Keyed off “no shift started today”, it would have pinged 568 people on Independence Day, and 641 of the 781 active staff on 13 August, when the platform had been unreachable until 10:25 because of a billing suspension, telling them to start a shift on a system they could not reach.
What we changed
Two one-shot pushes, Monday to Saturday. At 10:30 a start reminder goes to anybody in the active pool with no shift today. At 20:00 an end reminder goes only to people who started that day and have not ended. That second audience is the useful one: because it keys off actual starts, it shrinks by itself on a holiday, and would have gone to 229 people on Independence Day rather than more than 500. It needs no holiday calendar.
Each run writes the reminder to the person’s inbox before sending it, and skips anyone already reminded for that job today, so a restart or a manual trigger cannot send twice. The device-token lookup is one query rather than one per person, which saves about 450 round trips on the evening run. Push-token coverage was measured at 731 of 737 recent shifters.
Sending is switched off by default and the manual trigger cannot override the switch. The test system is a restore of production, real staff and real device tokens included, and an unguarded test run would have pushed to 763 real people. Scheduler logging was turned on, because there had been no log evidence the scheduler fired at all, and a reminder that silently does nothing is the dead job all over again.
What it did not fix
The nightly auto-close stays off, by the owner’s decision, so the open rows stay open. The morning reminder still misfires on holidays and outages; a cheap circuit-breaker was proposed, skip the run if today’s starts are under about half the trailing four-week average for that weekday, and it was not built in this piece of work. Somebody who never closes a shift will be reminded every working day, indefinitely. And if the server restarts across the firing time, that day’s reminder is lost; the scheduler does not catch up.
The mechanism
A scheduled job that had been disabled in one line and never raised an alarm. Its replacement derives its audience from what actually happened that day, and every volume was taken from production before anything was built.
Where this ends up
Sazinga Field records a field day as a start and an end, and the numbers above are what happens to the end when nothing is watching it.