GraphQL issue with deprecation of ExchangeV2 in favor of Returns

ISSUE: Exchange line items on a return need the location ID.

Using returns on the Order object to determine location is not fully compatible with exchangeV2s and requires an excessive amount of query cost.

Replacing exchangeV2s with returns has the following behavior:

Exchange scenario: Uneven POS exchange (money moved)
ExchangeV2.location: Store
Transactions only: Matches. The payment or refund transaction is processed at the store, and Return.transactions is scoped to order transactions created from the return.
Dispositions and transactions: Matches.

Exchange scenario: Even POS exchange, restocked
ExchangeV2.location: Store
Transactions only: Missed. A zero-dollar balance moves no money, so no transaction exists. The store only appears on the restock disposition.
Dispositions and transactions: Matches.

Exchange scenario: Even POS exchange, not restocked
ExchangeV2.location: Store
Transactions only: Missed.
Dispositions and transactions: Missed. There is no transaction or disposition, so nothing on Return carries the location.

Exchange scenario: Online or admin exchange
ExchangeV2.location: Null
Transactions only: Null. Transaction location is physical or POS only.
Dispositions and transactions: Can over-report. A warehouse restock disposition yields a location where exchangeV2s had none.

The even-restocked scenario is probably the biggest problem. An even swap, such as a size or color change, is one of the most common POS exchanges.

Hey @Sam - thanks for flagging this.

Just confirming, have you checked the outbound fulfillment path as well? Return.exchangeLineItems.lineItems should let you match the exchange line items against Order.fulfillments.fulfillmentLineItems.lineItem.id. From there, Fulfillment.location represents where the replacement item was processed.

I’d expect that to cover the even POS, not-restocked scenario, since no transaction or return disposition is created, but the replacement item is still fulfilled. ReturnAgreement.app may also help distinguish POS exchanges from Admin/API exchanges.

Could you share an example response where an even, not-restocked POS exchange has no matching fulfillment or fulfillment-order location? If you have an x-request-id for that request from the response headers, that would be super helpful.

I definitely get that this is more involved than the old ExchangeV2.location, though, so happy to dig into things further.

Hi Alan,

Thanks for the reply. I chatted with Partner Support today and I pasted their final conclusion below. Not sure if you can help push it along? But even once addressed, the queries will come at a much higher cost than the current ExchangeV2 solution.

"Our team confirmed this is a known gap. When no money moves and no disposition is created on an even POS exchange without a restock, there’s no way to infer location. We are working on adding this, so for now, continuing to use exchangeV2s is the best path forward. Since you already have access, the most accurate approach is to keep querying exchangeV2s in parallel with returns specifically for location resolution, and migrate fully once the parity gap is addressed”

“I genuinely appreciate you bringing this to our attention and patience while we looked into this. We don’t have a timeline yet, but once this is addressed it will show up in the Shopify developer changelog

Hey @Sam - thanks for sharing that confirmation. You’re right , the fulfillment path I mentioned isn’t a the best replacement for ExchangeV2.location. It represents where the outgoing item is routed or fulfilled, which isn’t necessarily the POS location where the exchange originated, sorry about the confusion there, I think I misunderstood your use case there. My apologies!

For now, continuing to query exchangeV2s alongside returns specifically for location resolution is the safest workaround while you still have access.

I did some digging internally and it does look like we have this tracked as an improvement to make on our end though. If you can share a representative redacted query and its extensions.cost block, that would help quantify the migration impact. I don’t have a timeline to share, but I’ll loop back here if I get a concrete update or if I have anything else to share.