Skip to content

Commit 735c909

Browse files
committed
ACP2E-3399: GraphQL Response for Order placement does not include the exception message
1 parent 03bea46 commit 735c909

File tree

10 files changed

+167
-109
lines changed

10 files changed

+167
-109
lines changed

app/code/Magento/QuoteGraphQl/Model/Cart/GetCartForCheckout.php

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1414
use Magento\Quote\Api\CartManagementInterface;
1515
use Magento\Quote\Model\Quote;
16-
use Magento\QuoteGraphQl\Model\ErrorMapper;
1716

1817
/**
1918
* Get cart
@@ -30,24 +29,16 @@ class GetCartForCheckout
3029
*/
3130
private GetCartForUser $getCartForUser;
3231

33-
/**
34-
* @var ErrorMapper
35-
*/
36-
private ErrorMapper $errorMapper;
37-
3832
/**
3933
* @param CheckCartCheckoutAllowance $checkoutAllowance
4034
* @param GetCartForUser $getCartForUser
41-
* @param ErrorMapper $errorMapper
4235
*/
4336
public function __construct(
4437
CheckCartCheckoutAllowance $checkoutAllowance,
45-
GetCartForUser $getCartForUser,
46-
ErrorMapper $errorMapper
38+
GetCartForUser $getCartForUser
4739
) {
4840
$this->checkoutAllowance = $checkoutAllowance;
4941
$this->getCartForUser = $getCartForUser;
50-
$this->errorMapper = $errorMapper;
5142
}
5243

5344
/**
@@ -72,11 +63,7 @@ public function execute(string $cartHash, ?int $customerId, int $storeId): Quote
7263

7364
if (null === $customerId || 0 === $customerId) {
7465
if (!$cart->getCustomerEmail()) {
75-
throw new GraphQlInputException(
76-
__("Guest email for cart is missing."),
77-
null,
78-
$this->errorMapper->getErrorMessageId('Guest email for cart is missing')
79-
);
66+
throw new GraphQlInputException(__("Guest email for cart is missing."));
8067
}
8168
$cart->setCheckoutMethod(CartManagementInterface::METHOD_GUEST);
8269
}

app/code/Magento/QuoteGraphQl/Model/ErrorMapper.php

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,25 @@ class ErrorMapper
1111
/**
1212
* Error message codes
1313
*/
14-
private const ERROR_CART_NOT_FOUND = 'CART_NOT_FOUND';
15-
private const ERROR_CART_NOT_ACTIVE = 'CART_NOT_ACTIVE';
16-
private const ERROR_GUEST_EMAIL_MISSING = 'GUEST_EMAIL_MISSING';
17-
private const ERROR_UNABLE_TO_PLACE_ORDER = 'UNABLE_TO_PLACE_ORDER';
18-
private const ERROR_UNDEFINED = 'UNDEFINED';
14+
public const ERROR_CART_NOT_FOUND = 'CART_NOT_FOUND';
15+
public const ERROR_CART_NOT_ACTIVE = 'CART_NOT_ACTIVE';
16+
public const ERROR_GUEST_EMAIL_MISSING = 'GUEST_EMAIL_MISSING';
17+
public const ERROR_UNABLE_TO_PLACE_ORDER = 'UNABLE_TO_PLACE_ORDER';
18+
public const ERROR_UNDEFINED = 'UNDEFINED';
1919

2020
/**
2121
* Error message codes ids
2222
*/
23-
private const ERROR_CART_NOT_FOUND_ID = 1001;
24-
private const ERROR_CART_NOT_ACTIVE_ID = 1002;
25-
private const ERROR_GUEST_EMAIL_MISSING_ID = 1003;
26-
private const ERROR_UNABLE_TO_PLACE_ORDER_ID = 1004;
27-
private const ERROR_UNDEFINED_ID = 1005;
23+
public const ERROR_CART_NOT_FOUND_ID = 1001;
24+
public const ERROR_CART_NOT_ACTIVE_ID = 1002;
25+
public const ERROR_GUEST_EMAIL_MISSING_ID = 1003;
26+
public const ERROR_UNABLE_TO_PLACE_ORDER_ID = 1004;
27+
public const ERROR_UNDEFINED_ID = 1005;
2828

2929
/**
3030
* List of error messages and codes ids.
3131
*/
32-
private const MESSAGE_IDS = [
32+
public const MESSAGE_IDS = [
3333
'Could not find a cart with ID' => self::ERROR_CART_NOT_FOUND_ID,
3434
'The cart isn\'t active' => self::ERROR_CART_NOT_ACTIVE_ID,
3535
'Guest email for cart is missing' => self::ERROR_GUEST_EMAIL_MISSING_ID,
@@ -47,7 +47,7 @@ class ErrorMapper
4747
/**
4848
* List of error message ids and codes.
4949
*/
50-
private const MESSAGE_CODE_IDS = [
50+
public const MESSAGE_CODE_IDS = [
5151
self::ERROR_CART_NOT_FOUND_ID => self::ERROR_CART_NOT_FOUND,
5252
self::ERROR_CART_NOT_ACTIVE_ID => self::ERROR_CART_NOT_ACTIVE,
5353
self::ERROR_GUEST_EMAIL_MISSING_ID => self::ERROR_GUEST_EMAIL_MISSING,
@@ -58,7 +58,7 @@ class ErrorMapper
5858
/**
5959
* List of error messages and codes.
6060
*/
61-
private const MESSAGE_CODES = [
61+
public const MESSAGE_CODES = [
6262
'Could not find a cart with ID' => self::ERROR_CART_NOT_FOUND,
6363
'The cart isn\'t active' => self::ERROR_CART_NOT_ACTIVE,
6464
'Guest email for cart is missing' => self::ERROR_GUEST_EMAIL_MISSING,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Copyright 2024 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model;
9+
10+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
12+
class QuoteException extends GraphQlInputException
13+
{
14+
/**
15+
* Get error category
16+
*
17+
* @return array
18+
*/
19+
public function getExtensions(): array
20+
{
21+
$extensions['category'] = $this->getCategory();
22+
if ($this->code) {
23+
$extensions['error_code'] = ErrorMapper::getMessageCode($this->code);
24+
}
25+
26+
return $extensions;
27+
}
28+
}

app/code/Magento/QuoteGraphQl/Model/Resolver/PlaceOrder.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Magento\GraphQl\Helper\Error\AggregateExceptionMessageFormatter;
1818
use Magento\QuoteGraphQl\Model\Cart\GetCartForCheckout;
1919
use Magento\QuoteGraphQl\Model\Cart\PlaceOrder as PlaceOrderModel;
20+
use Magento\QuoteGraphQl\Model\QuoteException;
2021
use Magento\Sales\Api\OrderRepositoryInterface;
2122
use Magento\SalesGraphQl\Model\Formatter\Order as OrderFormatter;
2223

@@ -62,7 +63,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
6263
__($exception->getMessage())
6364
);
6465
} catch (LocalizedException $exception) {
65-
throw $this->errorMessageFormatter->getFormatted(
66+
$exception = $this->errorMessageFormatter->getFormatted(
6667
$exception,
6768
__('Unable to place order: A server error stopped your order from being placed. ' .
6869
'Please try to place your order again'),
@@ -71,6 +72,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
7172
$context,
7273
$info
7374
);
75+
throw new QuoteException(__($exception->getMessage()), $exception, $exception->getCode());
7476
}
7577

7678
return [

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/PlaceOrderTest.php

Lines changed: 108 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2019 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

@@ -18,12 +18,14 @@
1818
use Magento\Quote\Test\Fixture\CustomerCart;
1919
use Magento\Quote\Test\Fixture\GuestCart as GuestCartFixture;
2020
use Magento\Quote\Test\Fixture\QuoteIdMask;
21+
use Magento\QuoteGraphQl\Model\ErrorMapper;
2122
use Magento\Sales\Api\OrderRepositoryInterface;
2223
use Magento\Sales\Model\ResourceModel\Order\CollectionFactory;
2324
use Magento\TestFramework\Fixture\Config;
2425
use Magento\TestFramework\Fixture\DataFixture;
2526
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
2627
use Magento\TestFramework\Helper\Bootstrap;
28+
use Magento\TestFramework\TestCase\GraphQl\ResponseContainsErrorsException;
2729
use Magento\TestFramework\TestCase\GraphQlAbstract;
2830
use Magento\Checkout\Test\Fixture\SetBillingAddress as SetBillingAddressFixture;
2931
use Magento\Checkout\Test\Fixture\SetDeliveryMethod as SetDeliveryMethodFixture;
@@ -139,18 +141,25 @@ public function testPlaceOrderIfCartIdIsEmpty()
139141
),
140142
DataFixture(QuoteIdMask::class, ['cart_id' => '$cart.id$'], 'quoteIdMask'),
141143
]
142-
public function testPlaceOrderWithNoItemsInCart()
144+
public function testPlaceOrderWithNoItemsInCart(): void
143145
{
144146
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
145147
$query = $this->getQuery($maskedQuoteId);
146-
147-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
148-
self::assertEquals(1, count($response['placeOrder']['errors']));
149-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
150-
self::assertEquals(
151-
'A server error stopped your order from being placed. Please try to place your order again.',
152-
$response['placeOrder']['errors'][0]['message']
153-
);
148+
try {
149+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
150+
} catch (ResponseContainsErrorsException $exception) {
151+
$exceptionData = $exception->getResponseData();
152+
self::assertEquals(1, count($exceptionData['errors']));
153+
self::assertEquals(
154+
'Unable to place order: A server error stopped your order from being placed.' .
155+
' Please try to place your order again',
156+
$exceptionData['errors'][0]['message']
157+
);
158+
self::assertEquals(
159+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
160+
$exceptionData['errors'][0]['extensions']['error_code']
161+
);
162+
}
154163
}
155164

156165
#[
@@ -173,13 +182,20 @@ public function testPlaceOrderWithNoShippingAddress()
173182
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
174183
$query = $this->getQuery($maskedQuoteId);
175184

176-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
177-
self::assertEquals(1, count($response['placeOrder']['errors']));
178-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
179-
self::assertEquals(
180-
'Some addresses can\'t be used due to the configurations for specific countries.',
181-
$response['placeOrder']['errors'][0]['message']
182-
);
185+
try {
186+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
187+
} catch (ResponseContainsErrorsException $exception) {
188+
$exceptionData = $exception->getResponseData();
189+
self::assertEquals(1, count($exceptionData['errors']));
190+
self::assertEquals(
191+
'Unable to place order: Some addresses can\'t be used due to the configurations for specific countries.',
192+
$exceptionData['errors'][0]['message']
193+
);
194+
self::assertEquals(
195+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
196+
$exceptionData['errors'][0]['extensions']['error_code']
197+
);
198+
}
183199
}
184200

185201
#[
@@ -203,13 +219,20 @@ public function testPlaceOrderWithNoShippingMethod()
203219
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
204220
$query = $this->getQuery($maskedQuoteId);
205221

206-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
207-
self::assertEquals(1, count($response['placeOrder']['errors']));
208-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
209-
self::assertEquals(
210-
'The shipping method is missing. Select the shipping method and try again.',
211-
$response['placeOrder']['errors'][0]['message']
212-
);
222+
try {
223+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
224+
} catch (ResponseContainsErrorsException $exception) {
225+
$exceptionData = $exception->getResponseData();
226+
self::assertEquals(1, count($exceptionData['errors']));
227+
self::assertEquals(
228+
'Unable to place order: The shipping method is missing. Select the shipping method and try again.',
229+
$exceptionData['errors'][0]['message']
230+
);
231+
self::assertEquals(
232+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
233+
$exceptionData['errors'][0]['extensions']['error_code']
234+
);
235+
}
213236
}
214237

215238
#[
@@ -237,13 +260,24 @@ public function testPlaceOrderWithNoBillingAddress()
237260
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
238261
$query = $this->getQuery($maskedQuoteId);
239262

240-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
241-
self::assertEquals(1, count($response['placeOrder']['errors']));
242-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
243-
self::assertStringContainsString(
244-
'Please check the billing address information.',
245-
$response['placeOrder']['errors'][0]['message']
246-
);
263+
try {
264+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
265+
} catch (ResponseContainsErrorsException $exception) {
266+
$exceptionData = $exception->getResponseData();
267+
self::assertEquals(1, count($exceptionData['errors']));
268+
self::assertEquals(
269+
'Unable to place order: Please check the billing address information.' .
270+
' "firstname" is required. Enter and try again. "lastname" is required. Enter and try again.' .
271+
' "street" is required. Enter and try again. "city" is required. ' .
272+
'Enter and try again. "telephone" is required. Enter and try again. ' .
273+
'"postcode" is required. Enter and try again. "countryId" is required. Enter and try again.',
274+
$exceptionData['errors'][0]['message']
275+
);
276+
self::assertEquals(
277+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
278+
$exceptionData['errors'][0]['extensions']['error_code']
279+
);
280+
}
247281
}
248282

249283
#[
@@ -272,13 +306,20 @@ public function testPlaceOrderWithNoPaymentMethod()
272306
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
273307
$query = $this->getQuery($maskedQuoteId);
274308

275-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
276-
self::assertEquals(1, count($response['placeOrder']['errors']));
277-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
278-
self::assertEquals(
279-
'Enter a valid payment method and try again.',
280-
$response['placeOrder']['errors'][0]['message']
281-
);
309+
try {
310+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
311+
} catch (ResponseContainsErrorsException $exception) {
312+
$exceptionData = $exception->getResponseData();
313+
self::assertEquals(1, count($exceptionData['errors']));
314+
self::assertEquals(
315+
'Unable to place order: Enter a valid payment method and try again.',
316+
$exceptionData['errors'][0]['message']
317+
);
318+
self::assertEquals(
319+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
320+
$exceptionData['errors'][0]['extensions']['error_code']
321+
);
322+
}
282323
}
283324

