Orders, Line Items, and the Cart
What follows is a rough summary of our conception of orders on Drupal 7. This brainstorming began in October at the first San Francisco sprint, and we spent a lot of time on Monday in Paris hashing out the details. There's still plenty more to consider, so feel free to speak up!
Like Products, Orders in Drupal Commerce are top-level fieldable entities. Unlike Products, we are initially supporting only a single Order Type, but this in no way limits the ability of contributed modules to alter in support for multiple Order Types.
The data inherent to the order object includes:
- A serial numeric order ID as the primary key used internally (order_id).
- An additional merchant-defined order ID (alphanumeric, pattern based - order_number), like product_id vs. sku.
- Meta data including a creator_uid and customer_uid, created and changed timestamps, and a revision ID (revision_id instead of the confusing vid used by nodes).
We'll retain the concept of order states as used in Ubercart but possibly turn the order status into a field. This needs to be teased out further, but the basic idea is that order states are major workflow steps in the life of an order (i.e. cart / checkout -> post-checkout / paid -> fulfillment -> complete). Each of these major steps can have many components that are going to be custom to the store's particular workflow, but modules need to be able to depend on the presence of some major order categories. To that end, order states would continue to be defined via a hook_commerce_order_state().
Customer information will be added to the order via default fields. I'm undecided on the primary e-mail address, (which really only applies to anonymous orders), as there is no default e-mail Field and I'm not sure we want that as a dependency at this point. However, we'll be depending on the Postal Address developed according to the xNAL Name and Address standard to attach billing / shipping addresses to orders. By default, the order module will attach a Billing Address field, while a separate Shippable Products module will add the appropriate shipping related fields to products and orders (defaulting to a single shipping address). This separate module should also handle hiding shipping related fields in checkout / on order viewing / editing.
Line items will be the heart of orders. We believe the best approach to be a new Line Item entity with multiple Line Item Types. Line items are anything on an order affecting the order total (e.g. products, taxes, shipping, discounts, fees, etc.). Line items will have a serial numeric line item ID (line_id), a reference to the appropriate order (order_id), a type, a merchant-defined ID (i.e. the product SKU, a tax rate name, a coupon code, etc.), a display title (fully editable on the order), a quantity, and a price field. When a line item is added to the order, we'll also save the total price of the line item (qty. * unit price) in a second price field to avoid rounding snafus. Line item types should also be able to specify display attributes, enabling for example the tax line item to not display a qty. field or a unit price. We're working with Bojhan on a way to make this system usable and will certainly need more detail as we implement specific line item types.
Orders will still have comments, but our goal is to move a majority of the administrative / logging comments either to a Payments tab or to the revisions tab as log messages. We'll further make use of versioning to store the changes to various order fields in revisions, and we hope to visualize those changes in a manner similar to the Project Issue module's handling of changes to issue fields in issue comments. Customer facing order comments will be preserved as is but simplified a bit in their presentation.
Shopping Cart Orders
Shopping Carts in Drupal Commerce will be saved and represented as orders. When a customer adds an item to his shopping cart, the action will create a new shopping cart order for the customer with the product in it. On subsequent pageloads, this order object will be available for us. However, as long as the order is still in the shopping cart state, its line items will be re-validated on load against the latest product prices / availability, etc. To that end, line items will need to specify at what point they're saved. For example, a discount line item doesn't need to be saved before an order is checked out, because discounts will be recalculated every time the order is loaded. Persisting such data across pageloads isn't really useful.
If an item is removed, delete the item from the order. If all items are deleted from the order, delete the order and provide a hook for modules to preserve any bit of data entered for reuse.
Orders can be identified as being in the shopping cart by both the order state and the fact that it will not have a merchant-defined order ID. As long as an order has not been checked out, it will not be revisioned. This could result in the loss of significant marketing data, so we want to evaluate and implement a way to capture customer interactions with the store in some sort of custom watchdog.
The shopping cart will be totally optional, meaning checkout will be implemented in a separate module. For now, we aren't even specifying the development of a shopping cart block and are targeting a simple shopping cart form based on Shopify. Ideally the block and/or the form could be Views based in the near future.