spree_api 5.4.0.beta4 → 5.4.0.beta5

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -4
  3. data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +1 -1
  4. data/app/controllers/concerns/spree/api/v3/error_handler.rb +12 -2
  5. data/app/controllers/concerns/spree/api/v3/http_caching.rb +10 -2
  6. data/app/controllers/concerns/spree/api/v3/idempotent.rb +82 -0
  7. data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +4 -1
  8. data/app/controllers/concerns/spree/api/v3/order_concern.rb +1 -6
  9. data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +31 -0
  10. data/app/controllers/concerns/spree/api/v3/resource_serializer.rb +30 -2
  11. data/app/controllers/concerns/spree/api/v3/security_headers.rb +4 -0
  12. data/app/controllers/spree/api/v3/admin/base_controller.rb +28 -0
  13. data/app/controllers/spree/api/v3/admin/resource_controller.rb +28 -0
  14. data/app/controllers/spree/api/v3/base_controller.rb +20 -1
  15. data/app/controllers/spree/api/v3/resource_controller.rb +35 -3
  16. data/app/controllers/spree/api/v3/store/auth_controller.rb +4 -24
  17. data/app/controllers/spree/api/v3/store/base_controller.rb +0 -11
  18. data/app/controllers/spree/api/v3/store/cart_controller.rb +6 -2
  19. data/app/controllers/spree/api/v3/store/categories/products_controller.rb +37 -0
  20. data/app/controllers/spree/api/v3/store/{taxons_controller.rb → categories_controller.rb} +8 -6
  21. data/app/controllers/spree/api/v3/store/countries_controller.rb +6 -0
  22. data/app/controllers/spree/api/v3/store/currencies_controller.rb +4 -0
  23. data/app/controllers/spree/api/v3/store/customers_controller.rb +102 -0
  24. data/app/controllers/spree/api/v3/store/locales_controller.rb +4 -0
  25. data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +6 -0
  26. data/app/controllers/spree/api/v3/store/markets_controller.rb +8 -0
  27. data/app/controllers/spree/api/v3/store/orders_controller.rb +3 -2
  28. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +9 -8
  29. data/app/controllers/spree/api/v3/store/products_controller.rb +12 -19
  30. data/app/jobs/spree/webhook_delivery_job.rb +4 -1
  31. data/app/serializers/spree/api/v3/admin/address_serializer.rb +24 -0
  32. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +36 -0
  33. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +15 -0
  34. data/app/serializers/spree/api/v3/admin/asset_serializer.rb +10 -0
  35. data/app/serializers/spree/api/v3/admin/category_serializer.rb +33 -0
  36. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +22 -0
  37. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +8 -6
  38. data/app/serializers/spree/api/v3/admin/digital_link_serializer.rb +10 -0
  39. data/app/serializers/spree/api/v3/admin/image_serializer.rb +10 -0
  40. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +36 -1
  41. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +13 -0
  42. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +13 -0
  43. data/app/serializers/spree/api/v3/admin/order_promotion_serializer.rb +10 -0
  44. data/app/serializers/spree/api/v3/admin/order_serializer.rb +47 -6
  45. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +14 -0
  46. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +56 -0
  47. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +10 -0
  48. data/app/serializers/spree/api/v3/admin/product_serializer.rb +23 -6
  49. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +21 -0
  50. data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +13 -0
  51. data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +17 -0
  52. data/app/serializers/spree/api/v3/admin/shipment_serializer.rb +44 -0
  53. data/app/serializers/spree/api/v3/admin/shipping_category_serializer.rb +14 -0
  54. data/app/serializers/spree/api/v3/admin/shipping_method_serializer.rb +11 -0
  55. data/app/serializers/spree/api/v3/admin/shipping_rate_serializer.rb +11 -0
  56. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +17 -0
  57. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +15 -0
  58. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +27 -0
  59. data/app/serializers/spree/api/v3/admin/tax_category_serializer.rb +15 -0
  60. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +11 -14
  61. data/app/serializers/spree/api/v3/base_serializer.rb +21 -4
  62. data/app/serializers/spree/api/v3/category_serializer.rb +71 -0
  63. data/app/serializers/spree/api/v3/country_serializer.rb +2 -1
  64. data/app/serializers/spree/api/v3/customer_serializer.rb +2 -1
  65. data/app/serializers/spree/api/v3/gift_card_serializer.rb +5 -21
  66. data/app/serializers/spree/api/v3/order_serializer.rb +2 -2
  67. data/app/serializers/spree/api/v3/payment_serializer.rb +1 -1
  68. data/app/serializers/spree/api/v3/product_serializer.rb +11 -11
  69. data/app/serializers/spree/api/v3/shipping_category_serializer.rb +11 -0
  70. data/app/serializers/spree/api/v3/shipping_rate_serializer.rb +2 -6
  71. data/app/serializers/spree/api/v3/tax_category_serializer.rb +11 -0
  72. data/app/serializers/spree/api/v3/variant_serializer.rb +4 -4
  73. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  74. data/app/services/spree/api/v3/filters_aggregator.rb +31 -25
  75. data/app/services/spree/webhooks/deliver_webhook.rb +23 -17
  76. data/app/subscribers/spree/webhook_event_subscriber.rb +1 -1
  77. data/config/initializers/alba.rb +1 -1
  78. data/config/initializers/typelizer.rb +26 -16
  79. data/config/locales/en.yml +1 -0
  80. data/config/routes.rb +9 -9
  81. data/lib/spree/api/configuration.rb +3 -1
  82. data/lib/spree/api/dependencies.rb +28 -5
  83. data/lib/spree/api/engine.rb +15 -0
  84. data/lib/spree/api/openapi/schema_helper.rb +27 -7
  85. data/lib/spree/api/testing_support/v3/base.rb +24 -1
  86. metadata +43 -19
  87. data/app/controllers/spree/api/v3/store/customer/account_controller.rb +0 -38
  88. data/app/controllers/spree/api/v3/store/stores_controller.rb +0 -26
  89. data/app/controllers/spree/api/v3/store/taxonomies_controller.rb +0 -19
  90. data/app/controllers/spree/api/v3/store/taxons/products_controller.rb +0 -37
  91. data/app/serializers/spree/api/v3/admin/taxon_serializer.rb +0 -20
  92. data/app/serializers/spree/api/v3/admin/taxonomy_serializer.rb +0 -15
  93. data/app/serializers/spree/api/v3/store_serializer.rb +0 -38
  94. data/app/serializers/spree/api/v3/taxon_serializer.rb +0 -78
  95. data/app/serializers/spree/api/v3/taxonomy_serializer.rb +0 -33
  96. data/app/services/spree/api/v3/orders/update.rb +0 -105
@@ -0,0 +1,102 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Store
5
+ class CustomersController < Store::BaseController
6
+ rate_limit to: Spree::Api::Config[:rate_limit_register], within: Spree::Api::Config[:rate_limit_window].seconds, store: Rails.cache, only: :create, with: RATE_LIMIT_RESPONSE
7
+
8
+ skip_before_action :authenticate_user, only: [:create]
9
+ prepend_before_action :require_authentication!, only: [:show, :update]
10
+
11
+ # POST /api/v3/store/customers
12
+ def create
13
+ user = Spree.user_class.new(create_params)
14
+
15
+ if user.save
16
+ token = generate_jwt(user)
17
+ render json: {
18
+ token: token,
19
+ user: user_serializer.new(user, params: serializer_params).to_h
20
+ }, status: :created
21
+ else
22
+ render_errors(user.errors)
23
+ end
24
+ end
25
+
26
+ # GET /api/v3/store/customer
27
+ def show
28
+ render json: serialize_resource(current_user)
29
+ end
30
+
31
+ # PATCH /api/v3/store/customer
32
+ def update
33
+ if sensitive_update? && !valid_current_password?
34
+ return render_error(
35
+ code: ErrorHandler::ERROR_CODES[:current_password_invalid],
36
+ message: Spree.t(:current_password_invalid, scope: :api),
37
+ status: :unprocessable_content
38
+ )
39
+ end
40
+
41
+ update_params = permitted_params.except(:current_password)
42
+
43
+ if current_user.update(update_params)
44
+ render json: serialize_resource(current_user)
45
+ else
46
+ render_errors(current_user.errors)
47
+ end
48
+ end
49
+
50
+ protected
51
+
52
+ def serializer_class
53
+ Spree.api.customer_serializer
54
+ end
55
+
56
+ def serializer_params
57
+ {
58
+ store: current_store,
59
+ locale: current_locale,
60
+ currency: current_currency,
61
+ user: current_user,
62
+ includes: []
63
+ }
64
+ end
65
+
66
+ def create_params
67
+ params.permit(:email, :password, :password_confirmation, :first_name, :last_name,
68
+ :phone, :accepts_email_marketing, metadata: {})
69
+ end
70
+
71
+ def permitted_params
72
+ params.permit(:email, :password, :password_confirmation, :first_name, :last_name,
73
+ :accepts_email_marketing, :phone, :current_password, metadata: {})
74
+ end
75
+
76
+ private
77
+
78
+ def sensitive_update?
79
+ (params[:email].present? && params[:email] != current_user.email) ||
80
+ params[:password].present?
81
+ end
82
+
83
+ def valid_current_password?
84
+ return false if params[:current_password].blank?
85
+
86
+ if current_user.respond_to?(:valid_password?)
87
+ current_user.valid_password?(params[:current_password])
88
+ elsif current_user.respond_to?(:authenticate)
89
+ current_user.authenticate(params[:current_password]).present?
90
+ else
91
+ false
92
+ end
93
+ end
94
+
95
+ def user_serializer
96
+ Spree.api.customer_serializer
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -3,10 +3,14 @@ module Spree
3
3
  module V3
4
4
  module Store
5
5
  class LocalesController < Store::BaseController
6
+ include Spree::Api::V3::HttpCaching
7
+
6
8
  # GET /api/v3/store/locales
7
9
  def index
8
10
  locales = current_store.supported_locales_list
9
11
 
12
+ return unless cache_collection(locales)
13
+
10
14
  render json: {
11
15
  data: locales.map { |code| Spree.api.locale_serializer.new(OpenStruct.new(code: code, name: locale_name(code))).to_h }
12
16
  }
@@ -4,12 +4,16 @@ module Spree
4
4
  module Store
5
5
  module Markets
6
6
  class CountriesController < Store::BaseController
7
+ include Spree::Api::V3::HttpCaching
8
+
7
9
  before_action :load_market
8
10
 
9
11
  # GET /api/v3/store/markets/:market_id/countries
10
12
  def index
11
13
  countries = @market.countries.order(:name)
12
14
 
15
+ return unless cache_collection(countries)
16
+
13
17
  render json: {
14
18
  data: countries.map { |country| serialize_country(country) }
15
19
  }
@@ -19,6 +23,8 @@ module Spree
19
23
  def show
20
24
  country = @market.countries.find_by!(iso: params[:id].upcase)
21
25
 
26
+ return unless cache_resource(country)
27
+
22
28
  render json: serialize_country(country)
23
29
  end
24
30
 
@@ -3,10 +3,14 @@ module Spree
3
3
  module V3
4
4
  module Store
5
5
  class MarketsController < Store::BaseController
6
+ include Spree::Api::V3::HttpCaching
7
+
6
8
  # GET /api/v3/store/markets
7
9
  def index
8
10
  markets = current_store.markets.includes(:countries).order(:position)
9
11
 
12
+ return unless cache_collection(markets)
13
+
10
14
  render json: {
11
15
  data: markets.map { |market| serialize_market(market) }
12
16
  }
@@ -16,6 +20,8 @@ module Spree
16
20
  def show
17
21
  market = current_store.markets.includes(:countries).find_by_prefix_id!(params[:id])
18
22
 
23
+ return unless cache_resource(market)
24
+
19
25
  render json: serialize_market(market)
20
26
  end
21
27
 
@@ -27,6 +33,8 @@ module Spree
27
33
 
28
34
  raise ActiveRecord::RecordNotFound unless market
29
35
 
36
+ return unless cache_resource(market)
37
+
30
38
  render json: serialize_market(market)
31
39
  end
32
40
 
@@ -22,7 +22,7 @@ module Spree
22
22
  #
23
23
  def update
24
24
  with_order_lock do
25
- result = Spree::Api::V3::Orders::Update.call(
25
+ result = Spree.order_update_service.call(
26
26
  order: @order,
27
27
  params: order_params
28
28
  )
@@ -118,7 +118,8 @@ module Spree
118
118
  :bill_address_id,
119
119
  ship_address: address_params,
120
120
  bill_address: address_params,
121
- metadata: {}
121
+ metadata: {},
122
+ line_items: [:variant_id, :quantity, { metadata: {}, options: {} }]
122
123
  )
123
124
  end
124
125
 
@@ -8,27 +8,28 @@ module Spree
8
8
  aggregator = Spree::Api::V3::FiltersAggregator.new(
9
9
  scope: filters_scope,
10
10
  currency: current_currency,
11
- taxon: taxon
11
+ category: category
12
12
  )
13
13
  render json: aggregator.call
14
14
  end
15
15
 
16
16
  private
17
17
 
18
- # Build scope from taxon and/or ransack params
18
+ # Build scope from category and/or ransack params
19
19
  # @return [ActiveRecord::Relation]
20
20
  def filters_scope
21
21
  scope = current_store.products.active(current_currency)
22
- scope = scope.in_taxon(taxon) if taxon.present?
22
+ scope = scope.in_category(category) if category.present?
23
23
  scope = scope.ransack(params[:q]).result if params[:q].present?
24
24
  scope.accessible_by(current_ability, :show)
25
25
  end
26
26
 
27
- # Fetches taxon from params
28
- # @param [String] taxon_id
29
- # @return [Spree::Taxon]
30
- def taxon
31
- @taxon ||= params[:taxon_id].present? ? current_store.taxons.find_by_param(params[:taxon_id]) : nil
27
+ # Fetches category from params
28
+ # @param [String] category_id
29
+ # @return [Spree::Category]
30
+ def category
31
+ category_id = params[:category_id]
32
+ @category ||= category_id.present? ? current_store.categories.find_by_param(category_id) : nil
32
33
  end
33
34
  end
34
35
  end
@@ -3,10 +3,12 @@ module Spree
3
3
  module V3
4
4
  module Store
5
5
  class ProductsController < ResourceController
6
+ include Spree::Api::V3::HttpCaching
7
+
6
8
  # Sort values that require special scopes (not plain Ransack column sorts).
7
9
  CUSTOM_SORT_SCOPES = {
8
- 'price asc' => :ascend_by_price,
9
- 'price desc' => :descend_by_price,
10
+ 'price' => :ascend_by_price,
11
+ '-price' => :descend_by_price,
10
12
  'best_selling' => :by_best_selling
11
13
  }.freeze
12
14
 
@@ -45,14 +47,9 @@ module Spree
45
47
  ]
46
48
  end
47
49
 
48
- # Disable distinct when using custom sort scopes that add computed columns
49
- def collection_distinct?
50
- !custom_sort_requested?
51
- end
52
-
53
50
  # Applies sorting from the unified `sort` param.
54
- # Custom values ('price asc', 'best_selling') use product-specific scopes.
55
- # Standard Ransack values ('name asc', 'created_at desc') are passed to q[s].
51
+ # Custom values ('price', '-price', 'best_selling') use product-specific scopes.
52
+ # Standard Ransack values ('name', '-created_at') are handled by base ResourceController.
56
53
  def apply_collection_sort(collection)
57
54
  sort_value = sort_param
58
55
  return collection unless sort_value.present?
@@ -61,17 +58,17 @@ module Spree
61
58
  return collection unless scope_method
62
59
 
63
60
  sorted = collection.reorder(nil)
64
- sort_value == 'best_selling' ? sorted.distinct(false).send(scope_method) : sorted.send(scope_method)
61
+ sorted.send(scope_method)
65
62
  end
66
63
 
67
- # Inject sort into ransack params when it's a standard Ransack sort
64
+ # Skip base Ransack sort injection for custom sort scopes
68
65
  def ransack_params
69
66
  rp = super
70
- sort_value = sort_param
71
67
 
72
- if sort_value.present? && !CUSTOM_SORT_SCOPES.key?(sort_value)
73
- rp = rp.respond_to?(:to_unsafe_h) ? rp.to_unsafe_h : rp.dup
74
- rp['s'] = sort_value
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')
75
72
  end
76
73
 
77
74
  rp
@@ -79,10 +76,6 @@ module Spree
79
76
 
80
77
  private
81
78
 
82
- def sort_param
83
- params[:sort] || params.dig(:q, :s)
84
- end
85
-
86
79
  def custom_sort_requested?
