Skip to content

Commit 39f0be8

Browse files
authored
Merge pull request #7966 from magento-lynx/purchase-order-graphql
[LYNX] Purchase order GraphQL delivery
2 parents 7e90ca5 + 9427c4e commit 39f0be8

File tree

9 files changed

+289
-175
lines changed

9 files changed

+289
-175
lines changed

app/code/Magento/Quote/Model/Cart/AddProductsToCart.php

Lines changed: 16 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
namespace Magento\Quote\Model\Cart;
99

10-
use Magento\Catalog\Api\ProductRepositoryInterface;
11-
use Magento\Framework\App\ObjectManager;
1210
use Magento\Framework\Exception\NoSuchEntityException;
1311
use Magento\Quote\Api\CartRepositoryInterface;
1412
use Magento\Quote\Model\Cart\BuyRequest\BuyRequestBuilder;
@@ -23,29 +21,6 @@
2321
*/
2422
class AddProductsToCart
2523
{
26-
/**#@+
27-
* Error message codes
28-
*/
29-
private const ERROR_PRODUCT_NOT_FOUND = 'PRODUCT_NOT_FOUND';
30-
private const ERROR_INSUFFICIENT_STOCK = 'INSUFFICIENT_STOCK';
31-
private const ERROR_NOT_SALABLE = 'NOT_SALABLE';
32-
private const ERROR_UNDEFINED = 'UNDEFINED';
33-
/**#@-*/
34-
35-
/**
36-
* List of error messages and codes.
37-
*/
38-
private const MESSAGE_CODES = [
39-
'Could not find a product with SKU' => self::ERROR_PRODUCT_NOT_FOUND,
40-
'The required options you selected are not available' => self::ERROR_NOT_SALABLE,
41-
'Product that you are trying to add is not available.' => self::ERROR_NOT_SALABLE,
42-
'This product is out of stock' => self::ERROR_INSUFFICIENT_STOCK,
43-
'There are no source items' => self::ERROR_NOT_SALABLE,
44-
'The fewest you may purchase is' => self::ERROR_INSUFFICIENT_STOCK,
45-
'The most you may purchase is' => self::ERROR_INSUFFICIENT_STOCK,
46-
'The requested qty is not available' => self::ERROR_INSUFFICIENT_STOCK,
47-
];
48-
4924
/**
5025
* @var CartRepositoryInterface
5126
*/
@@ -67,25 +42,29 @@ class AddProductsToCart
6742
private $productReader;
6843

6944
/**
70-
* @param ProductRepositoryInterface $productRepository
45+
* @var AddProductsToCartError
46+
*/
47+
private $error;
48+
49+
/**
7150
* @param CartRepositoryInterface $cartRepository
7251
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
7352
* @param BuyRequestBuilder $requestBuilder
74-
* @param ProductReaderInterface|null $productReader
75-
*
76-
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
53+
* @param ProductReaderInterface $productReader
54+
* @param AddProductsToCartError $addProductsToCartError
7755
*/
7856
public function __construct(
79-
ProductRepositoryInterface $productRepository,
8057
CartRepositoryInterface $cartRepository,
8158
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
8259
BuyRequestBuilder $requestBuilder,
83-
ProductReaderInterface $productReader = null
60+
ProductReaderInterface $productReader,
61+
AddProductsToCartError $addProductsToCartError
8462
) {
8563
$this->cartRepository = $cartRepository;
8664
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
8765
$this->requestBuilder = $requestBuilder;
88-
$this->productReader = $productReader ?: ObjectManager::getInstance()->get(ProductReaderInterface::class);
66+
$this->productReader = $productReader;
67+
$this->error = $addProductsToCartError;
8968
}
9069

9170
/**
@@ -106,7 +85,7 @@ public function execute(string $maskedCartId, array $cartItems): AddProductsToCa
10685

10786
/** @var MessageInterface $error */
10887
foreach ($errors as $error) {
109-
$allErrors[] = $this->createError($error->getText());
88+
$allErrors[] = $this->error->create($error->getText());
11089
}
11190
}
11291

@@ -181,22 +160,22 @@ private function addItemToCart(Quote $cart, Data\CartItem $cartItem, int $cartIt
181160
$result = null;
182161

183162
if ($cartItem->getQuantity() <= 0) {
184-
$errors[] = $this->createError(
163+
$errors[] = $this->error->create(
185164
__('The product quantity should be greater than 0')->render(),
186165
$cartItemPosition
187166
);
188167
} else {
189168
$product = $this->productReader->getProductBySku($sku);
190169
if (!$product || !$product->isSaleable() || !$product->isAvailable()) {
191-
$errors[] = $this->createError(
170+
$errors[] = $this->error->create(
192171
__('Could not find a product with SKU "%sku"', ['sku' => $sku])->render(),
193172
$cartItemPosition
194173
);
195174
} else {
196175
try {
197176
$result = $cart->addProduct($product, $this->requestBuilder->build($cartItem));
198177
} catch (\Throwable $e) {
199-
$errors[] = $this->createError(
178+
$errors[] = $this->error->create(
200179
__($e->getMessage())->render(),
201180
$cartItemPosition
202181
);
@@ -205,50 +184,14 @@ private function addItemToCart(Quote $cart, Data\CartItem $cartItem, int $cartIt
205184

206185
if (is_string($result)) {
207186
foreach (array_unique(explode("\n", $result)) as $error) {
208-
$errors[] = $this->createError(__($error)->render(), $cartItemPosition);
187+
$errors[] = $this->error->create(__($error)->render(), $cartItemPosition);
209188
}
210189
}
211190
}
212191

213192
return $errors;
214193
}
215194

216-
/**
217-
* Returns an error object
218-
*
219-
* @param string $message
220-
* @param int $cartItemPosition
221-
* @return Data\Error
222-
*/
223-
private function createError(string $message, int $cartItemPosition = 0): Data\Error
224-
{
225-
return new Data\Error(
226-
$message,
227-
$this->getErrorCode($message),
228-
$cartItemPosition
229-
);
230-
}
231-
232-
/**
233-
* Get message error code.
234-
*
235-
* TODO: introduce a separate class for getting error code from a message
236-
*
237-
* @param string $message
238-
* @return string
239-
*/
240-
private function getErrorCode(string $message): string
241-
{
242-
foreach (self::MESSAGE_CODES as $codeMessage => $code) {
243-
if (false !== stripos($message, $codeMessage)) {
244-
return $code;
245-
}
246-
}
247-
248-
/* If no code was matched, return the default one */
249-
return self::ERROR_UNDEFINED;
250-
}
251-
252195
/**
253196
* Creates a new output from existing errors
254197
*
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Quote\Model\Cart;
9+
10+
/**
11+
* Create instances of errors on adding products to cart. Identify error code based on the message
12+
*/
13+
class AddProductsToCartError
14+
{
15+
/**#@+
16+
* Error message codes
17+
*/
18+
private const ERROR_PRODUCT_NOT_FOUND = 'PRODUCT_NOT_FOUND';
19+
private const ERROR_INSUFFICIENT_STOCK = 'INSUFFICIENT_STOCK';
20+
private const ERROR_NOT_SALABLE = 'NOT_SALABLE';
21+
private const ERROR_UNDEFINED = 'UNDEFINED';
22+
/**#@-*/
23+
24+
/**
25+
* List of error messages and codes.
26+
*/
27+
private const MESSAGE_CODES = [
28+
'Could not find a product with SKU' => self::ERROR_PRODUCT_NOT_FOUND,
29+
'The required options you selected are not available' => self::ERROR_NOT_SALABLE,
30+
'Product that you are trying to add is not available.' => self::ERROR_NOT_SALABLE,
31+
'This product is out of stock' => self::ERROR_INSUFFICIENT_STOCK,
32+
'There are no source items' => self::ERROR_NOT_SALABLE,
33+
'The fewest you may purchase is' => self::ERROR_INSUFFICIENT_STOCK,
34+
'The most you may purchase is' => self::ERROR_INSUFFICIENT_STOCK,
35+
'The requested qty is not available' => self::ERROR_INSUFFICIENT_STOCK,
36+
];
37+
38+
/**
39+
* Returns an error object
40+
*
41+
* @param string $message
42+
* @param int $cartItemPosition
43+
* @return Data\Error
44+
*/
45+
public function create(string $message, int $cartItemPosition = 0): Data\Error
46+
{
47+
return new Data\Error(
48+
$message,
49+
$this->getErrorCode($message),
50+
$cartItemPosition
51+
);
52+
}
53+
54+
/**
55+
* Get message error code.
56+
*
57+
* @param string $message
58+
* @return string
59+
*/
60+
private function getErrorCode(string $message): string
61+
{
62+
foreach (self::MESSAGE_CODES as $codeMessage => $code) {
63+
if (false !== stripos($message, $codeMessage)) {
64+
return $code;
65+
}
66+
}
67+
68+
/* If no code was matched, return the default one */
69+
return self::ERROR_UNDEFINED;
70+
}
71+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Cart;
9+
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
14+
use Magento\Quote\Api\CartManagementInterface;
15+
use Magento\Quote\Model\Quote;
16+
17+
/**
18+
* Get cart
19+
*/
20+
class GetCartForCheckout
21+
{
22+
/**
23+
* @var CheckCartCheckoutAllowance
24+
*/
25+
private CheckCartCheckoutAllowance $checkoutAllowance;
26+
27+
/**
28+
* @var GetCartForUser
29+
*/
30+
private GetCartForUser $getCartForUser;
31+
32+
/**
33+
* @param CheckCartCheckoutAllowance $checkoutAllowance
34+
* @param GetCartForUser $getCartForUser
35+
*/
36+
public function __construct(
37+
CheckCartCheckoutAllowance $checkoutAllowance,
38+
GetCartForUser $getCartForUser
39+
) {
40+
$this->checkoutAllowance = $checkoutAllowance;
41+
$this->getCartForUser = $getCartForUser;
42+
}
43+
44+
/**
45+
* Gets the cart for the user validated and configured for guest checkout if applicable
46+
*
47+
* @param string $cartHash
48+
* @param int|null $customerId
49+
* @param int $storeId
50+
* @return Quote
51+
* @throws GraphQlAuthorizationException
52+
* @throws GraphQlInputException
53+
* @throws GraphQlNoSuchEntityException
54+
*/
55+
public function execute(string $cartHash, ?int $customerId, int $storeId): Quote
56+
{
57+
try {
58+
$cart = $this->getCartForUser->execute($cartHash, $customerId, $storeId);
59+
} catch (NoSuchEntityException $e) {
60+
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
61+
}
62+
$this->checkoutAllowance->execute($cart);
63+
64+
if (null === $customerId || 0 === $customerId) {
65+
if (!$cart->getCustomerEmail()) {
66+
throw new GraphQlInputException(__("Guest email for cart is missing."));
67+
}
68+
$cart->setCheckoutMethod(CartManagementInterface::METHOD_GUEST);
69+
}
70+
71+
return $cart;
72+
}
73+
}

0 commit comments

Comments
 (0)