Skip to content

Commit

Permalink
FIX coupling between objects
Browse files Browse the repository at this point in the history
  • Loading branch information
phoenix128 committed Nov 22, 2018
1 parent 930b0b4 commit 12a8b72
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 224 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,12 @@
use Magento\Framework\Exception\LocalizedException;
use Magento\InventoryApi\Api\GetSourcesAssignedToStockOrderedByPriorityInterface;
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\InventoryApi\Api\Data\SourceItemInterface;
use Magento\InventoryApi\Api\SourceItemRepositoryInterface;
use Magento\InventorySourceSelection\Model\Algorithms\Result\GetDefaultSortedSourcesResult;
use Magento\InventorySourceSelectionApi\Api\Data\AddressRequestInterface;
use Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestInterface;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionResultInterface;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionItemInterfaceFactory;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionResultInterfaceFactory;
use Magento\InventorySourceSelectionApi\Model\GetGeoReferenceProvider;
use Magento\InventorySourceSelectionApi\Model\SourceSelectionInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;

/**
* {@inheritdoc}
Expand All @@ -33,54 +29,30 @@ class DistanceBasedAlgorithm implements SourceSelectionInterface
private $getSourcesAssignedToStockOrderedByPriority;

/**
* @var SourceSelectionItemInterfaceFactory
*/
private $sourceSelectionItemFactory;

/**
* @var SourceSelectionResultInterfaceFactory
*/
private $sourceSelectionResultFactory;

/**
* @var SearchCriteriaBuilder
*/
private $searchCriteriaBuilder;

/**
* @var SourceItemRepositoryInterface
* @var GetGeoReferenceProvider
*/
private $sourceItemRepository;
private $getGeoReferenceProvider;

/**
* @var GetGeoReferenceProvider
* @var GetDefaultSortedSourcesResult
*/
private $getGeoReferenceProvider;
private $getDefaultSortedSourcesResult;

/**
* DistanceBasedAlgorithm constructor.
*
* @param GetSourcesAssignedToStockOrderedByPriorityInterface $getSourcesAssignedToStockOrderedByPriority
* @param SourceSelectionItemInterfaceFactory $sourceSelectionItemFactory
* @param SourceSelectionResultInterfaceFactory $sourceSelectionResultFactory
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param SourceItemRepositoryInterface $sourceItemRepository
* @param Result\GetDefaultSortedSourcesResult $getDefaultSortedSourcesResult
* @param GetGeoReferenceProvider $getGeoReferenceProvider
*/
public function __construct(
GetSourcesAssignedToStockOrderedByPriorityInterface $getSourcesAssignedToStockOrderedByPriority,
SourceSelectionItemInterfaceFactory $sourceSelectionItemFactory,
SourceSelectionResultInterfaceFactory $sourceSelectionResultFactory,
SearchCriteriaBuilder $searchCriteriaBuilder,
SourceItemRepositoryInterface $sourceItemRepository,
GetDefaultSortedSourcesResult $getDefaultSortedSourcesResult,
GetGeoReferenceProvider $getGeoReferenceProvider
) {
$this->getSourcesAssignedToStockOrderedByPriority = $getSourcesAssignedToStockOrderedByPriority;
$this->sourceSelectionItemFactory = $sourceSelectionItemFactory;
$this->sourceSelectionResultFactory = $sourceSelectionResultFactory;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->sourceItemRepository = $sourceItemRepository;
$this->getGeoReferenceProvider = $getGeoReferenceProvider;
$this->getDefaultSortedSourcesResult = $getDefaultSortedSourcesResult;
}

