Skip to content

feat(backend): add core work data APIs - #8

Merged
dohyeon16 merged 3 commits into
mainfrom
feature/backend-work-data
Aug 5, 2026
Merged

feat(backend): add core work data APIs#8
dohyeon16 merged 3 commits into
mainfrom
feature/backend-work-data

Conversation

@dohyeon16

@dohyeon16 dohyeon16 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Summary

Phase 3A on top of the existing WIP scaffolding (92f8891: geo.py + owned-record mixin). Completes full CRUD for the three core work-data resources: workplaces, work_schedules, attendance_records.

Builds on Phase 2 auth (base main = 770416e) — every endpoint is authenticated and scoped to the token's user. Schema is derived from the mobile app's local storage models, not guessed.

What's in it

Models & migration — Alembic 0003_work_data (← 0002_auth_tables): 3 tables with FKs, unique(user_id, client_id), check constraints (non-negative wage/break, coordinate range + pairing), and per-resource indexes. Times stored as "HH:mm" strings, work_date as DATE, money as integer won (no float).

Ownership & security — all queries scoped to the current user; cross-user or missing IDs return 404 (no existence leak); invalid UUIDs → 422. Two-account isolation covered by tests.

client_id idempotencyunique(user_id, client_id). Re-sending the same client_id returns the existing record (200) instead of duplicating; re-creating a deleted client_id409 (prevents offline-sync resurrection).

Deletion policy — soft delete everywhere. Deleting a workplace does not cascade-delete its schedules/attendance (history preserved). New schedule/attendance referencing a deleted (or others') workplace → 422.

Dates & timeswork_date is a real DATE (no UTC conversion); created_at/updated_at are timezone-aware UTC. Midnight-crossing shifts supported (end < start ⇒ next day), no separate end-date column, matching the mobile calc rule.

GPSclock_in_proximity/clock_out_proximity in responses are recomputed server-side from workplace coords via core/geo (client-sent distance is never accepted). Minimal fix to geo.proximity so the radius check uses the raw (un-rounded) distance — matches mobile evaluateProximity.

Listslimit/offset pagination (default 50, max 200), workplace_id/date_from/date_to filters, deterministic ordering, internal fields (user_id, deleted_at) hidden.

Tests

  • 45 new tests across workplaces / work_schedules / attendance_records + migration round-trip. Full suite: 100 passed, 2 skipped (PG-only).
  • Phase 2 auth regression: unchanged — all original auth/user/token/migration tests still pass.
  • Alembic verified: single head 0003_work_data, offline PG SQL for all 3 tables, and a real SQLite upgrade→downgrade→upgrade round-trip proving auth tables survive the downgrade.

Preview live verification (2026-08-05)

Verified against the live Preview deployment of 2820922 (service workproof-backend-preview, connected branch main, Neon Preview DB shy-thunder-48215343). Production was not touched.

  • Migration: Preview DB advanced 0002_auth_tables → 0003_work_data; revision confirmed on the DB. Applied once (not re-run).
  • Result: 55 / 55 checks PASSED against real PostgreSQL — no 5xx, no HTML tracebacks, no secrets in output.

Coverage exercised end-to-end over HTTP:

  • Health/health, /api/v1/health, /api/v1/health/db (database: connected) all 200.
  • Auth regression — register / login / users/me / refresh rotation + refresh-reuse detection (old token → 401); unauthenticated request → 401.
  • CRUD — workplaces, work-schedules, attendance-records (all 15 endpoints).
  • Ownership isolation — a second user's GET/PATCH/DELETE on another user's resources → 404; list excludes them.
  • client_id idempotency — replay → 200 with same id; reuse of a soft-deleted client_id409.
  • Soft delete — deleted resources excluded from both list and single GET (404).
  • Deleted-workplace references — new schedule/attendance against a deleted workplace → 422.
  • Filters / paging / orderingdate_from/date_to, workplace_id, limit/offset (disjoint pages), deterministic ordering, inverted range → 422.
  • GPS (server-side Haversine) — 150 m & 199 m → verified: true; 201 m & 250 m → verified: false; missing workplace or record coords → proximity: null. Display distances match half-up rounding (150/199/201/250 m).

Temp accounts and all verification work-data were cleaned up through the API (both accounts deleted; work-data soft-deleted) — 0 active temp rows remain in the Preview DB. This PR stays Draft; not merged, not wired to mobile.

Scope / not included

Notes

  • First commit 92f8891 (WIP scaffolding) is preserved; this PR adds 2820922 on top.
  • Draft — not ready to merge.

🤖 Generated with Claude Code

도현 and others added 2 commits August 4, 2026 17:51
Checkpoint of in-progress Phase 3A work data backend before pausing.
Incomplete: models/schemas/routers/migration not yet added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwR3pvvEE1hy9NNrmMjmCQ
Build out Phase 3A on the existing scaffolding (geo + owned-record mixin):
full CRUD for workplaces, work_schedules, and attendance_records.

- Models + Alembic 0003_work_data (FKs, unique(user_id, client_id), check
  constraints, indexes). Times as "HH:mm" strings, work_date as DATE, money
  as integer won. Schema mirrors the mobile local models.
- Ownership scoping (cross-user/missing -> 404), client_id idempotency
  (active replay -> 200, deleted -> 409), soft delete that preserves history
  (deleting a workplace keeps its schedules/attendance; new refs to a deleted
  workplace -> 422).
- GPS distance/proximity recomputed server-side from workplace coords via
  core/geo (client-sent distance ignored); minimal fix so radius check uses the
  raw distance (mobile parity).
- Pagination + workplace_id/date_from/date_to filters, deterministic ordering,
  internal fields hidden in responses.
- 45 new tests (100 passed, 2 skipped); Phase 2 auth suite unchanged.

Not yet wired to the mobile app; not deployed to Neon/Render.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AhusKsaukQ5TyJYCUgJvm
@dohyeon16
dohyeon16 marked this pull request as ready for review August 5, 2026 05:59
Preview verified (Neon Preview DB 0003_work_data, live verification 55/55 PASS);
Production migration/deploy still pending. Docs only; no code/migration/test changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PKqTTjZMNgaK1k6Udw8ATX
@dohyeon16
dohyeon16 merged commit e6bb6a0 into main Aug 5, 2026
2 checks passed
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.

1 participant