papinet / papiNet-API

papiNet is a global paper, forest products and bioproducts industry e-Business initiative.
http://www.papinet.org/
Apache License 2.0
9 stars 3 forks source link

Unlinking the _customer-article_ and the _seller-product_ in order to allow the mutability of the _seller-product_ #85

Open patricekrakow opened 1 year ago

patricekrakow commented 1 year ago

If we go for this unlinking, we still need to explore all its consequences of this, such as for our idea to remove the DELETE /customer-articles/{customerArticleId} API endpoint, only allowing the customer to inactivate his customer-products (via a PUT or a PATCH), and many more...

patricekrakow commented 1 year ago

The problem when defining a customer-article by only referencing a seller-product is that you cannot update the seller-product without creating an ambiguity on the customer-article; when using this customer-article, you will not be able to know if it refers to the seller-product before or after the update.

Let's illustrate this problem with, as an example, a seller-product with XYZ as id and 1000 as diameter, and create a customer-article with ABC as id by only referencing it. We will exclude the other properties for the conciseness of the example:

READ   seller-product   --> |     | XYZ | 1000
CREATE customer-article <-- | ABC | XYZ
READ   customer-article --> | ABC | XYZ | 1000

If afterwards the diameter of the seller-product XYZ is modified from 1000 to, let's say, 1250, it will not be possible to use the customer-article ABC as we will not know if its diameter is 1000 or 1250:

READ   seller-product   --> |     | XYZ | 1250 (UPDATE)
READ   customer-article --> | ABC | XYZ | Ambiguity

One solution to this problem would be to forbid any change of seller-products, constraining them to be immutable. However, this solution does not fit normal business practices.

Another solution is to decouple the customer-article from the seller-product from the customer point of view. The values of the properties of the customer-article will be fixed at the moment of its creation. In order to emphasize that, the customer-article will not explicitly refer to a seller-product, but all properties will be explicitly provided. Let's illustrate that with the same example:

READ   seller-product   --> |     | XYZ | 1000
CREATE customer-article <-- | ABC | ___ | 1000
READ   customer-article --> | ABC | ___ | 1000

This time, if there is an update of the seller-product after the creation of a customer-article (using it), it will not affect the customer-article:

READ   seller-product   --> |     | XYZ | 1250 (UPDATE)
READ   customer-article --> | ABC | ___ | 1000

We have decoupled the customer-article from the seller-product from the customer point of view, but, of course, on the seller side you still have a "mapping" between the customer-article, which is ordered, and one (or multiple) seller-product(s), which are produced. If the modification on seller side does not allow anymore the seller to provide the customer-article, it must become Inactive. It is important that the customer-article still exists, it cannot be deleted, as it is still used in past orders!

READ   seller-product   --> |     | XYZ | 1250 (UPDATE)
READ   customer-article --> | ABC | ___ | 1000 | status = Inactive

In the examples above, it would not make sense to modify the customer-article after an update of the seller-product as it would again create an ambiguity on the customer-article. So, we should remove the API endpoints PUT /customer-articles/{customerArticleId} and PATCH /customer-articles/{customerArticleId}. But, again, it's not that simple because of normal business practices that allow such modifications when they are backward compatibles.

A good example of a backward compatible change is when the seller is adding a possible value to a property. This backward compatible change of a seller-product can be safely transferred to customer-articles. It is up to the seller to decide what change are backward compatibles, giving the appropriate response for the API endpoints PUT /customer-articles/{customerArticleId} and PATCH /customer-articles/{customerArticleId}.

Let's illustrate that:

READ   seller-product   --> |     | XYZ | 1000, 1250
CREATE customer-article <-- | ABC | ___ | 1000, 1250
READ   customer-article --> | ABC | ___ | 1000, 1250

READ   seller-product   --> |     | XYZ | 1000, 1250, 1500 (UPDATE)
READ   customer-article --> | ABC | ___ | 1000, 1250

UPDATE customer-article <-- | ABC | ___ | 1000, 1250, 1500
READ   customer-article --> | ABC | ___ | 1000, 1250, 1500

On the other hand, removing a diameter is probably better considered as an incompatible change that should not be transferred:

READ   seller-product   --> |     | XYZ | 1000, 1250, 1500
CREATE customer-article <-- | ABC | ___ | 1000, 1250, 1500
READ   customer-article --> | ABC | ___ | 1000, 1250, 1500

