Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.

Add Configurable Products to Cart Without Variant SKU #699

Merged
merged 7 commits into from
Jul 30, 2019

Conversation

pmclain
Copy link
Contributor

@pmclain pmclain commented May 11, 2019

Description (*)

  • Add a module method for building buy requests used for adding items to cart
  • Only return visible cart items
  • Add configurable products to cart using the parent sku and desired configurations, matching the behavior of the existing storefront

Fixed Issues (if relevant)

  1. Adjust adding configurable products to the shopping cart #438

Manual testing scenarios (*)

  1. Create empty cart
  2. Fetch configurable product information:
{
  products(
    search:"configurable"
    pageSize:10
  ) {
    items {
      sku
      ... on ConfigurableProduct {
        configurable_options {
          attribute_id
          attribute_code
          id
          label
          position
          product_id
          use_default
          values {
            default_label
            label
            store_label
            use_default_value
            value_index
          }
        }
      }
    }
  }
}
  1. Add configurable product to cart:
mutation addConfigurableProductToCart(
  $cart_id:String!
  $sku:String!
) {
  addConfigurableProductsToCart(
    input:{
      cart_id:$cart_id
      cart_items:{
        configurable_attributes:[{
            id:190
            value:271
          },
        	{
            id:191
            value:273
          }
        ]
        data:{
          sku:$sku
          quantity:1
        }
      }
    }
  ) {
    cart {
      items {
        id
        quantity
        product {
          sku
        }
        ... on ConfigurableCartItem {
          configurable_options {
            id
            option_label
            value_id
            value_label
          }
        }
      }
    }
  }
}

Contribution checklist (*)

  • Pull request has a meaningful description of its purpose
  • All commits are accompanied by meaningful commit messages
  • All new or changed code is covered with unit/integration tests (if applicable)
  • All automated tests passed successfully (all builds are green)

pmclain added 2 commits May 5, 2019 16:09
This allows product type graphql modules a method for managing how inputs are
mapped when buy requests are created.
Allows adding configurable products to cart in the same manner as the current
Magento storefront.

Fixes magento#438
@lenaorobei
Copy link
Contributor

lenaorobei commented Jun 25, 2019

@pmclain thank you for the contribution. Such kind of changes requires detailed architecture review.

@TomashKhamlai
Copy link
Contributor

Could you please merge 2.3-develop to this branch or commit cc65d3e and everything before it?
Cannot place order

{
  "errors": [
    {
      "message": "Unable to place order: Some addresses can't be used due to the configurations for specific countries.",
      "category": "graphql-input",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "placeOrder"
      ]
    }
  ],
  "data": {
    "placeOrder": null
  }
}

@TomashKhamlai
Copy link
Contributor

TomashKhamlai commented Jul 18, 2019

Maybe it is a mistake ConfigurableProductCartItemInput.configurable_attributes: [ConfigurableCartItemAttributesInput]!

mutation addConfigurableProductToCart(
  $cart_id: String!
  $sku: String!
) {
  addConfigurableProductsToCart(
    input: {
      cart_id: $cart_id
      cart_items: {
        configurable_attributes: [
          {
            id: 93
            value: 4
          }
          {
            id: 93
            value: 5
          }
          {
            id: 93
            value: 6
          }
          {
            id: 93
            value: 7
          }
        ]
        data: {
          sku: $sku
          quantity: 4
        }
      }
    }
  ) {
    cart {
      items {
        id
        quantity
        product {
          sku
        }
        ... on ConfigurableCartItem {
          configurable_options {
            id
            option_label
            value_id
            value_label
          }
        }
      }
    }
  }
}

On storefront we can select only one configuration. Your code acts the same like on storefront, but schema gives me falsy expectations.

@pmclain
Copy link
Contributor Author

pmclain commented Jul 24, 2019

@TomashKhamlai The schema needs to support multiple configurable attributes, since a configuration may have multiple configurable attributes required ie: size and color.

@naydav should we add input validation that throws an error when multiple inputs contain the same attribute id?

@m2-community-project
Copy link

@TomashKhamlai unfortunately, only members of the maintainers team are allowed to assign developers to the pull request

@pmclain
Copy link
Contributor Author

pmclain commented Jul 26, 2019

@TomashKhamlai I'm working on the merge. I'll give you a mention when ready.

CartItemRepositoryInterface::save trigger quote collection and save. The update
cart items resolver accepts multiple quote items and save the quote. Saving
each quote item increases the quote save by the number of items passed in the
update request.
@pmclain
Copy link
Contributor Author

pmclain commented Jul 27, 2019

@TomashKhamlai Merge complete. This is ready for QA. I added the same cart item update fix as in #396.

