瀏覽代碼

Added validation of additions to basket to prevent out of stock products being added

master
David Winterbottom 14 年之前
父節點
當前提交
c0c0d3ef51

+ 8
- 0
oscar/apps/basket/forms.py 查看文件

@@ -3,6 +3,7 @@ from django.db.models import get_model
3 3
 
4 4
 basketline_model = get_model('basket', 'line')
5 5
 basket_model = get_model('basket', 'basket')
6
+Product = get_model('catalogue', 'product')
6 7
 
7 8
 
8 9
 class BasketLineForm(forms.ModelForm):
@@ -41,6 +42,13 @@ class AddToBasketForm(forms.Form):
41 42
             else:
42 43
                 self._create_product_fields(instance)
43 44
     
45
+    def clean_product_id(self):
46
+        id = self.cleaned_data['product_id']
47
+        product = Product.objects.get(id=id)
48
+        if not product.has_stockrecord or not product.stockrecord.is_available_to_buy:
49
+            raise forms.ValidationError("This product is not available for purchase")
50
+        return id
51
+    
44 52
     def _create_group_product_fields(self, item):
45 53
         u"""
46 54
         Adds the fields for a "group"-type product (eg, a parent product with a

+ 8
- 3
oscar/apps/basket/views.py 查看文件

@@ -60,8 +60,9 @@ class BasketView(ModelFormSetView):
60 60
 
61 61
 
62 62
 class BasketAddView(FormView):
63
-    u"""
64
-    Handles the add-to-basket operation, shouldn't be accessed via GET because there's nothing sensible to render.
63
+    """
64
+    Handles the add-to-basket operation, shouldn't be accessed via 
65
+    GET because there's nothing sensible to render.
65 66
     """
66 67
     form_class = AddToBasketForm
67 68
     product_model = get_model('catalogue', 'product')
@@ -80,7 +81,7 @@ class BasketAddView(FormView):
80 81
         return kwargs
81 82
     
82 83
     def get_success_url(self):
83
-        return self.request.META.get('HTTP_REFERER',reverse('basket:summary'))
84
+        return self.request.META.get('HTTP_REFERER', reverse('basket:summary'))
84 85
 
85 86
     def form_valid(self, form):
86 87
         options = []
@@ -93,6 +94,10 @@ class BasketAddView(FormView):
93 94
         return super(BasketAddView, self).form_valid(form)
94 95
     
95 96
     def form_invalid(self, form):
97
+        msgs = []
98
+        for error in form.errors.values():
99
+            msgs.append(error.as_text()) 
100
+        messages.error(self.request, ",".join(msgs))
96 101
         return HttpResponseRedirect(self.request.META.get('HTTP_REFERER',reverse('basket:summary')))
97 102
 
98 103
 

+ 7
- 0
oscar/apps/partner/abstract_models.py 查看文件

@@ -99,6 +99,13 @@ class AbstractStockRecord(models.Model):
99 99
     # Price retrieval methods - these default to no tax being applicable
100 100
     # These are intended to be overridden.   
101 101
     
102
+    @property
103
+    def is_available_to_buy(self):
104
+        """
105
+        Return whether this stockrecord allows the product to be purchased
106
+        """
107
+        return get_partner_wrapper(self.partner.name).is_available_to_buy(self)
108
+    
102 109
     @property
103 110
     def availability(self):
104 111
         u"""Return an item's availability as a string"""

+ 3
- 0
oscar/apps/partner/wrappers.py 查看文件

@@ -24,6 +24,9 @@ class DefaultWrapper(object):
24 24
     Default stockrecord wrapper
25 25
     """
26 26
     
27
+    def is_available_to_buy(self, stockrecord):
28
+        return stockrecord.num_in_stock > 0
29
+    
27 30
     def availability(self, stockrecord):
28 31
         if stockrecord.num_in_stock > 0:
29 32
             return _("In stock (%d available)" % stockrecord.num_in_stock)

+ 20
- 20
oscar/templates/catalogue/detail.html 查看文件

@@ -5,13 +5,13 @@
5 5
 {% load basket_tags %}
6 6
 
7 7
 {% block header %}
8
-    <h1>{{ item.get_title }}</h1>
8
+    <h1>{{ product.get_title }}</h1>
9 9
 {% endblock header %}
10 10
 
11 11
 
12 12
 {% block content %}
13 13
 <div class="images">
14
-    {% for image in item.images.all %}
14
+    {% for image in product.images.all %}
15 15
         <img src="{{ imageurl }}" width="200" height="200">
16 16
         {% if image.caption %}
17 17
             <div class="caption">{{ image.caption }}</div>
@@ -22,30 +22,30 @@
22 22
 <table>
23 23
     <caption>Product details</caption>
24 24
     <tr>
25
-        <th>UPC</th><td>{{item.upc}}</td>
25
+        <th>UPC</th><td>{{ product.upc }}</td>
26 26
     </tr>
27 27
     <tr>
28
-        <th>Product class</th><td>{{item.product_class.name}}</td>
28
+        <th>Product class</th><td>{{ product.product_class.name }}</td>
29 29
     </tr>
30
-    {% if item.stockrecord %}
30
+    {% if product.stockrecord %}
31 31
     <tr>
32
-        <th>Price (excl. tax)</th><td>{{item.stockrecord.price_incl_tax|currency}}</td>
32
+        <th>Price (excl. tax)</th><td>{{ product.stockrecord.price_incl_tax|currency }}</td>
33 33
     </tr>
34 34
     <tr>
35
-        <th>Price (incl. tax)</th><td>{{item.stockrecord.price_excl_tax|currency}}</td>
35
+        <th>Price (incl. tax)</th><td>{{ product.stockrecord.price_excl_tax|currency }}</td>
36 36
     </tr>
37 37
     <tr>
38 38
         <th>Availability</th>
39
-        <td>{{ item.stockrecord.availability }}</td>
39
+        <td>{{ product.stockrecord.availability }}</td>
40 40
     </tr>
41 41
     {% endif %}
42 42
     <tr>
43 43
         <th>Product type</th>
44 44
         <td>
45
-        {% if item.is_group %}Product group{% else %}{% if item.is_variant %}Variant{% else %}Stand-alone{% endif %}{% endif %}
45
+        {% if product.is_group %}Product group{% else %}{% if product.is_variant %}Variant{% else %}Stand-alone{% endif %}{% endif %}
46 46
         </td>
47 47
     </tr>
48
-    {% for attribute in item.attributes.all %}
48
+    {% for attribute in product.attributes.all %}
49 49
     <tr>
50 50
         <th>{{ attribute.type.name }}</th>
51 51
         <td>{{ attribute.value }}</td>
@@ -62,9 +62,9 @@
62 62
     
63 63
 </table>
64 64
 
65
-{% if item.stockrecord %}
65
+{% if product.stockrecord %}
66 66
 
67
-{% basket_form item as basket_form %}
67
+{% basket_form product as basket_form %}
68 68
 
69 69
 <form action="{% url basket:add %}" method="post">
70 70
     {% csrf_token %}
@@ -74,7 +74,7 @@
74 74
 {% endif %}
75 75
 
76 76
 <h2>Categories</h2>
77
-{% for category in item.categories.all %}
77
+{% for category in product.categories.all %}
78 78
 <p>
79 79
 {% for c in category.get_ancestors %}
80 80
 {% if not forloop.first %} > {% endif %}<a href="{{ c.get_absolute_url }}">{{ c.name }}</a>
@@ -87,10 +87,10 @@
87 87
 <h2>Customer Reviews</h2>
88 88
 <p>Read customer reviews on this product. If you have read this book, why not post your own
89 89
    review?</p>
90
-<p><a href="{% url catalogue:reviews-add item.slug item.id %}">Add a review</a></p>
90
+<p><a href="{% url catalogue:reviews-add product.slug product.id %}">Add a review</a></p>
91 91
 
92 92
 
93
-{% with item.reviews.all as reviews %}
93
+{% with product.reviews.all as reviews %}
94 94
 {% if reviews %}
95 95
     <div>
96 96
         {% for review in reviews|slice:":3" %}
@@ -108,29 +108,29 @@
108 108
                 {% endif %}
109 109
             </div>
110 110
         {% endfor %}
111
-        <p><a href="{% url catalogue:reviews-list item.slug item.id %}">See all reviews</a>.</p>
111
+        <p><a href="{% url catalogue:reviews-list product.slug product.id %}">See all reviews</a>.</p>
112 112
     </div>
113 113
 {% endif %}
114 114
 {% endwith %}
115 115
 
116 116
 {% endblock product_review %}
117 117
 
118
-{% if item.related_items.count %}
118
+{% if product.related_items.count %}
119 119
 <div class="products">
120 120
     <h4>Related items</h4>
121 121
     <ul>
122
-    {% for product in item.related_items.all %}
122
+    {% for product in product.related_items.all %}
123 123
         <li><a href="{{ product.get_absolute_url }}">{{ product.get_title }}</a></li>
124 124
     {% endfor %}
125 125
     </ul>
126 126
 </div>
127 127
 {% endif %}
128 128
 
129
-{% if item.recommended_items.count %}
129
+{% if product.recommended_items.count %}
130 130
 <div class="products">
131 131
     <h4>Recommended items</h4>
132 132
     <ul>
133
-    {% for product in item.recommended_items.all %}
133
+    {% for product in product.recommended_items.all %}
134 134
         <li><a href="{{ product.get_absolute_url }}">{{ product.get_title }}</a></li>
135 135
     {% endfor %}
136 136
     </ul>

Loading…
取消
儲存