4.5 KiB
4.5 KiB
Handoff — after backend-phase-14 (Reviews, ratings & patient care records)
The trust loop and the continuity-of-care loop are live. A customer leaves one moderated review per
completed booking; an admin/moderator publishes/hides/rejects it; the nurse's public rating is recomputed
from source on every transition (so hiding a 1-star lowers the count and re-derives the average — no
inflated-after-hide drift); low ratings auto-raise an internal support_alert; and nurses author encrypted,
patient-scoped clinical notes readable only under a strict clinical-access rule.
What the frontend (f13-b14) can now build
- Leave a review —
POST bookings/{bookingId}/review{ rating 1–5, body?, tagCodes? }(customer who owns a completed booking). Returns{ id, moderationStatus: "pending_moderation", lowRatingAlertRaised }. The review is not public until an admin publishes it — build the "submitted, awaiting moderation" state. - Public nurse reviews —
GET nurses/{nurseProfileId}/reviews?page=&pageSize=→{ aggregate: { averageRating, publishedCount }, reviews: PagedResult<{ id, rating, body, tagCodes[], createdAt }> }. Published only. - Public tag rollup —
GET nurses/{nurseProfileId}/review_tags→{ publishedReviewCount, tags: [{ code, labelFa, labelEn, count, percentage }] }("% punctual"). The seeded vocab (punctual/professional/clean/kind/ communicative) is always returned. - Tag your own review —
POST reviews/{reviewId}/tags{ tagCodes }(author or moderator; replaces the set). - Admin moderation console —
GET admin/reviews/moderation_queue?status=&page=&pageSize=(defaultpending_moderation; each row carries the linkedlowRatingAlertIdfor triage) andPATCH reviews/{reviewId}/status{ action: publish|hide|reject|unpublish, reason? }(hide/reject need a reason). The PATCH returns the recomputed{ averageRating, totalReviews }. - Patient care records —
POST patients/{patientId}/care_records{ bookingId?, body }(nurse with a confirmed booking) andGET patients/{patientId}/care_records?page=&pageSize=(owning customer / nurse with a confirmed booking / admin) → decrypted{ id, patientId, bookingId, nurseProfileId, nurseName, body, recordedAt }newest first. The history is patient-scoped — a new nurse taking over reads the whole history.
Contracts
dev/contracts/domains/reviews-records.md— all 8 endpoints, themoderationStatus/action enums, tag codes, DTO shapes, and the care-record access matrix.dev/contracts/openapi/swagger.v1.jsonrefreshed — the 8 review/care-record paths are in the snapshot.
What is mocked (and how it becomes real)
IReviewModerationService(new) — AI review pre-screen.MockReviewModerationServiceis a keyword filter: clean text → a human-review Flag by default (so the publish gate holds — reviews landpending_moderation); a banned-word substring → Reject (auto-hidden). ConfigSeams:ReviewModeration:{AutoApproveClean,BannedWords}. Make it real → a text classifier / LLM endpoint (see reports/mocks-registry.md).ModerateReviewCommandkeeps decision authority + the human override, so the real impl never touches the handler.
Load-bearing rules (don't regress)
- Recompute from source, not delta — every publish/hide/reject/unpublish re-derives
average_rating/total_reviewsover currently-published reviews (exclude-the-changed-review then fold in its new status), in the same transaction, then refreshes the search index. - Publish gate —
pending_moderation/hidden/rejectedare never in a public read and never counted. - 1:1 per completed booking —
UNIQUE(booking_id)+ handler pre-check; cross-tenant is a 404. - Low rating (≤ config
min_rating_for_support_alert, default 2) raises an internallow_ratingalert — internal-only, never in a user response (only its id shows on the admin queue). - Care records are patient-scoped, encrypted at rest, strict access — a nurse without a confirmed booking for the patient is denied read + write.
Deferred (flagged, not built)
- Two-way (nurse-reviews-customer) double-blind reviews with timed reveal.
- First-class
incidentsentity + ML fraud scoring (manual suspension +support_alertscover it now). - The ticket system, partner centers, and the admin support-alert worklist console → b15 (this phase only raises alerts).
SuspendNurse/ResolveSupportAlert/FlagConcernadmin actions → b15.