diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php index ce485eed58e67..c5e9bf00a5cb4 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Create.php @@ -14,14 +14,24 @@ */ class Create extends \Magento\Backend\App\Action { + /** + * @var \Magento\Framework\Escaper + */ + protected $escaper; + /** * @param Action\Context $context * @param \Magento\Catalog\Helper\Product $productHelper + * @param \Magento\Framework\Escaper $escaper */ - public function __construct(Action\Context $context, \Magento\Catalog\Helper\Product $productHelper) - { + public function __construct( + Action\Context $context, + \Magento\Catalog\Helper\Product $productHelper, + \Magento\Framework\Escaper $escaper + ) { parent::__construct($context); $productHelper->setSkipSaleableCheck(true); + $this->escaper = $escaper; } /** @@ -271,16 +281,33 @@ protected function _processActionData($action = null) if (isset($data) && isset($data['coupon']['code'])) { $couponCode = trim($data['coupon']['code']); } + if (!empty($couponCode)) { - if ($this->_getQuote()->getCouponCode() !== $couponCode) { + $isApplyDiscount = false; + foreach ($this->_getQuote()->getAllItems() as $item) { + if (!$item->getNoDiscount()) { + $isApplyDiscount = true; + break; + } + } + if (!$isApplyDiscount) { $this->messageManager->addError( __( - '"%1" coupon code is not valid.', - $this->_objectManager->get('Magento\Framework\Escaper')->escapeHtml($couponCode) + '"%1" coupon code was not applied. Do not apply discount is selected for item(s)', + $this->escaper->escapeHtml($couponCode) ) ); } else { - $this->messageManager->addSuccess(__('The coupon code has been accepted.')); + if ($this->_getQuote()->getCouponCode() !== $couponCode) { + $this->messageManager->addError( + __( + '"%1" coupon code is not valid.', + $this->escaper->escapeHtml($couponCode) + ) + ); + } else { + $this->messageManager->addSuccess(__('The coupon code has been accepted.')); + } } } diff --git a/dev/tests/unit/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/ProcessDataTest.php b/dev/tests/unit/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/ProcessDataTest.php new file mode 100644 index 0000000000000..da63836d01087 --- /dev/null +++ b/dev/tests/unit/testsuite/Magento/Sales/Controller/Adminhtml/Order/Create/ProcessDataTest.php @@ -0,0 +1,235 @@ +getMock('Magento\Backend\App\Action\Context', [], [], '', false); + + $this->request = $this->getMockForAbstractClass( + 'Magento\Framework\App\RequestInterface', + [], + '', + false, + true, + true, + [ + 'getParam', + 'getPost', + 'get', + 'has', + 'setModuleName', + 'setActionName', + 'initForward', + 'setDispatched', + 'getModuleName', + 'getActionName', + 'getCookie' + ] + ); + $response = $this->getMockForAbstractClass( + 'Magento\Framework\App\ResponseInterface', + [], + '', + false, + true, + true, + [] + ); + $context->expects($this->any())->method('getResponse')->willReturn($response); + $context->expects($this->any())->method('getRequest')->willReturn($this->request); + + $this->actionFlag = $this->getMock('Magento\Framework\App\ActionFlag', [], [], '', false); + $context->expects($this->any())->method('getActionFlag')->willReturn($this->actionFlag); + + $this->messageManager = $this->getMock('Magento\Framework\Message\ManagerInterface', [], [], '', false); + $context->expects($this->any())->method('getMessageManager')->willReturn($this->messageManager); + + $this->eventManager = $this->getMock('Magento\Framework\Event\ManagerInterface', [], [], '', false); + $context->expects($this->any())->method('getEventManager')->willReturn($this->eventManager); + + $this->objectManager = $this->getMock('Magento\Framework\ObjectManagerInterface'); + $context->expects($this->any())->method('getObjectManager')->willReturn($this->objectManager); + + $this->session = $this->getMock( + 'Magento\Backend\Model\Session\Quote', + ['setIsUrlNotice', 'getQuote'], + [], + '', + false + ); + $context->expects($this->any())->method('getSession')->willReturn($this->session); + $this->escaper = $this->getMock('Magento\Framework\Escaper', ['escapeHtml'], [], '', false); + + $this->processData = $objectManagerHelper->getObject( + 'Magento\Sales\Controller\Adminhtml\Order\Create\ProcessData', + [ + 'context' => $context, + 'escaper' => $this->escaper + ] + ); + } + + /** + * @param bool $noDiscount + * @param string $couponCode + * @param string $errorMessage + * @param string $actualCouponCode + * @dataProvider isApplyDiscountDataProvider + */ + public function testExecute($noDiscount, $couponCode, $errorMessage, $actualCouponCode) + { + $quote = $this->getMock( + 'Magento\Sales\Model\Quote', + ['getCouponCode', 'isVirtual', 'getAllItems'], + [], + '', + false + ); + $create = $this->getMock('Magento\Sales\Model\AdminOrder\Create', [], [], '', false); + + $paramReturnMap = [ + ['customer_id', null, null], + ['store_id', null, null], + ['currency_id', null, null] + ]; + $this->request->expects($this->atLeastOnce())->method('getParam')->willReturnMap($paramReturnMap); + + $objectManagerParamMap = [ + ['Magento\Sales\Model\AdminOrder\Create', $create], + ['Magento\Backend\Model\Session\Quote', $this->session] + ]; + $this->objectManager->expects($this->atLeastOnce())->method('get')->willReturnMap($objectManagerParamMap); + + $this->eventManager->expects($this->any())->method('dispatch'); + + $data = ['coupon' => ['code' => $couponCode]]; + $postReturnMap = [ + ['order', $data], + ['reset_shipping', false], + ['collect_shipping_rates', false], + ['sidebar', false], + ['add_product', false], + ['', false], + ['update_items', false], + ['remove_item', 1], + ['from', 2], + ['move_item', 1], + ['to', 2], + ['qty', 3], + ['payment', false], + [null, 'request'], + ['payment', false], + ['giftmessage', false], + ['add_products', false], + ['update_items', false], + + ]; + $this->request->expects($this->atLeastOnce())->method('getPost')->willReturnMap($postReturnMap); + + $create->expects($this->once())->method('importPostData')->willReturnSelf(); + $create->expects($this->once())->method('initRuleData')->willReturnSelf(); + $create->expects($this->any())->method('getQuote')->willReturn($quote); + + $address = $this->getMock('Magento\Sales\Model\Quote\Address', [], [], '', false); + $create->expects($this->once())->method('getBillingAddress')->willReturn($address); + + $quote->expects($this->any())->method('isVirtual')->willReturn(true); + + $this->request->expects($this->once())->method('has')->with('item')->willReturn(false); + + $create->expects($this->once())->method('saveQuote')->willReturnSelf(); + + $this->session->expects($this->any())->method('getQuote')->willReturn($quote); + $item = $this->getMockForAbstractClass( + 'Magento\Eav\Model\Entity\Collection\AbstractCollection', + [], + '', + false, + true, + true, + ['getNoDiscount'] + ); + $quote->expects($this->any())->method('getAllItems')->willReturn([$item]); + $item->expects($this->any())->method('getNoDiscount')->willReturn($noDiscount); + if (!$noDiscount) { + $quote->expects($this->once())->method('getCouponCode')->willReturn($actualCouponCode); + } + + $errorMessageManager = __( + $errorMessage, + $couponCode + ); + $this->escaper->expects($this->once())->method('escapeHtml')->with($couponCode)->willReturn($couponCode); + + $this->messageManager->expects($this->once())->method('addError')->with($errorMessageManager)->willReturnSelf(); + + $this->actionFlag->expects($this->once())->method('get')->willReturn(false); + $this->session->expects($this->once())->method('setIsUrlNotice')->with(false)->willReturn(false); + $this->request->expects($this->once())->method('initForward')->willReturnSelf(); + $this->request->expects($this->once())->method('setActionName')->willReturnSelf(); + $this->request->expects($this->once())->method('setDispatched')->willReturnSelf(); + $this->assertNull($this->processData->execute()); + } + + public function isApplyDiscountDataProvider() + { + return [ + [true, '123', '"%1" coupon code was not applied. Do not apply discount is selected for item(s)', null], + [false, '123', '"%1" coupon code is not valid.', '132'], + ]; + } +}