Quality incidents for Drupal Commerce: from the customer's complaint to the repaired item on its way back

Diagram: an order item already carried by a shipped shipment, a hand-made shipment with no item that UPS refuses, and the return shipment created from quality incident QI-2026-00042 carrying that same item.

A customer writes in: the sole of the left shoe has come away, three weeks after delivery. Someone answers the email, someone else notes it in a spreadsheet, the repair is agreed by phone with the workshop, and when the pair is ready, a shipment has to be made for an order that shipped a month ago. Six months later, nobody can say whether gluing fails more often than stitching, or on which model.

Commerce Quality Incident turns that complaint into a record in the store itself, attached to the order, the order item and the SKU that failed, with its own number, workflow and history. It is free software under GPL-2.0-or-later, published on drupal.org, and it builds on what a Commerce site already has: orders, State Machine, Commerce Log and Commerce Number Pattern. Version 1.1.0 adds the last step: the shipment that takes the repaired or replaced item back to the customer.

What you can build with it

  • One record per complaint, numbered like the orders (QI-2026-00001), reached from the order's own admin page, where every incident of that order is listed.
  • A defect report you can count. The category and subcategory come from a fixed list in the form, so "Manufacturing defect: Gluing" is the same thing every time, along with a severity from low to critical.
  • Categories that fit what you sell. The default plugin covers any product; a Footwear & Bags plugin ships as a worked example; your own takes one PHP class.
  • An incident that cannot be closed without saying how it was resolved.
  • The repair or replacement order, created from the incident with Commerce Make-to-Order, with its priority taken from the incident's severity.
  • The return shipment, created from the incident with Commerce Shipping, new in 1.1.0.
  • Defects found in production or at receiving, logged with no order at all.

The shipment Commerce would not build

The return shipment needed a submodule of its own because of how Commerce Shipping guards against shipping an item twice. Its shipment form only offers order items that no other shipment carries. A repaired pair travels back for an order item that already went out on the order's first shipment, so a shipment added there for the return has no item in it. Carriers that declare contents refuse it: UPS, for a parcel leaving the European Union, answers 128039 Invalid number of products.

The QI-Shipping submodule builds the shipment from the incident instead. It carries one unit of the incident's order item, goes to a copy of the order's shipping address, offers the shipping method the order last used, and points back to the incident in a source_incident field, which Views can list on an order's shipments. The incident page then shows the shipment with its state, items and tracking code, together with whatever operations other modules add to it, such as sending it to the carrier. A site that needs its own fields filled on the shipment, a reason code for instance, subscribes to one event and sets them before it is saved.

What it refuses to do

Each of these limits is there because the record has to be trustworthy months later, when someone counts.

The return shipment's item and address are shown in the dialog, not chosen. The shipment goes where the order went, for the item the incident is about. Sending it elsewhere is an edit to the shipment, made on purpose by someone who can see what they are changing.

There is one active return shipment per incident. The button disappears while one exists and comes back only when it is canceled, and canceled shipments stay listed on the incident. A second shipment created by a double click, or by two people on the same morning, is a parcel the carrier collects and the customer never expected.

Closing asks for resolution notes. An incident marked closed with nothing written in it is the spreadsheet again.

Where it came from

We built it for one of our clients, a footwear brand whose shoes are made by hand after they are ordered, and the Footwear & Bags category plugin is that store's list of what goes wrong with a shoe. It was in production there before its first public release in July, which brought the generic category plugin, its own tests and the cleanup for drupal.org. The return shipment came from the same store, which created its first return through the new submodule on the day 1.1.0 was released.

The make-to-order side of the same workflow has its own post: with both modules, a complaint becomes a repair order in the workshop and then a shipment, and each record links to the others.

Get it

composer require drupal/commerce_quality_incident
drush en commerce_quality_incident

It requires Drupal 10.3 or 11, PHP 8.1, Commerce 2.x or 3.x and State Machine. The two submodules are optional and enabled the same way: commerce_quality_incident_mto needs Commerce Make-to-Order, commerce_quality_incident_shipping needs Commerce Shipping. Stable releases are covered by Drupal's security advisory policy.

The project page has the full documentation. If your store handles complaints, warranty claims or repairs in a way the module does not fit yet, tell us in the issue queue.