spree_api 5.4.3 → 5.5.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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +19 -0
  3. data/app/controllers/concerns/spree/api/v3/admin/auth_cookies.rb +62 -0
  4. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +149 -0
  5. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +54 -0
  6. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +103 -0
  7. data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +60 -0
  8. data/app/controllers/concerns/spree/api/v3/error_handler.rb +4 -0
  9. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +84 -0
  10. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +88 -0
  11. data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +35 -1
  12. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +97 -0
  13. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +25 -0
  14. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +55 -0
  15. data/app/controllers/spree/api/v3/admin/auth_controller.rb +134 -0
  16. data/app/controllers/spree/api/v3/admin/base_controller.rb +3 -17
  17. data/app/controllers/spree/api/v3/admin/categories_controller.rb +25 -0
  18. data/app/controllers/spree/api/v3/admin/channels_controller.rb +65 -0
  19. data/app/controllers/spree/api/v3/admin/countries_controller.rb +38 -0
  20. data/app/controllers/spree/api/v3/admin/coupon_codes_controller.rb +33 -0
  21. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +34 -0
  22. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +108 -0
  23. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +31 -0
  24. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +88 -0
  25. data/app/controllers/spree/api/v3/admin/customers/credit_cards_controller.rb +31 -0
  26. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +93 -0
  27. data/app/controllers/spree/api/v3/admin/customers_controller.rb +119 -0
  28. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +44 -0
  29. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +40 -0
  30. data/app/controllers/spree/api/v3/admin/exports_controller.rb +89 -0
  31. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +31 -0
  32. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +33 -0
  33. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +138 -0
  34. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +70 -0
  35. data/app/controllers/spree/api/v3/admin/markets_controller.rb +42 -0
  36. data/app/controllers/spree/api/v3/admin/me_controller.rb +69 -0
  37. data/app/controllers/spree/api/v3/admin/media_controller.rb +119 -0
  38. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +34 -0
  39. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +27 -0
  40. data/app/controllers/spree/api/v3/admin/orders/base_controller.rb +26 -0
  41. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +104 -0
  42. data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +79 -0
  43. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +92 -0
  44. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +90 -0
  45. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +53 -0
  46. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +59 -0
  47. data/app/controllers/spree/api/v3/admin/orders_controller.rb +190 -0
  48. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +73 -0
  49. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +156 -0
  50. data/app/controllers/spree/api/v3/admin/prices_controller.rb +129 -0
  51. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +48 -0
  52. data/app/controllers/spree/api/v3/admin/products_controller.rb +237 -0
  53. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +78 -0
  54. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +56 -0
  55. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +78 -0
  56. data/app/controllers/spree/api/v3/admin/resource_controller.rb +29 -11
  57. data/app/controllers/spree/api/v3/admin/roles_controller.rb +29 -0
  58. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +35 -0
  59. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +36 -0
  60. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +29 -0
  61. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +75 -0
  62. data/app/controllers/spree/api/v3/admin/store_controller.rb +53 -0
  63. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +21 -0
  64. data/app/controllers/spree/api/v3/admin/tags_controller.rb +51 -0
  65. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +21 -0
  66. data/app/controllers/spree/api/v3/admin/variants_controller.rb +33 -0
  67. data/app/controllers/spree/api/v3/admin/webhook_deliveries_controller.rb +49 -0
  68. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +75 -0
  69. data/app/controllers/spree/api/v3/resource_controller.rb +90 -8
  70. data/app/controllers/spree/api/v3/store/auth_controller.rb +8 -28
  71. data/app/controllers/spree/api/v3/store/base_controller.rb +6 -0
  72. data/app/controllers/spree/api/v3/store/carts_controller.rb +1 -0
  73. data/app/controllers/spree/api/v3/store/customers_controller.rb +6 -0
  74. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +77 -0
  75. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +2 -2
  76. data/app/controllers/spree/api/v3/store/products_controller.rb +3 -3
  77. data/app/controllers/spree/api/v3/store/resource_controller.rb +10 -2
  78. data/app/jobs/spree/webhook_delivery_job.rb +5 -0
  79. data/app/models/spree/api_key_ability.rb +16 -0
  80. data/app/serializers/spree/api/v3/admin/address_serializer.rb +2 -6
  81. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +3 -15
  82. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +19 -3
  83. data/app/serializers/spree/api/v3/admin/allowed_origin_serializer.rb +2 -6
  84. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +42 -0
  85. data/app/serializers/spree/api/v3/admin/category_serializer.rb +4 -3
  86. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -0
  87. data/app/serializers/spree/api/v3/admin/country_serializer.rb +1 -1
  88. data/app/serializers/spree/api/v3/admin/coupon_code_serializer.rb +30 -0
  89. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +4 -2
  90. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +21 -0
  91. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +8 -3
  92. data/app/serializers/spree/api/v3/admin/customer_group_serializer.rb +27 -0
  93. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +58 -2
  94. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +143 -0
  95. data/app/serializers/spree/api/v3/admin/export_serializer.rb +40 -0
  96. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +2 -6
  97. data/app/serializers/spree/api/v3/admin/{asset_serializer.rb → gift_card_batch_serializer.rb} +1 -1
  98. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +39 -4
  99. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +64 -0
  100. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +4 -16
  101. data/app/serializers/spree/api/v3/admin/media_serializer.rb +24 -2
  102. data/app/serializers/spree/api/v3/admin/option_type_serializer.rb +4 -1
  103. data/app/serializers/spree/api/v3/admin/option_value_serializer.rb +4 -1
  104. data/app/serializers/spree/api/v3/admin/order_serializer.rb +21 -6
  105. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +11 -2
  106. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +2 -6
  107. data/app/serializers/spree/api/v3/admin/payment_source_serializer.rb +4 -1
  108. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +51 -0
  109. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +55 -0
  110. data/app/serializers/spree/api/v3/admin/price_serializer.rb +4 -0
  111. data/app/serializers/spree/api/v3/admin/product_publication_serializer.rb +11 -0
  112. data/app/serializers/spree/api/v3/admin/product_serializer.rb +34 -10
  113. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +71 -0
  114. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +85 -0
  115. data/app/serializers/spree/api/v3/admin/promotion_serializer.rb +41 -0
  116. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +4 -2
  117. data/app/serializers/spree/api/v3/admin/role_serializer.rb +17 -0
  118. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +16 -1
  119. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +11 -2
  120. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +46 -0
  121. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +37 -0
  122. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +19 -0
  123. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +11 -5
  124. data/app/serializers/spree/api/v3/admin/store_serializer.rb +55 -0
  125. data/app/serializers/spree/api/v3/admin/tax_category_serializer.rb +4 -2
  126. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +37 -6
  127. data/app/serializers/spree/api/v3/admin/webhook_delivery_serializer.rb +45 -0
  128. data/app/serializers/spree/api/v3/admin/webhook_endpoint_serializer.rb +69 -0
  129. data/app/serializers/spree/api/v3/channel_serializer.rb +14 -0
  130. data/app/serializers/spree/api/v3/custom_field_serializer.rb +9 -10
  131. data/app/serializers/spree/api/v3/customer_serializer.rb +5 -0
  132. data/app/serializers/spree/api/v3/market_serializer.rb +2 -1
  133. data/app/serializers/spree/api/v3/media_serializer.rb +8 -6
  134. data/app/serializers/spree/api/v3/order_serializer.rb +6 -1
  135. data/app/serializers/spree/api/v3/payment_method_serializer.rb +11 -2
  136. data/app/serializers/spree/api/v3/product_publication_serializer.rb +22 -0
  137. data/app/serializers/spree/api/v3/product_serializer.rb +6 -1
  138. data/app/serializers/spree/api/v3/stock_reservation_serializer.rb +10 -0
  139. data/config/locales/en.yml +2 -0
  140. data/config/routes.rb +235 -1
  141. data/lib/spree/api/configuration.rb +2 -2
  142. data/lib/spree/api/dependencies.rb +25 -1
  143. data/lib/spree/api/openapi/path_sorter.rb +126 -0
  144. data/lib/spree/api/openapi/schema_helper.rb +185 -6
  145. metadata +96 -8
  146. data/app/serializers/spree/api/v3/admin/shipping_category_serializer.rb +0 -14
