π₯ MediStore Backend API
A production-grade, multi-role pharmacy e-commerce backend built with Node.js, Express, Prisma ORM, and PostgreSQL β featuring a fully integrated multi-warehouse fulfillment system.
MediStore is a full-featured online pharmacy platform that supports multi-seller listings, prescription management, flash sales, wallet payments, and a sophisticated multi-warehouse fulfillment pipeline. Orders placed by customers are intelligently routed through the nearest warehouse using GPS-based geo-resolution, consolidated from multiple sellers, packed, and dispatched for delivery.
Layer
Technology
Runtime
Node.js (TypeScript)
Framework
Express.js
ORM
Prisma ORM
Database
PostgreSQL (via Prisma)
Authentication
Better Auth (session-based, cookie-backed)
File Uploads
Multer + Cloudinary
Email
Nodemailer
AI Chatbot
Google Gemini API
Payments
SSLCommerz
Geo Resolution
Custom Bangladesh district/division lookup
Dev Tools
ts-node, nodemon, eslint
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MediStore Backend β
β β
β ββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββββββ β
β β Customer β β Seller β β Admin β β Warehouse β β
β β Client β β Client β β Client β β Manager β β
β ββββββ¬ββββββ ββββββ¬ββββββ ββββββ¬ββββββ βββββββββ¬βββββββββ β
β β β β β β
β ββββββ΄βββββββββββββββ΄βββββββββββββββ΄βββββββββββββββββββ΄βββββββββ β
β Express REST API (port 4000) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Business Logic Modules (39 modules) β β
β β auth Β· orders Β· medicines Β· seller Β· cart Β· wallet Β· β β
β β fulfillment Β· shipmentLeg Β· warehouse Β· grn Β· coupon Β· β β
β β flashSale Β· prescription Β· payment Β· chatbot Β· profile... β β
β βββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ β
β β Prisma ORM ββ PostgreSQL β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Role
Capabilities
CUSTOMER
Browse, cart, checkout, track orders, wallet, prescriptions, returns
SELLER
List medicines, manage inventory, batches, flash sales, sub-order management
ADMIN
Platform-wide management, license approvals, user control, CMS
WAREHOUSE
Routing, pick & pack, dispatch, inventory, GRN, stock transfers
Customer selects medicines β Cart β Checkout
β Nearest destination warehouse resolved via GPS / district name
β Per-seller sub-orders created
β Per-seller shipment legs created (originWH = seller's nearest WH, destWH = customer's nearest WH)
β Wallet / SSLCommerz payment processed
2. Same-Warehouse (Fast Path)
originWH === destWH
β Leg status: AWAITING_ORIGIN_WH
β Warehouse receives from seller β status: AT_DEST_WH (direct skip)
β FulfillmentTask created immediately
β Proceeds to Pick & Pack
3. Multi-Warehouse (Transit Path)
originWH β destWH
β Leg: AWAITING_ORIGIN_WH β AT_ORIGIN_WH β IN_TRANSIT β AT_DEST_WH
β FulfillmentTask created when first leg arrives
β Workers stage packages as each seller's leg arrives
Warehouse Fulfillment Workflow
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Warehouse Fulfillment Pipeline β
β β
β [/routing] β
β Seller ships βββΊ Confirm Receipt (origin WH) β
β β β
β Same WH? ββYesβββΊ AT_DEST_WH (skip transit) β
β βNo β
β Dispatch to dest WH β
β β β
β Confirm Arrival at dest WH β
β β β
β AT_DEST_WH + FulfillmentTask created β
β β
β [/packing] β
β Mark each seller's package RECEIVED (per leg) β
β All legs received? βββΊ Create Packing Slip (PICKED) β
β β β
β [/dispatch] β
β PACKED βββΊ Dispatch to Customer (DISPATCHED) β
β βββΊ Customer Receives β DELIVERED β
β β β
β Auto-credit each seller wallet β
β β
β [/fulfillment] (history archive) β
β Read-only log of all DELIVERED orders + timeline β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Fulfillment Status Transitions
PENDING β CONSOLIDATING β PICKED β PACKED β DISPATCHED β DELIVERED
Shipment Leg Status Transitions
SELLER_PREPARING β AWAITING_ORIGIN_WH β AT_ORIGIN_WH β IN_TRANSIT β AT_DEST_WH
β same-WH shortcut βββββββββββββββ
Module
Path
Purpose
auth
/api/auth
Session-based auth via Better Auth
orders
/api/orders
Order creation, GPS warehouse resolution
cart
/api/cart
Shopping cart management
medicines
/api/medicines
Listings, stock, CRUD
seller
/api/seller
Seller dashboard, revenue, analytics
subOrder
/api/sub-orders
Per-seller order slices
payment
/api/payments
SSLCommerz integration
wallet
/api/wallet
Balance, transactions, credits
coupon
/api/coupons
Discount code engine
flashSale
/api/flash-sales
Time-limited sale pricing
prescription
/api/prescriptions
Upload & verification
return
/api/returns
Return request workflow
wishlist
/api/wishlist
Customer wishlist
search
/api/search
Medicine full-text search
π Warehouse Management System (WMS)
Module
Path
Purpose
warehouse
/api/warehouses
Warehouse CRUD, manager assignment
shipmentLeg
/api/shipment-legs
Inter-warehouse routing, same-WH detection
fulfillment
/api/fulfillment
Pack/dispatch/deliver lifecycle
grn
/api/grn
Goods Receipt Notes from suppliers
stockTransfer
/api/stock-transfers
Intra-warehouse stock movement
storageBin
/api/storage-bins
Bin allocation and location management
supplier
/api/suppliers
Supplier records and shipments
expiryAlert
/api/expiry-alerts
Medicine expiry monitoring
temperatureLog
/api/temperature-logs
Cold chain compliance logging
warehouseAnalytics
/api/warehouse-analytics
Operational KPI dashboard
medicineBatch
/api/batches
Batch/lot tracking
stockAlert
/api/stock-alerts
Low-stock notifications
Module
Path
Purpose
banner
/api/banners
Homepage hero banners
blog
/api/blogs
Health articles
testimonial
/api/testimonials
Customer reviews display
platformFeature
/api/platform-features
Feature highlight cards
newsletter
/api/newsletter
Email subscription
contact
/api/contact
Contact form messages
chatbot
/api/chatbot
AI-powered pharmacy assistant
notification
/api/notifications
In-app alerts
sellerLicense
/api/seller-license
License upload & admin approval
subscription
/api/subscriptions
Premium plan management
profile
/api/profile
Unified user profile endpoint
admin
/api/admin
Admin controls & analytics
dashboard
/api/dashboard
Role-based dashboard stats
Method
Endpoint
Description
POST
/api/auth/sign-up
Register a new user
POST
/api/auth/sign-in
Login
POST
/api/auth/sign-out
Logout
GET
/api/auth/session
Get current session
Method
Endpoint
Description
POST
/api/orders
Place order (GPS routing)
GET
/api/orders/my
Customer's orders
GET
/api/orders/:id
Order detail
PATCH
/api/orders/:id/cancel
Cancel order
Method
Endpoint
Description
GET
/api/fulfillment/my-queue
Warehouse's fulfillment queue
PATCH
/api/fulfillment/:id/receive-item
Mark seller package received
PATCH
/api/fulfillment/:id/pack
Create packing slip
PATCH
/api/fulfillment/:id/dispatch
Dispatch to customer
PATCH
/api/fulfillment/:id/deliver
Confirm delivery + pay sellers
Method
Endpoint
Description
GET
/api/shipment-legs/mine
Legs for this warehouse
PATCH
/api/shipment-legs/:id/receive-at-origin
Receive from seller (same-WH skip)
PATCH
/api/shipment-legs/:id/dispatch
Dispatch to dest WH
PATCH
/api/shipment-legs/:id/receive-at-dest
Confirm arrival at dest WH
User (CUSTOMER/SELLER/ADMIN/WAREHOUSE)
βββ Order
βββ OrderItem (medicine, qty, price)
βββ SubOrder (per seller)
β βββ ShipmentLeg (originWH β destWH)
β βββ OrderItem (scoped to seller)
βββ FulfillmentTask (warehouse pack/dispatch lifecycle)
β βββ PackingSlip
βββ OrderTracking (status audit trail)
Medicine
βββ MedicineBatch (lot/expiry tracking)
βββ FlashSale
βββ StockAlert
βββ Review
Warehouse
βββ StorageBin β BinAllocation
βββ WarehouseLocation β LocationStock
βββ GoodsReceiptNote β GRNItem
βββ StockTransfer β StockTransferItem
βββ TemperatureLog
βββ ExpiryAlert
Wallet
βββ WalletTransaction
βββ WithdrawalRequest
Node.js β₯ 18
PostgreSQL database
Cloudinary account (for image/PDF uploads)
SSLCommerz merchant account (for payments)
Google Gemini API key (for chatbot)
# Clone the repository
git clone < repo-url>
cd mediStore_backend
# Install dependencies
npm install
# Generate Prisma client
npx prisma generate
# Push schema to database
npx prisma db push
# Start development server
npm run dev
npm run dev # Start with ts-node-dev (hot reload)
npm run build # Compile TypeScript to dist/
npm run start # Run compiled output
npm run seed # Seed initial data
# Clear all transactional data (keep users + medicines)
npx ts-node clear-orders.ts
# Count records per model
npx ts-node count.ts
Create a .env file in the project root:
# Database
DATABASE_URL = " postgresql://user:password@localhost:5432/medistore"
# Authentication (Better Auth)
BETTER_AUTH_SECRET = " your-secret-key"
BETTER_AUTH_URL = " http://localhost:4000"
# Cloudinary
CLOUDINARY_CLOUD_NAME = " your-cloud-name"
CLOUDINARY_API_KEY = " your-api-key"
CLOUDINARY_API_SECRET = " your-api-secret"
# SSLCommerz Payment
SSLCOMMERZ_STORE_ID = " your-store-id"
SSLCOMMERZ_STORE_PASS = " your-store-password"
SSLCOMMERZ_IS_LIVE = false
# Google Gemini AI
GEMINI_API_KEY = " your-gemini-key"
# Email (Nodemailer)
SMTP_HOST = " smtp.gmail.com"
SMTP_PORT = 587
SMTP_USER = " your@email.com"
SMTP_PASS = " your-app-password"
# App
PORT = 4000
NODE_ENV = development
FRONTEND_URL = " http://localhost:3000"
npx prisma studio # Visual database browser
npx prisma migrate dev # Create and apply migration
npx prisma migrate reset # Reset database
npx prisma db push # Push schema without migration history
npx prisma generate # Regenerate client
Create warehouses via POST /api/warehouses with lat, lng, city
Assign a manager: PATCH /api/warehouses/:id/assign-manager
Warehouses without lat/lng are skipped in geo-resolution (Infinity distance)
mediStore_backend/
βββ prisma/
β βββ schema.prisma # 50+ model definitions
βββ src/
β βββ app.ts # Express app, CORS, route mounting
β βββ server.ts # HTTP server bootstrap
β βββ config/ # Environment configuration
β βββ errorHelpers/ # AppError, async wrappers
β βββ interfaces/ # Shared TypeScript interfaces
β βββ lib/
β β βββ auth.ts # Better Auth configuration
β β βββ prisma.ts # Prisma client (named export)
β β βββ cloudinary.ts # Cloudinary setup
β βββ middleware/
β β βββ globalErrorHandler.ts
β β βββ authMiddleware.ts # Session validation
β β βββ roleGuard.ts # Role-based access
β βββ module/ # 39 feature modules
β β βββ orders/ # GPS warehouse routing, order creation
β β βββ fulfillment/ # Pack β dispatch β deliver lifecycle
β β βββ shipmentLeg/ # Inter-warehouse routing + same-WH detection
β β βββ warehouse/ # WH CRUD, manager assignment
β β βββ ...
β βββ utils/
β β βββ bdGeo.ts # Bangladesh GPS β district/division lookup
β β βββ haversine.ts # Great-circle distance
β βββ template/ # Email templates
βββ clear-orders.ts # Bulk data reset utility
βββ count.ts # Record count utility
βββ package.json
Geographic Warehouse Resolution
The nearestWarehouse() function in order.service.ts resolves the correct warehouse using:
GPS pattern first β Detects GPS(lat,lng) embedded in customer address via regex (avoids comma-split bug)
District/division fallback β Parses Bangladesh district and division names from address tokens
Haversine distance β Calculates great-circle distance to all active warehouses
Null-safe β Warehouses missing lat/lng receive Infinity distance (never selected unless all warehouses lack coordinates)
First-warehouse fallback β Used only if no coordinates can be resolved at all
Coverage: 8 divisions + 64 districts + common alternate spellings (e.g., Barisal/Barishal, Cumilla/Comilla)
MIT Β© MediStore Team