This document describes the minimum contract the shop models are supposed to fulfill.

The simple example at examples/simple/ is supposed to demonstrate the most simple use of Plata.

Product model

The (base) product model has to be specified as PLATA_SHOP_PRODUCT using Django’s app_label.model_name notation. The model referenced will be the model pointed to by the OrderItem order line items.

Since it’s your responsibility to write all views and URLs for your product catalogue, there aren’t many things Plata’s products have to fulfill.

Plata provides an abstract model at plata.product.models.ProductBase. You do not have to use it - it just provides the standard interface to the price determination routines already.

  • get_price(currency=None, orderitem=None):

    The get_price method has to accept at least the current currency and optionally more arguments too, such as the current line item for the implementation of price tiers.

    This method must return a Price instance. It has to raise a Price.DoesNotExist exception if no price could be found for the passed arguments.

  • handle_order_item(self, orderitem):

    This method is called when modifying order items. This method is responsible for filling in the name and sku (Stock Keeping Unit) field on the order item.

Different product models

If you need different product models, consider using Django’s model inheritance and something like django-polymorphic.

Price model

Plata has a bundled abstract price model which does almost everything required. You have to provide the concrete price model yourself though.

The only thing it lacks for a basic price is a foreign key to product. ProductBase.get_price assumes that the foreign key is defined with related_name='prices'.

When modifying a cart or an order, Plata will call the price object’s handle_order_item method, passing the order item instance as the only argument. This method is responsible for filling the following attributes on the order item:

  • _unit_price: Unit price excl. tax.
  • _unit_tax: The tax on a single unit.
  • tax_rate: The applied tax rate as a percentage. This is slightly redundant as it could be calculated from _unit_price and _unit_tax.
  • tax_class: (Optional) a foreign key to This is purely informative. This field is not mandatory.
  • is_sale: Boolean flag denoting whether the price is a sale price or not. This flag is unconditionally set to False by the price base class.

The price model offers the following attributes:

  • unit_price_excl_tax

    A decimal.Decimal describing the unit price with tax excluded. unit_price_incl_tax and unit_price are offered by the default implementation too, but they aren’t mandatory.

  • unit_tax

    A decimal.Decimal too. This is the tax amount per unit, not the tax rate.

  • tax_class.rate

    The tax rate as a percentage, meaning 19.6 for a tax rate of 19.6%.

  • tax_class

    A object for the given price.

Contact model

The example at examples/custom shows how the contact model might be replaced with a different model. The following fields and methods are mandatory:

  • Contact.user: ForeignKey or OneToOneField to auth.User.
  • Contact.update_from_order(self, order, request=None): Updates the contact instance with data from the passed order (and from the optional request).
  • Contact.ADDRESS_FIELDS: A list of fields which are available as billing and/or shipping address fields.

The last point isn’t strictly necessary and can be circumvented by overriding offers all that, and more.