Boomerang for Craft CMS

Restocking and exchanges

Pro. Both of these run on arrival at a state that has the relevant switch turned on — see The state machine.

The right shelf

Returned goods do not all go back to the same place. Each return item carries a condition, which decides the inventory transaction type it is adjusted into:

ConditionGoes to
Resellableavailable
Damageddamaged
Inspectquality control

The condition is defaulted from the reason — goods that "arrived damaged" default to damaged, goods that are "faulty" default to quality control — and the desk can change it per item when the box is actually open.

It is an adjustment, not a restock movement

Commerce ships InventoryRestockMovement, and it is the wrong tool here. That model moves committed → available, for an order that was never shipped.

Goods coming back from a customer had their committed quantity consumed by fulfilment long ago, so using it would drive committed negative. Boomerang uses UpdateInventoryLevel with InventoryUpdateQuantityType::ADJUST instead, and picks the transaction type from the item's condition.

It is idempotent

services\Restock::apply() is the only place a return moves inventory, and it is idempotent per item through qtyRestocked. Re-entering a state that restocks, retrying a failed transition, or running the same transition twice from two browser tabs does not restock twice.

Exchange and replacement orders

Two resolutions create a new order:

  • Exchange — a new order for different goods, carrying a credit for what came back, so the customer pays only the difference.
  • Replacement — the same goods again, at a zero balance.

The credit is applied to the new order, so the customer's payment step shows the difference rather than the full price with a promise of a refund later.

When the exchange order is completed for less than the credit it carried, the remainder is settled back — into the wallet if the store has one, and otherwise as a refund.

Inventory locations

A return is restocked into one inventory location, chosen on the RMA. Stores with a single location never see the field; stores with several get to say which warehouse the goods physically arrived at, which is not always the one they shipped from.