@@ -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
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ module V3
6
+ module Admin
7
+ # Admin API serializer for {Spree::WebhookDelivery}.
8
+ #
9
+ # Surface the delivery log so admins can audit + retry failed webhook
10
+ # attempts. Includes the request payload + response body so they can
11
+ # inspect what was sent and what the endpoint returned.
12
+ class WebhookDeliverySerializer < V3::BaseSerializer
13
+ typelize event_name: :string,
14
+ event_id: [:string, nullable: true],
15
+ response_code: [:number, nullable: true],
16
+ execution_time: [:number, nullable: true],
17
+ error_type: [:string, nullable: true],
18
+ request_errors: [:string, nullable: true],
19
+ response_body: [:string, nullable: true],
20
+ success: [:boolean, nullable: true],
21
+ delivered_at: [:string, nullable: true],
22
+ payload: 'Record<string, unknown>',
23
+ webhook_endpoint_id: :string,
24
+ webhook_endpoint_url: :string
25
+
26
+ attributes :event_name, :event_id, :response_code, :execution_time,
27
+ :error_type, :request_errors, :response_body, :success,
28
+ :payload,
29
+ created_at: :iso8601, updated_at: :iso8601,
30
+ delivered_at: :iso8601
31
+
32
+ attribute :webhook_endpoint_id do |delivery|
33
+ delivery.webhook_endpoint&.prefixed_id
34
+ end
35
+
36
+ # Delegated from the parent endpoint — saves callers from having to
37
+ # join the endpoint payload to show "where did this delivery go?".
38
+ attribute :webhook_endpoint_url do |delivery|
39
+ delivery.webhook_endpoint&.url
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spree
4
+ module Api
5
+ module V3
6
+ module Admin
7
+ # Admin API serializer for {Spree::WebhookEndpoint}.
8
+ #
9
+ # Never exposes `secret_key` outside of the create response (encrypted
10
+ # at rest, plaintext only in memory after generation). The full secret
11
+ # is delivered exactly once via {#secret_key} below — `nil` everywhere
12
+ # else.
13
+ class WebhookEndpointSerializer < V3::BaseSerializer
14
+ typelize name: [:string, nullable: true],
15
+ url: :string,
16
+ active: :boolean,
17
+ subscriptions: [:string, multi: true],
18
+ secret_key: [:string, nullable: true],
19
+ disabled_at: [:string, nullable: true],
20
+ disabled_reason: [:string, nullable: true],
21
+ last_delivery_at: [:string, nullable: true],
22
+ recent_delivery_count: :number,
23
+ recent_failure_count: :number,
24
+ total_delivery_count: :number,
25
+ successful_delivery_count: :number,
26
+ failed_delivery_count: :number
27
+
28
+ attributes :name, :url, :active, :subscriptions,
29
+ :disabled_reason,
30
+ created_at: :iso8601, updated_at: :iso8601,
31
+ disabled_at: :iso8601
32
+
33
+ # Plaintext on the create response only — the model owns the
34
+ # "fresh-from-create" rule via `secret_key_for_response`. Every
35
+ # subsequent read serializes nil.
36
+ attribute :secret_key, &:secret_key_for_response
37
+
38
+ attribute :last_delivery_at do |endpoint|
39
+ value = endpoint.webhook_deliveries.maximum(:delivered_at)
40
+ value.respond_to?(:iso8601) ? value.iso8601 : value
41
+ end
42
+
43
+ attribute :recent_delivery_count do |endpoint|
44
+ endpoint.webhook_deliveries.where(created_at: 7.days.ago..).count
45
+ end
46
+
47
+ attribute :recent_failure_count do |endpoint|
48
+ endpoint.webhook_deliveries.where(created_at: 7.days.ago.., success: false).count
49
+ end
50
+
51
+ # Lifetime totals — back the health summary panel on the endpoint
52
+ # detail sheet (success % over all deliveries, like the legacy admin's
53
+ # `_summary.html.erb`).
54
+ attribute :total_delivery_count do |endpoint|
55
+ endpoint.webhook_deliveries.count
56
+ end
57
+
58
+ attribute :successful_delivery_count do |endpoint|
59
+ endpoint.webhook_deliveries.successful.count
60
+ end
61
+
62
+ attribute :failed_delivery_count do |endpoint|
63
+ endpoint.webhook_deliveries.failed.count
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ class ChannelSerializer < BaseSerializer
5
+ typelize name: :string,
6
+ code: :string,
7
+ active: :boolean,
8
+ default: :boolean
9
+
10
+ attributes :name, :code, :active, :default
11
+ end
12
+ end
13
+ end
14
+ end
@@ -2,19 +2,18 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  # Store API Custom Field Serializer
5
- # Customer-facing custom field data (public metafields only)
5
+ # Customer-facing custom field data (storefront-visible only)
6
6
  class CustomFieldSerializer < BaseSerializer
