Browse Source

Drop upper_charge logic for weight based shipping methods

Previously, weight based shipping methods accepted an upper charge
field. When no weight band matched the baskets weight, this was
returned. I am not aware of a single retailer who calculates shipping
charges like that. It's impossible to pick a sensible value for a
retailer, as there's no upper limit to the amount of items ordered, and
any shipping charges would have to cover costs for that.
master
Maik Hoepfel 11 years ago
parent
commit
6fd9ebc29f

+ 1
- 0
docs/source/releases/v0.8.rst View File

@@ -392,6 +392,7 @@ Migrations
392 392
 * Shipping:
393 393
 
394 394
     - ``0007`` - Change ``WeightBand.upper_limit`` from ``FloatField`` to ``DecimalField``
395
+    - ``0008`` - Drop ``WeightBased.upper_charge`` field.
395 396
 
396 397
 .. _deprecated_features_in_0.8:
397 398
 

+ 0
- 6
oscar/apps/shipping/abstract_models.py View File

@@ -83,12 +83,6 @@ class AbstractOrderAndItemCharges(AbstractBase):
83 83
 
84 84
 
85 85
 class AbstractWeightBased(AbstractBase):
86
-    upper_charge = models.DecimalField(
87
-        _("Upper Charge"), decimal_places=2, max_digits=12, null=True,
88
-        validators=[MinValueValidator(D('0.00'))],
89
-        help_text=_("This is the charge when the weight of the basket "
90
-                    "is greater than all the weight bands"))
91
-
92 86
     # The attribute code to use to look up the weight of a product
93 87
     weight_attribute = 'weight'
94 88
 

+ 62
- 0
oscar/apps/shipping/migrations/0008_auto__del_field_weightbased_upper_charge.py View File

@@ -0,0 +1,62 @@
1
+# -*- coding: utf-8 -*-
2
+from south.utils import datetime_utils as datetime
3
+from south.db import db
4
+from south.v2 import SchemaMigration
5
+from django.db import models
6
+
7
+
8
+class Migration(SchemaMigration):
9
+
10
+    def forwards(self, orm):
11
+        # Deleting field 'WeightBased.upper_charge'
12
+        db.delete_column(u'shipping_weightbased', 'upper_charge')
13
+
14
+
15
+    def backwards(self, orm):
16
+        # Adding field 'WeightBased.upper_charge'
17
+        db.add_column(u'shipping_weightbased', 'upper_charge',
18
+                      self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=12, decimal_places=2),
19
+                      keep_default=False)
20
+
21
+
22
+    models = {
23
+        u'address.country': {
24
+            'Meta': {'ordering': "('-display_order', 'name')", 'object_name': 'Country'},
25
+            'display_order': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0', 'db_index': 'True'}),
26
+            'is_shipping_country': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
27
+            'iso_3166_1_a2': ('django.db.models.fields.CharField', [], {'max_length': '2', 'primary_key': 'True'}),
28
+            'iso_3166_1_a3': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '3', 'blank': 'True'}),
29
+            'iso_3166_1_numeric': ('django.db.models.fields.PositiveSmallIntegerField', [], {'null': 'True', 'db_index': 'True'}),
30
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
31
+            'printable_name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
32
+        },
33
+        u'shipping.orderanditemcharges': {
34
+            'Meta': {'ordering': "['name']", 'object_name': 'OrderAndItemCharges'},
35
+            'code': ('oscar.models.fields.autoslugfield.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '128', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}),
36
+            'countries': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['address.Country']", 'null': 'True', 'blank': 'True'}),
37
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
38
+            'free_shipping_threshold': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '12', 'decimal_places': '2', 'blank': 'True'}),
39
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
40
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'}),
41
+            'price_per_item': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '12', 'decimal_places': '2'}),
42
+            'price_per_order': ('django.db.models.fields.DecimalField', [], {'default': "'0.00'", 'max_digits': '12', 'decimal_places': '2'})
43
+        },
44
+        u'shipping.weightband': {
45
+            'Meta': {'ordering': "['method', 'upper_limit']", 'object_name': 'WeightBand'},
46
+            'charge': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '2'}),
47
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
48
+            'method': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'bands'", 'to': u"orm['shipping.WeightBased']"}),
49
+            'upper_limit': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '3'})
50
+        },
51
+        u'shipping.weightbased': {
52
+            'Meta': {'ordering': "['name']", 'object_name': 'WeightBased'},
53
+            'code': ('oscar.models.fields.autoslugfield.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '128', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}),
54
+            'countries': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['address.Country']", 'null': 'True', 'blank': 'True'}),
55
+            'default_weight': ('django.db.models.fields.DecimalField', [], {'default': "'0.000'", 'max_digits': '12', 'decimal_places': '3'}),
56
+            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
57
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
58
+            'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '128'})
59
+        }
60
+    }
61
+
62
+    complete_apps = ['shipping']

+ 0
- 11
oscar/templates/oscar/dashboard/shipping/weight_based_detail.html View File

