Production planner for vendor allocation across programs and quarters.
Find a file
Taylor Blackburn 38733af3d8
All checks were successful
build-and-deploy / build (push) Successful in 50s
build-and-deploy / deploy-dev (push) Successful in 24s
ci: serialize same-branch runs to stop spurious cancellations
Forgejo Actions auto-cancels older in-progress runs that share a
workflow + ref when a new push lands. Back-to-back pushes to master
will end up with the older run's deploy + close-tasks jobs marked
"Has been cancelled" and silently dropping TASK closures. Add an
explicit per-ref concurrency group with cancel-in-progress=false so
back-to-back pushes queue instead of preempting each other.

Mirrors the fix shipped in notes-app for BUG-095 / TASK-273.
2026-05-11 22:25:33 -07:00
.forgejo/workflows ci: serialize same-branch runs to stop spurious cancellations 2026-05-11 22:25:33 -07:00
analytics Add Dockerfile + Forgejo deploy pipeline (dev only) 2026-05-11 19:20:31 -07:00
api Replace Perspective with Graphic Walker analytics app 2026-04-11 16:36:33 -07:00
archive Sticky section headers, collapsible groups, expanded seed data 2026-04-10 23:54:36 -07:00
data Add README, clean up stale DB files, update gitignore 2026-04-11 03:03:19 -07:00
migrations Extended analytics views: quantities, load, utilization 2026-04-11 16:41:55 -07:00
.dockerignore Add Dockerfile + Forgejo deploy pipeline (dev only) 2026-05-11 19:20:31 -07:00
.gitignore Replace Perspective with Graphic Walker analytics app 2026-04-11 16:36:33 -07:00
app.html Cumulative mode for scenario results table 2026-04-11 17:12:18 -07:00
Dockerfile Add Dockerfile + Forgejo deploy pipeline (dev only) 2026-05-11 19:20:31 -07:00
main.py Initial build: MPS page with forecast tracking, programs, facilities 2026-04-10 23:48:04 -07:00
pyproject.toml Initial build: MPS page with forecast tracking, programs, facilities 2026-04-10 23:48:04 -07:00
README.md Replace Perspective with Graphic Walker analytics app 2026-04-11 16:36:33 -07:00

Production Planner

Vendor allocation planning tool for global supply management. Built for managing assembly across multiple vendors and programs.

Quick Start

uv sync
uv run python main.py
# Open http://localhost:8001

First run auto-seeds with demo data (9 programs, 10 vendors, 5 forecast revisions).

Architecture

The app has two parts:

  • Main app (app.html) vanilla JS, no build step, served directly by FastAPI
  • Analytics (analytics/) Vite + React app with Graphic Walker (Tableau-like data exploration)

Both share the same FastAPI backend and SQLite database.

Backend

  • FastAPI + SQLite (WAL mode), single-file API at api/app.py
  • DB: data/gsm_tools.db (auto-created, gitignored)
  • Migrations: migrations/*.sql, applied in order on startup
  • Pre-built SQL views (v_demand, v_vendor_capacity, etc.) for analytics

Main App

  • Single app.html, vanilla JS, no dependencies, no build step
  • Sections: Current Forecast, Scenarios, Programs, Vendors, Forecast History, Revision Log, Debug

Analytics App

  • Vite + React app at analytics/
  • Embeds Graphic Walker drag-and-drop visual analytics like Tableau
  • Loads data from any table or SQL view via the /api/sql endpoint
  • Built output goes to static/analytics/, served by FastAPI at /analytics

Building the analytics app

cd analytics
npm install        # first time only
npm run build      # outputs to ../static/analytics/

For development with hot reload:

cd analytics
npm run dev        # runs on :5173, proxies /api to :8001
# (start the backend separately: uv run python main.py)

You only need to rebuild when you change the analytics app. The main app (app.html) requires no build step.

Data Model

Programs

  • Code (e.g. D93, D101) primary identifier, matches imported CSV files
  • Optional nickname for display (e.g. "iPhone 16 Pro")
  • group_name for visual grouping (e.g. D9x, D10x)
  • default_throughput (units/day/line) baseline for all vendors

Vendors

  • Code (e.g. FXN-ZZ, IPG-CH) primary identifier
  • Optional nickname for display (e.g. "Foxconn Zhengzhou")
  • group_name for visual grouping (e.g. FXN, IPG)
  • capacity total line capacity at the facility

Vendor-Program Associations

  • lines production lines allocated to this program at this vendor
  • throughput optional override of the program's default (0 = use default)

Scenarios

  • Named allocation strategies with rules per program
  • Each rule assigns percentages or fixed quantities to vendors
  • Transitions define phased allocation changes at specific quarters
  • Overrides adjust vendor capacity temporarily (e.g. planned maintenance)
  • Auto-saved to DB on every change

MPS (Master Production Schedule)

  • mps_commit each uploaded forecast is a versioned "commit"
  • mps_entry one row per program x quarter x commit
  • mps_diff auto-generated change records between revisions

Analytics Views

Pre-built SQL views for the analytics page:

  • v_demand latest forecast with program names/groups
  • v_vendor_capacity lines, throughput, quarterly capacity per vendor-program
  • v_vendor_group_summary aggregate stats by vendor group
  • v_scenario_allocations all allocation rules denormalized across scenarios
  • v_scenario_comparison base allocations for comparing scenarios side-by-side
  • v_scenario_overrides capacity overrides with names

File Structure

gsm-tools/
  main.py              # Entry point (uvicorn, port 8001)
  app.html             # Main app  single-page vanilla JS frontend
  pyproject.toml       # Python deps (fastapi, uvicorn, httpx)
  api/
    app.py             # All API endpoints + seed logic
    db.py              # SQLite helpers + migration runner
  analytics/           # Vite + React analytics app (Graphic Walker)
    src/
      App.jsx          # Main component  data loading + GraphicWalker
      index.css        # Styles matching main app design
    vite.config.js     # Build config (outputs to ../static/analytics/)
    package.json
  static/
    analytics/         # Built analytics app (gitignored, run npm run build)
  migrations/
    001-014            # Schema migrations (applied in order on startup)
  data/
    gsm_tools.db       # SQLite database (auto-created)

API Endpoints

Method Path Description
GET /api/mps/current Latest forecast with programs, quarters, entries
GET /api/mps/history All commits with diff counts
GET /api/mps/history/all Full entry history
POST /api/mps/preview Parse CSV, return diffs and conflicts
POST /api/mps/import Commit a previewed import
PUT /api/mps/commits/{id} Edit commit note/publish date
GET /api/programs Programs with aliases and vendor associations
PUT /api/programs/{id} Update program metadata
GET /api/vendors All vendors
POST /api/vendors Create vendor
PUT /api/vendors/{id} Update vendor
DELETE /api/vendors/{id} Delete vendor
POST /api/vendor-programs Create vendor-program association
PUT /api/vendor-programs/by-pair Upsert lines/throughput
DELETE /api/vendor-programs/{id} Delete association
GET /api/scenarios All scenarios with rules and overrides
POST /api/scenarios Create scenario
PUT /api/scenarios/{id} Update scenario (full replace)
DELETE /api/scenarios/{id} Delete scenario
POST /api/scenarios/reorder Update scenario tab order
POST /api/sql Execute arbitrary SQL (debug/analytics)