87
80
  CUSTOM_SORT_SCOPES.key?(sort_param)
88
81
  end
@@ -6,10 +6,13 @@ module Spree
6
6
 
7
7
  retry_on StandardError, wait: :polynomially_longer, attempts: 5
8
8
 
9
- def perform(delivery_id, secret_key)
9
+ # Accept optional second argument for backward compatibility with jobs
10
+ # enqueued before this change was deployed.
11
+ def perform(delivery_id, _deprecated_secret_key = nil)
10
12
  delivery = Spree::WebhookDelivery.find_by(id: delivery_id)
11
13
  return if delivery.nil?
12
14
 
15
+ secret_key = delivery.webhook_endpoint.secret_key
13
16
  Spree::Webhooks::DeliverWebhook.call(delivery: delivery, secret_key: secret_key)
14
17
  end
15
18
  end
@@ -0,0 +1,24 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class AddressSerializer < V3::AddressSerializer
6
+ typelize label: [:string, nullable: true],
7
+ user_id: [:string, nullable: true],
8
+ metadata: 'Record<string, unknown> | null'
9
+
10
+ attributes :label,
11
+ created_at: :iso8601, updated_at: :iso8601
12
+
13
+ attribute :user_id do |address|
14
+ address.user&.prefixed_id
15
+ end
16
+
17
+ attribute :metadata do |address|
18
+ address.metadata.presence
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,36 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class AdjustmentSerializer < V3::BaseSerializer
6
+ typelize label: :string, amount: :string, display_amount: :string,
7
+ state: :string, eligible: :boolean, mandatory: :boolean, included: :boolean,
8
+ source_type: [:string, nullable: true],
9
+ adjustable_type: :string, adjustable_id: :string,
10
+ order_id: [:string, nullable: true],
11
+ source_id: [:string, nullable: true]
12
+
13
+ attributes :label, :display_amount, :state, :eligible, :mandatory, :included,
14
+ :source_type, :adjustable_type,
15
+ created_at: :iso8601, updated_at: :iso8601
16
+
17
+ attribute :amount do |adjustment|
18
+ adjustment.amount.to_s
19
+ end
20
+
21
+ attribute :adjustable_id do |adjustment|
22
+ adjustment.adjustable&.prefixed_id
23
+ end
24
+
25
+ attribute :order_id do |adjustment|
26
+ adjustment.order&.prefixed_id
27
+ end
28
+
29
+ attribute :source_id do |adjustment|
30
+ adjustment.source&.prefixed_id
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class AdminUserSerializer < V3::BaseSerializer
6
+ typelize email: :string, first_name: [:string, nullable: true],
7
+ last_name: [:string, nullable: true]
8
+
9
+ attributes :email, :first_name, :last_name,
10
+ created_at: :iso8601, updated_at: :iso8601
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class AssetSerializer < V3::AssetSerializer
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Admin API Category Serializer
6
+ # Full category data including admin-only fields
7
+ class CategorySerializer < V3::CategorySerializer
8
+ typelize lft: :number, rgt: :number
9
+
10
+ # Nested set columns for tree operations
11
+ attributes :lft, :rgt
12
+
13
+ # Override inherited associations to use admin serializers
14
+ one :parent,
15
+ resource: Spree.api.admin_category_serializer,
16
+ if: proc { expand?('parent') }
17
+
18
+ many :children,
19
+ resource: Spree.api.admin_category_serializer,
20
+ if: proc { expand?('children') }
21
+
22
+ many :ancestors,
23
+ resource: Spree.api.admin_category_serializer,
24
+ if: proc { expand?('ancestors') }
25
+
26
+ many :metafields,
27
+ resource: Spree.api.admin_metafield_serializer,
28
+ if: proc { expand?('metafields') }
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class CreditCardSerializer < V3::CreditCardSerializer
6
+ typelize user_id: [:string, nullable: true],
7
+ payment_method_id: [:string, nullable: true]
8
+
9
+ attribute :user_id do |credit_card|
10
+ credit_card.user&.prefixed_id
11
+ end
12
+
13
+ attribute :payment_method_id do |credit_card|
14
+ credit_card.payment_method&.prefixed_id
15
+ end
16
+
17
+ attributes created_at: :iso8601, updated_at: :iso8601
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,14 +5,13 @@ module Spree
5
5
  # Admin API Customer Serializer
