예제 #1
0
    def before_save(self, request, cleaned_data, instance, edit):
        # default values
        if not edit:
            from cubane.ishop.views import get_shop
            shop = get_shop()
            instance.customer_not_present = True
            instance.payment_gateway = shop.get_default_payment_gateway()

        # save basket.
        basket = Basket(request, prefix=instance.backend_basket_prefix)
        if not basket.is_empty():
            instance.save_basket(basket)

        # change status
        if request.POST.get('next-status'):
            cleaned_data['status'] = int(request.POST.get('next-status'))
예제 #2
0
def delivery_options(request):
    """
    (2) Provide details on delivery options.
    """
    basket = Basket(request)
    if basket.is_empty():
        return HttpResponseRedirect('/')

    # construct delivery options form for entire basket
    items = basket.items
    choices = basket.get_delivery_choices()

    # construct form
    if request.method == 'POST':
        form = DeliveryOptionsFrom(request.POST)
        try:
            option = basket.get_delivery_options()[0]
        except IndexError:
            option = None
    else:
        option = basket.get_delivery_option_or_default()
        form = DeliveryOptionsFrom()

    # configure form with specific delivery options
    form.configure(request, choices, option)
    current_page = CurrentPage.DELIVERY_OPTIONS()

    # if the current open is not within the given set of choices,
    # then change the delivery option to the first one.
    if option:
        if option.id not in [_id for _id, _ in choices]:
            option = basket.get_default_delivery_option()
            basket.set_delivery_option(option)
            basket.save()
            basket = Basket(request)

    # form validation
    if request.method == 'POST' and form.is_valid():
        d = form.cleaned_data

        # get delivery option
        option = DeliveryOption.objects.get(pk=d.get('delivery_option'))

        # configure delivery option
        basket.set_delivery_option(option)

        # next...
        next = next_checkout_step(request, basket, current_page)
        basket.save()
        return next
    else:
        if basket.is_click_and_collect() and request.method == 'POST':
            next = next_checkout_step(request, basket, current_page)
            basket.save()
            return next

    delivery_option = basket.get_delivery_details(
        option) if option != None else None

    return {
        'basket': basket,
        'items': items,
        'form': form,
        'is_click_and_collect': basket.is_click_and_collect(),
        'delivery_option': delivery_option,
        'choices': choices
    }
