Initial commit: nick docs

This commit is contained in:
moojttaba
2026-05-23 20:35:34 +03:30
commit 0da235ae27
90 changed files with 18268 additions and 0 deletions

120
04 - Flows/Rating Flow.md Normal file
View File

@@ -0,0 +1,120 @@
---
title: Rating Flow
tags: [flow, rating, review, moderation]
related_models: ["[[Review]]", "[[ShopSettings]]", "[[PurchaseRequest]]"]
related_apis: ["POST /api/marketplace/reviews", "GET /api/marketplace/reviews/:subjectType/:subjectId"]
---
# Rating Flow
After an order is `completed`, the buyer rates the seller and (optionally) leaves a review; the seller can rate the buyer in the reciprocal flow. Reviews are scoped by `subjectType` (`seller` | `template`) and constrained by the seller's `ShopSettings`.
## Actors
- **Buyer** (typical reviewer).
- **Seller** (subject; can also be a reviewer in the reciprocal direction).
- **System** — enforces uniqueness and moderation rules.
- **Backend** — `backend/src/services/marketplace/reviewRoutes.ts`.
- **MongoDB** — `reviews` collection (`backend/src/models/Review.ts`).
## Preconditions
- The associated `PurchaseRequest` is `completed` (or `finalized`).
- The reviewer is the buyer of that request (for `isVerifiedBuyer` to be `true`).
- The subject's `ShopSettings.allowSellerReviews` / `allowTemplateReviews` is not `false` (`reviewRoutes.ts:15-31`).
## Step-by-step narrative
1. From the request detail or seller profile, the buyer clicks "Leave review". The form captures `rating` (15) and `comment` (≤ 1000 chars).
2. Frontend POSTs `POST /api/marketplace/reviews` with `{ subjectType: 'seller' | 'template', subjectId, rating, comment, purchaseRequestId? }`.
3. Backend route handler:
- Validates payload.
- Calls `isReviewsAllowed(subjectType, subjectId)` — checks the seller's `ShopSettings` (for sellers, look up the seller directly; for templates, look up the template's owning seller).
- Sets `isVerifiedBuyer = true` if the user owns a `completed` purchase request from that seller.
- Defaults `status: 'published'` (no moderation queue today).
4. Inserts a `Review` document. Unique index `{ subjectType, subjectId, reviewerId }` prevents a user from reviewing the same subject twice (`Review.ts:34`).
5. Aggregated stats are recomputed on read via `computeStats` (`reviewRoutes.ts:33-62`) — count, average, per-star histogram. No denormalised counter on `User` today; everything is computed at read-time.
## Visibility
- Public — anyone hitting `GET /api/marketplace/reviews/seller/:sellerId` sees `status: 'published'` reviews paginated by 10.
- If `ShopSettings.allowSellerReviews === false` (or `allowTemplateReviews === false`), reads return `403 Reviews are disabled by seller`.
- The seller can flag a review for moderation (planned — current statuses include `pending` and `rejected`, but no UI to flip them today; admin can update via direct DB).
## Sequence diagram
```mermaid
sequenceDiagram
autonumber
actor B as Buyer
participant FE as Frontend
participant BE as Backend
participant DB as MongoDB
B->>FE: Open seller profile / request detail
B->>FE: Click "Leave review", choose stars + comment
FE->>BE: POST /api/marketplace/reviews
BE->>DB: ShopSettings.findOne({sellerId}) → allowSellerReviews?
alt allowed
BE->>DB: PurchaseRequest.exists({buyer, seller, status:"completed"})?
BE->>DB: Review.create({status:"published", isVerifiedBuyer})
BE-->>FE: 201 { review }
else disabled
BE-->>FE: 403 Reviews disabled
end
Note over FE: Public visitor:
FE->>BE: GET /api/marketplace/reviews/seller/{id}
BE->>DB: Review.find / computeStats aggregate
BE-->>FE: { items, pagination, stats:{count, avg, histogram} }
```
## API calls
| Method | Endpoint | Purpose |
|---|---|---|
| `POST` | `/api/marketplace/reviews` | Submit review |
| `GET` | `/api/marketplace/reviews/:subjectType/:subjectId` | List reviews + stats |
| `PATCH` | `/api/marketplace/reviews/:id` | Edit own review (within edit window) |
| `DELETE` | `/api/marketplace/reviews/:id` | Delete own review |
## Database writes
- **`reviews`** — insert on submission; one document per `(subjectType, subjectId, reviewerId)`.
- **`shopsettings`** — read-only here; the seller controls `allowSellerReviews` / `allowTemplateReviews` in their shop settings.
## Socket events emitted
- None today. A `new-review` event broadcast to `user-{sellerId}` would be a useful enhancement so sellers see reviews appear live.
## Side effects
- Recompute aggregate on every list call — fine for small volumes; consider caching `stats` per subject when the review count grows.
- Order rating field also stamps `metadata.rating` on the purchase request when the marketplace endpoint accepts ratings inline (see `routes.ts` references in `backend/src/services/marketplace/routes.ts`).
## Error / edge cases
- **Duplicate review** → MongoDB `E11000` from the unique index; surface as `409 Already reviewed`.
- **Subject disabled reviews** → `403`.
- **Reviewer not a verified buyer** → review is still allowed but `isVerifiedBuyer = false`. Display this in the UI.
- **Rating out of 15** → Mongoose schema validator rejects.
- **Comment > 1000 chars** → schema-level rejection.
- **Seller toggles `allowSellerReviews=false` after reviews exist** → existing reviews remain stored but become unreadable via the public GET (`reviewRoutes.ts:81-83`).
- **Spam / abuse** → no automatic moderation; admin can flip `status` to `rejected` to hide.
> [!tip] Verified-buyer badge
> The `isVerifiedBuyer` flag is the most credible signal for prospective buyers. Always render a "Verified buyer" pill next to reviews where this is `true`.
## Linked flows
- [[Purchase Request Flow]] — precursor that makes the buyer "verified".
- [[Seller Offer Flow]] — display average rating on offer cards.
- [[Dispute Flow]] — a resolved dispute could trigger a review prompt; today they are independent.
## Source files
- Backend: `backend/src/services/marketplace/reviewRoutes.ts`
- Backend: `backend/src/models/Review.ts`
- Backend: `backend/src/services/marketplace/shopSettingsController.ts` (allow flags)
- Backend: `backend/src/services/marketplace/routes.ts` (inline rating on order completion)
- Frontend: review components under `frontend/src/sections/account/` and seller profile views