def configure(self, request, instance=None, edit=True): super(OrderForm, self).configure(request, instance, edit) if 'cubane.postcode' not in settings.INSTALLED_APPS: self.remove_field('delivery_postcode_lookup') self.remove_field('billing_postcode_lookup') self.Meta.sections['full_name'] = 'Billing Address' self.Meta.sections['delivery_name'] = 'Delivery Address' self.update_sections() # creating a new order should always have customer not present flag set if not edit: instance.customer_not_present = True instance.status = OrderBase.STATUS_NEW_ORDER # basket if request.method == 'POST': self.basket = Basket(request, prefix=instance.backend_basket_prefix) else: self.basket = Basket.restore_from_order( instance, request=request, prefix=instance.backend_basket_prefix, persistent=True) self.basket.save() self.fields['_basket'].widget.order = instance self.fields['_basket'].widget.basket = self.basket # status self.fields['status'].choices = self.get_available_status_choices( instance) # customer self.fields['customer'].queryset = User.objects.filter( is_staff=False, is_superuser=False, is_active=True) self.fields[ 'customer'].label_from_instance = lambda user: user.full_name_email # tracking provider if len(settings.TRACKING_PROVIDERS) > 0: self.fields['tracking_provider'].choices = [('', '-------')] + [ (name, name) for name, _ in settings.TRACKING_PROVIDERS ] else: self.remove_field('tracking_provider') self.remove_field('tracking_code') self.update_sections() # initial countries for billing/delivery try: default_country = Country.objects.get( iso=settings.SHOP_DEFAULT_DELIVERY_COUNTRY_ISO) self.fields['billing_country'].initial = default_country self.fields['delivery_country'].initial = default_country except Country.DoesNotExist: pass
def account_logout(self, request): basket = Basket(request) auth_logout(request) # hook shop = get_shop() shop.on_customer_logout(request, basket) basket.save() response = HttpResponseRedirect(reverse('shop.account.index')) response.set_cookie('cubaneShopLogin', '0') return response
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 shipping_notes(request, secret_id): """ Display for PDF creation of the shipping note/status """ basket = Basket(request) order = get_object_or_404(get_order_model(), secret_id=secret_id) return {'order': order}
def index(request): """ Return basket html content. """ if not request.is_ajax(): raise Http404('Ajax only.') # get basket prefix = get_basket_prefix(request, request.GET) basket = Basket(request, prefix=prefix) return HttpResponse(get_basket_html(request, basket))
def _destroy_basket(request): # destroy basket basket = Basket(request) basket.clear() if request.user.is_anonymous(): request.session[settings.GUEST_USER_SESSION_VAR] = None
def complete(request): """ (3) Final checkout step, where the order is actually created from the basket. """ basket = Basket(request) # redirect back to a previous step if we missed anything... next = get_next_checkout_step(request, basket, CurrentPage.COMPLETE()) if next: return HttpResponseRedirect(next) # state or county if 'state' in basket.billing_address: county = basket.billing_address.get('state') else: county = basket.billing_address.get('county') # create account if requested if basket.signup: # create user account md5 = hashlib.md5() md5.update(basket.signup.get('email')) email = basket.signup.get('email') if User.objects.filter(email=email).count() > 0: messages.warning( request, 'There is already an account with this email: %s.' % email) return HttpResponseRedirect(reverse('shop.account.login')) user = User.objects.create(username=md5.hexdigest()[:30], first_name=basket.signup.get('first_name'), last_name=basket.signup.get('last_name'), email=email) # replace username with user id and set password user.username = unicode(user.id) user.set_password(basket.signup.get('password')) user.save() # create profile get_customer_model().objects.create( user=user, first_name=user.first_name, last_name=user.last_name, email=user.email, title=basket.billing_address.get('title'), address1=basket.billing_address.get('address1'), address2=basket.billing_address.get('address2'), address3=basket.billing_address.get('address3'), city=basket.billing_address.get('city'), county=county, postcode=basket.billing_address.get('postcode'), country=basket.billing_address.get('country'), telephone=basket.billing_address.get('telephone'), newsletter=basket.newsletter) # log user in login_user_without_password(request, user) basket.signup = None else: if request.user.is_anonymous(): user = None else: user = request.user # if specified, copy relevant information to customer's profile if user != None and basket.update_profile: user.first_name = basket.billing_address.get('first_name') user.last_name = basket.billing_address.get('last_name') user.save() customer = get_customer_model().objects.get(user=user) customer.address1 = basket.billing_address.get('address1') customer.address2 = basket.billing_address.get('address2') customer.address3 = basket.billing_address.get('address3') customer.city = basket.billing_address.get('city') customer.county = county customer.postcode = basket.billing_address.get('postcode') customer.country = basket.billing_address.get('country') customer.telephone = basket.billing_address.get('telephone') customer.save() # create single order order = get_order_model().create_from_basket(request, basket, user) # mailchimp if request.settings.mailchimp_enabled and basket.newsletter: email = basket.billing_address.get('email') first_name = basket.billing_address.get('first_name') last_name = basket.billing_address.get('last_name') person_name = (first_name, last_name) merge_vars = {'FNAME': " ".join(person_name)} ms = MailSnake(request.settings.mailchimp_api) try: ms.listSubscribe(id=request.settings.mailchimp_list_id, email_address=email, merge_vars=merge_vars) except: pass # redirect to order status page (payment from there...) basket.save() return HttpResponseRedirect( reverse('shop.order.status', args=[order.secret_id]))
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 }
class OrderForm(BaseModelForm): ADDRESS_NAMES = [ 'company', 'address1', 'address2', 'address3', 'city', 'county', 'postcode', 'country' ] class Meta: model = get_order_model() fields = [ # status 'status', # tracking 'tracking_provider', 'tracking_code', # customer 'customer', 'email', 'telephone', # details 'special_requirements', # billing 'billing_postcode_lookup', 'full_name', 'billing_company', 'billing_address1', 'billing_address2', 'billing_address3', 'billing_city', 'billing_county', 'billing_postcode', 'billing_country', # delivery 'delivery_postcode_lookup', 'delivery_name', 'delivery_company', 'delivery_address1', 'delivery_address2', 'delivery_address3', 'delivery_city', 'delivery_county', 'delivery_postcode', 'delivery_country' ] tabs = [ { 'title': 'Line Items', 'fields': ['_basket'] }, { 'title': 'Status and Tracking', 'fields': [ # status 'status', # tracking 'tracking_provider', 'tracking_code' ] }, { 'title': 'Details', 'fields': [ # customer 'customer', 'email', 'telephone', # details 'special_requirements', # billing 'billing_postcode_lookup', 'full_name', 'billing_company', 'billing_address1', 'billing_address2', 'billing_address3', 'billing_city', 'billing_county', 'billing_postcode', 'billing_country', # delivery 'delivery_postcode_lookup', 'delivery_name', 'delivery_company', 'delivery_address1', 'delivery_address2', 'delivery_address3', 'delivery_city', 'delivery_county', 'delivery_postcode', 'delivery_country' ] } ] sections = { 'status': 'Order Status', 'tracking_provider': 'Order Delivery Tracking', 'customer': 'Customer Information', 'special_requirements': 'Customer Details', 'billing_postcode_lookup': 'Billing Address', 'delivery_postcode_lookup': 'Delivery Address', } _basket = BasketField() customer = BrowseCustomerField( required=False, help_text= 'The registered customer of this order; otherwise this order is a Guest Checkout.' ) tracking_provider = forms.ChoiceField( label='Tracking Provider', choices=[], required=False, help_text= 'Choose the tracking provider that is tracking the delivery of this order.' ) billing_postcode_lookup = PostcodeLookupField( label='Find Address', address1='id_billing_address1', address2='id_billing_address2', address3='id_billing_address3', address4=None, locality=None, city='id_billing_city', county='id_billing_county', postcode='id_billing_postcode') delivery_postcode_lookup = PostcodeLookupField( label='Find Address', address1='id_delivery_address1', address2='id_delivery_address2', address3='id_delivery_address3', address4=None, locality=None, city='id_delivery_city', county='id_delivery_county', postcode='id_delivery_postcode') def get_available_status_choices(self, instance): """ Return list of available status choices that are applicable for the given order. """ choices = OrderBase.BACKEND_STATUS_CHOICES_FILTER new_choices = [] if instance.click_and_collect: for choice in choices: if not choice[ 0] == OrderBase.STATUS_PARTIALLY_SHIPPED and not choice[ 0] == OrderBase.STATUS_SHIPPED: new_choices.append(choice) else: for choice in choices: if not choice[0] == OrderBase.STATUS_READY_TO_COLLECT: new_choices.append(choice) if instance.customer_not_present: # created via backend (customer not present) new_choices = filter( lambda c: c[0] in OrderBase.CUSTOMER_NOT_PRESENT_STATUS, new_choices) elif instance.is_invoice: # pay by invoice orders do not have any payment-related states new_choices = filter(lambda c: c[0] in OrderBase.INVOICE_STATUS, new_choices) elif instance.is_zero_amount_checkout: # zero amount checkout do not have payment-related status new_choices = filter( lambda c: c[0] in OrderBase.ZERO_AMOUNT_CHECKOUT_STATUS, new_choices) else: # regular non-invoice orders do not have invoice-related status new_choices = filter(lambda c: c[0] in OrderBase.PAYMENT_STATUS, new_choices) return new_choices 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 def configure(self, request, instance=None, edit=True): super(OrderForm, self).configure(request, instance, edit) if 'cubane.postcode' not in settings.INSTALLED_APPS: self.remove_field('delivery_postcode_lookup') self.remove_field('billing_postcode_lookup') self.Meta.sections['full_name'] = 'Billing Address' self.Meta.sections['delivery_name'] = 'Delivery Address' self.update_sections() # creating a new order should always have customer not present flag set if not edit: instance.customer_not_present = True instance.status = OrderBase.STATUS_NEW_ORDER # basket if request.method == 'POST': self.basket = Basket(request, prefix=instance.backend_basket_prefix) else: self.basket = Basket.restore_from_order( instance, request=request, prefix=instance.backend_basket_prefix, persistent=True) self.basket.save() self.fields['_basket'].widget.order = instance self.fields['_basket'].widget.basket = self.basket # status self.fields['status'].choices = self.get_available_status_choices( instance) # customer self.fields['customer'].queryset = User.objects.filter( is_staff=False, is_superuser=False, is_active=True) self.fields[ 'customer'].label_from_instance = lambda user: user.full_name_email # tracking provider if len(settings.TRACKING_PROVIDERS) > 0: self.fields['tracking_provider'].choices = [('', '-------')] + [ (name, name) for name, _ in settings.TRACKING_PROVIDERS ] else: self.remove_field('tracking_provider') self.remove_field('tracking_code') self.update_sections() # initial countries for billing/delivery try: default_country = Country.objects.get( iso=settings.SHOP_DEFAULT_DELIVERY_COUNTRY_ISO) self.fields['billing_country'].initial = default_country self.fields['delivery_country'].initial = default_country except Country.DoesNotExist: pass
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
def account_login(self, request): basket = Basket(request) checkout = request.GET.get('checkout', False) == '1' initial = { 'checkout': checkout } login_form = CustomerLoginForm(request=request, prefix='customer', initial=initial) guest_form = NewCustomerForm(prefix='guest', initial=initial) guest_form.configure(request) 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 = NewCustomerForm(request.POST, prefix='guest') guest_form.configure(request) form = guest_form if form != None and form.is_valid(): if isinstance(form, PasswordForgottenForm): email = form.cleaned_data.get('email') checkout = form.cleaned_data.get('checkout', '0') if request.context.password_forgotten(request, email): messages.success(request, 'Your new password has been sent to \'%s\'.' % email) else: messages.error(request, 'We were not able to recognise the email address \'%s\'. Please make sure that you entered your email address correctly.' % email) return HttpResponseRedirect(reverse('shop.account.login') + '?checkout=%s' % checkout) elif isinstance(form, CustomerLoginForm): user = form.get_user() checkout = form.cleaned_data.get('checkout', '0') if user.is_authenticated(): auth_login(request, user) if checkout: response = HttpResponseRedirect(reverse('shop.order.delivery')) else: response = HttpResponseRedirect(reverse('shop.account.index')) response.set_cookie('cubaneShopLogin', '1') # hook shop = get_shop() shop.on_customer_login(request, basket, user) return response else: checkout = form.cleaned_data.get('checkout', '0') if request.user.is_authenticated(): auth_logout(request) # hook shop = get_shop() shop.on_customer_logout(request, basket) basket.save() request.session[settings.SIGNUP_EMAIL_SESSION_VAR] = form.cleaned_data['email'] return HttpResponseRedirect(reverse('shop.account.signup') + '?checkout=%s' % checkout) request.session.set_test_cookie() return { 'account_section': True, 'login_form': login_form, 'guest_form': guest_form, }
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)
def add(request): """ Add given product to the customer's basket and redirect to the basket page. """ product = get_product_or_404(request) return_url = get_return_url(request) form = AddToBasketForm(request.POST, request=request, product=product) variant = '' quantity = 0 price = 0 prefix = None if form.is_valid(): d = form.cleaned_data variety_options = form.get_variety_options() variety_option_labels = form.get_variety_option_labels(variety_options) variant = ', '.join([option.title for option in variety_options]) quantity = form.get_quantity() prefix = get_basket_prefix(request, d) # add to basket basket = Basket(request, prefix=prefix) item = basket.add_item(product, variety_options, quantity, custom=None, labels=variety_option_labels) if item: price = item.total_product else: messages.error( request, "Please note that the product '%s' cannot be added to basket." % product.title) # alert for non-returnable products if product.non_returnable: messages.warning( request, "Please note that the product '%s' cannot be returned." % product.title) # hook shop = get_shop() shop.on_basket_added(request, basket, product, variety_options, quantity) basket.save() errors = False else: errors = form.errors if request.is_ajax(): basket = Basket(request, prefix=prefix) return to_json_response({ 'success': True, 'html': get_basket_html(request, basket), 'errors': errors, 'prefix': basket.prefix, 'added': product.to_ga_dict({ 'variant': variant, 'quantity': quantity, 'price': price }) }) else: return HttpResponseRedirect(return_url)
def google_products(self, request): def prettify_xml(elem): """ Return a pretty-printed XML string for the Element. """ rough_string = tostring(elem) reparsed = minidom.parseString(rough_string) return reparsed.toprettyxml(indent='\t').encode('utf-8', 'replace') products = get_product_model().objects.filter(feed_google=True) root = Element('rss') root.attrib['xmlns:g'] = 'http://base.google.com/ns/1.0' root.attrib['version'] = '2.0' channel = SubElement(root, 'channel') title = SubElement(channel, 'title') title.text = request.settings.name link = SubElement(channel, 'link') link.text = settings.DOMAIN_NAME description = SubElement(channel, 'description') for p in products: # availability if p.is_available and not p.pre_order: txt_availability = 'in stock' elif p.pre_order: txt_availability = 'preorder' else: txt_availability = 'out of stock' # determine delivery charge by placing the product onto the basket basket = Basket() basket.add_item(p, None, 1) delivery_charge = basket.delivery # determine feed item attributes txt_id = unicode(p.id) txt_title = clean_unicode(p.title).strip() txt_link = p.get_absolute_url() txt_description = text_from_html(p.description, 5000) txt_condition = 'new' txt_price = '%.2f GBP' % p.price txt_google_category = p.category.google_product_category if p.category and p.category.google_product_category else None txt_category = p.category.get_taxonomy_path( ) if p.category else None txt_country = 'GB' txt_delivery_price = '%s %s' % (delivery_charge, 'GBP') txt_barcode = p.barcode.strip() if p.barcode else None txt_part_number = p.part_number.strip() if p.part_number else None txt_brand = p.get_brand_title() # create item item = SubElement(channel, 'item') # id _id = SubElement(item, 'g:id') _id.text = txt_id # title title = SubElement(item, 'title') title.text = txt_title # link/url link = SubElement(item, 'link') link.text = txt_link # main text description = SubElement(item, 'description') description.text = txt_description # condition condition = SubElement(item, 'g:condition') condition.text = txt_condition # price price = SubElement(item, 'g:price') price.text = txt_price # availability availability = SubElement(item, 'g:availability') availability.text = txt_availability # google shopping category if txt_google_category: gcategory = SubElement(item, 'g:google_product_category') gcategory.text = txt_google_category # product type if txt_category: category = SubElement(item, 'g:product_type') category.text = txt_category # shipping shipping = SubElement(item, 'g:shipping') # country country = SubElement(shipping, 'g:country') country.text = txt_country # delivery price delivery_price = SubElement(shipping, 'g:price') delivery_price.text = txt_delivery_price # barcode, must be a valid UPC-A (GTIN-12), EAN/JAN (GTIN-13) # or GTIN-14, so we need to have at least 12 characters. if txt_barcode: gtin = SubElement(item, 'g:gtin') gtin.text = txt_barcode # part number if txt_part_number: _mpn = SubElement(item, 'g:mpn') _mpn.text = txt_part_number # brand if txt_brand: brand = SubElement(item, 'g:brand') brand.text = txt_brand # image if p.image: image = SubElement(item, 'g:image_link') image.text = p.image.large_url # additional images if len(p.gallery) > 0: for m in p.gallery[:10]: additional_image_link = SubElement( item, 'g:additional_image_link') additional_image_link.text = m.large_url # get temp. filename f = NamedTemporaryFile(delete=False) tmp_filename = f.name f.close() # create tmp file (utf-8) f = open(tmp_filename, 'w+b') f.write(prettify_xml(root)) f.seek(0) # send response filename = 'google_products_%s.xml' % datetime.date.today().strftime( '%d_%m_%Y') response = HttpResponse(FileWrapper(f), content_type='text/plain') response['Content-Disposition'] = 'attachment; filename=%s' % filename return response
def basket_editor(self, request): prefix = request.GET.get('prefix') basket = Basket(request, prefix=prefix) return {'basket': basket}