예제 #3
0
def delivery(request):
    """
    (1) Start to checkout by confirming the delivery address.
    The customer is required to login for checkout first (see login).
    """
    basket = Basket(request)
    if basket.is_empty():
        return HttpResponseRedirect('/')

    # if the basket contains collection only products,
    # force click and collect
    if basket.is_collection_only():
        basket.set_click_and_collect(True)

    if request.method == 'POST':
        form = DeliveryAddressFrom(request.POST)
    else:
        billing = basket.billing_address if basket.billing_address else {}
        delivery = basket.delivery_address if basket.delivery_address else {}

        profile = None
        default = {}
        user = request.user
        if not user.is_anonymous():
            try:
                profile = get_customer_model().objects.get(user=user)
                default = {
                    'title': profile.title,
                    'first_name': user.first_name,
                    'last_name': user.last_name,
                    'email': user.email,
                    'telephone': profile.telephone
                }

                if basket.has_billing_address():
                    default.update({
                        'company': profile.company,
                        'address1': profile.address1,
                        'address2': profile.address2,
                        'address3': profile.address3,
                        'city': profile.city,
                        'country': profile.country,
                        'county': profile.county,
                        'postcode': profile.postcode
                    })
            except get_customer_model().DoesNotExist:
                pass
        else:
            default = {
                'email': request.session.get(settings.GUEST_USER_SESSION_VAR),
                'country': 'GB'
            }

        def _get(name, data, fallback=None):
            v = data.get(name)
            if v is None and fallback is not None:
                v = fallback.get(name)
            return v

        form = DeliveryAddressFrom(
            initial={
                'title':
                _get('title', billing, default),
                'first_name':
                _get('first_name', billing, default),
                'last_name':
                _get('last_name', billing, default),
                'email':
                _get('email', billing, default),
                'telephone':
                _get('telephone', billing, default),
                'company':
                _get('company', billing, default),
                'address1':
                _get('address1', billing, default),
                'address2':
                _get('address2', billing, default),
                'address3':
                _get('address3', billing, default),
                'city':
                _get('city', billing, default),
                'country':
                _get('country', billing, default),
                'county':
                _get('county', billing, default),
                'postcode':
                _get('postcode', billing, default),
                'deliver_to':
                DeliveryAddressFrom.DELIVERY_COLLECTION if basket.
                is_click_and_collect(
                ) else DeliveryAddressFrom.DELIVERY_BILLING_ADDRESS,
                'free_name':
                _get('free_name', delivery),
                'delivery_name':
                _get('name', delivery),
                'delivery_company':
                _get('company', delivery),
                'delivery_address1':
                _get('address1', delivery),
                'delivery_address2':
                _get('address2', delivery),
                'delivery_address3':
                _get('address3', delivery),
                'delivery_city':
                _get('city', delivery),
                'delivery_country':
                _get('country', delivery, default),
                'delivery_county':
                _get('county', delivery),
                'delivery_postcode':
                _get('postcode', delivery),
                'finance_option':
                basket.finance_option,
                'loan_deposit':
                basket.loan_deposit,
                'newsletter':
                basket.newsletter,
                'terms':
                basket.terms,
                'special_req':
                basket.special_req,
                'survey':
                basket.survey,
                'signup':
                basket.signup != None,
                'password':
                basket.signup.get('password') if basket.signup else None,
                'password_confirm':
                basket.signup.get('password') if basket.signup else None,
                'update_profile':
                basket.update_profile
            })

    form.configure(request, basket)
    current_page = CurrentPage.DELIVERY_ADDRESS()

    if request.method == 'POST' and form.is_valid():
        d = form.cleaned_data

        if 'email' in d:
            email = d.get('email')
        else:
            email = request.user.email

        # keep initial address information if we are not allowed to change the
        # billing address
        if not basket.can_edit_billing_address:
            for field in [
                    'company', 'address1', 'address2', 'address3', 'city',
                    'country', 'county', 'postcode'
            ]:
                d[field] = basket.billing_address.get(field)

        # save billing address
        basket.set_billing_address(title=d.get('title'),
                                   first_name=d.get('first_name'),
                                   last_name=d.get('last_name'),
                                   email=email,
                                   telephone=d.get('telephone'),
                                   company=d.get('company'),
                                   address1=d.get('address1'),
                                   address2=d.get('address2'),
                                   address3=d.get('address3'),
                                   city=d.get('city'),
                                   country=d.get('country'),
                                   county=d.get('county'),
                                   postcode=d.get('postcode'))

        # get delivery method
        deliver_to = d.get('deliver_to',
                           DeliveryAddressFrom.DELIVERY_BILLING_ADDRESS)

        basket.set_click_and_collect(
            deliver_to == DeliveryAddressFrom.DELIVERY_COLLECTION
            or basket.is_collection_only())
        basket.set_free_delivery_to(False)

        if deliver_to == DeliveryAddressFrom.FREE_DELIVERY_TO:
            location = basket.get_normalized_free_delivery_to_address()

            basket.set_delivery_address(name=d.get('delivery_free_name'),
                                        company=location.get('title'),
                                        address1=location.get('address1'),
                                        address2=location.get('address2'),
                                        address3=location.get('address3'),
                                        city=location.get('city'),
                                        country=location.get('country'),
                                        county=location.get('county'),
                                        postcode=location.get('postcode'))
            basket.set_free_delivery_to(True)
        elif deliver_to == DeliveryAddressFrom.DELIVERY_BILLING_ADDRESS:
            # deliver to my billing address
            basket.set_delivery_address(
                name='%s %s' % (d.get('first_name'), d.get('last_name')),
                company=d.get('company'),
                address1=d.get('address1'),
                address2=d.get('address2'),
                address3=d.get('address3'),
                city=d.get('city'),
                country=d.get('country'),
                county=d.get('county'),
                postcode=d.get('postcode'))
        elif deliver_to == DeliveryAddressFrom.DELIVERY_NEW_ADDRESS:
            # enter new delivery address
            basket.set_delivery_address(name=d.get('delivery_name'),
                                        company=d.get('delivery_company'),
                                        address1=d.get('delivery_address1'),
                                        address2=d.get('delivery_address2'),
                                        address3=d.get('delivery_address3'),
                                        city=d.get('delivery_city'),
                                        country=d.get('delivery_country'),
                                        county=d.get('delivery_county'),
                                        postcode=d.get('delivery_postcode'))

            # create a new record for the customer's profile
            if not request.user.is_anonymous():
                n = DeliveryAddress.objects.filter(
                    user=request.user,
                    address1=d.get('delivery_address1'),
                    address2=d.get('delivery_address2'),
                    address3=d.get('delivery_address3'),
                    city=d.get('delivery_city'),
                    country=d.get('delivery_country'),
                    county=d.get('delivery_county'),
                    postcode=d.get('delivery_postcode')).count()

                if n == 0:
                    address = DeliveryAddress()
                    address.user = request.user
                    address.name = d.get('delivery_name')
                    address.company = d.get('delivery_company')
                    address.address1 = d.get('delivery_address1')
                    address.address2 = d.get('delivery_address2')
                    address.address3 = d.get('delivery_address3')
                    address.city = d.get('delivery_city')
                    address.country = d.get('delivery_country')
                    address.county = d.get('delivery_county')
                    address.postcode = d.get('delivery_postcode')
                    address.save()
        else:
            if not basket.is_click_and_collect():
                # delivery to one of my delivery addresses taken from my profile
                delivery_address = DeliveryAddress.objects.get(
                    user=request.user, pk=deliver_to)
                basket.set_delivery_address(name=delivery_address.name,
                                            company=delivery_address.company,
                                            address1=delivery_address.address1,
                                            address2=delivery_address.address2,
                                            address3=delivery_address.address3,
                                            city=delivery_address.city,
                                            country=delivery_address.country,
                                            county=delivery_address.county,
                                            postcode=delivery_address.postcode)

        is_loan_available = settings.SHOP_LOAN_ENABLED and 'finance_option' in d and 'loan_deposit' in d

        if is_loan_available and deliver_to == DeliveryAddressFrom.DELIVERY_NEW_ADDRESS:
            # deliver to my billing address as it is required by law if finance option is chosen
            if d.get('finance_option'):
                basket.set_delivery_address(
                    name='%s %s' % (d.get('first_name'), d.get('last_name')),
                    company=d.get('company'),
                    address1=d.get('address1'),
                    address2=d.get('address2'),
                    address3=d.get('address3'),
                    city=d.get('city'),
                    country=d.get('country'),
                    county=d.get('county'),
                    postcode=d.get('postcode'))

        # loan application
        if is_loan_available:
            basket.set_finance_option(d.get('finance_option'))
            basket.set_loan_deposit(d.get('loan_deposit'))
        else:
            basket.set_finance_option(None)
            basket.set_loan_deposit(None)

        # newsletter
        if request.settings.mailchimp_enabled and 'newsletter' in d and d.get(
                'newsletter'):
            basket.newsletter = True

        # terms and conditions
        if request.settings.has_terms and 'terms' in d and d.get('terms'):
            basket.terms = True

        # special requiremenets
        basket.special_req = d.get('special_req')

        # survey
        basket.survey = d.get('survey') if 'survey' in d else None

        # signup?
        if d.get('signup', False) == True:
            basket.set_signup(email=d.get('email'),
                              first_name=d.get('first_name'),
                              last_name=d.get('last_name'),
                              password=d.get('password'))
        else:
            basket.clear_signup()

        # default delivery address?
        if 'update_profile' in d and d.get('update_profile'):
            basket.update_profile = True

        # next...
        next = next_checkout_step(request, basket, current_page)
        basket.save()
        return next

    # generate list of available delivery addresses from customer's profile
    if request.user.is_anonymous():
        delivery_addresses = []
    else:
        delivery_addresses = [{
            'id': i,
            'iso': addr.country.iso
        } for i, addr in enumerate(request.user.delivery_addresses.all(),
                                   start=3)]

    return {
        'basket': basket,
        'form': form,
        'delivery_addresses': to_json(delivery_addresses)
    }