7
- typelize key: :string, label: :string, type: :string, value: :any
7
+ typelize key: :string,
8
+ label: :string,
9
+ type: [:string, deprecated: 'Use `field_type` instead. The legacy `type` field returns the Ruby STI class name (e.g. `Spree::Metafields::ShortText`) and will be removed in a future minor.'],
10
+ field_type: Spree::Metafield::FIELD_TYPE_TOKENS,
11
+ value: :any
8
12
 
9
- attributes :label, :type
13
+ attributes :label, :type, :field_type
10
14
 
11
- attribute :key do |metafield|
12
- metafield.full_key
13
- end
14
-
15
- attribute :value do |metafield|
16
- metafield.serialize_value
17
- end
15
+ attribute :key, &:full_key
16
+ attribute :value, &:serialize_value
18
17
  end
19
18
  end
20
19
  end
@@ -5,12 +5,17 @@ module Spree
5
5
  # Customer-facing user data
6
6
  class CustomerSerializer < BaseSerializer
7
7
  typelize email: :string, first_name: [:string, nullable: true], last_name: [:string, nullable: true],
8
+ full_name: :string,
8
9
  phone: [:string, nullable: true], accepts_email_marketing: :boolean,
9
10
  available_store_credit_total: :string, display_available_store_credit_total: :string,
10
11
  default_billing_address: { nullable: true }, default_shipping_address: { nullable: true }
11
12
 
12
13
  attributes :email, :first_name, :last_name, :phone, :accepts_email_marketing
13
14
 
15
+ attribute :full_name do |user|
16
+ user.full_name.presence || user.email
17
+ end
18
+
14
19
  attribute :available_store_credit_total do |user, params|
15
20
  store = params&.dig(:store) || Spree::Current.store
16
21
  currency = params&.dig(:currency) || Spree::Current.currency || store&.default_currency
@@ -5,10 +5,11 @@ module Spree
5
5
  typelize name: :string, currency: :string,
6
6
  default_locale: :string,
7
7
  supported_locales: [:string, multi: true],
8
+ country_isos: [:string, multi: true],
8
9
  tax_inclusive: :boolean,
9
10
  default: :boolean
10
11
 
11
- attributes :name, :currency, :default_locale, :tax_inclusive, :default
12
+ attributes :name, :currency, :default_locale, :tax_inclusive, :default, :country_isos
12
13
 
13
14
  attribute :supported_locales do |market|
14
15
  market.supported_locales_list
@@ -19,13 +19,15 @@ module Spree
19
19
  end
20
20
 
21
21
  # Returns prefixed IDs of variants this media is associated with.
22
- # Currently: single variant via viewable (legacy). In 6.0: multiple via VariantMedia join table.
22
+ # Two paths coexist in 5.5:
23
+ # - legacy: asset.viewable IS the variant (direct upload, viewable_type 'Spree::Variant')
24
+ # - new: asset.variants — product-level asset linked via VariantMedia rows
25
+ # Both are reported so the admin can show a unified "assigned variants" list.
23
26
  attribute :variant_ids do |asset|
24
- if asset.viewable_type == 'Spree::Variant'
25
- [asset.viewable&.prefixed_id].compact
26
- else
27
- []
28
- end
27
+ ids = []
28
+ ids << asset.viewable&.prefixed_id if asset.viewable_type == 'Spree::Variant' && asset.viewable
29
+ ids.concat(asset.variants.map(&:prefixed_id)) if asset.viewable_type == 'Spree::Product'
30
+ ids.compact.uniq
29
31
  end
30
32
 
31
33
  attributes :position, :alt, :media_type,
@@ -5,7 +5,8 @@ module Spree
5
5
  # Post-purchase order data (completed orders)
6
6
  class OrderSerializer < BaseSerializer
7
7
  typelize number: :string, email: :string,
8
- customer_note: [:string, nullable: true], market_id: [:string, nullable: true],
8
+ customer_note: [:string, nullable: true],
9
+ market_id: [:string, nullable: true], channel_id: [:string, nullable: true],
9
10
  currency: :string, locale: [:string, nullable: true], total_quantity: :number,
