A full-stack web application built with Django (backend) and React (frontend) for managing hardware or product-based devices within an organization.
It provides tools to:
- Register new devices with their serial numbers
- Approve devices for allocation
- Track device allocation status with full lifecycle management
- Deactivate devices when needed
- Map devices to customers with comprehensive filtering and sorting
- Manage authorized user access through JWT-based authentication
Designed for businesses and enterprises that need a streamlined device-tracking and allocation workflow.
- User signup and login with JWT token-based authentication
- Secure cookie-based session management with automatic token refresh
- Protected routes requiring authentication
- Role-based user system (configurable during signup)
- Device registration with unique serial numbers following pattern validation
- Device approval workflow - approve devices before allocation
- Allocation tracking - devices allocated through customer mapping
- Device lifecycle management - complete status tracking (0→1→2→3)
- Device deactivation - deactivate approved but unallocated devices
- Device details display - IMSI, IMEI, and Device ID tracking
- Special device handling - Support for devices with custom workflow
- Device-to-customer mapping - assign approved devices to customers
- Comprehensive filtering - filter by serial number, customer code, customer name, company, device type, approval status, and date range
- Advanced search - global search across multiple fields
- Sorting capabilities - sort by any column (ascending/descending)
- Pagination - configurable page sizes (5, 10, 25, 50, 100 records per page)
- Full CRUD operations - create, read, update mappings
- Auto-detection - device type automatically detected from serial number format
- Responsive design - works on desktop, tablet, and mobile devices
- Modal-based forms - clean interface for adding and editing mappings
- Real-time validation - client-side and server-side validation
- Loading states - clear feedback during API operations
- Error handling - comprehensive error messages and user feedback
- Advanced filtering - collapsible filter panel with multiple criteria
Frontend: React 19.2.0 + Vite
Backend: Django 5.2 + Django REST Framework
Database: MariaDB
Authentication: JWT (djangorestframework-simplejwt) with HTTP-only cookies
API Style: REST (DRF)
HTTP Client: Axios with token refresh interceptor
project-root/
├── BE/ # Backend (Django)
│ ├── manage.py
│ ├── BE/
│ │ ├── settings.py # Django settings with environment variables
│ │ ├── urls.py # Main URL configuration
│ │ └── wsgi.py
│ ├── ProductRegistration/ # Main Django app
│ │ ├── models.py # Database models
│ │ ├── serializers.py # DRF serializers
│ │ ├── views/
│ │ │ ├── auth_views.py # Authentication endpoints
│ │ │ ├── device_views.py # Device management endpoints
│ │ │ └── mapping_views.py # Customer mapping endpoints
│ │ └── urls.py # App URL patterns
│ └── .env # Environment variables (not in repo)
│
├── FE/ # Frontend (React + Vite)
│ ├── src/
│ │ ├── assets/
│ │ │ └── js/
│ │ │ ├── axiosConfig.js # Axios setup with interceptors
│ │ │ └── auth.js # Auth utility functions
│ │ ├── components/
│ │ │ ├── CustomerForm.jsx # Device-customer mapping form
│ │ │ ├── Modal.jsx # Reusable modal component
│ │ │ ├── ProtectedRoute.jsx # Route protection wrapper
│ │ │ └── Sidebar.jsx # Navigation sidebar
│ │ ├── pages/
│ │ │ ├── AddSerialNum.jsx # Serial number management page
│ │ │ ├── Home.jsx # Dashboard home page
│ │ │ ├── Layout.jsx # App layout wrapper
│ │ │ ├── ListingPage.jsx # Device-customer mapping page
│ │ │ ├── LoginPage.jsx # User login page
│ │ │ └── SignupPage.jsx # User registration page
│ │ ├── styles/ # CSS files
│ │ └── main.jsx # React entry point
│ ├── package.json
│ ├── vite.config.js
│ └── .env # Environment variables (not in repo)
│
└── README.md
- User signup with email, username, and password
- User login with JWT token generation
- Logout functionality with cookie cleanup
- Protected routes requiring authentication
- Automatic token refresh on expiration
- User session management via localStorage
- Add serial numbers with pattern validation (YYYYMM{AMP|API}XXXXXXB)
- View all registered devices in table format with filtering
- Approve serial numbers (production team workflow)
- Allocate devices through customer mapping
- Deactivate approved but unallocated devices
- Track full device lifecycle (Unallocated → Fetched → Allocated → Deactivated)
- Display device details (IMSI, IMEI, Device ID)
- Special handling for UPI PRO devices
- Fetch device details by serial number
- Advanced filtering and search in serial number list
- Pagination with multiple page size options
- View all device-customer mappings
- Create new mappings with approved devices
- Edit existing mappings
- Advanced filtering system:
- Filter by serial number, customer code, customer name
- Filter by company, device type, approval status
- Filter by date range (from/to dates)
- Global search across all fields
- Column-based sorting (all columns)
- Pagination with configurable page sizes
- Auto-detection of device type from serial format
- Full backend API integration
- Responsive design for all screen sizes
- Modal-based forms for clean UX
- Loading states and error handling
- Mobile-friendly navigation with hamburger menu
- Professional styling and layout
- Collapsible filter panels
- Enhanced ProtectedRoute using
/verify-auth/API endpoint (optional - currently uses localStorage for simplicity) - User role-based access control (RBAC)
- Permission-based feature restrictions
- Delete serial numbers endpoint and functionality
- Delete mapping endpoint and functionality
- Bulk mapping operations
- Export mappings to CSV/Excel
The application tracks devices through a complete lifecycle with four distinct states:
| Status | Value | Description | Transitions From | Transitions To |
|---|---|---|---|---|
| Unallocated | 0 | Device added but not assigned | - | Fetched (1), Deactivated (3) |
| Fetched | 1 | Device fetched via API for allocation | Unallocated (0) | Allocated (2) |
| Allocated | 2 | Device mapped to customer | Fetched (1) | - |
| Deactivated | 3 | Device removed from active pool | Unallocated (0) | - |
[New Device]
↓
[Unallocated: 0]
↓
[Approved by Production Team]
↓
├─→ [Fetched via API: 1] ─→ [Customer Mapping] ─→ [Allocated: 2]
│
└─→ [Deactivate] ─→ [Deactivated: 3]
- Only Approved (isapproved=1) and Unallocated (isallocated=0) devices can be deactivated
- Only Unallocated (0) devices appear in customer mapping dropdown
- Deactivated devices cannot be reactivated (permanent state)
- Allocated devices cannot be deactivated
- Python 3.8+
- Node.js 22
- MariaDB 10.5+
- Git
git clone <repository-url>
cd <project-directory>cd BE
python -m venv venv
# On Windows:
venv\Scripts\activate
# On macOS/Linux:
source venv/bin/activatepip install -r requirements.txtRequired packages (include in requirements.txt):
- django
- djangorestframework
- djangorestframework-simplejwt
- django-cors-headers
- mysqlclient
- django-environ
Create a .env file in the BE/ directory:
# Django Settings
SECRET_KEY=your-secret-key-here
DEBUG=True
ALLOWED_HOSTS=localhost,127.0.0.1
# Database Configuration
DB_NAME=your_database_name
DB_USER=your_database_user
DB_PASSWORD=your_database_password
DB_HOST=localhost
DB_PORT=3306
# CORS Settings
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173Security Notes:
- Set DEBUG=False in production
- Restrict ALLOWED_HOSTS in production
- Use environment-specific CORS_ALLOWED_ORIGINS
- Create MariaDB Database:
CREATE DATABASE your_database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;- Run Migrations:
python manage.py makemigrations
python manage.py migrate- Create Database Stored Procedures:
The application uses stored procedures for device and mapping operations. You'll need to create these in your database:
Device Management Procedures:
-
save_serial_number- Insert new serial numbers- Parameters:
serialnumber,category, OUTstatus, OUTmessage - Returns:
success,duplicate, orerror
- Parameters:
-
update_serial_number_approval- Approve serial numbers- Parameters:
serialnumber,isapproved, OUTstatus, OUTmessage - Returns:
success,not_found, orerror
- Parameters:
-
update_serial_number_allocate- Update allocation status- Parameters:
serialnumber,isallocated, OUTstatus, OUTmessage - Returns:
success,not_found, orerror - Note: Sets status to 1 (Fetched) or 2 (Allocated)
- Parameters:
-
get_single_unallocated_approved_serial- Fetch available serial for allocation- Parameters: OUT
serialnumber, OUTstatus, OUTmessage - Returns: Serial number of approved, unallocated device
- Parameters: OUT
-
save_upi_pro_serial_number- Handle UPI PRO device registration- Parameters:
serialnumber,category,isapproved,isallocated, OUTstatus, OUTmessage - Returns:
success,duplicate, orerror
- Parameters:
-
get_device_details_by_serial- Fetch device details- Parameters:
serialnumber - Returns: Device details row (IMSI, IMEI, deviceId, etc.)
- Parameters:
-
deactivate_serial_number- Deactivate approved but unallocated devices- Parameters:
serialnumber, OUTstatus, OUTmessage - Returns:
success,denied(if not eligible),not_found, orerror - Logic: Only devices with
isapproved=1ANDisallocated=0can be deactivated - Sets
isallocated=3for deactivated devices
- Parameters:
Customer Mapping Procedures:
-
save_serial_customer_details- Create device-customer mapping- Parameters:
serialnumber,uniqueIdentifier,customerCode,customerName,company,devicetype,licenseUrl,versionDetails, OUTstatus, OUTmessage - Returns:
success,duplicate, orerror - Note: Automatically updates device allocation status to 2 (Allocated)
- Parameters:
-
update_customer_by_serial- Update existing mapping- Parameters:
serialnumber,customerCode,uniqueIdentifier,customerName,company,devicetype,cLicenseURL,versionDetails, OUTstatus, OUTmessage - Returns:
success,not_found, orerror
- Parameters:
-
get_serial_customer_details- Fetch mappings with filtering and pagination- Parameters:
serialNumber,customerCode,customerName,company,deviceType,fromDate,toDate,approvedStatus,searchText,pageNumber,pageSize,sortingOrderIndex,sortingOrderDirection, OUTtotalCount - Returns: Result set with filtered mappings
- Parameters:
python manage.py runserver 8001The backend will be available at http://127.0.0.1:8001/
cd ../FEnpm installKey dependencies:
- react
- react-dom
- react-router-dom
- axios
Create a .env file in the FE/ directory:
VITE_API_BASE_URL=http://127.0.0.1:8001/silNotes:
- Vite requires the
VITE_prefix for environment variables - Adjust the base URL based on your backend configuration
- The
/silpath is the current API endpoint prefix (change accordingly)
npm run devThe frontend will be available at http://localhost:5173/ (default Vite port)
Base URL: http://127.0.0.1:8001/sil/
| Endpoint | Method | Description | Request Body | Response |
|---|---|---|---|---|
/signup/ |
POST | Register new user | {username, mailid, password, cpassword, role?} |
User data + success message |
/login/ |
POST | User login | {username, password} |
User data + JWT tokens in cookies |
/logout/ |
POST | User logout | None | Success message + clear cookies |
/token/refresh/ |
POST | Refresh access token | None (uses refresh_token cookie) | New access token in cookie |
/verify-auth/ |
GET | Verify authentication | None (uses access_token cookie) | User data if authenticated |
/protected/ |
GET | Test protected endpoint | None (uses access_token cookie) | User greeting |
Authentication Flow:
- Login sets HTTP-only cookies:
access_token(15 min) andrefresh_token(7 days) - Frontend axios interceptor automatically refreshes expired access tokens
- All protected endpoints validate access token from cookies
| Endpoint | Method | Description | Request Body | Response |
|---|---|---|---|---|
/get_serial_numbers/ |
GET | Retrieve all serial numbers | None | Array of device records |
/add_serial_number/ |
POST | Add new serial number | {serialnumber} |
Success/error status |
/approve_serial_number/ |
PATCH | Approve a serial number | {serialnumber} |
Success/error status |
/allocate_serial_number/ |
POST | Mark serial as allocated | {serialnumber} |
Success/error status |
/deactivate_serial_number/ |
POST | Deactivate device | {serialnumber} |
Success/denied/not_found/error |
/getSerialNumber/ |
GET | Get & allocate unallocated serial | None | Serial number + status |
/get_device_details/ |
GET | Get device details | Query: ?serialnumber=XXX |
Device details object |
Serial Number Format:
- Pattern:
YYYYMM{AMP|API}XXXXXXB - Example:
202505AMP123456B - YYYY: Year (4 digits)
- MM: Month (2 digits)
- AMP/API: Device type
- XXXXXX: 6-digit sequence
- B: Suffix
Deactivate Endpoint Details:
- Purpose: Remove approved but unallocated devices from active pool
- Eligibility: Only devices with
isapproved=1ANDisallocated=0 - Effect: Sets
isallocated=3(permanent state, cannot be reactivated) - Response Codes:
200- Successfully deactivated403- Denied (device not eligible - either not approved or already allocated)404- Serial number not found400- Other errors
| Endpoint | Method | Description | Query Parameters | Response |
|---|---|---|---|---|
/get_customer_mappings/ |
GET | Retrieve device-customer mappings | See filtering section below | Paginated mapping data |
/create_customer_mapping/ |
POST | Create new mapping | See request body below | Success/error status |
/update_customer_mapping/ |
POST | Update existing mapping | See request body below | Success/error status |
| Parameter | Type | Description | Default |
|---|---|---|---|
serialNumber |
string | Filter by serial number | null |
customerCode |
number | Filter by customer code | 0 |
customerName |
string | Filter by customer name | empty |
company |
string | Filter by company | empty |
deviceType |
string | Filter by device type (AMP/API) | empty |
fromDate |
date | Start date (YYYY-MM-DD) | 2020-01-01 |
toDate |
date | End date (YYYY-MM-DD) | current date |
approvedStatus |
number | Approval status (-1=all, 0=pending, 1=approved, 2=rejected) | -1 |
searchText |
string | Global search across all fields | empty |
pageNumber |
number | Offset (not page index) | 0 |
pageSize |
number | Records per page | 10 |
sortingOrderIndex |
number | Column index to sort (0-10) | 1 |
sortingOrderDirection |
number | Sort direction (0=ASC, 1=DESC) | 0 |
Sorting Column Indices:
- 0: Serial Number
- 1: Customer Code
- 2: Customer Name
- 3: Company
- 4: Device Type
- 5: Approval Status
- 6: Created Date
- 7: Modified Date
# JWT Token Configuration
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'AUTH_HEADER_TYPES': ('Bearer',),
}
# Cookie Settings (Development)
SESSION_COOKIE_SECURE = False # Set True in production (HTTPS)
CSRF_COOKIE_SECURE = False # Set True in production (HTTPS)
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'
# CORS Configuration
CORS_ALLOWED_ORIGINS = env.list('CORS_ALLOWED_ORIGINS')
CORS_ALLOW_CREDENTIALS = TrueProduction Considerations:
- Set
SESSION_COOKIE_SECURE = Truewhen using HTTPS - Set
CSRF_COOKIE_SECURE = Truewhen using HTTPS - Consider
SESSION_COOKIE_SAMESITE = 'Strict'for enhanced security - Restrict CORS_ALLOWED_ORIGINS to your production domains only
- User visits signup page
- Enters username, email, password
- Backend validates and creates user with hashed password
- User logs in with credentials
- Backend generates JWT tokens (access + refresh)
- Tokens stored in HTTP-only cookies
- Frontend stores user data in localStorage for UI purposes
- Protected routes check localStorage for user existence
- API requests automatically include cookies
- Expired access tokens automatically refreshed by interceptor
- Production/Hardware Team adds serial numbers via "Add Serial Number" page
- Serial number validated against pattern:
YYYYMM{AMP|API}XXXXXXB - Device stored in database with
isapproved=0,isallocated=0 - Production Team reviews and approves devices (
isapproved=1) - Device remains in Unallocated (0) state until mapped or deactivated
- Sales/Project Team maps device to customer (sets
isallocated=2) - OR Device can be deactivated if not needed (sets
isallocated=3) - Special handling for UPI PRO devices (auto-approved and allocated)
- Sales/Project Team navigates to "Map Devices" page
- Clicks "Map New Device" button
- Modal opens with form
- Selects from dropdown of approved, unallocated devices (
isapproved=1,isallocated=0) - Device type auto-detected from serial number
- Enters customer details (code, name, company, UID)
- Enters license URL and version details
- Form validates and submits to backend
- Backend creates mapping AND updates device
isallocated=2 - Table refreshes to show new mapping
- Team can edit/update mappings as needed
- Advanced filtering and search available for finding specific mappings
- Production/Admin Team views devices in "Add Serial Number" page
- Identifies device that needs deactivation (faulty, obsolete, etc.)
- Device must be Approved (1) and Unallocated (0) to be eligible
- Clicks "Deactivate" button
- Confirms deactivation in popup
- Backend validates eligibility:
- If
isapproved=1ANDisallocated=0: Proceed - Otherwise: Return 403 Forbidden
- If
- Backend sets
isallocated=3(permanent deactivation) - Deactivated devices no longer appear in customer mapping dropdowns
- Status reflected in table with appropriate styling
Issue: ModuleNotFoundError when running Django
- Solution: Ensure virtual environment is activated and dependencies installed
source venv/bin/activate # or venv\Scripts\activate on Windows
pip install -r requirements.txtIssue: Database connection errors
- Solution: Verify
.envfile has correct database credentials - Check MariaDB service is running
- Test connection:
mysql -u username -p database_name
Issue: CORS errors in browser console
- Solution: Verify
CORS_ALLOWED_ORIGINSin.envincludes frontend URL - Check
django-cors-headersis installed - Ensure middleware order is correct in
settings.py
Issue: Stored procedure errors
- Solution: Ensure all required stored procedures are created in database
- Check stored procedure parameters match view function calls
- Review database logs for SQL errors
- Verify
deactivate_serial_numberprocedure is created
Issue: Deactivate operation denied (403)
- Solution: Verify device is both approved (
isapproved=1) AND unallocated (isallocated=0) - Check device status in database
- Allocated or unapproved devices cannot be deactivated
Issue: Cannot connect to backend
- Solution: Verify
VITE_API_BASE_URLin frontend.envis correct - Check backend server is running on port 8001
- Inspect network tab in browser dev tools for failed requests
Issue: Authentication not working
- Solution: Clear browser cookies and localStorage
- Check cookies are being set (inspect Application tab in Chrome DevTools)
- Verify
withCredentials: truein axios config
Issue: Token refresh loop
- Solution: Check
/token/refresh/endpoint is excluded from interceptor - Verify refresh token cookie hasn't expired (7 days)
- Clear cookies and log in again
Issue: Components not rendering
- Solution: Check browser console for JavaScript errors
- Verify all imports are correct
- Ensure React Router is configured properly
Issue: Filters not working
- Solution: Check if filters are applied by clicking "Apply Filters" button
- Verify date formats are YYYY-MM-DD
- Check console for API errors
This project is licensed under the CC BY-NC 4.0 license.
You may use and modify the project for non-commercial purposes, with proper attribution.
Developed by: Adhwaith