Lead Time flow 2 — Inventory item lead time, and the Shopify push
This is the flow that decides what the customer is actually told. It takes the arrival date flow 1 wrote, combines it with stock on hand, stock on order, supplier stock and the product's supply type, and turns all of it into a sentence on the product page. It also decides whether the item can be ordered when it is out of stock.
Active. Verified against the live Celigo flow and all four saved searches on 2026-08-21. The bonded-warehouse change is confirmed deployed: every export now runs the script Lead Time: Inventory V3.0 Aug 2026 - bonded wh. Four defects have been fixed since this entry was first written —
LT2-D2,LT2-D3,LT2-D5andLT2-D9— and five remain open.
Where the LT- numbers map. The September 2026 rule set —
LT-001toLT-081, confirmed 2026-09-17 — is crosswalked onto registry rules in flow 1 → Confirmed rule set.
Rules & IDs
| Rule ID | Rule | Reading |
|---|---|---|
LI-BL-INV-011 |
Bonded stock covers the Sydney backorder before it can be promised | Business logic |
LI-BL-INV-006 |
The lead-time ladder, and the words the customer reads | Business logic |
LI-BL-INV-008 |
Whether an out-of-stock item can still be ordered | Business logic |
LI-BL-INV-009 |
Publishing to Shopify — product or variant | Business logic |
LI-BL-INV-011 runs first and rewrites the arrival date every other rule then reads, so it is
described before the ladder.
| What | Name in the system | |
|---|---|---|
| Celigo flow | 66e0e59d32b330462921d448 — Lead times: Inventory | open in integrator.io |
| Saved search — LocalNetSuite saved search | customsearch6212 — SCRIPT | LEAD TIMES | INVENTORY ITEMS | V2 - Sub-Matrix Local *live | open search 6212 |
| Saved search — ImportedNetSuite saved search | customsearch6186 — SCRIPT | LEAD TIMES | INVENTORY ITEMS | V2 - Sub-Matrix Imported *live | open search 6186 |
| Saved search — RugsNetSuite saved search | customsearch6220 — SCRIPT | LEAD TIMES | INVENTORY ITEMS | V2 - Sub-Matrix Rugs *live | open search 6220 |
| Saved search — Item SimpleNetSuite saved search | customsearch6221 — SCRIPT | LEAD TIMES | INVENTORY ITEMS | V2 - Simple *live | open search 6221 |
The NetSuite links use the account-neutral host, which redirects a signed-in user to this account. Ids and names are exact, so a search stays findable by name even if a link does not resolve.
Three readings of the same rules. Nothing is duplicated between them. Printing gives you the business reading followed by the diagrams.
What it does. It turns the arrival dates flow 1 recorded into the sentence a customer reads on the product page — how long the wait is, when new stock lands, and whether the item can be bought at all — and pushes that to Shopify.
Why it exists. Everything else in the chain is bookkeeping; this is the part the customer sees. A promise that is too short produces a late order and an apology. One that is too long loses the sale outright. This flow is where a date in NetSuite becomes the sentence someone reads before they spend money.
When it runs. It has no schedule of its own. Flow 1 starts it when flow 1 finishes — four times a day — whether or not flow 1 succeeded. A half-failed flow 1 still results in the storefront being updated.
What it looks at. Four separate lists of products, run one after another: Local, Imported, Rugs, and Item Simple. They are not slices of one list — they are four categories of product, each with its own list, all handled by exactly the same logic.
Who it affects. Customers read the result. Sales and showroom staff quote from it. Buying sees the consequences when a promise turns out to be wrong.
How it decides.
- Bonded stock is settled first: whatever the Sydney backorder does not swallow is spare, and the spare is what can honestly be promised.
- The product is then tested against a ladder of eight rungs, in order, and takes the first that fits — our own warehouse, then on order, then the supplier's stock, then made-to-order, and so on down.
- The wait is expressed as a band, never a date: one of twenty-three, from "2 - 3 days" to "44 - 48 weeks". Beyond forty-eight weeks it becomes "Please contact showroom for lead time".
- Where two arrival dates compete — ours and the supplier's — ours wins if they are within a week of each other, otherwise the earlier one does. A date more than a fortnight past is discarded.
- Three sentences come out of that: the in-stock message, the arrival window, and the out-of-stock message. Each is published separately.
- Whether an out-of-stock item can still be bought is decided separately from the wait, and is the more commercially dangerous of the two.
- Nothing is written unless something actually changed.
Outcomes. The three sentences and the quantities are updated and pushed to Shopify · the
product is skipped because nothing changed · the product is updated in NetSuite but never reaches
Shopify, because it has no Shopify id · no rung matches and the promise is left blank — defect
LT2-D6 · the whole run stops on one item with no supply type — defect LT2-D7.
Bonded stock on hand, and paying off the backorder first LI-BL-INV-011
Why it exists. Stock in the bonded warehouse in Vietnam is ours, but it is not sellable today — it has to cross the water and clear into Sydney first. Before this rule existed that stock was invisible: it could not shorten a promise, and a Sydney warehouse that was oversold published a negative on-order quantity straight to the storefront. This rule makes bonded stock count, but only for what it can honestly do.
Two separate jobs, and it is worth keeping them apart.
| Job | What it settles | Changed in V3.1? |
|---|---|---|
| Netting | How much bonded stock is genuinely spare, after paying off what we have already sold | No |
| The one missing date | Bonded stock on hand, which flow 1 structurally cannot see | Yes — this is all that is left of the old date calculation |
The two ideas behind netting.
- Bonded stock is never available now. It can shorten the arrival promise. It can never produce "Ships in 2 - 3 days".
- It pays off the backorder first. Sydney's on-order figure already has backorders netted out of it, so a negative figure means we have sold stock we do not have. Bonded stock covers that debt before any of it can be promised to a new customer.
How much bonded stock is spare.
| Step | What happens |
|---|---|
| 1 | Take Sydney's on-order figure. If it is negative, that is the shortfall — stock already sold and not covered |
| 2 | Pay the shortfall down with bonded stock on hand first, because it can move soonest |
| 3 | Pay any remainder down with bonded stock on order |
| 4 | Whatever bonded stock is left over is spare, and only that is promised to new customers |
| 5 | If a shortfall still remains after all of it, the item is oversold beyond what bonded can cover — nothing reports this, see defect LT2-D11 |
That spare figure is what the website's Quantity On Order is built from, and what allows bonded
stock to unlock backordering for supply types that would otherwise refuse it
(LI-BL-INV-008). None of it changed in V3.1.
What the Sydney figure already contains. The on-order number this starts from is NetSuite's own figure for the Sydney location, and it counts every inbound transfer order — including ones that have gone stale, and ones moving stock to a showroom. That is deliberate: the question the website's Quantity On Order answers is "how much is coming", not "how much is coming that we could promise". It is a different question from the one flow 1 asks when it picks an arrival date, which is why the two numbers can disagree on the same product without either being wrong.
The one arrival flow 1 cannot see. Flow 1 settles every arrival that has an order behind it — a Sydney purchase order, a bonded purchase order, a transfer order. It reads a report of open order lines, so anything without a line on that report is invisible to it.
Bonded stock sitting on hand with no transfer order raised yet is exactly that: a stock balance, not an order. It has no line, so flow 1 cannot date it. This rule contributes that one date, and nothing else:
| Source | Its date | Settled by |
|---|---|---|
| Sydney purchase order, transfer order, bonded purchase order | Flow 1's first arrival, taken as-is | Flow 1 |
| Bonded stock on hand, no transfer order | Today plus 35 days, recalculated every run so it rolls forward until a transfer order exists | This rule — but see below |
The earlier of the two becomes the date everything downstream uses. Only spare bonded stock may set a date — stock still covering the backorder is already promised to someone.
The customer-facing message reads the first arrival. Confirmed by the project owner on 2026-09-23. The three lead-time sentences and the dispatch band are all built from the arrival date this rule settles, and that date is meant to be the first arrival written by flow 1. Shopify runs no logic of its own — it displays the sentences as given. Because a stale first arrival is dropped and the second is promoted into its place, the message only ever has to read one field.
The code does not always honour this. Bonded stock on hand is allowed to beat the first arrival when it lands sooner, so on those items the message is built from a bonded estimate rather than from the first arrival — and the storefront then shows a different date from the one NetSuite holds. That is defect LT2-D17.
This contribution is legacy, and is being removed. The uplift here predates the first-arrival field, which now already accounts for bonded transit. On 2026-09-23 exactly one item held bonded stock available in Vietnam and it already carried a first arrival, so this path can only override a date flow 1 calculated correctly, never fill a gap. It is defect LT2-D17.
A consequence to settle. The confirmed rule that bonded stock on hand with no transfer order is dated at today plus thirty-five days then has no implementation anywhere: flow 1 reads a transaction search and bonded on-hand is a stock balance with no line on it. The rule would be dormant rather than wrong — it currently affects at most one item — but it should be a decision, not an accident.
The two dates can legitimately disagree, and that is not a fault. NetSuite's first-arrival field holds the next documented arrival. The date the customer reads is the next arrival of any kind. On an item with spare bonded stock on hand, the customer's date can be the earlier of the two. They answer different questions. Anyone comparing the product record against the website — customer service especially — needs to know that.
What changed on 2026-09-21. Until V3.1 this rule recalculated the arrival date from scratch and overwrote flow 1's answer. It did two things wrong doing so. It dropped flow 1's date whenever NetSuite's net location on-order was zero or below — a different measure from the one flow 1 uses, so correctly calculated dates were being blanked. And it added the 35-day transit to the raw bonded date a second time, on a field that deliberately includes stock already claimed by a transfer order — promising stock that was already spoken for. Both were removed. Flow 1's date is now passed through untouched.
Outcomes. The item carries the earlier of flow 1's date and a bonded-on-hand date · it carries flow 1's date unchanged, which is the common case · it carries a bonded-derived date when flow 1 found nothing sellable · it carries no date at all, and the customer is sent to the showroom.
The lead-time ladder, and the words the customer reads LI-BL-INV-006
The ladder. Each product is tested against these in order and takes the first one that fits. Nothing further is considered once a rung matches.
| Rung | If… | The promise becomes | Counted from |
|---|---|---|---|
| — | The product is In-Store Only and a showroom holds stock | "Available for in-store purchase in our … showroom" | Not a lead time at all |
| 1 | We have it in our own warehouse — Sydney only, never bonded | Ships in 2 - 3 days | Fixed |
| 2 | We have it on order — including unallocated bonded stock | The wait until it arrives | The resolved Sydney landing date from LI-BL-INV-011, not the purchase order's date |
| 3 | The supplier has it in stock, and has a stated in-stock lead time | That lead time | The supplier's standard |
| 4 | The supplier has it on order | The wait until the supplier receives it | The supplier's arrival date |
| 5 | It is Made To Order 1, with a stated lead time | That lead time | The supplier's standard |
| 6 | It is Made To Order 2, with a stated lead time | That lead time | The supplier's standard |
| 7 | It is End Of Line or Seasonal Only | "Please contact showroom for lead time" | — |
| 8 | The supplier has a stated out-of-stock lead time | That lead time | The supplier's standard |
| — | None of the above | Nothing is written — see defect LT2-D6 | — |
The last row is now a real rule, not a gap — changed 2026-09-23. Until that date three of the four conditions never rejected anything (
LT2-D21), so rung 8 fired for every product that got that far and "none of the above" was unreachable. A product with no lead time recorded anywhere was told "Please contact showroom for lead time" by accident. Both halves are now fixed: rungs 5, 6 and 8 genuinely check that a lead time exists, and a product matching nothing is given that same wording by rule. The customer sees no difference — that was the point, and it was measured across all 19,225 rows before either change shipped — but the ladder that runs is now the ladder written above.
A gap is reserved between rungs 1 and 2. The business has an open question about whether something belongs between "in our warehouse" and "on order" — showroom-only stock, or an item with one unit on hand and four on order, which today is quoted 2 - 3 days for the whole order. Until it is settled there is no rung there. It is numbered P2 in the project's own rule set, which is why that set counts nine priorities where this ladder shows eight.
The wait is always expressed as a band, never a date. A calculated number of weeks is rounded into one of twenty-three bands — "2 - 3 days", "1 - 2 weeks", … "44 - 48 weeks" — and anything beyond forty-eight weeks becomes "Please contact showroom for lead time".
Three sentences are produced for every product, and each is published separately:
| Sentence | Reads like | When the customer sees it |
|---|---|---|
| In-stock message | "Leaves our warehouse in 6 - 8 weeks." | Normally |
| Arrival-window message | "New stock arrives in our warehouse from 05/10/2026 - 12/10/2026." | When stock is on the way |
| Out-of-stock message | "Leaves our warehouse in 12 - 14 weeks." | When it is out of stock |
The arrival window is always the arrival date plus seven days — a one-week spread, not a real delivery estimate.
Whose warehouse the sentence names. If the supplier drop-ships, the wording becomes "our partners warehouse" instead of "our warehouse". Two brands are hard-coded by name:
- Ellison Studios — treated as not drop-ship, and any "our partners warehouse" wording is rewritten back to "our warehouse", so the customer is told the stock is ours.
- McMullin & Co. — see
LI-BL-INV-008.
Which arrival date wins. After LI-BL-INV-011 has settled ours, two remain: ours and the
supplier's.
| If… | Then… |
|---|---|
| Only one of the two exists | That one is used |
| The two are within a week of each other | Ours is used |
| The two are exactly the same day | Ours should be used. The supplier's is — defect LT2-D12 |
| Otherwise | The earlier of the two is used |
| A date is more than a fortnight in the past | It is discarded and treated as though it never existed |
| Neither exists | "Please contact showroom for lead time" |
The band and the sentence can describe different days. The wait band is always counted from our date, even on a product where the comparison above picked the supplier's. So a customer can read a dispatch band measured from one date and an arrival window quoting another. Defect
LT2-D13.
When nothing matches, say so — do not leave the last answer standing. A product that reaches
the bottom of the ladder, or an In-Store Only product with no showroom stock, should be told to
contact the showroom. Today the three sentences are simply left untouched in both cases, so the
product keeps whatever promise it was last given, however old. Defect LT2-D6, which covers both.
Which clock the dates are read on. Every date decision here — "is this more than a fortnight
past", "how many weeks until it lands", "is the supplier's ETA beyond seventy days", and the
bonded-on-hand estimate of today plus thirty-five — is meant to be made on the Australia/Sydney
date. The flow declares that timezone for its schedule, but the arithmetic inside it reads the
server's clock, which runs on UTC. Between 10am and midnight UTC the server is already on tomorrow's
date in Sydney, so those four decisions can land a day out. Flow 1
does this correctly; flow 2 does not. Defect LT2-D14.
Only real changes are written. Eight values are compared against what the product already carries — the three sentences, the dispatch band, the two Shopify quantities, the showroom total and the backorder flag. If any one differs, the product is written and pushed to Shopify. If none does, it is skipped entirely. On a full run around 5,300 products are examined and roughly a hundred are written.
Who signs a change off. The three sentences, the dispatch band and the arrival window are what a customer reads before deciding to buy. A change to any of that wording, or to how a date is chosen, is signed off by the customer service lead before it ships. This is a process rule, not something the code enforces — nothing in Celigo or NetSuite checks it, and the September 2026 changes to the Shopify push went in without it.
The arrival date is not one of the eight, and is never written back to NetSuite. Flow 2 calculates it, uses it for the wording, and sends it to Shopify — but the NetSuite field belongs to flow 1. Nor are the first and second arrival values the Shopify push now carries. A product whose only change is one of those never requalifies, so those metafields fill in as other things move rather than when they actually change. Defect
LT2-D15.
Whether an out-of-stock item can still be ordered LI-BL-INV-008
Separate from the lead time, and the more commercially dangerous of the two: this decides whether the storefront will let a customer buy something we do not currently have. Getting it wrong in one direction takes money for stock that may never come; in the other it refuses a sale we could have fulfilled.
| # | If… | Then… | Because |
|---|---|---|---|
| 1 | The second warehouse holds stock | Allowed, whatever else is true | Physical stock overrides every other consideration |
| 1a | Spare bonded stock exists, for a supply type that would otherwise be refused | Allowed | Since the bonded change, "on order" includes unallocated bonded stock, so stock in Vietnam can now unlock backorder where it previously could not |
| 2 | In-Store Only, nothing on order | Not allowed | It cannot be shipped at all |
| 3 | Drop Ship In-Stock Only, Seasonal Only or End Of Line, with nothing on order anywhere and no supplier stock | Not allowed | There is no path to fulfilling it |
| 4 | Drop Ship Seasonal Item with nothing on order anywhere | Not allowed | Same |
| 5 | Brand is McMullin & Co. and their stock is more than 70 days away | Not allowed | That brand's waits are long enough that the order would not be honoured in a reasonable time |
| 6 | Anything else | Allowed | Default is to take the order |
Publishing to Shopify — product or variant LI-BL-INV-009
Once NetSuite is updated, the same values go to the storefront. Each product takes one of two routes, and a product that fits neither is silently dropped.
| Route | Taken when | What is set |
|---|---|---|
| Variant | The item is marked as a variant, and has both a Shopify product and variant id | Nine values on that variant |
| Product | The item is marked as a product, and has a Shopify product id | The same nine values on the product |
| Neither | Anything else | Nothing is sent — the storefront keeps what it had |
Nine values are sent. Five have been there throughout — the three sentences, the on-order quantity and the warehouse on-hand quantity. Four were added on 2026-09-21 to carry the first and second arrival to the storefront, which is where the business expects sales to read them:
| Value | Source |
|---|---|
| The three sentences | Calculated here |
| On-order quantity | Calculated here, from the bonded netting in LI-BL-INV-011 |
| Warehouse on-hand quantity | Calculated here |
| First arrival date | The resolved date — flow 1's, or an earlier bonded-on-hand one |
| Second arrival date | Read straight from the saved search |
| First arrival quantity | Read straight from the saved search |
| Second arrival quantity | Read straight from the saved search |
Which searches carry the arrival values, and why two do not. The four saved searches behind this flow do not carry the same columns, and that is deliberate:
| Search | Catalogue | Arrival columns | Why |
|---|---|---|---|
| 6186 Imported | Goods we order into our own warehouse | ✅ | They have purchase orders behind them, so there is an arrival to report |
| 6221 Item Simple | Mixed — includes Life Interiors warehouse-stocked items | ✅ added 2026-09-21 | Its non-drop-ship items have real Sydney arrivals |
| 6220 Rugs | Rugs, which are ordered direct from the supplier | ❌ by design | Nothing is ordered into our warehouse, so there is no Life arrival to report |
| 6212 Local | Art prints, linen and similar, supplier-shipped | ❌ by design | Same reason — nothing is ordered into our warehouse |
A drop-ship item has no arrival, and that is the right answer. The absent columns are not a gap in those two searches; asking them for a Life arrival date would be asking the wrong question. What the customer waits on is the supplier's own lead time, which the ladder already handles.
NetSuite and Shopify must hold the same value. Confirmed by the project owner on 2026-09-22. The arrival metafields are internal visibility only — nothing on the storefront branches on them — so there is no reason for the two systems to differ, and NetSuite is the source of truth because it is written first.
| NetSuite holds | Shopify must hold |
|---|---|
| a date | that date |
| a quantity, including zero | that quantity |
| blank | blank |
Blank and zero both publish as nothing. Confirmed 2026-09-23. NetSuite distinguishes the two — the first-arrival quantity is null on 78,736 items and an explicit zero on 1,198 — and the distinction is real but is about provenance, not about the business answer:
| NetSuite | How it got there | Published to Shopify |
|---|---|---|
| null | No open inbound line has ever been in scope while the flow was running | metafield absent |
| zero | The item was in scope and the flow computed a clear | metafield absent |
Both mean nothing on order, which is what a customer or a salesperson needs to know, so carrying
the difference through to the storefront would show 0 on some items and nothing on others for no
reason either could name. It also removes 379 rows from the reconciliation that were never wrong.
Worked example:
421626Air Bedside Table (Oak Brown) has never had a purchase order and holds null.129586Air Bedside Table (Oak) has seven, all closed, the newest from April 2025, and also holds null.248034Abstract Console (Black) has six closed orders but was in scope while the flow ran, so it holds an explicit zero. All three publish nothing.
The rule covers all nine metafields, not only the four arrival ones. Confirmed 2026-09-23. The
on-order quantity, the warehouse quantity and the three sentences are held to the same standard.
Live gap found the same day: BE-ETH-AIR-VRNOAK holds 0 in NetSuite for the warehouse quantity
and has no metafield at all in Shopify, while every comparable item carries 0.
A negative is published as zero, and that is required rather than cosmetic. NetSuite's own
location figure is on order less backordered, so it goes negative when an item is oversold —
82169 Adele Armchair reads −1 today. That figure is an input this flow never writes. The
field it does write is clamped to zero before publishing, confirmed 2026-09-23 as necessary because
other calculations do arithmetic on it and a negative would propagate.
Blank and zero are genuinely different states: NetSuite stores 78,736 items with the 1st PO quantity null, 1,198 with an explicit zero and 1,503 above zero (verified 2026-09-23). So the rule can be honoured exactly rather than approximated.
How the two systems currently fail to match. The quantities are sent unconditionally, so an item with no arrival pushes an empty string into a whole-number metafield. The dates are wrapped in a presence test, which omits them when blank — and omitting is not clearing, so Shopify keeps a value NetSuite has already cleared. Both are defect LT2-D16, and the presence test is the wrong tool for the job: a blank quantity is
0, and a blank date needs the metafield deleted, because a date metafield cannot hold an empty value.
The date stays a date. Confirmed 2026-09-22 — the two arrival dates keep the Shopify
datetype rather than becoming text, so clearing one requires a delete rather than a blank value.
The warehouse quantity is not what the storefront sells against. It counts our own two warehouses and nothing else — no bonded stock, no showroom floor stock, no supplier stock. The quantity the customer can actually buy adds supplier on-hand on top, and is published through the inventory sync, not here. Two fields named
qty_available_whtherefore exist and hold different numbers: this one, and the NetSuite field, which means Life plus supplier. Anyone reading one and assuming the other will be wrong, and nothing in either system flags it.Confirmed as intended on 2026-09-23, and flagged as a concern to revisit — the project owner may rename one of the two so the names stop colliding. Until then, any reconciliation between NetSuite and Shopify must exclude this pair, or it reports every supplier-stocked item as a mismatch when both values are correct.
Change detection has no comparison for this metafield, nor for any of the four arrival values. An item whose sentences and quantities are all unchanged never requalifies, so those metafields fill in as stock moves rather than across the catalogue at once. See defect
LT2-D15.
Known defect — a product that fits neither route is discarded in silence. The router has a variant branch and a product branch and no default, so anything matching neither is dropped with no error and no log. This was first seen in August as
LT2-D2, when the Item Simple search did not return the Shopify type at all; that column was added and those products now publish. The mechanism was never fixed — only that one trigger for it. The live trigger today is an item with no Shopify id recorded in NetSuite. Measured 2026-09-23: 220 records a run are discarded this way. Most are items that genuinely are not on Shopify, which is the right outcome reached by the wrong mechanism — but 20 of them are live storefront products, and they lose every update, on every run, permanently. See defect LT2-D19.Two different fixes are needed and they should not be confused: a default branch that logs stops it being silent, and recording the missing Shopify ids stops it happening.
Nothing is ever read back from Shopify, and a failure is actively reported as a success. The storefront is written to and never compared, so a value changed in Shopify by hand is never noticed. Worse, a rejected write is not noticed either: Shopify answers a rejected metafield with HTTP 200 and the reason inside the response body, and neither import reads the body. A run can log hundreds of successes and have written nothing. See defect LT2-D18 — it is the reason no other defect in this chain can be measured until it is fixed.
Field registry
Every field this automation reads or writes, by the name it carries in the system — what it means, and what changes when it changes. Field ids are in the developer reading.
Inputs — what it reads
Values the automation looks at to make its decision. Change one of these and the decision changes.
| Field | What it means | What it changes | Status |
|---|---|---|---|
| Internal IDInventory Item | Which product this is. | Identifies the item the NetSuite update is applied to. | confirmed |
| Supply TypeInventory Item | Which supply arrangement the product is on. Buying maintains the list of valid types. | Selects the pricing of the promise — In-Store Only diverts to the showroom message, Made To Order 1 and 2, End Of Line and Seasonal Only each pick a different rung of the ladder. Also drives whether backorder is allowed. | confirmed |
| Brand - Life InteriorsInventory Item | Which brand Life Interiors sells this product under. | Two brands are special-cased by name — Ellison Studios has its wording rewritten to "our warehouse", and McMullin & Co. is denied backorder when its supplier date is more than 70 days out. | confirmed |
| Qty Available (Warehouse)Inventory Item | Capture the available quantity at this location, refreshed on a schedule rather than in real time. | Added to warehouse2 to give the on-hand total. Any on-hand stock at all short-circuits the ladder to "Ships in 2 - 3 days". | confirmed |
| needs confirmingInventory Item | needs confirming | Added to warehouse for the on-hand total, and on its own forces backorder to be allowed regardless of supply type. | needs confirming |
| needs confirmingInventory Item | needs confirming | The whole of the on-order total. Net of backordered quantity already. Decides whether the promise is built from the arrival date. | needs confirming |
| Next Available Receive DateInventory Item | When the next stock is expected in Sydney — the value flow 1 wrote. | No longer used as supplied. The bonded rule overwrites it in memory with a computed Sydney landing date before anything reads it, and the computed value is what gets written back to the item. | confirmed |
| Supplier Next Available Receive DateInventory Item | When the supplier expects their next stock. Only meaningful when the supplier has quantity on order. | The supplier's own arrival date. Competes with the Life date; the earlier one wins, with Life favoured on a tie inside a week. | confirmed |
| Supplier Quantity On HandInventory Item | The supplier's own stock on hand. Used for drop-ship items and local items from key suppliers. | Rung 4 of the ladder, and part of the quantity published to Shopify. | confirmed |
| Supplier Quantity On OrderInventory Item | The supplier's own stock on order. Used for local items from key suppliers. | Rung 5 of the ladder, and part of the on-order quantity published to Shopify. | confirmed |
| Drop ShipInventory Item | Whether this supplier ships straight to the customer. Drives both the courier choice and the wording of the lead-time message. | Switches the customer wording between "our warehouse" and "our partners warehouse". Overridden to false for Ellison Studios. | confirmed |
| Default In Stock Lead TimeInventory Item | The supplier's standard wait, in weeks, when they have stock. 0.3 means 2-3 days, 0.5 means 3-5 days, 0.7 means 5-7 days, 1 means 1-2 weeks. | Weeks used for rung 4. A zero disqualifies the rung entirely. | confirmed |
| Default Out Of Stock Lead TimeInventory Item | The supplier's standard production wait in weeks, buffer included. | Weeks used for the out-of-stock message, which is built for every item regardless of rung, and for rung 9. | confirmed |
| Default Made To Order 1 Lead TimeInventory Item | The supplier's standard made-to-order wait, in weeks. | Weeks used for rung 6. A zero disqualifies the rung. | confirmed |
| Default Made To Order 2 Lead TimeInventory Item | The supplier's second made-to-order wait, in weeks. | Weeks used for rung 7. A zero disqualifies the rung. | confirmed |
| Qty Available (Syd)Inventory Item | Stock on hand at the Sydney showroom. Refreshed on a schedule, so it is not real time. | Sydney showroom stock. Feeds the in-store message, the showroom total, and is written back unchanged. | confirmed |
| Qty Available (Mel)Inventory Item | Stock on hand at the Melbourne showroom. Refreshed on a schedule, so it is not real time. | Melbourne showroom stock. Same three uses as Sydney. | confirmed |
| Qty Available (Bris)Inventory Item | Stock on hand at the Brisbane showroom. Refreshed on a schedule, so it is not real time. | Brisbane showroom stock. Same three uses as Sydney. | confirmed |
| Qty Available (Gold Coast)Inventory Item | Stock on hand at the Gold Coast showroom. Refreshed on a schedule, so it is not real time. | Gold Coast showroom stock (location 24, Gold Coast Showroom - Miami). Named in the in-store message and, since the bonded change, included in the showroom total that decides whether an update is needed. | confirmed |
| Qty Available (Bonded Warehouse)Inventory Item | Stock on hand in the bonded warehouse in Vietnam. | Covers the Sydney backorder first. Whatever is left counts as on order, and dates its own arrival at 35 days from today. Returned as a real number by search 6186 only; the other three return it blank. | confirmed |
| needs confirmingInventory Item | Stock on order into the bonded warehouse in Vietnam. | Covers the Sydney backorder after bonded on-hand. Whatever is left counts as on order, and dates its arrival at its own receive date plus 35 days. Returned as a real number by search 6186 only. | needs confirming |
| Next Available Receive Date (Bonded WH)Inventory Item | When the next stock is expected to land in the bonded warehouse — the value flow 1 wrote. | The starting point for the bonded arrival estimate, plus 35 days of transit. Searches 6212, 6220 and 6221 do not return this column at all, so that estimate can never be produced for their items — see defect LT2-D9. | confirmed |
| ImportedInventory Item | Whether the item comes from an overseas supplier and is stocked and shipped from our own warehouse. | None. Returned by all four searches and never read. | confirmed |
| needs confirmingInventory Item | The product's id on the Shopify storefront. | Must be greater than zero or the item never reaches Shopify. Items carry "- None -" when they have no storefront presence. | confirmed |
| needs confirmingInventory Item | The variant's id on the Shopify storefront. | Required for the variant route. Absent or "- None -" sends the item down the product route instead. | confirmed |
| needs confirmingInventory Item | Whether this item is published to Shopify as a product or as a variant. | Chooses the Shopify route. Saved search 6221 does not return it at all, so its items match neither route and never reach Shopify — defect LT2-D2. | confirmed |
| Ships InInventory Item | The dispatch estimate the item currently carries. | One of the eleven comparisons that decide whether anything is written at all. | confirmed |
| In Stock Lead Time MessageInventory Item | The in-stock message the item currently carries. | Compared against the newly built message to decide whether to write. | confirmed |
| On Order Lead Time MessageInventory Item | The on-order message the item currently carries. | Compared against the newly built message to decide whether to write. | confirmed |
| Out Of Stock Lead Time MessageInventory Item | The out-of-stock message the item currently carries. | Compared against the newly built message to decide whether to write. | confirmed |
| Qty Available To Sell On WebsiteInventory Item | The website-available quantity the item currently carries. | Compared twice, against two different totals that cannot both match — see defect LT2-D4. | confirmed |
| Qty On Order Available To Sell On WebsiteInventory Item | The website on-order quantity the item currently carries. | Compared twice, against two different totals that cannot both match — see defect LT2-D4. | confirmed |
| needs confirmingInventory Item | needs confirming | Compared against Sydney + Melbourne + Brisbane showroom stock. Gold Coast is left out of that sum — see defect LT2-D5. | needs confirming |
| Shopify Enable Out Of Stock SellingInventory Item | Whether the storefront currently lets this be bought out of stock. | Compared against the newly derived backorder decision. | confirmed |
| Next Available Receive DateInventory Item | The arrival date the item currently carries. | None any more. The bonded change removed it from the comparison set, and search 6186 no longer returns it — so a changed arrival date no longer causes a write on its own. See defect LT2-D8. | confirmed |
Outputs — what it writes
Values the automation puts back. Everything downstream of this rule reads them, so a wrong value here travels.
| Field | What it means | What it changes | Status |
|---|---|---|---|
| Qty Available (Syd)Inventory Item | Stock on hand at the Sydney showroom. Refreshed on a schedule, so it is not real time. | Sydney showroom stock. Feeds the in-store message, the showroom total, and is written back unchanged. | confirmed |
| Qty Available (Mel)Inventory Item | Stock on hand at the Melbourne showroom. Refreshed on a schedule, so it is not real time. | Melbourne showroom stock. Same three uses as Sydney. | confirmed |
| Qty Available (Bris)Inventory Item | Stock on hand at the Brisbane showroom. Refreshed on a schedule, so it is not real time. | Brisbane showroom stock. Same three uses as Sydney. | confirmed |
| Qty Available (Gold Coast)Inventory Item | Stock on hand at the Gold Coast showroom. Refreshed on a schedule, so it is not real time. | Gold Coast showroom stock (location 24, Gold Coast Showroom - Miami). Named in the in-store message and, since the bonded change, included in the showroom total that decides whether an update is needed. | confirmed |
| Ships InInventory Item | The dispatch estimate. If the item is in stock it dispatches in a couple of days; otherwise this shows the order's estimated arrival. | The headline promise. Not itself sent to Shopify, but it is what the messages are built from. | confirmed |
| In Stock Lead Time MessageInventory Item | The in-stock lead time across our warehouses and the supplier's. Falls back to the out-of-stock wording when there is nothing in stock. | Published to Shopify as the in-stock lead time message. | confirmed |
| On Order Lead Time MessageInventory Item | The on-order lead time across our warehouses and the supplier's. Falls back to the out-of-stock wording when there is nothing on order. | Published to Shopify as the on-order lead time message. The window is always the arrival date plus seven days. | confirmed |
| Out Of Stock Lead Time MessageInventory Item | The out-of-stock lead time across our warehouses and the supplier's. | Published to Shopify. Built for every item from the supplier's out-of-stock lead time, independently of which rung the item landed on. | confirmed |
| Next Available Receive DateInventory Item | When the next stock is expected in Sydney. | Written back by this flow as well as flow 1, but no longer with the same meaning — flow 1 writes the purchase order's date, this flow now writes a computed date on which stock lands in Sydney. Two flows own one field and disagree about what it means. See defect LT2-D8. | confirmed |
| Qty Available To Sell On WebsiteInventory Item | Quantity available to sell, from our warehouses plus the supplier's stock on hand. This is what Shopify shows as available. | Life on-hand plus supplier on-hand. This is the quantity published to Shopify as available. | confirmed |
| Qty On Order Available To Sell On WebsiteInventory Item | Quantity on order available to sell, from our warehouses plus the supplier's. This is what syncs to Shopify as on order. | Life on-order plus supplier on-order. Published to Shopify as the on-order quantity. | confirmed |
| Qty Available (Warehouse)Inventory Item | Capture the available quantity at this location, refreshed on a schedule rather than in real time. | Life on-hand only, without the supplier's. | confirmed |
| Qty Available (Syd)Inventory Item | Stock on hand at the Sydney showroom. Refreshed on a schedule, so it is not real time. | Sydney showroom stock, written back unchanged. | confirmed |
| Qty Available (Mel)Inventory Item | Stock on hand at the Melbourne showroom. Refreshed on a schedule, so it is not real time. | Melbourne showroom stock, written back unchanged. | confirmed |
| Qty Available (Bris)Inventory Item | Stock on hand at the Brisbane showroom. Refreshed on a schedule, so it is not real time. | Brisbane showroom stock, written back unchanged. | confirmed |
| Qty Available (Gold Coast)Inventory Item | Stock on hand at the Gold Coast showroom. Refreshed on a schedule, so it is not real time. | Gold Coast showroom stock, written back unchanged. | confirmed |
| Shopify Enable Out Of Stock SellingInventory Item | Whether the storefront lets a customer buy this item when it is out of stock. | Whether the storefront lets a customer order this item when it is out of stock. | confirmed |
| needs confirmingShopify product / variant metafield | The in-stock lead time the customer reads on the product page. | Set from the NetSuite in-stock message. Never read back, so Shopify is never compared against NetSuite. | confirmed |
| needs confirmingShopify product / variant metafield | The arrival window the customer reads when stock is on the way. | Set from the NetSuite arrival-window message. | confirmed |
| needs confirmingShopify product / variant metafield | What the customer reads when the item is out of stock. | Set from the NetSuite out-of-stock message. | confirmed |
| needs confirmingShopify product / variant metafield | How many units are on order, as the storefront sees it. | Life on-order plus supplier on-order. | confirmed |
| Qty Available WarehouseShopify product / variant metafield | How many units are on hand in our own two warehouses, and nowhere else. | Life warehouse on-hand only. Excludes bonded stock, showroom floor stock and supplier stock, so it is deliberately not the quantity the storefront sells against. Two traps follow from that. It is not the same number as the available quantity published to Shopify, which adds supplier on-hand on top. And the NetSuite field of the same name, custitem_qty_available_wh, carries the NetSuite meaning of Life plus supplier — the two fields share a name and disagree by design. Change detection has no comparison for this metafield, so it populates as stock moves rather than all at once. | confirmed |
Inputs — the four saved searches
What it reads, and where from.
| Export | Saved search | Covers |
|---|---|---|
| Lead Time V2: Export Inventory - Local | 6212 | Locally-held stock |
| Lead Time V2: Export Inventory - Imported | 6186 | Imported stock |
| Lead Time V2: Export Inventory - Rugs | 6220 | Rugs |
| Lead Time V2: Export Inventory Item - Simple | 6221 | Simple items |
Run sequentially, not in parallel. All four are item searches and all four run the same
preSavePage hook, but they no longer return the same columns. Verified against the live
searches on 2026-08-18:
All four now return the same columns. That was not true when this entry was first written — on
2026-08-18 only the Imported search carried the bonded columns, and Item Simple did not return
shopifyItemType at all. Both gaps were closed on 2026-08-21 and re-verified live:
| Column | 6186 Imported | 6212 Local | 6220 Rugs | 6221 Item Simple |
|---|---|---|---|---|
new_receiveDate_bonded |
✅ | ✅ | ✅ | ✅ |
qtyAvailable_bonded / qtyOnOrder_bonded |
✅ | ✅ | ✅ | ✅ |
shopifyItemType |
✅ | ✅ | ✅ | ✅ |
current_receiveDate |
dropped | dropped | dropped | dropped |
current_receiveDate was dropped from all four searches, matching the script no longer comparing
it. Every field is listed in the field registry above.
A note for anyone re-verifying this. Reading these searches through a NetSuite API returns internal ids for
supplyType,brandandcurrent_shipsIn—"9","119","23". Celigo receives the display text —"Drop Ship Item","Ethnicraft","Ships in 12 - 14 weeks"— which is what the logic compares against. Do not conclude from an API sample that the text comparisons are dead code; they are not.
Processing — LI-BL-INV-006
What it does with that, step by step.
Hand-written and language-neutral per CONVENTIONS §3.
for each item in the page:
net the bonded warehouse against Sydney's backorder: -- LI-BL-INV-011
shortfall = Sydney's on-order figure, if negative
pay it down with bonded on-hand first, then bonded on-order
what is left of each is spare; a shortfall that survives is
recorded as uncovered and then discarded
resolve when stock can be in Sydney: -- LI-BL-INV-011
Sydney has stock on order -> its own arrival date, no transit added
spare bonded on hand -> today plus the transit allowance
spare bonded on order -> its bonded date plus the transit allowance
take the earliest of whichever of those apply; if none apply, no date
this replaces the arrival date for everything below
decide the drop-ship wording:
supplier drop-ships -> "our partners warehouse"
otherwise -> "our warehouse"
brand is Ellison Studios -> force "our warehouse"
settle the arrival date:
discard either date if it is more than a fortnight in the past
neither date left -> no arrival date
only one left -> use it
within a week of each other -> use ours
otherwise -> use the earlier
on-hand total = warehouse + warehouse 2 -- bonded deliberately excluded
on-order total = Sydney's on-order, floored at zero
+ spare bonded on hand + spare bonded on order
build the out-of-stock sentence from the supplier's out-of-stock lead time
(done for every item, whatever rung it lands on)
if supply type is In-Store Only:
any showroom holds stock -> in-store message, naming those showrooms
no showroom holds stock -> leave all three sentences unset
otherwise walk the ladder, first match wins:
on-hand > 0 -> ships in 2 - 3 days
on-order > 0 -> weeks from today to the arrival date
supplier on-hand + stated
in-stock lead time -> that lead time
supplier on-order -> weeks from today to the supplier's date
Made To Order 1 + stated time -> that lead time
Made To Order 2 + stated time -> that lead time
End Of Line or Seasonal Only -> contact showroom
stated out-of-stock lead time -> that lead time
no rung matched -> nothing set
turn the number of weeks into a band, and the band into a sentence
compare eight values against what the item already carries
any one differs -> mark for update
none differs -> skip the item entirely
(neither arrival date nor either arrival quantity is one of them -- LT2-D15)
The block above now matches production, as of 2026-09-23. Two lines did not until that day, and both are recorded here because the gap is the sort that returns:
- The guards on Made To Order 1, Made To Order 2 and out-of-stock lead time compared text to a number and so never rejected anything (
LT2-D21, fixed 06:24 UTC). Every value arrives from the saved search as text, so"0"was never equal to0.- "no rung matched → nothing set" is no longer a dead end: a final fallback sets the band and the two sentences to "Please contact showroom for lead time" (
LT2-D6, fixed 06:13 UTC). It also runs before the Ellison rewrite, which is what makesLT2-D20unreachable.
Verification against production
Everything in this chain by name. Ids live in links: and Source references. Using an id in a
ticket is fine; using one in conversation is how the last round of confusion started.
| Layer | Name |
|---|---|
| Celigo flow | Lead times: Inventory |
| Schedule | none of its own — schedule: "". It runs only because flow 1 starts it, so its six-times-a-day cadence is inherited, not configured here |
| preSavePage script | Lead Time: Inventory V3.1 Sep 2026 - bonded wh — one script, shared by all four exports. The code was replaced in place on 2026-09-23 and the record still carries the V3.1 name while holding the V3.2 catch-all. Replacing in place was right — all four exports point at this record, so nothing needed re-wiring — but the name now understates what is deployed. Cosmetic, and worth correcting |
| Export 1 → search | Lead Time V2: Export Inventory - Local → SCRIPT | LEAD TIMES | INVENTORY ITEMS | V2 - Sub-Matrix Local *live (6212) |
| Export 2 → search | Lead Time V2: Export Inventory - Imported → … V2 - Sub-Matrix Imported *live (6186) |
| Export 3 → search | Lead Time V2: Export Inventory - Rugs → … V2 - Sub-Matrix Rugs *live (6220) |
| Export 4 → search | Lead Time V2: Export Inventory Item - Simple → … V2 - Simple *live (6221) |
| Import — NetSuite | Lead Time V2: Import Inventory Data — 12 fields |
| Import — Shopify, variant branch | Lead Time V2: Update Shopify Variant Metafields |
| Import — Shopify, product branch | Lead Time V2: Update Shopify Product Metafields |
| Then starts | the Kits flow |
The four exports run sequentially, in the order above.
Run-level validation, 2026-09-23. The first time this chain was checked at the job level rather than by reading configuration. One full pass, 02:06 → 03:05 Australia/Sydney.
| Export | Records | NetSuite written | Shopify variant | Shopify product | Reached NetSuite, not Shopify |
|---|---|---|---|---|---|
| Local | 11,009 | 423 | 251 | 1 | 171 |
| Imported | 5,223 | 88 | 53 | 0 | 35 |
| Rugs | 2,159 | 368 | 365 | 0 | 3 |
| Item Simple | 834 | 34 | 0 | 23 | 11 |
| Total | 19,225 | 913 | 669 | 24 | 220 — 24% |
Zero errors on every step, and zero open errors on the flow. That is not evidence of health:
LT2-D18 means a rejected Shopify write is recorded as a success, so this chain cannot report a
metafield failure at all. The 220-record gap is LT2-D19.
| Checked | Result |
|---|---|
| Script health | Six consecutive runs, no exception thrown. The JavaScript is not the problem in this chain |
| Values arrive as text, not numbers | ✅ confirmed from live runs of searches 6220 and 6221 — "0", ".5", ".7", blanks as "". This is what makes LT2-D21 real |
| Supply type arrives as display text | ✅ "Drop Ship Seasonal Item", "In-store Only" — not an internal id |
| Item Simple carries the arrival columns | ✅ confirmed live, correcting an earlier reading taken from a cached sample |
| Local and Rugs omit them | ✅ Rugs confirmed live; Local not re-run (the search exceeds the 4,000-row limit available to this check). Both are intentional, per the project owner |
| Shopify partial-write behaviour | ✅ a rejected metafield does not lose the rest of the payload — read back from a Rugs variant |
| Router replay | Item Simple 366 of 833 records match no branch; Rugs 9 of 2,159 |
Logic replay, 2026-09-23 — complete coverage. The live script, fetched from Celigo and verified byte-identical to the deployed copy, run over every row of all four searches with each computed value diffed against what NetSuite holds. This is the test that checks the logic rather than the plumbing. Read-only; nothing was written anywhere.
| Search | Rows replayed | Exceptions | Would be written | Ladder fell through |
|---|---|---|---|---|
… V2 - Sub-Matrix Local *live (6212) |
11,009 | 0 | 29 | 10 rows / 5 products |
… V2 - Sub-Matrix Imported *live (6186) |
5,223 | 0 | 29 | 0 |
… V2 - Sub-Matrix Rugs *live (6220) |
2,159 | 0 | 0 | 0 |
… V2 - Simple *live (6221) |
834 | 0 | 3 | 2 |
| Total | 19,225 | 0 | 61 | 12 rows / 7 products |
The row counts match the flow's own export job counts exactly, search for search, so the replay covered the same population a live pass does.
The ladder reproduces production. 19,225 rows × 7 compared values = 134,575 comparisons, of which 100 differ — 99.93% agreement. Every one of the 100 was traced to a cause, and none is a logic defect:
| Differences | Distinct products | Cause | Verdict |
|---|---|---|---|
| 39 | 34 | Quantity drift. Stock was received between the 02:06 run and the 04:15 read, so on-order fell. NetSuite is higher than computed in every single case, never lower — exactly the signature receipts produce | Expected. Corrects on the next run |
| 37 | 9 | Supply changed after the run. Four are Arcola Outdoor Side Tables created today, still draft, seeded with placeholder wording and never yet touched by this flow. The other five had supplier quantities or arrival dates update after the run |
Expected. Corrects on the next run |
| 24 | 7 | LT2-D6 — In-Store Only with no showroom stock |
Genuine defect |
LT2-D6 at full scale: seven products, named. All are In-Store Only with all four showrooms at
zero, and all compute nothing for the dispatch band, the in-stock sentence and the on-order
sentence:
| Item | Product | Search |
|---|---|---|
173783 |
Danica Pot (Tangerine, Large) | Local |
173797 |
Palina Candle Holder (Mint, Small) | Local |
182372 |
Fiddle Leaf Plant (98cm) | Local |
190782 |
Floral Interiors Anthurium Stem (Blush) | Local |
375674 |
Pomponette Vase (Amber) | Local |
173803 |
Syngonium Batik Leaf Stem | Simple |
235919 |
Kinfolk: Islands Book | Simple |
That is the whole live population of this defect — seven products out of 19,225 rows. NetSuite
holds - None - for their in-stock message. Only the out-of-stock sentence is set, because that one
is built for every item regardless of rung.
One methodological trap, recorded because it nearly produced four false findings. The saved search returns internal ids for list fields —
supplyTypeas"6",brandas"109",current_shipsInas"23"— while Celigo receives display text. Replaying the raw ids made the script take different branches from production and reported 100% of items as changed, an In-Store Only item taking the wrong route, and 38% of backorder flags wrong. All four were artefacts of the data source. Resolving the ids against their custom lists first — 155 for supply type, 83 for brand,CUSTOMLIST_SHIPS_INfor the band — dropped every one of them to zero. Anyone repeating this must resolve first, or they will chase ghosts.
How to repeat it. The searches exceed the 4,000-row limit on a single ad-hoc run, and the underlying API caps a page at 1,000, so Local needs 12 calls and Imported 6, paged on an explicit row range. That is the only reason this had not been run before.
Fixing LT2-D6, and what it unlocks — measured, 2026-09-23. The replay was re-run with the
three broken guards (LT2-D21) corrected and nothing else changed, to size the fix before
anyone writes it.
| Scenario | Today | Guards fixed, no catch-all | Guards fixed + catch-all |
|---|---|---|---|
| 551 rows — no stock anywhere, no supplier lead times | "Please contact showroom for lead time." — by accident, because the broken guard lets the last rung fire with a zero lead time and no band matches | Nothing set ❌ | "Please contact showroom for lead time." — by rule ✅ |
| 12 rows / 7 products — In-Store Only, no showroom stock | Nothing set ❌ | Nothing set ❌ | "Please contact showroom for lead time." ✅ |
| The other 18,662 rows | Correct | Correct | Unchanged ✅ |
All 551 rows already produce exactly that sentence today. So adding a final catch-all changes what no customer sees — it only changes how the answer is reached, from an accident of a broken comparison to a stated rule. That makes it about as safe a change as this chain allows.
The fix is one block, and it closes three defects at once. After the In-Store Only branch and the ladder, before the brand rewrite: if no sentence was set, set all three to the contact-showroom wording. Then
LT2-D6closes — the 7 products get a promise instead of a blank page;LT2-D21becomes safe to fix — the 551 keep their wording instead of losing it;LT2-D20is permanently defused — the brand rewrite can no longer meet an unset sentence.
Order matters: the catch-all must ship first or together with the guard fix, never after.
Deployed 2026-09-23, 06:13 UTC, and verified in production — see LT2-D6. The change is a single inserted block — one
if, three assignments — with nothing else in the script edited, and it was replayed over all
19,225 rows before being handed over:
| Version | Rows | Exceptions | Items left with no promise | Items flagged for update | Output differs from live |
|---|---|---|---|---|---|
| V3.1, as deployed | 19,225 | 0 | 12 | 61 | — |
| + catch-all | 19,225 | 0 | 0 | 61 | 7 items |
| + catch-all and the three guards corrected | 19,225 | 0 | 0 | 61 | 7 items |
Two things to read off that table. First, exactly seven items change and they are the seven
LT2-D6 products, each going from three blank fields to the contact-showroom wording; the flagged
count is unchanged, so no extra writes are created. Second, the last two rows are identical —
once the catch-all is in, correcting the three guards changes nothing at all. That is the evidence
for shipping them in that order: the risky change becomes a no-op behind the safe one.
What the replay does not prove. It confirms the script turns its inputs into the right
outputs. It says nothing about whether those outputs reach Shopify — that is LT2-D15, LT2-D18
and LT2-D19, none of which the script is responsible for. The logic is sound; the delivery is
not.
Where this chain stands — 2026-09-23
Read this before the defect table. Two fixes shipped on 2026-09-23 and the table below is long enough that the live picture is easy to lose in it.
The script is not the problem. It was replayed over all 19,225 rows of all four searches with every computed value diffed against NetSuite: zero exceptions, 99.93% agreement, and every one of the 100 differences traced to stock movement or a known defect. Everything still open is in the exports, the imports or the router.
| Defect | What it costs | State |
|---|---|---|
LT2-D18 a rejected Shopify write is logged as a success |
Every Shopify failure in this chain is invisible. Blocks verification of everything else | 🔴 Live |
LT2-D19 the router drops a record with no Shopify id, silently |
220 records a run; 20 live storefront products never update | 🔴 Live |
LT2-D15 the four arrival values have no change detection |
1,374 items hold arrival data NetSuite has and Shopify never received | 🔴 Live |
LT2-D16 the two arrival quantities are sent unguarded |
Rejected on every run for Local and Rugs; invisible because of LT2-D18 |
🔴 Live |
LT2-D11 the oversold figure is computed then discarded |
The clearest oversold signal available is thrown away | 🟠 Live, low |
LT2-D12 / LT2-D13 tie-breaks and mismatched date bases |
Wrong warehouse named on tied dates | 🟠 Live, low |
LT2-D14 date maths on the server clock, not Sydney's |
Off-by-one near the day boundary | 🟠 Live, low |
LT2-D10 / LT2-D17 the legacy 35-day uplift |
Dormant — one item holds bonded stock and it already has an arrival | 🟡 Dormant |
LT2-D22 the McMullin 70-day rule never fires |
Fixed — now evaluated on all 115 McMullin rows; denies none today, will deny the first long ETA | ✅ Fixed |
LT2-D7 a missing supply type stops the run |
Latent — needs the column absent, not the value. 193 blank values replayed cleanly | 🟡 Latent |
LT2-D20 the Ellison rewrite is unguarded |
Unreachable by construction since the fallback shipped | ✅ Neutralised |
LT2-D6 a product with no matching rung got no promise |
Fixed 06:13 UTC, verified on 7 products and in Shopify | ✅ Fixed |
LT2-D21 three ladder guards compared text to a number |
Fixed 06:24 UTC, verified as a no-op across 19,225 rows | ✅ Fixed |
If you fix one thing next, fix LT2-D18. Not because it is the largest — LT2-D15 is — but
because until a rejected write raises an error, no other fix in this chain can be confirmed to
have worked.
Decision tree — LI-BL-INV-006
The same logic as a path through the decisions, in the order they run.
The single most-asked question about this chain is "why does this product say that?". Read it top to bottom and stop at the first match — that is exactly how the code runs.
Step 1 — which route?
item
├─ supply type = "In-store Only"
│ ├─ any showroom holds stock ? ──► in-store message, naming those showrooms
│ └─ no showroom holds stock ? ──► falls to the FALLBACK below
└─ anything else ──► walk the ladder (step 2)
Step 2 — the ladder. First match wins; nothing below it is considered.
| # | Fires when | Promise the customer reads | Notes |
|---|---|---|---|
| P1 | Our warehouse has stock | "Ships in 2 - 3 days" | Warehouse + warehouse 2. Bonded deliberately excluded |
| P3 | Our warehouse has stock on order | Weeks from today to the arrival date | Uses the first arrival from flow 1 |
| P4 | Supplier has stock and a stated in-stock lead time | That lead time | The only guard of the four written correctly |
| P5 | Supplier has stock on order | Weeks from today to the supplier's date | |
| P6 | Supply type contains "Made To Order 1" and a lead time is recorded | That lead time | Guard corrected 2026-09-23 |
| P7 | Supply type contains "Made To Order 2" and a lead time is recorded | That lead time | Guard corrected 2026-09-23 |
| P8 | Supply type is End Of Line or Seasonal Only | "Please contact showroom for lead time" | Exact match, so Drop Ship Seasonal Item does not land here |
| P9 | An out-of-stock lead time is recorded | That lead time | Guard corrected 2026-09-23. Was an unintended catch-all before that |
| Fallback | Nothing above matched | "Please contact showroom for lead time" | Added 2026-09-23. Also covers In-Store Only with no showroom stock |
There is no P2. The numbering follows the code, which never had one.
Step 3 — after the ladder, for every item:
FALLBACK nothing set yet ? -> band and both sentences become
"Please contact showroom for lead time"
out-of-stock sentence built for EVERY item, whatever rung fired
brand = Ellison Studios rewrite "our partners warehouse" -> "our warehouse"
└─ still unguarded, but the FALLBACK above
guarantees it never meets an unset value
append a full stop to each sentence that is set
└─ the band never gets one: it must match the
"Ships In" list value exactly
Step 4 — is it worth writing? Eight values are compared against what the item already holds: the three sentences, the dispatch band, available quantity, on-order quantity, the showroom total, and the backorder flag.
any of the eight differs ? ──► write NetSuite, then route to Shopify
none differs ? ──► skip entirely
The four arrival values are not in that comparison — so a product whose only change is a new
arrival date or quantity is never written to Shopify. That is LT2-D15, the largest defect here.
Step 5 — which way to Shopify?
record
├─ has product id AND variant id AND type = "variant" ──► variant metafields
├─ has product id AND type = "product" ──► product metafields
└─ neither ──► DISCARDED, silently, no error ← LT2-D19
Where to start when a product looks wrong
| Symptom | Look at |
|---|---|
| NetSuite and Shopify disagree on an arrival date or quantity | LT2-D15 first, then LT2-D16 |
| NetSuite and Shopify disagree on everything | LT2-D19 — does the item have a Shopify id? |
| A product page shows no lead time at all | Was LT2-D6, fixed 2026-09-23. If it recurs, the fallback is not running — check the script is still V3.3 |
| The message names the supplier's warehouse when it should name ours | LT2-D12 — were the two dates on the same day? |
| The date in the message moves later every single day | LT2-D10 — does it have bonded stock on hand? |
| The whole run stopped | LT2-D7 (no supply type) or LT2-D20 (Ellison, no sentence) |
| It all looks fine but nothing is reaching Shopify | LT2-D18 — the dashboard cannot tell you it failed |
Outputs & side effects
What it writes, and who reads it afterwards.
| Output | Written to | Downstream consumer |
|---|---|---|
| Dispatch band, three sentences, arrival date, five quantities, backorder flag | NetSuite inventoryitem, matched on internal id |
Shopify push; flow 3, whenever it next runs |
Nine metafields in namespace custom |
Shopify product or variant, via GraphQL. A record matching neither route is discarded — LT2-D19 |
The customer, on the product page |
The NetSuite import is an update only, filtered to items marked for update. The two Shopify imports carry no filter of their own — the routing conditions are what gates them.
Worked example — every field, one product, end to end
Real records carried end to end, so the logic can be checked against something that happened.
*Item 332634, Palermo Fabric Dining Chair (Oak, Cream Weave), SKU DC-SQH-PALE-FAB-CRWE.*
Export row, NetSuite record and Shopify metafields all read on 2026-09-23. This is the example
to hand anyone who asks what a single field means or where its value came from.
1 — what the search hands the script (Lead Time V2: Export Inventory - Imported, search 6186).
Note every value is text, including the zeros:
| Column | Value | |
|---|---|---|
supplyType |
"Stock Item" |
display text, not an id |
qtyAvailable_warehouse |
"3" |
Sydney |
qtyAvailable_warehouse2 |
"30" |
the second warehouse |
qtyAvailable_bonded |
"89" |
Vietnam — deliberately excluded from the on-hand total |
supplier_defaultInStockLeadTime |
"0" |
text zero. "0" !== 0 is true — this is LT2-D21 |
supplier_defaultOutOfStockLeadTime |
"15" |
weeks |
new_receiveDate |
"27/10/2026" |
first arrival, written by flow 1 |
new_receiveDate_po2 |
"4/11/2026" |
second arrival |
new_qtyOrder_po1 / _po2 |
"1" / "5" |
pass-through — the script never computes these |
brand |
"Life Interiors" |
not Ellison, so no rewrite |
2 — the calculations, in order:
| Step | Working | Result |
|---|---|---|
| On-hand total | 3 + 30, bonded excluded | 33 |
| Which rung? | on-hand 33 > 0 → P1, first match wins | "Ships in 2 - 3 days" |
| Whose warehouse? | supplier does not drop-ship | "our warehouse" |
| Out-of-stock sentence | built for every item regardless of rung; 15 weeks → the 14–16 band | "Leaves our warehouse in 14 - 16 weeks." |
| On-order sentence | first arrival 27/10, plus the fixed one-week window | "…from 27/10/2026 - 03/11/2026." |
3 — every published value, and where it came from:
| Shopify metafield | Value | Source | NetSuite agrees? |
|---|---|---|---|
in_stock_lead_time_message |
"Leaves our warehouse in 2 - 3 business days." | Rung P1, rephrased for our own warehouse | ✅ |
on_order_lead_time_message |
"New stock arrives in our warehouse from 27/10/2026 - 03/11/2026." | First arrival + 7 days | ✅ |
out_of_stock_lead_time_message |
"Leaves our warehouse in 14 - 16 weeks." | Supplier out-of-stock lead time, 15 weeks | ✅ |
quantity_on_order |
95 | Total on order across all purchase orders | ✅ |
qty_available_wh |
33 | 3 + 30. Not what the storefront sells against — bonded is excluded | ✅ |
po1_receive_date |
2026-10-27 | Pass-through from flow 1, reformatted to ISO for the date type |
✅ |
po2_receive_date |
2026-11-04 | Pass-through from flow 1 | ✅ |
po1_qty_on_order_available |
1 | Pass-through — sellable units on the first arrival only | ✅ |
po2_qty_on_order_available |
5 | Pass-through — second arrival only | ✅ |
All nine agree with NetSuite. This item is in the 7.7% that LT2-D15 has not caught out — its
messages change often enough that change detection fires and drags the four arrival values along
with them.
Why quantity_on_order is 95 but the two arrivals are 1 and 5. They answer different questions
and must not be reconciled: 95 counts every unit on order across every open purchase order;
1 and 5 count only what is still free to sell on the two arrivals that get published. A third
purchase order exists and is never published, because only two arrivals ever are.
*The fallback path — 375674 Pomponette Vase (Amber), SKU VA-MAB-POMP-AMB.* The product that
proved the LT2-D6 fix in production. Export row read live 2026-09-23; this is what a product with
nothing looks like going in, and why it now comes out with a sentence.
| Column | Value | |
|---|---|---|
supplyType |
In-store Only | takes the showroom route, never the ladder |
qtyAvailable_syd / _mel / _bris / _gc |
"0" / "0" / "0" / "0" |
no showroom holds it — this is the trigger |
qtyAvailable_warehouse / _warehouse2 |
"0" / "0" |
nothing of ours |
qtyAvailable_bonded / qtyOnOrder_bonded |
"0" / "0" |
nothing in Vietnam |
supplier_qtyAvailable / _qtyOnOrder |
"0" / "0" |
nothing at the supplier |
supplier_defaultOutOfStockLeadTime |
"0" |
no lead time recorded either |
current_inStockLeadTime |
"- None -" |
how the search renders an empty field |
Before 2026-09-23. The showroom message builder found no stock, returned nothing, and left the
band and both sentences unset. Change detection then compared "- None -" against unset,
judged it changed, and flagged the product — on every run, six times a day, writing nothing each
time because an unset value is not sent. The storefront showed no lead time at all.
After. The fallback sees nothing was set and fills all three:
| Field written | Value | Note |
|---|---|---|
custitem_ships_in |
Please contact showroom for lead time |
no full stop — it has to match Ships In list id 22 exactly |
custitem_ships_in_celigo |
Please contact showroom for lead time. |
full stop added by the existing block below |
custitem_next_receive_date_celigo |
Please contact showroom for lead time. |
same |
custitem_out_of_stock_message |
Please contact showroom for lead time. |
unchanged — built for every item regardless of rung, so the fallback leaves it alone |
Confirmed in Shopify the same day: in_stock_lead_time_message and on_order_lead_time_message
both written at 06:15:22 UTC, two minutes after deployment.
Why this wording and not a lead time. The product genuinely has none — no stock, no order, no supplier lead time. Any number here would be invented. "Please contact showroom for lead time" is what the ladder already says wherever a wait is unknown, so the fallback reuses it rather than introducing a second way of saying we don't know.
The contrast — RG-TRC-ADOR-GRAP-200-290, a Rugs item. Read the same day:
| Metafield | Value | |
|---|---|---|
in_stock_lead_time_message |
"Leaves our partners warehouse in 1 - 2 weeks." | ✅ present — drop-ship wording |
on_order_lead_time_message |
"Please contact showroom for lead time." | ✅ present |
out_of_stock_lead_time_message |
"Please contact showroom for lead time." | ✅ present |
quantity_on_order |
0 | ✅ present |
qty_available_wh |
0 | ✅ present, written 14 Sep |
po1_receive_date |
— | absent, correctly: omitted by the presence test, and Rugs has no purchase orders |
po2_receive_date |
— | absent, correctly |
po1_qty_on_order_available |
— | absent — but sent as an empty value and rejected, not omitted (LT2-D16) |
po2_qty_on_order_available |
— | absent, same |
The outcome is right and the mechanism is wrong. The four dates and quantities should be absent
for a drop-ship catalogue; two of them get there by being omitted and two by being rejected on every
run, six times a day, invisibly because of LT2-D18. The fifth metafield writing successfully on
14 September is what proves a rejection loses only that field, not the whole payload.
Worked examples
Real records carried end to end, so the logic can be checked against something that happened.
Two kinds of example below, and they are labelled: one traced from a real item read back from production, the rest walked through the documented ladder. Nothing here is a made-up record.
Example 1 — real: item 181283, Pierre Floor Mirror (Item Simple list). Verified live on
2026-08-21 while closing LT2-D2.
| Step | Value | Why |
|---|---|---|
| Input | The item is in saved search 6221, and now returns shopifyItemType = product |
The column was added to the search on 2026-08-21 |
| Decision | Routed down the product branch | The router matches on shopifyItemType and drops anything matching neither route |
| Written | NetSuite fields updated, and the five metafields pushed to the Shopify product | Before the fix its NetSuite fields updated and its storefront never did |
Example 2 — ladder walk: a product we hold in Sydney. Traced through LI-BL-INV-006, not
from a named record.
| Step | Value | Why |
|---|---|---|
| Rung tested | Rung 1 — in our own warehouse, Sydney only, never bonded | The first rung that fits wins, and nothing further is considered |
| Band | "2 - 3 days" | Rung 1 is a fixed promise, not a calculation |
| Written | In-stock message reads "Leaves our warehouse in 2 - 3 days." |
Example 3 — ladder walk: bonded stock, and where it recedes. Traced through LI-BL-INV-011
and defect LT2-D10.
| Step | Value | Why |
|---|---|---|
| Bonded netting | Bonded quantity less the Sydney backorder leaves a spare | LI-BL-INV-011 — only the spare can be promised |
| Arrival date | No transfer order exists yet, so the landing date is estimated as today plus the transit allowance | The allowance is a flat constant in the script — see Open questions |
| Rung | Rung 2 — on order, counted from the resolved Sydney landing date | |
| Written | An arrival-window message naming that date, plus seven days | The window is always the date plus a week, not a real estimate |
| ⚠️ Next run | The date is recomputed from today again, so it moves forward a day | LT2-D10 — the promise recedes daily, and the item re-pushes to Shopify every run |
Example 4 — ladder walk: nothing fits. Traced through defect LT2-D6.
| Step | Value | Why |
|---|---|---|
| Input | No stock anywhere, and no supplier lead times configured | |
| Decision | No rung matches, and there is no default | |
| Written | All three sentences are left unset and may be written as empty | LT2-D6 — the product page shows no lead time at all |
Test cases
What to run to know the behaviour is intact. Expected values, never “should work”.
| Case ID | Layer | Preconditions | Input | Expected output | Rule ref |
|---|---|---|---|---|---|
LT2-TC-T1 |
needs confirming | A product with Sydney stock and also a supplier lead time | The flow runs | Rung 1 wins — "2 - 3 days". The supplier rung is never reached | LI-BL-INV-006 |
LT2-TC-T2 |
needs confirming | A product with a computed wait beyond 48 weeks | The flow runs | "Please contact showroom for lead time", not a band | LI-BL-INV-006 |
LT2-TC-T3 |
needs confirming | Our arrival date and the supplier's, five days apart | The flow runs | Ours is used | LI-BL-INV-006 |
LT2-TC-T4 |
needs confirming | Our arrival date and the supplier's, three weeks apart | The flow runs | The earlier is used | LI-BL-INV-006 |
LT2-TC-T5 |
needs confirming | An arrival date sixteen days in the past | The flow runs | Discarded, as though it never existed | LI-BL-INV-006 |
LT2-TC-T6 |
needs confirming | An Ellison Studios drop-ship product | The flow runs | Wording says "our warehouse", not "our partners warehouse" | LI-BL-INV-006 |
LT2-TC-T7 |
needs confirming | An Imported item with bonded stock exceeding the Sydney backorder | The flow runs | The spare drives both the published quantity and the arrival date | LI-BL-INV-011 |
LT2-TC-T8 |
needs confirming | Sydney oversold by more than bonded can cover | The flow runs | Quantities publish as zero. Today the residual is discarded — LT2-D11 says it should be surfaced |
needs confirmingLT2-D11 |
LT2-TC-T9 |
needs confirming | A product where only the arrival date changed | The flow runs | Today: no update is triggered (LT2-D8). Once fixed: the item updates |
needs confirmingLT2-D8 |
LT2-TC-T10 |
needs confirming | One item with an empty supply type | The flow runs | Today: the whole run stops (LT2-D7). Once fixed: that item is skipped and the rest complete |
needs confirmingLT2-D7 |
LT2-TC-T11 |
needs confirming | A product with no Shopify product id | The flow runs | NetSuite updates; the item is dropped before Shopify. Intended | needs confirming |
LT2-TC-T12 |
needs confirming | An In-Store Only product with showroom stock | The flow runs | "Available for in-store purchase in our … showroom" — not a lead time | LI-BL-INV-006 |
LT2-TC-T13 |
needs confirming | A product where nothing changed | The flow runs twice | The second run writes nothing and pushes nothing | LI-BL-INV-006 |
LT2-TC-T14 |
needs confirming | Shopify rejects the metafield write | The flow runs | Nothing detects it. Recording this as a test is the point — there is no assertion to make today | needs confirming |
Derived from the rules and defects above. There is no automated test coverage for this flow — running these means driving it in a sandbox and reading the item and the storefront back. The expected column is what this entry documents; where today's behaviour is a known defect, both are given.
UAT
What a person checks, by hand, before it is trusted.
Signed off by reading the product page and the NetSuite item — no Celigo access required.
| # | Step | What to check | Signed off by | Date |
|---|---|---|---|---|
| U1 | Pick a product from each of the four lists — Local, Imported, Rugs, Item Simple | All four categories are represented in the run | ||
| U2 | Read the in-stock message on the NetSuite item | It is one of the twenty-three bands, or the showroom sentence | ||
| U3 | Open the same product on the storefront | The storefront sentence matches the NetSuite one | ||
| U4 | Check an Item Simple product, e.g. 181283 Pierre Floor Mirror |
It reaches Shopify — this is the LT2-D2 fix |
||
| U5 | Check an Imported product with bonded stock | The published quantity is the spare after the Sydney backorder, not the raw bonded quantity | ||
| U6 | Re-read the same bonded product the following day | ⚠️ If its arrival date has moved a day later with no other change, that is LT2-D10 |
||
| U7 | Check an out-of-stock product | Whether it can still be bought matches LI-BL-INV-008 |
||
| U8 | Confirm with customer service | They know the arrival date changed meaning to "lands in Sydney" — see Open questions |
Edge cases
The inputs that sit at the boundary, and whether each is handled.
| Case | Behaviour | Handled? |
|---|---|---|
| Supply type is empty | Handled. A blank list field arrives as an empty string, and upper-casing one is safe — 180 such items replayed cleanly on 2026-09-23. The item falls to the final rung | ✅ in practice. LT2-D7 fires only if the column is absent, which is a saved-search change, not a data state |
| Brand is McMullin and the supplier arrival is more than 70 days out | Backorder is refused | ✅ since 2026-09-23 (LT2-D22). The test matched McMullin & Co. exactly and so never fired; it now matches on the leading word |
| Supplier lead time is zero | The rung is NOT skipped. The guard tests against the number zero, but every value arrives from NetSuite as text, so "0" is not equal to 0 and the test passes. The rung fires with a zero lead time |
❌ LT2-D21 — corrected 2026-09-23; this row previously read "skipped, which is intended" |
| No rung of the ladder matches | The final fallback sets all three to "Please contact showroom for lead time" | ✅ since 2026-09-23 (LT2-D6). Not reachable at all today — LT2-D21 keeps the last rung firing |
| In-Store Only, no showroom holds stock | Same fallback. Was the one live path into LT2-D6 |
✅ since 2026-09-23, verified on two live products |
| An Ellison Studios item reaches the brand rewrite with no sentence set | Cannot happen — the fallback runs first and guarantees a sentence exists | ✅ LT2-D20 unreachable by construction since 2026-09-23 |
| Item is in the Item Simple list and has Shopify ids | Routed to Shopify on the product branch | ✅ since 2026-08-21, LT2-D2 |
| Item has bonded stock, in the Imported list | Netted against the Sydney backorder; the spare drives the quantity and the arrival date | ✅ since the bonded change |
| Item has bonded stock, in the Local, Rugs or Item Simple lists | All four searches now supply the bonded columns | ✅ since 2026-08-21, LT2-D9 |
| Sydney is oversold by more than bonded can cover | Quantities published as zero; the residual shortfall is calculated and thrown away | ❌ LT2-D11 |
| Spare bonded stock on hand, no transfer order raised | The arrival date is recomputed as today plus transit on every run, so it moves a day later every day | ❌ LT2-D10 |
| Only the arrival date or quantity changed | No update is triggered — none of the four is in the comparison set | ❌ LT2-D15 |
| Gold Coast is the only showroom whose stock changed | Counted in the showroom total, so an update is triggered | ✅ since the bonded change |
| Arrival date is in the past by less than a fortnight | Kept and used | ✅ intended buffer |
| Arrival date is in the past by more than a fortnight | Discarded | ✅ |
| Both arrival dates missing | "Please contact showroom for lead time" | ✅ |
| Item has no Shopify id at all | NetSuite is updated; the router matches neither branch and the record is discarded with no error. Measured 2026-09-23: 20 items live on Shopify lose every update this way, on every run | ❌ LT2-D19 — previously recorded as "intended" |
| Item is not on Shopify at all | Same discard, and correct — 237 such items in the Item Simple list alone | ✅ right outcome, wrong mechanism (see LT2-D19) |
| Shopify rejects one metafield in the payload | The other metafields still save; the rejected one is silently absent | ❌ LT2-D18 |
| Shopify rejects the write | Nothing detects it — the response is never inspected, and a rejection returns HTTP 200 | ❌ LT2-D18 |
Failure modes
What breaks it, how that shows, and how to recover.
| Failure | Symptom | Detection | Recovery |
|---|---|---|---|
| One item has no supply type | The flow stops; no promises update at all | Celigo error dashboard | Fix the item, re-run |
| Shopify write rejected | NetSuite and the storefront disagree | None, and worse than none — the rejection returns HTTP 200 and is counted as a success (LT2-D18) |
Force a change so the item requalifies |
| An item has no Shopify id | NetSuite updates, the storefront never does | None — the record is dropped by the router with no error (LT2-D19) |
Add the Shopify id in NetSuite |
| An Ellison Studios item reaches the brand rewrite with no sentence set | The whole run stops | Celigo error dashboard | Guard the rewrite (LT2-D20). Dormant until LT2-D21 is fixed |
| A guard is corrected to convert text to a number | The ladder starts falling through, and Ellison items then crash the run | Celigo error dashboard, after the damage | Fix LT2-D21, LT2-D6 and LT2-D20 in one change |
| Flow 1 failed but flow 2 ran | Promises built on a mixture of fresh and stale arrival dates | None | Re-run once flow 1 succeeds |
| A saved search is edited or renamed | Items silently drop out of the run | None | Restore the search |
| The four searches drift apart in columns | A rule works for some product categories and silently not for others, as with LT2-D9 |
None — the script reads a missing column as empty and carries on | Bring the searches back into line |
| An item qualifies on every run (LT2-D4) | Constant rewrites, and messages that flip back and forth within a day | Visible in item change history, if anyone looks | Fix the comparison |
How a failure is actually noticed today. As with flow 1, there is no automatic detection. The team raises a ticket when a product shows something they know to be wrong, and the project owner reviews and applies a fix.
Known limitations
Scope that was deliberately chosen. A limitation is a decision.
"Part Only" is how a kit component enters this flow, and an unticked component is skipped silently. Confirmed by the project owner on 2026-09-30. The checkbox reads like a description of the item and behaves like a membership criterion for the export. A component that is neither Part Only nor a sellable product in its own right is read by nothing here: its lead-time fields, its three sentences, its on-order quantity and its backorder setting freeze at whatever they last held. Nothing errors, nothing is logged, and the kits built from it inherit the frozen values — so a data-entry miss at item setup surfaces as a wrong promise on a kit page weeks later. Worked example:
422097Camille Marble Console Table (Top, Burgundy, Rosso Marble) carried a 1st-PO quantity of 10 and an arrival of 29/10/2026 while its website on-order quantity stayed blank and all three sentences read "Please contact showroom for lead time", last written 2026-09-21. Ticking the box, with no change to any script, produced the correct quantity, all three sentences and backorder allowed on the next run. Measured 2026-09-30: 503 kit components are unticked across 885 kits. The exposure is latent — it only shows once a purchase order is raised against the component, which is why a newly set-up range is where it bites. SeeLI-TERM-PART-ONLY.Items archived on the storefront are still read and still pushed. The item record carries a Shopify product status, and an item can be archived there while remaining active in NetSuite. None of the four saved searches excludes them. Item
129586Air Bedside Table (Oak) is archived and points at variant33436153118819, which no longer exists in Shopify — so it is read, calculated and pushed on every qualifying run, to nothing. Nothing reports the failure, because these writes return success and carry their errors in the response body. Excluding archived items in the four searches would remove the whole class; how many items are in this state is not recorded here. Deliberate scope, not defects. The defect table above is the list of things that are wrong; this is the list of things that are simply how it works.
| Limitation | Why it is this way | What to do instead |
|---|---|---|
| The wait is a band, never a date | A precise date the business cannot hold is worse than an honest range | Nothing |
| The arrival window is always the date plus seven days | It is a one-week spread, not a computed delivery estimate | Do not read it as a delivery promise |
| Only the first matching rung is used | The ladder is an order of preference, and stopping at the first match is the point | Change the ladder order, not the item |
| The transit allowance for bonded stock is a flat constant | It was set once in the script | Open question 1 — confirm it is still right |
| Two brands are hard-coded by name | Ellison Studios and McMullin & Co. are handled by name in the script | Any third exception needs a code change |
| It has no schedule of its own | Flow 1 starts it, whether or not flow 1 succeeded | Expect promises built on a mixture after a failed flow 1 |
| Shopify is never read back | Nothing confirms the storefront actually took the write | Someone notices and raises a ticket. LT2-D18 is the sharper version of this: the write is not merely unverified, a rejection is actively recorded as a success |
| Every value arrives as text, never as a number | The saved searches return NetSuite's display values, so 0 arrives as "0", .5 as ".5", and an empty field as "". Confirmed live 2026-09-23 |
Convert before comparing. Three guards that did not are LT2-D21. Comparisons using >, < or >= are safe, because they coerce; === and !== are not |
| There is no default route to Shopify | The router has a variant branch and a product branch and nothing else | Anything matching neither is dropped in silence — LT2-D19 |
| The four searches do not carry the same columns | Each category has different buying behaviour, so each search was built for its own | Confirmed deliberate 2026-09-23 for the arrival columns: Local and Rugs omit them because those categories are not normally bought on a purchase order. Never assume a column exists because another search has it — the script reads a missing column as empty and carries on |
Known defects
Where it does something other than what was decided. A defect is a mistake.
| Ref | Status | Defect | Rule |
|---|---|---|---|
LT2-D2Resolved |
Resolved2026-08-21 | Resolved 2026-08-21. Items from saved search 6221 (Item Simple) never reached Shopify, because the search did not return shopifyItemType and the router drops anything matching neither route. The column was added to the search; verified live on 2026-08-21, including on item 181283 Pierre Floor Mirror, which now returns product. Original description: ** The router sends an item down the variant route or the product route by matching shopifyItemType, and drops anything matching neither — there is no default branch. Search 6221 does not return shopifyItemType at all, confirmed both in the Celigo sample and by running the live search. Items in that list with real Shopify ids exist: 181283 Pierre Floor Mirror and 181284 Pierre Side Table. Their NetSuite fields update; their storefront does not** |
needs confirming |
LT2-D3Resolved |
Resolved2026-08-18 | Resolved 2026-08-18 by the bonded change. The bonded warehouse fed nothing: its quantities were returned and never read, and no bonded arrival date was consumed. LI-BL-INV-011 now nets it against the Sydney backorder and lets the spare set both the quantity and the arrival date |
needs confirming |
LT2-D4Resolved |
Resolved2026-09-21 | Resolved, confirmed 2026-09-21. The comparison set is now eight conditions, not eleven, and each value is compared once. The two duplicated pairs — available quantity against both the Life-plus-supplier and the Life-only total, and the same for on-order — are gone, and blank is normalised to zero before comparing. A full run on 2026-09-21 left 5,182 of 5,286 products untouched, which is inconsistent with every-run rewriting. Original description: ** Two of the eleven change-detection comparisons can never both hold, so those items are marked as changed on every run and rewritten needlessly ** | needs confirming |
LT2-D5Resolved |
Resolved2026-08-18 | Resolved 2026-08-18 by the bonded change. Gold Coast stock was named in the in-store message but left out of the showroom total used for change detection, so a Gold-Coast-only change never triggered an update. It is now included in that total | needs confirming |
LT2-D8Resolved |
Resolved | Not reproducible on the current configuration, verified 2026-09-21. Flow 2's NetSuite import maps twelve fields and custitemcust_receive_date is not among them, so the two flows do not write the same field and cannot fight over it. Flow 1 is its sole writer. What remains true, and is recorded in LI-BL-INV-011 rather than as a defect, is that flow 2 can show the customer an earlier date than the field holds when spare bonded stock on hand lands sooner — by design, since the two answer different questions. Whether the mapping was present earlier and removed is not recorded anywhere. Original description: ** Flow 1 and flow 2 write different meanings into the same field, and each overwrites the other four times a day ** |
needs confirming |
LT2-D9Resolved |
Resolved2026-08-21 | Resolved 2026-08-21. The bonded rule only worked for Imported items, because only search 6186 supplied the bonded columns. All four searches now supply them; verified live. Original description: ** The script reads new_receiveDate_bonded and real bonded quantities, but only saved search 6186 (Imported) supplies them. Verified live on 2026-08-18: searches 6212, 6220 and 6221 do not return the bonded date column at all and return the bonded quantities blank. For those three categories the rule is inert. Worse, if their bonded quantities are ever populated without the date column being added, bonded stock would count towards the published on-order quantity while being unable to produce any arrival date — a quantity with no promise attached** |
needs confirming |
LT2-D10Customer sees a date that never arrives; daily churn. **Resolved by the `LT2-D17` fix** — removing the uplift removes the only place a date is recalculated from today |
Open | A promise that recedes by a day, every day. Spare bonded stock on hand has no transfer order yet, so its arrival is estimated as today plus the transit allowance. Recomputed on every run, that date moves forward a day each day and the arrival never gets closer. Because the date is embedded in the customer-facing message, the message changes daily, which marks the item as changed and re-pushes it to Shopify every day | needs confirming |
LT2-D11A known-bad state is computed and never surfaced |
Open | Nothing reports an item oversold beyond bonded. The netting calculates exactly how much demand is still uncovered after all bonded stock is applied, labels it a diagnostic, and then discards it. That figure is the clearest signal available that something is oversold, and it is thrown away every run | needs confirming |
LT2-D6**Resolved.** Seven products, one of them live on the storefront |
Resolved2026-09-23 | Resolved 2026-09-23. Deployed and verified end to end. A final fallback was added to Lead Time: Inventory V3.1 Sep 2026 - bonded wh — after the In-Store Only branch and the ladder, before the brand rewrite — setting the dispatch band and the in-stock and on-order sentences to "Please contact showroom for lead time" whenever nothing above set them. Proved by a controlled experiment nobody designed. The deploy landed at 06:13 UTC during a run that had started at 06:08, so one run processed the same search under both versions. Three of the five affected Local products had already passed (rows 1,208 / 1,974 / 2,146) and stayed blank; the two that had not (173797 Palina Candle Holder, row 7,625, and 375674 Pomponette Vase (Amber), row 7,959) came out fully populated. Same run, same data, same item type — only the script differed. Shopify confirms the whole chain: VA-MAB-POMP-AMB and CA-CH-FLI-PALI-MINT-SM both carry the wording, written 06:15:22 and 06:15:00 UTC. The Local export then completed with 11,054 records and 0 errors. Four of the seven confirmed populated by 06:23 UTC: 173797 and 375674 from the split run, plus 173803 and 235919 once the Item Simple export re-ran at 06:21 under the new script. The remaining three — 173783, 182372, 190782 — sit at rows 1,208, 1,974 and 2,146 of the Local export and passed before the 06:13 deploy, so they wait for the next Local pass. A schedule, not a defect. Original: An item that matches no rung has its promise left unset — all three sentences stay unset and may be written to NetSuite as empty, leaving a product page with no lead time at all. |
needs confirming |
LT2-D7Whole-run outage **if a column is dropped**. No live exposure today |
Open | An item with no supply type stops the flow — but only if the column is absent, not if it is blank. Supply type is read and upper-cased without a null check, unlike brand, which is guarded. Corrected 2026-09-23 by the logic replay. A blank list field comes back from the saved search as an empty string, not null, and "".toUpperCase() is perfectly safe. Across all 19,225 rows replayed, 193 carry a blank supply type — 180 in Item Simple, 13 in Local — and every one processed without error — they still get a real lead time, not the contact-showroom fallback — supply type only gates the Made To Order and End Of Line rungs, so the in-stock, on-order and out-of-stock rungs are unaffected by it. Across the 193: 106 compute "14 - 16 weeks", 37 "10 - 12 weeks", 30 "2 - 3 business days", 15 "1 - 2 weeks" and 5 "12 - 14 weeks". A missing supply type is a data-hygiene problem, not a lead-time one. So this is latent, not live: it fires only if supplyType arrives as null or undefined, which means the column being dropped from a saved search, the same event the flow-1 column guard exists to catch. It should still be guarded — a one-line change removing a whole-run outage — but it is not currently at risk, and it is not the reason to treat blank supply types as urgent. An earlier review of this chain stated that 301 Shopify-active items with no supply type each put the run at risk. That was wrong, and this is the correction. |
needs confirming |
LT2-D12Wrong voice and wrong owner on tied dates |
Open | On identical dates the supplier wins, and it should be us. The comparison tests "within a week of each other" with a strictly-positive difference, so two dates falling on exactly the same day fall through to the final branch, which picks the supplier's. The confirmed rule is that ours wins on a tie. The wording the customer reads can therefore name the supplier's warehouse on a date we could have served ourselves | needs confirming |
LT2-D13Two customer-facing numbers that contradict each other |
Open | The dispatch band and the arrival sentence can be measured from different days. The band is always counted from our date; the sentence quotes whichever date the comparison picked. On a product where the supplier's date won, the two disagree, and nothing reconciles them | needs confirming |
LT2-D14Off-by-one dates near the day boundary, on customer-facing wording |
Open | Date arithmetic runs on the server's clock, not Sydney's. Four decisions read new Date() directly: clearing a date more than a fortnight past, counting the weeks to an arrival, the McMullin seventy-day test, and the bonded-on-hand estimate of today plus thirty-five. Celigo's server runs on UTC, so from 10am UTC each day it is already tomorrow in Sydney and each of those can land a day out. The flow's schedule is set to Australia/Sydney, which makes this easy to miss. Flow 1 does it correctly — it converts to the Sydney date explicitly |
needs confirming |
LT2-D15**Largest defect in the chain. 1,374 items wrong, 13 stale** **Two things are needed, not one.** Fixing the change detection only populates an item on its *next* change, so an item that is stable never gets a first write at all — `ST-COO-SCOT-OAK` holds a 24/11/2026 arrival in NetSuite, carries the matching sentence in Shopify written on 3 August, and has never had the four arrival metafields written because it has not changed since they were added on 21 September. A **one-time backfill** is therefore required alongside the fix; the project owner confirmed on 2026-09-23 that this will be run manually. |
Open | Four of the nine Shopify values have no change detection, and it is the largest defect in this chain. The two arrival dates and two arrival quantities are not in the eight-condition comparison and have no read-back column, so a product whose only change is one of those is never marked as changed and Shopify is never called. Measured against a NetSuite-to-Shopify audit on 2026-09-22: of 1,489 items carrying arrival data in NetSuite, 115 carry it in Shopify — 7.7%. 1,374 items hold values that have never reached the storefront. A further 13 items hold a stale quantity, and in all 13 Shopify is higher than NetSuite, never lower — stock was sold, NetSuite decremented, Shopify did not follow. Those 13 also prove the mutation itself works: the value reached Shopify once, so LT2-D16 is not silently failing the whole payload. LT-015, which says sales read the two arrivals in Shopify, is therefore true for 7.7% of the items it applies to. Confirmed 2026-09-23: the fix stays inside this flow and the Kits flow — no new Shopify import is being added — so the change detection has to gain a way to tell that a pass-through value has moved. |
needs confirming |
LT2-D16Storefront advertises arrivals that no longer exist; two fields rejected on every run for two of the four categories |
Open | Neither arrival value can express “blank”, in opposite directions. The two arrival quantities are sent unconditionally, so an item with no arrival pushes an empty string into a number_integer metafield. The two arrival dates are wrapped in a presence test, so a blank is omitted rather than cleared — and Shopify keeps whatever it last held. Live example on 2026-09-22: BE-BEB-MARL-OAK-V3 shows a 2nd PO of 70 units arriving 3 November on the storefront, which NetSuite cleared. Against the confirmed rule that the two systems must match, the fix is a blank quantity written as 0 and a blank date deleted (metafieldsDelete), since a date metafield cannot hold an empty value and the type is staying as date. Narrowed twice: originally raised as “three searches are missing columns” — two omit them by design and the third was given them on 2026-09-21. The worst case, Shopify rejecting the whole mutation, is ruled out by the 13 stale values under LT2-D15, and independently confirmed on 2026-09-23 — a Rugs variant that is sent an empty arrival quantity on every run still had its warehouse quantity written on 14 September, so Shopify rejects the one bad field and saves the rest. Confirmed by the project owner, 2026-09-23: the Local and Rugs searches omit the arrival columns on purpose, because those categories are not normally bought on a purchase order. The Item Simple search does carry all three — an earlier reading of this entry said it did not, which came from Celigo's cached sample rather than the live search. So the asymmetry below is not a missing-column problem, it is a guard problem: the two arrival dates are wrapped in a presence test and the two arrival quantities are not, in the same payload. For Local and Rugs items the two quantities are therefore posted as an empty value into an integer field on every run, six times a day, and rejected every time — invisibly, because of LT2-D18. Only one direction fixes it: wrap the two quantities in the same presence test the dates already have. Removing the test from the dates instead would post an empty value into a date metafield, which Shopify refuses outright. Wrapping the quantities is also consistent with the confirmed rule that blank and zero both publish as nothing.* |
needs confirming |
LT2-D17Storefront and NetSuite disagree; the message churns daily |
Open | The thirty-five day uplift in this flow is legacy, and now only ever overrides a better answer. The confirmed rule is that the customer-facing sentences and the dispatch band read the first arrival written by flow 1. This flow instead takes the earlier of that date and its own bonded-on-hand estimate of today plus thirty-five days. That uplift predates the first-arrival field — it was how bonded transit got accounted for before flow 1 existed to do it, and flow 1's date now already includes the uplift. Applying it again here is the old workaround outliving its purpose. Measured on 2026-09-23: one item holds bonded stock available in Vietnam, and it already carries a first arrival date; no item has bonded stock on hand without one. So the path can only ever override a date flow 1 calculated correctly — it can never fill a gap. Correction, 2026-09-23: an earlier version of this entry cited 332634 Palermo Fabric Dining Chair as holding 27/10 in NetSuite while the message quoted 26/10. That came from replaying the flow's stored sample data through the script, not from production. Checked live the same day, the item holds 27/10 in NetSuite and the storefront message reads “New stock arrives in our warehouse from 27/10/2026 - 03/11/2026” — they agree, because the item has no spare bonded stock on hand right now. The defect is the code path, which is reachable and wrong whenever spare bonded stock exists; it is currently dormant, consistent with only one item holding bonded availability. No verified live example exists today. Fix: remove the uplift from this flow and pass the first arrival through untouched. That also resolves LT2-D10, since nothing here recalculates a date from today any more. |
needs confirming |
LT2-D18**Every Shopify defect in this chain is invisible by construction.** Fix this first or you cannot measure the rest |
Open | A rejected Shopify write is recorded as a success, so no failure in this chain can ever surface. Both Shopify imports post a GraphQL mutation. Shopify answers a rejected metafield with HTTP 200 and the reason inside the body, under userErrors. Neither import is configured to read the response, so Celigo sees 200 and counts a success. Proven 2026-09-23: the run at 02:50 recorded Update Shopify Variant Metafields — 365 successes, 0 errors — while RG-TRC-ADOR-GRAP-200-290, one of those records, demonstrably has no po1_qty_on_order_available metafield in Shopify. The write was rejected and reported as fine. This is why LT2-D15 went unnoticed for months, and it is why "zero errors" on the Celigo dashboard means nothing for this chain. It also blocks verification of every other fix here: until the response is read, nobody can tell whether a change worked |
needs confirming |
LT2-D1920 live products permanently diverged. Two fixes, and they are different: a **default branch that logs** stops it being silent; **fixing the 20 items' Shopify ids** stops it happening |
Open | An item with no Shopify id is discarded silently, and 20 live products lose every update. The Products or Variants router sends a record down the variant branch or the product branch and has no default branch, so anything matching neither is dropped with no error and no log. This is the same shape as LT2-D2, which was closed in August by adding the missing column; the mechanism was never fixed, only that one trigger for it. Measured 2026-09-23 by replaying the router's own filters over a live run of the Item Simple and Rugs searches: 366 of 833 Item Simple records and 9 of 2,159 Rugs records match neither branch. Of the 366: 237 are not on Shopify at all and are correctly skipped, 6 are archived, 3 are draft, and 20 are live and active on Shopify with no Shopify id recorded in NetSuite. Those 20 have their NetSuite fields updated on every run and their storefront never. Across all four searches in that run, NetSuite updated 913 items and Shopify received 693 — a gap of 220 |
needs confirming |
LT2-D20Whole-run outage in principle. **Unreachable by construction since 2026-09-23** |
Open | A missing sentence crashes the whole run, for one brand only. After the ladder, Ellison Studios items have their three sentences rewritten to say "our warehouse" instead of "our partners warehouse". The rewrite calls a text replacement on all three without checking any of them is set — unlike the brand test immediately above it, which is guarded. If a sentence is unset the replacement throws, and a throw stops the entire page, so one product blocks the promise for every product behind it. Same failure shape as LT2-D7. Dormant today, because LT2-D21 keeps the final rung firing and so a sentence is always set. Corrected 2026-09-23 by the full replay — it stays dormant even after LT2-D21 is fixed. An earlier review of this chain put 174 Ellison products at risk, reasoning from NetSuite's item and vendor tables that items with no preferred vendor would have blank supplier lead times. The saved searches do not join the vendor that way. Of 523 Ellison rows across the four searches, the 183 with no stock anywhere all arrive carrying the Ellison vendor's lead times — inStock=".5", oos="12", mto1="19" — so a rung always fires and a sentence always exists. Replaying with the guards corrected produced 0 Ellison fall-throughs and 0 exceptions. The defect is real and the guard is still missing, but its live population is zero, before and after. Methodological note, and this is the second time it has bitten: never infer what a Celigo script receives from NetSuite's own tables — read what the saved search actually returns. Superseded 2026-09-23 by the LT2-D6 fix. The final fallback runs immediately before this rewrite and guarantees all three sentences are set, so the rewrite can no longer meet an unset value by construction — not merely because no item happens to reach it. The missing guard is now a tidy-up rather than a risk. |
needs confirming |
LT2-D21The documented ladder and the running ladder are not the same ladder. **Safe to fix since the catch-all shipped** |
Open | Three of the four ladder guards do nothing, because NetSuite sends text and the guard compares a number. The guards on Made To Order 1, Made To Order 2 and Out Of Stock each test !== 0 against the number zero. Every value arrives from the saved searches as text — confirmed 2026-09-23 from live runs of two of the four searches, where lead times come through as "0", ".5", ".7" and blanks as "". "0" is not equal to 0, so all three guards always pass. The In-Stock guard is written correctly and converts before comparing; the other three were not. Consequences, and they cut both ways. The final rung has become an unintended catch-all, which is the only reason LT2-D6 and LT2-D20 are dormant. But a rung fires with a zero lead time, and assignShipsIn("0") matches no band and falls through to "Please contact showroom for lead time" — so the item gets the fallback wording by accident rather than by rule. Fixing this in isolation breaks the run (LT2-D20) Fixed and deployed 2026-09-23, 06:24 UTC — not yet exercised by a run. Each of the three guards now converts before comparing, matching the In-Stock guard on P4 which was always written correctly. Replayed against the currently deployed script over all 19,225 rows: 0 rows differ, 0 exceptions, the flagged-for-update count unchanged at 61, and no item left without a promise. A third diagnostic run — tight guards with the LT2-D6 fallback disabled — leaves 563 rows with no promise at all, which is the measure of what the fallback is now carrying and why the order of the two changes mattered. The ladder that runs is now the ladder this entry documents, and P9 is no longer an accidental catch-all. Deployed one minute after the pass that ended 06:23:05 completed, so the first run to exercise it is the next scheduled pass — the check to make then is simply that errors stay at zero and the written count stays in its normal range, because a correct deploy changes nothing visible. |
needs confirming |
LT2-D22A confirmed business rule silently stopped applying. **Fixed 2026-09-23**; zero flag changes today, 115 rows now actually evaluated |
Open | The McMullin backorder rule has never fired, because the brand was renamed and the script was not. The rule: a McMullin product whose supplier arrival is more than 70 days out must not be orderable out of stock. The script tests brand === 'mcmullin & co.'. The value in NetSuite's brand list is McMullin (id 146, customlist 83) — confirmed 2026-09-23 by reading the list and by finding McMullin in live export rows. Lower-cased, that is mcmullin, which never equals mcmullin & co., so the branch is unreachable and the 70-day test is dead code. Almost certainly a brand rename that nothing followed up. Dormant today: 105 McMullin products are live on Shopify and none currently has a supplier arrival beyond 70 days, so no product is wrongly orderable right now. It becomes live the moment McMullin quotes a long lead time. Confirmed still wanted by the project owner on 2026-09-23, and fixed. The comparison now matches on the leading word — brand.indexOf('mcmullin') === 0 — rather than an exact string, so it survives the next rename as well. McMullin is the only entry in customlist 83 containing the word, so a prefix match cannot catch anything else, and brand is already null-guarded and lower-cased at that point. Verified against the deployed script over all 19,225 rows: 0 rows differ, 0 exceptions, and the backorder flag flips on none of the 115 McMullin rows — the rule now genuinely runs on all of them and denies none, because no McMullin product currently has a supplier arrival beyond 70 days. It will deny the first one that does, which is the whole point. |
needs confirming |
These are recorded as behaviour, not as proposals. Changing any of them is a change request; the registry is updated after that ships — CONVENTIONS §1.
Open questions
What could not be established. Recorded rather than guessed.
| Ref | Status | Question | Who can answer |
|---|---|---|---|
LT2-Q1 |
Open | Is the 35-day transit allowance still right? It is a flat constant in the script, with a note that it should move to a Celigo setting if Vietnam freight becomes seasonal. Every bonded promise the customer sees rests on it. | needs confirming |
LT2-Q2 |
Open | Has customer service been told the arrival date changed meaning? The script's own comment says to notify them before deploying. The field now means "lands in Sydney", not "date on the purchase order". | needs confirming |
LT2-Q3 |
Open | Which locations are warehouse and warehouse2? The on-hand total adds them together. Given flow 1 treats Sydney Overflow as Sydney, these are most likely Sydney Warehouse and Sydney Overflow, but the searches would need reading to confirm it. |
needs confirming |
LT2-Q4 |
Open | Is the Ships In dispatch band meant to reach Shopify? It is written to NetSuite but is not one of the five metafields pushed. The three sentences, the on-order quantity and the warehouse on-hand quantity go. |
needs confirming |
LT2-Q5 |
Part answered2026-09-23 | LT2-D19 hides in. |
needs confirming |
LT2-Q6 |
Open | Is the router's branching script still needed? The router names a script function that the exported script does not define. Routing is done by the branch filters, so it appears to be a leftover. Re-checked 2026-09-23, unchanged. |
needs confirming |
LT2-Q7 |
Open | Should the Local and Rugs searches keep the two arrival quantities out of the Shopify payload entirely? Raised 2026-09-23. Wrapping them in a presence test (LT2-D16) stops the rejected write, but it leaves two metafields that never exist for those categories. If the storefront theme reads them, it needs to handle absent as well as zero. Nobody has checked what the theme does. |
needs confirming |
LT2-Q8 |
Answered2026-09-23 | LT2-D19 need their Shopify ids recorded in NetSuite, which is a data fix, though not a Buying one. |
needs confirming |
LT2-Q9 |
Open | Which stock does rule 1 of LI-BL-INV-008 actually mean by "the second warehouse"? The rule is written as an absolute override — the second warehouse holds stock, allowed, whatever else is true — but production disagrees for the field the name suggests. Measured 2026-09-30 across active items: of those that are End Of Line with custitem_qty_available_wh above zero, nothing on order and no supplier stock, 140 are refused and only 12 allowed. Rule 3 is winning and rule 1 is not firing on that field. On those records custitem_qty_available_gc, _syd, _mel and _bris — the showroom locations — are all zero, so rule 1 may mean one of those rather than the warehouse figure, or may be narrower than written. It is not inferred here.Why it matters: Until it is confirmed the rule promises an override the flow does not apply, which is the kind of gap nobody re-checks because the page looks finished. It is also the root of LT3-D17 on kits: raised from 396981 Noir Oval Dining Table (220cm, Black Oak), where an End Of Line Top holding 3 units refuses backorder and vetoes the whole kit. Answering it decides whether that fix belongs at item level or kit level. |
The Back End Team for which field the flow reads; the Buying Team for whether an End Of Line item we physically hold should be sellable when nothing more is coming. |
Source references (read-only)
The code and searches this reading was written from.
Read directly from the live Celigo account on 2026-08-21 via the integrator.io API, and earlier
from the exports supplied on 2026-08-17 and 2026-08-18 — integration NetSuite Scripts
(5ad5bad381aef80b5ae1ec10), flow grouping Lead Time (620d943fb8184a400655ed19). Assets
are listed in code_refs. Cross-checked the same day against NetSuite: all four saved searches
run live, plus item records and item field change history.
Open convention question. CONVENTIONS §7 assumes repo + path + verified_at_commit.
Celigo-hosted script has no SHA, so drift cannot be detected here the way it can elsewhere in
this registry. exported_on carries the date of the export instead, and needs agreeing as the
convention for Celigo-hosted logic before this entry can go active.
Change history
What moved on this page, and when.
| Date | Change | Change request |
|---|---|---|
| 2026-10-01 | "Part Only" recorded as the membership criterion for this flow's export. Confirmed by the project owner 2026-09-30 after 422097 Camille Marble Console Table (Top, Burgundy, Rosso Marble) was found holding a 1st-PO quantity of 10 and an arrival of 29/10/2026 while its website on-order quantity stayed blank and all three sentences read "Please contact showroom for lead time", last written 2026-09-21. Ticking the box, with no script change, produced the correct quantity, all three sentences and backorder allowed on the next run. The script, the import mapping and the change detection were each checked and found correct first — the item was simply never in the export. Recorded as a limitation and as glossary term LI-TERM-PART-ONLY; 503 kit components across 885 kits are currently unticked. The exposure is latent until a purchase order is raised against the component, which is why it surfaces on newly set-up ranges. No rule, script or behaviour changed; last_reviewed not bumped. |
— |
| 2026-09-30 | LT2-Q9 raised: rule 1 of LI-BL-INV-008 does not fire on the field its wording implies. The rule reads as an absolute override — the second warehouse holds stock, allowed, whatever else is true — but measured against live NetSuite on 2026-09-30, active End Of Line items with custitem_qty_available_wh above zero, nothing on order and no supplier stock come out 140 refused to 12 allowed. Rule 3 is deciding them, not rule 1. The showroom fields custitem_qty_available_gc, _syd, _mel and _bris are zero on those records, so "the second warehouse" may be a showroom location rather than the warehouse figure — not inferred here, and left blank until confirmed. Raised from the kit side: kit 396981 Noir Oval Dining Table (220cm, Black Oak) is refused on Shopify because its End Of Line Top, holding 3 units, is flagged no-backorder, which vetoes the kit under gate 1 of LI-BL-INV-013 — recorded there as LT3-D17, affecting 31 kits. No rule, defect or behaviour changed on this entry; last_reviewed not bumped, since only rule 1 was tested and not the rest. |
— |
| 2026-09-28 | Developer sections reordered to the registry's skeleton (CONVENTIONS §15): Inputs · Processing · Decision tree · Outputs · Worked examples · Test cases · UAT · Edge cases · Failure modes · Known limitations · Known defects · Open questions · Source references · Change history. The entries had drifted into two house styles — four put the proof after the outputs, four put the problems there — so every shared heading sat at a different position depending on which entry you opened; Test cases alone appeared at five different ones. Every section moved whole and byte-identical: nothing inside any of them was touched, and no wording changed. The one-line description the site now prints under each heading is generated from build.mjs, not written here, so it reads the same on every entry. npm run check warns on a wrong order and on a missing section. No logic change, and last_reviewed is unchanged. |
— |
| 2026-09-28 | 14 test cases moved from the body table into the test_cases: front-matter register and restated in the shape a test pack uses — Case ID · Layer · Preconditions · Input · Expected output · Rule ref. Ids become LT2-TC-<case>, which keeps every case id the table already used while making them unique across the registry. The build renders them back under ### Test cases, and they now also appear on the generated Test cases page, so a pack spanning two entries no longer has to be retyped. 5 name no rule and 14 name no layer — neither is inferred, and npm run check now counts them. No expected value was changed. No behaviour was re-documented and last_reviewed is unchanged. |
— |
| 2026-09-28 | Defects and open questions moved from body tables into the defects: and open_questions: front-matter registers, namespaced LT2-: 21 defects (14 open) and 8 open questions (7 still open). The build renders them back under the same headings, so the page reads as it did; the prose around those tables is unchanged. They now also appear on the generated DEFECTS and Open questions pages, which is the point — the same list was unreadable spread across nine entries in five different column shapes. Every existing ref is preserved. No behaviour was re-documented, no defect status was reinterpreted, and last_reviewed is unchanged. |
— |
| 2026-09-23 | LT2-D22 fixed — the McMullin rule runs for the first time. The project owner confirmed the rule is still wanted. The comparison now matches on the leading word rather than an exact string, so it survives the next rename as well; McMullin is the only entry in customlist 83 containing the word, so a prefix match cannot catch anything else. Verified against the deployed script over all 19,225 rows: 0 rows differ, 0 exceptions, and the backorder flag flips on none of the 115 McMullin rows — the rule is now genuinely evaluated on all of them and denies none, because no McMullin product currently has a supplier arrival beyond 70 days. It will deny the first one that does. LT-064 in flow 1's crosswalk moves back to live. |
— |
| 2026-09-23 | Consolidation after the two deploys — the entry now describes the system as it runs, not as it was found. LT2-D21 shipped at 06:24 UTC, byte-identical to the verified build, closing the last script-side defect. Everything the two fixes made stale has been rewritten rather than annotated: the LI-BL-INV-006 ladder note (the three guards now genuinely check for a lead time, and none of the above is a real rule instead of an unreachable row), the processing pseudocode warnings, and the decision tree, which gains a Fallback row and loses the two "guard is inert" notes. The workflow diagram was rebuilt — eight nodes were wrong: it still said four runs a day rather than six, eleven change-detection values rather than eight, and showed LT2-D9 and LT2-D4 as live when both were resolved in August. The no rung matched node is now the fallback, and the change-detection node names the four arrival values that are not compared, which is LT2-D15. Added a Where this chain stands table ahead of the defect list, so the live picture is not lost in thirteen rows of history, and a worked example of the fallback path on 375674 Pomponette Vase (Amber) with its real export row, showing why a product with no stock, no order and no supplier lead time now gets a sentence instead of a blank page. |
— |
| 2026-09-23 | LT2-D6 resolved in production. The final fallback was deployed at 06:13 UTC into Lead Time: Inventory V3.1 Sep 2026 - bonded wh, byte-identical to the verified build, with the three LT2-D21 guards deliberately left alone. It was proved by an experiment nobody designed: the deploy landed during a run that started at 06:08, so one run processed the same search under both versions — the three affected products that had already passed stayed blank, the two that had not came out fully populated, and Shopify confirmed both within two minutes. The Local export finished with 11,054 records and 0 errors. Two knock-on updates: LT2-D20 is now unreachable by construction rather than dormant, because the fallback guarantees the brand rewrite always meets a set value; and LT2-D21 is unblocked — with the fallback in place, correcting the three guards is a measured no-op across all 19,225 rows and can ship on its own. Recorded against the flow: the script record still carries the V3.1 name while holding V3.2. |
— |
| 2026-09-23 | The fall-through fix sized, and two corrections. The replay was re-run with the three broken guards corrected and nothing else changed. 551 rows would newly lose their promise, and all 551 produce "Please contact showroom for lead time." today — by accident, via the broken guard. So a final catch-all setting exactly that wording changes what no customer sees, closes LT2-D6 for its 7 products, makes LT2-D21 safe to fix, and permanently defuses LT2-D20. One block, three defects, and it must ship before or with the guard fix, never after. Recorded with a before/after table. LT2-D20 corrected: an earlier review put 174 Ellison products at risk after a guard fix, reasoning from NetSuite's item and vendor tables that items without a preferred vendor would have blank lead times. The searches do not join the vendor that way — all 183 stockless Ellison rows arrive carrying oos="12" and mto1="19", and replaying with the guards fixed produced 0 Ellison fall-throughs. Its live population is zero, before and after. LT2-D7 corrected: a blank supply type does not fall to the contact-showroom wording — those 193 rows get real lead times, because supply type only gates the Made To Order and End Of Line rungs. It is data hygiene, not a lead-time defect. |
— |
| 2026-09-23 | Logic replay extended to full coverage — all 19,225 rows, all four searches, zero exceptions. The searches exceed the 4,000-row ad-hoc limit and the API caps a page at 1,000, so Local was paged in 12 calls and Imported in 6; the row counts match the flow's own export job counts search for search. 134,575 value comparisons, 100 differences, 99.93% agreement — and every one of the 100 traced to a cause, none of them a logic defect: 39 are quantity drift from stock received between the run and the read (NetSuite higher than computed in every case, never lower, which is the signature receipts produce), 37 are supply that changed after the run including four Arcola side tables created that morning and still seeded with placeholder wording, and 24 are LT2-D6. LT2-D6's population is now exactly seven named products, up from the two found in the partial run. LT2-D7 restated against the full set: 193 rows carry a blank supply type, 180 in Item Simple and 13 in Local, and every one processed without error. Recorded plainly: the logic is sound, the delivery is not — the replay says nothing about whether output reaches Shopify, which is LT2-D15, LT2-D18 and LT2-D19. |
— |
| 2026-09-23 | Logic replay — the ladder reproduces production exactly, and three corrections fall out of it. The live script, verified byte-identical to the deployed copy, was run over 2,993 live rows from the Rugs and Item Simple searches with every computed value diffed against what NetSuite holds. Zero exceptions, and all seven compared values match on every item bar three — two of them a known defect, one a genuine stock movement. The ladder this entry describes is the ladder that runs. LT2-D7 corrected: a blank supply type arrives as an empty string, not null, and upper-casing one is safe — 180 such items replayed without error, so the defect is latent (it needs the column to be absent) rather than live, and an earlier claim that 301 items each put the run at risk was wrong. LT2-D6 confirmed live with two named products, 235919 and 173803, both In-Store Only with no showroom stock. New LT2-D22: the McMullin 70-day backorder rule has never fired, because the brand list holds McMullin while the script tests for mcmullin & co. — 105 live products, dormant today because none has an ETA beyond 70 days. Also recorded: the replay's own trap, where the saved search returns list ids and Celigo receives display text, which produced four false findings until the ids were resolved. Coverage stated honestly at 16% — Local and Imported exceed the row limit available to an ad-hoc run, and Imported is the one carrying the arrival columns. |
— |
| 2026-09-23 | Ownership recorded, confirmed by the project owner: Back End Team for anything technical or calculation-related, Buying Team where a purchase order carries incorrect data — the test being whether correcting the purchase order in NetSuite would fix it. Every defect in this entry is the Back End kind, except that the 20 items under LT2-D19 also need their Shopify ids recorded. for_department corrected from Entire Life Interiors team, and the customer to Back End Team; the audience is unchanged and is stated in the business reading. Open question 8 closed. |
— |
| 2026-09-23 | First job-level validation of this chain, and four new defects. Six consecutive runs, zero errors, the script has never thrown — the JavaScript is not what is wrong here. Everything found sits in the wiring. LT2-D18: both Shopify imports ignore the response, and Shopify answers a rejected metafield with HTTP 200, so a rejection is recorded as a success — proven against a run that logged 365 successes for a variant whose metafield demonstrably does not exist. This is why LT2-D15 went unnoticed, and it blocks verification of every other fix here. LT2-D19: the router has no default branch, so a record with no Shopify id is discarded silently — 220 records a run, 20 of them live storefront products, measured by replaying the router's filters over live export data. LT2-D21: three of the four ladder guards compare text to a number and therefore never reject anything, confirmed from live runs where lead times arrive as "0" and ".5". LT2-D20: the Ellison Studios brand rewrite calls a text replacement without checking a sentence exists — dormant only because LT2-D21 keeps the last rung firing, and armed for 174 live products the moment LT2-D21 is fixed alone. LT2-D6 corrected: it is not reachable through the ladder, only through In-Store Only with no showroom stock. LT2-D16 narrowed on the project owner's confirmation that Local and Rugs omit the arrival columns deliberately while Item Simple carries them — an earlier reading to the contrary came from a cached sample, not the live search. Added a Verification against production section, a decision tree covering the route, the ladder, change detection and the Shopify split, plus a symptom-to-defect index. Four stale edge-case rows corrected, two stale diagram nodes rebuilt, and the flow's name in links: fixed from Lead times V2: Inventory to Lead times: Inventory. |
— |
| 2026-09-23 | Blank and zero both publish as nothing, confirmed by the project owner. NetSuite holds the two distinctly — 78,736 null against 1,198 explicit zeros — but the difference is provenance, not meaning: null is an item no open inbound line has ever been in scope for, zero is an item the flow cleared. Both mean nothing on order, so both publish as an absent metafield, which also removes 379 rows from the reconciliation that were never wrong. Worked examples added for all three states. Separately, the note about stale Shopify variant ids was rewritten: the item record carries a Shopify product status and 129586 is archived there while remaining active in NetSuite, which an earlier version of this entry got wrong by checking the wrong field. None of the four searches excludes archived items, so they are read, calculated and pushed to variants that no longer exist — a search criteria change rather than the data-cleanup project it was first recorded as. |
— |
| 2026-09-23 | Live three-way check across all nine metafields, and four confirmations. Compared NetSuite, the saved search and Shopify for a sample of items. Confirmed by the project owner: the match rule covers all nine metafields, not only the four arrival ones; publishing a negative on-order figure as zero is required rather than cosmetic, because other calculations do arithmetic on it; the two fields named qty_available_wh remain intended but are now flagged as a concern, possibly to be renamed, and must be excluded from any reconciliation meanwhile. LT2-D15 gained the finding that a change-detection fix alone is insufficient — a stable item never gets a first write, so a one-time backfill is needed, which the project owner will run manually. Two live gaps recorded: BE-ETH-AIR-VRNOAK holds 0 in NetSuite and no metafield in Shopify, and item 129586 points at a Shopify variant that no longer exists while remaining active in NetSuite. |
— |
| 2026-09-23 | Corrected a worked example in LT2-D17 that was not from production. The entry cited item 332634 as showing 27/10 in NetSuite against a message quoting 26/10. That figure came from replaying the flow's stored sample data through the script, not from the live system. Checked against NetSuite and Shopify the same day: NetSuite holds 27/10, the storefront message reads 27/10, and all four arrival metafields match NetSuite exactly — they agree, because the item has no spare bonded stock on hand. The defect stands as a reachable code path but is recorded as dormant, with no verified live example. |
— |
| 2026-09-23 | LT2-D17 reframed: the thirty-five day uplift in this flow is legacy, not a design tradeoff. The project owner confirmed that the uplift here predates the first-arrival field and that flow 1's date already includes it, so applying it again is an old workaround outliving its purpose. Evidence gathered the same day: exactly one item holds bonded stock available in Vietnam and it already carries a first arrival; no item has bonded on hand without one. The path can therefore only override a correct date, never fill a gap, which makes the fix a removal rather than a gate. LT2-D10 — the promise that recedes a day every day — is resolved by the same change, since nothing in this flow would recalculate from today any more. Recorded against LI-BL-INV-011 that its second job is being retired, and that this leaves the confirmed bonded-on-hand rule with no implementation — dormant rather than wrong, but a decision to take rather than drift into. |
— |
| 2026-09-23 | Two rules confirmed, and one of them turns into a defect. The project owner confirmed that the customer-facing message reads the first arrival — Shopify runs no logic of its own, it renders the sentences as given — and that a stale first arrival is dropped so the second is promoted into its place, the purpose being that everything downstream reads one field and never has to fall back to the second-arrival fields. Recording the first of those exposed LT2-D17: the code takes the earlier of the first arrival and a bonded-on-hand estimate, so on items with spare bonded stock the storefront shows a different date from NetSuite (332634 holds 27/10, the message quotes 26/10). Both open questions this entry carried on the subject are now closed. |
— |
| 2026-09-23 | Measured against a live NetSuite-to-Shopify audit, and three decisions recorded. The audit of 2026-09-22 puts arrival-data coverage at 115 of 1,489 items — 7.7%, with 1,374 items never pushed and 13 holding a stale quantity that is higher than NetSuite in all 13 cases. That re-ranks LT2-D15 as the largest defect in the chain and rules out LT2-D16's worst case, since the 13 prove the mutation reaches Shopify. Three confirmations from the project owner: the arrival metafields are internal visibility only, so NetSuite is the source of truth and the two systems must hold the same value; the dates stay the Shopify date type; and blank and zero are distinct — verified in NetSuite (78,736 null, 1,198 zero, 1,503 above zero), so the rule is implementable literally. LT2-D16 rewritten around that rule and now also covers the clear-down case, with BE-BEB-MARL-OAK-V3 recorded as the live example. A correction to this entry's own earlier guidance: wrapping the quantities in a presence test was proposed here and is wrong — omitting a value is not clearing it, and it would have produced the same stale state the dates already suffer. Also confirmed: no new Shopify import will be added; the fix stays inside this flow and the Kits flow. Audit read on 2026-09-22, NetSuite verified 2026-09-23. |
— |
| 2026-09-21 | Local (6212) confirmed by the project owner as drop-ship only, closing the one open question left by the row below it. Its missing arrival columns are now recorded as by design rather than observed. Both searches that omit them — Rugs (6220) and Local (6212) — are now confirmed rather than inferred. | — |
| 2026-09-21 | The four searches carry different columns on purpose, and LT2-D16 is narrowed to what is actually wrong. Confirmed by the project owner: Rugs (6220) is a drop-ship catalogue — nothing is ordered into our warehouse for it — so it has no Life arrival to report and the absent arrival columns are correct, not a gap. Local (6212) is observed to be the same (22 rows sampled across two offsets, all drop-ship, none carrying an arrival date) but that is not yet confirmed. Item Simple (6221) was the real exception: it holds Life Interiors warehouse-stocked items with genuine Sydney arrivals — 270451, 179681, 179676, 273604, 273605 among them — and the project owner added the three arrival columns to it on 2026-09-21; verified live the same day (179681 returns po1 25/9 qty 5, po2 19/10 qty 7). LI-BL-INV-009 now carries a table of which search holds what and why. What survives of LT2-D16 is narrower and unchanged in severity: both Shopify mutations guard the two arrival dates with a presence test but send the two arrival quantities unconditionally, so a genuinely drop-ship product pushes an empty value into a whole-number metafield. Whether Shopify rejects that field or the whole mutation is still unsettled. Searches read from NetSuite on 2026-09-21; last_reviewed already stands at that date. |
— |
| 2026-09-21 | Three confirmed rules that had landed nowhere are now recorded. LT-024 — all date maths uses the Australia/Sydney date — added to LI-BL-INV-006 as Which clock the dates are read on, with defect LT2-D14: four decisions in this flow read the server's UTC clock while only the schedule is set to Sydney, so they can land a day out. LT-081 — customer-facing wording and date changes are signed off by the CS lead — added to LI-BL-INV-006 as Who signs a change off, recorded as a process rule with no system enforcement. LT-052 — stale and showroom transfer orders do count in Quantity On Order — added to LI-BL-INV-011, explaining why that figure and flow 1's arrival date can disagree without either being wrong. All three were found by building the crosswalk in flow 1, which this entry now links to. LT-024 and LT-081 were not re-verified against production beyond reading the deployed script, so last_reviewed is unchanged. |
— |
| 2026-09-21 | Brought up to V3.1 and re-verified end to end. The script in production is now Lead Time: Inventory V3.1 Sep 2026 - bonded wh (6ab0c6e6…), deployed 2026-09-21 05:55 and hooked to all four exports; V3.0 (6a83c034…) is retained unreferenced as the rollback. LI-BL-INV-011 rewritten: it no longer recalculates the arrival date, and now describes its two genuinely separate jobs — bonded netting, which is unchanged, and contributing the single arrival flow 1 structurally cannot see, namely bonded stock on hand with no transfer order. The two removed behaviours are recorded there: flow 1's date being dropped whenever NetSuite's net location on-order was zero or below, and the 35-day transit being added a second time to a field that deliberately includes transfer-order-allocated stock. LI-BL-INV-006 corrected from eleven change-detection values to eight, and the claim that the arrival date is among them removed — it is neither compared nor written to NetSuite by this flow. Added the reserved P2 gap in the ladder, and defects LT2-D12 (supplier wins on identical dates) and LT2-D13 (band and sentence measured from different days). LI-BL-INV-009 corrected from five Shopify values to nine, with the four arrival values added to both mutations on 2026-09-21, plus defects LT2-D15 (four values have no change detection) and LT2-D16 (three of four searches do not supply the arrival columns — unresolved). LT2-D4 and LT2-D8 closed against the live configuration. Flow, all four exports, all three imports, the script, run statistics and the Shopify metafield definitions read from Celigo, NetSuite and Shopify on 2026-09-21, so last_reviewed is bumped. |
— |
| 2026-09-11 | Recorded a fifth Shopify metafield on the push: custom.qty_available_wh, written to both the product and the variant from the warehouse on-hand total. Shopify metafield definitions verified live on 2026-09-11 — number_integer on both owner types, zero values written at the time of checking. LI-BL-INV-009, the outputs table, the worked example and the diagram now say five values rather than four. Two traps recorded against the field: it counts our own two warehouses only, so it is not the quantity the storefront sells against; and the NetSuite field of the same name means Life plus supplier, so the two disagree by design. Change detection has no comparison for it, so it fills in as stock moves. Only the new field was verified against production, so last_reviewed is unchanged. |
— |
| 2026-08-31 | Placed on the order journey: journey_stage: supply (Supply), the stage confirmed with the business. The Organisation Map now groups and orders entries by journey stage rather than by folder. Front-matter only — no logic change, and last_reviewed is unchanged. |
— |
| 2026-08-21 | Restructured to the current registry shape: the business reading now answers what / why / who / when / how it decides / outcomes in that order; the developer reading gains worked examples, test cases, UAT, known limitations as named sections. Front-matter: version removed (nobody kept it accurate), replaced by documented_on / documented_updated for this page and script_created / script_updated for the source; links: added so the saved searches and flows are one click away. Script dates read from Celigo on 2026-08-21 (flow 66e0e59d, created 2024-09-11, last modified 2026-08-21). Saved-search names moved from the body into links:. No logic change, and last_reviewed is unchanged. |
— |
| 2026-08-21 | Linked the entry to the glossary: 19 terms recorded in terms:, including the three the bonded change introduced — bonded netting, resolved Sydney landing date and oversold. Four terms this entry depends on have no definition anywhere — Made To Order 1, Made To Order 2, End Of Line and Seasonal Only — and nothing records what separates the two Made To Order rungs; they are now visible as gaps rather than assumed. Removed a stray </content> tag at the end of the file, which was rendering as an empty row on the published change-history table. Vocabulary and rendering only — no logic change, and last_reviewed is unchanged. |
— |
| 2026-08-21 | Verified directly against the live Celigo flow. The bonded change is confirmed deployed — all four exports now run script V3.0. LT2-D2 and LT2-D9 resolved: search 6221 now returns shopifyItemType, and all four searches now carry the bonded columns |
— |
| 2026-08-18 | Confirmed live in production; status draft → active. Added links to the Celigo flow and all four saved searches |
— |
| 2026-08-18 | Bonded-warehouse change documented. New rule LI-BL-INV-011; the arrival date now means "lands in Sydney" and is resolved before the ladder runs; backorder now counts unallocated bonded stock; Gold Coast added to the showroom total. LT2-D3 and LT2-D5 resolved; LT2-D8 to LT2-D11 raised |
— |
| 2026-08-17 | Initial documentation of flow 2 from the Celigo export, verified against NetSuite and all four saved searches. Rules LI-BL-INV-006, LI-BL-INV-008 and LI-BL-INV-009 recorded; defects LT2-D2 to LT2-D7 raised |
— |
Field registry — ids
Inputs
| Field id | Field name | Record | Source | Type | Read / written | Used by |
|---|---|---|---|---|---|---|
internalID |
Internal ID | Inventory Item | Saved searches 6212 / 6186 / 6220 / 6221 | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
supplyType |
Supply Type | Inventory Item | Saved searches | select | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
brand |
Brand - Life Interiors | Inventory Item | Saved searches | select | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
qtyAvailable_warehouse |
Qty Available (Warehouse) | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_warehouse2 |
needs confirming | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
qtyOnOrder_warehouse |
needs confirming | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
new_receiveDate |
Next Available Receive Date | Inventory Item | Saved searches | date | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Bonded stock on hand, and paying off the backorder firstLI-BL-INV-011 |
supplier_receiveDate |
Supplier Next Available Receive Date | Inventory Item | Saved searches | date | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
supplier_qtyAvailable |
Supplier Quantity On Hand | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 Publishing to Shopify — product or variantLI-BL-INV-009 |
supplier_qtyOnOrder |
Supplier Quantity On Order | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Whether an out-of-stock item can still be orderedLI-BL-INV-008 Publishing to Shopify — product or variantLI-BL-INV-009 |
supplier_isDropShip |
Drop Ship | Inventory Item | Saved searches | checkbox | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
supplier_defaultInStockLeadTime |
Default In Stock Lead Time | Inventory Item | Saved searches | float | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
supplier_defaultOutOfStockLeadTime |
Default Out Of Stock Lead Time | Inventory Item | Saved searches | float | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
supplier_defaultMadeToOrderLeadTime1 |
Default Made To Order 1 Lead Time | Inventory Item | Saved searches | float | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
supplier_defaultMadeToOrderLeadTime2 |
Default Made To Order 2 Lead Time | Inventory Item | Saved searches | float | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_syd |
Qty Available (Syd) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_mel |
Qty Available (Mel) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_bris |
Qty Available (Bris) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_gc |
Qty Available (Gold Coast) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_bonded |
Qty Available (Bonded Warehouse) | Inventory Item | Saved searches | integer | read | Bonded stock on hand, and paying off the backorder firstLI-BL-INV-011 |
qtyOnOrder_bonded |
needs confirming | Inventory Item | Saved searches | integer | read | Bonded stock on hand, and paying off the backorder firstLI-BL-INV-011 |
new_receiveDate_bonded |
Next Available Receive Date (Bonded WH) | Inventory Item | Saved search 6186 only | date | read | Bonded stock on hand, and paying off the backorder firstLI-BL-INV-011 |
imported |
Imported | Inventory Item | Saved searches | checkbox | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
shopifyProductID |
needs confirming | Inventory Item | Saved searches | string | read | Publishing to Shopify — product or variantLI-BL-INV-009 |
shopifyVariantID |
needs confirming | Inventory Item | Saved searches | string | read | Publishing to Shopify — product or variantLI-BL-INV-009 |
shopifyItemType |
needs confirming | Inventory Item | Saved searches 6212 / 6186 / 6220 only | string | read | Publishing to Shopify — product or variantLI-BL-INV-009 |
current_shipsIn |
Ships In | Inventory Item | Saved searches | select | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_inStockLeadTime |
In Stock Lead Time Message | Inventory Item | Saved searches | string | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_onOrderLeadTime |
On Order Lead Time Message | Inventory Item | Saved searches | string | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_outOfStockLeadTime |
Out Of Stock Lead Time Message | Inventory Item | Saved searches | string | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_qtyAvailable |
Qty Available To Sell On Website | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_qtyOnOrder |
Qty On Order Available To Sell On Website | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_qtySR |
needs confirming | Inventory Item | Saved searches | integer | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
current_allowBackOrder |
Shopify Enable Out Of Stock Selling | Inventory Item | Saved searches | checkbox | read | Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
current_receiveDate |
Next Available Receive Date | Inventory Item | Saved searches 6212 / 6220 / 6221 only | date | read | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
Outputs
| Field id | Field name | Record | Source | Type | Read / written | Used by |
|---|---|---|---|---|---|---|
qtyAvailable_syd |
Qty Available (Syd) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_mel |
Qty Available (Mel) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_bris |
Qty Available (Bris) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
qtyAvailable_gc |
Qty Available (Gold Coast) | Inventory Item | Saved searches | integer | read-written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_ships_in |
Ships In | Inventory Item | NetSuite | select | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_ships_in_celigo |
In Stock Lead Time Message | Inventory Item | NetSuite | string | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Publishing to Shopify — product or variantLI-BL-INV-009 |
custitem_next_receive_date_celigo |
On Order Lead Time Message | Inventory Item | NetSuite | string | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Publishing to Shopify — product or variantLI-BL-INV-009 |
custitem_out_of_stock_message |
Out Of Stock Lead Time Message | Inventory Item | NetSuite | string | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Publishing to Shopify — product or variantLI-BL-INV-009 |
custitemcust_receive_date |
Next Available Receive Date | Inventory Item | NetSuite | date | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_qty_available_wh |
Qty Available To Sell On Website | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Publishing to Shopify — product or variantLI-BL-INV-009 |
custitem_qty_on_order |
Qty On Order Available To Sell On Website | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 Publishing to Shopify — product or variantLI-BL-INV-009 |
custitem_qty_available_warehouse |
Qty Available (Warehouse) | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_qty_available_syd |
Qty Available (Syd) | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_qty_available_mel |
Qty Available (Mel) | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_qty_available_bris |
Qty Available (Bris) | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_qty_available_gc |
Qty Available (Gold Coast) | Inventory Item | NetSuite | integer | written | The lead-time ladder, and the words the customer readsLI-BL-INV-006 |
custitem_celigo_shopify_enable_out_sto |
Shopify Enable Out Of Stock Selling | Inventory Item | NetSuite | checkbox | written | Whether an out-of-stock item can still be orderedLI-BL-INV-008 |
custom.in_stock_lead_time_message |
needs confirming | Shopify product / variant metafield | Shopify | single_line_text_field | written | Publishing to Shopify — product or variantLI-BL-INV-009 |
custom.on_order_lead_time_message |
needs confirming | Shopify product / variant metafield | Shopify | single_line_text_field | written | Publishing to Shopify — product or variantLI-BL-INV-009 |
custom.out_of_stock_lead_time_message |
needs confirming | Shopify product / variant metafield | Shopify | single_line_text_field | written | Publishing to Shopify — product or variantLI-BL-INV-009 |
custom.quantity_on_order |
needs confirming | Shopify product / variant metafield | Shopify | number_integer | written | Publishing to Shopify — product or variantLI-BL-INV-009 |
custom.qty_available_wh |
Qty Available Warehouse | Shopify product / variant metafield | Shopify | number_integer | written | Publishing to Shopify — product or variantLI-BL-INV-009 |
Hover any box to see what it means. Click to pin it.