Skip to content

md-nasim-mondal/parcel-dms-server

Repository files navigation

Parcel Delivery API

🎯 Project Overview

A secure, modular, and role-based backend API for a parcel delivery system (inspired by Pathao Courier or Sundarban) built with Express.js, TypeScript, and Mongoose. This system allows users to register as senders or receivers and perform parcel delivery operations such as create parcel, track status, and cancel or receive parcels.


Live Demo: Parcel Delivery Management System.

Postman Collection: Parcel Delivery Management System Postman Collection.

🧱 Features

  • πŸ” Authentication: Email/password-based login using JWT.
  • πŸ” Role-based access (SENDER, RECEIVER, ADMIN, SUPER_ADMIN, DELIVERY_PERSONNEL)
  • πŸ“¦ Parcel lifecycle: Request, approve, picked, dispatch, deliver, block, cancel, flagged
  • πŸ”„ Status Tracking: Track status changes for each parcel.
  • πŸ“² OTP-based registration verification support
  • 🧱 Scalable Modular Architecture
  • 🎟️ Coupon support (only admin/super admin can create)
  • ⚠️ Global error and validation handling
  • πŸ“§ Email notifications for OTP and password reset

🧩 Tech Stack

  • Node.js + Express β€” Backend framework
  • MongoDB + Mongoose β€” NoSQL Database with ODM
  • Zod β€” Schema validation
  • TypeScript β€” Optional typing (if enabled)
  • JWT β€” Authentication
  • SSL_Commerz β€” For Future Payment System
  • dotenv β€” Config management
  • Redis β€” Caching and session management
  • Redis β€” Caching and session management
  • EJS β€” Email templating
  • Postman β€” API testing and documentation
  • ESLint β€” Code quality and linting
  • Prettier β€” Code formatting
  • Nodemailer β€” Email sending
  • Vercel β€” Deployment platform

πŸ‘€ Some Credentials For Checking:


// ADMIN
email: "bedonad434@ekuali.com",
password: "12345@Mn"

// SENDER
email: "vilicab354@poesd.com",
password: "12345@Mn"

// RECEIVER
email: "ciweto1555@ekuali.com",
password: "12345@Mn",

//Delivery Personnel ID
 68ca9515cd3fcd1818b93892


✨ Features Implemented

πŸ” Authentication & Authorization

  • JWT-based authentication system
  • Secure password hashing with bcrypt
  • Role-based access control (admin, sender, receiver, super_admin)
  • Google OAuth integration with Passport.js
  • OTP verification system
  • Refresh token mechanism

πŸ‘₯ User Management

  • User registration and login
  • Profile management
  • User blocking/unblocking (Admin)
  • Email verification system

πŸ“¦ Parcel Management

  • Sender Features:

    • Create parcel delivery requests
    • Cancel parcels (if not dispatched)
    • View all their parcels with status logs
    • Delete parcels (with restrictions)
  • Receiver Features:

    • View incoming parcels
    • Confirm parcel delivery
    • View delivery history
  • Admin Features:

    • View and manage all users and parcels
    • Block or unblock users/parcels
    • Update delivery statuses
    • Assign delivery personnel
    • Create parcels on behalf of users

πŸ” Tracking System

  • Unique tracking ID generation (Format: TRK-YYYYMMDD-XXXXXX)
  • Public parcel tracking by tracking ID
  • Embedded status logs within parcel documents
  • Complete status transition validation

πŸ’° Additional Features

  • Dynamic fee calculation based on weight, type, and shipping method
  • Coupon system for discounts
  • Statistics and analytics
  • Advanced search and filtering
  • Pagination support

πŸ—οΈ Project Structure

β”œβ”€β”€ .git/ 🚫 (auto-hidden)
β”œβ”€β”€ dist/ 🚫 (auto-hidden)
β”œβ”€β”€ node_modules/ 🚫 (auto-hidden)
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”‚   β”œβ”€β”€ cloudinary.config.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ env.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ multer.config.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ passport.ts
β”‚   β”‚   β”‚   └── redis.config.ts
β”‚   β”‚   β”œβ”€β”€ errorHelpers/
β”‚   β”‚   β”‚   β”œβ”€β”€ AppError.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handleCastError.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handleDuplicate.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handleDuplicateError.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handleValidationError.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handleZodError.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ handlerValidationError.ts
β”‚   β”‚   β”‚   └── handlerZodError.ts
β”‚   β”‚   β”œβ”€β”€ interfaces/
β”‚   β”‚   β”‚   β”œβ”€β”€ error.types.ts
β”‚   β”‚   β”‚   └── index.d.ts
β”‚   β”‚   β”œβ”€β”€ middlewares/
β”‚   β”‚   β”‚   β”œβ”€β”€ checkAuth.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ globalErrorHandler.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ notFound.ts
β”‚   β”‚   β”‚   └── validateRequest.ts
β”‚   β”‚   β”œβ”€β”€ modules/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth.controller.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ auth.route.ts
β”‚   β”‚   β”‚   β”‚   └── auth.service.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ coupon/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.controller.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.interface.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.model.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.route.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.service.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ coupon.utils.ts
β”‚   β”‚   β”‚   β”‚   └── coupon.validation.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ otp/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ otp.controller.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ otp.route.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ otp.service.ts
β”‚   β”‚   β”‚   β”‚   └── otp.validation.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ parcel/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.controller.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.interface.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.model.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.route.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.service.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ parcel.utils.ts
β”‚   β”‚   β”‚   β”‚   └── parcel.validation.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ stats/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ stats.controller.ts
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ stats.route.ts
β”‚   β”‚   β”‚   β”‚   └── stats.service.ts
β”‚   β”‚   β”‚   └── user/
β”‚   β”‚   β”‚       β”œβ”€β”€ user.constant.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ user.controller.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ user.interface.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ user.model.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ user.route.ts
β”‚   β”‚   β”‚       β”œβ”€β”€ user.service.ts
β”‚   β”‚   β”‚       └── user.validation.ts
β”‚   β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”‚   └── index.ts
β”‚   β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”‚   β”œβ”€β”€ templates/
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ forgetPassword.ejs
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ invoice.ejs
β”‚   β”‚   β”‚   β”‚   └── otp.ejs
β”‚   β”‚   β”‚   β”œβ”€β”€ QueryBuilder.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ catchAsync.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ generateTrackingId.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ getTransactionId.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ invoice.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ jwt.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ seedSuperAdmin.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ sendEmail.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ sendResponse.ts
β”‚   β”‚   β”‚   β”œβ”€β”€ setCookie.ts
β”‚   β”‚   β”‚   └── userTokens.ts
β”‚   β”‚   └── constants.ts
β”‚   β”œβ”€β”€ app.ts
β”‚   └── server.ts
β”œβ”€β”€ .env 🚫 (auto-hidden)
β”œβ”€β”€ .gitignore
β”œβ”€β”€ README.md
β”œβ”€β”€ eslint.config.mjs
β”œβ”€β”€ package-lock.json
β”œβ”€β”€ package.json
└── tsconfig.json

πŸš€ Setup Instructions

Prerequisites

  • Node.js (v16 or higher)
  • MongoDB
  • Redis (for session management)
  • npm or yarn

Installation

  1. Clone the repository:
git clone https://github.com/md-nasim-mondal/parcel-dms-server
cd parcel-dms-server
  1. Install dependencies:
npm install
  1. Environment Setup: Create a .env file in the root directory:
NODE_ENV=development
PORT=5000
DB_URL=mongodb://localhost:27017
NODE_ENV=development

#JWT
JWT_ACCESS_SECRET=your_jwt_access_secret
JWT_REFRESH_SECRET=your_jwt_refresh_secret
JWT_ACCESS_EXPIRES=1d
JWT_REFRESH_EXPIRES=30d

# BCRYPT
BCRYPT_SALT_ROUNDS=your_bcrypt_salt_round


#For Seed SUPER ADMIN
SUPER_ADMIN_EMAIL=your_super_admin_email
SUPER_ADMIN_PASSWORD=your_super_admin_password


# Google
GOOGLE_CLIENT_ID=your_google_Oauth_client_id
GOOGLE_CLIENT_SECRET=your_google_Oauth_client_secret
GOOGLE_CALLBACK_URL=http://localhost:5000/api/v1/auth/google/callback

# Express Session
EXPRESS_SESSION_SECRET=express-session

# Frontend URL
FRONTEND_URL=http://localhost:5173


#sslCommerz
SSL_STORE_ID=your_ssl_store_id
SSL_STORE_PASS=your_ssl_store_pass
SSL_PAYMENT_API=ssl_payment_api
SSL_VALIDATION_API=ssl_payment_validation_api
SSL_IPN_URL=your_ipn_url


