Vive FBA Optimizer

How it works

How a run turns the forecast, today’s Odoo stock and the other inputs into SP, LTL and AWD units.

Overview

The planner thinks in days of cover. It takes each SKU’s daily rate, walks forward week by week (sell 7 days, add what arrives), and each shipping lane applies its own rule to that curve.

SP bridge
18 → 45 d
+ 7-day floor
LTL
45 → 75 d
trigger → target
AWD
34 → 60 d
trigger → target
B2B reserve
14 d
kept in the warehouse
  • Plan all is the only planning click. Emergency SP takes warehouse stock first, AWD fills from what is left at PA / CA / JX, LTL takes the rest.
  • Each lane is still saved as its own run, with its own manifest and files.
  • Numbers here are the defaults. Settings can change them; every run records the values it used.

1. Daily rate (TDR)

Every quantity starts from how many units a SKU sells on Amazon per day. The rate comes from Odoo’s FBA inbound forecast, pulled every Monday. No trend, no seasonality.

Odoo’s 30-day rate only counts days the SKU was in stock, so 20 units sold on a single in-stock day reads as 20 / day. The planner blends it toward the calendar rate when there are few in-stock days:

din=30−dOOSrcal=r30⋅din30c=min⁡ ⁣(din14, 1)r=c⋅r30+(1−c)⋅rcal \begin{aligned} d_{\text{in}} &= 30 - d_{\text{OOS}} \\[2pt] r_{\text{cal}} &= r_{30} \cdot \frac{d_{\text{in}}}{30} \\[2pt] c &= \min\!\left(\frac{d_{\text{in}}}{14},\, 1\right) \\[2pt] r &= c \cdot r_{30} + (1 - c)\cdot r_{\text{cal}} \end{aligned}

dOOSd_{\text{OOS}} = out-of-stock days in the last 30; r30r_{30} = Odoo’s 30-day rate. With 14+ in-stock days c=1c = 1 and the rate is Odoo’s figure unchanged.

If the 30-day rate is missing or zero, the first non-zero of these is used as is:

60-day rate→15-day rate→7-day rate→floor 0.02 / day
The 0.02 floor is a guess (typical of a new launch). Those SKUs are flagged for review — don’t treat that quantity as a forecast.

Never used as a rate: Amazon’s restock “recommended days”, or a B2B rate inferred from Amazon sales (B2B comes from Odoo warehouse pickings).

2. Coverage (days of inventory)

How long current stock lasts at the daily rate:

W0=units availablerW_0 = \frac{\text{units available}}{r}

Then it walks 14 weeks forward (8 on an AWD run). Each week burns 7 days and adds whatever arrives that week, also converted to days:

Wn=max⁡ ⁣(Wn−1+arriving unitsnr−7,  0)W_n = \max\!\left(W_{n-1} + \frac{\text{arriving units}_n}{r} - 7,\; 0\right)

Wn=0W_n = 0 means a projected stock-out by the end of week nn.

Coverage walk — 200 units, 10 / day, nothing inbound. LTL fires at week 14 and tops week 13 up to 75 days.
020406080LTL target · 75 daysLTL trigger · ≤ 45 days at W14W0: 20 days of cover20W0W1: 13 days of cover13W1W2: 6 days of cover6W2W3: 0 days of coverW3W4: 0 days of coverW4W5: 0 days of coverW5W6: 0 days of coverW6W7: 0 days of coverW7W8: 0 days of coverW8W9: 0 days of coverW9W10: 0 days of coverW10W11: 0 days of coverW11W12: 0 days of coverW12W13: 0 days of coverW13W14: 0 days of coverW14LTL: 75 − W13 (0) = 75 days → 10 × 75 = 750 units+75 days = 750 units

3. Stock already on the way

