Commits

Wai Yi Leung committed 3f4ea54 Merge

merge upto tip c40400eca0ea

  • Participants
  • Parent commits b8dda1d, c40400e

Comments (0)

Files changed (301)

-*.pyc
 satchmo/static/images/productimage-picture-*_*.jpg
 brand*translation-picture-*.jpg
 bannerimage-*jpg
+syntax: glob
+build
+.DS_Store
+.build
+.project
+.pydevproject
+*.orig
+*.rej
+*~
+*.o
+*.pyo
+*.pyc
+_private
+*_local.py
+_LOCAL_FLAG
+_DEVELOPMENT_FLAG
+_temp
+test.db
+dist
+build
+*.egg-info
+*_85x85_*
+*_84x84_*
+\#*\#
+.*.sw?
+*.egg
+.hg
+
 syntax: glob
 build
+.DS_Store
 .build
 .project
 .pydevproject
 *_85x85_*
 *_84x84_*
 \#*\#
+.*.sw?
+*.egg
+.git

docs/configuration.txt

 
 2. In addition to the Satchmo specific settings, there are some Django settings you will want to make sure are properly set:
 
-    - Make sure that your ``DATABASE_ENGINE`` variable is also set correctly.
+    - Make sure that your ``DATABASES['default']['ENGINE']`` variable is also set correctly.
     - You should ensure that all of your paths are setup correctly.  Key ones to look at are:
 
         + ``MEDIA_ROOT`` (this is where images will be stored)
 
     L10N_SETTINGS = {
       'currency_formats' : {
-         'EURO' : {'symbol': u'€', 'positive' : u"€%(val)0.2f", 'negative': u"€(%(val)0.2f)", 'decimal' : ','},
+         'EURO' : {'symbol': u'€', 'positive' : u"€%(val)0.2f", 'negative': u"€(%(val)0.2f)",
+                   'decimal' : ','},
       },
       'default_currency' : 'EURO',
       'show_admin_translations': False,
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Once your store is live, you may want to disable the admin ability to edit the site configuration.  To do this, edit your settings.py file and add a new entry ``LIVESETTINGS_OPTIONS`` with the settings you want to lock into place.
+The easiest way to get it is by the URL http://your.site/settings/export/.
 
 The ``LIVESETTINGS_OPTIONS`` must be formatted as follows::
 
     LIVESETTINGS_OPTIONS = {
         1 : {
-            'DB' : (True|False),
+            'DB' : False,   # or True for use db and ignore these settings
             'SETTINGS' : {
                 'GROUPKEY' : {
                     'KEY' : val,

docs/custom-admin.txt

 .. Note::
     These changes must be included in an application that is listed after 
     all the other Satchmo Apps in ``INSTALLED_APPS``
+
+Using Mix-ins to customize the admin
+------------------------------------
+
+Mix-ins are a very powerful feature available in python that allow for
+advanced customization of Satchmo.  With mix-ins you can add arbitrary
+elements (functions, model attributes, etc...) to any class/model.
+The full uses of mix-ins are outside the scope of this document but
+let’s start with an example.
+
+Suppose you want to show product SKUs of all the products in an order
+on the Product Orders page. The screenshot below shows you what the current
+order screen looks like:
+
+.. image:: /images/order-screen2.png
+
+We will modify it to show all the skus in an order like this:
+
+.. image:: /images/order-screen1.png
+
+
+Here is a chunk of code that would create a list of skus for a given order::
+
+        def order_sku(self):
+            allsku = ''
+            for item in self.orderitem_set.all():
+                allsku += "%s<br />" % item.product.sku
+            return allsku
+        order_sku.allow_tags = True
+        order_sku.short_description = "Order SKUs"
+
+
+You could then add ‘order_sku’ to the list display of Order.  The
+problem is, where do you put the chunk of code listed above?  You
+could add it to the Order models but that would be forking Satchmo and
+later when it was time to upgrade to the next version of Satchmo
+things could be much more difficult.  The solution is mix-ins.
+
+Mix-ins allow you to dynamically change the inheritance of a class.
+We will change Orders from looking like this::
+
+    class Order(models.Model):
+
+to this::
+    
+    class Order(models.Model, ourNewClass):
+    
+In order to accomplish this without actually modifying existing Satchmo done, you
+can put order_sku in a class::
+
+    class OrderExtend:
+        def order_sku(self):
+            allsku = ''
+            for item in self.orderitem_set.all():
+                allsku += "%s<br />" % item.product.sku
+            return allsku
+        order_sku.allow_tags = True
+        order_sku.short_description = "Order SKUs"
+
+and adding::
+
+    Order.__bases__ += (OrderExtend,)
+    
+The last bit takes the __bases__ of Order (which are its base
+inheritance classes) and adds OrderExtend to it.  Because Order now
+inherits from OrderExtend we can use order_sku.  To make skus show up
+in the admin we create ``localsite/admin.py`` and put all of our code in
+it so it looks like this::
+
+    from django.contrib import admin
+    from django.db import models
+    from satchmo_store.shop.models import Order, OrderItem
+    from satchmo_store.shop.admin import OrderOptions
+
+    class OrderExtend:
+        def order_sku(self):
+            allsku = ''
+            for item in self.orderitem_set.all():
+                allsku += "%s<br />" % item.product.sku
+            return allsku
+        order_sku.allow_tags = True
+        order_sku.short_description = "Order SKUs"
+
+    Order.__bases__ += (OrderExtend,)
+
+    admin.site.unregister(Order)
+
+    class CustomOrderAdmin(OrderOptions):
+        list_display = ('id', 'order_sku', 'contact', 'time_stamp',
+                        'order_total', 'balance_forward', 'status', 
+                        'invoice', 'packingslip','shippinglabel')
+
+    admin.site.register(Order, CustomOrderAdmin)
+
+Obviously you could do a lot more with mix-ins. You can add arbitray functions
+and attributes to any model and any class.  A much longer
+explaination that is not django specific but has more examples (and the document used as a reference
+for writing this up) can be found `here <http://www.linuxjournal.com/node/4540/print>`_

docs/custom-payment.txt

  - Takes order data and formats it in the appropriate manner (``prepareData``)
  - Sends the data to the processing server/url (``authorize_payment``, ``capture_payment``, ``capture_authorized_payment``) and returns the results.
 
-Of them, only ``capture_payment`` is required.  If the processor can both authorize and process, then you need to add a function "can_authorize", which returns True, and implement the other two methods.  See the ``dummy`` module for an example.
+Of them, only ``capture_payment`` is required.  If the processor can both authorize and process, then you need to add a function ``can_authorize``, which returns True, and implement the other two methods.  See the ``dummy`` module for an example.
 
 Optionally, the processor can include include test code so that it is easy to verify from
 the command line.
 
 Here is a stub you can use to create your own processor::
 
-	from payment.modules.base imort BasePaymentProcessor, ProcessorResult
+    from payment.modules.base import BasePaymentProcessor, ProcessorResult
+
     class PaymentProcessor(BasePaymentProcessor):
-
-
         def __init__(self, settings):
             # Set up your configuration for items like
             # Test server, url, various flags and settings
-        	super(PaymentProcessor, self).__init__('example', settings)
+            super(PaymentProcessor, self).__init__('example', settings)
 
         def capture_payment(self):
             # Send the data via the appropriate manner and return a ProcessorResult
 Create the new configuration group::
 
     PAYMENT_GROUP = ConfigurationGroup('PAYMENT_MYNEWPROCESSOR',
-    _('My New Processor Payment Settings'),
-    requires=PAYMENT_MODULES,
-    ordering=102)
+        _('My New Processor Payment Settings'),
+        ordering=102)
+
+.. Note:: The key of the ``ConfigurationGroup`` must be the module name, upper-cased.
+
+For example, if your custom payment module was located in ``mypaymentmodules.mynewprocessor``,
+the ``ConfigurationGroup`` should be given the key ``PAYMENT_MYNEWPROCESSOR``.
+The reason for this is that the ``active_gateways()`` function in ``payment/__init__.py`` attempts 
+to automatically determine these keys by appending the upper-cased module name to ``PAYMENT_``.
 
 Now register the settings you need::
 
-    config_register([
-
-        StringValue(PAYMENT_GROUP,
-            'KEY',
-            description=_("Module key"),
-            hidden=True,
-            default = 'MYNEWPROCESSOR'),
-
-        ModuleValue(PAYMENT_GROUP,
-            'MODULE',
-            description=_('Implementation module'),
-            hidden=True,
-            default = 'satchmo.payment.modules.mynewprocessor'),
-
-        BooleanValue(PAYMENT_GROUP,
-            'SSL',
-            description=_("Use SSL for the checkout pages?"),
-            default=False),
-
-
+    config_register_list(
         BooleanValue(PAYMENT_GROUP,
             'LIVE',
             description=_("Accept real payments"),
             description=_('Your Processor password'),
             default=""),
 
-
         BooleanValue(PAYMENT_GROUP,
             'EXTRA_LOGGING',
             description=_("Verbose logs"),
             help_text=_("Add extensive logs during post."),
             default=False)
-
-    ])
+    )
 
 All of these settings can be accessed in your ``__init__`` method (shown above).
 For example, the LIVE value above can be accessed by using ``settings.LIVE.value``
 The ``views.py`` file contains the information that maps your processor views to the existing
 views or your own custom view.
 
-For most people, the views contained in payment.common.views will be sufficient.  The example below
+For most people, the views contained in payment.views will be sufficient.  The example below
 maps these views to views already available in Satchmo::
 
     from livesettings import config_get_group
         return render_to_response(template, context)
 
 
-All of the current satchmo payment views are in ``/payment/common/views``.
+All of the current satchmo payment views are in ``/payment/views``.
 Please review these before trying to build one of your own!
 
 Url configuration
     config = config_get_group('PAYMENT_MYNEWPROCESSOR')
 
     urlpatterns = patterns('satchmo',
-         (r'^$', 'payment.modules.myprocessor.views.pay_ship_info', {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step2'),
-         (r'^confirm/$', 'payment.modules.trustcommerce.views.confirm_info', {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step3'),
-         (r'^success/$', 'payment.common.views.checkout.success', {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-success'),
+         (r'^$', 'mypaymentmodules.myprocessor.views.pay_ship_info',
+                        {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step2'),
+         (r'^confirm/$', 'payment.modules.trustcommerce.views.confirm_info',
+                        {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-step3'),
+         (r'^success/$', 'payment.views.checkout.success',
+                        {'SSL':config.SSL.value}, 'MYNEWPROCESSOR_satchmo_checkout-success'),
     )
 
 
     INSTALLED_APPS = (
             ...
             'payment',
-            'payment.modules.myprocessor',
+            'mypaymentmodules.myprocessor',
             ...
 
 

docs/custom-product.txt

 Building your module
 --------------------
 
-In a custom product module, most of the work is done in the ``models.py`` and
-template files. You will also need an ``admin.py`` file and a ``config.py``
-file. This section contains several example files that you can add to a new
-or existing app and extend.
+In a custom product module, most of the work is done in the
+``models.py`` and template files. You will also need an ``admin.py``
+file like for any other model which shall be available in the
+admin. This section contains several example files that you can add to
+a new or existing app and extend.
 
 A basic ``models.py`` file with a custom product model looks like this::
 
-
     from django.db import models
     from django.utils.translation import ugettext_lazy as _
     from product.models import Product
 
+    SATCHMO_PRODUCT=True
+
+    def get_product_types():
+        """
+        Returns a tuple of all product subtypes this app adds
+        """
+        return ('MyNewProduct', )
+
     class MyNewProduct(models.Model):
         product = models.OneToOneField(Product, verbose_name=_('Product'),
             primary_key=True)
 
         def _get_subtype(self):
+            """
+            Has to return the name of the product subtype
+            """
             return 'MyNewProduct'
 
         def __unicode__(self):
             verbose_name = _('My New Product')
             verbose_name_plural = _('My New Products')
 
+The important parts are the attribute :attr:`MyNewProduct.product`
+which links to the related :class:`product.models.Product` and the
+method :meth:`MyNewProduct._get_subtype()` which returns a string
+representation of this model.
+
+The function :func:`get_product_types()` returns a list of all custom
+product models this app adds. This method is used to discover the
+custom product models from all installed apps.
+
 
 This is the corresponding ``admin.py`` file. This file is needed to make your
-models visible in Django's admin app. Make sure that you replace ``my_app``
-with the name of your app::
-
+models visible in Django's admin app::
 
     from django.contrib import admin
-    from models import MyNewProduct # TODO: Replace app name!
+    from models import MyNewProduct
 
     admin.site.register(MyNewProduct)
 
 
-The ``config.py`` file tells Satchmo about your product model. Replace
-``my_app`` here too::
-
-
-    from django.utils.translation import ugettext_lazy as _
-    from livesettings import config_get
-
-    PRODUCT_TYPES = config_get('PRODUCT', 'PRODUCT_TYPES')
-
-    # TODO: Replace app name!
-    PRODUCT_TYPES.add_choice(('my_app::MyNewProduct', _('My New Product')))
-
-
 Configuration
 -------------
 
-Once you've created the above three files in your app, you have all the code
+Once you've created the above files in your app, you have all the code
 necessary to use your new product model in Satchmo. All that's left is the
 configuration.
 
-1. Make sure that the app with your product model is in your project's ``INSTALLED_APPS`` setting.
+1. Make sure that the app with your product model is in your project's
+   ``INSTALLED_APPS`` setting.
 
 2. Run ``python manage.py syncdb`` in your project directory.
 
 of Satchmo's default product types. You will find an "Add MyNewProduct" link in
 the "Product Subtypes" section of each product's admin page.
 
+
 Extending the model and templates
 ---------------------------------
 
 content::
 
 
-    {% extends "base_product.html" %}
+    {% extends "product/product.html" %}
 
     {% block title %}{{ product.mynewproduct.title }}{% endblock title %}
 
 ``templates/base_product.html``, and ``templates/product/`` in the Satchmo
 source code.
 
+
+Using model inheritance
+-----------------------
+
+There is another possibility for extending the product model using
+model inheritance. You can find more information in the `first installment <http://thisismedium.com/tech/satchmo-diaries-part-one/>`_
+of the Satchmo Diaries.
+
+.. warning::
+
+   Using inheritance is currently not recommended, because it has some
+   issues when it is used without care. Some methods of
+   :class:`product.models.Product` currently do not expect to find
+   subtypes which inherit attributes and methods from
+   :class:`product.models.Product`.
+
+If you want to use inheritance, make sure *not* to add
+your model to the list returned by :func:`get_product_types()`, else
+you might get some trouble with infinite recursions. An alternative
+would be to extend the current implementation to be able to handle
+models which inherit from :class:`product.models.Product`.
+
+So, your ``models.py`` file should look like this::
+
+    from django.db import models
+    from django.utils.translation import ugettext_lazy as _
+    from product.models import Product
+
+    class MyNewProduct(Product):
+
+        # TODO: your attributes here
+
+        objects = ProductManager()
+
+        def __unicode__(self):
+            return u"MyNewProduct: %s" % self.name
+
+        class Meta:
+            verbose_name = _('My New Product')
+            verbose_name_plural = _('My New Products')
+
+
+To make this model available in the admin interface you should create
+a corresponding ``admin.py``::
+
+    from django.contrib import admin
+    from models import MyNewProduct
+    from product.admin import ProductOptions
+
+    # TODO: do your customizations here
+    class MyNewProductAdmin(ProductOptions):
+        pass
+
+    admin.site.register(MyNewProduct, MyNewProductAdmin)
+
+
+
 Conclusion
 ----------
 
 model. If you need help with something discussed here or with more advanced
 topics, feel free to ask the `mailing list`_.
 
-There is another possibility for extending the product model using
-model inheritance. You can find more information in the `first installment <http://thisismedium.com/tech/satchmo-diaries-part-one/>`_
-of the Satchmo Diaries.
-
 Finally, if you create a product model that others may find useful, please
 consider contributing it to the Satchmo community.
 

docs/customization.txt

     1. Create the new tag in your application's templatetags directory
     2. Selectively override the Satchmo templates that use the tag
     3. Import the new tag at the top of each template and use it in the template
+
+Example tags
+++++++++++++
+
+Here is a quick example showing how you can create an `inclusion tag <http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags>`_
+to display a list of new arrivals or featured items.
+
+First, make sure you have a :file:`templatetags` directory in your :file:`localsite` directory (this assumes you 
+are using the default satchmo setup). In this directory, create a file called :file:`local_tags.py`
+
+Your :file:`local_tags.py` should look like this::
+
+    from django import template
+    from product.models import Product
+    register = template.Library()
+
+    @register.inclusion_tag('localsite/new_arrivals.html') 
+    def show_new_arrivals(number): 
+        new_arrivals = Product.objects.all().order_by('date_added')[:number] 
+        return {'new_arrivals': new_arrivals}
+
+    @register.inclusion_tag('localsite/featured_items.html') 
+    def show_featured_items(number): 
+        featured_items = Product.objects.filter(featured=True)[:number] 
+        return {'featured_items': featured_items}
+
+Each of these tags also will need a custom html template that will be used to render
+the items. Inside your template directory, create the following files :file:`/localsite/new_arrivals.html`::
+
+    {% for product in new_arrivals %}
+        <ul><a href="{{ product.get_absolute_url }}">{{product.translated_name}}</a></ul>
+    {% endfor %}
+
+As well as this file :file:`/localsite/featured_items.html`::
+
+    {% for product in featured_items %}
+        <ul><a href="{{ product.get_absolute_url }}">{{product.translated_name}}</a></ul>
+    {% endfor %}
+
+In order to use these tags, add them to your templates::
+
+    {% extends "shop/base.html" %}
+    {% load local_tags %}
+
+    <h1>New Arrivals</h1>
+        <ul>
+        {% show_new_arrivals 5 %}
+        </ul>
+    <h1>Featured Items</h1>
+        <ul>
+        {% show_featured_items 5 %}
+        </ul>
+
+This feature is a very powerful and simple way to add custom information into
+your custom satchmo site.

docs/directory_structure.txt

 Satchmo Projects
 ----------------
 
-This directory contains 3 example projects that illustrate how to layout Satchmo and integrate it with other
+This directory contains an example project that illustrate how to layout Satchmo and integrate it with other
 Django applications. The installation process will discuss how to setup your individual application based on
-these samples. The simple and large projects include a sample database and can be run directly to provide
+this sample. The simple project includes a sample database and can be run directly to provide
 a quick example of a Satchmo store.
 
-Base
-^^^^
-
-This project contains the basic building blocks of a Satchmo store.
-
 Simple
 ^^^^^^
 
 Username: admin
 Password: simple
 
-
-Large
-^^^^^
-
-This is a very basic example of a "large" Satchmo store.  Basically it has all the satchmo apps loaded, plus
-flatpages (built-in to Django) and Testimonials (from http://gosatchmo.com/apps/django-testimonials/)
-
-It should work right from checkout.  Start it with "./manage.py runserver" and browse to http://localhost:8000/
-
-Admin is:
-
-Username: admin
-Password: large
-
 Skeleton
 ^^^^^^^^
 

docs/discounts.txt

     {% if sale %}
     <div>
       <div class="saleprices">
-        <h3> Regular price: <span class="saleprice" id="price">{{product.unit_price|currency}}</span></h3>
-        <h3> {{ sale.percentage_text }} off: <span class="saleprice" id="sale_saved">{{ product|discount_saved:"sale"|currency }}</span></h3>
-        <h3> Your price: <span class="saleprice" id="sale_price">{{ product|discount_price:"sale"|currency }}</span></h3>
+        <h3> Regular price: <span class="saleprice" id="price">{{
+                           product.unit_price|currency}}</span></h3>
+        <h3> {{ sale.percentage_text }} off: <span class="saleprice" id="sale_saved">{{
+                           product|discount_saved:"sale"|currency }}</span></h3>
+        <h3> Your price: <span class="saleprice" id="sale_price">{{
+                           product|discount_price:"sale"|currency }}</span></h3>
     {% else %}
       <h3 id="price">{{product.unit_price|currency}}</h3>
     </div>

docs/images/order-screen1.png

Added
New image

docs/images/order-screen2.png

Added
New image

docs/migration.txt

 Installing Satchmo 0.9.1 with South
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-As the migrations in the ``product`` app are based on v0.9, you don't have to
-apply migrations from ``0001_initial`` onwards for a fresh installation - simply
-let django's ``syncdb`` do it's job.
-
 .. Note::
    We asume that you've already installed South, but have yet to take the leap
    with Satchmo; see `<http://south.aeracode.org/docs/installation.html>`_ for
 - Before installing Satchmo, ensure that your tables and migrations are
   up-to-date, by running ``syncdb`` and ``migrate``.
 
-- With Satchmo still not installed, disable South by removing/commenting it out
-  from your ``INSTALLED_APPS``.
-
 - Install Satchmo by adding it to your path and ``INSTALLED_APPS``.
 
-- Create the database tables for Satchmo's models::
+- You have two options:
 
-    $ python manage.py syncdb
+  - Create the database tables for Satchmo's non-migration models, then create
+    the ``product`` app tables and run the migrations::
 
-- Enable South by adding/uncommenting it from your ``INSTALLED_APPS``.
+      $ python manage.py syncdb
+      $ python manage.py migrate product
 
-- Since the database tables for Satchmo are already up-to-date, you can safely
-  "fake" all the migrations in Satchmo::
+  - Alternatively, you can create the tables directly and skip running the
+    migrations::
 
-    $ python manage.py migrate product --list
-
-     product
-      ( ) 0001_initial
-      ( ) 0002_add_attributeoption
-      ( ) 0003_add_productattribute_option
-      ( ) 0004_remove_productattribute_name
-      ( ) 0005_fix_attributeoption_error_default_spelling
-      ( ) 0006_custom_textfield_add_constraint
-      ( ) 0007_add_discount_valid_products_field
-      ( ) 0008_remove_discount_validproducts_field
-      ( ) 0009_add_categoryattributes
-      ( ) 0010_add_discountable_categories
-      ( ) 0011_split_products
-
-    $ python manage.py migrate product --fake
-     - Migrating forwards to 0012_update_contenttypes.
-     > subscription:0001_split
-       (faked)
-     > subscription:0002_update_contenttypes
-       (faked)
-     > product:0001_initial
-       (faked)
-     > product:0002_add_attributeoption
-       (faked)
-     > product:0003_add_productattribute_option
-       (faked)
-     > product:0004_remove_productattribute_name
-       (faked)
-     > product:0005_fix_attributeoption_error_default_spelling
-       (faked)
-     > product:0006_custom_textfield_add_constraint
-       (faked)
-     > product:0007_add_discount_valid_products_field
-       (faked)
-     > product:0008_remove_discount_validproducts_field
-       (faked)
-     > product:0009_add_categoryattributes
-       (faked)
-     > product:0010_add_discountable_categories
-       (faked)
-     > downloadable:0001_split
-       (faked)
-     > custom:0001_split
-       (faked)
-     > configurable:0001_split
-       (faked)
-     > product:0011_split_products
-       (faked)
-     > downloadable:0002_update_contenttypes
-       (faked)
-     > custom:0002_update_contenttypes
-       (faked)
-     > configurable:0002_update_contenttypes
-       (faked)
-     > product:0012_update_contenttypes
-       (faked)
+      $ python manage.py syncdb --all
+      $ python manage.py migrate product --fake
 
   .. Note::
      Users familiar with the codebase may wonder why we didn't tell South to

docs/new_installation.txt

 you have write access to. In the below example, we use :file:`/home/user/src`. You are expected to modify the path to fit your needs.
 
 .. warning::
-   You must have Django 1.1.x properly installed.
+   You must have Django >= 1.2.3 properly installed.
 
 A Quick Note About Installing Dependencies
 ------------------------------------------
 
 #. Install sorl-thumbnail:
 
-   - Check out from source::
-
-       hg clone https://sorl-thumbnail.googlecode.com/hg/ sorl-thumbnail
-       cd /path/to/sorl-thumbnail
-       python setup.py install
+   - Using pip::
+   
+       pip install sorl-thumbnail==3.2.5
 
 #. Install signals-ahoy:
 
 PayPal
 ------
 
+Satchmo uses `Paypal's Instant Payment Notification <https://www.paypal.com/ipn>`_ service. The notes below describe how to configure
+it for your setup.
+
 Configuration
 ^^^^^^^^^^^^^
 
 
    Defaults to `^paypal/`.
 
+Step by Step Instructions for Configuring Paypal IPN
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The following steps describe how to configure Paypal IPN for production use.
+
+    1.  Make sure that 'payment.modules.paypal' is listed in your INSTALLED_APPS tuple, within your settings.py file.
+
+Then go into your /admin settings and ensure the configuration is correct for yuour site:
+    
+    2. In Site Settings -> Payment Settings, Check "Accept real payments".
+    3. In Site Settings -> Paypal Payment Settings, enter your Merchant Paypal account email 
+    4. In Site Settings -> Paypal Payment Settings verify that POST URL is: https://www.paypal.com/cgi-bin/webscr 
+    5. If you want paypal to adjust your stock levels, make sure your Track inventory levels is checked                       
+
+Now, configure your Paypal Merchant Account through the Paypal website:
+    
+    6. In History select IPN History 
+    7. Select the enable IPN option
+    8. Use the correct Notification URL. For example: http://www.mydomain.com/checkout/paypal/ipn/
+
+Double check your Satchmo sites domain name to make sure it matches the notification url above:
+    9. Go to /admin/sites/site/ and make sure your domain name is the same as the one you configured about in PayPal. In the example above, under Sites put in mydomain.com
+
+There is one note to remember about using paypal with utf-8 characters. By default Paypal will send an IPN call encoded as cp-1252 which 
+will break when the payment module calls PayPal again in utf-8 and there are special characters in the call. The solution is to login to 
+PayPal and change the website encoding of your account on PayPal to utf-8 in your profile settings (bottom right link on the profile page).
+
 .. index:: Google Checkout
 
 Google Checkout
 <http://code.google.com/apis/checkout/developer/Google_Checkout_XML_API.html#create_checkout_cart>`_
 in order to understand how the process works.
 
-.. index:: Protx
+.. index:: Protx, Sage Pay
 
-Protx
------
+Sage Pay (Formerly Protx)
+-------------------------
 This processor is included in the default Satchmo store.
+
+.. index:: Sermepa
+
+Sermepa
+-------
+This processor is included in the default Satchmo store. 
+
   
 3. If the user has multiple tiers, return the lowest amount found in 2a & 2b.
 
-.. _Django_Extensions: http://code.google.com/p/django-command-extensions/
+.. _Django_Extensions: https://github.com/django-extensions/django-extensions/
+    Extensive Wiki on: http://code.google.com/p/django-command-extensions/

docs/release-notes-0-9-2.txt

 - Update google analytics code to use latest tracker js
 - Add an unlimited downloads option for downloadable products
 - Added support for Django's new CSRF support
+- UPS Shipping module now allows you to box products together into 1 container
+- Add a new config for the persistent cart to provide more options for how it handles returning users
+- New template tag to show tiered shipping pricing table
+- Control product variations inclusion in searching view the settings
+- UPS module will display actual shipping times
+- New template tag product_featured_list
+- New config option to allow users to create their username instead of automatically generating
+- Satchmo check now does a more thorough job of checking your environment for issues
 
 Translations
 ------------
-
+- Added Dutch translation
+- Added Czech translation
+- Updated French translation
 
 Bug Fixes
 ---------
 - Make sure "all valid" discounts are correctly applied
 - Fix Wishlish ajax add view
 - Ensure that product variation properly inherits shipping from its parent
-- Made a couple of view and template changes to reduce the number of SQL queries per page
 - Handling of gift certificate plus other payments fixed
 - Bug in tax processor rendering fixed
 - Bug in autosuccess payment module fixed
 - Rebuild pricing was deleting prices if multiple sites were being used
-
+- Currency template tags handles decimal places parameter correctly
+- Improve robustness of South migrations
+- Fix obscure issue where some users were able to edit the wrong information
+- Remove custom read only widget use and use Django's newer read only field
+- Paypal was not saving contact information correctly in certain cases
+- Newsletter subscription status could be lost when checking out
+- Use smart_attr for tiered weight shipping module
+- Make sure that the product image file name doesn't exceed the length of the file field
+- Multiple doc formatting fixes
+- Authorize.net now uses shipee first and last names if given
+- Typo in wishlist ajax view
+- Make sure jquery correctly shows error messages on product pages
+- Fixed problem where category caching was not handling translations correctly
+- Ensure Ajax calls in checkout use SSL if it is turned on
+- Akismet for comment moderation is fixed
+- Improvements to South migrations
+- Update Paypal IPN docs
+- Fix issue where inactive or out of stock products could be purchased if there was a time lag between cart addition and checkout
+- Cart template tag now allows show_discount
+- Several fixes to transaction management
+- Improve postgres syncdb support
+- UPS time in transit prevents weekend pickups
+- Payments weren't showing up correctly in admin
+- Multiple updates to the tests to make them more robust
+- Fix issue with persistent cart not working correctly
+- Updates and fixes to sermepa payment module
+- Fixes to syncdb
+- Fedex module API changes
+- Several fixes to handle unicode characters better
+- Replace some admin jquery scripts with simpler django readonly fields
 
 Performance Improvements
 ------------------------
 - Tweaks to price queries to reduce unneeded queries
+- Made a couple of view and template changes to reduce the number of SQL queries per page
+- Added db index on Price Lookup table
 
+Additional Packages
+-------------------
+We have also made several updates to satchmo's dependencies including:
+  - `livesettings <https://bitbucket.org/bkroeze/django-livesettings>`_ 
+  - `keyedcache <https://bitbucket.org/bkroeze/django-keyedcache>`_ 
+  - `django-caching-app-plugins <https://bitbucket.org/bkroeze/django-caching-app-plugins/>`_
+  
+You should upgrade these to the latest version when you upgrade your satchmo site.
 
 Migration Notes
 ---------------
 
 If you have an existing Satchmo store and need to support CSRF, you will need to do a couple of things:
 
-    1. Upgrade to Django 1.2.1 or greater
+    1. Upgrade to Django 1.2.3 or greater
     2. Ensure 'django.middleware.csrf.CsrfViewMiddleware' is in your MIDDLEWARE_CLASSES
     3. Ensure that any forms in your custom templates, have {% csrf_token %} inside the <form> element
     
     2. Add 'django.contrib.messages.context_processors.messages' to your TEMPLATE_CONTEXT_PROCESSORS
     3. Add 'django.contrib.messages' to your INSTALLED_APPS setting
     
+Protx Payment Module Renamed
+++++++++++++++++++++++++++++
+As of `rev 2051 <http://bitbucket.org/chris1610/satchmo/changeset/04f821df32ec>`_, the Protx module has been renamed to Sage Pay. You will need to manually copy over your former Protx credentials to
+the new Sage Pay module. No further changes should be necessary.
+
+ProductPriceLookup Index
+++++++++++++++++++++++++
+As of `rev 2120 <https://bitbucket.org/chris1610/satchmo/changeset/dd9fccf8a2aa>`_, the price lookup model has an index on the productslug to improve performance on large data sets.
+
+A south migration is included. To apply:
+    
+    python manage.py migrate product
+    
+Support for Django 1.3
+++++++++++++++++++++++
+As mentioned above, when using Django 1.3, it is important to upgrade `django-caching-app-plugins <https://bitbucket.org/bkroeze/django-caching-app-plugins/>`_ (app_plugins) to version 0.1.2.
+
+Active Products
++++++++++++++++
+Previously, category.active_products() would not consistently return the correct product variations. In `rev 2168 <https://bitbucket.org/chris1610/satchmo/changeset/318f7eb41140>`_
+this was fixed but had the unintended side effect of returning all the product variations in the default templates. In order to maintain
+consistency, the default variation display value is now False. The only people that will notice the issue is those that customized
+the variation display in the category page.

docs/requirements.txt

 Django instance to use Satchmo.  The `Django installation guide`_ will step you
 through the process.
 
-You must use Django 1.2.1 or greater in order to use the latest CSRF features.
+You must use Django 1.2.3 or greater in order to use the latest CSRF features.
 
 Satchmo requires Python 2.4 or later and a database supported by Django.
 
 - Satchmo's thumbnail capability is very robust and utilizes the following packages:
 
   - `Python Imaging Library`_
-  - `Sorl Thumbnails`_
+  - Sorl Thumbnails
+  
+  .. warning::
+    You must use Sorl Thumbnails version 3.2.5 with Satchmo.
 
 - In order to securely store sensitive information, you will need:
 
 
   - `Sphinx`_
 
+- If you wish to enable Akismet for spam prevention on product ratings, you will need to install:
+
+  - `Akismet`_
+
 - Satchmo uses South for migrating database schema changes. It is not required
   to run the store but is very useful for migrating versions.
 
 .. _snapshot: http://www.satchmoproject.com/snapshots/
 .. _`Django Threaded Multihost`: http://bitbucket.org/bkroeze/django-threaded-multihost
 .. _`Django App Plugins`: http://bitbucket.org/bkroeze/django-caching-app-plugins/
-.. _`Sorl Thumbnails`: http://code.google.com/p/sorl-thumbnail/
 .. _`SSL Backport`: http://pypi.python.org/pypi/ssl/
 .. _`Signals Ahoy`: http://bitbucket.org/bkroeze/django-signals-ahoy/
 .. _DocUtils: http://docutils.sourceforge.net/
 .. _Django Livesettings: http://bitbucket.org/bkroeze/django-livesettings
 .. _Django Keyedcache: http://bitbucket.org/bkroeze/django-keyedcache
+.. _Akismet: http://www.voidspace.org.uk/python/akismet_python.html

docs/settings.txt

 
 2. Copy the :file:`local_settings` file to mystore::
 
-        cp /home/user/src/satchmo-trunk/satchmo/projects/base/local_settings.py /home/user/src/mystore/local_settings.py
+        cp /home/user/src/satchmo-trunk/satchmo/projects/base/local_settings.py \
+            /home/user/src/mystore/local_settings.py
 
 3. You will need to verify the values assigned to the following items in :file:`local_settings.py`::
 
     especially important for MySQL. If you are using MySQL, you may want to use the
     following statement in your settings file to enforce utf-8 collation::
 
-        DATABASE_OPTIONS = {
+        DATABASES['default']['OPTIONS'] = {
            'init_command' : 'SET NAMES "utf8"',
            }
 
 
     form_init.connect(form_terms_listener, sender=SimplePayShipForm)
 
-The final step is to create your actual :file:`/templates/shop-terms.html`,
+The final step is to create your actual :file:`store-name/templates/localsite/shop-terms.html`,
 like this::
 
     {% extends "base.html" %}

docs/template-filters-tags.txt

 		{% load satchmo_discounts %}
 		{{ product|sale_price }}
 		
-This filter goes through all applicable `auto discounts`_, finds and then sorts them by percentage. The return value would represent the greatest discount available for a product.
+This filter finds all applicable :ref:`auto-discounts`, then sorts them by percentage. The return value would represent the greatest discount available for a product.
 
 Tag Reference
 -------------

docs/translation.txt

 1. Change to the directory where your Satchmo source is stored (somewhere on your PYTHONPATH). You can run the following
 find command to compile all of the langauge files for the satchmo apps::
 
-    find . -name locale -exec sh -c 'cd $0 && cd ../ && /path/to/django-trunk/django/bin/django-admin.py makemessages -l de -e html,txt,rml' {} \;
+    find . -name locale -exec sh -c 'cd $0 && cd ../ &&
+            /path/to/django-trunk/django/bin/django-admin.py makemessages -l de -e html,txt,rml' {} \;
 
 In the example above, replace "de" with the language code for the message file you want to create.
 The language code, in this case, is in locale format. For example, it’s pt_BR for Brazilian
 
 4. Compile the file using the compilemessages command (run from your satchmo source directory)::
 
-    find . -name locale -exec sh -c 'cd $0 && cd ../ && /path/to/django-admin.py compilemessages' {} \;
+    find . -name locale -exec sh -c 'cd $0 && cd ../ &&
+                                     /path/to/django-admin.py compilemessages' {} \;
 
 5. (Optional but encouraged) Submit a ticket with your translation.
 
 Here is a quick step by step overview for adding and using the upsell application.
 
 	- In your site's ``settings.py`` file, edit the ``INSTALLED_APP`` list to include ``satchmo_ext.upsell``. Run a syncdb on your site to ensure that the necessary database tables are created.
-	- Log into the your site's admin interface, and add a new product. You will want to add the target product (remember that an upselling item can be a standalone product, as well as a variation of an existing product) and an upsell product. You can read the Products_ page for details on how to do this.
+	- Log into the your site's admin interface, and add a new product. You will want to add the target product (remember that an upselling item can be a standalone product, as well as a variation of an existing product) and an upsell product. You can read the :doc:`Satchmo products <product>` page for details on how to do this.
 	- From your site's admin main page, navigate to the Upsells section to add/change an upsell.
 
 Useful links
 ----------------
 
-	- `Upsell template tag`_.
-	- Satchmo Products_ application.
+    - :doc:`Upsell template tag <template-filters-tags>`
+    - :doc:`Satchmo products <product>`
+
 
 References
 ---------------
 .. [#] Wikipedia article on Up-selling_
 
 .. _Up-selling: http://en.wikipedia.org/wiki/Up-selling
-.. _Products: product.html
-.. _`Upsell template tag`: templates.html
+
 
 .. class:: payment.forms.PaymentContactInfoForm
 
-   Subclasses :class:`payment.forms.PaymentMethodForm` and
-   :class:`satchmo_store.contact.forms.ContactInfoForm`.
+   Subclasses :class:`payment.forms.PaymentMethodForm`
+
+   and :class:`satchmo_store.contact.forms.ContactInfoForm`.
 
 .. class:: payment.forms.PaymentMethodForm
 

satchmo/apps/l10n/locale/cs/LC_MESSAGES/django.mo

Binary file added.

satchmo/apps/l10n/locale/cs/LC_MESSAGES/django.po

+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# , 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-08-14 09:52+0200\n"
+"PO-Revision-Date: 2010-08-14 10:01+0200\n"
+"Last-Translator: \n"
+"Language-Team: American English <kde-i18n-doc@kde.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: admin.py:15 admin.py:24
+msgid "1 country was"
+msgstr "Jedna Země byla"
+
+#: admin.py:17 admin.py:26
+#, python-format
+msgid "%s countries were"
+msgstr "%s zemí bylo"
+
+#: admin.py:18
+#, python-format
+msgid "%s successfully marked as active"
+msgstr "%s úspěšně označena jako aktivní"
+
+#: admin.py:19
+msgid "Mark selected countries as active"
+msgstr "Označ vybrané země jako aktivní"
+
+#: admin.py:27
+#, python-format
+msgid "%s successfully marked as inactive"
+msgstr "%s úspěšně označeny jako neaktivní"
+
+#: admin.py:28
+msgid "Mark selected countries as inactive"
+msgstr "Označ vybrané země jako neaktivní"
+
+#: models.py:6
+msgid "Africa"
+msgstr "Afrika"
+
+#: models.py:7
+msgid "North America"
+msgstr "Severní Amerika"
+
+#: models.py:8
+msgid "Europe"
+msgstr "Evropa"
+
+#: models.py:9
+msgid "Asia"
+msgstr "Asie"
+
+#: models.py:10
+msgid "Oceania"
+msgstr "Oceánie"
+
+#: models.py:11
+msgid "South America"
+msgstr "Jižní Amerika"
+
+#: models.py:12
+msgid "Antarctica"
+msgstr "Antarktida"
+
+#: models.py:16
+msgid "Another"
+msgstr "Jiné"
+
+#: models.py:17
+msgid "Island"
+msgstr "Ostrov"
+
+#: models.py:18
+msgid "Arrondissement"
+msgstr ""
+
+#: models.py:19
+msgid "Atoll"
+msgstr ""
+
+#: models.py:20
+msgid "Autonomous island"
+msgstr ""
+
+#: models.py:21
+msgid "Canton"
+msgstr "Kanton"
+
+#: models.py:22
+msgid "Commune"
+msgstr ""
+
+#: models.py:23
+msgid "County"
+msgstr ""
+
+#: models.py:24
+msgid "Department"
+msgstr ""
+
+#: models.py:25
+msgid "Dependency"
+msgstr ""
+
+#: models.py:26
+msgid "District"
+msgstr ""
+
+#: models.py:27
+msgid "Division"
+msgstr ""
+
+#: models.py:28
+msgid "Emirate"
+msgstr "Emirát"
+
+#: models.py:29
+msgid "Governorate"
+msgstr ""
+
+#: models.py:30
+msgid "Island council"
+msgstr ""
+
+#: models.py:31
+msgid "Island group"
+msgstr "Souostroví"
+
+#: models.py:32
+msgid "Island region"
+msgstr ""
+
+#: models.py:33
+msgid "Kingdom"
+msgstr "Království"
+
+#: models.py:34
+msgid "Municipality"
+msgstr ""
+
+#: models.py:35
+msgid "Parish"
+msgstr ""
+
+#: models.py:36
+msgid "Prefecture"
+msgstr ""
+
+#: models.py:37
+msgid "Province"
+msgstr "Provincie"
+
+#: models.py:38
+msgid "Region"
+msgstr "Region"
+
+#: models.py:39
+msgid "Republic"
+msgstr "Republika"
+
+#: models.py:40
+msgid "Sheading"
+msgstr ""
+
+#: models.py:41
+msgid "State"
+msgstr "Stát"
+
+#: models.py:42
+msgid "Subdivision"
+msgstr ""
+
+#: models.py:43
+msgid "Subject"
+msgstr ""
+
+#: models.py:44
+msgid "Territory"
+msgstr "Teritorium"
+
+#: models.py:53
+msgid "ISO alpha-2"
+msgstr ""
+
+#: models.py:54
+msgid "Official name (CAPS)"
+msgstr "Oficiální jméno (VELKÁ PÍSMENA)"
+
+#: models.py:55
+msgid "Country name"
+msgstr "Jméno země"
+
+#: models.py:56
+msgid "ISO alpha-3"
+msgstr ""
+
+#: models.py:57
+msgid "ISO numeric"
+msgstr ""
+
+#: models.py:58
+msgid "Country is active"
+msgstr "Země je aktivní"
+
+#: models.py:59
+msgid "Continent"
+msgstr "Kontinent"
+
+#: models.py:60 models.py:81
+msgid "Administrative Area"
+msgstr "Administrativní oblast"
+
+#: models.py:63
+msgid "Country"
+msgstr "Země"
+
+#: models.py:64
+msgid "Countries"
+msgstr "Země"
+
+#: models.py:76
+msgid "Admin Area name"
+msgstr "Jméno administrativní oblasti"
+
+#: models.py:77
+msgid "Postal Abbreviation"
+msgstr "Poštovní zkratka"
+
+#: models.py:78
+msgid "Area is active"
+msgstr "Oblast je aktivní"
+
+#: models.py:82
+msgid "Administrative Areas"
+msgstr " Administrativní oblasti"
+
+#: templates/l10n/_language_selection_form.html:5
+msgid "Change language"
+msgstr "Změnit jazyk"
+
+#: templates/l10n/_language_selection_form.html:11
+msgid "Change"
+msgstr "Změnit"
+
+#: validators/aupostcode.py:13
+msgid "Invalid Australian postal code"
+msgstr ""
+
+#: validators/capostcode.py:18
+msgid "Invalid postal code for Canada"
+msgstr ""
+
+#: validators/uspostcode.py:10
+msgid "Invalid ZIP code"
+msgstr "Neplatné PSČ"
+

satchmo/apps/l10n/locale/fr/LC_MESSAGES/django.mo

Binary file modified.

satchmo/apps/l10n/locale/fr/LC_MESSAGES/django.po

 "X-Poedit-SourceCharset: utf-8\n"
 
 #: admin.py:15 admin.py:24
-#, fuzzy
 msgid "1 country was"
-msgstr "Nom du pays"
+msgstr "Un pays a été"
 
 #: admin.py:17 admin.py:26
-#, fuzzy, python-format
+#, python-format
 msgid "%s countries were"
-msgstr "Pays"
+msgstr "%s pays ont été"
 
 #: admin.py:18
 #, python-format
 msgid "%s successfully marked as active"
-msgstr ""
+msgstr "%s correctement marqué comme actif(s)"
 
 #: admin.py:19
 msgid "Mark selected countries as active"
-msgstr ""
+msgstr "Marquer les pays sélectionnés comme actifs"
 
 #: admin.py:27
 #, python-format
 msgid "%s successfully marked as inactive"
-msgstr ""
+msgstr "%s correctement marqué comme inactif(s)"
 
 #: admin.py:28
 msgid "Mark selected countries as inactive"
-msgstr ""
+msgstr "Marquer les pays sélectionnés comme inactifs"
 
 #: models.py:6
 msgid "Africa"
 
 #: models.py:29
 msgid "Governorate"
-msgstr "Gouvernemental"
+msgstr "Governorat"
 
 #: models.py:30
 msgid "Island council"
 
 #: models.py:41
 msgid "State"
-msgstr "Département/Province"
+msgstr "État/Département/Région"
 
 #: models.py:42
 msgid "Subdivision"
 
 #: models.py:57
 msgid "ISO numeric"
-msgstr "ISO numeric"
+msgstr "Code ISO numérique"
 
 #: models.py:58
 msgid "Country is active"
-msgstr "pays actif"
+msgstr "Pays actif"
 
 #: models.py:59
 msgid "Continent"
 
 #: templates/l10n/_language_selection_form.html:5
 msgid "Change language"
-msgstr ""
+msgstr "Changer de langue"
 
 #: templates/l10n/_language_selection_form.html:11
 msgid "Change"
-msgstr ""
+msgstr "Modifier"
 
 #: validators/aupostcode.py:13
 msgid "Invalid Australian postal code"
-msgstr ""
+msgstr "Code postal australien invalide"
 
 #: validators/capostcode.py:18
 msgid "Invalid postal code for Canada"
-msgstr ""
+msgstr "Code postal canadien invalide"
 
 #: validators/uspostcode.py:10
 msgid "Invalid ZIP code"
-msgstr ""
+msgstr "Code postal invalide"

satchmo/apps/l10n/utils.py

 import logging
 import re
 
+# Create a regex to strip out the decimal places with currency formatting
+# Example string = u"$%(val)0.2f" so this regex should let us get the 0.2f portion
+decimal_fmt = re.compile(r'(\.\d+f)')
+
 log = logging.getLogger('l10n.utils')
 
 # Defined outside the function, so won't be recompiled each time
 
 
 
-def moneyfmt(val, currency_code=None, wrapcents=''):
+def moneyfmt(val, currency_code=None, wrapcents='', places=None):
     """Formats val according to the currency settings for the desired currency, as set in L10N_SETTINGS"""
     if val is None or val == '':
        val = Decimal('0')
         if currency_code == default_currency_code:
             raise ImproperlyConfigured("Default currency code '%s' not found in currency_formats in L10N_SETTINGS", currency_code)
 
-        return moneyfmt(val, currency_code=default_currency_code, wrapcents=wrapcents)
+        return moneyfmt(val, currency_code=default_currency_code, wrapcents=wrapcents, places=places)
 
     # here we are assured we have a currency format
 
     else:
         val = abs(val)
         key = 'negative'
-
-    fmt = currency[key]
+    
+    # If we've been passed places, modify the format to use the new value
+    if places is None or places == '':
+        fmt = currency[key]
+    else:
+        start_fmt = currency[key]
+        fmt_parts = re.split(decimal_fmt, start_fmt)
+        new_decimal = u".%sf" % places
+        # We need to keep track of all 3 parts because we might want to use
+        # () to denote a negative value and don't want to lose the trailing )
+        fmt = u''.join([fmt_parts[0], new_decimal, fmt_parts[2]])
     formatted = fmt % { 'val' : val }
 
     sep = currency.get('decimal', '.')
         pos = formatted.rfind(sep)
         if pos>-1:
             pos +=1
-            formatted = u"%s<%s>%s</%s>" % formatted[:pos], wrapcents, formatted[pos:], wrapcents
+            formatted = u"%s<%s>%s</%s>" % (formatted[:pos], wrapcents, formatted[pos:], wrapcents)
 
     return formatted

satchmo/apps/payment/config.py

     for module, group in active_gateways():
         defaultlabel = module.split('.')[-1]
         label = _(config_value(group, 'LABEL', default = defaultlabel))
-        choices.append((group, label))
-
+        key = config_value(group,'KEY')
+        choices.append((key, label))
+        
     signals.payment_choices.send(None, choices=choices)
     return choices
 

satchmo/apps/payment/fields.py

-from django.db import models
-from payment.config import credit_choices, labelled_gateway_choices
-
-class CreditChoiceCharField(models.CharField):
-
-    def __init__(self, choices="__DYNAMIC__", *args, **kwargs):
-        if choices == "__DYNAMIC__":
-            kwargs['choices'] = credit_choices()
-
-        super(CreditChoiceCharField, self).__init__(*args, **kwargs)
-
-class PaymentChoiceCharField(models.CharField):
-    
-    def __init__(self, choices="__DYNAMIC__", *args, **kwargs):
-        if choices == "__DYNAMIC__":
-            kwargs['choices'] = labelled_gateway_choices()
-                    
-        super(PaymentChoiceCharField, self).__init__(*args, **kwargs)

satchmo/apps/payment/forms.py

         form_initialdata.send('CustomChargeForm', form=self, initial=initial)
         kwargs['initial'] = initial
         super(CustomChargeForm, self).__init__(*args, **kwargs)
-        form_init.send(self.__class__, form=self)
+        form_init.send(CustomChargeForm, form=self)
 
     def clean(self, *args, **kwargs):
         super(CustomChargeForm, self).clean(*args, **kwargs)
-        form_validate.send(self.__class__, form=self)
+        form_validate.send(CustomChargeForm, form=self)
         return self.cleaned_data
 
 class PaymentMethodForm(ProxyContactForm):
                         shipping_dict = {cheapshipping: shipping_dict[cheapshipping]}
             except Discount.DoesNotExist:
                 pass
-
-        # possibly hide the shipping
+        
+        # possibly hide the shipping based on store config
         shiphide = config_value('SHIPPING','HIDING')
-
-        if shiphide in ('YES', 'DESCRIPTION') and len(shipping_choices) == 1:
+        # Handle a partial payment and make sure we don't show a shipping choice after one has
+        # already been chosen
+        if self.order.is_partially_paid and shipping_dict.get(self.order.shipping_model, False):
+            self.fields['shipping'] = forms.CharField(max_length=30, initial=self.order.shipping_model,
+                widget=forms.HiddenInput(attrs={'value' : shipping_choices[0][0]}))
+            self.shipping_hidden = True
+        # Possibly hide if there is only 1 choise
+        elif shiphide in ('YES', 'DESCRIPTION') and len(shipping_choices) == 1: