diff --git a/oscar/apps/dashboard/reviews/forms.py b/oscar/apps/dashboard/reviews/forms.py index efd1750b5a9..7e409fea302 100644 --- a/oscar/apps/dashboard/reviews/forms.py +++ b/oscar/apps/dashboard/reviews/forms.py @@ -8,5 +8,8 @@ class Meta: fields = ('title', 'body', 'score', 'status') -class ReviewSearchForm(forms.Form): - pass +class ProductReviewSearchForm(forms.Form): + keyword = forms.CharField(required=False) + date_from = forms.DateTimeField(required=False) + date_to = forms.DateTimeField(required=False, label='to') + name = forms.CharField(required=False) diff --git a/oscar/apps/dashboard/reviews/tests.py b/oscar/apps/dashboard/reviews/tests.py index 88cc39d951a..ed75da6138e 100644 --- a/oscar/apps/dashboard/reviews/tests.py +++ b/oscar/apps/dashboard/reviews/tests.py @@ -1,3 +1,5 @@ +from datetime import datetime, timedelta + from django.test import TestCase from django.db.models import get_model from django.core.urlresolvers import reverse @@ -40,3 +42,76 @@ def test_bulk_editing_review_status(self): self.assertEquals(ProductReview.objects.get(pk=1).status, 0) self.assertEquals(ProductReview.objects.get(pk=2).status, 1) self.assertEquals(ProductReview.objects.get(pk=3).status, 1) + + def test_filter_reviews_by_name(self): + url = reverse('dashboard:reviews-list') + + user1 = get(User, first_name='Peter', last_name='Griffin') + user2 = get(User, first_name='Lois', last_name='Griffin') + + review1 = get(ProductReview, user=user1, status=0) + review2 = get(ProductReview, user=user2, status=0) + review3 = get(ProductReview, user=user2, status=0) + + response = self.client.get(url, {'name': 'peter'}) + + self.assertEquals(len(response.context['review_list']), 1) + self.assertEquals(response.context['review_list'][0].user, user1) + + response = self.client.get(url, {'name': 'lois griffin'}) + + self.assertEquals(len(response.context['review_list']), 2) + for review in response.context['review_list']: + self.assertEquals(review.user, user2) + + def test_filter_reviews_by_keyword(self): + url = reverse('dashboard:reviews-list') + + user1 = get(User) + user2 = get(User) + + review1 = get(ProductReview, user=user1, title='Sexy Review') + review2 = get(ProductReview, user=user2, title='Anry Review', + body='argh') + review3 = get(ProductReview, user=user2, title='Lovely Thing') + + response = self.client.get(url, {'keyword': 'argh'}) + self.assertItemsEqual(response.context['review_list'], [review2]) + + response = self.client.get(url, {'keyword': 'review'}) + self.assertItemsEqual( + response.context['review_list'], + [review1, review2] + ) + + def test_filter_reviews_by_date(self): + url = reverse('dashboard:reviews-list') + + user1 = get(User) + user2 = get(User) + + now = datetime.now() + review1 = get(ProductReview, user=user1) + review1.date_created = now + review1.save() + review2 = get(ProductReview, user=user2) + review2.date_created = now - timedelta(days=2) + review2.save() + review3 = get(ProductReview, user=user2) + review3.date_created = now - timedelta(days=10) + review3.save() + + response = self.client.get(url, {'date_from': now - timedelta(days=5)}) + self.assertItemsEqual( + response.context['review_list'], + [review1, review2] + ) + + response = self.client.get(url, {'date_to': now - timedelta(days=5)}) + self.assertItemsEqual(response.context['review_list'], [review3]) + + response = self.client.get(url, { + 'date_from': now - timedelta(days=12), + 'date_to': now - timedelta(days=9) + }) + self.assertItemsEqual(response.context['review_list'], [review3]) diff --git a/oscar/apps/dashboard/reviews/views.py b/oscar/apps/dashboard/reviews/views.py index cfdd823baea..60bd0636a20 100644 --- a/oscar/apps/dashboard/reviews/views.py +++ b/oscar/apps/dashboard/reviews/views.py @@ -1,8 +1,10 @@ -from django.db.models import get_model +import datetime +from django.db.models import get_model, Q from django.core.urlresolvers import reverse from django.http import HttpResponse, HttpResponseRedirect from django.template.response import TemplateResponse from django.views.generic import ListView, UpdateView +from django.template.defaultfilters import date as format_date from oscar.views.generic import BulkEditMixin from oscar.apps.dashboard.reviews import forms @@ -14,25 +16,98 @@ class ReviewListView(ListView, BulkEditMixin): model = ProductReview template_name = 'dashboard/reviews/review_list.html' context_object_name = 'review_list' - form_class = forms.ReviewSearchForm - base_description = 'All reviews' + form_class = forms.ProductReviewSearchForm + review_form_class = forms.DashboardProductReviewForm paginate_by = 25 current_view = 'dashboard:reviews-list' actions = ('update_selected_review_status',) checkbox_object_name = 'review' + base_description = 'All reviews' + + def get(self, request, *args, **kwargs): + response = super(self.__class__, self).get(request, **kwargs) + self.form = self.form_class() + return response + + def get_date_from_to_queryset(self, date_from, date_to, queryset=None): + """ + Get a ``QuerySet`` of ``ProductReview`` items that match the time + frame specified by *date_from* and *date_to*. Both parameters are + expected to be in ``datetime`` format with *date_from* < *date_to*. + If *queryset* is specified, it will be filtered according to the + given dates. Otherwise, a new queryset for all ``ProductReview`` + items is created. + """ + if not queryset: + self.model.objects.all() + + if date_from and date_to: + # Add 24 hours to make search inclusive + date_to = date_to + datetime.timedelta(days=1) + queryset = queryset.filter( + date_created__gte=date_from + ).filter( + date_created__lt=date_to + ) + self.description += " created between %s and %s" % ( + format_date(date_from), + format_date(date_to) + ) + + elif date_from: + queryset = queryset.filter(date_created__gte=date_from) + self.description += " created after %s" % format_date(date_from) + + elif date_to: + # Add 24 hours to make search inclusive + date_to = date_to + datetime.timedelta(days=1) + queryset = queryset.filter(date_created__lt=date_to) + self.description += " created before %s" % format_date(date_to) + + return queryset def get_queryset(self): - return ProductReview.objects.all() + queryset = self.model.objects.all() + self.description = self.base_description + + self.form = self.form_class(self.request.GET) + if not self.form.is_valid(): + return queryset + + data = self.form.cleaned_data + + if data['keyword']: + queryset = queryset.filter( + Q(title__icontains=data['keyword']) | + Q(body__icontains=data['keyword']) + ).distinct() + self.description += " with keyword matching '%s'" % data['keyword'] + + queryset = self.get_date_from_to_queryset(data['date_from'], + data['date_to'], queryset) - def get(self, request, **kwargs): - return super(self.__class__, self).get(request, **kwargs) + if data['name']: + # If the value is two words, then assume they are first name and + # last name + parts = data['name'].split() + if len(parts) >= 2: + queryset = queryset.filter( + user__first_name__istartswith=parts[0], + user__last_name__istartswith=parts[1] + ).distinct() + else: + queryset = queryset.filter( + Q(user__first_name__istartswith=parts[0]) | + Q(user__last_name__istartswith=parts[-1]) + ).distinct() + self.description += " with customer name matching '%s'" % data['name'] - def post(self, request, **kwargs): - return super(self.__class__, self).post(request, **kwargs) + return queryset def get_context_data(self, **kwargs): context = super(self.__class__, self).get_context_data(**kwargs) - context['review_form'] = forms.DashboardProductReviewForm() + context['review_form'] = self.review_form_class() + context['form'] = self.form return context def update_selected_review_status(self, request, reviews): diff --git a/oscar/templates/dashboard/reviews/review_list.html b/oscar/templates/dashboard/reviews/review_list.html index b0c09cac978..6becbaa8358 100644 --- a/oscar/templates/dashboard/reviews/review_list.html +++ b/oscar/templates/dashboard/reviews/review_list.html @@ -25,11 +25,10 @@

Review management dashboard

{% block dashboard_content %}
-

Quick Review Search

+

Review Search

- {% include 'partials/form_fields_inline.html' with form=form %} + {% include 'partials/form_fields_inline.html' with form=form %} - Reset