magento / magento2

Prior to making any Submission(s), you must sign an Adobe Contributor License Agreement, available here at: https://opensource.adobe.com/cla.html. All Submissions you make to Adobe Inc. and its affiliates, assigns and subsidiaries (collectively “Adobe”) are subject to the terms of the Adobe Contributor License Agreement.
http://www.magento.com
Open Software License 3.0
11.44k stars 9.29k forks source link

[GraphQl] Cart error messages are faulty #34546

Closed Hexmage closed 1 year ago

Hexmage commented 2 years ago

Preconditions (*)

  1. Magento 2.4.2+

Steps to reproduce (*)

  1. Create a cart
  2. Add 2 products to the cart with at least 4 quantities each.
  3. Set the quantity of added products below the quantity in the cart.
  4. Retrieve cart through graphql
    {
    cart(cart_id: "RQg4YPcQX1htp47j6GMpTKRshfY6SVm6") {
    items {
      id
      product {
        name
        sku
        stock_status
      }
      quantity
    }
    }
    }

Expected result (*)

  1. A error message which tells me which item in the cart causes the error. So that we can give correct feedback to the Customer.
  2. A cart with valid values for items.
  3. An error message for each issue with the cart.

Actual result (*)

1.

{
  "errors": [
    {
      "message": "The requested qty is not available",
      "extensions": {
        "category": "graphql-input"
      },
      "locations": [
        {
          "line": 7,
          "column": 5
        }
      ],
      "path": [
        "cart",
        "items",
        0
      ]
    }
  ],
  "data": {
    "cart": {
      "items": [
        null,
        {
          "id": "32",
          "product": {
            "name": "Strive Shoulder Pack",
            "sku": "24-MB04",
            "stock_status": "IN_STOCK"
          },
          "quantity": 3
        },
        {
          "id": "33",
          "product": {
            "name": "Joust Duffle Bag",
            "sku": "24-MB01",
            "stock_status": "IN_STOCK"
          },
          "quantity": 4
        }
      ]
    }
  }
}
  1. In the items node there is a null entry, this only shows up when there is an error. In default Venia this breaks the cart page.
  2. I assume the path node in the error node should reference the item it's affecting. It currently points to the above null value.
  3. Only the first error of the cart shows up.

Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

m2-assistant[bot] commented 2 years ago

Hi @Hexmage. Thank you for your report. To speed up processing of this issue, make sure that you provided the following information:

Make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, Add a comment to the issue:

@magento give me 2.4-develop instance - upcoming 2.4.x release

For more details, review the Magento Contributor Assistant documentation.

Add a comment to assign the issue: @magento I am working on this

To learn more about issue processing workflow, refer to the Code Contributions.


:clock10: You can find the schedule on the Magento Community Calendar page.

:telephone_receiver: The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, join the Community Contributions Triage session to discuss the appropriate ticket.

:movie_camera: You can find the recording of the previous Community Contributions Triage on the Magento Youtube Channel

:pencil2: Feel free to post questions/proposals/feedback related to the Community Contributions Triage process to the corresponding Slack Channel

m2-assistant[bot] commented 2 years ago

Hi @engcom-Hotel. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

engcom-Hotel commented 2 years ago

Hello @Hexmage,

Thanks for posting the issue!

I would like to suggest you add stock_status, so that it will give the exact situation of stock.

for eg: The below query:

{
  cart(cart_id: "5VrDt8LhknXPP3ugJuXZZerItlVDrtB0") {
    items {
      id
      product {
        name
        sku
        stock_status
      }
      quantity
    }
  }
}

Will return:

{
  "errors": [
    {
      "message": "Some of the products are out of stock.",
      "extensions": {
        "category": "graphql-input"
      },
      "locations": [
        {
          "line": 7,
          "column": 5
        }
      ],
      "path": [
        "cart",
        "items",
        0
      ]
    }
  ],
  "data": {
    "cart": {
      "items": [
        null,
        {
          "id": "12",
          "product": {
            "name": "Joust Duffle Bag",
            "sku": "24-MB01",
            "stock_status": "OUT_OF_STOCK"
          },
          "quantity": 1
        },
        {
          "id": "13",
          "product": {
            "name": "Strive Shoulder Pack",
            "sku": "24-MB04",
            "stock_status": "IN_STOCK"
          },
          "quantity": 1
        }
      ]
    }
  }
}

