diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
index 1c7b36b9178be13a4ded31c26eacd0d4b3be34aa..f0fe5a55aa3af0016a1a4e78dd15d7ae66295400 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js
@@ -80,9 +80,10 @@ define(
                         });
                         if (proceed) {
                             quote.setPaymentMethod(methodData.method);
+                            //set the totals before setting PaymentData
+                            quote.setTotals(response);
                             service.setSelectedPaymentData(methodData);
                             service.setSelectedPaymentInfo(methodInfo);
-                            quote.setTotals(response);
                             navigator.setCurrent('paymentMethod').goNext();
                         }
                     }
diff --git a/app/code/Magento/PageCache/Block/Javascript.php b/app/code/Magento/PageCache/Block/Javascript.php
index bfc3b4a1a1e8b64e376b0889fa5bd75a4bfb08fe..980436b677bd3b51b23aaff170c32994e4b312a6 100644
--- a/app/code/Magento/PageCache/Block/Javascript.php
+++ b/app/code/Magento/PageCache/Block/Javascript.php
@@ -27,9 +27,10 @@ class Javascript extends \Magento\Framework\View\Element\Template
             ),
             'handles' => $this->_layout->getUpdate()->getHandles(),
             'originalRequest' => [
-                'route' => $this->getRequest()->getRouteName(),
+                'route'      => $this->getRequest()->getRouteName(),
                 'controller' => $this->getRequest()->getControllerName(),
-                'action' => $this->getRequest()->getActionName(),
+                'action'     => $this->getRequest()->getActionName(),
+                'uri'        => $this->getRequest()->getRequestUri(),
             ],
             'versionCookieName' => \Magento\Framework\App\PageCache\Version::COOKIE_NAME
         ];
diff --git a/app/code/Magento/PageCache/Controller/Block/Render.php b/app/code/Magento/PageCache/Controller/Block/Render.php
index 1544cca2cfacb36dfa57fa75fd8ae1138e42a8f5..789fb1b696fe0b824666f3f19a0e22dc0f3ea7a2 100644
--- a/app/code/Magento/PageCache/Controller/Block/Render.php
+++ b/app/code/Magento/PageCache/Controller/Block/Render.php
@@ -24,12 +24,15 @@ class Render extends \Magento\PageCache\Controller\Block
         $currentRoute = $this->getRequest()->getRouteName();
         $currentControllerName = $this->getRequest()->getControllerName();
         $currentActionName = $this->getRequest()->getActionName();
+        $currentRequestUri = $this->getRequest()->getRequestUri();
 
         $origRequest = $this->getRequest()->getParam('originalRequest');
         $origRequest = json_decode($origRequest, true);
         $this->getRequest()->setRouteName($origRequest['route']);
         $this->getRequest()->setControllerName($origRequest['controller']);
         $this->getRequest()->setActionName($origRequest['action']);
+        $this->getRequest()->setRequestUri($origRequest['uri']);
+
         /** @var \Magento\Framework\View\Element\BlockInterface[] $blocks */
         $blocks = $this->_getBlocks();
         $data = [];
@@ -41,6 +44,7 @@ class Render extends \Magento\PageCache\Controller\Block
         $this->getRequest()->setRouteName($currentRoute);
         $this->getRequest()->setControllerName($currentControllerName);
         $this->getRequest()->setActionName($currentActionName);
+        $this->getRequest()->setRequestUri($currentRequestUri);
 
         $this->getResponse()->setPrivateHeaders(\Magento\PageCache\Helper\Data::PRIVATE_MAX_AGE_CACHE);
         $this->translateInline->processResponseBody($data);
diff --git a/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php b/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php
index 56a23aa1ac84f28e78958214c2e6db5b2c190e70..5cac08b148cf2c401bf2b58fc2b7450b805be74b 100644
--- a/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Block/JavascriptTest.php
@@ -54,12 +54,14 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase
                 'getControllerName',
                 'getModuleName',
                 'getActionName',
+                'getRequestUri',
                 'getParam',
                 'setParams',
                 'getParams',
                 'setModuleName',
                 'isSecure',
                 'setActionName',
+                'setRequestUri',
                 'getCookie'
             ],
             [],
@@ -122,6 +124,9 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase
         $this->requestMock->expects($this->once())
             ->method('getActionName')
             ->will($this->returnValue('action'));
+        $this->requestMock->expects($this->once())
+            ->method('getRequestUri')
+            ->will($this->returnValue('uri'));
         $this->urlBuilderMock->expects($this->once())
             ->method('getUrl')
             ->willReturn($url);
@@ -153,10 +158,11 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase
      * @param string $route
      * @param string $controller
      * @param string $action
+     * @param string $uri
      * @param string $expectedResult
      * @dataProvider getScriptOptionsPrivateContentDataProvider
      */