# SSL Commerz BACKEND URLs
SSL_SUCCESS_BACKEND_URL="http://localhost:5000/api/v1/payment/success"
SSL_FAIL_BACKEND_URL="http://localhost:5000/api/v1/payment/fail"
SSL_CANCEL_BACKEND_URL="http://localhost:5000/api/v1/payment/cancel"


# SSL Commerz FRONTEND URLs
SSL_SUCCESS_FRONTEND_URL="http://localhost:5173/payment/success"
SSL_FAIL_FRONTEND_URL="http://localhost:5173/payment/fail"
SSL_CANCEL_FRONTEND_URL="http://localhost:5173/payment/cancel"

# CLOUDINARY Setup
CLOUDINARY_CLOUD_NAME=your_cloudinary_cloud_name
CLOUDINARY_API_KEY=your_cloudinary_api_key
CLOUDINARY_API_SECRET=your_cloudinary_api_secret

# SMTP GMAIL Setup With Nodemailer
SMTP_HOST=smtp.gmail.com
SMTP_PORT=465
SMTP_USER=your_smtp_user_email_address
SMTP_PASS=your_smtp_user_email_app_pass
SMTP_FORM=your_smtp_user_email_address

# Redis Setup
REDIS_HOST=your_redis_host_url or redis://localhost:6379
REDIS_PORT=13474
REDIS_USERNAME=your_redis_username
REDIS_PASSWORD=your_redis_password
  1. Start the development server:
npm run dev
  1. Build for production:
npm run build
npm start

πŸ“‹ API Endpoints

Authentication Routes (/api/v1/auth)

  • POST /register - User registration
  • POST /login - User login
  • POST /refresh-token - Get new access token
  • POST /change-password - Change password
  • POST /forgot-password - Forgot password
  • POST /reset-password - Reset password
  • GET /google - Google OAuth login

User Routes (/api/v1/users)

  • GET / - Get all users (Admin only)
  • GET /me - Get current user profile
  • GET /:id - Get single user (Admin only)
  • PUT /:id - Update user profile

Parcel Routes (/api/v1/parcels)

Sender Routes

  • POST / - Create parcel (Sender only)
  • POST /cancel/:id - Cancel parcel (Sender only)
  • DELETE /delete/:id - Delete parcel (Sender only)
  • GET /me - Get sender's parcels (Sender only)
  • GET /status-log/:id - Get parcel with history (Sender only)

Receiver Routes

  • GET /me/incoming - Get incoming parcels (Receiver only)
  • PATCH /confirm/:id - Confirm delivery (Receiver only)
  • GET /me/history - Get delivery history (Receiver only)

Admin Routes

  • GET / - Get all parcels (Admin only)
  • POST /create-parcel - Create parcel by admin (Admin only)
  • PATCH /delivery-status/:id - Update parcel status (Admin only)
  • PATCH /block-status/:id - Block/unblock parcel (Admin only)
  • GET /details/:id - Get parcel details (Admin only)

Public Routes

  • GET /tracking/:trackingId - Track parcel by tracking ID

OTP Routes (/api/v1/otp)

  • POST /send - Send OTP
  • POST /verify - Verify OTP

Coupon Routes (/api/v1/coupons)

  • POST / - Create coupon (Admin only)
  • GET / - Get all coupons

For applying coupons code you need to sendCoupon code as couponCode in parcel create time

Stats Routes (/api/v1/stats)

  • GET /user - Get system user statistics (Admin only)
  • GET /parcel - Get system parcel statistics (Admin only)

πŸ”’ Authentication & Authorization

Roles

  • SENDER: Can create, cancel, and view their parcels
  • RECEIVER: Can view incoming parcels and confirm deliveries
  • ADMIN: Can manage users and parcels
  • SUPER_ADMIN: Full Admin system access and super admin can demoted a admin

JWT Token Structure

{
  "userId": "user_id",
  "email": "user@example.com",
  "role": "SENDER",
  "iat": 1234567890,
  "exp": 1234567890
}

πŸ“¦ Parcel Status Flow

The parcel lifecycle goes through multiple stages. At each stage, certain exceptions such as Cancel, Return, Reschedule, Flag, On Hold, or Blocked may occur.

πŸ”„ Main Flow

