RefundOperationTest.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Sales\Test\Unit\Model\Order\Creditmemo;
  7. use Magento\Sales\Model\Order\Creditmemo;
  8. /**
  9. * Unit test for refund operation.
  10. */
  11. class RefundOperationTest extends \PHPUnit\Framework\TestCase
  12. {
  13. /**
  14. * @var \Magento\Sales\Model\Order\Creditmemo\RefundOperation
  15. */
  16. private $subject;
  17. /**
  18. * @var \Magento\Sales\Api\Data\OrderInterface|\PHPUnit_Framework_MockObject_MockObject
  19. */
  20. private $orderMock;
  21. /**
  22. * @var \Magento\Sales\Api\Data\CreditmemoInterface|\PHPUnit_Framework_MockObject_MockObject
  23. */
  24. private $creditmemoMock;
  25. /**
  26. * @var \Magento\Sales\Api\Data\OrderPaymentInterface|\PHPUnit_Framework_MockObject_MockObject
  27. */
  28. private $paymentMock;
  29. /**
  30. * @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
  31. */
  32. private $priceCurrencyMock;
  33. /**
  34. * @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject
  35. */
  36. private $eventManagerMock;
  37. protected function setUp()
  38. {
  39. $this->orderMock = $this->getMockBuilder(\Magento\Sales\Api\Data\OrderInterface::class)
  40. ->disableOriginalConstructor()
  41. ->getMockForAbstractClass();
  42. $this->creditmemoMock = $this->getMockBuilder(\Magento\Sales\Api\Data\CreditmemoInterface::class)
  43. ->disableOriginalConstructor()
  44. ->setMethods(['getBaseCost', 'setDoTransaction', 'getPaymentRefundDisallowed'])
  45. ->getMockForAbstractClass();
  46. $this->paymentMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
  47. ->disableOriginalConstructor()
  48. ->setMethods(['refund'])
  49. ->getMockForAbstractClass();
  50. $this->priceCurrencyMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
  51. ->disableOriginalConstructor()
  52. ->setMethods(['round'])
  53. ->getMockForAbstractClass();
  54. $contextMock = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
  55. ->disableOriginalConstructor()
  56. ->setMethods(['getEventDispatcher'])
  57. ->getMock();
  58. $this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
  59. ->disableOriginalConstructor()
  60. ->getMock();
  61. $contextMock->expects($this->once())
  62. ->method('getEventDispatcher')
  63. ->willReturn($this->eventManagerMock);
  64. $this->subject = new \Magento\Sales\Model\Order\Creditmemo\RefundOperation(
  65. $contextMock,
  66. $this->priceCurrencyMock
  67. );
  68. }
  69. /**
  70. * @param string $state
  71. * @dataProvider executeNotRefundedCreditmemoDataProvider
  72. */
  73. public function testExecuteNotRefundedCreditmemo($state)
  74. {
  75. $this->creditmemoMock->expects($this->once())
  76. ->method('getState')
  77. ->willReturn($state);
  78. $this->orderMock->expects($this->never())
  79. ->method('getEntityId');
  80. $this->assertEquals(
  81. $this->orderMock,
  82. $this->subject->execute(
  83. $this->creditmemoMock,
  84. $this->orderMock
  85. )
  86. );
  87. }
  88. /**
  89. * Data provider for testExecuteNotRefundedCreditmemo
  90. * @return array
  91. */
  92. public function executeNotRefundedCreditmemoDataProvider()
  93. {
  94. return [
  95. [Creditmemo::STATE_OPEN],
  96. [Creditmemo::STATE_CANCELED],
  97. ];
  98. }
  99. public function testExecuteWithWrongOrder()
  100. {
  101. $creditmemoOrderId = 1;
  102. $orderId = 2;
  103. $this->creditmemoMock->expects($this->once())
  104. ->method('getState')
  105. ->willReturn(Creditmemo::STATE_REFUNDED);
  106. $this->creditmemoMock->expects($this->once())
  107. ->method('getOrderId')
  108. ->willReturn($creditmemoOrderId);
  109. $this->orderMock->expects($this->once())
  110. ->method('getEntityId')
  111. ->willReturn($orderId);
  112. $this->orderMock->expects($this->never())
  113. ->method('setTotalRefunded');
  114. $this->assertEquals(
  115. $this->orderMock,
  116. $this->subject->execute($this->creditmemoMock, $this->orderMock)
  117. );
  118. }
  119. /**
  120. * @param array $amounts
  121. * @dataProvider baseAmountsDataProvider
  122. */
  123. public function testExecuteOffline($amounts)
  124. {
  125. $orderId = 1;
  126. $online = false;
  127. $this->creditmemoMock->expects($this->once())
  128. ->method('getState')
  129. ->willReturn(Creditmemo::STATE_REFUNDED);
  130. $this->creditmemoMock->expects($this->once())
  131. ->method('getOrderId')
  132. ->willReturn($orderId);
  133. $this->orderMock->expects($this->once())
  134. ->method('getEntityId')
  135. ->willReturn($orderId);
  136. $this->registerItems();
  137. $this->priceCurrencyMock->expects($this->any())
  138. ->method('round')
  139. ->willReturnArgument(0);
  140. $this->setBaseAmounts($amounts);
  141. $this->orderMock->expects($this->once())
  142. ->method('setTotalOfflineRefunded')
  143. ->with(2);
  144. $this->orderMock->expects($this->once())
  145. ->method('getTotalOfflineRefunded')
  146. ->willReturn(0);
  147. $this->orderMock->expects($this->once())
  148. ->method('setBaseTotalOfflineRefunded')
  149. ->with(1);
  150. $this->orderMock->expects($this->once())
  151. ->method('getBaseTotalOfflineRefunded')
  152. ->willReturn(0);
  153. $this->orderMock->expects($this->never())
  154. ->method('setTotalOnlineRefunded');
  155. $this->orderMock->expects($this->once())
  156. ->method('getPayment')
  157. ->willReturn($this->paymentMock);
  158. $this->paymentMock->expects($this->once())
  159. ->method('refund')
  160. ->with($this->creditmemoMock);
  161. $this->creditmemoMock->expects($this->once())
  162. ->method('setDoTransaction')
  163. ->with($online);
  164. $this->eventManagerMock->expects($this->once())
  165. ->method('dispatch')
  166. ->with(
  167. 'sales_order_creditmemo_refund',
  168. ['creditmemo' => $this->creditmemoMock]
  169. );
  170. $this->assertEquals(
  171. $this->orderMock,
  172. $this->subject->execute($this->creditmemoMock, $this->orderMock, $online)
  173. );
  174. }
  175. /**
  176. * @param array $amounts
  177. * @dataProvider baseAmountsDataProvider
  178. */
  179. public function testExecuteOnline($amounts)
  180. {
  181. $orderId = 1;
  182. $online = true;
  183. $this->creditmemoMock->expects($this->once())
  184. ->method('getState')
  185. ->willReturn(Creditmemo::STATE_REFUNDED);
  186. $this->creditmemoMock->expects($this->once())
  187. ->method('getOrderId')
  188. ->willReturn($orderId);
  189. $this->orderMock->expects($this->once())
  190. ->method('getEntityId')
  191. ->willReturn($orderId);
  192. $this->registerItems();
  193. $this->priceCurrencyMock->expects($this->any())
  194. ->method('round')
  195. ->willReturnArgument(0);
  196. $this->setBaseAmounts($amounts);
  197. $this->orderMock->expects($this->once())
  198. ->method('setTotalOnlineRefunded')
  199. ->with(2);
  200. $this->orderMock->expects($this->once())
  201. ->method('getTotalOnlineRefunded')
  202. ->willReturn(0);
  203. $this->orderMock->expects($this->once())
  204. ->method('setBaseTotalOnlineRefunded')
  205. ->with(1);
  206. $this->orderMock->expects($this->once())
  207. ->method('getBaseTotalOnlineRefunded')
  208. ->willReturn(0);
  209. $this->orderMock->expects($this->never())
  210. ->method('setTotalOfflineRefunded');
  211. $this->creditmemoMock->expects($this->once())
  212. ->method('setDoTransaction')
  213. ->with($online);
  214. $this->orderMock->expects($this->once())
  215. ->method('getPayment')
  216. ->willReturn($this->paymentMock);
  217. $this->paymentMock->expects($this->once())
  218. ->method('refund')
  219. ->with($this->creditmemoMock);
  220. $this->assertEquals(
  221. $this->orderMock,
  222. $this->subject->execute($this->creditmemoMock, $this->orderMock, $online)
  223. );
  224. }
  225. /**
  226. * @return array
  227. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  228. */
  229. public function baseAmountsDataProvider()
  230. {
  231. return [
  232. [[
  233. 'setBaseTotalRefunded' => [
  234. 'result' => 2,
  235. 'order' => ['method' => 'getBaseTotalRefunded', 'amount' => 1],
  236. 'creditmemo' => ['method' => 'getBaseGrandTotal', 'amount' => 1],
  237. ],
  238. 'setTotalRefunded' => [
  239. 'result' => 4,
  240. 'order' => ['method' => 'getTotalRefunded', 'amount' => 2],
  241. 'creditmemo' => ['method' => 'getGrandTotal', 'amount' => 2],
  242. ],
  243. 'setBaseSubtotalRefunded' => [
  244. 'result' => 6,
  245. 'order' => ['method' => 'getBaseSubtotalRefunded', 'amount' => 3],
  246. 'creditmemo' => ['method' => 'getBaseSubtotal', 'amount' => 3],
  247. ],
  248. 'setSubtotalRefunded' => [
  249. 'result' => 6,
  250. 'order' => ['method' => 'getSubtotalRefunded', 'amount' => 3],
  251. 'creditmemo' => ['method' => 'getSubtotal', 'amount' => 3],
  252. ],
  253. 'setBaseTaxRefunded' => [
  254. 'result' => 8,
  255. 'order' => ['method' => 'getBaseTaxRefunded', 'amount' => 4],
  256. 'creditmemo' => ['method' => 'getBaseTaxAmount', 'amount' => 4],
  257. ],
  258. 'setTaxRefunded' => [
  259. 'result' => 10,
  260. 'order' => ['method' => 'getTaxRefunded', 'amount' => 5],
  261. 'creditmemo' => ['method' => 'getTaxAmount', 'amount' => 5],
  262. ],
  263. 'setBaseDiscountTaxCompensationRefunded' => [
  264. 'result' => 12,
  265. 'order' => ['method' => 'getBaseDiscountTaxCompensationRefunded', 'amount' => 6],
  266. 'creditmemo' => ['method' => 'getBaseDiscountTaxCompensationAmount', 'amount' => 6],
  267. ],
  268. 'setDiscountTaxCompensationRefunded' => [
  269. 'result' => 14,
  270. 'order' => ['method' => 'getDiscountTaxCompensationRefunded', 'amount' => 7],
  271. 'creditmemo' => ['method' => 'getDiscountTaxCompensationAmount', 'amount' => 7],
  272. ],
  273. 'setBaseShippingRefunded' => [
  274. 'result' => 16,
  275. 'order' => ['method' => 'getBaseShippingRefunded', 'amount' => 8],
  276. 'creditmemo' => ['method' => 'getBaseShippingAmount', 'amount' => 8],
  277. ],
  278. 'setShippingRefunded' => [
  279. 'result' => 18,
  280. 'order' => ['method' => 'getShippingRefunded', 'amount' => 9],
  281. 'creditmemo' => ['method' => 'getShippingAmount', 'amount' => 9],
  282. ],
  283. 'setBaseShippingTaxRefunded' => [
  284. 'result' => 20,
  285. 'order' => ['method' => 'getBaseShippingTaxRefunded', 'amount' => 10],
  286. 'creditmemo' => ['method' => 'getBaseShippingTaxAmount', 'amount' => 10],
  287. ],
  288. 'setShippingTaxRefunded' => [
  289. 'result' => 22,
  290. 'order' => ['method' => 'getShippingTaxRefunded', 'amount' => 11],
  291. 'creditmemo' => ['method' => 'getShippingTaxAmount', 'amount' => 11],
  292. ],
  293. 'setAdjustmentPositive' => [
  294. 'result' => 24,
  295. 'order' => ['method' => 'getAdjustmentPositive', 'amount' => 12],
  296. 'creditmemo' => ['method' => 'getAdjustmentPositive', 'amount' => 12],
  297. ],
  298. 'setBaseAdjustmentPositive' => [
  299. 'result' => 26,
  300. 'order' => ['method' => 'getBaseAdjustmentPositive', 'amount' => 13],
  301. 'creditmemo' => ['method' => 'getBaseAdjustmentPositive', 'amount' => 13],
  302. ],
  303. 'setAdjustmentNegative' => [
  304. 'result' => 28,
  305. 'order' => ['method' => 'getAdjustmentNegative', 'amount' => 14],
  306. 'creditmemo' => ['method' => 'getAdjustmentNegative', 'amount' => 14],
  307. ],
  308. 'setBaseAdjustmentNegative' => [
  309. 'result' => 30,
  310. 'order' => ['method' => 'getBaseAdjustmentNegative', 'amount' => 15],
  311. 'creditmemo' => ['method' => 'getBaseAdjustmentNegative', 'amount' => 15],
  312. ],
  313. 'setDiscountRefunded' => [
  314. 'result' => 32,
  315. 'order' => ['method' => 'getDiscountRefunded', 'amount' => 16],
  316. 'creditmemo' => ['method' => 'getDiscountAmount', 'amount' => 16],
  317. ],
  318. 'setBaseDiscountRefunded' => [
  319. 'result' => 34,
  320. 'order' => ['method' => 'getBaseDiscountRefunded', 'amount' => 17],
  321. 'creditmemo' => ['method' => 'getBaseDiscountAmount', 'amount' => 17],
  322. ],
  323. 'setBaseTotalInvoicedCost' => [
  324. 'result' => 7,
  325. 'order' => ['method' => 'getBaseTotalInvoicedCost', 'amount' => 18],
  326. 'creditmemo' => ['method' => 'getBaseCost', 'amount' => 11],
  327. ],
  328. ]],
  329. ];
  330. }
  331. /**
  332. * @param $amounts
  333. */
  334. private function setBaseAmounts($amounts)
  335. {
  336. foreach ($amounts as $amountName => $summands) {
  337. $this->orderMock->expects($this->once())
  338. ->method($amountName)
  339. ->with($summands['result']);
  340. $this->orderMock->expects($this->once())
  341. ->method($summands['order']['method'])
  342. ->willReturn($summands['order']['amount']);
  343. $this->creditmemoMock->expects($this->any())
  344. ->method($summands['creditmemo']['method'])
  345. ->willReturn($summands['creditmemo']['amount']);
  346. }
  347. }
  348. private function registerItems()
  349. {
  350. $item1 = $this->getCreditmemoItemMock();
  351. $item1->expects($this->once())->method('isDeleted')->willReturn(true);
  352. $item1->expects($this->never())->method('setCreditMemo');
  353. $item2 = $this->getCreditmemoItemMock();
  354. $item2->expects($this->at(0))->method('isDeleted')->willReturn(false);
  355. $item2->expects($this->once())->method('setCreditMemo')->with($this->creditmemoMock);
  356. $item2->expects($this->once())->method('getQty')->willReturn(0);
  357. $item2->expects($this->at(3))->method('isDeleted')->with(true);
  358. $item2->expects($this->never())->method('register');
  359. $item3 = $this->getCreditmemoItemMock();
  360. $item3->expects($this->once())->method('isDeleted')->willReturn(false);
  361. $item3->expects($this->once())->method('setCreditMemo')->with($this->creditmemoMock);
  362. $item3->expects($this->once())->method('getQty')->willReturn(1);
  363. $item3->expects($this->once())->method('register');
  364. $this->creditmemoMock->expects($this->any())
  365. ->method('getItems')
  366. ->willReturn([$item1, $item2, $item3]);
  367. }
  368. /**
  369. * @return \PHPUnit_Framework_MockObject_MockObject
  370. */
  371. private function getCreditmemoItemMock()
  372. {
  373. return $this->getMockBuilder(\Magento\Sales\Api\Data\CreditmemoItemInterface::class)
  374. ->disableOriginalConstructor()
  375. ->setMethods(['isDeleted', 'setCreditMemo', 'getQty', 'register'])
  376. ->getMockForAbstractClass();
  377. }
  378. }