-    public function testGetScriptOptionsPrivateContent($url, $route, $controller, $action, $expectedResult)
+    public function testGetScriptOptionsPrivateContent($url, $route, $controller, $action, $uri, $expectedResult)
     {
         $handles = [
             'some',
@@ -179,6 +185,10 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase
             ->method('getActionName')
             ->will($this->returnValue($action));
 
+        $this->requestMock->expects($this->once())
+            ->method('getRequestUri')
+            ->will($this->returnValue($uri));
+
         $this->urlBuilderMock->expects($this->once())
             ->method('getUrl')
             ->willReturn($url);
@@ -191,14 +201,17 @@ class JavascriptTest extends \PHPUnit_Framework_TestCase
 
     public function getScriptOptionsPrivateContentDataProvider()
     {
+        // @codingStandardsIgnoreStart
         return [
             'http' => [
-                'url' => 'http://some-name.com/page_cache/block/render',
-                'route' => 'route',
-                'controller' => 'controller',
-                'action' => 'action',
-                'expectedResult' => '~"originalRequest":{"route":"route","controller":"controller","action":"action"}~'
+                'url'            => 'http://some-name.com/page_cache/block/render',
+                'route'          => 'route',
+                'controller'     => 'controller',
+                'action'         => 'action',
+                'uri'            => 'uri',
+                'expectedResult' => '~"originalRequest":{"route":"route","controller":"controller","action":"action","uri":"uri"}~'
             ],
         ];
+        //@codingStandardsIgnoreEnd
     }
 }
diff --git a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
index 0bd7fcee22587e778d4cf4d8a849cfa9b030d11a..a9493a7a4c3abb2b6ff6472ccfce3007d0089ea2 100644
--- a/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
+++ b/app/code/Magento/PageCache/Test/Unit/Controller/Block/RenderTest.php
@@ -88,11 +88,11 @@ class RenderTest extends \PHPUnit_Framework_TestCase
     public function testExecuteNoParams()
     {
         $this->requestMock->expects($this->once())->method('isAjax')->will($this->returnValue(true));
-        $this->requestMock->expects($this->at(8))
+        $this->requestMock->expects($this->at(10))
             ->method('getParam')
             ->with($this->equalTo('blocks'), $this->equalTo(''))
             ->will($this->returnValue(''));
-        $this->requestMock->expects($this->at(9))
+        $this->requestMock->expects($this->at(11))
             ->method('getParam')
             ->with($this->equalTo('handles'), $this->equalTo(''))
             ->will($this->returnValue(''));
@@ -103,7 +103,7 @@ class RenderTest extends \PHPUnit_Framework_TestCase
     {
         $blocks = ['block1', 'block2'];
         $handles = ['handle1', 'handle2'];
-        $originalRequest = '{"route":"route","controller":"controller","action":"action"}';
+        $originalRequest = '{"route":"route","controller":"controller","action":"action","uri":"uri"}';
         $expectedData = ['block1' => 'data1', 'block2' => 'data2'];
 
         $blockInstance1 = $this->getMock(
@@ -136,15 +136,18 @@ class RenderTest extends \PHPUnit_Framework_TestCase
             ->method('getActionName')
             ->will($this->returnValue('render'));
         $this->requestMock->expects($this->at(4))
+            ->method('getRequestUri')
+            ->will($this->returnValue('uri'));
+        $this->requestMock->expects($this->at(5))
             ->method('getParam')
             ->with($this->equalTo('originalRequest'))
             ->will($this->returnValue($originalRequest));
 
-        $this->requestMock->expects($this->at(8))
+        $this->requestMock->expects($this->at(10))
             ->method('getParam')
             ->with($this->equalTo('blocks'), $this->equalTo(''))
             ->will($this->returnValue(json_encode($blocks)));
-        $this->requestMock->expects($this->at(9))
+        $this->requestMock->expects($this->at(11))
             ->method('getParam')
             ->with($this->equalTo('handles'), $this->equalTo(''))
             ->will($this->returnValue(json_encode($handles)));
diff --git a/app/code/Magento/Sales/etc/extension_attributes.xml b/app/code/Magento/Sales/etc/extension_attributes.xml
deleted file mode 100644
index 970a003625928f218f2073cbb4262cd7d3876499..0000000000000000000000000000000000000000
--- a/app/code/Magento/Sales/etc/extension_attributes.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0"?>
-<!--
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
--->
-<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd">
-    <extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
-        <attribute code="applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface[]" />
-        <attribute code="item_applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[]" />
-        <attribute code="converting_from_quote" type="boolean" />
-    </extension_attributes>
-</config>
diff --git a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php
index 0d5f9de2e47c25c3261c4322fe94226c12058b70..9e9227adffd3487bf3f12b21966caee4fedd922d 100644
--- a/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php
+++ b/app/code/Magento/Tax/Model/App/Action/ContextPlugin.php
@@ -84,7 +84,8 @@ class ContextPlugin
         \Closure $proceed,
         \Magento\Framework\App\RequestInterface $request
     ) {
-        if (!$this->moduleManager->isEnabled('Magento_PageCache') ||
+        if (!$this->customerSession->isLoggedIn() ||
+            !$this->moduleManager->isEnabled('Magento_PageCache') ||
             !$this->cacheConfig->isEnabled() ||
             !$this->taxHelper->isCatalogPriceDisplayAffectedByTax()) {
             return $proceed($request);
diff --git a/app/code/Magento/Tax/Model/Observer.php b/app/code/Magento/Tax/Model/Observer.php
index 6f8d41fbb17e96ece0bcaad9c87cb57e14498fac..25bf3ea1b56461e019947d147ca109ca6297151a 100644
--- a/app/code/Magento/Tax/Model/Observer.php
+++ b/app/code/Magento/Tax/Model/Observer.php
@@ -20,16 +20,6 @@ class Observer
      */
     protected $_taxData;
 
-    /**
-     * @var \Magento\Tax\Model\Sales\Order\TaxFactory
-     */
-    protected $_orderTaxFactory;
-
-    /**
-     * @var \Magento\Sales\Model\Order\Tax\ItemFactory
-     */
-    protected $_taxItemFactory;
-
     /**
      * @var \Magento\Tax\Model\Calculation
      */
@@ -57,8 +47,6 @@ class Observer
 
     /**
      * @param \Magento\Tax\Helper\Data $taxData
-     * @param \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory
-     * @param \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory
      * @param \Magento\Tax\Model\Calculation $calculation
      * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
      * @param \Magento\Tax\Model\Resource\Report\TaxFactory $reportTaxFactory
@@ -67,8 +55,6 @@ class Observer
      */
     public function __construct(
         \Magento\Tax\Helper\Data $taxData,
-        \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory,
-        \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory,
         \Magento\Tax\Model\Calculation $calculation,
         \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
         \Magento\Tax\Model\Resource\Report\TaxFactory $reportTaxFactory,
@@ -76,8 +62,6 @@ class Observer
         \Magento\Framework\Registry $registry
     ) {
         $this->_taxData = $taxData;
-        $this->_orderTaxFactory = $orderTaxFactory;
-        $this->_taxItemFactory = $taxItemFactory;
         $this->_calculation = $calculation;
         $this->_localeDate = $localeDate;
         $this->_reportTaxFactory = $reportTaxFactory;
@@ -114,145 +98,6 @@ class Observer
         }
     }
 
-    /**
-     * Save order tax information
-     *
-     * @param \Magento\Framework\Event\Observer $observer
-     * @return void
-     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
-     * @SuppressWarnings(PHPMD.NPathComplexity)
-     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
-     */
-    public function salesEventOrderAfterSave(\Magento\Framework\Event\Observer $observer)
-    {
-        $order = $observer->getEvent()->getOrder();
-
-        if (!$order->getConvertingFromQuote() || $order->getAppliedTaxIsSaved()) {
-            return;
-        }
-
-        $taxesAttr = $order->getCustomAttribute('applied_taxes');
-        if (is_null($taxesAttr) || !is_array($taxesAttr->getValue())) {
-            $taxes = [];
-        } else {
-            $taxes = $taxesAttr->getValue();
-        }
-
-        $getTaxesForItemsAttr = $order->getCustomAttribute('item_applied_taxes');
-        if (is_null($getTaxesForItemsAttr) || !is_array($getTaxesForItemsAttr->getValue())) {
-            $getTaxesForItems = [];
-        } else {
-            $getTaxesForItems = $getTaxesForItemsAttr->getValue();
-        }
-
-        $ratesIdQuoteItemId = [];
-        foreach ($getTaxesForItems as $taxesArray) {
-            foreach ($taxesArray as $rates) {
-                if (count($rates['rates']) == 1) {
-                    $ratesIdQuoteItemId[$rates['id']][] = [
-                        'id' => $rates['item_id'],
-                        'percent' => $rates['percent'],
-                        'code' => $rates['rates'][0]['code'],
-                        'associated_item_id' => $rates['associated_item_id'],
-                        'item_type' => $rates['item_type'],
-                        'amount' => $rates['amount'],
-                        'base_amount' => $rates['base_amount'],
-                        'real_amount' => $rates['amount'],
-                        'real_base_amount' => $rates['base_amount'],
-                    ];
-                } else {
-                    $percentSum = 0;
-                    foreach ($rates['rates'] as $rate) {
-                        $real_amount = $rates['amount'] * $rate['percent'] / $rates['percent'];
-                        $real_base_amount = $rates['base_amount'] * $rate['percent'] / $rates['percent'];
-                        $ratesIdQuoteItemId[$rates['id']][] = [
-                            'id' => $rates['item_id'],
-                            'percent' => $rate['percent'],
-                            'code' => $rate['code'],
-                            'associated_item_id' => $rates['associated_item_id'],
-                            'item_type' => $rates['item_type'],
-                            'amount' => $rates['amount'],
-                            'base_amount' => $rates['base_amount'],
-                            'real_amount' => $real_amount,
-                            'real_base_amount' => $real_base_amount,
-                        ];
-                        $percentSum += $rate['percent'];
-                    }
-                }
-            }
-        }
-
-        foreach ($taxes as $row) {
-            $id = $row['id'];
-            foreach ($row['rates'] as $tax) {
-                if (is_null($row['percent'])) {
-                    $baseRealAmount = $row['base_amount'];
-                } else {
-                    if ($row['percent'] == 0 || $tax['percent'] == 0) {
-                        continue;
-                    }
-                    $baseRealAmount = $row['base_amount'] / $row['percent'] * $tax['percent'];
-                }
-                $hidden = isset($row['hidden']) ? $row['hidden'] : 0;
-                $priority = isset($tax['priority']) ? $tax['priority'] : 0;
-                $position = isset($tax['position']) ? $tax['position'] : 0;
-                $process = isset($row['process']) ? $row['process'] : 0;
-                $data = [
-                    'order_id' => $order->getId(),
-                    'code' => $tax['code'],
-                    'title' => $tax['title'],
-                    'hidden' => $hidden,
-                    'percent' => $tax['percent'],
-                    'priority' => $priority,
-                    'position' => $position,
-                    'amount' => $row['amount'],
-                    'base_amount' => $row['base_amount'],
-                    'process' => $process,
-                    'base_real_amount' => $baseRealAmount,
-                ];
-
-                /** @var $orderTax \Magento\Tax\Model\Sales\Order\Tax */
-                $orderTax = $this->_orderTaxFactory->create();
-                $result = $orderTax->setData($data)->save();
-
-                if (isset($ratesIdQuoteItemId[$id])) {
-                    foreach ($ratesIdQuoteItemId[$id] as $quoteItemId) {
-                        if ($quoteItemId['code'] == $tax['code']) {
-                            $itemId = null;
-                            $associatedItemId = null;
-                            if (isset($quoteItemId['id'])) {
-                                //This is a product item
-                                $item = $order->getItemByQuoteItemId($quoteItemId['id']);
-                                $itemId = $item->getId();
-                            } elseif (isset($quoteItemId['associated_item_id'])) {
-                                //This item is associated with a product item
-                                $item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
-                                $associatedItemId = $item->getId();
-                            }
-
-                            $data = [
-                                'item_id' => $itemId,
-                                'tax_id' => $result->getTaxId(),
-                                'tax_percent' => $quoteItemId['percent'],
-                                'associated_item_id' => $associatedItemId,
-                                'amount' => $quoteItemId['amount'],
-                                'base_amount' => $quoteItemId['base_amount'],
-                                'real_amount' => $quoteItemId['real_amount'],
-                                'real_base_amount' => $quoteItemId['real_base_amount'],
-                                'taxable_item_type' => $quoteItemId['item_type'],
-                            ];
-                            /** @var $taxItem \Magento\Sales\Model\Order\Tax\Item */
-                            $taxItem = $this->_taxItemFactory->create();
-                            $taxItem->setData($data)->save();
-                        }
-                    }
-                }
-            }
-        }
-
-        $order->setAppliedTaxIsSaved(true);
-    }
-
     /**
      * Refresh sales tax report statistics for last day
      *
diff --git a/app/code/Magento/Tax/Model/Plugin/OrderSave.php b/app/code/Magento/Tax/Model/Plugin/OrderSave.php
new file mode 100644
index 0000000000000000000000000000000000000000..145c98ad60e38784b8c52cc9818ffff9fa5cd6bc
--- /dev/null
+++ b/app/code/Magento/Tax/Model/Plugin/OrderSave.php
@@ -0,0 +1,184 @@
+<?php
+/**
+ *
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Tax\Model\Plugin;
+
+class OrderSave
+{
+    /**
+     * @var \Magento\Tax\Model\Sales\Order\TaxFactory
+     */
+    protected $orderTaxFactory;
+
+    /**
+     * @var \Magento\Sales\Model\Order\Tax\ItemFactory
+     */
+    protected $taxItemFactory;
+
+    /**
+     * @param \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory
+     * @param \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory
+     */
+    public function __construct(
+        \Magento\Tax\Model\Sales\Order\TaxFactory $orderTaxFactory,
+        \Magento\Sales\Model\Order\Tax\ItemFactory $taxItemFactory
+    ) {
+        $this->orderTaxFactory = $orderTaxFactory;
+        $this->taxItemFactory = $taxItemFactory;
+    }
+
+    /**
+     * Save order tax
+     *
+     * @param \Magento\Sales\Api\OrderRepositoryInterface $subject
+     * @param \Magento\Sales\Api\Data\OrderInterface $order
+     * @return \Magento\Sales\Api\Data\OrderInterface
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     */
+    public function afterSave(
+        \Magento\Sales\Api\OrderRepositoryInterface $subject,
+        \Magento\Sales\Api\Data\OrderInterface $order
+    ) {
+        $this->saveOrderTax($order);
+        return $order;
+    }
+
+    /**
+     * @param \Magento\Sales\Api\Data\OrderInterface $order
+     * @return $this
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    protected function saveOrderTax(\Magento\Sales\Api\Data\OrderInterface $order)
+    {
+        $extensionAttribute = $order->getExtensionAttributes();
+        if (!$extensionAttribute ||
+            !$extensionAttribute->getConvertingFromQuote() ||
+            $order->getAppliedTaxIsSaved()) {
+            return;
+        }
+
+        $taxes = $extensionAttribute->getAppliedTaxes();
+        if ($taxes == null) {
+            $taxes = [];
+        }
+
+        $taxesForItems = $extensionAttribute->getItemAppliedTaxes();
+        if ($taxesForItems == null) {
+            $taxesForItems = [];
+        }
+
+        $ratesIdQuoteItemId = [];
+        foreach ($taxesForItems as $taxesArray) {
+            foreach ($taxesArray as $rates) {
+                if (count($rates['rates']) == 1) {
+                    $ratesIdQuoteItemId[$rates['id']][] = [
+                        'id' => $rates['item_id'],
+                        'percent' => $rates['percent'],
+                        'code' => $rates['rates'][0]['code'],
+                        'associated_item_id' => $rates['associated_item_id'],
+                        'item_type' => $rates['item_type'],
+                        'amount' => $rates['amount'],
+                        'base_amount' => $rates['base_amount'],
+                        'real_amount' => $rates['amount'],
+                        'real_base_amount' => $rates['base_amount'],
+                    ];
+                } else {
+                    $percentSum = 0;
+                    foreach ($rates['rates'] as $rate) {
+                        $realAmount = $rates['amount'] * $rate['percent'] / $rates['percent'];
+                        $realBaseAmount = $rates['base_amount'] * $rate['percent'] / $rates['percent'];
+                        $ratesIdQuoteItemId[$rates['id']][] = [
+                            'id' => $rates['item_id'],
+                            'percent' => $rate['percent'],
+                            'code' => $rate['code'],
+                            'associated_item_id' => $rates['associated_item_id'],
+                            'item_type' => $rates['item_type'],
+                            'amount' => $rates['amount'],
+                            'base_amount' => $rates['base_amount'],
+                            'real_amount' => $realAmount,
+                            'real_base_amount' => $realBaseAmount,
+                        ];
+                        $percentSum += $rate['percent'];
+                    }
+                }
+            }
+        }
+
+        foreach ($taxes as $row) {
+            $id = $row['id'];
+            foreach ($row['rates'] as $tax) {
+                if ($row['percent'] == null) {
+                    $baseRealAmount = $row['base_amount'];
+                } else {
+                    if ($row['percent'] == 0 || $tax['percent'] == 0) {
+                        continue;
+                    }
+                    $baseRealAmount = $row['base_amount'] / $row['percent'] * $tax['percent'];
+                }
+                $hidden = isset($row['hidden']) ? $row['hidden'] : 0;
+                $priority = isset($tax['priority']) ? $tax['priority'] : 0;
+                $position = isset($tax['position']) ? $tax['position'] : 0;
+                $process = isset($row['process']) ? $row['process'] : 0;
+                $data = [
+                    'order_id' => $order->getEntityId(),
+                    'code' => $tax['code'],
+                    'title' => $tax['title'],
+                    'hidden' => $hidden,
+                    'percent' => $tax['percent'],
+                    'priority' => $priority,
+                    'position' => $position,
+                    'amount' => $row['amount'],
+                    'base_amount' => $row['base_amount'],
+                    'process' => $process,
+                    'base_real_amount' => $baseRealAmount,
+                ];
+
+                /** @var $orderTax \Magento\Tax\Model\Sales\Order\Tax */
+                $orderTax = $this->orderTaxFactory->create();
+                $result = $orderTax->setData($data)->save();
+
+                if (isset($ratesIdQuoteItemId[$id])) {
+                    foreach ($ratesIdQuoteItemId[$id] as $quoteItemId) {
+                        if ($quoteItemId['code'] == $tax['code']) {
+                            $itemId = null;
+                            $associatedItemId = null;
+                            if (isset($quoteItemId['id'])) {
+                                //This is a product item
+                                $item = $order->getItemByQuoteItemId($quoteItemId['id']);
+                                $itemId = $item->getId();
+                            } elseif (isset($quoteItemId['associated_item_id'])) {
+                                //This item is associated with a product item
+                                $item = $order->getItemByQuoteItemId($quoteItemId['associated_item_id']);
+                                $associatedItemId = $item->getId();
+                            }
+
+                            $data = [
+                                'item_id' => $itemId,
+                                'tax_id' => $result->getTaxId(),
+                                'tax_percent' => $quoteItemId['percent'],
+                                'associated_item_id' => $associatedItemId,
+                                'amount' => $quoteItemId['amount'],
+                                'base_amount' => $quoteItemId['base_amount'],
+                                'real_amount' => $quoteItemId['real_amount'],
+                                'real_base_amount' => $quoteItemId['real_base_amount'],
+                                'taxable_item_type' => $quoteItemId['item_type'],
+                            ];
+                            /** @var $taxItem \Magento\Sales\Model\Order\Tax\Item */
+                            $taxItem = $this->taxItemFactory->create();
+                            $taxItem->setData($data)->save();
+                        }
+                    }
+                }
+            }
+        }
+
+        $order->setAppliedTaxIsSaved(true);
+        return $this;
+    }
+}
diff --git a/app/code/Magento/Tax/Model/Quote/ToOrderConverter.php b/app/code/Magento/Tax/Model/Quote/ToOrderConverter.php
index c269ee02dad4e39942e757265796d51cd4f095fd..f45aebc00cbbc60b9c0b60da06024f69f23b7c0d 100644
--- a/app/code/Magento/Tax/Model/Quote/ToOrderConverter.php
+++ b/app/code/Magento/Tax/Model/Quote/ToOrderConverter.php
@@ -16,6 +16,20 @@ class ToOrderConverter
      */
     protected $quoteAddress;
 
+    /**
+     * @var \Magento\Sales\Api\Data\OrderExtensionFactory
+     */
+    protected $orderExtensionFactory;
+
+    /**
+     * @param \Magento\Sales\Api\Data\OrderExtensionFactory $orderExtensionFactory
+     */
+    public function __construct(
+        \Magento\Sales\Api\Data\OrderExtensionFactory $orderExtensionFactory
+    ) {
+        $this->orderExtensionFactory = $orderExtensionFactory;
+    }
+
     /**
      * @param QuoteAddressToOrder $subject
      * @param QuoteAddress $address
@@ -39,21 +53,20 @@ class ToOrderConverter
     {
         /** @var \Magento\Sales\Model\Order $order */
         $taxes = $this->quoteAddress->getAppliedTaxes();
-        if (is_array($taxes)) {
-            if (is_array($order->getAppliedTaxes())) {
-                $taxes = array_merge($order->getAppliedTaxes(), $taxes);
-            }
-            $order->setCustomAttribute('applied_taxes', $taxes);
-            $order->setCustomAttribute('converting_from_quote', true);
+        $extensionAttributes = $order->getExtensionAttributes();
+        if ($extensionAttributes == null) {
+            $extensionAttributes = $this->orderExtensionFactory->create();
+        }
+        if (!empty($taxes)) {
+            $extensionAttributes->setAppliedTaxes($taxes);
+            $extensionAttributes->setConvertingFromQuote(true);
         }
 
         $itemAppliedTaxes = $this->quoteAddress->getItemsAppliedTaxes();
-        if (is_array($itemAppliedTaxes)) {
-            if (is_array($order->getItemAppliedTaxes())) {
-                $itemAppliedTaxes = array_merge($order->getItemAppliedTaxes(), $itemAppliedTaxes);
-            }
-            $order->setCustomAttribute('item_applied_taxes', $itemAppliedTaxes);
+        if (!empty($itemAppliedTaxes)) {
+            $extensionAttributes->setItemAppliedTaxes($itemAppliedTaxes);
         }
+        $order->setExtensionAttributes($extensionAttributes);
         return $order;
     }
 }
diff --git a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php
index 66ad1afdbcad98f745caad2d25bc55af4ab53a91..a220173520494df90e106aa9c76734c667a83024 100644
--- a/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php
+++ b/app/code/Magento/Tax/Test/Unit/App/Action/ContextPluginTest.php
@@ -12,6 +12,16 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase
      */
     protected $taxHelperMock;
 
+    /**
+     * @var \Magento\Weee\Helper\Data
+     */
+    protected $weeeHelperMock;
+
+    /**
+     * @var \Magento\Weee\Model\Tax
+     */
+    protected $weeeTaxMock;
+
     /**
      * @var \Magento\Framework\App\Http\Context
      */
@@ -49,6 +59,14 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase
             ->disableOriginalConstructor()
             ->getMock();
 
+        $this->weeeHelperMock = $this->getMockBuilder('Magento\Weee\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->weeeTaxMock = $this->getMockBuilder('\Magento\Weee\Model\Tax')
+            ->disableOriginalConstructor()
+            ->getMock();
+
         $this->httpContextMock = $this->getMockBuilder('Magento\Framework\App\Http\Context')
             ->disableOriginalConstructor()
             ->getMock();
@@ -60,7 +78,8 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase
         $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session')
             ->disableOriginalConstructor()
             ->setMethods([
-                'getDefaultTaxBillingAddress', 'getDefaultTaxShippingAddress', 'getCustomerTaxClassId'
+                'getDefaultTaxBillingAddress', 'getDefaultTaxShippingAddress', 'getCustomerTaxClassId',
+                'getWebsiteId', 'isLoggedIn'
             ])
             ->getMock();
 
@@ -78,57 +97,87 @@ class ContextPluginTest extends \PHPUnit_Framework_TestCase
                 'customerSession' => $this->customerSessionMock,
                 'httpContext' => $this->httpContextMock,
                 'calculation' => $this->taxCalculationMock,
+                'weeeTax' => $this->weeeTaxMock,
                 'taxHelper' => $this->taxHelperMock,
+                'weeeHelper' => $this->weeeHelperMock,
                 'moduleManager' => $this->moduleManagerMock,
                 'cacheConfig' => $this->cacheConfigMock
             ]
         );
     }
 
