Skip to content

siddharth7113/PharmaFlow

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

219 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PharmaFlow - Frontend Overview & Local Setup

What is PharmaFlow?

PharmaFlow is an intelligent pharmacy operations platform built for retail pharmacies. It aims to digitize and streamline day-to-day pharmacy workflows, including:

  • Zero-entry invoice scanning - point the camera at a distributor's bill or upload a PDF; Google Cloud Vision + a format-agnostic parser extract line items into a review-ready draft receipt. Manual entry still available as a first-class fallback.
  • Inventory management - per-product view with batch-level detail, server-side filters for low-stock / near-expiry / out-of-stock, and FEFO allocation on sales.
  • Expiry management - near-expiry batches surface on the dashboard, inventory list, and returns flow.
  • Sales & invoice generation - create customer invoices with line items drawn FEFO from inventory batches; print via a self-contained popup window. Business-profile completeness is enforced before an invoice can be generated (invoices need a legally-compliant header).
  • Past Invoices with an OWNER-only Staff audit column - who rang each sale survives even if the employee is removed from the team.
  • Returns to distributor - select batches, auto-reserve the stock, print a regulation-compliant debit note (with the pharmacy's GSTIN, drug licence, and bank details), and record pickup to post an expense credit.
  • Expense tracking - log manual expenses; return credits surface automatically as negative-amount rows.
  • Analytics (owner-only) - one-page snapshot of revenue, cost-of-goods (from FEFO allocations), gross/net profit, sales trend, top products, payment-mode split, expense breakdown, and an inventory-health tile. Period selector toggles 7/30/90/365-day rolling windows.
  • Settings & Profile - business profile, bank details, distributor list (real API-backed CRUD; renames cascade to history via FK), profile-picture upload, self-service password change.
  • Team management (owner-only /team page) - invite / promote / disable / soft-remove MANAGER + STAFF accounts with server-generated temp passwords returned once in a copy-banner. Re-inviting a removed email reactivates the original row so every audit trail remains consistent.
  • Role-based access control - OWNER / MANAGER / STAFF enforced in two layers: <RoleRoute> wrappers in the frontend routes + @role_required() decorators on every mutating backend endpoint.

Developer docs


Frontend Directory Structure

frontend/
β”œβ”€β”€ index.html              # App shell, loads /src/main.jsx
β”œβ”€β”€ package.json            # Dependencies & scripts (named: pharmaflow-frontend)
β”œβ”€β”€ vite.config.js          # Vite config - dev server on :5173, proxies /api to :5000
β”œβ”€β”€ .gitignore
└── src/
    β”œβ”€β”€ main.jsx            # React entry point - wraps app in BrowserRouter + Toaster
    β”œβ”€β”€ App.jsx             # Root - applies ThemeProvider + AuthProvider
    β”œβ”€β”€ routes/
    β”‚   └── AppRoutes.jsx   # All routes with <RoleRoute allowed=[...]> per-page gating
    β”œβ”€β”€ pages/
    β”‚   β”œβ”€β”€ public/         # LandingPage, AboutUsPage, ContactUsPage
    β”‚   β”œβ”€β”€ auth/           # LoginPage (also handles /signup)
    β”‚   β”œβ”€β”€ dashboard/      # DashboardPage (with setup + temp-password banners)
    β”‚   β”œβ”€β”€ inventory/      # InventoryListPage, InventoryDetailPage
    β”‚   β”œβ”€β”€ sales/          # InvoiceGeneratorPage, PastInvoicesPage (OWNER/MANAGER)
    β”‚   β”œβ”€β”€ receipts/       # DrugReceiptsPage, ScanReceiptPage, ReviewReceiptPage, ManualReceiptPage (OWNER/MANAGER)
    β”‚   β”œβ”€β”€ returns/        # ReturnsManagementPage, ReturnReceiptPage (OWNER/MANAGER)
    β”‚   β”œβ”€β”€ expenses/       # ExpensesPage (OWNER)
    β”‚   β”œβ”€β”€ analytics/      # AnalyticsPage (OWNER)
    β”‚   β”œβ”€β”€ team/           # TeamPage - invite/promote/remove staff (OWNER)
    β”‚   └── settings/       # SettingsPage - profile, password, business, bank, distributors
    β”œβ”€β”€ layouts/            # PublicLayout, DashboardLayout, AuthLayout
    β”œβ”€β”€ context/            # AuthContext, ThemeContext
    β”œβ”€β”€ components/         # Reusable UI components (incl. settings/, expenses/, common/)
    β”œβ”€β”€ services/           # api.js axios client + per-domain services
    β”‚                       #   businessService, distributorService, teamService,
    β”‚                       #   invoiceService, receiptService, returnService,
    β”‚                       #   expenseService, inventoryService, analyticsService,
    β”‚                       #   dashboardService
    β”œβ”€β”€ data/               # Static seed data for dashboard placeholders
    └── styles/
        β”œβ”€β”€ index.css       # Global styles + .sr-only utility
        └── variables.css   # CSS custom properties (light + dark themes)

Key Architectural Details

Concern Detail
Framework React 18 with JSX
Build Tool Vite 5
Routing React Router DOM v6
API Calls Axios (proxied via Vite to backend at http://localhost:5000)
Animations Framer Motion
Charts Recharts
Notifications react-hot-toast
Icons Lucide React
Fuzzy Search Fuse.js
File Upload react-dropzone
Date Utils date-fns
Path Alias @ maps to ./src

Auth & Route Guards

  • ProtectedRoute - redirects unauthenticated users to /login.
  • RoleRoute allowed={[…]} - centralised role gate used by every role-scoped page in AppRoutes.jsx (e.g. <RoleRoute allowed={['OWNER','MANAGER']}>). See the full matrix in backend/docs/settings-architecture.md.
  • Auth state is managed globally via AuthContext; updateUser() is defensive about partial updates so a stray role: null can't silently demote a user.

Running the Frontend Locally

Prerequisites

  • Node.js β‰₯ 18 (recommended)
  • npm

Steps

# 1. Clone the repository and switch to the correct branch
git clone https://github.com/siddharth7113/SE_project.git
cd SE_project

# 2. Navigate into the frontend directory
cd frontend

# 3. Copy the environment file and fill in your Google Client ID
cp .env.example .env
# Then open .env and set: VITE_GOOGLE_CLIENT_ID=your-google-client-id.apps.googleusercontent.com

# 4. Install dependencies
npm install

# 5. Start the development server
npm run dev

The app will be available at http://localhost:5173.


Available Scripts

Command Description
npm run dev Start Vite dev server on port 5173
npm run build Build for production (outputs to dist/)
npm run preview Preview the production build locally
npm run lint Run ESLint across all .js and .jsx files

API Documentation

The full REST API specification is defined in OpenAPI 3.0 (Swagger) format:

πŸ“„ backend/docs/api-spec.yaml

You can preview it by pasting the contents into Swagger Editor, or install the VS Code OpenAPI extension for inline preview.


Backend - Flask + PostgreSQL

The backend lives in backend/ and uses Flask, SQLAlchemy ORM, and PostgreSQL 16.

Backend Prerequisites

  • Python β‰₯ 3.11
  • uv (Python package manager) - install with curl -LsSf https://astral.sh/uv/install.sh | sh
  • Docker & Docker Compose (for PostgreSQL)

Backend Setup for Windows

# 1. Start PostgreSQL (creates both dev and test databases automatically)
cd backend
.\check-docker.ps1
docker compose up -d

# 2. Configure Environment Variables
# Copy the example env file. You MUST configure JWT_SECRET_KEY and GOOGLE_CLIENT_ID 
# for full authentication functionality.
copy .env.example .env
notepad .env  # Or use your preferred editor like VS Code: code .env

# 3. Create virtual environment & install dependencies
python -m venv .venv
.\.venv\Scripts\activate
.\.venv\Scripts\python.exe -m pip install -r requirements.txt

# 4. Run database migrations
$env:FLASK_APP="manage.py"
.\.venv\Scripts\python.exe -m flask db upgrade

# 5. Seed the database with sample data
.\.venv\Scripts\python.exe seed.py

# 6. Start the development server
.\.venv\Scripts\python.exe run.py

Backend Setup for Linux

# 1. Start PostgreSQL (creates both dev and test databases automatically)
cd backend
docker compose up -d

# 2. Configure Environment Variables
# Copy the example env file. You MUST configure JWT_SECRET_KEY and GOOGLE_CLIENT_ID 
# for full authentication functionality.
cp .env.example .env
nano .env

# 3. Create virtual environment & install dependencies
uv venv .venv
source .venv/bin/activate
uv pip install -r requirements.txt

# 4. Run database migrations
FLASK_APP=manage.py flask db upgrade

# 5. Seed the database with sample data
python seed.py

# 6. Start the development server
python run.py

The backend server will be available at http://localhost:5000.

Running Tests for Linux

cd backend
source .venv/bin/activate
python -m pytest tests/ -v

Running Tests for Windows

cd backend
.\.venv\Scripts\python.exe -m pytest tests -v

All 250 tests should pass (including 39 auth tests, 14 distributors tests, 16 team tests, 15 business-profile tests, and 21 invoice tests). Tests run against a separate pharmaflow_test database. Each test truncates all tables at teardown to ensure isolation, so committed mutations in route handlers are fine.

Demo accounts

After running seed.py you can log in as any of three users on the same pharmacy to walk the role matrix:

Email Role Password Sees
vipul@vipulmedical.com OWNER password123 Everything (expenses, analytics, team, settings).
dharansh@email.com MANAGER password123 Add Inventory, Returns, Past Invoices, generate invoices.
ramesh@email.com STAFF password123 Dashboard, Inventory browse, Generate Invoice, Settings.

The seeded business already has a complete profile + bank account so invoices and debit notes can be printed out of the box. Log in as an OWNER first and watch for the Management sidebar section; it narrows as you switch to MANAGER and disappears entirely for STAFF.

Setting up Google OAuth

To use Google Sign-In on the frontend:

  1. Go to the Google Cloud Console
  2. Create a new project (or use an existing one)
  3. Navigate to APIs & Services > Credentials
  4. Create an OAuth 2.0 Client ID (Application type: Web application)
  5. Add http://localhost:5173 to Authorized JavaScript origins
  6. Copy the Client ID and add it to both .env files:
    • backend/.env as GOOGLE_CLIENT_ID
    • frontend/.env as VITE_GOOGLE_CLIENT_ID

Backend Directory Structure

backend/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ __init__.py            # Flask application factory + /api/uploads static route
β”‚   β”œβ”€β”€ extensions.py          # SQLAlchemy & Migrate instances
β”‚   β”œβ”€β”€ utils.py               # Shared parse/coerce helpers (date, expiry, int, float)
β”‚   β”œβ”€β”€ auth/                  # register/login/me/change-password/google + profile picture
β”‚   β”œβ”€β”€ business/              # /api/business profile + bank + completeness gate
β”‚   β”œβ”€β”€ distributors/          # /api/distributors CRUD (settings-editor backing)
β”‚   β”œβ”€β”€ team/                  # /api/team OWNER-only member CRUD + reactivation
β”‚   β”œβ”€β”€ invoices/              # /api/invoices (412 completeness gate, createdBy audit)
β”‚   β”œβ”€β”€ inventory/             # /api/inventory server-side filters
β”‚   β”œβ”€β”€ receipts/              # /api/receipts (OCR + manual + approve)
β”‚   β”œβ”€β”€ returns/               # /api/returns (debit notes)
β”‚   β”œβ”€β”€ expense/               # /api/expenses + categories
β”‚   β”œβ”€β”€ services/              # ocr_service (Google Cloud Vision integration)
β”‚   └── models/
β”‚       β”œβ”€β”€ __init__.py        # Re-exports all model classes
β”‚       β”œβ”€β”€ user.py            # User, UserPasswordAuth, UserOAuthAccount
β”‚       β”œβ”€β”€ business.py        # Business, BusinessMembership, BusinessBankAccount
β”‚       β”œβ”€β”€ distributor.py     # Distributor
β”‚       β”œβ”€β”€ customer.py        # Customer
β”‚       β”œβ”€β”€ product.py         # Product
β”‚       β”œβ”€β”€ inventory.py       # InventoryBatch, InventoryMovement
β”‚       β”œβ”€β”€ purchase.py        # PurchaseReceipt, PurchaseReceiptItem, ReceiptScan
β”‚       β”œβ”€β”€ sales.py           # SalesInvoice, SalesInvoiceItem, BatchAllocation
β”‚       β”œβ”€β”€ expense.py         # ExpenseCategory, Expense
β”‚       β”œβ”€β”€ returns.py         # ReturnRequest, ReturnRequestItem
β”‚       β”œβ”€β”€ audit.py           # AuditLog
β”‚       └── contact.py         # ContactMessage
β”œβ”€β”€ migrations/                # Alembic migration versions
β”œβ”€β”€ tests/                     # 250 tests (pytest) - see "Running Tests" below
β”‚   β”œβ”€β”€ conftest.py            # Fixtures (seed_user returns OWNER with complete business)
β”‚   β”œβ”€β”€ test_auth.py           # 39 tests incl. profile picture, must-change-password
β”‚   β”œβ”€β”€ test_business.py       # 15 tests incl. completeness gate
β”‚   β”œβ”€β”€ test_distributors.py   # 14 tests incl. rename-cascade + live-batch guard
β”‚   β”œβ”€β”€ test_team.py           # 16 tests incl. soft-remove reactivation + last-owner guards
β”‚   β”œβ”€β”€ test_invoices_inventory.py  # 21 tests incl. 412 gate + creator audit
β”‚   β”œβ”€β”€ test_receipts_inventory.py  # 36 tests
β”‚   β”œβ”€β”€ test_returns.py        # 30 tests
β”‚   β”œβ”€β”€ test_expenses.py       # 9 tests
β”‚   β”œβ”€β”€ test_ocr.py            # 22 tests (parser)
β”‚   β”œβ”€β”€ test_models.py         # 42 model tests
β”‚   └── test_seed.py           # 6 tests
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ api-spec.yaml              # OpenAPI 3 - 44 paths, 56 schemas
β”‚   β”œβ”€β”€ settings-architecture.md   # RBAC + team + distributors + profile picture (NEW)
β”‚   β”œβ”€β”€ auth-architecture.md       # Auth primitives (JWT, decorators, password rotation)
β”‚   β”œβ”€β”€ invoices-architecture.md   # FEFO allocation + completeness gate
β”‚   └── inventory-architecture.md  # Stock / receipts / returns / OCR
β”œβ”€β”€ uploads/                   # UPLOAD_DIR default - profiles/ + receipts/
β”œβ”€β”€ config.py                  # Dev / Testing / Production configs
β”œβ”€β”€ manage.py                  # Flask CLI entry point
β”œβ”€β”€ seed.py                    # Sample data seeder (idempotent)
β”œβ”€β”€ docker-compose.yml         # PostgreSQL 16 container
β”œβ”€β”€ requirements.txt           # Python dependencies
β”œβ”€β”€ .env                       # Local environment variables
└── .env.example               # Template for .env

Database Entity-Relationship Diagram (ERD)

The core architecture assumes a multi-tenant Business model where everything is scoped to a pharmacy. The diagram below illustrates the relationships between key entities:

erDiagram
    users ||--o{ business_memberships : "has"
    businesses ||--o{ business_memberships : "has"
    businesses ||--o{ products : "manages"
    businesses ||--o{ distributors : "partners with"
    businesses ||--o{ customers : "serves"
    businesses ||--o{ expenses : "incurs"
    businesses ||--o{ expense_categories : "defines"
    businesses ||--o{ sales_invoices : "issues"
    businesses ||--o{ purchase_receipts : "receives"
    businesses ||--o{ inventory_batches : "holds"
    businesses ||--o{ return_requests : "creates"
    businesses ||--o{ audit_logs : "tracks"

    distributors ||--o{ purchase_receipts : "supplies"
    distributors ||--o{ return_requests : "receives"
    distributors ||--o{ inventory_batches : "original source"

    customers ||--o{ sales_invoices : "pays"

    expense_categories ||--o{ expenses : "categorizes"

    purchase_receipts ||--o{ purchase_receipt_items : "contains"
    purchase_receipts ||--o| receipt_scans : "generated from"
    
    products ||--o{ purchase_receipt_items : "bought as"
    products ||--o{ sales_invoice_items : "sold as"
    products ||--o{ inventory_batches : "stocked as"
    products ||--o{ return_request_items : "returned as"

    purchase_receipt_items ||--o| inventory_batches : "creates"
    
    inventory_batches ||--o{ inventory_movements : "tracks history"
    inventory_batches ||--o{ sales_invoice_item_batch_allocations : "allocated to"
    
    sales_invoices ||--o{ sales_invoice_items : "contains"
    sales_invoice_items ||--o{ sales_invoice_item_batch_allocations : "fulfilled by"
    
    return_requests ||--o{ return_request_items : "contains"
    
    users ||--o{ audit_logs : "performs actions"
Loading

Backend Commands Reference

Command Description
docker compose up -d Start PostgreSQL container
docker compose down Stop PostgreSQL container
FLASK_APP=manage.py flask db migrate -m "msg" Generate a new migration
FLASK_APP=manage.py flask db upgrade Apply pending migrations
python seed.py Seed the database with sample data
python -m pytest tests/ -v Run all tests with verbose output
python -m pytest tests/ -v --cov=app Run tests with coverage report

About

IIT Madras Project for Software Engineering.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors