Skip to content

Commit bdb10fb

Browse files
author
Alexey Yakimovich
committed
MC-10971: [Magento Cloud] - Unable to Scope Catalog Price rules by custom product attribute
- Added possibility to use 'is undefined' filter in rule conditions;
1 parent 9c36f6f commit bdb10fb

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

app/code/Magento/Catalog/Model/Api/SearchCriteria/CollectionProcessor/ConditionProcessor/ConditionBuilder/EavAttributeCondition.php

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,38 @@ public function build(Filter $filter): string
5858
$conditionValue = $this->mapConditionValue($conditionType, $filter->getValue());
5959

6060
// NOTE: store scope was ignored intentionally to perform search across all stores
61-
$attributeSelect = $this->resourceConnection->getConnection()
62-
->select()
63-
->from(
64-
[$tableAlias => $attribute->getBackendTable()],
65-
$tableAlias . '.' . $attribute->getEntityIdField()
66-
)->where(
67-
$this->resourceConnection->getConnection()->prepareSqlCondition(
68-
$tableAlias . '.' . $attribute->getIdFieldName(),
69-
['eq' => $attribute->getAttributeId()]
70-
)
71-
)->where(
72-
$this->resourceConnection->getConnection()->prepareSqlCondition(
73-
$tableAlias . '.value',
74-
[$conditionType => $conditionValue]
75-
)
76-
);
61+
if ($conditionType == 'is_null') {
62+
$entityResourceModel = $attribute->getEntity();
63+
$attributeSelect = $this->resourceConnection->getConnection()
64+
->select()
65+
->from(
66+
[Collection::MAIN_TABLE_ALIAS => $entityResourceModel->getEntityTable()],
67+
Collection::MAIN_TABLE_ALIAS . '.' . $entityResourceModel->getEntityIdField()
68+
)->joinLeft(
69+
[$tableAlias => $attribute->getBackendTable()],
70+
$tableAlias . '.' . $attribute->getEntityIdField() . '=' . Collection::MAIN_TABLE_ALIAS .
71+
'.' . $entityResourceModel->getEntityIdField() . ' AND ' . $tableAlias . '.' .
72+
$attribute->getIdFieldName() . '=' . $attribute->getAttributeId(),
73+
''
74+
)->where($tableAlias . '.value is null');
75+
} else {
76+
$attributeSelect = $this->resourceConnection->getConnection()
77+
->select()
78+
->from(
79+
[$tableAlias => $attribute->getBackendTable()],
80+
$tableAlias . '.' . $attribute->getEntityIdField()
81+
)->where(
82+
$this->resourceConnection->getConnection()->prepareSqlCondition(
83+
$tableAlias . '.' . $attribute->getIdFieldName(),
84+
['eq' => $attribute->getAttributeId()]
85+
)
86+
)->where(
87+
$this->resourceConnection->getConnection()->prepareSqlCondition(
88+
$tableAlias . '.value',
89+
[$conditionType => $conditionValue]
90+
)
91+
);
92+
}
7793

7894
return $this->resourceConnection
7995
->getConnection()
@@ -86,6 +102,8 @@ public function build(Filter $filter): string
86102
}
87103

88104
/**
105+
* Get attribute entity by its code
106+
*
89107
* @param string $field
90108
* @return Attribute
91109
* @throws \Magento\Framework\Exception\LocalizedException

app/code/Magento/CatalogRule/Model/Rule/Condition/ConditionsToSearchCriteriaMapper.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public function mapConditionsToSearchCriteria(CombinedCondition $conditions): Se
7171
}
7272

7373
/**
74+
* Convert condition to filter group
75+
*
7476
* @param ConditionInterface $condition
7577
* @return null|\Magento\Framework\Api\CombinedFilterGroup|\Magento\Framework\Api\Filter
7678
* @throws InputException
@@ -89,6 +91,8 @@ private function mapConditionToFilterGroup(ConditionInterface $condition)
8991
}
9092

9193
/**
94+
* Convert combined condition to filter group
95+
*
9296
* @param Combine $combinedCondition
9397
* @return null|\Magento\Framework\Api\CombinedFilterGroup
9498
* @throws InputException
@@ -121,6 +125,8 @@ private function mapCombinedConditionToFilterGroup(CombinedCondition $combinedCo
121125
}
122126

123127
/**
128+
* Convert simple condition to filter group
129+
*
124130
* @param ConditionInterface $productCondition
125131
* @return FilterGroup|Filter
126132
* @throws InputException
@@ -139,6 +145,8 @@ private function mapSimpleConditionToFilterGroup(ConditionInterface $productCond
139145
}
140146

141147
/**
148+
* Convert simple condition with array value to filter group
149+
*
142150
* @param ConditionInterface $productCondition
143151
* @return FilterGroup
144152
* @throws InputException
@@ -161,6 +169,8 @@ private function processSimpleConditionWithArrayValue(ConditionInterface $produc
161169
}
162170

163171
/**
172+
* Get glue for multiple values by operator
173+
*
164174
* @param string $operator
165175
* @return string
166176
*/
@@ -211,6 +221,8 @@ private function reverseSqlOperatorInFilter(Filter $filter)
211221
}
212222