Stock already on a truck is credited, otherwise the planner would re-order it.

  • Odoo inbound shipments (pulled daily): arrival = created on+SP or LTL lead\text{created on} + \text{SP or LTL lead}.
  • No shipping type: treated as arriving now, unless it is more than 60 days late — then it is dropped.
  • Units to AWD come from Amazon’s AWD report and land in week 2.
  • Forecast stage buckets, for units with no shipment row:
StageMeaningCounts in
ReceivingAt the fulfilment centre, being checked inweek 1
ShippedLeft our warehouse, in transitweek 2
WorkingPlanned, not shipped — may never leaveweek 4

Late beats early: crediting too soon under-orders. Stages past the horizon are dropped, not squeezed into the last week.

4. Three lanes, three jobs

One click plans all three, in this order, so they never count the same coverage or the same shelf twice.

SP small parcelAWD Amazon WarehousingLTL freight to FBA
JobBridge to the next cheaper restockKeep AWD stockedRefill FBA
Looks atFBA cover, day 18 → next restockAWD’s own stock, trigger weekFBA cover at W14
Fires whenCover drops below 7 days in that windowWt∗≤34W_{t^*} \le 34W14≤45W_{14} \le 45
SendsJust enough to stay ≥ 7 days60−Wt∗60 - W_{t^*} days75−W1375 - W_{13} days
Horizon~45 days8 weeks14 weeks
AWD-eligible SKUsOwn emergency rule (§5)Only theseClosed

LTL — freight to FBA