/**
Expand All @@ -89,75 +61,18 @@ public function __construct(
*/
public function execute(InventoryRequestInterface $inventoryRequest): SourceSelectionResultInterface
{
$isShippable = true;
$destinationAddress = $inventoryRequest->getExtensionAttributes()->getDestinationAddress();
if ($destinationAddress === null) {
throw new LocalizedException(__('No destination address was provided in the request'));
}

$stockId = $inventoryRequest->getStockId();
$sources = $this->getEnabledSourcesOrderedByDistanceByStockId(
$sortedSources = $this->getEnabledSourcesOrderedByDistanceByStockId(
$stockId,
$destinationAddress
);
$sourceItemSelections = [];

foreach ($inventoryRequest->getItems() as $item) {
$itemSku = $item->getSku();
$qtyToDeliver = $item->getQty();
foreach ($sources as $source) {
$sourceItem = $this->getSourceItemBySourceCodeAndSku($source->getSourceCode(), $itemSku);
if (null === $sourceItem) {
continue;
}

if ($sourceItem->getStatus() !== SourceItemInterface::STATUS_IN_STOCK) {
continue;
}

$sourceItemQty = $sourceItem->getQuantity();
$qtyToDeduct = min($sourceItemQty, $qtyToDeliver);

// check if source has some qty of SKU, so it's possible to take them into account
if ($this->isZero((float)$sourceItemQty)) {
continue;
}

$sourceItemSelections[] = $this->sourceSelectionItemFactory->create([
'sourceCode' => $sourceItem->getSourceCode(),
'sku' => $itemSku,
'qtyToDeduct' => $qtyToDeduct,
'qtyAvailable' => $sourceItemQty
]);

$qtyToDeliver -= $qtyToDeduct;
}

// if we go through all sources from the stock and there is still some qty to delivery,
// then it doesn't have enough items to delivery
if (!$this->isZero($qtyToDeliver)) {
$isShippable = false;
}
}

return $this->sourceSelectionResultFactory->create(
[
'sourceItemSelections' => $sourceItemSelections,
'isShippable' => $isShippable
]
);
}

/**
* Compare float number with some epsilon
*
* @param float $floatNumber
*
* @return bool
*/
private function isZero(float $floatNumber): bool
{
return $floatNumber < 0.0000001;
return $this->getDefaultSortedSourcesResult->execute($inventoryRequest, $sortedSources);
}

/**
Expand Down Expand Up @@ -195,22 +110,4 @@ function (SourceInterface $a, SourceInterface $b) use ($geoReferenceProvider, $a

return $sources;
}

/**
* Returns source item from specific source by given SKU. Return null if source item is not found
*
* @param string $sourceCode
* @param string $sku
* @return SourceItemInterface|null
*/
private function getSourceItemBySourceCodeAndSku(string $sourceCode, string $sku): ?SourceItemInterface
{
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(SourceItemInterface::SOURCE_CODE, $sourceCode)
->addFilter(SourceItemInterface::SKU, $sku)
->create();
$sourceItemsResult = $this->sourceItemRepository->getList($searchCriteria);

return $sourceItemsResult->getTotalCount() > 0 ? current($sourceItemsResult->getItems()) : null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,10 @@

use Magento\InventoryApi\Api\GetSourcesAssignedToStockOrderedByPriorityInterface;
use Magento\InventoryApi\Api\Data\SourceInterface;
use Magento\InventoryApi\Api\Data\SourceItemInterface;
use Magento\InventoryApi\Api\SourceItemRepositoryInterface;
use Magento\InventorySourceSelection\Model\Algorithms\Result\GetDefaultSortedSourcesResult;
use Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestInterface;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionResultInterface;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionItemInterfaceFactory;
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionResultInterfaceFactory;
use Magento\InventorySourceSelectionApi\Model\SourceSelectionInterface;
use Magento\Framework\Api\SearchCriteriaBuilder;

/**
* {@inheritdoc}
Expand All @@ -30,114 +26,35 @@ class PriorityBasedAlgorithm implements SourceSelectionInterface
private $getSourcesAssignedToStockOrderedByPriority;

/**
* @var SourceSelectionItemInterfaceFactory
* @var GetDefaultSortedSourcesResult
*/
private $sourceSelectionItemFactory;

/**
* @var SourceSelectionResultInterfaceFactory
*/
private $sourceSelectionResultFactory;

/**
* @var SearchCriteriaBuilder
*/
private $searchCriteriaBuilder;

/**
* @var SourceItemRepositoryInterface
*/
private $sourceItemRepository;
private $getDefaultSortedSourcesResult;

/**
* PriorityBasedAlgorithm constructor.
*
* @param GetSourcesAssignedToStockOrderedByPriorityInterface $getSourcesAssignedToStockOrderedByPriority
* @param SourceSelectionItemInterfaceFactory $sourceSelectionItemFactory
* @param SourceSelectionResultInterfaceFactory $sourceSelectionResultFactory
* @param SearchCriteriaBuilder $searchCriteriaBuilder
* @param SourceItemRepositoryInterface $sourceItemRepository
* @param GetDefaultSortedSourcesResult $getDefaultSortedSourcesResult
*/
public function __construct(
GetSourcesAssignedToStockOrderedByPriorityInterface $getSourcesAssignedToStockOrderedByPriority,
SourceSelectionItemInterfaceFactory $sourceSelectionItemFactory,
SourceSelectionResultInterfaceFactory $sourceSelectionResultFactory,
SearchCriteriaBuilder $searchCriteriaBuilder,
SourceItemRepositoryInterface $sourceItemRepository
GetDefaultSortedSourcesResult $getDefaultSortedSourcesResult
) {
$this->getSourcesAssignedToStockOrderedByPriority = $getSourcesAssignedToStockOrderedByPriority;
$this->sourceSelectionItemFactory = $sourceSelectionItemFactory;
$this->sourceSelectionResultFactory = $sourceSelectionResultFactory;
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
$this->sourceItemRepository = $sourceItemRepository;
$this->getDefaultSortedSourcesResult = $getDefaultSortedSourcesResult;
}

/**
* @inheritdoc
* @throws \Magento\Framework\Exception\InputException
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function execute(InventoryRequestInterface $inventoryRequest): SourceSelectionResultInterface
{
$isShippable = true;
$stockId = $inventoryRequest->getStockId();
$sources = $this->getEnabledSourcesOrderedByPriorityByStockId($stockId);
$sourceItemSelections = [];

foreach ($inventoryRequest->getItems() as $item) {
$itemSku = $item->getSku();
$qtyToDeliver = $item->getQty();
foreach ($sources as $source) {
$sourceItem = $this->getSourceItemBySourceCodeAndSku($source->getSourceCode(), $itemSku);
if (null === $sourceItem) {
continue;
}

if ($sourceItem->getStatus() !== SourceItemInterface::STATUS_IN_STOCK) {
continue;
}

$sourceItemQty = $sourceItem->getQuantity();
$qtyToDeduct = min($sourceItemQty, $qtyToDeliver);

// check if source has some qty of SKU, so it's possible to take them into account
if ($this->isZero((float)$sourceItemQty)) {
continue;
}

$sourceItemSelections[] = $this->sourceSelectionItemFactory->create([
'sourceCode' => $sourceItem->getSourceCode(),
'sku' => $itemSku,
'qtyToDeduct' => $qtyToDeduct,
'qtyAvailable' => $sourceItemQty
]);
$sortedSources = $this->getEnabledSourcesOrderedByPriorityByStockId($stockId);

$qtyToDeliver -= $qtyToDeduct;
}

// if we go throw all sources from the stock and there is still some qty to delivery,
// then it doesn't have enough items to delivery
if (!$this->isZero($qtyToDeliver)) {
$isShippable = false;
}
}

return $this->sourceSelectionResultFactory->create(
[
'sourceItemSelections' => $sourceItemSelections,
'isShippable' => $isShippable
]
);
}

/**
* Compare float number with some epsilon
*
* @param float $floatNumber
*
* @return bool
*/
private function isZero(float $floatNumber): bool
{
return $floatNumber < 0.0000001;
return $this->getDefaultSortedSourcesResult->execute($inventoryRequest, $sortedSources);
}

/**
Expand All @@ -157,22 +74,4 @@ private function getEnabledSourcesOrderedByPriorityByStockId(int $stockId): arra
});
return $sources;
}

/**
* Returns source item from specific source by given SKU. Return null if source item is not found
*
* @param string $sourceCode
* @param string $sku
* @return SourceItemInterface|null
*/
private function getSourceItemBySourceCodeAndSku(string $sourceCode, string $sku): ?SourceItemInterface
{
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(SourceItemInterface::SOURCE_CODE, $sourceCode)
->addFilter(SourceItemInterface::SKU, $sku)
->create();
$sourceItemsResult = $this->sourceItemRepository->getList($searchCriteria);

return $sourceItemsResult->getTotalCount() > 0 ? current($sourceItemsResult->getItems()) : null;
}
}
Loading

0 comments on commit 12a8b72

Please sign in to comment.