@@ -49,10 +49,6 @@
49 49
                     <th>{% trans "Default product weight (kg)" %}</th>
50 50
                     <td>{{ method.default_weight }}</td>
51 51
                 </tr>
52
-                <tr>
53
-                    <th>{% trans "Upper charge" %}</th>
54
-                    <td>{{ method.upper_charge|currency }}</td>
55
-                </tr>
56 52
             </tbody>
57 53
         </table>
58 54
 
@@ -82,13 +78,6 @@
82 78
                             </td>
83 79
                         </tr>
84 80
                     {% endfor %}
85
-                    <tr>
86
-                        <td>{{ method.max_upper_limit|floatformat:3 }} - &infin;</td>
87
-                        <td>{{ method.upper_charge|currency }}</td>
88
-                        <td>
89
-                            <a href="{% url 'dashboard:shipping-method-edit' pk=method.pk %}" class="btn btn-primary">{% trans "Edit" %}</a>
90
-                        </td>
91
-                    </tr>
92 81
                 </tbody>
93 82
             </table>
94 83
         {% else %}

+ 0
- 2
oscar/templates/oscar/dashboard/shipping/weight_based_list.html View File

@@ -31,7 +31,6 @@
31 31
                 <tr>
32 32
                     <th>{% trans "Name" %}</th>
33 33
                     <th>{% trans "Number of weight bands" %}</th>
34
-                    <th>{% trans "Upper charge" %}</th>
35 34
                     <th>{% trans "Default weight (kg)" %}</th>
36 35
                     <th></th>
37 36
                 </tr>
@@ -43,7 +42,6 @@
43 42
                             <a href="{% url 'dashboard:shipping-method-detail' pk=method.pk %}">{{ method.name }}</a>
44 43
                         </td>
45 44
                         <td>{{ method.num_bands }}</td>
46
-                        <td>{{ method.upper_charge|currency }}</td>
47 45
                         <td>{{ method.default_weight }}</td>
48 46
                         <td>
49 47
                             <a href="{% url 'dashboard:shipping-method-detail' pk=method.pk %}" class="btn">{% trans "View" %}</a>

+ 0
- 1
tests/functional/dashboard/shipping_tests.py View File

@@ -15,7 +15,6 @@ class TestShippingMethodDashboard(WebTestCase):
15 15
         # Create a shipping method
16 16
         create_page = list_page.click(linkid="create_new_shipping_method")
17 17
         create_page.form['name'] = 'My method'
18
-        create_page.form['upper_charge'] = '25.00'
19 18
         detail_page = create_page.form.submit().follow()
20 19
         self.assertInContext(detail_page, 'method')
21 20
         self.assertEqual(1, models.WeightBased.objects.all().count())

+ 4
- 4
tests/integration/shipping/model_method_tests.py View File

@@ -164,14 +164,14 @@ class WeightBasedMethodTests(TestCase):
164 164
         self.assertEqual(D('0.00'), charge.incl_tax)
165 165
         self.assertTrue(charge.is_tax_known)
166 166
 
167
-    def test_correct_charge_returned(self):
167
+    def test_simple_shipping_cost_scenario_handled_correctly(self):
168 168
         basket = newfactories.BasketFactory()
169 169
         product_attribute_value = newfactories.ProductAttributeValueFactory(
170
-            value_float=0.5)
170
+            value_float=2.5)
171 171
         basket.add_product(product_attribute_value.product)
172 172
 
173
-        expected_charge = D('4.00')
174
-        self.standard.bands.create(upper_limit=1, charge=expected_charge)
173
+        expected_charge = D('3.00')
174
+        self.standard.bands.create(upper_limit=3, charge=expected_charge)
175 175
         charge = self.standard.calculate(basket)
176 176
 
177 177
         self.assertEqual(expected_charge, charge.excl_tax)

+ 1
- 12
tests/unit/shipping/model_tests.py View File

@@ -8,23 +8,12 @@ from oscar.apps.shipping import models
8 8
 
9 9
 class TestWeightBasedMethod(TestCase):
10 10
 
11
-    def test_doesnt_allow_negative_upper_charge(self):
12
-        method = models.WeightBased(
13
-            name="Dummy", upper_charge=D('-12.00'))
14
-        with self.assertRaises(ValidationError):
15
-            method.full_clean()
16
-
17 11
     def test_doesnt_allow_negative_default_weights(self):
18 12
         method = models.WeightBased(
19
-            name="Dummy", upper_charge=D('0.00'),
20
-            default_weight=D('-0.1'))
13
+            name="Dummy", default_weight=D('-0.1'))
21 14
         with self.assertRaises(ValidationError):
22 15
             method.full_clean()
23 16
 
24
-    def test_max_upper_limit_defaults_to_none(self):
25
-        method = models.WeightBased()
26
-        self.assertIsNone(method.max_upper_limit)
27
-
28 17
 
29 18
 class TestWeightBand(TestCase):
30 19
 

Loading…
Cancel
Save