284325
#[
@@ -317,13 +358,20 @@ public function testPlaceOrderWithOutOfStockProduct()
317358
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
318359
$query = $this->getQuery($maskedQuoteId);
319360

320-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
321-
self::assertEquals(1, count($response['placeOrder']['errors']));
322-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
323-
self::assertEquals(
324-
'Some of the products are out of stock.',
325-
$response['placeOrder']['errors'][0]['message']
326-
);
361+
try {
362+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
363+
} catch (ResponseContainsErrorsException $exception) {
364+
$exceptionData = $exception->getResponseData();
365+
self::assertEquals(1, count($exceptionData['errors']));
366+
self::assertEquals(
367+
'Unable to place order: Some of the products are out of stock.',
368+
$exceptionData['errors'][0]['message']
369+
);
370+
self::assertEquals(
371+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
372+
$exceptionData['errors'][0]['extensions']['error_code']
373+
);
374+
}
327375
}
328376

329377
#[
@@ -362,13 +410,20 @@ public function testPlaceOrderWithOutOfStockProductWithDisabledInventoryCheck()
362410
$maskedQuoteId = DataFixtureStorageManager::getStorage()->get('quoteIdMask')->getMaskedId();
363411
$query = $this->getQuery($maskedQuoteId);
364412

365-
$response = $this->graphQlMutation($query, [], '', $this->getHeaderMap());
366-
self::assertEquals(1, count($response['placeOrder']['errors']));
367-
self::assertEquals('UNABLE_TO_PLACE_ORDER', $response['placeOrder']['errors'][0]['code']);
368-
self::assertEquals(
369-
'Enter a valid payment method and try again.',
370-
$response['placeOrder']['errors'][0]['message']
371-
);
413+
try {
414+
$this->graphQlMutation($query, [], '', $this->getHeaderMap());
415+
} catch (ResponseContainsErrorsException $exception) {
416+
$exceptionData = $exception->getResponseData();
417+
self::assertEquals(1, count($exceptionData['errors']));
418+
self::assertEquals(
419+
'Unable to place order: Enter a valid payment method and try again.',
420+
$exceptionData['errors'][0]['message']
421+
);
422+
self::assertEquals(
423+
ErrorMapper::ERROR_UNABLE_TO_PLACE_ORDER,
424+
$exceptionData['errors'][0]['extensions']['error_code']
425+
);
426+
}
372427
}
373428

374429
#[

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/MergeGuestOrderTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,6 @@ private function getPlaceOrderQuery(string $maskedQuoteId): string
210210
number,
211211
email
212212
}
213-
errors {
214-
message
215-
code
216-
}
217213
}
218214
}
219215
QUERY;

0 commit comments

Comments
 (0)