Skip to content

software-community/BudgetMan

Repository files navigation

BudgetMan BOM Costing Generator

BudgetMan is a FastAPI app with a web portal that:

  • accepts a BOM CSV,
  • scrapes each product URL for price,
  • captures screenshots,
  • generates a PDF costing report.

The report now uses a single budget section (Components) instead of multiple grouped sections.

Features

  • CSV BOM upload from browser UI.
  • Club profile selection from static/clubs.json.
  • Scraping with Playwright (Chromium) and multiple fallback extractors.
  • Manual CSV price fallback for blocked or unsupported pages.
  • PDF with cover page, single budget table, and detailed screenshot annex.

Tech Stack

  • Python
  • FastAPI
  • Playwright + playwright-stealth
  • ReportLab

Project Structure

main.py                     FastAPI app entrypoint
routers/bom.py              API endpoint for report generation
services/parser.py          CSV parsing and validation
services/scraper.py         Product page scraping and screenshots
services/pdf_generator.py   PDF report rendering
services/club_profiles.py   Club profile normalization/lookup
static/index.html           Web UI
static/app.js               Frontend logic
static/clubs.json           Club profile data for UI and backend selection

Requirements

  • Python 3.10+
  • Chromium dependencies (installed by Playwright)

Local Setup

python -m venv venv

Windows PowerShell

./venv/Scripts/Activate.ps1

macOS/Linux

source venv/bin/activate

Install dependencies:

pip install -r requirements.txt
python -m playwright install chromium

Run server:

uvicorn main:app --reload --port 8000

Open:

  • http://localhost:8000/ (portal)
  • http://localhost:8000/docs (Swagger UI)

API

POST /generate-costing

Multipart form-data fields:

  • file (required): BOM CSV file.
  • club_profile_id (optional): profile ID from static/clubs.json.
  • project_name (optional): title shown on report cover.

Response:

  • application/pdf file named BOM_Costing_Report.pdf.

Example (curl on macOS/Linux):

curl -X POST http://localhost:8000/generate-costing \
  -F "file=@sample_bom.csv" \
  -F "club_profile_id=aeromodelling" \
  -F "project_name=Bipedal Bot" \
  --output BOM_Costing_Report.pdf

Example (curl.exe on Windows PowerShell):

curl.exe -X POST "http://localhost:8000/generate-costing" `
  -F "file=@sample_bom.csv" `
  -F "club_profile_id=aeromodelling" `
  -F "project_name=Bipedal Bot" `
  --output BOM_Costing_Report.pdf

CSV Format

Required headers:

  • name
  • url
  • quantity

Optional headers:

  • any additional columns are preserved in parsed data,
  • manual price fallback columns: price, unit_price, cost, estimated_price.

Example:

name,url,quantity,unit_price,notes
MQ2 Gas Sensor,https://robu.in/product/mq-2-mq2-smoke-gas-lpg-butane-hydrogen-gas-sensor-detector-module/,1,,Primary gas sensor
Special Sensor,https://example.com/protected-page,3,12.75,Manual price fallback

Notes:

  • quantity defaults to 1 when invalid.
  • rows missing name or url are skipped.
  • category/group fields are not used for report sectioning.

Club Profiles (static/clubs.json)

Frontend and backend both rely on profile IDs, and the backend loads normalized profile fields.

Current JSON shape:

{
  "profiles": [
    {
      "id": "aeromodelling",
      "club_name": "Aeromodelling Club",
      "secretary": {
        "name": "Nalin Angrish",
        "entry_number": "2023MEB1360",
        "phone_number": ""
      },
      "representative": {
        "name": "Kian Sparrow",
        "entry_number": "2024EPB1268",
        "phone_number": ""
      }
    }
  ]
}

Logo files should exist under static/clubs/ and follow /static/clubs/<clubid>.png. The BOST logo is loaded from /static/bost.png on both sides of the cover.

PDF Output

Generated report contains:

  1. Cover page with logos, club title, project name, and officer blocks.
  2. Budget section with a single Components table and grand total.
  3. Detailed list of components with screenshots.

Price Extraction Strategy

For each product URL, scraping tries:

  1. common CSS selectors,
  2. metadata tags,
  3. full-page text regex,
  4. manual CSV fallback price columns.

Limitations and Compliance

  • This project does not bypass bot protection (Cloudflare/challenges).
  • If scraping fails, provide manual price in CSV.
  • Prefer official supplier APIs when available.

Docker

Build:

docker build -t budgetman .

Run:

docker run --rm -p 8000:8000 budgetman

Open http://localhost:8000/.

Render Deployment

  1. Push repository to GitHub.
  2. Create a new Render Web Service from the repo.
  3. Render detects Dockerfile automatically.
  4. Deploy without a custom start command.

The container command already uses PORT:

uvicorn main:app --host 0.0.0.0 --port ${PORT:-8000}

Troubleshooting

  • Only CSV files accepted.: ensure filename ends with .csv.
  • CSV missing required columns: include name,url,quantity headers.
  • Empty report data: verify CSV rows include both name and url.
  • Missing prices: add unit_price or price in CSV for blocked pages.

About

A simple tool to prepare project budget proposals for mechatronics clubs of iit ropar

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors