Open-source Pharmacy Management System
POS · Inventory · Purchases · Returns · Reports · RBAC
ArogyaPMS is a modern, full-stack pharmacy management system built with React (Vite) + FastAPI + PostgreSQL. It handles the complete daily workflow of a pharmacy — Point of Sale billing, batch-aware inventory, purchases, suppliers, returns, patient records, reports, and fine-grained role-based access control.
- Features
- Screenshots
- Tech Stack
- Architecture
- Quick Start — Docker
- Manual Setup — Linux / macOS
- Manual Setup — Windows
- Configuration
- Default Credentials
- Project Structure
- Commands
- Troubleshooting
- Documentation
- License
| Module | Highlights |
|---|---|
| Dashboard | Real-time sales, today's bills, monthly summaries, inventory value, low-stock alerts (admin & staff views) |
| Point of Sale | Split-screen cart, batch-aware product search, expiry-sorted batches, draft carts, one-click checkout |
| Bills & Receipts | Order-based billing, browser print + PDF export, bill history with date/term filters |
| Returns | Full or partial returns against closed bills, per-item quantity validation, automatic stock restoration |
| Inventory | Batch-level tracking (name, batch, expiry, GST, price, rack), expiry/risk/out-of-stock/discarded views, day-by-day tracing |
| Purchases | Single & bulk entry, auto stock-increment, edit/delete with stock reversal |
| Suppliers & Categories | Full CRUD for suppliers and product categories |
| Doctors & Patients | Doctor directory with revenue stats; patient records (IPD/UHID) with full bill history |
| Reports | Date-filtered sales/returns/products/purchases reports, daily sign-off closure report |
| Access Control | Fine-grained RBAC — roles, permissions, exact-match checks on API + UI |
| Users & Profiles | User management, avatar uploads, profile editing, password change |
| Settings | Configurable app name, currency symbol, expiry-risk window |
| Audit Logs | Rotating log with searchable/downloadable entries |
| Backup & Restore | Super-admin pg_dump download and SQL restore endpoints |
| Dark Mode | Full light/dark theme |
Add your own screenshots to the
screenshots/directory and they will appear here.
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite 8, Tailwind CSS v4, React Router, Axios, Lucide Icons, Recharts, Fuse.js, jsPDF |
| Backend | Python 3.11+, FastAPI, SQLAlchemy 2.0 ORM, Pydantic v2, JWT (python-jose), Passlib/Bcrypt |
| Database | PostgreSQL 15 |
| Infrastructure | Docker Compose, Nginx (frontend), Uvicorn (backend) |
┌──────────────────────┐ HTTP / JSON ┌──────────────────────────┐
│ React SPA (Vite) │ ─────────────────────► │ FastAPI Backend │
│ /api → proxy │ ◄───────────────────── │ /api/* routers │
│ backend (8000) │ JWT Bearer token │ JWT middleware │
└──────────────────────┘ └───────────┬──────────────┘
│ SQLAlchemy ORM
┌───────▼────────┐
│ PostgreSQL 15 │
└────────────────┘
- Frontend (
frontend/) — Vite dev server proxies/apiand/uploadsto the backend. Production builds are served by Nginx. - Backend (
backend/) — FastAPI with routers underrouters/, ORM models undermodels/, Pydantic schemas underschemas/. - Auth — JWT access tokens (
HS256). Protected endpoints resolve the user viaget_current_user; permission-gated endpoints userequire_permission(...). - RBAC — Users ↔ Roles ↔ Permissions (many-to-many).
Super-adminbypasses all checks; all other roles are matched against exact permission slugs.
See documentation.md for the full architecture, data model, route map, and permission reference.
The fastest way to get everything running:
# Clone
git clone https://github.com/your-org/ArogyaPMS.git
cd ArogyaPMS
# Configure
cp backend/.env.example backend/.env
# Build and start (PostgreSQL + backend + frontend)
docker compose up --build -d
# Seed the database (first run only)
docker exec -it pms_backend python -m app.seed
# Open
# App → http://localhost:8080
# API → http://localhost:8000/docsStop / reset:
docker compose down # stop services
docker compose down -v # stop + wipe DB volumes# Option A — use Docker for Postgres only
docker compose up db -d
# Option B — use an existing PostgreSQL instance
createdb pms_dbcd backend
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
# Edit .env → set DATABASE_URL and SECRET_KEY
# e.g. DATABASE_URL=postgresql+psycopg://postgres:postgres@localhost:5433/pms_db
python -m app.seed
uvicorn app.main:app --reload --port 8000cd frontend
npm install
npm run devOpen http://localhost:5173.
One-command dev start (requires venv at backend/venv):
make runInstall PostgreSQL from postgresql.org, then:
psql -U postgres -c "CREATE DATABASE pms_db;"cd backend
py -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
copy .env.example .env
# Edit .env → set DATABASE_URL (default port 5432 on Windows)
# DATABASE_URL=postgresql+psycopg://postgres:postgres@localhost:5432/pms_db
python -m app.seed
uvicorn app.main:app --reload --port 8000cd frontend
npm install
npm run devOpen http://localhost:5173.
Note: Use
venv\Scripts\activate, notsource. Start backend and frontend in separate terminals. Ifpsqlis not on PATH, use the "SQL Shell (psql)" shortcut from the Start menu.
All backend settings live in backend/.env (copy from .env.example) and are loaded via Pydantic (backend/app/config.py).
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
— | SQLAlchemy connection string, e.g. postgresql+psycopg://postgres:postgres@localhost:5433/pms_db |
SECRET_KEY |
— | JWT signing secret — change in production |
ALGORITHM |
HS256 |
JWT signing algorithm |
ACCESS_TOKEN_EXPIRE_MINUTES |
1440 |
Token lifetime (24 h) |
APP_NAME |
ArogyaPMS |
Display name used by the API and settings seed |
APP_CURRENCY |
₹ |
Currency symbol shown across the UI |
UPLOAD_DIR |
uploads |
Directory for avatar/file uploads |
In Docker,
docker-compose.ymlsetsDATABASE_URLpointing at thedbservice. The.envenv_fileis also loaded butenvironmentvalues take precedence.
| Role | Password | |
|---|---|---|
| Super Admin | admin@admin.com |
password |
| Billing Staff | sales@sales.com |
password |
Change these immediately in production.
ArogyaPMS/
├── backend/
│ ├── app/
│ │ ├── main.py # FastAPI entrypoint, router registration, startup DDL
│ │ ├── config.py # Pydantic settings
│ │ ├── database.py # Engine, session factory, Base
│ │ ├── seed.py # Permissions, roles, admin user, defaults
│ │ ├── models/ # SQLAlchemy ORM models
│ │ ├── schemas/ # Pydantic request/response schemas
│ │ ├── middleware/auth.py # JWT auth + permission dependency
│ │ ├── routers/ # API route modules (one per domain)
│ │ └── utils/ # security, file upload, audit logger
│ ├── requirements.txt
│ ├── Dockerfile
│ └── .env.example
├── frontend/
│ ├── src/
│ │ ├── api/axios.js # Axios instance + JWT interceptor
│ │ ├── context/AuthContext.jsx
│ │ ├── components/ # Sidebar, Header, Modal, DataTable
│ │ ├── layouts/ # DashboardLayout
│ │ ├── pages/ # One folder per domain
│ │ ├── constants/ # permissionGuide.js
│ │ ├── App.jsx # Route definitions + guards
│ │ └── index.css # Tailwind v4 theme
│ ├── public/ # Logo.svg, favicon.svg
│ ├── Dockerfile
│ ├── nginx.conf
│ └── package.json
├── docker-compose.yml
├── Makefile
├── documentation.md # Full architecture, API & permission reference
└── README.md
# ── Backend (from backend/, venv active) ──
python -m app.seed # seed / refresh roles, permissions, admin
uvicorn app.main:app --reload # dev server
# ── Frontend (from frontend/) ──
npm install # install deps
npm run dev # Vite dev server
npm run lint # ESLint
npm run build # production build → dist/
# ── Docker ──
docker compose up --build -d # start all services
docker compose down # stop
docker compose down -v # stop + delete volumes (full DB reset)
docker compose logs -f backend # tail backend logs| Problem | Fix |
|---|---|
ModuleNotFoundError: fastapi |
Activate the venv and run pip install -r requirements.txt. |
| Backend can't connect to DB | Check DATABASE_URL in backend/.env; confirm Postgres is running (docker compose up db -d). |
| Login returns 401 | Run docker exec -it pms_backend python -m app.seed (or re-seed locally). Verify you're using the correct password. |
| Login redirects back to login | Token expired or SECRET_KEY changed. Clear browser localStorage and log in again. |
| Frontend API calls return 404 | Confirm backend is on port 8000 (dev proxy) or Nginx proxies /api → backend:8000 (Docker). |
| Ports already in use | Change ports in docker-compose.yml or uvicorn --port. |
For a complete reference — every feature, API route, data model table, and permission — see documentation.md.
This project is licensed under the MIT License.
