diff --git a/app/code/Magento/Sales/Api/InvoiceCancelInterface.php b/app/code/Magento/Sales/Api/InvoiceCancelInterface.php
new file mode 100644
index 0000000000000..56694f20b261f
--- /dev/null
+++ b/app/code/Magento/Sales/Api/InvoiceCancelInterface.php
@@ -0,0 +1,23 @@
+invoiceRepository = $invoiceRepository;
+ }
+
+ /**
+ * Cancel invoice
+ *
+ * @param int $invoiceId
+ * @return bool
+ */
+ public function cancel($invoiceId)
+ {
+ /** @var \Magento\Sales\Api\Data\InvoiceInterface $invoice */
+ $invoice = $this->invoiceRepository->get($invoiceId);
+ if ($invoice && $invoice->canCancel()) {
+ $invoice->cancel();
+ $this->invoiceRepository->save($invoice);
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/app/code/Magento/Sales/Test/Unit/Model/Service/InvoiceServiceTest.php b/app/code/Magento/Sales/Test/Unit/Model/Service/InvoiceServiceTest.php
index 30d26de5a06b1..b3aa4f1283aff 100644
--- a/app/code/Magento/Sales/Test/Unit/Model/Service/InvoiceServiceTest.php
+++ b/app/code/Magento/Sales/Test/Unit/Model/Service/InvoiceServiceTest.php
@@ -19,6 +19,13 @@ class InvoiceServiceTest extends \PHPUnit\Framework\TestCase
*/
protected $repositoryMock;
+ /**
+ * Invoice Cancel
+ *
+ * @var \Magento\Sales\Api\InvoiceCancelInterface|\PHPUnit_Framework_MockObject_MockObject
+ */
+ protected $invoiceCancelMock;
+
/**
* Repository
*
@@ -52,6 +59,11 @@ class InvoiceServiceTest extends \PHPUnit\Framework\TestCase
*/
protected $invoiceService;
+ /**
+ * @var \Magento\Sales\Model\Order\Invoice
+ */
+ protected $invoiceMock;
+
/**
* SetUp
*/
@@ -84,6 +96,16 @@ protected function setUp()
['notify']
);
+ $this->invoiceCancelMock = new \Magento\Sales\Model\Order\InvoiceCancel(
+ $this->repositoryMock
+ );
+
+ $this->invoiceMock = $this->getMockBuilder(
+ \Magento\Sales\Model\Order\Invoice::class
+ )
+ ->disableOriginalConstructor()
+ ->getMock();
+
$this->invoiceService = $objectManager->getObject(
\Magento\Sales\Model\Service\InvoiceService::class,
[
@@ -204,4 +226,40 @@ public function testSetVoid()
$this->assertTrue($this->invoiceService->setVoid($id));
}
+
+ /**
+ * Run test for Invoice::cancel()
+ */
+ public function testCancel()
+ {
+ $this->repositoryMock->expects($this->once())
+ ->method('get')
+ ->with(123)
+ ->willReturn($this->invoiceMock);
+ $this->invoiceMock->expects($this->once())
+ ->method('cancel')
+ ->willReturn($this->invoiceMock);
+ $this->invoiceMock->expects($this->once())
+ ->method('canCancel')
+ ->willReturn(true);
+ $this->assertTrue($this->invoiceCancelMock->cancel(123));
+ }
+
+ /**
+ * test for Invoice::cancel() fail case
+ */
+ public function testCancelFailed()
+ {
+ $this->repositoryMock->expects($this->once())
+ ->method('get')
+ ->with(123)
+ ->willReturn($this->invoiceMock);
+ $this->invoiceMock->expects($this->never())
+ ->method('cancel')
+ ->willReturn($this->invoiceMock);
+ $this->invoiceMock->expects($this->once())
+ ->method('canCancel')
+ ->willReturn(false);
+ $this->assertFalse($this->invoiceCancelMock->cancel(123));
+ }
}
diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml
index 9de3f238d6a39..5001e85856757 100644
--- a/app/code/Magento/Sales/etc/di.xml
+++ b/app/code/Magento/Sales/etc/di.xml
@@ -56,6 +56,7 @@
+
@@ -982,4 +983,4 @@
-
+
\ No newline at end of file
diff --git a/app/code/Magento/Sales/etc/webapi.xml b/app/code/Magento/Sales/etc/webapi.xml
index cee245e348393..cbb59f29c0645 100644
--- a/app/code/Magento/Sales/etc/webapi.xml
+++ b/app/code/Magento/Sales/etc/webapi.xml
@@ -139,6 +139,12 @@
+
+
+
+
+
+
@@ -277,4 +283,4 @@
-
+
\ No newline at end of file