LTL days={max⁡ ⁣(75−W13,  0)if W14≤450otherwiseunits=r⋅LTL days \text{LTL days} = \begin{cases} \max\!\left(75 - W_{13},\; 0\right) & \text{if } W_{14} \le 45 \\[2pt] 0 & \text{otherwise} \end{cases} \qquad \text{units} = r \cdot \text{LTL days}
  • Trigger on week 14, size from week 13: that is how the spreadsheet works. Turning off legacy compat in Settings sizes from week 14 instead.
  • A 120-day ceiling trims the order if current cover + new days would overshoot. An empty SKU is not affected.
Example (chart above) — 20 days on hand, 10 / day
W14=0≤45W_{14} = 0 \le 45 → fires. W13=0W_{13} = 0 → 75 days.
10×75=750 units10 \times 75 = \mathbf{750}\ \text{units}

SP — small parcel to FBA

SP is the expensive, fast lane. It is a bridge, not a refill: it keeps Amazon in stock until cheaper freight (or stock already on a truck) lands.

  1. Can SP get there in time? SP is fully received in 18 days. A stock-out before day 18 can’t be saved, so it doesn’t create SP units.
  2. Until when? Until the next restock that can hold the SKU: an inbound already coming, or a new LTL created today (received day 45).
  3. How much? Just enough that cover never drops below 7 days inside that window.
SP days=[ (tnext−tSP)⏟window  −  W(tSP)⏟cover left  +  7 ]+tSP=18,    tnext≤45 \text{SP days} = \Big[\,\underbrace{(t_{\text{next}} - t_{\text{SP}})}_{\text{window}} \;-\; \underbrace{W(t_{\text{SP}})}_{\text{cover left}} \;+\; 7\,\Big]^{+} \qquad t_{\text{SP}} = 18,\;\; t_{\text{next}} \le 45

With inbound landing inside the window, the engine walks the curve day by day and credits each arrival on its day — a partial inbound shortens the gap.

SP bridge — empty SKU, nothing inbound. SP covers the gap until freight lands, plus a 7-day floor.
Days 0–18: SP cannot arrive yet, so a stock-out here is not saved by SPtoo late for SPDays 18–45: SP bridges 27 days until LTL is receivedbridge · 27 days7-day safety floor on top of the bridge+7todaySP received · day 18LTL received · day 450d7d14d21d28d35d42d49d56dSP = 27 + 7 = 34 days → 340 units
Empty, nothing inbound
27−0+7=3427 - 0 + 7 = 34 days
10×34=34010 \times 34 = \mathbf{340}
10 days left at day 18
27−10+7=2427 - 10 + 7 = 24 days
10×24=24010 \times 24 = \mathbf{240}
Stock-out day 10, inbound day 18
SP can’t beat the inbound.
SP = 0
  • SP units then count as inbound on their arrival day, and LTL is sized on the updated curve.
  • Warehouse stock is applied later, at allocation: a short shelf limits what ships, it doesn’t change the need.
  • AWD-eligible SKUs use a different emergency SP (§5).

AWD — warehouse to Amazon Warehousing

AWD looks at AWD’s own stock (on hand + inbound to AWD), never FBA. It checks the week a new shipment would actually land:

t∗=⌈AWD inbound lead7⌉=⌈407⌉=6AWD days={max⁡ ⁣(60−Wt∗,  0)if Wt∗≤340otherwise t^* = \left\lceil \frac{\text{AWD inbound lead}}{7} \right\rceil = \left\lceil \frac{40}{7} \right\rceil = 6 \qquad \text{AWD days} = \begin{cases} \max\!\left(60 - W_{t^*},\; 0\right) & \text{if } W_{t^*} \le 34 \\[2pt] 0 & \text{otherwise} \end{cases}
AWD on hand 80, 50 inbound in week 2, 5 / day
W0=16,  W1=9,  W2=9+10−7=12,  …,  W6=0≤34W_0 = 16,\; W_1 = 9,\; W_2 = 9 + 10 - 7 = 12,\; \dots,\; W_6 = 0 \le 34
5×60=300 units5 \times 60 = \mathbf{300}\ \text{units}
  • Only SKUs on the AWD eligibility list; the rest are skipped on an AWD run.
  • No placement-fee bump (AWD isn’t charged it), but still a whole carton.

5. AWD-eligible SKUs

Eligibility comes from the awd_data upload. Once a SKU is eligible, AWD replenishes FBA — so sending freight to FBA as well would supply the same demand twice.

WarehousePA · CA · JX
→ 40 d
AWDAmazon Warehousing
→ 10 d
FBAcounts as cover
=
50 daysfull cycle
RuleWhat it means
LTL is closedFreight skips eligible SKUs; the AWD run replenishes them.
AWD isn’t instant FBAAWD on hand counts at FBA in week ⌈10/7⌉=2\lceil 10/7 \rceil = 2; inbound to AWD in week 4. A lag of 0 restores the old “AWD is FBA now” shortcut.
Already primedAWD on hand + inbound ≥ 25 days → no more AWD this run while migrating.
Fat FBAFBA cover (or FBA + receiving / shipped) > 80 days now → don’t park more in AWD.
Pallet cap (optional)Keeps the SKUs with the most potential revenue (rate × price or margin). Unmeasured SKUs don’t use the cap.
OriginsPA, CA, JX. Kansas is never an AWD origin but holds B2B stock. Caves only if ticked in Settings.

Migrating vs. settled

A newly eligible SKU has finished migrating only when both hold:

  • AWD on hand + inbound sits in the reorder band (34 – 60 days) and covers at least one inbound flight.
  • FBA cover, with AWD and inbound counted on their real arrival dates, never stocks out across the 50-day cycle.

Until then it is priming; after that, the normal 34 → 60 AWD rule applies.

Emergency SP for AWD SKUs

Not the 18 / 45 rule. It asks: counting FBA now, inbound that has actually left (never “working”), and AWD that can reach FBA in time, does cover fall too low in the ~20-day SP transit + 7-day buffer?

StateFires whenSends
Still migratingCover would drop below 7 daysThe shortfall up to 7 days
Migration completeProjected stock-out onlyUp to the 7-day buffer

B2B stock stays in the warehouse

AWD and FBA must not empty a building that also sells wholesale:

B2B reserve=⌈rB2B×14⌉\text{B2B reserve} = \left\lceil r_{\text{B2B}} \times 14 \right\rceil
  • rB2Br_{\text{B2B}} comes from the Monday Odoo pull — never from Amazon TDR.
  • Kansas stock counts toward the reserve first; only the rest is held at PA / CA / JX.
  • No B2B sales → no reserve.

6. From days to shippable units

units=⌈r×daysucarton⌉×ucarton\text{units} = \left\lceil \frac{r \times \text{days}}{u_{\text{carton}}} \right\rceil \times u_{\text{carton}}
  • Always rounded up — a short carton can’t ship. No carton spec → whole units.
  • FBA (SP, LTL): Amazon waives the placement fee at 5+ identical cartons. The planner may send a little extra to reach that, budgeted in days — default 0 (never over-send). AWD never bumps.
  • The SKU is then split across warehouses in legs: FBA legs aim for 5 cartons, AWD legs follow stock.

7. Ad-hoc requests

A listing manager can ask for units the forecast can’t know about — a promotion, a launch, a wholesale order. Their brief: How to raise an inbound request.

  • Always a floor: ship at least this many; a bigger forecast is kept.
  • Whole master cartons only; the form offers to round up.
  • A reason from a fixed list is required; the note is optional except for Other.
  • Ships SP only for the urgent part — the SKU’s own SP bridge, rounded up to whole cartons. The rest goes LTL, or AWD for an AWD SKU. A new launch, a test or Vine ask, a liquidation, or a SKU with no forecast ships no SP.
  • Nothing moves until a planner approves. A rejection always has a note.
  • Can override FBM Hold and Don’t Send after the LM confirms a warning. Can’t override Seller Central.
  • In the run and the weekly review, a SKU a request put on the plan is tagged LM request.
Openwaiting for a planner
→
Approvednext run applies it
→
Plannedunits on a manifest
→
Sentseen in Odoo inbound
  • Partially planned: stock covered only part of it (at least one closed carton); the note says how many units went. Cartons held by the B2B reserve aren’t counted.
  • Archiving the run puts planned requests back to approved, so the next plan picks them up.
  • A planner can leave a note without changing the status; the LM sees it on their request.

8. What never ships

Before any lane rule, a SKU can be blocked outright. Checked in this order:

#GateWhyRequest can override?
1FBM HoldFBM-only SKU; sending it to FBA is an errorYes, after a warning
2Seller Central restockAmazon doesn’t list it (only when that file is present)No
3Don’t SendASIN flagged — new launch, low stock, …Yes, after a warning

FBM Hold and Don’t Send are edited by listing managers and admins on Listing review; planners can look up any SKU there read-only.

Then the lane gates:

  • Not AWD-eligible → skipped on an AWD run.
  • AWD-eligible → skipped on an LTL run.
  • Fat FBA / already primed → no AWD.
  • FBA already covered → no emergency SP.

Daily inventory drops archived products, non-stock categories and zero or negative stock. Master cartons come from Odoo and decide every box count; specs are keyed by PO, and the oldest lot that covers the need boxes at that PO’s carton.

Default numbers

Built-in values. Settings can change any of them; each run records what it used.

WhatDefaultRole
LTL trigger / target45 → 75 daysFire at week 14; top up from week 13
SP bridge18 d → 45 d, 7 d floorCover from SP received until the next cheaper restock
AWD trigger / target34 → 60 daysChecked at the inbound-arrival week (40 d → W6)
AWD horizon8 weeksInbound plus the AWD → FBA transfer
AWD inbound lead40 daysWarehouse → AWD
AWD → FBA lag10 daysWhen AWD stock counts as FBA cover
Fat-FBA cap80 daysDon't prime AWD while FBA is already fat
AWD priming floor25 daysNo more AWD until migration completes
AWD emergency SP20 d lead, 7 d bufferBridge only; not the normal SP rule
B2B reserve14 daysFrom Odoo, never from TDR. No rate = no reserve
Coverage ceiling120 daysTrims an order that would overshoot
Carton bump0 daysNever over-send to chase the $0 fee
Rate floor0.02 / dayGuess for a SKU with no usable history
Inbound timingW1 / W2 / W4Receiving / shipped / working