Skip to content

Commit 9f8bfc8

Browse files
authored
Merge pull request #4203 from magento-tango/PR-2019-05-13
[tango] MAGETWO-99075: Duplicate orders with same quote ID when form is submitted using Enter key
2 parents a2385d2 + e91f2ac commit 9f8bfc8

File tree

32 files changed

+1191
-506
lines changed

32 files changed

+1191
-506
lines changed

app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/cc-form.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ define(
7979
*/
8080
onError: function (response) {
8181
braintree.showError($t('Payment ' + this.getTitle() + ' can\'t be initialized'));
82-
this.isPlaceOrderActionAllowed(true);
8382
throw response.message;
8483
},
8584

app/code/Magento/Braintree/view/frontend/web/js/view/payment/method-renderer/hosted-fields.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,6 @@ define([
156156
*/
157157
placeOrderClick: function () {
158158
if (this.validateCardType() && additionalValidators.validate()) {
159-
this.isPlaceOrderActionAllowed(false);
160159
$(this.getSelector('submit')).trigger('click');
161160
}
162161
},

app/code/Magento/CatalogImportExport/Model/Import/Product.php

Lines changed: 222 additions & 157 deletions
Large diffs are not rendered by default.

app/code/Magento/CatalogRule/Model/Indexer/IndexBuilder.php

Lines changed: 116 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
namespace Magento\CatalogRule\Model\Indexer;
88

99
use Magento\Catalog\Model\Product;
10+
use Magento\CatalogRule\Model\ResourceModel\Rule\Collection as RuleCollection;
1011
use Magento\CatalogRule\Model\ResourceModel\Rule\CollectionFactory as RuleCollectionFactory;
1112
use Magento\CatalogRule\Model\Rule;
1213
use Magento\Framework\App\ObjectManager;
@@ -15,6 +16,8 @@
1516
use Magento\CatalogRule\Model\Indexer\IndexerTableSwapperInterface as TableSwapper;
1617

1718
/**
19+
* Catalog rule index builder
20+
*
1821
* @api
1922
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2023
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
@@ -270,14 +273,14 @@ public function reindexByIds(array $ids)
270273
*/
271274
protected function doReindexByIds($ids)
272275
{
273-
$this->cleanByIds($ids);
276+
$this->cleanProductIndex($ids);
274277

275278
$products = $this->productLoader->getProducts($ids);
276-
foreach ($this->getActiveRules() as $rule) {
277-
foreach ($products as $product) {
278-
$this->applyRule($rule, $product);
279-
}
279+
$activeRules = $this->getActiveRules();
280+
foreach ($products as $product) {
281+
$this->applyRules($activeRules, $product);
280282
}
283+
$this->reindexRuleGroupWebsite->execute();
281284
}
282285

283286
/**
@@ -322,6 +325,30 @@ protected function doReindexFull()
322325
);
323326
}
324327

328+
/**
329+
* Clean product index
330+
*
331+
* @param array $productIds
332+
* @return void
333+
*/
334+
private function cleanProductIndex(array $productIds): void
335+
{
336+
$where = ['product_id IN (?)' => $productIds];
337+
$this->connection->delete($this->getTable('catalogrule_product'), $where);
338+
}
339+
340+
/**
341+
* Clean product price index
342+
*
343+
* @param array $productIds
344+
* @return void
345+
*/
346+
private function cleanProductPriceIndex(array $productIds): void
347+
{
348+
$where = ['product_id IN (?)' => $productIds];
349+
$this->connection->delete($this->getTable('catalogrule_product_price'), $where);
350+
}
351+
325352
/**
326353
* Clean by product ids
327354
*
@@ -330,51 +357,35 @@ protected function doReindexFull()
330357
*/
331358
protected function cleanByIds($productIds)
332359
{
333-
$query = $this->connection->deleteFromSelect(
334-
$this->connection
335-
->select()
336-
->from($this->resource->getTableName('catalogrule_product'), 'product_id')
337-
->distinct()
338-
->where('product_id IN (?)', $productIds),
339-
$this->resource->getTableName('catalogrule_product')
340-
);
341-
$this->connection->query($query);
342-
343-
$query = $this->connection->deleteFromSelect(
344-
$this->connection->select()
345-
->from($this->resource->getTableName('catalogrule_product_price'), 'product_id')
346-
->distinct()
347-
->where('product_id IN (?)', $productIds),
348-
$this->resource->getTableName('catalogrule_product_price')
349-
);
350-
$this->connection->query($query);
360+
$this->cleanProductIndex($productIds);
361+
$this->cleanProductPriceIndex($productIds);
351362
}
352363

353364
/**
365+
* Assign product to rule
366+
*
354367
* @param Rule $rule
355368
* @param Product $product
356-
* @return $this
357-
* @throws \Exception
358-
* @SuppressWarnings(PHPMD.NPathComplexity)
369+
* @return void
359370
*/
360-
protected function applyRule(Rule $rule, $product)
371+
private function assignProductToRule(Rule $rule, Product $product): void
361372
{
362-
$ruleId = $rule->getId();
363-
$productEntityId = $product->getId();
364-
$websiteIds = array_intersect($product->getWebsiteIds(), $rule->getWebsiteIds());
365-
366373
if (!$rule->validate($product)) {
367-
return $this;
374+
return;
368375
}
369376

377+
$ruleId = (int) $rule->getId();
378+
$productEntityId = (int) $product->getId();
379+
$ruleProductTable = $this->getTable('catalogrule_product');
370380
$this->connection->delete(
371-
$this->resource->getTableName('catalogrule_product'),
381+
$ruleProductTable,
372382
[
373-
$this->connection->quoteInto('rule_id = ?', $ruleId),
374-
$this->connection->quoteInto('product_id = ?', $productEntityId)
383+
'rule_id = ?' => $ruleId,
384+
'product_id = ?' => $productEntityId,
375385
]
376386
);
377387

388+
$websiteIds = array_intersect($product->getWebsiteIds(), $rule->getWebsiteIds());
378389
$customerGroupIds = $rule->getCustomerGroupIds();
379390
$fromTime = strtotime($rule->getFromDate());
380391
$toTime = strtotime($rule->getToDate());
@@ -385,43 +396,70 @@ protected function applyRule(Rule $rule, $product)
385396
$actionStop = $rule->getStopRulesProcessing();
386397

387398
$rows = [];
388-
try {
389-
foreach ($websiteIds as $websiteId) {
390-
foreach ($customerGroupIds as $customerGroupId) {
391-
$rows[] = [
392-
'rule_id' => $ruleId,
393-
'from_time' => $fromTime,
394-
'to_time' => $toTime,
395-
'website_id' => $websiteId,
396-
'customer_group_id' => $customerGroupId,
397-
'product_id' => $productEntityId,
398-
'action_operator' => $actionOperator,
399-
'action_amount' => $actionAmount,
400-
'action_stop' => $actionStop,
401-
'sort_order' => $sortOrder,
402-
];
403-
404-
if (count($rows) == $this->batchCount) {
405-
$this->connection->insertMultiple($this->getTable('catalogrule_product'), $rows);
406-
$rows = [];
407-
}
399+
foreach ($websiteIds as $websiteId) {
400+
foreach ($customerGroupIds as $customerGroupId) {
401+
$rows[] = [
402+
'rule_id' => $ruleId,
403+
'from_time' => $fromTime,
404+
'to_time' => $toTime,
405+
'website_id' => $websiteId,
406+
'customer_group_id' => $customerGroupId,
407+
'product_id' => $productEntityId,
408+
'action_operator' => $actionOperator,
409+
'action_amount' => $actionAmount,
410+
'action_stop' => $actionStop,
411+
'sort_order' => $sortOrder,
412+
];
413+
414+
if (count($rows) == $this->batchCount) {
415+
$this->connection->insertMultiple($ruleProductTable, $rows);
416+
$rows = [];
408417
}
409418
}
410-
411-
if (!empty($rows)) {
412-
$this->connection->insertMultiple($this->resource->getTableName('catalogrule_product'), $rows);
413-
}
414-
} catch (\Exception $e) {
415-
throw $e;
416419
}
420+
if ($rows) {
421+
$this->connection->insertMultiple($ruleProductTable, $rows);
422+
}
423+
}
417424

425+
/**
426+
* Apply rule
427+
*
428+
* @param Rule $rule
429+
* @param Product $product
430+
* @return $this
431+
* @throws \Exception
432+
* @SuppressWarnings(PHPMD.NPathComplexity)
433+
*/
434+
protected function applyRule(Rule $rule, $product)
435+
{
436+
$this->assignProductToRule($rule, $product);
418437
$this->reindexRuleProductPrice->execute($this->batchCount, $product);
419438
$this->reindexRuleGroupWebsite->execute();
420439

421440
return $this;
422441
}
423442

424443
/**
444+
* Apply rules
445+
*
446+
* @param RuleCollection $ruleCollection
447+
* @param Product $product
448+
* @return void
449+
*/
450+
private function applyRules(RuleCollection $ruleCollection, Product $product): void
451+
{
452+
foreach ($ruleCollection as $rule) {
453+
$this->assignProductToRule($rule, $product);
454+
}
455+
456+
$this->cleanProductPriceIndex([$product->getId()]);
457+
$this->reindexRuleProductPrice->execute($this->batchCount, $product);
458+
}
459+
460+
/**
461+
* Retrieve table name
462+
*
425463
* @param string $tableName
426464
* @return string
427465
*/
@@ -431,6 +469,8 @@ protected function getTable($tableName)
431469
}
432470

433471
/**
472+
* Update rule product data
473+
*
434474
* @param Rule $rule
435475
* @return $this
436476
* @deprecated 100.2.0
@@ -456,6 +496,8 @@ protected function updateRuleProductData(Rule $rule)
456496
}
457497

458498
/**
499+
* Apply all rules
500+
*
459501
* @param Product|null $product
460502
* @throws \Exception
461503
* @return $this
@@ -495,8 +537,10 @@ protected function deleteOldData()
495537
}
496538

497539
/**
540+
* Calculate rule product price
541+
*
498542
* @param array $ruleData
499-
* @param null $productData
543+
* @param array $productData
500544
* @return float
501545
* @deprecated 100.2.0
502546
* @see ProductPriceCalculator::calculate
@@ -507,6 +551,8 @@ protected function calcRuleProductPrice($ruleData, $productData = null)
507551
}
508552

509553
/**
554+
* Get rule products statement
555+
*
510556
* @param int $websiteId
511557
* @param Product|null $product
512558
* @return \Zend_Db_Statement_Interface
@@ -520,6 +566,8 @@ protected function getRuleProductsStmt($websiteId, Product $product = null)
520566
}
521567

522568
/**
569+
* Save rule product prices
570+
*
523571
* @param array $arrData
524572
* @return $this
525573
* @throws \Exception
@@ -535,7 +583,7 @@ protected function saveRuleProductPrices($arrData)
535583
/**
536584
* Get active rules
537585
*
538-
* @return array
586+
* @return RuleCollection
539587
*/
540588
protected function getActiveRules()
541589
{
@@ -545,14 +593,16 @@ protected function getActiveRules()
545593
/**
546594
* Get active rules
547595
*
548-
* @return array
596+
* @return RuleCollection
549597
*/
550598
protected function getAllRules()
551599
{
552600
return $this->ruleCollectionFactory->create();
553601
}
554602

555603
/**
604+
* Get product
605+
*
556606
* @param int $productId
557607
* @return Product
558608
*/
@@ -565,6 +615,8 @@ protected function getProduct($productId)
565615
}
566616

567617
/**
618+
* Log critical exception
619+
*
568620
* @param \Exception $e
569621
* @return void
570622
*/

app/code/Magento/CatalogRule/Model/Indexer/RuleProductPricesPersistor.php

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,25 +76,19 @@ public function execute(array $priceData, $useAdditionalTable = false)
7676
);
7777
}
7878

79-
$productIds = [];
80-
81-
try {
82-
foreach ($priceData as $key => $data) {
83-
$productIds['product_id'] = $data['product_id'];
84-
$priceData[$key]['rule_date'] = $this->dateFormat->formatDate($data['rule_date'], false);
85-
$priceData[$key]['latest_start_date'] = $this->dateFormat->formatDate(
86-
$data['latest_start_date'],
87-
false
88-
);
89-
$priceData[$key]['earliest_end_date'] = $this->dateFormat->formatDate(
90-
$data['earliest_end_date'],
91-
false
92-
);
93-
}
94-
$connection->insertOnDuplicate($indexTable, $priceData);
95-
} catch (\Exception $e) {
96-
throw $e;
79+
foreach ($priceData as $key => $data) {
80+
$priceData[$key]['rule_date'] = $this->dateFormat->formatDate($data['rule_date'], false);
81+
$priceData[$key]['latest_start_date'] = $this->dateFormat->formatDate(
82+
$data['latest_start_date'],
83+
false
84+
);
85+
$priceData[$key]['earliest_end_date'] = $this->dateFormat->formatDate(
86+
$data['earliest_end_date'],
87+
false
88+
);
9789
}
90+
$connection->insertOnDuplicate($indexTable, $priceData);
91+
9892
return true;
9993
}
10094
}

0 commit comments

Comments
 (0)