Happy House - Ecommerce Docs
Developer ResourcesReviews

Reviews Features and Flows

Complete feature list, actor journeys, state flows, business rules, edge cases, and diagrams for the Reviews module.

Reviews Features and Flows

Use this page for the reviews domain: what it does for customers and admins, and how each flow behaves from start to finish.

1. Documentation Evidence

Source TypeFiles or DocsWhat Was Extracted
APIapps/api/src/modules/reviews/customer/{product-review,my-review}/*.controller.ts, admin/{review,report}/*.controller.tsRoutes, permissions, rate limits
Backendshared/*.service.ts, customer/admin servicesLifecycle, aggregate deltas, eligibility
Schemapackages/db/src/schema/reviews/*.ts4 tables, 5 enums, GENERATED aggregate
Probe.omc/plans/reviews/probe-constraints.mjs107/0, both directions
Error registryapps/api/src/common/types/error-codes.ts (// REVIEW)REVIEW_* codes

2. Feature Summary

FieldValue
Modulereviews
SubmoduleN/A (product reviews + rating aggregate)
Primary user valueBuyers tell the truth about products they actually received; the product page renders a guaranteed-consistent average, count and distribution; moderators keep the page clean without ever rewriting a customer's words
ActorsGuest (public reads), customer (own reviews, reports), admin (moderation, abuse queue)
Main entry points/api/mobile/products/{productId}/reviews(/:summary), /api/mobile/reviews* (7), /api/admin/reviews* (9), /api/admin/review-reports* (2)
Main outputsReviews, the rating aggregate, moderation events, abuse reports
Related docsAPI, Backend

3. Actor Matrix

ActorCan DoCannot DoAuth RequirementNotes
GuestRead published reviews + summary for a productWrite, report, see non-published statesNone (@Public())Zeroes, never nulls, for unreviewed products
CustomerCheck eligibility, list/detail own reviews (every state), create (5/hr), edit, withdraw, report (10/hr)Review without a delivered purchase (403), hold two live reviews for one product (409), edit a hidden/deleted review (409 → withdraw), report own review (409)JWTREVIEW_NOT_FOUND for another customer's review
AdminList (2 queues), detail, events timeline, approve, reject, hide, restore, bulk approve, recalculate, report queue, dismissCreate or edit review content — moderation changes visibility onlyAdmin JWT + Reviews_*hide resolves the review's open reports
WorkerRecalculate, moderation emailsBullMQHourly drift sweep logs every repair

4. Capability Matrix

CapabilitySurfaceActorRoute/TriggerState ReadState WrittenLinked API Section
Public reviewsGuestGuestGET /api/mobile/products/:productId/reviewspublished reviewsAPI §4
Public summaryGuestGuestGET .../reviews/summaryaggregateAPI
EligibilityCustomerCustomerGET /api/mobile/reviews/eligibilityorders, reviewsAPI
My reviewsCustomerCustomerGET /api/mobile/reviews(/:id)own rowsAPI
CreateCustomerCustomerPOST /api/mobile/reviewseligibilityreview + aggregateAPI
EditCustomerCustomerPATCH /api/mobile/reviews/:idown rowreview + aggregateAPI
WithdrawCustomerCustomerDELETE /api/mobile/reviews/:idown rowdeleted_at + aggregateAPI
ReportCustomerCustomerPOST /api/mobile/reviews/:id/reportreviewreport rowAPI
Admin list/detail/eventsAdminAdmin/api/admin/reviews*reviews + eventsAPI
ModerationAdminAdmin/{id}/approve|reject|hide|restorereview + versionstatus + reasonAPI
Bulk approveAdminAdmin/bulk/approvereviewsstatusesAPI
RecalculateAdminAdmin/summary/:productId/recalculatereviewsaggregateAPI
Report queueAdminAdmin/api/admin/review-reports*reportsstatusAPI

5. User-Facing Flows

5.1 Write a review

Summary

A customer who received a product writes a review. The review publishes on submission — moderated reactively — and the aggregate moves in the same transaction.

Sequence Diagram

Branches and Edge Cases

BranchConditionBehaviorError/Result
Not eligibleNo delivered purchase403REVIEW_NOT_ELIGIBLE
Already reviewedLive review exists409 + existingReviewIdSwitch to edit
RetrySame Idempotency-KeyOriginal 201 replayedNo collision
Rate limit5/hour429Back off — not a bug
Product goneMissing/withdrawn404REVIEW_PRODUCT_NOT_FOUND

5.2 Edit a published review — the surprising one

An edit of a published review returns it to pending and removes it from the aggregate in the same transaction. It disappears from the product page until a moderator approves. This is deliberate — new content is trusted, changed content is not — and it closes bait-and-switch without gating the honest first submission. Tell the customer before they submit the edit; it is the single most surprising behaviour in the module.

5.3 Report a review

POST /api/mobile/reviews/:id/report — reason ∈ spam · offensive · fake · irrelevant · personal_information · other, detail optional (≤500, admin-only). A report never hides anything — it raises a counter that orders the moderator's queue, one report per customer per review. recorded: false with a 200 is a success (already reported) — never surface it as an error. Do not imply the review will be removed.

5.4 The product page

The detail response gained a rating block (averageRating, reviewCount, distribution). Detail responses only — listings do not carry it (a rating per card is a join per page); use the summary endpoint for the products a listing renders stars for. Zeroes, never nulls, for an unreviewed product — reviewCount is what tells you whether averageRating: 0 means "bad" or "nobody has said".

6. Admin Flows

  • Two queues: ?status=pending&sort=oldestPending (edits awaiting approval) and ?reportedOnly=true&sort=mostReported (abuse).
  • Moderation actions all take the fetched version — two moderators cannot silently overwrite each other (409 REVIEW_STALE_VERSION otherwise). reject and hide require a reason; hide resolves the review's open reports in the same transaction.
  • Bulk approve ({ "ids": [...] }, max 100) returns { approved, skipped }.
  • Recalculate (/summary/:productId/recalculate) returns 202 — a repair path, never the write path.
  • Report queue rows carry the review's own text so a moderator decides without a second call; the reporting customer is deliberately never identified — do not build a UI that expects it.
  • No admin create and no admin edit of review content — moderation changes visibility; the customer's words survive every action, and product_review_event records each one with no UPDATE path anywhere.

7. Lifecycle and State Transitions

FromEvent/ActionToGuardSide Effects
createpublisheddelivered purchase, no live reviewaggregate +1
publishedcustomer editpendingversionaggregate −1
pendingcustomer editpendingversionnone (still out)
pendingadmin approvepublishedversionaggregate +1
pendingadmin rejectrejectedversion + reason
publishedadmin hidehiddenversion + reasonaggregate −1, reports resolved
hiddenadmin restorepublishedversionaggregate +1
any livecustomer withdrawdeletedversionaggregate −1, slot freed

The aggregate is maintained by ±1 deltas inside the transaction; the recalculate job is a repair path only.

9. Data and Side Effects by Flow

FlowDB WritesCache EffectsJobsRealtimeAnalyticsNotifications
Createreview + aggregateproduct review cache
Editreview + aggregatecachemoderation email via outbox
Withdrawdeleted_at + aggregatecache
Reportreport row
Moderationstatus + reason + eventscachemoderation email
Recalculateaggregatecachequeuelog every repair

10. Error and Recovery Flows

ScenarioTriggerUser/System ExperienceRecoverySource
Stale versionConcurrent edit/moderation409Re-fetch, show current, ask againREVIEW_STALE_VERSION
Already existsSecond review409 + idSwitch to editREVIEW_ALREADY_EXISTS
Not editablehidden/deleted409Offer withdrawREVIEW_NOT_EDITABLE
Report ownSelf-report409Hide the controlREVIEW_REPORT_SELF
Report resolvedAnother moderator409RefreshREVIEW_REPORT_ALREADY_RESOLVED
Bulk too large>100 ids409SplitREVIEW_BULK_LIMIT_EXCEEDED
Aggregate driftAnythingHourly sweep repairsloggedrecalculate

11. Diagrams Required Per Module

  • Actor capability diagram — §3/§4.
  • Sequence diagram per major flow — §5.1.
  • State machine diagram — §5.2/§7.
  • Data side-effect diagram — §9.
  • Error branch diagram — §10.

12. Mandatory Feature and Flow Deep-Dive Pack

12.1 Feature Inventory With Minor Behaviors

FeatureMinor BehaviorActorTriggerUser/System ResultBackend Side EffectSource
EligibilitycanCreate is the keyCustomerCheckAlready accounts for purchase + existing
My listNo filter returns every stateCustomerListIncludes withdrawn
EditEmpty string clears, omit keepsCustomerPATCHOpposite meaningsasymmetry documented
EditeditedAt rendered with publishedAtCustomerViewEdited ≠ originalboth dates
WithdrawVersion as query paramCustomerDELETESurvives proxies
Reportrecorded:false = successCustomerRepeat reportAlready reported200
Admin listTwo named queuesAdminFilterspending-oldest, reported-most
HideResolves reportsAdminHideLeaves abuse queuesame tx
Recalculate202AdminRequestAsync repairlogged
SummaryZeroes not nullsGuestViewCount distinguishes
Detail ratingDetail-only blockGuestProduct pageListings untouched

12.2 Business Process Diagram Pack

12.3 Business Rules and Policy Traceability

RuleBusiness ReasonActor ImpactEnforced InAPI ImpactBackend ImpactTests
One review per (customer, product)One honest voteEdit, not secondpartial unique on deleted_at IS NULL409probe
Auto-publish, moderate reactivelyTrust new contentInstant visibilitystatus defaultprobe
Edit → pendingNo bait-and-switchSurprisetransitionaggregate −1probe
No verified-purchase flagStructuralBadge from roworder + item FKsprobe
Aggregate GENERATEDNo inconsistent averageGENERATED ALWAYS428C9 on writeprobe
Empty bucket decrement abortsNo negative averageCHECK23514probe
Report never hidesFree speech + moderationCounter onlyservicespec
No admin content writesWords surviveno UPDATE pathprobe

12.4 Tradeoffs and Product Rationale

Product DecisionUser BenefitEngineering BenefitAlternativeTradeoffRisk
Verified purchase structuralNo flag to forgetFK from order lineManual flagIneligible customers403
Auto-publishInstant feedbackReactive queuePre-moderationBad content briefly liveReports
Edit → pendingHonest editsAggregate consistentIn-place editSurpriseDocumented
Aggregate ±1 in txNo drift windowRecompute alwaysWrite costRecalculate repair
No admin content editsCustomer words surviveEvent log immutableAdmin rewriteModeration limitedHide/reject
Detail-only ratingNo join per cardListing ratingsSecond callSummary endpoint

12.5 Flow Edge-Case Matrix

FlowEdge CaseTriggerExpected BehaviorUser/System FeedbackSource
CreateSecond reviewLive exists409 + idswitch to edit
CreateNo purchaseIneligible403hide control
CreateRetrySame keyOriginal 201idempotency
EditStale versionConcurrent409re-fetch
EditHidden reviewEdit hidden409offer withdraw
WithdrawAfter withdrawNew reviewSlot freedcan create again
ReportSelfOwn review409hide control
ReportRepeatAlready reported200 recorded:falsesuccess
ModerateDouble actionTwo admins409refresh
RecalculateDuring writeConcurrentRepair path safelogged

12.6 Flow-to-Data Trace

FlowReadsWritesCacheJobs/EventsResponse Fields
Public reviewspublished reviewsproduct reviewitems, pagination
Summaryaggregateproduct reviewaverage, count, distribution
Createeligibilityreview + aggregateinvalidateMyReview
Editown reviewreview + aggregateinvalidatemoderation emailMyReview
Reportreviewreport rowrecorded
Moderatereview + versionstatus + reason + eventsinvalidateemailadmin row
Recalculatereviewsaggregateinvalidatequeue202

12.7 Experience Quality Checklist

  • The doc explains what the actor is trying to accomplish.
  • The doc explains what the backend does that the actor does not see (structural verification, aggregate deltas, GENERATED columns).
  • The doc covers every minor flow and branch.
  • The doc includes user, admin and worker flows.
  • The doc explains business logic, tradeoffs, and rationale.
  • The doc maps every flow to API routes and backend side effects.
  • The doc includes diagrams appropriate to each flow type.
  • The doc covers edge cases and failure recovery.

13. Completion Checklist

  • Every feature, minor action, and submodule capability is listed.
  • Every actor has allowed and forbidden behavior.
  • Every major and minor flow includes steps, branches, and diagrams.
  • Every lifecycle has a transition table and state diagram.
  • Every flow links to the API and backend docs.
  • TDD dependencies are called out where they shape behavior (no TDD pages published yet).

See Also