Skip to content

Mahakbajpai/Primora

Repository files navigation

πŸ“¦ Primora β€” Smart Purchase Order & Vendor Management System

A production-quality mini ERP system for managing Vendors, Products, and Purchase Orders. Built with FastAPI + PostgreSQL + SQLAlchemy + Vanilla JS.


πŸš€ Quick Start

Prerequisites

  • Python 3.10+
  • PostgreSQL 14+
  • Git

1. Clone & Setup

git clone <your-repo-url>
cd po-management

# Create virtual environment
python -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

2. Database Setup

# Create the database
createdb po_management

# Load schema + seed data
psql -U postgres -d po_management -f schema.sql

3. Configure Environment

cp .env.example .env
# Edit .env and set your DATABASE_URL

4. Run the Server

uvicorn backend.main:app --reload --host 0.0.0.0 --port 8000

Open your browser at http://localhost:8000


πŸ“ Project Structure

po-management/
β”‚
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ main.py               # FastAPI app entry point
β”‚   β”œβ”€β”€ database.py           # SQLAlchemy engine & session
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   └── models.py         # ORM table definitions
β”‚   β”œβ”€β”€ schemas/
β”‚   β”‚   └── schemas.py        # Pydantic request/response models
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ vendors.py        # GET/POST /api/vendors
β”‚   β”‚   β”œβ”€β”€ products.py       # GET/POST /api/products
β”‚   β”‚   └── purchase_orders.py# GET/POST /api/purchase-orders
β”‚   └── services/
β”‚       β”œβ”€β”€ vendor_service.py # Vendor business logic
β”‚       β”œβ”€β”€ product_service.py# Product business logic
β”‚       └── po_service.py     # PO business logic (tax, stock)
β”‚
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ css/
β”‚   β”‚   └── styles.css        # Dark industrial theme
β”‚   β”œβ”€β”€ js/
β”‚   β”‚   └── api.js            # Shared API client + helpers
β”‚   └── pages/
β”‚       β”œβ”€β”€ index.html        # Login page
β”‚       β”œβ”€β”€ dashboard.html    # PO list + stats
β”‚       β”œβ”€β”€ create_po.html    # Dynamic PO creation form
β”‚       └── receipt.html      # Order confirmation/receipt
β”‚
β”œβ”€β”€ schema.sql                # PostgreSQL DDL + seed data
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ .env.example
└── README.md

πŸ—„οΈ Database Design

Entity Relationship

vendors (1) ─────────── (N) purchase_orders (1) ─────────── (N) purchase_order_items
                                                                         β”‚
products (1) ─────────────────────────────────────────────────────── (N) β”˜

Design Decisions

Decision Reasoning
purchase_order_items.price stores snapshot Product prices change over time. Snapshotting at order creation preserves accurate billing history
total_amount stored (not computed) Avoids recalculating tax on every read; ensures the agreed total is immutable
ON DELETE RESTRICT for vendor FK Prevents accidental deletion of a vendor that has open orders
ON DELETE CASCADE for PO items Deleting a PO removes its line items atomically
Stock validated before any DB write Prevents partial orders; all-or-nothing stock deduction
Random 4-digit suffix in ref no Avoids sequential enumeration of PO IDs via public reference

Tables

vendors β€” Supplier master
id Β· name Β· contact Β· rating (0–5)

products β€” Product catalog
id Β· name Β· sku (UNIQUE) Β· unit_price Β· stock_level Β· description

purchase_orders β€” PO header
id Β· reference_no (UNIQUE) Β· vendor_id (FK) Β· total_amount Β· status Β· created_at

purchase_order_items β€” PO line items
id Β· po_id (FK) Β· product_id (FK) Β· quantity Β· price (snapshot)


πŸ”Œ API Reference

Base URL: http://localhost:8000/api
Interactive docs: http://localhost:8000/api/docs

Vendors

Method Endpoint Description
GET /vendors List all vendors. ?search= for filtering
GET /vendors/{id} Get single vendor
POST /vendors Create vendor

Create Vendor

POST /api/vendors
{
  "name": "Acme Supplies",
  "contact": "sales@acme.com",
  "rating": 4.5
}

Products

Method Endpoint Description
GET /products List all products
GET /products/{id} Get single product
POST /products Create product
POST /products/ai-description Generate AI description

Create Product

POST /api/products
{
  "name": "Industrial Drill Bit",
  "sku": "DRILL-001",
  "unit_price": 2999.00,
  "stock_level": 100
}

AI Description

POST /api/products/ai-description
{
  "product_name": "Industrial Drill Bit",
  "category": "Tools"
}

Purchase Orders

Method Endpoint Description
GET /purchase-orders List all POs (with vendor + items)
GET /purchase-orders/{id} Get single PO
POST /purchase-orders Create new PO

Create PO

POST /api/purchase-orders
{
  "vendor_id": 1,
  "items": [
    { "product_id": 1, "quantity": 5 },
    { "product_id": 3, "quantity": 2 }
  ]
}

Response includes auto-calculated totals:

{
  "id": 1,
  "reference_no": "PO-20240115-7823",
  "total_amount": 16537.50,
  "status": "Pending",
  ...
}

πŸ’‘ Business Logic

Total Calculation

subtotal     = Ξ£ (quantity Γ— unit_price)
tax          = subtotal Γ— 0.05          ← 5% tax
total_amount = subtotal + tax

Stock Validation Flow

For each item in order:
  1. Fetch product from DB
  2. If product.stock_level < requested quantity β†’ return HTTP 400
After all items pass validation:
  3. Create PO record
  4. Create all line items
  5. Deduct stock atomically
  6. Commit transaction

🎨 Frontend Pages

URL Page
/ Login (demo credentials pre-filled)
/dashboard All POs, stats, vendor/product panels
/create-po Dynamic PO form with add/remove rows
/receipt/{id} Order confirmation with printable receipt

✨ Features Implemented

  • Full CRUD for Vendors and Products
  • Purchase Order creation with multiple line items
  • Auto 5% tax calculation stored in total_amount
  • Stock validation and atomic deduction
  • Dynamic add/remove product rows in frontend
  • Real-time order summary panel (subtotal, tax, total)
  • Vendor search (debounced, case-insensitive)
  • AI product description via Anthropic API (with fallback)
  • Receipt page with printable view
  • Dark industrial UI theme
  • 20% discount banner (first-time user UI)
  • Toast notifications for all actions
  • API documentation at /api/docs

πŸ”’ Authentication Note

The system includes a simple session-based demo login. For production:

  1. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env
  2. Install authlib and python-jose[cryptography]
  3. Implement the OAuth2 flow in routes/auth.py

The frontend currently uses sessionStorage to simulate an auth session for demo purposes.


🀝 Submission Checklist

  • GitHub repository with clean commits
  • schema.sql with DDL + seed data
  • README.md with setup instructions
  • API documented at /api/docs (Swagger UI)
  • 2-minute video demo (record using OBS or Loom)

Built with FastAPI, PostgreSQL, SQLAlchemy, Bootstrap (dark theme), and Vanilla JS.

About

Primora - A smart purchase order & vendor management system built using FastAPI, PostgreSQL, SQLAlchemy, and Vanilla JS. Features vendor management, product catalog with AI descriptions, dynamic PO creation with auto 5% tax calculation, real-time stock validation, and a receipt system.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors