status field, an answer is a write to its seller_note, and removal is a soft delete. Average ratings aren’t stored anywhere: the Review module service computes them from the review rows each time you ask.
Status values
A review’sstatus holds one of three values. Every review starts as pending, and only updateReviewWorkflow changes it.
pending. Who can set the status depends on the API:
- Admin API:
POST /admin/reviews/:idsetsstatus,rating, andcustomer_note - Vendor API: a store can’t change
statusorrating; the respond route ignores both fields - Store API: a customer can edit
ratingandcustomer_note, but notstatus
Store answers
A store answers a review by writingseller_note through respondReviewWorkflow. The workflow refuses a second answer: it fails when seller_note is already set, so the first answer stays until someone clears it with updateReviewWorkflow. Answering never touches status, so a store can answer a pending review before it’s published.
Over HTTP, a store answers with POST /vendor/reviews/:id, which only accepts reviews linked to that store, so only seller reviews. An operator answers any review with POST /admin/reviews/:id/respond.
Deletion is soft
deleteReviewWorkflow soft deletes the review: it sets deleted_at and keeps the row and its links. query.graph and the APIs stop returning it, and the workflow restores it if a later step fails. Operators delete with DELETE /admin/reviews/:id, and customers delete their own reviews with DELETE /store/reviews/:id.
Average ratings are computed on read
The service’s rating helpers run anAVG(rating) query over the review table, joined through the product or seller link table. There’s no stored average to keep in sync. The helpers apply no filters beyond the target, which affects what counts:
- Every status counts:
pendingandrejectedreviews are part of the average - Soft deleted reviews count: the query doesn’t check
deleted_at, and the link rows stay in place - No reviews:
getAvgRatingreturnsnull
"4.5000000000000000", or null. When only published reviews should count, compute the average from query.graph results instead, as shown in Compute aggregate ratings.