예제 #4
0
def login(request):
    """
    Provide ability to choose to login with an existing account, create a new
    account or just providing an email address for a guest checkout.
    """
    basket = Basket(request)
    if basket.is_empty():
        return HttpResponseRedirect('/')

    login_form = CustomerLoginForm(request=request, prefix='customer')
    guest_form = GuestLoginForm(prefix='guest')
    form = None

    if request.method == 'POST':
        if request.POST.get('password_forgotten', None) != None:
            login_form = PasswordForgottenForm(request.POST, prefix='customer')
            form = login_form
        elif request.POST.get('customer', None) != None:
            login_form = CustomerLoginForm(request.POST,
                                           request=request,
                                           prefix='customer')
            form = login_form
        else:
            guest_form = GuestLoginForm(request.POST, prefix='guest')
            form = guest_form

    if form != None and form.is_valid():
        if isinstance(form, PasswordForgottenForm):
            email = form.cleaned_data.get('email')
            if request.context.password_forgotten(request, email):
                messages.success(
                    request, 'Your new password has been send to: %s.' % email)
            else:
                messages.error(
                    request,
                    'We were not able to send an email to: %s' % email)
            return HttpResponseRedirect(reverse('shop.order.login'))
        elif isinstance(form, CustomerLoginForm):
            user = form.get_user()
            if user.is_authenticated():
                auth_login(request, user)
                request.session[settings.GUEST_USER_SESSION_VAR] = ''
                response = HttpResponseRedirect(reverse('shop.order.delivery'))
                response.set_cookie('cubaneShopLogin', '1')

                # hook
                shop = get_shop()
                shop.on_customer_login(request, basket, user)

                return response
        else:
            if request.user.is_authenticated():
                auth_logout(request)

                # hook
                shop = get_shop()
                shop.on_customer_logout(request, basket)
                basket.save()

            request.session[
                settings.GUEST_USER_SESSION_VAR] = form.cleaned_data.get(
                    'email')
            return HttpResponseRedirect(reverse('shop.order.delivery'))

    return {
        'login_form': login_form,
        'guest_form': guest_form,
        'basket': basket
    }
