Skip to content

Commit ff84a75

Browse files
ENGCOM-3007: Mutations coupons #163
- Merge Pull Request magento/graphql-ce#163 from magento/graphql-ce:mutations-coupons - Merged commits: 1. ced2301 2. 6abc7e5 3. b6eaa1f 4. 1a077ac 5. 9cb459e 6. ba6dd12 7. 02c2bc0 8. 7f1148f 9. b6365e1 10. 3007b3a 11. 2a0a450 12. 462601c 13. 2f4767d 14. 343e463 15. 46b40b4 16. fc12cb7
2 parents 43dca41 + fc12cb7 commit ff84a75

File tree

7 files changed

+559
-16
lines changed

7 files changed

+559
-16
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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\Authorization;
9+
10+
use Magento\Authorization\Model\UserContextInterface;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
13+
use Magento\Quote\Api\CartRepositoryInterface;
14+
15+
/**
16+
* Service for checking that the shopping cart operations are allowed for current user
17+
*/
18+
class IsCartMutationAllowedForCurrentUser
19+
{
20+
/**
21+
* @var CartRepositoryInterface
22+
*/
23+
private $cartRepository;
24+
25+
/**
26+
* @var UserContextInterface
27+
*/
28+
private $userContext;
29+
30+
/**
31+
* @param UserContextInterface $userContext
32+
* @param CartRepositoryInterface $cartRepository
33+
*/
34+
public function __construct(
35+
UserContextInterface $userContext,
36+
CartRepositoryInterface $cartRepository
37+
) {
38+
$this->userContext = $userContext;
39+
$this->cartRepository = $cartRepository;
40+
}
41+
42+
/**
43+
* Check that the shopping cart operations are allowed for current user
44+
*
45+
* @param int $quoteId
46+
* @return bool
47+
* @throws GraphQlNoSuchEntityException
48+
*/
49+
public function execute(int $quoteId): bool
50+
{
51+
try {
52+
$quote = $this->cartRepository->get($quoteId);
53+
} catch (NoSuchEntityException $exception) {
54+
throw new GraphQlNoSuchEntityException(__($exception->getMessage()));
55+
}
56+
57+
$customerId = $quote->getCustomerId();
58+
59+
/* Guest cart, allow operations */
60+
if (!$customerId) {
61+
return true;
62+
}
63+
64+
/* If the quote belongs to the current customer allow operations */
65+
return $customerId == $this->userContext->getUserId();
66+
}
67+
}
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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\Resolver\Coupon;
9+
10+
use Magento\Framework\Exception\CouldNotSaveException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
16+
use Magento\Framework\GraphQl\Query\ResolverInterface;
17+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
18+
use Magento\Quote\Api\CouponManagementInterface;
19+
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
20+
use Magento\QuoteGraphQl\Model\Authorization\IsCartMutationAllowedForCurrentUser;
21+
22+
/**
23+
* @inheritdoc
24+
*/
25+
class ApplyCouponToCart implements ResolverInterface
26+
{
27+
/**
28+
* @var CouponManagementInterface
29+
*/
30+
private $couponManagement;
31+
32+
/**
33+
* @var MaskedQuoteIdToQuoteIdInterface
34+
*/
35+
private $maskedQuoteIdToQuoteId;
36+
37+
/**
38+
* @var IsCartMutationAllowedForCurrentUser
39+
*/
40+
private $isCartMutationAllowedForCurrentUser;
41+
42+
/**
43+
* @param CouponManagementInterface $couponManagement
44+
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToId
45+
* @param IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser
46+
*/
47+
public function __construct(
48+
CouponManagementInterface $couponManagement,
49+
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToId,
50+
IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser
51+
) {
52+
$this->couponManagement = $couponManagement;
53+
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToId;
54+
$this->isCartMutationAllowedForCurrentUser = $isCartMutationAllowedForCurrentUser;
55+
}
56+
57+
/**
58+
* @inheritdoc
59+
*/
60+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
61+
{
62+
if (!isset($args['input']['cart_id'])) {
63+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
64+
}
65+
$maskedCartId = $args['input']['cart_id'];
66+
67+
if (!isset($args['input']['coupon_code'])) {
68+
throw new GraphQlInputException(__('Required parameter "coupon_code" is missing'));
69+
}
70+
$couponCode = $args['input']['coupon_code'];
71+
72+
try {
73+
$cartId = $this->maskedQuoteIdToQuoteId->execute($maskedCartId);
74+
} catch (NoSuchEntityException $exception) {
75+
throw new GraphQlNoSuchEntityException(
76+
__('Could not find a cart with ID "%masked_cart_id"', ['masked_cart_id' => $maskedCartId])
77+
);
78+
}
79+
80+
if (false === $this->isCartMutationAllowedForCurrentUser->execute($cartId)) {
81+
throw new GraphQlAuthorizationException(
82+
__(
83+
'The current user cannot perform operations on cart "%masked_cart_id"',
84+
['masked_cart_id' => $maskedCartId]
85+
)
86+
);
87+
}
88+
89+
/* Check current cart does not have coupon code applied */
90+
$appliedCouponCode = $this->couponManagement->get($cartId);
91+
if (!empty($appliedCouponCode)) {
92+
throw new GraphQlInputException(
93+
__('A coupon is already applied to the cart. Please remove it to apply another')
94+
);
95+
}
96+
97+
try {
98+
$this->couponManagement->set($cartId, $couponCode);
99+
} catch (NoSuchEntityException $exception) {
100+
throw new GraphQlNoSuchEntityException(__($exception->getMessage()));
101+
} catch (CouldNotSaveException $exception) {
102+
throw new GraphQlInputException(__($exception->getMessage()));
103+
}
104+
105+
$data['cart']['applied_coupon'] = [
106+
'code' => $couponCode,
107+
];
108+
return $data;
109+
}
110+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
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\Resolver\Coupon;
9+
10+
use Magento\Framework\Exception\CouldNotDeleteException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
16+
use Magento\Framework\GraphQl\Query\ResolverInterface;
17+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
18+
use Magento\Quote\Api\CouponManagementInterface;
19+
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
20+
use Magento\QuoteGraphQl\Model\Authorization\IsCartMutationAllowedForCurrentUser;
21+
22+
/**
23+
* @inheritdoc
24+
*/
25+
class RemoveCouponFromCart implements ResolverInterface
26+
{
27+
/**
28+
* @var MaskedQuoteIdToQuoteIdInterface
29+
*/
30+
private $maskedQuoteIdToId;
31+
32+
/**
33+
* @var CouponManagementInterface
34+
*/
35+
private $couponManagement;
36+
37+
/**
38+
* @var IsCartMutationAllowedForCurrentUser
39+
*/
40+
private $isCartMutationAllowedForCurrentUser;
41+
42+
/**
43+
* @param CouponManagementInterface $couponManagement
44+
* @param IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser
45+
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToId
46+
*/
47+
public function __construct(
48+
CouponManagementInterface $couponManagement,
49+
IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser,
50+
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToId
51+
) {
52+
$this->couponManagement = $couponManagement;
53+
$this->isCartMutationAllowedForCurrentUser = $isCartMutationAllowedForCurrentUser;
54+
$this->maskedQuoteIdToId = $maskedQuoteIdToId;
55+
}
56+
57+
/**
58+
* @inheritdoc
59+
*/
60+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
61+
{
62+
if (!isset($args['input']['cart_id'])) {
63+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
64+
}
65+
$maskedCartId = $args['input']['cart_id'];
66+
67+
try {
68+
$cartId = $this->maskedQuoteIdToId->execute($maskedCartId);
69+
} catch (NoSuchEntityException $exception) {
70+
throw new GraphQlNoSuchEntityException(
71+
__('Could not find a cart with ID "%masked_cart_id"', ['masked_cart_id' => $maskedCartId])
72+
);
73+
}
74+
75+
if (false === $this->isCartMutationAllowedForCurrentUser->execute($cartId)) {
76+
throw new GraphQlAuthorizationException(
77+
__(
78+
'The current user cannot perform operations on cart "%masked_cart_id"',
79+
['masked_cart_id' => $maskedCartId]
80+
)
81+
);
82+
}
83+
84+
try {
85+
$this->couponManagement->remove($cartId);
86+
} catch (NoSuchEntityException $exception) {
87+
throw new GraphQlNoSuchEntityException(__($exception->getMessage()));
88+
} catch (CouldNotDeleteException $exception) {
89+
throw new GraphQlInputException(__($exception->getMessage()));
90+
}
91+
92+
$data['cart']['applied_coupon'] = [
93+
'code' => '',
94+
];
95+
return $data;
96+
}
97+
}

app/code/Magento/QuoteGraphQl/etc/schema.graphqls

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,35 @@
33

44
type Mutation {
55
createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user")
6+
applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Coupon\\ApplyCouponToCart")
7+
removeCouponFromCart(input: RemoveCouponFromCartInput): RemoveCouponFromCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Coupon\\RemoveCouponFromCart")
68
}
9+
10+
input ApplyCouponToCartInput {
11+
cart_id: String!
12+
coupon_code: String!
13+
}
14+
15+
type ApplyCouponToCartOutput {
16+
cart: Cart!
17+
}
18+
19+
type Cart {
20+
applied_coupon: AppliedCoupon
21+
}
22+
23+
type CartAddress {
24+
applied_coupon: AppliedCoupon
25+
}
26+
27+
type AppliedCoupon {
28+
code: String!
29+
}
30+
31+
input RemoveCouponFromCartInput {
32+
cart_id: String!
33+
}
34+
35+
type RemoveCouponFromCartOutput {
36+
cart: Cart
37+
}

0 commit comments

Comments
 (0)