Repository: saleor/saleor

Issue:
ProductCreate weight mutation

![p1](https://user-images.githubusercontent.com/36409853/79555939-f2032000-80d2-11ea-88cc-5e1809e51ec5.PNG)
![p2](https://user-images.githubusercontent.com/36409853/79556174-4b6b4f00-80d3-11ea-96d7-f06ee76bf1ee.PNG)


productCreate mutation

I followed the "amount unit" as said in the comment, but returns a "'StringValue(value='10.00 kg')' value must be a float."
Sorry just a beginner


Discussion:
Hi @jkain88 field `weight` is made by two other fields
- `unit`
- `value`

Try sth like this:
```
mutation{
  productCreate(
    input:{
      attributes: []
      basePrice: "300"
      category: "Q2F0ZWdvcnk6Nw=="
      chargeTaxes: false
      descriptionJson: "{}"
      isPublished: true
      name: "PRODUCT"
      productType: "UHJvZHVjdFR5cGU6MTE="
      seo:{
        description: "DESC"
        title: "TITLE"
      }
      sku: "ABC"
      quantity: 300
      weight: {
        unit: "KG"
        value: 10.0
      }
    }
  ){
    product{
      id
      name
      weight{
        unit
        value
      }
    }
  }
}
```

/edit/
But even then it throws error. I will look into that.
any updates?
Hi @jkain88 
I am still debugging this error. It looks like `WeightScalar` is not working as expected. 
I will let you know when we fix this error. in the meanwhile, try to create products without weight param.
ok. thank you

Resolving patch:
diff --git a/saleor/graphql/core/scalars.py b/saleor/graphql/core/scalars.py
--- a/saleor/graphql/core/scalars.py
+++ b/saleor/graphql/core/scalars.py
@@ -1,6 +1,8 @@
 import decimal
 
 import graphene
+from graphql.language import ast
+from graphql.error import GraphQLError
 from measurement.measures import Weight
 
 from ...core.weight import convert_weight, get_default_weight_unit
@@ -34,14 +36,14 @@ def parse_value(value):
 class WeightScalar(graphene.Scalar):
     @staticmethod
     def parse_value(value):
-        # Expects value to be a string "amount unit" separated by a single
-        # space.
-        try:
-            value = decimal.Decimal(value)
-        except decimal.DecimalException:
-            return None
-        default_unit = get_default_weight_unit()
-        return Weight(**{default_unit: value})
+        weight = None
+        if isinstance(value, dict):
+            weight = Weight(**{value["unit"]: value["value"]})
+        else:
+            weight = WeightScalar.parse_decimal(value)
+        if not weight:
+            raise GraphQLError(f"Unsupported value: {value}")
+        return weight
 
     @staticmethod
     def serialize(weight):
@@ -54,4 +56,35 @@ def serialize(weight):
 
     @staticmethod
     def parse_literal(node):
-        return node
+        weight = None
+        if isinstance(node, ast.ObjectValue):
+            weight = WeightScalar.parse_literal_object(node)
+        else:
+            weight = WeightScalar.parse_decimal(node.value)
+        if not weight:
+            raise GraphQLError(f"Unsupported value: {node.value}")
+        return weight
+
+    @staticmethod
+    def parse_decimal(value):
+        try:
+            value = decimal.Decimal(value)
+        except decimal.DecimalException:
+            return None
+        default_unit = get_default_weight_unit()
+        return Weight(**{default_unit: value})
+
+    @staticmethod
+    def parse_literal_object(node):
+        value = 0
+        unit = get_default_weight_unit()
+
+        for field in node.fields:
+            if field.name.value == "value":
+                try:
+                    value = decimal.Decimal(field.value.value)
+                except decimal.DecimalException:
+                    raise GraphQLError(f"Unsupported value: {field.value.value}")
+            if field.name.value == "unit":
+                unit = field.value.value
+        return Weight(**{unit: value})


Test patch:
diff --git a/tests/api/test_product.py b/tests/api/test_product.py
--- a/tests/api/test_product.py
+++ b/tests/api/test_product.py
@@ -3961,3 +3961,159 @@ def test_update_or_create_variant_stocks_empty_stocks_data(variant, warehouses):
     stock = variant.stocks.first()
     assert stock.warehouse == warehouses[0]
     assert stock.quantity == 5
+
+
+# Because we use Scalars for Weight this test query tests only a scenario when weight
+# value is passed by a variable
+MUTATION_CREATE_PRODUCT_WITH_WEIGHT_GQL_VARIABLE = """
+mutation createProduct(
+        $productType: ID!,
+        $category: ID!
+        $name: String!,
+        $sku: String,
+        $basePrice: Decimal!
+        $weight: WeightScalar)
+    {
+        productCreate(
+            input: {
+                category: $category,
+                productType: $productType,
+                name: $name,
+                sku: $sku,
+                basePrice: $basePrice,
+                weight: $weight
+            })
+        {
+            product {
+                id
+                weight{
+                    value
+                    unit
+                }
+            }
+            productErrors {
+                message
+                field
+                code
+            }
+        }
+    }
+    """
+
+
+@pytest.mark.parametrize(
+    "weight, expected_weight_value, expected_weight_unit",
+    (
+        (11.11, 11.11, "kg"),
+        (11, 11.0, "kg"),
+        ("11.11", 11.11, "kg"),
+        ({"value": 11.11, "unit": "kg"}, 11.11, "kg",),
+        ({"value": 11, "unit": "g"}, 11.0, "g",),
+        ({"value": "11.11", "unit": "ounce"}, 11.11, "oz",),
+    ),
+)
+def test_create_product_with_weight_variable(
+    weight,
+    expected_weight_value,
+    expected_weight_unit,
+    staff_api_client,
+    category,
+    permission_manage_products,
+    product_type_without_variant,
+):
+    category_id = graphene.Node.to_global_id("Category", category.pk)
+    product_type_id = graphene.Node.to_global_id(
+        "ProductType", product_type_without_variant.pk
+    )
+    variables = {
+        "category": category_id,
+        "productType": product_type_id,
+        "name": "Test",
+        "sku": "23434",
+        "basePrice": Decimal("19"),
+        "weight": weight,
+    }
+    response = staff_api_client.post_graphql(
+        MUTATION_CREATE_PRODUCT_WITH_WEIGHT_GQL_VARIABLE,
+        variables,
+        permissions=[permission_manage_products],
+    )
+    content = get_graphql_content(response)
+    result_weight = content["data"]["productCreate"]["product"]["weight"]
+    assert result_weight["value"] == expected_weight_value
+    assert result_weight["unit"] == expected_weight_unit
+
+
+@pytest.mark.parametrize(
+    "weight, expected_weight_value, expected_weight_unit",
+    (
+        ("11.11", 11.11, "kg"),
+        ("11", 11.0, "kg"),
+        ('"11.11"', 11.11, "kg"),
+        ('{value: 11.11, unit: "kg"}', 11.11, "kg",),
+        ('{value: 11, unit: "g"}', 11.0, "g",),
+        ('{value: "11.11", unit: "ounce"}', 11.11, "oz",),
+    ),
+)
+def test_create_product_with_weight_input(
+    weight,
+    expected_weight_value,
+    expected_weight_unit,
+    staff_api_client,
+    category,
+    permission_manage_products,
+    product_type_without_variant,
+):
+    # Because we use Scalars for Weight this test query tests only a scenario when
+    # weight value is passed by directly in input
+    query = f"""
+    mutation createProduct(
+            $productType: ID!,
+            $category: ID!
+            $name: String!,
+            $sku: String,
+            $basePrice: Decimal!)
+        {{
+            productCreate(
+                input: {{
+                    category: $category,
+                    productType: $productType,
+                    name: $name,
+                    sku: $sku,
+                    basePrice: $basePrice,
+                    weight: {weight}
+                }})
+            {{
+                product {{
+                    id
+                    weight{{
+                        value
+                        unit
+                    }}
+                }}
+                productErrors {{
+                    message
+                    field
+                    code
+                }}
+            }}
+        }}
+    """
+    category_id = graphene.Node.to_global_id("Category", category.pk)
+    product_type_id = graphene.Node.to_global_id(
+        "ProductType", product_type_without_variant.pk
+    )
+    variables = {
+        "category": category_id,
+        "productType": product_type_id,
+        "name": "Test",
+        "sku": "23434",
+        "basePrice": Decimal("19"),
+    }
+    response = staff_api_client.post_graphql(
+        query, variables, permissions=[permission_manage_products],
+    )
+    content = get_graphql_content(response)
+    result_weight = content["data"]["productCreate"]["product"]["weight"]
+    assert result_weight["value"] == expected_weight_value
+    assert result_weight["unit"] == expected_weight_unit