-    public function testAroundDispatch()
+    /**
+     * @param bool $cache
+     * @param bool $taxEnabled
+     * @param bool $loggedIn
+     * @dataProvider dataProviderAroundDispatch
+     */
+    public function testAroundDispatch($cache, $taxEnabled, $loggedIn)
     {
+        $this->customerSessionMock->expects($this->any())
+            ->method('isLoggedIn')
+            ->willReturn($loggedIn);
+
         $this->moduleManagerMock->expects($this->any())
             ->method('isEnabled')
             ->with('Magento_PageCache')
-            ->willReturn(true);
+            ->willReturn($cache);
 
         $this->cacheConfigMock->expects($this->any())
             ->method('isEnabled')
-            ->willReturn(true);
-
-        $this->taxHelperMock->expects($this->any())
-            ->method('isCatalogPriceDisplayAffectedByTax')
-            ->willReturn(true);
-
-        $this->customerSessionMock->expects($this->once())
-            ->method('getDefaultTaxBillingAddress')
-            ->willReturn(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
-        $this->customerSessionMock->expects($this->once())
-            ->method('getDefaultTaxShippingAddress')
-            ->willReturn(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
-        $this->customerSessionMock->expects($this->once())
-            ->method('getCustomerTaxClassId')
-            ->willReturn(1);
-
-        $this->taxCalculationMock->expects($this->once())
-            ->method('getTaxRates')
-            ->with(
-                ['country_id' => 1, 'region_id' => null, 'postcode' => 11111],
-                ['country_id' => 1, 'region_id' => null, 'postcode' => 11111],
-                1
-            )
-            ->willReturn([]);
-
-        $this->httpContextMock->expects($this->once())
-            ->method('setValue')
-            ->with('tax_rates', [], 0);
-
-        $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
-        $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
-        $expectedResult = 'expectedResult';
-        $proceed = function ($request) use ($expectedResult) {
-            return $expectedResult;
-        };
-        $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+            ->willReturn($cache);
+
+        if ($cache && $loggedIn) {
+            $this->taxHelperMock->expects($this->any())
+                ->method('isCatalogPriceDisplayAffectedByTax')
+                ->willReturn($taxEnabled);
+
+            if ($taxEnabled) {
+                $this->customerSessionMock->expects($this->once())
+                    ->method('getDefaultTaxBillingAddress')
+                    ->willReturn(['country_id' => 1, 'region_id' => 1, 'postcode' => 11111]);
+                $this->customerSessionMock->expects($this->once())
+                    ->method('getDefaultTaxShippingAddress')
+                    ->willReturn(['country_id' => 1, 'region_id' => 1, 'postcode' => 11111]);
+                $this->customerSessionMock->expects($this->once())
+                    ->method('getCustomerTaxClassId')
+                    ->willReturn(1);
+
+                $this->taxCalculationMock->expects($this->once())
+                    ->method('getTaxRates')
+                    ->with(
+                        ['country_id' => 1, 'region_id' => 1, 'postcode' => 11111],
+                        ['country_id' => 1, 'region_id' => 1, 'postcode' => 11111],
+                        1
+                    )
+                    ->willReturn([]);
+
+                $this->httpContextMock->expects($this->any())
+                    ->method('setValue')
+                    ->with('tax_rates', [], 0);
+            }
+
+            $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
+            $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
+            $expectedResult = 'expectedResult';
+            $proceed = function ($request) use ($expectedResult) {
+                return $expectedResult;
+            };
+            $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+        }
+    }
+
+    /**
+     * @return array
+     */
+    public function dataProviderAroundDispatch()
+    {
+        return [
+            [false, false, false],
+            [true, true, false],
+            [true, true, true],
+            [true, false, true],
+            [true, true, true]
+        ];
     }
 }
diff --git a/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php b/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php
index 8ef95ead2e386d8e95a03ff03d02a76b8350c89b..1226fa6e9d35d62140f1abe8bae59273c496910d 100755
--- a/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php
+++ b/app/code/Magento/Tax/Test/Unit/Model/Observer/SessionTest.php
@@ -64,7 +64,7 @@ class SessionTest extends \PHPUnit_Framework_TestCase
         $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session')
             ->disableOriginalConstructor()
             ->setMethods([
-                'setCustomerTaxClassId', 'setDefaultTaxBillingAddress', 'setDefaultTaxShippingAddress'
+                'setCustomerTaxClassId', 'setDefaultTaxBillingAddress', 'setDefaultTaxShippingAddress', 'setWebsiteId'
             ])
             ->getMock();
 
diff --git a/app/code/Magento/Tax/Test/Unit/Model/Plugin/OrderSaveTest.php b/app/code/Magento/Tax/Test/Unit/Model/Plugin/OrderSaveTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f50e79c9658b377c088ab51aed488d2494ee8f82
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Unit/Model/Plugin/OrderSaveTest.php
@@ -0,0 +1,463 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Tax\Test\Unit\Model\Plugin;
+
+use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class OrderSaveTest extends \PHPUnit_Framework_TestCase
+{
+    const ORDERID = 123;
+    const ITEMID = 151;
+    const ORDER_ITEM_ID = 116;
+
+    /**
+     * @var \Magento\Tax\Model\Sales\Order\TaxFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $orderTaxFactoryMock;
+
+    /**
+     * @var \Magento\Sales\Model\Order\Tax\ItemFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $taxItemFactoryMock;
+
+    /**
+     * @var \Magento\Sales\Api\OrderRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $subjectMock;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    protected $objectManagerHelper;
+
+    /**
+     * @var \Magento\Tax\Model\Plugin\OrderSave
+     */
+    protected $model;
+
+    public function setUp()
+    {
+        $this->orderTaxFactoryMock = $this->getMockBuilder(
+            '\Magento\Tax\Model\Sales\Order\TaxFactory'
+        )->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->taxItemFactoryMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Tax\ItemFactory')
+            ->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+        $this->subjectMock = $this->getMockForAbstractClass('\Magento\Sales\Api\OrderRepositoryInterface');
+
+        $this->objectManagerHelper = new ObjectManager($this);
+        $this->model = $this->objectManagerHelper->getObject(
+            '\Magento\Tax\Model\Plugin\OrderSave',
+            [
+                'orderTaxFactory' => $this->orderTaxFactoryMock,
+                'taxItemFactory' => $this->taxItemFactoryMock,
+            ]
+        );
+    }
+
+    protected function setupOrderMock()
+    {
+        $orderMock = $this->getMockBuilder('\Magento\Sales\Model\Order')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'getExtensionAttributes',
+                    'getAppliedTaxIsSaved',
+                    'getItemByQuoteItemId',
+                    'setAppliedTaxIsSaved',
+                    'getEntityId',
+                ]
+            )->getMock();
+
+        return $orderMock;
+    }
+
+    protected function setupExtensionAttributeMock()
+    {
+        $orderExtensionAttributeMock = $this->getMockBuilder('\Magento\Sales\Api\Data\OrderExtensionInterface')
+            ->disableOriginalConstructor()
+            ->setMethods(
+                [
+                    'getAppliedTaxes',
+                    'getConvertingFromQuote',
+                    'getItemAppliedTaxes',
+                ]
+            )->getMock();
+
+        return $orderExtensionAttributeMock;
+    }
+
+    protected function verifyOrderTaxes($expectedTaxes)
+    {
+        $index = 0;
+        $orderTaxes = [];
+        foreach ($expectedTaxes as $orderTaxId => $orderTaxData) {
+            $orderTaxMock = $this->getMockBuilder('\Magento\Tax\Model\Sales\Order\Tax')
+                ->disableOriginalConstructor()
+                ->setMethods(
+                    [
+                        'getTaxId',
+                        'setData',
+                        'save',
+                    ]
+                )->getMock();
+            $orderTaxMock->expects($this->once())
+                ->method('setData')
+                ->with($orderTaxData)
+                ->willReturnSelf();
+            $orderTaxMock->expects($this->once())
+                ->method('save')
+                ->willReturnSelf();
+            $orderTaxMock->expects($this->atLeastOnce())
+                ->method('getTaxId')
+                ->willReturn($orderTaxId);
+            $this->orderTaxFactoryMock->expects($this->at($index))
+                ->method('create')
+                ->willReturn($orderTaxMock);
+            $orderTaxes[] = $orderTaxMock;
+            $index++;
+        }
+    }
+
+    public function verifyItemTaxes($expectedItemTaxes)
+    {
+        $index = 0;
+        $itemTaxes = [];
+        foreach ($expectedItemTaxes as $itemTax) {
+            $itemTaxMock = $this->getMockBuilder('\Magento\Tax\Model\Sales\Order\Tax\Item')
+                ->disableOriginalConstructor()
+                ->setMethods(
+                    [
+                        'setData',
+                        'save',
+                    ]
+                )->getMock();
+            $itemTaxMock->expects($this->once())
+                ->method('setData')
+                ->with($itemTax)
+                ->willReturnSelf();
+            $itemTaxMock->expects($this->once())
+                ->method('save')
+                ->willReturnSelf();
+            $this->taxItemFactoryMock->expects($this->at($index))
+                ->method('create')
+                ->willReturn($itemTaxMock);
+            $itemTaxes[] = $itemTaxMock;
+            $index++;
+        }
+    }
+
+    /**
+     * @dataProvider afterSaveDataProvider
+     */
+    public function testAfterSave(
+        $appliedTaxes,
+        $itemAppliedTaxes,
+        $expectedTaxes,
+        $expectedItemTaxes
+    ) {
+        $orderMock = $this->setupOrderMock();
+
+        $extensionAttributeMock = $this->setupExtensionAttributeMock();
+        $extensionAttributeMock->expects($this->any())
+            ->method('getConvertingFromQuote')
+            ->willReturn(true);
+        $extensionAttributeMock->expects($this->any())
+            ->method('getAppliedTaxes')
+            ->willReturn($appliedTaxes);
+        $extensionAttributeMock->expects($this->any())
+            ->method('getItemAppliedTaxes')
+            ->willReturn($itemAppliedTaxes);
+
+
+        $orderItemMock = $this->getMockBuilder('\Magento\Sales\Model\Order\Item')
+            ->disableOriginalConstructor()
+            ->setMethods(['getId', ])
+            ->getMock();
+        $orderItemMock->expects($this->atLeastOnce())
+            ->method('getId')
+            ->willReturn(self::ORDER_ITEM_ID);
+        $orderMock->expects($this->once())
+            ->method('getAppliedTaxIsSaved')
+            ->willReturn(false);
+        $orderMock->expects($this->once())
+            ->method('getExtensionAttributes')
+            ->willReturn($extensionAttributeMock);
+        $orderMock->expects($this->atLeastOnce())
+            ->method('getItemByQuoteItemId')
+            ->with(self::ITEMID)
+            ->willReturn($orderItemMock);
+        $orderMock->expects($this->atLeastOnce())
+            ->method('getEntityId')
+            ->willReturn(self::ORDERID);
+
+        $orderMock->expects($this->once())
+            ->method('setAppliedTaxIsSaved')
+            ->with(true);
+
+        $this->verifyOrderTaxes($expectedTaxes);
+        $this->verifyItemTaxes($expectedItemTaxes);
+
+        $this->assertEquals($orderMock, $this->model->afterSave($this->subjectMock, $orderMock));
+    }
+
+    /**
+     * @return array
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function afterSaveDataProvider()
+    {
+        return [
+            //one item with shipping
+            //three tax rates: state and national tax rates of 6 and 5 percent with priority 0
+            //city tax rate of 3 percent with priority 1
+            'item_with_shipping_three_tax' => [
+                'applied_taxes' => [
+                    [
+                        'amount' => 0.66,
+                        'base_amount' => 0.66,
+                        'percent' => 11,
+                        'id' => 'ILUS',
+                        'rates' => [
+                            [
+                                'percent' => 6,
+                                'code' => 'IL',
+                                'title' => 'IL',
+                            ],
+                            [
+                                'percent' => 5,
+                                'code' => 'US',
+                                'title' => 'US',
+                            ],
+                        ],
+                    ],
+                    [
+                        'amount' => 0.2,
+                        'base_amount' => 0.2,
+                        'percent' => 3.33,
+                        'id' => 'CityTax',
+                        'rates' => [
+                            [
+                                'percent' => 3,
+                                'code' => 'CityTax',
+                                'title' => 'CityTax',
+                            ],
+                        ],
+                    ],
+                ],
+                'item_applied_taxes' => [
+                    //item tax, three tax rates
+                    [
+                        //first two taxes are combined
+                        [
+                            'amount' => 0.11,
+                            'base_amount' => 0.11,
+                            'percent' => 11,
+                            'id' => 'ILUS',
+                            'rates' => [
+                                [
+                                    'percent' => 6,
+                                    'code' => 'IL',
+                                    'title' => 'IL',
+                                ],
+                                [
+                                    'percent' => 5,
+                                    'code' => 'US',
+                                    'title' => 'US',
+                                ],
+                            ],
+                            'item_id' => self::ITEMID,
+                            'item_type' => 'product',
+                            'associated_item_id' => null,
+                        ],
+                        //city tax
+                        [
+                            'amount' => 0.03,
+                            'base_amount' => 0.03,
+                            'percent' => 3.33,
+                            'id' => 'CityTax',
+                            'rates' => [
+                                [
+                                    'percent' => 3,
+                                    'code' => 'CityTax',
+                                    'title' => 'CityTax',
+                                ],
+                            ],
+                            'item_id' => self::ITEMID,
+                            'item_type' => 'product',
+                            'associated_item_id' => null,
+                        ],
+                    ],
+                    //shipping tax
+                    [
+                        //first two taxes are combined
+                        [
+                            'amount' => 0.55,
+                            'base_amount' => 0.55,
+                            'percent' => 11,
+                            'id' => 'ILUS',
+                            'rates' => [
+                                [
+                                    'percent' => 6,
+                                    'code' => 'IL',
+                                    'title' => 'IL',
+                                ],
+                                [
+                                    'percent' => 5,
+                                    'code' => 'US',
+                                    'title' => 'US',
+                                ],
+                            ],
+                            'item_id' => null,
+                            'item_type' => 'shipping',
+                            'associated_item_id' => null,
+                        ],
+                        //city tax
+                        [
+                            'amount' => 0.17,
+                            'base_amount' => 0.17,
+                            'percent' => 3.33,
+                            'id' => 'CityTax',
+                            'rates' => [
+                                [
+                                    'percent' => 3,
+                                    'code' => 'CityTax',
+                                    'title' => 'CityTax',
+                                ],
+                            ],
+                            'item_id' => null,
+                            'item_type' => 'shipping',
+                            'associated_item_id' => null,
+                        ],
+                    ],
+                ],
+                'expected_order_taxes' => [
+                    //state tax
+                    '35' => [
+                        'order_id' => self::ORDERID,
+                        'code' => 'IL',
+                        'title' => 'IL',
+                        'hidden' => 0,
+                        'percent' => 6,
+                        'priority' => 0,
+                        'position' => 0,
+                        'amount' => 0.66,
+                        'base_amount' => 0.66,
+                        'process' => 0,
+                        'base_real_amount' => 0.36,
+                    ],
+                    //federal tax
+                    '36' => [
+                        'order_id' => self::ORDERID,
+                        'code' => 'US',
+                        'title' => 'US',
+                        'hidden' => 0,
+                        'percent' => 5,
+                        'priority' => 0,
+                        'position' => 0,
+                        'amount' => 0.66, //combined amount
+                        'base_amount' => 0.66,
+                        'process' => 0,
+                        'base_real_amount' => 0.3, //portion for specific rate
+                    ],
+                    //city tax
+                    '37' => [
+                        'order_id' => self::ORDERID,
+                        'code' => 'CityTax',
+                        'title' => 'CityTax',
+                        'hidden' => 0,
+                        'percent' => 3,
+                        'priority' => 0,
+                        'position' => 0,
+                        'amount' => 0.2, //combined amount
+                        'base_amount' => 0.2,
+                        'process' => 0,
+                        'base_real_amount' => 0.18018018018018, //this number is meaningless since this is single rate
+                    ],
+                ],
+                'expected_item_taxes' => [
+                    [
+                        //state tax for item
+                        'item_id' => self::ORDER_ITEM_ID,
+                        'tax_id' => '35',
+                        'tax_percent' => 6,
+                        'associated_item_id' => null,
+                        'amount' => 0.11,
+                        'base_amount' => 0.11,
+                        'real_amount' => 0.06,
+                        'real_base_amount' => 0.06,
+                        'taxable_item_type' => 'product',
+                    ],
+                    [
+                        //state tax for shipping
+                        'item_id' => null,
+                        'tax_id' => '35',
+                        'tax_percent' => 6,
+                        'associated_item_id' => null,
+                        'amount' => 0.55,
+                        'base_amount' => 0.55,
+                        'real_amount' => 0.3,
+                        'real_base_amount' => 0.3,
+                        'taxable_item_type' => 'shipping',
+                    ],
+                    [
+                        //federal tax for item
+                        'item_id' => self::ORDER_ITEM_ID,
+                        'tax_id' => '36',
+                        'tax_percent' => 5,
+                        'associated_item_id' => null,
+                        'amount' => 0.11,
+                        'base_amount' => 0.11,
+                        'real_amount' => 0.05,
+                        'real_base_amount' => 0.05,
+                        'taxable_item_type' => 'product',
+                    ],
+                    [
+                        //federal tax for shipping
+                        'item_id' => null,
+                        'tax_id' => '36',
+                        'tax_percent' => 5,
+                        'associated_item_id' => null,
+                        'amount' => 0.55,
+                        'base_amount' => 0.55,
+                        'real_amount' => 0.25,
+                        'real_base_amount' => 0.25,
+                        'taxable_item_type' => 'shipping',
+                    ],
+                    [
+                        //city tax for item
+                        'item_id' => self::ORDER_ITEM_ID,
+                        'tax_id' => '37',
+                        'tax_percent' => 3.33,
+                        'associated_item_id' => null,
+                        'amount' => 0.03,
+                        'base_amount' => 0.03,
+                        'real_amount' => 0.03,
+                        'real_base_amount' => 0.03,
+                        'taxable_item_type' => 'product',
+                    ],
+                    [
+                        //city tax for shipping
+                        'item_id' => null,
+                        'tax_id' => '37',
+                        'tax_percent' => 3.33,
+                        'associated_item_id' => null,
+                        'amount' => 0.17,
+                        'base_amount' => 0.17,
+                        'real_amount' => 0.17,
+                        'real_base_amount' => 0.17,
+                        'taxable_item_type' => 'shipping',
+                    ],
+                ],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Tax/Test/Unit/Model/Quote/ToOrderConverterTest.php b/app/code/Magento/Tax/Test/Unit/Model/Quote/ToOrderConverterTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cc72250a496783692451f8c12ecc610f9de28d43
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Unit/Model/Quote/ToOrderConverterTest.php
@@ -0,0 +1,195 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Tax\Test\Unit\Model\Quote;
+
+use \Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+
+class ToOrderConverterTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Sales\Api\Data\OrderExtensionFactory|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $orderExtensionFactoryMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote\Address|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $quoteAddressMock;
+
+    /**
+     * @var \Magento\Quote\Model\Quote\Address\ToOrder|\PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $subjectMock;
+
+    /**
+     * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager
+     */
+    protected $objectManagerHelper;
+
+    /**
+     * @var \Magento\Tax\Model\Quote\ToOrderConverter
+     */
+    protected $model;
+
+    public function setUp()
+    {
+        $this->orderExtensionFactoryMock = $this->getMockBuilder(
+            '\Magento\Sales\Api\Data\OrderExtensionFactory'
+        )->disableOriginalConstructor()
+            ->setMethods(['create'])
+            ->getMock();
+
+        $this->quoteAddressMock = $this->getMockBuilder('\Magento\Quote\Model\Quote\Address')
+            ->disableOriginalConstructor()
+            ->setMethods(['getAppliedTaxes', 'getItemsAppliedTaxes'])
+            ->getMock();
+        $this->subjectMock = $this->getMockBuilder('\Magento\Quote\Model\Quote\Address\ToOrder')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->objectManagerHelper = new ObjectManager($this);
+        $this->model = $this->objectManagerHelper->getObject(
+            '\Magento\Tax\Model\Quote\ToOrderConverter',
+            [
+                'orderExtensionFactory' => $this->orderExtensionFactoryMock,
+            ]
+        );
+    }
+
+    protected function setupOrderExtensionAttributeMock()
+    {
+        $orderExtensionAttributeMock = $this->getMockBuilder('\Magento\Sales\Api\Data\OrderExtensionInterface')
+            ->setMethods(
+                [
+                    'setAppliedTaxes',
+                    'setConvertingFromQuote',
+                    'setItemAppliedTaxes'
+                ]
+            )->getMock();
+
+        return $orderExtensionAttributeMock;
+    }
+
+    /**
+     * @dataProvider afterConvertDataProvider
+     */
+    public function testAfterConvert($appliedTaxes, $itemsAppliedTaxes)
+    {
+        $this->model->beforeConvert($this->subjectMock, $this->quoteAddressMock);
+
+        $this->quoteAddressMock->expects($this->once())
+            ->method('getAppliedTaxes')
+            ->willReturn($appliedTaxes);
+        $this->quoteAddressMock->expects($this->once())
+            ->method('getItemsAppliedTaxes')
+            ->willReturn($itemsAppliedTaxes);
+
+        $orderMock = $this->getMockBuilder('\Magento\Sales\Model\Order')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $orderExtensionAttributeMock = $this->setupOrderExtensionAttributeMock();
+
+        $orderMock->expects($this->once())
+            ->method('getExtensionAttributes')
+            ->willReturn($orderExtensionAttributeMock);
+
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setAppliedTaxes')
+            ->with($appliedTaxes);
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setConvertingFromQuote')
+            ->with(true);
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setItemAppliedTaxes')
+            ->with($itemsAppliedTaxes);
+        $orderMock->expects($this->once())
+            ->method('setExtensionAttributes')
+            ->with($orderExtensionAttributeMock);
+
+        $this->assertEquals($orderMock, $this->model->afterConvert($this->subjectMock, $orderMock));
+    }
+
+    /**
+     * @dataProvider afterConvertDataProvider
+     */
+    public function testAfterConvertNullExtensionAttribute($appliedTaxes, $itemsAppliedTaxes)
+    {
+        $this->model->beforeConvert($this->subjectMock, $this->quoteAddressMock);
+
+        $this->quoteAddressMock->expects($this->once())
+            ->method('getAppliedTaxes')
+            ->willReturn($appliedTaxes);
+        $this->quoteAddressMock->expects($this->once())
+            ->method('getItemsAppliedTaxes')
+            ->willReturn($itemsAppliedTaxes);
+
+        $orderExtensionAttributeMock = $this->setupOrderExtensionAttributeMock();
+        
+        $orderMock = $this->getMockBuilder('\Magento\Sales\Model\Order')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $orderMock->expects($this->once())
+            ->method('getExtensionAttributes')
+            ->willReturn(null);
+
+        $this->orderExtensionFactoryMock->expects($this->once())
+            ->method('create')
+            ->willReturn($orderExtensionAttributeMock);
+
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setAppliedTaxes')
+            ->with($appliedTaxes);
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setConvertingFromQuote')
+            ->with(true);
+        $orderExtensionAttributeMock->expects($this->once())
+            ->method('setItemAppliedTaxes')
+            ->with($itemsAppliedTaxes);
+        $orderMock->expects($this->once())
+            ->method('setExtensionAttributes')
+            ->with($orderExtensionAttributeMock);
+
+        $this->assertEquals($orderMock, $this->model->afterConvert($this->subjectMock, $orderMock));
+    }
+
+    public function afterConvertDataProvider()
+    {
+        return [
+            'afterConvert' => [
+                'applied_taxes' => [
+                    'IL' => [
+                        'amount' => 0.36,
+                        'percent' => 6,
+                        'rates' => [
+                            [
+                                'percent' => 6,
+                                'code' => 'IL',
+                                'title' => 'IL',
+                            ]
+                        ]
+                    ]
+                ],
+                'item_applied_taxes' => [
+                    'sequence-1' => [
+                        [
+                            'amount' => 0.06,
+                            'item_id' => 146,
+                        ],
+                    ],
+                    'shipping' => [
+                        [
+                            'amount' => 0.30,
+                            'item_type' => 'shipping',
+                        ]
+                    ],
+                ],
+            ],
+        ];
+    }
+}
diff --git a/app/code/Magento/Tax/etc/di.xml b/app/code/Magento/Tax/etc/di.xml
index 7b8eb051ac01d4018fa41484b157c856cc5e2d09..48b3173d60f09e739305f3c68cf501be8315be96 100644
--- a/app/code/Magento/Tax/etc/di.xml
+++ b/app/code/Magento/Tax/etc/di.xml
@@ -77,4 +77,7 @@
             <argument name="resourcePrefix" xsi:type="string">sales</argument>
         </arguments>
     </type>
