A comprehensive full-stack single vendor e-commerce system built with Express.js, Sequelize ORM, and MySQL. This system supports multiple business types including visa agencies, travel agencies, IT firms, educational institutions, and more.
- Role-Based Access Control: Hierarchical permission system with score-based access
- JWT Authentication: Secure authentication with refresh tokens
- RESTful API: Well-documented API with Swagger/OpenAPI
- Database Migrations: Sequelize-based database versioning
- Audit Logging: Complete audit trail for all user actions
- Backend: Node.js, Express.js
- Database: MySQL/Postgres with Sequelize ORM
- Authentication: JWT with bcryptjs
- Documentation: Swagger/OpenAPI
- File Upload: Express file upload
- Validation: Joi
- Rate Limiting: Express Rate Limit
- Security: Helmet, CORS
- Containerization: Docker & Docker Compose
``` src/ ├── assets/ # Static files & uploads ├── middleware/ # Authentication, error handling, rate limiting ├── admin/ # Admin-specific modules │ ├── controllers/ │ ├── routes/ │ └── services/ ├── user/ # User-specific modules ├── config/ # Database and app configuration ├── utils/ # Utility functions and helpers ├── models/ # Sequelize models with associations ├── migrations/ # Database migration files ├── seeders/ # Database seed files ├── scripts/ # CLI utilities and seed scripts ├── routes/ # API route definitions ├── webhooks/ # Webhook handlers └── server.js # Application entry point ```
Ensure you have the following installed on your machine:
- Node.js (v22.8.0 or higher)
- PostgreSQL
- npm or yarn
-
Install PostgreSQL via Homebrew:
If you have Homebrew installed, run the following command:
brew install postgresql
-
Start PostgreSQL:
After installation, you can start PostgreSQL with:
brew services start postgresql
-
Create a New Database User and Database:
psql postgres
In the
psqlshell, create a new user and database:CREATE USER your_username WITH PASSWORD 'your_password'; CREATE DATABASE your_database_name; GRANT ALL PRIVILEGES ON DATABASE your_database_name TO your_username;
-
Verify the Setup:
You can connect to your new database:
psql -U your_username -d your_database_name
-
Login and setup:
sudo -u postgres psql- Create new db
CREATE DATABASE your_db_name;- Create a new user (role) with password
CREATE USER your_username WITH PASSWORD 'your_password';- switch to your database
\c your_db_name;- Give full permissions on the DB to the user
GRANT ALL PRIVILEGES ON DATABASE your_db_name TO your_username;
or
GRANT ALL ON SCHEMA public to your_user_name
or
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO your_username;
- Make the user owner of the DB
ALTER DATABASE your_db_name OWNER TO your_username;-
Download PostgreSQL:
Download and install PostgreSQL from the official website: PostgreSQL for Windows.
-
Installation Process:
During the installation, you'll be prompted to create a superuser account (Postgres user) and set up a password.
-
Start PostgreSQL Service:
After installation, PostgreSQL should automatically start as a service. If not, you can manually start it from the "Services" panel on Windows.
-
Create a New Database:
Open
pgAdmin(PostgreSQL’s management tool) or use the command line to create a new user and database:psql -U postgres
In the
psqlshell, run the following:CREATE USER your_username WITH PASSWORD 'your_password'; CREATE DATABASE your_database_name; GRANT ALL PRIVILEGES ON DATABASE your_database_name TO your_username;
-
Verify the Setup:
Connect to your new database:
psql -U your_username -d your_database_name
-
Clone the Repository
First, clone the repository to your local machine:
git clone https://github.com/roshoon/roshoon-api.git
-
Install Dependencies
Navigate to the project directory and install the necessary Node.js dependencies:
cd erp-api npm install -
Set Up PostgreSQL Connection
Update your PostgreSQL connection details in
config.jsonor.env.If you're using environment variables, create a
.envfile with the following structure:DB_HOST=localhost DB_USER=your_username DB_PASSWORD=your_password DB_NAME=your_database_name DB_PORT=5432
-
Run Database Migrations
To create the required database tables and schema, run:
npx sequelize-cli db:migrate
-
Run the Application
Start the application:
node server.js
The app will be running on http://localhost:4545.
When creating a branch, please follow these conventions:
- Feature branches:
feature/[Jira-ticket-number]- Example:
feature/IVIS-12345
- Example:
- Bugfix branches:
bug/[Jira-ticket-number]- Example:
bug/IVIS-12345
- Example:
Follow this structure for commit messages:
[Jira-ticket-number]: Short description of the changeExample:
[IVIS-12345]: Add role management for usersWhen submitting a pull request:
- Add a detailed description of the changes made.
- Mention the relevant Jira ticket number.
- Describe how the changes were tested (unit tests, manual testing, etc.).
This project is licensed under the MIT License - see the LICENSE file for details.
npx sequelize-cli migration:generate --name create-your-table_name- Now Edit your migration file in the migrations folder and run:
npx sequelize-cli db:migratenpx sequelize-cli seed:generate --name seed-your-file-name- Now generate fake data
npx sequelize-cli db:seed:all- Now remove fake data
npx sequelize-cli db:seed:undo:allhttp://localhost:5000/api/v1
Most endpoints require authentication. Include the JWT token in the Authorization header:
Authorization: Bearer <your_jwt_token>
POST /auth/registerBody:
{
"name": "John Doe",
"email": "john@example.com",
"password": "password123",
"phone": "+1234567890",
"address": "123 Main St"
}POST /auth/loginBody:
{
"email": "john@example.com",
"password": "password123"
}GET /auth/profile
Authorization: Bearer <token>PUT /auth/update-profile
Authorization: Bearer <token>Body:
{
"name": "John Updated",
"phone": "+1234567890",
"address": "456 New St",
"avatar": "https://cloudinary.com/..."
}PUT /auth/update-password
Authorization: Bearer <token>Body:
{
"password": "oldPassword123",
"newPassword": "newPassword123",
"confirmPassword": "newPassword123"
}POST /auth/forgot-passwordBody:
{
"email": "john@example.com"
}POST /auth/reset-password?token=<reset_token>Body:
{
"newPassword": "newPassword123",
"confirmPassword": "newPassword123"
}POST /auth/logout
Authorization: Bearer <token>GET /categories?page=1&limit=10&search=laptop&sortBy=name&sortOrder=ASCQuery Parameters:
page(optional): Page number (default: 1)limit(optional): Items per page (default: 10)search(optional): Search by name or descriptionsortBy(optional): Sort field (default: created_at)sortOrder(optional): ASC or DESC (default: DESC)
GET /categories/:idPOST /categories
Authorization: Bearer <admin_token>Body:
{
"name": "Laptops",
"description": "High-performance laptops",
"image": "https://cloudinary.com/..."
}PUT /categories/:id
Authorization: Bearer <admin_token>Body:
{
"name": "Updated Laptops",
"description": "Updated description",
"image": "https://cloudinary.com/..."
}DELETE /categories/:id
Authorization: Bearer <admin_token>GET /products?page=1&limit=10&search=macbook&category_id=xxx&min_price=100&max_price=2000&status=active&sortBy=price&sortOrder=ASCQuery Parameters:
page(optional): Page numberlimit(optional): Items per pagesearch(optional): Search by name or descriptioncategory_id(optional): Filter by categorymin_price(optional): Minimum price filtermax_price(optional): Maximum price filterstatus(optional): active, inactive, out_of_stocksortBy(optional): Sort fieldsortOrder(optional): ASC or DESC
GET /products/:idPOST /products
Authorization: Bearer <admin_token>Body:
{
"name": "MacBook Pro 14",
"description": "Powerful laptop with M3 chip",
"price": 1999,
"category_id": "category-uuid",
"stock": 15,
"image": "https://cloudinary.com/...",
"rating": 4.8,
"reviews": 234
}PUT /products/:id
Authorization: Bearer <admin_token>Body:
{
"name": "Updated MacBook Pro",
"price": 2199,
"stock": 20,
"status": "active"
}PATCH /products/:id/stock
Authorization: Bearer <admin_token>Body:
{
"quantity": 10,
"operation": "add"
}Operations: add or subtract
DELETE /products/:id
Authorization: Bearer <admin_token>POST /orders
Authorization: Bearer <token>Body:
{
"items": [
{
"product_id": "product-uuid",
"quantity": 2
}
],
"payment_method": "STRIPE",
"shipping_address": "123 Main St, City, State 12345",
"notes": "Please handle with care"
}Payment Methods: STRIPE, PAYPAL, CASH_ON_DELIVERY, BANK_TRANSFER
GET /orders?page=1&limit=10&status=PENDING&payment_method=STRIPE&user_id=xxx
Authorization: Bearer <admin_token>Query Parameters:
status: PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED, REFUNDEDpayment_method: STRIPE, PAYPAL, CASH_ON_DELIVERY, BANK_TRANSFERuser_id: Filter by user
GET /orders/my-orders?page=1&limit=10&status=DELIVERED
Authorization: Bearer <token>GET /orders/:id
Authorization: Bearer <token>PATCH /orders/:id/status
Authorization: Bearer <admin_token>Body:
{
"status": "SHIPPED",
"tracking_number": "TRK123456789"
}POST /orders/:id/cancel
Authorization: Bearer <token>GET /heroes/activeGET /heroes?page=1&limit=10&status=active&sortBy=order&sortOrder=ASC
Authorization: Bearer <admin_token>GET /heroes/:idPOST /heroes
Authorization: Bearer <admin_token>Body:
{
"title": "MacBook Pro M3",
"subtitle": "Supercharged for pros",
"description": "The most powerful MacBook Pro ever",
"image": "https://cloudinary.com/...",
"bg_color": "from-slate-900 to-slate-700",
"cta": "Shop Now",
"category_id": "category-uuid",
"product_id": "product-uuid",
"price": "$1,999",
"badge": "New Arrival",
"order": 1,
"status": "active"
}PUT /heroes/:id
Authorization: Bearer <admin_token>PATCH /heroes/:id/order
Authorization: Bearer <admin_token>Body:
{
"order": 2
}POST /heroes/reorder
Authorization: Bearer <admin_token>Body:
{
"orderArray": [
{ "id": "hero-uuid-1", "order": 1 },
{ "id": "hero-uuid-2", "order": 2 },
{ "id": "hero-uuid-3", "order": 3 }
]
}PATCH /heroes/:id/toggle-status
Authorization: Bearer <admin_token>DELETE /heroes/:id
Authorization: Bearer <admin_token>GET /transactions?page=1&limit=10&status=COMPLETED&method=STRIPE&user_id=xxx
Authorization: Bearer <admin_token>GET /transactions/my-transactions?page=1&limit=10&status=COMPLETED
Authorization: Bearer <token>GET /transactions/:id
Authorization: Bearer <token>GET /transactions/stats?start_date=2025-01-01&end_date=2025-12-31
Authorization: Bearer <admin_token>PATCH /transactions/:id/status
Authorization: Bearer <admin_token>Body:
{
"status": "COMPLETED",
"metadata": {
"payment_gateway_id": "pi_xxx",
"note": "Payment verified"
}
}POST /transactions/:id/process
Authorization: Bearer <token>Body:
{
"payment_details": {
"transaction_id": "stripe_pi_xxx",
"card_last4": "4242",
"card_brand": "visa"
}
}POST /transactions
Authorization: Bearer <admin_token>Body:
{
"order_id": "order-uuid",
"amount": 999.99,
"method": "STRIPE",
"transaction_id": "stripe_pi_xxx",
"metadata": {}
}GET /users?page=1&limit=10&search=john&role_id=xxx&status=active&sortBy=created_at&sortOrder=DESC
Authorization: Bearer <admin_token>GET /users/stats
Authorization: Bearer <admin_token>GET /users/:id
Authorization: Bearer <admin_token>PUT /users/:id
Authorization: Bearer <admin_token>Body:
{
"name": "Updated Name",
"phone": "+1234567890",
"address": "New Address"
}PATCH /users/:id/status
Authorization: Bearer <admin_token>Body:
{
"status": "active"
}Status Options: active, inactive, suspended
PATCH /users/:id/role
Authorization: Bearer <admin_token>Body:
{
"role_id": "role-uuid"
}DELETE /users/:id
Authorization: Bearer <admin_token>{
"success": true,
"message": "Operation successful",
"data": { ... },
"token": "jwt_token_here" // (optional, for login/register)
}{
"success": false,
"message": "Error message",
"error": "Detailed error description"
}{
"success": true,
"message": "Data fetched successfully",
"data": {
"items": [ ... ],
"pagination": {
"total": 100,
"page": 1,
"limit": 10,
"totalPages": 10
}
}
}- Access own profile
- View products
- Create orders
- View own orders
- Cancel own orders
- View own transactions
- Process payments
- Manage categories
- Manage products
- Manage all orders
- Manage hero slides
- Manage all transactions
- Manage users
- View dashboard and stats
200- OK201- Created202- Accepted (Update)400- Bad Request401- Unauthorized403- Forbidden404- Not Found500- Internal Server Error