Skip to content

Commit ae516e7

Browse files
Merge remote-tracking branch 'origin/MAGETWO-64047-WebAPI-Its-impossible-to-empty-numeric-fields' into Okapis-PR
2 parents 5441188 + ce84e0c commit ae516e7

File tree

6 files changed

+68
-3
lines changed

6 files changed

+68
-3
lines changed

app/code/Magento/Catalog/Model/Product/Attribute/Backend/Price.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ public function afterSave($object)
128128
$attribute = $this->getAttribute();
129129
$attributeCode = $attribute->getAttributeCode();
130130
$value = $object->getData($attributeCode);
131-
if ((float)$value > 0) {
131+
// $value may be passed as null to unset the attribute
132+
if ($value === null || (float)$value > 0) {
132133
if ($attribute->isScopeWebsite() && $object->getStoreId() != \Magento\Store\Model\Store::DEFAULT_STORE_ID) {
133134
if ($this->isUseDefault($object)) {
134135
$value = null;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Observer;
7+
8+
use Magento\Framework\Event\ObserverInterface;
9+
10+
/**
11+
* Unset value for Special Price if passed as null
12+
*/
13+
class UnsetSpecialPrice implements ObserverInterface
14+
{
15+
/**
16+
* Unset the Special Price attribute if it is null
17+
*
18+
* @param \Magento\Framework\Event\Observer $observer
19+
* @return $this
20+
*/
21+
public function execute(\Magento\Framework\Event\Observer $observer)
22+
{
23+
/** @var $product \Magento\Catalog\Model\Product */
24+
$product = $observer->getEvent()->getProduct();
25+
if ($product->getSpecialPrice() === null) {
26+
$product->setData('special_price', '');
27+
}
28+
29+
return $this;
30+
}
31+
}

app/code/Magento/Catalog/etc/events.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
</event>
5757
<event name="catalog_product_save_before">
5858
<observer name="set_special_price_start_date" instance="Magento\Catalog\Observer\SetSpecialPriceStartDate" />
59+
<observer name="unset_special_price" instance="Magento\Catalog\Observer\UnsetSpecialPrice" />
5960
</event>
6061
<event name="store_save_after">
6162
<observer name="synchronize_website_attributes" instance="Magento\Catalog\Observer\SynchronizeWebsiteAttributesOnStoreChange" />

dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductRepositoryInterfaceTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,38 @@ public function testSpecialPrice()
12651265
$this->assertEquals(2, count(array_intersect($attributeCodes, $expectedAttribute)));
12661266
}
12671267

1268+
/**
1269+
* Tests the ability to "reset" (nullify) a special_price by passing null in the web api request.
1270+
*
1271+
* Steps:
1272+
* 1. Save the product with a special_price of $5.00
1273+
* 2. Save the product with a special_price of null
1274+
* 3. Confirm that the special_price is no longer set
1275+
*/
1276+
public function testResetSpecialPrice()
1277+
{
1278+
$this->_markTestAsRestOnly(
1279+
'In order to properly run this test for SOAP, XML must be used to specify <value></value> ' .
1280+
'for the special_price value. Otherwise, the null value gets processed as a string and ' .
1281+
'cast to a double value of 0.0.'
1282+
);
1283+
$productData = $this->getSimpleProductData();
1284+
$productData['custom_attributes'] = [
1285+
['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => 5.00]
1286+
];
1287+
$this->saveProduct($productData);
1288+
$response = $this->getProduct($productData[ProductInterface::SKU]);
1289+
$customAttributes = array_column($response['custom_attributes'], 'value', 'attribute_code');
1290+
$this->assertEquals(5, $customAttributes[self::KEY_SPECIAL_PRICE]);
1291+
$productData['custom_attributes'] = [
1292+
['attribute_code' => self::KEY_SPECIAL_PRICE, 'value' => null]
1293+
];
1294+
$this->saveProduct($productData);
1295+
$response = $this->getProduct($productData[ProductInterface::SKU]);
1296+
$customAttributes = array_column($response['custom_attributes'], 'value', 'attribute_code');
1297+
$this->assertFalse(array_key_exists(self::KEY_SPECIAL_PRICE, $customAttributes));
1298+
}
1299+
12681300
public function testUpdateStatus()
12691301
{
12701302
// Create simple product

dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/CategoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public function testSaveAction($inputData, $defaultAttributes, $attributesSaved
5959
if ($exists !== $category->getExistsStoreValueFlag($attribute)) {
6060
if ($exists) {
6161
$errors[] = "custom value for '{$attribute}' attribute is not found";
62-
} else {
62+
} elseif (!$exists && $category->getCustomAttribute($attribute) !== null) {
6363
$errors[] = "custom value for '{$attribute}' attribute is found, but default one must be used";
6464
}
6565
}

dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/AbstractProductExportImportTestCase.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private function assertEqualsOtherThanSkippedAttributes($expected, $actual, $ski
155155

156156
$this->assertEquals(
157157
$value,
158-
$actual[$key],
158+
isset($actual[$key]) ? $actual[$key] : null,
159159
'Assert value at key - ' . $key . ' failed'
160160
);
161161
}

0 commit comments

Comments
 (0)