Repository: saleor/saleor

Issue:
Don't show address form in checkout
Show address form only if user demand it. Highlight saved address and hide form after submit. Related with #100 issue.



Discussion:

Resolving patch:
diff --git a/saleor/checkout/steps.py b/saleor/checkout/steps.py
--- a/saleor/checkout/steps.py
+++ b/saleor/checkout/steps.py
@@ -1,6 +1,5 @@
 from __future__ import unicode_literals
 
-from django.forms.models import model_to_dict
 from django.core.exceptions import ValidationError
 from django.db import models
 from django.db import transaction
@@ -45,26 +44,28 @@ class BaseAddressStep(BaseCheckoutStep):
     def __init__(self, checkout, request, address):
         super(BaseAddressStep, self).__init__(checkout, request)
         if address:
-            address_dict = model_to_dict(address, exclude=['id', 'user'])
+            address_dict = Address.objects.as_data(address)
             self.address = Address(**address_dict)
         else:
             self.address = Address()
+        existing_selected = False
         address_form = AddressForm(request.POST or None, instance=self.address)
         if request.user.is_authenticated():
             address_book = list(request.user.address_book.all())
             for entry in address_book:
-                data = model_to_dict(entry.address, exclude=['id', 'user'])
+                data = Address.objects.as_data(entry.address)
                 instance = Address(**data)
                 entry.form = AddressForm(instance=instance)
-                entry.is_default = self.is_default_address(entry, request.user)
+                entry.is_selected = Address.objects.are_identical(
+                    entry.address, self.address)
+                if entry.is_selected:
+                    existing_selected = True
         else:
             address_book = []
+        self.existing_selected = existing_selected
         self.forms = {'address': address_form}
         self.address_book = address_book
 
-    def is_default_address(self, entry, user):
-        raise NotImplementedError()
-
     def forms_are_valid(self):
         self.cleaned_data = {}
         address_form = self.forms['address']
@@ -80,6 +81,7 @@ def process(self, extra_context=None):
         context = dict(extra_context or {})
         context['form'] = self.forms['address']
         context['address_book'] = self.address_book
+        context['existing_address_selected'] = self.existing_selected
         return super(BaseAddressStep, self).process(extra_context=context)
 
 
@@ -131,21 +133,19 @@ def save(self):
 
     def add_to_order(self, order):
         self.address.save()
-        if order.user:
-            User.objects.store_address(order.user, self.address, billing=True)
         order.anonymous_user_email = self.anonymous_user_email
         order.billing_address = self.address
         order.save()
+        if order.user:
+            alias = '%s, %s' % (order, self)
+            User.objects.store_address(order.user, self.address, alias,
+                                       billing=True)
 
     def validate(self):
         super(BillingAddressStep, self).validate()
         if 'anonymous' in self.forms and not self.anonymous_user_email:
             raise InvalidData()
 
-    def is_default_address(self, entry, user):
-        return (user.is_authenticated() and
-                user.default_billing_address_id == entry.id)
-
 
 class ShippingStep(BaseAddressStep):
 
@@ -191,18 +191,16 @@ def forms_are_valid(self):
 
     def add_to_order(self, order):
         self.address.save()
-        if order.user:
-            User.objects.store_address(order.user, self.address, shipping=True)
         delivery_method = self.group['delivery_method']
         group = ShippedDeliveryGroup.objects.create(
             order=order, address=self.address,
             price=delivery_method.get_price(),
             method=smart_text(delivery_method))
         group.add_items_from_partition(self.delivery_group)
-
-    def is_default_address(self, entry, user):
-        return (user.is_authenticated() and
-                user.default_shipping_address_id == entry.id)
+        if order.user:
+            alias = '%s, %s' % (order, self)
+            User.objects.store_address(order.user, self.address, alias,
+                                       shipping=True)
 
     def process(self, extra_context=None):
         context = dict(extra_context or {})
diff --git a/saleor/userprofile/models.py b/saleor/userprofile/models.py
--- a/saleor/userprofile/models.py
+++ b/saleor/userprofile/models.py
@@ -16,8 +16,8 @@
 
 class AddressBookManager(models.Manager):
 
-    def store_address(self, user, address):
-        data = model_to_dict(address, exclude=['id'])
+    def store_address(self, user, address, alias):
+        data = Address.objects.as_data(address)
         query = dict(('address__%s' % (key,), value)
                      for key, value in data.items())
         candidates = self.get_queryset().filter(user=user, **query)
@@ -26,7 +26,8 @@ def store_address(self, user, address):
             entry = candidates[0]
         except IndexError:
             address = Address.objects.create(**data)
-            entry = AddressBook.objects.create(user=user, address=address)
+            entry = AddressBook.objects.create(user=user, address=address,
+                                               alias=alias)
         return entry
 
 
@@ -63,6 +64,17 @@ def get_slug(self):
         return mark_safe(re.sub(r'[-\s]+', '-', value))
 
 
+class AddressManager(models.Manager):
+
+    def as_data(self, addr):
+        return model_to_dict(addr, exclude=['id', 'user'])
+
+    def are_identical(self, addr1, addr2):
+        data1 = self.as_data(addr1)
+        data2 = self.as_data(addr2)
+        return data1 == data2
+
+
 class Address(models.Model):
 
     first_name = models.CharField(
@@ -96,6 +108,8 @@ class Address(models.Model):
         pgettext_lazy('Address field', 'phone number'),
         max_length=30, blank=True)
 
+    objects = AddressManager()
+
     def __unicode__(self):
         return '%s %s' % (self.first_name, self.last_name)
 
@@ -134,8 +148,9 @@ def create_user(self, email, password=None, is_staff=False,
     def create_superuser(self, email, password=None, **extra_fields):
         return self.create_user(email, password, is_staff=True, **extra_fields)
 
-    def store_address(self, user, address, billing=False, shipping=False):
-        entry = AddressBook.objects.store_address(user, address)
+    def store_address(self, user, address, alias,
+                      billing=False, shipping=False):
+        entry = AddressBook.objects.store_address(user, address, alias)
         changed = False
         if billing and not user.default_billing_address_id:
             user.default_billing_address = entry


Test patch:
diff --git a/saleor/registration/tests.py b/saleor/registration/tests.py
--- a/saleor/registration/tests.py
+++ b/saleor/registration/tests.py
@@ -22,6 +22,12 @@
 URLENCODED_MIME_TYPE = 'application/x-www-form-urlencoded; charset=UTF-8'
 
 
+class SessionMock(Mock):
+
+    def __setitem__(self, key, value):
+        pass
+
+
 class LoginUrlsTestCase(TestCase):
     """Tests login url generation."""
 
@@ -259,6 +265,7 @@ def test_another_user_logged_out(self, get, now):
         another_user = Mock()
         request = Mock()
         request.user = another_user
+        request.session = SessionMock()
 
         # first user clicks link in his email
         result = change_email(request, token_object.token)