Bugs in Shopify's Returns Admin and Webhook

Seems to be at least one if not two bugs in the returns system when refunding/restocking multiple units of the same product variant / line item, when processing refunds for different units independently and selecting different restock options.

A) Choosing to restock one unit, then choosing not to restock another unit in a separate refund, results in being able to restock all units at a later time (duplicating the restock for any previously restocked units).

B) The shopify/returns/create webhook contains incorrect restock and restock_type values, seemingly using the values for the previous line item refund and not the current one. (TBF I’m getting the webhooks through an app which might be the source of the issue, so interesting to see if others can replicate).

To replicate either, follow the below:

Purchase 3 x same variant

  • product page stock correct, was 5 avail, now 2 avail, 3 com

Fulfil all 3

  • stock correct, 2 avail

Initiate return for 2 of 3.

Process Return for 1/2, select Restock

  • stock correct, 3 avail
  • shopify/refunds/create webhook correct (restock = true, refund line items: qty = 1, restock type = return).
  • order page correctly shows 1/2 returned.

Process Return again, for 1/1 but DON’T select restock.

  • stock correct, 3 avail
  • webhook now incorrect; same as initial return (restock = true, refund line items: qty = 1, restock type = return).

Click Restock, select 2 of 2.

  • Incorrectly allows restock of 2 units, despite 1 already having been restocked.
  • stock incorrect, 5 avail (should be 4)

Restock fulfilled item, for 1/1 and select Restock

  • webhook incorrect; uses the webhook that should have been present in previous return (restock = false, refund line items: qty = 1, restock type = no_restock).
  • stock correct, 5 avail (likely will be incorrect after further items are refunded/restocked)

EDIT: After a bit more testing, seems the webhook issue is that after refunding a line item unit with a restock, any future refunds for the same line item will also show as a restock (restock = true and restock_type = return) whether or not the restock option is chosen with them.
If a non-restock refund is done first, this isn’t an issue, until a restock refund is done.
Also doesn’t affect anything other than the webhook as far as i see (stock counts don’t change incorrectly in admin).

EDIT 2: narrowed the webhook issue down to the API restock and restockType values being unique to a RefundLineItem, but NOT to a unit within that, and once set to REFUND / restock=true, will not set back to NO_RESTOCK.

Which means any webhooks or future queries to the line item within a refund, once one of the units has been restocked, will not differenciate between restocked and non restocked units even when querying the unique RefundLineItem object (they’re all show as restocked if one of them has been).

So… that’s probably as designed, and would need SF to change or add an additional value in the RefundLineItem object to correctly query units of the same line item for their actual restock status.

Have a feeling the ability to restock more items than you sold is also by design, just dumb.

1 Like

So far most accurate way of dealing with returns I’ve found is this:

  • Subscribe to both shopify/refunds/create and shopify/reverse_fulfillment_orders/dispose.

  • If return=null in shopify/refunds/create, the restock values are accurate.

  • If return !=null, ignore as the restock values are inaccurate (tied to the line item not unit) in preference of…

  • shopify/reverse_fulfillment_orders/dispose will trigger if shopify/refunds/create return != null and there was a restock, giving correct unit qty.

  • shopify/reverse_fulfillment_orders/dispose will not trigger if there wasn’t a restock involved.

Also, never use the inline restock qty in admin (see pic) for previously refunded but not restocked item, as it’s basically just a shortcut to available inventory and doesn’t trigger any webhooks to suggest it’s a restock of a returned item (and it lets you restock more units than exist).

And if the order’s only partially fulfilled when any of this happens, afaict it all goes fubar.

Hey @pepsi_max2k, thanks for the reports here. It looks like you have been able to resolve most of the issues here. To make sure I’m not missing anything, can you clarify what issues are still remaining and steps I can take to replicate?

Have you looked in to the new return processing options? This release has cleared up some of the frustrations with the returns process.

Thanks @KyleG-Shopify - unfortunately it’s still acting odd despite CS’s insistence they fixed it.

The refunds/create webhook still contains restock=true regardless of whether an individual refund contained a restock (don’t know if this is buggy or by design as linked to the one line item, but you’d assume it could provide the correct restock value if it includes the correct unit count).

Also yes I’m trying via the reverse_fulfillment_orders/dispose webhook but this is also (possibly) buggy and doesn’t trigger consistently. Usually only if there’s a change of units being restocked - if you restock 1, don’t restock the next, restock the next, it’ll only trigger on the first and not the 1st and 3rd as I’d expect. Maybe it’s tied to another line-item-only type thing idk.

So yeah I’ve no idea how to consistently get correct restock data via webhooks.

To replicate, do as above screenshots on any item, or simpler: Just buy multiple units of the same variant (eg. 10), initiate a return, then start refunding one by one, alternating between not restock and restock. You’ll see the refunds/create webhook get stuck on restock=true after the first restock (possibly resets if you start refunding different qty of units at once). And dispose webhook fires whenever it wants, not whenever there’s a restock (although it’s never fired when there’s been no restock, thankfully).

EDIT:

Ok seems the restock data in the refunds webhook is a known issue due to semi-deprication.
See Is restock_type field reliable for handling refunds? - #3 by arsuceno - Shopify Community CS “This is why you are getting [incorrect restock value] now, as restocks done on Admin are no longer done under a refund mutation, but instead under a reverseFulfillmentOrderDispose mutation.
And Shopify Native Exchanges “Restocking through the Return APIs means means moving away from restocking though the Refund API and will result in static restock values within the refund object of an order” (no source)

So guessing as soon as you restock it starts using the return api and the restock data gets messed up?

Which would be fine if the dispose webhook triggered on every disposal, but it doesn’t (buggy?), and seems no way to query a specific disposal from any of the refund / returns webhooks that do.

Thank you. I think I was able to replicate this.

First issue, I noticed is that if I have multiple restock types in a single return, that all of the refund create webhooks return as restock true, even on the ones where restock was not selected.

Second issue, I only received a single dispose webhook per return, when I had multiple dispositions on that return.

Does that summarize what you are seeing or am I missing anything?

That seems about it - seems to vary slightly on the combination of returns, fulfilment and restocks but testing it all just got confusing. Assuming all stems from the same bug/design.

Also the issue of being able to restock more than you sold through admin, you can still restock units tha have essentially been restocked already, but they may well be by design somehow. But that’s a minor issue (no different from someone manual adjusting available stock really).

Thanks for confirming that. I’ll let you know what I find out.

1 Like

Hey Christopher,

Closing the loop here, we have created an internal issue to look in to why this is happening. I don’t have a timeline on a fix at this point, but I’ll keep an eye on it and update here when there’s movement.

Thanks again for reporting that and the great details you’ve shared.

Kyle do you know if this was ever corrected (or confirmed intended behaviour)? Not tested since I reported but be nice to thing it’s just magically working now :smiling_face:

Thanks for sharing that it’s working now. The issue I was tracking is still not resolved, so it could have been an unrelated update that ended up fixing this. I’ll look in to this and see if I can confirm that for you.

Can you confirm whether you’re seeing the correct webhook payload now, or just that their inventory isn’t being incorrectly restocked.

I can confirm the inventory behaviour is correct ( and that could lead to the web hook being correct) so I want to confirm if you’re seeing both resolved.

Hey sorry I meant I haven’t tested yet - I don’t know if it’s fixed. Was wondering if you could confirm, but I’ll check it out and see if I can replicate the initial issue again.

No worries. Sounds like it is, but curious to know in your tests if you see different.

Hey Kyle, looks like no changes to original issues - just tried the replication steps from op and exact same issues.

  • Can still restock more units than were ever dispatched under noted circumstance.

  • shopify/refunds/create webhook still seemingly lags by x1 (after first refund of line item, future refund webhooks give the previous refund’s status)

    Unless I’m just reading the webhooks wrong. FWIW I sort of worked around it by the following….

- Subscribe to both shopify/refunds/create and

  • shopify/reverse_fulfillment_orders/dispose.
  • If return=null in shopify/refunds/create, the restock values are accurate.
  • If return !=null, ignore as the restock values are inaccurate (tied to the line item not unit) in preference of…
  • shopify/reverse_fulfillment_orders/dispose will trigger if return != null and there was a restock, giving correct unit qty.
  • shopify/reverse_fulfillment_orders/dispose will not trigger if there wasn’t a restock involved.

which worked great until I found even shopify/reverse_fulfillment_orders/dispose wasn’t triggering every time it was meant to. maybe that was fixed but I forget how I even tested that one :frowning:

Thanks for testing that @pepsi_max2k. So the original issue we reported is still open and I’ll keep an eye on that and we can run it all through again once there is movement on that fix.

Really appreciate you taking the time to confirm that.