-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from AmpersandHQ/source-selection-order-placement
Force source selection on order placement
- Loading branch information
Showing
6 changed files
with
313 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<?php | ||
declare(strict_types=1); | ||
|
||
namespace Ampersand\DisableStockReservation\Model; | ||
|
||
use Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestExtensionInterfaceFactory; | ||
use Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestInterface; | ||
use Magento\InventorySourceSelectionApi\Api\Data\InventoryRequestInterfaceFactory; | ||
use Magento\InventorySourceSelectionApi\Api\Data\AddressInterfaceFactory; | ||
use Magento\InventorySourceSelectionApi\Api\Data\AddressInterface; | ||
use Magento\InventorySalesApi\Model\StockByWebsiteIdResolverInterface; | ||
use Magento\Sales\Api\Data\OrderInterface; | ||
use Magento\Sales\Model\Order\Address; | ||
use Magento\Sales\Api\OrderRepositoryInterface; | ||
use Magento\Store\Model\StoreManagerInterface; | ||
|
||
class GetInventoryRequestFromOrder | ||
{ | ||
/** | ||
* @var InventoryRequestInterfaceFactory | ||
*/ | ||
private $inventoryRequestFactory; | ||
|
||
/** | ||
* @var InventoryRequestExtensionInterfaceFactory | ||
*/ | ||
private $inventoryRequestExtensionFactory; | ||
|
||
/** | ||
* @var OrderRepositoryInterface | ||
*/ | ||
private $orderRepository; | ||
|
||
/** | ||
* @var AddressInterfaceFactory | ||
*/ | ||
private $addressInterfaceFactory; | ||
|
||
/** | ||
* @var StoreManagerInterface | ||
*/ | ||
private $storeManager; | ||
|
||
/** | ||
* @var StockByWebsiteIdResolverInterface | ||
*/ | ||
private $stockByWebsiteIdResolver; | ||
|
||
/** | ||
* @param InventoryRequestInterfaceFactory $inventoryRequestFactory | ||
* @param InventoryRequestExtensionInterfaceFactory $inventoryRequestExtensionFactory | ||
* @param OrderRepositoryInterface $orderRepository | ||
* @param AddressInterfaceFactory $addressInterfaceFactory | ||
* @param StoreManagerInterface $storeManager | ||
* @param StockByWebsiteIdResolverInterface $stockByWebsiteIdResolver | ||
*/ | ||
public function __construct( | ||
InventoryRequestInterfaceFactory $inventoryRequestFactory, | ||
InventoryRequestExtensionInterfaceFactory $inventoryRequestExtensionFactory, | ||
OrderRepositoryInterface $orderRepository, | ||
AddressInterfaceFactory $addressInterfaceFactory, | ||
StoreManagerInterface $storeManager, | ||
StockByWebsiteIdResolverInterface $stockByWebsiteIdResolver | ||
) { | ||
$this->inventoryRequestFactory = $inventoryRequestFactory; | ||
$this->inventoryRequestExtensionFactory = $inventoryRequestExtensionFactory; | ||
$this->orderRepository = $orderRepository; | ||
$this->addressInterfaceFactory = $addressInterfaceFactory; | ||
$this->storeManager = $storeManager; | ||
$this->stockByWebsiteIdResolver = $stockByWebsiteIdResolver; | ||
} | ||
|
||
/** | ||
* Same as GetInventoryRequestFromOrder, but takes an order instead of an order id | ||
* because in this scenario the order has not been saved yet. | ||
* | ||
* @param OrderInterface $order | ||
* @param array $requestItems | ||
* @return InventoryRequestInterface | ||
* @throws \Magento\Framework\Exception\NoSuchEntityException | ||
*/ | ||
public function execute(OrderInterface $order, array $requestItems): InventoryRequestInterface | ||
{ | ||
$store = $this->storeManager->getStore($order->getStoreId()); | ||
$stock = $this->stockByWebsiteIdResolver->execute((int)$store->getWebsiteId()); | ||
|
||
$inventoryRequest = $this->inventoryRequestFactory->create([ | ||
'stockId' => $stock->getStockId(), | ||
'items' => $requestItems | ||
]); | ||
|
||
$address = $this->getAddressFromOrder($order); | ||
if ($address !== null) { | ||
$extensionAttributes = $this->inventoryRequestExtensionFactory->create(); | ||
$extensionAttributes->setDestinationAddress($address); | ||
$inventoryRequest->setExtensionAttributes($extensionAttributes); | ||
} | ||
|
||
return $inventoryRequest; | ||
} | ||
|
||
/** | ||
* Create an address from an order | ||
* | ||
* @param OrderInterface $order | ||
* @return null|AddressInterface | ||
*/ | ||
private function getAddressFromOrder(OrderInterface $order): ?AddressInterface | ||
{ | ||
/** @var Address $shippingAddress */ | ||
$shippingAddress = $order->getShippingAddress(); | ||
if ($shippingAddress === null) { | ||
return null; | ||
} | ||
|
||
return $this->addressInterfaceFactory->create([ | ||
'country' => $shippingAddress->getCountryId(), | ||
'postcode' => $shippingAddress->getPostcode(), | ||
'street' => implode("\n", $shippingAddress->getStreet()), | ||
'region' => $shippingAddress->getRegion() ?? $shippingAddress->getRegionCode() ?? '', | ||
'city' => $shippingAddress->getCity() | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<?php | ||
|
||
namespace Ampersand\DisableStockReservation\Model; | ||
|
||
use Ampersand\DisableStockReservation\Model\GetInventoryRequestFromOrder; | ||
use Magento\Framework\App\ObjectManager; | ||
use Magento\InventorySalesApi\Model\GetSkuFromOrderItemInterface; | ||
use Magento\InventorySourceSelectionApi\Api\Data\ItemRequestInterfaceFactory; | ||
use Magento\Sales\Api\Data\OrderInterface; | ||
use Magento\InventorySourceSelectionApi\Api\SourceSelectionServiceInterface; | ||
use Magento\InventorySourceSelectionApi\Api\GetDefaultSourceSelectionAlgorithmCodeInterface; | ||
use Magento\InventorySourceSelectionApi\Api\Data\SourceSelectionResultInterface; | ||
use Magento\Sales\Api\Data\OrderItemInterface; | ||
use Traversable; | ||
|
||
class GetSourceSelectionResultFromOrder | ||
{ | ||
/** | ||
* @var GetSkuFromOrderItemInterface | ||
*/ | ||
private $getSkuFromOrderItem; | ||
|
||
/** | ||
* @var ItemRequestInterfaceFactory | ||
*/ | ||
private $itemRequestFactory; | ||
|
||
/** | ||
* @var GetDefaultSourceSelectionAlgorithmCodeInterface | ||
*/ | ||
private $getDefaultSourceSelectionAlgorithmCode; | ||
|
||
/** | ||
* @var SourceSelectionServiceInterface | ||
*/ | ||
private $sourceSelectionService; | ||
|
||
/** | ||
* @var GetInventoryRequestFromOrder | ||
*/ | ||
private $getInventoryRequestFromOrder; | ||
|
||
/** | ||
* @param GetSkuFromOrderItemInterface $getSkuFromOrderItem | ||
* @param ItemRequestInterfaceFactory $itemRequestFactory | ||
* @param GetDefaultSourceSelectionAlgorithmCodeInterface $getDefaultSourceSelectionAlgorithmCode | ||
* @param SourceSelectionServiceInterface $sourceSelectionService | ||
* @param GetInventoryRequestFromOrder|null $getInventoryRequestFromOrder | ||
* @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||
*/ | ||
public function __construct( | ||
GetSkuFromOrderItemInterface $getSkuFromOrderItem, | ||
ItemRequestInterfaceFactory $itemRequestFactory, | ||
GetDefaultSourceSelectionAlgorithmCodeInterface $getDefaultSourceSelectionAlgorithmCode, | ||
SourceSelectionServiceInterface $sourceSelectionService, | ||
GetInventoryRequestFromOrder $getInventoryRequestFromOrder = null | ||
) { | ||
$this->itemRequestFactory = $itemRequestFactory; | ||
$this->getDefaultSourceSelectionAlgorithmCode = $getDefaultSourceSelectionAlgorithmCode; | ||
$this->sourceSelectionService = $sourceSelectionService; | ||
$this->getSkuFromOrderItem = $getSkuFromOrderItem; | ||
$this->getInventoryRequestFromOrder = $getInventoryRequestFromOrder ?: | ||
ObjectManager::getInstance()->get(GetInventoryRequestFromOrder::class); | ||
} | ||
|
||
/** | ||
* @param OrderInterface $order | ||
* @return SourceSelectionResultInterface | ||
*/ | ||
public function execute(OrderInterface $order): SourceSelectionResultInterface | ||
{ | ||
/** @var OrderInterface $order */ | ||
$inventoryRequest = $this->getInventoryRequestFromOrder->execute( | ||
$order, | ||
$this->getSelectionRequestItems($order->getItems()) | ||
); | ||
|
||
$selectionAlgorithmCode = $this->getDefaultSourceSelectionAlgorithmCode->execute(); | ||
return $this->sourceSelectionService->execute($inventoryRequest, $selectionAlgorithmCode); | ||
} | ||
|
||
/** | ||
* Get selection request items | ||
* | ||
* @param OrderItemInterface[]|Traversable $orderItems | ||
* @return array | ||
*/ | ||
private function getSelectionRequestItems(iterable $orderItems): array | ||
{ | ||
$selectionRequestItems = []; | ||
foreach ($orderItems as $orderItem) { | ||
if ($orderItem->isDummy()) { | ||
continue; | ||
} | ||
|
||
$itemSku = $this->getSkuFromOrderItem->execute($orderItem); | ||
$qty = $this->castQty($orderItem, $orderItem->getQtyOrdered()); | ||
|
||
$selectionRequestItems[] = $this->itemRequestFactory->create([ | ||
'sku' => $itemSku, | ||
'qty' => $qty, | ||
]); | ||
} | ||
return $selectionRequestItems; | ||
} | ||
|
||
/** | ||
* Cast qty value | ||
* | ||
* @param OrderItemInterface $item | ||
* @param string|int|float $qty | ||
* @return float | ||
*/ | ||
private function castQty(OrderItemInterface $item, $qty): float | ||
{ | ||
if ($item->getIsQtyDecimal()) { | ||
$qty = (float) $qty; | ||
} else { | ||
$qty = (int) $qty; | ||
} | ||
|
||
return $qty > 0 ? $qty : 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.