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 update(request): """ Update basket. This may also trigger "continue shopping" and "checkout". """ # get prefix prefix = get_basket_prefix(request, request.POST) # get basket basket = Basket(request, prefix=prefix) return_url = get_return_url(request) # keep track of removed items removed_items = [] def add_removed_item(item): removed_items.append(item) if not basket.is_frozen: # update quantity for item in list(basket.items): k = 'qty_%s' % item.hash if k in request.POST: try: qty = int(request.POST.get(k, 0)) except ValueError: qty = 0 removed = basket.update_quantity_by_hash(item.hash, qty) if removed: add_removed_item(item) # remove item item_hash = request.POST.get('remove_basket_item', '') if item_hash != '': item = basket.remove_item_by_hash(item_hash) if item: add_removed_item(item) # voucher if 'voucher-code' in request.POST: voucher_code = request.POST.get('voucher-code') if voucher_code: voucher_code = voucher_code.upper() if voucher_code: if voucher_code != basket.get_voucher_code(): # add voucher code to basket if not basket.set_voucher(voucher_code): if not request.is_ajax(): messages.error( request, 'Expired or unrecognised voucher code.') else: basket.remove_voucher() # delivery country if 'country_iso' in request.POST: try: country = Country.objects.get( iso=request.POST.get('country_iso')) basket.set_delivery_country(country) except Country.DoesNotExist: pass # custom total (staff only) if request.user.is_staff or request.user.is_superuser: if 'custom-total' in request.POST: custom_total = request.POST.get('custom-total') if custom_total == '': basket.clear_custom_total() else: custom_total = Decimal(custom_total) basket.set_custom_total(custom_total) # click and collect if 'click_and_collect' in request.POST: basket.set_click_and_collect( request.POST.get('click_and_collect') in ['true', 'on']) # delivery option option_id = request.POST.get('delivery_option_id', None) delivery_option_details = None if option_id: try: option = DeliveryOption.objects.get(pk=option_id, enabled=True) delivery_option_details = basket.get_delivery_details(option) basket.set_delivery_option(option) except DeliveryOption.DoesNotExist: pass # processing state (backend only) if request.user.is_staff or request.user.is_superuser: for item in list(basket.items): k = 'processed_%s' % item.hash if k in request.POST: processed = request.POST.get(k, 'off') == 'on' basket.update_processed_by_hash(item.hash, processed) # save changes to basket basket.save() # ajax? if request.is_ajax(): basket = Basket(request, prefix=prefix) return to_json_response({ 'success': True, 'prefix': basket.prefix, 'html': get_basket_html(request, basket), 'delivery': get_delivery_option_details_html(request, delivery_option_details), 'is_collection_only': basket.is_collection_only(), 'finance_options': [option.to_dict() for option in basket.get_finance_options()], 'removed': [item.to_ga_dict() for item in removed_items] }) # next action = request.POST.get('action', 'update') if action == 'continue': return HttpResponseRedirect(return_url) elif action == 'checkout': return HttpResponseRedirect(reverse('shop.order.delivery')) else: return HttpResponseRedirect(return_url)