There’s a consistency problem: the price may have
changed between the time that we received the order
and the time we looked up the product. To patch it up,
we attach the product price to the order:
What you are describing is the lost update problem. This is solved in several ways. For example, an If-Unmodified-Since or If-Match header. In the first POST method, you had to get the product ID from somewhere, so you might have obtained a date or etag representing that product at a specific point in time.
When you POST the order, you could put the date of the last time you saw the price change in a header (or in the JSON itself, if you post multiple products). If the price changed, the server could respond with a 412 - Precondition failed. If you want to post a collection of items, maybe you could use If-Match. If you want to enforce this, you could return a 428 if the client didn't include some sort of preconditions.
Every product has a price, every product listed on an order has a price, these aren't necessarily the same thing. What if the order includes something that the manager threw in for free to sweeten the deal? The price of that product on that order is zero, but the product's list price at any given point in time was not zero.
I didn't say there is a consistency problem, I quoted FTA.
My suggestion actually has nothing to do with the price of the object, it only has to do with the server state of the object (product) and whether or not that state was updated (price, quantity available, etc...), which is what the article was worrying about (the lost update problem).
i.e. if the underlying objects in a transaction changed between the time a client retrieved information about the object and the time where a user was interested in creating an order with the object, in a way which might invalidate the transaction, I'm highlighting a potential solution to notifying the client.
What if the order includes something that the manager
threw in for free to sweeten the deal? The price of
that product on that order is zero, but the product's
list price at any given point in time was not zero.
Well, in that case, I hope there is a system the "manager" can create a discount object to and attach it to the order.
PUT /orders/12345?discount=FREE_IPAD_YO
PUT /orders/12345;discounts [{"discount_id":"FREE_IPAD_YO"}]
whatever flavor you want, etc...
Note: I don't work in the ecommerce ___domain, but I do develop systems which are often transactional in nature.
As the developer of a REST centric ecommerce platform[1], I agree. The price of an order item is specific to that order and does not necessarily match the product's base price. It may be calculated using special account pricing rules, tiered by quantity, or discounted by a coupon. In such a system I have found many occurrences where data has to be de-normalized for this reason. Although the the new state is derived, it may otherwise differ from the source. Not just a function of value and time.
When you POST the order, you could put the date of the last time you saw the price change in a header (or in the JSON itself, if you post multiple products). If the price changed, the server could respond with a 412 - Precondition failed. If you want to post a collection of items, maybe you could use If-Match. If you want to enforce this, you could return a 428 if the client didn't include some sort of preconditions.
http://tools.ietf.org/html/rfc6585#section-3
REST doesn't mean "Never user Headers".