diff --git a/app/code/Magento/Authorizenet/Model/Directpost.php b/app/code/Magento/Authorizenet/Model/Directpost.php index 41fac85a43db5..71e81e1727e8b 100644 --- a/app/code/Magento/Authorizenet/Model/Directpost.php +++ b/app/code/Magento/Authorizenet/Model/Directpost.php @@ -112,6 +112,11 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra */ protected $orderFactory; + /** + * @var \Magento\Sales\Api\TransactionRepositoryInterface + */ + protected $transactionRepository; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -129,6 +134,7 @@ class Directpost extends \Magento\Authorizenet\Model\Authorizenet implements Tra * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Quote\Model\QuoteRepository $quoteRepository * @param \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender + * @param \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -151,6 +157,7 @@ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Quote\Model\QuoteRepository $quoteRepository, \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender, + \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] @@ -160,6 +167,7 @@ public function __construct( $this->quoteRepository = $quoteRepository; $this->response = $responseFactory->create(); $this->orderSender = $orderSender; + $this->transactionRepository = $transactionRepository; $this->_code = static::METHOD_CODE; parent::__construct( @@ -795,7 +803,11 @@ protected function declineOrder(\Magento\Sales\Model\Order $order, $message = '' */ protected function getRealParentTransactionId($payment) { - $transaction = $payment->getTransaction($payment->getParentTransactionId()); + $transaction = $this->transactionRepository->getByTransactionId( + $payment->getParentTransactionId(), + $payment->getId(), + $payment->getOrder()->getId() + ); return $transaction->getAdditionalInformation(self::REAL_TRANSACTION_ID_KEY); } @@ -851,7 +863,11 @@ public function canCapture() */ public function fetchTransactionInfo(\Magento\Payment\Model\InfoInterface $payment, $transactionId) { - $transaction = $payment->getTransaction($transactionId); + $transaction = $this->transactionRepository->getByTransactionId( + $transactionId, + $payment->getId(), + $payment->getOrder()->getId() + ); $response = $this->getTransactionResponse($transactionId); if ($response->getXResponseCode() == self::RESPONSE_CODE_APPROVED) { diff --git a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethod/PayPalTest.php b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethod/PayPalTest.php index ba30489f63996..5b1dd02ca7b9f 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethod/PayPalTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethod/PayPalTest.php @@ -587,7 +587,7 @@ public function testAuthorizeSuccess( $this->assertEquals($this->model, $this->model->authorize($paymentObject, $amount)); foreach ($expectedPaymentFields as $key => $value) { if ($key == 'getTransactionAdditionalInfo') { - $this->assertEquals($value, $paymentObject->getTransactionAdditionalInfo('token')); + $this->assertEquals($value, $paymentObject->getTransactionAdditionalInfo()); } else { $this->assertEquals($value, $paymentObject->getData($key), 'Incorrect field in paymentobject: ' . $key); } diff --git a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php index 49af3b38364c1..50d0261aa46e8 100644 --- a/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php +++ b/app/code/Magento/Braintree/Test/Unit/Model/PaymentMethodTest.php @@ -788,7 +788,7 @@ public function testAuthorizeSuccess( $this->assertEquals($this->model, $this->model->authorize($paymentObject, $amount)); foreach ($expectedPaymentFields as $key => $value) { if ($key == 'getTransactionAdditionalInfo') { - $this->assertEquals($value, $paymentObject->getTransactionAdditionalInfo('token')); + $this->assertEquals($value, $paymentObject->getTransactionAdditionalInfo()); } else { $this->assertEquals($value, $paymentObject->getData($key), 'Incorrect field in paymentobject: ' . $key); } @@ -1385,7 +1385,7 @@ public function authorizeDataProvider() 'processorResponseCode' => '1000', 'processorResponseText' => 'Approved', ], - 'getTransactionAdditionalInfo' => self::CC_TOKEN + 'getTransactionAdditionalInfo' => ['token' => self::CC_TOKEN] ], ], 'token_with_3dsecure' => [ @@ -1458,7 +1458,7 @@ public function authorizeDataProvider() 'processorResponseCode' => '1000', 'processorResponseText' => 'Approved', ], - 'getTransactionAdditionalInfo' => self::CC_TOKEN + 'getTransactionAdditionalInfo' => ['token' => self::CC_TOKEN] ], ], 'token_with_3dsecure_backend' => [ @@ -1526,7 +1526,7 @@ public function authorizeDataProvider() 'processorResponseCode' => '1000', 'processorResponseText' => 'Approved', ], - 'getTransactionAdditionalInfo' => self::CC_TOKEN + 'getTransactionAdditionalInfo' => ['token' => self::CC_TOKEN] ], 'appState' => 'adminhtml', ], diff --git a/app/code/Magento/Paypal/Model/Express.php b/app/code/Magento/Paypal/Model/Express.php index 32c85cf2d99c8..a6b28ad52d2f6 100644 --- a/app/code/Magento/Paypal/Model/Express.php +++ b/app/code/Magento/Paypal/Model/Express.php @@ -8,6 +8,7 @@ use Magento\Paypal\Model\Api\Nvp; use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; use Magento\Paypal\Model\Express\Checkout as ExpressCheckout; +use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order\Payment; use Magento\Sales\Model\Order\Payment\Transaction; use Magento\Quote\Model\Quote; @@ -166,6 +167,16 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod */ protected $_exception; + /** + * @var \Magento\Sales\Api\TransactionRepositoryInterface + */ + protected $transactionRepository; + + /** + * @var Transaction\BuilderInterface + */ + protected $transactionBuilder; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -180,6 +191,8 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod * @param CartFactory $cartFactory * @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Framework\Exception\LocalizedExceptionFactory $exception + * @param \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository + * @param Transaction\BuilderInterface $transactionBuilder * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -199,6 +212,8 @@ public function __construct( \Magento\Paypal\Model\CartFactory $cartFactory, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\Exception\LocalizedExceptionFactory $exception, + \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository, + \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface $transactionBuilder, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] @@ -220,6 +235,8 @@ public function __construct( $this->_cartFactory = $cartFactory; $this->_checkoutSession = $checkoutSession; $this->_exception = $exception; + $this->transactionRepository = $transactionRepository; + $this->transactionBuilder = $transactionBuilder; $proInstance = array_shift($data); if ($proInstance && $proInstance instanceof \Magento\Paypal\Model\Pro) { @@ -380,7 +397,11 @@ public function order(\Magento\Payment\Model\InfoInterface $payment, $amount) $message = __('Ordered amount of %1', $formattedPrice); } - $payment->addTransaction(Transaction::TYPE_ORDER, null, false, $message); + $transaction = $this->transactionBuilder->setPayment($payment) + ->setOrder($order) + ->setTransactionId($payment->getTransactionId()) + ->build(Transaction::TYPE_ORDER); + $payment->addTransactionCommentsToOrder($transaction, $message); $this->_pro->importPaymentInfo($api, $payment); @@ -402,7 +423,11 @@ public function order(\Magento\Payment\Model\InfoInterface $payment, $amount) $payment->setTransactionId($api->getTransactionId()); $payment->setParentTransactionId($orderTransactionId); - $payment->addTransaction(Transaction::TYPE_AUTH, null, false, $message); + $transaction = $this->transactionBuilder->setPayment($payment) + ->setOrder($order) + ->setTransactionId($payment->getTransactionId()) + ->build(Transaction::TYPE_AUTH); + $payment->addTransactionCommentsToOrder($transaction, $message); $order->setState($state) ->setStatus($status); @@ -437,7 +462,7 @@ public function void(\Magento\Payment\Model\InfoInterface $payment) $this->_isOrderPaymentActionKey ) && !$payment->getVoidOnlyAuthorization() ) { - $orderTransaction = $payment->lookupTransaction(false, Transaction::TYPE_ORDER); + $orderTransaction = $this->getOrderTransaction($payment); if ($orderTransaction) { $payment->setParentTransactionId($orderTransaction->getTxnId()); $payment->setTransactionId($orderTransaction->getTxnId() . '-void'); @@ -511,14 +536,19 @@ public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount) $message = __('The authorized amount is %1.', $formatedPrice); } - $transaction = $payment->addTransaction(Transaction::TYPE_AUTH, null, true, $message); + $transaction = $this->transactionBuilder->setPayment($payment) + ->setOrder($order) + ->setTransactionId($payment->getTransactionId()) + ->setFailSafe(true) + ->build(Transaction::TYPE_AUTH); + $payment->addTransactionCommentsToOrder($transaction, $message); $payment->setParentTransactionId($api->getTransactionId()); $isAuthorizationCreated = true; } //close order transaction if needed if ($payment->getShouldCloseParentTransaction()) { - $orderTransaction = $payment->lookupTransaction(false, Transaction::TYPE_ORDER); + $orderTransaction = $this->getOrderTransaction($payment); if ($orderTransaction) { $orderTransaction->setIsClosed(true); @@ -737,7 +767,7 @@ public function canVoid() { $info = $this->getInfoInstance(); if ($info->getAdditionalInformation($this->_isOrderPaymentActionKey)) { - $orderTransaction = $info->lookupTransaction(false, Transaction::TYPE_ORDER); + $orderTransaction = $this->getOrderTransaction($info); if ($orderTransaction) { $info->setParentTransactionId($orderTransaction->getTxnId()); } @@ -757,7 +787,7 @@ public function canCapture() $this->_pro->getConfig()->setStoreId($payment->getOrder()->getStore()->getId()); if ($payment->getAdditionalInformation($this->_isOrderPaymentActionKey)) { - $orderTransaction = $payment->lookupTransaction(false, Transaction::TYPE_ORDER); + $orderTransaction = $this->getOrderTransaction($payment); if ($orderTransaction->getIsClosed()) { return false; } @@ -772,6 +802,7 @@ public function canCapture() return false; } } + return $this->_canCapture; } @@ -853,4 +884,19 @@ public function isActive($storeId = null) || (bool)(int)$this->_scopeConfig->getValue($pathStandardExpress, ScopeInterface::SCOPE_STORE, $storeId) || (bool)(int)$this->_scopeConfig->getValue($pathPaypalExpress, ScopeInterface::SCOPE_STORE, $storeId); } + + /** + * Get transaction with type order + * + * @param OrderPaymentInterface $payment + * @return false|\Magento\Sales\Api\Data\TransactionInterface + */ + protected function getOrderTransaction($payment) + { + return $this->transactionRepository->getByTransactionType( + Transaction::TYPE_ORDER, + $payment->getId(), + $payment->getOrder()->getId() + ); + } } diff --git a/app/code/Magento/Paypal/Model/Payflow/Pro.php b/app/code/Magento/Paypal/Model/Payflow/Pro.php index 5a33be4476d75..8d7bdd549b44b 100644 --- a/app/code/Magento/Paypal/Model/Payflow/Pro.php +++ b/app/code/Magento/Paypal/Model/Payflow/Pro.php @@ -67,8 +67,10 @@ protected function _isCaptureNeeded() protected function _getParentTransactionId(\Magento\Framework\DataObject $payment) { if ($payment->getParentTransactionId()) { - return $payment->getTransaction( - $payment->getParentTransactionId() + return $this->transactionRepository->getByTransactionId( + $payment->getParentTransactionId(), + $payment->getId(), + $payment->getOrder()->getId() )->getAdditionalInformation( self::TRANSPORT_PAYFLOW_TXN_ID ); diff --git a/app/code/Magento/Paypal/Model/PayflowExpress.php b/app/code/Magento/Paypal/Model/PayflowExpress.php index dd44e82a473e9..334f76d5daac5 100644 --- a/app/code/Magento/Paypal/Model/PayflowExpress.php +++ b/app/code/Magento/Paypal/Model/PayflowExpress.php @@ -63,6 +63,8 @@ class PayflowExpress extends \Magento\Paypal\Model\Express * @param CartFactory $cartFactory * @param \Magento\Checkout\Model\Session $checkoutSession * @param \Magento\Framework\Exception\LocalizedExceptionFactory $exception + * @param \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository + * @param Transaction\BuilderInterface $transactionBuilder * @param InfoFactory $paypalInfoFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection @@ -83,6 +85,8 @@ public function __construct( CartFactory $cartFactory, \Magento\Checkout\Model\Session $checkoutSession, \Magento\Framework\Exception\LocalizedExceptionFactory $exception, + \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository, + \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface $transactionBuilder, InfoFactory $paypalInfoFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -102,6 +106,8 @@ public function __construct( $cartFactory, $checkoutSession, $exception, + $transactionRepository, + $transactionBuilder, $resource, $resourceCollection, $data @@ -181,7 +187,11 @@ public function canRefund() /** @var \Magento\Sales\Model\Order\Payment $payment */ $payment = $this->getInfoInstance(); // we need the last capture transaction was made - $captureTransaction = $payment->lookupTransaction('', Transaction::TYPE_CAPTURE); + $captureTransaction = $this->transactionRepository->getByTransactionType( + Transaction::TYPE_CAPTURE, + $payment->getId(), + $payment->getOrder()->getId() + ); return $captureTransaction && $captureTransaction->getAdditionalInformation( Payflow\Pro::TRANSPORT_PAYFLOW_TXN_ID ) && $this->_canRefund; diff --git a/app/code/Magento/Paypal/Model/Pro.php b/app/code/Magento/Paypal/Model/Pro.php index baab75589b8b4..f3e29e6f8268c 100644 --- a/app/code/Magento/Paypal/Model/Pro.php +++ b/app/code/Magento/Paypal/Model/Pro.php @@ -9,6 +9,7 @@ namespace Magento\Paypal\Model; use Magento\Paypal\Model\Api\AbstractApi; +use Magento\Sales\Api\TransactionRepositoryInterface; /** * PayPal Website Payments Pro implementation for payment method instances @@ -73,19 +74,27 @@ class Pro */ protected $_infoFactory; + /** + * @var TransactionRepositoryInterface + */ + protected $transactionRepository; + /** * @param \Magento\Paypal\Model\Config\Factory $configFactory * @param \Magento\Paypal\Model\Api\Type\Factory $apiFactory * @param \Magento\Paypal\Model\InfoFactory $infoFactory + * @param TransactionRepositoryInterface $transactionRepository */ public function __construct( \Magento\Paypal\Model\Config\Factory $configFactory, \Magento\Paypal\Model\Api\Type\Factory $apiFactory, - \Magento\Paypal\Model\InfoFactory $infoFactory + \Magento\Paypal\Model\InfoFactory $infoFactory, + TransactionRepositoryInterface $transactionRepository ) { $this->_configFactory = $configFactory; $this->_apiFactory = $apiFactory; $this->_infoFactory = $infoFactory; + $this->transactionRepository = $transactionRepository; } /** diff --git a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php index 3b52016a81c7b..1c78434512703 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php @@ -49,6 +49,11 @@ class ExpressTest extends \PHPUnit_Framework_TestCase */ protected $_helper; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $transactionBuilder; + protected function setUp() { $this->_checkoutSession = $this->getMock( @@ -58,6 +63,13 @@ protected function setUp() '', false ); + $this->transactionBuilder = $this->getMockForAbstractClass( + 'Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface', + [], + '', + false, + false + ); $this->_nvp = $this->getMock( 'Magento\Paypal\Model\Api\Nvp', ['setProcessableErrors', 'setAmount', 'setCurrencyCode', 'setTransactionId', 'callDoAuthorization'], @@ -82,7 +94,11 @@ public function testSetApiProcessableErrors() $this->_pro->expects($this->any())->method('getApi')->will($this->returnValue($this->_nvp)); $this->_model = $this->_helper->getObject( 'Magento\Paypal\Model\Express', - ['proFactory' => $this->_pro, 'checkoutSession' => $this->_checkoutSession] + [ + 'proFactory' => $this->_pro, + 'checkoutSession' => $this->_checkoutSession, + 'transactionBuilder' => $this->transactionBuilder + ] ); } @@ -102,19 +118,40 @@ public function testOrder() $currency = $this->getMock('Magento\Directory\Model\Currency', ['__wakeup', 'formatTxt'], [], '', false); $paymentModel = $this->getMock( 'Magento\Sales\Model\Order\Payment', - ['__wakeup', 'getBaseCurrency', 'getOrder', 'getIsTransactionPending', 'addStatusHistoryComment'], + [ + '__wakeup', + 'getBaseCurrency', + 'getOrder', + 'getIsTransactionPending', + 'addStatusHistoryComment', + 'addTransactionCommentsToOrder' + ], + [], + '', + false + ); + $order = $this->getMock( + 'Magento\Sales\Model\Order', + ['setState', 'getBaseCurrency', 'getBaseCurrencyCode', 'setStatus'], [], '', false ); - $paymentModel->expects($this->any())->method('getOrder')->will($this->returnSelf()); - $paymentModel->expects($this->any())->method('getBaseCurrency')->will($this->returnValue($currency)); + $paymentModel->expects($this->any())->method('getOrder')->willReturn($order); + $order->expects($this->any())->method('getBaseCurrency')->willReturn($currency); + $order->expects($this->any())->method('setState')->with('payment_review')->willReturnSelf(); $paymentModel->expects($this->any())->method('getIsTransactionPending')->will($this->returnSelf()); + $this->transactionBuilder->expects($this->any())->method('setOrder')->with($order)->will($this->returnSelf()); + $this->transactionBuilder->expects($this->any())->method('setPayment')->will($this->returnSelf()); + $this->transactionBuilder->expects($this->any())->method('setTransactionId')->will($this->returnSelf()); $this->_model = $this->_helper->getObject( 'Magento\Paypal\Model\Express', - ['proFactory' => $this->_pro, 'checkoutSession' => $this->_checkoutSession] + [ + 'proFactory' => $this->_pro, + 'checkoutSession' => $this->_checkoutSession, + 'transactionBuilder' => $this->transactionBuilder + ] ); - $this->_model->order($paymentModel, 12.3); - $this->assertEquals('payment_review', $paymentModel->getState()); + $this->assertEquals($this->_model, $this->_model->order($paymentModel, 12.3)); } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/PayflowExpressTest.php b/app/code/Magento/Paypal/Test/Unit/Model/PayflowExpressTest.php index 55d42f6477bd3..7fa3ea13fd53c 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/PayflowExpressTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/PayflowExpressTest.php @@ -16,6 +16,11 @@ class PayflowExpressTest extends \PHPUnit_Framework_TestCase */ protected $_model; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $transactionRepository; + /** * Payflow pro transaction key */ @@ -31,20 +36,28 @@ public function setUp() $paypalPro = $this->getMockBuilder( 'Magento\Paypal\Model\Pro' )->disableOriginalConstructor()->setMethods([])->getMock(); + $this->transactionRepository = $this->getMockBuilder('\Magento\Sales\Api\TransactionRepositoryInterface') + ->disableOriginalConstructor() + ->setMethods(['getByTransactionType']) + ->getMockForAbstractClass(); $paypalPro->expects($this->any())->method('getApi')->will($this->returnValue($api)); $proFactory->expects($this->once())->method('create')->will($this->returnValue($paypalPro)); - $this->_model = $objectManager->getObject('Magento\Paypal\Model\PayflowExpress', ['proFactory' => $proFactory]); + $this->_model = $objectManager->getObject( + 'Magento\Paypal\Model\PayflowExpress', + ['proFactory' => $proFactory, 'transactionRepository' => $this->transactionRepository] + ); } public function testCanRefundCaptureNotExist() { $paymentInfo = $this->_getPreparedPaymentInfo(); - - $paymentInfo->expects($this->once())->method('lookupTransaction')->with('', Transaction::TYPE_CAPTURE)->will( - $this->returnValue(false) - ); + $paymentInfo->expects($this->once())->method('getOrder')->willReturnSelf(); + $this->transactionRepository->expects($this->once()) + ->method('getByTransactionType') + ->with(Transaction::TYPE_CAPTURE) + ->willReturn(false); $this->assertFalse($this->_model->canRefund()); } @@ -55,9 +68,11 @@ public function testCanRefundCaptureExistNoAdditionalInfo() $captureTransaction->expects($this->once())->method('getAdditionalInformation')->with( Payflow\Pro::TRANSPORT_PAYFLOW_TXN_ID )->will($this->returnValue(null)); - $paymentInfo->expects($this->once())->method('lookupTransaction')->with('', Transaction::TYPE_CAPTURE)->will( - $this->returnValue($captureTransaction) - ); + $paymentInfo->expects($this->once())->method('getOrder')->willReturnSelf(); + $this->transactionRepository->expects($this->once()) + ->method('getByTransactionType') + ->with(Transaction::TYPE_CAPTURE) + ->willReturn($captureTransaction); $this->assertFalse($this->_model->canRefund()); } @@ -68,9 +83,11 @@ public function testCanRefundCaptureExistValid() $captureTransaction->expects($this->once())->method('getAdditionalInformation')->with( Payflow\Pro::TRANSPORT_PAYFLOW_TXN_ID )->will($this->returnValue(self::TRANSPORT_PAYFLOW_TXN_ID)); - $paymentInfo->expects($this->once())->method('lookupTransaction')->with('', Transaction::TYPE_CAPTURE)->will( - $this->returnValue($captureTransaction) - ); + $paymentInfo->expects($this->once())->method('getOrder')->willReturnSelf(); + $this->transactionRepository->expects($this->once()) + ->method('getByTransactionType') + ->with(Transaction::TYPE_CAPTURE) + ->willReturn($captureTransaction); $this->assertTrue($this->_model->canRefund()); } diff --git a/app/code/Magento/Quote/Model/Quote/Address/ToOrderAddress.php b/app/code/Magento/Quote/Model/Quote/Address/ToOrderAddress.php index 52b1ab7dbaeee..cf8e0d337a00f 100644 --- a/app/code/Magento/Quote/Model/Quote/Address/ToOrderAddress.php +++ b/app/code/Magento/Quote/Model/Quote/Address/ToOrderAddress.php @@ -8,7 +8,7 @@ use Magento\Framework\DataObject\Copy; use Magento\Quote\Model\Quote\Address; -use Magento\Sales\Api\Data\OrderAddressInterfaceFactory as OrderAddressFactory; +use Magento\Sales\Model\Order\AddressRepository as OrderAddressRepository; use Magento\Sales\Api\Data\OrderAddressInterface; /** @@ -22,9 +22,9 @@ class ToOrderAddress protected $objectCopyService; /** - * @var OrderAddressFactory + * @var OrderAddressRepository */ - protected $orderAddressFactory; + protected $orderAddressRepository; /** * @var \Magento\Framework\Api\DataObjectHelper @@ -32,16 +32,16 @@ class ToOrderAddress protected $dataObjectHelper; /** - * @param OrderAddressFactory $orderAddressFactory + * @param OrderAddressRepository $orderAddressRepository * @param Copy $objectCopyService * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper */ public function __construct( - OrderAddressFactory $orderAddressFactory, + OrderAddressRepository $orderAddressRepository, Copy $objectCopyService, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper ) { - $this->orderAddressFactory = $orderAddressFactory; + $this->orderAddressRepository = $orderAddressRepository; $this->objectCopyService = $objectCopyService; $this->dataObjectHelper = $dataObjectHelper; } @@ -53,13 +53,14 @@ public function __construct( */ public function convert(Address $object, $data = []) { + $orderAddress = $this->orderAddressRepository->create(); + $orderAddressData = $this->objectCopyService->getDataFromFieldset( 'quote_convert_address', 'to_order_address', $object ); - $orderAddress = $this->orderAddressFactory->create(); $this->dataObjectHelper->populateWithArray( $orderAddress, array_merge($orderAddressData, $data), diff --git a/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php b/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php index 5098f557b92ff..ffc0bd63b3fcb 100644 --- a/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php +++ b/app/code/Magento/Quote/Model/Quote/Payment/ToOrderPayment.php @@ -7,7 +7,7 @@ namespace Magento\Quote\Model\Quote\Payment; use Magento\Quote\Model\Quote\Payment; -use Magento\Sales\Api\Data\OrderPaymentInterfaceFactory as OrderPaymentFactory; +use Magento\Sales\Api\OrderPaymentRepositoryInterface as OrderPaymentRepository; use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Framework\DataObject\Copy; use Magento\Payment\Model\Method\Substitution; @@ -23,9 +23,9 @@ class ToOrderPayment protected $objectCopyService; /** - * @var OrderPaymentFactory + * @var OrderPaymentRepository */ - protected $orderPaymentFactory; + protected $orderPaymentRepository; /** * @var \Magento\Framework\Api\DataObjectHelper @@ -33,16 +33,16 @@ class ToOrderPayment protected $dataObjectHelper; /** - * @param OrderPaymentFactory $orderPaymentFactory + * @param OrderPaymentRepository $orderPaymentRepository * @param Copy $objectCopyService * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper */ public function __construct( - OrderPaymentFactory $orderPaymentFactory, + OrderPaymentRepository $orderPaymentRepository, Copy $objectCopyService, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper ) { - $this->orderPaymentFactory = $orderPaymentFactory; + $this->orderPaymentRepository = $orderPaymentRepository; $this->objectCopyService = $objectCopyService; $this->dataObjectHelper = $dataObjectHelper; } @@ -60,7 +60,7 @@ public function convert(Payment $object, $data = []) $object ); - $orderPayment = $this->orderPaymentFactory->create(); + $orderPayment = $this->orderPaymentRepository->create(); $this->dataObjectHelper->populateWithArray( $orderPayment, array_merge($paymentData, $data), diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/ToOrderAddressTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/ToOrderAddressTest.php index 522caa3c2fae0..c9c889d4343f5 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/ToOrderAddressTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Address/ToOrderAddressTest.php @@ -18,9 +18,9 @@ class ToOrderAddressTest extends \PHPUnit_Framework_TestCase protected $objectCopyMock; /** - * @var \Magento\Sales\Api\Data\OrderAddressInterfaceFactory | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\AddressRepository | \PHPUnit_Framework_MockObject_MockObject */ - protected $orderAddressFactoryMock; + protected $orderAddressRepositoryMock; /** * @var \Magento\Sales\Api\Data\OrderInterface | \PHPUnit_Framework_MockObject_MockObject @@ -39,8 +39,8 @@ class ToOrderAddressTest extends \PHPUnit_Framework_TestCase protected function setUp() { - $this->orderAddressFactoryMock = $this->getMock( - 'Magento\Sales\Api\Data\OrderAddressInterfaceFactory', + $this->orderAddressRepositoryMock = $this->getMock( + 'Magento\Sales\Model\Order\AddressRepository', ['create'], [], '', @@ -53,7 +53,7 @@ protected function setUp() $this->converter = $objectManager->getObject( 'Magento\Quote\Model\Quote\Address\ToOrderAddress', [ - 'orderAddressFactory' => $this->orderAddressFactoryMock, + 'orderAddressRepository' => $this->orderAddressRepositoryMock, 'objectCopyService' => $this->objectCopyMock, 'dataObjectHelper' => $this->dataObjectHelper ] @@ -76,7 +76,7 @@ public function testConvert() $this->dataObjectHelper->expects($this->once())->method('populateWithArray') ->with($this->orderInterfaceMock, ['test' => 'beer'], '\Magento\Sales\Api\Data\OrderAddressInterface') ->willReturnSelf(); - $this->orderAddressFactoryMock->expects($this->once()) + $this->orderAddressRepositoryMock->expects($this->once()) ->method('create') ->willReturn($this->orderInterfaceMock); $this->assertSame($this->orderInterfaceMock, $this->converter->convert($object, $data)); diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php index 5ff4c57d67ccb..396014ea0510f 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/Payment/ToOrderPaymentTest.php @@ -17,9 +17,9 @@ class ToOrderPaymentTest extends \PHPUnit_Framework_TestCase { /** - * @var \Magento\Sales\Api\Data\OrderPaymentInterfaceFactory | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Api\OrderPaymentRepositoryInterface | \PHPUnit_Framework_MockObject_MockObject */ - protected $orderPaymentFactoryMock; + protected $orderPaymentRepositoryMock; /** * @var \Magento\Framework\DataObject\Copy | \PHPUnit_Framework_MockObject_MockObject @@ -51,11 +51,11 @@ public function setUp() false ); $this->objectCopyMock = $this->getMock('Magento\Framework\DataObject\Copy', [], [], '', false); - $this->orderPaymentFactoryMock = $this->getMock( - 'Magento\Sales\Api\Data\OrderPaymentInterfaceFactory', - ['create'], + $this->orderPaymentRepositoryMock = $this->getMockForAbstractClass( + 'Magento\Sales\Api\OrderPaymentRepositoryInterface', [], '', + false, false ); $this->dataObjectHelper = $this->getMock('\Magento\Framework\Api\DataObjectHelper', [], [], '', false); @@ -63,7 +63,7 @@ public function setUp() $this->converter = $objectManager->getObject( 'Magento\Quote\Model\Quote\Payment\ToOrderPayment', [ - 'orderPaymentFactory' => $this->orderPaymentFactoryMock, + 'orderPaymentRepository' => $this->orderPaymentRepositoryMock, 'objectCopyService' => $this->objectCopyMock, 'dataObjectHelper' => $this->dataObjectHelper ] @@ -122,7 +122,7 @@ public function testConvert() ->method('setCcCid') ->willReturnSelf(); - $this->orderPaymentFactoryMock->expects($this->once())->method('create')->willReturn($orderPayment); + $this->orderPaymentRepositoryMock->expects($this->once())->method('create')->willReturn($orderPayment); $this->dataObjectHelper->expects($this->once()) ->method('populateWithArray') ->with($orderPayment, array_merge($paymentData, $data), '\Magento\Sales\Api\Data\OrderPaymentInterface') diff --git a/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php b/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php index e5cf268b13651..551f48488869e 100644 --- a/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoManagementInterface.php @@ -23,6 +23,7 @@ interface CreditmemoManagementInterface * * @param int $id The credit memo ID. * @return bool + * @throws \Magento\Framework\Exception\LocalizedException */ public function cancel($id); @@ -41,4 +42,18 @@ public function getCommentsList($id); * @return bool */ public function notify($id); + + /** + * Prepare creditmemo to refund and save it. + * + * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo + * @param bool $offlineRequested + * @param bool $notifyCustomer + * @return \Magento\Sales\Api\Data\CreditmemoInterface + */ + public function refund( + \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, + $offlineRequested = false, + $notifyCustomer = false + ); } diff --git a/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php b/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php index e01a3e870c412..8bb487d732299 100644 --- a/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/CreditmemoRepositoryInterface.php @@ -31,6 +31,13 @@ public function getList(\Magento\Framework\Api\SearchCriteria $criteria); */ public function get($id); + /** + * Create credit memo instance + * + * @return \Magento\Sales\Api\Data\CreditmemoInterface Credit memo interface. + */ + public function create(); + /** * Deletes a specified credit memo. * diff --git a/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php b/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php index a7c67652dd7a4..b0be9bbd37cd3 100644 --- a/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php +++ b/app/code/Magento/Sales/Api/Data/OrderSearchResultInterface.php @@ -13,12 +13,20 @@ * a purchase order, is emailed to the customer. * @api */ -interface OrderSearchResultInterface +interface OrderSearchResultInterface extends \Magento\Framework\Api\SearchResultsInterface { /** - * Gets collection items. + * Get items. * * @return \Magento\Sales\Api\Data\OrderInterface[] Array of collection items. */ public function getItems(); + + /** + * Set items. + * + * @param \Magento\Sales\Api\Data\OrderInterface[] $items + * @return $this + */ + public function setItems(array $items = null); } diff --git a/app/code/Magento/Sales/Api/InvoiceManagementInterface.php b/app/code/Magento/Sales/Api/InvoiceManagementInterface.php index 21b17007eaf19..67d6012ad3fc4 100644 --- a/app/code/Magento/Sales/Api/InvoiceManagementInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceManagementInterface.php @@ -44,4 +44,14 @@ public function notify($id); * @return bool */ public function setVoid($id); + + /** + * Prepare order invoice based on order data and requested items qtys. If $qtys is not empty - the function will + * prepare only specified items, otherwise all containing in the order. + * + * @param int $orderId + * @param array $qtys + * @return \Magento\Sales\Api\Data\InvoiceInterface + */ + public function prepareInvoice($orderId, array $qtys = []); } diff --git a/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php b/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php index 23310e2926834..0fa5f268be642 100644 --- a/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/InvoiceRepositoryInterface.php @@ -21,6 +21,13 @@ interface InvoiceRepositoryInterface */ public function getList(\Magento\Framework\Api\SearchCriteria $criteria); + /** + * Return Invoice object + * + * @return \Magento\Sales\Api\Data\InvoiceInterface + */ + public function create(); + /** * Loads a specified invoice. * diff --git a/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php b/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php index eeaa7a0743f1f..e4ff2acf54ba6 100644 --- a/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/OrderPaymentRepositoryInterface.php @@ -46,4 +46,11 @@ public function delete(\Magento\Sales\Api\Data\OrderPaymentInterface $entity); * @return \Magento\Sales\Api\Data\OrderPaymentInterface Order payment interface. */ public function save(\Magento\Sales\Api\Data\OrderPaymentInterface $entity); + + /** + * Creates new Order Payment instance. + * + * @return \Magento\Sales\Api\Data\OrderPaymentInterface Transaction interface. + */ + public function create(); } diff --git a/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php b/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php index 2d19d0f6dbe46..1cfa85d87e66f 100644 --- a/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/ShipmentRepositoryInterface.php @@ -45,4 +45,11 @@ public function delete(\Magento\Sales\Api\Data\ShipmentInterface $entity); * @return \Magento\Sales\Api\Data\ShipmentInterface Shipment interface. */ public function save(\Magento\Sales\Api\Data\ShipmentInterface $entity); + + /** + * Creates new shipment instance. + * + * @return \Magento\Sales\Api\Data\ShipmentInterface Shipment interface. + */ + public function create(); } diff --git a/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php b/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php index 5cada3d87f7a2..7a256e7deaf7c 100644 --- a/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php +++ b/app/code/Magento/Sales/Api/TransactionRepositoryInterface.php @@ -44,4 +44,11 @@ public function delete(\Magento\Sales\Api\Data\TransactionInterface $entity); * @return \Magento\Sales\Api\Data\TransactionInterface Transaction interface. */ public function save(\Magento\Sales\Api\Data\TransactionInterface $entity); + + /** + * Creates new Transaction instance. + * + * @return \Magento\Sales\Api\Data\TransactionInterface Transaction interface. + */ + public function create(); } diff --git a/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php b/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php index 3d6fdb2808578..c05b79c32ce78 100644 --- a/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php +++ b/app/code/Magento/Sales/Block/Adminhtml/Transactions/Detail.php @@ -3,8 +3,11 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Sales\Block\Adminhtml\Transactions; +use Magento\Sales\Api\OrderPaymentRepositoryInterface; + /** * Adminhtml transaction detail * @@ -31,20 +34,28 @@ class Detail extends \Magento\Backend\Block\Widget\Container */ private $adminHelper; + /** + * @var OrderPaymentRepositoryInterface + */ + protected $orderPaymentRepository; + /** * @param \Magento\Backend\Block\Widget\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Sales\Helper\Admin $adminHelper + * @param \Magento\Sales\Api\OrderPaymentRepositoryInterface $orderPaymentRepository * @param array $data */ public function __construct( \Magento\Backend\Block\Widget\Context $context, \Magento\Framework\Registry $registry, \Magento\Sales\Helper\Admin $adminHelper, + OrderPaymentRepositoryInterface $orderPaymentRepository, array $data = [] ) { $this->_coreRegistry = $registry; $this->adminHelper = $adminHelper; + $this->orderPaymentRepository = $orderPaymentRepository; parent::__construct($context, $data); } @@ -70,7 +81,7 @@ protected function _construct() if ($this->_authorization->isAllowed( 'Magento_Sales::transactions_fetch' - ) && $this->_txn->getOrderPaymentObject()->getMethodInstance()->canFetchTransactionInfo() + ) && $this->orderPaymentRepository->get($this->_txn->getId())->getMethodInstance()->canFetchTransactionInfo() ) { $fetchUrl = $this->getUrl('sales/*/fetch', ['_current' => true]); $this->buttonList->add( diff --git a/app/code/Magento/Sales/Controller/AbstractController/PrintCreditmemo.php b/app/code/Magento/Sales/Controller/AbstractController/PrintCreditmemo.php index 4c97760450e22..24f13d49d08c7 100644 --- a/app/code/Magento/Sales/Controller/AbstractController/PrintCreditmemo.php +++ b/app/code/Magento/Sales/Controller/AbstractController/PrintCreditmemo.php @@ -8,6 +8,7 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; +use Magento\Sales\Api\CreditmemoRepositoryInterface; abstract class PrintCreditmemo extends \Magento\Framework\App\Action\Action { @@ -26,21 +27,29 @@ abstract class PrintCreditmemo extends \Magento\Framework\App\Action\Action */ protected $resultPageFactory; + /** + * @var CreditmemoRepositoryInterface + */ + protected $creditmemoRepository; + /** * @param Context $context * @param OrderViewAuthorizationInterface $orderAuthorization * @param \Magento\Framework\Registry $registry * @param PageFactory $resultPageFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository */ public function __construct( Context $context, OrderViewAuthorizationInterface $orderAuthorization, \Magento\Framework\Registry $registry, - PageFactory $resultPageFactory + PageFactory $resultPageFactory, + CreditmemoRepositoryInterface $creditmemoRepository ) { $this->orderAuthorization = $orderAuthorization; $this->_coreRegistry = $registry; $this->resultPageFactory = $resultPageFactory; + $this->creditmemoRepository = $creditmemoRepository; parent::__construct($context); } @@ -53,7 +62,7 @@ public function execute() { $creditmemoId = (int)$this->getRequest()->getParam('creditmemo_id'); if ($creditmemoId) { - $creditmemo = $this->_objectManager->create('Magento\Sales\Model\Order\Creditmemo')->load($creditmemoId); + $creditmemo = $this->creditmemoRepository->get($creditmemoId); $order = $creditmemo->getOrder(); } else { $orderId = (int)$this->getRequest()->getParam('order_id'); diff --git a/app/code/Magento/Sales/Controller/AbstractController/PrintInvoice.php b/app/code/Magento/Sales/Controller/AbstractController/PrintInvoice.php index 15cc2a5c2c48e..04088a9c79c2a 100644 --- a/app/code/Magento/Sales/Controller/AbstractController/PrintInvoice.php +++ b/app/code/Magento/Sales/Controller/AbstractController/PrintInvoice.php @@ -53,7 +53,7 @@ public function execute() { $invoiceId = (int)$this->getRequest()->getParam('invoice_id'); if ($invoiceId) { - $invoice = $this->_objectManager->create('Magento\Sales\Model\Order\Invoice')->load($invoiceId); + $invoice = $this->_objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface')->get($invoiceId); $order = $invoice->getOrder(); } else { $orderId = (int)$this->getRequest()->getParam('order_id'); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/Email.php b/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/Email.php index 98a3b5200f70f..68fc9d62e85ac 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/Email.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/Email.php @@ -31,12 +31,8 @@ public function execute() if (!$creditmemoId) { return; } - $creditmemo = $this->_objectManager->create('Magento\Sales\Model\Order\Creditmemo')->load($creditmemoId); - if (!$creditmemo) { - return; - } - $this->_objectManager->create('Magento\Sales\Model\Order\CreditmemoNotifier') - ->notify($creditmemo); + $this->_objectManager->create('Magento\Sales\Api\CreditmemoManagementInterface') + ->notify($creditmemoId); $this->messageManager->addSuccess(__('You sent the message.')); $resultRedirect = $this->resultRedirectFactory->create(); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/PrintAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/PrintAction.php index a3a52d05c8116..83befcc3b58f9 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/PrintAction.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/PrintAction.php @@ -7,6 +7,7 @@ use Magento\Framework\App\ResponseInterface; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Sales\Api\CreditmemoRepositoryInterface; class PrintAction extends \Magento\Backend\App\Action { @@ -20,18 +21,26 @@ class PrintAction extends \Magento\Backend\App\Action */ protected $resultForwardFactory; + /** + * @var CreditmemoRepositoryInterface + */ + protected $creditmemoRepository; + /** * @param \Magento\Backend\App\Action\Context $context * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository */ public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\App\Response\Http\FileFactory $fileFactory, - \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory + \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, + CreditmemoRepositoryInterface $creditmemoRepository ) { $this->_fileFactory = $fileFactory; $this->resultForwardFactory = $resultForwardFactory; + $this->creditmemoRepository = $creditmemoRepository; parent::__construct($context); } @@ -51,7 +60,7 @@ public function execute() /** @see \Magento\Sales\Controller\Adminhtml\Order\Invoice */ $creditmemoId = $this->getRequest()->getParam('creditmemo_id'); if ($creditmemoId) { - $creditmemo = $this->_objectManager->create('Magento\Sales\Model\Order\Creditmemo')->load($creditmemoId); + $creditmemo = $this->creditmemoRepository->get($creditmemoId); if ($creditmemo) { $pdf = $this->_objectManager->create( 'Magento\Sales\Model\Order\Pdf\Creditmemo' diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/Email.php b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/Email.php index 8436c8f1ceb3b..c807026addf05 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/Email.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/Email.php @@ -51,13 +51,12 @@ public function execute() if (!$invoiceId) { return $this->resultForwardFactory->create()->forward('noroute'); } - $invoice = $this->_objectManager->create('Magento\Sales\Model\Order\Invoice')->load($invoiceId); + $invoice = $this->_objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface')->get($invoiceId); if (!$invoice) { return $this->resultForwardFactory->create()->forward('noroute'); } - $this->_objectManager->create('Magento\Sales\Model\Order\InvoiceNotifier') - ->notify($invoice); + $this->_objectManager->create('Magento\Sales\Api\InvoiceManagementInterface')->notify($invoice->getEntityId()); $this->messageManager->addSuccess(__('You sent the message.')); return $this->resultRedirectFactory->create()->setPath( diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/PrintAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/PrintAction.php index b642486c7f8ce..ac5c97372b7f0 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/PrintAction.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/PrintAction.php @@ -51,7 +51,7 @@ public function execute() { $invoiceId = $this->getRequest()->getParam('invoice_id'); if ($invoiceId) { - $invoice = $this->_objectManager->create('Magento\Sales\Model\Order\Invoice')->load($invoiceId); + $invoice = $this->_objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface')->get($invoiceId); if ($invoice) { $pdf = $this->_objectManager->create('Magento\Sales\Model\Order\Pdf\Invoice')->getPdf([$invoice]); $date = $this->_objectManager->get('Magento\Framework\Stdlib\DateTime\DateTime')->date('Y-m-d_H-i-s'); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/View.php b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/View.php index 53eb15b93933d..e6e49dd0ca65b 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/View.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Invoice/AbstractInvoice/View.php @@ -72,7 +72,7 @@ protected function getInvoice() return false; } /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - $invoice = $this->_objectManager->create('Magento\Sales\Model\Order\Invoice')->load($invoiceId); + $invoice = $this->_objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface')->get($invoiceId); if (!$invoice) { return false; } diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php index 263edb51310c2..bbe955546d34f 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Cancel.php @@ -19,7 +19,8 @@ public function execute() $resultRedirect = $this->resultRedirectFactory->create(); if ($order) { try { - $order->cancel()->save(); + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); + $orderManagement->cancel($order->getEntityId()); $this->messageManager->addSuccess(__('You canceled the order.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php index 10714ace65789..ce4652929c7ba 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Cancel.php @@ -9,10 +9,6 @@ class Cancel extends \Magento\Backend\App\Action { - /** - * @var \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader - */ - protected $creditmemoLoader; /** * @var \Magento\Backend\Model\View\Result\ForwardFactory @@ -21,15 +17,12 @@ class Cancel extends \Magento\Backend\App\Action /** * @param Action\Context $context - * @param \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader $creditmemoLoader * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory */ public function __construct( Action\Context $context, - \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader $creditmemoLoader, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory ) { - $this->creditmemoLoader = $creditmemoLoader; $this->resultForwardFactory = $resultForwardFactory; parent::__construct($context); } @@ -49,30 +42,21 @@ protected function _isAllowed() */ public function execute() { - $this->creditmemoLoader->setOrderId($this->getRequest()->getParam('order_id')); - $this->creditmemoLoader->setCreditmemoId($this->getRequest()->getParam('creditmemo_id')); - $this->creditmemoLoader->setCreditmemo($this->getRequest()->getParam('creditmemo')); - $this->creditmemoLoader->setInvoiceId($this->getRequest()->getParam('invoice_id')); - $creditmemo = $this->creditmemoLoader->load(); - if ($creditmemo) { + $creditmemoId = $this->getRequest()->getParam('creditmemo_id'); + if ($creditmemoId) { try { - $creditmemo->cancel(); - $transactionSave = $this->_objectManager->create('Magento\Framework\DB\Transaction'); - $transactionSave->addObject($creditmemo); - $transactionSave->addObject($creditmemo->getOrder()); - - if ($creditmemo->getInvoice()) { - $transactionSave->addObject($creditmemo->getInvoice()); - } - $transactionSave->save(); + $creditmemoManagement = $this->_objectManager->create( + 'Magento\Sales\Api\CreditmemoManagementInterface' + ); + $creditmemoManagement->cancel($creditmemoId); $this->messageManager->addSuccess(__('The credit memo has been canceled.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); } catch (\Exception $e) { - $this->messageManager->addError(__('You canceled the credit memo.')); + $this->messageManager->addError(__('Credit memo has not been canceled.')); } $resultRedirect = $this->resultRedirectFactory->create(); - $resultRedirect->setPath('sales/*/view', ['creditmemo_id' => $creditmemo->getId()]); + $resultRedirect->setPath('sales/*/view', ['creditmemo_id' => $creditmemoId]); return $resultRedirect; } else { $resultForward = $this->resultForwardFactory->create(); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/PrintAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/PrintAction.php index ae3309c88ebfb..b5bb3333ac32e 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/PrintAction.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/PrintAction.php @@ -7,6 +7,7 @@ use Magento\Framework\App\ResponseInterface; use Magento\Backend\App\Action; +use Magento\Sales\Api\CreditmemoRepositoryInterface; class PrintAction extends \Magento\Sales\Controller\Adminhtml\Creditmemo\AbstractCreditmemo\PrintAction { @@ -15,23 +16,31 @@ class PrintAction extends \Magento\Sales\Controller\Adminhtml\Creditmemo\Abstrac */ protected $creditmemoLoader; + /** + * @var CreditmemoRepositoryInterface + */ + protected $creditmemoRepository; + /** * @param Action\Context $context * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository * @param \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader $creditmemoLoader */ public function __construct( \Magento\Backend\App\Action\Context $context, \Magento\Framework\App\Response\Http\FileFactory $fileFactory, \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory, + CreditmemoRepositoryInterface $creditmemoRepository, \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader $creditmemoLoader ) { $this->creditmemoLoader = $creditmemoLoader; parent::__construct( $context, $fileFactory, - $resultForwardFactory + $resultForwardFactory, + $creditmemoRepository ); } diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php index b9eff656be672..24d74e2177f1c 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Creditmemo/Save.php @@ -92,9 +92,6 @@ public function execute() $creditmemo->setCustomerNoteNotify(isset($data['comment_customer_notify'])); } - if (isset($data['do_refund'])) { - $creditmemo->setRefundRequested(true); - } if (isset($data['do_offline'])) { //do not allow online refund for Refund to Store Credit if (!$data['do_offline'] && !empty($data['refund_customerbalance_return_enable'])) { @@ -102,23 +99,11 @@ public function execute() __('Cannot create online refund for Refund to Store Credit.') ); } - $creditmemo->setOfflineRequested((bool)(int)$data['do_offline']); } - - $creditmemo->register(); - - $creditmemo->getOrder()->setCustomerNoteNotify(!empty($data['send_email'])); - $transactionSave = $this->_objectManager->create( - 'Magento\Framework\DB\Transaction' - )->addObject( - $creditmemo - )->addObject( - $creditmemo->getOrder() + $creditmemoManagement = $this->_objectManager->create( + 'Magento\Sales\Api\CreditmemoManagementInterface' ); - if ($creditmemo->getInvoice()) { - $transactionSave->addObject($creditmemo->getInvoice()); - } - $transactionSave->save(); + $creditmemoManagement->refund($creditmemo, (bool)$data['do_offline'], !empty($data['send_email'])); if (!empty($data['send_email'])) { $this->creditmemoSender->send($creditmemo); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php index ae21770d475e7..cf69855c1489c 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/CreditmemoLoader.php @@ -7,6 +7,8 @@ namespace Magento\Sales\Controller\Adminhtml\Order; use Magento\Framework\DataObject; +use Magento\Sales\Api\CreditmemoRepositoryInterface; +use \Magento\Sales\Model\Order\CreditmemoFactory; /** * Class CreditmemoLoader @@ -24,24 +26,24 @@ class CreditmemoLoader extends DataObject { /** - * @var \Magento\Sales\Model\Order\CreditmemoFactory + * @var CreditmemoRepositoryInterface; */ - protected $creditmemoFactory; + protected $creditmemoRepository; /** - * @var \Magento\Sales\Model\OrderFactory + * @var CreditmemoFactory; */ - protected $orderFactory; + protected $creditmemoFactory; /** - * @var \Magento\Sales\Model\Order\InvoiceFactory + * @var \Magento\Sales\Model\OrderFactory */ - protected $invoiceFactory; + protected $orderFactory; /** - * @var \Magento\Sales\Model\Service\OrderFactory + * @var \Magento\Sales\Api\InvoiceRepositoryInterface */ - protected $orderServiceFactory; + protected $invoiceRepository; /** * @var \Magento\Framework\Event\ManagerInterface @@ -69,10 +71,10 @@ class CreditmemoLoader extends DataObject protected $stockConfiguration; /** - * @param \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository + * @param CreditmemoFactory $creditmemoFactory * @param \Magento\Sales\Model\OrderFactory $orderFactory - * @param \Magento\Sales\Model\Order\InvoiceFactory $invoiceFactory - * @param \Magento\Sales\Model\Service\OrderFactory $orderServiceFactory + * @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Backend\Model\Session $backendSession * @param \Magento\Framework\Message\ManagerInterface $messageManager @@ -82,10 +84,10 @@ class CreditmemoLoader extends DataObject * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( - \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory, + CreditmemoRepositoryInterface $creditmemoRepository, + CreditmemoFactory $creditmemoFactory, \Magento\Sales\Model\OrderFactory $orderFactory, - \Magento\Sales\Model\Order\InvoiceFactory $invoiceFactory, - \Magento\Sales\Model\Service\OrderFactory $orderServiceFactory, + \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository, \Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Backend\Model\Session $backendSession, \Magento\Framework\Message\ManagerInterface $messageManager, @@ -93,10 +95,10 @@ public function __construct( \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration, array $data = [] ) { + $this->creditmemoRepository = $creditmemoRepository; $this->creditmemoFactory = $creditmemoFactory; $this->orderFactory = $orderFactory; - $this->invoiceFactory = $invoiceFactory; - $this->orderServiceFactory = $orderServiceFactory; + $this->invoiceRepository = $invoiceRepository; $this->eventManager = $eventManager; $this->backendSession = $backendSession; $this->messageManager = $messageManager; @@ -158,11 +160,8 @@ protected function _initInvoice($order) { $invoiceId = $this->getInvoiceId(); if ($invoiceId) { - $invoice = $this->invoiceFactory->create()->load( - $invoiceId - )->setOrder( - $order - ); + $invoice = $this->invoiceRepository->get($invoiceId); + $invoice->setOrder($order); if ($invoice->getId()) { return $invoice; } @@ -182,7 +181,7 @@ public function load() $creditmemoId = $this->getCreditmemoId(); $orderId = $this->getOrderId(); if ($creditmemoId) { - $creditmemo = $this->creditmemoFactory->create()->load($creditmemoId); + $creditmemo = $this->creditmemoRepository->get($creditmemoId); } elseif ($orderId) { $data = $this->getCreditmemo(); $order = $this->orderFactory->create()->load($orderId); @@ -206,11 +205,10 @@ public function load() } $data['qtys'] = $qtys; - $service = $this->orderServiceFactory->create(['order' => $order]); if ($invoice) { - $creditmemo = $service->prepareInvoiceCreditmemo($invoice, $data); + $creditmemo = $this->creditmemoFactory->createByInvoice($invoice, $data); } else { - $creditmemo = $service->prepareCreditmemo($data); + $creditmemo = $this->creditmemoFactory->createByOrder($order, $data); } /** diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php index e2dce6e111b8e..cae0ea11baacd 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Email.php @@ -17,7 +17,8 @@ public function execute() $order = $this->_initOrder(); if ($order) { try { - $this->_objectManager->create('Magento\Sales\Model\OrderNotifier')->notify($order); + $orderManagement = $this->_objectManager->create('Magento\Sales\Api\OrderManagementInterface'); + $orderManagement->notify($order->getEntityId()); $this->messageManager->addSuccess(__('You sent the order email.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Hold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Hold.php index 58a54b87f0ed9..ba69fe6510059 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Hold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Hold.php @@ -18,7 +18,8 @@ public function execute() $resultRedirect = $this->resultRedirectFactory->create(); if ($order) { try { - $order->hold()->save(); + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); + $orderManagement->hold($order->getEntityId()); $this->messageManager->addSuccess(__('You put the order on hold.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Capture.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Capture.php index 20ff3bfeaa9ab..50ab1d8a9f2bf 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Capture.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Capture.php @@ -23,7 +23,8 @@ public function execute() return $resultForward; } try { - $invoice->capture(); + $invoiceManagement = $this->_objectManager->get('Magento\Sales\Api\InvoiceManagementInterface'); + $invoiceManagement->setCapture($invoice->getEntityId()); $invoice->getOrder()->setIsInProcess(true); $this->_objectManager->create( 'Magento\Framework\DB\Transaction' diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php index b0a7f1ed4d2ad..cf6e90e398abe 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/NewAction.php @@ -82,10 +82,9 @@ public function execute() __('The order does not allow an invoice to be created.') ); } - + $invoiceManagement = $this->_objectManager->create('Magento\Sales\Api\InvoiceManagementInterface'); /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - $invoice = $this->_objectManager->create('Magento\Sales\Model\Service\Order', ['order' => $order]) - ->prepareInvoice($invoiceItems); + $invoice = $invoiceManagement->prepareInvoice($orderId, $invoiceItems); if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php index a30fcb59b995e..aa3af5fc1618d 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Save.php @@ -11,6 +11,7 @@ use Magento\Framework\Registry; use Magento\Sales\Model\Order\Email\Sender\InvoiceSender; use Magento\Sales\Model\Order\Email\Sender\ShipmentSender; +use Magento\Sales\Model\Order\ShipmentFactory; use Magento\Sales\Model\Order\Invoice; /** @@ -28,6 +29,11 @@ class Save extends \Magento\Backend\App\Action */ protected $shipmentSender; + /** + * @var ShipmentFactory + */ + protected $shipmentFactory; + /** * @var Registry */ @@ -38,16 +44,19 @@ class Save extends \Magento\Backend\App\Action * @param Registry $registry * @param InvoiceSender $invoiceSender * @param ShipmentSender $shipmentSender + * @param ShipmentFactory $shipmentFactory */ public function __construct( Action\Context $context, Registry $registry, InvoiceSender $invoiceSender, - ShipmentSender $shipmentSender + ShipmentSender $shipmentSender, + ShipmentFactory $shipmentFactory ) { $this->registry = $registry; $this->invoiceSender = $invoiceSender; $this->shipmentSender = $shipmentSender; + $this->shipmentFactory = $shipmentFactory; parent::__construct($context); } @@ -67,30 +76,19 @@ protected function _isAllowed() */ protected function _prepareShipment($invoice) { - $savedQtys = []; - $data = $this->getRequest()->getParam('invoice'); - if (isset($data['items'])) { - $savedQtys = $data['items']; - } - $shipment = $this->_objectManager->create( - 'Magento\Sales\Model\Service\Order', - ['order' => $invoice->getOrder()] - )->prepareShipment( - $savedQtys + $invoiceData = $this->getRequest()->getParam('invoice'); + + $shipment = $this->shipmentFactory->create( + $invoice->getOrder(), + isset($invoiceData['items']) ? $invoiceData['items'] : [], + $this->getRequest()->getPost('tracking') ); + if (!$shipment->getTotalQty()) { return false; } - $shipment->register(); - $tracks = $this->getRequest()->getPost('tracking'); - if ($tracks) { - foreach ($tracks as $data) { - $track = $this->_objectManager->create('Magento\Sales\Model\Order\Shipment\Track')->addData($data); - $shipment->addTrack($track); - } - } - return $shipment; + return $shipment->register(); } /** @@ -129,9 +127,9 @@ public function execute() ); } + $invoiceManagement = $this->_objectManager->create('Magento\Sales\Api\InvoiceManagementInterface'); /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - $invoice = $this->_objectManager->create('Magento\Sales\Model\Service\Order', ['order' => $order]) - ->prepareInvoice($invoiceItems); + $invoice = $invoiceManagement->prepareInvoice($orderId, $invoiceItems); if (!$invoice) { throw new LocalizedException(__('We can\'t save the invoice right now.')); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php index 85c51e0934339..7aee9d0e16cd9 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/UpdateQty.php @@ -77,8 +77,8 @@ public function execute() } /** @var \Magento\Sales\Model\Order\Invoice $invoice */ - $invoice = $this->_objectManager->create('Magento\Sales\Model\Service\Order', ['order' => $order]) - ->prepareInvoice($invoiceItems); + $invoiceManagement = $this->_objectManager->create('Magento\Sales\Api\InvoiceManagementInterface'); + $invoice = $invoiceManagement->prepareInvoice($orderId, $invoiceItems); if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Void.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Void.php index 9f346af8a27c0..841d517037b43 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Void.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Invoice/Void.php @@ -22,7 +22,10 @@ public function execute() return $resultForward->forward('noroute'); } try { - $invoice->void(); + /** @var \Magento\Sales\Api\InvoiceManagementInterface $invoiceManagement */ + $invoiceManagement = $this->_objectManager->get('Magento\Sales\Api\InvoiceManagementInterface'); + $invoiceManagement->setVoid($invoice->getEntityId()); + $invoice->getOrder()->setIsInProcess(true); $this->_objectManager->create( 'Magento\Framework\DB\Transaction' diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassCancel.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassCancel.php index 731363167b016..24330e58bf0d8 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassCancel.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassCancel.php @@ -13,17 +13,19 @@ class MassCancel extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassA * Cancel selected orders * * @param AbstractCollection $collection - * @return \Magento\Backend\Model\View\Result\Redirect + * @return void */ protected function massAction(AbstractCollection $collection) { $countCancelOrder = 0; + + /** @var \Magento\Sales\Api\OrderManagementInterface $orderManagement */ + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); foreach ($collection->getItems() as $order) { if (!$order->canCancel()) { continue; } - $order->cancel(); - $order->save(); + $orderManagement->cancel($order->getEntityId()); $countCancelOrder++; } $countNonCancelOrder = $collection->count() - $countCancelOrder; @@ -37,8 +39,5 @@ protected function massAction(AbstractCollection $collection) if ($countCancelOrder) { $this->messageManager->addSuccess(__('We canceled %1 order(s).', $countCancelOrder)); } - $resultRedirect = $this->resultRedirectFactory->create(); - $resultRedirect->setPath('sales/*/'); - return $resultRedirect; } } diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php index c10ab68f62078..cce9ab02eb325 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php @@ -18,12 +18,12 @@ class MassHold extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAct protected function massAction(AbstractCollection $collection) { $countHoldOrder = 0; + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); foreach ($collection->getItems() as $order) { if (!$order->canHold()) { continue; } - $order->hold(); - $order->save(); + $orderManagement->hold($order->getEntityId()); $countHoldOrder++; } $countNonHoldOrder = $collection->count() - $countHoldOrder; diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php index 80107a9f4ad8e..307f8dae53735 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php @@ -9,6 +9,11 @@ class MassUnhold extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction { + /** + * @var string + */ + protected $collection = 'Magento\Sales\Model\Resource\Order\Collection'; + /** * Unhold selected orders * @@ -19,12 +24,12 @@ protected function massAction(AbstractCollection $collection) { $countUnHoldOrder = 0; + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); foreach ($collection->getItems() as $order) { if (!$order->canUnhold()) { continue; } - $order->unhold(); - $order->save(); + $orderManagement->unHold($order->getEntityId()); $countUnHoldOrder++; } diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/Unhold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/Unhold.php index c57f4ca425146..186e70709e3ba 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/Unhold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/Unhold.php @@ -18,7 +18,11 @@ public function execute() $resultRedirect = $this->resultRedirectFactory->create(); if ($order) { try { - $order->unhold()->save(); + $orderManagement = $this->_objectManager->get('Magento\Sales\Api\OrderManagementInterface'); + if (!$order->canUnhold()) { + throw new \Magento\Framework\Exception\LocalizedException(__('Can\'t unhold order.')); + } + $orderManagement->unhold($order->getEntityId()); $this->messageManager->addSuccess(__('You released the order from holding status.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Transactions.php b/app/code/Magento/Sales/Controller/Adminhtml/Transactions.php index c64aec9aa8603..f5e76708f71e9 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Transactions.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Transactions.php @@ -9,6 +9,7 @@ use Magento\Framework\Registry; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\View\Result\LayoutFactory; +use Magento\Sales\Api\OrderPaymentRepositoryInterface; /** * Adminhtml sales transactions controller @@ -34,21 +35,29 @@ abstract class Transactions extends \Magento\Backend\App\Action */ protected $resultLayoutFactory; + /** + * @var OrderPaymentRepositoryInterface + */ + protected $orderPaymentRepository; + /** * @param \Magento\Backend\App\Action\Context $context * @param Registry $coreRegistry * @param PageFactory $resultPageFactory * @param LayoutFactory $resultLayoutFactory + * @param OrderPaymentRepositoryInterface $orderPaymentRepository */ public function __construct( \Magento\Backend\App\Action\Context $context, Registry $coreRegistry, PageFactory $resultPageFactory, - LayoutFactory $resultLayoutFactory + LayoutFactory $resultLayoutFactory, + OrderPaymentRepositoryInterface $orderPaymentRepository ) { $this->_coreRegistry = $coreRegistry; $this->resultPageFactory = $resultPageFactory; $this->resultLayoutFactory = $resultLayoutFactory; + $this->orderPaymentRepository = $orderPaymentRepository; parent::__construct($context); } diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php b/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php index 6b2af6cc1dd5f..df3a48ca4a76d 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Transactions/Fetch.php @@ -26,7 +26,7 @@ public function execute() return $resultRedirect->setPath('sales/*/'); } try { - $txn->getOrderPaymentObject()->setOrder($txn->getOrder())->importTransactionInfo($txn); + $this->orderPaymentRepository->get($txn->getId())->setOrder($txn->getOrder())->importTransactionInfo($txn); $txn->save(); $this->messageManager->addSuccess(__('The transaction details have been updated.')); } catch (\Magento\Framework\Exception\LocalizedException $e) { diff --git a/app/code/Magento/Sales/Controller/Guest/PrintCreditmemo.php b/app/code/Magento/Sales/Controller/Guest/PrintCreditmemo.php index 82a1a215399d6..5b6fd6c5a6a10 100644 --- a/app/code/Magento/Sales/Controller/Guest/PrintCreditmemo.php +++ b/app/code/Magento/Sales/Controller/Guest/PrintCreditmemo.php @@ -8,6 +8,7 @@ use Magento\Framework\App\Action\Context; use Magento\Framework\View\Result\PageFactory; +use Magento\Sales\Api\CreditmemoRepositoryInterface; class PrintCreditmemo extends \Magento\Sales\Controller\AbstractController\PrintCreditmemo { @@ -16,11 +17,17 @@ class PrintCreditmemo extends \Magento\Sales\Controller\AbstractController\Print */ protected $orderLoader; + /** + * @var CreditmemoRepositoryInterface; + */ + protected $creditmemoRepository; + /** * @param Context $context * @param OrderViewAuthorization $orderAuthorization * @param \Magento\Framework\Registry $registry * @param PageFactory $resultPageFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository * @param OrderLoader $orderLoader */ public function __construct( @@ -28,14 +35,17 @@ public function __construct( OrderViewAuthorization $orderAuthorization, \Magento\Framework\Registry $registry, PageFactory $resultPageFactory, + CreditmemoRepositoryInterface $creditmemoRepository, OrderLoader $orderLoader ) { $this->orderLoader = $orderLoader; + $this->creditmemoRepository = $creditmemoRepository; parent::__construct( $context, $orderAuthorization, $registry, - $resultPageFactory + $resultPageFactory, + $creditmemoRepository ); } @@ -51,7 +61,7 @@ public function execute() $creditmemoId = (int)$this->getRequest()->getParam('creditmemo_id'); if ($creditmemoId) { - $creditmemo = $this->_objectManager->create('Magento\Sales\Model\Order\Creditmemo')->load($creditmemoId); + $creditmemo = $this->creditmemoRepository->get($creditmemoId); $order = $creditmemo->getOrder(); } else { $order = $this->_coreRegistry->registry('current_order'); diff --git a/app/code/Magento/Sales/Controller/Guest/PrintInvoice.php b/app/code/Magento/Sales/Controller/Guest/PrintInvoice.php index 27796157f51c3..ddd943b3246b5 100644 --- a/app/code/Magento/Sales/Controller/Guest/PrintInvoice.php +++ b/app/code/Magento/Sales/Controller/Guest/PrintInvoice.php @@ -51,7 +51,7 @@ public function execute() $invoiceId = (int)$this->getRequest()->getParam('invoice_id'); if ($invoiceId) { - $invoice = $this->_objectManager->create('Magento\Sales\Model\Order\Invoice')->load($invoiceId); + $invoice = $this->_objectManager->create('Magento\Sales\Api\InvoiceRepositoryInterface')->get($invoiceId); $order = $invoice->getOrder(); } else { $order = $this->_coreRegistry->registry('current_order'); diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php index e10d73f241f5a..244cc11fdb384 100644 --- a/app/code/Magento/Sales/Model/AdminOrder/Create.php +++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php @@ -214,6 +214,11 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\ */ protected $dataObjectHelper; + /** + * @var \Magento\Sales\Api\OrderManagementInterface + */ + protected $orderManagement; + /** * @param \Magento\Framework\ObjectManagerInterface $objectManager * @param \Magento\Framework\Event\ManagerInterface $eventManager @@ -240,6 +245,7 @@ class Create extends \Magento\Framework\DataObject implements \Magento\Checkout\ * @param \Magento\Customer\Model\Customer\Mapper $customerMapper * @param \Magento\Quote\Model\QuoteManagement $quoteManagement * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper + * @param \Magento\Sales\Api\OrderManagementInterface $orderManagement * @param array $data * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -269,6 +275,7 @@ public function __construct( \Magento\Customer\Model\Customer\Mapper $customerMapper, \Magento\Quote\Model\QuoteManagement $quoteManagement, \Magento\Framework\Api\DataObjectHelper $dataObjectHelper, + \Magento\Sales\Api\OrderManagementInterface $orderManagement, array $data = [] ) { $this->_objectManager = $objectManager; @@ -296,6 +303,7 @@ public function __construct( $this->customerMapper = $customerMapper; $this->quoteManagement = $quoteManagement; $this->dataObjectHelper = $dataObjectHelper; + $this->orderManagement = $orderManagement; parent::__construct($data); } @@ -1858,7 +1866,7 @@ public function createOrder() $oldOrder = $this->getSession()->getOrder(); $oldOrder->setRelationChildId($order->getId()); $oldOrder->setRelationChildRealId($order->getIncrementId()); - $oldOrder->cancel()->save(); + $this->orderManagement->cancel($oldOrder->getEntityId()); $order->save(); } if ($this->getSendConfirmation()) { diff --git a/app/code/Magento/Sales/Model/Convert/Order.php b/app/code/Magento/Sales/Model/Convert/Order.php index 6e386b4c6813c..d6245d46df5f2 100644 --- a/app/code/Magento/Sales/Model/Convert/Order.php +++ b/app/code/Magento/Sales/Model/Convert/Order.php @@ -22,9 +22,9 @@ class Order extends \Magento\Framework\DataObject protected $_eventManager = null; /** - * @var \Magento\Sales\Model\Order\Invoice + * @var \Magento\Sales\Api\InvoiceRepositoryInterface */ - protected $_orderInvoiceFactory; + protected $invoiceRepository; /** * @var \Magento\Sales\Model\Order\Invoice\ItemFactory @@ -32,14 +32,14 @@ class Order extends \Magento\Framework\DataObject protected $_invoiceItemFactory; /** - * @var \Magento\Sales\Model\Order\ShipmentFactory + * @var \Magento\Sales\Model\Order\ShipmentRepository */ - protected $_orderShipmentFactory; + protected $shipmentRepository; /** - * @var \Magento\Sales\Model\Order\CreditmemoFactory + * @var \Magento\Sales\Api\CreditmemoRepositoryInterface */ - protected $_creditmemoFactory; + protected $creditmemoRepository; /** * @var \Magento\Sales\Model\Order\Creditmemo\ItemFactory @@ -53,11 +53,11 @@ class Order extends \Magento\Framework\DataObject /** * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Sales\Model\Order\InvoiceFactory $orderInvoiceFactory + * @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository * @param \Magento\Sales\Model\Order\Invoice\ItemFactory $invoiceItemFactory - * @param \Magento\Sales\Model\Order\ShipmentFactory $orderShipmentFactory + * @param \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository * @param \Magento\Sales\Model\Order\Shipment\ItemFactory $shipmentItemFactory - * @param \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory + * @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository * @param \Magento\Sales\Model\Order\Creditmemo\ItemFactory $creditmemoItemFactory * @param \Magento\Framework\DataObject\Copy $objectCopyService * @param array $data @@ -66,21 +66,21 @@ class Order extends \Magento\Framework\DataObject */ public function __construct( \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Sales\Model\Order\InvoiceFactory $orderInvoiceFactory, + \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository, \Magento\Sales\Model\Order\Invoice\ItemFactory $invoiceItemFactory, - \Magento\Sales\Model\Order\ShipmentFactory $orderShipmentFactory, + \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository, \Magento\Sales\Model\Order\Shipment\ItemFactory $shipmentItemFactory, - \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory, + \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository, \Magento\Sales\Model\Order\Creditmemo\ItemFactory $creditmemoItemFactory, \Magento\Framework\DataObject\Copy $objectCopyService, array $data = [] ) { $this->_eventManager = $eventManager; - $this->_orderInvoiceFactory = $orderInvoiceFactory; + $this->invoiceRepository = $invoiceRepository; $this->_invoiceItemFactory = $invoiceItemFactory; - $this->_orderShipmentFactory = $orderShipmentFactory; + $this->shipmentRepository = $shipmentRepository; $this->_shipmentItemFactory = $shipmentItemFactory; - $this->_creditmemoFactory = $creditmemoFactory; + $this->creditmemoRepository = $creditmemoRepository; $this->_creditmemoItemFactory = $creditmemoItemFactory; $this->_objectCopyService = $objectCopyService; parent::__construct($data); @@ -94,7 +94,7 @@ public function __construct( */ public function toInvoice(\Magento\Sales\Model\Order $order) { - $invoice = $this->_orderInvoiceFactory->create(); + $invoice = $this->invoiceRepository->create(); $invoice->setOrder( $order )->setStoreId( @@ -139,7 +139,7 @@ public function itemToInvoiceItem(\Magento\Sales\Model\Order\Item $item) */ public function toShipment(\Magento\Sales\Model\Order $order) { - $shipment = $this->_orderShipmentFactory->create(); + $shipment = $this->shipmentRepository->create(); $shipment->setOrder( $order )->setStoreId( @@ -184,7 +184,7 @@ public function itemToShipmentItem(\Magento\Sales\Model\Order\Item $item) */ public function toCreditmemo(\Magento\Sales\Model\Order $order) { - $creditmemo = $this->_creditmemoFactory->create(); + $creditmemo = $this->creditmemoRepository->create(); $creditmemo->setOrder( $order )->setStoreId( diff --git a/app/code/Magento/Sales/Model/EntityStorage.php b/app/code/Magento/Sales/Model/EntityStorage.php new file mode 100644 index 0000000000000..b5932c74b8374 --- /dev/null +++ b/app/code/Magento/Sales/Model/EntityStorage.php @@ -0,0 +1,130 @@ +getId()) { + throw new \Magento\Framework\Exception\InputException(__('Id required')); + } + $this->storageMapper[$storageName][$this->getHash($identifyingFields)] = $object->getId(); + $this->registry[$object->getId()] = $object; + } + + /** + * Add entity to registry if entity in it + * + * @param \Magento\Framework\Model\AbstractModel $entity + * @return void + */ + public function add($entity) + { + $this->registry[$entity->getId()] = $entity; + } + + /** + * Retrieve entity from registry if entity in it + * + * @param int $id + * @return bool|FrameworkAbstractModel + */ + public function get($id) + { + if ($this->has($id)) { + return $this->registry[$id]; + } + return false; + } + + /** + * Gets entity by identifying fields + * + * @param array $identifyingFields + * @param string $storageName + * @return bool|FrameworkAbstractModel + */ + public function getByIdentifyingFields(array $identifyingFields, $storageName) + { + $hash = $this->getHash($identifyingFields); + if (isset($this->storageMapper[$storageName][$hash])) { + return $this->get($this->storageMapper[$storageName][$hash]); + } + return false; + } + + /** + * Remove entity from storage + * + * @param int $id + * @return void + */ + public function remove($id) + { + if ($this->has($id)) { + unset($this->registry[$id]); + } + } + + /** + * Checks if entity is in storage + * + * @param int $id + * @return bool + */ + public function has($id) + { + return isset($this->registry[$id]); + } + + /** + * Gets hash using concatenation of identifying fields + * + * @param array $fields + * @return string + */ + protected function getHash(array $fields) + { + $stringForKey = implode(self::GLUE, $fields); + return sha1($stringForKey); + } +} diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index f1faf18a39fa7..87dffadfa8dfd 100755 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -203,9 +203,9 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface protected $_productVisibility; /** - * @var \Magento\Sales\Model\Service\OrderFactory + * @var \Magento\Sales\Api\InvoiceManagementInterface */ - protected $_serviceOrderFactory; + protected $invoiceManagement; /** * @var \Magento\Directory\Model\CurrencyFactory @@ -273,7 +273,7 @@ class Order extends AbstractModel implements EntityInterface, OrderInterface * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param Resource\Order\Item\CollectionFactory $orderItemCollectionFactory * @param \Magento\Catalog\Model\Product\Visibility $productVisibility - * @param Service\OrderFactory $serviceOrderFactory + * @param \Magento\Sales\Api\InvoiceManagementInterface $invoiceManagement * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory * @param \Magento\Eav\Model\Config $eavConfig * @param Order\Status\HistoryFactory $orderHistoryFactory @@ -302,7 +302,7 @@ public function __construct( \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, \Magento\Sales\Model\Resource\Order\Item\CollectionFactory $orderItemCollectionFactory, \Magento\Catalog\Model\Product\Visibility $productVisibility, - \Magento\Sales\Model\Service\OrderFactory $serviceOrderFactory, + \Magento\Sales\Api\InvoiceManagementInterface $invoiceManagement, \Magento\Directory\Model\CurrencyFactory $currencyFactory, \Magento\Eav\Model\Config $eavConfig, \Magento\Sales\Model\Order\Status\HistoryFactory $orderHistoryFactory, @@ -326,7 +326,7 @@ public function __construct( $this->timezone = $timezone; $this->_orderItemCollectionFactory = $orderItemCollectionFactory; $this->_productVisibility = $productVisibility; - $this->_serviceOrderFactory = $serviceOrderFactory; + $this->invoiceManagement = $invoiceManagement; $this->_currencyFactory = $currencyFactory; $this->_eavConfig = $eavConfig; $this->_orderHistoryFactory = $orderHistoryFactory; @@ -1867,20 +1867,7 @@ public function getIsNotVirtual() */ public function prepareInvoice($qtys = []) { - $invoice = $this->_serviceOrderFactory->create(['order' => $this])->prepareInvoice($qtys); - return $invoice; - } - - /** - * Create new shipment with maximum qty for shipping for each item - * - * @param array $qtys - * @return \Magento\Sales\Model\Order\Shipment - */ - public function prepareShipment($qtys = []) - { - $shipment = $this->_serviceOrderFactory->create(['order' => $this])->prepareShipment($qtys); - return $shipment; + return $this->invoiceManagement->prepareInvoice($this->getEntityId(), $qtys); } /** diff --git a/app/code/Magento/Sales/Model/Order/AddressRepository.php b/app/code/Magento/Sales/Model/Order/AddressRepository.php new file mode 100644 index 0000000000000..3e5d98aec70b4 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/AddressRepository.php @@ -0,0 +1,163 @@ +metadata = $metadata; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * Loads a specified order address. + * + * @param int $id + * @return \Magento\Sales\Api\Data\OrderAddressInterface + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function get($id) + { + if (!$id) { + throw new InputException(__('Id required')); + } + + if (!isset($this->registry[$id])) { + /** @var \Magento\Sales\Api\Data\OrderAddressInterface $entity */ + $entity = $this->metadata->getNewInstance(); + + $this->metadata->getMapper()->load($entity, $id); + + if (!$entity->getEntityId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + + $this->registry[$id] = $entity; + } + + return $this->registry[$id]; + } + + /** + * Find order addresses by criteria. + * + * @param \Magento\Framework\Api\SearchCriteria $criteria + * @return \Magento\Sales\Api\Data\OrderAddressInterface[] + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + //@TODO: fix search logic + /** @var \Magento\Sales\Api\Data\OrderAddressSearchResultInterface $searchResult */ + $searchResult = $this->searchResultFactory->create(); + + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + + $searchResult->setCurPage($criteria->getCurrentPage()); + $searchResult->setPageSize($criteria->getPageSize()); + + return $searchResult; + } + + /** + * Deletes a specified order address. + * + * @param \Magento\Sales\Api\Data\OrderAddressInterface $entity + * @return bool + * @throws CouldNotDeleteException + */ + public function delete(\Magento\Sales\Api\Data\OrderAddressInterface $entity) + { + try { + $this->metadata->getMapper()->delete($entity); + + unset($this->registry[$entity->getEntityId()]); + } catch (\Exception $e) { + throw new CouldNotDeleteException(__('Could not delete order address'), $e); + } + + return true; + } + + /** + * Deletes order address by Id. + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->get($id); + + return $this->delete($entity); + } + + /** + * Performs persist operations for a specified order address. + * + * @param \Magento\Sales\Api\Data\OrderAddressInterface $entity + * @return \Magento\Sales\Api\Data\OrderAddressInterface + * @throws CouldNotSaveException + */ + public function save(\Magento\Sales\Api\Data\OrderAddressInterface $entity) + { + try { + $this->metadata->getMapper()->save($entity); + $this->registry[$entity->getEntityId()] = $entity; + } catch (\Exception $e) { + throw new CouldNotSaveException(__('Could not save order address'), $e); + } + + return $this->registry[$entity->getEntityId()]; + } + + /** + * Creates new order address instance. + * + * @return \Magento\Sales\Api\Data\OrderAddressInterface + */ + public function create() + { + return $this->metadata->getNewInstance(); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Creditmemo.php b/app/code/Magento/Sales/Model/Order/Creditmemo.php index 56d1c892985da..9ec06e8350adb 100644 --- a/app/code/Magento/Sales/Model/Order/Creditmemo.php +++ b/app/code/Magento/Sales/Model/Order/Creditmemo.php @@ -432,174 +432,6 @@ public function canVoid() return $canVoid; } - /** - * @return $this - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function refund() - { - $this->setState(self::STATE_REFUNDED); - $orderRefund = $this->priceCurrency->round( - $this->getOrder()->getTotalRefunded() + $this->getGrandTotal() - ); - $baseOrderRefund = $this->priceCurrency->round( - $this->getOrder()->getBaseTotalRefunded() + $this->getBaseGrandTotal() - ); - - if ($baseOrderRefund > $this->priceCurrency->round($this->getOrder()->getBaseTotalPaid())) { - $baseAvailableRefund = $this->getOrder()->getBaseTotalPaid() - $this->getOrder()->getBaseTotalRefunded(); - - throw new LocalizedException( - __( - 'The most money available to refund is %1.', - $this->getOrder()->formatBasePrice($baseAvailableRefund) - ) - ); - } - $order = $this->getOrder(); - $order->setBaseTotalRefunded($baseOrderRefund); - $order->setTotalRefunded($orderRefund); - - $order->setBaseSubtotalRefunded($order->getBaseSubtotalRefunded() + $this->getBaseSubtotal()); - $order->setSubtotalRefunded($order->getSubtotalRefunded() + $this->getSubtotal()); - - $order->setBaseTaxRefunded($order->getBaseTaxRefunded() + $this->getBaseTaxAmount()); - $order->setTaxRefunded($order->getTaxRefunded() + $this->getTaxAmount()); - $order->setBaseDiscountTaxCompensationRefunded($order->getBaseDiscountTaxCompensationRefunded() + $this->getBaseDiscountTaxCompensationAmount()); - $order->setDiscountTaxCompensationRefunded($order->getDiscountTaxCompensationRefunded() + $this->getDiscountTaxCompensationAmount()); - - $order->setBaseShippingRefunded($order->getBaseShippingRefunded() + $this->getBaseShippingAmount()); - $order->setShippingRefunded($order->getShippingRefunded() + $this->getShippingAmount()); - - $order->setBaseShippingTaxRefunded($order->getBaseShippingTaxRefunded() + $this->getBaseShippingTaxAmount()); - $order->setShippingTaxRefunded($order->getShippingTaxRefunded() + $this->getShippingTaxAmount()); - - $order->setAdjustmentPositive($order->getAdjustmentPositive() + $this->getAdjustmentPositive()); - $order->setBaseAdjustmentPositive($order->getBaseAdjustmentPositive() + $this->getBaseAdjustmentPositive()); - - $order->setAdjustmentNegative($order->getAdjustmentNegative() + $this->getAdjustmentNegative()); - $order->setBaseAdjustmentNegative($order->getBaseAdjustmentNegative() + $this->getBaseAdjustmentNegative()); - - $order->setDiscountRefunded($order->getDiscountRefunded() + $this->getDiscountAmount()); - $order->setBaseDiscountRefunded($order->getBaseDiscountRefunded() + $this->getBaseDiscountAmount()); - - if ($this->getInvoice()) { - $this->getInvoice()->setIsUsedForRefund(true); - $this->getInvoice()->setBaseTotalRefunded( - $this->getInvoice()->getBaseTotalRefunded() + $this->getBaseGrandTotal() - ); - $this->setInvoiceId($this->getInvoice()->getId()); - } - - if (!$this->getPaymentRefundDisallowed()) { - $order->getPayment()->refund($this); - } - - $this->_eventManager->dispatch('sales_order_creditmemo_refund', [$this->_eventObject => $this]); - return $this; - } - - /** - * Cancel Creditmemo action - * - * @return $this - */ - public function cancel() - { - $this->setState(self::STATE_CANCELED); - foreach ($this->getAllItems() as $item) { - $item->cancel(); - } - $this->getOrder()->getPayment()->cancelCreditmemo($this); - - if ($this->getTransactionId()) { - $this->getOrder()->setTotalOnlineRefunded( - $this->getOrder()->getTotalOnlineRefunded() - $this->getGrandTotal() - ); - $this->getOrder()->setBaseTotalOnlineRefunded( - $this->getOrder()->getBaseTotalOnlineRefunded() - $this->getBaseGrandTotal() - ); - } else { - $this->getOrder()->setTotalOfflineRefunded( - $this->getOrder()->getTotalOfflineRefunded() - $this->getGrandTotal() - ); - $this->getOrder()->setBaseTotalOfflineRefunded( - $this->getOrder()->getBaseTotalOfflineRefunded() - $this->getBaseGrandTotal() - ); - } - - $this->getOrder()->setBaseSubtotalRefunded( - $this->getOrder()->getBaseSubtotalRefunded() - $this->getBaseSubtotal() - ); - $this->getOrder()->setSubtotalRefunded($this->getOrder()->getSubtotalRefunded() - $this->getSubtotal()); - - $this->getOrder()->setBaseTaxRefunded($this->getOrder()->getBaseTaxRefunded() - $this->getBaseTaxAmount()); - $this->getOrder()->setTaxRefunded($this->getOrder()->getTaxRefunded() - $this->getTaxAmount()); - - $this->getOrder()->setBaseShippingRefunded( - $this->getOrder()->getBaseShippingRefunded() - $this->getBaseShippingAmount() - ); - $this->getOrder()->setShippingRefunded($this->getOrder()->getShippingRefunded() - $this->getShippingAmount()); - - $this->_eventManager->dispatch('sales_order_creditmemo_cancel', [$this->_eventObject => $this]); - return $this; - } - - /** - * Register creditmemo - * - * Apply to order, order items etc. - * - * @return $this - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function register() - { - if ($this->getId()) { - throw new LocalizedException(__('We cannot register an existing credit memo.')); - } - - foreach ($this->getAllItems() as $item) { - if ($item->getQty() > 0) { - $item->register(); - } else { - $item->isDeleted(true); - } - } - - $this->setDoTransaction(true); - if ($this->getOfflineRequested()) { - $this->setDoTransaction(false); - } - $this->refund(); - - if ($this->getDoTransaction()) { - $this->getOrder()->setTotalOnlineRefunded( - $this->getOrder()->getTotalOnlineRefunded() + $this->getGrandTotal() - ); - $this->getOrder()->setBaseTotalOnlineRefunded( - $this->getOrder()->getBaseTotalOnlineRefunded() + $this->getBaseGrandTotal() - ); - } else { - $this->getOrder()->setTotalOfflineRefunded( - $this->getOrder()->getTotalOfflineRefunded() + $this->getGrandTotal() - ); - $this->getOrder()->setBaseTotalOfflineRefunded( - $this->getOrder()->getBaseTotalOfflineRefunded() + $this->getBaseGrandTotal() - ); - } - - $this->getOrder()->setBaseTotalInvoicedCost( - $this->getOrder()->getBaseTotalInvoicedCost() - $this->getBaseCost() - ); - - $state = $this->getState(); - if (is_null($state)) { - $this->setState(self::STATE_OPEN); - } - return $this; - } - /** * Retrieve Creditmemo states array * diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php b/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php new file mode 100644 index 0000000000000..a4d36f9095ba6 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/CreditmemoFactory.php @@ -0,0 +1,248 @@ +convertor = $convertOrderFactory->create(); + $this->taxConfig = $taxConfig; + } + + /** + * Prepare order creditmemo based on order items and requested params + * + * @param \Magento\Sales\Model\Order $order + * @param array $data + * @return Creditmemo + */ + public function createByOrder(\Magento\Sales\Model\Order $order, array $data = []) + { + $totalQty = 0; + $creditmemo = $this->convertor->toCreditmemo($order); + $qtys = isset($data['qtys']) ? $data['qtys'] : []; + + foreach ($order->getAllItems() as $orderItem) { + if (!$this->canRefundItem($orderItem, $qtys)) { + continue; + } + + $item = $this->convertor->itemToCreditmemoItem($orderItem); + if ($orderItem->isDummy()) { + $qty = 1; + $orderItem->setLockedDoShip(true); + } else { + if (isset($qtys[$orderItem->getId()])) { + $qty = (double)$qtys[$orderItem->getId()]; + } elseif (!count($qtys)) { + $qty = $orderItem->getQtyToRefund(); + } else { + continue; + } + } + $totalQty += $qty; + $item->setQty($qty); + $creditmemo->addItem($item); + } + $creditmemo->setTotalQty($totalQty); + + $this->initData($creditmemo, $data); + + $creditmemo->collectTotals(); + return $creditmemo; + } + + /** + * Prepare order creditmemo based on invoice and requested params + * + * @param \Magento\Sales\Model\Order\Invoice $invoice + * @param array $data + * @return Creditmemo + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function createByInvoice(\Magento\Sales\Model\Order\Invoice $invoice, array $data = []) + { + $order = $invoice->getOrder(); + $totalQty = 0; + $qtys = isset($data['qtys']) ? $data['qtys'] : []; + $creditmemo = $this->convertor->toCreditmemo($order); + $creditmemo->setInvoice($invoice); + + $invoiceQtysRefunded = []; + foreach ($invoice->getOrder()->getCreditmemosCollection() as $createdCreditmemo) { + if ($createdCreditmemo->getState() != Creditmemo::STATE_CANCELED && + $createdCreditmemo->getInvoiceId() == $invoice->getId() + ) { + foreach ($createdCreditmemo->getAllItems() as $createdCreditmemoItem) { + $orderItemId = $createdCreditmemoItem->getOrderItem()->getId(); + if (isset($invoiceQtysRefunded[$orderItemId])) { + $invoiceQtysRefunded[$orderItemId] += $createdCreditmemoItem->getQty(); + } else { + $invoiceQtysRefunded[$orderItemId] = $createdCreditmemoItem->getQty(); + } + } + } + } + + $invoiceQtysRefundLimits = []; + foreach ($invoice->getAllItems() as $invoiceItem) { + $invoiceQtyCanBeRefunded = $invoiceItem->getQty(); + $orderItemId = $invoiceItem->getOrderItem()->getId(); + if (isset($invoiceQtysRefunded[$orderItemId])) { + $invoiceQtyCanBeRefunded = $invoiceQtyCanBeRefunded - $invoiceQtysRefunded[$orderItemId]; + } + $invoiceQtysRefundLimits[$orderItemId] = $invoiceQtyCanBeRefunded; + } + + foreach ($invoice->getAllItems() as $invoiceItem) { + $orderItem = $invoiceItem->getOrderItem(); + + if (!$this->canRefundItem($orderItem, $qtys, $invoiceQtysRefundLimits)) { + continue; + } + + $item = $this->convertor->itemToCreditmemoItem($orderItem); + if ($orderItem->isDummy()) { + $qty = 1; + } else { + if (isset($qtys[$orderItem->getId()])) { + $qty = (double)$qtys[$orderItem->getId()]; + } elseif (!count($qtys)) { + $qty = $orderItem->getQtyToRefund(); + } else { + continue; + } + if (isset($invoiceQtysRefundLimits[$orderItem->getId()])) { + $qty = min($qty, $invoiceQtysRefundLimits[$orderItem->getId()]); + } + } + $qty = min($qty, $invoiceItem->getQty()); + $totalQty += $qty; + $item->setQty($qty); + $creditmemo->addItem($item); + } + $creditmemo->setTotalQty($totalQty); + + $this->initData($creditmemo, $data); + if (!isset($data['shipping_amount'])) { + $isShippingInclTax = $this->taxConfig->displaySalesShippingInclTax($order->getStoreId()); + if ($isShippingInclTax) { + $baseAllowedAmount = $order->getBaseShippingInclTax() - + $order->getBaseShippingRefunded() - + $order->getBaseShippingTaxRefunded(); + } else { + $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded(); + $baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount()); + } + $creditmemo->setBaseShippingAmount($baseAllowedAmount); + } + + $creditmemo->collectTotals(); + return $creditmemo; + } + + /** + * Check if order item can be refunded + * + * @param \Magento\Sales\Model\Order\Item $item + * @param array $qtys + * @param array $invoiceQtysRefundLimits + * @return bool + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function canRefundItem($item, $qtys = [], $invoiceQtysRefundLimits = []) + { + if ($item->isDummy()) { + if ($item->getHasChildren()) { + foreach ($item->getChildrenItems() as $child) { + if (empty($qtys)) { + if ($this->canRefundNoDummyItem($child, $invoiceQtysRefundLimits)) { + return true; + } + } else { + if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) { + return true; + } + } + } + return false; + } elseif ($item->getParentItem()) { + $parent = $item->getParentItem(); + if (empty($qtys)) { + return $this->canRefundNoDummyItem($parent, $invoiceQtysRefundLimits); + } else { + return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0; + } + } + } else { + return $this->canRefundNoDummyItem($item, $invoiceQtysRefundLimits); + } + } + + /** + * Check if no dummy order item can be refunded + * + * @param \Magento\Sales\Model\Order\Item $item + * @param array $invoiceQtysRefundLimits + * @return bool + */ + protected function canRefundNoDummyItem($item, $invoiceQtysRefundLimits = []) + { + if ($item->getQtyToRefund() < 0) { + return false; + } + if (isset($invoiceQtysRefundLimits[$item->getId()])) { + return $invoiceQtysRefundLimits[$item->getId()] > 0; + } + return true; + } + + /** + * Initialize creditmemo state based on requested parameters + * + * @param Creditmemo $creditmemo + * @param array $data + * @return void + */ + protected function initData($creditmemo, $data) + { + if (isset($data['shipping_amount'])) { + $creditmemo->setBaseShippingAmount((double)$data['shipping_amount']); + } + if (isset($data['adjustment_positive'])) { + $creditmemo->setAdjustmentPositive($data['adjustment_positive']); + } + if (isset($data['adjustment_negative'])) { + $creditmemo->setAdjustmentNegative($data['adjustment_negative']); + } + } +} diff --git a/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php new file mode 100644 index 0000000000000..a54047c6cc516 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/CreditmemoRepository.php @@ -0,0 +1,143 @@ +metadata = $metadata; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * Loads a specified credit memo. + * + * @param int $id The credit memo ID. + * @return \Magento\Sales\Api\Data\CreditmemoInterface Credit memo interface. + * @throws InputException + * @throws NoSuchEntityException + */ + public function get($id) + { + if (!$id) { + throw new InputException(__('Id required')); + } + if (!isset($this->registry[$id])) { + /** @var \Magento\Sales\Api\Data\CreditmemoInterface $entity */ + $entity = $this->metadata->getNewInstance(); + $this->metadata->getMapper()->load($entity, $id); + if (!$entity->getEntityId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + $this->registry[$id] = $entity; + } + return $this->registry[$id]; + } + + /** + * Create credit memo instance + * + * @return \Magento\Sales\Api\Data\CreditmemoInterface + */ + public function create() + { + return $this->metadata->getNewInstance(); + } + + /** + * Lists credit memos that match specified search criteria. + * + * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @return \Magento\Sales\Api\Data\CreditmemoSearchResultInterface Credit memo search result interface. + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + /** @var \Magento\Sales\Api\Data\CreditmemoSearchResultInterface $searchResult */ + $searchResult = $this->searchResultFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + $searchResult->setCurPage($criteria->getCurrentPage()); + $searchResult->setPageSize($criteria->getPageSize()); + return $searchResult; + } + + /** + * Deletes a specified credit memo. + * + * @param \Magento\Sales\Api\Data\CreditmemoInterface $entity The credit memo. + * @return bool + * @throws CouldNotDeleteException + */ + public function delete(\Magento\Sales\Api\Data\CreditmemoInterface $entity) + { + try { + $this->metadata->getMapper()->delete($entity); + unset($this->registry[$entity->getEntityId()]); + } catch (\Exception $e) { + throw new CouldNotDeleteException(__('Could not delete credit memo'), $e); + } + return true; + } + + /** + * Performs persist operations for a specified credit memo. + * + * @param \Magento\Sales\Api\Data\CreditmemoInterface $entity The credit memo. + * @return \Magento\Sales\Api\Data\CreditmemoInterface Credit memo interface. + * @throws CouldNotSaveException + */ + public function save(\Magento\Sales\Api\Data\CreditmemoInterface $entity) + { + try { + $this->metadata->getMapper()->save($entity); + $this->registry[$entity->getEntityId()] = $entity; + } catch (\Exception $e) { + throw new CouldNotSaveException(__('Could not save credit memo'), $e); + } + return $this->registry[$entity->getEntityId()]; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Invoice.php b/app/code/Magento/Sales/Model/Order/Invoice.php index 0d093fedb883a..c5a9472bfe95a 100644 --- a/app/code/Magento/Sales/Model/Order/Invoice.php +++ b/app/code/Magento/Sales/Model/Order/Invoice.php @@ -357,12 +357,7 @@ public function pay() } $this->_wasPayCalled = true; - $invoiceState = self::STATE_PAID; - if ($this->getOrder()->getPayment()->hasForcedState()) { - $invoiceState = $this->getOrder()->getPayment()->getForcedState(); - } - - $this->setState($invoiceState); + $this->setState(self::STATE_PAID); $this->getOrder()->getPayment()->pay($this); $this->getOrder()->setTotalPaid($this->getOrder()->getTotalPaid() + $this->getGrandTotal()); diff --git a/app/code/Magento/Sales/Model/Order/InvoiceRepository.php b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php new file mode 100644 index 0000000000000..2ef7165762346 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/InvoiceRepository.php @@ -0,0 +1,141 @@ +metadata = $invoiceMetadata; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * Load entity + * + * @param int $id + * @return mixed + * @throws NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + */ + public function get($id) + { + if (!$id) { + throw new \Magento\Framework\Exception\InputException(__('ID required')); + } + if (!isset($this->registry[$id])) { + /** @var \Magento\Sales\Api\Data\InvoiceInterface $entity */ + $entity = $this->metadata->getNewInstance(); + $this->metadata->getMapper()->load($entity, $id); + if (!$entity->getEntityId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + $this->registry[$id] = $entity; + } + return $this->registry[$id]; + } + + /** + * @return \Magento\Sales\Api\Data\InvoiceInterface + */ + public function create() + { + return $this->metadata->getNewInstance(); + } + + /** + * Find entities by criteria + * + * @param \Magento\Framework\Api\SearchCriteria $criteria + * @return \Magento\Sales\Api\Data\InvoiceInterface[] + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + /** @var \Magento\Sales\Model\Resource\Order\Invoice\Collection $collection */ + $collection = $this->searchResultFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + $collection->setCurPage($criteria->getCurrentPage()); + $collection->setPageSize($criteria->getPageSize()); + return $collection; + } + + /** + * Register entity to delete + * + * @param \Magento\Sales\Api\Data\InvoiceInterface $entity + * @return bool + */ + public function delete(\Magento\Sales\Api\Data\InvoiceInterface $entity) + { + $this->metadata->getMapper()->delete($entity); + unset($this->registry[$entity->getEntityId()]); + return true; + } + + /** + * Delete entity by Id + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->get($id); + return $this->delete($entity); + } + + /** + * Perform persist operations for one entity + * + * @param \Magento\Sales\Api\Data\InvoiceInterface $entity + * @return \Magento\Sales\Api\Data\InvoiceInterface + */ + public function save(\Magento\Sales\Api\Data\InvoiceInterface $entity) + { + $this->metadata->getMapper()->save($entity); + $this->registry[$entity->getEntityId()] = $entity; + return $this->registry[$entity->getEntityId()]; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment.php b/app/code/Magento/Sales/Model/Order/Payment.php index 9566358cc7919..3811b28fa58fd 100755 --- a/app/code/Magento/Sales/Model/Order/Payment.php +++ b/app/code/Magento/Sales/Model/Order/Payment.php @@ -13,6 +13,7 @@ use Magento\Sales\Api\Data\OrderPaymentInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment\Transaction; +use Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface; /** * Order payment information @@ -49,14 +50,6 @@ class Payment extends Info implements OrderPaymentInterface */ protected $_canVoidLookup = null; - /** - * Transactions registry to spare resource calls - * array(txn_id => sales/order_payment_transaction) - * - * @var array - */ - protected $_transactionsLookup = []; - /** * @var string */ @@ -72,32 +65,37 @@ class Payment extends Info implements OrderPaymentInterface * * @var array */ - protected $_transactionAdditionalInfo = []; + protected $transactionAdditionalInfo = []; /** - * @var \Magento\Sales\Model\Service\Order + * @var \Magento\Sales\Model\Order\CreditmemoFactory */ - protected $_serviceOrderFactory; + protected $creditmemoFactory; /** - * @var \Magento\Sales\Model\Order\Payment\TransactionFactory + * @var PriceCurrencyInterface */ - protected $_transactionFactory; + protected $priceCurrency; /** - * @var \Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory + * @var \Magento\Sales\Api\TransactionRepositoryInterface */ - protected $_transactionCollectionFactory; + protected $transactionRepository; /** - * @var \Magento\Store\Model\StoreManagerInterface + * @var \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface */ - protected $_storeManager; + protected $transactionManager; /** - * @var PriceCurrencyInterface + * @var \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface */ - protected $priceCurrency; + protected $transactionBuilder; + + /** + * @var Payment\Processor + */ + protected $orderPaymentProcessor; /** * @param \Magento\Framework\Model\Context $context @@ -106,11 +104,11 @@ class Payment extends Info implements OrderPaymentInterface * @param \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory * @param \Magento\Payment\Helper\Data $paymentData * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor - * @param \Magento\Sales\Model\Service\OrderFactory $serviceOrderFactory - * @param Payment\TransactionFactory $transactionFactory - * @param \Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory $transactionCollectionFactory - * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory * @param PriceCurrencyInterface $priceCurrency + * @param \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository + * @param \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface $transactionManager + * @param Transaction\BuilderInterface $transactionBuilder * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -123,20 +121,22 @@ public function __construct( \Magento\Framework\Api\AttributeValueFactory $customAttributeFactory, \Magento\Payment\Helper\Data $paymentData, \Magento\Framework\Encryption\EncryptorInterface $encryptor, - \Magento\Sales\Model\Service\OrderFactory $serviceOrderFactory, - \Magento\Sales\Model\Order\Payment\TransactionFactory $transactionFactory, - \Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory $transactionCollectionFactory, - \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory, PriceCurrencyInterface $priceCurrency, + \Magento\Sales\Api\TransactionRepositoryInterface $transactionRepository, + ManagerInterface $transactionManager, + \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface $transactionBuilder, + \Magento\Sales\Model\Order\Payment\Processor $paymentProcessor, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { $this->priceCurrency = $priceCurrency; - $this->_serviceOrderFactory = $serviceOrderFactory; - $this->_transactionFactory = $transactionFactory; - $this->_transactionCollectionFactory = $transactionCollectionFactory; - $this->_storeManager = $storeManager; + $this->creditmemoFactory = $creditmemoFactory; + $this->transactionRepository = $transactionRepository; + $this->transactionManager = $transactionManager; + $this->transactionBuilder = $transactionBuilder; + $this->orderPaymentProcessor = $paymentProcessor; parent::__construct( $context, $registry, @@ -198,6 +198,16 @@ public function setTransactionId($transactionId) return $this; } + /** + * Return transaction id + * + * @return int + */ + public function getTransactionId() + { + return $this->getData('transaction_id'); + } + /** * Sets transaction close flag * @@ -233,9 +243,10 @@ public function canCapture() // Check Authorization transaction state $authTransaction = $this->getAuthorizationTransaction(); if ($authTransaction && $authTransaction->getIsClosed()) { - $orderTransaction = $this->_lookupTransaction( - null, - Transaction::TYPE_ORDER + $orderTransaction = $this->transactionRepository->getByTransactionType( + Transaction::TYPE_ORDER, + $this->getId(), + $this->getOrder()->getId() ); if (!$orderTransaction) { return false; @@ -402,105 +413,13 @@ protected function processAction($action, Order $order) * Updates transactions hierarchy, if required * Updates payment totals, updates order status and adds proper comments * - * TODO: eliminate logic duplication with registerCaptureNotification() - * * @param null|Invoice $invoice * @throws \Magento\Framework\Exception\LocalizedException * @return $this */ public function capture($invoice = null) { - if (is_null($invoice)) { - $invoice = $this->_invoice(); - $this->setCreatedInvoice($invoice); - if ($this->getIsFraudDetected()) { - $this->getOrder()->setStatus(Order::STATUS_FRAUD); - } - return $this; - } - $amountToCapture = $this->_formatAmount($invoice->getBaseGrandTotal()); - $order = $this->getOrder(); - - // prepare parent transaction and its amount - $paidWorkaround = 0; - if (!$invoice->wasPayCalled()) { - $paidWorkaround = (double)$amountToCapture; - } - $this->_isCaptureFinal($paidWorkaround); - - $this->_generateTransactionId( - Transaction::TYPE_CAPTURE, - $this->getAuthorizationTransaction() - ); - - $this->_eventManager->dispatch( - 'sales_order_payment_capture', - ['payment' => $this, 'invoice' => $invoice] - ); - - /** - * Fetch an update about existing transaction. It can determine whether the transaction can be paid - * Capture attempt will happen only when invoice is not yet paid and the transaction can be paid - */ - if ($invoice->getTransactionId()) { - $method = $this->getMethodInstance(); - $method->setStore( - $order->getStoreId() - ); - $method->fetchTransactionInfo( - $this, - $invoice->getTransactionId() - ); - } - $status = false; - if (!$invoice->getIsPaid()) { - // attempt to capture: this can trigger "is_transaction_pending" - $method = $this->getMethodInstance(); - $method->setStore( - $order->getStoreId() - ); - $method->capture($this, $amountToCapture); - - $transaction = $this->_addTransaction( - Transaction::TYPE_CAPTURE, - $invoice, - true - ); - - if ($this->getIsTransactionPending()) { - $message = __( - 'An amount of %1 will be captured after being approved at the payment gateway.', - $this->_formatPrice($amountToCapture) - ); - $state = Order::STATE_PAYMENT_REVIEW; - if ($this->getIsFraudDetected()) { - $status = Order::STATUS_FRAUD; - } - $invoice->setIsPaid(false); - } else { - // normal online capture: invoice is marked as "paid" - $message = __('Captured amount of %1 online', $this->_formatPrice($amountToCapture)); - $state = Order::STATE_PROCESSING; - $invoice->setIsPaid(true); - $this->_updateTotals(['base_amount_paid_online' => $amountToCapture]); - } - $message = $this->_prependMessage($message); - $message = $this->_appendTransactionToMessage($transaction, $message); - - if (!$status) { - $status = $order->getConfig()->getStateDefaultStatus($state); - } - - $order->setState($state) - ->setStatus($status) - ->addStatusHistoryComment($message); - - $invoice->setTransactionId($this->getLastTransId()); - return $this; - } - throw new \Magento\Framework\Exception\LocalizedException( - __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) - ); + return $this->orderPaymentProcessor->capture($this, $invoice); } /** @@ -510,72 +429,13 @@ public function capture($invoice = null) * Prevents transaction double processing * Updates payment totals, updates order status and adds proper comments * - * TODO: eliminate logic duplication with capture() - * * @param float $amount * @param bool $skipFraudDetection * @return $this */ public function registerCaptureNotification($amount, $skipFraudDetection = false) { - $this->_generateTransactionId( - Transaction::TYPE_CAPTURE, - $this->getAuthorizationTransaction() - ); - - $order = $this->getOrder(); - $amount = (double)$amount; - $invoice = $this->_getInvoiceForTransactionId($this->getTransactionId()); - - // register new capture - if (!$invoice) { - if ($this->_isSameCurrency() && $this->_isCaptureFinal($amount)) { - $invoice = $order->prepareInvoice()->register(); - $order->addRelatedObject($invoice); - $this->setCreatedInvoice($invoice); - } else { - $this->setIsFraudDetected(!$skipFraudDetection); - $this->_updateTotals(['base_amount_paid_online' => $amount]); - } - } - - if ($this->getIsTransactionPending()) { - $message = __( - 'An amount of %1 will be captured after being approved at the payment gateway.', - $this->_formatPrice($amount) - ); - $state = Order::STATE_PAYMENT_REVIEW; - } else { - $message = __('Registered notification about captured amount of %1.', $this->_formatPrice($amount)); - $state = Order::STATE_PROCESSING; - // register capture for an existing invoice - if ($invoice && Invoice::STATE_OPEN == $invoice->getState()) { - $invoice->pay(); - $this->_updateTotals(['base_amount_paid_online' => $amount]); - $order->addRelatedObject($invoice); - } - } - if ($this->getIsFraudDetected()) { - $state = Order::STATE_PAYMENT_REVIEW; - $message = __( - 'Order is suspended as its capture amount %1 is suspected to be fraudulent.', - $this->_formatPrice($amount) - ); - $status = Order::STATUS_FRAUD; - } else { - $status = $order->getConfig()->getStateDefaultStatus($state); - } - - $transaction = $this->_addTransaction( - Transaction::TYPE_CAPTURE, - $invoice, - true - ); - $message = $this->_prependMessage($message); - $message = $this->_appendTransactionToMessage($transaction, $message); - - $order->setState($state)->setStatus($status)->addStatusHistoryComment($message); - return $this; + return $this->orderPaymentProcessor->registerCaptureNotification($this, $amount, $skipFraudDetection); } /** @@ -587,7 +447,7 @@ public function registerCaptureNotification($amount, $skipFraudDetection = false */ public function registerAuthorizationNotification($amount) { - return $this->_isTransactionExists() ? $this : $this->authorize(false, $amount); + return $this->checkIfTransactionExists() ? $this : $this->authorize(false, $amount); } /** @@ -736,9 +596,10 @@ public function getCreditmemo() */ public function refund($creditmemo) { - $baseAmountToRefund = $this->_formatAmount($creditmemo->getBaseGrandTotal()); - - $this->_generateTransactionId(Transaction::TYPE_REFUND); + $baseAmountToRefund = $this->formatAmount($creditmemo->getBaseGrandTotal()); + $this->setTransactionId( + $this->transactionManager->generateTransactionId($this, Transaction::TYPE_REFUND) + ); // call refund from gateway if required $isOnline = false; @@ -749,7 +610,11 @@ public function refund($creditmemo) $invoice = $creditmemo->getInvoice(); if ($invoice) { $isOnline = true; - $captureTxn = $this->_lookupTransaction($invoice->getTransactionId()); + $captureTxn = $this->transactionRepository->getByTransactionId( + $invoice->getTransactionId(), + $this->getId(), + $this->getOrder()->getId() + ); if ($captureTxn) { $this->setParentTransactionId($captureTxn->getTxnId()); } @@ -790,20 +655,20 @@ public function refund($creditmemo) ); // update transactions and order state - $transaction = $this->_addTransaction( + $transaction = $this->addTransaction( Transaction::TYPE_REFUND, $creditmemo, $isOnline ); if ($invoice) { - $message = __('We refunded %1 online.', $this->_formatPrice($baseAmountToRefund)); + $message = __('We refunded %1 online.', $this->formatPrice($baseAmountToRefund)); } else { $message = $this->hasMessage() ? $this->getMessage() : __( 'We refunded %1 offline.', - $this->_formatPrice($baseAmountToRefund) + $this->formatPrice($baseAmountToRefund) ); } - $message = $message = $this->_prependMessage($message); + $message = $message = $this->prependMessage($message); $message = $this->_appendTransactionToMessage($transaction, $message); $this->setOrderStateProcessing($message); $this->_eventManager->dispatch( @@ -829,23 +694,27 @@ public function refund($creditmemo) public function registerRefundNotification($amount) { $notificationAmount = $amount; - $this->_generateTransactionId( - Transaction::TYPE_REFUND, - $this->_lookupTransaction($this->getParentTransactionId()) + $this->setTransactionId( + $this->transactionManager->generateTransactionId( + $this, + Transaction::TYPE_REFUND, + $this->transactionRepository->getByTransactionId( + $this->getParentTransactionId(), + $this->getId(), + $this->getOrder()->getId() + ) + ) ); - if ($this->_isTransactionExists()) { + if ($this->checkIfTransactionExists()) { return $this; } $order = $this->getOrder(); $invoice = $this->_getInvoiceForTransactionId($this->getParentTransactionId()); - if ($invoice) { - $baseGrandTotal = $invoice->getBaseGrandTotal(); - $amountRefundLeft = $baseGrandTotal - $invoice->getBaseTotalRefunded(); - } else { - $baseGrandTotal = $order->getBaseGrandTotal(); - $amountRefundLeft = $baseGrandTotal - $order->getBaseTotalRefunded(); - } + //choose where we get totals + $salesEntity = $invoice ?: $order; + $baseGrandTotal = $salesEntity->getBaseGrandTotal(); + $amountRefundLeft = $baseGrandTotal - $salesEntity->getBaseTotalRefunded(); if ($amountRefundLeft < $amount) { $amount = $amountRefundLeft; @@ -855,7 +724,7 @@ public function registerRefundNotification($amount) $order->addStatusHistoryComment( __( 'IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of %1. Transaction ID: "%2". Credit Memo has not been created. Please create offline Credit Memo.', - $this->_formatPrice($notificationAmount), + $this->formatPrice($notificationAmount), $this->getTransactionId() ), false @@ -863,31 +732,7 @@ public function registerRefundNotification($amount) return $this; } - $serviceModel = $this->_serviceOrderFactory->create(['order' => $order]); - if ($invoice) { - if ($invoice->getBaseTotalRefunded() > 0) { - $adjustment = ['adjustment_positive' => $amount]; - } else { - $adjustment = ['adjustment_negative' => $baseGrandTotal - $amount]; - } - $creditmemo = $serviceModel->prepareInvoiceCreditmemo($invoice, $adjustment); - if ($creditmemo) { - $totalRefunded = $invoice->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal(); - $this->setShouldCloseParentTransaction($invoice->getBaseGrandTotal() <= $totalRefunded); - } - } else { - if ($order->getBaseTotalRefunded() > 0) { - $adjustment = ['adjustment_positive' => $amount]; - } else { - $adjustment = ['adjustment_negative' => $baseGrandTotal - $amount]; - } - $creditmemo = $serviceModel->prepareCreditmemo($adjustment); - if ($creditmemo) { - $totalRefunded = $order->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal(); - $this->setShouldCloseParentTransaction($order->getBaseGrandTotal() <= $totalRefunded); - } - } - + $creditmemo = $this->prepareCreditMemo($amount, $baseGrandTotal, $invoice); $creditmemo->setPaymentRefundDisallowed( true )->setAutomaticallyCreated( @@ -903,12 +748,12 @@ public function registerRefundNotification($amount) $this->setCreatedCreditmemo($creditmemo); // update transactions and order state - $transaction = $this->_addTransaction( + $transaction = $this->addTransaction( Transaction::TYPE_REFUND, $creditmemo ); - $message = $this->_prependMessage( - __('Registered notification about refunded amount of %1.', $this->_formatPrice($amount)) + $message = $this->prependMessage( + __('Registered notification about refunded amount of %1.', $this->formatPrice($amount)) ); $message = $this->_appendTransactionToMessage($transaction, $message); $this->setOrderStateProcessing($message); @@ -998,14 +843,14 @@ public function accept() $invoice = $this->_getInvoiceForTransactionId($transactionId); $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('Approved the payment online.')) + $this->prependMessage(__('Approved the payment online.')) ); $this->updateBaseAmountPaidOnlineTotal($invoice); $this->setOrderStateProcessing($message); } else { $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('There is no need to approve this payment.')) + $this->prependMessage(__('There is no need to approve this payment.')) ); $this->setOrderStatePaymentReview($message, $transactionId); } @@ -1037,7 +882,7 @@ public function deny($isOnline = true) $invoice = $this->_getInvoiceForTransactionId($transactionId); $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('Denied the payment online')) + $this->prependMessage(__('Denied the payment online')) ); $this->cancelInvoiceAndRegisterCancellation($invoice, $message); } else { @@ -1045,7 +890,7 @@ public function deny($isOnline = true) 'There is no need to deny this payment.' : 'Registered notification about denied payment.'; $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__($txt)) + $this->prependMessage(__($txt)) ); $this->setOrderStatePaymentReview($message, $transactionId); } @@ -1064,7 +909,6 @@ public function update($isOnline = true) $transactionId = $isOnline ? $this->getLastTransId() : $this->getTransactionId(); $invoice = $this->_getInvoiceForTransactionId($transactionId); - if ($isOnline) { $method = $this->getMethodInstance(); $method->setStore($this->getOrder()->getStoreId()); @@ -1074,20 +918,20 @@ public function update($isOnline = true) if ($this->getIsTransactionApproved()) { $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('Registered update about approved payment.')) + $this->prependMessage(__('Registered update about approved payment.')) ); $this->updateBaseAmountPaidOnlineTotal($invoice); $this->setOrderStateProcessing($message); } elseif ($this->getIsTransactionDenied()) { $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('Registered update about denied payment.')) + $this->prependMessage(__('Registered update about denied payment.')) ); $this->cancelInvoiceAndRegisterCancellation($invoice, $message); } else { $message = $this->_appendTransactionToMessage( $transactionId, - $this->_prependMessage(__('There is no update for the payment.')) + $this->prependMessage(__('There is no update for the payment.')) ); $this->setOrderStatePaymentReview($message, $transactionId); } @@ -1169,47 +1013,7 @@ protected function setOrderStatePaymentReview($message, $transactionId) */ protected function _order($amount) { - // update totals - $amount = $this->_formatAmount($amount, true); - - // do ordering - $order = $this->getOrder(); - - $state = Order::STATE_PROCESSING; - $status = false; - $method = $this->getMethodInstance(); - $method->setStore($order->getStoreId()); - $method->order($this, $amount); - - if ($this->getSkipOrderProcessing()) { - return $this; - } - - // similar logic of "payment review" order as in capturing - if ($this->getIsTransactionPending()) { - $message = __( - 'The order amount of %1 is pending approval on the payment gateway.', - $this->_formatPrice($amount) - ); - $state = Order::STATE_PAYMENT_REVIEW; - if ($this->getIsFraudDetected()) { - $status = Order::STATUS_FRAUD; - } - } else { - $message = __('Ordered amount of %1', $this->_formatPrice($amount)); - } - - // update transactions, order state and add comments - $transaction = $this->_addTransaction(Transaction::TYPE_ORDER); - $message = $this->_prependMessage($message); - $message = $this->_appendTransactionToMessage($transaction, $message); - - if (!$status) { - $status = $order->getConfig()->getStateDefaultStatus($state); - } - - $order->setState($state)->setStatus($status)->addStatusHistoryComment($message); - return $this; + return $this->orderPaymentProcessor->order($this, $amount); } /** @@ -1225,62 +1029,7 @@ protected function _order($amount) */ public function authorize($isOnline, $amount) { - // check for authorization amount to be equal to grand total - $this->setShouldCloseParentTransaction(false); - $isSameCurrency = $this->_isSameCurrency(); - if (!$isSameCurrency || !$this->_isCaptureFinal($amount)) { - $this->setIsFraudDetected(true); - } - - // update totals - $amount = $this->_formatAmount($amount, true); - $this->setBaseAmountAuthorized($amount); - - // do authorization - $order = $this->getOrder(); - $state = Order::STATE_PROCESSING; - $status = false; - if ($isOnline) { - // invoke authorization on gateway - $method = $this->getMethodInstance(); - $method->setStore($order->getStoreId()); - $method->authorize($this, $amount); - } - - // similar logic of "payment review" order as in capturing - if ($this->getIsTransactionPending()) { - $state = Order::STATE_PAYMENT_REVIEW; - $message = __( - 'We will authorize %1 after the payment is approved at the payment gateway.', - $this->_formatPrice($amount) - ); - } else { - if ($this->getIsFraudDetected()) { - $state = Order::STATE_PROCESSING; - $message = __( - 'Order is suspended as its authorizing amount %1 is suspected to be fraudulent.', - $this->_formatPrice($amount, $this->getCurrencyCode()) - ); - } else { - $message = __('Authorized amount of %1', $this->_formatPrice($amount)); - } - } - if ($this->getIsFraudDetected()) { - $status = Order::STATUS_FRAUD; - } - - // update transactions, order state and add comments - $transaction = $this->_addTransaction(Transaction::TYPE_AUTH); - $message = $this->_prependMessage($message); - $message = $this->_appendTransactionToMessage($transaction, $message); - - if (!$status) { - $status = $order->getConfig()->getStateDefaultStatus($state); - } - - $order->setState($state)->setStatus($status)->addStatusHistoryComment($message); - - return $this; + return $this->orderPaymentProcessor->authorize($this, $isOnline, $amount); } /** @@ -1300,7 +1049,9 @@ protected function _void($isOnline, $amount = null, $gatewayCallback = 'void') { $order = $this->getOrder(); $authTransaction = $this->getAuthorizationTransaction(); - $this->_generateTransactionId(Transaction::TYPE_VOID, $authTransaction); + $this->setTransactionId( + $this->transactionManager->generateTransactionId($this, Transaction::TYPE_VOID, $authTransaction) + ); $this->setShouldCloseParentTransaction(true); // attempt to void @@ -1309,7 +1060,7 @@ protected function _void($isOnline, $amount = null, $gatewayCallback = 'void') $method->setStore($order->getStoreId()); $method->{$gatewayCallback}($this); } - if ($this->_isTransactionExists()) { + if ($this->checkIfTransactionExists()) { return $this; } @@ -1325,15 +1076,15 @@ protected function _void($isOnline, $amount = null, $gatewayCallback = 'void') } if ($amount) { - $amount = $this->_formatAmount($amount); + $amount = $this->formatAmount($amount); } // update transactions, order state and add comments - $transaction = $this->_addTransaction(Transaction::TYPE_VOID, null, true); + $transaction = $this->addTransaction(Transaction::TYPE_VOID, null, true); $message = $this->hasMessage() ? $this->getMessage() : __('Voided authorization.'); - $message = $this->_prependMessage($message); + $message = $this->prependMessage($message); if ($amount) { - $message .= ' ' . __('Amount: %1.', $this->_formatPrice($amount)); + $message .= ' ' . __('Amount: %1.', $this->formatPrice($amount)); } $message = $this->_appendTransactionToMessage($transaction, $message); $this->setOrderStateProcessing($message); @@ -1341,120 +1092,32 @@ protected function _void($isOnline, $amount = null, $gatewayCallback = 'void') return $this; } - // /** - // * TODO: implement this - // * @param Invoice $invoice - // * @return $this - // */ - // public function cancelCapture($invoice = null) - // { - // } - /** - * Create transaction, - * prepare its insertion into hierarchy and add its information to payment and comments - * - * To add transactions and related information, - * the following information should be set to payment before processing: - * - transaction_id - * - is_transaction_closed (optional) - whether transaction should be closed or open (closed by default) - * - parent_transaction_id (optional) - * - should_close_parent_transaction (optional) - whether to close parent transaction (closed by default) - * - * If the sales document is specified, it will be linked to the transaction as related for future usage. - * Currently transaction ID is set into the sales object - * This method writes the added transaction ID into last_trans_id field of the payment object - * - * To make sure transaction object won't cause trouble before saving, use $failsafe = true + * Public access to _addTransaction method * * @param string $type * @param \Magento\Sales\Model\AbstractModel $salesDocument - * @param bool $failsafe + * @param bool $failSafe * @return null|Transaction - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) */ - protected function _addTransaction($type, $salesDocument = null, $failsafe = false) + public function addTransaction($type, $salesDocument = null, $failSafe = false) { - if ($this->getSkipTransactionCreation()) { - $this->unsTransactionId(); - return null; - } - - // look for set transaction ids - $transactionId = $this->getTransactionId(); - if (null !== $transactionId) { - // set transaction parameters - $transaction = false; - if ($this->getOrder()->getId()) { - $transaction = $this->_lookupTransaction($transactionId); - } - if (!$transaction) { - $transaction = $this->_transactionFactory->create()->setTxnId($transactionId); - } - $transaction->setOrderPaymentObject($this)->setTxnType($type)->isFailsafe($failsafe); - - if ($this->hasIsTransactionClosed()) { - $transaction->setIsClosed((int)$this->getIsTransactionClosed()); - } - - //set transaction addition information - if ($this->_transactionAdditionalInfo) { - foreach ($this->_transactionAdditionalInfo as $key => $value) { - $transaction->setAdditionalInformation($key, $value); - } - $this->_transactionAdditionalInfo = []; - } - - // link with sales entities - $this->setLastTransId($transactionId); - $this->setCreatedTransaction($transaction); - $this->getOrder()->addRelatedObject($transaction); - if ($salesDocument && $salesDocument instanceof \Magento\Sales\Model\AbstractModel) { - $salesDocument->setTransactionId($transactionId); - } - - // link with parent transaction - $parentTransactionId = $this->getParentTransactionId(); - - if ($parentTransactionId) { - $transaction->setParentTxnId($parentTransactionId); - if ($this->getShouldCloseParentTransaction()) { - $parentTransaction = $this->_lookupTransaction($parentTransactionId); - if ($parentTransaction) { - if (!$parentTransaction->getIsClosed()) { - $parentTransaction->isFailsafe($failsafe)->close(false); - } - $this->getOrder()->addRelatedObject($parentTransaction); - } - } - } - return $transaction; + $builder = $this->transactionBuilder->setPayment($this) + ->setOrder($this->getOrder()) + ->setFailSafe($failSafe) + ->setTransactionId($this->getTransactionId()) + ->setAdditionalInformation($this->transactionAdditionalInfo); + if ($salesDocument) { + $builder->setSalesDocument($salesDocument); } - - return null; + return $builder->build($type); } - /** - * Public access to _addTransaction method - * - * @param string $type - * @param \Magento\Sales\Model\AbstractModel $salesDocument - * @param bool $failsafe - * @param bool|string $message - * @return null|Transaction - */ - public function addTransaction($type, $salesDocument = null, $failsafe = false, $message = false) + public function addTransactionCommentsToOrder($transaction, $message) { - $transaction = $this->_addTransaction($type, $salesDocument, $failsafe); - - if ($message) { - $order = $this->getOrder(); - $message = $this->_appendTransactionToMessage($transaction, $message); - $order->addStatusHistoryComment($message); - } - - return $transaction; + $order = $this->getOrder(); + $message = $this->_appendTransactionToMessage($transaction, $message); + $order->addStatusHistoryComment($message); } /** @@ -1469,14 +1132,14 @@ public function importTransactionInfo(Transaction $transactionTo) $method->setStore( $this->getOrder()->getStoreId() ); - $method->fetchTransactionInfo( + $data = $method->fetchTransactionInfo( $this, $transactionTo->getTxnId() ); - if ($method) { + if ($data) { $transactionTo->setAdditionalInformation( Transaction::RAW_DETAILS, - $method + $data ); } return $this; @@ -1499,20 +1162,6 @@ protected function _updateTotals($data) } } - /** - * Check transaction existence by specified transaction id - * - * @param string $txnId - * @return boolean - */ - protected function _isTransactionExists($txnId = null) - { - if (null === $txnId) { - $txnId = $this->getTransactionId(); - } - return $txnId && $this->_lookupTransaction($txnId); - } - /** * Append transaction ID (if any) message to the specified message * @@ -1536,7 +1185,7 @@ protected function _appendTransactionToMessage($transaction, $message) * @param string|\Magento\Sales\Model\Order\Status\History $messagePrependTo * @return string|\Magento\Sales\Model\Order\Status\History */ - protected function _prependMessage($messagePrependTo) + public function prependMessage($messagePrependTo) { $preparedMessage = $this->getPreparedMessage(); if ($preparedMessage) { @@ -1564,7 +1213,7 @@ protected function _prependMessage($messagePrependTo) * @param bool $asFloat * @return string|float */ - protected function _formatAmount($amount, $asFloat = false) + public function formatAmount($amount, $asFloat = false) { $amount = $this->priceCurrency->round($amount); return !$asFloat ? (string)$amount : $amount; @@ -1575,112 +1224,22 @@ protected function _formatAmount($amount, $asFloat = false) * @param float $amount * @return string */ - protected function _formatPrice($amount) + public function formatPrice($amount) { return $this->getOrder()->getBaseCurrency()->formatTxt($amount); } - /** - * Find one transaction by ID or type - * - * @param string $txnId - * @param bool|string $txnType - * @return Transaction|false - */ - protected function _lookupTransaction($txnId, $txnType = false) - { - if (!$txnId) { - if ($txnType && $this->getId()) { - $collection = $this->_transactionCollectionFactory->create()->setOrderFilter( - $this->getOrder() - )->addPaymentIdFilter( - $this->getId() - )->addTxnTypeFilter( - $txnType - )->setOrder( - 'created_at', - \Magento\Framework\Data\Collection::SORT_ORDER_DESC - )->setOrder( - 'transaction_id', - \Magento\Framework\Data\Collection::SORT_ORDER_DESC - ); - foreach ($collection as $txn) { - $txn->setOrderPaymentObject($this); - $this->_transactionsLookup[$txn->getTxnId()] = $txn; - return $txn; - } - } - return false; - } - if (isset($this->_transactionsLookup[$txnId])) { - return $this->_transactionsLookup[$txnId]; - } - $txn = $this->_transactionFactory->create()->setOrderPaymentObject($this)->loadByTxnId($txnId); - if ($txn->getId()) { - $this->_transactionsLookup[$txnId] = $txn; - } else { - $this->_transactionsLookup[$txnId] = false; - } - return $this->_transactionsLookup[$txnId]; - } - - /** - * Find one transaction by ID or type - * - * @param string $txnId - * @param bool|string $txnType - * @return Transaction|false - */ - public function lookupTransaction($txnId, $txnType = false) - { - return $this->_lookupTransaction($txnId, $txnType); - } - /** * Lookup an authorization transaction using parent transaction id, if set * @return Transaction|false */ public function getAuthorizationTransaction() { - if ($this->getParentTransactionId()) { - $txn = $this->_lookupTransaction($this->getParentTransactionId()); - } else { - $txn = false; - } - - if (!$txn) { - $txn = $this->_lookupTransaction(false, Transaction::TYPE_AUTH); - } - return $txn; - } - - /** - * Lookup the transaction by id - * @param string $transactionId - * @return Transaction|false - */ - public function getTransaction($transactionId) - { - return $this->_lookupTransaction($transactionId); - } - - /** - * Update transaction ids for further processing - * If no transactions were set before invoking, may generate an "offline" transaction id - * - * @param string $type - * @param bool|Transaction $transactionBasedOn - * @return void - */ - protected function _generateTransactionId($type, $transactionBasedOn = false) - { - if (!$this->getParentTransactionId() && !$this->getTransactionId() && $transactionBasedOn) { - $this->setParentTransactionId($transactionBasedOn->getTxnId()); - } - // generate transaction id for an offline action or payment method that didn't set it - if (($parentTxnId = $this->getParentTransactionId()) && !$this->getTransactionId()) { - $this->setTransactionId("{$parentTxnId}-{$type}"); - } + return $this->transactionManager->getAuthorizationTransaction( + $this->getParentTransactionId(), + $this->getId(), + $this->getOrder()->getId() + ); } /** @@ -1689,11 +1248,11 @@ protected function _generateTransactionId($type, $transactionBasedOn = false) * @param float $amountToCapture * @return bool */ - protected function _isCaptureFinal($amountToCapture) + public function isCaptureFinal($amountToCapture) { - $amountPaid = $this->_formatAmount($this->getBaseAmountPaid(), true); - $amountToCapture = $this->_formatAmount($amountToCapture, true); - $orderGrandTotal = $this->_formatAmount($this->getOrder()->getBaseGrandTotal(), true); + $amountPaid = $this->formatAmount($this->getBaseAmountPaid(), true); + $amountToCapture = $this->formatAmount($amountToCapture, true); + $orderGrandTotal = $this->formatAmount($this->getOrder()->getBaseGrandTotal(), true); if ($orderGrandTotal == $amountPaid + $amountToCapture) { if (false !== $this->getShouldCloseParentTransaction()) { $this->setShouldCloseParentTransaction(true); @@ -1708,7 +1267,7 @@ protected function _isCaptureFinal($amountToCapture) * * @return bool */ - protected function _isSameCurrency() + public function isSameCurrency() { return !$this->getCurrencyCode() || $this->getCurrencyCode() == $this->getOrder()->getBaseCurrencyCode(); } @@ -1722,25 +1281,17 @@ protected function _isSameCurrency() */ public function setTransactionAdditionalInfo($key, $value) { - if (is_array($key)) { - $this->_transactionAdditionalInfo = $key; - } else { - $this->_transactionAdditionalInfo[$key] = $value; - } + $this->transactionAdditionalInfo[$key] = $value; } /** - * Additional transaction info getter + * Additional transaction info setter * - * @param string $key - * @return mixed + * @return array */ - public function getTransactionAdditionalInfo($key = null) + public function getTransactionAdditionalInfo() { - if (is_null($key)) { - return $this->_transactionAdditionalInfo; - } - return isset($this->_transactionAdditionalInfo[$key]) ? $this->_transactionAdditionalInfo[$key] : null; + return $this->transactionAdditionalInfo; } /** @@ -1750,10 +1301,52 @@ public function getTransactionAdditionalInfo($key = null) */ public function resetTransactionAdditionalInfo() { - $this->_transactionAdditionalInfo = []; + $this->transactionAdditionalInfo = []; return $this; } + /** + * Prepare credit memo + * + * @param $amount + * @param $baseGrandTotal + * @param false|Invoice $invoice + * @return mixed + */ + protected function prepareCreditMemo($amount, $baseGrandTotal, $invoice) + { + $entity = $invoice ?: $this->getOrder(); + if ($entity->getBaseTotalRefunded() > 0) { + $adjustment = ['adjustment_positive' => $amount]; + } else { + $adjustment = ['adjustment_negative' => $baseGrandTotal - $amount]; + } + if ($invoice) { + $creditMemo = $this->creditmemoFactory->createByInvoice($invoice, $adjustment); + } else { + $creditMemo = $this->creditmemoFactory->createByOrder($this->getOrder(), $adjustment); + } + if ($creditMemo) { + $totalRefunded = $entity->getBaseTotalRefunded() + $creditMemo->getBaseGrandTotal(); + $this->setShouldCloseParentTransaction($entity->getBaseGrandTotal() <= $totalRefunded); + } + + return $creditMemo; + } + + /** + * Checks if transaction exists + * + * @return bool + */ + protected function checkIfTransactionExists() + { + return $this->transactionManager->isTransactionExists( + $this->getTransactionId(), + $this->getId(), + $this->getOrder()->getId()); + } + /** * Return invoice model for transaction * diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/AbstractOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/AbstractOperation.php new file mode 100644 index 0000000000000..25feec5b4e4b2 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/AbstractOperation.php @@ -0,0 +1,121 @@ +stateCommand = $stateCommand; + $this->transactionBuilder = $transactionBuilder; + $this->transactionManager = $transactionManager; + $this->eventManager = $eventManager; + } + + /** + * Create new invoice with maximum qty for invoice for each item + * register this invoice and capture + * + * @param OrderPaymentInterface $payment + * @return Invoice + */ + protected function invoice(OrderPaymentInterface $payment) + { + /** @var Invoice $invoice */ + $invoice = $payment->getOrder()->prepareInvoice(); + + $invoice->register(); + if ($payment->getMethodInstance()->canCapture()) { + $invoice->capture(); + } + + $payment->getOrder()->addRelatedObject($invoice); + return $invoice; + } + + /** + * Totals updater utility method + * Updates self totals by keys in data array('key' => $delta) + * + * @param OrderPaymentInterface $payment + * @param array $data + * @return void + */ + protected function updateTotals(OrderPaymentInterface $payment, $data) + { + foreach ($data as $key => $amount) { + if (null !== $amount) { + $was = $payment->getDataUsingMethod($key); + $payment->setDataUsingMethod($key, $was + $amount); + } + } + } + + /** + * Return invoice model for transaction + * + * @param OrderInterface $order + * @param string $transactionId + * @return false|Invoice + */ + protected function getInvoiceForTransactionId(OrderInterface $order, $transactionId) + { + foreach ($order->getInvoiceCollection() as $invoice) { + if ($invoice->getTransactionId() == $transactionId) { + $invoice->load($invoice->getId()); + // to make sure all data will properly load (maybe not required) + return $invoice; + } + } + foreach ($order->getInvoiceCollection() as $invoice) { + if ($invoice->getState() == \Magento\Sales\Model\Order\Invoice::STATE_OPEN + && $invoice->load($invoice->getId()) + ) { + $invoice->setTransactionId($transactionId); + return $invoice; + } + } + return false; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/AuthorizeOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/AuthorizeOperation.php new file mode 100644 index 0000000000000..8b519c53d8e92 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/AuthorizeOperation.php @@ -0,0 +1,56 @@ +setShouldCloseParentTransaction(false); + $isSameCurrency = $payment->isSameCurrency(); + if (!$isSameCurrency || !$payment->isCaptureFinal($amount)) { + $payment->setIsFraudDetected(true); + } + + // update totals + $amount = $payment->formatAmount($amount, true); + $payment->setBaseAmountAuthorized($amount); + + // do authorization + $order = $payment->getOrder(); + if ($isOnline) { + // invoke authorization on gateway + $method = $payment->getMethodInstance(); + $method->setStore($order->getStoreId()); + $method->authorize($payment, $amount); + } + + $message = $this->stateCommand->execute($payment, $amount, $order); + // update transactions, order state and add comments + $transaction = $payment->addTransaction(Transaction::TYPE_AUTH); + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + + return $payment; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php new file mode 100644 index 0000000000000..f46ed0aef2343 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/CaptureOperation.php @@ -0,0 +1,107 @@ +invoice($payment); + $payment->setCreatedInvoice($invoice); + if ($payment->getIsFraudDetected()) { + $payment->getOrder()->setStatus(Order::STATUS_FRAUD); + } + return $payment; + } + $amountToCapture = $payment->formatAmount($invoice->getBaseGrandTotal()); + $order = $payment->getOrder(); + + // prepare parent transaction and its amount + $paidWorkaround = 0; + if (!$invoice->wasPayCalled()) { + $paidWorkaround = (double)$amountToCapture; + } + $payment->isCaptureFinal($paidWorkaround); + + $payment->setTransactionId( + $this->transactionManager->generateTransactionId( + $payment, + Transaction::TYPE_CAPTURE, + $payment->getAuthorizationTransaction() + ) + ); + + $this->eventManager->dispatch( + 'sales_order_payment_capture', + ['payment' => $payment, 'invoice' => $invoice] + ); + + /** + * Fetch an update about existing transaction. It can determine whether the transaction can be paid + * Capture attempt will happen only when invoice is not yet paid and the transaction can be paid + */ + if ($invoice->getTransactionId()) { + $method = $payment->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + $method->fetchTransactionInfo( + $payment, + $invoice->getTransactionId() + ); + } + + if (!$invoice->getIsPaid()) { + // attempt to capture: this can trigger "is_transaction_pending" + $method = $payment->getMethodInstance(); + $method->setStore( + $order->getStoreId() + ); + //TODO replace for sale usage + $method->capture($payment, $amountToCapture); + + $transaction = $this->transactionBuilder->setPayment($this) + ->setOrder($order) + ->setFailSafe(true) + ->setTransactionId($payment->getTransactionId()) + ->setAdditionalInformation($payment->getTransactionAdditionalInfo()) + ->setSalesDocument($invoice)->build(Transaction::TYPE_CAPTURE); + $message = $this->stateCommand->execute($payment, $amountToCapture, $order); + if ($payment->getIsTransactionPending()) { + $invoice->setIsPaid(false); + } else { + $invoice->setIsPaid(true); + $this->updateTotals($payment, ['base_amount_paid_online' => $amountToCapture]); + } + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + $invoice->setTransactionId($payment->getLastTransId()); + + return $payment; + } + throw new \Magento\Framework\Exception\LocalizedException( + __('The transaction "%1" cannot be captured yet.', $invoice->getTransactionId()) + ); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/OrderOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/OrderOperation.php new file mode 100644 index 0000000000000..9a9a2dbce7a9a --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/OrderOperation.php @@ -0,0 +1,49 @@ +formatAmount($amount, true); + + // do ordering + $order = $payment->getOrder(); + + $method = $payment->getMethodInstance(); + $method->setStore($order->getStoreId()); + $method->order($payment, $amount); + + if ($payment->getSkipOrderProcessing()) { + return $payment; + } + + $message = $this->stateCommand->execute($payment, $amount, $order); + // update transactions, order state and add comments + $transaction = $payment->addTransaction(Transaction::TYPE_ORDER); + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + + return $payment; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php b/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php new file mode 100644 index 0000000000000..7c5e892ce0358 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Operations/RegisterCaptureNotificationOperation.php @@ -0,0 +1,72 @@ +setTransactionId( + $this->transactionManager->generateTransactionId( + $payment, + Transaction::TYPE_CAPTURE, + $payment->getAuthorizationTransaction() + ) + ); + + $order = $payment->getOrder(); + $amount = (double)$amount; + $invoice = $this->getInvoiceForTransactionId($order, $payment->getTransactionId()); + + // register new capture + if (!$invoice) { + if ($payment->isSameCurrency() && $payment->isCaptureFinal($amount)) { + $invoice = $order->prepareInvoice()->register(); + $invoice->setOrder($order); + $order->addRelatedObject($invoice); + $payment->setCreatedInvoice($invoice); + } else { + $payment->setIsFraudDetected(!$skipFraudDetection); + $this->updateTotals($payment, ['base_amount_paid_online' => $amount]); + } + } + + if (!$payment->getIsTransactionPending()) { + if ($invoice && Invoice::STATE_OPEN == $invoice->getState()) { + $invoice->setOrder($order); + $invoice->pay(); + $this->updateTotals($payment, ['base_amount_paid_online' => $amount]); + $order->addRelatedObject($invoice); + } + } + + $message = $this->stateCommand->execute($payment, $amount, $order); + $transaction = $payment->addTransaction( + Transaction::TYPE_CAPTURE, + $invoice, + true + ); + $message = $payment->prependMessage($message); + $payment->addTransactionCommentsToOrder($transaction, $message); + return $payment; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Processor.php b/app/code/Magento/Sales/Model/Order/Payment/Processor.php new file mode 100644 index 0000000000000..987c454697b4b --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Processor.php @@ -0,0 +1,115 @@ +authorizeOperation = $authorizeOperation; + $this->captureOperation = $captureOperation; + $this->orderOperation = $orderOperation; + $this->registerCaptureNotification = $registerCaptureNotification; + } + + /** + * Process authorize operation + * + * @param OrderPaymentInterface $payment + * @param bool $isOnline + * @param float $amount + * @return OrderPaymentInterface|Payment + */ + public function authorize(OrderPaymentInterface $payment, $isOnline, $amount) + { + return $this->authorizeOperation->authorize($payment, $isOnline, $amount); + } + + /** + * Process capture operation + * + * @param OrderPaymentInterface $payment + * @param InvoiceInterface $invoice + * @return OrderPaymentInterface|Payment + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function capture(OrderPaymentInterface $payment, $invoice) + { + return $this->captureOperation->capture($payment, $invoice); + } + + /** + * Process order operation + * + * @param OrderPaymentInterface $payment + * @param float $amount + * @return OrderPaymentInterface|Payment + */ + public function order(OrderPaymentInterface $payment, $amount) + { + return $this->orderOperation->order($payment, $amount); + } + + /** + * Registers capture notification. + * + * @param OrderPaymentInterface $payment + * @param string|float $amount + * @param bool|int $skipFraudDetection + * @return OrderPaymentInterface + */ + public function registerCaptureNotification( + OrderPaymentInterface $payment, + $amount, + $skipFraudDetection = false + ) { + return $this->registerCaptureNotification->registerCaptureNotification($payment, $amount, $skipFraudDetection); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Repository.php b/app/code/Magento/Sales/Model/Order/Payment/Repository.php new file mode 100644 index 0000000000000..28d3ab374dc02 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Repository.php @@ -0,0 +1,125 @@ +metaData = $metaData; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * Lists order payments that match specified search criteria. + * + * @param \Magento\Framework\Api\SearchCriteria $criteria The search criteria. + * @return \Magento\Sales\Api\Data\OrderPaymentSearchResultInterface Order payment search result interface. + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + /** @var \Magento\Sales\Model\Resource\Order\Payment\Collection $collection */ + $collection = $this->searchResultFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + $collection->setCurPage($criteria->getCurrentPage()); + $collection->setPageSize($criteria->getPageSize()); + return $collection; + } + + /** + * Loads a specified order payment. + * + * @param int $id The order payment ID. + * @return \Magento\Sales\Api\Data\OrderPaymentInterface Order payment interface. + * @throws NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + */ + public function get($id) + { + if (!$id) { + throw new \Magento\Framework\Exception\InputException(__('ID required')); + } + if (!isset($this->registry[$id])) { + $entity = $this->metaData->getNewInstance(); + $this->metaData->getMapper()->load($entity, $id); + if (!$entity->getId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + $this->registry[$id] = $entity; + } + return $this->registry[$id]; + } + + /** + * Deletes a specified order payment. + * + * @param \Magento\Sales\Api\Data\OrderPaymentInterface $entity The order payment ID. + * @return bool + */ + public function delete(\Magento\Sales\Api\Data\OrderPaymentInterface $entity) + { + $this->metaData->getMapper()->delete($entity); + return true; + } + + /** + * Performs persist operations for a specified order payment. + * + * @param \Magento\Sales\Api\Data\OrderPaymentInterface $entity The order payment ID. + * @return \Magento\Sales\Api\Data\OrderPaymentInterface Order payment interface. + */ + public function save(\Magento\Sales\Api\Data\OrderPaymentInterface $entity) + { + $this->metaData->getMapper()->save($entity); + return $entity; + } + + /** + * Creates new Order Payment instance. + * + * @return \Magento\Sales\Api\Data\OrderPaymentInterface Transaction interface. + */ + public function create() + { + return $this->metaData->getNewInstance(); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/State/AuthorizeCommand.php b/app/code/Magento/Sales/Model/Order/Payment/State/AuthorizeCommand.php new file mode 100644 index 0000000000000..ecb04bef520b2 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/State/AuthorizeCommand.php @@ -0,0 +1,65 @@ +getBaseCurrency()->formatTxt($amount); + if ($payment->getIsTransactionPending()) { + $state = Order::STATE_PAYMENT_REVIEW; + $message = __( + 'We will authorize %1 after the payment is approved at the payment gateway.', + $formattedAmount + ); + } else { + if ($payment->getIsFraudDetected()) { + $state = Order::STATE_PROCESSING; + $message = __( + 'Order is suspended as its authorizing amount %1 is suspected to be fraudulent.', + $formattedAmount + ); + } else { + $message = __('Authorized amount of %1', $formattedAmount); + } + } + if ($payment->getIsFraudDetected()) { + $status = Order::STATUS_FRAUD; + } + $this->setOrderStateAndStatus($order, $status, $state); + + return $message; + } + + /** + * @param Order $order + * @param string $status + * @param string $state + * @return void + */ + protected function setOrderStateAndStatus(Order $order, $status, $state) + { + if (!$status) { + $status = $order->getConfig()->getStateDefaultStatus($state); + } + + $order->setState($state)->setStatus($status); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/State/CaptureCommand.php b/app/code/Magento/Sales/Model/Order/Payment/State/CaptureCommand.php new file mode 100644 index 0000000000000..950ef4d7d7a22 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/State/CaptureCommand.php @@ -0,0 +1,59 @@ +getBaseCurrency()->formatTxt($amount); + if ($payment->getIsTransactionPending()) { + $message = __( + 'An amount of %1 will be captured after being approved at the payment gateway.', + $formattedAmount + ); + $state = SalesOrder::STATE_PAYMENT_REVIEW; + if ($payment->getIsFraudDetected()) { + $status = SalesOrder::STATUS_FRAUD; + } + } else { + // normal online capture: invoice is marked as "paid" + $message = __('Captured amount of %1 online', $formattedAmount); + } + $this->setOrderStateAndStatus($order, $status, $state); + + return $message; + } + + /** + * @param SalesOrder $order + * @param string $status + * @param string $state + * @return void + */ + protected function setOrderStateAndStatus(SalesOrder $order, $status, $state) + { + if (!$status) { + $status = $order->getConfig()->getStateDefaultStatus($state); + } + + $order->setState($state)->setStatus($status); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/State/CommandInterface.php b/app/code/Magento/Sales/Model/Order/Payment/State/CommandInterface.php new file mode 100644 index 0000000000000..74797be0b70b0 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/State/CommandInterface.php @@ -0,0 +1,25 @@ +getBaseCurrency()->formatTxt($amount); + if ($payment->getIsTransactionPending()) { + $message = __( + 'The order amount of %1 is pending approval on the payment gateway.', + $formattedAmount + ); + $state = Order::STATE_PAYMENT_REVIEW; + if ($payment->getIsFraudDetected()) { + $status = Order::STATUS_FRAUD; + } + } else { + $message = __('Ordered amount of %1', $formattedAmount); + } + $this->setOrderStateAndStatus($order, $status, $state); + + return $message; + } + + /** + * @param Order $order + * @param string $status + * @param string $state + * @return void + */ + protected function setOrderStateAndStatus(Order $order, $status, $state) + { + if (!$status) { + $status = $order->getConfig()->getStateDefaultStatus($state); + } + + $order->setState($state)->setStatus($status); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/State/RegisterCaptureNotificationCommand.php b/app/code/Magento/Sales/Model/Order/Payment/State/RegisterCaptureNotificationCommand.php new file mode 100644 index 0000000000000..88d90080ef2f0 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/State/RegisterCaptureNotificationCommand.php @@ -0,0 +1,67 @@ +getBaseCurrency()->formatTxt($amount); + if ($payment->getIsTransactionPending()) { + $message = __( + 'An amount of %1 will be captured after being approved at the payment gateway.', + $formattedAmount + ); + $state = Order::STATE_PAYMENT_REVIEW; + } else { + $message = __('Registered notification about captured amount of %1.', $formattedAmount); + } + if ($payment->getIsFraudDetected()) { + $state = Order::STATE_PAYMENT_REVIEW; + $message = __( + 'Order is suspended as its capture amount %1 is suspected to be fraudulent.', + $formattedAmount + ); + $status = Order::STATUS_FRAUD; + } + $this->setOrderStateAndStatus($order, $status, $state); + + return $message; + } + + /** + * @param Order $order + * @param string $status + * @param string $state + * @return void + */ + protected function setOrderStateAndStatus(Order $order, $status, $state) + { + if (!$status) { + $status = $order->getConfig()->getStateDefaultStatus($state); + } + + $order->setState($state)->setStatus($status); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php index 40d528fbeb8d5..187e19ee22aa6 100644 --- a/app/code/Magento/Sales/Model/Order/Payment/Transaction.php +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction.php @@ -49,13 +49,6 @@ class Transaction extends AbstractModel implements TransactionInterface */ const RAW_DETAILS = 'raw_details_info'; - /** - * Payment instance. Required for most transaction writing and search operations - * - * @var \Magento\Sales\Model\Order\Payment - */ - protected $_paymentObject = null; - /** * Order instance * @@ -129,11 +122,6 @@ class Transaction extends AbstractModel implements TransactionInterface */ protected $_orderWebsiteId = null; - /** - * @var \Magento\Sales\Model\Order\PaymentFactory - */ - protected $_paymentFactory; - /** * @var \Magento\Sales\Model\OrderFactory */ @@ -149,12 +137,21 @@ class Transaction extends AbstractModel implements TransactionInterface */ protected $_transactionFactory; + /** + * @var \Magento\Sales\Api\OrderPaymentRepositoryInterface + */ + protected $orderPaymentRepository; + + /** + * @var \Magento\Sales\Api\OrderRepositoryInterface + */ + protected $orderRepository; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory - * @param \Magento\Sales\Model\Order\PaymentFactory $paymentFactory * @param \Magento\Sales\Model\OrderFactory $orderFactory * @param \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory * @param TransactionFactory $transactionFactory @@ -168,18 +165,20 @@ public function __construct( \Magento\Framework\Registry $registry, \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, - \Magento\Sales\Model\Order\PaymentFactory $paymentFactory, \Magento\Sales\Model\OrderFactory $orderFactory, + \Magento\Sales\Api\OrderPaymentRepositoryInterface $orderPaymentRepository, + \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Framework\Stdlib\DateTime\DateTimeFactory $dateFactory, TransactionFactory $transactionFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] ) { - $this->_paymentFactory = $paymentFactory; $this->_orderFactory = $orderFactory; $this->_dateFactory = $dateFactory; $this->_transactionFactory = $transactionFactory; + $this->orderPaymentRepository = $orderPaymentRepository; + $this->orderRepository = $orderRepository; parent::__construct( $context, $registry, @@ -202,19 +201,6 @@ protected function _construct() parent::_construct(); } - /** - * Payment instance setter - * - * @param \Magento\Sales\Model\Order\Payment $payment - * @return $this - */ - public function setOrderPaymentObject(\Magento\Sales\Model\Order\Payment $payment) - { - $this->_paymentObject = $payment; - $this->setOrder($payment->getOrder()); - return $this; - } - /** * Transaction ID setter * @@ -277,7 +263,10 @@ public function getParentTransaction($shouldLoad = true) if ($parentId) { $this->_parentTransaction = $this->_transactionFactory->create(); if ($shouldLoad) { - $this->_parentTransaction->setOrderPaymentObject($this->_paymentObject)->load($parentId); + $this->_parentTransaction + ->setOrderId($this->getOrderId()) + ->setPaymentId($this->getPaymentId()) + ->load($parentId); if (!$this->_parentTransaction->getId()) { $this->_parentTransaction = false; } else { @@ -464,47 +453,6 @@ public function hasChildTransaction($whetherHasChild = null) return $this->_hasChild; } - /** - * Check object before loading by by specified transaction ID - * - * @param mixed $txnId - * @return $this - */ - protected function _beforeLoadByTxnId($txnId) - { - $this->_verifyPaymentObject(); - $this->_eventManager->dispatch( - $this->_eventPrefix . '_load_by_txn_id_before', - $this->_getEventData() + ['txn_id' => $txnId] - ); - return $this; - } - - /** - * Load self by specified transaction ID. Requires the valid payment object to be set - * - * @param string $txnId - * @return $this - */ - public function loadByTxnId($txnId) - { - $this->_beforeLoadByTxnId($txnId); - $this->getResource()->loadObjectByTxnId($this, $this->getOrderId(), $this->_paymentObject->getId(), $txnId); - $this->_afterLoadByTxnId(); - return $this; - } - - /** - * Check object after loading by by specified transaction ID - * - * @return $this - */ - protected function _afterLoadByTxnId() - { - $this->_eventManager->dispatch($this->_eventPrefix . '_load_by_txn_id_after', $this->_getEventData()); - return $this; - } - /** * Additional information setter * Updates data inside the 'additional_information' array @@ -603,29 +551,6 @@ public function close($shouldSave = true) return $this; } - /** - * Order Payment instance getter - * Will attempt to load by payment_id if it is set in data - * - * @param bool $shouldLoad - * @return \Magento\Sales\Model\Order\Payment - */ - public function getOrderPaymentObject($shouldLoad = true) - { - $this->_verifyThisTransactionExists(); - if (null === $this->_paymentObject && $shouldLoad) { - /** @var \Magento\Sales\Model\Order\Payment $payment */ - $payment = $this->_paymentFactory->create()->load($this->getPaymentId()); - if ($payment->getId()) { - if (!$payment->getOrder()) { - $payment->setOrder($this->getOrder()); - } - $this->setOrderPaymentObject($payment); - } - } - return $this->_paymentObject; - } - /** * Order ID getter * Attempts to get ID from set order payment object, if any, or from data by key 'order_id' @@ -638,14 +563,11 @@ public function getOrderId() if ($orderId) { return $orderId; } - if ($this->_paymentObject) { - $orderId = $this->_paymentObject - ->getOrder() ? $this - ->_paymentObject - ->getOrder() - ->getId() : $this - ->_paymentObject - ->getParentId(); + if ($this->getPaymentId()) { + $payment = $this->orderPaymentRepository->get($this->getPaymentId()); + if ($payment) { + $orderId = $payment->getParentId(); + } } return $orderId; @@ -676,10 +598,8 @@ public function getOrder() public function setOrder($order = null) { if (null === $order || $order === true) { - if (null !== $this->_paymentObject && $this->_paymentObject->getOrder()) { - $this->_order = $this->_paymentObject->getOrder(); - } elseif ($this->getOrderId() && $order === null) { - $this->_order = $this->_orderFactory->create()->load($this->getOrderId()); + if ($this->getOrderId()) { + $this->_order = $this->orderRepository->get($this->getOrderId()); } else { $this->_order = false; } @@ -714,18 +634,15 @@ public function isFailsafe($setFailsafe = null) */ public function beforeSave() { + if (!$this->getOrderId() && $this->getOrder()) { + $this->setOrderId($this->getOrder()->getId()); + } + if (!$this->getPaymentId() && $this->getOrder() && $this->getOrder()->getPayment()) { + $this->setPaymentId($this->getOrder()->getPayment()->getId()); + } // set parent id $this->_verifyPaymentObject(); if (!$this->getId()) { - // We need to set order and payment ids only for new transactions - if (null !== $this->_paymentObject) { - $this->setPaymentId($this->_paymentObject->getId()); - } - - if (null !== $this->_order) { - $this->setOrderId($this->_order->getId()); - } - $this->setCreatedAt($this->_dateFactory->create()->gmtDate()); } return parent::beforeSave(); @@ -747,9 +664,7 @@ protected function _loadChildren() // make sure minimum required data is set $this->_verifyThisTransactionExists(); - $payment = $this->_verifyPaymentObject(true); - $paymentId = $payment ? $payment->getId() : $this->_getData('payment_id'); - if (!$paymentId) { + if (!$this->getPaymentId()) { throw new \Magento\Framework\Exception\LocalizedException(__('At minimum, you need to set a payment ID.')); } @@ -765,7 +680,7 @@ protected function _loadChildren() $children = $this->getResourceCollection()->setOrderFilter( $orderFilter )->addPaymentIdFilter( - $paymentId + $this->getPaymentId() )->addParentIdFilter( $this->getId() ); @@ -774,8 +689,8 @@ protected function _loadChildren() $this->_children = []; $this->_identifiedChildren = []; foreach ($children as $child) { - if ($payment) { - $child->setOrderPaymentObject($payment); + if ($this->getPaymentId()) { + $child->setOrderId($this->getOrderId())->setPaymentId($this->getPaymentId()); } $this->_children[$child->getId()] = $child; if (false !== $this->_identifiedChildren) { @@ -873,17 +788,18 @@ protected function _verifyTxnType($txnType = null) * $dryRun allows to not throw exception * * @param bool $dryRun - * @return \Magento\Sales\Model\Order\Payment|null|false + * @return void * @throws \Magento\Framework\Exception\LocalizedException */ protected function _verifyPaymentObject($dryRun = false) { - if (!$this->_paymentObject || !$this->getOrderId()) { + if (!$this->getPaymentId() || !$this->getOrderId()) { if (!$dryRun) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please set a proper payment object.')); + throw new \Magento\Framework\Exception\LocalizedException( + __('Please set a proper payment and order id.') + ); } } - return $this->_paymentObject; } /** diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction/Builder.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Builder.php new file mode 100644 index 0000000000000..55d49463e9c4b --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction/Builder.php @@ -0,0 +1,243 @@ +transactionRepository = $transactionRepository; + } + + /** + * {@inheritdoc} + */ + public function setPayment(OrderPaymentInterface $payment) + { + $this->payment = $payment; + return $this; + } + + /** + * {@inheritdoc} + */ + public function setOrder(OrderInterface $order) + { + $this->order = $order; + return $this; + } + + /** + * {@inheritdoc} + */ + public function setSalesDocument(\Magento\Sales\Model\AbstractModel $document) + { + $this->document = $document; + return $this; + } + + /** + * {@inheritdoc} + */ + public function setFailSafe($failSafe) + { + $this->failSafe = $failSafe; + return $this; + } + + /** + * {@inheritdoc} + */ + public function setMessage($message) + { + $this->message = $message; + return $this; + } + + /** + * {@inheritdoc} + */ + public function setTransactionId($transactionId) + { + $this->transactionId = $transactionId; + return $this; + } + + + /** + * {@inheritdoc} + */ + public function setAdditionalInformation(array $value) + { + $this->transactionAdditionalInfo = $value; + return $this; + } + + /** + * {@inheritdoc} + */ + public function addAdditionalInformation($key, $value) + { + $this->transactionAdditionalInfo[$key] = $value; + return $this; + } + + /** + * {@inheritdoc} + */ + public function reset() + { + unset($this->payment); + unset($this->document); + unset($this->order); + unset($this->message); + unset($this->transactionId); + $this->failSafe = false; + $this->transactionAdditionalInfo = []; + return $this; + } + + /** + * Checks if payment was set + * + * @return bool + */ + protected function isPaymentExists() + { + if ($this->payment) { + if ($this->payment->getSkipTransactionCreation()) { + $this->payment->unsTransactionId(); + return false; + } + return true; + } + return false; + } + + /** + * {@inheritdoc} + */ + public function build($type) + { + if ($this->isPaymentExists() && $this->transactionId !== null) { + $transaction = $this->transactionRepository->getByTransactionId( + $this->transactionId, + $this->payment->getId(), + $this->order->getId() + ); + if (!$transaction) { + $transaction = $this->transactionRepository->create()->setTxnId($this->transactionId); + } + $transaction->setPaymentId($this->payment->getId()) + ->setOrderId($this->order->getId()) + ->setTxnType($type) + ->isFailsafe($this->failSafe); + + if ($this->payment->hasIsTransactionClosed()) { + $transaction->setIsClosed((int)$this->payment->getIsTransactionClosed()); + } + if ($this->transactionAdditionalInfo) { + foreach ($this->transactionAdditionalInfo as $key => $value) { + $transaction->setAdditionalInformation($key, $value); + } + } + $this->transactionAdditionalInfo = []; + + $this->payment->setLastTransId($transaction->getTxnId()); + $this->payment->setCreatedTransaction($transaction); + $this->order->addRelatedObject($transaction); + if ($this->document && $this->document instanceof AbstractModel) { + $this->document->setTransactionId($transaction->getTxnId()); + } + + return $this->linkWithParentTransaction($transaction); + } + return null; + } + + /** + * Links transaction with parent transaction + * + * @param TransactionInterface $transaction + * @return TransactionInterface + */ + protected function linkWithParentTransaction(TransactionInterface $transaction) + { + $parentTransactionId = $this->payment->getParentTransactionId(); + + if ($parentTransactionId) { + $transaction->setParentTxnId($parentTransactionId); + if ($this->payment->getShouldCloseParentTransaction()) { + $parentTransaction = $this->transactionRepository->getByTransactionId( + $parentTransactionId, + $this->payment->getid(), + $this->order->getId() + ); + if ($parentTransaction) { + if (!$parentTransaction->getIsClosed()) { + $parentTransaction->isFailsafe($this->failSafe)->close(false); + } + $this->order->addRelatedObject($parentTransaction); + } + } + } + return $transaction; + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction/BuilderInterface.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction/BuilderInterface.php new file mode 100644 index 0000000000000..1ae13bd6506c7 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction/BuilderInterface.php @@ -0,0 +1,106 @@ +transactionRepository = $transactionRepository; + } + + /** + * {@inheritdoc} + */ + public function getAuthorizationTransaction($parentTransactionId, $paymentId, $orderId) + { + $transaction = false; + if ($parentTransactionId) { + $transaction = $this->transactionRepository->getByTransactionId( + $parentTransactionId, + $paymentId, + $orderId + ); + } + + return $transaction ?: $this->transactionRepository->getByTransactionType( + Transaction::TYPE_AUTH, + $paymentId, + $orderId + ); + } + + /** + * Checks if transaction exists by txt id + * + * @param string $transactionId + * @param int $paymentId + * @param int $orderId + * @return bool + */ + public function isTransactionExists($transactionId, $paymentId, $orderId) + { + return $transactionId && $this->transactionRepository->getByTransactionId($transactionId, $paymentId, $orderId); + } + + /** + * Update transaction ids for further processing + * If no transactions were set before invoking, may generate an "offline" transaction id + * + * @param OrderPaymentInterface $payment + * @param string $type + * @param bool|Transaction $transactionBasedOn + * @return string|null + */ + public function generateTransactionId(OrderPaymentInterface $payment, $type, $transactionBasedOn = false) + { + if (!$payment->getParentTransactionId() && !$payment->getTransactionId() && $transactionBasedOn) { + $payment->setParentTransactionId($transactionBasedOn->getTxnId()); + } + // generate transaction id for an offline action or payment method that didn't set it + if (($parentTxnId = $payment->getParentTransactionId()) && !$payment->getTransactionId()) { + return "{$parentTxnId}-{$type}"; + } + return $payment->getTransactionId(); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/Transaction/ManagerInterface.php b/app/code/Magento/Sales/Model/Order/Payment/Transaction/ManagerInterface.php new file mode 100644 index 0000000000000..8f8cf817ca537 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/Payment/Transaction/ManagerInterface.php @@ -0,0 +1,47 @@ +searchResultFactory = $searchResultFactory; + $this->filterBuilder = $filterBuilder; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->sortOrderBuilder = $sortOrderBuilder; + $this->metaData = $metaData; + $this->entityStorage = $entityStorageFactory->create(); + } + + /** + * {@inheritdoc} + */ + public function get($id) + { + if (!$id) { + throw new \Magento\Framework\Exception\InputException(__('ID required')); + } + if (!$this->entityStorage->has($id)) { + $entity = $this->metaData->getNewInstance(); + /** @var \Magento\Sales\Api\Data\TransactionInterface $entity */ + $this->metaData->getMapper()->load($entity, $id); + if (!$entity->getTransactionId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + $this->entityStorage->add($entity); + } + return $this->entityStorage->get($id); + } + + /** + * @param int $transactionType + * @param int $paymentId + * @param int $orderId + * @return bool|\Magento\Framework\Model\AbstractModel|mixed + * @throws \Magento\Framework\Exception\InputException + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function getByTransactionType($transactionType, $paymentId, $orderId) + { + $identityFieldsForCache = [$transactionType, $paymentId]; + $cacheStorage = 'txn_type'; + $entity = $this->entityStorage->getByIdentifyingFields($identityFieldsForCache, $cacheStorage); + if (!$entity) { + $filters[] = $this->filterBuilder + ->setField(TransactionInterface::TXN_TYPE) + ->setValue($transactionType) + ->create(); + $filters[] = $this->filterBuilder + ->setField(TransactionInterface::PAYMENT_ID) + ->setValue($paymentId) + ->create(); + $transactionIdSort = $this->sortOrderBuilder + ->setField('transaction_id') + ->setDirection(Collection::SORT_ORDER_DESC) + ->create(); + $createdAtSort = $this->sortOrderBuilder + ->setField('created_at') + ->setDirection(Collection::SORT_ORDER_DESC) + ->create(); + $entity = current( + $this->getList( + $this->searchCriteriaBuilder + ->addFilters($filters) + ->addSortOrder($transactionIdSort) + ->addSortOrder($createdAtSort) + ->create() + )->getItems() + ); + if ($entity) { + $this->entityStorage->addByIdentifyingFields($entity, $identityFieldsForCache, $cacheStorage); + } + } + + return $entity; + } + + /** + * @param int $transactionId + * @param int $paymentId + * @param int $orderId + * @return bool|\Magento\Framework\Api\ExtensibleDataInterface|\Magento\Framework\Model\AbstractModel + * @throws \Magento\Framework\Exception\InputException + */ + public function getByTransactionId($transactionId, $paymentId, $orderId) + { + $identityFieldsForCache = [$transactionId, $paymentId, $orderId]; + $cacheStorage = 'txn_id'; + $entity = $this->entityStorage->getByIdentifyingFields($identityFieldsForCache, $cacheStorage); + if (!$entity) { + $entity = $this->metaData->getNewInstance(); + $this->metaData->getMapper()->loadObjectByTxnId( + $entity, + $orderId, + $paymentId, + $transactionId + ); + if ($entity && $entity->getId()) { + $this->entityStorage->addByIdentifyingFields($entity, $identityFieldsForCache, $cacheStorage); + return $entity; + } + return false; + } + return $entity; + } + + /** + * {@inheritdoc} + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + /** @var TransactionResource\Collection $collection */ + $collection = $this->searchResultFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + $collection->setCurPage($criteria->getCurrentPage()); + $collection->setPageSize($criteria->getPageSize()); + $collection->addPaymentInformation(['method']); + $collection->addOrderInformation(['increment_id']); + return $collection; + } + + /** + * {@inheritdoc} + */ + public function delete(\Magento\Sales\Api\Data\TransactionInterface $entity) + { + $this->metaData->getMapper()->delete($entity); + $this->entityStorage->remove($entity->getTransactionId()); + return true; + } + + /** + * {@inheritdoc} + */ + public function save(\Magento\Sales\Api\Data\TransactionInterface $entity) + { + $this->metaData->getMapper()->save($entity); + $this->entityStorage->add($entity); + return $this->entityStorage->get($entity->getTransactionId()); + } + + /** + * Creates new Transaction instance. + * + * @return \Magento\Sales\Api\Data\TransactionInterface Transaction interface. + */ + public function create() + { + return $this->metaData->getNewInstance(); + } +} diff --git a/app/code/Magento/Sales/Model/Order/Payment/TransactionRepository.php b/app/code/Magento/Sales/Model/Order/Payment/TransactionRepository.php deleted file mode 100644 index bbe428020fc9f..0000000000000 --- a/app/code/Magento/Sales/Model/Order/Payment/TransactionRepository.php +++ /dev/null @@ -1,136 +0,0 @@ -transactionFactory = $transactionFactory; - $this->transactionCollectionFactory = $transactionCollectionFactory; - $this->filterBuilder = $filterBuilder; - $this->searchCriteriaBuilder = $searchCriteriaBuilder; - } - - /** - * load entity - * - * @param int $id - * @return Transaction - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - */ - public function get($id) - { - if (!$id) { - throw new \Magento\Framework\Exception\InputException(__('ID required')); - } - if (!isset($this->registry[$id])) { - $filter = $this->filterBuilder->setField('transaction_id')->setValue($id)->setConditionType('eq')->create(); - $this->searchCriteriaBuilder->addFilters([$filter]); - $this->find($this->searchCriteriaBuilder->create()); - - if (!isset($this->registry[$id])) { - throw new \Magento\Framework\Exception\NoSuchEntityException( - __('Requested entity doesn\'t exist') - ); - } - } - return $this->registry[$id]; - } - - /** - * Register entity - * - * @param Transaction $object - * @return TransactionRepository - */ - public function register(Transaction $object) - { - if ($object->getId() && !isset($this->registry[$object->getId()])) { - $this->registry[$object->getId()] = $object; - } - return $this; - } - - /** - * Find entities by criteria - * - * @param \Magento\Framework\Api\SearchCriteria $criteria - * @return Transaction[] - */ - public function find(\Magento\Framework\Api\SearchCriteria $criteria) - { - /** @var TransactionResource\Collection $collection */ - $collection = $this->transactionCollectionFactory->create(); - foreach ($criteria->getFilterGroups() as $filterGroup) { - foreach ($filterGroup->getFilters() as $filter) { - $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; - $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); - } - } - $collection->setCurPage($criteria->getCurrentPage()); - $collection->setPageSize($criteria->getPageSize()); - $collection->addPaymentInformation(['method']); - $collection->addOrderInformation(['increment_id']); - foreach ($collection as $object) { - $this->register($object); - } - $objectIds = $collection->getAllIds(); - return array_intersect_key($this->registry, array_flip($objectIds)); - } -} diff --git a/app/code/Magento/Sales/Model/Order/Shipment.php b/app/code/Magento/Sales/Model/Order/Shipment.php index 21ad40b2c30b9..b43efb1490d06 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment.php +++ b/app/code/Magento/Sales/Model/Order/Shipment.php @@ -234,9 +234,7 @@ public function getShippingAddress() } /** - * Register shipment - * - * Apply to order, order items etc. + * Registers shipment. * * @return $this * @throws \Magento\Framework\Exception\LocalizedException @@ -244,13 +242,18 @@ public function getShippingAddress() public function register() { if ($this->getId()) { - throw new \Magento\Framework\Exception\LocalizedException(__('We cannot register an existing shipment')); + throw new \Magento\Framework\Exception\LocalizedException( + __('We cannot register an existing shipment') + ); } $totalQty = 0; + + /** @var \Magento\Sales\Model\Order\Shipment\Item $item */ foreach ($this->getAllItems() as $item) { if ($item->getQty() > 0) { $item->register(); + if (!$item->getOrderItem()->isDummy(true)) { $totalQty += $item->getQty(); } @@ -258,6 +261,7 @@ public function register() $item->isDeleted(true); } } + $this->setTotalQty($totalQty); return $this; @@ -453,36 +457,6 @@ public function getCommentsCollection($reload = false) return $this->getComments(); } - /** - * Before object save - * - * @return $this - */ - protected function _beforeSave() - { - return parent::_beforeSave(); - } - - /** - * Before object delete - * - * @return $this - */ - protected function _beforeDelete() - { - return parent::_beforeDelete(); - } - - /** - * After object save manipulations - * - * @return $this - */ - protected function _afterSave() - { - return parent::_afterSave(); - } - /** * Retrieve store model instance * diff --git a/app/code/Magento/Sales/Model/Order/Shipment/Track.php b/app/code/Magento/Sales/Model/Order/Shipment/Track.php index 7c203248241da..0b0116171e3cd 100644 --- a/app/code/Magento/Sales/Model/Order/Shipment/Track.php +++ b/app/code/Magento/Sales/Model/Order/Shipment/Track.php @@ -44,9 +44,9 @@ class Track extends AbstractModel implements ShipmentTrackInterface protected $_storeManager; /** - * @var \Magento\Sales\Model\Order\ShipmentFactory + * @var \Magento\Sales\Model\Order\ShipmentRepository */ - protected $_shipmentFactory; + protected $shipmentRepository; /** * @param \Magento\Framework\Model\Context $context @@ -54,7 +54,7 @@ class Track extends AbstractModel implements ShipmentTrackInterface * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory + * @param \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection * @param array $data @@ -66,7 +66,7 @@ public function __construct( \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, + \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, array $data = [] @@ -81,7 +81,7 @@ public function __construct( $data ); $this->_storeManager = $storeManager; - $this->_shipmentFactory = $shipmentFactory; + $this->shipmentRepository = $shipmentRepository; } /** @@ -141,7 +141,7 @@ public function setShipment(\Magento\Sales\Model\Order\Shipment $shipment) public function getShipment() { if (!$this->_shipment instanceof \Magento\Sales\Model\Order\Shipment) { - $this->_shipment = $this->_shipmentFactory->create()->load($this->getParentId()); + $this->_shipment = $this->shipmentRepository->get($this->getParentId()); } return $this->_shipment; diff --git a/app/code/Magento/Sales/Model/Order/ShipmentFactory.php b/app/code/Magento/Sales/Model/Order/ShipmentFactory.php new file mode 100644 index 0000000000000..444b8ceaf06ad --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/ShipmentFactory.php @@ -0,0 +1,214 @@ +converter = $convertOrderFactory->create(); + $this->trackFactory = $trackFactory; + $this->instanceName = '\Magento\Sales\Api\Data\ShipmentInterface'; + } + + /** + * Creates shipment instance with specified parameters. + * + * @param \Magento\Sales\Model\Order $order + * @param array $items + * @param array|null $tracks + * @return \Magento\Sales\Api\Data\ShipmentInterface + */ + public function create(\Magento\Sales\Model\Order $order, array $items = [], $tracks = null) + { + $shipment = $this->prepareItems($this->converter->toShipment($order), $order, $items); + + if ($tracks) { + $shipment = $this->prepareTracks($shipment, $tracks); + } + + return $shipment; + } + + /** + * Adds items to the shipment. + * + * @param \Magento\Sales\Api\Data\ShipmentInterface $shipment + * @param \Magento\Sales\Model\Order $order + * @param array $items + * @return \Magento\Sales\Api\Data\ShipmentInterface + */ + protected function prepareItems( + \Magento\Sales\Api\Data\ShipmentInterface $shipment, + \Magento\Sales\Model\Order $order, + array $items = [] + ) { + $totalQty = 0; + + foreach ($order->getAllItems() as $orderItem) { + if (!$this->canShipItem($orderItem, $items)) { + continue; + } + + /** @var \Magento\Sales\Model\Order\Shipment\Item $item */ + $item = $this->converter->itemToShipmentItem($orderItem); + + if ($orderItem->isDummy(true)) { + $qty = 0; + + if (isset($items[$orderItem->getParentItemId()])) { + $productOptions = $orderItem->getProductOptions(); + + if (isset($productOptions['bundle_selection_attributes'])) { + $bundleSelectionAttributes = unserialize( + $productOptions['bundle_selection_attributes'] + ); + + if ($bundleSelectionAttributes) { + $qty = $bundleSelectionAttributes['qty'] * $items[$orderItem->getParentItemId()]; + $qty = min($qty, $orderItem->getSimpleQtyToShip()); + + $item->setQty($qty); + $shipment->addItem($item); + + continue; + } else { + $qty = 1; + } + } + } else { + $qty = 1; + } + } else { + if (isset($items[$orderItem->getId()])) { + $qty = min($items[$orderItem->getId()], $orderItem->getQtyToShip()); + } elseif (!count($items)) { + $qty = $orderItem->getQtyToShip(); + } else { + continue; + } + } + + $totalQty += $qty; + + $item->setQty($qty); + $shipment->addItem($item); + } + + return $shipment->setTotalQty($totalQty); + } + + /** + * Adds tracks to the shipment. + * + * @param \Magento\Sales\Api\Data\ShipmentInterface $shipment + * @param array $tracks + * @throws \Magento\Framework\Exception\LocalizedException + * @return \Magento\Sales\Api\Data\ShipmentInterface + */ + protected function prepareTracks(\Magento\Sales\Api\Data\ShipmentInterface $shipment, array $tracks) + { + foreach ($tracks as $data) { + if (empty($data['number'])) { + throw new \Magento\Framework\Exception\LocalizedException( + __('Please enter a tracking number.') + ); + } + + $shipment->addTrack( + $this->trackFactory->create()->addData($data) + ); + } + + return $shipment; + } + + /** + * Checks if order item can be shipped. + * + * Dummy item can be shipped or with his children or + * with parent item which is included to shipment. + * + * @param \Magento\Sales\Model\Order\Item $item + * @param array $items + * @return bool + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function canShipItem($item, array $items = []) + { + if ($item->getIsVirtual() || $item->getLockedDoShip()) { + return false; + } + + if ($item->isDummy(true)) { + if ($item->getHasChildren()) { + if ($item->isShipSeparately()) { + return true; + } + + foreach ($item->getChildrenItems() as $child) { + if ($child->getIsVirtual()) { + continue; + } + + if (empty($items)) { + if ($child->getQtyToShip() > 0) { + return true; + } + } else { + if (isset($items[$child->getId()]) && $items[$child->getId()] > 0) { + return true; + } + } + } + + return false; + } elseif ($item->getParentItem()) { + $parent = $item->getParentItem(); + + if (empty($items)) { + return $parent->getQtyToShip() > 0; + } else { + return isset($items[$parent->getId()]) && $items[$parent->getId()] > 0; + } + } + } else { + return $item->getQtyToShip() > 0; + } + } +} diff --git a/app/code/Magento/Sales/Model/Order/ShipmentRepository.php b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php new file mode 100644 index 0000000000000..c4240377da7f9 --- /dev/null +++ b/app/code/Magento/Sales/Model/Order/ShipmentRepository.php @@ -0,0 +1,163 @@ +metadata = $metadata; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * Loads a specified shipment. + * + * @param int $id + * @return \Magento\Sales\Api\Data\ShipmentInterface + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function get($id) + { + if (!$id) { + throw new InputException(__('Id required')); + } + + if (!isset($this->registry[$id])) { + /** @var \Magento\Sales\Api\Data\ShipmentInterface $entity */ + $entity = $this->metadata->getNewInstance(); + + $this->metadata->getMapper()->load($entity, $id); + + if (!$entity->getEntityId()) { + throw new NoSuchEntityException(__('Requested entity doesn\'t exist')); + } + + $this->registry[$id] = $entity; + } + + return $this->registry[$id]; + } + + /** + * Find shipments by criteria. + * + * @param \Magento\Framework\Api\SearchCriteria $criteria + * @return \Magento\Sales\Api\Data\ShipmentInterface[] + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + //@TODO: fix search logic + /** @var \Magento\Sales\Api\Data\ShipmentSearchResultInterface $searchResult */ + $searchResult = $this->searchResultFactory->create(); + + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + + $searchResult->setCurPage($criteria->getCurrentPage()); + $searchResult->setPageSize($criteria->getPageSize()); + + return $searchResult; + } + + /** + * Deletes a specified shipment. + * + * @param \Magento\Sales\Api\Data\ShipmentInterface $entity + * @return bool + * @throws CouldNotDeleteException + */ + public function delete(\Magento\Sales\Api\Data\ShipmentInterface $entity) + { + try { + $this->metadata->getMapper()->delete($entity); + + unset($this->registry[$entity->getEntityId()]); + } catch (\Exception $e) { + throw new CouldNotDeleteException(__('Could not delete shipment'), $e); + } + + return true; + } + + /** + * Deletes shipment by Id. + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->get($id); + + return $this->delete($entity); + } + + /** + * Performs persist operations for a specified shipment. + * + * @param \Magento\Sales\Api\Data\ShipmentInterface $entity + * @return \Magento\Sales\Api\Data\ShipmentInterface + * @throws CouldNotSaveException + */ + public function save(\Magento\Sales\Api\Data\ShipmentInterface $entity) + { + try { + $this->metadata->getMapper()->save($entity); + $this->registry[$entity->getEntityId()] = $entity; + } catch (\Exception $e) { + throw new CouldNotSaveException(__('Could not save shipment'), $e); + } + + return $this->registry[$entity->getEntityId()]; + } + + /** + * Creates new shipment instance. + * + * @return \Magento\Sales\Api\Data\ShipmentInterface + */ + public function create() + { + return $this->metadata->getNewInstance(); + } +} diff --git a/app/code/Magento/Sales/Model/OrderRepository.php b/app/code/Magento/Sales/Model/OrderRepository.php new file mode 100644 index 0000000000000..d04a2d7005f09 --- /dev/null +++ b/app/code/Magento/Sales/Model/OrderRepository.php @@ -0,0 +1,132 @@ +metadata = $metadata; + $this->searchResultFactory = $searchResultFactory; + } + + /** + * load entity + * + * @param int $id + * @return \Magento\Sales\Api\Data\OrderInterface + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function get($id) + { + if (!$id) { + throw new InputException('Id required'); + } + if (!isset($this->registry[$id])) { + /** @var \Magento\Sales\Api\Data\OrderInterface $entity */ + $entity = $this->metadata->getNewInstance(); + $this->metadata->getMapper()->load($entity, $id); + if (!$entity->getEntityId()) { + throw new NoSuchEntityException('Requested entity doesn\'t exist'); + } + $this->registry[$id] = $entity; + } + return $this->registry[$id]; + } + + /** + * Find entities by criteria + * + * @param \Magento\Framework\Api\SearchCriteria $criteria + * @return \Magento\Sales\Api\Data\OrderInterface[] + */ + public function getList(\Magento\Framework\Api\SearchCriteria $criteria) + { + //@TODO: fix search logic + /** @var \Magento\Sales\Api\Data\OrderSearchResultInterface $searchResult */ + $searchResult = $this->searchResultFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $searchResult->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); + } + } + $searchResult->setCurPage($criteria->getCurrentPage()); + $searchResult->setPageSize($criteria->getPageSize()); + return $searchResult; + } + + /** + * Register entity to delete + * + * @param \Magento\Sales\Api\Data\OrderInterface $entity + * @return bool + */ + public function delete(\Magento\Sales\Api\Data\OrderInterface $entity) + { + $this->metadata->getMapper()->delete($entity); + unset($this->registry[$entity->getEntityId()]); + return true; + } + + /** + * Delete entity by Id + * + * @param int $id + * @return bool + */ + public function deleteById($id) + { + $entity = $this->get($id); + return $this->delete($entity); + } + + /** + * Perform persist operations for one entity + * + * @param \Magento\Sales\Api\Data\OrderInterface $entity + * @return \Magento\Sales\Api\Data\OrderInterface + */ + public function save(\Magento\Sales\Api\Data\OrderInterface $entity) + { + $this->metadata->getMapper()->save($entity); + $this->registry[$entity->getEntityId()] = $entity; + return $this->registry[$entity->getEntityId()]; + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php b/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php index 53bd3b0aaa02a..c65755f58de46 100644 --- a/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php +++ b/app/code/Magento/Sales/Model/Resource/Collection/AbstractCollection.php @@ -16,6 +16,11 @@ abstract class AbstractCollection extends \Magento\Framework\Model\Resource\Db\V */ protected $_countSelect; + /** + * @var \Magento\Framework\Api\SearchCriteriaInterface + */ + protected $searchCriteria; + /** * Set select count sql * @@ -157,7 +162,7 @@ public function getAllIds($limit = null, $offset = null) */ public function getSearchCriteria() { - return null; + return $this->searchCriteria; } /** @@ -169,6 +174,7 @@ public function getSearchCriteria() */ public function setSearchCriteria(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria = null) { + $this->searchCriteria = $searchCriteria; return $this; } @@ -199,10 +205,15 @@ public function setTotalCount($totalCount) * * @param \Magento\Framework\Api\ExtensibleDataInterface[] $items * @return $this - * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function setItems(array $items = null) { + if (!$items) { + return $this; + } + foreach ($items as $item) { + $this->addItem($item); + } return $this; } } diff --git a/app/code/Magento/Sales/Model/Resource/Metadata.php b/app/code/Magento/Sales/Model/Resource/Metadata.php new file mode 100644 index 0000000000000..0ae10810ffa5d --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Metadata.php @@ -0,0 +1,58 @@ +objectManager = $objectManager; + $this->resourceClassName = $resourceClassName; + $this->modelClassName = $modelClassName; + } + + /** + * @return \Magento\Framework\Model\Resource\Db\AbstractDb + */ + public function getMapper() + { + return $this->objectManager->get($this->resourceClassName); + } + + /** + * @return \Magento\Framework\Api\ExtensibleDataInterface + */ + public function getNewInstance() + { + return $this->objectManager->create($this->modelClassName); + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Grid/StatusList.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Grid/StatusList.php index fd200358dc9c4..0b65f060875f3 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Grid/StatusList.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Grid/StatusList.php @@ -11,16 +11,16 @@ class StatusList implements \Magento\Framework\Option\ArrayInterface { /** - * @var \Magento\Sales\Model\Order\CreditmemoFactory + * @var \Magento\Sales\Api\CreditmemoRepositoryInterface */ - protected $creditmemoFactory; + protected $creditmemoRepository; /** - * @param \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory + * @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository */ - public function __construct(\Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory) + public function __construct(\Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository) { - $this->creditmemoFactory = $creditmemoFactory; + $this->creditmemoRepository = $creditmemoRepository; } /** @@ -30,6 +30,6 @@ public function __construct(\Magento\Sales\Model\Order\CreditmemoFactory $credit */ public function toOptionArray() { - return $this->creditmemoFactory->create()->getStates(); + return $this->creditmemoRepository->create()->getStates(); } } diff --git a/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation/Refund.php b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation/Refund.php new file mode 100644 index 0000000000000..355c0003f9123 --- /dev/null +++ b/app/code/Magento/Sales/Model/Resource/Order/Creditmemo/Relation/Refund.php @@ -0,0 +1,162 @@ +orderRepository = $orderRepository; + $this->invoiceRepository = $invoiceRepository; + $this->priceCurrency = $priceCurrency; + } + + /** + * Process relations for CreditMemo + * + * @param \Magento\Framework\Model\AbstractModel $object + * @throws \Exception + * @return void + */ + public function processRelation(\Magento\Framework\Model\AbstractModel $object) + { + /** @var \Magento\Sales\Model\Order\Creditmemo $object */ + if ($object->getState() == \Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED) { + $this->prepareOrder($object); + $this->orderRepository->save($object->getOrder()); + if ($object->getInvoice()) { + $this->prepareInvoice($object); + $this->invoiceRepository->save($object->getInvoice()); + } + $this->preparePayment($object); + } + } + + /** + * Prepare order data for refund + * + * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo + * @return void + */ + protected function prepareOrder(\Magento\Sales\Model\Order\Creditmemo $creditmemo) + { + $order = $creditmemo->getOrder(); + $baseOrderRefund = $this->priceCurrency->round( + $order->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal() + ); + $orderRefund = $this->priceCurrency->round( + $order->getTotalRefunded() + $creditmemo->getGrandTotal() + ); + $order->setBaseTotalRefunded($baseOrderRefund); + $order->setTotalRefunded($orderRefund); + + $order->setBaseSubtotalRefunded($order->getBaseSubtotalRefunded() + $creditmemo->getBaseSubtotal()); + $order->setSubtotalRefunded($order->getSubtotalRefunded() + $creditmemo->getSubtotal()); + + $order->setBaseTaxRefunded($order->getBaseTaxRefunded() + $creditmemo->getBaseTaxAmount()); + $order->setTaxRefunded($order->getTaxRefunded() + $creditmemo->getTaxAmount()); + $order->setBaseDiscountTaxCompensationRefunded( + $order->getBaseDiscountTaxCompensationRefunded() + $creditmemo->getBaseDiscountTaxCompensationAmount() + ); + $order->setDiscountTaxCompensationRefunded( + $order->getDiscountTaxCompensationRefunded() + $creditmemo->getDiscountTaxCompensationAmount() + ); + + $order->setBaseShippingRefunded($order->getBaseShippingRefunded() + $creditmemo->getBaseShippingAmount()); + $order->setShippingRefunded($order->getShippingRefunded() + $creditmemo->getShippingAmount()); + + $order->setBaseShippingTaxRefunded( + $order->getBaseShippingTaxRefunded() + $creditmemo->getBaseShippingTaxAmount() + ); + $order->setShippingTaxRefunded($order->getShippingTaxRefunded() + $creditmemo->getShippingTaxAmount()); + + $order->setAdjustmentPositive($order->getAdjustmentPositive() + $creditmemo->getAdjustmentPositive()); + $order->setBaseAdjustmentPositive( + $order->getBaseAdjustmentPositive() + $creditmemo->getBaseAdjustmentPositive() + ); + + $order->setAdjustmentNegative($order->getAdjustmentNegative() + $creditmemo->getAdjustmentNegative()); + $order->setBaseAdjustmentNegative( + $order->getBaseAdjustmentNegative() + $creditmemo->getBaseAdjustmentNegative() + ); + + $order->setDiscountRefunded($order->getDiscountRefunded() + $creditmemo->getDiscountAmount()); + $order->setBaseDiscountRefunded($order->getBaseDiscountRefunded() + $creditmemo->getBaseDiscountAmount()); + + if ($creditmemo->getDoTransaction()) { + $order->setTotalOnlineRefunded($order->getTotalOnlineRefunded() + $creditmemo->getGrandTotal()); + $order->setBaseTotalOnlineRefunded($order->getBaseTotalOnlineRefunded() + $creditmemo->getBaseGrandTotal()); + } else { + $order->setTotalOfflineRefunded($order->getTotalOfflineRefunded() + $creditmemo->getGrandTotal()); + $order->setBaseTotalOfflineRefunded( + $order->getBaseTotalOfflineRefunded() + $creditmemo->getBaseGrandTotal() + ); + } + + $order->setBaseTotalInvoicedCost( + $order->getBaseTotalInvoicedCost() - $creditmemo->getBaseCost() + ); + } + + /** + * Prepare invoice data for refund + * + * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo + * @return void + */ + protected function prepareInvoice(\Magento\Sales\Model\Order\Creditmemo $creditmemo) + { + if ($creditmemo->getInvoice()) { + $creditmemo->getInvoice()->setIsUsedForRefund(true); + $creditmemo->getInvoice()->setBaseTotalRefunded( + $creditmemo->getInvoice()->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal() + ); + $creditmemo->setInvoiceId($creditmemo->getInvoice()->getId()); + } + } + + /** + * Prepare payment data for refund + * + * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo + * @return void + */ + protected function preparePayment(\Magento\Sales\Model\Order\Creditmemo $creditmemo) + { + if (!$creditmemo->getPaymentRefundDisallowed()) { + $creditmemo->getOrder()->getPayment()->refund($creditmemo); + } + } +} diff --git a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Grid/StatusList.php b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Grid/StatusList.php index ad0fed5b4f33c..bfdd88978a25c 100644 --- a/app/code/Magento/Sales/Model/Resource/Order/Invoice/Grid/StatusList.php +++ b/app/code/Magento/Sales/Model/Resource/Order/Invoice/Grid/StatusList.php @@ -11,16 +11,16 @@ class StatusList implements \Magento\Framework\Option\ArrayInterface { /** - * @var \Magento\Sales\Model\Order\InvoiceFactory + * @var \Magento\Sales\Api\InvoiceRepositoryInterface */ - protected $invoiceFactory; + protected $invoiceRepository; /** - * @param \Magento\Sales\Model\Order\InvoiceFactory $invoiceFactory + * @param \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository */ - public function __construct(\Magento\Sales\Model\Order\InvoiceFactory $invoiceFactory) + public function __construct(\Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository) { - $this->invoiceFactory = $invoiceFactory; + $this->invoiceRepository = $invoiceRepository; } /** @@ -30,6 +30,6 @@ public function __construct(\Magento\Sales\Model\Order\InvoiceFactory $invoiceFa */ public function toOptionArray() { - return $this->invoiceFactory->create()->getStates(); + return $this->invoiceRepository->create()->getStates(); } } diff --git a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/TypeList.php b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/TypeList.php index d920909f4e014..153300b4e4f4f 100644 --- a/app/code/Magento/Sales/Model/Resource/Transaction/Grid/TypeList.php +++ b/app/code/Magento/Sales/Model/Resource/Transaction/Grid/TypeList.php @@ -5,22 +5,24 @@ */ namespace Magento\Sales\Model\Resource\Transaction\Grid; +use Magento\Sales\Api\TransactionRepositoryInterface; + /** * Sales transaction types option array */ class TypeList implements \Magento\Framework\Option\ArrayInterface { /** - * @var \Magento\Sales\Model\Order\Payment\TransactionFactory + * @var TransactionRepositoryInterface */ - protected $_transactionFactory; + protected $transactionRepository; /** - * @param \Magento\Sales\Model\Order\Payment\TransactionFactory $transactionFactory + * @param TransactionRepositoryInterface $transactionRepository */ - public function __construct(\Magento\Sales\Model\Order\Payment\TransactionFactory $transactionFactory) + public function __construct(TransactionRepositoryInterface $transactionRepository) { - $this->_transactionFactory = $transactionFactory; + $this->transactionRepository = $transactionRepository; } /** @@ -30,6 +32,6 @@ public function __construct(\Magento\Sales\Model\Order\Payment\TransactionFactor */ public function toOptionArray() { - return $this->_transactionFactory->create()->getTransactionTypes(); + return $this->transactionRepository->create()->getTransactionTypes(); } } diff --git a/app/code/Magento/Sales/Model/Service/CreditmemoService.php b/app/code/Magento/Sales/Model/Service/CreditmemoService.php index 8e4b2c7256861..ea0e1ed82d1b3 100644 --- a/app/code/Magento/Sales/Model/Service/CreditmemoService.php +++ b/app/code/Magento/Sales/Model/Service/CreditmemoService.php @@ -19,7 +19,7 @@ class CreditmemoService implements \Magento\Sales\Api\CreditmemoManagementInterf /** * @var \Magento\Sales\Api\CreditmemoCommentRepositoryInterface */ - protected $creditmemoCommentRepository; + protected $commentRepository; /** * @var \Magento\Framework\Api\SearchCriteriaBuilder @@ -36,40 +36,70 @@ class CreditmemoService implements \Magento\Sales\Api\CreditmemoManagementInterf */ protected $creditmemoNotifier; + /** + * @var \Magento\Framework\Pricing\PriceCurrencyInterface + */ + protected $priceCurrency; + + /** + * @var \Magento\Framework\Event\ManagerInterface + */ + protected $eventManager; + /** * @param \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository * @param \Magento\Sales\Api\CreditmemoCommentRepositoryInterface $creditmemoCommentRepository * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder * @param \Magento\Framework\Api\FilterBuilder $filterBuilder * @param \Magento\Sales\Model\Order\CreditmemoNotifier $creditmemoNotifier + * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency + * @param \Magento\Framework\Event\ManagerInterface $eventManager */ public function __construct( \Magento\Sales\Api\CreditmemoRepositoryInterface $creditmemoRepository, \Magento\Sales\Api\CreditmemoCommentRepositoryInterface $creditmemoCommentRepository, \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder, \Magento\Framework\Api\FilterBuilder $filterBuilder, - \Magento\Sales\Model\Order\CreditmemoNotifier $creditmemoNotifier + \Magento\Sales\Model\Order\CreditmemoNotifier $creditmemoNotifier, + \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, + \Magento\Framework\Event\ManagerInterface $eventManager ) { $this->creditmemoRepository = $creditmemoRepository; - $this->creditmemoCommentRepository = $creditmemoCommentRepository; + $this->commentRepository = $creditmemoCommentRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->filterBuilder = $filterBuilder; $this->creditmemoNotifier = $creditmemoNotifier; + $this->priceCurrency = $priceCurrency; + $this->eventManager = $eventManager; } /** * Cancel an existing creditmemo * - * @param int $id + * @param int $id Credit Memo Id * @return bool + * @throws \Magento\Framework\Exception\LocalizedException */ public function cancel($id) { - return (bool)$this->creditmemoRepository->get($id)->cancel(); + throw new \Magento\Framework\Exception\LocalizedException(__('You can not cancel Credit Memo')); + try { + $creditmemo = $this->creditmemoRepository->get($id); + $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_CANCELED); + foreach ($creditmemo->getAllItems() as $item) { + $item->cancel(); + } + $this->eventManager->dispatch('sales_order_creditmemo_cancel', ['creditmemo' => $creditmemo]); + $this->creditmemoRepository->save($creditmemo); + } catch (\Exception $e) { + throw new \Magento\Framework\Exception\LocalizedException(__('Could not cancel creditmemo'), $e); + } + return true; } /** * Returns list of comments attached to creditmemo + * * @param int $id * @return \Magento\Sales\Api\Data\CreditmemoCommentSearchResultInterface */ @@ -79,7 +109,7 @@ public function getCommentsList($id) [$this->filterBuilder->setField('parent_id')->setValue($id)->setConditionType('eq')->create()] ); $criteria = $this->searchCriteriaBuilder->create(); - return $this->creditmemoCommentRepository->getList($criteria); + return $this->commentRepository->getList($criteria); } /** @@ -90,6 +120,68 @@ public function getCommentsList($id) */ public function notify($id) { - return $this->creditmemoNotifier->notify($this->creditmemoRepository->get($id)); + $creditmemo = $this->creditmemoRepository->get($id); + return $this->creditmemoNotifier->notify($creditmemo); + } + + /** + * Prepare creditmemo to refund and save it. + * + * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo + * @param bool $offlineRequested + * @param bool $notifyCustomer + * @return \Magento\Sales\Api\Data\CreditmemoInterface + */ + public function refund( + \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo, + $offlineRequested = false, + $notifyCustomer = false + ) { + $this->validateForRefund($creditmemo); + $creditmemo->setState(\Magento\Sales\Model\Order\Creditmemo::STATE_REFUNDED); + + foreach ($creditmemo->getAllItems() as $item) { + if ($item->getQty() > 0) { + $item->register(); + } else { + $item->isDeleted(true); + } + } + + $creditmemo->setDoTransaction(!$offlineRequested); + + $this->eventManager->dispatch('sales_order_creditmemo_refund', ['creditmemo' => $creditmemo]); + $this->creditmemoRepository->save($creditmemo); + return $creditmemo; + } + + /** + * @param \Magento\Sales\Api\Data\CreditmemoInterface $creditmemo + * @return bool + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function validateForRefund(\Magento\Sales\Api\Data\CreditmemoInterface $creditmemo) + { + if ($creditmemo->getId()) { + throw new \Magento\Framework\Exception\LocalizedException( + __('We cannot register an existing credit memo.') + ); + } + + $baseOrderRefund = $this->priceCurrency->round( + $creditmemo->getOrder()->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal() + ); + if ($baseOrderRefund > $this->priceCurrency->round($creditmemo->getOrder()->getBaseTotalPaid())) { + $baseAvailableRefund = $creditmemo->getOrder()->getBaseTotalPaid() + - $creditmemo->getOrder()->getBaseTotalRefunded(); + + throw new \Magento\Framework\Exception\LocalizedException( + __( + 'The most money available to refund is %1.', + $creditmemo->getOrder()->formatBasePrice($baseAvailableRefund) + ) + ); + } + return true; } } diff --git a/app/code/Magento/Sales/Model/Service/InvoiceService.php b/app/code/Magento/Sales/Model/Service/InvoiceService.php index cc1d737c69d9d..a0892ea4ebf75 100644 --- a/app/code/Magento/Sales/Model/Service/InvoiceService.php +++ b/app/code/Magento/Sales/Model/Service/InvoiceService.php @@ -47,6 +47,16 @@ class InvoiceService implements InvoiceManagementInterface */ protected $invoiceNotifier; + /** + * @var \Magento\Sales\Api\OrderRepositoryInterface + */ + protected $orderRepository; + + /** + * @var \Magento\Sales\Model\Convert\Order + */ + protected $orderConverter; + /** * Constructor * @@ -55,26 +65,29 @@ class InvoiceService implements InvoiceManagementInterface * @param \Magento\Framework\Api\SearchCriteriaBuilder $criteriaBuilder * @param \Magento\Framework\Api\FilterBuilder $filterBuilder * @param \Magento\Sales\Model\Order\InvoiceNotifier $notifier + * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository + * @param \Magento\Sales\Model\Convert\Order $orderConverter */ public function __construct( \Magento\Sales\Api\InvoiceRepositoryInterface $repository, \Magento\Sales\Api\InvoiceCommentRepositoryInterface $commentRepository, \Magento\Framework\Api\SearchCriteriaBuilder $criteriaBuilder, \Magento\Framework\Api\FilterBuilder $filterBuilder, - \Magento\Sales\Model\Order\InvoiceNotifier $notifier + \Magento\Sales\Model\Order\InvoiceNotifier $notifier, + \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, + \Magento\Sales\Model\Convert\Order $orderConverter ) { $this->repository = $repository; $this->commentRepository = $commentRepository; $this->criteriaBuilder = $criteriaBuilder; $this->filterBuilder = $filterBuilder; $this->invoiceNotifier = $notifier; + $this->orderRepository = $orderRepository; + $this->orderConverter = $orderConverter; } /** - * Set invoice capture - * - * @param int $id - * @return string + * @inheritdoc */ public function setCapture($id) { @@ -82,9 +95,7 @@ public function setCapture($id) } /** - * Returns list of comments attached to invoice - * @param int $id - * @return \Magento\Sales\Api\Data\InvoiceSearchResultInterface + * @inheritdoc */ public function getCommentsList($id) { @@ -96,10 +107,7 @@ public function getCommentsList($id) } /** - * Notify user - * - * @param int $id - * @return bool + * @inheritdoc */ public function notify($id) { @@ -108,13 +116,110 @@ public function notify($id) } /** - * Set invoice void - * - * @param int $id - * @return bool + * @inheritdoc */ public function setVoid($id) { return (bool)$this->repository->get($id)->void(); } + + /** + * @inheritdoc + */ + public function prepareInvoice($orderId, array $qtys = []) + { + $order = $this->orderRepository->get($orderId); + $invoice = $this->orderConverter->toInvoice($order); + $totalQty = 0; + foreach ($order->getAllItems() as $orderItem) { + if (!$this->_canInvoiceItem($orderItem)) { + continue; + } + $item = $this->orderConverter->itemToInvoiceItem($orderItem); + if ($orderItem->isDummy()) { + $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1; + } elseif (isset($qtys[$orderItem->getId()])) { + $qty = (double) $qtys[$orderItem->getId()]; + } else { + $qty = $orderItem->getQtyToInvoice(); + } + $totalQty += $qty; + $this->setInvoiceItemQuantity($item, $qty); + $invoice->addItem($item); + } + $invoice->setTotalQty($totalQty); + $invoice->collectTotals(); + $order->getInvoiceCollection()->addItem($invoice); + return $invoice; + } + + /** + * Check if order item can be invoiced. Dummy item can be invoiced or with his children or + * with parent item which is included to invoice + * + * @param \Magento\Sales\Api\Data\OrderItemInterface $item + * @return bool + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + */ + protected function _canInvoiceItem(\Magento\Sales\Api\Data\OrderItemInterface $item) + { + $qtys = []; + if ($item->getLockedDoInvoice()) { + return false; + } + if ($item->isDummy()) { + if ($item->getHasChildren()) { + foreach ($item->getChildrenItems() as $child) { + if (empty($qtys)) { + if ($child->getQtyToInvoice() > 0) { + return true; + } + } else { + if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) { + return true; + } + } + } + return false; + } elseif ($item->getParentItem()) { + $parent = $item->getParentItem(); + if (empty($qtys)) { + return $parent->getQtyToInvoice() > 0; + } else { + return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0; + } + } + } else { + return $item->getQtyToInvoice() > 0; + } + } + + /** + * Set quantity to invoice item + * + * @param \Magento\Sales\Api\Data\InvoiceItemInterface $item + * @param float $qty + * @return $this + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function setInvoiceItemQuantity(\Magento\Sales\Api\Data\InvoiceItemInterface $item, $qty) + { + $qty = ($item->getOrderItem()->getIsQtyDecimal()) ? (double) $qty : (int) $qty; + $qty = $qty > 0 ? $qty : 0; + + /** + * Check qty availability + */ + $qtyToInvoice = sprintf("%F", $item->getOrderItem()->getQtyToInvoice()); + $qty = sprintf("%F", $qty); + if ($qty > $qtyToInvoice && !$item->getOrderItem()->isDummy()) { + throw new \Magento\Framework\Exception\LocalizedException( + __('We found an invalid quantity to invoice item "%1".', $item->getName()) + ); + } + + $item->setQty($qty); + + return $this; + } } diff --git a/app/code/Magento/Sales/Model/Service/Order.php b/app/code/Magento/Sales/Model/Service/Order.php deleted file mode 100644 index fa22e21ff0e17..0000000000000 --- a/app/code/Magento/Sales/Model/Service/Order.php +++ /dev/null @@ -1,486 +0,0 @@ -_order = $order; - $this->_convertor = $convertOrderFactory->create(); - $this->_taxConfig = $taxConfig; - } - - /** - * Quote convertor declaration - * - * @param \Magento\Sales\Model\Convert\Order $convertor - * @return $this - */ - public function setConvertor(\Magento\Sales\Model\Convert\Order $convertor) - { - $this->_convertor = $convertor; - return $this; - } - - /** - * Get assigned order object - * - * @return \Magento\Sales\Model\Order - */ - public function getOrder() - { - return $this->_order; - } - - /** - * Prepare order invoice based on order data and requested items qtys. If $qtys is not empty - the function will - * prepare only specified items, otherwise all containing in the order. - * - * @param array $qtys - * @return \Magento\Sales\Model\Order\Invoice - */ - public function prepareInvoice($qtys = []) - { - $invoice = $this->_convertor->toInvoice($this->_order); - $totalQty = 0; - foreach ($this->_order->getAllItems() as $orderItem) { - if (!$this->_canInvoiceItem($orderItem, [])) { - continue; - } - $item = $this->_convertor->itemToInvoiceItem($orderItem); - if ($orderItem->isDummy()) { - $qty = $orderItem->getQtyOrdered() ? $orderItem->getQtyOrdered() : 1; - } elseif (isset($qtys[$orderItem->getId()])) { - $qty = (double) $qtys[$orderItem->getId()]; - } else { - $qty = $orderItem->getQtyToInvoice(); - } - $totalQty += $qty; - $this->setInvoiceItemQuantity($item, $qty); - $invoice->addItem($item); - } - $invoice->setTotalQty($totalQty); - $invoice->collectTotals(); - $this->_order->getInvoiceCollection()->addItem($invoice); - return $invoice; - } - - /** - * Set quantity to invoice item - * - * @param \Magento\Sales\Model\Order\Invoice\Item $item - * @param float $qty - * @return $this - * @throws \Magento\Framework\Exception\LocalizedException - */ - protected function setInvoiceItemQuantity(\Magento\Sales\Model\Order\Invoice\Item $item, $qty) - { - $qty = ($item->getOrderItem()->getIsQtyDecimal()) ? (double) $qty : (int) $qty; - $qty = $qty > 0 ? $qty : 0; - - /** - * Check qty availability - */ - $qtyToInvoice = sprintf("%F", $item->getOrderItem()->getQtyToInvoice()); - $qty = sprintf("%F", $qty); - if ($qty > $qtyToInvoice && !$item->getOrderItem()->isDummy()) { - throw new \Magento\Framework\Exception\LocalizedException( - __('We found an invalid quantity to invoice item "%1".', $item->getName()) - ); - } - - $item->setQty($qty); - - return $this; - } - - /** - * Prepare order shipment based on order items and requested items qty - * - * @param array $qtys - * @return \Magento\Sales\Model\Order\Shipment - */ - public function prepareShipment($qtys = []) - { - $totalQty = 0; - $shipment = $this->_convertor->toShipment($this->_order); - foreach ($this->_order->getAllItems() as $orderItem) { - if (!$this->_canShipItem($orderItem, $qtys)) { - continue; - } - - $item = $this->_convertor->itemToShipmentItem($orderItem); - - if ($orderItem->isDummy(true)) { - $qty = 0; - if (isset($qtys[$orderItem->getParentItemId()])) { - $productOptions = $orderItem->getProductOptions(); - if (isset($productOptions['bundle_selection_attributes'])) { - $bundleSelectionAttributes = unserialize($productOptions['bundle_selection_attributes']); - - if ($bundleSelectionAttributes) { - $qty = $bundleSelectionAttributes['qty'] * $qtys[$orderItem->getParentItemId()]; - $qty = min($qty, $orderItem->getSimpleQtyToShip()); - - $item->setQty($qty); - $shipment->addItem($item); - continue; - } else { - $qty = 1; - } - } - } else { - $qty = 1; - } - } else { - if (isset($qtys[$orderItem->getId()])) { - $qty = min($qtys[$orderItem->getId()], $orderItem->getQtyToShip()); - } elseif (!count($qtys)) { - $qty = $orderItem->getQtyToShip(); - } else { - continue; - } - } - $totalQty += $qty; - $item->setQty($qty); - $shipment->addItem($item); - } - - $shipment->setTotalQty($totalQty); - return $shipment; - } - - /** - * Prepare order creditmemo based on order items and requested params - * - * @param array $data - * @return \Magento\Sales\Model\Order\Creditmemo - */ - public function prepareCreditmemo($data = []) - { - $totalQty = 0; - $creditmemo = $this->_convertor->toCreditmemo($this->_order); - $qtys = isset($data['qtys']) ? $data['qtys'] : []; - - foreach ($this->_order->getAllItems() as $orderItem) { - if (!$this->_canRefundItem($orderItem, $qtys)) { - continue; - } - - $item = $this->_convertor->itemToCreditmemoItem($orderItem); - if ($orderItem->isDummy()) { - $qty = 1; - $orderItem->setLockedDoShip(true); - } else { - if (isset($qtys[$orderItem->getId()])) { - $qty = (double)$qtys[$orderItem->getId()]; - } elseif (!count($qtys)) { - $qty = $orderItem->getQtyToRefund(); - } else { - continue; - } - } - $totalQty += $qty; - $item->setQty($qty); - $creditmemo->addItem($item); - } - $creditmemo->setTotalQty($totalQty); - - $this->_initCreditmemoData($creditmemo, $data); - - $creditmemo->collectTotals(); - return $creditmemo; - } - - /** - * Prepare order creditmemo based on invoice items and requested requested params - * - * @param object $invoice - * @param array $data - * @return \Magento\Sales\Model\Order\Creditmemo - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function prepareInvoiceCreditmemo($invoice, $data = []) - { - $totalQty = 0; - $qtys = isset($data['qtys']) ? $data['qtys'] : []; - $creditmemo = $this->_convertor->toCreditmemo($this->_order); - $creditmemo->setInvoice($invoice); - - $invoiceQtysRefunded = []; - foreach ($invoice->getOrder()->getCreditmemosCollection() as $createdCreditmemo) { - if ($createdCreditmemo->getState() != \Magento\Sales\Model\Order\Creditmemo::STATE_CANCELED && - $createdCreditmemo->getInvoiceId() == $invoice->getId() - ) { - foreach ($createdCreditmemo->getAllItems() as $createdCreditmemoItem) { - $orderItemId = $createdCreditmemoItem->getOrderItem()->getId(); - if (isset($invoiceQtysRefunded[$orderItemId])) { - $invoiceQtysRefunded[$orderItemId] += $createdCreditmemoItem->getQty(); - } else { - $invoiceQtysRefunded[$orderItemId] = $createdCreditmemoItem->getQty(); - } - } - } - } - - $invoiceQtysRefundLimits = []; - foreach ($invoice->getAllItems() as $invoiceItem) { - $invoiceQtyCanBeRefunded = $invoiceItem->getQty(); - $orderItemId = $invoiceItem->getOrderItem()->getId(); - if (isset($invoiceQtysRefunded[$orderItemId])) { - $invoiceQtyCanBeRefunded = $invoiceQtyCanBeRefunded - $invoiceQtysRefunded[$orderItemId]; - } - $invoiceQtysRefundLimits[$orderItemId] = $invoiceQtyCanBeRefunded; - } - - foreach ($invoice->getAllItems() as $invoiceItem) { - $orderItem = $invoiceItem->getOrderItem(); - - if (!$this->_canRefundItem($orderItem, $qtys, $invoiceQtysRefundLimits)) { - continue; - } - - $item = $this->_convertor->itemToCreditmemoItem($orderItem); - if ($orderItem->isDummy()) { - $qty = 1; - } else { - if (isset($qtys[$orderItem->getId()])) { - $qty = (double)$qtys[$orderItem->getId()]; - } elseif (!count($qtys)) { - $qty = $orderItem->getQtyToRefund(); - } else { - continue; - } - if (isset($invoiceQtysRefundLimits[$orderItem->getId()])) { - $qty = min($qty, $invoiceQtysRefundLimits[$orderItem->getId()]); - } - } - $qty = min($qty, $invoiceItem->getQty()); - $totalQty += $qty; - $item->setQty($qty); - $creditmemo->addItem($item); - } - $creditmemo->setTotalQty($totalQty); - - $this->_initCreditmemoData($creditmemo, $data); - if (!isset($data['shipping_amount'])) { - $order = $invoice->getOrder(); - $isShippingInclTax = $this->_taxConfig->displaySalesShippingInclTax($order->getStoreId()); - if ($isShippingInclTax) { - $baseAllowedAmount = $order->getBaseShippingInclTax() - - $order->getBaseShippingRefunded() - - $order->getBaseShippingTaxRefunded(); - } else { - $baseAllowedAmount = $order->getBaseShippingAmount() - $order->getBaseShippingRefunded(); - $baseAllowedAmount = min($baseAllowedAmount, $invoice->getBaseShippingAmount()); - } - $creditmemo->setBaseShippingAmount($baseAllowedAmount); - } - - $creditmemo->collectTotals(); - return $creditmemo; - } - - /** - * Initialize creditmemo state based on requested parameters - * - * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo - * @param array $data - * @return void - */ - protected function _initCreditmemoData($creditmemo, $data) - { - if (isset($data['shipping_amount'])) { - $creditmemo->setBaseShippingAmount((double)$data['shipping_amount']); - } - - if (isset($data['adjustment_positive'])) { - $creditmemo->setAdjustmentPositive($data['adjustment_positive']); - } - - if (isset($data['adjustment_negative'])) { - $creditmemo->setAdjustmentNegative($data['adjustment_negative']); - } - } - - /** - * Check if order item can be invoiced. Dummy item can be invoiced or with his children or - * with parent item which is included to invoice - * - * @param \Magento\Sales\Model\Order\Item $item - * @param array $qtys - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _canInvoiceItem($item, $qtys = []) - { - if ($item->getLockedDoInvoice()) { - return false; - } - if ($item->isDummy()) { - if ($item->getHasChildren()) { - foreach ($item->getChildrenItems() as $child) { - if (empty($qtys)) { - if ($child->getQtyToInvoice() > 0) { - return true; - } - } else { - if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) { - return true; - } - } - } - return false; - } elseif ($item->getParentItem()) { - $parent = $item->getParentItem(); - if (empty($qtys)) { - return $parent->getQtyToInvoice() > 0; - } else { - return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0; - } - } - } else { - return $item->getQtyToInvoice() > 0; - } - } - - /** - * Check if order item can be shipped. Dummy item can be shipped or with his children or - * with parent item which is included to shipment - * - * @param \Magento\Sales\Model\Order\Item $item - * @param array $qtys - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _canShipItem($item, $qtys = []) - { - if ($item->getIsVirtual() || $item->getLockedDoShip()) { - return false; - } - if ($item->isDummy(true)) { - if ($item->getHasChildren()) { - if ($item->isShipSeparately()) { - return true; - } - foreach ($item->getChildrenItems() as $child) { - if ($child->getIsVirtual()) { - continue; - } - if (empty($qtys)) { - if ($child->getQtyToShip() > 0) { - return true; - } - } else { - if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) { - return true; - } - } - } - return false; - } elseif ($item->getParentItem()) { - $parent = $item->getParentItem(); - if (empty($qtys)) { - return $parent->getQtyToShip() > 0; - } else { - return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0; - } - } - } else { - return $item->getQtyToShip() > 0; - } - } - - /** - * Check if order item can be refunded - * - * @param \Magento\Sales\Model\Order\Item $item - * @param array $qtys - * @param array $invoiceQtysRefundLimits - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _canRefundItem($item, $qtys = [], $invoiceQtysRefundLimits = []) - { - if ($item->isDummy()) { - if ($item->getHasChildren()) { - foreach ($item->getChildrenItems() as $child) { - if (empty($qtys)) { - if ($this->_canRefundNoDummyItem($child, $invoiceQtysRefundLimits)) { - return true; - } - } else { - if (isset($qtys[$child->getId()]) && $qtys[$child->getId()] > 0) { - return true; - } - } - } - return false; - } elseif ($item->getParentItem()) { - $parent = $item->getParentItem(); - if (empty($qtys)) { - return $this->_canRefundNoDummyItem($parent, $invoiceQtysRefundLimits); - } else { - return isset($qtys[$parent->getId()]) && $qtys[$parent->getId()] > 0; - } - } - } else { - return $this->_canRefundNoDummyItem($item, $invoiceQtysRefundLimits); - } - } - - /** - * Check if no dummy order item can be refunded - * - * @param \Magento\Sales\Model\Order\Item $item - * @param array $invoiceQtysRefundLimits - * @return bool - */ - protected function _canRefundNoDummyItem($item, $invoiceQtysRefundLimits = []) - { - if ($item->getQtyToRefund() < 0) { - return false; - } - - if (isset($invoiceQtysRefundLimits[$item->getId()])) { - return $invoiceQtysRefundLimits[$item->getId()] > 0; - } - - return true; - } -} diff --git a/app/code/Magento/Sales/Model/Service/OrderService.php b/app/code/Magento/Sales/Model/Service/OrderService.php index b2673a3e8178f..5df21bf9df691 100644 --- a/app/code/Magento/Sales/Model/Service/OrderService.php +++ b/app/code/Magento/Sales/Model/Service/OrderService.php @@ -148,7 +148,9 @@ public function getStatus($id) */ public function hold($id) { - return (bool)$this->orderRepository->get($id)->hold(); + $order = $this->orderRepository->get($id); + $order->hold(); + return (bool)$this->orderRepository->save($order); } /** @@ -159,7 +161,9 @@ public function hold($id) */ public function unHold($id) { - return (bool)$this->orderRepository->get($id)->unhold(); + $object = $this->orderRepository->get($id); + $object->unhold(); + return (bool)$this->orderRepository->save($object); } /** diff --git a/app/code/Magento/Sales/Test/Unit/Block/Items/AbstractTest.php b/app/code/Magento/Sales/Test/Unit/Block/Items/AbstractTest.php index 2c191b98afb77..b7f36d409531c 100644 --- a/app/code/Magento/Sales/Test/Unit/Block/Items/AbstractTest.php +++ b/app/code/Magento/Sales/Test/Unit/Block/Items/AbstractTest.php @@ -80,7 +80,7 @@ public function testGetItemRenderer() * @expectedException \RuntimeException * @expectedExceptionMessage Renderer list for block "" is not defined */ - public function te1stGetItemRendererThrowsExceptionForNonexistentRenderer() + public function testGetItemRendererThrowsExceptionForNonexistentRenderer() { $layout = $this->getMock( 'Magento\Framework\View\Layout', diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/EmailTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/EmailTest.php index 09554226bc356..6a78aef9bcf3d 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/EmailTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Creditmemo/AbstractCreditmemo/EmailTest.php @@ -134,9 +134,7 @@ public function setUp() $this->creditmemoEmail = $objectManagerHelper->getObject( 'Magento\Sales\Controller\Adminhtml\Creditmemo\AbstractCreditmemo\Email', [ - 'context' => $this->context, - 'request' => $this->request, - 'response' => $this->response, + 'context' => $this->context ] ); } @@ -144,31 +142,21 @@ public function setUp() public function testEmail() { $cmId = 10000031; - $creditmemoClassName = 'Magento\Sales\Model\Order\Creditmemo'; - $cmNotifierClassName = 'Magento\Sales\Model\Order\CreditmemoNotifier'; - $creditmemo = $this->getMock($creditmemoClassName, ['load', '__wakeup'], [], '', false); - $cmNotifier = $this->getMock($cmNotifierClassName, ['notify', '__wakeup'], [], '', false); + $cmManagement = 'Magento\Sales\Api\CreditmemoManagementInterface'; + $cmManagementMock = $this->getMock($cmManagement, [], [], '', false); $this->prepareRedirect($cmId); $this->request->expects($this->once()) ->method('getParam') ->with('creditmemo_id') - ->will($this->returnValue($cmId)); - $this->objectManager->expects($this->at(0)) + ->willReturn($cmId); + $this->objectManager->expects($this->once()) ->method('create') - ->with($creditmemoClassName) - ->will($this->returnValue($creditmemo)); - $creditmemo->expects($this->once()) - ->method('load') - ->with($cmId) - ->will($this->returnSelf()); - $this->objectManager->expects($this->at(1)) - ->method('create') - ->with($cmNotifierClassName) - ->will($this->returnValue($cmNotifier)); - $cmNotifier->expects($this->once()) + ->with($cmManagement) + ->willReturn($cmManagementMock); + $cmManagementMock->expects($this->once()) ->method('notify') - ->will($this->returnValue(true)); + ->willReturn(true); $this->messageManager->expects($this->once()) ->method('addSuccess') ->with('You sent the message.'); @@ -190,28 +178,6 @@ public function testEmailNoCreditmemoId() $this->assertNull($this->creditmemoEmail->execute()); } - public function testEmailNoCreditmemo() - { - $cmId = 10000031; - $creditmemoClassName = 'Magento\Sales\Model\Order\Creditmemo'; - $creditmemo = $this->getMock($creditmemoClassName, ['load', '__wakeup'], [], '', false); - - $this->request->expects($this->once()) - ->method('getParam') - ->with('creditmemo_id') - ->will($this->returnValue($cmId)); - $this->objectManager->expects($this->at(0)) - ->method('create') - ->with($creditmemoClassName) - ->will($this->returnValue($creditmemo)); - $creditmemo->expects($this->once()) - ->method('load') - ->with($cmId) - ->will($this->returnValue(null)); - - $this->assertNull($this->creditmemoEmail->execute()); - } - /** * @param int $cmId */ diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Invoice/AbstractInvoice/EmailTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Invoice/AbstractInvoice/EmailTest.php index 994cfca6db432..4e5bd8e7472da 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Invoice/AbstractInvoice/EmailTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Invoice/AbstractInvoice/EmailTest.php @@ -84,6 +84,11 @@ class EmailTest extends \PHPUnit_Framework_TestCase */ protected $resultForwardFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceManagement; + public function setUp() { $objectManagerHelper = new ObjectManagerHelper($this); @@ -128,6 +133,9 @@ public function setUp() ->method('getResultRedirectFactory') ->willReturn($this->resultRedirectFactory); + $this->invoiceManagement = $this->getMockBuilder('Magento\Sales\Api\InvoiceManagementInterface') + ->disableOriginalConstructor() + ->getMock(); $this->resultForward = $this->getMockBuilder('Magento\Backend\Model\View\Result\Forward') ->disableOriginalConstructor() ->getMock(); @@ -150,9 +158,11 @@ public function testEmail() $invoiceId = 10000031; $orderId = 100000030; $invoiceClassName = 'Magento\Sales\Model\Order\Invoice'; - $cmNotifierClassName = 'Magento\Sales\Model\Order\InvoiceNotifier'; + $cmNotifierClassName = 'Magento\Sales\Api\InvoiceManagementInterface'; $invoice = $this->getMock($invoiceClassName, [], [], '', false); - $notifier = $this->getMock($cmNotifierClassName, [], [], '', false); + $invoice->expects($this->once()) + ->method('getEntityId') + ->willReturn($invoiceId); $order = $this->getMock('Magento\Sales\Model\Order', [], [], '', false); $order->expects($this->once()) ->method('getId') @@ -162,23 +172,28 @@ public function testEmail() ->method('getParam') ->with('invoice_id') ->willReturn($invoiceId); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoice); $this->objectManager->expects($this->at(0)) ->method('create') - ->with($invoiceClassName) - ->willReturn($invoice); - $invoice->expects($this->once()) - ->method('load') - ->with($invoiceId) - ->willReturnSelf(); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); + $invoice->expects($this->once()) ->method('getOrder') ->willReturn($order); $this->objectManager->expects($this->at(1)) ->method('create') ->with($cmNotifierClassName) - ->willReturn($notifier); - $notifier->expects($this->once()) + ->willReturn($this->invoiceManagement); + + $this->invoiceManagement->expects($this->once()) ->method('notify') + ->with($invoiceId) ->willReturn(true); $this->messageManager->expects($this->once()) ->method('addSuccess') @@ -214,21 +229,22 @@ public function testEmailNoInvoiceId() public function testEmailNoInvoice() { $invoiceId = 10000031; - $invoiceClassName = 'Magento\Sales\Model\Order\Invoice'; - $invoice = $this->getMock($invoiceClassName, [], [], '', false); - $this->request->expects($this->once()) ->method('getParam') ->with('invoice_id') ->willReturn($invoiceId); + + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn(null); $this->objectManager->expects($this->at(0)) ->method('create') - ->with($invoiceClassName) - ->willReturn($invoice); - $invoice->expects($this->once()) - ->method('load') - ->with($invoiceId) - ->willReturn(null); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); + $this->resultForwardFactory->expects($this->any()) ->method('create') ->willReturn($this->resultForward); diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/CancelTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/CancelTest.php index 5029fdac67c3d..223b5a9753b63 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/CancelTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/CancelTest.php @@ -20,11 +20,6 @@ class CancelTest extends \PHPUnit_Framework_TestCase */ protected $contextMock; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $loaderMock; - /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -41,9 +36,9 @@ class CancelTest extends \PHPUnit_Framework_TestCase protected $objectManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Api\CreditmemoManagementInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $creditmemoMock; + protected $creditmemoManagementMock; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -90,10 +85,13 @@ class CancelTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $this->creditmemoMock = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') - ->disableOriginalConstructor() - ->setMethods(['getInvoice', 'getOrder', 'cancel', 'getId', '__wakeUp']) - ->getMock(); + $this->creditmemoManagementMock = $this->getMock( + 'Magento\Sales\Api\CreditmemoManagementInterface', + [], + [], + '', + false + ); $titleMock = $this->getMockBuilder('Magento\Framework\App\Action\Title') ->disableOriginalConstructor() ->getMock(); @@ -113,9 +111,6 @@ public function setUp() $this->helperMock = $this->getMockBuilder('Magento\Backend\Helper\Data') ->disableOriginalConstructor() ->getMock(); - $this->loaderMock = $this->getMockBuilder('Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader') - ->disableOriginalConstructor() - ->getMock(); $this->resultRedirectFactoryMock = $this->getMockBuilder('Magento\Backend\Model\View\Result\RedirectFactory') ->disableOriginalConstructor() ->setMethods(['create']) @@ -169,7 +164,6 @@ public function setUp() 'Magento\Sales\Controller\Adminhtml\Order\Creditmemo\Cancel', [ 'context' => $this->contextMock, - 'creditmemoLoader' => $this->loaderMock, 'resultForwardFactory' => $this->resultForwardFactoryMock ] ); @@ -180,28 +174,28 @@ public function setUp() */ public function testExecuteModelException() { - $id = 123; + $creditmemoId = 123; $message = 'Model exception'; $e = new \Magento\Framework\Exception\LocalizedException(__($message)); - $this->requestMock->expects($this->any()) + $this->requestMock->expects($this->once()) ->method('getParam') - ->willReturnArgument(0); - $this->creditmemoMock->expects($this->once()) + ->with('creditmemo_id') + ->willReturn($creditmemoId); + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with('Magento\Sales\Api\CreditmemoManagementInterface') + ->willReturn($this->creditmemoManagementMock); + $this->creditmemoManagementMock->expects($this->once()) ->method('cancel') + ->with($creditmemoId) ->willThrowException($e); - $this->loaderMock->expects($this->once()) - ->method('load') - ->willReturn($this->creditmemoMock); $this->resultRedirectFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->resultRedirectMock); - $this->creditmemoMock->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($id); $this->resultRedirectMock->expects($this->once()) ->method('setPath') - ->with('sales/*/view', ['creditmemo_id' => $id]) + ->with('sales/*/view', ['creditmemo_id' => $creditmemoId]) ->willReturnSelf(); $this->assertInstanceOf( @@ -215,28 +209,28 @@ public function testExecuteModelException() */ public function testExecuteException() { - $id = 321; + $creditmemoId = 321; $message = 'Model exception'; $e = new \Exception($message); - $this->requestMock->expects($this->any()) + $this->requestMock->expects($this->once()) ->method('getParam') - ->willReturnArgument(0); - $this->creditmemoMock->expects($this->once()) + ->with('creditmemo_id') + ->willReturn($creditmemoId); + $this->objectManagerMock->expects($this->once()) + ->method('create') + ->with('Magento\Sales\Api\CreditmemoManagementInterface') + ->willReturn($this->creditmemoManagementMock); + $this->creditmemoManagementMock->expects($this->once()) ->method('cancel') + ->with($creditmemoId) ->willThrowException($e); - $this->loaderMock->expects($this->once()) - ->method('load') - ->willReturn($this->creditmemoMock); $this->resultRedirectFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->resultRedirectMock); - $this->creditmemoMock->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($id); $this->resultRedirectMock->expects($this->once()) ->method('setPath') - ->with('sales/*/view', ['creditmemo_id' => $id]) + ->with('sales/*/view', ['creditmemo_id' => $creditmemoId]) ->willReturnSelf(); $this->assertInstanceOf( @@ -250,13 +244,10 @@ public function testExecuteException() */ public function testExecuteNoCreditmemo() { - $this->requestMock->expects($this->any()) + $this->requestMock->expects($this->once()) ->method('getParam') - ->withAnyParameters() - ->willReturnArgument(0); - $this->loaderMock->expects($this->once()) - ->method('load') - ->willReturn(false); + ->with('creditmemo_id') + ->willReturn(null); $this->resultForwardFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->resultForwardMock); @@ -276,46 +267,28 @@ public function testExecuteNoCreditmemo() */ public function testExecute() { - $id = '111'; + $creditmemoId = '111'; - $transactionMock = $this->getMockBuilder('Magento\Framework\DB\Transaction') - ->disableOriginalConstructor() - ->getMock(); - $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') - ->disableOriginalConstructor() - ->getMock(); - $orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') - ->disableOriginalConstructor() - ->getMock(); - - $this->requestMock->expects($this->any()) + $this->requestMock->expects($this->once()) ->method('getParam') - ->willReturnArgument(0); - $this->loaderMock->expects($this->once()) - ->method('load') - ->willReturn($this->creditmemoMock); + ->with('creditmemo_id') + ->willReturn($creditmemoId); $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Framework\DB\Transaction') - ->willReturn($transactionMock); - $this->creditmemoMock->expects($this->any()) - ->method('getOrder') - ->willReturn($orderMock); - $this->creditmemoMock->expects($this->any()) - ->method('getInvoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\CreditmemoManagementInterface') + ->willReturn($this->creditmemoManagementMock); + $this->creditmemoManagementMock->expects($this->once()) + ->method('cancel') + ->with($creditmemoId); $this->messageManagerMock->expects($this->once()) ->method('addSuccess') ->with('The credit memo has been canceled.'); $this->resultRedirectFactoryMock->expects($this->once()) ->method('create') ->willReturn($this->resultRedirectMock); - $this->creditmemoMock->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($id); $this->resultRedirectMock->expects($this->once()) ->method('setPath') - ->with('sales/*/view', ['creditmemo_id' => $id]) + ->with('sales/*/view', ['creditmemo_id' => $creditmemoId]) ->willReturnSelf(); $this->assertInstanceOf( diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/PrintActionTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/PrintActionTest.php index 394a6252c7343..7f2ae31af7e98 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/PrintActionTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Creditmemo/PrintActionTest.php @@ -31,6 +31,11 @@ class PrintActionTest extends \PHPUnit_Framework_TestCase */ protected $creditmemoLoaderMock; + /** + * @var \Magento\Sales\Api\CreditmemoRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $creditmemoRepositoryMock; + /** * @var \Magento\Framework\ObjectManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ @@ -94,6 +99,13 @@ public function setUp() ->getMock(); $this->objectManagerMock = $this->getMockBuilder('Magento\Framework\ObjectManagerInterface') ->getMock(); + $this->creditmemoRepositoryMock = $this->getMock( + 'Magento\Sales\Api\CreditmemoRepositoryInterface', + [], + [], + '', + false + ); $this->creditmemoMock = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') ->disableOriginalConstructor() ->getMock(); @@ -132,8 +144,9 @@ public function setUp() [ 'context' => $this->context, 'fileFactory' => $this->fileFactoryMock, + 'resultForwardFactory' => $this->resultForwardFactoryMock, 'creditmemoLoader' => $this->creditmemoLoaderMock, - 'resultForwardFactory' => $this->resultForwardFactoryMock + 'creditmemoRepository' => $this->creditmemoRepositoryMock, ] ); } @@ -157,10 +170,10 @@ public function testExecute() ['Magento\Sales\Model\Order\Pdf\Creditmemo', [], $this->creditmemoPdfMock] ] ); - $this->creditmemoMock->expects($this->once()) - ->method('load') + $this->creditmemoRepositoryMock->expects($this->once()) + ->method('get') ->with($creditmemoId) - ->willReturnSelf(); + ->willReturn($this->creditmemoMock); $this->creditmemoPdfMock->expects($this->once()) ->method('getPdf') ->with([$this->creditmemoMock]) diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/CreditmemoLoaderTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/CreditmemoLoaderTest.php index e90cc3a0f5547..f5ed9c434c475 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/CreditmemoLoaderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/CreditmemoLoaderTest.php @@ -17,7 +17,12 @@ class CreditmemoLoaderTest extends \PHPUnit_Framework_TestCase protected $loader; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Api\CreditmemoRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $creditmemoRepositoryMock; + + /** + * @var \Magento\Sales\Model\Order\CreditmemoFactory|\PHPUnit_Framework_MockObject_MockObject */ protected $creditmemoFactoryMock; @@ -29,7 +34,7 @@ class CreditmemoLoaderTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $invoiceFactoryMock; + protected $invoiceRepositoryMock; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -69,18 +74,18 @@ class CreditmemoLoaderTest extends \PHPUnit_Framework_TestCase public function setUp() { $data = []; - $this->creditmemoFactoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\CreditmemoFactory') + $this->creditmemoRepositoryMock = $this->getMockBuilder('Magento\Sales\Api\CreditmemoRepositoryInterface') ->disableOriginalConstructor() - ->setMethods(['create', 'get']) ->getMock(); + $this->creditmemoFactoryMock = $this->getMock('Magento\Sales\Model\Order\CreditmemoFactory', [], [], '', false); $this->orderFactoryMock = $this->getMockBuilder('Magento\Sales\Model\OrderFactory') ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->invoiceFactoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\InvoiceFactory') + $this->invoiceRepositoryMock = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') ->disableOriginalConstructor() ->setMethods(['create']) - ->getMock(); + ->getMockForAbstractClass(); $this->serviceOrderFactoryMock = $this->getMockBuilder('Magento\Sales\Model\Service\OrderFactory') ->disableOriginalConstructor() ->setMethods(['create']) @@ -112,10 +117,10 @@ public function setUp() ->getMock(); $this->loader = new \Magento\Sales\Controller\Adminhtml\Order\CreditmemoLoader( + $this->creditmemoRepositoryMock, $this->creditmemoFactoryMock, $this->orderFactoryMock, - $this->invoiceFactoryMock, - $this->serviceOrderFactoryMock, + $this->invoiceRepositoryMock, $this->eventManagerMock, $this->sessionMock, $this->messageManagerMock, @@ -135,11 +140,8 @@ public function testLoadByCreditmemoId() ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $creditmemoMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); - $this->creditmemoFactoryMock->expects($this->once()) - ->method('create') + $this->creditmemoRepositoryMock->expects($this->once()) + ->method('get') ->willReturn($creditmemoMock); $this->assertInstanceOf('Magento\Sales\Model\Order\Creditmemo', $this->loader->load()); @@ -147,10 +149,12 @@ public function testLoadByCreditmemoId() public function testLoadCannotCreditmemo() { + $orderId = 1234; + $invoiceId = 99; $this->loader->setCreditmemoId(0); - $this->loader->setOrderId(1); + $this->loader->setOrderId($orderId); $this->loader->setCreditmemo('test'); - $this->loader->setInvoiceId(1); + $this->loader->setInvoiceId($invoiceId); $orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') ->disableOriginalConstructor() @@ -161,7 +165,7 @@ public function testLoadCannotCreditmemo() ->willReturnSelf(); $orderMock->expects($this->once()) ->method('getId') - ->willReturn(1); + ->willReturn($orderId); $orderMock->expects($this->once()) ->method('canCreditmemo') ->willReturn(false); @@ -172,17 +176,15 @@ public function testLoadCannotCreditmemo() ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->any()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->any()) ->method('setOrder') + ->with($orderMock) ->willReturnSelf(); $invoiceMock->expects($this->any()) ->method('getId') ->willReturn(1); - $this->invoiceFactoryMock->expects($this->once()) - ->method('create') + $this->invoiceRepositoryMock->expects($this->once()) + ->method('get') ->willReturn($invoiceMock); $this->assertFalse($this->loader->load()); @@ -190,12 +192,14 @@ public function testLoadCannotCreditmemo() public function testLoadByOrder() { + $orderId = 1234; + $invoiceId = 99; $qty = 1; $data = ['items' => [1 => ['qty' => $qty, 'back_to_stock' => true]]]; $this->loader->setCreditmemoId(0); - $this->loader->setOrderId(1); + $this->loader->setOrderId($orderId); $this->loader->setCreditmemo($data); - $this->loader->setInvoiceId(1); + $this->loader->setInvoiceId($invoiceId); $orderMock = $this->getMockBuilder('Magento\Sales\Model\Order') ->disableOriginalConstructor() @@ -206,7 +210,7 @@ public function testLoadByOrder() ->willReturnSelf(); $orderMock->expects($this->once()) ->method('getId') - ->willReturn(1); + ->willReturn($orderId); $orderMock->expects($this->once()) ->method('canCreditmemo') ->willReturn(true); @@ -215,24 +219,16 @@ public function testLoadByOrder() ->willReturn($orderMock); $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->any()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->any()) ->method('setOrder') ->willReturnSelf(); $invoiceMock->expects($this->any()) ->method('getId') ->willReturn(1); - $this->invoiceFactoryMock->expects($this->once()) - ->method('create') + $this->invoiceRepositoryMock->expects($this->once()) + ->method('get') ->willReturn($invoiceMock); - $serviceOrder = $this->getMockBuilder('Magento\Sales\Model\Service\Order') - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); $creditmemoMock = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') ->disableOriginalConstructor() ->setMethods([]) @@ -253,13 +249,12 @@ public function testLoadByOrder() $creditmemoMock->expects($this->any()) ->method('getAllItems') ->willReturn($items); - $serviceOrder->expects($this->any()) - ->method('prepareInvoiceCreditmemo') + $data['qtys'] = [1 => $qty]; + $this->creditmemoFactoryMock->expects($this->any()) + ->method('createByInvoice') + ->with($invoiceMock, $data) ->willReturn($creditmemoMock); - $this->serviceOrderFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($serviceOrder); - $this->assertInstanceOf('Magento\Sales\Model\Order\Creditmemo', $this->loader->load()); + $this->assertEquals($creditmemoMock, $this->loader->load()); } } diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php index 6eedbf0af8636..fe36332d13983 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/EmailTest.php @@ -147,9 +147,11 @@ public function testEmail() { $orderId = 10000031; $orderClassName = 'Magento\Sales\Model\Order'; - $orderNotifierClassName = 'Magento\Sales\Model\OrderNotifier'; + $orderNotifierClassName = 'Magento\Sales\Api\OrderManagementInterface'; $order = $this->getMock($orderClassName, ['load', 'getId', '__wakeup'], [], '', false); - $cmNotifier = $this->getMock($orderNotifierClassName, ['notify', '__wakeup'], [], '', false); + $cmNotifier = $this->getMockBuilder('Magento\Sales\Api\OrderManagementInterface') + ->disableOriginalConstructor() + ->getMock(); $this->request->expects($this->once()) ->method('getParam') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/AddCommentTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/AddCommentTest.php index 0f552a950113c..f8b5c3f44b178 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/AddCommentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/AddCommentTest.php @@ -217,14 +217,17 @@ public function testExecute() ->with($data['comment'], false, false); $invoiceMock->expects($this->once()) ->method('save'); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $commentsBlockMock = $this->getMockBuilder('Magento\Sales\Block\Adminhtml\Order\Invoice\View\Comments') ->disableOriginalConstructor() diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CancelTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CancelTest.php index 682550783e261..689d7efa270a7 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CancelTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CancelTest.php @@ -196,18 +196,22 @@ public function testExecute() ->method('addSuccess') ->with('You canceled the invoice.'); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $this->objectManagerMock->expects($this->at(1)) ->method('create') ->with('Magento\Framework\DB\Transaction') ->will($this->returnValue($transactionMock)); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); @@ -237,17 +241,17 @@ public function testExecuteNoInvoice() ->with('invoice_id') ->will($this->returnValue($invoiceId)); - $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') + $invoiceRepository->expects($this->any()) + ->method('get') ->willReturn(null); + $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultForward = $this->getMockBuilder('Magento\Backend\Model\View\Result\Forward') ->disableOriginalConstructor() @@ -289,17 +293,21 @@ public function testExecuteModelException() ->method('addError') ->with($message); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() @@ -341,17 +349,21 @@ public function testExecuteException() ->method('addError') ->with($message); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CaptureTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CaptureTest.php index 3c067f3f8603e..c0e86d79f3481 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CaptureTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/CaptureTest.php @@ -64,6 +64,11 @@ class CaptureTest extends \PHPUnit_Framework_TestCase */ protected $controller; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceManagement; + /** * @return void */ @@ -141,11 +146,20 @@ public function setUp() ->method('getResultRedirectFactory') ->willReturn($this->resultRedirectFactoryMock); + $this->invoiceManagement = $this->getMockBuilder('Magento\Sales\Api\InvoiceManagementInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with('Magento\Sales\Api\InvoiceManagementInterface') + ->willReturn($this->invoiceManagement); + $this->controller = $objectManager->getObject( 'Magento\Sales\Controller\Adminhtml\Order\Invoice\Capture', [ 'context' => $contextMock, - 'resultForwardFactory' => $this->resultForwardFactoryMock + 'resultForwardFactory' => $this->resultForwardFactoryMock, ] ); } @@ -167,12 +181,17 @@ public function testExecute() ->setMethods(['setIsInProcess', '__wakeup']) ->getMock(); + $this->invoiceManagement->expects($this->once()) + ->method('setCapture') + ->with($invoiceId); + $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('capture'); + $invoiceMock->expects($this->any()) + ->method('getEntityId') + ->will($this->returnValue($invoiceId)); $invoiceMock->expects($this->any()) ->method('getOrder') ->will($this->returnValue($orderMock)); @@ -196,26 +215,28 @@ public function testExecute() ->method('addSuccess') ->with('The invoice has been captured.'); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); - $this->objectManagerMock->expects($this->at(0)) - ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') ->willReturn($invoiceMock); - $this->objectManagerMock->expects($this->at(1)) + $this->objectManagerMock->expects($this->at(0)) + ->method('create') + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); + $this->objectManagerMock->expects($this->at(2)) ->method('create') ->with('Magento\Framework\DB\Transaction') ->will($this->returnValue($transactionMock)); $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); $resultRedirect->expects($this->once())->method('setPath')->with('sales/*/view', ['invoice_id' => $invoiceId]); @@ -238,21 +259,20 @@ public function testExecuteNoInvoice() ->with('invoice_id') ->will($this->returnValue($invoiceId)); - $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') + $invoiceRepository->expects($this->any()) + ->method('get') ->willReturn(null); + $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultForward = $this->getMockBuilder('Magento\Backend\Model\View\Result\Forward') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); $resultForward->expects($this->once())->method('forward')->with(('noroute'))->will($this->returnSelf()); @@ -270,9 +290,14 @@ public function testExecuteModelException() { $invoiceId = 2; - $message = 'model exception'; + $message = 'Invoice capturing error'; $e = new \Magento\Framework\Exception\LocalizedException(__($message)); + $this->invoiceManagement->expects($this->once()) + ->method('setCapture') + ->with($invoiceId) + ->will($this->throwException($e)); + $this->requestMock->expects($this->once()) ->method('getParam') ->with('invoice_id') @@ -280,31 +305,33 @@ public function testExecuteModelException() $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('capture') - ->will($this->throwException($e)); $this->messageManagerMock->expects($this->once()) ->method('addError') ->with($message); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); + $invoiceMock->expects($this->once()) + ->method('getEntityId') + ->will($this->returnValue($invoiceId)); + + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); $resultRedirect->expects($this->once())->method('setPath')->with('sales/*/view', ['invoice_id' => $invoiceId]); @@ -330,29 +357,37 @@ public function testExecuteException() ->with('invoice_id') ->will($this->returnValue($invoiceId)); + $this->invoiceManagement->expects($this->once()) + ->method('setCapture') + ->with($invoiceId) + ->will($this->throwException($e)); + $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('capture') - ->will($this->throwException($e)); $this->messageManagerMock->expects($this->once()) ->method('addError') ->with($message); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); + $invoiceMock->expects($this->once()) + ->method('getEntityId') + ->will($this->returnValue($invoiceId)); + + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultRedirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') ->disableOriginalConstructor() diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/NewActionTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/NewActionTest.php index 5e60a34a35541..115023377689f 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/NewActionTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/NewActionTest.php @@ -239,12 +239,12 @@ public function testExecute() ->method('canInvoice') ->willReturn(true); - $orderService = $this->getMockBuilder('Magento\Sales\Model\Service\Order') + $invoiceManagement = $this->getMockBuilder('Magento\Sales\Api\InvoiceManagementInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $orderService->expects($this->once()) + $invoiceManagement->expects($this->once()) ->method('prepareInvoice') + ->with($orderId, []) ->willReturn($invoiceMock); $menuBlockMock = $this->getMockBuilder('Magento\Backend\Block\Menu') @@ -270,8 +270,8 @@ public function testExecute() ->willReturn($orderMock); $this->objectManagerMock->expects($this->at(1)) ->method('create') - ->with('Magento\Sales\Model\Service\Order') - ->willReturn($orderService); + ->with('Magento\Sales\Api\InvoiceManagementInterface') + ->willReturn($invoiceManagement); $this->objectManagerMock->expects($this->at(2)) ->method('get') ->with('Magento\Backend\Model\Session') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/PrintActionTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/PrintActionTest.php index e43dbf96abe61..223e5e4311ea8 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/PrintActionTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/PrintActionTest.php @@ -118,9 +118,7 @@ public function testExecute() ->will($this->returnValue($invoiceId)); $invoiceMock = $this->getMock('Magento\Sales\Model\Order\Invoice', [], [], '', false); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); + $pdfMock = $this->getMock('Magento\Sales\Model\Order\Pdf\Invoice', ['render', 'getPdf'], [], '', false); $pdfMock->expects($this->once()) ->method('getPdf') @@ -129,10 +127,17 @@ public function testExecute() ->method('render'); $dateTimeMock = $this->getMock('Magento\Framework\Stdlib\DateTime\DateTime', [], [], '', false); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $this->objectManagerMock->expects($this->at(1)) ->method('create') ->with('Magento\Sales\Model\Order\Pdf\Invoice') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/UpdateQtyTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/UpdateQtyTest.php index 90b9a5abf31f3..bac3e4dac37ba 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/UpdateQtyTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/UpdateQtyTest.php @@ -199,12 +199,12 @@ public function testExecute() ->method('canInvoice') ->willReturn(true); - $orderService = $this->getMockBuilder('Magento\Sales\Model\Service\Order') + $invoiceManagement = $this->getMockBuilder('Magento\Sales\Api\InvoiceManagementInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $orderService->expects($this->once()) + $invoiceManagement->expects($this->once()) ->method('prepareInvoice') + ->with($orderId, []) ->willReturn($invoiceMock); $this->objectManagerMock->expects($this->at(0)) @@ -213,8 +213,8 @@ public function testExecute() ->willReturn($orderMock); $this->objectManagerMock->expects($this->at(1)) ->method('create') - ->with('Magento\Sales\Model\Service\Order') - ->willReturn($orderService); + ->with('Magento\Sales\Api\InvoiceManagementInterface') + ->willReturn($invoiceManagement); $blockItemMock = $this->getMockBuilder('Magento\Sales\Block\Order\Items') ->disableOriginalConstructor() diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/ViewTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/ViewTest.php index 22e3ba6630ed0..edb47e37f44f6 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/ViewTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/ViewTest.php @@ -225,14 +225,18 @@ public function testExecute() ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') - ->willReturnSelf(); + + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $this->resultPageMock->expects($this->once())->method('setActiveMenu')->with('Magento_Sales::sales_order'); @@ -251,18 +255,18 @@ public function testExecuteNoInvoice() ->method('getParam') ->with('invoice_id') ->will($this->returnValue($invoiceId)); - $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') + $invoiceRepository->expects($this->any()) + ->method('get') ->willReturn(null); $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $resultForward = $this->getMockBuilder('Magento\Backend\Model\View\Result\Forward') ->disableOriginalConstructor() diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/VoidTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/VoidTest.php index 4f9b93ea6e279..c2bfc012aa69e 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/VoidTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/Invoice/VoidTest.php @@ -69,6 +69,11 @@ class VoidTest extends \PHPUnit_Framework_TestCase */ protected $resultForwardFactoryMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $invoiceManagement; + /** * @return void */ @@ -122,6 +127,14 @@ public function setUp() ->setMethods(['create']) ->getMock(); + $this->invoiceManagement = $this->getMockBuilder('Magento\Sales\Api\InvoiceManagementInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with('Magento\Sales\Api\InvoiceManagementInterface') + ->willReturn($this->invoiceManagement); + $contextMock = $this->getMockBuilder('Magento\Backend\App\Action\Context') ->disableOriginalConstructor() ->setMethods([]) @@ -180,16 +193,17 @@ public function testExecute() ->setMethods(['setIsInProcess', '__wakeup']) ->getMock(); + $this->invoiceManagement->expects($this->once()) + ->method('setVoid') + ->with($invoiceId) + ->willReturn(true); + $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') - ->with($invoiceId) - ->willReturnSelf(); - $invoiceMock->expects($this->once()) - ->method('void'); + $invoiceMock->expects($this->any()) + ->method('getEntityId') + ->will($this->returnValue($invoiceId)); $invoiceMock->expects($this->any()) ->method('getOrder') ->will($this->returnValue($orderMock)); @@ -199,7 +213,6 @@ public function testExecute() $transactionMock = $this->getMockBuilder('Magento\Framework\DB\Transaction') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); $transactionMock->expects($this->at(0)) ->method('addObject') @@ -212,11 +225,18 @@ public function testExecute() $transactionMock->expects($this->at(2)) ->method('save'); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->at(0)) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); - $this->objectManagerMock->expects($this->at(1)) + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); + $this->objectManagerMock->expects($this->at(2)) ->method('create') ->with('Magento\Framework\DB\Transaction') ->will($this->returnValue($transactionMock)); @@ -250,18 +270,17 @@ public function testExecuteNoInvoice() ->with('invoice_id') ->will($this->returnValue($invoiceId)); - $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); - $invoiceMock->expects($this->once()) - ->method('load') + $invoiceRepository->expects($this->any()) + ->method('get') ->willReturn(null); $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $this->messageManagerMock->expects($this->never()) ->method('addError'); @@ -295,25 +314,32 @@ public function testExecuteModelException() ->with('invoice_id') ->will($this->returnValue($invoiceId)); + $this->invoiceManagement->expects($this->once()) + ->method('setVoid') + ->with($invoiceId) + ->will($this->throwException($e)); + $invoiceMock = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') ->disableOriginalConstructor() - ->setMethods([]) ->getMock(); $invoiceMock->expects($this->once()) - ->method('load') - ->with($invoiceId) - ->willReturnSelf(); - $invoiceMock->expects($this->once()) - ->method('void') - ->will($this->throwException($e)); + ->method('getEntityId') + ->will($this->returnValue($invoiceId)); $invoiceMock->expects($this->once()) ->method('getId') ->will($this->returnValue($invoiceId)); + $invoiceRepository = $this->getMockBuilder('Magento\Sales\Api\InvoiceRepositoryInterface') + ->disableOriginalConstructor() + ->getMock(); + $invoiceRepository->expects($this->any()) + ->method('get') + ->willReturn($invoiceMock); + $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Order\Invoice') - ->willReturn($invoiceMock); + ->with('Magento\Sales\Api\InvoiceRepositoryInterface') + ->willReturn($invoiceRepository); $this->messageManagerMock->expects($this->once()) ->method('addError'); diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php index 69b02f1522b24..f26c096c20ae6 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php @@ -75,6 +75,15 @@ class MassCancelTest extends \PHPUnit_Framework_TestCase */ protected $orderCollectionMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $orderManagement; + + /** + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function setUp() { $objectManagerHelper = new ObjectManagerHelper($this); @@ -114,7 +123,7 @@ public function setUp() ->disableOriginalConstructor()->getMock(); $this->objectManagerMock = $this->getMock( 'Magento\Framework\ObjectManager\ObjectManager', - ['create'], + [], [], '', false @@ -164,6 +173,14 @@ public function setUp() ->method('getResultFactory') ->willReturn($resultFactoryMock); + $this->orderManagement = $this->getMockBuilder('Magento\Sales\Api\OrderManagementInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with('Magento\Sales\Api\OrderManagementInterface') + ->willReturn($this->orderManagement); + $this->massAction = $objectManagerHelper->getObject( 'Magento\Sales\Controller\Adminhtml\Order\MassCancel', [ @@ -209,13 +226,15 @@ public function testExecuteTwoOrderCanceled() ->method('getItems') ->willReturn([$order1, $order2]); + $this->orderManagement->expects($this->at(0)) + ->method('cancel') + ->with(1); $order1->expects($this->once()) ->method('canCancel') ->willReturn(true); $order1->expects($this->once()) - ->method('cancel'); - $order1->expects($this->once()) - ->method('save'); + ->method('getEntityId') + ->willReturn(1); $this->orderCollectionMock->expects($this->once()) ->method('count') @@ -233,11 +252,6 @@ public function testExecuteTwoOrderCanceled() ->method('addSuccess') ->with('We canceled 1 order(s).'); - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - $this->massAction->execute(); } @@ -294,11 +308,6 @@ public function testExcludedOrderCannotBeCanceled() ->method('addError') ->with('You cannot cancel the order(s).'); - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - $this->massAction->execute(); } @@ -349,12 +358,16 @@ public function testException() ->method('getItems') ->willReturn([$order1]); + $this->orderManagement->expects($this->once()) + ->method('cancel') + ->with(1) + ->willThrowException($exception); $order1->expects($this->once()) ->method('canCancel') ->willReturn(true); $order1->expects($this->once()) - ->method('cancel') - ->willThrowException($exception); + ->method('getEntityId') + ->willReturn(1); $this->messageManagerMock->expects($this->once()) ->method('addError') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php index bb25130c4171d..d74b5139766b9 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php @@ -75,6 +75,15 @@ class MassHoldTest extends \PHPUnit_Framework_TestCase */ protected $orderCollectionMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $orderManagement; + + /** + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function setUp() { $objectManagerHelper = new ObjectManagerHelper($this); @@ -114,7 +123,7 @@ public function setUp() ->disableOriginalConstructor()->getMock(); $this->objectManagerMock = $this->getMock( 'Magento\Framework\ObjectManager\ObjectManager', - ['create'], + [], [], '', false @@ -163,6 +172,13 @@ public function setUp() ->method('getResultFactory') ->willReturn($resultFactoryMock); + $this->orderManagement = $this->getMockBuilder('Magento\Sales\Api\OrderManagementInterface') + ->disableOriginalConstructor() + ->getMock(); + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with('Magento\Sales\Api\OrderManagementInterface') + ->willReturn($this->orderManagement); $this->massAction = $objectManagerHelper->getObject( 'Magento\Sales\Controller\Adminhtml\Order\MassHold', [ @@ -204,13 +220,15 @@ public function testExecuteTwoOrdersPutOnHold() ->method('getItems') ->willReturn([$order1, $order2]); + $this->orderManagement->expects($this->once()) + ->method('hold') + ->with(1); $order1->expects($this->once()) ->method('canHold') ->willReturn(true); $order1->expects($this->once()) - ->method('hold'); - $order1->expects($this->once()) - ->method('save'); + ->method('getEntityId') + ->willReturn(1); $this->orderCollectionMock->expects($this->once()) ->method('count') diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php index 9b3175ab6d7e5..cec2ba1b5ae99 100644 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php +++ b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php @@ -75,6 +75,15 @@ class MassUnholdTest extends \PHPUnit_Framework_TestCase */ protected $orderCollectionMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $orderManagement; + + /** + * @return void + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function setUp() { $objectManagerHelper = new ObjectManagerHelper($this); @@ -114,7 +123,7 @@ public function setUp() ->disableOriginalConstructor()->getMock(); $this->objectManagerMock = $this->getMock( 'Magento\Framework\ObjectManager\ObjectManager', - ['create'], + [], [], '', false @@ -164,6 +173,15 @@ public function setUp() ->method('getResultFactory') ->willReturn($resultFactoryMock); + $this->orderManagement = $this->getMockBuilder('Magento\Sales\Api\OrderManagementInterface') + ->disableOriginalConstructor() + ->getMock(); + + $this->objectManagerMock->expects($this->any()) + ->method('get') + ->with('Magento\Sales\Api\OrderManagementInterface') + ->willReturn($this->orderManagement); + $this->massAction = $objectManagerHelper->getObject( 'Magento\Sales\Controller\Adminhtml\Order\MassUnhold', [ @@ -196,7 +214,7 @@ public function testExecuteTwoOrdersReleasedFromHold() $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Resource\Order\Grid\Collection') + ->with('Magento\Sales\Model\Resource\Order\Collection') ->willReturn($this->orderCollectionMock); $this->orderCollectionMock->expects($this->once()) ->method('addFieldToFilter') @@ -205,13 +223,16 @@ public function testExecuteTwoOrdersReleasedFromHold() ->method('getItems') ->willReturn([$order1, $order2]); + $this->orderManagement->expects($this->once()) + ->method('unHold') + ->with(1); + $order1->expects($this->once()) ->method('canUnhold') ->willReturn(true); $order1->expects($this->once()) - ->method('unhold'); - $order1->expects($this->once()) - ->method('save'); + ->method('getEntityId') + ->willReturn(1); $this->orderCollectionMock->expects($this->once()) ->method('count') @@ -261,7 +282,7 @@ public function testExecuteOneOrderWhereNotReleasedFromHold() $this->objectManagerMock->expects($this->once()) ->method('create') - ->with('Magento\Sales\Model\Resource\Order\Grid\Collection') + ->with('Magento\Sales\Model\Resource\Order\Collection') ->willReturn($this->orderCollectionMock); $this->orderCollectionMock->expects($this->once()) ->method('addFieldToFilter') diff --git a/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php new file mode 100644 index 0000000000000..d392df97b3b3f --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/InvoiceRepositoryTest.php @@ -0,0 +1,253 @@ +invoiceMetadata = $this->getMock('Magento\Sales\Model\Resource\Metadata', [], [], '', false); + $this->searchResultFactory = $this->getMockBuilder('Magento\Sales\Api\Data\InvoiceSearchResultInterfaceFactory') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMock(); + $this->invoice = $objectManager->getObject( + 'Magento\Sales\Model\Order\InvoiceRepository', + [ + 'invoiceMetadata' => $this->invoiceMetadata, + 'searchResultFactory' => $this->searchResultFactory + ] + ); + $this->type = $this->getMock('Magento\Eav\Model\Entity\Type', ['fetchNewIncrementId'], [], '', false); + } + + public function testGet() + { + $id = 1; + + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn($id); + $this->invoiceMetadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('load') + ->with($entity, $id); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + $this->assertEquals($entity, $this->invoice->get($id)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage ID required + */ + public function testGetNoId() + { + $this->invoice->get(null); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested entity doesn't exist + */ + public function testGetEntityNoId() + { + $id = 1; + + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn(null); + $this->invoiceMetadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('load') + ->with($entity, $id); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + $this->assertNull($entity, $this->invoice->get($id)); + } + + public function testCreate() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $this->invoiceMetadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + $this->assertEquals($entity, $this->invoice->create()); + } + + public function testGetList() + { + $filterGroup = $this->getMockBuilder('Magento\Framework\Api\Search\FilterGroup') + ->disableOriginalConstructor() + ->getMock(); + $filterGroups = [$filterGroup]; + $field = 'test_field'; + $fieldValue = 'test_value'; + + $filter = $this->getMockBuilder('Magento\Framework\Api\Filter') + ->disableOriginalConstructor() + ->getMock(); + $filter->expects($this->any()) + ->method('getConditionType') + ->willReturn(false); + $filter->expects($this->any()) + ->method('getField') + ->willReturn($field); + $filter->expects($this->any()) + ->method('getValue') + ->willReturn($fieldValue); + + $filterGroup->expects($this->once()) + ->method('getFilters') + ->willReturn([$filter]); + + $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') + ->disableOriginalConstructor() + ->getMock(); + $criteria->expects($this->once()) + ->method('getFilterGroups') + ->willReturn($filterGroups); + + $collection = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice\Collection') + ->disableOriginalConstructor() + ->getMock(); + $collection->expects($this->once()) + ->method('addFieldToFilter') + ->withAnyParameters(); + + $this->searchResultFactory->expects($this->once()) + ->method('create') + ->willReturn($collection); + + $this->assertEquals($collection, $this->invoice->getList($criteria)); + } + + public function testDelete() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('delete') + ->with($entity); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertTrue($this->invoice->delete($entity)); + } + + public function testDeleteById() + { + $id = 1; + + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->any()) + ->method('getEntityId') + ->willReturn($id); + $this->invoiceMetadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('load') + ->with($entity, $id); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $mapper->expects($this->once()) + ->method('delete') + ->with($entity); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertTrue($this->invoice->deleteById($id)); + } + + public function testSave() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->any()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Invoice') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('save') + ->with($entity); + + $this->invoiceMetadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($entity, $this->invoice->save($entity)); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php new file mode 100644 index 0000000000000..a545d687d9b4b --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/AddressRepositoryTest.php @@ -0,0 +1,356 @@ +metadata = $this->getMock( + 'Magento\Sales\Model\Resource\Metadata', + ['getNewInstance', 'getMapper'], + [], + '', + false + ); + + $this->searchResultFactory = $this->getMock( + 'Magento\Sales\Api\Data\OrderAddressSearchResultInterfaceFactory', + ['create'], + [], + '', + false + ); + + $this->subject = $objectManager->getObject( + 'Magento\Sales\Model\Order\AddressRepository', + [ + 'metadata' => $this->metadata, + 'searchResultFactory' => $this->searchResultFactory + ] + ); + } + + /** + * @param int|null $id + * @param int|null $entityId + * @dataProvider getDataProvider + */ + public function testGet($id, $entityId) + { + if (!$id) { + $this->setExpectedException( + 'Magento\Framework\Exception\InputException' + ); + + $this->subject->get($id); + } else { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + $address->expects($this->once()) + ->method('getEntityId') + ->willReturn($entityId); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['load'] + ); + $mapper->expects($this->once()) + ->method('load') + ->with($address, $id) + ->willReturnSelf(); + + $this->metadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($address); + $this->metadata->expects($this->once()) + ->method('getMapper') + ->willReturn($mapper); + + if (!$entityId) { + $this->setExpectedException( + 'Magento\Framework\Exception\NoSuchEntityException' + ); + + $this->subject->get($id); + } else { + $this->assertEquals($address, $this->subject->get($id)); + + $mapper->expects($this->never()) + ->method('load'); + + $this->metadata->expects($this->never()) + ->method('getNewInstance'); + $this->metadata->expects($this->never()) + ->method('getMapper'); + + $this->assertEquals($address, $this->subject->get($id)); + } + } + } + + /** + * @return array + */ + public function getDataProvider() + { + return [ + [null, null], + [1, null], + [1, 1] + ]; + } + + public function testGetList() + { + $filter = $this->getMock( + 'Magento\Framework\Api\Filter', + ['getConditionType', 'getField', 'getValue'], + [], + '', + false + ); + $filter->expects($this->any()) + ->method('getConditionType') + ->willReturn(false); + $filter->expects($this->any()) + ->method('getField') + ->willReturn('test_field'); + $filter->expects($this->any()) + ->method('getValue') + ->willReturn('test_value'); + + $filterGroup = $this->getMock( + 'Magento\Framework\Api\Search\FilterGroup', + ['getFilters'], + [], + '', + false + ); + $filterGroup->expects($this->once()) + ->method('getFilters') + ->willReturn([$filter]); + + $criteria = $this->getMock( + 'Magento\Framework\Api\SearchCriteria', + ['getFilterGroups'], + [], + '', + false + ); + $criteria->expects($this->once()) + ->method('getFilterGroups') + ->willReturn([$filterGroup]); + + $collection = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Address\Collection', + ['addFieldToFilter'], + [], + '', + false + ); + $collection->expects($this->once()) + ->method('addFieldToFilter') + ->withAnyParameters(); + + $this->searchResultFactory->expects($this->once()) + ->method('create') + ->willReturn($collection); + + $this->assertEquals($collection, $this->subject->getList($criteria)); + } + + public function testDelete() + { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + $address->expects($this->once()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['delete'] + ); + $mapper->expects($this->once()) + ->method('delete') + ->with($address); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertTrue($this->subject->delete($address)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotDeleteException + * @expectedExceptionMessage Could not delete order address + */ + public function testDeleteWithException() + { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + $address->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['delete'] + ); + $mapper->expects($this->once()) + ->method('delete') + ->willThrowException(new \Exception('error')); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->subject->delete($address); + } + + public function testSave() + { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + $address->expects($this->any()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['save'] + ); + $mapper->expects($this->once()) + ->method('save') + ->with($address); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($address, $this->subject->save($address)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage Could not save order address + */ + public function testSaveWithException() + { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + $address->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['save'] + ); + $mapper->expects($this->once()) + ->method('save') + ->willThrowException(new \Exception('error')); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($address, $this->subject->save($address)); + } + + public function testCreate() + { + $address = $this->getMock( + 'Magento\Sales\Model\Order\Address', + ['getEntityId'], + [], + '', + false + ); + + $this->metadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($address); + + $this->assertEquals($address, $this->subject->create()); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoNotifierTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoNotifierTest.php index ebffcd4ad781c..9f6096a4b02da 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoNotifierTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoNotifierTest.php @@ -22,12 +22,12 @@ class CreditmemoNotifierTest extends \PHPUnit_Framework_TestCase protected $historyCollectionFactory; /** - * @var \Magento\Sales\Model\CreditmemoNotifier + * @var CreditmemoNotifier */ protected $notifier; /** - * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Creditmemo|\PHPUnit_Framework_MockObject_MockObject */ protected $creditmemo; diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php new file mode 100644 index 0000000000000..79fafb090ecc8 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/CreditmemoRepositoryTest.php @@ -0,0 +1,274 @@ +metadataMock = $this->getMock('Magento\Sales\Model\Resource\Metadata', [], [], '', false); + $this->searchResultFactoryMock = $this->getMock( + 'Magento\Sales\Api\Data\CreditmemoSearchResultInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->creditmemo = $objectManager->getObject( + 'Magento\Sales\Model\Order\CreditmemoRepository', + [ + 'metadata' => $this->metadataMock, + 'searchResultFactory' => $this->searchResultFactoryMock + ] + ); + $this->type = $this->getMock('Magento\Eav\Model\Entity\Type', ['fetchNewIncrementId'], [], '', false); + } + + public function testGet() + { + $id = 1; + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn($id); + $this->metadataMock->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('load') + ->with($entity, $id); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + $this->assertEquals($entity, $this->creditmemo->get($id)); + //retrieve entity from registry + $this->assertEquals($entity, $this->creditmemo->get($id)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @expectedExceptionMessage Id required + */ + public function testGetNoId() + { + $this->creditmemo->get(null); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @expectedExceptionMessage Requested entity doesn't exist + */ + public function testGetEntityNoId() + { + $id = 1; + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn(null); + $this->metadataMock->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('load') + ->with($entity, $id); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + $this->assertNull($entity, $this->creditmemo->get($id)); + } + + public function testCreate() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $this->metadataMock->expects($this->once()) + ->method('getNewInstance') + ->willReturn($entity); + $this->assertEquals($entity, $this->creditmemo->create()); + } + + public function testGetList() + { + $filterGroup = $this->getMockBuilder('Magento\Framework\Api\Search\FilterGroup') + ->disableOriginalConstructor() + ->getMock(); + $filterGroups = [$filterGroup]; + $field = 'test_field'; + $fieldValue = 'test_value'; + + $filter = $this->getMockBuilder('Magento\Framework\Api\Filter') + ->disableOriginalConstructor() + ->getMock(); + $filter->expects($this->any()) + ->method('getConditionType') + ->willReturn(false); + $filter->expects($this->any()) + ->method('getField') + ->willReturn($field); + $filter->expects($this->any()) + ->method('getValue') + ->willReturn($fieldValue); + + $filterGroup->expects($this->once()) + ->method('getFilters') + ->willReturn([$filter]); + + $criteria = $this->getMockBuilder('Magento\Framework\Api\SearchCriteria') + ->disableOriginalConstructor() + ->getMock(); + $criteria->expects($this->once()) + ->method('getFilterGroups') + ->willReturn($filterGroups); + + $collection = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo\Collection') + ->disableOriginalConstructor() + ->getMock(); + $collection->expects($this->once()) + ->method('addFieldToFilter') + ->withAnyParameters(); + + $this->searchResultFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($collection); + + $this->assertEquals($collection, $this->creditmemo->getList($criteria)); + } + + public function testDelete() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('delete') + ->with($entity); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertTrue($this->creditmemo->delete($entity)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotDeleteException + * @expectedExceptionMessage Could not delete credit memo + */ + public function testDeleteWithException() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('delete') + ->willThrowException(new \Exception('error')); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->creditmemo->delete($entity); + } + + public function testSave() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->any()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('save') + ->with($entity); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($entity, $this->creditmemo->save($entity)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage Could not save credit memo + */ + public function testSaveWithException() + { + $entity = $this->getMockBuilder('Magento\Sales\Model\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockBuilder('Magento\Sales\Model\Resource\Order\Creditmemo') + ->disableOriginalConstructor() + ->getMock(); + $mapper->expects($this->once()) + ->method('save') + ->willThrowException(new \Exception('error')); + + $this->metadataMock->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($entity, $this->creditmemo->save($entity)); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php index ce8fe0cf97dd0..61e519785d59b 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/InvoiceTest.php @@ -78,7 +78,7 @@ protected function setUp() $this->paymentMock = $this->getMockBuilder( 'Magento\Sales\Model\Order\Payment' )->disableOriginalConstructor()->setMethods( - ['canVoid', '__wakeup', 'canCapture', 'capture', 'pay', 'hasForcedState', 'getForcedState'] + ['canVoid', '__wakeup', 'canCapture', 'capture', 'pay'] )->getMock(); $this->orderFactory = $this->getMock('Magento\Sales\Model\OrderFactory', ['create'], [], '', false); @@ -344,19 +344,13 @@ public function testCapturePaid() $this->model->setIsPaid(true); $this->orderMock->expects($this->any())->method('getPayment')->willReturn($this->paymentMock); $this->paymentMock->expects($this->any())->method('capture')->with($this->model)->willReturnSelf(); - $this->mockPay(false, null); + $this->mockPay(); $this->assertEquals($this->model, $this->model->capture()); } - public function mockPay($hasForcedState, $forcedState) + public function mockPay() { $this->orderMock->expects($this->any())->method('getPayment')->willReturn($this->paymentMock); - $this->paymentMock->expects($this->once())->method('hasForcedState')->willReturn($hasForcedState); - if ($hasForcedState) { - $this->paymentMock->expects($this->once())->method('getForcedState')->willReturn($forcedState); - } else { - $this->paymentMock->expects($this->never())->method('getForcedState'); - } $this->paymentMock->expects($this->once())->method('pay')->with($this->model)->willReturnSelf(); $this->eventManagerMock ->expects($this->once()) @@ -366,8 +360,6 @@ public function mockPay($hasForcedState, $forcedState) /** * @dataProvider payDataProvider - * @param bool $hasForcedState - * @param float string|null $forcedState * @param float $orderTotalPaid * @param float $orderBaseTotalPaid * @param float $grandTotal @@ -375,15 +367,13 @@ public function mockPay($hasForcedState, $forcedState) * @param float $expectedState */ public function testPay( - $hasForcedState, - $forcedState, $orderTotalPaid, $orderBaseTotalPaid, $grandTotal, $baseGrandTotal, $expectedState ) { - $this->mockPay($hasForcedState, $forcedState); + $this->mockPay(); $this->model->setGrandTotal($grandTotal); $this->model->setBaseGrandTotal($baseGrandTotal); $this->orderMock->setTotalPaid($orderTotalPaid); @@ -400,7 +390,7 @@ public function payDataProvider() { //ToDo: fill data provider and uncomment assertings totals in testPay return [ - [true, 'payment_state', 10.99, 1.00, 10.99, 1.00, 'payment_state'] + [10.99, 1.00, 10.99, 1.00, Invoice::STATE_PAID] ]; } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/RepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/RepositoryTest.php new file mode 100644 index 0000000000000..d9a8b0e70223b --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/RepositoryTest.php @@ -0,0 +1,217 @@ +metaData = $this->getMock( + 'Magento\Sales\Model\Resource\Metadata', + [], + [], + '', + false + ); + $this->searchResultFactory = $this->getMock( + 'Magento\Sales\Api\Data\OrderPaymentSearchResultInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->searchCriteria = $this->getMock( + 'Magento\Framework\Api\SearchCriteria', + [], + [], + '', + false + ); + $this->collection = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Payment\Collection', + [], + [], + '', + false + ); + $this->paymentResource = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Payment', + [], + [], + '', + false + ); + $this->filterGroup = $this->getMock( + 'Magento\Framework\Api\Search\FilterGroup', + [], + [], + '', + false + ); + $this->filter = $this->getMock( + 'Magento\Framework\Api\Filter', + [], + [], + '', + false + ); + $this->repository = $objectManager->getObject( + 'Magento\Sales\Model\Order\Payment\Repository', + [ + 'searchResultFactory' => $this->searchResultFactory, + 'metaData' => $this->metaData, + ] + ); + } + + public function testCreate() + { + $expected = "expect"; + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($expected); + $this->assertEquals($expected, $this->repository->create()); + } + + public function testSave() + { + $payment = $this->mockPayment(); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->paymentResource); + $this->paymentResource->expects($this->once())->method('save') + ->with($payment) + ->willReturn($payment); + $this->assertSame($payment, $this->repository->save($payment)); + } + + public function testDelete() + { + $payment = $this->mockPayment(); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->paymentResource); + $this->paymentResource->expects($this->once())->method('delete')->with($payment); + $this->assertTrue($this->repository->delete($payment)); + } + + public function testGet() + { + $paymentId = 1; + $payment = $this->mockPayment($paymentId); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($payment); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->paymentResource); + $this->paymentResource->expects($this->once())->method('load')->with($payment, $paymentId); + $this->assertSame($payment, $this->repository->get($paymentId)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function testGetException() + { + $this->repository->get(null); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function testGetNoSuchEntity() + { + $paymentId = 1; + $payment = $this->mockPayment(null); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($payment); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->paymentResource); + $this->paymentResource->expects($this->once())->method('load')->with($payment, $paymentId); + $this->assertSame($payment, $this->repository->get($paymentId)); + } + + public function testGetList() + { + $field = 'order_id'; + $value = 45; + $this->getListMock($field, $value); + $this->assertSame($this->collection, $this->repository->getList($this->searchCriteria)); + } + + protected function mockPayment($id = false) + { + $payment = $this->getMock( + 'Magento\Sales\Model\Order\Payment', + [], + [], + '', + false + ); + if ($id !== false) { + $payment->expects($this->once())->method('getId')->willReturn($id); + } + + return $payment; + } + + /** + * @param $field + * @param $value + */ + protected function getListMock($field, $value) + { + $currentPage = 1; + $pageSize = 10; + $this->searchResultFactory->expects($this->atLeastOnce())->method('create')->willReturn($this->collection); + $this->searchCriteria->expects($this->once())->method('getFilterGroups')->willReturn([$this->filterGroup]); + $this->filterGroup->expects($this->once())->method('getFilters')->willReturn([$this->filter]); + $this->filter->expects($this->once())->method('getConditionType')->willReturn(null); + $this->filter->expects($this->once())->method('getField')->willReturn($field); + $this->filter->expects($this->once())->method('getValue')->willReturn($value); + $this->collection->expects($this->once())->method('addFieldToFilter')->with($field, ['eq' => $value]); + $this->searchCriteria->expects($this->once())->method('getCurrentPage')->willReturn($currentPage); + $this->searchCriteria->expects($this->once())->method('getPageSize')->willReturn($pageSize); + $this->collection->expects($this->once())->method('setCurPage')->with(); + $this->collection->expects($this->once())->method('setPageSize')->with(); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/BuilderTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/BuilderTest.php new file mode 100644 index 0000000000000..ca0163757896e --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/BuilderTest.php @@ -0,0 +1,318 @@ +repositoryMock = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction\Repository', + [], + [], + '', + false + ); + $this->paymentMock = $this->getMock( + 'Magento\Sales\Model\Order\Payment', + [ + 'hasIsTransactionClosed', + 'getIsTransactionClosed', + 'getId', + 'getParentTransactionId', + 'getShouldCloseParentTransaction' + ], + [], + '', + false + ); + $this->orderMock = $this->getMock( + 'Magento\Sales\Model\Order', + [], + [], + '', + false + ); + $this->builder = $objectManager->getObject( + 'Magento\Sales\Model\Order\Payment\Transaction\Builder', + ['transactionRepository' => $this->repositoryMock] + ); + } + + /** + * @dataProvider createDataProvider + * @param string|null $transactionId + * @param int $orderId + * @param int $paymentId + * @param bool $failSafe + * @param string $type + * @param bool $isPaymentTransactionClosed + * @param array $additionalInfo + * @param bool $document + * @param bool $isTransactionExists + */ + public function testCreate( + $transactionId, + $orderId, + $paymentId, + $failSafe, + $type, + $isPaymentTransactionClosed, + $additionalInfo, + $document, + $isTransactionExists + ) { + $parentTransactionId = "12"; + $shouldCloseParentTransaction = true; + $parentTransactionIsClosed = false; + if ($document) { + $document = $this->expectDocument($transactionId); + } + + $parentTransaction = $this->expectTransaction($orderId, $paymentId); + $transaction = $this->expectTransaction($orderId, $paymentId); + $transaction->expects($this->atLeastOnce())->method('getTxnId')->willReturn($transactionId); + + if ($isTransactionExists) { + $this->repositoryMock->method('getByTransactionId') + ->withConsecutive( + [$transactionId, $paymentId, $orderId], + [$parentTransactionId, $paymentId, $orderId] + )->willReturnOnConsecutiveCalls( + $transaction, + $parentTransaction + ); + } else { + $this->repositoryMock->method('getByTransactionId') + ->withConsecutive( + [$transactionId, $paymentId, $orderId], + [$parentTransactionId, $paymentId, $orderId] + )->willReturnOnConsecutiveCalls(false, $parentTransaction); + $this->repositoryMock->method('create') + ->willReturn($transaction); + $transaction->expects($this->once())->method('setTxnId') + ->with($transactionId) + ->willReturn($transaction); + } + $this->expectSetPaymentObject($transaction, $type, $failSafe); + $this->expectsIsPaymentTransactionClosed($isPaymentTransactionClosed, $transaction); + $this->expectsIsPaymentTransactionClosed($isPaymentTransactionClosed, $transaction); + $this->expectSetPaymentObject($transaction, $type, $failSafe); + $this->expectsLinkWithParentTransaction( + $transaction, + $parentTransactionId, + $shouldCloseParentTransaction, + $parentTransaction, + $parentTransactionIsClosed + ); + if ($additionalInfo) { + $transaction->expects($this->exactly(count($additionalInfo)))->method('setAdditionalInformation'); + } + + $builder = $this->builder->setPayment($this->paymentMock) + ->setOrder($this->orderMock) + ->setAdditionalInformation($additionalInfo) + ->setFailSafe($failSafe) + ->setTransactionId($transactionId); + if ($document) { + $builder->setSalesDocument($document); + } + $this->assertSame($transaction, $builder->build($type)); + } + + /** + * @param \PHPUnit_Framework_MockObject_MockObject $transaction + * @param string|null $parentTransactionId + * @param bool $shouldCloseParentTransaction + * @param \PHPUnit_Framework_MockObject_MockObject $parentTransaction + * @param bool $parentTransactionIsClosed + */ + protected function expectsLinkWithParentTransaction( + $transaction, + $parentTransactionId, + $shouldCloseParentTransaction, + $parentTransaction, + $parentTransactionIsClosed + ) { + $this->paymentMock->method('getParentTransactionId')->willReturn($parentTransactionId); + if ($parentTransactionId) { + $transaction->expects($this->once())->method('setParentTxnId')->with($parentTransactionId); + $this->paymentMock->expects($this->once()) + ->method('getShouldCloseParentTransaction') + ->willReturn($shouldCloseParentTransaction); + if ($shouldCloseParentTransaction) { + $parentTransaction->expects($this->once())->method('getIsClosed') + ->willReturn($parentTransactionIsClosed); + if (!$parentTransactionIsClosed) { + $parentTransaction->expects( + $this->once() + )->method('isFailsafe') + ->willReturnSelf(); + $parentTransaction->expects( + $this->once() + )->method('close') + ->with(false) + ->willReturnSelf(); + } + $this->orderMock->expects($this->at(2))->method('addRelatedObject')->with($parentTransaction); + } + } + } + + + /** + * @param int $orderId + * @param int $paymentId + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function expectTransaction($orderId, $paymentId) + { + $newTransaction = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [ + 'getId', + 'setOrderId', + 'setPaymentId', + 'loadByTxnId', + 'setTxnId', + 'setTxnType', + 'isFailsafe', + 'getTxnId', + 'getHtmlTxnId', + 'getTxnType', + 'setAdditionalInformation', + 'setParentTxnId', + 'close', + 'getIsClosed' + ], + [], + '', + false + ); + + $this->orderMock->expects($this->atLeastOnce())->method('getId')->willReturn($orderId); + $this->paymentMock->expects($this->atLeastOnce())->method('getId')->willReturn($paymentId); + return $newTransaction; + } + + /** + * @param string $transactionId + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function expectDocument($transactionId) + { + $document = $this->getMock( + 'Magento\Sales\Model\Order', + [ + 'setTransactionId' + ], + [], + '', + false + ); + + $document->expects($this->once())->method('setTransactionId')->with($transactionId); + return $document; + } + + /** + * @param \PHPUnit_Framework_MockObject_MockObject $newTransaction + * @param string $type + * @param bool $failSafe + */ + protected function expectSetPaymentObject($newTransaction, $type, $failSafe) + { + $newTransaction->expects($this->once())->method('setOrderId') + ->willReturnSelf(); + $newTransaction->expects($this->once())->method('setPaymentId') + ->willReturnSelf(); + $newTransaction->expects($this->once())->method('setTxnType') + ->with($type) + ->willReturnSelf(); + $newTransaction->expects($this->once())->method('isFailsafe') + ->with($failSafe) + ->willReturnSelf(); + } + + /** + * @param bool $isPaymentTransactionClosed + * @param \PHPUnit_Framework_MockObject_MockObject $newTransaction + */ + protected function expectsIsPaymentTransactionClosed($isPaymentTransactionClosed, $newTransaction) + { + $this->paymentMock->expects($this->once()) + ->method('hasIsTransactionClosed') + ->willReturn($isPaymentTransactionClosed); + $newTransaction->expects($isPaymentTransactionClosed ? $this->once() : $this->never()) + ->method('setIsClosed')->with((int)$isPaymentTransactionClosed); + $this->paymentMock->expects($isPaymentTransactionClosed ? $this->once() : $this->never()) + ->method('getIsTransactionClosed') + ->willReturn($isPaymentTransactionClosed); + } + + public function createDataProvider() + { + return [ + 'transactionNotExists' => [ + 'transactionId' => 33, + 'orderId' => 19, + 'paymentId' => 15, + 'failSafe' => false, + 'type' => Transaction::TYPE_REFUND, + 'isPaymentTransactionClosed' => false, + 'additionalInfo' => ['some_key' => '332-ou'], + 'document' => true, + 'isTransactionExists' => false + ], + 'transactionExists' => [ + 'transactionId' => 33, + 'orderId' => 19, + 'paymentId' => 15, + 'failSafe' => false, + 'type' => Transaction::TYPE_REFUND, + 'isPaymentTransactionClosed' => false, + 'additionalInfo' => ['some_key' => '332-ou'], + 'document' => true, + 'isTransactionExists' => true + ], + 'transactionWithoutDocument' => [ + 'transactionId' => 33, + 'orderId' => 19, + 'paymentId' => 15, + 'failSafe' => false, + 'type' => Transaction::TYPE_REFUND, + 'isPaymentTransactionClosed' => false, + 'additionalInfo' => ['some_key' => '332-ou'], + 'document' => false, + 'isTransactionExists' => true + ] + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/ManagerTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/ManagerTest.php new file mode 100644 index 0000000000000..1336dd83dc0fe --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/ManagerTest.php @@ -0,0 +1,203 @@ +repositoryMock = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction\Repository', + [], + [], + '', + false + ); + $this->manager = $objectManager->getObject( + 'Magento\Sales\Model\Order\Payment\Transaction\Manager', + ['transactionRepository' => $this->repositoryMock] + ); + } + + /** + * @dataProvider getAuthorizationDataProvider + * @param $parentTransactionId + * @param $paymentId + * @param $orderId + */ + public function testGetAuthorizationTransaction($parentTransactionId, $paymentId, $orderId) + { + $transaction = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [], + [], + '', + false + ); + if ($parentTransactionId) { + $this->repositoryMock->expects($this->once())->method('getByTransactionId')->with( + $parentTransactionId, + $paymentId, + $orderId + )->willReturn($transaction); + } else { + $this->repositoryMock->expects($this->once())->method('getByTransactionType')->with( + Transaction::TYPE_AUTH, + $paymentId, + $orderId + )->willReturn($transaction); + } + $this->assertEquals( + $transaction, + $this->manager->getAuthorizationTransaction($parentTransactionId, $paymentId, $orderId) + ); + } + + /** + * @dataProvider isTransactionExistsDataProvider + * @param string|null $transactionId + * @param bool $isRepositoryReturnTransaction + * @param bool $expectedResult + */ + public function testIsTransactionExists($transactionId, $isRepositoryReturnTransaction, $expectedResult) + { + $paymentId = 1; + $orderId = 9; + + if ($transactionId && $isRepositoryReturnTransaction) { + $transaction = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [], + [], + '', + false + ); + $this->repositoryMock->expects($this->once())->method('getByTransactionId')->willReturn($transaction); + } + + $this->assertEquals( + $expectedResult, + $this->manager->isTransactionExists($transactionId, $paymentId, $orderId) + ); + } + + /** + * @dataProvider generateTransactionIdDataProvider + * @param string|null $transactionId + * @param string|null $parentTransactionId + * @param string|null $transactionBasedTxnId + * @param string $type + * @param string|null $expectedResult + */ + public function testGenerateTransactionId( + $transactionId, + $parentTransactionId, + $transactionBasedTxnId, + $type, + $expectedResult + ) { + $transactionBasedOn = false; + + $payment = $this->getMock( + 'Magento\Sales\Model\Order\Payment', + ["setParentTransactionId", "getParentTransactionId", "getTransactionId"], + [], + '', + false + ); + $payment->expects($this->atLeastOnce())->method('getTransactionId')->willReturn($transactionId); + + if (!$parentTransactionId && !$transactionId && $transactionBasedTxnId) { + $transactionBasedOn = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [], + [], + '', + false + ); + $transactionBasedOn->expects($this->once())->method('getTxnId')->willReturn($transactionBasedTxnId); + $payment->expects($this->once())->method("setParentTransactionId")->with($transactionBasedTxnId); + } + $payment->expects($this->exactly(2))->method('getParentTransactionId')->willReturnOnConsecutiveCalls( + $parentTransactionId, + $transactionBasedOn ? $transactionBasedTxnId : $parentTransactionId + ); + + $this->assertEquals( + $expectedResult, + $this->manager->generateTransactionId($payment, $type, $transactionBasedOn) + ); + } + + /** + * @return array$transactionId, $parentTransactionId, $transactionBasedTxnId + */ + public function generateTransactionIdDataProvider() + { + return [ + 'withoutTransactionId' => [ + 'transactionId' => null, + 'parentTransactionId' => 2, + 'transactionBasedOnId' => 1, + 'type' => Transaction::TYPE_REFUND, + 'expectedResult' => "2-" . Transaction::TYPE_REFUND + ], + 'withTransactionId' => [ + 'transactionId' => 33, + 'parentTransactionId' => 2, + 'transactionBasedOnId' => 1, + 'type' => Transaction::TYPE_REFUND, + 'expectedResult' => 33 + ], + 'withBasedTransactionId' => [ + 'transactionId' => null, + 'parentTransactionId' => null, + 'transactionBasedOnId' => 4, + 'type' => Transaction::TYPE_REFUND, + 'expectedResult' => "4-" . Transaction::TYPE_REFUND + ], + ]; + } + + public function isTransactionExistsDataProvider() + { + return [ + 'withTransactionIdAndTransaction' => ["100-refund", true, true], + 'withoutTransactionIdAndWithTransaction' => [null, true, false], + 'withTransactionIdAndWithoutTransaction' => ["100-refund", false, false], + 'withoutTransactionIdAndWithoutTransaction' => [null, false, false], + ]; + } + + public function getAuthorizationDataProvider() + { + return [ + 'withParentId' => [false, 1, 1], + 'withoutParentId' => [1, 2, 1] + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/RepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/RepositoryTest.php new file mode 100644 index 0000000000000..1babb714902ef --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/Transaction/RepositoryTest.php @@ -0,0 +1,465 @@ +searchResultFactory = $this->getMock( + 'Magento\Sales\Api\Data\TransactionSearchResultInterfaceFactory', + ['create'], + [], + '', + false + ); + $this->filterBuilder = $this->getMock( + 'Magento\Framework\Api\FilterBuilder', + [], + [], + '', + false + ); + $this->searchCriteriaBuilder = $this->getMock( + 'Magento\Framework\Api\SearchCriteriaBuilder', + [], + [], + '', + false + ); + $this->sortOrderBuilder = $this->getMock( + 'Magento\Framework\Api\SortOrderBuilder', + [], + [], + '', + false + ); + $this->metaData = $this->getMock( + 'Magento\Sales\Model\Resource\Metadata', + [], + [], + '', + false + ); + $entityStorageFactory = $this->getMock( + 'Magento\Sales\Model\EntityStorageFactory', + ['create'], + [], + '', + false + ); + $this->entityStorage = $this->getMock( + 'Magento\Sales\Model\EntityStorage', + [], + [], + '', + false + ); + $this->transactionResource = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Payment\Transaction', + [], + [], + '', + false + ); + $this->searchCriteria = $this->getMock( + 'Magento\Framework\Api\SearchCriteria', + [], + [], + '', + false + ); + $this->filterGroup = $this->getMock( + 'Magento\Framework\Api\Search\FilterGroup', + [], + [], + '', + false + ); + $this->filter = $this->getMock( + 'Magento\Framework\Api\Filter', + [], + [], + '', + false + ); + $this->collection = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Payment\Transaction\Collection', + [], + [], + '', + false + ); + $entityStorageFactory->expects($this->once())->method('create')->willReturn($this->entityStorage); + $this->repository = $objectManager->getObject( + 'Magento\Sales\Model\Order\Payment\Transaction\Repository', + [ + 'searchResultFactory' => $this->searchResultFactory, + 'filterBuilder' => $this->filterBuilder, + 'searchCriteriaBuilder' => $this->searchCriteriaBuilder, + 'sortOrderBuilder' => $this->sortOrderBuilder, + 'metaData' => $this->metaData, + 'entityStorageFactory' => $entityStorageFactory, + ] + ); + } + + public function testCreate() + { + $expected = "expect"; + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($expected); + $this->assertEquals($expected, $this->repository->create()); + } + + public function testSave() + { + $transactionId = 12; + $transaction = $this->mockTransaction($transactionId); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->transactionResource->expects($this->once())->method('save') + ->with($transaction) + ->willReturn($transaction); + $this->entityStorage->expects($this->once())->method('add')->with($transaction); + $this->entityStorage->expects($this->once())->method('get')->with($transactionId)->willReturn($transaction); + $this->assertSame($transaction, $this->repository->save($transaction)); + } + + public function testDelete() + { + $transactionId = 12; + $transaction = $this->mockTransaction($transactionId); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->transactionResource->expects($this->once())->method('delete')->with($transaction); + $this->entityStorage->expects($this->once())->method('remove')->with($transactionId); + $this->assertTrue($this->repository->delete($transaction)); + } + + public function testGet() + { + $transactionId = 12; + $transaction = $this->mockTransaction($transactionId); + $this->entityStorage->method('has')->with($transactionId)->willReturn(false); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($transaction); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->transactionResource->expects($this->once())->method('load')->with($transaction, $transactionId); + $this->entityStorage->expects($this->once())->method('add')->with($transaction); + $this->entityStorage->expects($this->once())->method('get')->with($transactionId)->willReturn($transaction); + $this->assertSame($transaction, $this->repository->get($transactionId)); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function testGetException() + { + $transactionId = null; + $this->repository->get($transactionId); + } + + /** + * @expectedException \Magento\Framework\Exception\NoSuchEntityException + * @throws \Magento\Framework\Exception\InputException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function testGetNoSuchEntity() + { + $transactionId = null; + $transactionIdFromArgument = 12; + $transaction = $this->mockTransaction($transactionId); + $this->entityStorage->method('has')->with($transactionIdFromArgument)->willReturn(false); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($transaction); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->transactionResource->expects($this->once())->method('load')->with( + $transaction, + $transactionIdFromArgument + ); + $this->entityStorage->expects($this->never())->method('add'); + $this->entityStorage->expects($this->never())->method('get'); + $this->assertSame($transaction, $this->repository->get(12)); + } + + public function testGetExistInStorage() + { + $transactionId = 12; + $transaction = "transaction"; + $this->entityStorage->method('has')->with($transactionId)->willReturn(true); + $this->metaData->expects($this->never())->method('getNewInstance')->willReturn($transaction); + $this->metaData->expects($this->never())->method('getMapper')->willReturn($this->transactionResource); + $this->transactionResource->expects($this->never())->method('load')->with($transaction, $transactionId); + $this->entityStorage->expects($this->never())->method('add')->with($transaction); + $this->entityStorage->expects($this->once())->method('get')->with($transactionId)->willReturn($transaction); + $this->assertSame($transaction, $this->repository->get($transactionId)); + } + + public function testGetList() + { + $field = 'txn_id'; + $value = '33-refund'; + $this->getListMock($field, $value); + $this->assertSame($this->collection, $this->repository->getList($this->searchCriteria)); + } + + public function testGetByTransactionId() + { + $transactionId = "100-refund"; + $paymentId = 1; + $orderId = 3; + $cacheStorage = 'txn_id'; + $transaction = $this->mockTransaction($transactionId, true); + $identityFieldsForCache = [$transactionId, $paymentId, $orderId]; + $this->entityStorage->method('getByIdentifyingFields') + ->with($identityFieldsForCache, $cacheStorage) + ->willReturn(false); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($transaction); + $this->transactionResource->expects($this->once())->method('loadObjectByTxnId')->with( + $transaction, + $orderId, + $paymentId, + $transactionId + )->willReturn($transaction); + $transaction->expects($this->once())->method('getId')->willReturn($transactionId); + $this->entityStorage->expects($this->once()) + ->method('addByIdentifyingFields') + ->with($transaction, $identityFieldsForCache, $cacheStorage); + $this->assertEquals($transaction, $this->repository->getByTransactionId($transactionId, $paymentId, $orderId)); + } + + public function testGetByTransactionIdNotFound() + { + $transactionId = "100-refund"; + $paymentId = 1; + $orderId = 3; + $cacheStorage = 'txn_id'; + $transaction = $this->mockTransaction($transactionId, true); + $identityFieldsForCache = [$transactionId, $paymentId, $orderId]; + $this->entityStorage->method('getByIdentifyingFields') + ->with($identityFieldsForCache, $cacheStorage) + ->willReturn(false); + $this->metaData->expects($this->once())->method('getMapper')->willReturn($this->transactionResource); + $this->metaData->expects($this->once())->method('getNewInstance')->willReturn($transaction); + $this->transactionResource->expects($this->once())->method('loadObjectByTxnId')->with( + $transaction, + $orderId, + $paymentId, + $transactionId + )->willReturn(false); + $transaction->expects($this->once())->method('getId')->willReturn(false); + $this->assertEquals( + false, + $this->repository->getByTransactionId($transactionId, $paymentId, $orderId) + ); + } + + public function testGetByTransactionIdFromStorage() + { + $transactionId = "100-refund"; + $paymentId = 1; + $orderId = 3; + $cacheStorage = 'txn_id'; + $transaction = "transaction"; + $identityFieldsForCache = [$transactionId, $paymentId, $orderId]; + $this->entityStorage->method('getByIdentifyingFields') + ->with($identityFieldsForCache, $cacheStorage) + ->willReturn($transaction); + $this->assertEquals( + $transaction, + $this->repository->getByTransactionId($transactionId, $paymentId, $orderId) + ); + } + + public function testGetByTransactionType() + { + $transactionType = Transaction::TYPE_AUTH; + $paymentId = 1; + $orderId = 3; + $cacheStorage = 'txn_type'; + $identityFieldsForCache = [$transactionType, $paymentId]; + $this->entityStorage->expects($this->once()) + ->method('getByIdentifyingFields') + ->with($identityFieldsForCache, $cacheStorage) + ->willReturn(false); + $this->filterBuilder->expects($this->exactly(2))->method('setField') + ->withConsecutive( + [\Magento\Sales\Api\Data\TransactionInterface::TXN_TYPE], + [\Magento\Sales\Api\Data\TransactionInterface::PAYMENT_ID] + )->willReturnSelf(); + $this->filterBuilder->expects($this->exactly(2))->method('setValue') + ->withConsecutive( + [$transactionType], + [$paymentId] + )->willReturnSelf(); + $this->filterBuilder->expects($this->exactly(2))->method('create')->willReturn($this->filter); + + $transactionIdSort = "TransactionIdSort"; + $createdAtSort = "createdAtSort"; + $this->sortOrderBuilder->expects($this->exactly(2))->method('setField') + ->withConsecutive( + ['transaction_id'], + ['created_at'] + )->willReturnSelf(); + $this->sortOrderBuilder->expects($this->exactly(2))->method('setDirection') + ->with(\Magento\Framework\Data\Collection::SORT_ORDER_DESC)->willReturnSelf(); + $this->sortOrderBuilder->expects($this->exactly(2))->method('create')->willReturnOnConsecutiveCalls( + $transactionIdSort, + $createdAtSort + ); + $this->searchCriteriaBuilder->expects($this->once()) + ->method('addFilters') + ->with([$this->filter, $this->filter]) + ->willReturnSelf(); + $this->searchCriteriaBuilder->expects($this->exactly(2)) + ->method('addSortOrder') + ->withConsecutive( + [$transactionIdSort], + [$createdAtSort] + )->willReturnSelf(); + $this->searchCriteriaBuilder->expects($this->once()) + ->method('create') + ->willReturn($this->searchCriteria); + $this->getListMock(\Magento\Sales\Api\Data\TransactionInterface::TXN_TYPE, $transactionType); + $transaction = $this->mockTransaction(1, true); + $this->collection->expects($this->once())->method('getItems')->willReturn([$transaction]); + $this->entityStorage->expects($this->once()) + ->method('addByIdentifyingFields') + ->with($transaction, $identityFieldsForCache, $cacheStorage); + $this->assertEquals( + $transaction, + $this->repository->getByTransactionType($transactionType, $paymentId, $orderId) + ); + } + + public function testGetByTransactionTypeFromCache() + { + $transactionType = Transaction::TYPE_AUTH; + $paymentId = 1; + $orderId = 3; + $cacheStorage = 'txn_type'; + $transaction = "transaction"; + $identityFieldsForCache = [$transactionType, $paymentId]; + $this->entityStorage->method('getByIdentifyingFields') + ->with($identityFieldsForCache, $cacheStorage) + ->willReturn($transaction); + $this->assertEquals( + $transaction, + $this->repository->getByTransactionType($transactionType, $paymentId, $orderId) + ); + } + + /** + * @param string|int|null $transactionId + * @param bool $withoutTransactionIdMatcher + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function mockTransaction($transactionId, $withoutTransactionIdMatcher = false) + { + $transaction = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [], + [], + '', + false + ); + if (!$withoutTransactionIdMatcher) { + $transaction->expects($this->once())->method('getTransactionId')->willReturn($transactionId); + } + return $transaction; + } + + /** + * @param $field + * @param $value + */ + protected function getListMock($field, $value) + { + $currentPage = 1; + $pageSize = 10; + $this->searchResultFactory->method('create')->willReturn($this->collection); + $this->searchCriteria->expects($this->once())->method('getFilterGroups')->willReturn([$this->filterGroup]); + $this->filterGroup->expects($this->once())->method('getFilters')->willReturn([$this->filter]); + $this->filter->expects($this->once())->method('getConditionType')->willReturn(null); + $this->filter->expects($this->once())->method('getField')->willReturn($field); + $this->filter->expects($this->once())->method('getValue')->willReturn($value); + $this->collection->expects($this->once())->method('addFieldToFilter')->with($field, ['eq' => $value]); + $this->searchCriteria->expects($this->once())->method('getCurrentPage')->willReturn($currentPage); + $this->searchCriteria->expects($this->once())->method('getPageSize')->willReturn($pageSize); + $this->collection->expects($this->once())->method('setCurPage')->with(); + $this->collection->expects($this->once())->method('setPageSize')->with(); + $this->collection->expects($this->once())->method('addPaymentInformation')->with(['method']); + $this->collection->expects($this->once())->method('addOrderInformation')->with(['increment_id']); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionRepositoryTest.php deleted file mode 100644 index 0b42ab53944a0..0000000000000 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Payment/TransactionRepositoryTest.php +++ /dev/null @@ -1,191 +0,0 @@ -transactionFactory = $this->getMock( - 'Magento\Sales\Model\Order\Payment\TransactionFactory', - ['create'], - [], - '', - false - ); - $this->transactionCollectionFactory = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory', - ['create'], - [], - '', - false - ); - $this->filterBuilder = $this->getMock('Magento\Framework\Api\FilterBuilder', [], [], '', false); - $this->searchCriteriaBuilder = $this->getMock( - 'Magento\Framework\Api\SearchCriteriaBuilder', - [], - [], - '', - false - ); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->transactionRepository = $this->objectManagerHelper->getObject( - 'Magento\Sales\Model\Order\Payment\TransactionRepository', - [ - 'transactionFactory' => $this->transactionFactory, - 'transactionCollectionFactory' => $this->transactionCollectionFactory, - 'filterBuilder' => $this->filterBuilder, - 'searchCriteriaBuilder' => $this->searchCriteriaBuilder - ] - ); - } - - public function testGetIOException() - { - $this->setExpectedException('Magento\Framework\Exception\InputException', 'ID required'); - $this->transactionRepository->get(null); - } - - /** - * @param int $id - * @param array $collectionIds - * @param $conditionType - * @dataProvider getDataProvider - */ - public function testGet($id, array $collectionIds, $conditionType) - { - $filter = $this->getMock( - 'Magento\Framework\Api\Filter', - ['getConditionType', 'getField', 'getValue'], - [], - '', - false - ); - $filter->expects($this->any())->method('getConditionType')->willReturn($conditionType); - - $this->filterBuilder->expects($this->once())->method('setField')->with('transaction_id')->willReturnSelf(); - $this->filterBuilder->expects($this->once())->method('setValue')->with($id)->willReturnSelf(); - $this->filterBuilder->expects($this->once())->method('setConditionType')->with('eq')->willReturnSelf(); - $this->filterBuilder->expects($this->once())->method('create')->willReturn($filter); - - $filterGroup = $this->getMock('Magento\Framework\Api\Search\FilterGroup', [], [], '', false); - $filterGroup->expects($this->any()) - ->method('getFilters') - ->willReturn($filter); - $searchCriteria = $this->getMock('Magento\Framework\Api\SearchCriteria', [], [], '', false); - $searchCriteria->expects($this->any()) - ->method('getFilterGroups') - ->willReturn([$filterGroup]); - $this->searchCriteriaBuilder->expects($this->once()) - ->method('addFilters') - ->with([$filter]); - $this->searchCriteriaBuilder->expects($this->once()) - ->method('create') - ->willReturn($searchCriteria); - $transactionModelMock = $this->getMockBuilder('Magento\Sales\Model\Order\Payment\Transaction') - ->disableOriginalConstructor()->setMethods([])->getMock(); - $transactionModelMock->expects($this->any())->method('getId')->will($this->returnValue($id)); - - $this->prepareCollection($transactionModelMock, $collectionIds); - - $this->assertSame($transactionModelMock, $this->transactionRepository->get($id)); - } - - public function testFind() - { - list($id, $collectionIds, $filterData) = [1, [1], ['field', 'value', 'lteq']]; - $transactionModelMock = $this->getMockBuilder('Magento\Sales\Model\Order\Payment\Transaction') - ->disableOriginalConstructor()->setMethods([])->getMock(); - $transactionModelMock->expects($this->any())->method('getId')->will($this->returnValue($id)); - $collection = $this->prepareCollection($transactionModelMock, $collectionIds); - - $searchCriteriaMock = $this->getMock('Magento\Framework\Api\SearchCriteria', [], [], '', false); - $filterGroup = $this->getMock('Magento\Framework\Api\Search\FilterGroup', [], [], '', false); - $filter = $this->getMock('Magento\Framework\Api\Filter', [], [], '', false); - - $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->will( - $this->returnValue([$filterGroup]) - ); - $filterGroup->expects($this->once())->method('getFilters')->will($this->returnValue([$filter])); - $filter->expects($this->once())->method('getField')->will($this->returnValue($filterData[0])); - $filter->expects($this->once())->method('getValue')->will($this->returnValue($filterData[1])); - $filter->expects($this->any())->method('getConditionType')->will($this->returnValue($filterData[2])); - $collection->expects($this->once())->method('addFieldToFilter')->with( - $filterData[0], - [$filterData[2] => $filterData[1]] - ); - $collection->expects($this->once())->method('addPaymentInformation')->with(['method']); - $collection->expects($this->once())->method('addOrderInformation')->with(['increment_id']); - $this->assertSame([$id => $transactionModelMock], $this->transactionRepository->find($searchCriteriaMock)); - } - - /** - * @return array - */ - public function getDataProvider() - { - return [ - [1, [1], 'eq'], - [1, [], null], - ]; - } - - /** - * @param $transactionModelMock - * @param $collectionIds - * @return \PHPUnit_Framework_MockObject_MockObject - */ - private function prepareCollection($transactionModelMock, $collectionIds) - { - $collection = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Payment\Transaction\Collection', - [], - [], - '', - false - ); - $collection->expects($this->once())->method('getIterator')->will( - $this->returnValue(new \ArrayIterator([$transactionModelMock])) - ); - $collection->expects($this->once())->method('getAllIds')->will($this->returnValue($collectionIds)); - $this->transactionCollectionFactory->expects($this->once()) - ->method('create') - ->willReturn($collection); - return $collection; - } -} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php index 61a08ea6c877d..bae07f65c98ee 100755 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/PaymentTest.php @@ -7,11 +7,13 @@ use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\Payment; +use Magento\Sales\Model\Order\Payment\Transaction; /** * Class PaymentTest * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyFields) */ class PaymentTest extends \PHPUnit_Framework_TestCase { @@ -56,32 +58,46 @@ class PaymentTest extends \PHPUnit_Framework_TestCase private $transactionId; /** - * @var \Magento\Sales\Model\Order\Payment\TransactionFactory | \PHPUnit_Framework_MockObject_MockObject + * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $transactionFactory; + protected $transactionCollectionFactory; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\CreditmemoFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $transactionCollectionFactory; + protected $creditmemoFactoryMock; /** - * @var \Magento\Sales\Model\Service\OrderFactory | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Creditmemo | \PHPUnit_Framework_MockObject_MockObject */ - protected $serviceOrderFactory; + protected $creditMemoMock; /** - * @var \Magento\Sales\Model\Service\Order | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Transaction\Repository | \PHPUnit_Framework_MockObject_MockObject */ - protected $serviceOrder; + protected $transactionRepositoryMock; /** - * @var \Magento\Sales\Model\Order\Creditmemo | \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface| \PHPUnit_Framework_MockObject_MockObject + */ + protected $transactionManagerMock; + + /** + * @var \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface | \PHPUnit_Framework_MockObject_MockObject + */ + + protected $transactionBuilderMock; + + /** + * @var \Magento\Sales\Model\Order\Payment\Processor|\PHPUnit_Framework_MockObject_MockObject */ - protected $creditMemoMock; + + protected $paymentProcessor; /** + * @return void * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.TooManyFields) */ protected function setUp() { @@ -110,6 +126,12 @@ protected function setUp() ->disableOriginalConstructor() ->setMethods(['formatTxt']) ->getMock(); + $transaction = 'Magento\Sales\Model\Order\Payment\Transaction\Repository'; + $this->transactionRepositoryMock = $this->getMockBuilder($transaction) + ->disableOriginalConstructor() + ->setMethods(['get', 'getByTransactionType', 'getByTransactionId']) + ->getMock(); + $this->paymentProcessor = $this->getMock('Magento\Sales\Model\Order\Payment\Processor', [], [], '', false); $this->priceCurrencyMock->expects($this->any()) ->method('format') @@ -192,29 +214,29 @@ function ($value) { ) ->getMock(); - $this->transactionFactory = $this->getMock( - 'Magento\Sales\Model\Order\Payment\TransactionFactory', + $this->transactionCollectionFactory = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory', ['create'], [], '', false ); - $this->transactionCollectionFactory = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Payment\Transaction\CollectionFactory', - ['create'], + $this->creditmemoFactoryMock = $this->getMock( + 'Magento\Sales\Model\Order\CreditmemoFactory', + [], [], '', false ); - $this->serviceOrderFactory = $this->getMock( - 'Magento\Sales\Model\Service\OrderFactory', - ['create'], + $this->transactionManagerMock = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction\Manager', + [], [], '', false ); - $this->serviceOrder = $this->getMock( - 'Magento\Sales\Model\Service\Order', + $this->transactionBuilderMock = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction\Builder', [], [], '', @@ -278,13 +300,7 @@ public function testPlace() ->method('getConfigPaymentAction') ->willReturn(null); - $this->eventManagerMock->expects($this->at(0)) - ->method('dispatch') - ->with('sales_order_payment_place_start', ['payment' => $this->payment]); - - $this->eventManagerMock->expects($this->at(1)) - ->method('dispatch') - ->with('sales_order_payment_place_end', ['payment' => $this->payment]); + $this->mockPlaceEvents(); $this->assertEquals($this->payment, $this->payment->place()); } @@ -294,6 +310,7 @@ public function testPlaceActionOrder() $newOrderStatus = 'new_status'; $customerNote = 'blabla'; $sum = 10; + $this->payment->setTransactionId($this->transactionId); $this->orderMock->expects($this->any())->method('getTotalDue')->willReturn($sum); $this->orderMock->expects($this->any())->method('getBaseTotalDue')->willReturn($sum); $this->helperMock->expects($this->once()) @@ -302,6 +319,7 @@ public function testPlaceActionOrder() $this->paymentMethodMock->expects($this->once()) ->method('getConfigPaymentAction') ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER); + $this->paymentMethodMock->expects($this->once())->method('isInitializeNeeded')->willReturn(false); $this->paymentMethodMock->expects($this->any()) ->method('getConfigData') ->with('order_status', null) @@ -315,21 +333,11 @@ public function testPlaceActionOrder() ->method('setStatus') ->with($newOrderStatus) ->willReturnSelf(); - $this->paymentMethodMock->expects($this->once()) - ->method('getConfigPaymentAction') - ->willReturn(null); - $this->orderMock->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock); - $this->currencyMock->method('formatTxt')->willReturn($sum); - $this->paymentMethodMock->expects($this->once()) + $this->paymentProcessor->expects($this->once()) ->method('order') ->with($this->payment, $sum) ->willReturnSelf(); - $this->eventManagerMock->expects($this->at(0)) - ->method('dispatch') - ->with('sales_order_payment_place_start', ['payment' => $this->payment]); - $this->eventManagerMock->expects($this->at(1)) - ->method('dispatch') - ->with('sales_order_payment_place_end', ['payment' => $this->payment]); + $this->mockPlaceEvents(); $statusHistory = $this->getMockForAbstractClass( 'Magento\Sales\Api\Data\OrderStatusHistoryInterface' ); @@ -337,7 +345,6 @@ public function testPlaceActionOrder() $this->orderMock->expects($this->any()) ->method('addStatusHistoryComment') ->withConsecutive( - [__('Ordered amount of %1', $sum)], [$customerNote] ) ->willReturn($statusHistory); @@ -345,9 +352,20 @@ public function testPlaceActionOrder() ->method('setIsCustomerNotified') ->with(true) ->willReturn($statusHistory); + $this->assertEquals($this->payment, $this->payment->place()); } + protected function mockPlaceEvents() + { + $this->eventManagerMock->expects($this->at(0)) + ->method('dispatch') + ->with('sales_order_payment_place_start', ['payment' => $this->payment]); + $this->eventManagerMock->expects($this->at(1)) + ->method('dispatch') + ->with('sales_order_payment_place_end', ['payment' => $this->payment]); + } + public function testPlaceActionAuthorizeInitializeNeeded() { $newOrderStatus = 'new_status'; @@ -379,15 +397,7 @@ public function testPlaceActionAuthorizeInitializeNeeded() ->method('setStatus') ->with($newOrderStatus) ->willReturnSelf(); - $this->paymentMethodMock->expects($this->once()) - ->method('getConfigPaymentAction') - ->willReturn(null); - $this->eventManagerMock->expects($this->at(0)) - ->method('dispatch') - ->with('sales_order_payment_place_start', ['payment' => $this->payment]); - $this->eventManagerMock->expects($this->at(1)) - ->method('dispatch') - ->with('sales_order_payment_place_end', ['payment' => $this->payment]); + $this->mockPlaceEvents(); $statusHistory = $this->getMockForAbstractClass( 'Magento\Sales\Api\Data\OrderStatusHistoryInterface' ); @@ -416,6 +426,7 @@ public function testPlaceActionAuthorizeFraud() $this->helperMock->expects($this->once()) ->method('getMethodInstance') ->will($this->returnValue($this->paymentMethodMock)); + $this->payment->setTransactionId($this->transactionId); $this->paymentMethodMock->expects($this->once()) ->method('getConfigPaymentAction') ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE); @@ -429,9 +440,7 @@ public function testPlaceActionAuthorizeFraud() $this->orderMock->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->orderMock->expects($this->any()) ->method('addStatusHistoryComment') - ->withConsecutive( - [__('Order is suspended as its authorizing amount %1 is suspected to be fraudulent.', $sum)] - ) + ->with($customerNote) ->willReturn($statusHistory); $this->mockGetDefaultStatus(Order::STATE_PROCESSING, Order::STATUS_FRAUD, ['first', 'second']); $this->orderMock->expects($this->any()) @@ -449,8 +458,6 @@ public function testPlaceActionAuthorizeFraud() $this->paymentMethodMock->expects($this->once()) ->method('getConfigPaymentAction') ->willReturn(null); - $this->orderMock->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock); - $this->currencyMock->method('formatTxt')->willReturn($sum); $this->assertEquals($this->payment, $this->payment->place()); //maybe we don't need write authorised sum when fraud was detected $this->assertEquals($sum, $this->payment->getAmountAuthorized()); @@ -476,11 +483,6 @@ public function testPlaceActionAuthorizeCapture() $statusHistory = $this->getMockForAbstractClass( 'Magento\Sales\Api\Data\OrderStatusHistoryInterface' ); - $this->invoiceMock->expects($this->once())->method('register')->willReturnSelf(); - $this->invoiceMock->expects($this->once())->method('capture')->willReturnSelf(); - $this->paymentMethodMock->expects($this->once())->method('canCapture')->willReturn(true); - $this->orderMock->expects($this->any())->method('prepareInvoice')->willReturn($this->invoiceMock); - $this->orderMock->expects($this->once())->method('addRelatedObject')->with($this->invoiceMock); $this->orderMock->expects($this->any())->method('getCustomerNote')->willReturn($customerNote); $this->orderMock->expects($this->any()) ->method('addStatusHistoryComment') @@ -501,174 +503,34 @@ public function testPlaceActionAuthorizeCapture() $this->assertEquals($this->payment, $this->payment->place()); - $this->assertEquals($this->invoiceMock, $this->payment->getCreatedInvoice()); $this->assertEquals($sum, $this->payment->getAmountAuthorized()); $this->assertEquals($sum, $this->payment->getBaseAmountAuthorized()); } - public function testAuthorize() - { - $storeID = 1; - $amount = 10; - $status = 'status'; - - $this->helperMock->expects($this->once()) - ->method('getMethodInstance') - ->will($this->returnValue($this->paymentMethodMock)); - - $this->paymentMethodMock->expects($this->once()) - ->method('setStore') - ->will($this->returnSelf()); - - $baseCurrencyMock = $this->getMockBuilder('Magento\Directory\Model\Currency') - ->disableOriginalConstructor() - ->setMethods(['formatTxt']) - ->getMock(); - - $baseCurrencyMock->expects($this->once()) - ->method('formatTxt') - ->willReturnCallback( - function ($value) { - return $value; - } - ); - - $this->orderMock->expects($this->once()) - ->method('getStoreId') - ->willReturn($storeID); - - $this->orderMock->expects($this->once()) - ->method('getBaseGrandTotal') - ->willReturn($amount); - - $this->orderMock->expects($this->once()) - ->method('getBaseCurrency') - ->willReturn($baseCurrencyMock); - - $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status); - $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, 'Authorized amount of ' . $amount); - - $this->paymentMethodMock->expects($this->once()) - ->method('authorize') - ->with($this->payment) - ->willReturnSelf(); - - $paymentResult = $this->payment->authorize(true, $amount); - - $this->assertInstanceOf('Magento\Sales\Model\Order\Payment', $paymentResult); - $this->assertEquals($amount, $paymentResult->getBaseAmountAuthorized()); - } - - public function testAuthorizeFraudDetected() + /** + * @param bool $isOnline + * @param float $amount + * @dataProvider authorizeDataProvider + */ + public function testAuthorize($isOnline, $amount) { - $storeID = 1; - $amount = 10; - $message = "Order is suspended as its authorizing amount $amount is suspected to be fraudulent."; - - $this->helperMock->expects($this->once()) - ->method('getMethodInstance') - ->will($this->returnValue($this->paymentMethodMock)); - - $this->paymentMethodMock->expects($this->once()) - ->method('setStore') - ->will($this->returnSelf()); - - $baseCurrencyMock = $this->getMockBuilder('Magento\Directory\Model\Currency') - ->disableOriginalConstructor() - ->setMethods(['formatTxt']) - ->getMock(); - - $baseCurrencyMock->expects($this->once()) - ->method('formatTxt') - ->willReturnCallback( - function ($value) { - return $value; - } - ); - - $this->orderMock->expects($this->once()) - ->method('getStoreId') - ->willReturn($storeID); - - $this->orderMock->expects($this->once()) - ->method('getBaseCurrencyCode') - ->willReturn("USD"); - - $this->orderMock->expects($this->once()) - ->method('getBaseCurrency') - ->willReturn($baseCurrencyMock); - - $this->assertOrderUpdated(Order::STATE_PROCESSING, Order::STATUS_FRAUD, $message); - - $this->paymentMethodMock->expects($this->once()) + $this->paymentProcessor->expects($this->once()) ->method('authorize') - ->with($this->payment) - ->willReturnSelf(); - - $this->payment->setCurrencyCode('GBP'); - - $paymentResult = $this->payment->authorize(true, $amount); - - $this->assertInstanceOf('Magento\Sales\Model\Order\Payment', $paymentResult); - $this->assertEquals($amount, $paymentResult->getBaseAmountAuthorized()); - $this->assertTrue($paymentResult->getIsFraudDetected()); + ->with($this->payment, $isOnline, $amount) + ->willReturn($this->payment); + $this->assertEquals($this->payment, $this->payment->authorize($isOnline, $amount)); } - public function testAuthorizeTransactionPending() + /** + * Data rpovider for testAuthorize + * @return array + */ + public function authorizeDataProvider() { - $storeID = 1; - $amount = 10; - $status = 'status'; - $message = "We will authorize $amount after the payment is approved at the payment gateway."; - - $this->helperMock->expects($this->once()) - ->method('getMethodInstance') - ->will($this->returnValue($this->paymentMethodMock)); - - $this->paymentMethodMock->expects($this->once()) - ->method('setStore') - ->will($this->returnSelf()); - - $baseCurrencyMock = $this->getMockBuilder('Magento\Directory\Model\Currency') - ->disableOriginalConstructor() - ->setMethods(['formatTxt']) - ->getMock(); - - $baseCurrencyMock->expects($this->once()) - ->method('formatTxt') - ->willReturnCallback( - function ($value) { - return $value; - } - ); - - $this->orderMock->expects($this->once()) - ->method('getStoreId') - ->willReturn($storeID); - - $this->orderMock->expects($this->once()) - ->method('getBaseGrandTotal') - ->willReturn($amount); - - $this->orderMock->expects($this->once()) - ->method('getBaseCurrency') - ->willReturn($baseCurrencyMock); - - $this->mockGetDefaultStatus(Order::STATE_PAYMENT_REVIEW, $status); - $this->assertOrderUpdated(Order::STATE_PAYMENT_REVIEW, $status, $message); - - $this->paymentMethodMock->expects($this->once()) - ->method('authorize') - ->with($this->payment) - ->willReturnSelf(); - - $this->payment->setIsTransactionPending(true); - - $paymentResult = $this->payment->authorize(true, $amount); - - $this->assertInstanceOf('Magento\Sales\Model\Order\Payment', $paymentResult); - $this->assertEquals($amount, $paymentResult->getBaseAmountAuthorized()); - $this->assertTrue($paymentResult->getIsTransactionPending()); + return [ + [false, 9.99], + [true, 0.01] + ]; } public function testAcceptApprovePaymentTrue() @@ -1274,25 +1136,17 @@ public function testCanCaptureCreateTransaction() ->willReturn(true); $parentTransactionId = 1; + $paymentId = 22; + $this->payment->setId($paymentId); $this->payment->setParentTransactionId($parentTransactionId); $transaction = $this->getMock('Magento\Sales\Model\Order\Payment\Transaction', [], [], '', false); - $transaction->expects($this->once()) - ->method('setOrderPaymentObject') - ->willReturnSelf(); - $transaction->expects($this->once()) - ->method('loadByTxnId') - ->willReturnSelf(); - $transaction->expects($this->once()) - ->method('getId') - ->willReturn($parentTransactionId); - $transaction->expects($this->once()) ->method('getIsClosed') ->willReturn(false); - - $this->transactionFactory->expects($this->once()) - ->method('create') + $this->transactionManagerMock->expects($this->once()) + ->method('getAuthorizationTransaction') + ->with($parentTransactionId, $paymentId) ->willReturn($transaction); $this->assertTrue($this->payment->canCapture()); @@ -1301,39 +1155,23 @@ public function testCanCaptureCreateTransaction() public function testCanCaptureAuthorizationTransaction() { $paymentId = 1; + $parentTransactionId = 1; + $this->payment->setParentTransactionId($parentTransactionId); $this->payment->setId($paymentId); - $this->paymentMethodMock->expects($this->once()) ->method('canCapture') ->willReturn(true); - $transaction = $this->getMock('Magento\Sales\Model\Order\Payment\Transaction', [], [], '', false); - $collection = $this->getMock( - 'Magento\Sales\Model\Resource\Order\Payment\Transaction\Collection', - [], - [], - '', - false - ); - $this->transactionCollectionFactory->expects($this->once()) - ->method('create') - ->willReturn($collection); - $collection->expects($this->once()) - ->method('setOrderFilter') - ->willReturnSelf(); - $collection->expects($this->once()) - ->method('addPaymentIdFilter') - ->willReturnSelf(); - $collection->expects($this->once()) - ->method('addTxnTypeFilter') - ->willReturnSelf(); - $collection->method('setOrder') - ->willReturnMap( - [ - ['created_at', \Magento\Framework\Data\Collection::SORT_ORDER_DESC, $collection], - ['transaction_id', \Magento\Framework\Data\Collection::SORT_ORDER_DESC, [$transaction]] - ] - ); + $this->transactionManagerMock->expects($this->once()) + ->method('getAuthorizationTransaction') + ->with($parentTransactionId, $paymentId) + ->willReturn($transaction); + $transaction->expects($this->once())->method('getIsClosed')->willReturn(true); + + $this->transactionRepositoryMock->expects($this->once()) + ->method('getByTransactionType') + ->with(Transaction::TYPE_ORDER, $paymentId) + ->willReturn($transaction); $this->assertTrue($this->payment->canCapture()); } @@ -1411,33 +1249,34 @@ public function testCancelInvoice() public function testRegisterRefundNotificationTransactionExists() { $amount = 10; + $paymentId = 1; + $orderId = 9; $this->payment->setParentTransactionId($this->transactionId); + $this->payment->setId($paymentId); + $this->orderMock->setId($orderId); $transaction = $this->getMock( 'Magento\Sales\Model\Resource\Order\Payment\Transaction', - ['setOrderPaymentObject', 'loadByTxnId', 'getId'], + [], [], '', false ); - $this->transactionFactory->expects($this->atLeastOnce()) - ->method('create') + $newTransactionId = $this->transactionId . '-' . Transaction::TYPE_REFUND; + $this->transactionRepositoryMock->expects($this->once()) + ->method('getByTransactionId') + ->with($this->transactionId) ->willReturn($transaction); - $transaction->expects($this->atLeastOnce()) - ->method('setOrderPaymentObject') - ->with($this->payment) - ->willReturnSelf(); - $transaction->expects($this->exactly(2)) - ->method('loadByTxnId') - ->withConsecutive( - [$this->transactionId], - [$this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND] - )->willReturnSelf(); - $transaction->expects($this->atLeastOnce()) - ->method('getId') - ->willReturnOnConsecutiveCalls( - $this->transactionId, - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - ); + + $this->transactionManagerMock->expects($this->once()) + ->method('isTransactionExists') + ->with($newTransactionId, $paymentId, $orderId) + ->willReturn(true); + + $this->transactionManagerMock->expects($this->once()) + ->method('generateTransactionId') + ->with($this->payment, Transaction::TYPE_REFUND, $transaction) + ->willReturn($newTransactionId); + $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount)); } @@ -1458,15 +1297,10 @@ public function testRegisterRefundNotification() $this->creditMemoMock->expects($this->any())->method('getGrandTotal')->willReturn($grandTotalCreditMemo); $this->payment->setParentTransactionId($this->transactionId); $this->mockInvoice($this->transactionId, 1); - $this->serviceOrderFactory->expects($this->once())->method('create')->with( - ['order' => $this->orderMock] - )->willReturn($this->serviceOrder); - $this->serviceOrder->expects($this->once())->method('prepareInvoiceCreditmemo')->with( - $this->invoiceMock, - ['adjustment_negative' => $invoiceBaseGrandTotal - $amount] - )->willReturn( - $this->creditMemoMock - ); + $this->creditmemoFactoryMock->expects($this->once()) + ->method('createByInvoice') + ->with($this->invoiceMock, ['adjustment_negative' => $invoiceBaseGrandTotal - $amount]) + ->willReturn($this->creditMemoMock); $this->creditMemoMock->expects($this->once())->method('setPaymentRefundDisallowed')->willReturnSelf(); $this->creditMemoMock->expects($this->once())->method('setAutomaticallyCreated')->willReturnSelf(); $this->creditMemoMock->expects($this->once())->method('register')->willReturnSelf(); @@ -1474,79 +1308,42 @@ public function testRegisterRefundNotification() $this->creditMemoMock->expects($this->once())->method('save')->willReturnSelf(); $this->orderMock->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock); - $newTransaction = $this->getMock( - 'Magento\Sales\Model\Order\Payment\Transaction', - [ - 'getId', - 'setOrderPaymentObject', - 'loadByTxnId', - 'setTxnId', - 'setTxnType', - 'isFailsafe', - 'getTxnId', - 'getHtmlTxnId', - 'getTxnType' - ], - [], - '', - false - ); - $parentTransaction = $this->getMock( 'Magento\Sales\Model\Order\Payment\Transaction', - ['setOrderPaymentObject', 'loadByTxnId', 'getId', 'getTxnId', 'getTxnType'], + ['setOrderId', 'setPaymentId', 'loadByTxnId', 'getId', 'getTxnId', 'setTxnId', 'getTxnType'], [], '', false ); - $this->transactionFactory->expects($this->exactly(3)) - ->method('create') - ->willReturnOnConsecutiveCalls($parentTransaction, $newTransaction, $newTransaction, $newTransaction); - $parentTransaction->expects($this->atLeastOnce()) - ->method('setOrderPaymentObject') - ->with($this->payment) - ->willReturnSelf(); - $parentTransaction->expects($this->exactly(1)) - ->method('loadByTxnId') - ->with($this->transactionId)->willReturnSelf(); - $newTransaction->expects($this->exactly(1)) - ->method('loadByTxnId') - ->with($this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND) - ->willReturnSelf(); - $parentTransaction->expects($this->atLeastOnce()) - ->method('getId') - ->willReturnOnConsecutiveCalls( - $this->transactionId, - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - )->willReturnOnConsecutiveCalls( - $this->transactionId, - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - ); - $newTransaction->expects($this->once())->method('setTxnId')->with( - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - )->willReturn($newTransaction); - $newTransaction->expects($this->atLeastOnce())->method('getHtmlTxnId')->willReturn( - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - ); - $newTransaction->expects($this->atLeastOnce())->method('getTxnId')->willReturn( - $this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - ); - $newTransaction->expects($this->atLeastOnce()) - ->method('setOrderPaymentObject') - ->willReturnSelf(); - $newTransaction->expects($this->once())->method('setTxnType')->with( - \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND - )->willReturn($newTransaction); - $newTransaction->expects($this->once())->method('isFailsafe')->with( - false - )->willReturn($newTransaction); - $this->orderMock->expects($this->atLeastOnce())->method('addRelatedObject'); + $newTransactionId = $this->transactionId . '-' . Transaction::TYPE_REFUND; + $this->transactionRepositoryMock->expects($this->once()) + ->method('getByTransactionId') + ->with($this->transactionId) + ->willReturn($parentTransaction); + + $this->transactionManagerMock->expects($this->once()) + ->method('isTransactionExists') + ->with($newTransactionId) + ->willReturn(false); + $this->transactionManagerMock->expects($this->once()) + ->method('generateTransactionId') + ->with($this->payment, Transaction::TYPE_REFUND, $parentTransaction) + ->willReturn($newTransactionId); $status = 'status'; - $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status); $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message); + $additionalInformation = []; + $failSafe = false; + $transactionType = Transaction::TYPE_REFUND; + $this->getTransactionBuilderMock( + $additionalInformation, + $failSafe, + $transactionType, + $this->transactionId . '-' . Transaction::TYPE_REFUND + ); + $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount)); $this->assertSame($this->creditMemoMock, $this->payment->getData('created_creditmemo')); $this->assertEquals($grandTotalCreditMemo, $this->payment->getData('amount_refunded')); @@ -1568,44 +1365,27 @@ public function testRegisterRefundNotificationWrongAmount() $this->orderMock->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock); $parentTransaction = $this->getMock( 'Magento\Sales\Model\Order\Payment\Transaction', - ['setOrderPaymentObject', 'loadByTxnId', 'getId', 'getTxnId', 'getTxnType'], + ['setOrderId', 'setPaymentId', 'loadByTxnId', 'getId', 'getTxnId', 'getTxnType'], [], '', false ); - $parentTransaction->expects($this->atLeastOnce()) - ->method('setOrderPaymentObject') - ->with($this->payment) - ->willReturnSelf(); - $parentTransaction->expects($this->exactly(1)) - ->method('loadByTxnId') - ->with($this->transactionId)->willReturnSelf(); - $newTransaction = $this->getMock( - 'Magento\Sales\Model\Order\Payment\Transaction', - [ - 'getId', - 'setOrderPaymentObject', - 'loadByTxnId', - 'setTxnId', - 'setTxnType', - 'isFailsafe', - 'getTxnId', - 'getTxnType' - ], - [], - '', - false - ); - $this->transactionFactory->expects($this->exactly(2)) - ->method('create') - ->willReturnOnConsecutiveCalls($parentTransaction, $newTransaction); - $newTransaction->expects($this->exactly(1)) - ->method('loadByTxnId') - ->with($this->transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND) - ->willReturnSelf(); - $newTransaction->expects($this->atLeastOnce()) - ->method('setOrderPaymentObject') - ->willReturnSelf(); + //generate new transaction and check if not exists + $this->transactionRepositoryMock->expects($this->once()) + ->method('getByTransactionId') + ->with($this->transactionId) + ->willReturn($parentTransaction); + + $newTransactionId = $this->transactionId . '-refund'; + $this->transactionManagerMock->expects($this->once()) + ->method('isTransactionExists') + ->with($newTransactionId) + ->willReturn(false); + + $this->transactionManagerMock->expects($this->once()) + ->method('generateTransactionId') + ->with($this->payment, Transaction::TYPE_REFUND, $parentTransaction) + ->willReturn($newTransactionId); $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount)); } @@ -1637,11 +1417,13 @@ protected function initPayment($context) 'Magento\Sales\Model\Order\Payment', [ 'context' => $context, - 'serviceOrderFactory' => $this->serviceOrderFactory, + 'creditmemoFactory' => $this->creditmemoFactoryMock, 'paymentData' => $this->helperMock, 'priceCurrency' => $this->priceCurrencyMock, - 'transactionFactory' => $this->transactionFactory, - 'transactionCollectionFactory' => $this->transactionCollectionFactory + 'transactionRepository' => $this->transactionRepositoryMock, + 'transactionManager' => $this->transactionManagerMock, + 'transactionBuilder' => $this->transactionBuilderMock, + 'paymentProcessor' => $this->paymentProcessor ] ); @@ -1703,4 +1485,81 @@ protected function mockGetDefaultStatus($state, $status, $allStatuses = []) ->method('getConfig') ->will($this->returnValue($orderConfigMock)); } + + protected function getTransactionMock($transactionId) + { + $transaction = $this->getMock( + 'Magento\Sales\Model\Order\Payment\Transaction', + [ + 'getId', + 'setOrderId', + 'setPaymentId', + 'loadByTxnId', + 'setTxnId', + 'getTransactionId', + 'setTxnType', + 'isFailsafe', + 'getTxnId', + 'getHtmlTxnId', + 'getTxnType' + ], + [], + '', + false + ); + $transaction->expects($this->any())->method('getId')->willReturn($transactionId); + $transaction->expects($this->any())->method('getTxnId')->willReturn($transactionId); + $transaction->expects($this->any())->method('getHtmlTxnId')->willReturn($transactionId); + return $transaction; + } + + /** + * @param $additionalInformation + * @param $failSafe + * @param $transactionType + * @param bool $transactionId + */ + protected function getTransactionBuilderMock( + $additionalInformation, + $failSafe, + $transactionType, + $transactionId = false + ) { + if (!$transactionId) { + $transactionId = $this->transactionId; + } + $this->transactionBuilderMock->expects($this->once()) + ->method('setPayment') + ->with($this->payment) + ->willReturnSelf(); + $this->transactionBuilderMock->expects($this->once()) + ->method('setOrder') + ->with($this->orderMock) + ->willReturnSelf(); + $this->transactionBuilderMock->expects($this->once()) + ->method('setTransactionId') + ->with($transactionId) + ->willReturnSelf(); + $this->transactionBuilderMock->expects($this->once()) + ->method('setAdditionalInformation') + ->with($additionalInformation) + ->willReturnSelf(); + $this->transactionBuilderMock->expects($this->once()) + ->method('setFailSafe') + ->with($failSafe) + ->willReturnSelf(); + $transaction = $this->getTransactionMock($transactionId); + $this->transactionBuilderMock->expects($this->once()) + ->method('build') + ->with($transactionType) + ->willReturn($transaction); + } + + /** + * @return string + */ + protected function getTransactionIdComment() + { + return __(' Transaction ID: "%1"', $this->transactionId); + } } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/TrackTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/TrackTest.php index 4fb1b63fcbb3e..879e2c8ea3d6f 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/TrackTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/TrackTest.php @@ -16,8 +16,8 @@ protected function setUp() { $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $arguments = [ - 'shipmentFactory' => $this->getMock( - 'Magento\Sales\Model\Order\ShipmentFactory', + 'shipmentRepository' => $this->getMock( + 'Magento\Sales\Model\Order\ShipmentRepository', [], [], '', diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php new file mode 100644 index 0000000000000..c295323dae7d3 --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php @@ -0,0 +1,198 @@ +converter = $this->getMock( + 'Magento\Sales\Model\Convert\Order', + ['toShipment', 'itemToShipmentItem'], + [], + '', + false + ); + + $convertOrderFactory = $this->getMock( + 'Magento\Sales\Model\Convert\OrderFactory', + ['create'], + [], + '', + false + ); + $convertOrderFactory->expects($this->once()) + ->method('create') + ->willReturn($this->converter); + + $this->trackFactory = $this->getMock( + 'Magento\Sales\Model\Order\Shipment\TrackFactory', + ['create'], + [], + '', + false + ); + + $this->subject = $objectManager->getObject( + 'Magento\Sales\Model\Order\ShipmentFactory', + [ + 'convertOrderFactory' => $convertOrderFactory, + 'trackFactory' => $this->trackFactory + ] + ); + } + + /** + * @param array|null $tracks + * @dataProvider createDataProvider + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function testCreate($tracks) + { + $orderItem = $this->getMock( + 'Magento\Sales\Model\Order\Item', + ['getId', 'getQtyOrdered'], + [], + '', + false + ); + $orderItem->expects($this->any()) + ->method('getId') + ->willReturn(1); + $orderItem->expects($this->any()) + ->method('getQtyOrdered') + ->willReturn(5); + + $shipmentItem = $this->getMock( + 'Magento\Sales\Model\Order\Shipment\Item', + ['setQty'], + [], + '', + false + ); + $shipmentItem->expects($this->once()) + ->method('setQty') + ->with(5); + + $order = $this->getMock( + 'Magento\Sales\Model\Order', + ['getAllItems'], + [], + '', + false + ); + $order->expects($this->any()) + ->method('getAllItems') + ->willReturn([$orderItem]); + + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['addItem', 'setTotalQty', 'addTrack'], + [], + '', + false + ); + $shipment->expects($this->once()) + ->method('addItem') + ->with($shipmentItem); + $shipment->expects($this->once()) + ->method('setTotalQty') + ->with(5) + ->willReturn($shipment); + + $this->converter->expects($this->any()) + ->method('toShipment') + ->with($order) + ->willReturn($shipment); + $this->converter->expects($this->any()) + ->method('itemToShipmentItem') + ->with($orderItem) + ->willReturn($shipmentItem); + + if ($tracks) { + $shipmentTrack = $this->getMock( + 'Magento\Sales\Model\Order\Shipment\Track', + ['addData'], + [], + '', + false + ); + + if (empty($tracks[0]['number'])) { + $shipmentTrack->expects($this->never()) + ->method('addData'); + + $this->trackFactory->expects($this->never()) + ->method('create'); + + $shipment->expects($this->never()) + ->method('addTrack'); + + $this->setExpectedException( + 'Magento\Framework\Exception\LocalizedException' + ); + } else { + $shipmentTrack->expects($this->once()) + ->method('addData') + ->willReturnSelf(); + + $this->trackFactory->expects($this->once()) + ->method('create') + ->willReturn($shipmentTrack); + + $shipment->expects($this->once()) + ->method('addTrack') + ->with($shipmentTrack); + } + } + + $this->assertEquals($shipment, $this->subject->create($order, ['1' => 5], $tracks)); + } + + /** + * @return array + */ + public function createDataProvider() + { + return [ + [null], + [[['number' => 'TEST_TRACK']]], + [[['number' => '']]], + ]; + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php new file mode 100644 index 0000000000000..f1dc70905c92f --- /dev/null +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentRepositoryTest.php @@ -0,0 +1,356 @@ +metadata = $this->getMock( + 'Magento\Sales\Model\Resource\Metadata', + ['getNewInstance', 'getMapper'], + [], + '', + false + ); + + $this->searchResultFactory = $this->getMock( + 'Magento\Sales\Api\Data\ShipmentSearchResultInterfaceFactory', + ['create'], + [], + '', + false + ); + + $this->subject = $objectManager->getObject( + 'Magento\Sales\Model\Order\ShipmentRepository', + [ + 'metadata' => $this->metadata, + 'searchResultFactory' => $this->searchResultFactory + ] + ); + } + + /** + * @param int|null $id + * @param int|null $entityId + * @dataProvider getDataProvider + */ + public function testGet($id, $entityId) + { + if (!$id) { + $this->setExpectedException( + 'Magento\Framework\Exception\InputException' + ); + + $this->subject->get($id); + } else { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['getEntityId'], + [], + '', + false + ); + $shipment->expects($this->once()) + ->method('getEntityId') + ->willReturn($entityId); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['load'] + ); + $mapper->expects($this->once()) + ->method('load') + ->with($shipment, $id) + ->willReturnSelf(); + + $this->metadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($shipment); + $this->metadata->expects($this->once()) + ->method('getMapper') + ->willReturn($mapper); + + if (!$entityId) { + $this->setExpectedException( + 'Magento\Framework\Exception\NoSuchEntityException' + ); + + $this->subject->get($id); + } else { + $this->assertEquals($shipment, $this->subject->get($id)); + + $mapper->expects($this->never()) + ->method('load'); + + $this->metadata->expects($this->never()) + ->method('getNewInstance'); + $this->metadata->expects($this->never()) + ->method('getMapper'); + + $this->assertEquals($shipment, $this->subject->get($id)); + } + } + } + + /** + * @return array + */ + public function getDataProvider() + { + return [ + [null, null], + [1, null], + [1, 1] + ]; + } + + public function testGetList() + { + $filter = $this->getMock( + 'Magento\Framework\Api\Filter', + ['getConditionType', 'getField', 'getValue'], + [], + '', + false + ); + $filter->expects($this->any()) + ->method('getConditionType') + ->willReturn(false); + $filter->expects($this->any()) + ->method('getField') + ->willReturn('test_field'); + $filter->expects($this->any()) + ->method('getValue') + ->willReturn('test_value'); + + $filterGroup = $this->getMock( + 'Magento\Framework\Api\Search\FilterGroup', + ['getFilters'], + [], + '', + false + ); + $filterGroup->expects($this->once()) + ->method('getFilters') + ->willReturn([$filter]); + + $criteria = $this->getMock( + 'Magento\Framework\Api\SearchCriteria', + ['getFilterGroups'], + [], + '', + false + ); + $criteria->expects($this->once()) + ->method('getFilterGroups') + ->willReturn([$filterGroup]); + + $collection = $this->getMock( + 'Magento\Sales\Model\Resource\Order\Shipment\Collection', + ['addFieldToFilter'], + [], + '', + false + ); + $collection->expects($this->once()) + ->method('addFieldToFilter') + ->withAnyParameters(); + + $this->searchResultFactory->expects($this->once()) + ->method('create') + ->willReturn($collection); + + $this->assertEquals($collection, $this->subject->getList($criteria)); + } + + public function testDelete() + { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['getEntityId'], + [], + '', + false + ); + $shipment->expects($this->once()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['delete'] + ); + $mapper->expects($this->once()) + ->method('delete') + ->with($shipment); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertTrue($this->subject->delete($shipment)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotDeleteException + * @expectedExceptionMessage Could not delete shipment + */ + public function testDeleteWithException() + { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['getEntityId'], + [], + '', + false + ); + $shipment->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['delete'] + ); + $mapper->expects($this->once()) + ->method('delete') + ->willThrowException(new \Exception('error')); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->subject->delete($shipment); + } + + public function testSave() + { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['getEntityId'], + [], + '', + false + ); + $shipment->expects($this->any()) + ->method('getEntityId') + ->willReturn(1); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['save'] + ); + $mapper->expects($this->once()) + ->method('save') + ->with($shipment); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($shipment, $this->subject->save($shipment)); + } + + /** + * @expectedException \Magento\Framework\Exception\CouldNotSaveException + * @expectedExceptionMessage Could not save shipment + */ + public function testSaveWithException() + { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + ['getEntityId'], + [], + '', + false + ); + $shipment->expects($this->never()) + ->method('getEntityId'); + + $mapper = $this->getMockForAbstractClass( + 'Magento\Framework\Model\Resource\Db\AbstractDb', + [], + '', + false, + true, + true, + ['save'] + ); + $mapper->expects($this->once()) + ->method('save') + ->willThrowException(new \Exception('error')); + + $this->metadata->expects($this->any()) + ->method('getMapper') + ->willReturn($mapper); + + $this->assertEquals($shipment, $this->subject->save($shipment)); + } + + public function testCreate() + { + $shipment = $this->getMock( + 'Magento\Sales\Model\Order\Shipment', + [], + [], + '', + false + ); + + $this->metadata->expects($this->once()) + ->method('getNewInstance') + ->willReturn($shipment); + + $this->assertEquals($shipment, $this->subject->create()); + } +} diff --git a/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php index 388d0ddebef0c..fce1442f8f0d2 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Service/CreditmemoServiceTest.php @@ -97,26 +97,12 @@ protected function setUp() /** * Run test cancel method + * @expectedExceptionMessage You can not cancel Credit Memo + * @expectedException \Magento\Framework\Exception\LocalizedException */ public function testCancel() { - $id = 10; - $creditmemoMock = $this->getMock( - 'Magento\Sales\Model\Order\Creditmemo', - ['cancel'], - [], - '', - false - ); - $this->creditmemoRepositoryMock->expects($this->once()) - ->method('get') - ->with($id) - ->will($this->returnValue($creditmemoMock)); - $creditmemoMock->expects($this->once()) - ->method('cancel') - ->will($this->returnValue(true)); - - $this->assertTrue($this->creditmemoService->cancel($id)); + $this->assertTrue($this->creditmemoService->cancel(1)); } /** diff --git a/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php index a318afa775f7f..dfbdd79bd3373 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Service/OrderServiceTest.php @@ -220,6 +220,10 @@ public function testHold() ->method('get') ->with(123) ->willReturn($this->orderMock); + $this->orderRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->orderMock) + ->willReturn($this->orderMock); $this->orderMock->expects($this->once()) ->method('hold') ->willReturn($this->orderMock); @@ -232,6 +236,10 @@ public function testUnHold() ->method('get') ->with(123) ->willReturn($this->orderMock); + $this->orderRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->orderMock) + ->willReturn($this->orderMock); $this->orderMock->expects($this->once()) ->method('unHold') ->willReturn($this->orderMock); diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php index 251328dcde8a7..32bf994688ef3 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/Status/OptionsTest.php @@ -29,7 +29,7 @@ public function setUp() $objectManager = new ObjectManager($this); $this->collectionFactoryMock = $this->getMock( 'Magento\Sales\Model\Resource\Order\Status\CollectionFactory', - [], + ['create'], [], '', false diff --git a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/StatusTest.php b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/StatusTest.php index 0b1d3c8179e01..905a4561ac222 100644 --- a/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/StatusTest.php +++ b/app/code/Magento/Sales/Test/Unit/Ui/Component/Listing/Column/StatusTest.php @@ -33,7 +33,7 @@ public function testPrepareDataSource() $collectionFactoryMock = $this->getMock( 'Magento\Sales\Model\Resource\Order\Status\CollectionFactory', - [], + ['create'], [], '', false diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State.php index 311f5c5ad729d..3bef29ecb99ca 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State.php @@ -8,7 +8,7 @@ use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Sales\Model\Order\CreditmemoFactory; +use Magento\Sales\Api\CreditmemoRepositoryInterface; /** * Class State @@ -25,18 +25,18 @@ class State extends Column * * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory - * @param CreditmemoFactory $creditmemoFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository * @param array $components * @param array $data */ public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, - CreditmemoFactory $creditmemoFactory, + CreditmemoRepositoryInterface $creditmemoRepository, array $components = [], array $data = [] ) { - $this->states = $creditmemoFactory->create()->getStates(); + $this->states = $creditmemoRepository->create()->getStates(); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -50,7 +50,9 @@ public function prepareDataSource(array & $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $item[$this->getData('name')] = $this->states[$item[$this->getData('name')]]; + $item[$this->getData('name')] = isset($this->states[$item[$this->getData('name')]]) + ? $this->states[$item[$this->getData('name')]] + : $item[$this->getData('name')]; } } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State/Options.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State/Options.php index edb9e3519273b..28bcb6395354d 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State/Options.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Creditmemo/State/Options.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Ui\Component\Listing\Column\Creditmemo\State; use Magento\Framework\Data\OptionSourceInterface; -use Magento\Sales\Model\Order\CreditmemoFactory; +use Magento\Sales\Api\CreditmemoRepositoryInterface; /** * Class Options @@ -19,18 +19,18 @@ class Options implements OptionSourceInterface protected $options; /** - * @var CreditmemoFactory + * @var CreditmemoRepositoryInterface */ - protected $creditmemoFactory; + protected $creditmemoRepository; /** * Constructor * - * @param CreditmemoFactory $creditmemoFactory + * @param CreditmemoRepositoryInterface $creditmemoRepository */ - public function __construct(CreditmemoFactory $creditmemoFactory) + public function __construct(CreditmemoRepositoryInterface $creditmemoRepository) { - $this->creditmemoFactory = $creditmemoFactory; + $this->creditmemoRepository = $creditmemoRepository; } /** @@ -44,7 +44,7 @@ public function toOptionArray() $this->options = []; /** @var \Magento\Framework\Phrase $state */ - foreach ($this->creditmemoFactory->create()->getStates() as $id => $state) { + foreach ($this->creditmemoRepository->create()->getStates() as $id => $state) { $this->options[] = [ 'value' => $id, 'label' => $state->render() diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/CustomerGroup.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/CustomerGroup.php index d33d301d3311b..02226d6e9e0c0 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/CustomerGroup.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/CustomerGroup.php @@ -5,6 +5,8 @@ */ namespace Magento\Sales\Ui\Component\Listing\Column; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; @@ -50,8 +52,14 @@ public function prepareDataSource(array & $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $item[$this->getData('name')] = $this->groupRepository->getById($item[$this->getData('name')]) - ->getCode(); + try { + $item[$this->getData('name')] = $this->groupRepository->getById($item[$this->getData('name')]) + ->getCode(); + } catch (NoSuchEntityException $exception) { + $item[$this->getData('name')] = __('Group was removed'); + } catch (\Exception $exception) { + $item[$this->getData('name')] = ''; + } } } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State.php index d65b8e5e7f842..f03f9b01359f0 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State.php @@ -8,7 +8,7 @@ use Magento\Ui\Component\Listing\Columns\Column; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Sales\Model\Order\InvoiceFactory; +use Magento\Sales\Api\InvoiceRepositoryInterface; /** * Class State @@ -25,18 +25,18 @@ class State extends Column * * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory - * @param InvoiceFactory $invoiceFactory + * @param InvoiceRepositoryInterface $invoiceRepository * @param array $components * @param array $data */ public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, - InvoiceFactory $invoiceFactory, + InvoiceRepositoryInterface $invoiceRepository, array $components = [], array $data = [] ) { - $this->states = $invoiceFactory->create()->getStates(); + $this->states = $invoiceRepository->create()->getStates(); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -50,7 +50,9 @@ public function prepareDataSource(array & $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $item[$this->getData('name')] = $this->states[$item[$this->getData('name')]]; + $item[$this->getData('name')] = isset($this->states[$item[$this->getData('name')]]) + ? $this->states[$item[$this->getData('name')]] + : $item[$this->getData('name')]; } } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State/Options.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State/Options.php index 8c4ec82ee21f6..a2b3dc8c25983 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State/Options.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Invoice/State/Options.php @@ -6,7 +6,7 @@ namespace Magento\Sales\Ui\Component\Listing\Column\Invoice\State; use Magento\Framework\Data\OptionSourceInterface; -use Magento\Sales\Model\Order\InvoiceFactory; +use Magento\Sales\Api\InvoiceRepositoryInterface; /** * Class Options @@ -19,18 +19,18 @@ class Options implements OptionSourceInterface protected $options; /** - * @var InvoiceFactory + * @var InvoiceRepositoryInterface */ - protected $invoiceFactory; + protected $invoiceRepository; /** * Constructor * - * @param InvoiceFactory $invoiceFactory + * @param InvoiceRepositoryInterface $invoiceRepository */ - public function __construct(InvoiceFactory $invoiceFactory) + public function __construct(InvoiceRepositoryInterface $invoiceRepository) { - $this->invoiceFactory = $invoiceFactory; + $this->invoiceRepository = $invoiceRepository; } /** @@ -44,7 +44,7 @@ public function toOptionArray() $this->options = []; /** @var \Magento\Framework\Phrase $state */ - foreach ($this->invoiceFactory->create()->getStates() as $id => $state) { + foreach ($this->invoiceRepository->create()->getStates() as $id => $state) { $this->options[] = [ 'value' => $id, 'label' => $state->render() diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/PaymentMethod.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/PaymentMethod.php index 2e245ab41cb9b..b8e4829804b7f 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/PaymentMethod.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/PaymentMethod.php @@ -54,7 +54,7 @@ public function prepareDataSource(array & $dataSource) $item[$this->getData('name')] = $this->paymentHelper ->getMethodInstance($item[$this->getData('name')]) ->getTitle(); - } catch (\UnexpectedValueException $exception) { + } catch (\Exception $exception) { //Displaying payment code (with no changes) if payment method is not available in system } } diff --git a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status.php b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status.php index 34b6dd60ea31a..7ca0c02a2a106 100644 --- a/app/code/Magento/Sales/Ui/Component/Listing/Column/Status.php +++ b/app/code/Magento/Sales/Ui/Component/Listing/Column/Status.php @@ -50,7 +50,9 @@ public function prepareDataSource(array & $dataSource) { if (isset($dataSource['data']['items'])) { foreach ($dataSource['data']['items'] as & $item) { - $item[$this->getData('name')] = $this->statuses[$item[$this->getData('name')]]; + $item[$this->getData('name')] = isset($this->statuses[$item[$this->getData('name')]]) + ? $this->statuses[$item[$this->getData('name')]] + : $item[$this->getData('name')]; } } } diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index ede03303e516e..48b8ace07b2a3 100755 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -37,27 +37,29 @@ - + - + - + - + - - + + - + - + + + @@ -261,6 +263,7 @@ Magento\Sales\Model\Resource\Order\Creditmemo\Relation + Magento\Sales\Model\Resource\Order\Creditmemo\Relation\Refund @@ -567,4 +570,101 @@ Magento\Framework\App\State\Proxy + + + Magento\Sales\Model\Resource\Order + Magento\Sales\Model\Order + + + + + Magento\Sales\Model\Resource\Order\Invoice + Magento\Sales\Model\Order\Invoice + + + + + Magento\Sales\Model\Resource\Order\Shipment + Magento\Sales\Model\Order\Shipment + + + + + Magento\Sales\Model\Resource\Order\Creditmemo + Magento\Sales\Model\Order\Creditmemo + + + + + Magento\Sales\Model\Resource\Order\Payment\Transaction + Magento\Sales\Model\Order\Payment\Transaction + + + + + Magento\Sales\Model\Resource\Order\Payment + Magento\Sales\Model\Order\Payment + + + + + Magento\Sales\Model\Resource\Order\Address + Magento\Sales\Model\Order\Address + + + + + orderMetadata + + + + + invoiceMetadata + + + + + shipmentMetadata + + + + + creditmemoMetadata + + + + + transactionMetaData + + + + + paymentMetaData + + + + + orderAddressMetadata + + + + + Magento\Sales\Model\Order\Payment\State\AuthorizeCommand + + + + + Magento\Sales\Model\Order\Payment\State\CaptureCommand + + + + + Magento\Sales\Model\Order\Payment\State\OrderCommand + + + + + Magento\Sales\Model\Order\Payment\State\RegisterCaptureNotificationCommand + + diff --git a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php index 52cd9c81760c9..e2b3e9fe1fedf 100644 --- a/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php +++ b/app/code/Magento/Shipping/Controller/Adminhtml/Order/ShipmentLoader.php @@ -34,9 +34,9 @@ class ShipmentLoader extends DataObject protected $registry; /** - * @var \Magento\Sales\Model\Order\ShipmentFactory + * @var \Magento\Sales\Model\Order\ShipmentRepository */ - protected $shipmentFactory; + protected $shipmentRepository; /** * @var \Magento\Sales\Model\OrderFactory @@ -44,9 +44,9 @@ class ShipmentLoader extends DataObject protected $orderFactory; /** - * @var \Magento\Sales\Model\Service\OrderFactory + * @var \Magento\Sales\Model\Order\ShipmentFactory */ - protected $orderServiceFactory; + protected $shipmentFactory; /** * @var \Magento\Sales\Model\Order\Shipment\TrackFactory @@ -56,26 +56,26 @@ class ShipmentLoader extends DataObject /** * @param \Magento\Framework\Message\ManagerInterface $messageManager * @param \Magento\Framework\Registry $registry - * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory + * @param \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository * @param \Magento\Sales\Model\OrderFactory $orderFactory - * @param \Magento\Sales\Model\Service\OrderFactory $orderServiceFactory + * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory * @param \Magento\Sales\Model\Order\Shipment\TrackFactory $trackFactory * @param array $data */ public function __construct( \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Framework\Registry $registry, - \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, + \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository, \Magento\Sales\Model\OrderFactory $orderFactory, - \Magento\Sales\Model\Service\OrderFactory $orderServiceFactory, + \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, \Magento\Sales\Model\Order\Shipment\TrackFactory $trackFactory, array $data = [] ) { $this->messageManager = $messageManager; $this->registry = $registry; - $this->shipmentFactory = $shipmentFactory; + $this->shipmentRepository = $shipmentRepository; $this->orderFactory = $orderFactory; - $this->orderServiceFactory = $orderServiceFactory; + $this->shipmentFactory = $shipmentFactory; $this->trackFactory = $trackFactory; parent::__construct($data); } @@ -88,12 +88,8 @@ public function __construct( protected function getItemQtys() { $data = $this->getShipment(); - if (isset($data['items'])) { - $qtys = $data['items']; - } else { - $qtys = []; - } - return $qtys; + + return isset($data['items']) ? $data['items'] : []; } /** @@ -108,7 +104,7 @@ public function load() $orderId = $this->getOrderId(); $shipmentId = $this->getShipmentId(); if ($shipmentId) { - $shipment = $this->shipmentFactory->create()->load($shipmentId); + $shipment = $this->shipmentRepository->get($shipmentId); } elseif ($orderId) { $order = $this->orderFactory->create()->load($orderId); @@ -134,19 +130,11 @@ public function load() return false; } - $savedQtys = $this->getItemQtys(); - $shipment = $this->orderServiceFactory->create(['order' => $order])->prepareShipment($savedQtys); - if ($this->getTracking()) { - foreach ((array)$this->getTracking() as $data) { - if (empty($data['number'])) { - throw new \Magento\Framework\Exception\LocalizedException( - __('Please enter a tracking number.') - ); - } - $track = $this->trackFactory->create()->addData($data); - $shipment->addTrack($track); - } - } + $shipment = $this->shipmentFactory->create( + $order, + $this->getItemQtys(), + $this->getTracking() + ); } $this->registry->register('current_shipment', $shipment); diff --git a/app/code/Magento/Shipping/Model/Info.php b/app/code/Magento/Shipping/Model/Info.php index ac9fdd692029e..956a012224d16 100644 --- a/app/code/Magento/Shipping/Model/Info.php +++ b/app/code/Magento/Shipping/Model/Info.php @@ -32,9 +32,9 @@ class Info extends \Magento\Framework\DataObject protected $_orderFactory; /** - * @var \Magento\Sales\Model\Order\ShipmentFactory + * @var \Magento\Sales\Model\Order\ShipmentRepository */ - protected $_shipmentFactory; + protected $shipmentRepository; /** * @var \Magento\Shipping\Model\Order\TrackFactory @@ -49,7 +49,7 @@ class Info extends \Magento\Framework\DataObject /** * @param \Magento\Shipping\Helper\Data $shippingData * @param \Magento\Sales\Model\OrderFactory $orderFactory - * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory + * @param \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository * @param \Magento\Shipping\Model\Order\TrackFactory $trackFactory * @param \Magento\Shipping\Model\Resource\Order\Track\CollectionFactory $trackCollectionFactory * @param array $data @@ -57,14 +57,14 @@ class Info extends \Magento\Framework\DataObject public function __construct( \Magento\Shipping\Helper\Data $shippingData, \Magento\Sales\Model\OrderFactory $orderFactory, - \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, + \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository, \Magento\Shipping\Model\Order\TrackFactory $trackFactory, \Magento\Shipping\Model\Resource\Order\Track\CollectionFactory $trackCollectionFactory, array $data = [] ) { $this->_shippingData = $shippingData; $this->_orderFactory = $orderFactory; - $this->_shipmentFactory = $shipmentFactory; + $this->shipmentRepository = $shipmentRepository; $this->_trackFactory = $trackFactory; $this->_trackCollectionFactory = $trackCollectionFactory; parent::__construct($data); @@ -131,8 +131,7 @@ protected function _initOrder() protected function _initShipment() { /* @var $model Shipment */ - $model = $this->_shipmentFactory->create(); - $ship = $model->load($this->getShipId()); + $ship = $this->shipmentRepository->get($this->getShipId()); if (!$ship->getEntityId() || $this->getProtectCode() != $ship->getProtectCode()) { return false; } diff --git a/app/code/Magento/Shipping/Model/Order/Track.php b/app/code/Magento/Shipping/Model/Order/Track.php index e46b40c6c4572..e9c914ae85328 100644 --- a/app/code/Magento/Shipping/Model/Order/Track.php +++ b/app/code/Magento/Shipping/Model/Order/Track.php @@ -35,7 +35,7 @@ class Track extends \Magento\Sales\Model\Order\Shipment\Track * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory * @param AttributeValueFactory $customAttributeFactory * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory + * @param \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository * @param \Magento\Shipping\Model\CarrierFactory $carrierFactory * @param \Magento\Framework\Model\Resource\AbstractResource $resource * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection @@ -49,7 +49,7 @@ public function __construct( \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, AttributeValueFactory $customAttributeFactory, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory, + \Magento\Sales\Model\Order\ShipmentRepository $shipmentRepository, \Magento\Shipping\Model\CarrierFactory $carrierFactory, \Magento\Framework\Model\Resource\AbstractResource $resource = null, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, @@ -61,7 +61,7 @@ public function __construct( $extensionFactory, $customAttributeFactory, $storeManager, - $shipmentFactory, + $shipmentRepository, $resource, $resourceCollection, $data diff --git a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/ShipmentLoaderTest.php b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/ShipmentLoaderTest.php index 7ad83ff5a9fb0..8b38639a2a824 100644 --- a/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/ShipmentLoaderTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Controller/Adminhtml/Order/ShipmentLoaderTest.php @@ -3,10 +3,8 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Shipping\Test\Unit\Controller\Adminhtml\Order; - /** * Class ShipmentLoaderTest * @@ -30,9 +28,9 @@ class ShipmentLoaderTest extends \PHPUnit_Framework_TestCase protected $messageManagerMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\ShipmentRepository|\PHPUnit_Framework_MockObject_MockObject */ - protected $shipmentFactoryMock; + protected $shipmentRepositoryMock; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -40,9 +38,9 @@ class ShipmentLoaderTest extends \PHPUnit_Framework_TestCase protected $orderFactoryMock; /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var \Magento\Sales\Model\Order\ShipmentFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $orderServiceFactoryMock; + protected $shipmentFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -56,9 +54,9 @@ class ShipmentLoaderTest extends \PHPUnit_Framework_TestCase public function setUp() { - $this->shipmentFactoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\ShipmentFactory') + $this->shipmentRepositoryMock = $this->getMockBuilder('Magento\Sales\Model\Order\ShipmentRepository') ->disableOriginalConstructor() - ->setMethods(['create']) + ->setMethods(['get']) ->getMock(); $this->registryMock = $this->getMockBuilder('Magento\Framework\Registry') ->disableOriginalConstructor() @@ -68,7 +66,7 @@ public function setUp() ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); - $this->orderServiceFactoryMock = $this->getMockBuilder('Magento\Sales\Model\Service\OrderFactory') + $this->shipmentFactory = $this->getMockBuilder('Magento\Sales\Model\Order\ShipmentFactory') ->disableOriginalConstructor() ->setMethods(['create']) ->getMock(); @@ -94,9 +92,9 @@ public function setUp() $this->loader = new \Magento\Shipping\Controller\Adminhtml\Order\ShipmentLoader( $this->messageManagerMock, $this->registryMock, - $this->shipmentFactoryMock, + $this->shipmentRepositoryMock, $this->orderFactoryMock, - $this->orderServiceFactoryMock, + $this->shipmentFactory, $this->trackFactoryMock, $data ); @@ -108,13 +106,10 @@ public function testLoadShipmentId() ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->shipmentFactoryMock->expects($this->once()) - ->method('create') - ->will($this->returnValue($shipmentModelMock)); - $shipmentModelMock->expects($this->once()) - ->method('load') + $this->shipmentRepositoryMock->expects($this->once()) + ->method('get') ->with($this->loader->getShipmentId()) - ->will($this->returnSelf()); + ->willReturn($shipmentModelMock); $this->registryMock->expects($this->once()) ->method('register') ->with('current_shipment', $shipmentModelMock); @@ -144,22 +139,14 @@ public function testLoadOrderId() $orderMock->expects($this->once()) ->method('canShip') ->will($this->returnValue(true)); - $orderServiceMock = $this->getMockBuilder('Magento\Sales\Model\Service\Order') - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); $shipmentModelMock = $this->getMockBuilder('Magento\Sales\Model\Order\Shipment') ->disableOriginalConstructor() ->setMethods([]) ->getMock(); - $this->orderServiceFactoryMock->expects($this->once()) + $this->shipmentFactory->expects($this->once()) ->method('create') - ->with(['order' => $orderMock]) - ->will($this->returnValue($orderServiceMock)); - $orderServiceMock->expects($this->once()) - ->method('prepareShipment') - ->with($this->loader->getShipment()['items']) - ->will($this->returnValue($shipmentModelMock)); + ->with($orderMock, $this->loader->getShipment()['items']) + ->willReturn($shipmentModelMock); $trackMock = $this->getMockBuilder('Magento\Sales\Model\Order\Shipment\Track') ->disableOriginalConstructor() ->setMethods([]) diff --git a/app/code/Magento/Shipping/Test/Unit/Model/Order/TrackTest.php b/app/code/Magento/Shipping/Test/Unit/Model/Order/TrackTest.php index 546912ee8a9e7..afe1842c3f34b 100644 --- a/app/code/Magento/Shipping/Test/Unit/Model/Order/TrackTest.php +++ b/app/code/Magento/Shipping/Test/Unit/Model/Order/TrackTest.php @@ -32,26 +32,25 @@ public function testLookup() $shipment = $this->getMock( 'Magento\OfflineShipping\Model\Carrier\Freeshipping', - ['load'], + [], [], '', false ); - $shipment->expects($this->any())->method('load')->will($this->returnValue($shipment)); - $shipmentFactory = $this->getMock( - '\Magento\Sales\Model\Order\ShipmentFactory', - ['create'], + $shipmentRepository = $this->getMock( + 'Magento\Sales\Model\Order\ShipmentRepository', + ['get'], [], '', false ); - $shipmentFactory->expects($this->any())->method('create')->will($this->returnValue($shipment)); + $shipmentRepository->expects($this->any())->method('get')->willReturn($shipment); /** @var \Magento\Shipping\Model\Order\Track $model */ $model = $helper->getObject( 'Magento\Shipping\Model\Order\Track', - ['carrierFactory' => $carrierFactory, 'shipmentFactory' => $shipmentFactory] + ['carrierFactory' => $carrierFactory, 'shipmentRepository' => $shipmentRepository] ); $this->assertEquals('trackingInfo', $model->getNumberDetail()); diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php index 7f94bd5c989c0..fd420b3e8496b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoCancelTest.php @@ -23,6 +23,7 @@ class CreditmemoCancelTest extends WebapiAbstract */ public function testCreditmemoCancel() { + $this->markTestSkipped('You can not cancel Credit Memo'); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Sales\Model\Resource\Order\Creditmemo\Collection $creditmemoCollection */ diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php index a605c5191da5e..10c64693ecd85 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditmemoEmailTest.php @@ -30,8 +30,8 @@ public function testCreditmemoEmail() $creditmemo = $creditmemoCollection->getFirstItem(); $serviceInfo = [ 'rest' => [ - 'resourcePath' => '/V1/creditmemo/' . $creditmemo->getId(), - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_PUT, + 'resourcePath' => '/V1/creditmemo/' . $creditmemo->getId() . '/emails', + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, ], 'soap' => [ 'service' => self::SERVICE_NAME, diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php index 9671029364b2c..6adfff3a65a3c 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/OrderCreateTest.php @@ -36,8 +36,8 @@ protected function prepareOrder() $orderItemFactory = $this->objectManager->get('Magento\Sales\Model\Order\ItemFactory'); /** @var \Magento\Sales\Api\Data\OrderPaymentFactory $orderPaymentFactory */ $orderPaymentFactory = $this->objectManager->get('Magento\Sales\Model\Order\PaymentFactory'); - /** @var \Magento\Sales\Api\Data\OrderAddressFactory $orderAddressFactory */ - $orderAddressFactory = $this->objectManager->get('Magento\Sales\Model\Order\AddressFactory'); + /** @var \Magento\Sales\Model\Order\AddressRepository $orderAddressRepository */ + $orderAddressRepository = $this->objectManager->get('Magento\Sales\Model\Order\AddressRepository'); $order = $orderFactory->create( ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderInterface')] @@ -48,9 +48,6 @@ protected function prepareOrder() $orderPayment = $orderPaymentFactory->create( ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderPaymentInterface')] ); - $orderAddressBilling = $orderAddressFactory->create( - ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderAddressInterface')] - ); $email = uniqid() . 'email@example.com'; $orderItem->setSku('sku#1'); @@ -69,6 +66,9 @@ protected function prepareOrder() $order->setGrandTotal(100); $order->setItems([$orderItem->getData()]); $order->setPayments([$orderPayment->getData()]); + + $orderAddressBilling = $orderAddressRepository->create(); + $orderAddressBilling->setCity('City'); $orderAddressBilling->setPostcode('12345'); $orderAddressBilling->setLastname('Last Name'); @@ -78,9 +78,8 @@ protected function prepareOrder() $orderAddressBilling->setCountryId(1); $orderAddressBilling->setAddressType('billing'); - $orderAddressShipping = $orderAddressFactory->create( - ['data' => $this->getDataStructure('Magento\Sales\Api\Data\OrderAddressInterface')] - ); + $orderAddressShipping = $orderAddressRepository->create(); + $orderAddressShipping->setCity('City'); $orderAddressShipping->setPostcode('12345'); $orderAddressShipping->setLastname('Last Name'); diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php index cbba01c42b788..2081f0502ff73 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/TransactionTest.php @@ -50,12 +50,17 @@ public function testTransactionGet() { /** @var Order $order */ $order = $this->objectManager->create('Magento\Sales\Model\Order'); + /** + * @var $transactionRepository \Magento\Sales\Model\Order\Payment\Transaction\Repository + */ + $transactionRepository = 'Magento\Sales\Model\Order\Payment\Transaction\Repository'; + $transactionRepository = $this->objectManager->create($transactionRepository); $order->loadByIncrementId('100000006'); /** @var Payment $payment */ $payment = $order->getPayment(); /** @var Transaction $transaction */ - $transaction = $payment->getTransaction('trx_auth'); + $transaction = $transactionRepository->getByTransactionId('trx_auth', $payment->getId(), $order->getId()); $childTransactions = $transaction->getChildTransactions(); $childTransaction = reset($childTransactions); @@ -89,12 +94,17 @@ public function testTransactionList($filters) { /** @var Order $order */ $order = $this->objectManager->create('Magento\Sales\Model\Order'); + /** + * @var $transactionRepository \Magento\Sales\Model\Order\Payment\Transaction\Repository + */ + $transactionRepository = 'Magento\Sales\Model\Order\Payment\Transaction\Repository'; + $transactionRepository = $this->objectManager->create($transactionRepository); $order->loadByIncrementId('100000006'); /** @var Payment $payment */ $payment = $order->getPayment(); /** @var Transaction $transaction */ - $transaction = $payment->getTransaction('trx_auth'); + $transaction = $transactionRepository->getByTransactionId('trx_auth', $payment->getId(), $order->getId()); $childTransactions = $transaction->getChildTransactions(); diff --git a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php index 74bf7687e0e9e..44decd293a134 100644 --- a/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Webapi/JoinDirectivesTest.php @@ -85,6 +85,9 @@ public function testGetList() */ public function testAutoGeneratedGetList() { + $this->markTestSkipped( + 'Invoice repository is not autogenerated anymore and does not have joined extension attributes' + ); $this->getExpectedExtensionAttributes(); /** @var SortOrder $sortOrder */ $sortOrder = $this->sortOrderBuilder->setField('store_id')->setDirection(SortOrder::SORT_ASC)->create(); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php index 7210b415ac2c9..b81c11211dbbe 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Api/ExtensionAttribute/JoinProcessorTest.php @@ -383,6 +383,9 @@ public function testGetListWithFilterByComplexDummyAttributeWithSetterMapping() */ public function testGetListWithExtensionAttributesAutoGeneratedRepository() { + $this->markTestSkipped( + 'Invoice repository is not autogenerated anymore and does not have joined extension attributes' + ); $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $searchCriteriaBuilder = $objectManager->create('Magento\Framework\Api\SearchCriteriaBuilder'); /** @var \Magento\Sales\Api\InvoiceRepositoryInterface $invoiceRepository */ diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Payment/TransactionTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Payment/TransactionTest.php index 33dd1245ea0dc..132ddedcf2a96 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Payment/TransactionTest.php +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Payment/TransactionTest.php @@ -18,14 +18,24 @@ public function testLoadByTxnId() $order = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Sales\Model\Order'); $order->loadByIncrementId('100000001'); - $model = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( - 'Magento\Sales\Model\Order\Payment\Transaction' + /** + * @var $repository \Magento\Sales\Model\Order\Payment\Transaction\Repository + */ + $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + 'Magento\Sales\Model\Order\Payment\Transaction\Repository' + ); + /** + * @var $model \Magento\Sales\Model\Order\Payment\Transaction + */ + $model = $repository->getByTransactionId( + 'invalid_transaction_id', + $order->getPayment()->getId(), + $order->getId() ); - $model->setOrderPaymentObject($order->getPayment())->loadByTxnId('invalid_transaction_id'); - $this->assertNull($model->getId()); + $this->assertFalse($model); - $model->loadByTxnId('trx1'); - $this->assertNotNull($model->getId()); + $model = $repository->getByTransactionId('trx1', $order->getPayment()->getId(), $order->getId()); + $this->assertNotFalse($model->getId()); } } diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php index 9c7a95bf6da27..e937301b02bc7 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_for_get.php @@ -12,9 +12,9 @@ $order = $objectManager->create('Magento\Sales\Model\Order'); $order->loadByIncrementId('100000001'); -/** @var Magento\Sales\Model\Service\Order $service */ -$service = $objectManager->get('Magento\Sales\Model\Service\Order'); -$creditmemo = $service->prepareCreditmemo($order->getData()); +/** @var \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory */ +$creditmemoFactory = $objectManager->get('Magento\Sales\Model\Order\CreditmemoFactory'); +$creditmemo = $creditmemoFactory->createByOrder($order, $order->getData()); $creditmemo->setOrder($order); $creditmemo->setState(Magento\Sales\Model\Order\Creditmemo::STATE_OPEN); $creditmemo->setIncrementId('100000001'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_list.php b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_list.php index 76a98798e5828..9ff83b98fb805 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_list.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/creditmemo_with_list.php @@ -13,9 +13,9 @@ $order = $orderCollection->getFirstItem(); $creditmemoItemFactory = $objectManager->create('Magento\Sales\Model\Order\Creditmemo\ItemFactory'); -/** @var Magento\Sales\Model\Service\Order $service */ -$service = $objectManager->get('Magento\Sales\Model\Service\Order'); -$creditmemo = $service->prepareCreditmemo($order->getData()); +/** @var \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory */ +$creditmemoFactory = $objectManager->get('Magento\Sales\Model\Order\CreditmemoFactory'); +$creditmemo = $creditmemoFactory->createByOrder($order, $order->getData()); $creditmemo->setOrder($order); $creditmemo->setState(Magento\Sales\Model\Order\Creditmemo::STATE_OPEN); foreach ($order->getItems() as $item) { diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice.php b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice.php index b23b4a5b7e583..c67acd1387924 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice.php @@ -11,11 +11,11 @@ /** @var \Magento\Sales\Model\Order $order */ $orderService = \Magento\TestFramework\ObjectManager::getInstance()->create( - 'Magento\Sales\Model\Service\Order', - ['order' => $order] + 'Magento\Sales\Api\InvoiceManagementInterface' ); -$invoice = $orderService->prepareInvoice(); +$invoice = $orderService->prepareInvoice($order->getEntityId()); $invoice->register(); +$order = $invoice->getOrder(); $order->setIsInProcess(true); $transactionSave = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Framework\DB\Transaction'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_fixture_store_order.php b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_fixture_store_order.php index dabd96f2011c0..9825a310bf8f3 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_fixture_store_order.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_fixture_store_order.php @@ -10,11 +10,11 @@ /** @var \Magento\Sales\Model\Order $order */ $orderService = \Magento\TestFramework\ObjectManager::getInstance()->create( - 'Magento\Sales\Model\Service\Order', - ['order' => $order] + 'Magento\Sales\Api\InvoiceManagementInterface' ); -$invoice = $orderService->prepareInvoice(); +$invoice = $orderService->prepareInvoice($order->getEntityId()); $invoice->register(); +$order = $invoice->getOrder(); $order->setIsInProcess(true); $transactionSave = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Framework\DB\Transaction'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_payflowpro.php b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_payflowpro.php index c8a9607ac8cf3..649724b9d3f0c 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_payflowpro.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/invoice_payflowpro.php @@ -10,12 +10,12 @@ /** @var \Magento\Sales\Model\Order $order */ $orderService = \Magento\TestFramework\ObjectManager::getInstance()->create( - 'Magento\Sales\Model\Service\Order', - ['order' => $order] + 'Magento\Sales\Api\InvoiceManagementInterface' ); -$invoice = $orderService->prepareInvoice(); +$invoice = $orderService->prepareInvoice($order->getEntityId()); /** To allow invoice cancelling it should be created without capturing. */ $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::NOT_CAPTURE)->register(); +$order = $invoice->getOrder(); $order->setIsInProcess(true); $transactionSave = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->create('Magento\Framework\DB\Transaction'); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/order_info.php b/dev/tests/integration/testsuite/Magento/Sales/_files/order_info.php index b38b7c4f54d79..a5112056824d6 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/order_info.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/order_info.php @@ -71,30 +71,22 @@ /** @var $item \Magento\Sales\Model\Order\Item */ $item = $order->getAllItems()[0]; -/** @var \Magento\Sales\Model\Service\Order $orderService */ -$orderService = $objectManager->create('Magento\Sales\Model\Service\Order', ['order' => $order]); +/** @var \Magento\Sales\Model\Order\InvoiceFactory $invoiceFactory */ +$invoiceFactory = $objectManager->get('Magento\Sales\Api\InvoiceManagementInterface'); /** @var $invoice \Magento\Sales\Model\Order\Invoice */ -$invoice = $orderService->prepareInvoice([$item->getId() => 10]); +$invoice = $invoiceFactory->prepareInvoice($order->getId(), [$item->getId() => 10]); $invoice->register(); $invoice->save(); -$creditmemo = $orderService->prepareInvoiceCreditmemo($invoice, ['qtys' => [$item->getId() => 5]]); +/** @var \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory */ +$creditmemoFactory = $objectManager->get('Magento\Sales\Model\Order\CreditmemoFactory'); +$creditmemo = $creditmemoFactory->createByInvoice($invoice, ['qtys' => [$item->getId() => 5]]); foreach ($creditmemo->getAllItems() as $creditmemoItem) { //Workaround to return items to stock $creditmemoItem->setBackToStock(true); } -$creditmemo->register(); -$creditmemo->save(); - -/** @var \Magento\Framework\DB\Transaction $transactionSave */ -$transactionSave = $objectManager->create('Magento\Framework\DB\Transaction') - ->addObject($creditmemo) - ->addObject($creditmemo->getOrder()); -if ($creditmemo->getInvoice()) { - $transactionSave->addObject($creditmemo->getInvoice()); -} - -$transactionSave->save(); +$creditmemoManagement = $objectManager->create('Magento\Sales\Api\CreditmemoManagementInterface'); +$creditmemoManagement->refund($creditmemo); diff --git a/dev/tests/integration/testsuite/Magento/Sales/_files/transactions_detailed.php b/dev/tests/integration/testsuite/Magento/Sales/_files/transactions_detailed.php index 2d6ed7cbf4c42..881014c173fab 100644 --- a/dev/tests/integration/testsuite/Magento/Sales/_files/transactions_detailed.php +++ b/dev/tests/integration/testsuite/Magento/Sales/_files/transactions_detailed.php @@ -19,6 +19,8 @@ $payment->setTransactionAdditionalInfo('auth_key', 'data'); $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH); +$payment->resetTransactionAdditionalInfo(); + $payment->setTransactionId('trx_capture'); $payment->setIsTransactionClosed(false); $payment->setTransactionAdditionalInfo('capture_key', 'data'); diff --git a/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php b/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php index 482f4580c5b96..b242bb0ef8464 100644 --- a/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php +++ b/dev/tests/integration/testsuite/Magento/Shipping/Helper/DataTest.php @@ -35,8 +35,8 @@ public function testGetTrackingPopupUrlBySalesModel($modelName, $getIdMethod, $e $orderFactory = $this->_getMockOrderFactory($code); $constructArgs['orderFactory'] = $orderFactory; } elseif ('Magento\Sales\Model\Order\Shipment\Track' == $modelName) { - $shipmentFactory = $this->_getMockShipmentFactory($code); - $constructArgs['shipmentFactory'] = $shipmentFactory; + $shipmentRepository = $this->_getMockShipmentRepository($code); + $constructArgs['shipmentRepository'] = $shipmentRepository; } $model = $objectManager->create($modelName, $constructArgs); @@ -66,24 +66,24 @@ protected function _getMockOrderFactory($code) /** * @param $code - * @return \PHPUnit_Framework_MockObject_MockObject + * @return \Magento\Sales\Model\Order\ShipmentRepository|\PHPUnit_Framework_MockObject_MockObject */ - protected function _getMockShipmentFactory($code) + protected function _getMockShipmentRepository($code) { $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); $orderFactory = $this->_getMockOrderFactory($code); $shipmentArgs = ['orderFactory' => $orderFactory]; $shipment = $objectManager->create('Magento\Sales\Model\Order\Shipment', $shipmentArgs); - $shipmentFactory = $this->getMock( - 'Magento\Sales\Model\Order\ShipmentFactory', - ['create'], + $shipmentRepository = $this->getMock( + 'Magento\Sales\Model\Order\ShipmentRepository', + ['get'], [], '', false ); - $shipmentFactory->expects($this->atLeastOnce())->method('create')->will($this->returnValue($shipment)); - return $shipmentFactory; + $shipmentRepository->expects($this->atLeastOnce())->method('get')->willReturn($shipment); + return $shipmentRepository; } /** diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php index f94f03c2ff826..243f3978c52db 100644 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_methods.php @@ -2401,4 +2401,7 @@ ['getStoreCodeFromCookie', '\Magento\Store\Model\Store'], ['deleteCookie', '\Magento\Store\Model\Store'], ['setCookie', '\Magento\Store\Model\Store'], + ['prepareShipment', 'Magento\Sales\Model\Order'], + ['prepareShipment', 'Magento\Sales\Model\Service\Order'], + ['prepareInvoice', 'Magento\Sales\Model\Service\Order'], ];