Skip to content

asapial/mediStore_backend

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

54 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ₯ 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.


πŸ“‹ Table of Contents


Overview

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.


Tech Stack

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

System Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        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                    β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

User Roles & Permissions

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

Core Workflow

1. Order Placement

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 Reference

πŸ›’ Commerce Core

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

πŸ“£ CMS & Engagement

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

API Endpoints

Authentication

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

Orders

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

Fulfillment

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

Shipment Legs

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

Data Models

Key Relationships

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

Getting Started

Prerequisites

  • Node.js β‰₯ 18
  • PostgreSQL database
  • Cloudinary account (for image/PDF uploads)
  • SSLCommerz merchant account (for payments)
  • Google Gemini API key (for chatbot)

Installation

# 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

Development Scripts

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

Utility Scripts

# Clear all transactional data (keep users + medicines)
npx ts-node clear-orders.ts

# Count records per model
npx ts-node count.ts

Environment Variables

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"

Database Management

Prisma Commands

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

Warehouse Setup

  1. Create warehouses via POST /api/warehouses with lat, lng, city
  2. Assign a manager: PATCH /api/warehouses/:id/assign-manager
  3. Warehouses without lat/lng are skipped in geo-resolution (Infinity distance)

Project Structure

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:

  1. GPS pattern first β€” Detects GPS(lat,lng) embedded in customer address via regex (avoids comma-split bug)
  2. District/division fallback β€” Parses Bangladesh district and division names from address tokens
  3. Haversine distance β€” Calculates great-circle distance to all active warehouses
  4. Null-safe β€” Warehouses missing lat/lng receive Infinity distance (never selected unless all warehouses lack coordinates)
  5. 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)


License

MIT Β© MediStore Team

About

A robust, production-ready RESTful API for an online medicine e-commerce platform. Built with Express 5, TypeScript, Prisma 7, and PostgreSQL.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors