You can create a Draft Order with GraphQL, and you'll get back a valid GID. Great. For convenience sake, let us assume you did not want to hassle the merchant to actually convert that Draft Order to a real order, it is after all, ready to go to the person designated to pay for the order and its contents.
The sketchy thing going on here is this: Shopify has to actually play and build this Draft Order and just because you have an ID, does not mean you can complete the Draft Order!!
Wow. Who knew? You can inspect your call to see the Draft Order Complete and you'll discover this little ditty: This order has not finished calculating, please try again later
So now we are once again in territory and turf where for all intents, you get handed a 200 OK from some asynchronous call to do something, you get an ID, but the reality is, nothing is settled yet. So what to do there. Run the completion in some background job set to run in an arbitrary 30 seconds later?
This reminds of getting Shopify Orders without customer records, or shipping address or other crucial things you would not expect to see.
Logically I would expect an API service to pass back the response only _after_ the request has been fulfilled on the back-end. Whether creating a new record, modifying an existing record, deleting an existing record, etc.
Of course if there is a processing delay on the back-end this could result in a rather ugly synchronous client hang, but at least when the API response comes back the result is a done deal.
I am simply the messenger here. It seems Draft Order create will indeed respond with a 200 OK and an ID, for a resource that is not yet actually built. Which leads to further confusion when you provide the Draft Order Complete with said ID, and it responds with the "Sorry but this resource is still under construction, try again real soon now"...
I have seen this is other places too. The classic was creating a smart collection with API calls. Shopify would return a 200 OK, and you'd think you'd be in business, but in fact all you've done is spun up a background job in the Shopify machine, and that collection may not actually be ready for any use for a good many minutes. In that case, that does make some sense, but the responsible thing there would've been to wrap that process in a polling style similar to bulk operations. The voyage of discovery! This kind of stuff must crush N00bs in their quest for knowledge and automation.
Would it not make sense to have this call to draftOrderCreate provide a default attribute of complete: false that we can set to true, so that once Shopify gets around to actually creating and calculating the order, they can also do the complete action? Eliminates a pain point for sure, neatens up the process and saves us the hassle of polling.
So far no comment from Shopify on this?
We also extensively use Draft Orders to model checkouts in our application.
Things like assigning a shipping address to a Draft Order will cause the Draft Order to be incomplete and processing after the update call. But as far as I know, this state is represented correctly in the Rest API using the HTTP status code 202 Accepted.
I think this behavior is modeled using the DraftOrder.ready attribute in GraphQL: https://shopify.dev/docs/admin-api/graphql/reference/object/draftorder?api[version]=2020-07#privatem...
# Whether or not the Draft Order is ready and can be completed. Draft Orders may have asynchronous operations that can take time to finish. ready (Boolean!)
Yes! OK. Thanks for pointing that out. It provides me with the same solution though, which is ugly but reliable:
1. I can keep trying the draftOrderComplete in a loop till it sends an error-free response, or
2. I can read the order's ready boolean till it is true and then complete the draft order.
So in both cases, my intended pattern, which is to establish an Order from a Draft Order in one fell swoop, is more involved than thought it would be, since the draftOrderCreate hands backs an error free response. As you point out, even touching a Draft Order with an update mutation also starts up all this background asynchrounous machinery, so I might as well get used to the pattern.
Exactly our solution right now. We keep reloading the REST API DraftOrder (respecting the throttle headers from the API of course) until it's status goes from 202 to 200. And in GraphQL, you would keep reloading until ready: true.
Honestly, I understand your frustration because I thought this was bad design as well. But if asynchronous operations are ran on DraftOrders, how would you possibly model this more reliably? Webhooks? Because webhooks can have massive delays on them as well. Perhaps open a websocket that will push status updates? Sounds very technically expensive as well. I can't seem to think of an architectural solution for this problem at Shopify so I'm content with this.
I already posted the million dollar solution.
When I create a draftOrder using that mutation, and I provide an attribute "complete: true", when Shopify's internal asynchronous machinery has actually terminated its processing and the draftOrder is actually "ready:true", spawn a new background job to complete the draftOrder for me. I explicitely WANT that. So if the default is "complete:false" we get the current behaviour, as is. Otherwise, I know what I want, and what I want is to have it completed once it is built. End of Story for my use case.