diff --git a/app/code/Magento/Quote/Observer/Backend/Quote/Address/CollectTotalsObserver.php b/app/code/Magento/Quote/Observer/Backend/Quote/Address/CollectTotalsObserver.php new file mode 100755 index 0000000000000..3f413d6069bd6 --- /dev/null +++ b/app/code/Magento/Quote/Observer/Backend/Quote/Address/CollectTotalsObserver.php @@ -0,0 +1,81 @@ +state = $state; + } + + /** + * Conditions to change customer group + * + * @param int|null $groupId + * @return bool + */ + protected function assignCustomerGroupConditions($groupId) + { + if ($groupId !== null + && !( + $this->state->getAreaCode() == Area::AREA_ADMINHTML + && $groupId == $this->groupManagement->getNotLoggedInGroup()->getId() + )) { + return true; + } + + return false; + } +} diff --git a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php old mode 100644 new mode 100755 index a1228903e2323..2e9d8e4910181 --- a/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php +++ b/app/code/Magento/Quote/Observer/Frontend/Quote/Address/CollectTotalsObserver.php @@ -131,7 +131,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) ); } - if ($groupId !== null) { + if ($this->assignCustomerGroupConditions($groupId)) { $address->setPrevQuoteCustomerGroupId($quote->getCustomerGroupId()); $quote->setCustomerGroupId($groupId); $this->customerSession->setCustomerGroupId($groupId); @@ -139,4 +139,15 @@ public function execute(\Magento\Framework\Event\Observer $observer) $quote->setCustomer($customer); } } + + /** + * Conditions to change customer group + * + * @param int|null $groupId + * @return bool + */ + protected function assignCustomerGroupConditions($groupId) + { + return $groupId !== null ? true : false; + } } diff --git a/app/code/Magento/Quote/Test/Unit/Observer/Backend/Quote/Address/CollectTotalsObserverTest.php b/app/code/Magento/Quote/Test/Unit/Observer/Backend/Quote/Address/CollectTotalsObserverTest.php new file mode 100755 index 0000000000000..b7a2d9a2f586e --- /dev/null +++ b/app/code/Magento/Quote/Test/Unit/Observer/Backend/Quote/Address/CollectTotalsObserverTest.php @@ -0,0 +1,488 @@ +objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->storeId = 1; + $this->customerMock = $this->getMockForAbstractClass( + \Magento\Customer\Api\Data\CustomerInterface::class, + [], + '', + false, + true, + true, + ['getStoreId', 'getCustomAttribute', 'getId', '__wakeup'] + ); + $this->customerAddressMock = $this->createMock(\Magento\Customer\Helper\Address::class); + $this->customerVatMock = $this->createMock(\Magento\Customer\Model\Vat::class); + $this->customerDataFactoryMock = $this->createPartialMock( + \Magento\Customer\Api\Data\CustomerInterfaceFactory::class, + ['mergeDataObjectWithArray', 'create'] + ); + $this->vatValidatorMock = $this->createMock(\Magento\Quote\Observer\Frontend\Quote\Address\VatValidator::class); + $this->observerMock = $this->createPartialMock( + \Magento\Framework\Event\Observer::class, + ['getShippingAssignment', 'getQuote'] + ); + + $this->quoteAddressMock = $this->createPartialMock( + \Magento\Quote\Model\Quote\Address::class, + ['getCountryId', 'getVatId', 'getQuote', 'setPrevQuoteCustomerGroupId', '__wakeup'] + ); + + $this->quoteMock = $this->createPartialMock( + \Magento\Quote\Model\Quote::class, + ['setCustomerGroupId', 'getCustomerGroupId', 'getCustomer', '__wakeup', 'setCustomer'] + ); + + $this->groupManagementMock = $this->getMockForAbstractClass( + \Magento\Customer\Api\GroupManagementInterface::class, + [], + '', + false, + true, + true, + [ + 'getDefaultGroup', + 'getNotLoggedInGroup' + ] + ); + + $this->groupInterfaceMock = $this->getMockForAbstractClass( + \Magento\Customer\Api\Data\GroupInterface::class, + [], + '', + false, + true, + true, + ['getId'] + ); + + $this->stateMock = $this->createPartialMock( + State::class, + ['getAreaCode'] + ); + + $shippingAssignmentMock = $this->createMock(\Magento\Quote\Api\Data\ShippingAssignmentInterface::class); + $shippingMock = $this->createMock(\Magento\Quote\Api\Data\ShippingInterface::class); + $shippingAssignmentMock->expects($this->once())->method('getShipping')->willReturn($shippingMock); + $shippingMock->expects($this->once())->method('getAddress')->willReturn($this->quoteAddressMock); + + $this->observerMock->expects($this->once()) + ->method('getShippingAssignment') + ->willReturn($shippingAssignmentMock); + + $this->observerMock->expects($this->once())->method('getQuote')->willReturn($this->quoteMock); + $this->quoteMock->expects($this->any()) + ->method('getCustomer') + ->will($this->returnValue($this->customerMock)); + + $this->addressRepository = $this->createMock(\Magento\Customer\Api\AddressRepositoryInterface::class); + $this->customerSession = $this->getMockBuilder(\Magento\Customer\Model\Session::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->customerMock->expects($this->any())->method('getStoreId')->will($this->returnValue($this->storeId)); + + $this->model = new \Magento\Quote\Observer\Backend\Quote\Address\CollectTotalsObserver( + $this->customerAddressMock, + $this->customerVatMock, + $this->vatValidatorMock, + $this->customerDataFactoryMock, + $this->groupManagementMock, + $this->addressRepository, + $this->customerSession, + $this->stateMock + ); + } + + public function testDispatchWithDisableVatValidator() + { + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(false)); + $this->model->execute($this->observerMock); + } + + /** + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testDispatchWithCustomerCountryNotInEUAndNotLoggedCustomerInGroup() + { + $this->groupManagementMock->expects($this->once()) + ->method('getNotLoggedInGroup') + ->will($this->returnValue($this->groupInterfaceMock)); + $this->groupInterfaceMock->expects($this->once()) + ->method('getId')->will($this->returnValue(null)); + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->quoteAddressMock->expects($this->once()) + ->method('getCountryId') + ->will($this->returnValue('customerCountryCode')); + $this->quoteAddressMock->expects($this->once())->method('getVatId')->will($this->returnValue('vatId')); + + $this->customerVatMock->expects( + $this->once() + )->method( + 'isCountryInEU' + )->with( + 'customerCountryCode' + )->will( + $this->returnValue(false) + ); + + $this->customerMock->expects($this->once())->method('getId')->will($this->returnValue(null)); + + /** Assertions */ + $this->quoteAddressMock->expects($this->never())->method('setPrevQuoteCustomerGroupId'); + $this->customerDataFactoryMock->expects($this->never())->method('mergeDataObjectWithArray'); + $this->quoteMock->expects($this->never())->method('setCustomerGroupId'); + + /** SUT execution */ + $this->model->execute($this->observerMock); + } + + /** + * @SuppressWarnings(PHPMD.UnusedLocalVariable) + */ + public function testDispatchWithNotLoggedCustomerInGroupAndInAdminArea() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode')->will($this->returnValue(Area::AREA_ADMINHTML)); + $this->groupManagementMock->expects($this->exactly(2)) + ->method('getNotLoggedInGroup') + ->will($this->returnValue($this->groupInterfaceMock)); + $this->groupInterfaceMock->expects($this->exactly(2)) + ->method('getId')->will($this->returnValue(0)); + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->quoteAddressMock->expects($this->once()) + ->method('getCountryId') + ->will($this->returnValue('customerCountryCode')); + $this->quoteAddressMock->expects($this->once())->method('getVatId')->will($this->returnValue('vatId')); + + $this->customerVatMock->expects( + $this->once() + )->method( + 'isCountryInEU' + )->with( + 'customerCountryCode' + )->will( + $this->returnValue(false) + ); + + $this->customerMock->expects($this->once())->method('getId')->will($this->returnValue(null)); + + /** Assertions */ + $this->quoteAddressMock->expects($this->never())->method('setPrevQuoteCustomerGroupId'); + $this->customerDataFactoryMock->expects($this->never())->method('mergeDataObjectWithArray'); + $this->quoteMock->expects($this->never())->method('setCustomerGroupId'); + + /** SUT execution */ + $this->model->execute($this->observerMock); + } + + public function testDispatchWithDefaultCustomerGroupId() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode')->will($this->returnValue(Area::AREA_FRONTEND)); + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->quoteAddressMock->expects($this->once()) + ->method('getCountryId') + ->will($this->returnValue('customerCountryCode')); + $this->quoteAddressMock->expects($this->once())->method('getVatId')->will($this->returnValue(null)); + + $this->quoteMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue('customerGroupId')); + $this->customerMock->expects($this->once())->method('getId')->will($this->returnValue('1')); + $this->groupManagementMock->expects($this->once()) + ->method('getDefaultGroup') + ->will($this->returnValue($this->groupInterfaceMock)); + $this->groupInterfaceMock->expects($this->once()) + ->method('getId')->will($this->returnValue('defaultCustomerGroupId')); + /** Assertions */ + $this->quoteAddressMock->expects($this->once()) + ->method('setPrevQuoteCustomerGroupId') + ->with('customerGroupId'); + $this->quoteMock->expects($this->once())->method('setCustomerGroupId')->with('defaultCustomerGroupId'); + $this->customerDataFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->customerMock); + + $this->quoteMock->expects($this->once())->method('setCustomer')->with($this->customerMock); + + /** SUT execution */ + $this->model->execute($this->observerMock); + } + + public function testDispatchWithCustomerCountryInEU() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode')->will($this->returnValue(Area::AREA_FRONTEND)); + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->quoteAddressMock->expects($this->once()) + ->method('getCountryId') + ->will($this->returnValue('customerCountryCode')); + $this->quoteAddressMock->expects($this->once()) + ->method('getVatId') + ->will($this->returnValue('vatID')); + + $this->customerVatMock->expects($this->once()) + ->method('isCountryInEU') + ->with('customerCountryCode') + ->willReturn(true); + + $this->quoteMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue('customerGroupId')); + + $validationResult = ['some' => 'result']; + $this->vatValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue($validationResult)); + + $this->customerVatMock->expects($this->once()) + ->method('getCustomerGroupIdBasedOnVatNumber') + ->with('customerCountryCode', $validationResult, $this->storeId) + ->will($this->returnValue('customerGroupId')); + + /** Assertions */ + $this->quoteAddressMock->expects($this->once()) + ->method('setPrevQuoteCustomerGroupId') + ->with('customerGroupId'); + + $this->quoteMock->expects($this->once())->method('setCustomerGroupId')->with('customerGroupId'); + $this->quoteMock->expects($this->once())->method('setCustomer')->with($this->customerMock); + $this->customerDataFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->customerMock); + $this->model->execute($this->observerMock); + } + + public function testDispatchWithAddressCustomerVatIdAndCountryId() + { + $customerCountryCode = "BE"; + $customerVat = "123123123"; + $defaultShipping = 1; + + $customerAddress = $this->createMock(\Magento\Quote\Model\Quote\Address::class); + $customerAddress->expects($this->any()) + ->method("getVatId") + ->willReturn($customerVat); + + $customerAddress->expects($this->any()) + ->method("getCountryId") + ->willReturn($customerCountryCode); + + $this->addressRepository->expects($this->once()) + ->method("getById") + ->with($defaultShipping) + ->willReturn($customerAddress); + + $this->customerMock->expects($this->atLeastOnce()) + ->method("getDefaultShipping") + ->willReturn($defaultShipping); + + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->customerVatMock->expects($this->once()) + ->method('isCountryInEU') + ->with($customerCountryCode) + ->willReturn(true); + + $this->model->execute($this->observerMock); + } + + public function testDispatchWithEmptyShippingAddress() + { + $this->stateMock->expects($this->once()) + ->method('getAreaCode')->will($this->returnValue(Area::AREA_FRONTEND)); + $customerCountryCode = "DE"; + $customerVat = "123123123"; + $defaultShipping = 1; + + $customerAddress = $this->createMock(\Magento\Customer\Api\Data\AddressInterface::class); + $customerAddress->expects($this->once()) + ->method("getCountryId") + ->willReturn($customerCountryCode); + + $customerAddress->expects($this->once()) + ->method("getVatId") + ->willReturn($customerVat); + $this->addressRepository->expects($this->once()) + ->method("getById") + ->with($defaultShipping) + ->willReturn($customerAddress); + + $this->customerMock->expects($this->atLeastOnce()) + ->method("getDefaultShipping") + ->willReturn($defaultShipping); + + $this->vatValidatorMock->expects($this->once()) + ->method('isEnabled') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue(true)); + + $this->quoteAddressMock->expects($this->once()) + ->method('getCountryId') + ->will($this->returnValue(null)); + $this->quoteAddressMock->expects($this->once()) + ->method('getVatId') + ->will($this->returnValue(null)); + + $this->customerVatMock->expects($this->once()) + ->method('isCountryInEU') + ->with($customerCountryCode) + ->willReturn(true); + + $this->quoteMock->expects($this->once()) + ->method('getCustomerGroupId') + ->will($this->returnValue('customerGroupId')); + $validationResult = ['some' => 'result']; + $this->customerVatMock->expects($this->once()) + ->method('getCustomerGroupIdBasedOnVatNumber') + ->with($customerCountryCode, $validationResult, $this->storeId) + ->will($this->returnValue('customerGroupId')); + $this->customerSession->expects($this->once()) + ->method("setCustomerGroupId") + ->with('customerGroupId'); + + $this->vatValidatorMock->expects($this->once()) + ->method('validate') + ->with($this->quoteAddressMock, $this->storeId) + ->will($this->returnValue($validationResult)); + + /** Assertions */ + $this->quoteAddressMock->expects($this->once()) + ->method('setPrevQuoteCustomerGroupId') + ->with('customerGroupId'); + + $this->quoteMock->expects($this->once())->method('setCustomerGroupId')->with('customerGroupId'); + $this->quoteMock->expects($this->once())->method('setCustomer')->with($this->customerMock); + $this->customerDataFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->customerMock); + $this->model->execute($this->observerMock); + } +} diff --git a/app/code/Magento/Quote/etc/adminhtml/events.xml b/app/code/Magento/Quote/etc/adminhtml/events.xml old mode 100644 new mode 100755 index 54943fe4cd34f..f0dd18c34af32 --- a/app/code/Magento/Quote/etc/adminhtml/events.xml +++ b/app/code/Magento/Quote/etc/adminhtml/events.xml @@ -9,4 +9,7 @@ + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupWithAutomaticAssignmentToCustomerGroupInNewOrderTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupWithAutomaticAssignmentToCustomerGroupInNewOrderTest.xml new file mode 100644 index 0000000000000..326658f4415b8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminChangeCustomerGroupWithAutomaticAssignmentToCustomerGroupInNewOrderTest.xml @@ -0,0 +1,28 @@ + + + + + + + + <stories value="Admin Create Order and Select Customer Group, when enabled 'Automatic Assignment to Customer Group'"/> + <description value="Customer Account Group should be available to select while creating a new customer in order, when enabled 'Automatic Assignment to Customer Group'"/> + <severity value="MAJOR"/> + <group value="sales"/> + </annotations> + + <before> + <magentoCLI command="config:set customer/create_account/auto_group_assign 1" after="login" stepKey="setConfigSettings"/> + </before> + + <after> + <magentoCLI command="config:set customer/create_account/auto_group_assign 0" after="logout" stepKey="revertConfigSettings"/> + </after> + + </test> +</tests>