diff --git a/app/code/Magento/AsynchronousOperations/Api/BulkStatusInterface.php b/app/code/Magento/AsynchronousOperations/Api/BulkStatusInterface.php new file mode 100644 index 00000000000..1c200f299f6 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Api/BulkStatusInterface.php @@ -0,0 +1,34 @@ +operationCollectionFactory = $operationCollection; $this->bulkCollectionFactory = $bulkCollection; $this->resourceConnection = $resourceConnection; $this->calculatedStatusSql = $calculatedStatusSql; $this->metadataPool = $metadataPool; + $this->bulkDetailedFactory = $bulkDetailedFactory; + $this->bulkShortFactory = $bulkShortFactory; + $this->entityManager = $entityManager; } /** @@ -73,12 +106,13 @@ public function getFailedOperationsByBulkId($bulkUuid, $failureType = null) ? [$failureType] : [ OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, - OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED + OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, ]; $operations = $this->operationCollectionFactory->create() ->addFieldToFilter('bulk_uuid', $bulkUuid) ->addFieldToFilter('status', $failureCodes) ->getItems(); + return $operations; } @@ -87,24 +121,10 @@ public function getFailedOperationsByBulkId($bulkUuid, $failureType = null) */ public function getOperationsCountByBulkIdAndStatus($bulkUuid, $status) { - if ($status === OperationInterface::STATUS_TYPE_OPEN) { - /** - * Total number of operations that has been scheduled within the given bulk - */ - $allOperationsQty = $this->getOperationCount($bulkUuid); - - /** - * Number of operations that has been processed (i.e. operations with any status but 'open') - */ - $allProcessedOperationsQty = (int)$this->operationCollectionFactory->create() - ->addFieldToFilter('bulk_uuid', $bulkUuid) - ->getSize(); - - return $allOperationsQty - $allProcessedOperationsQty; - } /** @var \Magento\AsynchronousOperations\Model\ResourceModel\Operation\Collection $collection */ $collection = $this->operationCollectionFactory->create(); + return $collection->addFieldToFilter('bulk_uuid', $bulkUuid) ->addFieldToFilter('status', $status) ->getSize(); @@ -123,11 +143,15 @@ public function getBulksByUser($userId) OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, BulkSummaryInterface::NOT_STARTED, OperationInterface::STATUS_TYPE_OPEN, - OperationInterface::STATUS_TYPE_COMPLETE + OperationInterface::STATUS_TYPE_COMPLETE, ]; $select = $collection->getSelect(); $select->columns(['status' => $this->calculatedStatusSql->get($operationTableName)]) - ->order(new \Zend_Db_Expr('FIELD(status, ' . implode(',', $statusesArray) . ')')); + ->order( + new \Zend_Db_Expr( + 'FIELD(status, ' . implode(',', $statusesArray) . ')' + ) + ); $collection->addFieldToFilter('user_id', $userId) ->addOrder('start_time'); @@ -163,11 +187,14 @@ public function getBulkStatus($bulkUuid) /** * Number of operations that has been completed successfully */ - $allCompleteOperationsQty = $this->operationCollectionFactory->create() - ->addFieldToFilter('bulk_uuid', $bulkUuid)->addFieldToFilter( + $allCompleteOperationsQty = $this->operationCollectionFactory + ->create() + ->addFieldToFilter('bulk_uuid', $bulkUuid) + ->addFieldToFilter( 'status', OperationInterface::STATUS_TYPE_COMPLETE - )->getSize(); + ) + ->getSize(); if ($allCompleteOperationsQty == $allOperationsQty) { return BulkSummaryInterface::FINISHED_SUCCESSFULLY; @@ -197,4 +224,51 @@ private function getOperationCount($bulkUuid) ->where('uuid = ?', $bulkUuid) ); } + + /** + * @inheritDoc + */ + public function getBulkDetailedStatus($bulkUuid) + { + $bulkSummary = $this->bulkDetailedFactory->create(); + + /** @var \Magento\AsynchronousOperations\Api\Data\DetailedBulkStatusInterface $bulk */ + $bulk = $this->entityManager->load($bulkSummary, $bulkUuid); + + if ($bulk->getBulkId() === null) { + throw new NoSuchEntityException( + __( + 'Bulk uuid %bulkUuid not exist', + ['bulkUuid' => $bulkUuid] + ) + ); + } + $operations = $this->operationCollectionFactory->create()->addFieldToFilter('bulk_uuid', $bulkUuid)->getItems(); + $bulk->setOperationsList($operations); + + return $bulk; + } + + /** + * @inheritDoc + */ + public function getBulkShortStatus($bulkUuid) + { + $bulkSummary = $this->bulkShortFactory->create(); + + /** @var \Magento\AsynchronousOperations\Api\Data\BulkStatusInterface $bulk */ + $bulk = $this->entityManager->load($bulkSummary, $bulkUuid); + if ($bulk->getBulkId() === null) { + throw new NoSuchEntityException( + __( + 'Bulk uuid %bulkUuid not exist', + ['bulkUuid' => $bulkUuid] + ) + ); + } + $operations = $this->operationCollectionFactory->create()->addFieldToFilter('bulk_uuid', $bulkUuid)->getItems(); + $bulk->setOperationsList($operations); + + return $bulk; + } } diff --git a/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Detailed.php b/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Detailed.php new file mode 100644 index 00000000000..8d5cf80e3f4 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Detailed.php @@ -0,0 +1,29 @@ +getData(self::OPERATIONS_LIST); + } + + /** + * @inheritDoc + */ + public function setOperationsList($operationStatusList) + { + return $this->setData(self::OPERATIONS_LIST, $operationStatusList); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Short.php b/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Short.php new file mode 100644 index 00000000000..a11dc493aee --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/BulkStatus/Short.php @@ -0,0 +1,29 @@ +getData(self::OPERATIONS_LIST); + } + + /** + * @inheritDoc + */ + public function setOperationsList($operationStatusList) + { + return $this->setData(self::OPERATIONS_LIST, $operationStatusList); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/Entity/BulkSummaryMapper.php b/app/code/Magento/AsynchronousOperations/Model/Entity/BulkSummaryMapper.php index 94ebbdca445..4abbde4c360 100644 --- a/app/code/Magento/AsynchronousOperations/Model/Entity/BulkSummaryMapper.php +++ b/app/code/Magento/AsynchronousOperations/Model/Entity/BulkSummaryMapper.php @@ -8,7 +8,6 @@ use Magento\Framework\EntityManager\MapperInterface; use Magento\Framework\App\ResourceConnection; use Magento\Framework\EntityManager\MetadataPool; -use Magento\AsynchronousOperations\Api\Data\BulkSummaryInterface; /** * @deprecated 100.2.0 diff --git a/app/code/Magento/AsynchronousOperations/Model/Operation.php b/app/code/Magento/AsynchronousOperations/Model/Operation.php index dbfce3ccd8b..31488c5d900 100644 --- a/app/code/Magento/AsynchronousOperations/Model/Operation.php +++ b/app/code/Magento/AsynchronousOperations/Model/Operation.php @@ -78,6 +78,22 @@ public function setSerializedData($serializedData) return $this->setData(self::SERIALIZED_DATA, $serializedData); } + /** + * @inheritDoc + */ + public function getResultSerializedData() + { + return $this->getData(self::RESULT_SERIALIZED_DATA); + } + + /** + * @inheritDoc + */ + public function setResultSerializedData($resultSerializedData) + { + return $this->setData(self::RESULT_SERIALIZED_DATA, $resultSerializedData); + } + /** * @inheritDoc */ diff --git a/app/code/Magento/AsynchronousOperations/Model/Operation/Details.php b/app/code/Magento/AsynchronousOperations/Model/Operation/Details.php index 398934f0933..d248f9c3e92 100644 --- a/app/code/Magento/AsynchronousOperations/Model/Operation/Details.php +++ b/app/code/Magento/AsynchronousOperations/Model/Operation/Details.php @@ -3,9 +3,11 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\AsynchronousOperations\Model\Operation; use Magento\Framework\Bulk\OperationInterface; +use Magento\Framework\Bulk\BulkStatusInterface; class Details { @@ -19,23 +21,36 @@ class Details */ private $bulkStatus; + /** + * @var null + */ + private $bulkUuid; + /** * Map between status codes and human readable indexes + * * @var array */ private $statusMap = [ - OperationInterface::STATUS_TYPE_COMPLETE => 'operations_successful', - OperationInterface::STATUS_TYPE_RETRIABLY_FAILED => 'failed_retriable', + OperationInterface::STATUS_TYPE_COMPLETE => 'operations_successful', + OperationInterface::STATUS_TYPE_RETRIABLY_FAILED => 'failed_retriable', OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED => 'failed_not_retriable', + OperationInterface::STATUS_TYPE_OPEN => 'open', + OperationInterface::STATUS_TYPE_REJECTED => 'rejected', ]; /** + * Init dependencies. + * * @param \Magento\Framework\Bulk\BulkStatusInterface $bulkStatus + * @param null $bulkUuid */ public function __construct( - \Magento\Framework\Bulk\BulkStatusInterface $bulkStatus + BulkStatusInterface $bulkStatus, + $bulkUuid = null ) { $this->bulkStatus = $bulkStatus; + $this->bulkUuid = $bulkUuid; } /** @@ -47,11 +62,12 @@ public function __construct( public function getDetails($bulkUuid) { $details = [ - 'operations_total' => 0, + 'operations_total' => 0, 'operations_successful' => 0, - 'operations_failed' => 0, - 'failed_retriable' => 0, - 'failed_not_retriable' => 0, + 'operations_failed' => 0, + 'failed_retriable' => 0, + 'failed_not_retriable' => 0, + 'rejected' => 0, ]; if (array_key_exists($bulkUuid, $this->operationCache)) { @@ -65,13 +81,84 @@ public function getDetails($bulkUuid) ); } - // total is sum of successful, retriable, not retriable and open operations - $details['operations_total'] = array_sum($details) + $this->bulkStatus->getOperationsCountByBulkIdAndStatus( - $bulkUuid, - OperationInterface::STATUS_TYPE_OPEN - ); + $details['operations_total'] = array_sum($details); $details['operations_failed'] = $details['failed_retriable'] + $details['failed_not_retriable']; $this->operationCache[$bulkUuid] = $details; + return $details; } + + /** + * @inheritDoc + */ + public function getOperationsTotal() + { + $this->getDetails($this->bulkUuid); + + return $this->operationCache[$this->bulkUuid]['operations_total']; + } + + /** + * @inheritDoc + */ + public function getOpen() + { + $this->getDetails($this->bulkUuid); + $statusKey = $this->statusMap[OperationInterface::STATUS_TYPE_OPEN]; + + return $this->operationCache[$this->bulkUuid][$statusKey]; + } + + /** + * @inheritDoc + */ + public function getOperationsSuccessful() + { + $this->getDetails($this->bulkUuid); + $statusKey = $this->statusMap[OperationInterface::STATUS_TYPE_COMPLETE]; + + return $this->operationCache[$this->bulkUuid][$statusKey]; + } + + /** + * @inheritDoc + */ + public function getTotalFailed() + { + $this->getDetails($this->bulkUuid); + + return $this->operationCache[$this->bulkUuid]['operations_failed']; + } + + /** + * @inheritDoc + */ + public function getFailedNotRetriable() + { + $statusKey = $this->statusMap[OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED]; + + return $this->operationCache[$this->bulkUuid][$statusKey]; + } + + /** + * @inheritDoc + */ + public function getFailedRetriable() + { + $this->getDetails($this->bulkUuid); + $statusKey = $this->statusMap[OperationInterface::STATUS_TYPE_RETRIABLY_FAILED]; + + return $this->operationCache[$this->bulkUuid][$statusKey]; + } + + /** + * @inheritDoc + */ + public function getRejected() + { + $this->getDetails($this->bulkUuid); + $statusKey = $this->statusMap[OperationInterface::STATUS_TYPE_REJECTED]; + + return $this->operationCache[$this->bulkUuid][$statusKey]; + } } diff --git a/app/code/Magento/AsynchronousOperations/Model/OperationStatus.php b/app/code/Magento/AsynchronousOperations/Model/OperationStatus.php new file mode 100644 index 00000000000..6af12b9ba25 --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/Model/OperationStatus.php @@ -0,0 +1,50 @@ +getData(OperationInterface::ID); + } + + /** + * @inheritDoc + */ + public function getStatus() + { + return $this->getData(OperationInterface::STATUS); + } + + /** + * @inheritDoc + */ + public function getResultMessage() + { + return $this->getData(OperationInterface::RESULT_MESSAGE); + } + + /** + * @inheritDoc + */ + public function getErrorCode() + { + return $this->getData(OperationInterface::ERROR_CODE); + } +} diff --git a/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php b/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php index 76c7820fa99..8457a641ed9 100644 --- a/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php +++ b/app/code/Magento/AsynchronousOperations/Model/ResourceModel/System/Message/Collection/Synchronized/Plugin.php @@ -143,7 +143,7 @@ private function getText($operationDetails) $summaryReport .= __( '%1 item(s) have been successfully updated.', $operationDetails['operations_successful'] - ) ; + ); } if ($operationDetails['operations_failed'] > 0) { diff --git a/app/code/Magento/AsynchronousOperations/Model/StatusMapper.php b/app/code/Magento/AsynchronousOperations/Model/StatusMapper.php index 3ad260cf26a..e5aee6d2f59 100644 --- a/app/code/Magento/AsynchronousOperations/Model/StatusMapper.php +++ b/app/code/Magento/AsynchronousOperations/Model/StatusMapper.php @@ -25,6 +25,7 @@ public function operationStatusToBulkSummaryStatus($operationStatus) $statusMapping = [ OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED => BulkSummaryInterface::FINISHED_WITH_FAILURE, OperationInterface::STATUS_TYPE_RETRIABLY_FAILED => BulkSummaryInterface::FINISHED_WITH_FAILURE, + OperationInterface::STATUS_TYPE_REJECTED => BulkSummaryInterface::FINISHED_WITH_FAILURE, OperationInterface::STATUS_TYPE_COMPLETE => BulkSummaryInterface::FINISHED_SUCCESSFULLY, OperationInterface::STATUS_TYPE_OPEN => BulkSummaryInterface::IN_PROGRESS, BulkSummaryInterface::NOT_STARTED => BulkSummaryInterface::NOT_STARTED @@ -47,7 +48,8 @@ public function bulkSummaryStatusToOperationStatus($bulkStatus) $statusMapping = [ BulkSummaryInterface::FINISHED_WITH_FAILURE => [ OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, - OperationInterface::STATUS_TYPE_RETRIABLY_FAILED + OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, + OperationInterface::STATUS_TYPE_REJECTED ], BulkSummaryInterface::FINISHED_SUCCESSFULLY => OperationInterface::STATUS_TYPE_COMPLETE, BulkSummaryInterface::IN_PROGRESS => OperationInterface::STATUS_TYPE_OPEN, diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/BulkStatusTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/BulkStatusTest.php index cda55161ab8..c32134fe295 100644 --- a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/BulkStatusTest.php +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/BulkStatusTest.php @@ -54,11 +54,26 @@ class BulkStatusTest extends \PHPUnit\Framework\TestCase */ private $metadataPoolMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $bulkDetailedFactory; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $bulkShortFactory; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ private $entityMetadataMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $entityManager; + /** * @var \PHPUnit_Framework_MockObject_MockObject */ @@ -81,6 +96,15 @@ protected function setUp() \Magento\AsynchronousOperations\Model\BulkStatus\CalculatedStatusSql::class ); $this->metadataPoolMock = $this->createMock(\Magento\Framework\EntityManager\MetadataPool::class); + $this->bulkDetailedFactory = $this->createPartialMock( + \Magento\AsynchronousOperations\Api\Data\DetailedBulkStatusInterfaceFactory ::class, + ['create'] + ); + $this->bulkShortFactory = $this->createPartialMock( + \Magento\AsynchronousOperations\Api\Data\BulkStatusInterfaceFactory::class, + ['create'] + ); + $this->entityManager = $this->createMock(\Magento\Framework\EntityManager\EntityManager::class); $this->entityMetadataMock = $this->createMock(\Magento\Framework\EntityManager\EntityMetadataInterface::class); $this->connectionMock = $this->createMock(\Magento\Framework\DB\Adapter\AdapterInterface::class); @@ -90,7 +114,10 @@ protected function setUp() $this->operationCollectionFactory, $this->resourceConnectionMock, $this->calculatedStatusSqlMock, - $this->metadataPoolMock + $this->metadataPoolMock, + $this->bulkDetailedFactory, + $this->bulkShortFactory, + $this->entityManager ); } @@ -151,12 +178,13 @@ public function getFailedOperationsByBulkIdDataProvider() { return [ [1, [1]], - [null, + [ + null, [ OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, - OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED - ] - ] + OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, + ], + ], ]; } diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/Operation/DetailsTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/Operation/DetailsTest.php index 7060a48e773..f62e2b7f9d5 100644 --- a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/Operation/DetailsTest.php +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/Operation/DetailsTest.php @@ -34,6 +34,7 @@ public function testGetDetails() $failedRetriable = 23; $failedNotRetriable = 45; $open = 303; + $rejected = 0; $expectedResult = [ 'operations_total' => $completed + $failedRetriable + $failedNotRetriable + $open, @@ -41,6 +42,8 @@ public function testGetDetails() 'operations_failed' => $failedRetriable + $failedNotRetriable, 'failed_retriable' => $failedRetriable, 'failed_not_retriable' => $failedNotRetriable, + 'rejected' => $rejected, + 'open' => $open, ]; $this->bulkStatusMock->method('getOperationsCountByBulkIdAndStatus') @@ -49,6 +52,7 @@ public function testGetDetails() [$uuid, OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, $failedRetriable], [$uuid, OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, $failedNotRetriable], [$uuid, OperationInterface::STATUS_TYPE_OPEN, $open], + [$uuid, OperationInterface::STATUS_TYPE_REJECTED, $rejected], ]); $result = $this->model->getDetails($uuid); diff --git a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/StatusMapperTest.php b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/StatusMapperTest.php index 87d2bbac3ca..89fa80de363 100644 --- a/app/code/Magento/AsynchronousOperations/Test/Unit/Model/StatusMapperTest.php +++ b/app/code/Magento/AsynchronousOperations/Test/Unit/Model/StatusMapperTest.php @@ -73,7 +73,8 @@ public function testBulkSummaryStatusToOperationStatus() $this->model->bulkSummaryStatusToOperationStatus(BulkSummaryInterface::FINISHED_WITH_FAILURE), [ OperationInterface::STATUS_TYPE_NOT_RETRIABLY_FAILED, - OperationInterface::STATUS_TYPE_RETRIABLY_FAILED + OperationInterface::STATUS_TYPE_RETRIABLY_FAILED, + OperationInterface::STATUS_TYPE_REJECTED ] ); diff --git a/app/code/Magento/AsynchronousOperations/etc/db_schema.xml b/app/code/Magento/AsynchronousOperations/etc/db_schema.xml index b986b98abf3..1b99ce9a280 100644 --- a/app/code/Magento/AsynchronousOperations/etc/db_schema.xml +++ b/app/code/Magento/AsynchronousOperations/etc/db_schema.xml @@ -37,6 +37,8 @@ comment="Name of the related message queue topic"/> + + + + + diff --git a/app/code/Magento/AsynchronousOperations/etc/webapi.xml b/app/code/Magento/AsynchronousOperations/etc/webapi.xml new file mode 100644 index 00000000000..253dedd1c7a --- /dev/null +++ b/app/code/Magento/AsynchronousOperations/etc/webapi.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/internal/Magento/Framework/Bulk/OperationInterface.php b/lib/internal/Magento/Framework/Bulk/OperationInterface.php index c6d714b0363..4b626ac6596 100644 --- a/lib/internal/Magento/Framework/Bulk/OperationInterface.php +++ b/lib/internal/Magento/Framework/Bulk/OperationInterface.php @@ -19,6 +19,7 @@ interface OperationInterface const BULK_ID = 'bulk_uuid'; const TOPIC_NAME = 'topic_name'; const SERIALIZED_DATA = 'serialized_data'; + const RESULT_SERIALIZED_DATA = 'result_serialized_data'; const STATUS = 'status'; const RESULT_MESSAGE = 'result_message'; const ERROR_CODE = 'error_code'; @@ -31,6 +32,7 @@ interface OperationInterface const STATUS_TYPE_RETRIABLY_FAILED = 2; const STATUS_TYPE_NOT_RETRIABLY_FAILED = 3; const STATUS_TYPE_OPEN = 4; + const STATUS_TYPE_REJECTED = 5; /**#@-*/ /** @@ -101,6 +103,23 @@ public function getSerializedData(); */ public function setSerializedData($serializedData); + /** + * Result serialized Data + * + * @return string + * @since 100.3.0 + */ + public function getResultSerializedData(); + + /** + * Set result serialized data + * + * @param string $resultSerializedData + * @return $this + * @since 100.3.0 + */ + public function setResultSerializedData($resultSerializedData); + /** * Get operation status *