spree_api 5.4.0.beta8 → 5.4.0.beta10
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.
- checksums.yaml +4 -4
- data/Rakefile +17 -0
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +1 -0
- data/app/controllers/concerns/spree/api/v3/http_caching.rb +1 -1
- data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +27 -0
- data/app/controllers/spree/api/v3/store/auth_controller.rb +62 -19
- data/app/controllers/spree/api/v3/store/carts/{shipments_controller.rb → fulfillments_controller.rb} +13 -13
- data/app/controllers/spree/api/v3/store/carts_controller.rb +9 -7
- data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +2 -2
- data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +2 -0
- data/app/controllers/spree/api/v3/store/customers_controller.rb +6 -2
- data/app/controllers/spree/api/v3/store/products/filters_controller.rb +14 -10
- data/app/controllers/spree/api/v3/store/products_controller.rb +16 -36
- data/app/serializers/spree/api/v3/address_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/{shipping_method_serializer.rb → delivery_method_serializer.rb} +1 -1
- data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/{order_promotion_serializer.rb → discount_serializer.rb} +1 -1
- data/app/serializers/spree/api/v3/admin/{shipment_serializer.rb → fulfillment_serializer.rb} +3 -3
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +8 -7
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +0 -5
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/cart_serializer.rb +19 -12
- data/app/serializers/spree/api/v3/credit_card_serializer.rb +4 -3
- data/app/serializers/spree/api/v3/{shipping_method_serializer.rb → delivery_method_serializer.rb} +1 -1
- data/app/serializers/spree/api/v3/{shipping_rate_serializer.rb → delivery_rate_serializer.rb} +4 -4
- data/app/serializers/spree/api/v3/{cart_promotion_serializer.rb → discount_serializer.rb} +5 -5
- data/app/serializers/spree/api/v3/fulfillment_serializer.rb +45 -0
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/line_item_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/option_type_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/option_value_serializer.rb +5 -5
- data/app/serializers/spree/api/v3/order_serializer.rb +15 -13
- data/app/serializers/spree/api/v3/payment_serializer.rb +6 -2
- data/app/serializers/spree/api/v3/payment_source_serializer.rb +1 -3
- data/app/serializers/spree/api/v3/product_serializer.rb +0 -5
- data/app/serializers/spree/api/v3/promotion_serializer.rb +4 -16
- data/app/serializers/spree/api/v3/return_authorization_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/variant_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/{wished_item_serializer.rb → wishlist_item_serializer.rb} +1 -1
- data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
- data/app/services/spree/api/v3/filters_aggregator.rb +2 -2
- data/config/initializers/typelizer.rb +13 -1
- data/config/routes.rb +2 -1
- data/lib/spree/api/configuration.rb +1 -0
- data/lib/spree/api/dependencies.rb +16 -10
- data/lib/spree/api/openapi/schema_helper.rb +31 -1
- metadata +17 -17
- data/app/serializers/spree/api/v3/admin/shipping_rate_serializer.rb +0 -11
- data/app/serializers/spree/api/v3/order_promotion_serializer.rb +0 -16
- data/app/serializers/spree/api/v3/shipment_serializer.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3501d1a88ac6902a6a1ec3bb13d6fbf32740c8fb99dbc7c307b9459889d04cf
|
|
4
|
+
data.tar.gz: 7db1fed6aaaec434b3a0e22ab93024dfdddf02fa18e8b4d74758112c549253c4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 013bbf4bb70026183fbdd6be58976e87402757580c18d4c71537ea6c205677cf5270179f7c9830447156020af5618b4c2635dea742e9feb3a13c0c4de1ede34e
|
|
7
|
+
data.tar.gz: c934ecf6b24a136073093632d63af7a9a85c5834b95c97a427e8411ae13d58f144499bec306dee7638030331d4f381a5b83e21c495cf1ae9d5ddecc073aa1a90
|
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
|
|
|
@@ -12,6 +12,7 @@ module Spree
|
|
|
12
12
|
access_denied: 'access_denied',
|
|
13
13
|
invalid_token: 'invalid_token',
|
|
14
14
|
invalid_provider: 'invalid_provider',
|
|
15
|
+
invalid_refresh_token: 'invalid_refresh_token',
|
|
15
16
|
current_password_invalid: 'current_password_invalid',
|
|
16
17
|
password_reset_token_invalid: 'password_reset_token_invalid',
|
|
17
18
|
redirect_url_not_allowed: 'redirect_url_not_allowed',
|
|
@@ -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
|
|
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
|
|
@@ -7,9 +7,9 @@ module Spree
|
|
|
7
7
|
rate_limit to: Spree::Api::Config[:rate_limit_login], within: Spree::Api::Config[:rate_limit_window].seconds, store: Rails.cache, only: :create, with: RATE_LIMIT_RESPONSE
|
|
8
8
|
rate_limit to: Spree::Api::Config[:rate_limit_refresh], within: Spree::Api::Config[:rate_limit_window].seconds, store: Rails.cache, only: :refresh, with: RATE_LIMIT_RESPONSE
|
|
9
9
|
rate_limit to: Spree::Api::Config[:rate_limit_oauth], within: Spree::Api::Config[:rate_limit_window].seconds, store: Rails.cache, only: :oauth_callback, with: RATE_LIMIT_RESPONSE
|
|
10
|
+
rate_limit to: Spree::Api::Config[:rate_limit_refresh], within: Spree::Api::Config[:rate_limit_window].seconds, store: Rails.cache, only: :logout, with: RATE_LIMIT_RESPONSE
|
|
10
11
|
|
|
11
|
-
skip_before_action :authenticate_user, only: [:create, :oauth_callback]
|
|
12
|
-
prepend_before_action :require_authentication!, only: [:refresh]
|
|
12
|
+
skip_before_action :authenticate_user, only: [:create, :refresh, :oauth_callback]
|
|
13
13
|
|
|
14
14
|
# POST /api/v3/store/auth/login
|
|
15
15
|
# Supports multiple authentication providers via :provider param
|
|
@@ -23,11 +23,7 @@ module Spree
|
|
|
23
23
|
|
|
24
24
|
if result.success?
|
|
25
25
|
user = result.value
|
|
26
|
-
|
|
27
|
-
render json: {
|
|
28
|
-
token: token,
|
|
29
|
-
user: user_serializer.new(user, params: serializer_params).to_h
|
|
30
|
-
}
|
|
26
|
+
render json: auth_response(user)
|
|
31
27
|
else
|
|
32
28
|
render_error(
|
|
33
29
|
code: ERROR_CODES[:authentication_failed],
|
|
@@ -38,21 +34,55 @@ module Spree
|
|
|
38
34
|
end
|
|
39
35
|
|
|
40
36
|
# POST /api/v3/store/auth/refresh
|
|
37
|
+
# Accepts: { "refresh_token": "rt_xxx" }
|
|
38
|
+
# Returns new access JWT + rotated refresh token
|
|
41
39
|
def refresh
|
|
42
|
-
|
|
40
|
+
refresh_token_value = params[:refresh_token]
|
|
41
|
+
|
|
42
|
+
if refresh_token_value.blank?
|
|
43
|
+
return render_error(
|
|
44
|
+
code: ERROR_CODES[:invalid_refresh_token],
|
|
45
|
+
message: 'refresh_token is required',
|
|
46
|
+
status: :unauthorized
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
refresh_token = Spree::RefreshToken.active.find_by(token: refresh_token_value)
|
|
51
|
+
|
|
52
|
+
if refresh_token.nil?
|
|
53
|
+
return render_error(
|
|
54
|
+
code: ERROR_CODES[:invalid_refresh_token],
|
|
55
|
+
message: 'Invalid or expired refresh token',
|
|
56
|
+
status: :unauthorized
|
|
57
|
+
)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
user = refresh_token.user
|
|
61
|
+
new_refresh_token = refresh_token.rotate!(request_env: request_env_for_token)
|
|
62
|
+
|
|
43
63
|
render json: {
|
|
44
|
-
token:
|
|
45
|
-
|
|
64
|
+
token: generate_jwt(user),
|
|
65
|
+
refresh_token: new_refresh_token.token,
|
|
66
|
+
user: user_serializer.new(user, params: serializer_params).to_h
|
|
46
67
|
}
|
|
47
68
|
end
|
|
48
69
|
|
|
70
|
+
# POST /api/v3/store/auth/logout
|
|
71
|
+
# Accepts: { "refresh_token": "rt_xxx" }
|
|
72
|
+
# Revokes the refresh token
|
|
73
|
+
def logout
|
|
74
|
+
refresh_token_value = params[:refresh_token]
|
|
75
|
+
|
|
76
|
+
if refresh_token_value.present?
|
|
77
|
+
Spree::RefreshToken.find_by(token: refresh_token_value)&.destroy
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
head :no_content
|
|
81
|
+
end
|
|
82
|
+
|
|
49
83
|
# POST /api/v3/store/auth/oauth/callback
|
|
50
84
|
# OAuth callback endpoint for server-side OAuth flows
|
|
51
85
|
def oauth_callback
|
|
52
|
-
# This endpoint is designed for OAuth flows where the server
|
|
53
|
-
# exchanges the authorization code for an access token
|
|
54
|
-
# For client-side flows, use the regular /login endpoint with id_token
|
|
55
|
-
|
|
56
86
|
strategy = authentication_strategy
|
|
57
87
|
return unless strategy # Error already rendered by determine_strategy
|
|
58
88
|
|
|
@@ -60,11 +90,7 @@ module Spree
|
|
|
60
90
|
|
|
61
91
|
if result.success?
|
|
62
92
|
user = result.value
|
|
63
|
-
|
|
64
|
-
render json: {
|
|
65
|
-
token: token,
|
|
66
|
-
user: user_serializer.new(user, params: serializer_params).to_h
|
|
67
|
-
}
|
|
93
|
+
render json: auth_response(user)
|
|
68
94
|
else
|
|
69
95
|
render_error(
|
|
70
96
|
code: ERROR_CODES[:authentication_failed],
|
|
@@ -88,6 +114,23 @@ module Spree
|
|
|
88
114
|
|
|
89
115
|
private
|
|
90
116
|
|
|
117
|
+
def auth_response(user)
|
|
118
|
+
refresh_token = Spree::RefreshToken.create_for(user, request_env: request_env_for_token)
|
|
119
|
+
|
|
120
|
+
{
|
|
121
|
+
token: generate_jwt(user),
|
|
122
|
+
refresh_token: refresh_token.token,
|
|
123
|
+
user: user_serializer.new(user, params: serializer_params).to_h
|
|
124
|
+
}
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def request_env_for_token
|
|
128
|
+
{
|
|
129
|
+
ip_address: request.remote_ip,
|
|
130
|
+
user_agent: request.user_agent&.truncate(255)
|
|
131
|
+
}
|
|
132
|
+
end
|
|
133
|
+
|
|
91
134
|
def authentication_strategy
|
|
92
135
|
strategy_class = determine_strategy
|
|
93
136
|
strategy_class.new(
|
data/app/controllers/spree/api/v3/store/carts/{shipments_controller.rb → fulfillments_controller.rb}
RENAMED
|
@@ -3,31 +3,31 @@ module Spree
|
|
|
3
3
|
module V3
|
|
4
4
|
module Store
|
|
5
5
|
module Carts
|
|
6
|
-
class
|
|
6
|
+
class FulfillmentsController < Store::BaseController
|
|
7
7
|
include Spree::Api::V3::CartResolvable
|
|
8
8
|
include Spree::Api::V3::OrderLock
|
|
9
9
|
|
|
10
10
|
before_action :find_cart!
|
|
11
11
|
|
|
12
|
-
# GET /api/v3/store/carts/:cart_id/
|
|
12
|
+
# GET /api/v3/store/carts/:cart_id/fulfillments
|
|
13
13
|
def index
|
|
14
|
-
|
|
14
|
+
fulfillments = @cart.shipments.includes(shipping_rates: :shipping_method)
|
|
15
15
|
render json: {
|
|
16
|
-
data:
|
|
17
|
-
meta: { count:
|
|
16
|
+
data: fulfillments.map { |s| Spree.api.fulfillment_serializer.new(s, params: serializer_params).to_h },
|
|
17
|
+
meta: { count: fulfillments.size }
|
|
18
18
|
}
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
# PATCH /api/v3/store/carts/:cart_id/
|
|
22
|
-
# Select a
|
|
21
|
+
# PATCH /api/v3/store/carts/:cart_id/fulfillments/:id
|
|
22
|
+
# Select a delivery rate for a specific fulfillment
|
|
23
23
|
def update
|
|
24
24
|
with_order_lock do
|
|
25
|
-
|
|
25
|
+
fulfillment = @cart.shipments.find_by_prefix_id!(params[:id])
|
|
26
26
|
|
|
27
|
-
if permitted_params[:
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
27
|
+
if permitted_params[:selected_delivery_rate_id].present?
|
|
28
|
+
delivery_rate = fulfillment.shipping_rates.find_by_prefix_id!(permitted_params[:selected_delivery_rate_id])
|
|
29
|
+
fulfillment.selected_shipping_rate_id = delivery_rate.id
|
|
30
|
+
fulfillment.save!
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Auto-advance (e.g. delivery → payment) after rate selection.
|
|
@@ -41,7 +41,7 @@ module Spree
|
|
|
41
41
|
private
|
|
42
42
|
|
|
43
43
|
def permitted_params
|
|
44
|
-
params.permit(:
|
|
44
|
+
params.permit(:selected_delivery_rate_id)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
# Temporary — Spree 6 removes the checkout state machine.
|
|
@@ -140,13 +140,14 @@ module Spree
|
|
|
140
140
|
def permitted_params
|
|
141
141
|
params.permit(
|
|
142
142
|
:email,
|
|
143
|
-
:
|
|
143
|
+
:customer_note,
|
|
144
144
|
:currency,
|
|
145
145
|
:locale,
|
|
146
|
-
:
|
|
147
|
-
:
|
|
148
|
-
|
|
149
|
-
|
|
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, :
|
|
158
|
-
:
|
|
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
|
-
:
|
|
77
|
-
:
|
|
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
|
|
@@ -55,10 +55,12 @@ module Spree
|
|
|
55
55
|
|
|
56
56
|
if user.update(password: params[:password], password_confirmation: params[:password_confirmation])
|
|
57
57
|
jwt = generate_jwt(user)
|
|
58
|
+
refresh_token = Spree::RefreshToken.create_for(user, request_env: { ip_address: request.remote_ip, user_agent: request.user_agent&.truncate(255) })
|
|
58
59
|
user.publish_event('customer.password_reset')
|
|
59
60
|
|
|
60
61
|
render json: {
|
|
61
62
|
token: jwt,
|
|
63
|
+
refresh_token: refresh_token.token,
|
|
62
64
|
user: serializer_class.new(user, params: serializer_params).to_h
|
|
63
65
|
}
|
|
64
66
|
else
|
|
@@ -13,9 +13,13 @@ module Spree
|
|
|
13
13
|
user = Spree.user_class.new(create_params)
|
|
14
14
|
|
|
15
15
|
if user.save
|
|
16
|
-
|
|
16
|
+
refresh_token = Spree::RefreshToken.create_for(user, request_env: {
|
|
17
|
+
ip_address: request.remote_ip,
|
|
18
|
+
user_agent: request.user_agent&.truncate(255)
|
|
19
|
+
})
|
|
17
20
|
render json: {
|
|
18
|
-
token:
|
|
21
|
+
token: generate_jwt(user),
|
|
22
|
+
refresh_token: refresh_token.token,
|
|
19
23
|
user: user_serializer.new(user, params: serializer_params).to_h
|
|
20
24
|
}, status: :created
|
|
21
25
|
else
|
|
@@ -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
|
-
|
|
10
|
+
result = search_provider.search_and_filter(
|
|
9
11
|
scope: filters_scope,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
query: search_query,
|
|
13
|
+
filters: (search_filters || {}).merge('_category' => category),
|
|
14
|
+
page: 1,
|
|
15
|
+
limit: 0
|
|
12
16
|
)
|
|
13
|
-
|
|
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
|
-
#
|
|
51
|
-
#
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
|
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],
|
|
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 :
|
|
13
|
-
:city, :
|
|
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
|
|
@@ -4,13 +4,13 @@ module Spree
|
|
|
4
4
|
module Admin
|
|
5
5
|
class AddressSerializer < V3::AddressSerializer
|
|
6
6
|
typelize label: [:string, nullable: true],
|
|
7
|
-
|
|
7
|
+
customer_id: [:string, nullable: true],
|
|
8
8
|
metadata: 'Record<string, unknown> | null'
|
|
9
9
|
|
|
10
10
|
attributes :label,
|
|
11
11
|
created_at: :iso8601, updated_at: :iso8601
|
|
12
12
|
|
|
13
|
-
attribute :
|
|
13
|
+
attribute :customer_id do |address|
|
|
14
14
|
address.user&.prefixed_id
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -3,10 +3,10 @@ module Spree
|
|
|
3
3
|
module V3
|
|
4
4
|
module Admin
|
|
5
5
|
class CreditCardSerializer < V3::CreditCardSerializer
|
|
6
|
-
typelize
|
|
6
|
+
typelize customer_id: [:string, nullable: true],
|
|
7
7
|
payment_method_id: [:string, nullable: true]
|
|
8
8
|
|
|
9
|
-
attribute :
|
|
9
|
+
attribute :customer_id do |credit_card|
|
|
10
10
|
credit_card.user&.prefixed_id
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Admin
|
|
5
|
+
class DeliveryRateSerializer < V3::DeliveryRateSerializer
|
|
6
|
+
one :shipping_method, key: :delivery_method, resource: Spree.api.admin_delivery_method_serializer, if: proc { expand?('delivery_method') }
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
data/app/serializers/spree/api/v3/admin/{shipment_serializer.rb → fulfillment_serializer.rb}
RENAMED
|
@@ -2,7 +2,7 @@ module Spree
|
|
|
2
2
|
module Api
|
|
3
3
|
module V3
|
|
4
4
|
module Admin
|
|
5
|
-
class
|
|
5
|
+
class FulfillmentSerializer < V3::FulfillmentSerializer
|
|
6
6
|
typelize metadata: 'Record<string, unknown> | null',
|
|
7
7
|
order_id: [:string, nullable: true],
|
|
8
8
|
stock_location_id: [:string, nullable: true],
|
|
@@ -26,9 +26,9 @@ module Spree
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
# Override inherited associations to use admin serializers
|
|
29
|
-
one :shipping_method, resource: Spree.api.
|
|
29
|
+
one :shipping_method, key: :delivery_method, resource: Spree.api.admin_delivery_method_serializer, if: proc { expand?('delivery_method') }
|
|
30
30
|
one :stock_location, resource: Spree.api.admin_stock_location_serializer, if: proc { expand?('stock_location') }
|
|
31
|
-
many :shipping_rates, resource: Spree.api.
|
|
31
|
+
many :shipping_rates, key: :delivery_rates, resource: Spree.api.admin_delivery_rate_serializer, if: proc { expand?('delivery_rates') }
|
|
32
32
|
|
|
33
33
|
one :order,
|
|
34
34
|
resource: Spree.api.admin_order_serializer,
|
|
@@ -11,7 +11,7 @@ module Spree
|
|
|
11
11
|
store_owner_notification_delivered: :boolean,
|
|
12
12
|
internal_note: [:string, nullable: true], approver_id: [:string, nullable: true],
|
|
13
13
|
canceler_id: [:string, nullable: true], created_by_id: [:string, nullable: true],
|
|
14
|
-
|
|
14
|
+
customer_id: [:string, nullable: true],
|
|
15
15
|
canceled_at: [:string, nullable: true], approved_at: [:string, nullable: true],
|
|
16
16
|
payment_total: :string, display_payment_total: :string,
|
|
17
17
|
metadata: 'Record<string, unknown> | null'
|
|
@@ -38,24 +38,25 @@ module Spree
|
|
|
38
38
|
order.created_by&.prefixed_id
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
attribute :
|
|
41
|
+
attribute :customer_id do |order|
|
|
42
42
|
order.user&.prefixed_id
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# Override inherited associations to use admin serializers
|
|
46
|
-
many :
|
|
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 :
|
|
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 :
|
|
52
|
-
one :
|
|
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
|
|
|
56
56
|
one :user,
|
|
57
|
+
key: :customer,
|
|
57
58
|
resource: Spree.api.admin_customer_serializer,
|
|
58
|
-
if: proc { expand?('
|
|
59
|
+
if: proc { expand?('customer') }
|
|
59
60
|
|
|
60
61
|
one :approver,
|
|
61
62
|
resource: Spree.api.admin_customer_serializer,
|
|
@@ -32,11 +32,6 @@ module Spree
|
|
|
32
32
|
resource: Spree.api.admin_variant_serializer,
|
|
33
33
|
if: proc { expand?('default_variant') }
|
|
34
34
|
|
|
35
|
-
one :master,
|
|
36
|
-
key: :master_variant,
|
|
37
|
-
resource: Spree.api.admin_variant_serializer,
|
|
38
|
-
if: proc { expand?('master_variant') }
|
|
39
|
-
|
|
40
35
|
one :primary_media,
|
|
41
36
|
resource: Spree.api.admin_media_serializer,
|
|
42
37
|
if: proc { expand?('primary_media') }
|
|
@@ -3,11 +3,11 @@ module Spree
|
|
|
3
3
|
module V3
|
|
4
4
|
module Admin
|
|
5
5
|
class StoreCreditSerializer < V3::StoreCreditSerializer
|
|
6
|
-
typelize
|
|
6
|
+
typelize customer_id: [:string, nullable: true],
|
|
7
7
|
created_by_id: [:string, nullable: true],
|
|
8
8
|
metadata: 'Record<string, unknown> | null'
|
|
9
9
|
|
|
10
|
-
attribute :
|
|
10
|
+
attribute :customer_id do |store_credit|
|
|
11
11
|
store_credit.user&.prefixed_id
|
|
12
12
|
end
|
|
13
13
|
|