+    <type name="Magento\Sales\Api\OrderRepositoryInterface">
+        <plugin name="save_order_tax" type="Magento\Tax\Model\Plugin\OrderSave"/>
+    </type>
 </config>
diff --git a/app/code/Magento/Tax/etc/events.xml b/app/code/Magento/Tax/etc/events.xml
index 4d2c2d3ba60da356a557d9c5f87e6fc33df14cd2..b523cf565dd000c1b1e0877911973ca364534642 100644
--- a/app/code/Magento/Tax/etc/events.xml
+++ b/app/code/Magento/Tax/etc/events.xml
@@ -6,9 +6,6 @@
  */
 -->
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Event/etc/events.xsd">
-    <event name="sales_order_save_after">
-        <observer name="tax" instance="Magento\Tax\Model\Observer" method="salesEventOrderAfterSave" />
-    </event>
     <event name="sales_quote_collect_totals_before">
         <observer name="tax" instance="Magento\Tax\Model\Observer" method="quoteCollectTotalsBefore" />
     </event>
diff --git a/app/code/Magento/Tax/etc/extension_attributes.xml b/app/code/Magento/Tax/etc/extension_attributes.xml
index 0302ae2fcd16a12a2f270d5f7e04fda059c52af4..810c04b8c1917e9230db99faeac529445844b019 100644
--- a/app/code/Magento/Tax/etc/extension_attributes.xml
+++ b/app/code/Magento/Tax/etc/extension_attributes.xml
@@ -9,4 +9,9 @@
     <extension_attributes for="Magento\Quote\Api\Data\TotalsInterface">
         <attribute code="tax_grandtotal_details" type="Magento\Tax\Api\Data\GrandTotalDetailsInterface[]" />
     </extension_attributes>
+    <extension_attributes for="Magento\Sales\Api\Data\OrderInterface">
+        <attribute code="applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsAppliedTaxInterface[]" />
+        <attribute code="item_applied_taxes" type="Magento\Tax\Api\Data\OrderTaxDetailsItemInterface[]" />
+        <attribute code="converting_from_quote" type="boolean" />
+    </extension_attributes>
 </config>
diff --git a/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fcb1aa0e363166b4b39e7cb4296a165b02ab123
--- /dev/null
+++ b/app/code/Magento/Weee/Model/App/Action/ContextPlugin.php
@@ -0,0 +1,205 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+namespace Magento\Weee\Model\App\Action;
+
+/**
+ * Class ContextPlugin
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ContextPlugin
+{
+    /**
+     * @var \Magento\Customer\Model\Session
+     */
+    protected $customerSession;
+
+    /**
+     * @var \Magento\Framework\App\Http\Context
+     */
+    protected $httpContext;
+
+    /**
+     * @var \Magento\Tax\Helper\Data
+     */
+    protected $taxHelper;
+
+    /**
+     * @var \Magento\Weee\Helper\Data
+     */
+    protected $weeeHelper;
+
+    /**
+     * @var \Magento\Framework\Module\Manager
+     */
+    protected $moduleManager;
+
+    /**
+     * @var \Magento\Weee\Model\Tax
+     */
+    protected $weeeTax;
+
+    /**
+     * @var \Magento\PageCache\Model\Config
+     */
+    protected $cacheConfig;
+
+    /**
+     * @var \Magento\Store\Model\StoreManagerInterface
+     */
+    protected $storeManager;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfigInterface
+     */
+    protected $scopeConfig;
+
+    /**
+     * @param \Magento\Customer\Model\Session $customerSession
+     * @param \Magento\Framework\App\Http\Context $httpContext
+     * @param \Magento\Weee\Model\Tax $weeeTax
+     * @param \Magento\Tax\Helper\Data $taxHelper
+     * @param \Magento\Weee\Helper\Data $weeeHelper
+     * @param \Magento\Framework\Module\Manager $moduleManager
+     * @param \Magento\PageCache\Model\Config $cacheConfig
+     * @param \Magento\Store\Model\StoreManagerInterface $storeManager
+     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+     */
+    public function __construct(
+        \Magento\Customer\Model\Session $customerSession,
+        \Magento\Framework\App\Http\Context $httpContext,
+        \Magento\Weee\Model\Tax $weeeTax,
+        \Magento\Tax\Helper\Data $taxHelper,
+        \Magento\Weee\Helper\Data $weeeHelper,
+        \Magento\Framework\Module\Manager $moduleManager,
+        \Magento\PageCache\Model\Config $cacheConfig,
+        \Magento\Store\Model\StoreManagerInterface $storeManager,
+        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
+    ) {
+        $this->customerSession = $customerSession;
+        $this->httpContext = $httpContext;
+        $this->weeeTax = $weeeTax;
+        $this->taxHelper = $taxHelper;
+        $this->weeeHelper = $weeeHelper;
+        $this->moduleManager = $moduleManager;
+        $this->cacheConfig = $cacheConfig;
+        $this->storeManager = $storeManager;
+        $this->scopeConfig = $scopeConfig;
+    }
+
+    /**
+     * @param \Magento\Framework\App\Action\Action $subject
+     * @param callable $proceed
+     * @param \Magento\Framework\App\RequestInterface $request
+     * @return mixed
+     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+     */
+    public function aroundDispatch(
+        \Magento\Framework\App\Action\Action $subject,
+        \Closure $proceed,
+        \Magento\Framework\App\RequestInterface $request
+    ) {
+        if (!$this->weeeHelper->isEnabled() ||
+            !$this->customerSession->isLoggedIn() ||
+            !$this->moduleManager->isEnabled('Magento_PageCache') ||
+            !$this->cacheConfig->isEnabled()) {
+            return $proceed($request);
+        }
+
+        $basedOn = $this->taxHelper->getTaxBasedOn();
+        if ($basedOn != 'shipping' && $basedOn != 'billing') {
+            return $proceed($request);
+        }
+
+        $weeeTaxRegion = $this->getWeeeTaxRegion($basedOn);
+        $websiteId = $this->storeManager->getStore()->getWebsiteId();
+        $countryId = $weeeTaxRegion['countryId'];
+        $regionId = $weeeTaxRegion['regionId'];
+
+        if (!$countryId && !$regionId) {
+            // country and region does not exist
+            return $proceed($request);
+        } else if ($countryId && !$regionId) {
+            // country exist and region does not exist
+            $regionId = 0;
+            $exist = $this->weeeTax->isWeeeInLocation(
+                $countryId,
+                $regionId,
+                $websiteId
+            );
+        } else {
+            // country and region exist
+            $exist = $this->weeeTax->isWeeeInLocation(
+                $countryId,
+                $regionId,
+                $websiteId
+            );
+            if (!$exist) {
+                // just check the country for weee
+                $regionId = 0;
+                $exist = $this->weeeTax->isWeeeInLocation(
+                    $countryId,
+                    $regionId,
+                    $websiteId
+                );
+            }
+        }
+
+        if ($exist) {
+            $this->httpContext->setValue(
+                'weee_tax_region',
+                ['countryId' => $countryId, 'regionId' => $regionId],
+                0
+            );
+        }
+        return $proceed($request);
+    }
+
+    /**
+     * @param string $basedOn
+     * @return array
+     */
+    protected function getWeeeTaxRegion($basedOn)
+    {
+        $countryId = null;
+        $regionId = null;
+        $defaultCountryId = $this->scopeConfig->getValue(
+            \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY,
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            null
+        );
+        $defaultRegionId = $this->scopeConfig->getValue(
+            \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
+            \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+            null
+        );
+
+        if ($basedOn == 'shipping') {
+            $defaultShippingAddress = $this->customerSession->getDefaultTaxShippingAddress();
+            if (empty($defaultShippingAddress)) {
+                $countryId = $defaultCountryId;
+                $regionId = $defaultRegionId;
+            } else {
+                $countryId = $defaultShippingAddress['country_id'];
+                $regionId = $defaultShippingAddress['region_id'];
+            }
+
+        } else if ($basedOn == 'billing') {
+            $defaultBillingAddress = $this->customerSession->getDefaultTaxBillingAddress();
+            if (empty($defaultBillingAddress)) {
+                $countryId = $defaultCountryId;
+                $regionId = $defaultRegionId;
+            } else {
+                $countryId = $defaultBillingAddress['country_id'];
+                $regionId = $defaultBillingAddress['region_id'];
+            }
+        }
+        return ['countryId' => $countryId, 'regionId' => $regionId];
+    }
+}
diff --git a/app/code/Magento/Weee/Model/Observer/Session.php b/app/code/Magento/Weee/Model/Observer/Session.php
new file mode 100644
index 0000000000000000000000000000000000000000..7f72b64c6bf792eff2d650191fa8016cb5ad2325
--- /dev/null
+++ b/app/code/Magento/Weee/Model/Observer/Session.php
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/**
+ * Customer Session Event Observer
+ */
+namespace Magento\Weee\Model\Observer;
+
+class Session
+{
+    /**
+     * @var \Magento\Customer\Model\Session
+     */
+    protected $customerSession;
+
+    /**
+     * @var \Magento\Weee\Helper\Data
+     */
+    protected $weeeHelper;
+
+    /**
+     * Module manager
+     *
+     * @var \Magento\Framework\Module\Manager
+     */
+    private $moduleManager;
+
+    /**
+     * Cache config
+     *
+     * @var \Magento\PageCache\Model\Config
+     */
+    private $cacheConfig;
+
+    /**
+     * @param \Magento\Customer\Model\Session $customerSession
+     * @param \Magento\Weee\Helper\Data $weeeHelper
+     * @param \Magento\Framework\Module\Manager $moduleManager
+     * @param \Magento\PageCache\Model\Config $cacheConfig
+     */
+    public function __construct(
+        \Magento\Customer\Model\Session $customerSession,
+        \Magento\Weee\Helper\Data $weeeHelper,
+        \Magento\Framework\Module\Manager $moduleManager,
+        \Magento\PageCache\Model\Config $cacheConfig
+    ) {
+        $this->customerSession = $customerSession;
+        $this->weeeHelper = $weeeHelper;
+        $this->moduleManager = $moduleManager;
+        $this->cacheConfig = $cacheConfig;
+    }
+
+    /**
+     * @param \Magento\Framework\Event\Observer $observer
+     * @return void
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function customerLoggedIn(\Magento\Framework\Event\Observer $observer)
+    {
+        if ($this->moduleManager->isEnabled('Magento_PageCache') && $this->cacheConfig->isEnabled() &&
+            $this->weeeHelper->isEnabled()) {
+            /** @var \Magento\Customer\Model\Data\Customer $customer */
+            $customer = $observer->getData('customer');
+
+            /** @var \Magento\Customer\Api\Data\AddressInterface[] $addresses */
+            $addresses = $customer->getAddresses();
+            if (isset($addresses)) {
+                $defaultShippingFound = false;
+                $defaultBillingFound = false;
+                foreach ($addresses as $address) {
+                    if ($address->isDefaultBilling()) {
+                        $defaultBillingFound = true;
+                        $this->customerSession->setDefaultTaxBillingAddress(
+                            [
+                                'country_id' => $address->getCountryId(),
+                                'region_id'  => $address->getRegion() ? $address->getRegion()->getRegionId() : null,
+                                'postcode'   => $address->getPostcode(),
+                            ]
+                        );
+                    }
+                    if ($address->isDefaultShipping()) {
+                        $defaultShippingFound = true;
+                        $this->customerSession->setDefaultTaxShippingAddress(
+                            [
+                                'country_id' => $address->getCountryId(),
+                                'region_id'  => $address->getRegion() ? $address->getRegion()->getRegionId() : null,
+                                'postcode'   => $address->getPostcode(),
+                            ]
+                        );
+                    }
+                    if ($defaultShippingFound && $defaultBillingFound) {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Address after save event handler
+     *
+     * @param \Magento\Framework\Event\Observer $observer
+     * @return void
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     */
+    public function afterAddressSave($observer)
+    {
+        if ($this->moduleManager->isEnabled('Magento_PageCache') && $this->cacheConfig->isEnabled() &&
+            $this->weeeHelper->isEnabled()) {
+            /** @var $customerAddress Address */
+            $address = $observer->getCustomerAddress();
+
+            // Check if the address is either the default billing, shipping, or both
+            if ($address->getIsPrimaryBilling() || $address->getIsDefaultBilling()) {
+                $this->customerSession->setDefaultTaxBillingAddress(
+                    [
+                        'country_id' => $address->getCountryId(),
+                        'region_id'  => $address->getRegion() ? $address->getRegionId() : null,
+                        'postcode'   => $address->getPostcode(),
+                    ]
+                );
+            }
+
+            if ($address->getIsPrimaryShipping() || $address->getIsDefaultShipping()) {
+                $this->customerSession->setDefaultTaxShippingAddress(
+                    [
+                        'country_id' => $address->getCountryId(),
+                        'region_id'  => $address->getRegion() ? $address->getRegionId() : null,
+                        'postcode'   => $address->getPostcode(),
+                    ]
+                );
+            }
+        }
+    }
+}
diff --git a/app/code/Magento/Weee/Model/Resource/Tax.php b/app/code/Magento/Weee/Model/Resource/Tax.php
index e55e57340028adefa033fe7f02ba45e081ed9fcc..ee7e3783b9d62d0e305c28d03097f990be3d24c3 100644
--- a/app/code/Magento/Weee/Model/Resource/Tax.php
+++ b/app/code/Magento/Weee/Model/Resource/Tax.php
@@ -52,4 +52,38 @@ class Tax extends \Magento\Framework\Model\Resource\Db\AbstractDb
     {
         return $this->_getReadAdapter()->fetchOne($select);
     }
+
+    /**
+     * @param int $countryId
+     * @param int $regionId
+     * @param int $websiteId
+     * @return boolean
+     */
+    public function isWeeeInLocation($countryId, $regionId, $websiteId)
+    {
+        // Check if there is a weee_tax for the country and region
+        $attributeSelect = $this->getReadConnection()->select();
+        $attributeSelect->from(
+            $this->getTable('weee_tax'),
+            'value'
+        )->where(
+            'website_id IN(?)',
+            [$websiteId, 0]
+        )->where(
+            'country = ?',
+            $countryId
+        )->where(
+            'state = ?',
+            $regionId
+        )->limit(
+            1
+        );
+
+        $value = $this->getReadConnection()->fetchOne($attributeSelect);
+        if ($value) {
+            return true;
+        }
+
+        return false;
+    }
 }
diff --git a/app/code/Magento/Weee/Model/Tax.php b/app/code/Magento/Weee/Model/Tax.php
index 3b41cdeeb598382ab50aa542c442c0d672e0da65..91dd14ffa3f1f26d0607b862f2eae95544d20431 100644
--- a/app/code/Magento/Weee/Model/Tax.php
+++ b/app/code/Magento/Weee/Model/Tax.php
@@ -232,8 +232,18 @@ class Tax extends \Magento\Framework\Model\AbstractModel
             if ($customerId = $this->_customerSession->getCustomerId()) {
                 $shipping = $this->accountManagement->getDefaultShippingAddress($customerId);
                 $billing = $this->accountManagement->getDefaultBillingAddress($customerId);
+                $customerTaxClass = null;
+            } else {
+                $shippingAddressArray = $this->_customerSession->getDefaultTaxShippingAddress();
+                $billingAddressArray = $this->_customerSession->getDefaultTaxBillingAddress();
+                if (!empty($billingAddressArray)) {
+                    $billing = new \Magento\Framework\Object($billingAddressArray);
+                }
+                if (!empty($shippingAddressArray)) {
+                    $shipping = new \Magento\Framework\Object($shippingAddressArray);
+                }
+                $customerTaxClass = $this->_customerSession->getCustomerTaxClassId();
             }
-            $customerTaxClass = null;
         }
 
         $rateRequest = $calculator->getRateRequest(
@@ -322,4 +332,15 @@ class Tax extends \Magento\Framework\Model\AbstractModel
         }
         return $result;
     }
+
+    /**
+     * @param int $countryId
+     * @param int $regionId
+     * @param int $websiteId
+     * @return boolean
+     */
+    public function isWeeeInLocation($countryId, $regionId, $websiteId)
+    {
+        return $this->getResource()->isWeeeInLocation($countryId, $regionId, $websiteId);
+    }
 }
