Answers.Body: <p>Probably best to just update the address business tax ID if it is in the wrong format automatically for them.</p>
  <pre><code>Event::on(Order::class, Order::EVENT_BEFORE_SAVE, function(\craft\events\ModelEvent $event) {
      /** @var Order $order */
      $order = $event-&gt;sender;
      if ($order-&gt;getShippingAddress() &amp;&amp; $order-&gt;getShippingAddress()-&gt;businessTaxId) {
          $newTaxId = &quot;AU&quot;.$order-&gt;shippingAddress-&gt;businessTaxId; // transform this into the right format based on address country (if it is not already)
          $address = $order-&gt;shippingAddress;
          $address-&gt;businessTaxId = $newTaxId;
          $order-&gt;setShippingAddress($address); //  address will save when order saves.
      }
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-28T08:39:33.200Z
Answers.Text: Great, thanks Luke
Answers.UserDisplayName: Cole Henley
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-28T08:29:56.007Z
Answers.LastActivityDate: 2020-07-28T08:29:56.007Z
Answers.UserDisplayName: Luke Holder
Body: <p>We have a single page checkout where the items are selected and addressed added before going to
  a cart summary page showing amount owed and tax due.</p>
  <p>Was confused as to why certain codes were not working (checking validation against the service at <a href="https://ec.europa.eu/taxation_customs/vies/vatResponse.html" rel="nofollow noreferrer">https://ec.europa.eu/taxation_customs/vies/vatResponse.html</a>) and realised the Craft Commerce submission requires the country ISO code as a prefix, eg a UK submission <code>166211234</code> needs to be <code>GB166211234</code>. Similarly dots and spacesm, etc need to be stripped out. Unless these are in the correct format relevant rules (eg do not add VAT if valid VAT tax record is added will not kick in).</p>
  <p>So as a means for preparing this data thought could tap into an event to update this value.
  The <code>Addresses::EVENT_BEFORE_SAVE_ADDRESS</code> event won't work as the update cart method/action saves the address after adding the line items and relevant calculations are made.</p>
  <p>So then looked into the <code>LineItems::EVENT_POPULATE_LINE_ITEM</code> event so can theoretically fetch and update the address associated with the cart/line item being saved (we are only ever adding one item to the cart at a time. If an item already exists in the cart then that is removed first.</p>
  <p>The following code looked promising (would ideally like to limit to EU tax zone but for now assume all sales are EU):</p>
  <pre><code>    // get line item
      $lineItem = $event-&gt;lineItem;
      // get order
      $order = $lineItem-&gt;order;
      // get billing address
      $billingAddress = $order-&gt;billingAddressId;
      // get billing address by ID
      $address = craftCommerce::getInstance()-&gt;getAddresses()-&gt;getAddressById($billingAddress);
      // get billing address tax ID    
      $taxId = $address-&gt;businessTaxId; 
      // get billing address country ID    
      $countryId = $address-&gt;countryId;
      // get country ISO    
      $country = craftCommerce::getInstance()-&gt;getCountries()-&gt;getCountryById($countryId);
      $countryIso = $country-&gt;iso;
      // strip non-alphanumeric characters from tax ID
      $cleanTax = preg_replace(&quot;/[^A-Za-z0-9 ]/&quot;, '', $taxId);
      // specify new, ideal tax ID
      $newTax = $countryIso . $cleanTax;
      // check if tax is specified, is not already optimised if not already changed
      if ($cleanTax !== '' &amp;&amp; strpos($cleanTax,$countryIso) === false &amp;&amp; $address-&gt;businessTaxId != $newTax) $address-&gt;businessTaxId = $newTax;                    
      // save the new address
      craftCommerce::getInstance()-&gt;getAddresses()-&gt;saveAddress($address, false);
  </code></pre>
  <p>However, whilst this saves the new address it doesn't update the existing one.</p>
  <p>Any thoughts? Am I doing about this completely the wrong way.
  Would rather than do this in the front-end JS if at all possible.</p>
  <p>Cheers,</p>
  <p>Cole</p>
  <p>Craft 3.4.29.1.
  Craft Commerce 3.1.12</p>
  
Tags: <plugin-development><plugin-craftcommerce><plugin-craftcommerce2><plugin-craftcommerce3><tax>
Title: Tax validation in Craft Commerce
ThreadText: # Tax validation in Craft Commerce
  
  (Asked by: username_0 on 2020-07-28)
  
  We have a single page checkout where the items are selected and addressed added before going to
  a cart summary page showing amount owed and tax due.
  
  Was confused as to why certain codes were not working (checking validation against the service at <https://ec.europa.eu/taxation_customs/vies/vatResponse.html>) and realised the Craft Commerce submission requires the country ISO code as a prefix, eg a UK submission `166211234` needs to be `GB166211234`. Similarly dots and spacesm, etc need to be stripped out. Unless these are in the correct format relevant rules (eg do not add VAT if valid VAT tax record is added will not kick in).
  
  So as a means for preparing this data thought could tap into an event to update this value.
  The `Addresses::EVENT_BEFORE_SAVE_ADDRESS` event won't work as the update cart method/action saves the address after adding the line items and relevant calculations are made.
  
  So then looked into the `LineItems::EVENT_POPULATE_LINE_ITEM` event so can theoretically fetch and update the address associated with the cart/line item being saved (we are only ever adding one item to the cart at a time. If an item already exists in the cart then that is removed first.
  
  The following code looked promising (would ideally like to limit to EU tax zone but for now assume all sales are EU):
  
  ```
      // get line item
      $lineItem = $event->lineItem;
      // get order
      $order = $lineItem->order;
      // get billing address
      $billingAddress = $order->billingAddressId;
      // get billing address by ID
      $address = craftCommerce::getInstance()->getAddresses()->getAddressById($billingAddress);
      // get billing address tax ID    
      $taxId = $address->businessTaxId; 
      // get billing address country ID    
      $countryId = $address->countryId;
      // get country ISO    
      $country = craftCommerce::getInstance()->getCountries()->getCountryById($countryId);
      $countryIso = $country->iso;
      // strip non-alphanumeric characters from tax ID
      $cleanTax = preg_replace("/[^A-Za-z0-9 ]/", '', $taxId);
      // specify new, ideal tax ID
      $newTax = $countryIso . $cleanTax;
      // check if tax is specified, is not already optimised if not already changed
      if ($cleanTax !== '' && strpos($cleanTax,$countryIso) === false && $address->businessTaxId != $newTax) $address->businessTaxId = $newTax;                    
      // save the new address
      craftCommerce::getInstance()->getAddresses()->saveAddress($address, false);
  
  ```
  
  However, whilst this saves the new address it doesn't update the existing one.
  
  Any thoughts? Am I doing about this completely the wrong way.
  Would rather than do this in the front-end JS if at all possible.
  
  Cheers,
  
  username_0
  
  Craft 3.4.29.1.
  Craft Commerce 3.1.12
  
  **Tags:** plugin-development, plugin-craftcommerce, plugin-craftcommerce2, plugin-craftcommerce3, tax
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-07-28. Score: 2 | Accepted answer
  
  Probably best to just update the address business tax ID if it is in the wrong format automatically for them.
  
  ```
  Event::on(Order::class, Order::EVENT_BEFORE_SAVE, function(\craft\events\ModelEvent $event) {
      /** @var Order $order */
      $order = $event->sender;
      if ($order->getShippingAddress() && $order->getShippingAddress()->businessTaxId) {
          $newTaxId = "AU".$order->shippingAddress->businessTaxId; // transform this into the right format based on address country (if it is not already)
          $address = $order->shippingAddress;
          $address->businessTaxId = $newTaxId;
          $order->setShippingAddress($address); //  address will save when order saves.
      }
  });
  
  ```
  
  > **Comments:**
  > **username_0**: Great, thanks username_1  
  
  ---
  
  