Skip to content

Commit

Permalink
Merge pull request #3555 from mirumee/3543/SKU_unique_validation
Browse files Browse the repository at this point in the history
Unique validation SKU when default variant create in GraphQL API
  • Loading branch information
maarcingebala committed Jan 7, 2019
2 parents 9b48cc9 + 19c9f55 commit 2983fe0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,4 @@ All notable, unreleased changes to this project will be documented in this file.
- Fixed the no shipping orders payment crash on Stripe - #3550 by @NyanKiyoshi
- Change TypeScript loader to speed up the build process - #3545 by @patrys
- Fix storybook dependencies conflict - #3544 by @dominik-zeglen
- Unique validation SKU when default variant create in GraphQL API - #3555 by @fowczarek
18 changes: 13 additions & 5 deletions saleor/graphql/product/mutations/products.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,8 +336,13 @@ def clean_sku(cls, product_type, cleaned_input, errors):
See the documentation for `has_variants` field for details:
http://docs.getsaleor.com/en/latest/architecture/products.html#product-types
"""
if not product_type.has_variants and not cleaned_input.get('sku'):
cls.add_error(errors, 'sku', 'This field cannot be blank.')
if not product_type.has_variants:
input_sku = cleaned_input.get('sku')
if not input_sku:
cls.add_error(errors, 'sku', 'This field cannot be blank.')
elif models.ProductVariant.objects.filter(sku=input_sku).exists():
cls.add_error(
errors, 'sku', 'Product with this SKU already exists.')

@classmethod
@transaction.atomic
Expand Down Expand Up @@ -377,9 +382,12 @@ class Meta:

@classmethod
def clean_sku(cls, product_type, cleaned_input, errors):
# SKU is an optional field in the product update mutation,
# so we explicitly skip the validation.
pass
input_sku = cleaned_input.get('sku')
if (not product_type.has_variants and
input_sku and
models.ProductVariant.objects.filter(sku=input_sku).exists()):
cls.add_error(
errors, 'sku', 'Product with this SKU already exists.')

@classmethod
@transaction.atomic
Expand Down
74 changes: 74 additions & 0 deletions tests/api/test_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,41 @@ def test_create_product_without_variants_sku_validation(
assert data['errors'][0]['message'] == 'This field cannot be blank.'


def test_create_product_without_variants_sku_duplication(
staff_api_client, product_type_without_variant, category,
permission_manage_products, product_with_default_variant):
query = QUERY_CREATE_PRODUCT_WITHOUT_VARIANTS

product_type = product_type_without_variant
product_type_id = graphene.Node.to_global_id(
'ProductType', product_type.pk)
category_id = graphene.Node.to_global_id(
'Category', category.pk)
product_name = 'test name'
product_description = 'description'
product_price = 10
quantity = 1
track_inventory = True
sku = '1234'

variables = {
'productTypeId': product_type_id,
'categoryId': category_id,
'name': product_name,
'description': product_description,
'price': product_price,
'sku': sku,
'quantity': quantity,
'trackInventory': track_inventory}

response = staff_api_client.post_graphql(
query, variables, permissions=[permission_manage_products])
content = get_graphql_content(response)
data = content['data']['productCreate']
assert data['errors'][0]['field'] == 'sku'
assert data['errors'][0]['message'] == 'Product with this SKU already exists.'


def test_update_product(
staff_api_client, category, non_default_category, product,
permission_manage_products):
Expand Down Expand Up @@ -751,6 +786,45 @@ def test_update_product_without_variants(
assert product['trackInventory'] == product_track_inventory


def test_update_product_without_variants_sku_duplication(
staff_api_client, product_with_default_variant,
permission_manage_products, product):
query = """
mutation updateProduct(
$productId: ID!,
$sku: String)
{
productUpdate(
id: $productId,
input: {
sku: $sku
})
{
product {
id
}
errors {
message
field
}
}
}"""
product = product_with_default_variant
product_id = graphene.Node.to_global_id('Product', product.pk)
product_sku = "123"

variables = {
'productId': product_id,
'sku': product_sku}

response = staff_api_client.post_graphql(
query, variables, permissions=[permission_manage_products])
content = get_graphql_content(response)
data = content['data']['productUpdate']
assert data['errors']
assert data['errors'][0]['field'] == 'sku'
assert data['errors'][0]['message'] == 'Product with this SKU already exists.'

def test_delete_product(staff_api_client, product, permission_manage_products):
query = """
mutation DeleteProduct($id: ID!) {
Expand Down
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def product_with_default_variant(product_type_without_variant, category):
name='Test product', price=Money('10.00', 'USD'),
product_type=product_type_without_variant, category=category)
ProductVariant.objects.create(
product=product, sku='123', track_inventory=True,
product=product, sku='1234', track_inventory=True,
quantity=100)
return product

Expand Down

0 comments on commit 2983fe0

Please sign in to comment.