Start
On-hand quantity snapshot from ERP (NetSuite)
Open Purchase Orders - quantities and expected delivery dates
OOS risk flags and new demand events
Full model rebuild - velocity recalculation, lead time refresh
Safety stock and reorder point recalculation for all SKUs
ABC reclassification run - SKUs may move class based on last 12 months revenue
Seasonality index recalibration
What do these terms mean?
On-hand: The physical count of units currently sitting in the warehouse, pulled directly from NetSuite.
Open PO: A purchase order already placed with a vendor but not yet received. The model counts this as incoming stock when calculating what to order.
OOS flag: Triggered when available units drop to zero. Urgency escalation starts here.

Why 3 cadences? Daily keeps buyers aware of critical changes overnight. The weekly rebuild ensures all velocity, lead time, and SS formulas use fresh inputs. Monthly recalibrates longer-term classifications (ABC, seasonality) that only need adjusting as trends shift.
Inactive or Discontinued? YES - STOP: excluded entirely from all output
Phase-Out flagged? YES - Set Order Qty = 0, do not reorder; still appears in dashboard
Reactivated SKU? YES - Flag for buyer review; use pre-inactivity velocity as starting point
All checks pass? NO flags - Active SKU, continue to Phase 3
What do these SKU states mean?
Active (no flag): Normal SKU, fully in catalogue, sold regularly. No restriction on ordering.
Inactive / Discontinued: No longer stocked or sold. The model excludes it completely - no order recommendation, no priority score, no dashboard row.
Phase-Out: Still selling through remaining stock but no new orders will be placed. Order Qty is forced to 0. Buyer sees it in the dashboard so they can monitor sell-through.
Reactivated: Was inactive and has been re-added to the catalogue. The model uses its last active velocity as a starting point - flagged because demand may have changed significantly since it was last active.
Trend / RecencyWindow UsedRationale
Growing90-dayRecent demand best predicts future
Stable90-dayConsistent demand, recent window sufficient
Declining (moderate)180-daySmooths short-term drop, avoids over-cutting
Declining (heavy)90-dayUses most recent to reflect current reality
No recent activityLifetime avgSparse sales, uses all available data
No sales at allNoneVelocity = 0, routed to No Velocity status
Multiply by Seasonality Index (based on month-of-year historical pattern)
Apply Event Uplift multiplier if next promo event falls within lead time (capped at +50%)
Key terms explained
Velocity: Average units sold per day. A SKU with velocity = 5 sells roughly 5 units every day.
Window (90d / 180d): The lookback period. 90d = uses only the last 90 days of sales to calculate velocity. 180d = uses the last 6 months.
Trend: Compares recent 90-day sales rate to the prior year. A SKU selling 10/day now vs 6/day a year ago is Growing. One going from 10 to 6 is Declining.

Seasonality Index: A monthly multiplier based on historical patterns. If acupuncture needles historically sell 40% above average in March, the March index is 1.40. Off-peak months are below 1.0.
Event Uplift: When a Listrek promotional event falls within the lead time window, velocity is increased by the SKU's historical event uplift percentage. Capped at 50% to prevent runaway overordering.
Tier 1 SKU actual median - uses any available PO history for this specific SKU - most accurate
Tier 2 Vendor actual - median lead time across all SKUs from the same vendor
Tier 3 Item master default lead time (as set in NetSuite for this item)
Tier 3.5 Category median - used when item master equals the 15-day default (avoids circular fallback)
Tier 4 15-day system default (last resort fallback)
Vendor Unreliable: std dev of delivery time >= 14 days - vendor timing is unpredictable
Why a waterfall, not a simple lookup?
Lead Time: Days between placing a purchase order and receiving the goods in the warehouse. Crucial - if you underestimate it, you run out before the order arrives.
Why Tier 1 is best: It uses this exact SKU's own history with this exact vendor. Vendor-SKU combinations often have quirks that a generic average misses.
Tier 2 (Vendor actual): If no SKU-specific data exists, the model looks at all POs from that vendor across all their SKUs. Still real delivery data, just less specific.
Tier 3.5 edge case: When the NetSuite item master says "15 days" (which is also the system default), the model can't tell if that was manually set or just inherited. It falls back to the category median instead.

Vendor Unreliable flag: If a vendor's std dev is 14+ days, they might deliver 2 weeks early or 2 weeks late. The model flags this so buyers know the lead time estimate is unreliable and extra buffer may be needed.
SS = Z x (Monthly_StdDev / sqrt(30)) x sqrt(Lead_Time_Days)
ROP = (Velocity x Lead_Time_Days) + Safety_Stock
SKU ClassMethodZ-ScoreService Level
A-classStatistical1.6595%
B-classStatistical1.6595%
C-classQuarterly Reviewn/aReview cycle
Promotional event within lead time window: increase ROP by event demand estimate
How the formula works in practice
Safety Stock: Extra units held as a buffer against unexpected demand spikes or late deliveries. Think of it as insurance stock.
Z = 1.65: A value from the statistics normal distribution table. Z = 1.65 means: if you hold SS = 1.65 x daily StdDev x sqrt(LT), you will avoid a stockout 95% of the time. Only 5 months in 100 would see a stockout despite holding SS.
Monthly StdDev / sqrt(30): Converts monthly sales variability into a daily rate. A SKU with monthly StdDev = 30 units has daily StdDev = 30 / 5.48 = 5.5 units/day.
ROP: The inventory level at which you trigger the next purchase order. Below this = order now.

Real example - Blue Poppy Sports Oil (BP.T.CHSMO):
Inputs Monthly StdDev = 28.25 units
Lead Time = 23 days
Velocity = 4.54 units/day
Safety Stock calculation Daily StdDev = 28.25 / sqrt(30) = 5.16
SS = 1.65 x 5.16 x sqrt(23)
SS = 1.65 x 5.16 x 4.80 = 40.8 ~ 41 units
Reorder Point ROP = (4.54 x 23) + 41
ROP = 104.4 + 41 = 145 units
If available stock drops to 145 units, place a reorder. Safety buffer of 41 units absorbs demand spikes during the 23-day lead time.
Available = 0
OUT OF STOCK
Available < Safety Stock
BELOW SAFETY STOCK
Available < Reorder Point
REORDER NOW
Days Cover < Lead Time x 1.5
REORDER SOON
Days Cover > 365
EXCESS STOCK
Normal coverage, velocity > 0
HEALTHY
Velocity = 0, no sales recorded
NO VELOCITY
Very low velocity, long-term declining
SLOW / DEAD STOCK
What each status means for the buyer
OUT OF STOCK: Zero available units. Every day without stock is lost sales and lost margin. Order immediately - no delay justified.
BELOW SAFETY STOCK: Units exist but you have dipped below your safety buffer. You are burning through insurance stock. Order urgently.
REORDER NOW: Stock has reached the planned trigger point. Place order as scheduled - normal urgency, not emergency.
REORDER SOON: Comfortable today but if you miss this buying cycle you risk a stockout. Prepare the order.
EXCESS STOCK: Over a year of cover. Capital is tied up. Do not reorder. Consider promotions or return to vendor.
HEALTHY: Good coverage with no action needed this cycle.
NO VELOCITY: No sales data. Do not order. Verify whether this SKU is actually active and being sold.
SLOW / DEAD STOCK: Very low and declining sales over a long period. Flag for clearance, price reduction, or phase-out decision.
A-class: 7-day review cycle | B-class: 14-day | C-class: 21-day
Fast-moving (>1/day): +10% | Medium (0.1-1/day): +20% | Slow (<0.1/day): +30%
OQ = CEIL(Velocity x (Lead_Time + Review_Cycle) x Buffer)
- Available - Open_PO_Qty
Result capped at 180 days of cover
Status = Phase-Out, Healthy, or Excess: OQ = 0
Critical status with OQ <= 0: force OQ = 1 x MOQ (minimum order quantity)
Breaking down the OQ formula
Review Cycle: How often you look at each class. A-class SKUs (high value) are reviewed every 7 days. You are ordering to cover Lead Time + Review Cycle days of demand.
Movement Profile: How fast a SKU sells. Fast = over 1 unit/day. Medium = 0.1-1/day. Slow = under 0.1/day. Slower movers get a larger buffer because their demand is harder to predict.
Buffer: The multiplier above 1.0 adds a safety margin. Medium = 1.20 means you order 20% more than the bare coverage window to absorb demand variance.
Netting open POs: Already-ordered stock is subtracted so you don't double-order.

