Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#518 Simplest “By Priority” Algorithm implementation #560

Merged
merged 26 commits into from
Mar 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f3bbc5f
#518 [WIP] Loaded sources by priority
Feb 15, 2018
0b22472
Merge branch 'develop' into 518-priority-adjustments-simple-selection…
Feb 17, 2018
68694a8
#518 Refactored the default shipping selection algo to process source…
Feb 17, 2018
131fc1c
#518 Put all variable assignments in the same places
Feb 17, 2018
32ffc90
#518 Refactored shipping selection algo classname
Feb 17, 2018
74a08e4
#518 Changed the epsilon
Feb 17, 2018
adfa7f7
#518 Added the message if order items can’t be delivered by the curre…
Feb 17, 2018
1f3cf0b
[TASK] #518 Commented the algorithm
Feb 17, 2018
9adcaec
#518 Renamed the classname
Feb 17, 2018
39ca211
#518 Made the tab hidden if source items are not enough to deliver th…
Feb 17, 2018
2101841
Merge branch 'develop' into 518-priority-adjustments-simple-selection…
Feb 22, 2018
8639184
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 23, 2018
4690f24
Merge remote-tracking branch 'origin/518-priority-adjustments-simple-…
p-bystritsky Feb 23, 2018
9de498f
Merge branch '519_Adatp_UI_according_to_Single_or_Multi_Stocks' into …
Feb 23, 2018
2e15fda
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 23, 2018
0dcfc62
Merge remote-tracking branch 'origin/518-priority-adjustments-simple-…
p-bystritsky Feb 23, 2018
28ec1f8
Merge branch 'develop' into 518-priority-adjustments-simple-selection…
Feb 26, 2018
a6962b6
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 26, 2018
0fb5f25
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 26, 2018
54add71
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 27, 2018
1d8d603
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 28, 2018
1a6b455
518: Simplest “By Priority” Algorithm implementation
p-bystritsky Feb 28, 2018
e9d7682
Merge remote-tracking branch 'origin/develop' into 518-priority-adjus…
Mar 1, 2018
11364c5
MSI-518: Simplest “By Priority” Algorithm implementation
Mar 1, 2018
1e3752a
MSI-518: Simplest “By Priority” Algorithm implementation
Mar 1, 2018
4a18953
MSI-518: Simplest “By Priority” Algorithm implementation
Mar 1, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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