213223
/**
224+
* Convert filters array into combined filter group
225+
*
214226
* @param array $filters
215227
* @param string $combinationMode
216228
* @return FilterGroup
@@ -227,6 +239,8 @@ private function createCombinedFilterGroup(array $filters, string $combinationMo
227239
}
228240

229241
/**
242+
* Creating of filter object by filtering params
243+
*
230244
* @param string $field
231245
* @param string $value
232246
* @param string $conditionType
@@ -264,6 +278,7 @@ private function mapRuleOperatorToSQLCondition(string $ruleOperator): string
264278
'!{}' => 'nlike', // does not contains
265279
'()' => 'in', // is one of
266280
'!()' => 'nin', // is not one of
281+
'<=>' => 'is_null'
267282
];
268283

269284
if (!array_key_exists($ruleOperator, $operatorsMap)) {

app/code/Magento/CatalogRule/Model/Rule/Condition/Product.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
* See COPYING.txt for license details.
55
*/
66

7-
/**
8-
* Catalog Rule Product Condition data model
9-
*/
107
namespace Magento\CatalogRule\Model\Rule\Condition;
118

129
/**
10+
* Catalog Rule Product Condition data model
11+
*
1312
* @method string getAttribute() Returns attribute code
1413
*/
1514
class Product extends \Magento\Rule\Model\Condition\Product\AbstractProduct
@@ -29,6 +28,9 @@ public function validate(\Magento\Framework\Model\AbstractModel $model)
2928

3029
$oldAttrValue = $model->getData($attrCode);
3130
if ($oldAttrValue === null) {
31+
if ($this->getOperator() === '<=>') {
32+
return true;
33+
}
3234
return false;
3335
}
3436

app/code/Magento/Rule/Model/Condition/AbstractCondition.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ public function getDefaultOperatorInputByType()
106106
'string' => ['==', '!=', '>=', '>', '<=', '<', '{}', '!{}', '()', '!()'],
107107
'numeric' => ['==', '!=', '>=', '>', '<=', '<', '()', '!()'],
108108
'date' => ['==', '>=', '<='],
109-
'select' => ['==', '!='],
110-
'boolean' => ['==', '!='],
109+
'select' => ['==', '!=', '<=>'],
110+
'boolean' => ['==', '!=', '<=>'],
111111
'multiselect' => ['{}', '!{}', '()', '!()'],
112112
'grid' => ['()', '!()'],
113113
];
@@ -137,6 +137,7 @@ public function getDefaultOperatorOptions()
137137
'!{}' => __('does not contain'),
138138
'()' => __('is one of'),
139139
'!()' => __('is not one of'),
140+
'<=>' => __('is undefined'),
140141
];
141142
}
142143
return $this->_defaultOperatorOptions;

app/code/Magento/Rule/view/adminhtml/web/rules.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ define([
101101

102102
if (!elem.multiple) {
103103
Event.observe(elem, 'change', this.hideParamInputField.bind(this, container));
104+
105+
this.changeVisibilityForValueRuleParam(elem);
106+
104107
}
105108
Event.observe(elem, 'blur', this.hideParamInputField.bind(this, container));
106109
}
@@ -262,6 +265,8 @@ define([
262265
label.innerHTML = str != '' ? str : '...';
263266
}
264267

268+
this.changeVisibilityForValueRuleParam(elem);
269+
265270
elem = Element.down(container, 'input.input-text');
266271

267272
if (elem) {
@@ -293,6 +298,23 @@ define([
293298
this.shownElement = null;
294299
},
295300

301+
changeVisibilityForValueRuleParam: function(elem) {
302+
let parsedElementId = elem.id.split('__');
303+
if (parsedElementId[2] != 'operator') {
304+
return false;
305+
}
306+
307+
let valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value');
308+
309+
if(elem.value == '<=>') {
310+
valueElement.closest('.rule-param').hide();
311+
} else {
312+
valueElement.closest('.rule-param').show();
313+
}
314+
315+
return true;
316+
},
317+
296318
addRuleNewChild: function (elem) {
297319
var parent_id = elem.id.replace(/^.*__(.*)__.*$/, '$1');
298320
var children_ul_id = elem.id.replace(/__/g, ':').replace(/[^:]*$/, 'children').replace(/:/g, '__');

0 commit comments

Comments
 (0)