10
11
  fulfillment_status: [:string, nullable: true], payment_status: [:string, nullable: true],
11
12
  item_total: :string, display_item_total: :string,
@@ -28,6 +29,10 @@ module Spree
28
29
  order.market&.prefixed_id
29
30
  end
30
31
 
32
+ attribute :channel_id do |order|
33
+ order.channel&.prefixed_id
34
+ end
35
+
31
36
  attributes :number, :email, :customer_note,
32
37
  :currency, :locale, :total_quantity,
33
38
  :item_total, :display_item_total,
@@ -2,13 +2,22 @@ module Spree
2
2
  module Api
3
3
  module V3
4
4
  class PaymentMethodSerializer < BaseSerializer
5
- typelize name: :string, description: [:string, nullable: true], type: :string, session_required: :boolean
5
+ typelize name: :string, description: [:string, nullable: true], type: :string,
6
+ session_required: :boolean, source_required: :boolean
6
7
 
7
- attributes :name, :description, :type
8
+ attributes :name, :description
9
+
10
+ attribute :type do |payment_method|
11
+ payment_method.class.api_type
12
+ end
8
13
 
9
14
  attribute :session_required do |payment_method|
10
15
  payment_method.session_required?
11
16
  end
17
+
18
+ attribute :source_required do |payment_method|
19
+ payment_method.source_required?
20
+ end
12
21
  end
13
22
  end
14
23
  end
@@ -0,0 +1,22 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ class ProductPublicationSerializer < BaseSerializer
5
+ typelize product_id: :string,
6
+ channel_id: :string,
7
+ published_at: [:string, nullable: true],
8
+ unpublished_at: [:string, nullable: true]
9
+
10
+ attributes published_at: :iso8601, unpublished_at: :iso8601
11
+
12
+ attribute :product_id do |publication|
13
+ publication.product&.prefixed_id
14
+ end
15
+
16
+ attribute :channel_id do |publication|
17
+ publication.channel&.prefixed_id
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -5,6 +5,7 @@ module Spree
5
5
  # Customer-facing product data with limited fields
6
6
  class ProductSerializer < BaseSerializer
7
7
  typelize name: :string, description: [:string, nullable: true], description_html: [:string, nullable: true], slug: :string,
8
+ meta_title: [:string, nullable: true],
8
9
  meta_description: [:string, nullable: true], meta_keywords: [:string, nullable: true],
9
10
  variant_count: :number,
10
11
  default_variant_id: :string,
@@ -16,7 +17,7 @@ module Spree
16
17
  tags: [:string, multi: true]
17
18
 
18
19
  attributes :name, :slug,
19
- :meta_description, :meta_keywords,
20
+ :meta_title, :meta_description, :meta_keywords,
20
21
  :variant_count,
21
22
  available_on: :iso8601
22
23
 
@@ -99,6 +100,10 @@ module Spree
99
100
  resource: Spree.api.option_type_serializer,
100
101
  if: proc { expand?('option_types') }
101
102
 
103
+ many :option_values,
104
+ resource: Spree.api.option_value_serializer,
105
+ if: proc { expand?('option_values') }
106
+
102
107
  many :taxons,
103
108
  proc { |taxons, params|
104
109
  taxons.select { |t| t.taxonomy.store_id == params[:store].id }
@@ -0,0 +1,10 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Minimal base; admin extends with full fields. Reservations have no
5
+ # customer-facing exposure today.
6
+ class StockReservationSerializer < BaseSerializer
7
+ end
8
+ end
9
+ end
10
+ end
@@ -2,6 +2,7 @@
2
2
  en:
3
3
  spree:
4
4
  api:
5
+ cannot_delete: "%{model} cannot be deleted"
5
6
  current_password_invalid: Current password is invalid or missing
6
7
  gateway_error: 'There was a problem with the payment gateway: %{text}'
7
8
  invalid_api_key: Invalid API key (%{key}) specified.
@@ -9,6 +10,7 @@ en:
9
10
  invalid_taxonomy_id: Invalid taxonomy id.
10
11
  must_specify_api_key: You must specify an API key.
11
12
  negative_quantity: quantity is negative
13
+ newsletter_verification_token_invalid: Newsletter verification token is invalid or has expired.
12
14
  order:
13
15
  could_not_transition: The order could not be transitioned. Please fix the errors and try again.
14
16
  insufficient_quantity: An item in your cart has become unavailable.