A full-stack pharmacy management web application built for both Wholesale and Retail pharmacies β featuring billing, inventory, credit management, expiry tracking, sales analytics, and more.
| Technology | Version | Purpose |
|---|---|---|
| React | 18.3 | UI framework |
| Vite | 5.4 | Build tool & dev server |
| React Router v6 | 6.26 | Client-side routing |
| TanStack React Query | 5.56 | Server state, caching (30s stale time) |
| Zustand | 5.0 | Client state (auth, settings) |
| Axios | 1.7 | HTTP client with JWT interceptor |
| Recharts | 3.8 | Charts β bar, line, pie |
| Technology | Version | Purpose |
|---|---|---|
| Python / Flask | 3.x | REST API server |
| Flask-JWT-Extended | β | JWT authentication & partition identity |
| Flask-CORS | β | Cross-origin requests |
| psycopg2 | β | PostgreSQL driver with connection pooling |
| Werkzeug | β | Password hashing (bcrypt) |
| Resend API | β | Transactional email (credit bills, OTP) |
| SMTP fallback | β | Email fallback if Resend unavailable |
| Service | Purpose |
|---|---|
| PostgreSQL (Supabase) | Primary database β Transaction Pooler port 6543 |
| Render Web Service | Flask backend hosting |
| Render Static Site | React frontend hosting |
| GitHub | Source control & auto-deploy trigger |
- JWT-based login & registration
- Drug License No. as primary identifier
- OTP-based password reset via email
- OTP-based email change verification
- Welcome email on registration
- Auto-logout on token expiry (401 intercept)
The entire app is partition-aware β every feature, endpoint, and UI adapts to the active pharmacy type:
- Wholesale Pharma β Box/Strip pricing, retailer billing, GSTIN fields, supplier-side credit
- Retail Pharmacy / Hospital / Medical Store / Ayurvedic Store β Strip/Piece pricing, customer billing, doctor fields, patient-side credit
- Today's revenue & bill count
- Total medicines & low stock alerts
- Expiry alerts (expired + upcoming)
- Revenue trend β last 7 days (bar chart)
- Weekly profit analysis β current month (4 weeks)
- Top selling medicines (horizontal bar chart)
- Expiring soon panel
- Recent bills list
- Per-pharmacy-type dashboard reset (hide old data without deleting)
- Add / Edit / Delete medicines
- Fields: Name, Brand, Category, SKU/Batch, Form (Tablet/Syrup/etc.), Unit, MRP, Selling Price, Purchase Price, GST%, Stock, Min Stock, Pieces/Strip, Strips/Box, Expiry Month
- Low stock threshold alerts
- Real-time stock deduction on billing
- Category-based filtering
Wholesale billing:
- Shop / Retailer name, Shopkeeper GSTIN, phone
- Box / Strip quantity types with automatic pack-size price calculation
- Bill No. format:
GSTIN-XXXX - Columns: Medicine, Form, Qty, MRP, Selling Price, Disc%, GST, Amt Before Tax, Total
- Bill preview modal with QR code (UPI payment)
Retail billing:
- Customer name, phone, doctor name
- Strip / Piece quantity types
- Bill No. format:
#XXXX - Columns: Medicine, Form, Qty, MRP, Disc%, GST, Amount
- TAX INVOICE layout with green header
Both types:
- Live GST + discount calculation
- Round-off to nearest rupee
- Print-ready PDF preview
- Low stock toast alert after bill generation
- Print Last Bill button
- All bills with search & date filter
- Bill detail expand / print
- Export as CSV
- Filter by payment mode
- Track every stock entry with supplier, quantity, purchase price, batch, expiry
- Per-pharmacy-type filtering
- Linked to Purchase Records
- Supplier order tracking
- Delivery status management
- Linked to stock-in entries
Wholesale Credit:
- Multi-item credit bills for retailers
- GST / discount toggles per item
- Email credit bill to shopkeeper via Resend API
- PDF print of credit bill
- Bulk delete
Retail Credit (Shop Credits):
- Track supplier / wholesaler payments
- Cumulative pending balance calculation
- Supplier History Modal β full payment timeline
MAX(ctid)tiebreaker for accurate latest-record queries
- Revenue by period (7 / 30 / 90 / 365 days)
- Category-wise revenue breakdown with progress bars
- Top selling medicines ranking
- GST collected summary
- Profit margin analysis
- Line chart & bar chart views
- Medicines grouped by: Expired / Within 30 / 60 / 90 days / Safe
- Color-coded badges (red / amber / green)
- Stat cards with counts per group
- Filter buttons to switch views instantly
- Add / Edit / Delete medicine categories
- Medicine count per category
- Revenue contribution per category (from analysis data)
- Revenue progress bars
- Store name, type, address, phone, email
- GSTIN, Drug License No.
- Owner name, Supplier name
- UPI QR code upload (separate for Wholesale & Retail)
- Currency symbol
- Low stock threshold
- Pharmacy type lock (prevents accidental type change)
- OTP-based email update
- Excel import for medicines bulk upload
- Sales history import
- Credits import
- Full backup export (JSON)
Pharma-Pro-Project/
β
βββ app.py # Flask backend β 61 API routes, 4800+ lines
βββ requirements.txt # Python dependencies
βββ Procfile # Render start command
βββ runtime.txt # Python version
β
βββ frontend/ # React + Vite SPA
βββ public/
β βββ favicon.ico
β βββ logo.jpeg
β βββ site.webmanifest
βββ src/
β βββ api/
β β βββ client.js # Axios instance with JWT interceptor
β βββ store/
β β βββ authStore.js # Zustand β token, user
β β βββ settingsStore.js # Zustand β pharmacy settings, type
β βββ components/
β β βββ Layout.jsx # Sidebar, topbar, bottom nav
β βββ pages/
β β βββ AuthPage.jsx
β β βββ DashboardPage.jsx
β β βββ ProductsPage.jsx
β β βββ BillingPage.jsx
β β βββ HistoryPage.jsx
β β βββ StockInPage.jsx
β β βββ CreditPage.jsx
β β βββ AnalysisPage.jsx
β β βββ ExpiryPage.jsx
β β βββ CategoriesPage.jsx
β β βββ PurchasePage.jsx
β β βββ SettingsPage.jsx
β βββ App.jsx # Routes + protected route wrapper
β βββ main.jsx # React Query + BrowserRouter setup
β βββ styles.css # Global CSS with responsive utilities
βββ index.html
βββ vite.config.js
βββ package.json
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register |
Register new pharmacy |
| POST | /api/auth/login |
Login, returns JWT |
| GET | /api/auth/me |
Get current user |
| GET/PUT | /api/settings |
Get / update pharmacy settings |
| GET/POST | /api/products |
List / add medicines |
| PUT/DELETE | /api/products/:id |
Edit / delete medicine |
| GET/POST | /api/categories |
List / add categories |
| GET/POST | /api/bills |
List / create bills |
| GET | /api/bills/next-number |
Next formatted bill number |
| GET/POST | /api/stock-ins |
Stock entry records |
| GET/POST | /api/credits |
Wholesale credit records |
| GET/POST | /api/shop-credits |
Retail supplier credits |
| GET | /api/dashboard |
Full dashboard aggregation |
| GET | /api/analysis |
Sales analytics (7/30/90/365 days) |
| GET | /api/expiry |
Medicines by expiry category |
| GET/POST | /api/purchase-records |
Supplier purchase orders |
| POST | /api/auth/forgot-password/send-otp |
Password reset OTP |
| GET | /api/export/backup |
Full data backup (JSON) |
| POST | /api/import/medicines |
Bulk medicine import (Excel) |
# Install dependencies
pip install -r requirements.txt
# Set environment variables
export DATABASE_URL="postgresql://..."
export JWT_SECRET_KEY="your-secret"
export RESEND_API_KEY="re_..."
# Run Flask
python app.pycd frontend
# Install dependencies
npm install
# Run dev server (proxies /api to localhost:5000)
npm run dev
# Build for production
npm run build| Service | Type | Config |
|---|---|---|
Pharma-Pro-Project |
Web Service (Flask) | Root dir: /, Build: pip install -r requirements.txt, Start: gunicorn app:app |
Pharma-Pro-Project-1 |
Static Site (React) | Root dir: frontend, Build: npm install && npm run build, Publish: dist |
Environment variables on Static Site:
VITE_API_URL = https://pharma-pro-project.onrender.com/api
(Wholesaler Pharma) : GSTIN : 27ABCEF1234F1Z0
(Retail Pharma) : GSTIN : 27ABCEF1234F2Z4
(MAIL ME FOR PASSWORD)
Not licensed for commercial use.