REQUESTED β†’ APPROVED β†’ PICKED β†’ DISPATCHED β†’ IN_TRANSIT β†’ DELIVERED

❌ Cancel / Return / Reschedule Paths

REQUESTED β†’ CANCELLED APPROVED β†’ CANCELLED PICKED β†’ RETURNED DISPATCHED β†’ RETURNED IN_TRANSIT β†’ RESCHEDULED

⚠️ Special Cases

CANCELLED β†’ FLAGGED β†’ BLOCKED RETURNED β†’ FLAGGED β†’ BLOCKED RESCHEDULED β†’ ON_HOLD β†’ BLOCKED


πŸ“– Status Explanation

  • REQUESTED β†’ When the customer places an order.
  • APPROVED β†’ When the order is verified and approved by the seller/admin.
  • PICKED β†’ When the courier picks up the parcel.
  • DISPATCHED β†’ When the parcel is dispatched toward its destination.
  • IN_TRANSIT β†’ While the parcel is on the way.
  • DELIVERED β†’ When the parcel is successfully delivered to the customer.
  • CANCELLED / RETURNED / RESCHEDULED β†’ Possible exception states depending on customer or delivery issues.
  • FLAGGED / ON_HOLD / BLOCKED β†’ Security or policy-related statuses for further investigation.

βœ… This flow clearly illustrates how a parcel progresses step by step and what exceptional cases may occur during the delivery process.

🎯 Parcel Features

Tracking ID Format

  • Format: TRK-YYYYMMDD-XXXXXX
  • Example: TRK-20241201-A1B2C3

Fee Calculation

  • Base fee: ΰ§³50
  • Weight-based pricing:
    • Up to 500g: +ΰ§³50
    • 500g-1kg: +ΰ§³100
    • 1kg-2kg: +ΰ§³150
    • 2kg-5kg: +ΰ§³250
    • 5kg-10kg: +ΰ§³400

Parcel Types

  • DOCUMENT: No surcharge
  • PACKAGE: +ΰ§³10
  • FRAGILE: +ΰ§³25
  • ELECTRONICS: +ΰ§³40

Shipping Types

  • STANDARD: No surcharge (5 days)
  • EXPRESS: +ΰ§³50 (2 days)
  • OVERNIGHT: +ΰ§³75 (1 day)
  • SAME_DAY: +ΰ§³100 (6 hours)

πŸ› οΈ Technologies Used

  • Backend: Node.js, Express.js, TypeScript
  • Database: MongoDB with Mongoose ODM
  • Authentication: JWT, bcrypt, Passport.js
  • Session Store: Redis
  • Validation: Zod
  • Development: ts-node-dev, ESLint, Prettier

πŸ§ͺ Testing

Use the provided Postman collection to test all endpoints. Import the collection and set up the environment variables:

  • baseURL: http://localhost:5000/api/v1
  • accessToken: JWT token from login response

πŸ“ Sample API Requests

User Registration

POST /api/v1/auth/register
{
  "name": "John Doe",
  "email": "john@example.com",
  "password": "password123",
  "role": "SENDER",
  "phone": "+8801234567890",
  "defaultAddress": "123 Main St, Dhaka"
}

Create Parcel by Admin

POST /api/v1/parcels
{
  "receiverName": "Jane Smith",
  "receiverPhone": "+8801987654321",
  "receiverEmail": "jane@example.com",
  "pickupAddress": "123 Sender St, Dhaka",
  "deliveryAddress": "456 Receiver Ave, Chittagong",
  "weight": 2.5,
  "type": "PACKAGE",
  "shippingType": "EXPRESS",
  "description": "Important documents"
}

Track Parcel

GET /api/v1/parcel/tracking/TRK-20241201-A1B2C3

πŸ”§ Development Scripts

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm start - Start production server
  • npm run lint - Run ESLint
  • npm run lint:fix - Fix ESLint issues
  • npm run prettier - Format code with Prettier

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests and linting
  5. Submit a pull request

πŸ“„ License

This project is licensed under the MIT License.

πŸ‘¨β€πŸ’» Author

Developed with ❀️ for the parcel delivery system.


Note: This API is fully functional and includes all the requirements specified in the project brief. All endpoints are protected with proper authentication and authorization, and the system supports complete parcel lifecycle management with embedded status tracking. Additionally, the system includes coupon management features, allowing for the creation, application, and management of discount codes for parcel deliveries.