Skip to content
M329xrtPublic

About

Delivery management platform for small Kenyan retailers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

6 Commits

Folders and files

Repository files navigation

Reflex — Delivery Management MVP

Reflex is a delivery coordination app for small Kenyan retailers—electronics shops, pharmacies, and hardware stores—that currently manage dispatch through calls and WhatsApp. It creates a single record of each delivery, assigns a rider, and keeps retailers, dispatchers, and riders in sync as the order moves from request to delivery.

Architecture

┌───────────────────────────┐
│       React Frontend      │
│                           │
│ Retailer | Dispatcher     │
│ Rider                    │
└─────────────┬─────────────┘
              │ REST API
              ▼
┌───────────────────────────┐
│      Node + Express       │
│ Delivery / assignment     │
│ status validation / auth  │
└─────────────┬─────────────┘
              │
              ▼
┌───────────────────────────┐
│       PostgreSQL          │
│ Users / deliveries /      │
│ status history            │
└───────────────────────────┘
             ▲
             │ Socket.IO
             ▼
       Real-time updates

Technology choices

  • React + Vite, React Router, Axios, and Socket.IO client
  • Node.js + Express REST API with centralized error handling
  • PostgreSQL accessed through pg, using foreign keys and transactional changes
  • JWT authentication and bcrypt password hashing
  • Socket.IO broadcasts after database commits; a 15-second browser fallback refresh is used if a socket is unavailable

Delivery lifecycle and access control

The backend, not the UI, enforces the lifecycle:

REQUESTED → ASSIGNED → PICKED_UP → DELIVERED
     └──────────────→ CANCELLED

Only a retailer can create their own delivery. Only a dispatcher can assign an unassigned REQUESTED delivery to a user whose server-side role is RIDER. Only the assigned rider can progress it from ASSIGNED to PICKED_UP, then DELIVERED. Every legitimate state change creates a row in delivery_status_history. Duplicate or invalid transitions return 409 Conflict; access violations return 403 Forbidden.

The schema is in database/migrations/001_initial.sql. It creates users, deliveries, and delivery_status_history; delivery foreign keys link retailers and riders to users.

API

Method Endpoint Access Purpose
POST /api/auth/register Public Register a role-based account
POST /api/auth/login Public Receive JWT and public user data
GET /api/auth/me Authenticated Load session user
POST /api/deliveries Retailer Create a delivery
GET /api/deliveries Authenticated Role-scoped delivery list
GET /api/deliveries/:id Authorized viewer Detail and status history
PATCH /api/deliveries/:id/assign Dispatcher Assign a rider
PATCH /api/deliveries/:id/status Assigned rider Set PICKED_UP or DELIVERED
GET /api/users/riders Dispatcher Selectable riders

All protected endpoints require Authorization: Bearer <JWT> and use JSON request/response payloads.

Run locally

1. Configure PostgreSQL

Create a database named reflex, then copy .env.example to .env and set a real DATABASE_URL and long JWT_SECRET.

createdb reflex
cp .env.example .env

On Windows PowerShell, use Copy-Item .env.example .env instead.

2. Install packages and initialize data

npm run install:all
npm run migrate
npm run seed

3. Start the app

npm run dev

Open http://localhost:5173. The API is served at http://localhost:4000.

To start the services separately, use these commands from the project root:

# Backend API
npm run dev --prefix server

# Frontend
npm run dev --prefix client

If Vite reports that port 5173 is occupied, it will choose the next available port; use the URL printed in the terminal. Ensure CLIENT_URL in .env matches that frontend origin, or use one of the supported local Vite ports (5173/5174).

Demo accounts

Every seeded account uses password ReflexDemo123!.

Role Email
Retailer — Jane Wanjiku jane@reflex.demo
Dispatcher — David Mwangi david@reflex.demo
Rider — Brian Kamau brian@reflex.demo
Rider — Kevin Otieno kevin@reflex.demo
Rider — Mary Njeri mary@reflex.demo

The seed creates deliveries covering REQUESTED, ASSIGNED, PICKED_UP, and DELIVERED. Rerunning it is safe; it does not duplicate demo deliveries.

Tests

npm test

The included tests verify the delivery state machine, including every normal transition and rejected delivered/duplicate transitions. The server also enforces rider ownership, role restrictions, rider-role assignment validation, duplicate assignment prevention, and missing-record handling at the API boundary.

QR boundary and future roadmap

Each delivery has a cryptographically generated qr_token at the database layer, ready for a scanner endpoint that verifies both the token and assigned rider before confirmation. The visual scanner is intentionally deferred to keep the core create → assign → pick up → deliver workflow stable.

Future additions: rider QR scan UI, proof-of-delivery photos/signatures, retailer team accounts, dispatch reassignment rules, delivery notifications, analytics, and production deployment configuration.

Known MVP trade-offs

This is a single-organization MVP: dispatchers can view all deliveries and there is no retailer organization table yet. Socket rooms are role/user scoped, while PostgreSQL remains the source of truth. Public self-registration supports all three demo roles; a production version should restrict dispatcher and rider invitation/registration.

About

Delivery management platform for small Kenyan retailers

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages