Skip to content

Commit

Permalink
Merge pull request #560 from magento-engcom/518-priority-adjustments-…
Browse files Browse the repository at this point in the history
…simple-selection-algorithm

#518 Simplest “By Priority” Algorithm implementation
  • Loading branch information
Valeriy Nayda authored Mar 1, 2018
2 parents ba9538c + 4a18953 commit f4ab977
Show file tree
Hide file tree
Showing 16 changed files with 559 additions and 252 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
*/
declare(strict_types=1);

namespace Magento\Inventory\Model\StockSourceLink\Command;
namespace Magento\Inventory\Model\Source\Command;

use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\Api\SortOrderBuilder;
use Magento\Framework\Exception\LocalizedException;
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\InventoryApi\Api\Data\StockSourceLinkInterface;
use Magento\InventoryApi\Api\GetAssignedSourcesForStockInterface;
use Magento\InventoryApi\Api\GetSourcesAssignedToStockOrderedByPriorityInterface;
use Magento\InventoryApi\Api\GetStockSourceLinksInterface;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Psr\Log\LoggerInterface;

/**
* @inheritdoc
*/
class GetAssignedSourcesForStock implements GetAssignedSourcesForStockInterface
class GetSourcesAssignedToStockOrderedByPriority implements GetSourcesAssignedToStockOrderedByPriorityInterface
{
/**
* @var SearchCriteriaBuilder
Expand All @@ -41,22 +41,30 @@ class GetAssignedSourcesForStock implements GetAssignedSourcesForStockInterface
*/
private $logger;

/**
* @var SortOrderBuilder
*/
private $sortOrderBuilder;

/**
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param SourceRepositoryInterface $sourceRepository
* @param GetStockSourceLinksInterface $getStockSourceLinks
* @param SortOrderBuilder $sortOrderBuilder
* @param LoggerInterface $logger
*/
public function __construct(
SearchCriteriaBuilder $searchCriteriaBuilder,
SourceRepositoryInterface $sourceRepository,
GetStockSourceLinksInterface $getStockSourceLinks,
SortOrderBuilder $sortOrderBuilder,
LoggerInterface $logger
) {
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->sourceRepository = $sourceRepository;
$this->getStockSourceLinks = $getStockSourceLinks;
$this->logger = $logger;
$this->sortOrderBuilder = $sortOrderBuilder;
}

/**
Expand All @@ -65,42 +73,37 @@ public function __construct(
public function execute(int $stockId): array
{
try {
$sourceCodes = $this->getAssignedSourceCodes($stockId);

$searchCriteria = $this->searchCriteriaBuilder
->addFilter(SourceInterface::SOURCE_CODE, $sourceCodes, 'in')
->create();

$searchResult = $this->sourceRepository->getList($searchCriteria);
$stockSourceLinks = $this->getStockSourceLinks($stockId);
$sources = [];
foreach ($stockSourceLinks as $link) {
$sources[] = $this->sourceRepository->get($link->getSourceCode());
}

return $searchResult->getItems();
return $sources;
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
throw new LocalizedException(__('Could not load Sources for Stock'), $e);
}
}

/**
* Get all linked SourceCodes by given stockId
* Get all stock-source links by given stockId
*
* @param int $stockId
* @return array
*/
private function getAssignedSourceCodes(int $stockId): array
private function getStockSourceLinks(int $stockId): array
{
$sortOrder = $this->sortOrderBuilder
->setField(StockSourceLinkInterface::PRIORITY)
->setAscendingDirection()
->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(StockSourceLinkInterface::STOCK_ID, $stockId)
->addSortOrder($sortOrder)
->create();
$searchResult = $this->getStockSourceLinks->execute($searchCriteria);

if (0 === $searchResult->getTotalCount()) {
return [];
}

$sourceCodes = [];
foreach ($searchResult->getItems() as $link) {
$sourceCodes[] = $link->getSourceCode();
}
return $sourceCodes;
return $searchResult->getItems();
}
}
2 changes: 1 addition & 1 deletion app/code/Magento/Inventory/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<preference for="Magento\InventoryApi\Api\Data\SourceInterface" type="Magento\Inventory\Model\Source"/>
<preference for="Magento\InventoryApi\Api\Data\SourceCarrierLinkInterface" type="Magento\Inventory\Model\SourceCarrierLink"/>
<preference for="Magento\InventoryApi\Api\Data\SourceSearchResultsInterface" type="Magento\Inventory\Model\SourceSearchResults"/>
<preference for="Magento\InventoryApi\Api\GetSourcesAssignedToStockOrderedByPriorityInterface" type="Magento\Inventory\Model\Source\Command\GetSourcesAssignedToStockOrderedByPriority"/>
<preference for="Magento\Inventory\Model\SourceCarrierLinkManagementInterface" type="Magento\Inventory\Model\SourceCarrierLinkManagement"/>
<preference for="Magento\Inventory\Model\SourceItem\Command\GetSourceItemsBySkuInterface" type="Magento\Inventory\Model\SourceItem\Command\GetSourceItemsBySku"/>
<preference for="Magento\Inventory\Model\Source\Command\GetInterface" type="Magento\Inventory\Model\Source\Command\Get"/>
Expand Down Expand Up @@ -69,7 +70,6 @@
<preference for="Magento\InventoryApi\Api\GetStockSourceLinksInterface" type="Magento\Inventory\Model\StockSourceLink\Command\GetStockSourceLinks"/>
<preference for="Magento\InventoryApi\Api\StockSourceLinksSaveInterface" type="Magento\Inventory\Model\StockSourceLink\Command\StockSourceLinksSave"/>
<preference for="Magento\InventoryApi\Api\StockSourceLinksDeleteInterface" type="Magento\Inventory\Model\StockSourceLink\Command\StockSourceLinksDelete"/>
<preference for="Magento\InventoryApi\Api\GetAssignedSourcesForStockInterface" type="Magento\Inventory\Model\StockSourceLink\Command\GetAssignedSourcesForStock"/>
<preference for="Magento\InventoryApi\Api\UnassignSourceFromStockInterface" type="Magento\Inventory\Model\StockSourceLink\Command\UnassignSourceFromStock"/>
<preference for="Magento\Inventory\Model\StockSourceLink\Validator\StockSourceLinkValidatorInterface" type="Magento\Inventory\Model\StockSourceLink\Validator\ValidatorChain"/>
<type name="Magento\Inventory\Model\StockSourceLink\Validator\ValidatorChain">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
namespace Magento\InventoryApi\Api;

/**
* Get assigned Sources for Stock
* Retrieve sources related to current stock ordered by priority
*
* Used fully qualified namespaces in annotations for proper work of WebApi request parser
*
* @api
*/
interface GetAssignedSourcesForStockInterface
interface GetSourcesAssignedToStockOrderedByPriorityInterface
{
/**
* Get Sources assigned to Stock
* Get Sources assigned to Stock ordered by priority
*
* If Stock with given id doesn't exist then return an empty array
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\TestFramework\TestCase\WebapiAbstract;

class GetAssignedSourcesForStockTest extends WebapiAbstract
class GetSourcesAssignedToStockOrderedByPriorityTest extends WebapiAbstract
{
/**#@+
* Service constants
*/
const RESOURCE_PATH_GET_ASSIGNED_SOURCES_FOR_STOCK = '/V1/inventory/stock/get-assigned-sources';
const SERVICE_NAME_GET_ASSIGNED_SOURCES_FOR_STOCK = 'inventoryApiGetAssignedSourcesForStockV1';
const RESOURCE_PATH_GET_ASSIGNED_SOURCES_FOR_STOCK
= '/V1/inventory/get-sources-assigned-to-stock-ordered-by-priority';
const SERVICE_NAME_GET_ASSIGNED_SOURCES_FOR_STOCK = 'inventoryApiGetSourcesAssignedToStockOrderedByPriorityV1';
/**#@-*/

/**
Expand All @@ -28,7 +29,7 @@ class GetAssignedSourcesForStockTest extends WebapiAbstract
*/
public function testGetAssignedSourcesForStock()
{
$stockId = 10;
$stockId = 30;
$serviceInfo = [
'rest' => [
'resourcePath' => self::RESOURCE_PATH_GET_ASSIGNED_SOURCES_FOR_STOCK . '/' . $stockId,
Expand All @@ -43,7 +44,7 @@ public function testGetAssignedSourcesForStock()
? $this->_webApiCall($serviceInfo)
: $this->_webApiCall($serviceInfo, ['stockId' => $stockId]);
self::assertEquals(
['eu-1', 'eu-2', 'eu-3', 'eu-disabled'],
['us-1', 'eu-disabled', 'eu-3', 'eu-2', 'eu-1'],
array_column($response, SourceInterface::SOURCE_CODE)
);
}
Expand Down
81 changes: 59 additions & 22 deletions app/code/Magento/InventoryApi/Test/_files/stock_source_links.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
*/
declare(strict_types=1);

use Magento\Framework\Api\DataObjectHelper;
use Magento\InventoryApi\Api\Data\StockSourceLinkInterface;
use Magento\InventoryApi\Api\Data\StockSourceLinkInterfaceFactory;
use Magento\InventoryApi\Api\StockSourceLinksSaveInterface;
use Magento\TestFramework\Helper\Bootstrap;

/** @var DataObjectHelper $dataObjectHelper */
$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class);
/** @var StockSourceLinksSaveInterface $stockSourceLinksSave */
$stockSourceLinksSave = Bootstrap::getObjectManager()->get(StockSourceLinksSaveInterface::class);
/** @var StockSourceLinkInterfaceFactory $stockSourceLinkFactory */
Expand All @@ -25,35 +28,69 @@
*
* EU-source-1(code:eu-1) - Global-stock(id:30)
* EU-source-2(code:eu-2) - Global-stock(id:30)
* EU-source-2(code:eu-2) - Global-stock(id:30)
* EU-source-3(code:eu-3) - Global-stock(id:30)
* EU-source-disabled(code:eu-disabled) - Global-stock(id:30)
* US-source-1(code:us-1) - Global-stock(id:30)
*/

/**
* $stock ID => list of source codes
*/
$linksData = [
10 => ['eu-1', 'eu-2', 'eu-3', 'eu-disabled'],
20 => ['us-1'],
30 => ['eu-1', 'eu-2', 'eu-3', 'eu-disabled', 'us-1']
[
StockSourceLinkInterface::STOCK_ID => 10,
StockSourceLinkInterface::SOURCE_CODE => 'eu-1',
StockSourceLinkInterface::PRIORITY => 1,
],
[
StockSourceLinkInterface::STOCK_ID => 10,
StockSourceLinkInterface::SOURCE_CODE => 'eu-2',
StockSourceLinkInterface::PRIORITY => 2,
],
[
StockSourceLinkInterface::STOCK_ID => 10,
StockSourceLinkInterface::SOURCE_CODE => 'eu-3',
StockSourceLinkInterface::PRIORITY => 3,
],
[
StockSourceLinkInterface::STOCK_ID => 10,
StockSourceLinkInterface::SOURCE_CODE => 'eu-disabled',
StockSourceLinkInterface::PRIORITY => 4,
],
[
StockSourceLinkInterface::STOCK_ID => 20,
StockSourceLinkInterface::SOURCE_CODE => 'us-1',
StockSourceLinkInterface::PRIORITY => 1,
],
[
StockSourceLinkInterface::STOCK_ID => 30,
StockSourceLinkInterface::SOURCE_CODE => 'eu-1',
StockSourceLinkInterface::PRIORITY => 5,
],
[
StockSourceLinkInterface::STOCK_ID => 30,
StockSourceLinkInterface::SOURCE_CODE => 'eu-2',
StockSourceLinkInterface::PRIORITY => 4,
],
[
StockSourceLinkInterface::STOCK_ID => 30,
StockSourceLinkInterface::SOURCE_CODE => 'eu-3',
StockSourceLinkInterface::PRIORITY => 3,
],
[
StockSourceLinkInterface::STOCK_ID => 30,
StockSourceLinkInterface::SOURCE_CODE => 'eu-disabled',
StockSourceLinkInterface::PRIORITY => 2,
],
[
StockSourceLinkInterface::STOCK_ID => 30,
StockSourceLinkInterface::SOURCE_CODE => 'us-1',
StockSourceLinkInterface::PRIORITY => 1,
],
];



$links = [];
$priority = 0;
foreach ($linksData as $stockId => $sourceCodes) {
foreach ($sourceCodes as $sourceCode) {
/** @var StockSourceLinkInterface $link */
$link = $stockSourceLinkFactory->create();

$link->setStockId($stockId);
$link->setSourceCode($sourceCode);
$link->setPriority(++$priority);

$links[] = $link;
}
foreach ($linksData as $linkData) {
/** @var StockSourceLinkInterface $link */
$link = $stockSourceLinkFactory->create();
$dataObjectHelper->populateWithArray($link, $linkData, StockSourceLinkInterface::class);
$links[] = $link;
}

$stockSourceLinksSave->execute($links);
12 changes: 6 additions & 6 deletions app/code/Magento/InventoryApi/etc/webapi.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
<resource ref="Magento_InventoryApi::source_edit"/>
</resources>
</route>
<route url="/V1/inventory/get-sources-assigned-to-stock-ordered-by-priority/:stockId" method="GET">
<service class="Magento\InventoryApi\Api\GetSourcesAssignedToStockOrderedByPriorityInterface" method="execute"/>
<resources>
<resource ref="Magento_InventoryApi::source"/>
</resources>
</route>
<!-- Stock -->
<route url="/V1/inventory/stock" method="GET">
<service class="Magento\InventoryApi\Api\StockRepositoryInterface" method="getList"/>
Expand Down Expand Up @@ -70,12 +76,6 @@
</resources>
</route>
<!-- StockSourceLink -->
<route url="/V1/inventory/stock/get-assigned-sources/:stockId" method="GET">
<service class="Magento\InventoryApi\Api\GetAssignedSourcesForStockInterface" method="execute"/>
<resources>
<resource ref="Magento_InventoryApi::source_stock_link"/>
</resources>
</route>
<route url="/V1/inventory/stock-source-link" method="GET">
<service class="Magento\InventoryApi\Api\GetStockSourceLinksInterface" method="execute"/>
<resources>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Magento\Framework\Registry;
use Magento\InventoryApi\Api\SourceRepositoryInterface;
use Magento\InventoryShipping\Model\ShippingAlgorithmProviderInterface;
use Magento\InventoryShipping\Model\ShippingAlgorithmResult\ShippingAlgorithmResultInterface;
use Magento\InventoryShipping\Model\ShippingAlgorithmResult\SourceSelectionInterface;

/**
Expand All @@ -22,6 +23,11 @@
*/
class SourceSelection extends Template implements TabInterface
{
/**
* @var ShippingAlgorithmResultInterface
*/
private $shippingAlgorithmResult;

/**
* @var Registry
*/
Expand Down Expand Up @@ -57,16 +63,24 @@ public function __construct(
$this->sourceRepository = $sourceRepository;
}

/**
* Check if order items can be shipped by the current shipping algorithm
*
* @return bool
*/
public function isShippable()
{
return $this->getShippingAlgorithmResult()->isShippable();
}

/**
* Get source selections for order
*
* @return SourceSelectionInterface[]
*/
public function getSourceSelections(): array
{
$order = $this->registry->registry('current_order');
$shippingAlgorithm = $this->shippingAlgorithmProvider->execute();
return $shippingAlgorithm->execute($order)->getSourceSelections();
return $this->getShippingAlgorithmResult()->getSourceSelections();
}

/**
Expand Down Expand Up @@ -102,7 +116,7 @@ public function getTabTitle()
*/
public function canShowTab()
{
return true;
return $this->isShippable();
}

/**
Expand All @@ -112,4 +126,19 @@ public function isHidden()
{
return false;
}

/**
* @return ShippingAlgorithmResultInterface
*/
private function getShippingAlgorithmResult()
{
if (null === $this->shippingAlgorithmResult) {
$order = $this->registry->registry('current_order');
$shippingAlgorithm = $this->shippingAlgorithmProvider->execute();

$this->shippingAlgorithmResult = $shippingAlgorithm->execute($order);
}

return $this->shippingAlgorithmResult;
}
}
Loading

0 comments on commit f4ab977

Please sign in to comment.