spree_api 5.4.0.beta9 → 5.4.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +17 -0
  3. data/app/controllers/concerns/spree/api/v3/http_caching.rb +1 -1
  4. data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +27 -0
  5. data/app/controllers/spree/api/v3/store/carts_controller.rb +9 -7
  6. data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +2 -2
  7. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +14 -10
  8. data/app/controllers/spree/api/v3/store/products_controller.rb +16 -36
  9. data/app/serializers/spree/api/v3/address_serializer.rb +4 -4
  10. data/app/serializers/spree/api/v3/admin/{order_promotion_serializer.rb → discount_serializer.rb} +1 -1
  11. data/app/serializers/spree/api/v3/admin/order_serializer.rb +4 -4
  12. data/app/serializers/spree/api/v3/cart_serializer.rb +17 -18
  13. data/app/serializers/spree/api/v3/credit_card_serializer.rb +4 -3
  14. data/app/serializers/spree/api/v3/{cart_promotion_serializer.rb → discount_serializer.rb} +5 -5
  15. data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -2
  16. data/app/serializers/spree/api/v3/option_type_serializer.rb +2 -2
  17. data/app/serializers/spree/api/v3/option_value_serializer.rb +5 -5
  18. data/app/serializers/spree/api/v3/order_serializer.rb +12 -26
  19. data/app/serializers/spree/api/v3/payment_source_serializer.rb +1 -3
  20. data/app/serializers/spree/api/v3/promotion_serializer.rb +4 -16
  21. data/app/serializers/spree/api/v3/return_authorization_serializer.rb +2 -2
  22. data/app/serializers/spree/api/v3/{wished_item_serializer.rb → wishlist_item_serializer.rb} +1 -1
  23. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  24. data/app/services/spree/api/v3/filters_aggregator.rb +2 -2
  25. data/config/initializers/typelizer.rb +13 -1
  26. data/lib/spree/api/dependencies.rb +4 -4
  27. metadata +10 -10
  28. data/app/serializers/spree/api/v3/order_promotion_serializer.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7630000b76a8d6596d6a94e2e5ef3b928ad55035995a777d79a855da0b83e707
4
- data.tar.gz: 5621ebbdb257e9c69518e3ad71a9368954c0fbf7db6ad7a3b4adb237b00cb83b
3
+ metadata.gz: 4378e0d0d201591ada81caa1958a92ca6aa55d8e2ff79d8b90b58016ff1b834b
4
+ data.tar.gz: 32fddc14b53ae38f7c80192be53a456e84b4862f58ddc3492a499ccbf2e67d53
5
5
  SHA512:
6
- metadata.gz: ecdbc7f8b2e6792a1e8641ebaabfcc69423705f032435bb960ff3f2ae36eb19c89dc224b8af79278b3e74536ca95112442139278e847cca9710f437300d9395e
7
- data.tar.gz: 8264257bdf243e8bc504880ceed1f99233baaf09bf6e7264714ab9395b59429e0c9c553269012015d9e870dd3dc797b19224d204b7a33518681878533200e71e
6
+ metadata.gz: 8f597f0fcb3d074cb90593a0feb619220642e13dbeefc994839b208f7639eabd0273e5b4a8223e8c4aa6ebbe9bd05add4559a9c6aac0de50cd837ee56060dcec
7
+ data.tar.gz: 03e32f252a79ec570e5d91fc5ed4113367b6892c384c7bc49eb0772b3f00c899d2007fc3be6424676cdbab7522b00f6db550425c9c68e932b761f582061bda14
data/Rakefile CHANGED
@@ -46,6 +46,23 @@ namespace :typelizer do
46
46
 
47
47
  # Writer config is in config/initializers/typelizer.rb
48
48
  Typelizer::Generator.call(force: true)
