Skip to content

Commit bd8a83b

Browse files
committed
MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some
1 parent 3bdff12 commit bd8a83b

File tree

2 files changed

+167
-2
lines changed

2 files changed

+167
-2
lines changed

app/code/Magento/Sales/Model/Order.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,13 @@ public function canCancel()
546546
break;
547547
}
548548
}
549-
if ($allInvoiced) {
549+
550+
$allRefunded = true;
551+
foreach ($this->getAllItems() as $orderItem) {
552+
$allRefunded = $allRefunded && ((float)$orderItem->getQtyRefunded() == (float)$orderItem->getQtyInvoiced());
553+
}
554+
555+
if ($allInvoiced && !$allRefunded) {
550556
return false;
551557
}
552558

app/code/Magento/Sales/Test/Unit/Model/OrderTest.php

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ protected function setUp()
114114
'getParentItemId',
115115
'getQuoteItemId',
116116
'getLockedDoInvoice',
117-
'getProductId'
117+
'getProductId',
118+
'getQtyRefunded',
119+
'getQtyInvoiced',
118120
]);
119121
$this->salesOrderCollectionMock = $this->getMockBuilder(
120122
\Magento\Sales\Model\ResourceModel\Order\Collection::class
@@ -619,6 +621,163 @@ public function testCanCancelAllInvoiced()
619621
$this->item->expects($this->any())
620622
->method('getQtyToInvoice')
621623
->willReturn(0);
624+
$this->item->expects($this->any())
625+
->method('getQtyRefunded')
626+
->willReturn(0);
627+
$this->item->expects($this->any())
628+
->method('getQtyInvoiced')
629+
->willReturn(1);
630+
631+
$this->assertFalse($this->order->canCancel());
632+
}
633+
634+
public function testCanCancelAllRefunded()
635+
{
636+
$paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
637+
->disableOriginalConstructor()
638+
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
639+
->getMock();
640+
$paymentMock->expects($this->any())
641+
->method('canReviewPayment')
642+
->will($this->returnValue(false));
643+
$paymentMock->expects($this->any())
644+
->method('canFetchTransactionInfo')
645+
->will($this->returnValue(false));
646+
$collectionMock = $this->createPartialMock(
647+
\Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
648+
['getItems', 'setOrderFilter']
649+
);
650+
$this->orderItemCollectionFactoryMock->expects($this->any())
651+
->method('create')
652+
->will($this->returnValue($collectionMock));
653+
$collectionMock->expects($this->any())
654+
->method('setOrderFilter')
655+
->willReturnSelf();
656+
$this->preparePaymentMock($paymentMock);
657+
658+
$this->prepareItemMock(0);
659+
660+
$this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
661+
$this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
662+
663+
$this->item->expects($this->any())
664+
->method('isDeleted')
665+
->willReturn(false);
666+
$this->item->expects($this->any())
667+
->method('getQtyToInvoice')
668+
->willReturn(0);
669+
$this->item->expects($this->any())
670+
->method('getQtyRefunded')
671+
->willReturn(10);
672+
$this->item->expects($this->any())
673+
->method('getQtyInvoiced')
674+
->willReturn(10);
675+
676+
$this->assertTrue($this->order->canCancel());
677+
}
678+
679+
/**
680+
* Test that order can be canceled if some items were partially invoiced with certain qty
681+
* and then refunded for this qty.
682+
* Sample:
683+
* - ordered qty = 20
684+
* - invoiced = 10
685+
* - refunded = 10
686+
*/
687+
public function testCanCancelPartiallyInvoicedAndRefunded()
688+
{
689+
$paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
690+
->disableOriginalConstructor()
691+
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
692+
->getMock();
693+
$paymentMock->expects($this->any())
694+
->method('canReviewPayment')
695+
->will($this->returnValue(false));
696+
$paymentMock->expects($this->any())
697+
->method('canFetchTransactionInfo')
698+
->will($this->returnValue(false));
699+
$collectionMock = $this->createPartialMock(
700+
\Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
701+
['getItems', 'setOrderFilter']
702+
);
703+
$this->orderItemCollectionFactoryMock->expects($this->any())
704+
->method('create')
705+
->will($this->returnValue($collectionMock));
706+
$collectionMock->expects($this->any())
707+
->method('setOrderFilter')
708+
->willReturnSelf();
709+
$this->preparePaymentMock($paymentMock);
710+
711+
$this->prepareItemMock(0);
712+
713+
$this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
714+
$this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
715+
716+
$this->item->expects($this->any())
717+
->method('isDeleted')
718+
->willReturn(false);
719+
$this->item->expects($this->any())
720+
->method('getQtyToInvoice')
721+
->willReturn(10);
722+
$this->item->expects($this->any())
723+
->method('getQtyRefunded')
724+
->willReturn(10);
725+
$this->item->expects($this->any())
726+
->method('getQtyInvoiced')
727+
->willReturn(10);
728+
729+
$this->assertTrue($this->order->canCancel());
730+
}
731+
732+
/**
733+
* Test that order CAN NOT be canceled if some items were partially invoiced with certain qty
734+
* and then refunded for less than that qty.
735+
* Sample:
736+
* - ordered qty = 10
737+
* - invoiced = 10
738+
* - refunded = 5
739+
*/
740+
public function testCanCancelPartiallyInvoicedAndNotFullyRefunded()
741+
{
742+
$paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class)
743+
->disableOriginalConstructor()
744+
->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp'])
745+
->getMock();
746+
$paymentMock->expects($this->any())
747+
->method('canReviewPayment')
748+
->will($this->returnValue(false));
749+
$paymentMock->expects($this->any())
750+
->method('canFetchTransactionInfo')
751+
->will($this->returnValue(false));
752+
$collectionMock = $this->createPartialMock(
753+
\Magento\Sales\Model\ResourceModel\Order\Item\Collection::class,
754+
['getItems', 'setOrderFilter']
755+
);
756+
$this->orderItemCollectionFactoryMock->expects($this->any())
757+
->method('create')
758+
->will($this->returnValue($collectionMock));
759+
$collectionMock->expects($this->any())
760+
->method('setOrderFilter')
761+
->willReturnSelf();
762+
$this->preparePaymentMock($paymentMock);
763+
764+
$this->prepareItemMock(0);
765+
766+
$this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false);
767+
$this->order->setState(\Magento\Sales\Model\Order::STATE_NEW);
768+
769+
$this->item->expects($this->any())
770+
->method('isDeleted')
771+
->willReturn(false);
772+
$this->item->expects($this->any())
773+
->method('getQtyToInvoice')
774+
->willReturn(0);
775+
$this->item->expects($this->any())
776+
->method('getQtyRefunded')
777+
->willReturn(5);
778+
$this->item->expects($this->any())
779+
->method('getQtyInvoiced')
780+
->willReturn(10);
622781

623782
$this->assertFalse($this->order->canCancel());
624783
}

0 commit comments

Comments
 (0)