예제 #5
0
    def clean(self):
        d = super(OrderForm, self).clean()
        click_and_collect = self.basket.click_and_collect

        # clean billing address
        clean_company(self, d, 'billing_company')
        clean_address_line(self, d, 'billing_address1')
        clean_address_line(self, d, 'billing_address2')
        clean_address_line(self, d, 'billing_address3')
        clean_city(self, d, 'billing_city')
        clean_county(self, d, 'billing_county', 'billing_country')
        clean_postcode(self, d, 'billing_postcode', 'billing_country')

        # clean delivery address
        if not click_and_collect:
            # setup default values for delivery address based on billing address
            for fieldname in self.ADDRESS_NAMES:
                delivery_fieldname = 'delivery_%s' % fieldname
                if not d.get(delivery_fieldname):
                    self.cleaned_data[delivery_fieldname] = d[
                        delivery_fieldname] = d.get('billing_%s' % fieldname)

            # clean delivery address
            clean_company(self, d, 'delivery_company')
            clean_address_line(self, d, 'delivery_address1')
            clean_address_line(self, d, 'delivery_address2')
            clean_address_line(self, d, 'delivery_address3')
            clean_city(self, d, 'delivery_city')
            clean_county(self, d, 'delivery_county', 'delivery_country')
            clean_postcode(self, d, 'delivery_postcode', 'delivery_country')

        # make delivery address fields required if not click and collect
        if not click_and_collect:
            address1 = d.get('delivery_address1')
            city = d.get('delivery_city')
            postcode = d.get('delivery_postcode')
            country = d.get('delivery_country')

            if not address1:
                self.field_error('delivery_address1', self.ERROR_REQUIRED)
            if not city: self.field_error('delivery_city', self.ERROR_REQUIRED)
            if not postcode:
                self.field_error('delivery_postcode', self.ERROR_REQUIRED)
            if not country:
                self.field_error('delivery_country', self.ERROR_REQUIRED)

        # verify that we do not end up with an empty basket
        basket = Basket(self._request,
                        prefix=self._instance.backend_basket_prefix)
        if basket.is_empty():
            from cubane.lib.mail import trigger_exception_email
            trigger_exception_email(self._request,
                                    'Cannot save empty order.',
                                    data={
                                        'form':
                                        self,
                                        'formdata':
                                        d,
                                        'basket:':
                                        basket.save_to_dict(use_session=False)
                                    })
            raise forms.ValidationError('Cannot save empty order.')

        return d