-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
…g orders #4580
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -172,6 +172,28 @@ public function getReservedOrderId($quote) | |
->getNextValue(); | ||
} | ||
|
||
/** | ||
* Check is order increment id use in sales/order table | ||
* | ||
* @param int $orderIncrementId | ||
* @return bool | ||
*/ | ||
public function isOrderIncrementIdUsed($orderIncrementId) | ||
{ | ||
/** @var \Magento\Framework\DB\Adapter\AdapterInterface $adapter */ | ||
$adapter = $this->getConnection(); | ||
$bind = [':increment_id' => $orderIncrementId]; | ||
/** @var \Magento\Framework\DB\Select $select */ | ||
$select = $adapter->select(); | ||
$select->from($this->getTable('sales_order'), 'entity_id')->where('increment_id = :increment_id'); | ||
$entity_id = $adapter->fetchOne($select, $bind); | ||
This comment has been minimized.
Sorry, something went wrong.
sshymko
|
||
if ($entity_id > 0) { | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* Mark quotes - that depend on catalog price rules - to be recollected on demand | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
/** | ||
* Copyright © 2016 Magento. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
|
||
namespace Magento\Quote\Test\Unit\Model\ResourceModel; | ||
|
||
|
||
class QuoteTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @var \Magento\Quote\Model\ResourceModel\Quote | ||
*/ | ||
private $model; | ||
|
||
/** | ||
* @var \Magento\Framework\App\ResourceConnection | ||
*/ | ||
private $resourceMock; | ||
|
||
/** | ||
* @var \Magento\Framework\DB\Adapter\Pdo\Mysql | ||
*/ | ||
private $adapterMock; | ||
|
||
/** | ||
* @var \Magento\Framework\DB\Select | ||
*/ | ||
private $selectMock; | ||
|
||
protected function setUp() | ||
{ | ||
$objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); | ||
$this->selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class) | ||
->disableOriginalConstructor() | ||
->getMock(); | ||
$this->selectMock->expects($this->any())->method('from')->will($this->returnSelf()); | ||
$this->selectMock->expects($this->any())->method('where'); | ||
|
||
$this->adapterMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\Pdo\Mysql::class) | ||
->disableOriginalConstructor() | ||
->getMock(); | ||
$this->adapterMock->expects($this->any())->method('select')->will($this->returnValue($this->selectMock)); | ||
|
||
$this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class) | ||
->disableOriginalConstructor() | ||
->getMock(); | ||
$this->resourceMock->expects( | ||
$this->any() | ||
)->method( | ||
'getConnection' | ||
)->will( | ||
$this->returnValue($this->adapterMock) | ||
); | ||
|
||
$this->model = $objectManagerHelper->getObject( | ||
\Magento\Quote\Model\ResourceModel\Quote::class, | ||
[ | ||
'resource' => $this->resourceMock | ||
] | ||
); | ||
} | ||
|
||
/** | ||
* Unit test to verify if isOrderIncrementIdUsed method works with different types increment ids | ||
* | ||
* @param array $value | ||
* @dataProvider isOrderIncrementIdUsedDataProvider | ||
*/ | ||
public function testIsOrderIncrementIdUsed($value) | ||
{ | ||
$expectedBind = [':increment_id' => $value]; | ||
$this->adapterMock->expects($this->once())->method('fetchOne')->with($this->selectMock, $expectedBind); | ||
$this->model->isOrderIncrementIdUsed($value); | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
public function isOrderIncrementIdUsedDataProvider() | ||
{ | ||
return [[100000001], ['10000000001'], ['M10000000001']]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
<?php | ||
/** | ||
* Copyright © 2016 Magento. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
|
||
namespace Magento\Quote\Model\ResourceModel; | ||
|
||
/** | ||
* Class QuoteTest to verify isOrderIncrementIdUsed method behaviour | ||
*/ | ||
class QuoteTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
/** | ||
* @var \Magento\Quote\Model\ResourceModel\Quote | ||
*/ | ||
private $_resourceModel; | ||
|
||
protected function setUp() | ||
{ | ||
$this->_resourceModel = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( | ||
\Magento\Quote\Model\ResourceModel\Quote::class | ||
); | ||
} | ||
|
||
/** | ||
* Test to verify if isOrderIncrementIdUsed method works with numeric increment ids | ||
* | ||
* @magentoDataFixture Magento/Sales/_files/order.php | ||
*/ | ||
public function testIsOrderIncrementIdUsedNumericIncrementId() | ||
{ | ||
$this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('100000001')); | ||
} | ||
|
||
/** | ||
* Test to verify if isOrderIncrementIdUsed method works with alphanumeric increment ids | ||
* | ||
* @magentoDataFixture Magento/Sales/_files/order_alphanumeric_id.php | ||
*/ | ||
public function testIsOrderIncrementIdUsedAlphanumericIncrementId() | ||
{ | ||
$this->assertTrue($this->_resourceModel->isOrderIncrementIdUsed('M00000001')); | ||
} | ||
} |
12 comments
on commit fe97d9e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@irenelagno Will this commit be included in 2.1.3?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I have the same problem when any logged in user is going through with the checkout process, i have integrated all the changes in the respective files but it does not seems to be solve my problem. I have cleared the cache too but the problem still stick to the place where it was. Can you please recommend/suggest any alternative in order to fix this ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ctucker9233 , this fix wasn't included in 2.1.3 release. @zeeshan2523806 , Could you please provide steps to reproduce this problem, env details and Magento version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for responding. i am using Magento ver. 2.1.1
When any guest user tries to place an order it works fine, but when any loggedin user try to place the order it throws an error on the order placement portion of checkout page with this information :
{"message":"SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '000000041-1' for key
'SALES_ORDER_INCREMENT_ID_STORE_ID', query was: INSERT INTO sales_order
(state
, status
, protect_code
, shipping_description
, is_virtual
, store_id
, customer_id
, base_discount_amount
, base_grand_total
, base_shipping_amount
, base_shipping_tax_amount
, base_subtotal
, base_tax_amount
, base_to_global_rate
, base_to_order_rate
, discount_amount
, grand_total
, shipping_amount
, shipping_tax_amount
,
store_to_base_rate
, store_to_order_rate
, subtotal
, tax_amount
, total_qty_ordered
, customer_is_guest
, customer_note_notify
, customer_group_id
, quote_id
, base_shipping_discount_amount
, base_subtotal_incl_tax
, base_total_due
, shipping_discount_amount
, subtotal_incl_tax
, total_due
, weight
, increment_id
, applied_rule_ids
, base_currency_code
, customer_email
, customer_firstname
, customer_lastname
, customer_middlename
, discount_description
, global_currency_code
, order_currency_code
, remote_ip
, shipping_method
, store_currency_code
, store_name
, total_item_count
, discount_tax_compensation_amount
, base_discount_tax_compensation_amount
, shipping_discount_tax_compensation_amount
, shipping_incl_tax
, base_shipping_incl_tax
, gift_message_id
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?)","code":23000,"trace":"#0 /var/www/portoland/vendor/magento/framework
/DB/Statement/Pdo/Mysql.php(95): Zend_Db_Statement_Pdo->_execute(Array)\n#1 /var/www/portoland
/vendor/magento/zendframework1/library/Zend/Db/Statement.php(303): Magento\Framework\DB\Statement
\Pdo\Mysql->_execute(Array)\n#2 /var/www/portoland/vendor/magento/zendframework1/library/Zend
/Db/Adapter/Abstract.php(480): Zend_Db_Statement->execute(Array)\n#3 /var/www/portoland/vendor
/magento/zendframework1/library/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract-
query('INSERT INTO
sa...', Array)\n#4 \/var\/www\/portoland\/vendor\/magento\/framework\/DB\/Adapter \/Pdo\/Mysql.php(452): Zend_Db_Adapter_Pdo_Abstract->query('INSERT INTO
sa...', Array)\n#5 /var/www
/portoland/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php(507): Magento\Framework\DB\Adapter
\Pdo\Mysql->_query('INSERT INTOsa...', Array)\n#6 \/var\/www\/portoland\/vendor\/magento\/zendframework1 \/library\/Zend\/Db\/Adapter\/Abstract.php(576): Magento\\Framework\\DB\\Adapter\\Pdo\\Mysql->query('INSERT INTO
sa...', Array)\n#7 /var/www/portoland/vendor/magento/module-sales/Model/ResourceModel
/EntityAbstract.php(180): Zend_Db_Adapter_Abstract->insert('sales_order', Array)\n#8 /var/www/portoland
/vendor/magento/framework/Model/ResourceModel/Db/AbstractDb.php(405): Magento\Sales\Model\ResourceModel
\EntityAbstract->saveNewObject(Object(Magento\Sales\Model\Order))\n#9 /var/www/portoland/vendor
/magento/module-sales/Model/ResourceModel/Order.php(174): Magento\Framework\Model\ResourceModel
\Db\AbstractDb->save(Object(Magento\Sales\Model\Order))\n#10 /var/www/portoland/var/generation
/Magento/Sales/Model/ResourceModel/Order/Interceptor.php(24): Magento\Sales\Model\ResourceModel
\Order->save(Object(Magento\Sales\Model\Order))\n#11 /var/www/portoland/vendor/magento/module-sales
/Model/OrderRepository.php(161): Magento\Sales\Model\ResourceModel\Order\Interceptor->save(Object
(Magento\Sales\Model\Order))\n#12 /var/www/portoland/vendor/magento/framework/Interception
/Interceptor.php(146): Magento\Sales\Model\OrderRepository->save(Object(Magento\Sales\Model\Order
))\n#13 /var/www/portoland/var/generation/Magento/Sales/Model/OrderRepository/Interceptor.php
(52): Magento\Sales\Model\OrderRepository\Interceptor->___callPlugins('save', Array, Array)\n#14
/var/www/portoland/vendor/magento/module-sales/Model/Service/OrderService.php(191): Magento
\Sales\Model\OrderRepository\Interceptor->save(Object(Magento\Sales\Model\Order))\n#15 /var
/www/portoland/vendor/magento/module-quote/Model/QuoteManagement.php(488): Magento\Sales\Model
\Service\OrderService->place(Object(Magento\Sales\Model\Order))\n#16 /var/www/portoland/vendor
/magento/module-quote/Model/QuoteManagement.php(391): Magento\Quote\Model\QuoteManagement->submitQuote
(Object(Magento\Quote\Model\Quote), Array)\n#17 /var/www/portoland/vendor/magento/module-quote
/Model/QuoteManagement.php(349): Magento\Quote\Model\QuoteManagement->submit(Object(Magento\Quote
\Model\Quote))\n#18 /var/www/portoland/vendor/magento/module-checkout/Model/PaymentInformationManagement
.php(69): Magento\Quote\Model\QuoteManagement->placeOrder(82072)\n#19 /var/www/portoland/vendor
/magento/framework/Interception/Interceptor.php(146): Magento\Checkout\Model\PaymentInformationManagement-
savePaymentInformationAndPlaceOrder(82072, Object(Magento\Quote\Model\Quote\Payment), Object(Magento
\Quote\Model\Quote\Address\Interceptor))\n#20 /var/www/portoland/var/generation/Magento/Checkout
/Model/PaymentInformationManagement/Interceptor.php(26): Magento\Checkout\Model\PaymentInformationManagement
\Interceptor->___callPlugins('savePaymentInfo...', Array, Array)\n#21 [internal function]: Magento
\Checkout\Model\PaymentInformationManagement\Interceptor->savePaymentInformationAndPlaceOrder(82072
, Object(Magento\Quote\Model\Quote\Payment), Object(Magento\Quote\Model\Quote\Address\Interceptor
))\n#22 /var/www/portoland/vendor/magento/module-webapi/Controller/Rest.php(307): call_user_func_array
(Array, Array)\n#23 /var/www/portoland/vendor/magento/module-webapi/Controller/Rest.php(216)
: Magento\Webapi\Controller\Rest->processApiRequest()\n#24 /var/www/portoland/var/generation
/Magento/Webapi/Controller/Rest/Interceptor.php(24): Magento\Webapi\Controller\Rest->dispatch
(Object(Magento\Framework\App\Request\Http))\n#25 /var/www/portoland/vendor/magento/framework
/App/Http.php(135): Magento\Webapi\Controller\Rest\Interceptor->dispatch(Object(Magento\Framework
\App\Request\Http))\n#26 /var/www/portoland/vendor/magento/framework/App/Bootstrap.php(258
): Magento\Framework\App\Http->launch()\n#27 /var/www/portoland/pub/index.php(42): Magento\Framework
\App\Bootstrap->run(Object(Magento\Framework\App\Http))\n#28 {main}"}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Steps to Reproduce this error:
-> Add any product to the cart,
-> Go to checkout page.
-> logged in with registered user
-> Fill the other shipping information and choose shipping method
-> Go to Payment Page and select payment method and place the order
Expected Results:
-> Order place successfully when chooses cash on delivery or take the user to payment gateway url for payment
Actual results:
-> It throws an error i have mentioned above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zeeshan2523806, Does this problem exist for newly created customers after applying fix? Do you use some customization for checkout? Because I coudn't reproduce this issue on 2.1.1 with changes in the /Magento/Quote/Model/Quote.php and /Magento/Quote/Model/ResourceModel/Quote.php.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure about the newly created customer as i havent created any one. but is there any way to fix it on already existing customer because we already have around 56,000 customers which are already on the system.
Yes we are using Amasty Extension for Customer order attributes + some other custom development in order to fix the customization needs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial fix for this issue should work for existing customers too on checkout without customization. New order id will be regenerated if it already in use in the \Magento\Quote\Model\QuoteManagement::submitQuote. It is better to create new issue about this problem or add comment to existing issue #4474.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@irenelagno What release will have it then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@irenelagno Any updates on what release will include this fix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, the underlying problem that this commit solves is that when some customers/users place orders, the quote from which the order was placed never gets changed to “is_active” = “0”. So when the customer returns to place another order, Magento tries to create a second order using the same “quote.reserved_order_id” value, causing this MySQL error:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '10000045345-1' for key 'SALES_ORDER_INCREMENT_ID_STORE_ID', query was: INSERT INTO
sales_order(
state,
status,
protect_code,
shipping_description,
is_virtual,
store_id,
customer_id,
base_discount_amount,
base_discount_invoiced,
base_grand_total,
base_shipping_amount,
base_shipping_invoiced,
base_shipping_tax_amount,
base_subtotal,
base_subtotal_invoiced,
base_tax_amount,
base_tax_invoiced,
base_to_global_rate,
base_to_order_rate,
base_total_invoiced,
base_total_invoiced_cost,
base_total_paid,
discount_amount,
discount_invoiced,
grand_total,
shipping_amount,
shipping_invoiced,
shipping_tax_amount,
store_to_base_rate,
store_to_order_rate,
subtotal,
subtotal_invoiced,
tax_amount,
tax_invoiced,
total_invoiced,
total_paid,
total_qty_ordered,
customer_is_guest,
customer_note_notify,
customer_group_id,
quote_id,
base_shipping_discount_amount,
base_subtotal_incl_tax,
base_total_due,
shipping_discount_amount,
subtotal_incl_tax,
total_due,
weight,
increment_id,
applied_rule_ids,
base_currency_code,
customer_email,
customer_firstname,
customer_lastname,
customer_middlename,
discount_description,
global_currency_code,
order_currency_code,
remote_ip,
shipping_method,
store_currency_code,
store_name,
total_item_count,
discount_tax_compensation_amount,
base_discount_tax_compensation_amount,
shipping_discount_tax_compensation_amount,
discount_tax_compensation_invoiced,
base_discount_tax_compensation_invoiced,
shipping_incl_tax,
base_shipping_incl_tax,
gift_cards,
base_gift_cards_amount,
gift_cards_amount,
gift_message_id,
gw_id,
gw_allow_gift_receipt,
gw_add_card,
gw_base_price,
gw_price,
gw_items_base_price,
gw_items_price,
gw_card_base_price,
gw_card_price,
gw_base_tax_amount,
gw_tax_amount,
gw_items_base_tax_amount,
gw_items_tax_amount,
gw_card_base_tax_amount,
gw_card_tax_amount,
gw_base_price_incl_tax,
gw_price_incl_tax,
gw_items_base_price_incl_tax,
gw_items_price_incl_tax,
gw_card_base_price_incl_tax,
gw_card_price_incl_tax,
originating_quote_id,
cart_in_stock) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
To find out if an M2 site has quotes where this problem exists, run this query and if any results are returned, you’ll need to apply this commit as a patch to your install:
-- Find all quotes that have been ordered but where the quote is still active
SELECT
sales_order.increment_id AS order_increment,
sales_order.entity_id AS order_id,
quote.entity_id AS quote_id,
sales_order.customer_email
FROM `quote`
INNER JOIN sales_order ON quote.entity_id = sales_order.quote_id
LEFT JOIN customer_entity ON sales_order.customer_id = customer_entity.entity_id AND quote.customer_email = customer_entity.email
INNER JOIN sales_order_payment ON sales_order.entity_id = sales_order_payment.parent_id
AND quote.is_active = 1
ORDER BY quote.entity_id DESC
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any plans to backport this to 2.1?
This can be simplified to: