spree_api 5.4.3 → 5.5.0.rc2

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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +36 -0
  3. data/app/controllers/concerns/spree/api/v3/admin/auth_cookies.rb +62 -0
  4. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +52 -0
  5. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +149 -0
  6. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +54 -0
  7. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +103 -0
  8. data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +60 -0
  9. data/app/controllers/concerns/spree/api/v3/error_handler.rb +4 -0
  10. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +84 -0
  11. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +104 -0
  12. data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +35 -1
  13. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +109 -0
  14. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +25 -0
  15. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +84 -0
  16. data/app/controllers/spree/api/v3/admin/auth_controller.rb +134 -0
  17. data/app/controllers/spree/api/v3/admin/base_controller.rb +3 -17
  18. data/app/controllers/spree/api/v3/admin/categories_controller.rb +25 -0
  19. data/app/controllers/spree/api/v3/admin/channels_controller.rb +65 -0
  20. data/app/controllers/spree/api/v3/admin/countries_controller.rb +38 -0
  21. data/app/controllers/spree/api/v3/admin/coupon_codes_controller.rb +33 -0
  22. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +34 -0
  23. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +129 -0
  24. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +31 -0
  25. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +83 -0
  26. data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +33 -0
  27. data/app/controllers/spree/api/v3/admin/customers/credit_cards_controller.rb +25 -0
  28. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +92 -0
  29. data/app/controllers/spree/api/v3/admin/customers_controller.rb +119 -0
  30. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +44 -0
  31. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +40 -0
  32. data/app/controllers/spree/api/v3/admin/exports_controller.rb +136 -0
  33. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +31 -0
  34. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +33 -0
  35. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +138 -0
  36. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +81 -0
  37. data/app/controllers/spree/api/v3/admin/markets_controller.rb +42 -0
  38. data/app/controllers/spree/api/v3/admin/me_controller.rb +69 -0
  39. data/app/controllers/spree/api/v3/admin/media_controller.rb +119 -0
  40. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +34 -0
  41. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +27 -0
  42. data/app/controllers/spree/api/v3/admin/orders/base_controller.rb +31 -0
  43. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +104 -0
  44. data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +79 -0
  45. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +92 -0
  46. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +90 -0
  47. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +53 -0
  48. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +59 -0
  49. data/app/controllers/spree/api/v3/admin/orders_controller.rb +190 -0
  50. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +73 -0
  51. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +179 -0
  52. data/app/controllers/spree/api/v3/admin/prices_controller.rb +157 -0
  53. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +48 -0
  54. data/app/controllers/spree/api/v3/admin/products_controller.rb +237 -0
  55. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +78 -0
  56. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +56 -0
  57. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +78 -0
  58. data/app/controllers/spree/api/v3/admin/resource_controller.rb +29 -11
  59. data/app/controllers/spree/api/v3/admin/roles_controller.rb +29 -0
  60. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +35 -0
  61. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +36 -0
  62. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +29 -0
  63. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +75 -0
  64. data/app/controllers/spree/api/v3/admin/store_controller.rb +53 -0
  65. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +21 -0
  66. data/app/controllers/spree/api/v3/admin/tags_controller.rb +51 -0
  67. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +21 -0
  68. data/app/controllers/spree/api/v3/admin/variants_controller.rb +33 -0
  69. data/app/controllers/spree/api/v3/admin/webhook_deliveries_controller.rb +49 -0
  70. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +75 -0
  71. data/app/controllers/spree/api/v3/resource_controller.rb +117 -8
  72. data/app/controllers/spree/api/v3/store/auth_controller.rb +8 -28
  73. data/app/controllers/spree/api/v3/store/base_controller.rb +6 -0
  74. data/app/controllers/spree/api/v3/store/carts_controller.rb +1 -0
  75. data/app/controllers/spree/api/v3/store/customers_controller.rb +6 -0
  76. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +77 -0
  77. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +2 -2
  78. data/app/controllers/spree/api/v3/store/products_controller.rb +4 -3
  79. data/app/controllers/spree/api/v3/store/resource_controller.rb +10 -2
  80. data/app/jobs/spree/webhook_delivery_job.rb +5 -0
  81. data/app/models/spree/api_key_ability.rb +16 -0
  82. data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -6
  83. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +3 -15
  84. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +19 -3
  85. data/app/serializers/spree/api/v3/admin/allowed_origin_serializer.rb +2 -6
  86. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +42 -0
  87. data/app/serializers/spree/api/v3/admin/category_serializer.rb +4 -3
  88. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -0
  89. data/app/serializers/spree/api/v3/admin/country_serializer.rb +1 -1
  90. data/app/serializers/spree/api/v3/admin/coupon_code_serializer.rb +30 -0
  91. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +4 -2
  92. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +21 -0
  93. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +8 -3
  94. data/app/serializers/spree/api/v3/admin/customer_group_serializer.rb +27 -0
  95. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +58 -2
  96. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +143 -0
  97. data/app/serializers/spree/api/v3/admin/export_serializer.rb +40 -0
  98. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +2 -6
  99. data/app/serializers/spree/api/v3/admin/{asset_serializer.rb → gift_card_batch_serializer.rb} +1 -1
  100. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +39 -4
  101. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +64 -0
  102. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +4 -16
  103. data/app/serializers/spree/api/v3/admin/media_serializer.rb +24 -2
  104. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +4 -1
  105. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +4 -1
  106. data/app/serializers/spree/api/v3/admin/order_serializer.rb +21 -6
  107. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +11 -2
  108. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +2 -6
  109. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +4 -1
  110. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +51 -0
  111. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +55 -0
  112. data/app/serializers/spree/api/v3/admin/price_serializer.rb +4 -0
  113. data/app/serializers/spree/api/v3/admin/product_publication_serializer.rb +11 -0
  114. data/app/serializers/spree/api/v3/admin/product_serializer.rb +34 -10
  115. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +71 -0
  116. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +85 -0
  117. data/app/serializers/spree/api/v3/admin/promotion_serializer.rb +41 -0
  118. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +4 -2
  119. data/app/serializers/spree/api/v3/admin/role_serializer.rb +17 -0
  120. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +16 -1
  121. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +11 -2
  122. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +46 -0
  123. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +37 -0
  124. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +19 -0
  125. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +11 -5
  126. data/app/serializers/spree/api/v3/admin/store_serializer.rb +55 -0
  127. data/app/serializers/spree/api/v3/admin/tax_category_serializer.rb +4 -2
  128. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +37 -6
  129. data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +45 -0
  130. data/app/serializers/spree/api/v3/admin/webhook_endpoint_serializer.rb +69 -0
  131. data/app/serializers/spree/api/v3/channel_serializer.rb +14 -0
  132. data/app/serializers/spree/api/v3/custom_field_serializer.rb +9 -10
  133. data/app/serializers/spree/api/v3/customer_serializer.rb +5 -0
  134. data/app/serializers/spree/api/v3/market_serializer.rb +2 -1
  135. data/app/serializers/spree/api/v3/media_serializer.rb +8 -6
  136. data/app/serializers/spree/api/v3/order_serializer.rb +6 -1
  137. data/app/serializers/spree/api/v3/payment_method_serializer.rb +11 -2
  138. data/app/serializers/spree/api/v3/product_publication_serializer.rb +22 -0
  139. data/app/serializers/spree/api/v3/product_serializer.rb +6 -1
  140. data/app/serializers/spree/api/v3/stock_reservation_serializer.rb +10 -0
  141. data/config/locales/en.yml +2 -0
  142. data/config/routes.rb +235 -1
  143. data/lib/spree/api/configuration.rb +2 -2
  144. data/lib/spree/api/dependencies.rb +25 -1
  145. data/lib/spree/api/openapi/path_sorter.rb +126 -0
  146. data/lib/spree/api/openapi/schema_helper.rb +185 -6
  147. data/lib/spree/api/testing_support/v3/base.rb +28 -0
  148. metadata +98 -8
  149. data/app/serializers/spree/api/v3/admin/shipping_category_serializer.rb +0 -14
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class ProductPublicationSerializer < V3::ProductPublicationSerializer
6
+ attributes created_at: :iso8601, updated_at: :iso8601
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -7,21 +7,33 @@ module Spree
7
7
  # Extends the store serializer with additional attributes
