v0.1.17 Release

Shopify Inventory Sync, Now Actually Catching Up Every Few Minutes

The Shopify delta inventory webhook shipped in v0.1.15 finally has the SKU lookup it needs to apply real adjustments. Every existing Shopify product is mapped on the first n8n sync after deploy, and from then on every Shopify-side stock change lands in the WMS within seconds. Plus a clear audit trail and a much friendlier way to watch the flow from the terminal.

When v0.1.15 turned on real-time Shopify inventory webhooks, every event was technically arriving, getting verified, and… being silently skipped. The webhook payload only carries a numeric inventory_item_id (not the SKU), and the lookup table that translates it to SKU was empty on every fresh deployment. So nothing actually adjusted.

This release closes that gap and adds a couple of operator-facing niceties on top.

The catch-up happens on the next sync

The existing VaporDNA Inventory Sync (Shopify) connection that runs every 30 minutes already iterates every Shopify product to keep prices and locations in step. We've extended it to also seed the inventory_item_id ↔ SKU lookup table on every run.

The first time the cron fires after this deploy (or you click Sync Now in Settings → Sync Connections), the entire Shopify catalogue gets mapped in one pass — roughly 12,000 SKUs in a few seconds. From the next webhook onward, every Shopify-side stock change resolves to a real product and adjusts the WMS accordingly.

For the rare cases where a Shopify SKU's ID comes through in the longer GID format (gid://shopify/InventoryItem/44899547054139), we normalise it down to the same numeric ID the webhook payload uses, so both ingest paths land on the same row.

What you'll see on the order side

Every applied delta records two things: a real inventory adjustment row (audit trail) and an activity feed entry on the affected product.

Activity Logs filtered to Shopify delta entries — applied removes, an applied add, and one skipped-and-flagged case

Three outcomes you'll see in the feed:

  • Inventory Adjusted — Shopify Delta — the common case. Description spells out the math, e.g. "Shopify reported 245, WMS had 250, delta -5 removed from G-2-3."
  • Inventory Adjusted — Shopify Delta with delta +N — Shopify is ahead of the WMS, so we add the difference to the primary location.
  • Shopify Delta Skipped — No Location Holds Enough — the safety guard. Shopify wants us to remove more than any single location holds, so instead of pushing a location negative we skip the adjustment and flag it for manual reconciliation. These should be rare and worth eyeballing when they appear.

Search the global activity log for Shopify Delta to pull the audit trail at any time.

A friendlier way to watch the flow

Bundled in this release: Laravel Pail for real-time log tailing. Replaces the brittle tail -f storage/logs/laravel.log | grep … flow with a single artisan command that pretty-prints structured payloads, colours by log level, and filters cleanly.

Some commands that pair well with the new visibility logs:

# Everything Shopify is doing right now
php artisan pail --filter="Shopify inventory_levels"

# Just the deltas that landed (applied_add / applied_remove)
php artisan pail --filter="applied_"

# Just the safety-flag skips (worth eyeballing when they fire)
php artisan pail --filter="Shopify Delta Skipped"

# The n8n puller — when it ran and how many mappings it seeded
php artisan pail --filter="Inventory sync ["

# Or zoomed out, levelled
php artisan pail --level=warning

Works identically on local, staging, and production. No setup beyond composer install after pulling this release.

Heads-up: data-hygiene side effect

When the first wave of Shopify deltas lands you may notice a chunk of adjustments routing to a location called (Unspecified) rather than a real warehouse bin. That's the catch-all the WMS uses for products that don't have a proper warehouse location attached yet — the delta math is correct, it's just landing in the unassigned bucket.

Easiest cleanup: pull a quick report of products whose primary location is (Unspecified), assign them to their real bins in Product Management, and from then on Shopify deltas will route to the right place automatically.