Occurrences overview

Every check template (frequency + type) generates occurrences — individual items a staff member completes. An occurrence has a due_at timestamp calculated from the tenant's timezone and the check's frequency slots.

Calendar slots

Each frequency maps to fixed local-time slots in the tenant's timezone (set in the tenant settings, default Europe/London):

FrequencySlots (local time)
twice_daily00:00 and 12:00 every day
daily00:00 every day
twice_weeklyMonday 00:00 and Thursday 00:00
weeklyMonday 00:00
twice_monthly1st and 15th 00:00
monthly1st 00:00
quarterlyJan/Apr/Jul/Oct 1st 00:00

Generation (lazy, on read)

Occurrences are generated when the list endpoint is called, not by a background cron. For each active check:

States

Every occurrence is in one of three derived states (no status column):

StatusDerived fromMeaning
pendingchecked_at IS NULL AND skipped_at IS NULLNeeds attention
donechecked_at IS NOT NULLCompleted by a staff member
skippedskipped_at IS NOT NULLDeliberately skipped (e.g. equipment offline)

The API response also includes an overdue boolean — true when status === "pending" and due_at is in the past.

Validation

Completion is validated server-side by check type:

TypeReadings
simpleNo readings allowed
cold_storeOne reading per every active fridge, each with fridge_id
food≥1 reading, each with valid food_item_id
washerNo readings allowed

Permissions

Daily checklist (mobile app)

The home screen shows a Daily Hygiene card with a real-time progress bar and a task carousel. Swipe through pending occurrences — simple checks complete in one tap; cold_store and food checks open a temperature-reading modal with per-unit sliders.

The Daily Checklist screen (sidebar) shows the full list grouped by status: Overdue / Pending / Done / Skipped. Tap to complete or record temperatures.

API reference

GET  /v1/tenants/{tenantCode}/check-data                  — list occurrences
POST /v1/tenants/{tenantCode}/check-data/{id}/complete     — complete (with readings)
POST /v1/tenants/{tenantCode}/check-data/{id}/uncomplete   — undo completion
POST /v1/tenants/{tenantCode}/check-data/{id}/skip         — skip (admin only)

All request and response bodies use snake_case keys. See the OpenAPI reference for full schema details.