8
8
  class ProductSerializer < V3::ProductSerializer
9
9
 
10
- # Additional type hints for admin-only computed attributes
11
- typelize status: :string, make_active_at: [:string, nullable: true], discontinue_on: [:string, nullable: true],
12
- cost_price: [:string, nullable: true], cost_currency: [:string, nullable: true],
13
- deleted_at: [:string, nullable: true]
10
+ typelize status: :string,
11
+ tax_category_id: [:string, nullable: true],
12
+ price: ['Price', nullable: true],
13
+ deleted_at: [:string, nullable: true],
14
+ metadata: 'Record<string, unknown>'
14
15
 
15
- # Admin-only attributes
16
- attributes :status, :make_active_at, :discontinue_on, deleted_at: :iso8601,
16
+ attributes :status,
17
+ :metadata, deleted_at: :iso8601,
17
18
  created_at: :iso8601, updated_at: :iso8601
18
19
 
19
- attribute :cost_price do |product|
20
- product.master&.cost_price
20
+ attribute :tax_category_id do |product|
21
+ product.tax_category&.prefixed_id
21
22
  end
22
23
 
23
- attribute :cost_currency do |product|
24
- product.master&.cost_currency
24
+ attribute :price do |product|
25
+ price = price_for(product.default_variant)
26
+ Spree.api.admin_price_serializer.new(price, params: params).to_h if price&.persisted?
27
+ end
28
+
29
+ attribute :original_price do |product|
30
+ variant = product.default_variant
31
+ calculated = price_for(variant)
32
+ base = price_in(variant)
33
+
34
+ if calculated.present? && base.present? && calculated.id != base.id
35
+ Spree.api.admin_price_serializer.new(base, params: params).to_h
36
+ end
25
37
  end
