Repository: saleor/saleor

Issue:
Return a variant price instead of the priceOverride
### What I'm trying to achieve
In my impression, `priceOverride` is an internal functionality which shouldn't be available in the API.
In addition, when I want to show a variant price I need to always introduce logic like:
```
let variantPrice = variants[0].priceOverride || product.price
```

### Describe a proposed solution
I propose to change the attribute `priceOverride` to `price` which shows product price when the override is empty.



Discussion:
I think we should offer both, the price override requiring product admin privileges.

Resolving patch:
diff --git a/saleor/graphql/product/types.py b/saleor/graphql/product/types.py
--- a/saleor/graphql/product/types.py
+++ b/saleor/graphql/product/types.py
@@ -90,6 +90,7 @@ class ProductVariant(CountableDjangoObjectType):
         Money,
         description="""Override the base price of a product if necessary.
         A value of `null` indicates that the default product price is used.""")
+    price = graphene.Field(Money, description="Price of the product variant.")
     attributes = graphene.List(
         SelectedAttribute,
         description='List of attributes assigned to this variant.')
@@ -114,6 +115,15 @@ def resolve_attributes(self, info):
     def resolve_margin(self, info):
         return get_margin_for_variant(self)
 
+    def resolve_price(self, info):
+        return (
+            self.price_override
+            if self.price_override is not None else self.product.price)
+
+    @permission_required('product.manage_products')
+    def resolve_price_override(self, info):
+        return self.price_override
+
 
 class ProductAvailability(graphene.ObjectType):
     available = graphene.Boolean()


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
@@ -1336,3 +1336,50 @@ def test_collection_image_query(user_api_client, collection):
     data = content['data']['collection']
     thumbnail_url = collection.background_image.thumbnail['120x120'].url
     assert data['backgroundImage']['url'] == thumbnail_url
+
+
+@pytest.mark.parametrize('product_price, variant_override, api_variant_price', [
+    (100, None, 100),
+    (100, 200, 200),
+    (100, 0, 0)
+])
+def test_product_variant_price(
+        product_price, variant_override, api_variant_price,
+        user_api_client, variant):
+    # Set price override on variant that is different than product price
+    product = variant.product
+    product.price = Money(amount=product_price, currency='USD')
+    product.save()
+    if variant_override is not None:
+        product.variants.update(
+            price_override=Money(amount=variant_override, currency='USD'))
+    else:
+        product.variants.update(price_override=None)
+    # Drop other variants
+    # product.variants.exclude(id=variant.pk).delete()
+
+    query = '''
+        query getProductVariants($id: ID!) {
+            product(id: $id) {
+                variants {
+                    edges {
+                        node {
+                            price {
+                                amount
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        '''
+    product_id = graphene.Node.to_global_id('Product', variant.product.id)
+    variables = json.dumps({'id': product_id})
+
+    response = user_api_client.post(
+        reverse('api'), {'query': query, 'variables': variables})
+    content = get_graphql_content(response)
+    assert 'errors' not in content
+    data = content['data']['product']
+    variant_price = data['variants']['edges'][0]['node']['price']
+    assert variant_price['amount'] == api_variant_price