Dentolize · Daily Notifications Cron Walkthrough
On this pageWhy this mattersScope and riskReal risk to flagWhat this is not

For Stakeholders

Why this matters

Retention and daily-active-use levers are usually about giving people a reason to open the app without being asked. This feature does the opposite on purpose: it pushes a reason to notice the app (a summary arrives whether or not anyone asks for it) at a moment — closing time — when an owner is naturally thinking about how the day went. It's a small feature, but it's the kind that compounds engagement without adding a single new screen to learn.

Scope and risk

This is a genuinely small, additive change:

  • 2 new database columns, both defaulting to true (no backfill risk, no

breaking change for existing users).

  • 1 new hourly cron job, isolated in its own file, using the same locking

and observability patterns every other cron already uses.

  • 2 new toggles reusing an existing settings screen on both web and

mobile — no new UI surface to design or maintain.

  • No new third-party dependency — it reuses the existing Expo push

integration already used for other notification types.

Real risk to flag

  • **A latent crash condition, not introduced by this PR but newly and

incorrectly commented as "handled" here:** if a company has no time zone configured, the code throws instead of falling back to UTC as its own comment claims — and because the whole nightly loop runs inside one try/catch, that throw would abort the run for every company not yet processed in that hour, not just the misconfigured one. This same gap already exists in three other crons this codebase runs nightly (expenses, messages, appointments), so it's a pre-existing condition across the crons module rather than something new — but it's worth a quick check that every live company actually has a time zone set, since this PR increases how much nightly value rides on that being true. See The Cron for the exact code path.

  • Fire-and-forget delivery. If Expo's push service rejects a batch,

those users simply don't get notified — no retry, no alert. This matches the codebase's existing pattern for other push sends, so it's not a regression, just a ceiling on how reliable "guaranteed nightly delivery" can be marketed as.

  • No automated test coverage for the new cron or its translation

helper — consistent with the rest of packages/server/src/cronJobs/, which has none either. Correctness currently rests on manual QA via the admin panel's manual-execute path.

What this is not

Not a reporting or analytics feature, not a compliance requirement, not tied to any external regulatory deadline (unlike, say, ZATCA work). It's a UX/engagement feature with a small, contained blast radius.