Skip to content

Commit

Permalink
MAGETWO-54412: [MERCHANT] Integrity Constraint Violation when creatin…
Browse files Browse the repository at this point in the history
…g orders #4580
  • Loading branch information
irenelagno committed Oct 6, 2016
1 parent a9510d3 commit fe97d9e
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 3 deletions.
6 changes: 6 additions & 0 deletions app/code/Magento/Quote/Model/Quote.php
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,12 @@ public function reserveOrderId()
{
if (!$this->getReservedOrderId()) {
$this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
} else {

This comment has been minimized.

Copy link
@mimarcel

mimarcel Jan 2, 2017

Contributor

This can be simplified to:

        if (!$this->getReservedOrderId()
            || $this->_getResource()->isOrderIncrementIdUsed($this->getReservedOrderId())) {
            $this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
        }
//checking if reserved order id was already used for some order
//if yes reserving new one if not using old one
if ($this->_getResource()->isOrderIncrementIdUsed($this->getReservedOrderId())) {
$this->setReservedOrderId($this->_getResource()->getReservedOrderId($this));
}
}
return $this;
}
Expand Down
22 changes: 22 additions & 0 deletions app/code/Magento/Quote/Model/ResourceModel/Quote.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Copy link
@sshymko

sshymko Oct 27, 2017

Can be simplified to return ($entity_id > 0);

Also, variable name does not follow the lowerCamelCase naming convention, should be $entityId.

This comment has been minimized.

Copy link
@mimarcel

mimarcel Oct 27, 2017

Contributor

If only @irenelango would care

This comment has been minimized.

Copy link
@orlangur

orlangur Oct 27, 2017

Contributor

@mimarcel @sshymko nowadays it is possible to propose a PR with suggested changes instead of commenting on a commit 😃

if ($entity_id > 0) {
return true;
}

return false;
}

/**
* Mark quotes - that depend on catalog price rules - to be recollected on demand
*
Expand Down
31 changes: 30 additions & 1 deletion app/code/Magento/Quote/Test/Unit/Model/QuoteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,10 @@ protected function setUp()
'customerRepository' => $this->customerRepositoryMock,
'objectCopyService' => $this->objectCopyServiceMock,
'extensionAttributesJoinProcessor' => $this->extensionAttributesJoinProcessorMock,
'customerDataFactory' => $this->customerDataFactoryMock
'customerDataFactory' => $this->customerDataFactoryMock,
'data' => [
'reserved_order_id' => 1000001
]
]
);
}
Expand Down Expand Up @@ -1237,4 +1240,30 @@ public function testGetAllItems()

$this->assertEquals($itemResult, $this->quote->getAllItems());
}

/**
* Test to verify if existing reserved_order_id in use
*
* @param bool $isReservedOrderIdExist
* @param int $reservedOrderId
* @dataProvider reservedOrderIdDataProvider
*/
public function testReserveOrderId($isReservedOrderIdExist, $reservedOrderId)
{
$this->resourceMock
->expects($this->once())
->method('isOrderIncrementIdUsed')
->with(1000001)->willReturn($isReservedOrderIdExist);
$this->resourceMock->expects($this->any())->method('getReservedOrderId')->willReturn($reservedOrderId);
$this->quote->reserveOrderId();
$this->assertEquals($reservedOrderId, $this->quote->getReservedOrderId());
}

public function reservedOrderIdDataProvider()
{
return [
'id_already_in_use' => [true, 100002],
'id_not_in_use' => [false, 1000001]
];
}
}
85 changes: 85 additions & 0 deletions app/code/Magento/Quote/Test/Unit/Model/ResourceModel/QuoteTest.php
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']];
}
}
2 changes: 1 addition & 1 deletion dev/tests/integration/etc/install-config-mysql.php.dist
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
return [
'db-host' => 'localhost',
'db-user' => 'root',
'db-password' => '123123q',
'db-password' => '',
'db-name' => 'magento_integration_tests',
'db-prefix' => '',
'backend-frontname' => 'backend',
Expand Down
19 changes: 19 additions & 0 deletions dev/tests/integration/testsuite/Magento/Quote/Model/QuoteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -404,4 +404,23 @@ protected function _getCustomerDataArray()
\Magento\Customer\Model\Data\Customer::WEBSITE_ID => 1
];
}

/**
* Test to verify that reserved_order_id will be changed if it already in used
*
* @magentoDataFixture Magento/Sales/_files/order.php
* @magentoDataFixture Magento/Quote/_files/empty_quote.php
*/
public function testReserveOrderId()
{
$objectManager = Bootstrap::getObjectManager();
/** @var \Magento\Quote\Model\Quote $quote */
$quote = $objectManager->create(\Magento\Quote\Model\Quote::class);
$quote->load('reserved_order_id', 'reserved_order_id');
$quote->reserveOrderId();
$this->assertEquals('reserved_order_id', $quote->getReservedOrderId());
$quote->setReservedOrderId('100000001');
$quote->reserveOrderId();
$this->assertNotEquals('100000001', $quote->getReservedOrderId());
}
}
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'));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2155,7 +2155,6 @@
['addOrderedQty', 'Magento\Reports\Model\ResourceModel\Product\Collection'],
['prepareForProductsInCarts', 'Magento\Reports\Model\ResourceModel\Quote\Collection'],
['getOrdersSubSelect', 'Magento\Reports\Model\ResourceModel\Quote\Collection'],
['isOrderIncrementIdUsed', 'Magento\Quote\Model\ResourceModel\Quote'],
['isStateProtected', 'Magento\Sales\Model\Order'],
['_getBundleOptions', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'],
['_getSelectionFinalPrice', 'Magento\Bundle\Block\Checkout\Cart\Item\Renderer'],
Expand Down

12 comments on commit fe97d9e

@Ctucker9233
Copy link

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?

@zeeshan2523806
Copy link

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 ?

@irenelagno
Copy link
Contributor Author

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?

@zeeshan2523806
Copy link

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 INTO sa...', 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}"}

@zeeshan2523806
Copy link

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.

@irenelagno
Copy link
Contributor Author

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.

@zeeshan2523806
Copy link

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.

@irenelagno
Copy link
Contributor Author

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.

@Ctucker9233
Copy link

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?

@Ctucker9233
Copy link

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?

@erikhansen
Copy link
Contributor

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

@Ctucker9233
Copy link

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?

Please sign in to comment.