I don't like being sandy but I love building sand castles. The potential is high but the stakes are low. You have unlimited raw material to build whatever you can imagine, and if you screw up you can just knock it over (to the delight of your children) and start again.
When your constant is impermanence, you adjust your expectations accordingly. If the sands shift or the tide rises, you shrug it off and start again or go back to bocce. However, if you were somehow bound by the fruit of your labor, you'd think twice about the when, where, and how of your building.
Lyle and I started developing Ubercart when Drupal 5 was still in beta, and we put up with the impermanence because we were just two dudes learning a lot and working from a clean slate.
Moving that forward to Drupal 6 took even longer because our codebase grew unwieldy, so I decided at Commerce Guys to trim the fat and start over. We didn't learn every lesson moving to Drupal 7, though, as it was still unstable when we began developing Drupal Commerce. With an unstable Views module. And an unstable Rules module. And an incomplete Entity API.
I don't think we would've done any differently, as the flip side of the instability is the opportunity to positively impact the development of the projects you depend on. For Drupal 8 we ended up contributing to core in other ways while tackling a full Drupal Commerce rewrite more slowly than we hoped. Even the code that we did develop against Drupal 8 is now outdated, as we had to juggle managing our existing ecosystem, writing new code, and rewriting that code to track changes in Drupal 8 itself.
However, we've recently been given the opportunity to host a variety of developers / documenters in Paris from June 30 - July 4 to re-evaluate ourCommerce 2.x roadmap with the direct help and guidance of key members of the Symfony project. Specifically, we'll be looking to both move our code "upstream" from our Drupal modules into generalized libraries and take advantage of existing Symfony projects where possible.
Our target is an even leaner codebase with connections to the broader world of PHP based eCommerce. If you have any insights in this direction, please comment or contact me directly and consider joining us in Paris to learn and contribute.
Development of Drupal Commerce 2.x began in Drupal core through contributions to core initiatives and new core modules. As a result, the next version of Drupal Commerce will feature a shrunken codebase thanks to updates to Drupal's core Entity API and the Entity Reference module, which alone deprecates a significant portion of the Product Reference, Line Item, and Customer modules.
The roadmap lists out the changes we'll be making to the architecture of the core Commerce modules in response to the changes already present in Drupal 8. It also features a variety of topically organized tasks we've lined up to mitigate the configuration and development challenges our users have faced using Drupal Commerce 1.x.
Our original goal was to have a beta release by the time Drupal 8 hit a full release. However, in an attempt to avoid repeating the turbulent experience of developing Drupal Commerce 1.x on an unstable Drupal 7 / Entity API / Views, we postponed active development of Commerce 2.x until Drupal core settled down.
Development of Commerce 2.x will truly begin in earnest once Drupal 8 has an alpha or beta release. In the meantime, our focus is on ensuring Drupal 8 itself is a success and on testing implementations of proposed features on the new Drupal 8 APIs as they develop.
If Drupal 8 truly has a full release around DrupalCon Prague, there's little chance Drupal Commerce 2.x will be beta ready. We'll be sure to update the forecast as the date draws nearer.
While many of the items in the roadmap task list are grouped according to the subsystem affected, others are more abstract in scope and represent an attempt to apply a general principle or development emphasis more broadly to the codebase. The emphases listed here are described below, providing you with the context necessary to understand the reasoning behind these broader changes:
- Improve Drupal Commerce as a conduit vs. a container
- Serve the majority use case
- Use explicit configuration instead of implicit behavior
- Build and use robust internal APIs
Our task list certainly does not catch every area in Commerce where a principle should be applied. Contributors should feel free to propose changes not on the list that reflect one or more of these emphases, and we will discuss as a community which of these changes should become a part of the roadmap. All such discussion should take place in the issue queue as tasks or feature requests.
Improve Drupal Commerce as a conduit vs. a container
To move Drupal Commerce forward on Drupal 8, we need to look backward and recover one of our core founding principles: an eCommerce site is a data conduit, not a container. It should be easy to move data between a Drupal Commerce site and the various web services the site uses to power eCommerce at a much broader scale than is possible through the website alone.
- Drupal Commerce 1.0 was the initial implementation of eCommerce native to Drupal 7, architecting around the Entity API, Field API, Views, and Rules to build a truly flexible eCommerce framework.
- Commerce Kickstart 2.0 focused on the simplification of the launch and administration of a feature rich store built with Drupal Commerce.
- Drupal Commerce 2.0 brings a renewed focus on integration with third party web services that make eCommerce possible and profitable.
This effort revolves around a refactoring on Drupal 8 that takes advantage of core REST functionality along with the hypermedia principles being pursued in Commerce Services on behalf of Commerce Guys' mobile app and client requirements.
Serve the majority use case
There are a few clear instances where we added premature "power features" or pursued a local solution to a task better managed by a third party service. This should be addressed in Drupal Commerce 2.0 to better serve the majority use case:
- Shopping cart refresh - we refresh the cart on every single load of the order to ensure up to date pricing, but this load is unnecessary on most sites. We should instead provide configuration options to govern the refresh of an order, perhaps depending on an "on load" Rules event instead.
- Product pricing rules - we force all price calculations to go through Rules in order to facilitate a largely unused feature, sell price pre-calculation. If pre-calculation is disabled, there's no harm in allowing modules to directly hook into the product pricing system, but we should provide a more robust API that doesn't depend on Rules actions to get the price components right.
- Shopping cart revisions - by default we create new revisions of shopping cart orders on every cart operation to track shopping history and cart abandonment, but these analytics are better monitored through a third party service like our entry level freemium partner service Jirafe.
- Checkout form validation / submission - similarly, we validate and submit every checkout pane on a checkout page to capture as much data as possible in spite of errors on the page. This makes dependencies between checkout panes impossible without custom logic in the checkout pane code itself. We could switch this to be a checkout page setting.
Note that this emphasis does not mean we'll remove any feature that is inconvenient to the average user. For example, many people are surprised by customer profile duplication, but this is an essential feature of Commerce for preserving the integrity of historical order data.
Use explicit configuration instead of implicit behavior
We did a fair job of stamping out "magic" configurations in Commerce 1.x - cases where a setting or combination of settings results in a secondary feature that isn't explicitly mentioned. For example, Commerce 1.x originally depended on a combination of settings for fields to be considered product attribute fields, but we eventually removed this implicit behavior with an explicit settings form built into the field edit form.
Build and use robust internal APIs
Commerce 1.x served as proof of concept for many of the Drupal 7 core and contributed APIs, most notably the Entity / Fields APIs. However, we did not do a great job developing and using APIs within our own modules to facilitate development tasks like creating orders, manipulating prices, and processing payments. This emphasis ties back into the first, as we should develop our systems with REST application in mind.
In Commerce 2.x, we should ensure that our modules define robust internal APIs that are then used by forms, Rules actions, etc. as opposed to embedding functionality into these systems' related callbacks. Most notably, we should seek to make price manipulation and price component management much easier as we open up the sell price calculation process to direct manipulation in module code (as opposed to strictly using Rules) when sell price pre-calculation is disabled.
Roadmap Task List
Each of these tasks will ultimately link to an issue on drupal.org where the change will be discussed and patched. Stricken tasks indicate completion of the core task, though there may be related issues still present in the issue queue.
Add the Entity Reference module to core
Check to see where support stands for reference via UUID and revision referencing.
Add support for Entity Reference behavior plugins
Use behavior plugins to cascade CRUD operations to referenced entities, prevent deletion of referenced entities, and inject fields from referenced entities into the display of the referencing entity. This may also accommodate our product hierarchy model's field value inheritance.
- Add automatic Entity API integration into Views
- Finish the core conditions patch
- Convert core actions to the plugin system
- Propose events in core (to complete Rules support)
Finish full entity storage
This grants us a per-entity type storage backend and unified access control.
Propose entity subtype plugins
To enable subtype specific callbacks (i.e. line item field population), default field creation and integrity checks, etc. At a minimum, extend our core entity controller to support default field management.
Add support for extra field display settings
This is to support the Add to Cart form field on products, but we might consider just making it a field with default form settings defined in the field but overrideable at the product level.
- Ensure the core profile entity supports mulitple profiles per bundle
- Replace the Product Reference field with Entity Reference
- Replace the Line Item Reference field with Entity Reference
- Replace the Customer Profile Reference field with Entity Reference
- Update all of our Views handlers for D8 Views
Update and re-export all of our default Views
If exported default Views are stored in CMI configuration files, then we need to research default View alteration to facilitate the Cart module's alteration of the Order admin View.
- Convert the cart block / form to use Views entirely
- Convert our configurable data structures to use CMI
- Convert Commerce conditions to the new condition plugin format
- Convert Commerce actions to the action plugin format
- Convert all of our theme functions and template files to Twig
Convert checkout panes to the plugin system
Plugin type = checkout pane, Plugins = checkout panes
Convert payment methods to the plugin system
Plugin type = payment method, Plugins = payment methods offered by the gateway, Derivatives = payment method instances
Convert taxes to the plugin system
Plugin type = tax, Plugins = tax rates (no more tax types)
Remove the concept of tax types
Rounding and display inclusiveness become tax rate settings; rounding settings also include the rounding precision.
Extend #ajax to use hidden buttons that are clicked to trigger updates (to facilitate Cart / Checkout form degradability)
Use a "button_value" property on #ajax arrays using the onchange event and automatically add the hidden button / click it to trigger the refresh instead of depending on the onchange directly.
- Deprecate Drupal Commerce's hidden product reference field widget.
- Add a dependency on Inline Entity Form for all three reference fields
- Add an API to IEF to let modules use it outside of a reference field
- Add a dependency on Message for translatable e-mail templates
- Update entity controllers to the D8 Entity API
- Replace use of entity_metadata_wrapper() with the D8 property API
- Add a new Store entity type
- Add abstract support for entity deletion prevention
- Propose treating all entities as "append only" with read only past revisions
- Propose entity revision tagging
- Anything defining a title should define a title callback instead
Implement the new product data model
This involves product hierarchies, field inheritance, product entities as displays, and the custom inline edit form for child products.
- Support unpurchasable products (i.e. parts of a kit)
- Add default flat and multi-level product hierarchies
- Add some Commerce Fancy Attributes support to core
- Enable configurable shopping cart refresh conditions
- Allow shopping cart refresh on order save, not just load
- Make the Add to Cart form JS degradable
Add Commerce Customizable Products to core
But ensure we can map line item types to product types and individual products, and allow field / option availability to be filtered at either level as well.
- Refresh the Add to Cart form when line item fields are updated
Spec out the implementation of complex checkout flows
We need to support dynamic single page via AJAX, multivariate testing of alternate checkout flows, conditional pages and panes, independent vs. dependent checkout panes.
- Enable configurable translatable checkout page titles and button values
- Add a checkout progress wizard block to core
- Make the checkout form JS degradable
- Add Address Book to core
- Add a "buy it now" display formatter that creates an order and proceeds to checkout without requiring Cart
- Evaluate checkout form caching for PCI compliance
- Use Message to make visible, e-mailable comments on orders
- Implement a Kickstart 2.x style order history View to orders
- Implement the complete design for order view pages
- Rename order states to order status groups
- Add UI / Cart + Checkout module support for multiple order types
Re-implement line items to be saved / updated through orders
$order->line_items->product = $product; $order->save();
- Implement line item revisions
- Propose replacing order line item reference field w/ a computed list property
- Add a generic line item type to be used for order level discounts / fees
- Instantiate payment methods outside of Rules and simply enable them
- Add split payment support to the Payment checkout pane
- Convert the price field widget to a new form element type and use that
- Store the precision denominator in the price field schema
Depend on the BigInteger library for string storage of price amounts
- Separate the computation precision from the display precision
- Create and use a complete API for price manipulations
- Support price calculation through a hook when pre-calculation is off
- Perform all price amount computations with fixed previsions
Separate price calculation history from the price components array
Price components should be a flat array with only one value per price component type.
Split "Calculating the sell price of a product" into separate events:
- Is it sellable?
- Determine the base price.
- Apply pre-tax fixed discounts.
- Apply a percentage tax; can be based on any property of the product or the order except the price.
- Apply post-tax fixed discounts.
- Apply fixed amount fees / taxes.
- Propose normalizing the storage of price components
- Add a CMI based UI for managing price component types
- Make the VAT inclusive select list an explicit option on price fields
- Create a feature specification area where we publish module blueprints
- Add a blueprint for Commerce Product Kit
- Add the blueprint for the next Commerce Stock