It is correct to change unit_price of commerce_order_item programmatically under several conditions? I am developing a module that allows you to select additional options for a product that is not a product or a purchase entity. It's like commerce_option but for D8.

My inspirations come from Product Attributes shipped with Drupal Commerce. So I have mostly the same two entity types:


Product Option (config entity type) - bundle.
Product Option Value (content entity type) - the actual option with price field.


The options can be attached to commerce_order_item types as entity references. Then add to cart form display them as options to select.



The confusion comes at the part when these options come to commerce_order_item and actual order.

At the current moment, I've created a new field type with three properties: option (textfield), option value (textfield), price (commerce_price). This field automatically filled when commerce_order_item added to the cart.



Next, the most obscure part. What's the correct way to handle those additional and their prices?

I see several ways:


(current implementation) My current field type + commerce_order_item adjustments. The problem here I see, there is a bit mess with cart and other stuff. I need manually use getAdjustedUnitPrice() to get real product price. It can be affected by tax and other stuff, so this becomes a mess in the future. Plus, in this way I don't see the proper way to add a discount for this line item. Since the promotion applies to unit_price or total_price, but this amounts in adjustments. It can be solved, but may be tricky.
My current field type + override of unit_price. In this way the discount and tax problem disappear. But rises another problem. The manager, when editing order item, must take product options into account when editing it, since their price will be already included.


Maybe you can advise another approach? I also think about special commerce_order_item type + entity_reference (much complicated I think). But here all the problems of the first approach raise again.

Is it good to edit unit_price directly on order_item save\update? Or it is not expected behavior, when some event will change order_item price by adding the amounts? Also, how this must work on second and so on saves? E.g. order_item price $10, and selected option $5. When order_items saved, the current_price will become $15. When some changes are made, how to detect those options already included? The way I see, recalculate the new unit_price by grabbing the price from purchased_entity. But what if this price was manually overridden by the manager from $10, to $8? The only solution I see now, is to store price before it affected by options in the data field. Is this also correct or I miss something?

The reason because I create special field to store values is almost the same as order_item existence. The option prices can be changed, or even deleted, so order_item doesn't know anything about it and store the raw results values.
As a proof of concept a module with this functionality already exists. Unfortunately, it's not published yet because that requires a couple of final touches with a time frame allocated for this kind of work.

https://github.com/drugan/commerce_oiaddon

The price adjustment is taken from a pseudo-price field added to some entity type and then the order item price recalculated at the event of an order item added to or removed from a shopping cart. So I am not sure why you can't get the same result as in the commerce_oiaddon module. Just do the same as it shown in the example and it should work.