refactor(time-tracking): cycle 2 — re-implement field actions against Drizzle
Replaces the in-progress stub (RPC + brandId params) with Drizzle + the shared SECURITY DEFINER wrappers in db/client. - field.ts: cookie session, scrypt PIN, clock-in/out, getOpenClockIn, getWorkerPayPeriodHours. Cookie payload now 7 fields; parseSessionCookie re-resolves name/role/lang/brand_id from DB on every read so a stale or tampered cookie cannot impersonate a different brand. - index.ts: admin CRUD for workers / tasks / settings / logs / notifications + getWorkerPeriodTotals. All admin actions drop the brandId param; the helpers pull it from the admin session via getAdminUser(). - notifications.ts: overtime check inserts with status='pending' (not optimistic 'sent') since email/SMS dispatch is out of scope until the notification_targets columns land in a follow-up migration. - export/route: cast fix for the changed TimeLog shape. DB: - 0094 partial unique index on time_tracking_logs (worker_id) WHERE clock_out IS NULL — enforces one open clock-in per worker against concurrent / retried requests (READ COMMITTED cannot).
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
-- ============================================================================
|
||||
-- 0094_time_tracking_one_open_clock_in.sql
|
||||
--
|
||||
-- Cycle 2 of the water-log/time-tracking refactor. A field worker must not
|
||||
-- have two open clock-ins at once — concurrent requests, offline retries,
|
||||
-- and double-taps on a slow phone all create the same hazard. A partial
|
||||
-- unique index on (worker_id) WHERE clock_out IS NULL is the only DB-level
|
||||
-- guard, since READ COMMITTED transactions can both pass an
|
||||
-- "is there an open log?" SELECT before either INSERT commits.
|
||||
--
|
||||
-- The application catches the unique violation and returns
|
||||
-- "Already clocked in" to the worker. The `clockOutWorker` action picks
|
||||
-- the most-recent open log (ORDER BY clock_in DESC LIMIT 1) — that
|
||||
-- behavior is unchanged.
|
||||
-- ============================================================================
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS
|
||||
time_tracking_logs_one_open_per_worker_idx
|
||||
ON time_tracking_logs (worker_id)
|
||||
WHERE clock_out IS NULL;
|
||||
|
||||
COMMENT ON INDEX time_tracking_logs_one_open_per_worker_idx IS
|
||||
'Cycle 2: enforces at most one open clock-in per worker. Catches concurrent / retry race in field app.';
|
||||
Reference in New Issue
Block a user