rp-reviews
Purpose
The shop's review system, in three tables that answer three different questions.
— what a customer said, what the shop said back, and whether it isreviews
on the site. Moderation lives here: a review that came from outside is bornand is visible only inside the console until somebody publishes it.pending— one personal, single-use link per order, and what becamereview_invites
of it: sent, opened, answered, expired. This is the funnel the shop reads.— one row of JSON: the external platforms, the threshold,review_settings
the mail templates, the delays and the chase allowance.
Responsibility boundary
Owns reviews, invitations and the funnel settings. Knows nothing about orders: and Review.orderId are opaque strings, and joining themReviewInvite.orderId
to actual orders is the job of (which asks) andwf-order-review-request (which shows). Does not own community threads.sf-reviews
Two doors
Access is by tag, as everywhere: a published review carries , anythingpublic
else carries plus authenticated, which is what lets the shop actmoderator
on a review nobody at the shop wrote.
The customer's door is different. , getInviteByToken andmarkInviteOpened are authorised by the token itself — a capability, not asubmitByToken
session — so the public form works with no login at all. They return a narrowed
view that carries neither the contact nor the invite id, and submitByToken
spends the link conditionally, so two submissions from the same mail produce
one review and one refusal rather than two reviews.
Review gating
moves the emphasis of the public form and nothing else:positiveThreshold
at or above it the author is offered the external platforms first, below it a
word with the shop first. The platform links stay visible either way, because
showing the path to a public review only to satisfied customers is what Google
and several other platforms forbid. The safe behaviour is the default.
Direct module dependencies
- None
Solution membership
production
Source
modules/repositories/business/rp-reviews