Covers all questions related to inventory management, order fulfillment, and shipping.
Hi,
Our fulfillment service app makes inventory adjustments based on various factors. One is when an order is placed in the WMS from a source other than Shopify. We were recording these in Shopify with the "reservation_created" reason so they could easily be distinguished in the adjustment history from other reasons for adjustment. However, we recently discovered that these adjustments seem to actually create a reservation that is not visible anywhere in the Shopify UI or the API rather than just adjusting the on hand amount. So if we report 493 units on hand but previously reported -93 units with a "reservation_created" reason, then those 93 units will forever be unavailable and Shopify just shows 400 on hand. We're calling this "phantom reserved inventory" because the only evidence that it exists is that Shopify's on hand number is lower than ours by that amount.
We might have found a workaround but it is very inconsistent.. We noticed in a few cases if we disable "Track quantity" for a product and then later enable it, the inventory returns back to normal. But often times this doesn't work and it goes back to having phantom reserved inventory when tracking is enabled again.
We probably misused this "reservation_created" reason and have ceased using it in favor of "other" since that is the only other reason that fits. But now we can't find a way to recover this phantom inventory for over 70 Shopify stores and hundreds or thousands of SKUs.
I've attached a couple screenshots showing that the inventory reported by Shopify via GraphQL and the Admin UI for SKU C0007 is 400 while the "reserved" is 0, but our "fetch_stock.json" response clearly returns 493 which is the true number. So the 93 units are missing from Shopify with no way to recover them.
GraphQL API:
Admin UI:
Fetch stock callback:
Please advise, how can we get these reserved units back to available?
Thanks!
Colin
Solved! Go to the solution
This is an accepted solution.
Hi Colin,
Those cases seem to be a cases of mismatched data. We are investigating those. What is happening is that the committed value does not correctly reflect open fulfillment orders.
However, it should not matter soon as we will be slowly rolling out a more generic fix to the fetch_stock sync. It will now correctly set whatever value it receives as on_hand value, meaning available will get adjusted accordingly based on committed / unavailable inventory.
Richard
Hello Colin,
I have checked your situation, and I am not mistaken I believe you were using the inventorySetOnHandQuantities mutation, with the reason "reservation_created".
That mutation is used to edit your "on-hand" quantities directly, to keep the most accurate information about how many units you have present, and it directly affects "available".
available = on-hand - committed - unavailable
The reason field on the mutation can be viewed as a text field that is just attached to the change. It does not bear any logic and even if you use "reservation_created" it will not create a reservation per se, it will just edit quantities and attach the message to the change.
(same as you were to just change available or on-hand in admin - no reservation created)
I believe what you are looking for is the inventoryMoveQuantities mutation which allows you to move inventory from available to reserved, which should fit your use case better.
The example describes how to move from available to reserved, which is exactly what you are looking for, with the reason damaged (which you can change to "reservation_created")
As a major difference from the setOnHand mutation, you will need referenceDocumentUri and ledgerDocumentUris for the individual changes.
Your moved quantities will then be shown in the Unavailable column and you should see your app in the breakdown.
To solve your current situation, where the stock have been reduced by the amount you intended to reserve, you will first need to increase the stock amount using the inventorySetOnHandQuantities back to the original value, and then move it to reserved state using inventoryMoveQuantities.
Hope this helps.
Richard
Hi Richard,
Thanks for looking into this and your reply.
@Richard_L wrote:I believe you were using the inventorySetOnHandQuantities mutation, with the reason "reservation_created".
I checked the logs to be sure and we were only using `inventoryAdjustQuantities` mutation for these updates, not `inventorySetOnHandQuantities`. Here is a sample request from the logs:
{"query":"mutation ShipStreamMutation($input: InventoryAdjustQuantitiesInput!) {
inventoryAdjustQuantities(input: $input) {
userErrors {
code
field
message
}
}
}","variables":{"input":{"name":"available","reason":"reservation_created","changes":[{"delta":-1,"inventoryItemId":"gid:\/\/shopify\/InventoryItem\/33337217056841","locationId":"gid:\/\/shopify\/Location\/64510001225"}]}}}
Is this valid to adjust the "available" amount rather than the "on_hand" amount?
I actually don't want to create any reserved/unavailable inventory because these adjustments are just to keep Shopify in sync when non-Shopify orders are received. That is, the units were sold through another channel so are never expected to become available again and are already deducted from the available amount which will be reported to `fetch_stock.json` the next time it is requested - I just want to "push" the update sooner rather than wait for Shopify to "pull" that adjustment.
I tried using `inventorySetOnHandQuantities` to update the inventory by reporting 481 units on hand with reason being "correction". That resulted in an adjustment of +93 which is what I wanted, but then shortly after, Shopify ran the `fetch_stock.json` which also returned 481 units (verified with logs) but Shopify made a -93 adjustment so I'm back to square one with 93 phantom units missing from Shoipify's available/on_hand amount.
So it's like Shopify is computing:
on_hand = reported - 93
or:
available = on_hand - committed - unavailable - 93
So I've tried adjusting both the available amount and the on hand amount and neither of them stick so I don't see how this isn't a bug or corruption in the Shopify inventory?
Thanks,
Colin
Hi Colin,
Just to make sure I understand correctly.
You are creating orders out of shopify and the aim is just to set the new inventory quantity. Those orders will not be created inside shopify?
I will need to explore the fetch_stock.json. I have noticed the following post which seems to be related. It doesn't seem to be behaving as intended.
I will enable a fix within the next week for the shop used on examples here, which should eliminate this.
What seems to be happening is the fetch_stock.json is incorrectly setting available quantity by subtracting you open fulfillments which at the time of your request were set to 118.
Meaning 481 - 118 = 363 which is the new available after change.
Thanks, Richard. Your understanding is correct, we just want to update Shopify inventory immediately rather than wait for the next hourly sync to avoid oversells.
I had a support ticket open with Dan T. in which he stated that some changes and data corrections were made so I thought we had it resolved but it appears there is still more phantom inventory even on SKUs where the data corrections entries appear in the adjustment history. The problem he described is different to what I originally thought was the issue as it appears to only have something to do with fetch_stock.json and not the reservation adjustments.
As a current example, we report 776 units for the SKU C0005 (gid://shopify/InventoryLevel/4638867491?inventory_item_id=7238539968547), but Shopify shows 753 on hand with 37 committed. There is no explanation for the 23 units difference between the 776 we report and the 753 Shopify says are on hand. We expect Shopify should have 776 on hand just as we report to fetch_stock.json in the response.
As a workaround, what would happen if we returned an empty array to fetch_stock.json and then just pushed our own updates to keep it in sync? I'd hate to do that as it wouldn't be able to account for race conditions but as there are still a lot of SKUs affected I think that would be better for us until this is fully resolved.
Thanks,
Colin
This is an accepted solution.
Hi Colin,
Those cases seem to be a cases of mismatched data. We are investigating those. What is happening is that the committed value does not correctly reflect open fulfillment orders.
However, it should not matter soon as we will be slowly rolling out a more generic fix to the fetch_stock sync. It will now correctly set whatever value it receives as on_hand value, meaning available will get adjusted accordingly based on committed / unavailable inventory.
Richard