$result[] = [
'id' => $option['option_id'],
'option_label' => $option['label'],
'value_id' => $option['option_value'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{
  "errors": [
    {
      "debugMessage": "Notice: Undefined index: option_value in /shared/httpd/graphql-ce/graphql-ce/app/code/Magento/ConfigurableProductGraphQl/Model/Resolver/ConfigurableCartItemOptions.php on line 61",
      "message": "Internal server error",
      "category": "internal",
      "locations": [
        {
          "line": 9,
          "column": 9
        }
      ],
      "path": [
        "cart",
        "items",
        0,
        "configurable_options"
      ]
    }
  ],
  "data": {
    "cart": {
      "applied_coupon": null,
      "email": "[email protected]",
      "items": [
        null
      ],
      "prices": {
        "grand_total": {
          "value": 14.75,
          "currency": "USD"
        }
      },
      "shipping_addresses": [
        {
          "postcode": "90230"
        }
      ],
      "billing_address": {
        "postcode": "90230"
      }
    }
  }
}

The request was:

query viewCart(
  $cart_id: String!
) {
  cart(
    cart_id: $cart_id
  ) {
    applied_coupon {
      code
    }
    email
    items {
      ... on ConfigurableCartItem {
        configurable_options {
          id
          option_label
          value_id
          value_label
        }
        customizable_options {
          id
          is_required
          label
          sort_order
          values {
            id
            label
            price {
              type
              units
              value
            }
            value
          }
        }
      }
      product {
        sku
        stock_status

        ... on ConfigurableProduct {
          attribute_set_id
          color
          sku
          variants {
            attributes {
              code
              label
              value_index
            }
            product {
              options {
                option_id
                required
                sort_order
                title
                __typename
              }
              tier_prices {
                customer_group_id
                percentage_value
                qty
                value
                website_id
              }
              product_links {
                link_type
                linked_product_sku
                linked_product_type
                position
                sku
                __typename
              }
            }
          }
        }

        ... on SimpleProduct {
          gift_message_available
          attribute_set_id
          categories {
            __typename
            url_path
            url_key
            product_count
            path_in_store
            level
            display_mode
            path
          }
          websites {
            code
            default_group_id
            id
            is_default
            name
          }
          weight
          type_id
          canonical_url
          url_key
          url_path
          special_price
          tier_price
          tier_prices {
            customer_group_id
            percentage_value
            qty
            value
            website_id
          }
        }
      }
      quantity
    }
    prices {
      grand_total {
        value
        currency
      }
    }
    shipping_addresses {
      postcode
    }
    billing_address {
      postcode
    }
  }
}

@TomashKhamlai
Copy link
Contributor

Probably it is already reported. Just informing you. Also, it will help me in the future (#663)

{
  "errors": [
    {
      "debugMessage": "Cannot return null for non-nullable field ConfigurableCartItem.customizable_options.",
      "message": "Internal server error",
      "category": "internal",
      "locations": [
        {
          "line": 7,
          "column": 9
        }
      ],
      "path": [
        "cart",
        "items",
        0,
        "customizable_options"
      ]
    }
  ],
  "data": {
    "cart": {
      "items": [
        null
      ]
    }
  }
}

The request was

query viewCart (
  $cart_id: String!
) {
  cart(
    cart_id: $cart_id
  ) {
    items {
      ... on ConfigurableCartItem {
        quantity
        id
        customizable_options {
          id
          values {
            id
            value
          }
        }
        configurable_options {
          id
          value_id
        }
      }
    }
  }
}

@TomashKhamlai
Copy link
Contributor

TomashKhamlai commented Jul 29, 2019

Before changes in c7d9130 we had the problem which would sound like "The cart is not updating properly: new cart items are created instead of changing quantity while adding the same product to the cart. At the same time update of the first cart item do not trigger recalculation while update of the last one joins them back together.", but now it sounds like "The cart is not updating properly: and update of the first item can be mysteriously rolled back to the initial state by the update of the last cart item and cart items are never joined, while they should".

The problem sounds weird and can pollute the conversation here. I am thinking about excluding changes that are relative to mutation updateCartItem. Because it looks like a complex problem for me and can be addressed as a separate PR. @naydav hasn't approved this approach yet. But he approved that any problems related to updateCartItem can be reported as a separate issue. The main reason for it is that the problem became common for different types of products except for the simple product.

If you see any advantage of the approach that I suggested, please contact @naydav in Slack. Otherwise, feel free to continue with updateCartItem here in this PR. I will link this PR to the issues that I've described briefly.

@ghost
Copy link

ghost commented Jul 30, 2019

Hi @pmclain, thank you for your contribution!
Please, complete Contribution Survey, it will take less than a minute.
Your feedback will help us to improve contribution process.

@TomashKhamlai
Copy link
Contributor

We still have some failures. Mention m in comments if we need confirmation that problems were fixed.

@TomashKhamlai TomashKhamlai added QA failed and removed QA in progress We are checking labels Aug 2, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants