| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- from urlparse import urlparse
- from django.contrib import messages
- from django.core.urlresolvers import reverse, resolve
- from django.db.models import get_model
- from django.http import HttpResponseRedirect, Http404
- from django.views.generic import FormView, View
- from django.utils.translation import ugettext_lazy as _
- from django.core.exceptions import ObjectDoesNotExist
-
- from extra_views import ModelFormSetView
- from oscar.apps.basket.signals import basket_addition, voucher_addition
- from oscar.core.loading import get_class, get_classes
- Applicator = get_class('offer.utils', 'Applicator')
- BasketLineForm, AddToBasketForm, BasketVoucherForm, \
- SavedLineFormSet, SavedLineForm, ProductSelectionForm = get_classes(
- 'basket.forms', ('BasketLineForm', 'AddToBasketForm',
- 'BasketVoucherForm', 'SavedLineFormSet',
- 'SavedLineForm', 'ProductSelectionForm'))
- Repository = get_class('shipping.repository', ('Repository'))
-
-
- class BasketView(ModelFormSetView):
- model = get_model('basket', 'Line')
- basket_model = get_model('basket', 'Basket')
- form_class = BasketLineForm
- extra = 0
- can_delete = True
- template_name = 'basket/basket.html'
-
- def get_queryset(self):
- return self.request.basket.all_lines()
-
- def get_default_shipping_method(self, basket):
- return Repository().get_default_shipping_method(
- self.request.user, self.request.basket)
-
- def get_basket_warnings(self, basket):
- """
- Return a list of warnings that apply to this basket
- """
- warnings = []
- for line in basket.all_lines():
- warning = line.get_warning()
- if warning:
- warnings.append(warning)
- return warnings
-
- def get_upsell_messages(self, basket):
- offers = Applicator().get_offers(self.request, basket)
- msgs = []
- for offer in offers:
- if offer.is_condition_partially_satisfied(basket):
- data = {
- 'message': offer.get_upsell_message(basket),
- 'offer': offer
- }
- msgs.append(data)
- return msgs
-
- def get_context_data(self, **kwargs):
- context = super(BasketView, self).get_context_data(**kwargs)
- context['voucher_form'] = BasketVoucherForm()
- method = self.get_default_shipping_method(self.request.basket)
- context['shipping_method'] = method
- context['shipping_charge_incl_tax'] = method.basket_charge_incl_tax()
- context['order_total_incl_tax'] = (
- self.request.basket.total_incl_tax +
- method.basket_charge_incl_tax())
- context['basket_warnings'] = self.get_basket_warnings(
- self.request.basket)
- context['upsell_messages'] = self.get_upsell_messages(
- self.request.basket)
-
- if self.request.user.is_authenticated():
- try:
- saved_basket = self.basket_model.saved.get(
- owner=self.request.user)
- except self.basket_model.DoesNotExist:
- pass
- else:
- if not saved_basket.is_empty:
- saved_queryset = saved_basket.all_lines().select_related(
- 'product', 'product__stockrecord')
- formset = SavedLineFormSet(user=self.request.user,
- basket=self.request.basket,
- queryset=saved_queryset,
- prefix='saved')
- context['saved_formset'] = formset
- return context
-
- def get_success_url(self):
- messages.success(self.request, _("Basket updated"))
- return self.request.META.get('HTTP_REFERER', reverse('basket:summary'))
-
- def formset_valid(self, formset):
- save_for_later = False
- for form in formset:
- if (hasattr(form, 'cleaned_data') and
- form.cleaned_data['save_for_later']):
- line = form.instance
- if self.request.user.is_authenticated():
- self.move_line_to_saved_basket(line)
- messages.info(
- self.request,
- _(u"'%(title)s' has been saved for later") % {
- 'title': line.product})
- save_for_later = True
- else:
- messages.error(
- self.request,
- _("You can't save an item for later if you're not logged in!"))
- return HttpResponseRedirect(self.get_success_url())
-
- if save_for_later:
- # No need to call super if we're moving lines to the saved basket
- return HttpResponseRedirect(self.get_success_url())
- return super(BasketView, self).formset_valid(formset)
-
- def move_line_to_saved_basket(self, line):
- saved_basket, _ = get_model('basket', 'basket').saved.get_or_create(
- owner=self.request.user)
- saved_basket.merge_line(line)
-
- def formset_invalid(self, formset):
- errors = []
- for error_dict in formset.errors:
- errors += [error_list.as_text()
- for error_list in error_dict.values()]
- msg = _("Your basket couldn't be updated because:\n%s") % (
- "\n".join(errors),)
- messages.warning(self.request, msg)
- return super(BasketView, self).formset_invalid(formset)
-
-
- class BasketAddView(FormView):
- """
- Handles the add-to-basket operation, shouldn't be accessed via
- GET because there's nothing sensible to render.
- """
- form_class = AddToBasketForm
- product_select_form_class = ProductSelectionForm
- product_model = get_model('catalogue', 'product')
- add_signal = basket_addition
-
- def get(self, request, *args, **kwargs):
- return HttpResponseRedirect(reverse('basket:summary'))
-
- def get_form_kwargs(self):
- kwargs = super(BasketAddView, self).get_form_kwargs()
- product_select_form = self.product_select_form_class(self.request.POST)
-
- if product_select_form.is_valid():
- kwargs['instance'] = product_select_form.cleaned_data['product_id']
- else:
- kwargs['instance'] = None
- kwargs['user'] = self.request.user
- kwargs['basket'] = self.request.basket
- return kwargs
-
- def get_success_url(self):
- url = None
- if self.request.POST.get('next'):
- url = self.request.POST.get('next')
- elif 'HTTP_REFERER' in self.request.META:
- url = self.request.META['HTTP_REFERER']
- if url:
- # We only allow internal URLs so we see if the url resolves
- try:
- resolve(urlparse(url).path)
- except Http404:
- url = None
- if url is None:
- url = reverse('basket:summary')
- return url
-
- def form_valid(self, form):
- self.request.basket.add_product(
- form.instance, form.cleaned_data['quantity'],
- form.cleaned_options())
- messages.success(self.request, self.get_success_message(form))
-
- # Send signal for basket addition
- self.add_signal.send(
- sender=self, product=form.instance, user=self.request.user)
-
- return super(BasketAddView, self).form_valid(form)
-
- def get_success_message(self, form):
- qty = form.cleaned_data['quantity']
- title = form.instance.get_title()
- if qty == 1:
- return _("'%(title)s' has been added to your basket") % {
- 'title': title}
- else:
- return _(
- "'%(title)s' (quantity %(quantity)d) has been added to your"
- "basket") % {'title': title, 'quantity': qty}
-
- def form_invalid(self, form):
- msgs = []
- for error in form.errors.values():
- msgs.append(error.as_text())
- messages.error(self.request, ",".join(msgs))
- return HttpResponseRedirect(
- self.request.META.get('HTTP_REFERER', reverse('basket:summary')))
-
-
- class VoucherAddView(FormView):
- form_class = BasketVoucherForm
- voucher_model = get_model('voucher', 'voucher')
- add_signal = voucher_addition
-
- def get(self, request, *args, **kwargs):
- return HttpResponseRedirect(reverse('basket:summary'))
-
- def apply_voucher_to_basket(self, voucher):
- if not voucher.is_active():
- messages.error(
- self.request,
- _("The '%(code)s' voucher has expired") % {
- 'code': voucher.code})
- return
-
- is_available, message = voucher.is_available_to_user(self.request.user)
- if not is_available:
- messages.error(self.request, message)
- return
-
- self.request.basket.vouchers.add(voucher)
-
- # Raise signal
- self.add_signal.send(sender=self,
- basket=self.request.basket,
- voucher=voucher)
-
- # Recalculate discounts to see if the voucher gives any
- self.request.basket.remove_discounts()
- Applicator().apply(self.request, self.request.basket)
- discounts_after = self.request.basket.get_discounts()
-
- # Look for discounts from this new voucher
- found_discount = False
- for discount in discounts_after:
- if discount['voucher'] and discount['voucher'] == voucher:
- found_discount = True
- break
- if not found_discount:
- messages.warning(
- self.request,
- _("Your basket does not qualify for a voucher discount"))
- self.request.basket.vouchers.remove(voucher)
- else:
- messages.info(
- self.request,
- _("Voucher '%(code)s' added to basket") % {
- 'code': voucher.code})
-
- def form_valid(self, form):
- code = form.cleaned_data['code']
- if not self.request.basket.id:
- return HttpResponseRedirect(
- self.request.META.get('HTTP_REFERER',
- reverse('basket:summary')))
- if self.request.basket.contains_voucher(code):
- messages.error(
- self.request,
- _("You have already added the '%(code)s' voucher to "
- "your basket") % {'code': code})
- else:
- try:
- voucher = self.voucher_model._default_manager.get(code=code)
- except self.voucher_model.DoesNotExist:
- messages.error(
- self.request,
- _("No voucher found with code '%(code)s'") % {
- 'code': code})
- else:
- self.apply_voucher_to_basket(voucher)
- return HttpResponseRedirect(
- self.request.META.get('HTTP_REFERER', reverse('basket:summary')))
-
- def form_invalid(self, form):
- messages.error(self.request, _("Please enter a voucher code"))
- return HttpResponseRedirect(reverse('basket:summary') + '#voucher')
-
-
- class VoucherRemoveView(View):
- voucher_model = get_model('voucher', 'voucher')
-
- def get(self, request, *args, **kwargs):
- return HttpResponseRedirect(reverse('basket:summary'))
-
- def post(self, request, *args, **kwargs):
- voucher_id = int(kwargs.pop('pk'))
- if not request.basket.id:
- # Hacking attempt - the basket must be saved for it to have
- # a voucher in it.
- return HttpResponseRedirect(reverse('basket:summary'))
- try:
- voucher = request.basket.vouchers.get(id=voucher_id)
- except ObjectDoesNotExist:
- messages.error(
- request, _("No voucher found with id '%d'") % voucher_id)
- else:
- request.basket.vouchers.remove(voucher)
- request.basket.save()
- messages.info(
- request, _("Voucher '%s' removed from basket") % voucher.code)
- return HttpResponseRedirect(reverse('basket:summary'))
-
-
- class SavedView(ModelFormSetView):
- model = get_model('basket', 'line')
- basket_model = get_model('basket', 'basket')
- formset_class = SavedLineFormSet
- form_class = SavedLineForm
- extra = 0
- can_delete = True
-
- def get(self, request, *args, **kwargs):
- return HttpResponseRedirect(reverse('basket:summary'))
-
- def get_queryset(self):
- try:
- saved_basket = self.basket_model.saved.get(owner=self.request.user)
- return saved_basket.all_lines().select_related(
- 'product', 'product__stockrecord')
- except self.basket_model.DoesNotExist:
- return []
-
- def get_success_url(self):
- return self.request.META.get('HTTP_REFERER', reverse('basket:summary'))
-
- def get_formset_kwargs(self):
- kwargs = super(SavedView, self).get_formset_kwargs()
- kwargs['prefix'] = 'saved'
- kwargs['basket'] = self.request.basket
- kwargs['user'] = self.request.user
- return kwargs
-
- def formset_valid(self, formset):
- is_move = False
- for form in formset:
- if form.cleaned_data['move_to_basket']:
- is_move = True
- msg = _("'%(product)s' has been moved back to your basket") % {
- 'product': form.instance.product}
- messages.info(self.request, msg)
- real_basket = self.request.basket
- real_basket.merge_line(form.instance)
- if is_move:
- return HttpResponseRedirect(self.get_success_url())
-
- return super(SavedView, self).formset_valid(formset)
-
- def formset_invalid(self, formset):
- messages.error(
- self.request,
- '\n'.join(
- error for ed in formset.errors for el
- in ed.values() for error in el))
- return HttpResponseRedirect(
- self.request.META.get('HTTP_REFERER', reverse('basket:summary')))
|