docs/plans/6.0-normalize-state-to-status.md
Status: Design finalized, implementation not started Target: Spree 6.0 Depends on: Cart/Order split (6.0-cart-order-split.md), Split Adjustments (6.0-split-adjustments.md) Author: Damian + Claude Last updated: 2026-03-16
Rename the state column to status on the five remaining models that still use it. Newer models already use status. Order and Adjustment state columns are removed entirely by other 6.0 plans. This finishes the normalization so every state machine in Spree uses status.
Spree has two conventions for the state machine column name:
state: Payment, Shipment, InventoryUnit, ReturnAuthorization, GiftCardstatus: Product, PriceList, PaymentSession, PaymentSetupSession, Import, ImportRow, InvitationThis inconsistency means developers must remember which column each model uses. API responses mix state and status fields. Ransack filters differ per model. The CLAUDE.md rule says "default column should be status, legacy models use state" — 6.0 is the window to eliminate the exception.
| Model | Current column | 6.0 action |
|---|---|---|
| Order | state | Removed (cart-order-split — no state machine on Order) |
| Adjustment | state | Removed (split-adjustments — no state machine) |
| Payment | state | Rename → status |
| Shipment | state | Rename → status |
| InventoryUnit | state | Rename → status |
| ReturnAuthorization | state | Rename → status |
| GiftCard | state | Rename → status |
| Product | status | Already correct |
| PriceList | status | Already correct |
| PaymentSession | status | Already correct |
| PaymentSetupSession | status | Already correct |
| Import | status | Already correct |
| ImportRow | status | Already correct |
| Invitation | status | Already correct |
| ReturnItem | reception_status, acceptance_status | Already correct |
| Reimbursement | reimbursement_status | Already correct |
status is the standard. All state machines use status as the column name.alias_attribute :state, :status) for one release to avoid breaking custom code that reads .state.status everywhere. No more state field in serializers.payment_state and shipment_state stay as-is. These are derived summary fields on Order, not state machine columns. Renaming them to payment_status/shipment_status is optional and lower priority.class RenameStateToStatus < ActiveRecord::Migration[7.2]
def change
rename_column :spree_payments, :state, :status
rename_column :spree_shipments, :state, :status
rename_column :spree_inventory_units, :state, :status
rename_column :spree_return_authorizations, :state, :status
rename_column :spree_gift_cards, :state, :status
end
end
For each of the five models:
state_machine declaration:# Before
state_machine initial: :pending do
# After
state_machine :status, initial: :pending do
# Temporary — remove in 6.1
alias_attribute :state, :status
state column directly (e.g., where(state: 'shipped') → where(status: 'shipped')).status instead of statefilter[status_eq]=shipped instead of filter[state_eq]=shippedSpree::StateChange records state transitions with name field (e.g., "payment", "shipment"). The previous_state and next_state columns stay as-is — they store values like "pending", "shipped", not column names.
alias_attribute :state, :status from all five modelsstate references in specs and factoriesstatus in all new code. Don't add new state references.status column. This is already the rule in CLAUDE.md.status. Existing v3 endpoints will be updated in this plan.None.
status (legacy uses state)"6.0-cart-order-split.md (removes Order.state entirely)6.0-split-adjustments.md (removes Adjustment.state entirely)docs/plans/decisions.md (2026-03-16 entry)