Preamble
Due to legal requirements in Germany/the EU I have to show the prices with VAT or without VAT or both depending on use case/the type of customer. So I added a price field called unit_price_net to my order item type to have as much as possible flexibility. I created a custom order processor which grabs the price before the TaxOrderProcessor is running, to get the item price without VAT and put it into my unit_price_net field. So far so good.
The order is only processed by my OrderProcessor when the order is saved completely. It’s not processed, when I add my order items via admin order form (particularly the inline entity form (IEF) for the order items). So I struggle, if the admin (or a sales person etc.) is using the backend to create an order and overrides the unit price.
Problem and my solution in mind
My solution in mind is quite dirty, but I have not found a nicer alternative right now. The related order type is configured to enter prices without VAT. So the admin user has to fill in the net price into the unit price field and I fake the field rendering to look like the net price field.
/** * Implements hook_inline_entity_form_entity_form_alter(). */ function MYMODULE_inline_entity_form_entity_form_alter(array &$entity_form, FormStateInterface &$form_state) { if ($entity_form['#entity_type'] == 'commerce_order_item'){ switch ($entity_form['#bundle']) { case 'my_first_order_item_type': //Unset the not allowed product variation types for this order type, to simplyfy UI. unset($entity_form['purchased_entity']['widget']['#options']['My Second Product Variation Type']); //Fake the display of the gross price to look like the net price for correct intuitive input $entity_form['unit_price']['widget'][0]['amount']['#title'] = t('Unit Price (net)'); $entity_form['unit_price']['widget'][0]['amount']['#description'] = t('<i>Please note:</i> Due to that the current order is a "My First Order Type" order, please enter the <strong>net</strong> price (without VAT) here. Valid number format for example: <i>9.99</i>'); array_unshift($entity_form['#element_validate'],'MYMODULE_inline_entity_form_validate_order_items'); array_unshift($entity_form['#ief_element_submit'],'MYMODULE_inline_entity_form_submit_order_items'); break; case 'my_second_order_item_type': //Unset the not allowed product variation types for this order type, to simplyfy UI. unset($entity_form['purchased_entity']['widget']['#options']['My First Product Variation Type']); break; } //Hide the net price field $entity_form['field_mymodule_price_unit_net']['#access'] = FALSE; } }
Now I want to achieve, that the filled in price gets copied into my real net price field programmatically, before the IEF is submitted. All my trials don’t have an effect to alter the field value. I thought I can achieve this with a form validate function. How can I do this?
Here’s my code:
function MYMODULE_inline_entity_form_validate_order_items(array $entity_form, FormStateInterface $form_state) { if ($entity_form['#entity_type'] == 'commerce_order_item'){ if ($entity_form['#bundle'] == 'my_first_order_item_type'){ if ($entity_form['#of'] == 'add') { $entity_form['field_mymodule_price_unit_net']['#access'] = TRUE; (integer)$faked_net_price_number = $entity_form["unit_price"]["widget"][0]["amount"]["number"]["#value"]; (string)$faked_net_price_currency_code = $entity_form["unit_price"]["widget"][0]["amount"]["currency_code"]["#value"]; $faked_net_price = new Price($faked_net_price_number, $faked_net_price_currency_code); $entity_form["#entity"]->set('field_mymodule_price_unit_net', $faked_net_price); } } } }
Some other "nice to have" things
For a nicer UI/better UX I would like to alter the admin order item table that the unit price value (gross price) is displayed as "NA" as long as the order isn’t saved and the order processor wasn’t able to run. The entered price should be shown in the net price field of the table. I tried to alter the table fields a bit. But I wasn’t able to display a fallback value/or a text in the table yet
/** * Implements hook_inline_entity_form_table_fields_alter(). */ function MYMODULE_inline_entity_form_table_fields_alter(array &$fields, array $context) { $fields['quantity']['weight'] = 3; $fields['field_mymodule_price_unit_net'] = [ 'type' => 'field', 'label' => t('Unit price (net)'), 'weight' => 4, ]; $fields['unit_price']['weight'] = 5; }
Thanks in advance for any hints 🙂