feat(GRO-2154): geocoding endpoints + auto-geocode on client mutations #170

Merged
Flea Flicker merged 2 commits from feat/gro-2154-geocoding-endpoints-dev into dev 2026-06-08 11:45:09 +00:00
Member

GRO-2154 — Route Optimization: Geocoding Endpoints (Phase 1.3)

Exposes the GRO-2153 geocoding service as API endpoints and hooks auto-geocoding into the existing client mutation flow.

Endpoints

  • POST /api/clients/:clientId/geocode — geocode a single client's address (manager-only). Maps outcomes to HTTP status: geocoded → 200, provider error → 502, no_address/unresolved → 422, missing client → 404.
  • POST /api/clients/geocode-batch?limit= — batch-geocode un-geocoded clients (geocodedAt IS NULL with a non-blank address), throttled by the active provider's rate limiter (manager-only). Processes up to limit per call (default 50, clamped 1..500) and returns remaining so managers re-run to completion — avoids HTTP timeouts under Nominatim's 1 req/sec policy.

Auto-geocode hook

  • POST /api/clients and PATCH /api/clients/:id auto-geocode when an address is supplied; the response carries a structured geocoding field. Best-effort — a flaky geocoding backend never breaks the mutation.
  • Clearing the address (address: "") drops stale latitude/longitude/geocodedAt.
  • Unrelated patches (status toggle, name, etc.) do not trigger geocoding.

Persistence & failure surfacing

  • Persists latitude / longitude / geocodedAt to the clients table (schema from GRO-2152 migration 0041).
  • Structured outcomes — geocoded | no_address | unresolved | error — with clear, actionable messages so groomers/managers know when an address is ambiguous.

Files

  • src/services/clientGeocoding.ts — provider resolution, single-client geocode+persist, throttled batch.
  • src/routes/clients.ts — two endpoints + create/update auto-geocode.
  • src/index.ts — manager-only route guard registered before the general /clients/* write guard.
  • src/__tests__/clientGeocoding.test.ts — 8 unit tests (all outcomes, batch tally/remaining, limit clamp, provider default).

UAT Playbook

  • Updated UAT_PLAYBOOK.md §4.2 — added TC-API-2.7 … TC-API-2.17 covering single/batch geocode, manager-only RBAC, no-address/unresolved/not-found cases, auto-geocode on create/update, and address-clear coordinate reset.

Verification

  • pnpm run typecheck ✓ (+ @groombook/db typecheck ✓)
  • pnpm run lint ✓ (0 errors)
  • pnpm run test ✓ (610 passed, incl. 8 new)

Closes GRO-2154.

🤖 Generated with Claude Code

## GRO-2154 — Route Optimization: Geocoding Endpoints (Phase 1.3) Exposes the GRO-2153 geocoding service as API endpoints and hooks auto-geocoding into the existing client mutation flow. ### Endpoints - `POST /api/clients/:clientId/geocode` — geocode a single client's address (**manager-only**). Maps outcomes to HTTP status: `geocoded → 200`, provider `error → 502`, `no_address`/`unresolved → 422`, missing client → 404. - `POST /api/clients/geocode-batch?limit=` — batch-geocode un-geocoded clients (`geocodedAt IS NULL` with a non-blank address), throttled by the active provider's rate limiter (**manager-only**). Processes up to `limit` per call (default 50, clamped 1..500) and returns `remaining` so managers re-run to completion — avoids HTTP timeouts under Nominatim's 1 req/sec policy. ### Auto-geocode hook - `POST /api/clients` and `PATCH /api/clients/:id` auto-geocode when an `address` is supplied; the response carries a structured `geocoding` field. Best-effort — a flaky geocoding backend never breaks the mutation. - Clearing the address (`address: ""`) drops stale `latitude`/`longitude`/`geocodedAt`. - Unrelated patches (status toggle, name, etc.) do **not** trigger geocoding. ### Persistence & failure surfacing - Persists `latitude` / `longitude` / `geocodedAt` to the `clients` table (schema from GRO-2152 migration 0041). - Structured outcomes — `geocoded | no_address | unresolved | error` — with clear, actionable messages so groomers/managers know when an address is ambiguous. ### Files - `src/services/clientGeocoding.ts` — provider resolution, single-client geocode+persist, throttled batch. - `src/routes/clients.ts` — two endpoints + create/update auto-geocode. - `src/index.ts` — manager-only route guard registered before the general `/clients/*` write guard. - `src/__tests__/clientGeocoding.test.ts` — 8 unit tests (all outcomes, batch tally/remaining, limit clamp, provider default). ### UAT Playbook - Updated `UAT_PLAYBOOK.md` §4.2 — added **TC-API-2.7 … TC-API-2.17** covering single/batch geocode, manager-only RBAC, no-address/unresolved/not-found cases, auto-geocode on create/update, and address-clear coordinate reset. ### Verification - `pnpm run typecheck` ✓ (+ `@groombook/db` typecheck ✓) - `pnpm run lint` ✓ (0 errors) - `pnpm run test` ✓ (610 passed, incl. 8 new) Closes GRO-2154. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Flea Flicker added 1 commit 2026-06-08 11:40:39 +00:00
feat(GRO-2154): geocoding endpoints + auto-geocode on client mutations
CI / Test (pull_request) Successful in 25s
CI / Lint & Typecheck (pull_request) Successful in 29s
CI / Build & Push Docker Images (pull_request) Failing after 49s
47dae603ac
Phase 1.3 of Route Optimization. Exposes the GRO-2153 geocoding service
as API endpoints and wires auto-geocoding into the client mutation flow.

- POST /api/clients/:clientId/geocode — geocode one client (manager-only)
- POST /api/clients/geocode-batch?limit= — throttled batch geocode of
  un-geocoded clients, reports `remaining` so managers re-run to finish
  (avoids HTTP timeouts under Nominatim's 1 req/sec policy)
- Auto-geocode on client create/update when an address is supplied;
  clearing the address drops stale coordinates
- Persists latitude/longitude/geocodedAt to the clients table
- Structured outcomes (geocoded | no_address | unresolved | error) with
  clear messages so ambiguous addresses are surfaced to groomers/managers
- src/services/clientGeocoding.ts orchestrates provider resolution +
  persistence; unit tests cover all outcomes and batch tallying
- Updated UAT_PLAYBOOK.md §4.2 — added TC-API-2.7 .. 2.17 (geocoding)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker added 1 commit 2026-06-08 11:43:25 +00:00
ci: retrigger (transient apk add curl network flake in docker build)
CI / Test (pull_request) Successful in 24s
CI / Lint & Typecheck (pull_request) Successful in 27s
CI / Build & Push Docker Images (pull_request) Successful in 55s
ecfdfa939b
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Flea Flicker merged commit 582c376df9 into dev 2026-06-08 11:45:09 +00:00
Sign in to join this conversation.