internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: saleor/saleor

Issue:
Sales with products applied to wrong products
- Create a sale in discounts and add a product to it.
- The discount is applied to an other product.

The system is using the product pk (not the product variant pk) for calculating the discount.
So the discount is applied to the product with variant pk equal to product pk.



Discussion:

Resolving patch:
diff --git a/saleor/discount/models.py b/saleor/discount/models.py
--- a/saleor/discount/models.py
+++ b/saleor/discount/models.py
@@ -265,10 +265,9 @@ def _product_has_category_discount(self, product, discounted_categories):
         return False
 
     def modifier_for_variant(self, variant):
-        check_price = variant.get_price_per_item()
         discounted_products = [p.pk for p in self.products.all()]
         discounted_categories = list(self.categories.all())
-        if discounted_products and variant.pk not in discounted_products:
+        if discounted_products and variant.product.pk not in discounted_products:
             raise NotApplicable('Discount not applicable for this product')
         if (discounted_categories and not
             self._product_has_category_discount(


Test patch:
diff --git a/saleor/discount/test_discounts.py b/saleor/discount/test_discounts.py
--- a/saleor/discount/test_discounts.py
+++ b/saleor/discount/test_discounts.py
@@ -206,3 +206,20 @@ def test_products_voucher_checkout_discount_not(settings, monkeypatch, prices,
     checkout = Mock(cart=Mock())
     discount = voucher.get_discount_for_checkout(checkout)
     assert discount.amount == Price(expected_value, currency='USD')
+
+
+@pytest.mark.django_db
+def test_sale_applies_to_correct_products():
+    product = Product.objects.create(name='Test Product', price=10, weight=1,
+                                     description='', pk=10)
+    variant = ProductVariant.objects.create(product=product, sku='firstvar')
+    product2 = Product.objects.create(name='Second product', price=15, weight=1,
+                                      description='')
+    sec_variant = ProductVariant.objects.create(product=product2, sku='secvar',
+                                                pk=10)
+    sale = Sale.objects.create(name='Test sale', value=5, type=Sale.FIXED)
+    sale.products.add(product)
+    assert product2 not in sale.products.all()
+    assert sale.modifier_for_variant(variant).amount == Price(net=5, currency='USD')
+    with pytest.raises(NotApplicable):
+        sale.modifier_for_variant(sec_variant)
Repository: saleor/saleor

Issue:
Drop file field in Attributes
This field makes no sense for now, attribute value should contain only text value and optional color hex value.


Discussion:

Resolving patch:
diff --git a/saleor/product/migrations/0025_auto_20161219_0517.py b/saleor/product/migrations/0025_auto_20161219_0517.py
new file mode 100644
--- /dev/null
+++ b/saleor/product/migrations/0025_auto_20161219_0517.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.3 on 2016-12-19 11:17
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('product', '0024_migrate_json_data'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='attributechoicevalue',
+            name='image',
+        )
+    ]
diff --git a/saleor/product/models/base.py b/saleor/product/models/base.py
--- a/saleor/product/models/base.py
+++ b/saleor/product/models/base.py
@@ -360,9 +360,6 @@ class AttributeChoiceValue(models.Model):
         max_length=7,
         validators=[RegexValidator('^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$')],
         blank=True)
-    image = VersatileImageField(
-        pgettext_lazy('Attribute choice value field', 'image'),
-        upload_to='attributes', blank=True, null=True)
     attribute = models.ForeignKey(ProductAttribute, related_name='values')
 
     def __str__(self):


Test patch:
Repository: saleor/saleor

Issue:
`StockManage.decrease_stock` incorrectly sets quantity
*Steps to Reproduce*

* Create single product variant with stock (e.g. 100 quantity, 10 allocated).
* Create an order for a single item.
* Make a note of the quantity and allocated quantity (e.g. 100 quantity, 11 allocated).
* Mark the item as shipped in the dashboard.

*Expected behaviour*

Stock item quantity to be decremented by order item quantity, quantity allocated to be decremented by order item quantity (e.g. 99 quantity, 10 allocated).

*Actual Behaviour*

Stock item quantity is set to quantity_allocated - order item quantity. (e.g. 10 quantity, 10 allocated) and is effectively out of stock. 

The `decrease_stock` method is incorrectly overwriting `stock.quantity` with `stock.quantity_allocated`:

```
    def decrease_stock(self, stock, quantity):
        stock.quantity = F('quantity_allocated') - quantity 
        stock.quantity_allocated = F('quantity_allocated') - quantity
        stock.save(update_fields=['quantity', 'quantity_allocated'])
```



Discussion:

Resolving patch:
diff --git a/saleor/product/models/base.py b/saleor/product/models/base.py
--- a/saleor/product/models/base.py
+++ b/saleor/product/models/base.py
@@ -292,7 +292,7 @@ def deallocate_stock(self, stock, quantity):
         stock.save(update_fields=['quantity_allocated'])
 
     def decrease_stock(self, stock, quantity):
-        stock.quantity = F('quantity_allocated') - quantity
+        stock.quantity = F('quantity') - quantity
         stock.quantity_allocated = F('quantity_allocated') - quantity
         stock.save(update_fields=['quantity', 'quantity_allocated'])
 


Test patch:
diff --git a/tests/test_product.py b/tests/test_product.py
--- a/tests/test_product.py
+++ b/tests/test_product.py
@@ -22,6 +22,28 @@ def test_stock_allocator(product_in_stock):
     assert stock.quantity_allocated == 1
 
 
+def test_decrease_stock(product_in_stock):
+    stock = product_in_stock.variants.first().stock.first()
+    stock.quantity = 100
+    stock.quantity_allocated = 80
+    stock.save()
+    models.Stock.objects.decrease_stock(stock, 50)
+    stock.refresh_from_db()
+    assert stock.quantity == 50
+    assert stock.quantity_allocated == 30
+
+
+def test_deallocate_stock(product_in_stock):
+    stock = product_in_stock.variants.first().stock.first()
+    stock.quantity = 100
+    stock.quantity_allocated = 80
+    stock.save()
+    models.Stock.objects.deallocate_stock(stock, 50)
+    stock.refresh_from_db()
+    assert stock.quantity == 100
+    assert stock.quantity_allocated == 30
+
+
 def test_product_page_redirects_to_correct_slug(client, product_in_stock):
     uri = product_in_stock.get_absolute_url()
     uri = uri.replace(product_in_stock.get_slug(), 'spanish-inquisition')
Repository: saleor/saleor

Issue:
Add search results page with new design
Search results page should be rendered as it's designed:
![image](https://cloud.githubusercontent.com/assets/1754812/21310830/5564677e-c5e4-11e6-853b-e246d14ede34.png)

For now facetting will be not supported. 


Discussion:

Resolving patch:
diff --git a/saleor/order/views.py b/saleor/order/views.py
--- a/saleor/order/views.py
+++ b/saleor/order/views.py
@@ -116,7 +116,7 @@ def cancel_payment(request, order):
 
 def create_password(request, token):
     if request.user.is_authenticated():
-        return redirect('order:detials', token=token)
+        return redirect('order:details', token=token)
     order = get_object_or_404(Order, token=token)
     email = order.user_email
     form_data = request.POST.copy()
diff --git a/saleor/search/views.py b/saleor/search/views.py
--- a/saleor/search/views.py
+++ b/saleor/search/views.py
@@ -5,7 +5,7 @@
 from django.http import Http404
 from django.shortcuts import render
 from .forms import SearchForm
-from ..product.utils import products_with_details
+from ..product.utils import products_with_details, products_with_availability
 
 
 def paginate_results(results, get_data, paginate_by=25):
@@ -23,6 +23,10 @@ def search(request):
     if form.is_valid():
         visible_products = products_with_details(request.user)
         results = form.search(model_or_queryset=visible_products)
+        results = products_with_availability(
+            results, discounts=request.discounts,
+            local_currency=request.currency)
+        results = list(results)
         page = paginate_results(results, request.GET, settings.PAGINATE_BY)
     else:
         page = form.no_query_found()


Test patch:
Repository: saleor/saleor

Issue:
are product class labels switched?
Hello,
I'm looking at the new product class feature.

About the labels ... should not be the other way around?
https://github.com/mirumee/saleor/blob/master/saleor/dashboard/product/forms.py#L53-L59

![schermata del 2016-12-29 17-05-55](https://cloud.githubusercontent.com/assets/650691/21547927/6e6023b4-cde9-11e6-92a3-b1b16fa41ab1.png)

![schermata del 2016-12-29 17-06-31](https://cloud.githubusercontent.com/assets/650691/21547913/592f5636-cde9-11e6-83b3-40160b51b2b5.png)






Discussion:

Resolving patch:
diff --git a/saleor/dashboard/product/forms.py b/saleor/dashboard/product/forms.py
--- a/saleor/dashboard/product/forms.py
+++ b/saleor/dashboard/product/forms.py
@@ -51,10 +51,10 @@ class Meta:
         model = ProductClass
         exclude = []
         labels = {
-            'product_attributes': pgettext_lazy(
+            'variant_attributes': pgettext_lazy(
                 'Product class form label',
                 'Attributes specific to each variant'),
-            'variant_attributes': pgettext_lazy(
+            'product_attributes': pgettext_lazy(
                 'Product class form label',
                 'Attributes common to all variants')}
 


Test patch:
Repository: saleor/saleor

Issue:
Improve cart page styles
Cart page styles should look like they were designed:
![image](https://cloud.githubusercontent.com/assets/1754812/21525524/2775db72-cd1e-11e6-9095-e85da9c421bb.png)



Discussion:

Resolving patch:
diff --git a/saleor/cart/views.py b/saleor/cart/views.py
--- a/saleor/cart/views.py
+++ b/saleor/cart/views.py
@@ -73,7 +73,9 @@ def update(request, cart, variant_id):
         form.save()
         response = {'productId': variant_id,
                     'subtotal': 0,
-                    'total': 0}
+                    'total': 0,
+                    'cart': cart.quantity,
+                    'cart_length': len(cart)}
         updated_line = cart.get_line(form.cart_line.variant)
         if updated_line:
             response['subtotal'] = currencyfmt(


Test patch:
Repository: saleor/saleor

Issue:
Add checkout steps navigation
Now there's no explicit navigation. Using browser back button can be dangerous in some cases and it's not a common behavior in ecommerce


Discussion:

Resolving patch:
diff --git a/saleor/order/views.py b/saleor/order/views.py
--- a/saleor/order/views.py
+++ b/saleor/order/views.py
@@ -133,5 +133,5 @@ def create_password(request, token):
         if auth_user is not None:
             auth.login(request, auth_user)
         return redirect('order:details', token=token)
-    ctx = {'form': form, 'email': email}
+    ctx = {'form': form, 'email': email, 'order': order}
     return TemplateResponse(request, 'order/create_password.html', ctx)


Test patch:
Repository: saleor/saleor

Issue:
no_query_found method is missing.
Hello,
the user gets an error if he submits the search form without a query.
There is not "no_query_found" method inside SearchForm.

https://github.com/mirumee/saleor/blob/35956e20a85b66abc95e08491f38fa69d74d5f12/saleor/search/views.py#L28






Discussion:
Thank you @itbabu, we'll fix it soon.

Resolving patch:
diff --git a/saleor/search/views.py b/saleor/search/views.py
--- a/saleor/search/views.py
+++ b/saleor/search/views.py
@@ -23,10 +23,11 @@ def search(request):
     if form.is_valid():
         visible_products = products_with_details(request.user)
         results = form.search(model_or_queryset=visible_products)
-        page = paginate_results(results, request.GET, settings.PAGINATE_BY)
+        query = form.cleaned_data.get('q', '')
     else:
-        page = form.no_query_found()
-    query = form.cleaned_data['q']
+        results = []
+        query = ''
+    page = paginate_results(results, request.GET, settings.PAGINATE_BY)
     ctx = {
         'query': query,
         'results': page,


Test patch:
Repository: saleor/saleor

Issue:
Links to Product with preselected variant attributes
It would be nice to have links to product with selected variant attributes, even if there is no such varriant in database. This could be used for links in wishlist.
Use case:

1. User selects on product_details view product which is currently not available
2. User add it to wishlist
3. When clicking on this product in wishlist view
4. Details page should show product with chosen attributes



Discussion:
@artursmet @maciekjablonski  What do you think about this feature? Any missing points?

It looks good, we can serialize attributes set in GET variables and set initial state for variant selector

Resolving patch:
diff --git a/saleor/product/utils.py b/saleor/product/utils.py
--- a/saleor/product/utils.py
+++ b/saleor/product/utils.py
@@ -5,8 +5,13 @@
 from ..cart.utils import get_cart_from_request, get_or_create_cart_from_request
 from ..core.utils import to_local_currency
 from .forms import get_form_class_for_product
-from .models.utils import get_attributes_display_map
 from .models import Product
+from .models.utils import get_attributes_display_map
+
+try:
+    from urllib.parse import urlencode
+except ImportError:
+    from urllib import urlencode
 
 
 def products_visible_to_user(user):
@@ -128,7 +133,7 @@ def get_variant_picker_data(product, discounts=None):
             'pk': attribute.pk,
             'display': attribute.display,
             'name': attribute.name,
-            'values': [{'pk': value.pk, 'display': value.display}
+            'values': [{'pk': value.pk, 'display': value.display, 'slug': value.slug}
                        for value in attribute.values.all()]})
 
     for variant in variants:
@@ -171,3 +176,18 @@ def price_range_as_dict(price_range):
         return None
     return {'maxPrice': price_as_dict(price_range.max_price),
             'minPrice': price_as_dict(price_range.min_price)}
+
+
+def get_variant_url_from_product(product, attributes):
+    return '%s?%s' % (product.get_absolute_url(), urlencode(attributes))
+
+
+def get_variant_url(variant):
+    attributes = {}
+    values = {}
+    for attribute in variant.product.product_class.variant_attributes.all():
+        attributes[str(attribute.pk)] = attribute
+        for value in attribute.values.all():
+            values[str(value.pk)] = value
+
+    return get_variant_url_from_product(variant.product, attributes)


Test patch:
Repository: saleor/saleor

Issue:
Wrong discount amount for shipping vouchers
![voucher_error](https://cloud.githubusercontent.com/assets/5188636/22153772/04882aee-df29-11e6-8158-79d2729773db.png)

When shipping discount is bigger than checkout total, then displayed discount is incorrect.


Discussion:

Resolving patch:
diff --git a/saleor/discount/templatetags/__init__.py b/saleor/discount/templatetags/__init__.py
new file mode 100644
diff --git a/saleor/discount/templatetags/voucher.py b/saleor/discount/templatetags/voucher.py
new file mode 100644
--- /dev/null
+++ b/saleor/discount/templatetags/voucher.py
@@ -0,0 +1,11 @@
+from django import template
+from django_prices.templatetags.prices_i18n import gross
+from prices import Price
+
+register = template.Library()
+
+
+@register.simple_tag
+def discount_as_negative(discount, html=False):
+    zero = Price(0, currency=discount.amount.currency)
+    return gross(zero-discount.amount, html=html)


Test patch:
Repository: saleor/saleor

Issue:
Don't use random to generate test data unique fields



Discussion:

Resolving patch:
diff --git a/saleor/core/utils/random_data.py b/saleor/core/utils/random_data.py
--- a/saleor/core/utils/random_data.py
+++ b/saleor/core/utils/random_data.py
@@ -183,12 +183,14 @@ def create_products_by_class(product_class, schema,
             create_product_images(
                 product, random.randrange(1, 5), class_placeholders)
         variant_combinations = get_variant_combinations(product)
-        for attr_combination in variant_combinations:
+        for i, attr_combination in enumerate(variant_combinations, 1337):
+            sku = '%s-%s' % (product.pk, i)
             create_variant(product, attributes=attr_combination,
-                           price_override=get_price_override(schema))
+                           price_override=get_price_override(schema), sku=sku)
         if not variant_combinations:
             # Create min one variant for products without variant level attrs
-            create_variant(product)
+            sku = '%s-%s' % (product.pk, fake.random_int(1000, 100000))
+            create_variant(product, sku=sku)
         if stdout is not None:
             stdout.write('Product: %s (%s), %s variant(s)' % (
                 product, product_class.name, len(variant_combinations) or 1))
@@ -259,7 +261,6 @@ def create_stock(variant, **kwargs):
 def create_variant(product, **kwargs):
     defaults = {
         'name': fake.word(),
-        'sku': '%s-%s' % (product.pk, fake.random_int(1, 100000)),
         'product': product}
     defaults.update(kwargs)
     variant = ProductVariant.objects.create(**defaults)


Test patch:
Repository: saleor/saleor

Issue:
Calling get_price_range() on an empty item range
On the product detail page backend doesn't check existence of product variants.
If the product requires variants, but they don't exist, Django throws an exception `Calling get_price_range() on an empty item range`.


Discussion:

Resolving patch:
diff --git a/saleor/product/utils.py b/saleor/product/utils.py
--- a/saleor/product/utils.py
+++ b/saleor/product/utils.py
@@ -45,6 +45,15 @@ def products_with_availability(products, discounts, local_currency):
 
 
 def get_availability(product, discounts=None, local_currency=None):
+    if not product.variants.exists():
+        return ProductAvailability(
+            available=False,
+            price_range=None,
+            price_range_undiscounted=None,
+            discount=None,
+            price_range_local_currency=None,
+            discount_local_currency=None)
+
     # In default currency
     price_range = product.get_price_range(discounts=discounts)
     undiscounted = product.get_price_range()
@@ -142,12 +151,14 @@ def get_product_attributes_data(product):
 
 def price_as_dict(price):
     if not price:
-        return {}
+        return None
     return {'currency': price.currency,
             'gross': price.gross,
             'net': price.net}
 
 
 def price_range_as_dict(price_range):
+    if not price_range:
+        return None
     return {'maxPrice': price_as_dict(price_range.max_price),
             'minPrice': price_as_dict(price_range.min_price)}


Test patch:
Repository: saleor/saleor

Issue:
Prepare better categories for data generator
We should consider extending data generator and deliver more categories with better placeholder images.


Discussion:

Resolving patch:
diff --git a/saleor/core/utils/random_data.py b/saleor/core/utils/random_data.py
--- a/saleor/core/utils/random_data.py
+++ b/saleor/core/utils/random_data.py
@@ -99,6 +99,7 @@
             'Cover': ['Soft', 'Hard']
         },
         'images_dir': 'books/',
+        'different_variant_prices': True,
         'is_shipping_required': True
     }
 }


Test patch:
Repository: saleor/saleor

Issue:
Improve homepage styles
* Images on mobile should be square
* Products section should look like on the latest design (4 products in row)

![image](https://cloud.githubusercontent.com/assets/1754812/22293645/b1222882-e310-11e6-86f2-43bcda5cb572.png)



Discussion:

Resolving patch:
diff --git a/saleor/core/views.py b/saleor/core/views.py
--- a/saleor/core/views.py
+++ b/saleor/core/views.py
@@ -4,7 +4,7 @@
 
 
 def home(request):
-    products = products_with_details(request.user)[:6]
+    products = products_with_details(request.user)[:8]
     products = products_with_availability(
         products, discounts=request.discounts, local_currency=request.currency)
     return TemplateResponse(


Test patch:
Repository: saleor/saleor

Issue:
Javascript strings are not translated
Hello,
I'm translating saleor into Italian. I've noticed that some strings are not accessible to translations.
Eg "[Load More](https://github.com/mirumee/saleor/blob/2c7817fcdbd32b4888cd915625f234bf439b9bf6/saleor/static/js/components/categoryPage/ProductList.js#L29)", "filters:" etc.

Would [JavaScriptCatalog / javascript_catalog view](https://docs.djangoproject.com/en/1.10/topics/i18n/translation/#module-django.views.i18n)  work without problems with React and Webpack?





Discussion:

Resolving patch:
diff --git a/saleor/urls.py b/saleor/urls.py
--- a/saleor/urls.py
+++ b/saleor/urls.py
@@ -4,6 +4,8 @@
 from django.contrib import admin
 from django.contrib.sitemaps.views import sitemap
 from django.contrib.staticfiles.views import serve
+from django.views.i18n import javascript_catalog
+
 from graphene_django.views import GraphQLView
 
 from .cart.urls import urlpatterns as cart_urls
@@ -28,6 +30,7 @@
     url(r'^checkout/', include(checkout_urls, namespace='checkout')),
     url(r'^dashboard/', include(dashboard_urls, namespace='dashboard')),
     url(r'^graphql', GraphQLView.as_view(graphiql=settings.DEBUG)),
+    url(r'^jsi18n/$', javascript_catalog, name='javascript-catalog'),
     url(r'^order/', include(order_urls, namespace='order')),
     url(r'^products/', include(product_urls, namespace='product')),
     url(r'^profile/', include(userprofile_urls, namespace='profile')),


Test patch:
Repository: saleor/saleor

Issue:
Server Error (500) when adding attribute
Hi,

First of all thanks for this excellent software, makes my life easier.

I deployed it on heroku using the heroku elements (https://elements.heroku.com/buttons/mirumee/saleor).

Then I tried to add an attribute but that resulted in Server Error (500) page. Is this expected behavior? Any settings that have to be changed? If yes then any way to do that on heroku?

Thanks!



Discussion:

Resolving patch:
diff --git a/saleor/product/models/utils.py b/saleor/product/models/utils.py
--- a/saleor/product/models/utils.py
+++ b/saleor/product/models/utils.py
@@ -11,5 +11,5 @@ def get_attributes_display_map(obj, attributes):
             if choice_obj:
                 display_map[attribute.pk] = choice_obj
             else:
-                display_map[attribute.pk] = value_pk
+                display_map[attribute.pk] = value
     return display_map


Test patch: