diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php index 7a9bdd926764c..48711ec38c4f8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php @@ -56,6 +56,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value 'value' => $cartTotals->getSubtotalWithDiscount(), 'currency' => $currency ], 'applied_taxes' => $this->getAppliedTaxes($cartTotals, $currency), + 'discount' => $this->getDiscount($cartTotals, $currency), 'model' => $quote ]; } @@ -84,4 +85,22 @@ private function getAppliedTaxes(Total $total, string $currency): array } return $appliedTaxesData; } + + /** + * Returns information about an applied discount + * + * @param Total $total + * @param string $currency + * @return array|null + */ + private function getDiscount(Total $total, string $currency) + { + if ($total->getDiscountAmount() === 0) { + return null; + } + return [ + 'label' => explode(', ', $total->getDiscountDescription()), + 'amount' => ['value' => $total->getDiscountAmount(), 'currency' => $currency] + ]; + } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 02d94231b7570..5a5d8cf60702e 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -146,6 +146,7 @@ type CartPrices { grand_total: Money subtotal_including_tax: Money subtotal_excluding_tax: Money + discount: CartDiscount subtotal_with_discount_excluding_tax: Money applied_taxes: [CartTaxItem] } @@ -155,6 +156,11 @@ type CartTaxItem { label: String! } +type CartDiscount { + amount: Money! + label: [String!]! +} + type SetPaymentMethodOnCartOutput { cart: Cart! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartDiscountTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartDiscountTest.php new file mode 100644 index 0000000000000..37c53a62f7d39 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/CartDiscountTest.php @@ -0,0 +1,123 @@ +getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetDiscountInformation() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $discountResponse = $response['cart']['prices']['discount']; + self::assertEquals(-10, $discountResponse['amount']['value']); + self::assertEquals(['50% Off for all orders'], $discountResponse['label']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/Checkout/_files/discount_10percent_generalusers.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php + */ + public function testGetDiscountInformationWithTwoRulesApplied() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + $discountResponse = $response['cart']['prices']['discount']; + self::assertEquals(-11, $discountResponse['amount']['value']); + self::assertEquals(['50% Off for all orders', 'Test Coupon for General'], $discountResponse['label']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/customer/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetDiscountInformationWithNoRulesApplied() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + self::assertEquals(null, $response['cart']['prices']['discount']); + } + + /** + * Generates GraphQl query for retrieving cart discount + * + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return <<customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartDiscountTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartDiscountTest.php new file mode 100644 index 0000000000000..4dc02c343d707 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/CartDiscountTest.php @@ -0,0 +1,101 @@ +getMaskedQuoteIdByReservedOrderId = $objectManager->get(GetMaskedQuoteIdByReservedOrderId::class); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetDiscountInformation() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + $discountResponse = $response['cart']['prices']['discount']; + self::assertEquals(-10, $discountResponse['amount']['value']); + self::assertEquals(['50% Off for all orders'], $discountResponse['label']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/SalesRule/_files/coupon_code_with_wildcard.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/apply_coupon.php + */ + public function testGetDiscountInformationWithTwoRulesApplied() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + $discountResponse = $response['cart']['prices']['discount']; + self::assertEquals(-15, $discountResponse['amount']['value']); + self::assertEquals(['50% Off for all orders', '5$ fixed discount on whole cart'], $discountResponse['label']); + } + + /** + * @magentoApiDataFixture Magento/GraphQl/Catalog/_files/simple_product.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/guest/create_empty_cart.php + * @magentoApiDataFixture Magento/GraphQl/Quote/_files/add_simple_product.php + */ + public function testGetDiscountInformationWithNoRulesApplied() + { + $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_quote'); + $query = $this->getQuery($maskedQuoteId); + $response = $this->graphQlQuery($query); + self::assertEquals(null, $response['cart']['prices']['discount']); + } + + /** + * Generates GraphQl query for retrieving cart discount. + * + * @param string $maskedQuoteId + * @return string + */ + private function getQuery(string $maskedQuoteId): string + { + return << 'Test Coupon for General', 'is_active' => true, + 'store_labels' => [0 => 'Test Coupon for General'], 'website_ids' => [ \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get( \Magento\Store\Model\StoreManagerInterface::class diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php new file mode 100644 index 0000000000000..0735307b0bfbf --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon.php @@ -0,0 +1,55 @@ +get(RuleRepositoryInterface::class); +/** @var DataObjectHelper $dataObjectHelper */ +$dataObjectHelper = Bootstrap::getObjectManager()->get(DataObjectHelper::class); +$ruleLabel = $objectManager->create(RuleLabelInterface::class); +$ruleLabelFactory = $objectManager->get(RuleLabelFactory::class); + + +/** @var RuleData $salesRule */ +$salesRule = $objectManager->create(RuleData::class); +/** @var RuleLabelInterface $ruleLabel */ +$ruleLabel = $ruleLabelFactory->create(); +$ruleLabel->setStoreId(0); +$ruleLabel->setStoreLabel('50% Off for all orders'); +$ruleData = [ + 'name' => '50% Off for all orders', + 'is_active' => 1, + 'customer_group_ids' => [CustomerGroupManagement::NOT_LOGGED_IN_ID, 1], + 'coupon_type' => RuleData::COUPON_TYPE_NO_COUPON, + 'conditions' => [], + 'simple_action' => 'by_percent', + 'discount_amount' => 50, + 'discount_step' => 0, + 'website_ids' => [ + $objectManager->get( + StoreManagerInterface::class + )->getWebsite()->getId(), + ], + 'discount_qty' => 0, + 'apply_to_shipping' => 1, + 'simple_free_shipping' => 1, + 'stop_rules_processing' => 0 +]; +$dataObjectHelper->populateWithArray($salesRule, $ruleData, RuleInterface::class); +$salesRule->setStoreLabels([$ruleLabel]); + +$ruleRepository->save($salesRule); diff --git a/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon_rollback.php b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon_rollback.php new file mode 100644 index 0000000000000..b94365c4a2c2b --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/GraphQl/Quote/_files/cart_rule_discount_no_coupon_rollback.php @@ -0,0 +1,21 @@ +get(RuleRepositoryInterface::class); +/** @var RuleCollectionFactory $ruleCollectionFactory */ +$ruleCollectionFactory = $objectManager->get(RuleCollectionFactory::class); +$ruleCollection = $ruleCollectionFactory->create(); + +foreach ($ruleCollection->getItems() as $rule) { + $ruleRepository->deleteById($rule->getRuleId()); +} diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_100_percent_off_rollback.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_100_percent_off_rollback.php index c7d95455c78d5..e747cc38522a7 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_100_percent_off_rollback.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/cart_rule_100_percent_off_rollback.php @@ -5,11 +5,19 @@ */ declare(strict_types=1); +use Magento\Framework\Registry; +use Magento\SalesRule\Api\RuleRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +$objectManager = Bootstrap::getObjectManager(); /** @var Magento\Framework\Registry $registry */ -$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); +$registry = Bootstrap::getObjectManager()->get(Registry::class); +/** @var RuleRepositoryInterface $ruleRepository */ +$ruleRepository = $objectManager->get(RuleRepositoryInterface::class); /** @var Magento\SalesRule\Model\Rule $rule */ -$rule = $registry->registry('cart_rule_100_percent_off'); -if ($rule) { - $rule->delete(); +$ruleId = $registry->registry('Magento/SalesRule/_files/cart_rule_100_percent_off'); + +if ($ruleId) { + $ruleRepository->deleteById($ruleId); } diff --git a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupon_code_with_wildcard.php b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupon_code_with_wildcard.php index 9005284f984cf..61fe3e9ea74f1 100644 --- a/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupon_code_with_wildcard.php +++ b/dev/tests/integration/testsuite/Magento/SalesRule/_files/coupon_code_with_wildcard.php @@ -27,6 +27,7 @@ 'discount_amount' => 5, 'discount_step' => 0, 'stop_rules_processing' => 1, + 'store_labels' => [0 => '5$ fixed discount on whole cart'], 'website_ids' => [ $objectManager->get(StoreManagerInterface::class)->getWebsite()->getId(), ],