diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
index 23fc2026ab111..82a0086ad67ec 100644
--- a/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
+++ b/app/code/Magento/Bundle/Block/Adminhtml/Sales/Order/Items/Renderer.php
@@ -100,6 +100,8 @@ public function getChildren($item)
}
/**
+ * Check if item can be shipped separately
+ *
* @param mixed $item
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -136,6 +138,8 @@ public function isShipmentSeparately($item = null)
}
/**
+ * Check if child items calculated
+ *
* @param mixed $item
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -174,6 +178,8 @@ public function isChildCalculated($item = null)
}
/**
+ * Retrieve selection attributes values
+ *
* @param mixed $item
* @return mixed|null
*/
@@ -191,6 +197,8 @@ public function getSelectionAttributes($item)
}
/**
+ * Retrieve order item options array
+ *
* @return array
*/
public function getOrderOptions()
@@ -212,6 +220,8 @@ public function getOrderOptions()
}
/**
+ * Retrieve order item
+ *
* @return mixed
*/
public function getOrderItem()
@@ -223,6 +233,8 @@ public function getOrderItem()
}
/**
+ * Get html info for item
+ *
* @param mixed $item
* @return string
*/
@@ -245,6 +257,8 @@ public function getValueHtml($item)
}
/**
+ * Check if we can show price info for this item
+ *
* @param object $item
* @return bool
*/
diff --git a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml
index ff26d67bd8378..12da960a9c6cf 100644
--- a/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml
+++ b/app/code/Magento/Bundle/view/adminhtml/templates/sales/invoice/create/items/renderer.phtml
@@ -28,8 +28,17 @@
+ getOrderItem()->getProductType() == \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) ?
+ !$_item->getOrderItem()->isShipSeparately() : !$_item->getOrderItem()->getParentItem()->isShipSeparately()
+ ?>
setPriceDataObject($_item) ?>
getOrderItem()->getParentItem()): ?>
+
getSelectionAttributes($_item) ?>
@@ -60,14 +69,14 @@
- canShowPriceInfo($_item)): ?>
+ canShowPriceInfo($_item) || $shipTogether): ?>
= $block->getColumnHtml($_item, 'price') ?>
|
- canShowPriceInfo($_item)): ?>
+ canShowPriceInfo($_item) || $shipTogether): ?>
= /* @escapeNotVerified */ __('Ordered') ?> |
@@ -116,7 +125,7 @@
- canShowPriceInfo($_item)): ?>
+ canShowPriceInfo($_item) || $shipTogether): ?>
canEditQty()) : ?>
getNodeById($rootId);
- if ($root && $rootId != \Magento\Catalog\Model\Category::TREE_ROOT_ID) {
+ if ($root) {
$root->setIsVisible(true);
- } elseif ($root && $root->getId() == \Magento\Catalog\Model\Category::TREE_ROOT_ID) {
- $root->setName(__('Root'));
+ if ($root->getId() == \Magento\Catalog\Model\Category::TREE_ROOT_ID) {
+ $root->setName(__('Root'));
+ }
}
$this->_coreRegistry->register('root', $root);
@@ -162,6 +175,8 @@ public function getRoot($parentNodeCategory = null, $recursionLevel = 3)
}
/**
+ * Get Default Store Id
+ *
* @return int
*/
protected function _getDefaultStoreId()
@@ -170,6 +185,8 @@ protected function _getDefaultStoreId()
}
/**
+ * Get category collection
+ *
* @return \Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection
*/
public function getCategoryCollection()
@@ -227,6 +244,8 @@ public function getRootByIds($ids)
}
/**
+ * Get category node for tree
+ *
* @param mixed $parentNodeCategory
* @param int $recursionLevel
* @return Node
@@ -249,6 +268,8 @@ public function getNode($parentNodeCategory, $recursionLevel = 2)
}
/**
+ * Get category save url
+ *
* @param array $args
* @return string
*/
@@ -260,6 +281,8 @@ public function getSaveUrl(array $args = [])
}
/**
+ * Get category edit url
+ *
* @return string
*/
public function getEditUrl()
diff --git a/app/code/Magento/Catalog/Model/CategoryList.php b/app/code/Magento/Catalog/Model/CategoryList.php
index 790ea6b921fbe..e3318db505489 100644
--- a/app/code/Magento/Catalog/Model/CategoryList.php
+++ b/app/code/Magento/Catalog/Model/CategoryList.php
@@ -15,6 +15,9 @@
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
+/**
+ * Class for getting category list.
+ */
class CategoryList implements CategoryListInterface
{
/**
@@ -64,7 +67,7 @@ public function __construct(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getList(SearchCriteriaInterface $searchCriteria)
{
@@ -73,10 +76,11 @@ public function getList(SearchCriteriaInterface $searchCriteria)
$this->extensionAttributesJoinProcessor->process($collection);
$this->collectionProcessor->process($searchCriteria, $collection);
+ $collection->load();
$items = [];
- foreach ($collection->getAllIds() as $id) {
- $items[] = $this->categoryRepository->get($id);
+ foreach ($collection->getItems() as $category) {
+ $items[] = $this->categoryRepository->get($category->getId());
}
/** @var CategorySearchResultsInterface $searchResult */
diff --git a/app/code/Magento/Catalog/Model/Product/Option/Repository.php b/app/code/Magento/Catalog/Model/Product/Option/Repository.php
index 9dc9695daffd1..bb4e247de32db 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/Repository.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/Repository.php
@@ -14,6 +14,8 @@
use Magento\Framework\App\ObjectManager;
/**
+ * Product custom options repository
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Repository implements \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface
@@ -83,7 +85,7 @@ public function __construct(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getList($sku)
{
@@ -92,7 +94,7 @@ public function getList($sku)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getProductOptions(ProductInterface $product, $requiredOnly = false)
{
@@ -104,7 +106,7 @@ public function getProductOptions(ProductInterface $product, $requiredOnly = fal
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function get($sku, $optionId)
{
@@ -117,7 +119,7 @@ public function get($sku, $optionId)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function delete(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $entity)
{
@@ -126,7 +128,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $e
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function duplicate(
\Magento\Catalog\Api\Data\ProductInterface $product,
@@ -142,7 +144,7 @@ public function duplicate(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $option)
{
@@ -184,7 +186,7 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function deleteByIdentifier($sku, $optionId)
{
@@ -209,8 +211,8 @@ public function deleteByIdentifier($sku, $optionId)
/**
* Mark original values for removal if they are absent among new values
*
- * @param $newValues array
- * @param $originalValues \Magento\Catalog\Model\Product\Option\Value[]
+ * @param array $newValues
+ * @param \Magento\Catalog\Model\Product\Option\Value[] $originalValues
* @return array
*/
protected function markRemovedValues($newValues, $originalValues)
@@ -234,6 +236,8 @@ protected function markRemovedValues($newValues, $originalValues)
}
/**
+ * Get hydrator pool
+ *
* @return \Magento\Framework\EntityManager\HydratorPool
* @deprecated 101.0.0
*/
diff --git a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php
index c4a2d60414a7b..0941aa2478935 100644
--- a/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php
+++ b/app/code/Magento/Catalog/Model/Product/Option/SaveHandler.php
@@ -28,6 +28,8 @@ public function __construct(
}
/**
+ * Perform action on relation/extension attribute
+ *
* @param object $entity
* @param array $arguments
* @return \Magento\Catalog\Api\Data\ProductInterface|object
@@ -35,6 +37,10 @@ public function __construct(
*/
public function execute($entity, $arguments = [])
{
+ if ($entity->getOptionsSaved()) {
+ return $entity;
+ }
+
$options = $entity->getOptions();
$optionIds = [];
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/AbstractResource.php b/app/code/Magento/Catalog/Model/ResourceModel/AbstractResource.php
index b9e629912a5b3..9cf1431317944 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/AbstractResource.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/AbstractResource.php
@@ -7,6 +7,10 @@
namespace Magento\Catalog\Model\ResourceModel;
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
+use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend;
+use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
+use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
+use Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface;
/**
* Catalog entity abstract model
@@ -37,16 +41,18 @@ abstract class AbstractResource extends \Magento\Eav\Model\Entity\AbstractEntity
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
* @param \Magento\Catalog\Model\Factory $modelFactory
* @param array $data
+ * @param UniqueValidationInterface|null $uniqueValidator
*/
public function __construct(
\Magento\Eav\Model\Entity\Context $context,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\Factory $modelFactory,
- $data = []
+ $data = [],
+ UniqueValidationInterface $uniqueValidator = null
) {
$this->_storeManager = $storeManager;
$this->_modelFactory = $modelFactory;
- parent::__construct($context, $data);
+ parent::__construct($context, $data, $uniqueValidator);
}
/**
@@ -86,9 +92,7 @@ protected function _isApplicableAttribute($object, $attribute)
/**
* Check whether attribute instance (attribute, backend, frontend or source) has method and applicable
*
- * @param AbstractAttribute|\Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
- * |\Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend
- * |\Magento\Eav\Model\Entity\Attribute\Source\AbstractSource $instance
+ * @param AbstractAttribute|AbstractBackend|AbstractFrontend|AbstractSource $instance
* @param string $method
* @param array $args array of arguments
* @return boolean
@@ -112,6 +116,7 @@ protected function _isCallableAttributeInstance($instance, $method, $args)
/**
* Retrieve select object for loading entity attributes values
+ *
* Join attribute store value
*
* @param \Magento\Framework\DataObject $object
@@ -244,6 +249,7 @@ protected function _saveAttributeValue($object, $attribute, $value)
/**
* Check if attribute present for non default Store View.
+ *
* Prevent "delete" query locking in a case when nothing to delete
*
* @param AbstractAttribute $attribute
diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product.php b/app/code/Magento/Catalog/Model/ResourceModel/Product.php
index d71ec23881982..24174391be829 100644
--- a/app/code/Magento/Catalog/Model/ResourceModel/Product.php
+++ b/app/code/Magento/Catalog/Model/ResourceModel/Product.php
@@ -8,6 +8,7 @@
use Magento\Catalog\Model\ResourceModel\Product\Website\Link as ProductWebsiteLink;
use Magento\Framework\App\ObjectManager;
use Magento\Catalog\Model\Indexer\Category\Product\TableMaintainer;
+use Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface;
/**
* Product entity resource model
@@ -101,6 +102,7 @@ class Product extends AbstractResource
* @param \Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes
* @param array $data
* @param TableMaintainer|null $tableMaintainer
+ * @param UniqueValidationInterface|null $uniqueValidator
*
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
@@ -115,7 +117,8 @@ public function __construct(
\Magento\Eav\Model\Entity\TypeFactory $typeFactory,
\Magento\Catalog\Model\Product\Attribute\DefaultAttributes $defaultAttributes,
$data = [],
- TableMaintainer $tableMaintainer = null
+ TableMaintainer $tableMaintainer = null,
+ UniqueValidationInterface $uniqueValidator = null
) {
$this->_categoryCollectionFactory = $categoryCollectionFactory;
$this->_catalogCategory = $catalogCategory;
@@ -127,7 +130,8 @@ public function __construct(
$context,
$storeManager,
$modelFactory,
- $data
+ $data,
+ $uniqueValidator
);
$this->connectionName = 'catalog';
$this->tableMaintainer = $tableMaintainer ?: ObjectManager::getInstance()->get(TableMaintainer::class);
@@ -289,7 +293,7 @@ protected function _afterSave(\Magento\Framework\DataObject $product)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function delete($object)
{
@@ -593,7 +597,7 @@ public function countAll()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function validate($object)
{
@@ -633,7 +637,7 @@ public function load($object, $entityId, $attributes = [])
}
/**
- * {@inheritdoc}
+ * @inheritdoc
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
* @since 101.0.0
*/
@@ -675,6 +679,8 @@ public function save(\Magento\Framework\Model\AbstractModel $object)
}
/**
+ * Retrieve entity manager object
+ *
* @return \Magento\Framework\EntityManager\EntityManager
*/
private function getEntityManager()
@@ -687,6 +693,8 @@ private function getEntityManager()
}
/**
+ * Retrieve ProductWebsiteLink object
+ *
* @deprecated 101.1.0
* @return ProductWebsiteLink
*/
@@ -696,6 +704,8 @@ private function getProductWebsiteLink()
}
/**
+ * Retrieve CategoryLink object
+ *
* @deprecated 101.1.0
* @return \Magento\Catalog\Model\ResourceModel\Product\CategoryLink
*/
@@ -710,9 +720,10 @@ private function getProductCategoryLink()
/**
* Extends parent method to be appropriate for product.
+ *
* Store id is required to correctly identify attribute value we are working with.
*
- * {@inheritdoc}
+ * @inheritdoc
* @since 101.1.0
*/
protected function getAttributeRow($entity, $object, $attribute)
diff --git a/app/code/Magento/Catalog/Plugin/Model/Product/Option/UpdateProductCustomOptionsAttributes.php b/app/code/Magento/Catalog/Plugin/Model/Product/Option/UpdateProductCustomOptionsAttributes.php
new file mode 100644
index 0000000000000..dd750cfbc696e
--- /dev/null
+++ b/app/code/Magento/Catalog/Plugin/Model/Product/Option/UpdateProductCustomOptionsAttributes.php
@@ -0,0 +1,56 @@
+productRepository = $productRepository;
+ }
+
+ /**
+ * Update product 'has_options' and 'required_options' attributes after option save
+ *
+ * @param \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface $subject
+ * @param \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option
+ *
+ * @return \Magento\Catalog\Api\Data\ProductCustomOptionInterface
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterSave(
+ \Magento\Catalog\Api\ProductCustomOptionRepositoryInterface $subject,
+ \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option
+ ) {
+ $product = $this->productRepository->get($option->getProductSku());
+ if (!$product->getHasOptions() ||
+ ($option->getIsRequire() && !$product->getRequiredOptions())) {
+ $product->setCanSaveCustomOptions(true);
+ $product->setOptionsSaved(true);
+ $currentOptions = array_filter($product->getOptions(), function ($iOption) use ($option) {
+ return $option->getOptionId() != $iOption->getOptionId();
+ });
+ $currentOptions[] = $option;
+ $product->setOptions($currentOptions);
+ $product->save();
+ }
+
+ return $option;
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
index 50e3e5864f4c3..6d0d953e44676 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/ProductData.xml
@@ -35,6 +35,9 @@
EavStockItem
CustomAttributeCategoryIds
+
+ 100
+
ApiProductDescription
ApiProductShortDescription
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
index ef6fb99e88eed..14e714cb2b6b7 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
@@ -13,7 +13,7 @@
-
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml
index 05be20b14acc0..ee6af87b8e2c5 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml
@@ -78,6 +78,7 @@
type="button" selector="#advanced_fieldset-wrapper"/>
+
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php
index b8b76524099f4..f78c0ad924954 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryListTest.php
@@ -93,7 +93,7 @@ public function testGetList()
$collection = $this->getMockBuilder(Collection::class)->disableOriginalConstructor()->getMock();
$collection->expects($this->once())->method('getSize')->willReturn($totalCount);
- $collection->expects($this->once())->method('getAllIds')->willReturn([$categoryIdFirst, $categoryIdSecond]);
+ $collection->expects($this->once())->method('getItems')->willReturn([$categoryFirst, $categorySecond]);
$this->collectionProcessorMock->expects($this->once())
->method('process')
diff --git a/app/code/Magento/Catalog/etc/webapi_rest/di.xml b/app/code/Magento/Catalog/etc/webapi_rest/di.xml
index 2a5d60222e9f8..44cdd473bf74e 100644
--- a/app/code/Magento/Catalog/etc/webapi_rest/di.xml
+++ b/app/code/Magento/Catalog/etc/webapi_rest/di.xml
@@ -19,4 +19,7 @@
+
+
+
diff --git a/app/code/Magento/Catalog/etc/webapi_soap/di.xml b/app/code/Magento/Catalog/etc/webapi_soap/di.xml
index 2a5d60222e9f8..44cdd473bf74e 100644
--- a/app/code/Magento/Catalog/etc/webapi_soap/di.xml
+++ b/app/code/Magento/Catalog/etc/webapi_soap/di.xml
@@ -19,4 +19,7 @@
+
+
+
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml
index 00a1580923a7b..ee67acd0ebd46 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/checkboxes/tree.phtml
@@ -20,7 +20,7 @@
"categoryCheckboxTree": {
"dataUrl": "= $block->escapeUrl($block->getLoadTreeUrl()) ?>",
"divId": "= /* @noEscape */ $divId ?>",
- "rootVisible": = /* @noEscape */ $block->getRoot()->getIsVisible() ? 'true' : 'false' ?>,
+ "rootVisible": false,
"useAjax": = $block->escapeHtml($block->getUseAjax()) ?>,
"currentNodeId": = (int)$block->getCategoryId() ?>,
"jsFormObject": "= /* @noEscape */ $block->getJsFormObject() ?>",
@@ -28,7 +28,7 @@
"checked": "= $block->escapeHtml($block->getRoot()->getChecked()) ?>",
"allowdDrop": = /* @noEscape */ $block->getRoot()->getIsVisible() ? 'true' : 'false' ?>,
"rootId": = (int)$block->getRoot()->getId() ?>,
- "expanded": = (int)$block->getIsWasExpanded() ?>,
+ "expanded": true,
"categoryId": = (int)$block->getCategoryId() ?>,
"treeJson": = /* @noEscape */ $block->getTreeJson() ?>
}
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml
index 93666470b1b2c..f448edc692ce2 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml
@@ -302,6 +302,7 @@
}
//updateContent(url); //commented since ajax requests replaced with http ones to load a category
+ jQuery('#tree-div').find('.x-tree-node-el').first().remove();
}
jQuery(function () {
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml
index dbe66ef1aecd3..69737b8a37c1c 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/widget/tree.phtml
@@ -160,7 +160,7 @@ jQuery(function()
loader: categoryLoader,
enableDD: false,
containerScroll: true,
- rootVisible: '= /* @escapeNotVerified */ $block->getRoot()->getIsVisible() ?>',
+ rootVisible: false,
useAjax: true,
currentNodeId: = (int) $block->getCategoryId() ?>,
addNodeTo: false
@@ -177,7 +177,7 @@ jQuery(function()
text: 'Psw',
draggable: false,
id: = (int) $block->getRoot()->getId() ?>,
- expanded: = (int) $block->getIsWasExpanded() ?>,
+ expanded: true,
category_id: = (int) $block->getCategoryId() ?>
};
diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
index 52ab8d49ec546..75249e4907862 100644
--- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php
+++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php
@@ -351,6 +351,7 @@ class Product extends \Magento\ImportExport\Model\Export\Entity\AbstractEntity
/**
* Product constructor.
+ *
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Magento\Eav\Model\Config $config
* @param \Magento\Framework\App\ResourceConnection $resource
@@ -941,15 +942,17 @@ protected function getExportData()
protected function loadCollection(): array
{
$data = [];
-
$collection = $this->_getEntityCollection();
foreach (array_keys($this->_storeIdToCode) as $storeId) {
+ $collection->setOrder('entity_id', 'asc');
+ $this->_prepareEntityCollection($collection);
$collection->setStoreId($storeId);
+ $collection->load();
foreach ($collection as $itemId => $item) {
$data[$itemId][$storeId] = $item;
}
+ $collection->clear();
}
- $collection->clear();
return $data;
}
diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
index 92ba6bf2bbbb1..c5e309df3cad6 100644
--- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php
+++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php
@@ -82,11 +82,14 @@ public function getConfig()
'baseUrl' => $this->getBaseUrl(),
'minicartMaxItemsVisible' => $this->getMiniCartMaxItemsCount(),
'websiteId' => $this->_storeManager->getStore()->getWebsiteId(),
- 'maxItemsToDisplay' => $this->getMaxItemsToDisplay()
+ 'maxItemsToDisplay' => $this->getMaxItemsToDisplay(),
+ 'storeId' => $this->_storeManager->getStore()->getId()
];
}
/**
+ * Get serialized config
+ *
* @return string
* @since 100.2.0
*/
@@ -96,6 +99,8 @@ public function getSerializedConfig()
}
/**
+ * Get image html template
+ *
* @return string
*/
public function getImageHtmlTemplate()
@@ -130,6 +135,7 @@ public function getShoppingCartUrl()
*
* @return string
* @codeCoverageIgnore
+ * @SuppressWarnings(PHPMD.RequestAwareBlockMethod)
*/
public function getUpdateItemQtyUrl()
{
@@ -141,6 +147,7 @@ public function getUpdateItemQtyUrl()
*
* @return string
* @codeCoverageIgnore
+ * @SuppressWarnings(PHPMD.RequestAwareBlockMethod)
*/
public function getRemoveItemUrl()
{
@@ -210,6 +217,7 @@ private function getMiniCartMaxItemsCount()
/**
* Returns maximum cart items to display
+ *
* This setting regulates how many items will be displayed in minicart
*
* @return int
diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php
index 01e91d75c02d9..169be4cc62f01 100644
--- a/app/code/Magento/Checkout/CustomerData/Cart.php
+++ b/app/code/Magento/Checkout/CustomerData/Cart.php
@@ -10,6 +10,8 @@
/**
* Cart source
+ *
+ * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
*/
class Cart extends \Magento\Framework\DataObject implements SectionSourceInterface
{
@@ -98,7 +100,8 @@ public function getSectionData()
'items' => $this->getRecentItems(),
'extra_actions' => $this->layout->createBlock(\Magento\Catalog\Block\ShortcutButtons::class)->toHtml(),
'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(),
- 'website_id' => $this->getQuote()->getStore()->getWebsiteId()
+ 'website_id' => $this->getQuote()->getStore()->getWebsiteId(),
+ 'storeId' => $this->getQuote()->getStore()->getStoreId()
];
}
diff --git a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
index d2bd680aa38f3..e0de45a3f0dea 100644
--- a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
+++ b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php
@@ -118,7 +118,9 @@ public function savePaymentInformation(
$shippingAddress = $quote->getShippingAddress();
if ($shippingAddress && $shippingAddress->getShippingMethod()) {
$shippingRate = $shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod());
- $shippingAddress->setLimitCarrier($shippingRate->getCarrier());
+ $shippingAddress->setLimitCarrier(
+ $shippingRate ? $shippingRate->getCarrier() : $shippingAddress->getShippingMethod()
+ );
}
}
$this->paymentMethodManagement->set($cartId, $paymentMethod);
diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml
index 0d3c6e419cc07..dcfb12fd4e965 100644
--- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml
+++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutCartProductSection.xml
@@ -26,6 +26,7 @@
parameterized="true"/>
+
diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml
index ad2a43eb90c8c..6838824400b96 100644
--- a/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml
+++ b/app/code/Magento/Checkout/Test/Mftf/Section/CheckoutShippingGuestInfoSection.xml
@@ -19,5 +19,9 @@
+
+
+
+
diff --git a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml
index a894f2fbb1af9..bdb02835c6276 100644
--- a/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml
+++ b/app/code/Magento/Checkout/Test/Mftf/Section/StorefrontMiniCartSection.xml
@@ -13,6 +13,7 @@
+
diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml
new file mode 100644
index 0000000000000..3401369a8c749
--- /dev/null
+++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontProductNameMinicartOnCheckoutPageDifferentStoreViewsTest.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php
index 1c5224d007ec8..f69ced3b094c7 100644
--- a/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/Block/Cart/SidebarTest.php
@@ -144,7 +144,8 @@ public function testGetConfig()
'baseUrl' => $baseUrl,
'minicartMaxItemsVisible' => 3,
'websiteId' => 100,
- 'maxItemsToDisplay' => 8
+ 'maxItemsToDisplay' => 8,
+ 'storeId' => null
];
$valueMap = [
@@ -161,7 +162,7 @@ public function testGetConfig()
$this->urlBuilderMock->expects($this->exactly(4))
->method('getUrl')
->willReturnMap($valueMap);
- $this->storeManagerMock->expects($this->exactly(2))->method('getStore')->willReturn($storeMock);
+ $this->storeManagerMock->expects($this->any())->method('getStore')->willReturn($storeMock);
$storeMock->expects($this->once())->method('getBaseUrl')->willReturn($baseUrl);
$this->scopeConfigMock->expects($this->at(0))
diff --git a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php
index 75e181cbabd08..e3e13cc5b1e69 100644
--- a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php
+++ b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php
@@ -113,7 +113,7 @@ public function testGetSectionData()
$storeMock = $this->createPartialMock(\Magento\Store\Model\System\Store::class, ['getWebsiteId']);
$storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId);
- $quoteMock->expects($this->once())->method('getStore')->willReturn($storeMock);
+ $quoteMock->expects($this->any())->method('getStore')->willReturn($storeMock);
$productMock = $this->createPartialMock(
\Magento\Catalog\Model\Product::class,
@@ -162,6 +162,7 @@ public function testGetSectionData()
'isGuestCheckoutAllowed' => 1,
'website_id' => $websiteId,
'subtotalAmount' => 200,
+ 'storeId' => null
];
$this->assertEquals($expectedResult, $this->model->getSectionData());
}
@@ -199,7 +200,7 @@ public function testGetSectionDataWithCompositeProduct()
$storeMock = $this->createPartialMock(\Magento\Store\Model\System\Store::class, ['getWebsiteId']);
$storeMock->expects($this->once())->method('getWebsiteId')->willReturn($websiteId);
- $quoteMock->expects($this->once())->method('getStore')->willReturn($storeMock);
+ $quoteMock->expects($this->any())->method('getStore')->willReturn($storeMock);
$this->checkoutCartMock->expects($this->once())->method('getSummaryQty')->willReturn($summaryQty);
$this->checkoutHelperMock->expects($this->once())
@@ -265,6 +266,7 @@ public function testGetSectionDataWithCompositeProduct()
'isGuestCheckoutAllowed' => 1,
'website_id' => $websiteId,
'subtotalAmount' => 200,
+ 'storeId' => null
];
$this->assertEquals($expectedResult, $this->model->getSectionData());
}
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
index a2f8c8c56ff33..5e29fa209a641 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js
@@ -81,6 +81,7 @@ define([
maxItemsToDisplay: window.checkout.maxItemsToDisplay,
cart: {},
+ // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
/**
* @override
*/
@@ -101,12 +102,16 @@ define([
self.isLoading(true);
});
- if (cartData()['website_id'] !== window.checkout.websiteId) {
+ if (cartData().website_id !== window.checkout.websiteId ||
+ cartData().store_id !== window.checkout.storeId
+ ) {
customerData.reload(['cart'], false);
}
return this._super();
},
+ //jscs:enable requireCamelCaseOrUpperCaseIdentifiers
+
isLoading: ko.observable(false),
initSidebar: initSidebar,
diff --git a/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigSalesTaxClassActionGroup.xml b/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigSalesTaxClassActionGroup.xml
index 06c041fabeb35..1a7b641070ad8 100644
--- a/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigSalesTaxClassActionGroup.xml
+++ b/app/code/Magento/Config/Test/Mftf/ActionGroup/ConfigSalesTaxClassActionGroup.xml
@@ -28,4 +28,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php
index 3f2c7cda7608d..1bc6bb1da3680 100644
--- a/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php
+++ b/app/code/Magento/Customer/Block/Adminhtml/Edit/Tab/View/Cart.php
@@ -71,7 +71,7 @@ public function __construct(
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
protected function _construct()
{
@@ -94,7 +94,7 @@ protected function _prepareCollection()
$quote = $this->getQuote();
if ($quote) {
- $collection = $quote->getItemsCollection(false);
+ $collection = $quote->getItemsCollection(true);
} else {
$collection = $this->_dataCollectionFactory->create();
}
@@ -106,7 +106,7 @@ protected function _prepareCollection()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
protected function _prepareColumns()
{
@@ -144,7 +144,7 @@ protected function _prepareColumns()
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getRowUrl($row)
{
@@ -152,7 +152,7 @@ public function getRowUrl($row)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
public function getHeadersVisibility()
{
diff --git a/app/code/Magento/Customer/Block/Widget/Name.php b/app/code/Magento/Customer/Block/Widget/Name.php
index d50045f4a4092..6f1b051af7465 100644
--- a/app/code/Magento/Customer/Block/Widget/Name.php
+++ b/app/code/Magento/Customer/Block/Widget/Name.php
@@ -55,7 +55,7 @@ public function __construct(
}
/**
- * @return void
+ * @inheritdoc
*/
public function _construct()
{
@@ -245,10 +245,13 @@ public function getStoreLabel($attributeCode)
*/
public function getAttributeValidationClass($attributeCode)
{
- return $this->_addressHelper->getAttributeValidationClass($attributeCode);
+ $attributeMetadata = $this->_getAttribute($attributeCode);
+ return $attributeMetadata ? $attributeMetadata->getFrontendClass() : '';
}
/**
+ * Check if attribute is required
+ *
* @param string $attributeCode
* @return bool
*/
@@ -259,6 +262,8 @@ private function _isAttributeRequired($attributeCode)
}
/**
+ * Check if attribute is visible
+ *
* @param string $attributeCode
* @return bool
*/
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml
index 7482193031091..0e31f0e0c7782 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerSidebarSection.xml
@@ -10,5 +10,6 @@
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/SectionObject.xsd">
diff --git a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
index 0522ea0432176..d0a5e8de53ae9 100644
--- a/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
+++ b/app/code/Magento/Eav/Model/Entity/AbstractEntity.php
@@ -10,6 +10,7 @@
use Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend;
use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
+use Magento\Eav\Model\Entity\Attribute\UniqueValidationInterface;
use Magento\Framework\App\Config\Element;
use Magento\Framework\DataObject;
use Magento\Framework\DB\Adapter\DuplicateException;
@@ -215,12 +216,21 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac
*/
protected $objectRelationProcessor;
+ /**
+ * @var UniqueValidationInterface
+ */
+ private $uniqueValidator;
+
/**
* @param Context $context
* @param array $data
+ * @param UniqueValidationInterface|null $uniqueValidator
*/
- public function __construct(Context $context, $data = [])
- {
+ public function __construct(
+ Context $context,
+ $data = [],
+ UniqueValidationInterface $uniqueValidator = null
+ ) {
$this->_eavConfig = $context->getEavConfig();
$this->_resource = $context->getResource();
$this->_attrSetEntity = $context->getAttributeSetEntity();
@@ -229,6 +239,8 @@ public function __construct(Context $context, $data = [])
$this->_universalFactory = $context->getUniversalFactory();
$this->transactionManager = $context->getTransactionManager();
$this->objectRelationProcessor = $context->getObjectRelationProcessor();
+ $this->uniqueValidator = $uniqueValidator ?:
+ ObjectManager::getInstance()->get(UniqueValidationInterface::class);
parent::__construct();
$properties = get_object_vars($this);
foreach ($data as $key => $value) {
@@ -488,6 +500,7 @@ public function addAttribute(AbstractAttribute $attribute, $object = null)
/**
* Get attributes by scope
*
+ * @param string $suffix
* @return array
*/
private function getAttributesByScope($suffix)
@@ -958,12 +971,8 @@ public function checkAttributeUniqueValue(AbstractAttribute $attribute, $object)
$data = $connection->fetchCol($select, $bind);
- $objectId = $object->getData($entityIdField);
- if ($objectId) {
- if (isset($data[0])) {
- return $data[0] == $objectId;
- }
- return true;
+ if ($object->getData($entityIdField)) {
+ return $this->uniqueValidator->validate($attribute, $object, $this, $entityIdField, $data);
}
return !count($data);
@@ -1972,7 +1981,8 @@ public function afterDelete(DataObject $object)
/**
* Load attributes for object
- * if the object will not pass all attributes for this entity type will be loaded
+ *
+ * If the object will not pass all attributes for this entity type will be loaded
*
* @param array $attributes
* @param AbstractEntity|null $object
diff --git a/app/code/Magento/Eav/Model/Entity/Attribute/UniqueValidationInterface.php b/app/code/Magento/Eav/Model/Entity/Attribute/UniqueValidationInterface.php
new file mode 100644
index 0000000000000..b68e79d7b7d20
--- /dev/null
+++ b/app/code/Magento/Eav/Model/Entity/Attribute/UniqueValidationInterface.php
@@ -0,0 +1,33 @@
+getData($entityLinkField);
+ }
+ return true;
+ }
+}
diff --git a/app/code/Magento/Eav/etc/di.xml b/app/code/Magento/Eav/etc/di.xml
index 8e897b979d2f0..a4c89dcfab2af 100644
--- a/app/code/Magento/Eav/etc/di.xml
+++ b/app/code/Magento/Eav/etc/di.xml
@@ -8,6 +8,7 @@
+
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
index bb81f9ebb475f..373d64afc8cc3 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
@@ -227,12 +227,12 @@ public function getCode($type, $code = '')
$codes = [
'condition_name' => [
'package_weight' => __('Weight vs. Destination'),
- 'package_value' => __('Price vs. Destination'),
+ 'package_value_with_discount' => __('Price vs. Destination'),
'package_qty' => __('# of Items vs. Destination'),
],
'condition_name_short' => [
'package_weight' => __('Weight (and above)'),
- 'package_value' => __('Order Subtotal (and above)'),
+ 'package_value_with_discount' => __('Order Subtotal (and above)'),
'package_qty' => __('# of Items (and above)'),
],
];
diff --git a/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateShippingTablerate.php b/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateShippingTablerate.php
new file mode 100644
index 0000000000000..070105846fdd8
--- /dev/null
+++ b/app/code/Magento/OfflineShipping/Setup/Patch/Data/UpdateShippingTablerate.php
@@ -0,0 +1,73 @@
+moduleDataSetup = $moduleDataSetup;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function apply()
+ {
+ $this->moduleDataSetup->getConnection()->startSetup();
+ $connection = $this->moduleDataSetup->getConnection();
+ $connection->update(
+ $this->moduleDataSetup->getTable('shipping_tablerate'),
+ ['condition_name' => 'package_value_with_discount'],
+ [new \Zend_Db_Expr('condition_name = \'package_value\'')]
+ );
+ $connection->update(
+ $this->moduleDataSetup->getTable('core_config_data'),
+ ['value' => 'package_value_with_discount'],
+ [
+ new \Zend_Db_Expr('value = \'package_value\''),
+ new \Zend_Db_Expr('path = \'carriers/tablerate/condition_name\'')
+ ]
+ );
+ $this->moduleDataSetup->getConnection()->endSetup();
+
+ $connection->endSetup();
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function getDependencies()
+ {
+ return [];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAliases()
+ {
+ return [];
+ }
+}
diff --git a/app/code/Magento/OfflineShipping/etc/db_schema.xml b/app/code/Magento/OfflineShipping/etc/db_schema.xml
index 0510ce9b9b8eb..5129e8a29b2a1 100644
--- a/app/code/Magento/OfflineShipping/etc/db_schema.xml
+++ b/app/code/Magento/OfflineShipping/etc/db_schema.xml
@@ -18,7 +18,7 @@
default="0" comment="Destination Region Id"/>
-
+
hasItemsCollection()) {
+ if ($this->hasItemsCollection() && $useCache) {
return $this->getData('items_collection');
}
- if (null === $this->_items) {
+ if (null === $this->_items || !$useCache) {
$this->_items = $this->_quoteItemCollectionFactory->create();
$this->extensionAttributesJoinProcessor->process($this->_items);
$this->_items->setQuote($this);
diff --git a/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php
new file mode 100644
index 0000000000000..19a7e03264d8a
--- /dev/null
+++ b/app/code/Magento/Quote/Plugin/UpdateQuoteItemStore.php
@@ -0,0 +1,72 @@
+quoteRepository = $quoteRepository;
+ $this->checkoutSession = $checkoutSession;
+ }
+
+ /**
+ * Update store id in active quote after store view switching.
+ *
+ * @param StoreSwitcherInterface $subject
+ * @param string $result
+ * @param StoreInterface $fromStore store where we came from
+ * @param StoreInterface $targetStore store where to go to
+ * @param string $redirectUrl original url requested for redirect after switching
+ * @return string url to be redirected after switching
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function afterSwitch(
+ StoreSwitcherInterface $subject,
+ $result,
+ StoreInterface $fromStore,
+ StoreInterface $targetStore,
+ string $redirectUrl
+ ): string {
+ $quote = $this->checkoutSession->getQuote();
+ if ($quote->getIsActive()) {
+ $quote->setStoreId(
+ $targetStore->getId()
+ );
+ $quote->getItemsCollection(false);
+ $this->quoteRepository->save($quote);
+ }
+ return $result;
+ }
+}
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Cart/CartTotalRepositoryTest.php b/app/code/Magento/Quote/Test/Unit/Model/Cart/CartTotalRepositoryTest.php
index 1e999cb5e523e..804f0863d2d2a 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Cart/CartTotalRepositoryTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Cart/CartTotalRepositoryTest.php
@@ -77,7 +77,8 @@ protected function setUp()
'getAllVisibleItems',
'getBaseCurrencyCode',
'getQuoteCurrencyCode',
- 'getItemsQty'
+ 'getItemsQty',
+ 'collectTotals'
]);
$this->quoteRepositoryMock = $this->createMock(\Magento\Quote\Api\CartRepositoryInterface::class);
$this->addressMock = $this->createPartialMock(
diff --git a/app/code/Magento/Quote/etc/frontend/di.xml b/app/code/Magento/Quote/etc/frontend/di.xml
index 125afb96f20fd..ecad94fbbc249 100644
--- a/app/code/Magento/Quote/etc/frontend/di.xml
+++ b/app/code/Magento/Quote/etc/frontend/di.xml
@@ -12,6 +12,9 @@
Magento\Checkout\Model\Session\Proxy
+
+
+
diff --git a/app/code/Magento/Quote/etc/sales.xml b/app/code/Magento/Quote/etc/sales.xml
index 3d54a6375c8d9..3db72a1226236 100644
--- a/app/code/Magento/Quote/etc/sales.xml
+++ b/app/code/Magento/Quote/etc/sales.xml
@@ -9,7 +9,7 @@
diff --git a/app/code/Magento/Sales/Model/Service/InvoiceService.php b/app/code/Magento/Sales/Model/Service/InvoiceService.php
index 791274d3f23bd..ba6ae7eb14ba7 100644
--- a/app/code/Magento/Sales/Model/Service/InvoiceService.php
+++ b/app/code/Magento/Sales/Model/Service/InvoiceService.php
@@ -7,9 +7,14 @@
use Magento\Sales\Api\InvoiceManagementInterface;
use Magento\Sales\Model\Order;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Serialize\Serializer\Json;
+use Magento\Catalog\Model\Product\Type;
/**
* Class InvoiceService
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class InvoiceService implements InvoiceManagementInterface
{
@@ -58,6 +63,13 @@ class InvoiceService implements InvoiceManagementInterface
*/
protected $orderConverter;
+ /**
+ * Serializer interface instance.
+ *
+ * @var Json
+ */
+ private $serializer;
+
/**
* Constructor
*
@@ -68,6 +80,7 @@ class InvoiceService implements InvoiceManagementInterface
* @param \Magento\Sales\Model\Order\InvoiceNotifier $notifier
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
* @param \Magento\Sales\Model\Convert\Order $orderConverter
+ * @param Json|null $serializer
*/
public function __construct(
\Magento\Sales\Api\InvoiceRepositoryInterface $repository,
@@ -76,7 +89,8 @@ public function __construct(
\Magento\Framework\Api\FilterBuilder $filterBuilder,
\Magento\Sales\Model\Order\InvoiceNotifier $notifier,
\Magento\Sales\Api\OrderRepositoryInterface $orderRepository,
- \Magento\Sales\Model\Convert\Order $orderConverter
+ \Magento\Sales\Model\Convert\Order $orderConverter,
+ Json $serializer = null
) {
$this->repository = $repository;
$this->commentRepository = $commentRepository;
@@ -85,6 +99,7 @@ public function __construct(
$this->invoiceNotifier = $notifier;
$this->orderRepository = $orderRepository;
$this->orderConverter = $orderConverter;
+ $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
}
/**
@@ -172,13 +187,13 @@ private function prepareItemsQty(Order $order, array $qtys = [])
{
foreach ($order->getAllItems() as $orderItem) {
if (empty($qtys[$orderItem->getId()])) {
- $parentId = $orderItem->getParentItemId();
- if ($parentId && array_key_exists($parentId, $qtys)) {
- $qtys[$orderItem->getId()] = $qtys[$parentId];
+ if ($orderItem->getProductType() == Type::TYPE_BUNDLE && !$orderItem->isShipSeparately()) {
+ $qtys[$orderItem->getId()] = $orderItem->getQtyOrdered() - $orderItem->getQtyInvoiced();
} else {
continue;
}
}
+
$this->prepareItemQty($orderItem, $qtys);
}
@@ -186,20 +201,27 @@ private function prepareItemsQty(Order $order, array $qtys = [])
}
/**
- * Prepare qty to invoice item.
+ * Prepare qty_invoiced for order item
*
- * @param Order\Item $orderItem
+ * @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem
* @param array $qtys
- * @return void
*/
private function prepareItemQty(\Magento\Sales\Api\Data\OrderItemInterface $orderItem, &$qtys)
{
+ $this->prepareBundleQty($orderItem, $qtys);
+
if ($orderItem->isDummy()) {
if ($orderItem->getHasChildren()) {
foreach ($orderItem->getChildrenItems() as $child) {
if (!isset($qtys[$child->getId()])) {
$qtys[$child->getId()] = $child->getQtyToInvoice();
}
+ $parentId = $orderItem->getParentItemId();
+ if ($parentId && array_key_exists($parentId, $qtys)) {
+ $qtys[$orderItem->getId()] = $qtys[$parentId];
+ } else {
+ continue;
+ }
}
} elseif ($orderItem->getParentItem()) {
$parent = $orderItem->getParentItem();
@@ -210,6 +232,26 @@ private function prepareItemQty(\Magento\Sales\Api\Data\OrderItemInterface $orde
}
}
+ /**
+ * Prepare qty to invoice for bundle products
+ *
+ * @param \Magento\Sales\Api\Data\OrderItemInterface $orderItem
+ * @param array $qtys
+ */
+ private function prepareBundleQty(\Magento\Sales\Api\Data\OrderItemInterface $orderItem, &$qtys)
+ {
+ if ($orderItem->getProductType() == Type::TYPE_BUNDLE && !$orderItem->isShipSeparately()) {
+ foreach ($orderItem->getChildrenItems() as $childItem) {
+ $bundleSelectionAttributes = $childItem->getProductOptionByCode('bundle_selection_attributes');
+ if (is_string($bundleSelectionAttributes)) {
+ $bundleSelectionAttributes = $this->serializer->unserialize($bundleSelectionAttributes);
+ }
+
+ $qtys[$childItem->getId()] = $qtys[$orderItem->getId()] * $bundleSelectionAttributes['qty'];
+ }
+ }
+ }
+
/**
* Check if order item can be invoiced.
*
diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/OrderAndReturnActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontOrderActionGroupActionGroup.xml
similarity index 64%
rename from app/code/Magento/Sales/Test/Mftf/ActionGroup/OrderAndReturnActionGroup.xml
rename to app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontOrderActionGroupActionGroup.xml
index c46dd612022fd..fcea25f997591 100644
--- a/app/code/Magento/Sales/Test/Mftf/ActionGroup/OrderAndReturnActionGroup.xml
+++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/StorefrontOrderActionGroupActionGroup.xml
@@ -9,11 +9,11 @@
-
+
-
-
+
+
@@ -24,13 +24,4 @@
-
-
-
-
-
-
-
-
-
diff --git a/app/code/Magento/Sales/Test/Mftf/Data/SalesEnableRMAStorefrontConfigData.xml b/app/code/Magento/Sales/Test/Mftf/Data/SalesEnableRMAStorefrontConfigData.xml
deleted file mode 100644
index 76ff20813483e..0000000000000
--- a/app/code/Magento/Sales/Test/Mftf/Data/SalesEnableRMAStorefrontConfigData.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
- EnableRMAStorefront
-
-
- 1
-
-
-
- DisableRMAStorefront
-
-
- 0
-
-
diff --git a/app/code/Magento/Sales/Test/Mftf/Metadata/sales_enable_rma_config-meta.xml b/app/code/Magento/Sales/Test/Mftf/Metadata/sales_enable_rma_config-meta.xml
deleted file mode 100644
index 86226265dd146..0000000000000
--- a/app/code/Magento/Sales/Test/Mftf/Metadata/sales_enable_rma_config-meta.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontOrdersAndReturnsPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontOrdersAndReturnsPage.xml
index 32d94c3175807..ee546174d9680 100644
--- a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontOrdersAndReturnsPage.xml
+++ b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontOrdersAndReturnsPage.xml
@@ -9,7 +9,6 @@
-
-
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCreateNewReturnMainSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCreateNewReturnMainSection.xml
deleted file mode 100644
index fe8391cf3c28f..0000000000000
--- a/app/code/Magento/Sales/Test/Mftf/Section/StorefrontCreateNewReturnMainSection.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml
new file mode 100644
index 0000000000000..7c83f35468ce6
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminCorrectnessInvoicedItemInBundleProductTest.xml
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php b/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php
new file mode 100644
index 0000000000000..c37ca276e0ee2
--- /dev/null
+++ b/app/code/Magento/SalesRule/Model/Quote/Address/Total/ShippingDiscount.php
@@ -0,0 +1,101 @@
+calculator = $calculator;
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @param Quote $quote
+ * @param ShippingAssignment $shippingAssignment
+ * @param Total $total
+ * @return ShippingDiscount
+ */
+ public function collect(Quote $quote, ShippingAssignment $shippingAssignment, Total $total): self
+ {
+ parent::collect($quote, $shippingAssignment, $total);
+
+ $address = $shippingAssignment->getShipping()->getAddress();
+ $this->calculator->reset($address);
+
+ $items = $shippingAssignment->getItems();
+ if (!count($items)) {
+ return $this;
+ }
+
+ $address->setShippingDiscountAmount(0);
+ $address->setBaseShippingDiscountAmount(0);
+ if ($address->getShippingAmount()) {
+ $this->calculator->processShippingAmount($address);
+ $total->addTotalAmount(DiscountCollector::COLLECTOR_TYPE_CODE, -$address->getShippingDiscountAmount());
+ $total->addBaseTotalAmount(
+ DiscountCollector::COLLECTOR_TYPE_CODE,
+ -$address->getBaseShippingDiscountAmount()
+ );
+ $total->setShippingDiscountAmount($address->getShippingDiscountAmount());
+ $total->setBaseShippingDiscountAmount($address->getBaseShippingDiscountAmount());
+
+ $this->calculator->prepareDescription($address);
+ $total->setDiscountDescription($address->getDiscountDescription());
+ $total->setSubtotalWithDiscount($total->getSubtotal() + $total->getDiscountAmount());
+ $total->setBaseSubtotalWithDiscount($total->getBaseSubtotal() + $total->getBaseDiscountAmount());
+
+ $address->setDiscountAmount($total->getDiscountAmount());
+ $address->setBaseDiscountAmount($total->getBaseDiscountAmount());
+ }
+
+ return $this;
+ }
+
+ /**
+ * @inheritdoc
+ *
+ * @param \Magento\Quote\Model\Quote $quote
+ * @param \Magento\Quote\Model\Quote\Address\Total $total
+ * @return array
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ */
+ public function fetch(Quote $quote, Total $total): array
+ {
+ $result = [];
+ $amount = $total->getDiscountAmount();
+
+ if ($amount != 0) {
+ $description = $total->getDiscountDescription() ?: '';
+ $result = [
+ 'code' => DiscountCollector::COLLECTOR_TYPE_CODE,
+ 'title' => strlen($description) ? __('Discount (%1)', $description) : __('Discount'),
+ 'value' => $amount
+ ];
+ }
+ return $result;
+ }
+}
diff --git a/app/code/Magento/SalesRule/Model/Quote/Discount.php b/app/code/Magento/SalesRule/Model/Quote/Discount.php
index 693a61b272f66..315ce874513a3 100644
--- a/app/code/Magento/SalesRule/Model/Quote/Discount.php
+++ b/app/code/Magento/SalesRule/Model/Quote/Discount.php
@@ -5,8 +5,13 @@
*/
namespace Magento\SalesRule\Model\Quote;
+/**
+ * Discount totals calculation model.
+ */
class Discount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
{
+ const COLLECTOR_TYPE_CODE = 'discount';
+
/**
* Discount calculation object
*
@@ -43,7 +48,7 @@ public function __construct(
\Magento\SalesRule\Model\Validator $validator,
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
) {
- $this->setCode('discount');
+ $this->setCode(self::COLLECTOR_TYPE_CODE);
$this->eventManager = $eventManager;
$this->calculator = $validator;
$this->storeManager = $storeManager;
@@ -124,21 +129,14 @@ public function collect(
}
}
- /** Process shipping amount discount */
- $address->setShippingDiscountAmount(0);
- $address->setBaseShippingDiscountAmount(0);
- if ($address->getShippingAmount()) {
- $this->calculator->processShippingAmount($address);
- $total->addTotalAmount($this->getCode(), -$address->getShippingDiscountAmount());
- $total->addBaseTotalAmount($this->getCode(), -$address->getBaseShippingDiscountAmount());
- $total->setShippingDiscountAmount($address->getShippingDiscountAmount());
- $total->setBaseShippingDiscountAmount($address->getBaseShippingDiscountAmount());
- }
-
$this->calculator->prepareDescription($address);
$total->setDiscountDescription($address->getDiscountDescription());
$total->setSubtotalWithDiscount($total->getSubtotal() + $total->getDiscountAmount());
$total->setBaseSubtotalWithDiscount($total->getBaseSubtotal() + $total->getBaseDiscountAmount());
+
+ $address->setDiscountAmount($total->getDiscountAmount());
+ $address->setBaseDiscountAmount($total->getBaseDiscountAmount());
+
return $this;
}
diff --git a/app/code/Magento/SalesRule/etc/sales.xml b/app/code/Magento/SalesRule/etc/sales.xml
index 3ab197d40b0df..d2db664224873 100644
--- a/app/code/Magento/SalesRule/etc/sales.xml
+++ b/app/code/Magento/SalesRule/etc/sales.xml
@@ -8,7 +8,8 @@
diff --git a/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentItemsSection.xml b/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentItemsSection.xml
index a7bf82588f7c7..0345c3f2949f4 100644
--- a/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentItemsSection.xml
+++ b/app/code/Magento/Shipping/Test/Mftf/Section/AdminShipmentItemsSection.xml
@@ -15,5 +15,6 @@
+
-
\ No newline at end of file
+
diff --git a/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
index bad64260cf58a..939facd02c02d 100644
--- a/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
+++ b/app/code/Magento/Tax/Model/Calculation/AbstractAggregateCalculator.php
@@ -7,6 +7,9 @@
use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
+/**
+ * Abstract aggregate calculator.
+ */
abstract class AbstractAggregateCalculator extends AbstractCalculator
{
/**
@@ -106,11 +109,12 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
$rowTaxes = [];
$rowTaxesBeforeDiscount = [];
$appliedTaxes = [];
+ $rowTotalForTaxCalculation = $this->getPriceForTaxCalculation($item, $price) * $quantity;
//Apply each tax rate separately
foreach ($appliedRates as $appliedRate) {
$taxId = $appliedRate['id'];
$taxRate = $appliedRate['percent'];
- $rowTaxPerRate = $this->calculationTool->calcTaxAmount($rowTotal, $taxRate, false, false);
+ $rowTaxPerRate = $this->calculationTool->calcTaxAmount($rowTotalForTaxCalculation, $taxRate, false, false);
$deltaRoundingType = self::KEY_REGULAR_DELTA_ROUNDING;
if ($applyTaxAfterDiscount) {
$deltaRoundingType = self::KEY_TAX_BEFORE_DISCOUNT_DELTA_ROUNDING;
@@ -121,7 +125,10 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
//Handle discount
if ($applyTaxAfterDiscount) {
//TODO: handle originalDiscountAmount
- $taxableAmount = max($rowTotal - $discountAmount, 0);
+ $taxableAmount = max($rowTotalForTaxCalculation - $discountAmount, 0);
+ if ($taxableAmount && !$applyTaxAfterDiscount) {
+ $taxableAmount = $rowTotalForTaxCalculation;
+ }
$rowTaxAfterDiscount = $this->calculationTool->calcTaxAmount(
$taxableAmount,
$taxRate,
@@ -168,6 +175,26 @@ protected function calculateWithTaxNotInPrice(QuoteDetailsItemInterface $item, $
->setAppliedTaxes($appliedTaxes);
}
+ /**
+ * Get price for tax calculation.
+ *
+ * @param QuoteDetailsItemInterface $item
+ * @param float $price
+ * @return float
+ */
+ private function getPriceForTaxCalculation(QuoteDetailsItemInterface $item, float $price)
+ {
+ if ($item->getExtensionAttributes() && $item->getExtensionAttributes()->getPriceForTaxCalculation()) {
+ $priceForTaxCalculation = $this->calculationTool->round(
+ $item->getExtensionAttributes()->getPriceForTaxCalculation()
+ );
+ } else {
+ $priceForTaxCalculation = $price;
+ }
+
+ return $priceForTaxCalculation;
+ }
+
/**
* Round amount
*
diff --git a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php
index 0901e1b7bc78c..bff489ee50c2f 100644
--- a/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php
+++ b/app/code/Magento/Tax/Model/Sales/Total/Quote/CommonTaxCollector.php
@@ -15,12 +15,17 @@
use Magento\Quote\Model\Quote\Item\AbstractItem;
use Magento\Store\Model\Store;
use Magento\Tax\Api\Data\QuoteDetailsInterfaceFactory;
+use Magento\Tax\Api\Data\QuoteDetailsItemInterface;
use Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory;
use Magento\Tax\Api\Data\TaxClassKeyInterface;
use Magento\Tax\Api\Data\TaxDetailsInterface;
use Magento\Tax\Api\Data\TaxDetailsItemInterface;
use Magento\Tax\Api\Data\QuoteDetailsInterface;
use Magento\Quote\Api\Data\ShippingAssignmentInterface;
+use Magento\Tax\Helper\Data as TaxHelper;
+use Magento\Framework\App\ObjectManager;
+use Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterface;
+use Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterfaceFactory;
/**
* Tax totals calculation model
@@ -129,6 +134,16 @@ class CommonTaxCollector extends AbstractTotal
*/
protected $quoteDetailsItemDataObjectFactory;
+ /**
+ * @var TaxHelper
+ */
+ private $taxHelper;
+
+ /**
+ * @var QuoteDetailsItemExtensionInterfaceFactory
+ */
+ private $quoteDetailsItemExtensionFactory;
+
/**
* Class constructor
*
@@ -139,6 +154,8 @@ class CommonTaxCollector extends AbstractTotal
* @param \Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory
* @param CustomerAddressFactory $customerAddressFactory
* @param CustomerAddressRegionFactory $customerAddressRegionFactory
+ * @param TaxHelper|null $taxHelper
+ * @param QuoteDetailsItemExtensionInterfaceFactory|null $quoteDetailsItemExtensionInterfaceFactory
*/
public function __construct(
\Magento\Tax\Model\Config $taxConfig,
@@ -147,7 +164,9 @@ public function __construct(
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $quoteDetailsItemDataObjectFactory,
\Magento\Tax\Api\Data\TaxClassKeyInterfaceFactory $taxClassKeyDataObjectFactory,
CustomerAddressFactory $customerAddressFactory,
- CustomerAddressRegionFactory $customerAddressRegionFactory
+ CustomerAddressRegionFactory $customerAddressRegionFactory,
+ TaxHelper $taxHelper = null,
+ QuoteDetailsItemExtensionInterfaceFactory $quoteDetailsItemExtensionInterfaceFactory = null
) {
$this->taxCalculationService = $taxCalculationService;
$this->quoteDetailsDataObjectFactory = $quoteDetailsDataObjectFactory;
@@ -156,6 +175,9 @@ public function __construct(
$this->quoteDetailsItemDataObjectFactory = $quoteDetailsItemDataObjectFactory;
$this->customerAddressFactory = $customerAddressFactory;
$this->customerAddressRegionFactory = $customerAddressRegionFactory;
+ $this->taxHelper = $taxHelper ?: ObjectManager::getInstance()->get(TaxHelper::class);
+ $this->quoteDetailsItemExtensionFactory = $quoteDetailsItemExtensionInterfaceFactory ?:
+ ObjectManager::getInstance()->get(QuoteDetailsItemExtensionInterfaceFactory::class);
}
/**
@@ -186,7 +208,7 @@ public function mapAddress(QuoteAddress $address)
* @param bool $priceIncludesTax
* @param bool $useBaseCurrency
* @param string $parentCode
- * @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface
+ * @return QuoteDetailsItemInterface
*/
public function mapItem(
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
@@ -199,7 +221,7 @@ public function mapItem(
$sequence = 'sequence-' . $this->getNextIncrement();
$item->setTaxCalculationItemId($sequence);
}
- /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
+ /** @var QuoteDetailsItemInterface $itemDataObject */
$itemDataObject = $itemDataObjectFactory->create();
$itemDataObject->setCode($item->getTaxCalculationItemId())
->setQuantity($item->getQty())
@@ -215,12 +237,28 @@ public function mapItem(
if (!$item->getBaseTaxCalculationPrice()) {
$item->setBaseTaxCalculationPrice($item->getBaseCalculationPriceOriginal());
}
+
+ if ($this->taxHelper->applyTaxOnOriginalPrice()) {
+ $baseTaxCalculationPrice = $item->getBaseOriginalPrice();
+ } else {
+ $baseTaxCalculationPrice = $item->getBaseCalculationPriceOriginal();
+ }
+ $this->setPriceForTaxCalculation($itemDataObject, (float)$baseTaxCalculationPrice);
+
$itemDataObject->setUnitPrice($item->getBaseTaxCalculationPrice())
->setDiscountAmount($item->getBaseDiscountAmount());
} else {
if (!$item->getTaxCalculationPrice()) {
$item->setTaxCalculationPrice($item->getCalculationPriceOriginal());
}
+
+ if ($this->taxHelper->applyTaxOnOriginalPrice()) {
+ $taxCalculationPrice = $item->getOriginalPrice();
+ } else {
+ $taxCalculationPrice = $item->getCalculationPriceOriginal();
+ }
+ $this->setPriceForTaxCalculation($itemDataObject, (float)$taxCalculationPrice);
+
$itemDataObject->setUnitPrice($item->getTaxCalculationPrice())
->setDiscountAmount($item->getDiscountAmount());
}
@@ -230,6 +268,23 @@ public function mapItem(
return $itemDataObject;
}
+ /**
+ * Set price for tax calculation.
+ *
+ * @param QuoteDetailsItemInterface $quoteDetailsItem
+ * @param float $taxCalculationPrice
+ * @return void
+ */
+ private function setPriceForTaxCalculation(QuoteDetailsItemInterface $quoteDetailsItem, float $taxCalculationPrice)
+ {
+ $extensionAttributes = $quoteDetailsItem->getExtensionAttributes();
+ if (!$extensionAttributes) {
+ $extensionAttributes = $this->quoteDetailsItemExtensionFactory->create();
+ }
+ $extensionAttributes->setPriceForTaxCalculation($taxCalculationPrice);
+ $quoteDetailsItem->setExtensionAttributes($extensionAttributes);
+ }
+
/**
* Map item extra taxables
*
@@ -237,7 +292,7 @@ public function mapItem(
* @param AbstractItem $item
* @param bool $priceIncludesTax
* @param bool $useBaseCurrency
- * @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface[]
+ * @return QuoteDetailsItemInterface[]
*/
public function mapItemExtraTaxables(
\Magento\Tax\Api\Data\QuoteDetailsItemInterfaceFactory $itemDataObjectFactory,
@@ -260,7 +315,7 @@ public function mapItemExtraTaxables(
} else {
$unitPrice = $extraTaxable[self::KEY_ASSOCIATED_TAXABLE_UNIT_PRICE];
}
- /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
+ /** @var QuoteDetailsItemInterface $itemDataObject */
$itemDataObject = $itemDataObjectFactory->create();
$itemDataObject->setCode($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_CODE])
->setType($extraTaxable[self::KEY_ASSOCIATED_TAXABLE_TYPE])
@@ -283,9 +338,9 @@ public function mapItemExtraTaxables(
* Add quote items
*
* @param ShippingAssignmentInterface $shippingAssignment
- * @param bool $useBaseCurrency
* @param bool $priceIncludesTax
- * @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface[]
+ * @param bool $useBaseCurrency
+ * @return QuoteDetailsItemInterface[]
*/
public function mapItems(
ShippingAssignmentInterface $shippingAssignment,
@@ -361,10 +416,12 @@ public function populateAddressData(QuoteDetailsInterface $quoteDetails, QuoteAd
}
/**
+ * Get shipping data object.
+ *
* @param ShippingAssignmentInterface $shippingAssignment
* @param QuoteAddress\Total $total
* @param bool $useBaseCurrency
- * @return \Magento\Tax\Api\Data\QuoteDetailsItemInterface
+ * @return QuoteDetailsItemInterface
*/
public function getShippingDataObject(
ShippingAssignmentInterface $shippingAssignment,
@@ -379,7 +436,7 @@ public function getShippingDataObject(
$total->setBaseShippingTaxCalculationAmount($total->getBaseShippingAmount());
}
if ($total->getShippingTaxCalculationAmount() !== null) {
- /** @var \Magento\Tax\Api\Data\QuoteDetailsItemInterface $itemDataObject */
+ /** @var QuoteDetailsItemInterface $itemDataObject */
$itemDataObject = $this->quoteDetailsItemDataObjectFactory->create()
->setType(self::ITEM_TYPE_SHIPPING)
->setCode(self::ITEM_CODE_SHIPPING)
@@ -414,7 +471,7 @@ public function getShippingDataObject(
* Populate QuoteDetails object from quote address object
*
* @param ShippingAssignmentInterface $shippingAssignment
- * @param \Magento\Tax\Api\Data\QuoteDetailsItemInterface[] $itemDataObjects
+ * @param QuoteDetailsItemInterface[] $itemDataObjects
* @return \Magento\Tax\Api\Data\QuoteDetailsInterface
*/
protected function prepareQuoteDetails(ShippingAssignmentInterface $shippingAssignment, $itemDataObjects)
@@ -543,6 +600,7 @@ protected function processProductItems(
* Process applied taxes for items and quote
*
* @param QuoteAddress\Total $total
+ * @param ShippingAssignmentInterface $shippingAssignment
* @param array $itemsByType
* @return $this
*/
@@ -846,8 +904,9 @@ protected function saveAppliedTaxes()
}
/**
- * Increment and return counter. This function is intended to be used to generate temporary
- * id for an item.
+ * Increment and return counter.
+ *
+ * This function is intended to be used to generate temporary id for an item.
*
* @return int
*/
diff --git a/app/code/Magento/Tax/Test/Mftf/Data/TaxRateData.xml b/app/code/Magento/Tax/Test/Mftf/Data/TaxRateData.xml
index 887203a76fdad..4409ea0a21df6 100644
--- a/app/code/Magento/Tax/Test/Mftf/Data/TaxRateData.xml
+++ b/app/code/Magento/Tax/Test/Mftf/Data/TaxRateData.xml
@@ -106,4 +106,8 @@
0
0.1
+
+ 51
+ 6
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontCreateNewReturnPage.xml b/app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRatePage.xml
similarity index 63%
rename from app/code/Magento/Sales/Test/Mftf/Page/StorefrontCreateNewReturnPage.xml
rename to app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRatePage.xml
index 2a14f814eac16..26152d5497a98 100644
--- a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontCreateNewReturnPage.xml
+++ b/app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRatePage.xml
@@ -8,7 +8,7 @@
-
-
+
+
diff --git a/app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRulePage.xml b/app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRulePage.xml
new file mode 100644
index 0000000000000..c0e4958619c89
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Mftf/Page/AdminEditTaxRulePage.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Tax/Test/Mftf/Section/AdminConfigureTaxSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/AdminConfigureTaxSection.xml
index bfb082c145f07..e69bfbaebbfd9 100644
--- a/app/code/Magento/Tax/Test/Mftf/Section/AdminConfigureTaxSection.xml
+++ b/app/code/Magento/Tax/Test/Mftf/Section/AdminConfigureTaxSection.xml
@@ -28,6 +28,8 @@
+
+
diff --git a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml
index 29c53242b90f6..46d92e30395e0 100644
--- a/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml
+++ b/app/code/Magento/Tax/Test/Mftf/Section/AdminTaxRulesSection.xml
@@ -33,5 +33,6 @@
+
diff --git a/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml
new file mode 100644
index 0000000000000..732470d2558c7
--- /dev/null
+++ b/app/code/Magento/Tax/Test/Mftf/Test/AdminTaxCalcWithApplyTaxOnSettingTest.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php
index cbd7ed46e38d7..2a7eeb27ee07e 100644
--- a/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php
+++ b/app/code/Magento/Tax/Test/Unit/Model/Calculation/RowBaseAndTotalBaseCalculatorTestCase.php
@@ -9,6 +9,7 @@
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Tax\Model\Calculation\RowBaseCalculator;
use Magento\Tax\Model\Calculation\TotalBaseCalculator;
+use Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterface;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -66,6 +67,11 @@ class RowBaseAndTotalBaseCalculatorTestCase extends \PHPUnit\Framework\TestCase
*/
protected $taxDetailsItem;
+ /**
+ * @var \Magento\Tax\Api\Data\QuoteDetailsItemExtensionInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $quoteDetailsItemExtension;
+
/**
* initialize all mocks
*
@@ -101,7 +107,14 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
- $this->mockItem = $this->getMockBuilder(\Magento\Tax\Api\Data\QuoteDetailsItemInterface::class)->getMock();
+ $this->mockItem = $this->getMockBuilder(\Magento\Tax\Api\Data\QuoteDetailsItemInterface::class)
+ ->disableOriginalConstructor()->setMethods(['getExtensionAttributes', 'getUnitPrice'])
+ ->getMockForAbstractClass();
+ $this->quoteDetailsItemExtension = $this->getMockBuilder(QuoteDetailsItemExtensionInterface::class)
+ ->disableOriginalConstructor()->setMethods(['getPriceForTaxCalculation'])
+ ->getMockForAbstractClass();
+ $this->mockItem->expects($this->any())->method('getExtensionAttributes')
+ ->willReturn($this->quoteDetailsItemExtension);
$this->appliedTaxDataObjectFactory = $this->createPartialMock(
\Magento\Tax\Api\Data\AppliedTaxInterfaceFactory::class,
diff --git a/app/code/Magento/Tax/etc/extension_attributes.xml b/app/code/Magento/Tax/etc/extension_attributes.xml
index 90a5e6d2ecee3..41af1df836d6f 100644
--- a/app/code/Magento/Tax/etc/extension_attributes.xml
+++ b/app/code/Magento/Tax/etc/extension_attributes.xml
@@ -20,4 +20,7 @@
+
+
+
diff --git a/app/code/Magento/Tax/etc/sales.xml b/app/code/Magento/Tax/etc/sales.xml
index 64d29ece898de..15afd499bce3f 100644
--- a/app/code/Magento/Tax/etc/sales.xml
+++ b/app/code/Magento/Tax/etc/sales.xml
@@ -9,7 +9,7 @@
-
+
-
diff --git a/app/code/Magento/Translation/Model/Json/PreProcessor.php b/app/code/Magento/Translation/Model/Json/PreProcessor.php
index 5d46c3c8b0618..c178a324cb40b 100644
--- a/app/code/Magento/Translation/Model/Json/PreProcessor.php
+++ b/app/code/Magento/Translation/Model/Json/PreProcessor.php
@@ -6,6 +6,7 @@
namespace Magento\Translation\Model\Json;
+use Magento\Framework\App\Area;
use Magento\Framework\App\AreaList;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\TranslateInterface;
@@ -13,6 +14,7 @@
use Magento\Framework\View\Asset\PreProcessor\Chain;
use Magento\Framework\View\Asset\PreProcessorInterface;
use Magento\Framework\View\DesignInterface;
+use Magento\Backend\App\Area\FrontNameResolver;
use Magento\Translation\Model\Js\Config;
use Magento\Translation\Model\Js\DataProviderInterface;
@@ -83,7 +85,7 @@ public function process(Chain $chain)
$context = $chain->getAsset()->getContext();
$themePath = '*/*';
- $areaCode = \Magento\Backend\App\Area\FrontNameResolver::AREA_CODE;
+ $areaCode = FrontNameResolver::AREA_CODE;
if ($context instanceof FallbackContext) {
$themePath = $context->getThemePath();
@@ -92,8 +94,10 @@ public function process(Chain $chain)
$this->viewDesign->setDesignTheme($themePath, $areaCode);
}
- $area = $this->areaList->getArea($areaCode);
- $area->load(\Magento\Framework\App\Area::PART_TRANSLATE);
+ if ($areaCode !== FrontNameResolver::AREA_CODE) {
+ $area = $this->areaList->getArea($areaCode);
+ $area->load(Area::PART_TRANSLATE);
+ }
$this->translate->setLocale($context->getLocale())->loadData($areaCode, true);
diff --git a/app/code/Magento/Translation/Test/Unit/Model/Json/PreProcessorTest.php b/app/code/Magento/Translation/Test/Unit/Model/Json/PreProcessorTest.php
index d9340e03dc996..cbeeefed6be6e 100644
--- a/app/code/Magento/Translation/Test/Unit/Model/Json/PreProcessorTest.php
+++ b/app/code/Magento/Translation/Test/Unit/Model/Json/PreProcessorTest.php
@@ -8,39 +8,43 @@
use Magento\Translation\Model\Js\Config;
use Magento\Translation\Model\Js\DataProvider;
use Magento\Translation\Model\Json\PreProcessor;
+use Magento\Backend\App\Area\FrontNameResolver;
class PreProcessorTest extends \PHPUnit\Framework\TestCase
{
/**
* @var PreProcessor
*/
- protected $model;
+ private $model;
/**
* @var Config|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $configMock;
+ private $configMock;
/**
* @var DataProvider|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $dataProviderMock;
+ private $dataProviderMock;
/**
* @var \Magento\Framework\App\AreaList|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $areaListMock;
+ private $areaListMock;
/**
* @var \Magento\Framework\TranslateInterface|\PHPUnit_Framework_MockObject_MockObject
*/
- protected $translateMock;
+ private $translateMock;
/**
* @var \Magento\Framework\View\DesignInterface|\PHPUnit_Framework_MockObject_MockObject
*/
private $designMock;
+ /**
+ * @inheritdoc
+ */
protected function setUp()
{
$this->configMock = $this->createMock(\Magento\Translation\Model\Js\Config::class);
@@ -57,7 +61,14 @@ protected function setUp()
);
}
- public function testGetData()
+ /**
+ * Test 'process' method.
+ *
+ * @param array $data
+ * @param array $expects
+ * @dataProvider processDataProvider
+ */
+ public function testProcess(array $data, array $expects)
{
$chain = $this->createMock(\Magento\Framework\View\Asset\PreProcessor\Chain::class);
$asset = $this->createMock(\Magento\Framework\View\Asset\File::class);
@@ -66,8 +77,10 @@ public function testGetData()
$targetPath = 'path/js-translation.json';
$themePath = '*/*';
$dictionary = ['hello' => 'bonjour'];
- $areaCode = 'adminhtml';
+ $areaCode = $data['area_code'];
+
$area = $this->createMock(\Magento\Framework\App\Area::class);
+ $area->expects($expects['area_load'])->method('load')->willReturnSelf();
$chain->expects($this->once())
->method('getTargetAssetPath')
@@ -93,7 +106,7 @@ public function testGetData()
$this->designMock->expects($this->once())->method('setDesignTheme')->with($themePath, $areaCode);
- $this->areaListMock->expects($this->once())
+ $this->areaListMock->expects($expects['areaList_getArea'])
->method('getArea')
->with($areaCode)
->willReturn($area);
@@ -114,4 +127,33 @@ public function testGetData()
$this->model->process($chain);
}
+
+ /**
+ * Data provider for 'process' method test.
+ *
+ * @return array
+ */
+ public function processDataProvider()
+ {
+ return [
+ [
+ [
+ 'area_code' => FrontNameResolver::AREA_CODE
+ ],
+ [
+ 'areaList_getArea' => $this->never(),
+ 'area_load' => $this->never(),
+ ]
+ ],
+ [
+ [
+ 'area_code' => 'frontend'
+ ],
+ [
+ 'areaList_getArea' => $this->once(),
+ 'area_load' => $this->once(),
+ ]
+ ],
+ ];
+ }
}
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
index c335b66505b0e..f3be684f93a4d 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductCustomOptionRepositoryTest.php
@@ -146,6 +146,10 @@ public function testGetList()
public function testSave($optionData)
{
$productSku = 'simple';
+ /** @var \Magento\Catalog\Model\ProductRepository $productRepository */
+ $productRepository = $this->objectManager->create(
+ \Magento\Catalog\Model\ProductRepository::class
+ );
$optionDataPost = $optionData;
$optionDataPost['product_sku'] = $productSku;
@@ -162,6 +166,7 @@ public function testSave($optionData)
];
$result = $this->_webApiCall($serviceInfo, ['option' => $optionDataPost]);
+ $product = $productRepository->get($productSku);
unset($result['product_sku']);
unset($result['option_id']);
if (!empty($result['values'])) {
@@ -169,7 +174,12 @@ public function testSave($optionData)
unset($result['values'][$key]['option_type_id']);
}
}
+
$this->assertEquals($optionData, $result);
+ $this->assertTrue($product->getHasOptions() == 1);
+ if ($optionDataPost['is_require']) {
+ $this->assertTrue($product->getRequiredOptions() == 1);
+ }
}
public function optionDataProvider()
diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
index a001cae645434..a3ded4f5f125c 100644
--- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php
@@ -12,6 +12,8 @@
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\TestFramework\ObjectManager;
use Magento\TestFramework\TestCase\WebapiAbstract;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\Quote\Address;
class CartTotalRepositoryTest extends WebapiAbstract
{
@@ -54,36 +56,11 @@ public function testGetTotals()
/** @var \Magento\Quote\Model\Quote\Address $shippingAddress */
$shippingAddress = $quote->getShippingAddress();
- $data = [
- Totals::KEY_GRAND_TOTAL => $quote->getGrandTotal(),
- Totals::KEY_BASE_GRAND_TOTAL => $quote->getBaseGrandTotal(),
- Totals::KEY_SUBTOTAL => $quote->getSubtotal(),
- Totals::KEY_BASE_SUBTOTAL => $quote->getBaseSubtotal(),
- Totals::KEY_DISCOUNT_AMOUNT => $shippingAddress->getDiscountAmount(),
- Totals::KEY_BASE_DISCOUNT_AMOUNT => $shippingAddress->getBaseDiscountAmount(),
- Totals::KEY_SUBTOTAL_WITH_DISCOUNT => $quote->getSubtotalWithDiscount(),
- Totals::KEY_BASE_SUBTOTAL_WITH_DISCOUNT => $quote->getBaseSubtotalWithDiscount(),
- Totals::KEY_SHIPPING_AMOUNT => $shippingAddress->getShippingAmount(),
- Totals::KEY_BASE_SHIPPING_AMOUNT => $shippingAddress->getBaseShippingAmount(),
- Totals::KEY_SHIPPING_DISCOUNT_AMOUNT => $shippingAddress->getShippingDiscountAmount(),
- Totals::KEY_BASE_SHIPPING_DISCOUNT_AMOUNT => $shippingAddress->getBaseShippingDiscountAmount(),
- Totals::KEY_TAX_AMOUNT => $shippingAddress->getTaxAmount(),
- Totals::KEY_BASE_TAX_AMOUNT => $shippingAddress->getBaseTaxAmount(),
- Totals::KEY_SHIPPING_TAX_AMOUNT => $shippingAddress->getShippingTaxAmount(),
- Totals::KEY_BASE_SHIPPING_TAX_AMOUNT => $shippingAddress->getBaseShippingTaxAmount(),
- Totals::KEY_SUBTOTAL_INCL_TAX => $shippingAddress->getSubtotalInclTax(),
- Totals::KEY_BASE_SUBTOTAL_INCL_TAX => $shippingAddress->getBaseSubtotalTotalInclTax(),
- Totals::KEY_SHIPPING_INCL_TAX => $shippingAddress->getShippingInclTax(),
- Totals::KEY_BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(),
- Totals::KEY_BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(),
- Totals::KEY_QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(),
- Totals::KEY_ITEMS_QTY => $quote->getItemsQty(),
- Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)],
- ];
+ $data = $this->getData($quote, $shippingAddress);
+ $data = $this->formatTotalsData($data);
$requestData = ['cartId' => $cartId];
- $data = $this->formatTotalsData($data);
$actual = $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData);
unset($actual['items'][0]['options']);
unset($actual['weee_tax_applied_amount']);
@@ -213,7 +190,32 @@ public function testGetMyTotals()
/** @var \Magento\Quote\Model\Quote\Address $shippingAddress */
$shippingAddress = $quote->getShippingAddress();
- $data = [
+ $data = $this->getData($quote, $shippingAddress);
+ $data = $this->formatTotalsData($data);
+
+ $actual = $this->_webApiCall($serviceInfo);
+ unset($actual['items'][0]['options']);
+ unset($actual['weee_tax_applied_amount']);
+
+ /** TODO: cover total segments with separate test */
+ unset($actual['total_segments']);
+ if (array_key_exists('extension_attributes', $actual)) {
+ unset($actual['extension_attributes']);
+ }
+ $this->assertEquals($data, $actual);
+ }
+
+ /**
+ * Get expected data.
+ *
+ * @param Quote $quote
+ * @param Address $shippingAddress
+ *
+ * @return array
+ */
+ private function getData(Quote $quote, Address $shippingAddress) : array
+ {
+ return [
Totals::KEY_GRAND_TOTAL => $quote->getGrandTotal(),
Totals::KEY_BASE_GRAND_TOTAL => $quote->getBaseGrandTotal(),
Totals::KEY_SUBTOTAL => $quote->getSubtotal(),
@@ -239,17 +241,5 @@ public function testGetMyTotals()
Totals::KEY_ITEMS_QTY => $quote->getItemsQty(),
Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)],
];
-
- $data = $this->formatTotalsData($data);
- $actual = $this->_webApiCall($serviceInfo);
- unset($actual['items'][0]['options']);
- unset($actual['weee_tax_applied_amount']);
-
- /** TODO: cover total segments with separate test */
- unset($actual['total_segments']);
- if (array_key_exists('extension_attributes', $actual)) {
- unset($actual['extension_attributes']);
- }
- $this->assertEquals($data, $actual);
}
}
diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartTotalRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartTotalRepositoryTest.php
index 7ad0e62f29dc3..28195cca679f8 100644
--- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartTotalRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/GuestCartTotalRepositoryTest.php
@@ -63,14 +63,14 @@ public function testGetTotals()
$shippingAddress = $quote->getShippingAddress();
$data = [
- Totals::KEY_BASE_GRAND_TOTAL => $quote->getBaseGrandTotal(),
Totals::KEY_GRAND_TOTAL => $quote->getGrandTotal(),
- Totals::KEY_BASE_SUBTOTAL => $quote->getBaseSubtotal(),
+ Totals::KEY_BASE_GRAND_TOTAL => $quote->getBaseGrandTotal(),
Totals::KEY_SUBTOTAL => $quote->getSubtotal(),
- Totals::KEY_BASE_SUBTOTAL_WITH_DISCOUNT => $quote->getBaseSubtotalWithDiscount(),
- Totals::KEY_SUBTOTAL_WITH_DISCOUNT => $quote->getSubtotalWithDiscount(),
+ Totals::KEY_BASE_SUBTOTAL => $quote->getBaseSubtotal(),
Totals::KEY_DISCOUNT_AMOUNT => $shippingAddress->getDiscountAmount(),
Totals::KEY_BASE_DISCOUNT_AMOUNT => $shippingAddress->getBaseDiscountAmount(),
+ Totals::KEY_SUBTOTAL_WITH_DISCOUNT => $quote->getSubtotalWithDiscount(),
+ Totals::KEY_BASE_SUBTOTAL_WITH_DISCOUNT => $quote->getBaseSubtotalWithDiscount(),
Totals::KEY_SHIPPING_AMOUNT => $shippingAddress->getShippingAmount(),
Totals::KEY_BASE_SHIPPING_AMOUNT => $shippingAddress->getBaseShippingAmount(),
Totals::KEY_SHIPPING_DISCOUNT_AMOUNT => $shippingAddress->getShippingDiscountAmount(),
@@ -94,6 +94,7 @@ public function testGetTotals()
$data = $this->formatTotalsData($data);
$actual = $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData);
+ $actual = $this->formatTotalsData($actual);
unset($actual['items'][0]['options']);
unset($actual['weee_tax_applied_amount']);
diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php
index 9b12c467e5775..4d6d06ac6e625 100644
--- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php
+++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php
@@ -46,7 +46,7 @@ public function getData($key = null)
$optionData = [
'title' => $checkoutOption['title'],
'value' => "{$qty} x {$value} {$price}",
- 'sku' => "{$qty} x {$value}"
+ 'sku' => "{$value}"
];
$checkoutBundleOptions[$checkoutOptionKey] = $optionData;
diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method.php
index 3c54fe16db7d3..61779da29c65f 100644
--- a/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method.php
+++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/quote_with_shipping_method.php
@@ -11,10 +11,18 @@
require 'quote_with_address_saved.php';
+$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+$rate = $objectManager->get(\Magento\Quote\Model\Quote\Address\Rate::class);
+
$quote->load('test_order_1', 'reserved_order_id');
$shippingAddress = $quote->getShippingAddress();
$shippingAddress->setShippingMethod('flatrate_flatrate')
->setShippingDescription('Flat Rate - Fixed')
- ->setShippingAmount(10.0)
- ->setBaseShippingAmount(12.0)
->save();
+
+$rate->setPrice(0)
+ ->setAddressId($shippingAddress->getId())
+ ->save();
+$shippingAddress->setBaseShippingAmount($rate->getPrice());
+$shippingAddress->setShippingAmount($rate->getPrice());
+$rate->delete();
diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php
index 16a15cfcd2e26..384892d6fd5d2 100644
--- a/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php
+++ b/dev/tests/integration/testsuite/Magento/GraphQl/Controller/GraphQlControllerTest.php
@@ -116,7 +116,6 @@ public function testDispatch() : void
*/
public function testError() : void
{
- $this->markTestSkipped('Causes failiure with php unit and php 7.2');
$query
= <<toArray(
$this->exceptionFormatter->shouldShowDetail() ?
- \GraphQL\Error\Debug::INCLUDE_DEBUG_MESSAGE | \GraphQL\Error\Debug::INCLUDE_TRACE : false
+ \GraphQL\Error\Debug::INCLUDE_DEBUG_MESSAGE : false
);
}
}
| |