26
38
 
27
39
  # Admin uses admin variant serializer
@@ -46,6 +58,10 @@ module Spree
46
58
  resource: Spree.api.admin_option_type_serializer,
47
59
  if: proc { expand?('option_types') }
48
60
 
61
+ many :option_values,
62
+ resource: Spree.api.admin_option_value_serializer,
63
+ if: proc { expand?('option_values') }
64
+
49
65
  many :taxons,
50
66
  proc { |taxons, params|
51
67
  taxons.select { |t| t.taxonomy.store_id == params[:store].id }
@@ -58,6 +74,14 @@ module Spree
58
74
  key: :custom_fields,
59
75
  resource: Spree.api.admin_custom_field_serializer,
60
76
  if: proc { expand?('custom_fields') }
77
+
78
+ many :product_publications,
79
+ resource: Spree.api.admin_product_publication_serializer,
80
+ if: proc { expand?('product_publications') }
81
+
82
+ many :channels,
83
+ resource: Spree.api.admin_channel_serializer,
84
+ if: proc { expand?('channels') }
61
85
  end
62
86
  end
63
87
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ module V3
6
+ module Admin
7
+ # Serializes Spree::PromotionAction (and its STI subclasses) for the
8
+ # admin promotion editor. The shape is intentionally generic so a
9
+ # single component can render any subclass — `preferences` is the
10
+ # current value hash, `preference_schema` describes its fields.
11
+ class PromotionActionSerializer < BaseSerializer
12
+ typelize type: :string,
13
+ promotion_id: :string,
14
+ preferences: 'Record<string, unknown>',
15
+ preference_schema: "Array<{ key: string; type: string; default: unknown }>",
16
+ label: :string,
17
+ calculator: "{ type: string; label: string; preferences: Record<string, unknown>; preference_schema: Array<{ key: string; type: string; default: unknown }> } | null",
18
+ line_items: 'Array<{ variant_id: string; quantity: number }> | null'
19
+
20
+ attributes created_at: :iso8601, updated_at: :iso8601
21
+
22
+ attribute :type do |action|
23
+ action.class.api_type
24
+ end
25
+
26
+ attribute :promotion_id do |action|
27
+ action.promotion&.prefixed_id
28
+ end
29
+
30
+ attribute :preferences, &:serialized_preferences
31
+ attribute :preference_schema, &:serialized_preference_schema
32
+
33
+ attribute :label do |action|
34
+ action.respond_to?(:human_name) ? action.human_name : action.type.to_s.demodulize
35
+ end
36
+
37
+ # Calculator is exposed as a nested object so the SPA can render
38
+ # the calculator picker + its own preference fields. Null for
39
+ # actions that don't include CalculatedAdjustments. The SPA
40
+ # formats the row summary itself off `label` + `preferences` —
41
+ # see the action-summary helper in the admin promotion editor.
42
+ attribute :calculator do |action|
43
+ next nil unless action.respond_to?(:calculator) && action.calculator
44
+
45
+ calc = action.calculator
46
+ {
47
+ type: calc.class.api_type,
48
+ label: calc.class.respond_to?(:description) ? calc.class.description : calc.class.to_s.demodulize.titleize,
49
+ preferences: calc.serialized_preferences,
50
+ preference_schema: calc.serialized_preference_schema
51
+ }
52
+ end
53
+
54
+ # Line items the action will add for CreateLineItems. variant_id
55
+ # is prefixed for consistency with the rest of the API. Null on
56
+ # actions that don't have the association.
57
+ attribute :line_items do |action|
58
+ next nil unless action.respond_to?(:promotion_action_line_items)
59
+
60
+ action.promotion_action_line_items.map do |item|
61
+ {
62
+ variant_id: item.variant&.prefixed_id,
63
+ quantity: item.quantity
64
+ }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ module V3
6
+ module Admin
7
+ # Serializes Spree::PromotionRule (and its STI subclasses) for the
8
+ # admin promotion editor. Same shape as PromotionAction so the
9
+ # frontend renders both with the same generic component.
10
+ class PromotionRuleSerializer < BaseSerializer
11
+ typelize type: :string,
12
+ promotion_id: :string,
13
+ preferences: 'Record<string, unknown>',
14
+ preference_schema: "Array<{ key: string; type: string; default: unknown }>",
15
+ label: :string,
16
+ product_ids: 'Array<string> | null',
17
+ category_ids: 'Array<string> | null',
18
+ customer_ids: 'Array<string> | null'
19
+
20
+ attributes created_at: :iso8601, updated_at: :iso8601
21
+
22
+ attribute :type do |rule|
23
+ rule.class.api_type
24
+ end
25
+
26
+ attribute :promotion_id do |rule|
27
+ rule.promotion&.prefixed_id
28
+ end
29
+
30
+ attribute :preferences, &:serialized_preferences
31
+ attribute :preference_schema, &:serialized_preference_schema
32
+
33
+ attribute :label do |rule|
34
+ rule.respond_to?(:human_name) ? rule.human_name : rule.class.to_s.demodulize
35
+ end
36
+
37
+ # Association IDs for rules that wire products/taxons/users through
38
+ # join tables. Returned as prefixed IDs to match the rest of the
39
+ # API; null on rules that don't have the association. The matching
40
+ # `products`/`categories`/`customers` collections below embed the
41
+ # full records via their admin serializers so the SPA can render
42
+ # names + extra info without an extra round-trip.
43
+ attribute :product_ids do |rule|
44
+ rule.products.map(&:prefixed_id) if rule.respond_to?(:products)
45
+ end
46
+
47
+ attribute :category_ids do |rule|
48
+ rule.taxons.map(&:prefixed_id) if rule.respond_to?(:taxons)
49
+ end
50
+
51
+ attribute :customer_ids do |rule|
52
+ rule.users.map(&:prefixed_id) if rule.respond_to?(:users)
53
+ end
54
+
55
+ # Embed the related records so promotion-row summaries can render
56
+ # names + extra info without a separate fetch. Rules that don't
57
+ # carry a given collection (e.g. an ItemTotal rule has no
58
+ # products) skip via `if:` and the key is omitted from the
59
+ # payload.
60
+ many :products,
61
+ resource: Spree.api.admin_product_serializer,
62
+ if: proc { |rule| rule.respond_to?(:products) }
63
+
64
+ many :taxons,
65
+ key: :categories,
66
+ resource: Spree.api.admin_category_serializer,
67
+ if: proc { |rule| rule.respond_to?(:taxons) }
68
+
69
+ many :users,
70
+ key: :customers,
71
+ resource: Spree.api.admin_customer_serializer,
72
+ if: proc { |rule| rule.respond_to?(:users) }
73
+
74
+ many :customer_groups,
75
+ resource: Spree.api.admin_customer_group_serializer,
76
+ if: proc { |rule| rule.respond_to?(:customer_groups) }
77
+
78
+ many :countries,
79
+ resource: Spree.api.admin_country_serializer,
80
+ if: proc { |rule| rule.respond_to?(:countries) }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ module V3
6
+ module Admin
7
+ # Admin Promotion serializer — adds operational fields the Store API
8
+ # never exposes (multi-codes counts, usage stats, internal promotion
9
+ # category, store assignments, timestamps).
10
+ class PromotionSerializer < V3::PromotionSerializer
11
+ typelize starts_at: [:string, nullable: true],
12
+ expires_at: [:string, nullable: true],
13
+ usage_limit: [:number, nullable: true],
14
+ match_policy: "'all' | 'any'",
15
+ path: [:string, nullable: true],
16
+ kind: "'coupon_code' | 'automatic'",
17
+ multi_codes: :boolean,
18
+ number_of_codes: [:number, nullable: true],
19
+ code_prefix: [:string, nullable: true],
20
+ promotion_category_id: [:string, nullable: true],
21
+ metadata: 'Record<string, unknown>',
22
+ action_ids: 'string[]',
23
+ rule_ids: 'string[]'
24
+
25
+ attributes :starts_at, :expires_at, :usage_limit, :match_policy,
26
+ :path, :kind, :multi_codes, :number_of_codes, :code_prefix,
27
+ :promotion_category_id, :metadata,
28
+ created_at: :iso8601, updated_at: :iso8601
29
+
30
+ attribute :action_ids do |promotion|
31
+ promotion.promotion_actions.map(&:prefixed_id)
32
+ end
33
+
34
+ attribute :rule_ids do |promotion|
35
+ promotion.promotion_rules.map(&:prefixed_id)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -5,9 +5,11 @@ module Spree
5
5
  class RefundSerializer < V3::RefundSerializer
6
6
  typelize payment_id: [:string, nullable: true],
7
7
  refund_reason_id: [:string, nullable: true],
8
- reimbursement_id: [:string, nullable: true]
8
+ reimbursement_id: [:string, nullable: true],
9
+ metadata: 'Record<string, unknown>'
9
10
 
10
- attributes created_at: :iso8601, updated_at: :iso8601
11
+ attributes :metadata,
12
+ created_at: :iso8601, updated_at: :iso8601
11
13
 
12
14
  one :payment,
13
15
  resource: Spree.api.admin_payment_serializer,
@@ -0,0 +1,17 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Admin API serializer for {Spree::Role}. Read-only — used to populate
6
+ # the role picker on the staff invite/edit forms. Spree core ships
7
+ # with a single `admin` role today; richer role/permission management
8
+ # is on the roadmap.
9
+ class RoleSerializer < V3::BaseSerializer
10
+ typelize name: :string
11
+
12
+ attributes :name, created_at: :iso8601, updated_at: :iso8601
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -3,7 +3,22 @@ module Spree
3
3
  module V3
4
4
  module Admin
5
5
  class StockItemSerializer < V3::StockItemSerializer
6
- attributes created_at: :iso8601, updated_at: :iso8601
6
+ typelize metadata: 'Record<string, unknown>',
7
+ allocated_count: :number, available_count: :number
8
+
9
+ attributes :metadata,
10
+ created_at: :iso8601, updated_at: :iso8601
11
+
12
+ # Units already allocated to pending shipments. Always 0 in 5.5;
13
+ # 6.0 Typed Stock Movements wires it up.
14
+ attribute :allocated_count do |stock_item|
15
+ stock_item.allocated_count.to_i
16
+ end
17
+
18
+ # Physical stock minus allocated units (per stock_item).
19
+ attribute :available_count do |stock_item|
20
+ stock_item.available_count.to_i
21
+ end
7
22
 
8
23
  one :stock_location,
9
24
  resource: Spree.api.admin_stock_location_serializer,
@@ -4,9 +4,18 @@ module Spree
4
4
  module Admin
5
5
  class StockLocationSerializer < V3::StockLocationSerializer
6
6
  typelize active: :boolean, default: :boolean, backorderable_default: :boolean,
7
- propagate_all_variants: :boolean
7
+ propagate_all_variants: :boolean, pickup_enabled: :boolean,
8
+ admin_name: [:string, nullable: true],
9
+ address2: [:string, nullable: true], state_name: [:string, nullable: true],
10
+ phone: [:string, nullable: true], company: [:string, nullable: true],
11
+ kind: :string, pickup_stock_policy: :string,
12
+ pickup_ready_in_minutes: [:number, nullable: true],
13
+ pickup_instructions: [:string, nullable: true]
8
14
 
9
- attributes :active, :default, :backorderable_default, :propagate_all_variants,
15
+ attributes :admin_name, :address2, :state_name, :phone, :company,
16
+ :active, :default, :backorderable_default, :propagate_all_variants,
17
+ :kind, :pickup_enabled, :pickup_stock_policy,
18
+ :pickup_ready_in_minutes, :pickup_instructions,
10
19
  created_at: :iso8601, updated_at: :iso8601
11
20
  end
12
21
  end
@@ -0,0 +1,46 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class StockReservationSerializer < V3::StockReservationSerializer
6
+ typelize stock_item_id: :string,
7
+ line_item_id: :string,
8
+ order_id: :string,
9
+ variant_id: [:string, nullable: true],
10
+ stock_location_id: [:string, nullable: true],
11
+ quantity: :number,
12
+ expires_at: :string,
13
+ active: :boolean
14
+
15
+ attribute :stock_item_id do |reservation|
16
+ reservation.stock_item.prefixed_id
17
+ end
18
+
19
+ attribute :line_item_id do |reservation|
20
+ reservation.line_item.prefixed_id
21
+ end
22
+
23
+ attribute :order_id do |reservation|
24
+ reservation.order.prefixed_id
25
+ end
26
+
27
+ attribute :variant_id do |reservation|
28
+ reservation.stock_item&.variant&.prefixed_id
29
+ end
30
+
31
+ attribute :stock_location_id do |reservation|
32
+ reservation.stock_item&.stock_location&.prefixed_id
33
+ end
34
+
35
+ attributes :quantity, expires_at: :iso8601
36
+
37
+ attribute :active do |reservation|
38
+ reservation.active?
39
+ end
40
+
41
+ attributes created_at: :iso8601, updated_at: :iso8601
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,37 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Inventory movement between two stock locations (or external →
6
+ # location for receives). The originating location is `nil` for
7
+ # receives (vendor stock arriving) and present for transfers.
8
+ class StockTransferSerializer < V3::BaseSerializer
9
+ typelize number: :string,
10
+ reference: [:string, nullable: true],
11
+ source_location_id: [:string, nullable: true],
12
+ destination_location_id: [:string, nullable: true],
13
+ metadata: 'Record<string, unknown>'
14
+
15
+ attributes :number, :reference, :metadata,
16
+ created_at: :iso8601, updated_at: :iso8601
17
+
18
+ attribute :source_location_id do |stock_transfer|
19
+ stock_transfer.source_location&.prefixed_id
20
+ end
21
+
22
+ attribute :destination_location_id do |stock_transfer|
23
+ stock_transfer.destination_location&.prefixed_id
24
+ end
25
+
26
+ one :source_location,
27
+ resource: Spree.api.admin_stock_location_serializer,
28
+ if: proc { expand?('source_location') }
29
+
30
+ one :destination_location,
31
+ resource: Spree.api.admin_stock_location_serializer,
32
+ if: proc { expand?('destination_location') }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class StoreCreditCategorySerializer < V3::BaseSerializer
6
+ typelize name: :string,
7
+ non_expiring: :boolean
8
+
9
+ attributes :name,
10
+ created_at: :iso8601, updated_at: :iso8601
11
+
12
+ attribute :non_expiring do |store_credit_category|
13
+ store_credit_category.non_expiring?
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -5,9 +5,13 @@ module Spree
5
5
  class StoreCreditSerializer < V3::StoreCreditSerializer
6
6
  typelize customer_id: [:string, nullable: true],
7
7
  created_by_id: [:string, nullable: true],
8
- metadata: 'Record<string, unknown> | null'
8
+ category_id: [:string, nullable: true],
9
+ category_name: [:string, nullable: true],
10
+ memo: [:string, nullable: true],
11
+ metadata: 'Record<string, unknown>'
9
12
 
10
- attributes created_at: :iso8601, updated_at: :iso8601
13
+ attributes :memo, :metadata,
14
+ created_at: :iso8601, updated_at: :iso8601
11
15
 
12
16
  attribute :customer_id do |store_credit|
13
17
  store_credit.user&.prefixed_id
@@ -17,11 +21,13 @@ module Spree
17
21
  store_credit.created_by&.prefixed_id
18
22
  end
19
23
 
20
- attribute :metadata do |store_credit|
21
- store_credit.metadata.presence
24
+ attribute :category_id do |store_credit|
25
+ store_credit.category&.prefixed_id
22
26
  end
23
27
 
24
- attributes created_at: :iso8601, updated_at: :iso8601
28
+ attribute :category_name do |store_credit|
29
+ store_credit.category_name
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -0,0 +1,55 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ class StoreSerializer < V3::BaseSerializer
6
+ typelize name: :string, url: :string,
7
+ default_currency: :string, default_locale: :string,
8
+ supported_currencies: [:string, multi: true],
9
+ supported_locales: [:string, multi: true],
10
+ logo_url: [:string, nullable: true],
11
+ mailer_logo_url: [:string, nullable: true],
12
+ mail_from_address: [:string, nullable: true],
13
+ customer_support_email: [:string, nullable: true],
14
+ new_order_notifications_email: [:string, nullable: true],
15
+ preferred_send_consumer_transactional_emails: :boolean,
16
+ preferred_admin_locale: [:string, nullable: true],
17
+ preferred_timezone: :string,
18
+ preferred_weight_unit: :string,
19
+ preferred_unit_system: :string,
20
+ metadata: 'Record<string, unknown>'
21
+
22
+ attributes :metadata,
23
+ :name,
24
+ :default_currency,
25
+ :default_locale,
26
+ :mail_from_address,
27
+ :customer_support_email,
28
+ :new_order_notifications_email,
29
+ :preferred_send_consumer_transactional_emails,
30
+ :preferred_admin_locale,
31
+ :preferred_timezone,
32
+ :preferred_weight_unit,
33
+ :preferred_unit_system,
34
+ created_at: :iso8601, updated_at: :iso8601
35
+
36
+ attribute :url, &:storefront_url
37
+
38
+ attribute :supported_currencies do |store|
39
+ store.supported_currencies_list.map(&:iso_code)
40
+ end
41
+
42
+ attribute :supported_locales, &:supported_locales_list
43
+
44
+ attribute :logo_url do |store|
45
+ image_url_for(store.logo)
46
+ end
47
+
48
+ attribute :mailer_logo_url do |store|
49
+ image_url_for(store.mailer_logo)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -3,10 +3,12 @@ module Spree
3
3
  module V3
4
4
  module Admin
5
5
  class TaxCategorySerializer < V3::BaseSerializer
6
- typelize name: :string, tax_code: [:string, nullable: true],
6
+ typelize name: :string,
7
+ tax_code: [:string, nullable: true],
8
+ description: [:string, nullable: true],
7
9
  is_default: :boolean
8
10
 
9
- attributes :name, :tax_code, :is_default,
11
+ attributes :name, :tax_code, :description, :is_default,
10
12
  created_at: :iso8601, updated_at: :iso8601
11
13
  end
12
14
  end
@@ -6,16 +6,43 @@ module Spree
6
6
  # Full variant data including admin-only fields
7
7
  class VariantSerializer < V3::VariantSerializer
8
8
 
9
- # Additional type hints for admin-only attributes
10
- typelize position: :number, tax_category_id: [:string, nullable: true],
9
+ typelize product_name: :string,
10
+ position: :number, tax_category_id: [:string, nullable: true],
11
11
  cost_price: [:string, nullable: true], cost_currency: [:string, nullable: true],
12
- total_on_hand: [:number, nullable: true],
13
- deleted_at: [:string, nullable: true]
12
+ barcode: [:string, nullable: true],
13
+ weight_unit: [:string, nullable: true], dimensions_unit: [:string, nullable: true],
14
+ available_stock: [:number, nullable: true],
15
+ reserved_quantity: :number, total_on_hand: [:number, nullable: true],
16
+ deleted_at: [:string, nullable: true],
17
+ metadata: 'Record<string, unknown>'
14
18
 
15
- # Admin-only attributes
16
- attributes :position, :total_on_hand, :tax_category_id, :cost_price, :cost_currency, deleted_at: :iso8601,
19
+ attributes :metadata, :position, :cost_price, :cost_currency,
20
+ :barcode, :weight_unit, :dimensions_unit, deleted_at: :iso8601,
17
21
  created_at: :iso8601, updated_at: :iso8601
18
22
 
23
+ attribute :tax_category_id do |variant|
24
+ variant.tax_category&.prefixed_id
25
+ end
26
+
27
+ # Physical pool minus already-allocated units. In 5.5 allocated_count
28
+ # is always 0, so this equals SUM(stock_items.count_on_hand).
29
+ attribute :available_stock do |variant|
30
+ variant.available_stock.to_i if variant.should_track_inventory?
31
+ end
32
+
33
+ attribute :reserved_quantity do |variant|
34
+ variant.reserved_quantity.to_i
35
+ end
36
+
37
+ # Purchasable now: available_stock minus active reservations.
38
+ attribute :total_on_hand do |variant|
39
+ variant.total_on_hand.to_i if variant.should_track_inventory?
40
+ end
41
+
42
+ attribute :product_name do |variant|
43
+ variant.product&.name
44
+ end
45
+
19
46
  # Override inherited associations to use admin serializers
20
47
  one :primary_media,
21
48
  resource: Spree.api.admin_media_serializer,
@@ -37,6 +64,10 @@ module Spree
37
64
  key: :custom_fields,
38
65
  resource: Spree.api.admin_custom_field_serializer,
39
66
  if: proc { expand?('custom_fields') }
67
+
68
+ many :stock_items,
69
+ resource: Spree.api.admin_stock_item_serializer,
70
+ if: proc { expand?('stock_items') }
40
71
  end
41
72
  end
42
73
  end