docs/plans/5.4-store-api-naming-standardization.md
Status: In Progress
Target: Spree 5.4 (API surface + model aliases); Spree 6.0 (database columns/tables)
Depends on: 5.4-store-api-bridges.md (same pattern: rename API surface now, models/DB later)
Author: Damian + Claude
Last updated: 2026-03-19
Standardize Spree Store API entity and attribute names against industry conventions (Shopify, Medusa, Saleor, Vendure, BigCommerce, commercetools). Changes follow the established bridge pattern: rename serializers, controllers, and add model aliases now (5.4), defer database column/table renames to 6.0.
5.4-store-api-bridges.md)ship_address / bill_address → shipping_address / billing_addressSerializers: Cart and Order serializers use key: :billing_address / key: :shipping_address on the association.
Controllers: Cart update accepts shipping_address_id, billing_address_id, shipping_address: {}, billing_address: {}.
Service: Carts::Update uses assign_address(:shipping_address) / :billing_address directly.
Model aliases (already existed + new):
alias_method :billing_address, :bill_address (existed)alias_method :shipping_address, :ship_address (existed)alias_attribute :billing_address_id, :bill_address_id (new)alias_attribute :shipping_address_id, :ship_address_id (new)alias shipping_address_attributes= ship_address_attributes= (new)alias billing_address_attributes= bill_address_attributes= (new)6.0 database: Rename spree_orders.bill_address_id → billing_address_id, spree_orders.ship_address_id → shipping_address_id
firstname/lastname → first_name/last_nameSerializer: AddressSerializer exposes first_name / last_name.
Controllers: Accept first_name / last_name only.
Model (already existed): Spree::Address has first_name / last_name accessor methods and Spree::PermittedAttributes includes both forms.
6.0 database: Rename spree_addresses.firstname → first_name, spree_addresses.lastname → last_name
zipcode → postal_codeSerializer: AddressSerializer exposes postal_code.
Controllers: Accept postal_code only.
Model (already existed): alias_attribute :postal_code, :zipcode on Spree::Address.
6.0 database: Rename spree_addresses.zipcode → postal_code
Serializers:
DiscountSerializer (single serializer for both cart and order promotions)CartPromotionSerializer and OrderPromotionSerializer fileskey: :discounts on the associationAdmin::DiscountSerializer replaces Admin::OrderPromotionSerializerModel aliases: alias discounts order_promotions on Spree::Order
Dependencies: discount_serializer, cart_promotion_serializer, order_promotion_serializer all point to DiscountSerializer. Admin: admin_discount_serializer and admin_order_promotion_serializer point to Admin::DiscountSerializer.
TypeScript type: CartPromotion / OrderPromotion → Discount
promo_total → discount_totalSerializers: Cart, Order, LineItem serializers expose discount_total / display_discount_total.
Model aliases:
Spree::Order: alias_attribute :discount_total, :promo_total, alias display_discount_total display_promo_totalSpree::LineItem: alias_attribute :discount_total, :promo_total, alias display_discount_total display_promo_total6.0 database: Rename spree_orders.promo_total → discount_total, spree_line_items.promo_total → discount_total
Serializers: Created WishlistItemSerializer, WishlistSerializer references it. Old WishedItemSerializer kept for now (dependency points to new one).
Model alias: alias wishlist_items wished_items on Spree::Wishlist
Dependencies: wishlist_item_serializer and wished_item_serializer both point to WishlistItemSerializer.
6.0 database/model: Rename Spree::WishedItem → Spree::WishlistItem, table spree_wished_items → spree_wishlist_items, prefix wi_ → wli_
special_instructions → customer_noteSerializers: Cart and Order serializers expose customer_note.
Controller: Cart update accepts customer_note only.
Service: Carts::Update assigns cart.customer_note.
Model alias: alias_attribute :customer_note, :special_instructions on Spree::Order
6.0 database: Rename spree_orders.special_instructions → customer_note
presentation → labelSerializers: OptionTypeSerializer and OptionValueSerializer expose label. OptionValueSerializer exposes option_type_label.
Model aliases: alias_attribute :label, :presentation on both Spree::OptionType and Spree::OptionValue
6.0 database: Rename spree_option_types.presentation → label, spree_option_values.presentation → label
AssetSerializer excluded from Store SDK types via Typelizer reject_class filter. Media serializer is the correct Store-facing entity.
Added Typelizer reject_class filter excluding serializers with no Store API controller:
Asset, CartPromotion, OrderPromotion, StockItem, StockMovement, StockTransfer, ShippingCategory, Reimbursement, Report, Export, Import, ImportRow, TaxCategory, CustomerReturn
PromotionSerializer reduced to: id, name, description, code. Full promotion details remain in Admin serializer only.
cc_type → brand, last_digits → last4Serializer: CreditCardSerializer exposes brand and last4.
Model aliases:
alias_attribute :brand, :cc_type (already existed)alias_attribute :last4, :last_digits (new)6.0 database: Rename spree_credit_cards.cc_type → brand, spree_credit_cards.last_digits → last4
gateway_payment_profile_id from Store APIRemoved from CreditCardSerializer and PaymentSourceSerializer. Added to Admin::CreditCardSerializer and Admin::PaymentSourceSerializer.
item_count → total_quantitySerializers: Cart and Order serializers expose total_quantity.
Model alias: alias_attribute :total_quantity, :item_count on Spree::Order
6.0 database: Rename spree_orders.item_count → total_quantity
state → statusSerializer: ReturnAuthorizationSerializer exposes status (reads object.state).
6.0 database: Covered by 6.0-normalize-state-to-status.md
These aliases consolidate all naming bridges on Spree::Order:
alias fulfillments shipmentsalias_attribute :delivery_total, :shipment_totalalias display_delivery_total display_shipment_totalalias_attribute :fulfillment_status, :shipment_statealias_attribute :payment_status, :payment_stateapi/app/serializers/spree/api/v3/discount_serializer.rbapi/app/serializers/spree/api/v3/wishlist_item_serializer.rbapi/app/serializers/spree/api/v3/admin/discount_serializer.rbapi/app/serializers/spree/api/v3/cart_promotion_serializer.rbapi/app/serializers/spree/api/v3/order_promotion_serializer.rbapi/app/serializers/spree/api/v3/admin/order_promotion_serializer.rbapi/app/serializers/spree/api/v3/address_serializer.rb — firstname→first_name, lastname→last_name, zipcode→postal_codeapi/app/serializers/spree/api/v3/cart_serializer.rb — all renames (customer_note, total_quantity, discount_total, billing/shipping_address, discounts)api/app/serializers/spree/api/v3/order_serializer.rb — same as cartapi/app/serializers/spree/api/v3/line_item_serializer.rb — promo_total→discount_totalapi/app/serializers/spree/api/v3/option_type_serializer.rb — presentation→labelapi/app/serializers/spree/api/v3/option_value_serializer.rb — presentation→label, option_type_presentation→option_type_labelapi/app/serializers/spree/api/v3/credit_card_serializer.rb — cc_type→brand, last_digits→last4, removed gateway_payment_profile_idapi/app/serializers/spree/api/v3/payment_source_serializer.rb — removed gateway_payment_profile_idapi/app/serializers/spree/api/v3/return_authorization_serializer.rb — state→statusapi/app/serializers/spree/api/v3/promotion_serializer.rb — slimmed to name/description/codeapi/app/serializers/spree/api/v3/wishlist_serializer.rb — references wishlist_item_serializerapi/app/serializers/spree/api/v3/admin/order_serializer.rb — discounts key, billing/shipping_address keys, admin_discount_serializerapi/app/serializers/spree/api/v3/admin/credit_card_serializer.rb — added gateway_payment_profile_idapi/app/serializers/spree/api/v3/admin/payment_source_serializer.rb — added gateway_payment_profile_idapi/app/controllers/spree/api/v3/store/carts_controller.rb — new param names onlyapi/app/controllers/spree/api/v3/store/customer/addresses_controller.rb — new param names onlyapi/lib/spree/api/dependencies.rb — added discount_serializer, wishlist_item_serializer, admin_discount_serializerapi/config/initializers/typelizer.rb — exclude admin-only schemas from Store typescore/app/models/spree/order.rb — all aliases (discount_total, customer_note, total_quantity, billing/shipping_address_id, discounts, fulfillments, etc.)core/app/models/spree/line_item.rb — discount_total aliascore/app/models/spree/option_type.rb — label aliascore/app/models/spree/option_value.rb — label aliascore/app/models/spree/credit_card.rb — last4 aliascore/app/models/spree/wishlist.rb — wishlist_items aliascore/app/services/spree/carts/update.rb — uses new names (shipping_address, billing_address, customer_note)api/spec/integration/spree/api/v3/store/carts_spec.rbapi/spec/integration/spree/api/v3/store/addresses_spec.rbapi/spec/integration/spree/api/v3/store/credit_cards_spec.rbbundle exec rake typelizer:generate)cd packages/sdk && pnpm generate:zod)bundle exec rake rswag:specs:swaggerize)None — all decisions made.
5.4-store-api-bridges.md — prior art for this exact pattern6.0-normalize-state-to-status.md — covers state → status DB rename