49
+
50
+ # Post-process: convert `type Foo = {` to `interface Foo {` for declaration merging support.
51
+ # This lets SDK consumers extend generated types via `declare module '@spree/sdk' { interface Product { ... } }`.
52
+ api_root = Spree::Api::Engine.root
53
+ [
54
+ api_root.join('../../packages/sdk/src/types/generated'),
55
+ api_root.join('../../packages/admin-sdk/src/types/generated')
56
+ ].each do |dir|
57
+ Dir[File.join(dir, '*.ts')].each do |file|
58
+ next if File.basename(file) == 'index.ts'
59
+
60
+ content = File.read(file)
61
+ updated = content.gsub(/^type (\w+) = \{/, 'interface \1 {')
62
+ File.write(file, updated) if updated != content
63
+ end
64
+ end
65
+
49
66
  puts "Generated types → packages/sdk/src/types/generated/ & packages/admin-sdk/src/types/generated/"
50
67
  end
51
68
 
@@ -72,7 +72,7 @@ module Spree
72
72
  # Includes: latest updated_at, total count, query params, pagination, expand, currency, locale
73
73
  def collection_cache_key(collection)
74
74
  # For ActiveRecord collections use updated_at, for plain arrays use store's updated_at as proxy
75
- latest_updated_at = if collection.first.respond_to?(:updated_at)
75
+ latest_updated_at = if collection.first&.respond_to?(:updated_at)
76
76
  collection.map(&:updated_at).max&.to_i
77
77
  else
78
78
  current_store&.updated_at&.to_i
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Store
5
+ module SearchProviderSupport
6
+ extend ActiveSupport::Concern
7
+
8
+ private
9
+
10
+ def search_query
11
+ params.dig(:q, :search)
12
+ end
13
+
14
+ def search_filters
15
+ q = params[:q]&.to_unsafe_h || params[:q] || {}
16
+ q = q.to_h if q.respond_to?(:to_h) && !q.is_a?(Hash)
17
+ q.except('search').presence
18
+ end
19
+
20
+ def search_provider
21
+ @search_provider ||= Spree.search_provider.constantize.new(current_store)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -140,13 +140,14 @@ module Spree
140
140
  def permitted_params
141
141
  params.permit(
142
142
  :email,
143
- :special_instructions,
143
+ :customer_note,
144
144
  :currency,
145
145
  :locale,
146
- :ship_address_id,
147
- :bill_address_id,
148
- ship_address: address_params,
149
- bill_address: address_params,
146
+ :shipping_address_id,
147
+ :billing_address_id,
148
+ :use_shipping,
149
+ shipping_address: address_params,
150
+ billing_address: address_params,
150
151
  metadata: {},
151
152
  items: item_params
152
153
  )
@@ -154,8 +155,9 @@ module Spree
154
155
 
155
156
  def address_params
156
157
  [
157
- :id, :firstname, :lastname, :address1, :address2,
158
- :city, :zipcode, :phone, :company,
158
+ :id, :first_name, :last_name,
159
+ :address1, :address2,
160
+ :city, :postal_code, :phone, :company,
159
161
  :country_iso, :state_abbr, :state_name, :quick_checkout
160
162
  ]
161
163
  end
@@ -73,8 +73,8 @@ module Spree
73
73
 
74
74
  def permitted_params
75
75
  params.permit(
76
- :firstname, :lastname, :address1, :address2, :city,
77
- :zipcode, :phone, :company, :country_iso, :state_abbr, :state_name
76
+ :first_name, :last_name, :address1, :address2, :city,
77
+ :postal_code, :phone, :company, :country_iso, :state_abbr, :state_name
78
78
  )
79
79
  end
80
80
  end
@@ -4,29 +4,33 @@ module Spree
4
4
  module Store
5
5
  module Products
6
6
  class FiltersController < Store::BaseController
7
+ include Spree::Api::V3::Store::SearchProviderSupport
8
+
7
9
  def index
8
- aggregator = Spree::Api::V3::FiltersAggregator.new(
10
+ result = search_provider.search_and_filter(
9
11
  scope: filters_scope,
10
- currency: current_currency,
11
- category: category
12
+ query: search_query,
13
+ filters: (search_filters || {}).merge('_category' => category),
14
+ page: 1,
15
+ limit: 0
12
16
  )
13
- render json: aggregator.call
17
+
18
+ render json: {
19
+ filters: result.filters,
20
+ sort_options: result.sort_options,
21
+ default_sort: result.default_sort,
22
+ total_count: result.total_count
23
+ }
14
24
  end
15
25
 
16
26
  private
17
27
 
18
- # Build scope from category and/or ransack params
19
- # @return [ActiveRecord::Relation]
20
28
  def filters_scope
21
29
  scope = current_store.products.active(current_currency)
22
30
  scope = scope.in_category(category) if category.present?
23
- scope = scope.ransack(params[:q]).result if params[:q].present?
24
31
  scope.accessible_by(current_ability, :show)
25
32
  end
26
33
 
27
- # Fetches category from params
28
- # @param [String] category_id
29
- # @return [Spree::Category]
30
34
  def category
31
35
  category_id = params[:category_id]
32
36
  @category ||= category_id.present? ? current_store.categories.find_by_param(category_id) : nil
@@ -4,13 +4,7 @@ module Spree
4
4
  module Store
5
5
  class ProductsController < ResourceController
6
6
  include Spree::Api::V3::HttpCaching
7
-
8
- # Sort values that require special scopes (not plain Ransack column sorts).
9
- CUSTOM_SORT_SCOPES = {
10
- 'price' => :ascend_by_price,
11
- '-price' => :descend_by_price,
12
- 'best_selling' => :by_best_selling
13
- }.freeze
7
+ include Spree::Api::V3::Store::SearchProviderSupport
14
8
 
15
9
  protected
16
10
 
@@ -47,37 +41,23 @@ module Spree
47
41
  ]
48
42
  end
49
43
 
50
- # Applies sorting from the unified `sort` param.
51
- # Custom values ('price', '-price', 'best_selling') use product-specific scopes.
52
- # Standard Ransack values ('name', '-created_at') are handled by base ResourceController.
53
- def apply_collection_sort(collection)
54
- sort_value = sort_param
55
- return collection unless sort_value.present?
56
-
57
- scope_method = CUSTOM_SORT_SCOPES[sort_value]
58
- return collection unless scope_method
59
-
60
- sorted = collection.reorder(nil)
61
- sorted.send(scope_method)
62
- end
63
-
64
- # Skip base Ransack sort injection for custom sort scopes
65
- def ransack_params
66
- rp = super
67
-
68
- # Remove Ransack sort when a custom scope handles it
69
- if sort_param.present? && CUSTOM_SORT_SCOPES.key?(sort_param)
70
- rp = rp.is_a?(Hash) ? rp.dup : rp.to_unsafe_h
71
- rp.delete('s')
72
- end
73
-
74
- rp
75
- end
44
+ # Override collection to use search provider.
45
+ # The provider handles search, filtering, sorting, pagination, and returns a Pagy object.
46
+ def collection
47
+ return @collection if @collection.present?
76
48
 
77
- private
49
+ result = search_provider.search_and_filter(
50
+ scope: scope.includes(collection_includes).preload_associations_lazily.accessible_by(current_ability, :show),
51
+ query: search_query,
52
+ filters: search_filters,
53
+ sort: sort_param,
54
+ page: page,
55
+ limit: limit
56
+ )
78
57
 
79
- def custom_sort_requested?
80
- CUSTOM_SORT_SCOPES.key?(sort_param)
58
+ @search_result = result
59
+ @pagy = result.pagy
60
+ @collection = result.products
81
61
  end
82
62
  end
83
63
  end
@@ -2,15 +2,15 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class AddressSerializer < BaseSerializer
5
- typelize firstname: [:string, nullable: true], lastname: [:string, nullable: true], full_name: :string,
5
+ typelize first_name: [:string, nullable: true], last_name: [:string, nullable: true], full_name: :string,
6
6
  address1: [:string, nullable: true], address2: [:string, nullable: true],
7
- city: [:string, nullable: true], zipcode: [:string, nullable: true], phone: [:string, nullable: true],
7
+ city: [:string, nullable: true], postal_code: [:string, nullable: true], phone: [:string, nullable: true],
8
8
  company: [:string, nullable: true], state_abbr: [:string, nullable: true], state_name: [:string, nullable: true],
9
9
  state_text: [:string, nullable: true], country_iso: :string, country_name: :string,
10
10
  quick_checkout: :boolean
11
11
 
12
- attributes :firstname, :lastname, :full_name, :address1, :address2,
13
- :city, :zipcode, :phone, :company, :country_name, :country_iso, :state_text,
12
+ attributes :first_name, :last_name, :full_name, :address1, :address2, :postal_code,
13
+ :city, :phone, :company, :country_name, :country_iso, :state_text,
14
14
  :state_abbr, :quick_checkout
15
15
 
16
16
  # State name - used for countries without predefined states
@@ -2,7 +2,7 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  module Admin
5
- class OrderPromotionSerializer < V3::OrderPromotionSerializer
5
+ class DiscountSerializer < V3::DiscountSerializer
6
6
  end
7
7
  end
8
8
  end
@@ -43,13 +43,13 @@ module Spree
43
43
  end
44
44
 
45
45
  # Override inherited associations to use admin serializers
46
- many :order_promotions, key: :promotions, resource: Spree.api.admin_order_promotion_serializer, if: proc { expand?('promotions') }
46
+ many :discounts, resource: Spree.api.admin_discount_serializer, if: proc { expand?('discounts') }
47
47
  many :line_items, key: :items, resource: Spree.api.admin_line_item_serializer, if: proc { expand?('items') }
48
- many :shipments, key: :fulfillments, resource: Spree.api.admin_fulfillment_serializer, if: proc { expand?('fulfillments') }
48
+ many :fulfillments, resource: Spree.api.admin_fulfillment_serializer, if: proc { expand?('fulfillments') }
49
49
  many :payments, resource: Spree.api.admin_payment_serializer, if: proc { expand?('payments') }
50
50
 
51
- one :bill_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('bill_address') }
52
- one :ship_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('ship_address') }
51
+ one :billing_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('billing_address') }
52
+ one :shipping_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('shipping_address') }
53
53
 
