| 1 |
Browser |
Header.jsx |
User clicks ↑ Upload button — UploadModal opens |
Frontend |
| 2 |
Browser |
UploadModal.jsx |
POST /api/upload/reset — clears previous job state on server |
API |
| 3 |
Browser |
UploadModal.jsx |
POST /api/upload — sends .xlsx file as multipart form-data |
API |
| 4 |
Server |
upload_server.py |
Saves file to _uploads/, spawns background thread, returns HTTP 200 immediately |
Python |
| 5 |
Server |
upload_server.py |
subprocess.Popen → runs python -m pipeline.run with the uploaded file |
Python |
| 6 |
Pipeline |
pipeline/loader.py |
Reads sheet 1_Source_Data → 3,207 rows DataFrame. Reads sheet 2_Brand_Config → focal brand + competitors |
Python |
| 7 |
Pipeline |
pipeline/config.py |
Loads DEFAULT_PACK_ORDER and all modelling thresholds (no I/O) |
Python |
| 8 |
Pipeline |
pipeline/modelling.py |
build_wide_pivot() builds monthly CH×Region tables. run_elasticity_models() tests 343 OLS specs per grain, selects best Adj-R² |
Python |
| 9 |
Pipeline |
pipeline/proxies.py |
assign_proxies() fills 7 grains that failed sign check. compute_freq_anchors() finds dominant pack per CH×Region |
Python |
| 10 |
Pipeline |
pipeline/diagnostics.py |
Runs collinearity, RPI, distribution, cannibalization checks → writes Step1_Diagnostics.xlsx |
Python |
| 11 |
Exporters |
exporters/stats.py |
Writes models.json, stats.json, freq_anchors.json to output/ |
Output |
| 12 |
Exporters |
exporters/market.py |
Writes trend.json, ms.json, vol_salience.json, val_share.json, comp_ms.json, vtm.json |
Output |
| 13 |
Exporters |
exporters/ppa.py |
Reads Excel sheets 3_PPA_MT and 4_PPA_TT → writes ppa_mt.json, ppa_tt.json |
Output |
| 14 |
Exporters |
exporters/analytics.py |
Writes interaction.json, growth_decomp.json, pgi.json |
Output |
| 15 |
Exporters |
exporters/recommendations.py |
Writes recs_full.json |
Output |
| 16 |
Server |
upload_server.py |
Copies all 16 JSON files from output/ to public/data/ as static fallback. Sets job status = done |
Python |
| 17 |
Browser |
UploadModal.jsx |
Polling detects status = done. User clicks Reload Dashboard |
Frontend |
| 18 |
Browser |
DataContext.jsx |
Fires GET /api/data/{key} × 16 calls to fetch all computed JSON data |
API |
| 19 |
Server |
upload_server.py |
@app.get("/api/data/{key}") reads output/{key}.json → returns JSON to browser |
Python |
| 20 |
Browser |
All 9 tab components |
React re-renders every tab with fresh pipeline-computed data |
Frontend |