diff --git a/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0f7a3ad75fb91b47bdcd3a62aea9ca32b7495586
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/App/Action/ContextPluginTest.php
@@ -0,0 +1,378 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Weee\Test\Unit\App\Action;
+
+/**
+ * Class ContextPluginTest
+ *
+ * @package Magento\Weee\Test\Unit\App\Action
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class ContextPluginTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Tax\Helper\Data
+     */
+    protected $taxHelperMock;
+
+    /**
+     * @var \Magento\Weee\Helper\Data
+     */
+    protected $weeeHelperMock;
+
+    /**
+     * @var \Magento\Weee\Model\Tax
+     */
+    protected $weeeTaxMock;
+
+    /**
+     * @var \Magento\Framework\App\Http\Context
+     */
+    protected $httpContextMock;
+
+    /**
+     * @var \Magento\Tax\Model\Calculation\Proxy
+     */
+    protected $taxCalculationMock;
+
+    /**
+     * @var \Magento\Framework\Module\Manager
+     */
+    protected $moduleManagerMock;
+
+    /**
+     * @var \Magento\PageCache\Model\Config
+     */
+    protected $cacheConfigMock;
+
+    /**
+     * @var \Magento\Store\Model\StoreManager
+     */
+    protected $storeManageMock;
+
+    /**
+     * @var \Magento\Framework\App\Config\ScopeConfig
+     */
+    protected $scopeConfigMock;
+
+    /**
+     * @var \Magento\Tax\Model\App\Action\ContextPlugin
+     */
+    protected $contextPlugin;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->taxHelperMock = $this->getMockBuilder('Magento\Tax\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->weeeHelperMock = $this->getMockBuilder('Magento\Weee\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->weeeTaxMock = $this->getMockBuilder('\Magento\Weee\Model\Tax')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->httpContextMock = $this->getMockBuilder('Magento\Framework\App\Http\Context')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session')
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'getDefaultTaxBillingAddress', 'getDefaultTaxShippingAddress', 'getCustomerTaxClassId',
+                'getWebsiteId', 'isLoggedIn'
+            ])
+            ->getMock();
+
+        $this->moduleManagerMock = $this->getMockBuilder('Magento\Framework\Module\Manager')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->cacheConfigMock = $this->getMockBuilder('Magento\PageCache\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->storeManagerMock = $this->getMockBuilder('Magento\Store\Model\StoreManager')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->scopeConfigMock = $this->getMockBuilder('Magento\Framework\App\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->contextPlugin = $this->objectManager->getObject(
+            'Magento\Weee\Model\App\Action\ContextPlugin',
+            [
+                'customerSession' => $this->customerSessionMock,
+                'httpContext' => $this->httpContextMock,
+                'weeeTax' => $this->weeeTaxMock,
+                'taxHelper' => $this->taxHelperMock,
+                'weeeHelper' => $this->weeeHelperMock,
+                'moduleManager' => $this->moduleManagerMock,
+                'cacheConfig' => $this->cacheConfigMock,
+                'storeManager' => $this->storeManagerMock,
+                'scopeConfig' => $this->scopeConfigMock
+            ]
+        );
+    }
+
+    public function testAroundDispatchBasedOnDefault()
+    {
+        $this->customerSessionMock->expects($this->once())
+            ->method('isLoggedIn')
+            ->willReturn(true);
+
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->taxHelperMock->expects($this->once())
+            ->method('getTaxBasedOn')
+            ->willReturn('billing');
+
+        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $storeMock->expects($this->once())
+            ->method('getWebsiteId')
+            ->willReturn(1);
+
+        $this->storeManagerMock->expects($this->once())
+            ->method('getStore')
+            ->willReturn($storeMock);
+
+        $this->scopeConfigMock->expects($this->at(0))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn('US');
+
+        $this->scopeConfigMock->expects($this->at(1))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn(0);
+
+        $this->weeeTaxMock->expects($this->once())
+            ->method('isWeeeInLocation')
+            ->with('US', 0, 1)
+            ->willReturn(true);
+
+        $this->httpContextMock->expects($this->once())
+            ->method('setValue')
+            ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 0], 0);
+
+        $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
+        $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
+        $expectedResult = 'expectedResult';
+        $proceed = function ($request) use ($expectedResult) {
+            return $expectedResult;
+        };
+        $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+    }
+
+    public function testAroundDispatchBasedOnOrigin()
+    {
+        $this->customerSessionMock->expects($this->once())
+            ->method('isLoggedIn')
+            ->willReturn(true);
+
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->taxHelperMock->expects($this->once())
+            ->method('getTaxBasedOn')
+            ->willReturn('origin');
+
+        $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
+        $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
+        $expectedResult = 'expectedResult';
+        $proceed = function ($request) use ($expectedResult) {
+            return $expectedResult;
+        };
+        $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+    }
+
+    public function testAroundDispatchBasedOnBilling()
+    {
+        $this->customerSessionMock->expects($this->once())
+            ->method('isLoggedIn')
+            ->willReturn(true);
+
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->taxHelperMock->expects($this->once())
+            ->method('getTaxBasedOn')
+            ->willReturn('billing');
+
+        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $storeMock->expects($this->once())
+            ->method('getWebsiteId')
+            ->willReturn(1);
+
+        $this->storeManagerMock->expects($this->once())
+            ->method('getStore')
+            ->willReturn($storeMock);
+
+        $this->scopeConfigMock->expects($this->at(0))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn('US');
+
+        $this->scopeConfigMock->expects($this->at(1))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn(0);
+
+        $this->customerSessionMock->expects($this->once())
+            ->method('getDefaultTaxBillingAddress')
+            ->willReturn(['country_id' => 'US', 'region_id' => 1]);
+
+        $this->weeeTaxMock->expects($this->once())
+            ->method('isWeeeInLocation')
+            ->with('US', 1, 1)
+            ->willReturn(true);
+
+        $this->httpContextMock->expects($this->once())
+            ->method('setValue')
+            ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 1], 0);
+
+        $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
+        $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
+        $expectedResult = 'expectedResult';
+        $proceed = function ($request) use ($expectedResult) {
+            return $expectedResult;
+        };
+        $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+    }
+
+    public function testAroundDispatchBasedOnShipping()
+    {
+        $this->customerSessionMock->expects($this->once())
+            ->method('isLoggedIn')
+            ->willReturn(true);
+
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->taxHelperMock->expects($this->once())
+            ->method('getTaxBasedOn')
+            ->willReturn('shipping');
+
+        $storeMock = $this->getMockBuilder('Magento\Store\Model\Store')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $storeMock->expects($this->once())
+            ->method('getWebsiteId')
+            ->willReturn(1);
+
+        $this->storeManagerMock->expects($this->once())
+            ->method('getStore')
+            ->willReturn($storeMock);
+
+        $this->scopeConfigMock->expects($this->at(0))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_COUNTRY,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn('US');
+
+        $this->scopeConfigMock->expects($this->at(1))
+            ->method('getValue')
+            ->with(
+                \Magento\Tax\Model\Config::CONFIG_XML_PATH_DEFAULT_REGION,
+                \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
+                null
+            )
+            ->willReturn(0);
+
+        $this->customerSessionMock->expects($this->once())
+            ->method('getDefaultTaxShippingAddress')
+            ->willReturn(['country_id' => 'US', 'region_id' => 1]);
+
+        $this->weeeTaxMock->expects($this->once())
+            ->method('isWeeeInLocation')
+            ->with('US', 1, 1)
+            ->willReturn(true);
+
+        $this->httpContextMock->expects($this->once())
+            ->method('setValue')
+            ->with('weee_tax_region', ['countryId' => 'US', 'regionId' => 1], 0);
+
+        $action = $this->objectManager->getObject('Magento\Framework\App\Action\Action');
+        $request = $this->getMock('\Magento\Framework\App\Request\Http', ['getActionName'], [], '', false);
+        $expectedResult = 'expectedResult';
+        $proceed = function ($request) use ($expectedResult) {
+            return $expectedResult;
+        };
+        $this->contextPlugin->aroundDispatch($action, $proceed, $request);
+    }
+}
diff --git a/app/code/Magento/Weee/Test/Unit/Model/Observer/SessionTest.php b/app/code/Magento/Weee/Test/Unit/Model/Observer/SessionTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..db31c7931bedab29ca21223702a8b8cd035a3070
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Model/Observer/SessionTest.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Weee\Test\Unit\Model\Observer;
+
+class SessionTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Framework\Event\Observer
+     */
+    protected $observerMock;
+
+    /**
+     * @var \Magento\Customer\Model\Session
+     */
+    protected $customerSessionMock;
+
+    /**
+     * Module manager
+     *
+     * @var \Magento\Framework\Module\Manager
+     */
+    private $moduleManagerMock;
+
+    /**
+     * Cache config
+     *
+     * @var \Magento\PageCache\Model\Config
+     */
+    private $cacheConfigMock;
+
+    /**
+     * @var \Magento\Weee\Helper\Data
+     */
+    protected $weeeHelperMock;
+
+    /**
+     * @var \Magento\Tax\Model\Observer\Session
+     */
+    protected $session;
+
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+        $this->observerMock = $this->getMockBuilder('Magento\Framework\Event\Observer')
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'getCustomerAddress', 'getData'
+            ])
+            ->getMock();
+
+        $this->customerSessionMock = $this->getMockBuilder('Magento\Customer\Model\Session')
+            ->disableOriginalConstructor()
+            ->setMethods([
+                'setDefaultTaxBillingAddress', 'setDefaultTaxShippingAddress', 'setWebsiteId'
+            ])
+            ->getMock();
+
+        $this->moduleManagerMock = $this->getMockBuilder('Magento\Framework\Module\Manager')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->cacheConfigMock = $this->getMockBuilder('Magento\PageCache\Model\Config')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->weeeHelperMock = $this->getMockBuilder('Magento\Weee\Helper\Data')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->session = $this->objectManager->getObject(
+            'Magento\Weee\Model\Observer\Session',
+            [
+                'customerSession' => $this->customerSessionMock,
+                'weeeHelper' => $this->weeeHelperMock,
+                'moduleManager' => $this->moduleManagerMock,
+                'cacheConfig' => $this->cacheConfigMock
+            ]
+        );
+    }
+
+    public function testCustomerLoggedIn()
+    {
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->any())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $customerMock = $this->getMockBuilder('Magento\Customer\Model\Data\Customer')
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->observerMock->expects($this->once())
+            ->method('getData')
+            ->with('customer')
+            ->willReturn($customerMock);
+
+        $address = $this->objectManager->getObject('Magento\Customer\Model\Data\Address');
+        $address->setIsDefaultShipping(true);
+        $address->setIsDefaultBilling(true);
+        $address->setCountryId(1);
+        $address->setPostCode(11111);
+
+        $addresses = [$address];
+        $customerMock->expects($this->once())
+            ->method('getAddresses')
+            ->willReturn($addresses);
+
+        $this->customerSessionMock->expects($this->once())
+            ->method('setDefaultTaxBillingAddress')
+            ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
+        $this->customerSessionMock->expects($this->once())
+            ->method('setDefaultTaxShippingAddress')
+            ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
+
+        $this->session->customerLoggedIn($this->observerMock);
+    }
+
+    public function testAfterAddressSave()
+    {
+        $this->moduleManagerMock->expects($this->once())
+            ->method('isEnabled')
+            ->with('Magento_PageCache')
+            ->willReturn(true);
+
+        $this->cacheConfigMock->expects($this->once())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $this->weeeHelperMock->expects($this->any())
+            ->method('isEnabled')
+            ->willReturn(true);
+
+        $address = $this->objectManager->getObject('Magento\Customer\Model\Address');
+        $address->setIsDefaultShipping(true);
+        $address->setIsDefaultBilling(true);
+        $address->setIsPrimaryBilling(true);
+        $address->setIsPrimaryShipping(true);
+        $address->setCountryId(1);
+        $address->setData('postcode', 11111);
+
+        $this->customerSessionMock->expects($this->once())
+            ->method('setDefaultTaxBillingAddress')
+            ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
+        $this->customerSessionMock->expects($this->once())
+            ->method('setDefaultTaxShippingAddress')
+            ->with(['country_id' => 1, 'region_id' => null, 'postcode' => 11111]);
+
+        $this->observerMock->expects($this->once())
+            ->method('getCustomerAddress')
+            ->willReturn($address);
+
+        $this->session->afterAddressSave($this->observerMock);
+    }
+}
diff --git a/app/code/Magento/Weee/Test/Unit/Model/Resource/TaxTest.php b/app/code/Magento/Weee/Test/Unit/Model/Resource/TaxTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..27a4dedc845dd2b530a082088417a4412686faa0
--- /dev/null
+++ b/app/code/Magento/Weee/Test/Unit/Model/Resource/TaxTest.php
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Weee\Test\Unit\Model\Resource;
+
+class TaxTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var \Magento\Weee\Model\Resource\Tax
+     */
+    protected $model;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $resourceMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $storeManagerMock;
+
+    /**
+     * @var \PHPUnit_Framework_MockObject_MockObject
+     */
+    protected $adapterMock;
+
+    protected function setUp()
+    {
+        $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+
+        $this->storeManagerMock = $this->getMock('\Magento\Store\Model\StoreManagerInterface');
+
+        $this->selectMock = $this->getMock('\Magento\Framework\DB\Select', [], [], '', false);
+
+        $this->adapterMock = $this->getMock('\Magento\Framework\DB\Adapter\AdapterInterface', [], [], '', false);
+        $this->adapterMock->expects($this->once())
+            ->method('select')
+            ->willReturn($this->selectMock);
+
+        $this->resourceMock = $this->getMock('\Magento\Framework\App\Resource', [], [], '', false);
+        $this->resourceMock->expects($this->at(0))
+            ->method('getConnection')
+            ->with('core_write')
+            ->willReturn($this->adapterMock);
+
+        $this->resourceMock->expects($this->at(1))
+            ->method('getConnection')
+            ->with('core_read')
+            ->willReturn($this->adapterMock);
+
+        $this->resourceMock->expects($this->once())
+            ->method('getTableName')
+            ->willReturn('table_name');
+
+        $contextMock = $this->getMock('\Magento\Framework\Model\Resource\Db\Context', [], [], '', false);
+        $contextMock->expects($this->once())->method('getResources')->willReturn($this->resourceMock);
+
+        $this->model = $this->objectManager->getObject(
+            'Magento\Weee\Model\Resource\Tax',
+            [
+                'context' => $contextMock,
+            ]
+        );
+    }
+
+    public function testInWeeeLocation()
+    {
+        $this->selectMock->expects($this->at(1))
+            ->method('where')
+            ->with('website_id IN(?)', [1, 0])
+            ->willReturn($this->selectMock);
+
+        $this->selectMock->expects($this->at(2))
+            ->method('where')
+            ->with('country = ?', 'US')
+            ->willReturn($this->selectMock);
+
+        $this->selectMock->expects($this->at(3))
+            ->method('where')
+            ->with('state = ?', 0)
+            ->willReturn($this->selectMock);
+
+        $this->selectMock->expects($this->any())
+            ->method('from')
+            ->with('table_name', 'value')
+            ->willReturn($this->selectMock);
+
+        $this->model->isWeeeInLocation('US', 0, 1);
+    }
+}
diff --git a/app/code/Magento/Weee/composer.json b/app/code/Magento/Weee/composer.json
index a6d45896b5d202f3b0cc375979217c7576e0a331..6fe75a545c2e3d77c698cfc70bbd201305e99d51 100644
--- a/app/code/Magento/Weee/composer.json
+++ b/app/code/Magento/Weee/composer.json
@@ -11,6 +11,7 @@
         "magento/module-directory": "0.74.0-beta15",
         "magento/module-eav": "0.74.0-beta15",
         "magento/module-customer": "0.74.0-beta15",
+        "magento/module-page-cache": "0.74.0-beta15",
         "magento/module-quote": "0.74.0-beta15",
         "magento/module-checkout": "0.74.0-beta15",
         "magento/framework": "0.74.0-beta15",
diff --git a/app/code/Magento/Weee/etc/frontend/di.xml b/app/code/Magento/Weee/etc/frontend/di.xml
index 274af56fa7134cb28eb908da6c486daa4c45b333..c9b706532877b79db60711a610859a92117c4fe7 100644
--- a/app/code/Magento/Weee/etc/frontend/di.xml
+++ b/app/code/Magento/Weee/etc/frontend/di.xml
@@ -13,4 +13,8 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\App\Action\Action">
+        <plugin name="weee-app-action-dispatchController-context-plugin"
+                type="Magento\Weee\Model\App\Action\ContextPlugin"/>
+    </type>
 </config>