54
54
  many :payment_methods, resource: Spree.api.admin_payment_method_serializer, if: proc { expand?('payment_methods') }
55
55
 
@@ -5,39 +5,34 @@ module Spree
5
5
  # Pre-purchase cart data with checkout progression info
6
6
  class CartSerializer < BaseSerializer
7
7
  typelize number: :string, current_step: :string, completed_steps: 'string[]', token: :string, email: [:string, nullable: true],
8
- special_instructions: [:string, nullable: true], currency: :string, locale: [:string, nullable: true], item_count: :number,
8
+ customer_note: [:string, nullable: true], currency: :string, locale: [:string, nullable: true], total_quantity: :number,
9
9
  requirements: 'Array<{step: string, field: string, message: string}>',
10
10
  item_total: :string, display_item_total: :string,
11
11
  delivery_total: :string, display_delivery_total: :string,
12
12
  adjustment_total: :string, display_adjustment_total: :string,
13
- promo_total: :string, display_promo_total: :string,
13
+ discount_total: :string, display_discount_total: :string,
14
14
  tax_total: :string, display_tax_total: :string,
15
15
  included_tax_total: :string, display_included_tax_total: :string,
16
16
  additional_tax_total: :string, display_additional_tax_total: :string,
17
17
  total: :string, display_total: :string,