You can see stock_status as OUT_OF_STOCK where the product is out of stock.

Thanks

Hexmage commented 2 years ago

@engcom-Hotel But what if the stock of a product changes from 3 to 2 and I had 3 in my cart. stock_status won't help me identify what the problem is in that scenario.

It's nice that there are error messages in the cart response, but they need a second pass over. Because as they are now they aren't good enough.

engcom-Hotel commented 2 years ago

Hello @Hexmage,

Thanks for the reply!

This is the valid point, if the cart item is less in stock then proper handling is required. I have followed the below steps to reproduce the issue:

Updating the main description as well.

Thanks

github-jira-sync-bot commented 2 years ago

Unfortunately, not enough information was provided to create a Jira ticket. Please make sure you added the following label(s): Reproduced on 2.4.x, ^Area:.*

Once all required labels are present, please add Issue: Confirmed label again.

github-jira-sync-bot commented 2 years ago

:white_check_mark: Jira issue https://jira.corp.magento.com/browse/AC-1965 is successfully created for this GitHub issue.

m2-assistant[bot] commented 2 years ago

:white_check_mark: Confirmed by @engcom-Hotel. Thank you for verifying the issue.
Issue Available: @engcom-Hotel, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.

Hexmage commented 2 years ago

@engcom-Hotel I also consider the fact that a null object appears in the items node when an error occurs very crucial to resolve. As it currently breaks default Venia.

Usik2203 commented 2 years ago

@magento I am working on this

Hexmage commented 2 years ago

@Usik2203 I'd rather have something that has to be unique to identify the product, because the product name can be identical for products. Also your solution doesn't solve the null object that suddenly got added to the items array.

alitopaloglu commented 2 years ago

Any update about null value? I can still reproduce this on 2.4.3-p2

Hexmage commented 2 years ago

@alitopaloglu I've learned that the null value is the actual exception object. Which is handled by the resolver to make the error node in the response. But this node is never deleted after its handled. I'm currently testing some code on my own environment where I moved the Exception Object to a new node in the item that created it. But this will not work with default Venia.

PauloPhagula commented 2 years ago

Hi @Hexmage did you make any progress on this? I'm desperately looking for a solution.

Hexmage commented 2 years ago

@PauloPhagula Think they fixed it in https://github.com/magento/magento2-pwa which is a repo with pwa specific fixes because the normal magento repo doesn't update fast enough.

marwan-corals commented 2 years ago

Hello, Any Update on this error, its been setting here for months @m2-assistant

marwan-corals commented 2 years ago

@Hexmage I just checked and magento2-pwa didnt fix the issue either

Hexmage commented 2 years ago

@marwan-corals They sort of did. They added a new graphql endpoint for just errors. While this doesn't fix the fact that there is an empty error object in the cart, it does allow you to easier find out which errors are in the cart.

Personally I used a plugin on the function to add an error string element to each order_item with the raw exception message in there instead of the empty node.

marwan-corals commented 2 years ago

@Hexmage, thanks for the reply, but if the item is shown as null, how is this handled? also can you please share with me this plugin

marwan-corals commented 2 years ago

@Hexmage are you willing to help here ?

Hexmage commented 2 years ago

@marwan-corals The Plugin

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
declare(strict_types=1);

namespace Experius\CartFix\Plugin\Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\Uid;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Item as QuoteItem;
use Magento\QuoteGraphQl\Model\Cart\GetCartProducts;

/**
 * @inheritdoc
 */
class CartItems
{
    /**
     * @var GetCartProducts
     */
    private $getCartProducts;

    /** @var Uid */
    private $uidEncoder;

    /**
     * @param GetCartProducts $getCartProducts
     * @param Uid $uidEncoder
     */
    public function __construct(
        GetCartProducts $getCartProducts,
        Uid $uidEncoder
    ) {
        $this->getCartProducts = $getCartProducts;
        $this->uidEncoder = $uidEncoder;
    }

