Situation
- One catalogue of products (default type) with it's variations (default type)
- Anonymous (role) => default user
- Wholesaler (role) => wholesaler user
-
commerce_pricelist →
module for managing different prices based on context user role (using Calculated Price formatter we already see the different prices for the wholesaler user)
- I need the different checkout experience for the 2 users. Simple (default multistep for guest user), and a customized one with more steps for the wholesaler. I need the different Cart view for them and different cart blocks too.
We need 2 different product types and it's relative variation types as the Add to cart form is actually an "Entity Form" for an Order Item to build. So the parent order may be different himself and the workflows / Carts etc ... may be different. The order item types MAY contain the same prodcut variation type inside, but the product variation (in it's Configuration form [/admin/commerce/config/product-variation-types/%type/edit] has only 1 order item type as reference, while not the other way ... many order item types can reference the same product variation type.
Currently i can't do that with 1 catalogue only, i have to duplicate my products into "wholesale" products that have the "wholesale product variations" that on front-end will generate add to cart form which embeds the entity of type "Wholesale order item" (not the default one).
Now, that being said ... this small diagram that shows the current state of art:
Hack solution 1
Add a form alter HOOK, that drops all the add_to_cart_form::submitForm() actions and manually creates the "wholesaler" order item (as a child of order type "wholesaler") copying the info from the form_state prepared for the "default" order item. Stop ... after that .. i suppose the rest is out-of-the-box functionality.
Hack solution 2
Actually there's more elegant solution (but still hacky): The commerce/modules/product actually defines a FieldFormatter AddToCartFormatter for the productVariations inside product display. And this guy uses a lazy builder for building the actual form:
public function viewElements(FieldItemListInterface $items, $langcode) {
$elements = [];
$elements[0]['add_to_cart_form'] = [
'#lazy_builder' => [
'commerce_product.lazy_builders:addToCartForm', [
$items->getEntity()->id(),
$this->viewMode,
$this->getSetting('combine'),
$langcode,
],
],
'#create_placeholder' => TRUE,
];
return $elements;
}
So basically we could alter the service for this lazy builder with our own and do whatever we want.
Hack solution 3 (by @mgalman)
With a simple HOOK_entity_type_build we can alter the Class that comands the add to cart form. Which is actually is a entity form for commerce_order_item bundle content entity.
/**
* Implements hook_entity_type_build().
*/
function mymodule_entity_type_build(array &$entity_types) {
$entity_types['commerce_order_item']->setFormClass('add_to_cart', '\Drupal\mymodule\Form\CustomAddToCartForm');
}
Then alter the logics of the add to cart form as you wish.
Proposed solution
We need a some kind of Order Item Type Resolver
Something like this...
The basic patch is included.