The EFI Sourcing Dashboard at sourcing.energyfeeds.net (or http://localhost:3002 in development) is a supply-demand gap analysis tool with AI-powered purchasing recommendations. It answers three questions:
Every number in the dashboard is deterministic and traceable — the rules engine uses fixed formulas, not AI judgment, to compute gaps, rank suppliers, and calculate landed costs. AI is used only to write the natural-language explanations on recommendation cards. If the AI is unavailable, all recommendations still function with structured placeholder text.
| Source | What it provides |
|---|---|
| Airtable CRM | Demand: contracts, open orders, forecasts, inventory availability, customer data |
| PostgreSQL ERP | Supply: supplier purchase orders, shipping windows, supplier capacities, port/route reference data |
| AI (optional) | Narrative text on recommendation cards (reasoning, risk notes, price rationale) |
| View | URL | Purpose |
|---|---|---|
| Gap Matrix | /gap |
Product × month coverage heatmap with drill-down |
| AI Recommendations | /gap/recommendations |
Actionable purchase recommendations per gap |
| Forecast Audit | /gap/forecast-audit |
Customer-level forecast accuracy analysis |
Navigation links for all three appear in the top nav bar on every page.
/gap)This is the main view. It shows every product across the next 6 months in a color-coded grid.
Four KPI cards appear at the top:
| Card | What it shows |
|---|---|
| Total Demand | Contracts + open orders + confidence-adjusted forecast, summed across all products and months |
| Supplier POs | Metric tons on order from suppliers (purchase orders placed for upcoming shipping months) |
| On-Hand Inventory | Physical inventory on hand right now (beginning stock + arrived POs + expected arrivals, current month only) |
| Overall Coverage | Total supply / total demand as a percentage. Green at 100%+, yellow at 50–99%, red below 50% |
Each cell in the matrix is colored by coverage level:
| Color | Meaning | Coverage |
|---|---|---|
| Green | Fully covered — supply meets or exceeds demand | 100%+ |
| Yellow | Partial coverage — some shortfall | 50–99% |
| Red | Shortfall — significant gap | Below 50% |
| Light blue | Gap exists but is fully covered by sourcing plans already in the pipeline | Planned |
| Light gray | Supply exists but no demand (informational only) | Supply only |
Each cell packs several data points into a compact layout:
72% ← coverage percentage (bold)
D: 5,000 / S: 3,100 ← total demand vs total supply
C: 2,000 F: 1,200 ← contracts vs forecast (forecast in orange)
PO: 2,800 Inv: 300 ← PO tons vs inventory
+1,900 ST ← gap (red if positive = shortfall)
Avg FOB: $965 ← weighted average FOB price
Clickable cells: Red and yellow cells (those with unplanned gaps) are clickable — they link directly to the AI Recommendations view filtered to that specific product and month.
Many products ship to multiple warehouses (BAL, HOU, OAK, TAC, SAV, FTW). Click the chevron (▶) next to a product name to expand warehouse-level detail.
This is important because a product cell may show green at the aggregate level while individual warehouses have shortfalls. When this happens, a badge appears in the cell:
2 WH gaps (+300 ST)) — unplanned warehouse-level gaps exist despite overall coverage2 planned) — warehouse gaps exist but are covered by sourcing plansExpand further (chevron on a warehouse row) to see the full demand/supply breakdown by category:
These rows show month-by-month values and are useful for diagnosing why a gap exists.
Click any product name in the matrix to open the Product Detail view (/gap/product?name=X). This shows:
All three views share the same filter controls. Active filters persist in the URL, so bookmarks and shared links preserve the current view.
Click warehouse abbreviations (BAL, HOU, OAK, etc.) to toggle them on/off. Active chips are highlighted in red. When no chips are selected, all warehouses are shown.
Filter by packaging type (Bags, Totes, etc.). Same toggle behavior as warehouse chips.
Select a specific customer to see only their demand (contracts + orders + forecast). Supply stays company-wide since purchase orders are not customer-specific. Choose "All Customers" to return to the aggregate view.
Override the forecast confidence level for what-if scenarios:
| Option | Effect |
|---|---|
| Historical (default) | Uses each sales rep's actual historical accuracy rate per product |
| 100% | Trust all forecast at face value |
| 80% | Apply 80% confidence to all unsold forecast |
| 50% | Halve all forecast — conservative scenario |
| 20% | Aggressive skepticism — mostly ignore forecast |
| 0% (contracts only) | Zero out all forecast, show only firm demand |
This is a powerful planning tool. For example, set confidence to 0% to see "what's the gap if no new contracts come in?" — the firm floor. Then compare against Historical to see how much depends on forecast accuracy.
Understanding the engine helps you evaluate whether a recommendation makes sense for your situation.
Every recommendation is deterministic — the same inputs always produce the same output. There is no AI judgment in the numbers. The engine follows a fixed set of rules:
Not all demand is equally certain. The engine splits demand into three tiers:
| Tier | Source | Sourcing Commitment |
|---|---|---|
| Tier 1: Firm Floor | Forward + Conversion + Spot contracts, open orders | 100% — always source for this |
| Tier 2: High-Confidence Unsold | Unsold forecast from reps with >80% historical accuracy | Source proportionally at the rep's accuracy rate |
| Tier 3: Low-Confidence Unsold | Unsold forecast from reps with <60% accuracy, or unsold spot | Source only 50% — mostly monitor |
Reps in the 60–80% accuracy range are scaled linearly between tiers 2 and 3.
The engine always computes two scenarios:
Before recommending a new purchase order, the engine tries to fill the gap from existing sources, in this priority order:
| Step | Source | Description |
|---|---|---|
| 1 | General pool (same warehouse) | Unallocated inventory already at the right warehouse |
| 2 | General pool (nearby warehouse) | Unallocated inventory at adjacent warehouses (shared budget prevents double-counting) |
| 3 | Strategic reserve | Reserved inventory that can be released if needed |
| 4 | Cross-warehouse excess | Surplus from warehouses with no deficit — only allowed when firm demand is ≥50% of total (prevents speculative transfers) |
| 5 | Existing sourcing plan | Planned supply already in the pipeline (negotiated POs not yet shipped) |
| 6 | New PO | Fresh purchase order to a ranked supplier — only after steps 1–5 are exhausted |
| 7 | Buy-ahead | Over-source this month at a favorable price to cover next month's gap — only when price trend is falling and savings exceed 2% |
When a new PO is needed (step 6), the engine ranks available suppliers using a 5-factor weighted score:
| Weight | Factor | What it measures |
|---|---|---|
| 35% | Landed Cost | Lower total delivered cost = higher score |
| 25% | Capacity | More available allocation remaining = higher score |
| 20% | Reliability | More historical POs completed = higher score |
| 10% | Recent Activity | More recent PO activity = higher score |
| 10% | Relationship | More total tonnage ordered historically = higher score |
Diversification rule: No single supplier can exceed 60% of total monthly sourcing for a product. When this threshold is hit, the engine automatically splits the order across the top 2–3 suppliers.
Each recommendation includes a full landed cost breakdown:
FOB (supplier quote) $950/MT
+ Ocean Freight $155/MT (contract rate — 5+ containers)
+ Tariff $42/MT
+ Drayage (port → warehouse) $18/MT
+ Handling & Storage $15/MT
+ Customs Broker Fee $9/MT
─────────────────────────────────────
Total Landed $1,189/MT
Ocean freight uses the contract rate when the order fills 5+ containers (100+ MT), and the higher spot rate for smaller volumes.
Each recommendation computes the full timeline from PO placement to warehouse receipt:
PO Confirmation 4 days
Production 10 days (supplier-specific, 7–14 day range)
Ship Window 1st–15th of month before delivery month
Ocean Transit ~28 days (route-specific)
Port Clearance 6 days
───────────────────────────
Total lead time ~48 days
The engine works backward from the target delivery month to compute:
/gap/recommendations)This view shows the engine's output as actionable recommendation cards, grouped by product and sorted by urgency.
Five KPI cards appear at the top:
| Card | What it shows |
|---|---|
| Gaps Analyzed | Total number of product × month gaps evaluated |
| Actionable | Count of recommendations requiring action (excludes hold/wait) |
| Total to Order | Sum of recommended metric tons across all fill_gap and buy_ahead recs |
| Est. Total Cost | Sum of estimated total cost for all actionable recommendations |
| Immediate | Count of recommendations with <14 days to order deadline (red, only shown if >0) |
A type summary line below the cards shows counts per recommendation type (e.g., "3 Fill Gap · 1 Buy Ahead · 2 Redirect").
When filters are applied (from the gap matrix or URL), they appear as removable chips at the top. Click the × on any chip to remove it, or use "Clear All" to reset.
Recommendations are grouped by product in collapsible sections. Each section header shows:
Click to expand and see individual recommendation cards.
Each recommendation card has a colored left border and type badge indicating what action to take:
ORDER (red badge)Place a new purchase order. This is the most common recommendation.
The card tells you exactly what to do:
BUY AHEAD (green badge)Over-source now to lock in a favorable price for a future month. Only fires when:
The card shows the target month the extra tonnage covers and the estimated per-MT savings.
REDIRECT (blue badge)Reroute an existing or planned PO from an excess warehouse to a deficit warehouse. No new purchase required — this is a logistics change.
Example: "BAL → HOU: Redirect 80 ST" — Baltimore has excess, Houston has a shortfall.
REALLOCATE (purple badge)Release existing inventory from general pool or strategic reserve. No PO required — the product is already in a warehouse.
Example: "Release 50 ST from Strategic Reserve at BAL"
WAIT (amber badge)Don't source yet — demand is too uncertain. Fires when firm demand is below 50% of total and the delivery month is 2+ months out.
The card shows a demand certainty bar — a progress bar indicating what percentage of demand is from firm contracts. Below 50%, the engine recommends waiting for more contracts to materialize rather than sourcing against speculative forecast.
HOLD (gray badge)No action needed. Existing plans or inventory already cover this gap. The card explains why.
When redirect or reallocation opportunities exist for a product, a purple transfer banner appears at the top of the product section summarizing all transfer recommendations before the individual cards.
At the bottom of the page, a collapsible "Fully Sourced" section lists all gaps that are already covered by existing sourcing plans. This confirms which product/month combinations require no action.
Recommendations are cached for 60 minutes. Add ?nocache=1 to the URL to force a fresh generation. If the AI enrichment service is unavailable, the page displays a yellow banner ("AI Recommendations Unavailable") but still shows any fully sourced gaps and the back link.
/gap/forecast-audit)The Forecast Audit analyzes how accurate each sales rep's forecasts have been and flags customers whose forecast numbers don't hold up against historical patterns.
Eight KPI cards across the top:
| Card | What it shows |
|---|---|
| Customers Audited | Total distinct customers analyzed |
| High Severity | Customers with critical forecasting issues (red) |
| Medium Severity | Customers needing monitoring (orange) |
| Low Severity | Informational items (green) |
| Over-Forecasters | Customers whose forecast consistently exceeds actual purchases |
| Under-Forecasters | Customers whose actual purchases consistently exceed forecast |
| Missing Customers | Customers with recent purchase history but no current forecast at all |
| Net FC Adjustment | Total metric tons the audit recommends adding or removing across all customers |
The forecast audit has its own filter bar:
| Filter | Type | Options |
|---|---|---|
| Month | Multi-select chips | Specific months (e.g., "Mar 26", "Apr 26") |
| Warehouse | Multi-select chips | Warehouse abbreviations |
| Sort | Dropdown | Severity (default), Customer Name, Accuracy %, Forecast Delta |
| Issue Type | Dropdown | All Issues, or filter to a specific issue type |
| Sales Rep | Dropdown | All Reps, or filter to a specific rep |
Customers are organized into three collapsible severity groups: High (red), Medium (orange), and Low (green). Each group header shows the customer count, total issues, and net forecast adjustment.
Expand any customer row to see:
| Issue | Severity | What it means |
|---|---|---|
| Over Forecasting | High | Rep's forecast has been >30% above actuals for 3+ months running |
| Large Customer Not Contracted | High | Top-quartile customer by tonnage has no forward or conversion contracts for upcoming months |
| Contract Non-Delivery | High | Customer's actual deliveries are below 80% of contracted volume |
| Forecast Exceeds Opportunity | Medium | Total forecast exceeds the opportunity ceiling for a month |
| Under Forecasting | Medium | Actual demand has exceeded forecast by 40%+ for 3+ months |
| Ignores Trailing Trend | Medium | Forecast deviates ±25% or more from the trailing 3-month average |
| Ignores Lost Sales | Medium | Loss reports were filed but future forecast wasn't reduced |
| Inconsistent With History | Low | Future forecast deviates >50% from historical average |
| Inventory Stockout Loss | Low | Forecast dropped >20% after a zero-sold month (customer may have gone elsewhere) |
| Missing Customer | Low | Customer has purchase history in the last 12 months but no current forecast |
| Weekly Distribution Risk | Low | A single product makes up >75% of the customer's weekly forecast |
The forecast audit isn't just informational — its findings automatically adjust the sourcing engine's demand tiers:
| Audit Finding | Engine Adjustment |
|---|---|
| Chronic over-forecasting | Reduces confidence to the rep's actual accuracy rate |
| Chronic under-forecasting | Increases confidence, flags potential stockout risk |
| Contract non-delivery (<80%) | Reduces firm demand by the non-delivery rate |
| Ignores trailing trend | Substitutes trailing 3-month average for raw forecast |
| Forecast exceeds opportunity | Caps demand at the opportunity ceiling |
| Missing customer | Adds estimated demand based on historical purchase pattern |
This means the gap matrix and recommendations already reflect audit-adjusted demand — you don't need to manually correct for known forecasting issues.
At the bottom of the page, a collapsible "Missing Customers" section lists customers who have purchased in the last 12 months but have no current forecast. The table shows their last purchase date, average tonnage, products purchased, and months since last order. Recently active customers (≤3 months) are highlighted in red.
Present on every page:
/gap)/gap/recommendations)/gap/forecast-audit)| I want to... | Do this |
|---|---|
| See the big picture | Go to /gap — the gap matrix shows everything at a glance |
| Investigate a specific product | Click the product name in the gap matrix to open the product detail view |
| Get purchase recommendations | Click the red "Get AI Recommendations" button, or click any red/yellow cell |
| See recommendations for one product/month | Click the specific red/yellow cell in the gap matrix |
| Check forecast accuracy | Go to Forecast Audit in the nav bar |
| Run a what-if scenario | Change the Confidence Override chips (e.g., 0% = contracts only) |
| See only one warehouse | Click that warehouse chip in the filter bar |
| See one customer's view | Select them from the Customer dropdown |
| Force fresh data | Add ?nocache=1 to the URL |
| Get raw JSON data | Use the API endpoints below |
For programmatic access or integration:
| Endpoint | Returns |
|---|---|
GET /api/gap |
Full gap report JSON |
GET /api/gap/recommendations |
Recommendations JSON |
GET /api/gap/forecast-audit |
Forecast audit JSON |
GET /api/gap/analytics |
Supplier scorecards, price trends, forecast accuracy, route costs |
All endpoints accept the same query parameters as the UI views (customer, warehouse, packaging, confidence, nocache).