- Replace .select({ count: appointments.id }).limit(1) + .length with
sql<number>`count(*)::int` pattern per project standard (references invoices.ts:86)
- Add gte(appointments.startTime, new Date()) to upcomingAppointment query
so past appointments in scheduled/confirmed status are excluded
- Add visitCount regression tests: 2+ completed appointments → visitCount >= 2,
no completed → visitCount = 0
Updated UAT_PLAYBOOK.md §profile-summary (visitCount regression + date filter)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Returns aggregated pet profile with:
- All pet fields (basic + extended)
- recentGroomingHistory: last 10 entries from groomingVisitLogs with staff name join
- lastVisitDate: most recent groomedAt timestamp
- visitCount: count of completed appointments
- upcomingAppointment: next scheduled/confirmed appointment with service/staff name
Enforces same groomer RBAC as GET /:id. Returns 404 for non-existent pets.
Adds PetProfileSummary, GroomingHistoryEntry, and UpcomingAppointment types.
Adds unit tests covering: 404, 403, aggregated profile, empty history, no upcoming appt.
Updates UAT_PLAYBOOK.md §3 with TC-API-3.8 and TC-API-3.9.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>