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'))
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 }
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) }
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 }
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