Initial commit: nick docs
This commit is contained in:
127
04 - Flows/Delivery Confirmation Flow.md
Normal file
127
04 - Flows/Delivery Confirmation Flow.md
Normal file
@@ -0,0 +1,127 @@
|
||||
---
|
||||
title: Delivery Confirmation Flow
|
||||
tags: [flow, delivery, escrow-release, code]
|
||||
related_models: ["[[PurchaseRequest]]", "[[Payment]]"]
|
||||
related_apis: ["POST /api/marketplace/purchase-requests/:id/delivery-code", "POST /api/marketplace/purchase-requests/:id/verify-delivery"]
|
||||
---
|
||||
|
||||
# Delivery Confirmation Flow
|
||||
|
||||
After the escrow is funded ([[Payment Flow - SHKeeper]] / [[Payment Flow - DePay & Web3]]) and the seller has prepared the item, the seller **marks shipped**, the buyer **enters a delivery code** to confirm receipt, and the escrow becomes eligible for release ([[Payout Flow]]).
|
||||
|
||||
## Actors
|
||||
|
||||
- **Seller** — marks the order shipped and presents the delivery code to the buyer at hand-off.
|
||||
- **Buyer** — confirms by entering the code in the dashboard.
|
||||
- **Backend** — `DeliveryService` (`backend/src/services/delivery/DeliveryService.ts`), exposed through the marketplace routes (`backend/src/services/marketplace/routes.ts`).
|
||||
- **MongoDB** — `purchaserequests.deliveryInfo` subdocument fields.
|
||||
- **Socket.IO** — `delivery-code-generated`, `delivery-update`.
|
||||
|
||||
## Preconditions
|
||||
|
||||
- `PurchaseRequest.status` is `payment`, `processing`, or `delivery`.
|
||||
- `Payment.escrowState === 'funded'`.
|
||||
|
||||
## Step-by-step narrative
|
||||
|
||||
1. **Seller marks shipped** — from the seller step `frontend/src/sections/request/components/seller-steps/step-3-ship-goods.tsx`, clicks "Mark as shipped". This patches the request status to `delivery`.
|
||||
2. **Delivery code generation** — when the order transitions to `delivery`, `DeliveryService.generateDeliveryCode(requestId)` is invoked. It:
|
||||
- Generates a 6-digit code (`Math.floor(100000 + Math.random()*900000)`).
|
||||
- Sets `deliveryInfo.deliveryCode`, `deliveryCodeGeneratedAt = now`, `deliveryCodeExpiresAt = now + 7d`, `deliveryCodeUsed = false`.
|
||||
- Emits `delivery-code-generated` and `delivery-update` to `request-{requestId}`.
|
||||
- Sends a notification to the buyer with the code (in-app, and via email if configured).
|
||||
3. **Buyer entry** — buyer meets the courier / picks up the item, enters the code in `frontend/src/sections/request/components/seller-steps/delivery-code-verification.tsx` (also surfaced on the buyer side via `step-5-receive-goods.tsx`).
|
||||
4. **Verification** — `POST /api/marketplace/purchase-requests/:id/verify-delivery` with `{ code }`:
|
||||
- Matches `code` against `deliveryInfo.deliveryCode`.
|
||||
- Checks `deliveryCodeExpiresAt > now` and `deliveryCodeUsed === false`.
|
||||
- On success: `deliveryInfo.deliveryCodeUsed = true; deliveryCodeUsedAt = now`. Status flips `delivery → delivered`.
|
||||
- Emits `purchase-request-update` `status-changed`.
|
||||
- Triggers buyer/seller notifications via `notifyDeliveryConfirmed` (see `PurchaseRequestService.ts:631-641`).
|
||||
5. **Optional auto-release timer** — once `status === 'delivered'`, a scheduled job can flip the request to `confirming` and then to `seller_paid` after a grace period (e.g. 48h). The auto-release worker is not yet implemented; today an admin completes the chain via [[Payout Flow]].
|
||||
6. **Manual fast-track** — the buyer can also tap "Confirm I received it" to skip the code (used when the code path fails — e.g. lost in transit) which patches `status` to `delivered`. This relies on admin trust.
|
||||
|
||||
## Sequence diagram
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
actor S as Seller
|
||||
actor B as Buyer
|
||||
participant FE as Frontend
|
||||
participant BE as Backend
|
||||
participant DB as MongoDB
|
||||
participant IO as Socket.IO
|
||||
|
||||
S->>FE: Click "Mark as shipped"
|
||||
FE->>BE: PATCH /api/marketplace/purchase-requests/{id} {status:"delivery"}
|
||||
BE->>DB: PurchaseRequest.status="delivery"
|
||||
BE->>BE: DeliveryService.generateDeliveryCode
|
||||
BE->>DB: deliveryInfo.deliveryCode=XXXXXX\nexpires=+7d
|
||||
BE->>IO: emit request-{id} 'delivery-code-generated'
|
||||
BE->>B: notification w/ code (in-app/email)
|
||||
|
||||
S->>B: At hand-off, share the 6-digit code (verbally)
|
||||
B->>FE: Enter code in dashboard
|
||||
FE->>BE: POST /api/marketplace/purchase-requests/{id}/verify-delivery {code}
|
||||
BE->>DB: match code, expires>now, !used
|
||||
BE->>DB: deliveryCodeUsed=true; status="delivered"
|
||||
BE->>IO: emit request-{id} 'purchase-request-update' status-changed
|
||||
BE->>B,S: notifyDeliveryConfirmed
|
||||
Note over BE: Auto-release timer (planned) → seller_paid → payout
|
||||
```
|
||||
|
||||
## API calls
|
||||
|
||||
| Method | Endpoint | Purpose |
|
||||
|---|---|---|
|
||||
| `PATCH` | `/api/marketplace/purchase-requests/:id` `{status:"delivery"}` | Seller marks shipped |
|
||||
| `POST` | `/api/marketplace/purchase-requests/:id/delivery-code` | Manual code regeneration (admin) |
|
||||
| `POST` | `/api/marketplace/purchase-requests/:id/verify-delivery` | Buyer confirms with code |
|
||||
| `PATCH` | `/api/marketplace/purchase-requests/:id/confirm-delivery` | Buyer fast-track confirm (no code) |
|
||||
|
||||
## Database writes
|
||||
|
||||
- **`purchaserequests.deliveryInfo`** — `deliveryCode`, `deliveryCodeGeneratedAt`, `deliveryCodeExpiresAt`, `deliveryCodeUsed`, `deliveryCodeUsedAt`.
|
||||
- **`purchaserequests.status`** — `delivery` → `delivered` → (eventually `seller_paid` → `completed`).
|
||||
- **`notifications`** — generated for both parties.
|
||||
|
||||
## Socket events emitted
|
||||
|
||||
- **`delivery-code-generated`** → `request-{id}` (with code, expiresAt).
|
||||
- **`delivery-update`** → `request-{id}` (`type: 'code-generated'`).
|
||||
- **`purchase-request-update`** `status-changed` on `delivery → delivered`.
|
||||
- **`new-notification`** → `user-{buyerId}` with the code.
|
||||
|
||||
## Side effects
|
||||
|
||||
- Code is **emitted via socket and in-app notification**. If a malicious actor has access to the buyer's notifications, they could intercept and confirm delivery prematurely. Treat the code as confidential at the UI layer.
|
||||
- Triggers the path that eventually frees up the escrow (manual today via [[Payout Flow]], auto in the future).
|
||||
|
||||
## Error / edge cases
|
||||
|
||||
- **Wrong code** → `400 Invalid delivery code`.
|
||||
- **Expired code** (>7 days) → `400 Code expired`. Admin can regenerate via the manual endpoint.
|
||||
- **Already used code** → `400 Code already used`.
|
||||
- **Buyer never confirms** → status remains `delivery`. Auto-release timer (not yet built) should trigger `delivered` after N days. Until then, admin intervention.
|
||||
- **Seller delivers but never marks shipped** → buyer can dispute via [[Dispute Flow]]; the dispute resolution will release the escrow regardless.
|
||||
- **Lost code** → `POST /:id/delivery-code` regenerates a new 6-digit value, invalidates the old one, and re-notifies. Restrict to admin/seller to avoid abuse.
|
||||
|
||||
> [!tip] Use the code as proof-of-handover
|
||||
> The seller should ask the courier or the buyer at the door for the code before leaving the item. If the buyer disputes "never received", an unused code is strong circumstantial evidence; a used code = buyer confirmed.
|
||||
|
||||
## Linked flows
|
||||
|
||||
- [[Payment Flow - SHKeeper]] / [[Payment Flow - DePay & Web3]] — funding precondition.
|
||||
- [[Escrow Flow]] — state transitions triggered by confirmation.
|
||||
- [[Payout Flow]] — fires after confirmation (manual today).
|
||||
- [[Dispute Flow]] — escape hatch.
|
||||
- [[Notification Flow]] — channel for the code.
|
||||
|
||||
## Source files
|
||||
|
||||
- Backend: `backend/src/services/delivery/DeliveryService.ts`
|
||||
- Backend: `backend/src/services/marketplace/routes.ts` (delivery endpoints)
|
||||
- Backend: `backend/src/services/marketplace/PurchaseRequestService.ts:631-641` (confirmation notifications)
|
||||
- Frontend: `frontend/src/sections/request/components/seller-steps/step-3-ship-goods.tsx`
|
||||
- Frontend: `frontend/src/sections/request/components/seller-steps/delivery-code-verification.tsx`
|
||||
- Frontend: `frontend/src/sections/request/components/buyer-steps/step-5-receive-goods.tsx`
|
||||
Reference in New Issue
Block a user