A full-stack Pharmacy Management System built with Spring Boot, React (Vite), and MySQL. Developed as a Second Year, First Semester Academic Project, MediCare provides a complete solution for modern pharmacy operations — including Role-Based Access Control (RBAC), medicine inventory management, batch expiry tracking, sales processing, delivery tracking, and automated reporting.
┌─────────────────────────────────────────────────────────────┐
│ CLIENT (React SPA) │
│ React 18 + Vite + Tailwind CSS + Axios + React Router │
└──────────────────────┬──────────────────────────────────────┘
│ HTTPS + JWT Bearer Token
▼
┌─────────────────────────────────────────────────────────────┐
│ BACKEND (Spring Boot) │
│ │
│ ┌─────────────────┐ ┌──────────────────────────────┐ │
│ │ Spring Security │──▶│ REST Controllers │ │
│ │ JWT Filter │ │ (Auth, Users, Medicines, │ │
│ └─────────────────┘ │ Sales, Delivery, Reports, │ │
│ │ Expiry, Notifications) │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ┌──────────────▼───────────────┐ │
│ │ Service Layer │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ┌──────────────▼───────────────┐ │
│ │ Spring Data JPA / Hibernate │ │
│ └──────────────┬───────────────┘ │
└───────────────────────────────────────┼─────────────────────┘
│
┌────────────────▼────────────────┐
│ MySQL 8.x Database │
└─────────────────────────────────┘
- User Management — Create, edit, and delete Admin and Customer accounts
- Medicine Management — Add, update, and permanently delete medicines with cascade handling
- Sales Management — View all orders with advanced filtering by status, date, customer, and amount
- Delivery Management — Track and update delivery statuses for all orders
- Expiry Tracking — Monitor medicine batches with automated status classification
- Report Generation — One-click 30-day sales and low-stock inventory reports
- Urgent Alert Center — Real-time banners for critical low stock and expiry warnings
- Browse Medicines — Search, filter by category, and sort the full medicine catalogue
- Shopping Cart — Add medicines, adjust quantities, and checkout
- Order History — View personal order status and history
- Dark Mode — Toggle between light and dark themes
-
Granular Batch Tracking — Track batches by vendor, quantity, purchase value, manufacture date, and expiry date
-
Automated Status Classification:
Status Condition ACTIVEExpiry > 30 days away EXPIRING_SOONExpiry within 30 days NEAR_EXPIRYExpiry within 7 days EXPIREDPast expiry date DISPOSEDManually marked disposed RECALLEDMarked as recalled -
Financial Risk Assessment — Shows total value-at-risk for expired/near-expiry batches
-
Bulk Disposal — Dispose of multiple expired batches in a single action
- 30-Day Sales Summary — Revenue, order count, and top-selling medicines
- Low Stock Report — Instant list of medicines below threshold for timely restocking
- JWT Authentication — Stateless sessions with short-lived JSON Web Tokens
- Role-Based Access Control —
ADMINandCUSTOMERroles with@PreAuthorizeendpoint protection - BCrypt Password Hashing — Industry-standard password encryption
- Environment Variable Secrets — No credentials hardcoded in source code
| Technology | Purpose |
|---|---|
| React 18 | UI framework (SPA) |
| Vite | Build tool & dev server |
| Tailwind CSS + PostCSS | Styling & design system |
| React Router DOM v6 | Client-side routing |
| Axios | HTTP client with JWT interceptors |
| React Toastify | Toast notifications |
| Lucide React | Icon library |
| Context API | Auth, Cart & Theme state management |
| Technology | Purpose |
|---|---|
| Spring Boot 3.x | Application framework |
| Spring Security | Authentication & authorization |
| JWT (JSON Web Tokens) | Stateless auth tokens |
| Spring Data JPA | ORM & database abstraction |
| Hibernate | JPA implementation |
| MySQL 8.x | Relational database |
| Swagger UI / OpenAPI 3 | API documentation |
| Maven | Build & dependency management |
pharmacy-app/
├── backend/
│ ├── src/main/java/com/example/pharmacy/
│ │ ├── config/ # CORS, Web, Security config
│ │ ├── controller/ # REST API endpoints
│ │ │ ├── AuthController.java
│ │ │ ├── UserController.java
│ │ │ ├── MedicineController.java
│ │ │ ├── MedicineExpiryController.java
│ │ │ ├── SaleController.java
│ │ │ ├── DeliveryController.java
│ │ │ ├── ReportController.java
│ │ │ └── ExpiryNotificationController.java
│ │ ├── dto/ # Request/Response DTOs
│ │ ├── entity/ # JPA entity models
│ │ ├── repository/ # Spring Data repositories
│ │ ├── security/ # JWT filter & security config
│ │ ├── service/ # Business logic layer
│ │ ├── strategy/ # Strategy pattern (reports)
│ │ └── util/ # JWT utility class
│ ├── src/main/resources/
│ │ └── application.properties
│ ├── .env.example # Environment variable template
│ └── pom.xml
│
├── frontend/
│ ├── src/
│ │ ├── api/ # Axios instance & interceptors
│ │ ├── components/ # Reusable components
│ │ │ ├── NavBar.jsx
│ │ │ ├── ProtectedRoute.jsx
│ │ │ ├── SimpleExpiryDashboard.jsx
│ │ │ └── SimpleExpiryNotifications.jsx
│ │ ├── context/ # React Context providers
│ │ │ ├── AuthContext.jsx
│ │ │ ├── CartContext.jsx
│ │ │ └── ThemeContext.jsx
│ │ ├── pages/ # Page components
│ │ │ ├── Login.jsx
│ │ │ ├── Register.jsx
│ │ │ ├── Browse.jsx
│ │ │ ├── Cart.jsx
│ │ │ └── SimpleAdminPanel.jsx
│ │ ├── index.css # Global styles & Tailwind
│ │ └── main.jsx # App entry point & routing
│ ├── index.html
│ ├── package.json
│ ├── tailwind.config.js
│ └── vite.config.js
│
├── docker/
│ └── docker-compose.yml # MySQL container setup
└── README.md
- Java Development Kit (JDK) 17+
- Node.js v18+ and npm
- MySQL Server 8.0+ or Docker Desktop
Option A — Docker (Recommended)
cd docker
docker-compose up -dStarts MySQL 8.0 on port
3306. Database:pharmacy, Password:root
Option B — Manual MySQL
CREATE DATABASE phamarcy_db_1;- Navigate to the backend directory:
cd backend- Create your local environment file by copying the example:
copy .env.example .env- Fill in your
.envfile with your actual database credentials:
DB_URL=jdbc:mysql://localhost:3306/phamarcy_db_1
DB_USERNAME=root
DB_PASSWORD=your_password
SERVER_PORT=8082- Run the Spring Boot application:
mvn spring-boot:run- Verify the backend is running:
- Base API:
http://localhost:8082 - Swagger Docs:
http://localhost:8082/swagger-ui/index.html
- Base API:
Note
JPA will auto-create/update tables on first run (ddl-auto=update). Populate the database with sample data using /backend/src/main/resources/sample-data.sql if available.
- Navigate to the frontend directory:
cd frontend- Install dependencies:
npm install- Start the Vite dev server:
npm run dev- Open the app in your browser:
- URL:
http://localhost:5173
- URL:
| Role | Username | Password | Access |
|---|---|---|---|
| ADMIN | admin |
password |
Full system access |
| CUSTOMER | alice |
password |
Browse, cart & orders |
| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/api/auth/login |
PUBLIC | Login, returns JWT token |
POST |
/api/auth/register |
PUBLIC | Register new customer |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/users |
ADMIN | List all users |
POST |
/api/users |
ADMIN | Create new user |
PUT |
/api/users/{id} |
ADMIN | Update user |
DELETE |
/api/users/{id} |
ADMIN | Delete user |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/medicines |
PUBLIC | List medicines (?availableOnly=true) |
POST |
/api/medicines |
ADMIN | Add new medicine |
PUT |
/api/medicines/{id} |
ADMIN | Update medicine |
DELETE |
/api/medicines/{id} |
ADMIN | Delete medicine (hard delete) |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/medicine-expiry |
ADMIN | List all expiry batches |
POST |
/api/medicine-expiry |
ADMIN | Register new batch |
GET |
/api/medicine-expiry/dashboard |
ADMIN | Expiry KPIs & value at risk |
PUT |
/api/medicine-expiry/bulk-status |
ADMIN | Bulk update batch status |
GET |
/api/notifications/summary |
ADMIN | Alert counts by priority |
| Method | Endpoint | Access | Description |
|---|---|---|---|
POST |
/api/sales |
CUSTOMER | Create order/checkout |
GET |
/api/sales |
ADMIN | View all sales & orders |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/deliveries |
ADMIN | List all deliveries |
PUT |
/api/deliveries/{id} |
ADMIN | Update delivery status |
| Method | Endpoint | Access | Description |
|---|---|---|---|
GET |
/api/reports |
ADMIN | Generate 30-day sales & low-stock report |
Developed as a Second Year, First Semester Academic Project at SLIIT.
| Student ID | Contributor | Module |
|---|---|---|
| IT24100878 | Imalki G.N. | Process Sales |
| IT24200343 | Avekshika A.H.E. | Monitor Expiry |
| IT24100765 | Perera S.A.L.N. | Track Delivery |
| IT24100883 | Karanayaka K.K.I.M. | Generate Reports |
| IT24100862 | Kavishka G.D.H. | Manage Users |
| IT24100830 | Supeshala R.D.M. | Manage Stock |
Before deploying to production, ensure the following:
- Set all environment variables (
DB_URL,DB_USERNAME,DB_PASSWORD) on the server - Change the default JWT secret key in
JwtUtil.java - Switch
spring.jpa.hibernate.ddl-autofromupdatetovalidate - Disable SQL logging (
spring.jpa.show-sql=false) - Configure restrictive CORS origins in
WebConfig.java(no wildcards) - Enforce HTTPS / SSL for all traffic
- Resolve customer ID from server-side JWT context, not from client payload
For bug reports or contributions, please open an issue in the repository.