Real example - AcuFast Needles .20x30 (AF.20x30):
Inputs Class: A | Velocity: 6.6/day
Lead Time: 14 days | Movement: Medium
Available: 0 units | Open PO: 0 units
OQ calculation Review Cycle (A) = 7 days
Buffer (Medium) = 1.20
OQ = CEIL(6.6 x (14 + 7) x 1.20) - 0 - 0
OQ = CEIL(6.6 x 21 x 1.20)
OQ = CEIL(166.3) = 167 units
Order 167 units. This covers 14-day lead time + 7-day review cycle + 20% demand buffer.
ComponentMax PtsDetail
Urgency (Status)40OOS=40 | Below SS=30 | Reorder Now=20 | Reorder Soon=10
Margin at Risk30(Margin at Risk / highest MAR in current dataset) x 30
ABC Class20A=20 | B=12 | C=5
Days Cover100d=10 | <7d=8 | <14d=6 | <30d=4
Score 85+
Order today
Score 60-84
Order this cycle
Score 35-59
Watch - monitor
How to read the priority score
Why a composite score? When 600 SKUs all need reordering, buyers need a ranked list. The score combines urgency + financial impact + strategic class + time pressure into one number.
Urgency (40 pts): Status alone drives the top of the score. An OOS A-class SKU scores at least 60 pts (40 urgency + 20 ABC) before MAR and days cover are even counted.
Margin at Risk (MAR$): Estimated gross profit at stake while the SKU is out or running low. Formula: daily gross margin x days exposed. Normalized against the highest MAR in the current dataset run - so a 30-point score means you have the highest financial exposure in today's list.
Dynamic denominator: The MAR normalization uses the current dataset's maximum, not a fixed number. This means scores shift slightly each run as the mix of at-risk SKUs changes.

Score 85+: Drop everything, order today. Most likely OOS or Below SS with high margin exposure.
Score 60-84: Handle in this buying cycle, don't skip it.
Score 35-59: Watch list - not urgent but keep an eye on it.
SKUs classified as Strong Seasonality or Moderate Seasonality only
Days of cover > days remaining in season AND fewer than 90 days remain in season?
Flag: Overstock Risk - reduce order quantity or defer to next season
What triggers the overstock check
Why only seasonal SKUs? A non-seasonal SKU with 200 days of cover is fine - it will sell through eventually. For a seasonal SKU, 200 days of cover in November means the stock will still be sitting there when the season ends and demand drops to near zero.
The 90-day window: The check activates when fewer than 90 days remain in the peak season. Before that, there is still enough time to sell through normally.
Seasonality classification: SKUs are classified as Strong Seasonality, Moderate Seasonality, Mild Seasonality, or Flat based on the month-over-month demand pattern across prior years.

Example: A winter heating pad SKU with 200 days of cover, checked in mid-November with 60 days left in the winter season. 200 > 60 and fewer than 90 days remain - Overstock Risk flag is set. Recommendation: do not order, or reduce qty significantly.
2 or more OOS events in the past 12 months? YES - Flag as Chronic OOS
Demand Spike / Planning Gap - recent velocity significantly exceeds historical model
Vendor Unreliable - high lead time variance (std dev >= 14 days) flagged in Phase 4
Insufficient PO History - too few POs to build a reliable Tier 1 lead time estimate
Safety Stock Too Low - service level may need review for this SKU
Chronic OOS vs. a one-off stockout
OOS event definition: Available = 0 during a period when the SKU historically sells at normal levels. A naturally slow month doesn't count - the context must show active demand.
Why 2+ events = Chronic? One stockout can be bad luck. Two or more in 12 months means the planning model is systematically failing for this SKU - something structural needs fixing.

Root cause matters for the fix:
Demand Spike: The model underestimated demand. Review velocity inputs and safety stock level.
Vendor Unreliable: Lead time variance too high. Talk to the vendor or qualify an alternate source.
Insufficient PO History: Lead time is falling back to Tier 3 or 4 (less accurate). Place more orders or update item master.
Safety Stock Too Low: Z-score or formula inputs need recalibration for this SKU's demand profile.
Priority Score (0-100) with action threshold band
Dynamic Order Quantity (units, net of available and open POs)
Margin at Risk ($) - potential gross margin loss from the current stock position
Plain-English Recommendation - generated from status, score and flags
OUT OF STOCK
BELOW SAFETY STOCK
REORDER NOW
REORDER SOON
HEALTHY
EXCESS STOCK
NO VELOCITY
SLOW / DEAD STOCK
What the buyer actually sees
Each SKU row in the dashboard shows its status badge, priority score, order qty, and a one-line recommendation. The buyer works down the sorted list by priority score, highest first.

Example recommendations:
OOS for 2 days. A-class. Order 108 units.
$3,200 margin at risk. Priority: 91.
Reorder point reached. A-class, fast moving.
Order 167 units. Priority: 72.
Healthy - 83 days of cover.
No action needed. Priority: 0.

Dashboard tab assignment: The tab a SKU lands in equals its status. Buyers typically start with the OOS tab (most urgent), work through Below Safety Stock, then Reorder Now, then Reorder Soon. Healthy and Excess are informational.
END - Output Delivered to Dashboard