6
6
  # Full customer data including admin-only fields
7
7
  class CustomerSerializer < V3::CustomerSerializer
8
- typelize phone: [:string, nullable: true], login: [:string, nullable: true],
9
- accepts_email_marketing: :boolean,
8
+ typelize login: [:string, nullable: true],
10
9
  last_sign_in_at: [:string, nullable: true], current_sign_in_at: [:string, nullable: true],
11
10
  sign_in_count: :number, failed_attempts: :number,
12
11
  last_sign_in_ip: [:string, nullable: true], current_sign_in_ip: [:string, nullable: true]
13
12
 
14
13
  # Admin-only attributes
15
- attributes :phone, :login, :accepts_email_marketing,
14
+ attributes :login,
16
15
  last_sign_in_at: :iso8601, current_sign_in_at: :iso8601
17
16
 
18
17
  attribute :sign_in_count do |user|
@@ -31,11 +30,14 @@ module Spree
31
30
  user.current_sign_in_ip
32
31
  end
33
32
 
33
+ # Override inherited associations to use admin serializers
34
+ many :addresses, resource: Spree.api.admin_address_serializer, if: proc { expand?('addresses') }
35
+ one :bill_address, key: :default_billing_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('default_billing_address') }
36
+ one :ship_address, key: :default_shipping_address, resource: Spree.api.admin_address_serializer, if: proc { expand?('default_shipping_address') }
37
+
34
38
  many :orders,
35
39
  resource: Spree.api.admin_order_serializer,
36
- if: proc { params[:expand]&.include?('orders') }
37
-
38
- # TODO: Add store_credits association when Admin API is implemented
40
+ if: proc { expand?('orders') }
39
41
  end
40
42
  end
41
43
  end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class DigitalLinkSerializer < V3::DigitalLinkSerializer
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class ImageSerializer < V3::ImageSerializer
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end
@@ -5,11 +5,46 @@ module Spree
5
5
  # Admin API Line Item Serializer
6
6
  # Extends the store serializer with metadata visibility
7
7
  class LineItemSerializer < V3::LineItemSerializer
8
- typelize metadata: 'Record<string, unknown> | null'
8
+ typelize metadata: 'Record<string, unknown> | null',
9
+ cost_price: [:string, nullable: true],
10
+ tax_category_id: [:string, nullable: true],
11
+ order_id: [:string, nullable: true]
9
12
 
10
13
  attribute :metadata do |line_item|
11
14
  line_item.metadata.presence
12
15
  end
16
+
17
+ attribute :cost_price do |line_item|
18
+ line_item.cost_price&.to_s
19
+ end
20
+
21
+ attribute :tax_category_id do |line_item|
22
+ line_item.tax_category&.prefixed_id
23
+ end
24
+
25
+ attribute :order_id do |line_item|
26
+ line_item.order&.prefixed_id
27
+ end
28
+
29
+ # Override inherited associations to use admin serializers
30
+ many :option_values, resource: Spree.api.admin_option_value_serializer
31
+ many :digital_links, resource: Spree.api.admin_digital_link_serializer
32
+
33
+ one :order,
34
+ resource: Spree.api.admin_order_serializer,
35
+ if: proc { expand?('order') }
36
+
37
+ one :variant,
38
+ resource: Spree.api.admin_variant_serializer,
39
+ if: proc { expand?('variant') }
40
+
41
+ one :tax_category,
42
+ resource: Spree.api.admin_tax_category_serializer,
43
+ if: proc { expand?('tax_category') }
44
+
45
+ many :adjustments,
46
+ resource: Spree.api.admin_adjustment_serializer,
47
+ if: proc { expand?('adjustments') }
13
48
  end
14
49
  end
15
50
  end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class OptionTypeSerializer < V3::OptionTypeSerializer
6
+ many :option_values,
7
+ resource: Spree.api.admin_option_value_serializer,
8
+ if: proc { expand?('option_values') }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class OptionValueSerializer < V3::OptionValueSerializer
6
+ one :option_type,
7
+ resource: Spree.api.admin_option_type_serializer,
8
+ if: proc { expand?('option_type') }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class OrderPromotionSerializer < V3::OrderPromotionSerializer
6
+ end
7
+ end
8
+ end
9
+ end
10
+ end