18
- bill_address: { nullable: true }, ship_address: { nullable: true }
18
+ shipping_eq_billing_address: :boolean,
19
+ billing_address: { nullable: true }, shipping_address: { nullable: true }
19
20
 
20
21
  # Override ID to use cart_ prefix
21
22
  attribute :id do |order|
22
23
  "cart_#{Spree::PrefixedId::SQIDS.encode([order.id])}"
23
24
  end
24
25
 
25
- attributes :number, :token, :email, :special_instructions,
26
- :currency, :locale, :item_count,
26
+ attributes :number, :token, :email, :customer_note,
27
+ :currency, :locale, :total_quantity,
27
28
  :item_total, :display_item_total,
28
- :adjustment_total, :display_adjustment_total, :promo_total, :display_promo_total,
29
+ :adjustment_total, :display_adjustment_total,
30
+ :discount_total, :display_discount_total,
29
31
  :tax_total, :display_tax_total, :included_tax_total, :display_included_tax_total,
30
32
  :additional_tax_total, :display_additional_tax_total, :total, :display_total,
33
+ :delivery_total, :display_delivery_total,
31
34
  created_at: :iso8601, updated_at: :iso8601
32
35
 
33
- attribute :delivery_total do |order|
34
- order.ship_total
35
- end
36
-
37
- attribute :display_delivery_total do |order|
38
- order.display_ship_total.to_s
39
- end
40
-
41
36
  attribute :current_step do |order|
42
37
  order.current_checkout_step
43
38
  end
@@ -50,12 +45,16 @@ module Spree
50
45
  Spree::Checkout::Requirements.new(order).call
51
46
  end
52
47
 
53
- many :cart_promotions, key: :promotions, resource: Spree.api.cart_promotion_serializer
48
+ attribute :shipping_eq_billing_address do |order|
49
+ order.shipping_eq_billing_address?
50
+ end
51
+
52
+ many :discounts, resource: Spree.api.discount_serializer
54
53
  many :line_items, key: :items, resource: Spree.api.line_item_serializer
55
- many :shipments, key: :fulfillments, resource: Spree.api.fulfillment_serializer
54
+ many :fulfillments, resource: Spree.api.fulfillment_serializer
56
55
  many :payments, resource: Spree.api.payment_serializer
57
- one :bill_address, resource: Spree.api.address_serializer
58
- one :ship_address, resource: Spree.api.address_serializer
56
+ one :billing_address, resource: Spree.api.address_serializer
57
+ one :shipping_address, resource: Spree.api.address_serializer
59
58
 
60
59
  many :payment_methods, resource: Spree.api.payment_method_serializer
61
60
  end
@@ -2,10 +2,11 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class CreditCardSerializer < BaseSerializer
5
- typelize cc_type: :string, last_digits: :string, month: :number, year: :number,
6
- name: [:string, nullable: true], default: :boolean, gateway_payment_profile_id: [:string, nullable: true]
5
+ typelize brand: :string, last4: :string, month: :number, year: :number,
6
+ name: [:string, nullable: true], default: :boolean,
7
+ gateway_payment_profile_id: [:string, nullable: true]
7
8
 
8
- attributes :cc_type, :last_digits, :month, :year, :name, :default, :gateway_payment_profile_id
9
+ attributes :brand, :last4, :month, :year, :name, :default, :gateway_payment_profile_id
9
10
  end
10
11
  end
11
12
  end
@@ -1,14 +1,14 @@
1
1
  module Spree
2
2
  module Api
3
3
  module V3
4
- # Cart-facing promotion serializer.
5
- # Same data as OrderPromotionSerializer but IDs use the cp_ prefix.
6
- class CartPromotionSerializer < BaseSerializer
4
+ # Unified discount serializer for applied promotions on Cart and Order.
5
+ # Replaces CartPromotionSerializer and OrderPromotionSerializer.
6
+ class DiscountSerializer < BaseSerializer
7
7
  typelize name: :string, description: [:string, nullable: true], code: [:string, nullable: true],
8
8
  amount: :string, display_amount: :string, promotion_id: :string
9
9
 
10
- attribute :promotion_id do |cart_promotion|
11
- cart_promotion.promotion&.prefixed_id
10
+ attribute :promotion_id do |record|
11
+ record.promotion&.prefixed_id
12
12
  end
13
13
 
14
14
  attributes :name, :description, :code, :amount, :display_amount
@@ -8,7 +8,7 @@ module Spree
8
8
  adjustment_total: :string, display_adjustment_total: :string,
9
9
  additional_tax_total: :string, display_additional_tax_total: :string,
10
10
  included_tax_total: :string, display_included_tax_total: :string,
11
- promo_total: :string, display_promo_total: :string,
11
+ discount_total: :string, display_discount_total: :string,
12
12
  pre_tax_amount: :string, display_pre_tax_amount: :string,
13
13
  discounted_amount: :string, display_discounted_amount: :string,
14
14
  compare_at_amount: [:string, nullable: true], display_compare_at_amount: [:string, nullable: true],
@@ -23,7 +23,7 @@ module Spree
23
23
  :adjustment_total, :display_adjustment_total,
24
24
  :additional_tax_total, :display_additional_tax_total,
25
25
  :included_tax_total, :display_included_tax_total,
26
- :promo_total, :display_promo_total,
26
+ :discount_total, :display_discount_total,
27
27
  :pre_tax_amount, :display_pre_tax_amount,
28
28
  :discounted_amount, :display_discounted_amount,
29
29
  :display_compare_at_amount,
@@ -2,9 +2,9 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class OptionTypeSerializer < BaseSerializer
5
- typelize name: :string, presentation: :string, position: :number
5
+ typelize name: :string, label: :string, position: :number
6
6
 
7
- attributes :name, :presentation, :position
7
+ attributes :name, :label, :position
8
8
  end
9
9
  end
10
10
  end
@@ -2,21 +2,21 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class OptionValueSerializer < BaseSerializer
5
- typelize name: :string, presentation: :string, position: :number, option_type_id: :string,
6
- option_type_name: :string, option_type_presentation: :string
5
+ typelize name: :string, label: :string, position: :number, option_type_id: :string,
6
+ option_type_name: :string, option_type_label: :string
7
7
 
8
8
  attribute :option_type_id do |option_value|
9
9
  option_value.option_type&.prefixed_id
10
10
  end
11
11
 
12
- attributes :name, :presentation, :position
12
+ attributes :name, :label, :position
13
13
 
14
14
  attribute :option_type_name do |option_value|
15
15
  option_value.option_type.name
16
16
  end
17
17
 
18
- attribute :option_type_presentation do |option_value|
19
- option_value.option_type.presentation
18
+ attribute :option_type_label do |option_value|
19
+ option_value.option_type.label
20
20
  end
21
21
  end
22
22
  end
@@ -5,48 +5,34 @@ module Spree
5
5
  # Post-purchase order data (completed orders)
6
6
  class OrderSerializer < BaseSerializer
7
7
  typelize number: :string, email: :string,
8
- special_instructions: [:string, nullable: true], currency: :string, locale: [:string, nullable: true], item_count: :number,
8
+ customer_note: [:string, nullable: true], currency: :string, locale: [:string, nullable: true], total_quantity: :number,
9
9
  fulfillment_status: [:string, nullable: true], payment_status: [:string, nullable: true],
10
10
  item_total: :string, display_item_total: :string,
11
11
  delivery_total: :string, display_delivery_total: :string,
12
12
  adjustment_total: :string, display_adjustment_total: :string,
13
- promo_total: :string, display_promo_total: :string,
13
+ discount_total: :string, display_discount_total: :string,
14
14
  tax_total: :string, display_tax_total: :string,
15
15
  included_tax_total: :string, display_included_tax_total: :string,
16
16
  additional_tax_total: :string, display_additional_tax_total: :string,
17
17
  total: :string, display_total: :string, completed_at: [:string, nullable: true],
18
- bill_address: { nullable: true }, ship_address: { nullable: true }
18
+ billing_address: { nullable: true }, shipping_address: { nullable: true }
19
19
 
20
- attributes :number, :email, :special_instructions,
21
- :currency, :locale, :item_count,
20
+ attributes :number, :email, :customer_note,
21
+ :currency, :locale, :total_quantity,
22
22
  :item_total, :display_item_total,
23
- :adjustment_total, :display_adjustment_total, :promo_total, :display_promo_total,
23
+ :adjustment_total, :display_adjustment_total,
24
+ :discount_total, :display_discount_total,
24
25
  :tax_total, :display_tax_total, :included_tax_total, :display_included_tax_total,
25
26
  :additional_tax_total, :display_additional_tax_total, :total, :display_total,
27
+ :delivery_total, :display_delivery_total, :fulfillment_status, :payment_status,
26
28
  completed_at: :iso8601, created_at: :iso8601, updated_at: :iso8601
27
29
 
28
- attribute :fulfillment_status do |order|
29
- order.shipment_state
30
- end
31
-
32
- attribute :payment_status do |order|
33
- order.payment_state
34
- end
35
-
36
- attribute :delivery_total do |order|
37
- order.ship_total
38
- end
39
-
40
- attribute :display_delivery_total do |order|
41
- order.display_ship_total.to_s
42
- end
43
-
44
- many :order_promotions, key: :promotions, resource: Spree.api.order_promotion_serializer
30
+ many :discounts, resource: Spree.api.discount_serializer
45
31
  many :line_items, key: :items, resource: Spree.api.line_item_serializer
46
- many :shipments, key: :fulfillments, resource: Spree.api.fulfillment_serializer
32
+ many :fulfillments, resource: Spree.api.fulfillment_serializer
47
33
  many :payments, resource: Spree.api.payment_serializer
48
- one :bill_address, resource: Spree.api.address_serializer
49
- one :ship_address, resource: Spree.api.address_serializer
34
+ one :billing_address, resource: Spree.api.address_serializer
35
+ one :shipping_address, resource: Spree.api.address_serializer
50
36
  end
51
37
  end
52
38
  end
@@ -4,9 +4,7 @@ module Spree
4
4
  class PaymentSourceSerializer < BaseSerializer
5
5
  typelize gateway_payment_profile_id: [:string, nullable: true]
6
6
 
7
- attribute :gateway_payment_profile_id do |source|
8
- source.try(:gateway_payment_profile_id)
9
- end
7
+ attributes :gateway_payment_profile_id
10
8
  end
11
9
  end
12
10
  end
@@ -3,25 +3,13 @@
3
3
  module Spree
4
4
  module Api
5
5
  module V3
6
+ # Store API Promotion Serializer
7
+ # Minimal public-facing promotion info. Full details in Admin serializer.
6
8
  class PromotionSerializer < BaseSerializer
7
9
  typelize name: :string, description: [:string, nullable: true],
8
- code: [:string, nullable: true], type: [:string, nullable: true],
9
- kind: [:string, nullable: true], path: [:string, nullable: true],
10
- match_policy: [:string, nullable: true], usage_limit: [:number, nullable: true],
11
- advertise: :boolean, multi_codes: :boolean,
12
- code_prefix: [:string, nullable: true], number_of_codes: [:number, nullable: true],
13
- starts_at: [:string, nullable: true], expires_at: [:string, nullable: true],
14
- promotion_category_id: [:string, nullable: true]
10
+ code: [:string, nullable: true]
15
11
 
16
- attributes :name, :description, :code, :type, :kind, :path,
17
- :match_policy, :usage_limit, :advertise, :multi_codes,
18
- :code_prefix, :number_of_codes,
19
- starts_at: :iso8601, expires_at: :iso8601,
20
- created_at: :iso8601, updated_at: :iso8601
21
-
22
- attribute :promotion_category_id do |promotion|
23
- promotion.promotion_category&.prefixed_id
24
- end
12
+ attributes :name, :description, :code
25
13
  end
26
14
  end
27
15
  end
@@ -4,13 +4,13 @@ module Spree
4
4
  module Api
5
5
  module V3
6
6
  class ReturnAuthorizationSerializer < BaseSerializer
7
- typelize number: :string, state: :string,
7
+ typelize number: :string, status: :string,
8
8
  order_id: [:string, nullable: true], stock_location_id: [:string, nullable: true],
9
9
  return_authorization_reason_id: [:string, nullable: true]
10
10
 
11
11
  attributes :number, created_at: :iso8601, updated_at: :iso8601
12
12
 
13
- attribute :state do |return_authorization|
13
+ attribute :status do |return_authorization|
14
14
  return_authorization.state.to_s
15
15
  end
16
16
 
@@ -1,7 +1,7 @@
1
1
  module Spree
2
2
  module Api
3
3
  module V3
4
- class WishedItemSerializer < BaseSerializer
4
+ class WishlistItemSerializer < BaseSerializer
5
5
  typelize variant_id: :string, wishlist_id: :string, quantity: :number
6
6
 
7
7
  attribute :variant_id do |wished_item|
@@ -17,7 +17,7 @@ module Spree
17
17
 
18
18
  many :wished_items,
19
19
  key: :items,
20
- resource: Spree.api.wished_item_serializer,
20
+ resource: Spree.api.wishlist_item_serializer,
21
21
  if: proc { expand?('items') }
22
22
  end
23
23
  end
@@ -85,7 +85,7 @@ module Spree
85
85
  id: option_type.prefixed_id,
86
86
  type: 'option',
87
87
  name: option_type.name,
88
- presentation: option_type.presentation,
88
+ label: option_type.label,
89
89
  options: values.map { |ov| option_value_data(option_type, ov) }
90
90
  }
91
91
  end
@@ -105,7 +105,7 @@ module Spree
105
105
  {
106
106
  id: option_value.prefixed_id,
107
107
  name: option_value.name,
108
- presentation: option_value.presentation,
108
+ label: option_value.label,
109
109
  position: option_value.position,
110
110
  count: count
111
111
  }
@@ -10,10 +10,22 @@ Rails.application.config.after_initialize do
10
10
  config.comments = true
11
11
  config.listen = false
12
12
 