diff --git a/app/code/Magento/Weee/etc/frontend/events.xml b/app/code/Magento/Weee/etc/frontend/events.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2bc96ce0399341f63d40f814ee72e061f54d205c
--- /dev/null
+++ b/app/code/Magento/Weee/etc/frontend/events.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0"?>
+<!--
+/**
+ * Copyright © 2015 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+-->
+<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="../../../../../../lib/internal/Magento/Framework/Event/etc/events.xsd">
+    <event name="customer_data_object_login">
+        <observer name="customer_weee_logged_in" instance="Magento\Weee\Model\Observer\Session" method="customerLoggedIn" />
+    </event>
+    <event name="customer_address_save_after">
+        <observer name="customer_weee_after_address_save" instance="Magento\Weee\Model\Observer\Session" method="afterAddressSave" />
+    </event>
+</config>
diff --git a/dev/tests/integration/testsuite/Magento/Framework/Url/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Framework/Url/Helper/DataTest.php
index ce94b1e855a8acbcf54132c42c930a80783fa932..d40ef433bcc0a6c958bded00ad3a9a6bc78e7173 100644
--- a/dev/tests/integration/testsuite/Magento/Framework/Url/Helper/DataTest.php
+++ b/dev/tests/integration/testsuite/Magento/Framework/Url/Helper/DataTest.php
@@ -14,8 +14,6 @@ class DataTest extends \PHPUnit_Framework_TestCase
 
     protected function setUp()
     {
-        $_SERVER['HTTP_HOST'] = 'example.com';
-        $_SERVER['REQUEST_URI'] = '/fancy_uri';
         $this->_helper = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
             'Magento\Framework\Url\Helper\Data'
         );
@@ -23,12 +21,12 @@ class DataTest extends \PHPUnit_Framework_TestCase
 
     public function testGetCurrentBase64Url()
     {
-        $this->assertEquals('aHR0cDovL2xvY2FsaG9zdDo4MQ,,', $this->_helper->getCurrentBase64Url());
+        $this->assertEquals('aHR0cDovL2xvY2FsaG9zdDo4MS8,', $this->_helper->getCurrentBase64Url());
     }
 
     public function testGetEncodedUrl()
     {
-        $this->assertEquals('aHR0cDovL2xvY2FsaG9zdDo4MQ,,', $this->_helper->getEncodedUrl());
+        $this->assertEquals('aHR0cDovL2xvY2FsaG9zdDo4MS8,', $this->_helper->getEncodedUrl());
         $this->assertEquals('aHR0cDovL2V4YW1wbGUuY29tLw,,', $this->_helper->getEncodedUrl('http://example.com/'));
     }
 }
diff --git a/dev/tools/performance-toolkit/fixtures/orders.php b/dev/tools/performance-toolkit/fixtures/orders.php
deleted file mode 100644
index e2aa2c832e0fb6390dda692fce7b5b831329b047..0000000000000000000000000000000000000000
--- a/dev/tools/performance-toolkit/fixtures/orders.php
+++ /dev/null
@@ -1,314 +0,0 @@
-<?php
-/**
- * Copyright © 2015 Magento. All rights reserved.
- * See COPYING.txt for license details.
- */
-
-/**
- * Class OrdersFixture
- */
-class OrdersFixture extends \Magento\ToolkitFramework\Fixture
-{
-    /**
-     * @var int
-     */
-    protected $priority = 135;
-
-    /**
-     * {@inheritdoc}
-     */
-    public function execute()
-    {
-        $ordersCount = \Magento\ToolkitFramework\Config::getInstance()->getValue('orders', 0);
-        if ($ordersCount < 1) {
-            return;
-        }
-        $this->application->resetObjectManager();
-
-        $writeAdapter = $this->getConnection('write');
-
-        $quoteTableName = $this->getTableName(
-            'quote',
-            'Magento\Quote\Model\Resource\Quote'
-        );
-        $quoteAddressTableName = $this->getTableName(
-            'quote_address',
-            'Magento\Quote\Model\Resource\Quote\Address'
-        );
-        $quoteItemTableName = $this->getTableName(
-            'quote_item',
-            'Magento\Quote\Model\Resource\Quote\Item'
-        );
-        $quoteItemOptionTableName = $this->getTableName(
-            'quote_item_option',
-            'Magento\Quote\Model\Resource\Quote\Item\Option'
-        );
-        $quotePaymentTableName = $this->getTableName(
-            'quote_payment',
-            'Magento\Quote\Model\Resource\Quote\Payment'
-        );
-        $quoteAddressRateTableName = $this->getTableName(
-            'quote_shipping_rate',
-            'Magento\Quote\Model\Resource\Quote\Address\Rate'
-        );
-        $reportEventTableName = $this->getTableName(
-            'report_event',
-            'Magento\Reports\Model\Resource\Event'
-        );
-        $salesOrderTableName = $this->getTableName(
-            'sales_order',
-            'Magento\Sales\Model\Resource\Order'
-        );
-        $salesOrderAddressTableName = $this->getTableName(
-            'sales_order_address',
-            'Magento\Sales\Model\Resource\Order'
-        );
-        $salesOrderGridTableName = $this->getTableName(
-            'sales_order_grid',
-            'Magento\Sales\Model\Resource\Order\Grid'
-        );
-        $salesOrderItemTableName = $this->getTableName(
-            'sales_order_item',
-            'Magento\Sales\Model\Resource\Order\Item'
-        );
-        $salesOrderPaymentTableName = $this->getTableName(
-            'sales_order_payment',
-            'Magento\Sales\Model\Resource\Order\Payment'
-        );
-        $salesOrderStatusHistoryTableName = $this->getTableName(
-            'sales_order_status_history',
-            'Magento\Sales\Model\Resource\Order\Status\History'
-        );
-        $eavEntityStoreTableName = $this->getTableName(
-            'eav_entity_store',
-            '\Magento\Eav\Model\Resource\Entity\Store'
-        );
-        /** @var \Magento\Store\Model\StoreManager $storeManager */
-        $storeManager = $this->application->getObjectManager()->create('Magento\Store\Model\StoreManager');
-        /** @var $category \Magento\Catalog\Model\Category */
-        $category = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category');
-        /** @var $product \Magento\Catalog\Model\Product */
-        $product = $this->application->getObjectManager()->get('Magento\Catalog\Model\Product');
-
-        $result = [];
-        $stores = $storeManager->getStores();
-        foreach ($stores as $store) {
-            $storeId = $store->getStoreId();
-            $websiteId = $store->getWebsite()->getId();
-            $websiteName = $store->getWebsite()->getName();
-            $groupName = $store->getGroup()->getName();
-            $storeName = $store->getName();
-            $storeRootCategory = $store->getRootCategoryId();
-            $category->load($storeRootCategory);
-            $categoryResource = $category->getResource();
-            //Get all categories
-            $resultsCategories = $categoryResource->getAllChildren($category);
-            foreach ($resultsCategories as $resultsCategory) {
-                $category->load($resultsCategory);
-                $structure = explode('/', $category->getPath());
-                $pathSize = count($structure);
-                if ($pathSize > 1) {
-                    $path = [];
-                    for ($i = 1; $i < $pathSize; $i++) {
-                        $path[] = $category->load($structure[$i])->getName();
-                    }
-                    array_shift($path);
-                    $resultsCategoryName = implode('/', $path);
-                } else {
-                    $resultsCategoryName = $category->getName();
-                }
-                //Not use root categories
-                if (trim($resultsCategoryName) != '') {
-                    /** @var $productCategory \Magento\Catalog\Model\Category */
-                    $productCategory = $this->application->getObjectManager()->get('Magento\Catalog\Model\Category');
-
-                    /** @var $simpleProductCollection \Magento\Catalog\Model\Resource\Product\Collection */
-                    $simpleProductCollection = $this->application->getObjectManager()->create(
-                        'Magento\Catalog\Model\Resource\Product\Collection'
-                    );
-
-                    $simpleProductCollection->addStoreFilter($storeId);
-                    $simpleProductCollection->addWebsiteFilter($websiteId);
-                    $simpleProductCollection->addCategoryFilter($productCategory->load($resultsCategory));
-                    $simpleProductCollection->getSelect()->where(" type_id = 'simple' ");
-                    $simpleIds = $simpleProductCollection->getAllIds(2);
-                    $simpleProductsResult = [];
-                    foreach ($simpleIds as $key => $simpleId) {
-                        $simpleProduct = $product->load($simpleId);
-                        $simpleProductsResult[$key]['simpleProductId'] = $simpleId;
-                        $simpleProductsResult[$key]['simpleProductSku'] = $simpleProduct->getSku();
-                        $simpleProductsResult[$key]['simpleProductName'] = $simpleProduct->getName();
-                    }
-
-                    $result[] = [
-                        $storeId,
-                        $websiteName. '\n'. $groupName . '\n' . $storeName,
-                        $simpleProductsResult
-                    ];
-                }
-            }
-        }
-
-        $productStoreId = function ($index) use ($result) {
-            return $result[$index % count($result)][0];
-        };
-        $productStoreName = function ($index) use ($result) {
-            return $result[$index % count($result)][1];
-        };
-
-        $simpleProductId[0] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][0]['simpleProductId'];
-        };
-        $simpleProductId[1] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][1]['simpleProductId'];
-        };
-        $simpleProductSku[0] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][0]['simpleProductSku'];
-        };
-        $simpleProductSku[1] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][1]['simpleProductSku'];
-        };
-        $simpleProductName[0] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][0]['simpleProductName'];
-        };
-        $simpleProductName[1] = function ($index) use ($result) {
-            return $result[$index % count($result)][2][1]['simpleProductName'];
-        };
-
-        $entityId = 1;
-        while ($entityId <= $ordersCount) {
-            $queries = "";
-
-            $orderNumber = 100000000 * $productStoreId($entityId) + $entityId;
-            $email = 'order_' . $entityId . '@example.com';
-            $firstName = 'First Name';
-            $lastName = 'Last Name';
-            $company = 'Company';
-            $address = 'Address';
-            $city = 'City';
-            $state = 'Alabama';
-            $country = 'US';
-            $zip = '11111';
-            $phone = '911';
-            $time = date("Y-m-d h:i:s");
-
-            $simpleProductIdLen[0] = strlen($simpleProductId[0]($entityId));
-            $simpleProductIdLen[1] = strlen($simpleProductId[1]($entityId));
-
-            $queries .= "INSERT INTO `{$eavEntityStoreTableName}` (`entity_store_id`, `entity_type_id`, `store_id`, `increment_prefix`, `increment_last_id`) VALUES ({$productStoreId($entityId)}, 5, {$productStoreId($entityId)}, '{$productStoreId($entityId)}', '{$orderNumber}') ON DUPLICATE KEY UPDATE `increment_last_id`='{$orderNumber}';";
-
-            $quoteId = $entityId;
-            $queries .= "INSERT INTO `{$quoteTableName}` (`entity_id`, `store_id`, `created_at`, `updated_at`, `converted_at`, `is_active`, `is_virtual`, `is_multi_shipping`, `items_count`, `items_qty`, `orig_order_id`, `store_to_base_rate`, `store_to_quote_rate`, `base_currency_code`, `store_currency_code`, `quote_currency_code`, `grand_total`, `base_grand_total`, `checkout_method`, `customer_id`, `customer_tax_class_id`, `customer_group_id`, `customer_email`, `customer_prefix`, `customer_firstname`, `customer_middlename`, `customer_lastname`, `customer_suffix`, `customer_dob`, `customer_note`, `customer_note_notify`, `customer_is_guest`, `remote_ip`, `applied_rule_ids`, `reserved_order_id`, `password_hash`, `coupon_code`, `global_currency_code`, `base_to_global_rate`, `base_to_quote_rate`, `customer_taxvat`, `customer_gender`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `is_changed`, `trigger_recollect`, `ext_shipping_info`, `is_persistent`, `gift_message_id`) VALUES ({$quoteId}, {$productStoreId($entityId)}, '{$time}', '1970-01-01 03:00:00', NULL, 0, 0, 0, 2, 2.0000, 0, 0.0000, 0.0000, 'USD', 'USD', 'USD', 25.3000, 25.3000, 'guest', NULL, 3, 0, '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1, 1, '127.0.0.1', '1', NULL, NULL, NULL, 'USD', 1.0000, 1.0000, NULL, NULL, 17.0000, 17.0000, 15.3000, 15.3000, 1, 0, NULL, 0, NULL);";
-
-            $quoteAddressId[0] = $entityId * 2 - 1;
-            $quoteAddressId[1] = $entityId * 2;
-            $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[0]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 1, NULL, 'billing', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 0, 0, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, 0.0000, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);";
-            $queries .= "INSERT INTO `{$quoteAddressTableName}` (`address_id`, `quote_id`, `created_at`, `updated_at`, `customer_id`, `save_in_address_book`, `customer_address_id`, `address_type`, `email`, `prefix`, `firstname`, `middlename`, `lastname`, `suffix`, `company`, `street`, `city`, `region`, `region_id`, `postcode`, `country_id`, `telephone`, `fax`, `same_as_billing`, `collect_shipping_rates`, `shipping_method`, `shipping_description`, `weight`, `subtotal`, `base_subtotal`, `subtotal_with_discount`, `base_subtotal_with_discount`, `tax_amount`, `base_tax_amount`, `shipping_amount`, `base_shipping_amount`, `shipping_tax_amount`, `base_shipping_tax_amount`, `discount_amount`, `base_discount_amount`, `grand_total`, `base_grand_total`, `customer_notes`, `applied_taxes`, `discount_description`, `shipping_discount_amount`, `base_shipping_discount_amount`, `subtotal_incl_tax`, `base_subtotal_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `shipping_incl_tax`, `base_shipping_incl_tax`, `free_shipping`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`, `gift_message_id`) VALUES ({$quoteAddressId[1]}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', NULL, 0, NULL, 'shipping', '{$email}', NULL, '{$firstName}', NULL, '{$lastName}', NULL, '{$company}', '{$address}', '{$city}', '{$state}', 1, '{$zip}', '{$country}', '{$phone}', NULL, 1, 0, 'flatrate_flatrate', 'Flat Rate - Fixed', 2.0000, 17.0000, 17.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 10.0000, 0.0000, 0.0000, -1.7000, -1.7000, 25.3000, 25.3000, NULL, 'a:0:{}', NULL, 0.0000, 0.0000, 17.0000, NULL, 0.0000, 0.0000, 0.0000, NULL, 10.0000, 10.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL);";
-
-            $quoteItemId[0] = $entityId * 4 - 3;
-            $quoteItemId[1] = $entityId * 4 - 2;
-            $quoteItemId[2] = $entityId * 4 - 1;
-            $quoteItemId[3] = $entityId * 4;
-            $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[0]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[0]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);";
-            $queries .= "INSERT INTO `{$quoteItemTableName}` (`item_id`, `quote_id`, `created_at`, `updated_at`, `product_id`, `store_id`, `parent_item_id`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `weight`, `qty`, `price`, `base_price`, `custom_price`, `discount_percent`, `discount_amount`, `base_discount_amount`, `tax_percent`, `tax_amount`, `base_tax_amount`, `row_total`, `base_row_total`, `row_total_with_discount`, `row_weight`, `product_type`, `base_tax_before_discount`, `tax_before_discount`, `original_custom_price`, `redirect_url`, `base_cost`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `free_shipping`, `gift_message_id`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$quoteItemId[1]}, {$quoteId}, '1970-01-01 03:00:00', '1970-01-01 03:00:00', {$simpleProductId[1]($entityId)}, {$productStoreId($entityId)}, NULL, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, 1.0000, 1.0000, 8.5000, 8.5000, NULL, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 1.0000, 'simple', NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);";
-
-            $quoteItemOptionId[0] = $entityId * 8 - 7;
-            $quoteItemOptionId[1] = $entityId * 8 - 6;
-            $quoteItemOptionId[2] = $entityId * 8 - 5;
-            $quoteItemOptionId[3] = $entityId * 8 - 4;
-            $quoteItemOptionId[4] = $entityId * 8 - 3;
-            $quoteItemOptionId[5] = $entityId * 8 - 2;
-            $quoteItemOptionId[6] = $entityId * 8 - 1;
-            $quoteItemOptionId[7] = $entityId * 8;
-            $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[0]}, {$quoteItemId[0]}, {$simpleProductId[0]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}');";
-            $queries .= "INSERT INTO `{$quoteItemOptionTableName}` (`option_id`, `item_id`, `product_id`, `code`, `value`) VALUES ({$quoteItemOptionId[1]}, {$quoteItemId[1]}, {$simpleProductId[1]($entityId)}, 'info_buyRequest', 'a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}');";
-
-            $quotePaymentId = $quoteId;
-            $queries .= "INSERT INTO `{$quotePaymentTableName}` (`payment_id`, `quote_id`, `created_at`, `updated_at`, `method`, `cc_type`, `cc_number_enc`, `cc_last_4`, `cc_cid_enc`, `cc_owner`, `cc_exp_month`, `cc_exp_year`, `cc_ss_owner`, `cc_ss_start_month`, `cc_ss_start_year`, `po_number`, `additional_data`, `cc_ss_issue`, `additional_information`) VALUES ({$quotePaymentId}, {$quoteId}, '{$time}', '1970-01-01 03:00:00', 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, NULL, NULL, NULL, NULL);";
-
-            $quoteShippingRateId = $quoteAddressId[1];
-            $queries .= "INSERT INTO `{$quoteAddressRateTableName}` (`rate_id`, `address_id`, `created_at`, `updated_at`, `carrier`, `carrier_title`, `code`, `method`, `method_description`, `price`, `error_message`, `method_title`) VALUES ({$quoteShippingRateId}, {$quoteAddressId[1]}, '{$time}', '1970-01-01 03:00:00', 'flatrate', 'Flat Rate', 'flatrate_flatrate', 'flatrate', NULL, 10.0000, NULL, 'Fixed');";
-
-            $reportEventId[0] = $quoteItemId[0];
-            $reportEventId[1] = $quoteItemId[1];
-            $reportEventId[2] = $quoteItemId[2];
-            $reportEventId[3] = $quoteItemId[3];
-            $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[0]}, '{$time}', 4, {$simpleProductId[0]($entityId)}, 2, 1, {$productStoreId($entityId)});";
-            $queries .= "INSERT INTO `{$reportEventTableName}` (`event_id`, `logged_at`, `event_type_id`, `object_id`, `subject_id`, `subtype`, `store_id`) VALUES ({$reportEventId[1]}, '{$time}', 4, {$simpleProductId[1]($entityId)}, 2, 1, {$productStoreId($entityId)});";
-
-            $salesOrderId = $quoteId;
-            $queries .= "INSERT INTO `{$salesOrderTableName}` (`entity_id`, `state`, `status`, `coupon_code`, `protect_code`, `shipping_description`, `is_virtual`, `store_id`, `customer_id`, `base_discount_amount`, `base_discount_canceled`, `base_discount_invoiced`, `base_discount_refunded`, `base_grand_total`, `base_shipping_amount`, `base_shipping_canceled`, `base_shipping_invoiced`, `base_shipping_refunded`, `base_shipping_tax_amount`, `base_shipping_tax_refunded`, `base_subtotal`, `base_subtotal_canceled`, `base_subtotal_invoiced`, `base_subtotal_refunded`, `base_tax_amount`, `base_tax_canceled`, `base_tax_invoiced`, `base_tax_refunded`, `base_to_global_rate`, `base_to_order_rate`, `base_total_canceled`, `base_total_invoiced`, `base_total_invoiced_cost`, `base_total_offline_refunded`, `base_total_online_refunded`, `base_total_paid`, `base_total_qty_ordered`, `base_total_refunded`, `discount_amount`, `discount_canceled`, `discount_invoiced`, `discount_refunded`, `grand_total`, `shipping_amount`, `shipping_canceled`, `shipping_invoiced`, `shipping_refunded`, `shipping_tax_amount`, `shipping_tax_refunded`, `store_to_base_rate`, `store_to_order_rate`, `subtotal`, `subtotal_canceled`, `subtotal_invoiced`, `subtotal_refunded`, `tax_amount`, `tax_canceled`, `tax_invoiced`, `tax_refunded`, `total_canceled`, `total_invoiced`, `total_offline_refunded`, `total_online_refunded`, `total_paid`, `total_qty_ordered`, `total_refunded`, `can_ship_partially`, `can_ship_partially_item`, `customer_is_guest`, `customer_note_notify`, `billing_address_id`, `customer_group_id`, `edit_increment`, `email_sent`, `send_email`, `forced_shipment_with_invoice`, `payment_auth_expiration`, `quote_address_id`, `quote_id`, `shipping_address_id`, `adjustment_negative`, `adjustment_positive`, `base_adjustment_negative`, `base_adjustment_positive`, `base_shipping_discount_amount`, `base_subtotal_incl_tax`, `base_total_due`, `payment_authorization_amount`, `shipping_discount_amount`, `subtotal_incl_tax`, `total_due`, `weight`, `customer_dob`, `increment_id`, `applied_rule_ids`, `base_currency_code`, `customer_email`, `customer_firstname`, `customer_lastname`, `customer_middlename`, `customer_prefix`, `customer_suffix`, `customer_taxvat`, `discount_description`, `ext_customer_id`, `ext_order_id`, `global_currency_code`, `hold_before_state`, `hold_before_status`, `order_currency_code`, `original_increment_id`, `relation_child_id`, `relation_child_real_id`, `relation_parent_id`, `relation_parent_real_id`, `remote_ip`, `shipping_method`, `store_currency_code`, `store_name`, `x_forwarded_for`, `customer_note`, `created_at`, `updated_at`, `total_item_count`, `customer_gender`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `shipping_discount_tax_compensation_amount`, `base_shipping_discount_tax_compensation_amnt`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `shipping_incl_tax`, `base_shipping_incl_tax`, `coupon_rule_name`, `gift_message_id`) VALUES ({$salesOrderId}, 'new', 'pending', NULL, '272ecb', 'Flat Rate - Fixed', 0, {$productStoreId($entityId)}, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, 1.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1.7000, NULL, NULL, NULL, 25.3000, 10.0000, NULL, NULL, NULL, 0.0000, NULL, 0.0000, 0.0000, 17.0000, NULL, NULL, NULL, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 2.0000, NULL, NULL, NULL, 1, 1, 2, 0, NULL, 1, 1, NULL, NULL, NULL, 1, 1, NULL, NULL, NULL, NULL, NULL, 17.0000, 25.3000, NULL, NULL, 17.0000, 25.3000, 2.0000, NULL, {$orderNumber}, '1', 'USD', '{$email}', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'USD', NULL, NULL, 'USD', NULL, NULL, NULL, NULL, NULL, '127.0.0.1', 'flatrate_flatrate', 'USD', '{$productStoreName($entityId)}', NULL, NULL, '{$time}', '{$time}', 2, NULL, 0.0000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL);";
-
-            $salesOrderAddressId[0] = $quoteAddressId[0];
-            $salesOrderAddressId[1] = $quoteAddressId[1];
-            $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[0]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'shipping', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);";
-            $queries .= "INSERT INTO `{$salesOrderAddressTableName}` (`entity_id`, `parent_id`, `customer_address_id`, `quote_address_id`, `region_id`, `customer_id`, `fax`, `region`, `postcode`, `lastname`, `street`, `city`, `email`, `telephone`, `country_id`, `firstname`, `address_type`, `prefix`, `middlename`, `suffix`, `company`, `vat_id`, `vat_is_valid`, `vat_request_id`, `vat_request_date`, `vat_request_success`) VALUES ({$salesOrderAddressId[1]}, {$salesOrderId}, NULL, NULL, 1, NULL, NULL, '{$state}', '{$zip}', '{$lastName}', '{$address}', '{$city}', '{$email}', '{$phone}', '{$country}', '{$firstName}', 'billing', NULL, NULL, NULL, '{$company}', NULL, NULL, NULL, NULL, NULL);";
-
-            $salesOrderGridId = $salesOrderId;
-            $queries .= "INSERT INTO `{$salesOrderGridTableName}` (`entity_id`, `status`, `store_id`, `store_name`, `customer_id`, `base_grand_total`, `base_total_paid`, `grand_total`, `total_paid`, `increment_id`, `base_currency_code`, `order_currency_code`, `shipping_name`, `billing_name`, `created_at`, `updated_at`) VALUES ({$salesOrderGridId}, 'pending', {$productStoreId($entityId)}, '{$productStoreName($entityId)}', NULL, 25.3000, NULL, 25.3000, NULL, {$orderNumber}, 'USD', 'USD', '', '', '{$time}', NULL);";
-
-            $salesOrderItemId[0] = $quoteItemId[0];
-            $salesOrderItemId[1] = $quoteItemId[1];
-            $salesOrderItemId[2] = $quoteItemId[2];
-            $salesOrderItemId[3] = $quoteItemId[3];
-            $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[0]}, {$salesOrderId}, NULL, {$quoteItemId[0]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[0]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[0]}:\"{$simpleProductId[0]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[0]($entityId)}', '{$simpleProductName[0]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);";
-            $queries .= "INSERT INTO `{$salesOrderItemTableName}` (`item_id`, `order_id`, `parent_item_id`, `quote_item_id`, `store_id`, `created_at`, `updated_at`, `product_id`, `product_type`, `product_options`, `weight`, `is_virtual`, `sku`, `name`, `description`, `applied_rule_ids`, `additional_data`, `is_qty_decimal`, `no_discount`, `qty_backordered`, `qty_canceled`, `qty_invoiced`, `qty_ordered`, `qty_refunded`, `qty_shipped`, `base_cost`, `price`, `base_price`, `original_price`, `base_original_price`, `tax_percent`, `tax_amount`, `base_tax_amount`, `tax_invoiced`, `base_tax_invoiced`, `discount_percent`, `discount_amount`, `base_discount_amount`, `discount_invoiced`, `base_discount_invoiced`, `amount_refunded`, `base_amount_refunded`, `row_total`, `base_row_total`, `row_invoiced`, `base_row_invoiced`, `row_weight`, `base_tax_before_discount`, `tax_before_discount`, `ext_order_item_id`, `locked_do_invoice`, `locked_do_ship`, `price_incl_tax`, `base_price_incl_tax`, `row_total_incl_tax`, `base_row_total_incl_tax`, `discount_tax_compensation_amount`, `base_discount_tax_compensation_amount`, `discount_tax_compensation_invoiced`, `base_discount_tax_compensation_invoiced`, `discount_tax_compensation_refunded`, `base_discount_tax_compensation_refunded`, `tax_canceled`, `discount_tax_compensation_canceled`, `tax_refunded`, `base_tax_refunded`, `discount_refunded`, `base_discount_refunded`, `free_shipping`, `gift_message_id`, `gift_message_available`, `weee_tax_applied`, `weee_tax_applied_amount`, `weee_tax_applied_row_amount`, `weee_tax_disposition`, `weee_tax_row_disposition`, `base_weee_tax_applied_amount`, `base_weee_tax_applied_row_amnt`, `base_weee_tax_disposition`, `base_weee_tax_row_disposition`) VALUES ({$salesOrderItemId[1]}, {$salesOrderId}, NULL, {$quoteItemId[1]}, {$productStoreId($entityId)}, '{$time}', '0000-00-00 00:00:00', {$simpleProductId[1]($entityId)}, 'simple', 'a:1:{s:15:\"info_buyRequest\";a:3:{s:4:\"uenc\";s:44:\"aHR0cDovL21hZ2UyLmNvbS9jYXRlZ29yeS0xLmh0bWw,\";s:7:\"product\";s:{$simpleProductIdLen[1]}:\"{$simpleProductId[1]($entityId)}\";s:3:\"qty\";i:1;}}', 1.0000, 0, '{$simpleProductSku[1]($entityId)}', '{$simpleProductName[1]($entityId)}', NULL, '1', NULL, 0, 0, NULL, 0.0000, 0.0000, 1.0000, 0.0000, 0.0000, NULL, 8.5000, 8.5000, 10.0000, 10.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 10.0000, 0.8500, 0.8500, 0.0000, 0.0000, 0.0000, 0.0000, 8.5000, 8.5000, 0.0000, 0.0000, 1.0000, NULL, NULL, NULL, NULL, NULL, 8.5000, 8.5000, 8.5000, 8.5000, 0.0000, 0.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);";
-
-            $salesOrderPaymentId = $salesOrderId;
-            $queries .= "INSERT INTO `{$salesOrderPaymentTableName}` (`entity_id`, `parent_id`, `base_shipping_captured`, `shipping_captured`, `amount_refunded`, `base_amount_paid`, `amount_canceled`, `base_amount_authorized`, `base_amount_paid_online`, `base_amount_refunded_online`, `base_shipping_amount`, `shipping_amount`, `amount_paid`, `amount_authorized`, `base_amount_ordered`, `base_shipping_refunded`, `shipping_refunded`, `base_amount_refunded`, `amount_ordered`, `base_amount_canceled`, `quote_payment_id`, `additional_data`, `cc_exp_month`, `cc_ss_start_year`, `echeck_bank_name`, `method`, `cc_debug_request_body`, `cc_secure_verify`, `protection_eligibility`, `cc_approval`, `cc_last_4`, `cc_status_description`, `echeck_type`, `cc_debug_response_serialized`, `cc_ss_start_month`, `echeck_account_type`, `last_trans_id`, `cc_cid_status`, `cc_owner`, `cc_type`, `po_number`, `cc_exp_year`, `cc_status`, `echeck_routing_number`, `account_status`, `anet_trans_method`, `cc_debug_response_body`, `cc_ss_issue`, `echeck_account_name`, `cc_avs_status`, `cc_number_enc`, `cc_trans_id`, `address_status`, `additional_information`) VALUES ({$salesOrderPaymentId}, {$salesOrderId}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 10.0000, 10.0000, NULL, NULL, 25.3000, NULL, NULL, NULL, 25.3000, NULL, NULL, NULL, NULL, '0', NULL, 'checkmo', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'a:1:{s:53:\"a:1:{s:12:\"method_title\";s:19:\"Check / Money order\";}\";N;}');";
-
-            $salesOrderStatusHistoryId = $salesOrderId;
-            $queries .= "INSERT INTO `{$salesOrderStatusHistoryTableName}` (`entity_id`, `parent_id`, `is_customer_notified`, `is_visible_on_front`, `comment`, `status`, `created_at`, `entity_name`) VALUES ({$salesOrderStatusHistoryId}, {$salesOrderId}, 1, 0, NULL, 'pending', '{$time}', 'order');";
-
-            $writeAdapter->multiQuery($queries);
-
-            $entityId++;
-        }
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getActionTitle()
-    {
-        return 'Generating orders';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function introduceParamLabels()
-    {
-        return [
-            'orders'     => 'Orders'
-        ];
-    }
-
-    /**
-     * Get real table name for db table, validated by db adapter
-     *
-     * @param string $tableName
-     * @param string $resourceName
-     * @return string
-     */
-    public function getTableName($tableName, $resourceName)
-    {
-        $resource = $this->application->getObjectManager()->get($resourceName);
-        return $this->getConnection('write')->getTableName($resource->getTable($tableName));
-    }
-
-    /**
-     * Retrieve connection to resource specified by $resourceName
-     *
-     * @param string $resourceName
-     * @return \Magento\Framework\DB\Adapter\AdapterInterface|false
-     */
-    public function getConnection($resourceName)
-    {
-        return $this->application->getObjectManager()->get(
-            'Magento\Framework\App\Resource'
-        )->getConnection($resourceName);
-    }
-}
-
-return new OrdersFixture($this);
diff --git a/lib/internal/Magento/Framework/Api/DataObjectHelper.php b/lib/internal/Magento/Framework/Api/DataObjectHelper.php
index 2fb75d5f841613fb0523cc88e7062112d1fc6729..70a7b79c71b8b9b011aae799e4e3b76f6c7027f2 100644
--- a/lib/internal/Magento/Framework/Api/DataObjectHelper.php
+++ b/lib/internal/Magento/Framework/Api/DataObjectHelper.php
@@ -176,7 +176,7 @@ class DataObjectHelper
             $object = $this->objectFactory->create($returnType, []);
             $this->populateWithArray($object, $value, $returnType);
         } else if (is_subclass_of($returnType, '\Magento\Framework\Api\ExtensionAttributesInterface')) {
-            $object = $this->extensionFactory->create(get_class($dataObject), $value);
+            $object = $this->extensionFactory->create(get_class($dataObject), ['data' => $value]);
         } else {
             $object = $this->objectFactory->create($returnType, $value);
         }