    /**
     * @inheritdoc
     */
    public function afterResolve($subject, $result, Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
    {
        if (!isset($value['model'])) {
            throw new LocalizedException(__('"model" value should be specified'));
        }
        /** @var Quote $cart */
        $cart = $value['model'];

        $itemsData = [];
        $cartProductsData = $this->getCartProductsData($cart);
        $cartItems = $cart->getAllVisibleItems();
        /** @var QuoteItem $cartItem */
        foreach ($cartItems as $cartItem) {
            $productId = $cartItem->getProduct()->getId();
            if (!isset($cartProductsData[$productId])) {
                $itemsData[] = new GraphQlNoSuchEntityException(
                    __("The product that was requested doesn't exist. Verify the product and try again.")
                );
                continue;
            }
            $productData = $cartProductsData[$productId];
            $errorMessages = null;
            if ($cart->getData('has_error')) {
                foreach ($cartItem->getErrorInfos() as $error) {
                    $errorMessages[] = $error;
                }
            }

            $itemsData[] = [
                'id' => $cartItem->getItemId(),
                'uid' => $this->uidEncoder->encode((string) $cartItem->getItemId()),
                'quantity' => $cartItem->getQty(),
                'product' => $productData,
                'errors' =>  $errorMessages,
                'model' => $cartItem,
            ];
        }
        return $itemsData;
    }

    /**
     * Get product data for cart items
     *
     * @param Quote $cart
     * @return array
     */
    private function getCartProductsData(Quote $cart): array
    {
        $products = $this->getCartProducts->execute($cart);
        $productsData = [];
        foreach ($products as $product) {
            $productsData[$product->getId()] = $product->getData();
            $productsData[$product->getId()]['model'] = $product;
            $productsData[$product->getId()]['uid'] = $this->uidEncoder->encode((string) $product->getId());
        }

        return $productsData;
    }
}

The schema.graphqls additions

interface CartItemInterface {
    errors: [Error]
}

type Error {
    origin: String
    type: Int
    message: String
}
alexmtch commented 2 years ago

They removed the module : https://github.com/magento/magento2-pwa/commit/96c5f5f2ed31865f0b87f096221ddb9245f194da

Hexmage commented 2 years ago

That explains a lot.

marwan-corals commented 2 years ago

Thanks, @Hexmage the provided code is helpful; one more note here is to add to di.xml

    <type name="Magento\QuoteGraphQl\Model\Resolver\CartItems">
        <plugin name="Magento_CartItems_Add_Source_Errors" type="PathTo\Your\Class\Resolver\CartItems" />
    </type>
engcom-Lima commented 2 years ago

Hi @Hexmage ,

Thanks for your contribution and collaboration.

I have tried to reproduce the issue in 2.4-develop but issue is not reproducible to me.

Followed below steps :

  1. Create a cart
  2. Add 2 products to the cart with at least 4 quantities each.
  3. Set the quantity of added products below the quantity in the cart from admin.
  4. Get cart details through graphql query:

    query {
    
    customerCart {
    id
    items {
      uid
      product {
        name
        sku
      }
      quantity
    }
    }
    }

    After running above query I am not getting any error message "message": "The requested qty is not available", as you have reported. Below is the screenshot for your reference: image If anything missing in above steps kindly provide the information. Please note that I did PR changes but the response of step 4 was same.

Please test it in latest 2.4-develop if you are facing any issue kindly provide the information.

Thanks

Hexmage commented 2 years ago

@engcom-Lima Feels like you don't have manage stock turned on. Because there should be an error message when the stock is below the available stock.

engcom-Lima commented 1 year ago

HI @Hexmage ,

I have tried to reproduce the issue in 2.4-develop and followed below steps but issue is not reproducible to me:

  1. Create a cart
  2. Add 2 products to the cart with at least 4 quantities each.
  3. Set the quantity of added products below the quantity in the cart from admin.
  4. Get cart details through graphql query:

    query {
    
    customerCart {
    id
    items {
      uid
      product {
        name
        sku
      }
      quantity
    }
    }
    }
  5. Also Stores >> configuration >> Catalog >> inventory >>Product Stock Options >> Set Yes in Manage Stock.

Kindly provide me more information inorder to reproduce the isssue. Also, please check in latest 2.4-develop and inform us whether issue is reproducible or not.

Thanks

engcom-Lima commented 1 year ago

Hi @Hexmage ,

Thank for your contribution and collaboration.

Please provide more information required to reproduce the issue.

Thanks