Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <title>Genesis AI β Complete Data Flow</title> | |
| <script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script> | |
| <style> | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { | |
| font-family: 'Segoe UI', Arial, sans-serif; | |
| background: #f4f6f9; | |
| color: #1a1a2e; | |
| padding: 32px; | |
| } | |
| h1 { | |
| font-size: 22px; | |
| font-weight: 700; | |
| color: #1a6b2f; | |
| border-bottom: 3px solid #1a6b2f; | |
| padding-bottom: 10px; | |
| margin-bottom: 6px; | |
| } | |
| .subtitle { | |
| font-size: 12px; | |
| color: #666; | |
| margin-bottom: 32px; | |
| } | |
| /* ββ Section cards ββ */ | |
| .section { | |
| background: #fff; | |
| border-radius: 12px; | |
| box-shadow: 0 2px 12px rgba(0,0,0,.08); | |
| padding: 24px 28px; | |
| margin-bottom: 28px; | |
| } | |
| .section-title { | |
| font-size: 14px; | |
| font-weight: 700; | |
| letter-spacing: .5px; | |
| text-transform: uppercase; | |
| color: #1a6b2f; | |
| margin-bottom: 18px; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .section-title .badge { | |
| background: #1a6b2f; | |
| color: #fff; | |
| font-size: 11px; | |
| border-radius: 20px; | |
| padding: 2px 10px; | |
| } | |
| /* ββ Mermaid diagram wrapper ββ */ | |
| .mermaid { | |
| overflow-x: auto; | |
| padding: 8px 0; | |
| } | |
| /* ββ Step table ββ */ | |
| table { | |
| width: 100%; | |
| border-collapse: collapse; | |
| font-size: 12px; | |
| } | |
| thead tr { | |
| background: #1a6b2f; | |
| color: #fff; | |
| } | |
| thead th { | |
| padding: 9px 14px; | |
| text-align: left; | |
| font-weight: 600; | |
| letter-spacing: .3px; | |
| } | |
| tbody tr:nth-child(odd) { background: #f8faf8; } | |
| tbody tr:nth-child(even) { background: #fff; } | |
| tbody tr:hover { background: #e8f5e9; } | |
| td { | |
| padding: 8px 14px; | |
| vertical-align: top; | |
| border-bottom: 1px solid #e8ede9; | |
| } | |
| td:first-child { font-weight: 600; color: #1a6b2f; white-space: nowrap; } | |
| .tag { | |
| display: inline-block; | |
| font-size: 10px; | |
| font-weight: 600; | |
| padding: 2px 7px; | |
| border-radius: 4px; | |
| white-space: nowrap; | |
| } | |
| .tag-fe { background: #e3f2fd; color: #1565c0; } | |
| .tag-api { background: #fff3e0; color: #e65100; } | |
| .tag-py { background: #e8f5e9; color: #1a6b2f; } | |
| .tag-out { background: #f3e5f5; color: #6a1b9a; } | |
| /* ββ File list ββ */ | |
| .file-grid { | |
| display: grid; | |
| grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); | |
| gap: 10px; | |
| margin-top: 4px; | |
| } | |
| .file-card { | |
| background: #f8faf8; | |
| border: 1px solid #c8e6c9; | |
| border-radius: 8px; | |
| padding: 10px 13px; | |
| } | |
| .file-card .fname { | |
| font-family: 'Consolas', monospace; | |
| font-size: 11px; | |
| font-weight: 700; | |
| color: #1a6b2f; | |
| } | |
| .file-card .fsrc { | |
| font-size: 10px; | |
| color: #888; | |
| margin-top: 3px; | |
| } | |
| /* ββ API table ββ */ | |
| code { | |
| font-family: 'Consolas', monospace; | |
| font-size: 11.5px; | |
| background: #f0f4f0; | |
| padding: 2px 6px; | |
| border-radius: 4px; | |
| } | |
| .footer { | |
| text-align: center; | |
| font-size: 11px; | |
| color: #aaa; | |
| margin-top: 32px; | |
| padding-top: 16px; | |
| border-top: 1px solid #e0e0e0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Genesis AI β Price Elasticity Intelligence</h1> | |
| <div class="subtitle">Complete Data Flow | Frontend β API β Python Pipeline β Output β Dashboard</div> | |
| <!-- ββ MASTER FLOWCHART ββ --> | |
| <div class="section"> | |
| <div class="section-title"><span class="badge">1</span> Master Flow Diagram</div> | |
| <div class="mermaid"> | |
| flowchart TD | |
| A([User opens Dashboard\nbrowser Β· localhost:5173]) --> B | |
| B{Upload server\nrunning?} | |
| B -- YES --> C1[GET /api/data/key x16\nFastAPI reads output/*.json] | |
| B -- NO --> C2[GET /data/key.json x16\nVite serves public/data/ static files] | |
| C1 --> D([React tabs render\nwith computed data]) | |
| C2 --> D | |
| style A fill:#1a6b2f,color:#fff,rx:20 | |
| style D fill:#1a6b2f,color:#fff,rx:20 | |
| style B fill:#fff3e0,color:#333 | |
| </div> | |
| </div> | |
| <!-- ββ UPLOAD FLOW ββ --> | |
| <div class="section"> | |
| <div class="section-title"><span class="badge">2</span> Upload Button β Python Pipeline β Dashboard Refresh</div> | |
| <div class="mermaid"> | |
| flowchart TD | |
| U1([User clicks Upload button\nHeader.jsx]) -->|opens| U2[UploadModal.jsx] | |
| U2 -->|POST /api/upload/reset| U3[FastAPI resets job state β idle] | |
| U3 --> U4[User drags or picks .xlsx file] | |
| U4 -->|POST /api/upload\nmultipart form-data| U5 | |
| U5[upload_server.py\n@app.post /api/upload] --> U6[Save file to\n_uploads/ folder] | |
| U6 --> U7[Spawn background thread\n_run_pipeline] | |
| U7 -->|returns immediately| U8[HTTP 200 Β· ok: true] | |
| U8 --> U9[UploadModal polls every 1.5s\nGET /api/upload/status\nGET /api/upload/logs] | |
| U7 -->|subprocess.Popen| P1 | |
| P1[pipeline/run.py\nEntry Point] --> P2 | |
| P2[pipeline/loader.py\nload_source_data\nread_brand_config] --> P3 | |
| P3[pipeline/config.py\nDEFAULT_PACK_ORDER\nconstants only] --> P4 | |
| P4[pipeline/modelling.py\nbuild_wide_pivot\nrun_elasticity_models\n343 specs tested] --> P5 | |
| P5[pipeline/proxies.py\nassign_proxies 7 grains\ncompute_freq_anchors] --> P6 | |
| P6[pipeline/diagnostics.py\nrun_diagnostics\nStep1_Diagnostics.xlsx] --> P7 | |
| P7[pipeline/exporters/stats.py] --> J1[models.json\nstats.json\nfreq_anchors.json] | |
| P7 --> EX2 | |
| EX2[pipeline/exporters/market.py] --> J2[trend.json Β· ms.json\nvol_salience.json Β· val_share.json\ncomp_ms.json Β· vtm.json] | |
| EX2 --> EX3 | |
| EX3[pipeline/exporters/ppa.py\nreads sheet 3_PPA_MT\nreads sheet 4_PPA_TT] --> J3[ppa_mt.json\nppa_tt.json] | |
| EX3 --> EX4 | |
| EX4[pipeline/exporters/analytics.py] --> J4[interaction.json\ngrowth_decomp.json\npgi.json] | |
| EX4 --> EX5 | |
| EX5[pipeline/exporters/recommendations.py] --> J5[recs_full.json] | |
| J1 & J2 & J3 & J4 & J5 --> OUT[16 JSON files\nin output/] | |
| OUT --> CP[Copied to\npublic/data/ as fallback] | |
| OUT --> ST[Job status = done] | |
| ST --> PL[UploadModal sees done\nUser clicks Reload Dashboard] | |
| PL -->|GET /api/data/key x16| SV[upload_server.py\n@app.get /api/data/key\nreads output/key.json] | |
| SV --> RD([React re-renders\nall 9 tabs with fresh data]) | |
| style U1 fill:#1a6b2f,color:#fff | |
| style RD fill:#1a6b2f,color:#fff | |
| style P1 fill:#1565c0,color:#fff | |
| style OUT fill:#6a1b9a,color:#fff | |
| </div> | |
| </div> | |
| <!-- ββ STEP BY STEP TABLE ββ --> | |
| <div class="section"> | |
| <div class="section-title"><span class="badge">3</span> Step-by-Step Reference</div> | |
| <table> | |
| <thead> | |
| <tr> | |
| <th>Step</th> | |
| <th>Where</th> | |
| <th>File / Endpoint</th> | |
| <th>What happens</th> | |
| <th>Layer</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <tr> | |
| <td>1</td> | |
| <td>Browser</td> | |
| <td><code>Header.jsx</code></td> | |
| <td>User clicks β Upload button β UploadModal opens</td> | |
| <td><span class="tag tag-fe">Frontend</span></td> | |
| </tr> | |
| <tr> | |
| <td>2</td> | |
| <td>Browser</td> | |
| <td><code>UploadModal.jsx</code></td> | |
| <td>POST /api/upload/reset β clears previous job state on server</td> | |
| <td><span class="tag tag-api">API</span></td> | |
| </tr> | |
| <tr> | |
| <td>3</td> | |
| <td>Browser</td> | |
| <td><code>UploadModal.jsx</code></td> | |
| <td>POST /api/upload β sends .xlsx file as multipart form-data</td> | |
| <td><span class="tag tag-api">API</span></td> | |
| </tr> | |
| <tr> | |
| <td>4</td> | |
| <td>Server</td> | |
| <td><code>upload_server.py</code></td> | |
| <td>Saves file to _uploads/, spawns background thread, returns HTTP 200 immediately</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>5</td> | |
| <td>Server</td> | |
| <td><code>upload_server.py</code></td> | |
| <td>subprocess.Popen β runs python -m pipeline.run with the uploaded file</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>6</td> | |
| <td>Pipeline</td> | |
| <td><code>pipeline/loader.py</code></td> | |
| <td>Reads sheet 1_Source_Data β 3,207 rows DataFrame. Reads sheet 2_Brand_Config β focal brand + competitors</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>7</td> | |
| <td>Pipeline</td> | |
| <td><code>pipeline/config.py</code></td> | |
| <td>Loads DEFAULT_PACK_ORDER and all modelling thresholds (no I/O)</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>8</td> | |
| <td>Pipeline</td> | |
| <td><code>pipeline/modelling.py</code></td> | |
| <td>build_wide_pivot() builds monthly CHΓRegion tables. run_elasticity_models() tests 343 OLS specs per grain, selects best Adj-RΒ²</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>9</td> | |
| <td>Pipeline</td> | |
| <td><code>pipeline/proxies.py</code></td> | |
| <td>assign_proxies() fills 7 grains that failed sign check. compute_freq_anchors() finds dominant pack per CHΓRegion</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>10</td> | |
| <td>Pipeline</td> | |
| <td><code>pipeline/diagnostics.py</code></td> | |
| <td>Runs collinearity, RPI, distribution, cannibalization checks β writes Step1_Diagnostics.xlsx</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>11</td> | |
| <td>Exporters</td> | |
| <td><code>exporters/stats.py</code></td> | |
| <td>Writes models.json, stats.json, freq_anchors.json to output/</td> | |
| <td><span class="tag tag-out">Output</span></td> | |
| </tr> | |
| <tr> | |
| <td>12</td> | |
| <td>Exporters</td> | |
| <td><code>exporters/market.py</code></td> | |
| <td>Writes trend.json, ms.json, vol_salience.json, val_share.json, comp_ms.json, vtm.json</td> | |
| <td><span class="tag tag-out">Output</span></td> | |
| </tr> | |
| <tr> | |
| <td>13</td> | |
| <td>Exporters</td> | |
| <td><code>exporters/ppa.py</code></td> | |
| <td>Reads Excel sheets 3_PPA_MT and 4_PPA_TT β writes ppa_mt.json, ppa_tt.json</td> | |
| <td><span class="tag tag-out">Output</span></td> | |
| </tr> | |
| <tr> | |
| <td>14</td> | |
| <td>Exporters</td> | |
| <td><code>exporters/analytics.py</code></td> | |
| <td>Writes interaction.json, growth_decomp.json, pgi.json</td> | |
| <td><span class="tag tag-out">Output</span></td> | |
| </tr> | |
| <tr> | |
| <td>15</td> | |
| <td>Exporters</td> | |
| <td><code>exporters/recommendations.py</code></td> | |
| <td>Writes recs_full.json</td> | |
| <td><span class="tag tag-out">Output</span></td> | |
| </tr> | |
| <tr> | |
| <td>16</td> | |
| <td>Server</td> | |
| <td><code>upload_server.py</code></td> | |
| <td>Copies all 16 JSON files from output/ to public/data/ as static fallback. Sets job status = done</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>17</td> | |
| <td>Browser</td> | |
| <td><code>UploadModal.jsx</code></td> | |
| <td>Polling detects status = done. User clicks Reload Dashboard</td> | |
| <td><span class="tag tag-fe">Frontend</span></td> | |
| </tr> | |
| <tr> | |
| <td>18</td> | |
| <td>Browser</td> | |
| <td><code>DataContext.jsx</code></td> | |
| <td>Fires GET /api/data/{key} Γ 16 calls to fetch all computed JSON data</td> | |
| <td><span class="tag tag-api">API</span></td> | |
| </tr> | |
| <tr> | |
| <td>19</td> | |
| <td>Server</td> | |
| <td><code>upload_server.py</code></td> | |
| <td>@app.get("/api/data/{key}") reads output/{key}.json β returns JSON to browser</td> | |
| <td><span class="tag tag-py">Python</span></td> | |
| </tr> | |
| <tr> | |
| <td>20</td> | |
| <td>Browser</td> | |
| <td>All 9 tab components</td> | |
| <td>React re-renders every tab with fresh pipeline-computed data</td> | |
| <td><span class="tag tag-fe">Frontend</span></td> | |
| </tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- ββ API ENDPOINTS ββ --> | |
| <div class="section"> | |
| <div class="section-title"><span class="badge">4</span> All API Endpoints</div> | |
| <table> | |
| <thead> | |
| <tr><th>Method</th><th>Endpoint</th><th>Called by</th><th>Purpose</th></tr> | |
| </thead> | |
| <tbody> | |
| <tr><td>POST</td><td><code>/api/upload</code></td><td>UploadModal.jsx</td><td>Upload .xlsx file β triggers Python pipeline</td></tr> | |
| <tr><td>GET</td> <td><code>/api/upload/status</code></td><td>UploadModal.jsx (poll)</td><td>Returns { status, message, elapsed_s }</td></tr> | |
| <tr><td>GET</td> <td><code>/api/upload/logs</code></td><td>UploadModal.jsx (poll)</td><td>Returns live pipeline stdout as { logs }</td></tr> | |
| <tr><td>POST</td><td><code>/api/upload/reset</code></td><td>UploadModal.jsx (on open)</td><td>Clears job state back to idle</td></tr> | |
| <tr><td>GET</td> <td><code>/api/data/{key}</code></td><td>DataContext.jsx</td><td>Serves output/{key}.json computed by pipeline</td></tr> | |
| <tr><td>GET</td> <td><code>/api/data</code></td><td>(debug)</td><td>Lists all available data keys and file sizes</td></tr> | |
| <tr><td>GET</td> <td><code>/data/{key}.json</code></td><td>DataContext.jsx (fallback)</td><td>Vite static file β used only when server is down</td></tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| <!-- ββ OUTPUT FILES ββ --> | |
| <div class="section"> | |
| <div class="section-title"><span class="badge">5</span> Python Output Files β Dashboard Tabs</div> | |
| <div class="file-grid"> | |
| <div class="file-card"><div class="fname">models.json</div><div class="fsrc">exporters/stats.py β Elasticity Results tab</div></div> | |
| <div class="file-card"><div class="fname">stats.json</div><div class="fsrc">exporters/stats.py β Header KPIs</div></div> | |
| <div class="file-card"><div class="fname">freq_anchors.json</div><div class="fsrc">exporters/stats.py β Methodology tab</div></div> | |
| <div class="file-card"><div class="fname">trend.json</div><div class="fsrc">exporters/market.py β Trends tab</div></div> | |
| <div class="file-card"><div class="fname">ms.json</div><div class="fsrc">exporters/market.py β shared</div></div> | |
| <div class="file-card"><div class="fname">vol_salience.json</div><div class="fsrc">exporters/market.py β shared</div></div> | |
| <div class="file-card"><div class="fname">val_share.json</div><div class="fsrc">exporters/market.py β shared</div></div> | |
| <div class="file-card"><div class="fname">comp_ms.json</div><div class="fsrc">exporters/market.py β shared</div></div> | |
| <div class="file-card"><div class="fname">vtm.json</div><div class="fsrc">exporters/market.py β Brand Interaction tab</div></div> | |
| <div class="file-card"><div class="fname">ppa_mt.json</div><div class="fsrc">exporters/ppa.py β PPA tab (MT)</div></div> | |
| <div class="file-card"><div class="fname">ppa_tt.json</div><div class="fsrc">exporters/ppa.py β PPA tab (TT)</div></div> | |
| <div class="file-card"><div class="fname">interaction.json</div><div class="fsrc">exporters/analytics.py β Brand Interaction tab</div></div> | |
| <div class="file-card"><div class="fname">growth_decomp.json</div><div class="fsrc">exporters/analytics.py β Growth Decomp tab</div></div> | |
| <div class="file-card"><div class="fname">pgi.json</div><div class="fsrc">exporters/analytics.py β Price Gradient tab</div></div> | |
| <div class="file-card"><div class="fname">recs_full.json</div><div class="fsrc">exporters/recommendations.py β Recommendations tab</div></div> | |
| <div class="file-card"><div class="fname">recs.json</div><div class="fsrc">alias of recs_full.json</div></div> | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| Genesis AI Β· Price Elasticity Intelligence Β· Dabur Sarson Amla | Generated by Claude Code | |
| </div> | |
| <script> | |
| mermaid.initialize({ | |
| startOnLoad: true, | |
| theme: 'default', | |
| flowchart: { curve: 'basis', padding: 20 }, | |
| themeVariables: { | |
| primaryColor: '#e8f5e9', | |
| primaryTextColor: '#1a1a2e', | |
| primaryBorderColor: '#1a6b2f', | |
| lineColor: '#1a6b2f', | |
| secondaryColor: '#fff3e0', | |
| tertiaryColor: '#e3f2fd', | |
| } | |
| }) | |
| </script> | |
| </body> | |
| </html> | |