diff --git a/lib/internal/Magento/Framework/Test/Unit/UrlTest.php b/lib/internal/Magento/Framework/Test/Unit/UrlTest.php
index baa556bb19f789d773d6c48fdf9ac454ac19f951..c5bcc5175ab5dbe63db53e0ea4fcad888e96c8fa 100644
--- a/lib/internal/Magento/Framework/Test/Unit/UrlTest.php
+++ b/lib/internal/Magento/Framework/Test/Unit/UrlTest.php
@@ -121,7 +121,7 @@ class UrlTest extends \PHPUnit_Framework_TestCase
     public function testGetCurrentUrl($httpHost, $url)
     {
         $requestMock = $this->getRequestMock();
-        $requestMock->expects($this->once())->method('getServer')->with('REQUEST_URI')->willReturn('/fancy_uri');
+        $requestMock->expects($this->once())->method('getRequestUri')->willReturn('/fancy_uri');
         $requestMock->expects($this->once())->method('getScheme')->will($this->returnValue('http'));
         $requestMock->expects($this->once())->method('getHttpHost')->will($this->returnValue($httpHost));
         $model = $this->getUrlModel(['request' => $requestMock]);
diff --git a/lib/internal/Magento/Framework/Url.php b/lib/internal/Magento/Framework/Url.php
index 7d4c4c33399ac0ae5ee53379727681a291cc7bfd..a300ebe01f4858c06dd598d769d1352ed79394d8 100644
--- a/lib/internal/Magento/Framework/Url.php
+++ b/lib/internal/Magento/Framework/Url.php
@@ -1045,7 +1045,7 @@ class Url extends \Magento\Framework\Object implements \Magento\Framework\UrlInt
                 $port = ':' . $httpHostWithPort[1];
             }
         }
-        return $this->_request->getScheme() . '://' . $httpHost . $port . $this->_request->getServer('REQUEST_URI');
+        return $this->_request->getScheme() . '://' . $httpHost . $port . $this->_request->getRequestUri();
     }
 
     /**