READ   seller-product   --> |     | XYZ | 1000, 1250       (UPDATE)
READ   customer-article --> | ABC | ___ | 1000, 1250, 1500

UPDATE customer-article <-- | ABC | ___ | 1000, 1250 --> Error!

Unfortunately, there are more subtle incompatible change like adding a possible value to a property when it was previously a single-value property. Let's illustrate that:

READ   seller-product   --> |     | XYZ | 1000
CREATE customer-article <-- | ABC | ___ | 1000
READ   customer-article --> | ABC | ___ | 1000

READ   seller-product   --> |     | XYZ | 1000, 1250       (UPDATE)
READ   customer-article --> | ABC | ___ | 1000

UPDATE customer-article <-- | ABC | ___ | 1000, 1250 --> Error!

Why should the seller return a error? The fact that the diameter had one single value 1000 meant that when the customer-articles ABC was used, for instance within an order, its id was sufficient to use it. On the other hand, when you are using a customer-articles with one or multiple multi-value properties within an order, you MUST always specify the value you want out of the possible values. Thus, if you allow this kinf of update, there will be an ambiguity on the customer-article used in orders.

patricekrakow commented 1 year ago

QUESTION 1: Since we allow seller-product to be updated by the seller, do we allow customers to order directly seller-product (without creating customer-article first)?

Indeed, if we do allow that, we will end up with an ambiguity on the seller-product property values in orders. Let's illustrate that with an example:

READ   seller-product   -->     | XYZ | 1000
CREATE order            <-- | 1 | XYZ |

READ   seller-product   --> |   | XYZ | 1250 (UPDATE)
CREATE order            <-- | 2 | XYZ |

READ   order            --> | 1 | XYZ |
READ   seller-product   --> |   | XYZ | 1250

For the order 1 the seller-product XYZ has a diameter of 1000, but for the order 2 the seller-product XYZ has a diameter of 1250. However, when we will later read the order 2 and lookup for the diameter of the seller-product XYZ, the answer will be 1250, as the update of the seller-product XYZ has erased the previous diameter of 1000!

We could solve this problem by making the creation of a customer-article has a mandatory step, but we can notice that this problem does not occur when we have an update on a multi-value property. Let's illustrate that with an example:

READ   seller-product   -->     | XYZ | 1000, 1250
CREATE order            <-- | 1 | XYZ | 1000

READ   seller-product   --> |   | XYZ | 1000, 1250, 1500 (UPDATE)
CREATE order            <-- | 2 | XYZ | 1500

READ   order            --> | 1 | XYZ | 1500
READ   seller-product   --> |   | XYZ | 1000, 1250, 1500

Indeed, when you have a multi-value property, you MUST specify the value you want out of the possible values and therefore you keep the 'memory' of the right value!

QUESTION 2: If we allow customers to order directly seller-product, do we oblige them to specify every properties of the seller-product, even the single-value one?

REMARK. For the customer-article, we could have the same reasoning, but we can also reject incompatible changes (see above). If we would oblige customers to specify every properties of the customer-article when creating an order, it would make the concept of customer-article obsolete and/or ambiguous. Let's illustrate that with an example:

READ   seller-product   --> |   |     | XYZ | 1000
CREATE customer-article <-- |   | ABC | ___ | 1000
CREATE order            <-- | 1 | ABC |

READ   order            --> | 1 | ABC
READ   customer-article --> |   | ABC | ___ | 1000

READ   seller-product   --> |   |     | XYZ | 1000, 1250       (UPDATE)
READ   customer-article --> |   | ABC | ___ | 1000
CREATE order            <-- | 2 | ABC |

READ   order            --> | 2 | ABC
READ   customer-article --> |   | ABC | ___ | 1000
READ   order            --> | 1 | ABC
READ   customer-article --> |   | ABC | ___ | 1000

UPDATE customer-article <-- |   | ABC | ___ | 1000, 1250 --> Error!

CREATE customer-article <-- |   | DEF | ___ | 1250
CREATE order            <-- | 3 | DEF |

READ   order            --> | 3 | DEF
READ   customer-article --> |   | DEF | ___ | 1250
READ   order            --> | 2 | ABC
READ   customer-article --> |   | ABC | ___ | 1000
READ   order            --> | 1 | ABC
READ   customer-article --> |   | ABC | ___ | 1000
patricekrakow commented 1 year ago

QUESTION 3: After all these explanations, and I am still not sure that I have covered all the corners of the subject, I am wondering if we should not make the radical decision to enforce the immutability of both seller-product and customer-article?