13
+ # Serializers that exist only for Admin API or events — no Store API controller
14
+ store_excluded = %w[
15
+ Asset CartPromotion OrderPromotion
16
+ StockItem StockMovement StockTransfer ShippingCategory
17
+ Reimbursement Report Export Import ImportRow
18
+ TaxCategory CustomerReturn
19
+ ].to_set
20
+
13
21
  # Store SDK — no prefix, package provides namespace
14
22
  config.writer(:store) do |c|
15
23
  c.output_dir = api_root.join('../../packages/sdk/src/types/generated')
16
- c.reject_class = ->(serializer:) { serializer.name.to_s.include?('::Admin::') }
24
+ c.reject_class = ->(serializer:) {
25
+ name = serializer.name.to_s
26
+ name.include?('::Admin::') ||
27
+ store_excluded.include?(name.sub(/\ASpree::Api::V3::/, '').sub(/Serializer\z/, ''))
28
+ }
17
29
  c.serializer_name_mapper = ->(serializer) {
18
30
  serializer.name.to_s
19
31
  .sub(/\ASpree::Api::V3::/, '')
@@ -115,7 +115,8 @@ module Spree
115
115
  market_serializer: 'Spree::Api::V3::MarketSerializer',
116
116
  state_serializer: 'Spree::Api::V3::StateSerializer',
117
117
  wishlist_serializer: 'Spree::Api::V3::WishlistSerializer',
118
- wished_item_serializer: 'Spree::Api::V3::WishedItemSerializer',
118
+ wishlist_item_serializer: 'Spree::Api::V3::WishlistItemSerializer',
119
+ wished_item_serializer: 'Spree::Api::V3::WishlistItemSerializer',
119
120
  payment_method_serializer: 'Spree::Api::V3::PaymentMethodSerializer',
120
121
  shipping_method_serializer: 'Spree::Api::V3::DeliveryMethodSerializer',
121
122
  shipping_rate_serializer: 'Spree::Api::V3::DeliveryRateSerializer',
@@ -123,8 +124,7 @@ module Spree
123
124
  delivery_rate_serializer: 'Spree::Api::V3::DeliveryRateSerializer',
124
125
  stock_location_serializer: 'Spree::Api::V3::StockLocationSerializer',
125
126
  category_serializer: 'Spree::Api::V3::CategorySerializer',
126
- cart_promotion_serializer: 'Spree::Api::V3::CartPromotionSerializer',
127
- order_promotion_serializer: 'Spree::Api::V3::OrderPromotionSerializer',
127
+ discount_serializer: 'Spree::Api::V3::DiscountSerializer',
128
128
  digital_link_serializer: 'Spree::Api::V3::DigitalLinkSerializer',
129
129
  gift_card_serializer: 'Spree::Api::V3::GiftCardSerializer',
130
130
  currency_serializer: 'Spree::Api::V3::CurrencySerializer',
@@ -154,6 +154,7 @@ module Spree
154
154
  stock_transfer_serializer: 'Spree::Api::V3::StockTransferSerializer',
155
155
 
156
156
  # v3 admin serializers (API v3 Admin)
157
+ admin_discount_serializer: 'Spree::Api::V3::Admin::DiscountSerializer',
157
158
  admin_customer_serializer: 'Spree::Api::V3::Admin::CustomerSerializer',
158
159
  admin_order_serializer: 'Spree::Api::V3::Admin::OrderSerializer',
159
160
  admin_product_serializer: 'Spree::Api::V3::Admin::ProductSerializer',
@@ -183,7 +184,6 @@ module Spree
183
184
  admin_stock_location_serializer: 'Spree::Api::V3::Admin::StockLocationSerializer',
184
185
  admin_shipping_rate_serializer: 'Spree::Api::V3::Admin::DeliveryRateSerializer',
185
186
  admin_delivery_rate_serializer: 'Spree::Api::V3::Admin::DeliveryRateSerializer',
186
- admin_order_promotion_serializer: 'Spree::Api::V3::Admin::OrderPromotionSerializer',
187
187
  admin_payment_method_serializer: 'Spree::Api::V3::Admin::PaymentMethodSerializer',
188
188
  admin_credit_card_serializer: 'Spree::Api::V3::Admin::CreditCardSerializer',
189
189
  admin_store_credit_serializer: 'Spree::Api::V3::Admin::StoreCreditSerializer',
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spree_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.4.0.beta9
4
+ version: 5.4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vendo Connect Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-17 00:00:00.000000000 Z
11
+ date: 2026-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rswag-specs
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 5.4.0.beta9
89
+ version: 5.4.0.rc1
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 5.4.0.beta9
96
+ version: 5.4.0.rc1
97
97
  description: Spree's API
98
98
  email:
99
99
  - hello@spreecommerce.org
@@ -114,6 +114,7 @@ files:
114
114
  - app/controllers/concerns/spree/api/v3/rate_limit_headers.rb
115
115
  - app/controllers/concerns/spree/api/v3/resource_serializer.rb
116
116
  - app/controllers/concerns/spree/api/v3/security_headers.rb
117
+ - app/controllers/concerns/spree/api/v3/store/search_provider_support.rb
117
118
  - app/controllers/spree/api/v3/admin/base_controller.rb
118
119
  - app/controllers/spree/api/v3/admin/resource_controller.rb
119
120
  - app/controllers/spree/api/v3/base_controller.rb
@@ -164,13 +165,13 @@ files:
164
165
  - app/serializers/spree/api/v3/admin/delivery_method_serializer.rb
165
166
  - app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb
166
167
  - app/serializers/spree/api/v3/admin/digital_link_serializer.rb
168
+ - app/serializers/spree/api/v3/admin/discount_serializer.rb
167
169
  - app/serializers/spree/api/v3/admin/fulfillment_serializer.rb
168
170
  - app/serializers/spree/api/v3/admin/line_item_serializer.rb
169
171
  - app/serializers/spree/api/v3/admin/media_serializer.rb
170
172
  - app/serializers/spree/api/v3/admin/metafield_serializer.rb
171
173
  - app/serializers/spree/api/v3/admin/option_type_serializer.rb
172
174
  - app/serializers/spree/api/v3/admin/option_value_serializer.rb
173
- - app/serializers/spree/api/v3/admin/order_promotion_serializer.rb
174
175
  - app/serializers/spree/api/v3/admin/order_serializer.rb
175
176
  - app/serializers/spree/api/v3/admin/payment_method_serializer.rb
176
177
  - app/serializers/spree/api/v3/admin/payment_serializer.rb
@@ -188,7 +189,6 @@ files:
188
189
  - app/serializers/spree/api/v3/admin/variant_serializer.rb
189
190
  - app/serializers/spree/api/v3/asset_serializer.rb
190
191
  - app/serializers/spree/api/v3/base_serializer.rb
191
- - app/serializers/spree/api/v3/cart_promotion_serializer.rb
192
192
  - app/serializers/spree/api/v3/cart_serializer.rb
193
193
  - app/serializers/spree/api/v3/category_serializer.rb
194
194
  - app/serializers/spree/api/v3/country_serializer.rb
@@ -200,6 +200,7 @@ files:
200
200
  - app/serializers/spree/api/v3/delivery_rate_serializer.rb
201
201
  - app/serializers/spree/api/v3/digital_link_serializer.rb
202
202
  - app/serializers/spree/api/v3/digital_serializer.rb
203
+ - app/serializers/spree/api/v3/discount_serializer.rb
203
204
  - app/serializers/spree/api/v3/export_serializer.rb
204
205
  - app/serializers/spree/api/v3/fulfillment_serializer.rb
205
206
  - app/serializers/spree/api/v3/gift_card_batch_serializer.rb
@@ -215,7 +216,6 @@ files:
215
216
  - app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb
216
217
  - app/serializers/spree/api/v3/option_type_serializer.rb
217
218
  - app/serializers/spree/api/v3/option_value_serializer.rb
218
- - app/serializers/spree/api/v3/order_promotion_serializer.rb
219
219
  - app/serializers/spree/api/v3/order_serializer.rb
220
220
  - app/serializers/spree/api/v3/payment_method_serializer.rb
221
221
  - app/serializers/spree/api/v3/payment_serializer.rb
@@ -239,7 +239,7 @@ files:
239
239
  - app/serializers/spree/api/v3/store_credit_serializer.rb
240
240
  - app/serializers/spree/api/v3/tax_category_serializer.rb
241
241
  - app/serializers/spree/api/v3/variant_serializer.rb
242
- - app/serializers/spree/api/v3/wished_item_serializer.rb
242
+ - app/serializers/spree/api/v3/wishlist_item_serializer.rb
243
243
  - app/serializers/spree/api/v3/wishlist_serializer.rb
244
244
  - app/services/spree/api/v3/filters_aggregator.rb
245
245
  - app/services/spree/webhooks/deliver_webhook.rb
@@ -268,9 +268,9 @@ licenses:
268
268
  - BSD-3-Clause
269
269
  metadata:
270
270
  bug_tracker_uri: https://github.com/spree/spree/issues
271
- changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.beta9
271
+ changelog_uri: https://github.com/spree/spree/releases/tag/v5.4.0.rc1
272
272
  documentation_uri: https://docs.spreecommerce.org/
273
- source_code_uri: https://github.com/spree/spree/tree/v5.4.0.beta9
273
+ source_code_uri: https://github.com/spree/spree/tree/v5.4.0.rc1
274
274
  post_install_message:
275
275
  rdoc_options: []
276
276
  require_paths:
@@ -1,16 +0,0 @@
1
- module Spree
2
- module Api
3
- module V3
4
- class OrderPromotionSerializer < BaseSerializer
5
- typelize name: :string, description: [:string, nullable: true], code: [:string, nullable: true],
6
- amount: :string, display_amount: :string, promotion_id: :string
7
-
8
- attribute :promotion_id do |order_promotion|
9
- order_promotion.promotion&.prefixed_id
10
- end
11
-
12
- attributes :name, :description, :code, :amount, :display_amount
13
- end
14
- end
15
- end
16
- end