spree_api 5.6.1 → 6.0.0.beta1

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 (540) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +28 -0
  3. data/Rakefile +1 -1
  4. data/app/controllers/concerns/spree/api/v3/address_params.rb +17 -0
  5. data/app/controllers/concerns/spree/api/v3/admin/product_listing.rb +46 -0
  6. data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +110 -0
  7. data/app/controllers/concerns/spree/api/v3/admin/receivable_actions.rb +68 -0
  8. data/app/controllers/concerns/spree/api/v3/admin/reporting_authorization.rb +27 -0
  9. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +69 -33
  10. data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +86 -0
  11. data/app/controllers/concerns/spree/api/v3/admin/store_context.rb +97 -0
  12. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +12 -6
  13. data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +91 -0
  14. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +9 -5
  15. data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +41 -5
  16. data/app/controllers/concerns/spree/api/v3/authentication_strategies.rb +48 -0
  17. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +4 -6
  18. data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +52 -16
  19. data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +37 -0
  20. data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +41 -0
  21. data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +35 -0
  22. data/app/controllers/concerns/spree/api/v3/error_handler.rb +53 -11
  23. data/app/controllers/concerns/spree/api/v3/idempotent.rb +10 -4
  24. data/app/controllers/concerns/spree/api/v3/items_payload.rb +54 -0
  25. data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +23 -3
  26. data/app/controllers/concerns/spree/api/v3/key_store_context.rb +31 -0
  27. data/app/controllers/concerns/spree/api/v3/locale_and_currency.rb +3 -3
  28. data/app/controllers/concerns/spree/api/v3/order_lock.rb +22 -3
  29. data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +112 -0
  30. data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +105 -0
  31. data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +117 -0
  32. data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +157 -0
  33. data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +76 -0
  34. data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +116 -0
  35. data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +128 -0
  36. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +7 -4
  37. data/app/controllers/concerns/spree/api/v3/permission_serialization.rb +42 -0
  38. data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +40 -6
  39. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +80 -26
  40. data/app/controllers/concerns/spree/api/v3/seller/auth_cookies.rb +62 -0
  41. data/app/controllers/concerns/spree/api/v3/seller/seller_context.rb +127 -0
  42. data/app/controllers/concerns/spree/api/v3/seller_authentication.rb +40 -0
  43. data/app/controllers/concerns/spree/api/v3/storefront_access.rb +38 -0
  44. data/app/controllers/concerns/spree/api/v3/streams_shipping_label.rb +37 -0
  45. data/app/controllers/concerns/spree/api/v3/tax_identifier_validation.rb +41 -0
  46. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +11 -14
  47. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +1 -1
  48. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +16 -7
  49. data/app/controllers/spree/api/v3/admin/auth_controller.rb +138 -22
  50. data/app/controllers/spree/api/v3/admin/base_controller.rb +2 -0
  51. data/app/controllers/spree/api/v3/admin/catalog_assignments_controller.rb +27 -0
  52. data/app/controllers/spree/api/v3/admin/catalogs/base_controller.rb +29 -0
  53. data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +40 -0
  54. data/app/controllers/spree/api/v3/admin/catalogs/products_controller.rb +107 -0
  55. data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +75 -0
  56. data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +191 -0
  57. data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +28 -41
  58. data/app/controllers/spree/api/v3/admin/categories_controller.rb +16 -7
  59. data/app/controllers/spree/api/v3/admin/channels_controller.rb +50 -2
  60. data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +25 -0
  61. data/app/controllers/spree/api/v3/admin/claims_controller.rb +31 -0
  62. data/app/controllers/spree/api/v3/admin/collection_rules_controller.rb +40 -0
  63. data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +101 -0
  64. data/app/controllers/spree/api/v3/admin/collections_controller.rb +56 -0
  65. data/app/controllers/spree/api/v3/admin/commission_lines_controller.rb +39 -0
  66. data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +174 -0
  67. data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +65 -0
  68. data/app/controllers/spree/api/v3/admin/companies/base_controller.rb +29 -0
  69. data/app/controllers/spree/api/v3/admin/companies/invitations_controller.rb +56 -0
  70. data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +66 -0
  71. data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +137 -0
  72. data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +46 -0
  73. data/app/controllers/spree/api/v3/admin/companies_controller.rb +59 -0
  74. data/app/controllers/spree/api/v3/admin/concerns/external_references.rb +166 -0
  75. data/app/controllers/spree/api/v3/admin/consent_records_controller.rb +31 -0
  76. data/app/controllers/spree/api/v3/admin/countries_controller.rb +12 -4
  77. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +19 -4
  78. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +5 -5
  79. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +1 -1
  80. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +4 -4
  81. data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +1 -1
  82. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +2 -3
  83. data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +43 -0
  84. data/app/controllers/spree/api/v3/admin/customers_controller.rb +190 -11
  85. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +24 -20
  86. data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +60 -0
  87. data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +54 -0
  88. data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +114 -0
  89. data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +243 -0
  90. data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +80 -0
  91. data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +107 -0
  92. data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +116 -0
  93. data/app/controllers/spree/api/v3/admin/digital_links_controller.rb +48 -0
  94. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +17 -3
  95. data/app/controllers/spree/api/v3/admin/exchanges_controller.rb +31 -0
  96. data/app/controllers/spree/api/v3/admin/exports_controller.rb +2 -2
  97. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +1 -1
  98. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +3 -2
  99. data/app/controllers/spree/api/v3/admin/imports_controller.rb +71 -8
  100. data/app/controllers/spree/api/v3/admin/integrations_controller.rb +67 -0
  101. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +5 -5
  102. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +5 -1
  103. data/app/controllers/spree/api/v3/admin/locales_controller.rb +3 -1
  104. data/app/controllers/spree/api/v3/admin/markets_controller.rb +9 -5
  105. data/app/controllers/spree/api/v3/admin/me_controller.rb +4 -30
  106. data/app/controllers/spree/api/v3/admin/media_controller.rb +88 -38
  107. data/app/controllers/spree/api/v3/admin/media_library_controller.rb +156 -0
  108. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +1 -0
  109. data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +25 -0
  110. data/app/controllers/spree/api/v3/admin/order_groups_controller.rb +43 -0
  111. data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +1 -1
  112. data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +56 -0
  113. data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +66 -0
  114. data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +86 -0
  115. data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +99 -0
  116. data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +62 -0
  117. data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +83 -0
  118. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +45 -67
  119. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +40 -22
  120. data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +75 -0
  121. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +36 -18
  122. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +39 -18
  123. data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +70 -0
  124. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +2 -2
  125. data/app/controllers/spree/api/v3/admin/orders/tax_identifiers_controller.rb +41 -0
  126. data/app/controllers/spree/api/v3/admin/orders/tax_lines_controller.rb +32 -0
  127. data/app/controllers/spree/api/v3/admin/orders_controller.rb +157 -32
  128. data/app/controllers/spree/api/v3/admin/package_types_controller.rb +39 -0
  129. data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +1 -1
  130. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +15 -4
  131. data/app/controllers/spree/api/v3/admin/payout_providers_controller.rb +27 -0
  132. data/app/controllers/spree/api/v3/admin/permissions_controller.rb +30 -0
  133. data/app/controllers/spree/api/v3/admin/policies_controller.rb +42 -0
  134. data/app/controllers/spree/api/v3/admin/price_lists/products_controller.rb +93 -0
  135. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +43 -29
  136. data/app/controllers/spree/api/v3/admin/prices_controller.rb +41 -4
  137. data/app/controllers/spree/api/v3/admin/product_types_controller.rb +93 -0
  138. data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +148 -0
  139. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +24 -3
  140. data/app/controllers/spree/api/v3/admin/products_controller.rb +149 -33
  141. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +6 -2
  142. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +1 -1
  143. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +1 -5
  144. data/app/controllers/spree/api/v3/admin/purchase_orders/stock_receipts_controller.rb +32 -0
  145. data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +161 -0
  146. data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +25 -0
  147. data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +45 -0
  148. data/app/controllers/spree/api/v3/admin/reporting_controller.rb +95 -0
  149. data/app/controllers/spree/api/v3/admin/resource_controller.rb +27 -10
  150. data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +25 -0
  151. data/app/controllers/spree/api/v3/admin/returns_controller.rb +31 -0
  152. data/app/controllers/spree/api/v3/admin/roles_controller.rb +50 -6
  153. data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +83 -0
  154. data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +139 -0
  155. data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +115 -0
  156. data/app/controllers/spree/api/v3/admin/seller_transfers_controller.rb +36 -0
  157. data/app/controllers/spree/api/v3/admin/sellers/balances_controller.rb +44 -0
  158. data/app/controllers/spree/api/v3/admin/sellers/invitations_controller.rb +77 -0
  159. data/app/controllers/spree/api/v3/admin/sellers/payouts_controller.rb +107 -0
  160. data/app/controllers/spree/api/v3/admin/sellers/team_controller.rb +64 -0
  161. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +197 -0
  162. data/app/controllers/spree/api/v3/admin/setup_controller.rb +231 -0
  163. data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +172 -0
  164. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +3 -2
  165. data/app/controllers/spree/api/v3/admin/stock_movements_controller.rb +37 -0
  166. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +1 -1
  167. data/app/controllers/spree/api/v3/admin/stock_transfers/stock_receipts_controller.rb +31 -0
  168. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +134 -38
  169. data/app/controllers/spree/api/v3/admin/store_controller.rb +65 -0
  170. data/app/controllers/spree/api/v3/admin/store_credits/events_controller.rb +47 -0
  171. data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +87 -0
  172. data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +30 -0
  173. data/app/controllers/spree/api/v3/admin/tags_controller.rb +2 -2
  174. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +4 -0
  175. data/app/controllers/spree/api/v3/admin/tax_providers_controller.rb +25 -0
  176. data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +33 -0
  177. data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +33 -0
  178. data/app/controllers/spree/api/v3/admin/translatable_resources_controller.rb +37 -9
  179. data/app/controllers/spree/api/v3/admin/translations_controller.rb +10 -5
  180. data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +150 -0
  181. data/app/controllers/spree/api/v3/admin/variants_controller.rb +11 -4
  182. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +1 -1
  183. data/app/controllers/spree/api/v3/base_controller.rb +59 -16
  184. data/app/controllers/spree/api/v3/resource_controller.rb +154 -38
  185. data/app/controllers/spree/api/v3/seller/auth_controller.rb +169 -0
  186. data/app/controllers/spree/api/v3/seller/balances_controller.rb +35 -0
  187. data/app/controllers/spree/api/v3/seller/base_controller.rb +25 -0
  188. data/app/controllers/spree/api/v3/seller/claim_reasons_controller.rb +20 -0
  189. data/app/controllers/spree/api/v3/seller/countries_controller.rb +38 -0
  190. data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +265 -0
  191. data/app/controllers/spree/api/v3/seller/delivery_profiles_controller.rb +65 -0
  192. data/app/controllers/spree/api/v3/seller/delivery_zones_controller.rb +41 -0
  193. data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +21 -0
  194. data/app/controllers/spree/api/v3/seller/exports_controller.rb +195 -0
  195. data/app/controllers/spree/api/v3/seller/import_rows_controller.rb +49 -0
  196. data/app/controllers/spree/api/v3/seller/imports_controller.rb +317 -0
  197. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +152 -0
  198. data/app/controllers/spree/api/v3/seller/invitations_controller.rb +71 -0
  199. data/app/controllers/spree/api/v3/seller/me_controller.rb +72 -0
  200. data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +111 -0
  201. data/app/controllers/spree/api/v3/seller/order_cancellation_reasons_controller.rb +25 -0
  202. data/app/controllers/spree/api/v3/seller/orders/base_controller.rb +44 -0
  203. data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +45 -0
  204. data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +38 -0
  205. data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +50 -0
  206. data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +79 -0
  207. data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +55 -0
  208. data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +82 -0
  209. data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +44 -0
  210. data/app/controllers/spree/api/v3/seller/orders_controller.rb +199 -0
  211. data/app/controllers/spree/api/v3/seller/package_types_controller.rb +100 -0
  212. data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +155 -0
  213. data/app/controllers/spree/api/v3/seller/payouts_controller.rb +47 -0
  214. data/app/controllers/spree/api/v3/seller/policies_controller.rb +57 -0
  215. data/app/controllers/spree/api/v3/seller/product_types_controller.rb +35 -0
  216. data/app/controllers/spree/api/v3/seller/products_controller.rb +394 -0
  217. data/app/controllers/spree/api/v3/seller/profile_controller.rb +137 -0
  218. data/app/controllers/spree/api/v3/seller/reasons_controller.rb +45 -0
  219. data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +95 -0
  220. data/app/controllers/spree/api/v3/seller/resource_controller.rb +75 -0
  221. data/app/controllers/spree/api/v3/seller/return_reasons_controller.rb +20 -0
  222. data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +56 -0
  223. data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +48 -0
  224. data/app/controllers/spree/api/v3/seller/team_controller.rb +103 -0
  225. data/app/controllers/spree/api/v3/seller/tracking_carriers_controller.rb +35 -0
  226. data/app/controllers/spree/api/v3/seller/transfers_controller.rb +43 -0
  227. data/app/controllers/spree/api/v3/store/account/companies_controller.rb +42 -0
  228. data/app/controllers/spree/api/v3/store/auth_controller.rb +21 -34
  229. data/app/controllers/spree/api/v3/store/base_controller.rb +4 -0
  230. data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +24 -2
  231. data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +41 -15
  232. data/app/controllers/spree/api/v3/store/carts/items_controller.rb +53 -20
  233. data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +36 -20
  234. data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +111 -0
  235. data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +2 -2
  236. data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +96 -0
  237. data/app/controllers/spree/api/v3/store/carts_controller.rb +57 -12
  238. data/app/controllers/spree/api/v3/store/categories_controller.rb +6 -3
  239. data/app/controllers/spree/api/v3/store/collections/products_controller.rb +59 -0
  240. data/app/controllers/spree/api/v3/store/collections_controller.rb +36 -0
  241. data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +81 -0
  242. data/app/controllers/spree/api/v3/store/companies/base_controller.rb +24 -0
  243. data/app/controllers/spree/api/v3/store/companies/invitations_controller.rb +50 -0
  244. data/app/controllers/spree/api/v3/store/companies/members_controller.rb +66 -0
  245. data/app/controllers/spree/api/v3/store/companies/orders_controller.rb +28 -0
  246. data/app/controllers/spree/api/v3/store/companies_controller.rb +47 -0
  247. data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +90 -0
  248. data/app/controllers/spree/api/v3/store/countries_controller.rb +8 -6
  249. data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +3 -1
  250. data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +78 -0
  251. data/app/controllers/spree/api/v3/store/customer/digital_links_controller.rb +52 -0
  252. data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +6 -0
  253. data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +7 -3
  254. data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +3 -3
  255. data/app/controllers/spree/api/v3/store/customer/store_credits_controller.rb +0 -3
  256. data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +91 -0
  257. data/app/controllers/spree/api/v3/store/customers_controller.rb +26 -31
  258. data/app/controllers/spree/api/v3/store/data_feeds_controller.rb +11 -0
  259. data/app/controllers/spree/api/v3/store/data_request_downloads_controller.rb +58 -0
  260. data/app/controllers/spree/api/v3/store/delivery_methods_controller.rb +108 -0
  261. data/app/controllers/spree/api/v3/store/digital_links_controller.rb +105 -0
  262. data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +5 -9
  263. data/app/controllers/spree/api/v3/store/markets_controller.rb +4 -4
  264. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +8 -9
  265. data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +94 -0
  266. data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +116 -0
  267. data/app/controllers/spree/api/v3/store/orders/tax_identifiers_controller.rb +46 -0
  268. data/app/controllers/spree/api/v3/store/orders_controller.rb +12 -15
  269. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +10 -3
  270. data/app/controllers/spree/api/v3/store/products_controller.rb +25 -6
  271. data/app/controllers/spree/api/v3/store/resource_controller.rb +2 -0
  272. data/app/controllers/spree/api/v3/store/sellers_controller.rb +43 -0
  273. data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +9 -6
  274. data/app/controllers/spree/api/v3/store/wishlists_controller.rb +3 -3
  275. data/app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb +88 -0
  276. data/app/controllers/spree/api/v3/webhooks/payments_controller.rb +5 -2
  277. data/app/controllers/spree/api/v3/webhooks/payouts_controller.rb +61 -0
  278. data/app/models/spree/api/data_request_urls.rb +25 -0
  279. data/app/models/spree/api/digital_link_urls.rb +26 -0
  280. data/app/serializers/spree/api/v3/address_serializer.rb +17 -5
  281. data/app/serializers/spree/api/v3/admin/address_serializer.rb +27 -4
  282. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +13 -10
  283. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +1 -1
  284. data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +15 -0
  285. data/app/serializers/spree/api/v3/admin/cart_serializer.rb +34 -0
  286. data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +32 -0
  287. data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +23 -0
  288. data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +48 -0
  289. data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +23 -0
  290. data/app/serializers/spree/api/v3/admin/catalog_product_serializer.rb +57 -0
  291. data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +38 -0
  292. data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +37 -0
  293. data/app/serializers/spree/api/v3/admin/catalog_serializer.rb +46 -0
  294. data/app/serializers/spree/api/v3/admin/category_serializer.rb +3 -2
  295. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -1
  296. data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +16 -0
  297. data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +21 -0
  298. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +29 -0
  299. data/app/serializers/spree/api/v3/admin/collection_rule_serializer.rb +22 -0
  300. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +29 -0
  301. data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +67 -0
  302. data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +69 -0
  303. data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +61 -0
  304. data/app/serializers/spree/api/v3/admin/company_invitation_serializer.rb +15 -0
  305. data/app/serializers/spree/api/v3/admin/company_membership_serializer.rb +11 -0
  306. data/app/serializers/spree/api/v3/admin/company_serializer.rb +37 -0
  307. data/app/serializers/spree/api/v3/admin/concerns/external_references_attribute.rb +33 -0
  308. data/app/serializers/spree/api/v3/admin/consent_record_serializer.rb +28 -0
  309. data/app/serializers/spree/api/v3/admin/country_serializer.rb +2 -2
  310. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -1
  311. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +2 -2
  312. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +2 -2
  313. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +23 -22
  314. data/app/serializers/spree/api/v3/admin/dashboard_counter_serializer.rb +24 -0
  315. data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +36 -0
  316. data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +32 -0
  317. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +66 -1
  318. data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +15 -0
  319. data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +34 -0
  320. data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +65 -0
  321. data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +10 -1
  322. data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +20 -0
  323. data/app/serializers/spree/api/v3/admin/delivery_zone_member_serializer.rb +11 -0
  324. data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +29 -0
  325. data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +59 -0
  326. data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -4
  327. data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +16 -0
  328. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +35 -0
  329. data/app/serializers/spree/api/v3/admin/export_serializer.rb +20 -1
  330. data/app/serializers/spree/api/v3/admin/fee_serializer.rb +14 -0
  331. data/app/serializers/spree/api/v3/admin/freight_summary_line_serializer.rb +46 -0
  332. data/app/serializers/spree/api/v3/admin/freight_summary_serializer.rb +16 -0
  333. data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +39 -0
  334. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +31 -9
  335. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -3
  336. data/app/serializers/spree/api/v3/admin/import_serializer.rb +15 -2
  337. data/app/serializers/spree/api/v3/admin/integration_serializer.rb +32 -0
  338. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +4 -4
  339. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +19 -5
  340. data/app/serializers/spree/api/v3/admin/market_serializer.rb +5 -1
  341. data/app/serializers/spree/api/v3/admin/media_serializer.rb +50 -2
  342. data/app/serializers/spree/api/v3/admin/membership_product_serializer.rb +29 -0
  343. data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +29 -0
  344. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +50 -0
  345. data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +2 -6
  346. data/app/serializers/spree/api/v3/admin/order_serializer.rb +131 -19
  347. data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +53 -0
  348. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +8 -2
  349. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -0
  350. data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +41 -0
  351. data/app/serializers/spree/api/v3/admin/permission_serializer.rb +39 -0
  352. data/app/serializers/spree/api/v3/admin/policy_serializer.rb +11 -0
  353. data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +22 -0
  354. data/app/serializers/spree/api/v3/admin/price_list_product_serializer.rb +32 -0
  355. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +20 -8
  356. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +2 -12
  357. data/app/serializers/spree/api/v3/admin/price_serializer.rb +3 -0
  358. data/app/serializers/spree/api/v3/admin/product_serializer.rb +54 -8
  359. data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +39 -0
  360. data/app/serializers/spree/api/v3/admin/product_type_custom_field_definition_serializer.rb +44 -0
  361. data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +34 -0
  362. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +6 -12
  363. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +17 -15
  364. data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +80 -0
  365. data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +94 -0
  366. data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +27 -0
  367. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +0 -5
  368. data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +72 -0
  369. data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +16 -0
  370. data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +21 -0
  371. data/app/serializers/spree/api/v3/admin/return_serializer.rb +59 -0
  372. data/app/serializers/spree/api/v3/admin/role_serializer.rb +24 -6
  373. data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +33 -0
  374. data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +37 -0
  375. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +46 -0
  376. data/app/serializers/spree/api/v3/admin/seller_requirement_serializer.rb +68 -0
  377. data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +48 -0
  378. data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +57 -0
  379. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +92 -0
  380. data/app/serializers/spree/api/v3/admin/seller_team_member_serializer.rb +29 -0
  381. data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +53 -0
  382. data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +82 -0
  383. data/app/serializers/spree/api/v3/admin/state_serializer.rb +1 -1
  384. data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +65 -0
  385. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +20 -4
  386. data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +116 -0
  387. data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +57 -0
  388. data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +49 -0
  389. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +5 -5
  390. data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +57 -0
  391. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +36 -16
  392. data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +32 -0
  393. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +42 -7
  394. data/app/serializers/spree/api/v3/admin/store_serializer.rb +63 -1
  395. data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +39 -0
  396. data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +67 -0
  397. data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +43 -0
  398. data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +21 -0
  399. data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +49 -0
  400. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +49 -8
  401. data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +23 -0
  402. data/app/serializers/spree/api/v3/base_serializer.rb +39 -2
  403. data/app/serializers/spree/api/v3/cart_serializer.rb +90 -12
  404. data/app/serializers/spree/api/v3/category_serializer.rb +3 -3
  405. data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +50 -0
  406. data/app/serializers/spree/api/v3/claim_reason_serializer.rb +20 -0
  407. data/app/serializers/spree/api/v3/claim_serializer.rb +62 -0
  408. data/app/serializers/spree/api/v3/collection_serializer.rb +41 -0
  409. data/app/serializers/spree/api/v3/company_invitation_serializer.rb +28 -0
  410. data/app/serializers/spree/api/v3/company_membership_serializer.rb +28 -0
  411. data/app/serializers/spree/api/v3/company_serializer.rb +33 -0
  412. data/app/serializers/spree/api/v3/custom_field_serializer.rb +2 -2
  413. data/app/serializers/spree/api/v3/customer_serializer.rb +9 -1
  414. data/app/serializers/spree/api/v3/data_request_event_serializer.rb +30 -0
  415. data/app/serializers/spree/api/v3/data_request_serializer.rb +40 -0
  416. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +12 -2
  417. data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +34 -17
  418. data/app/serializers/spree/api/v3/delivery_serializer.rb +29 -0
  419. data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +29 -0
  420. data/app/serializers/spree/api/v3/delivery_zone_serializer.rb +13 -0
  421. data/app/serializers/spree/api/v3/digital_asset_serializer.rb +23 -0
  422. data/app/serializers/spree/api/v3/digital_link_serializer.rb +6 -2
  423. data/app/serializers/spree/api/v3/discount_serializer.rb +21 -7
  424. data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +53 -0
  425. data/app/serializers/spree/api/v3/exchange_serializer.rb +61 -0
  426. data/app/serializers/spree/api/v3/fee_serializer.rb +27 -0
  427. data/app/serializers/spree/api/v3/freight_summary_serializer.rb +38 -0
  428. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +28 -15
  429. data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
  430. data/app/serializers/spree/api/v3/import_row_serializer.rb +1 -1
  431. data/app/serializers/spree/api/v3/import_serializer.rb +18 -4
  432. data/app/serializers/spree/api/v3/invitation_serializer.rb +1 -1
  433. data/app/serializers/spree/api/v3/line_item_serializer.rb +18 -1
  434. data/app/serializers/spree/api/v3/market_serializer.rb +2 -2
  435. data/app/serializers/spree/api/v3/{asset_serializer.rb → media_event_serializer.rb} +4 -4
  436. data/app/serializers/spree/api/v3/media_serializer.rb +48 -7
  437. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +1 -1
  438. data/app/serializers/spree/api/v3/option_type_serializer.rb +1 -1
  439. data/app/serializers/spree/api/v3/order_group_serializer.rb +60 -0
  440. data/app/serializers/spree/api/v3/order_serializer.rb +58 -6
  441. data/app/serializers/spree/api/v3/payment_method_serializer.rb +1 -1
  442. data/app/serializers/spree/api/v3/payment_serializer.rb +2 -6
  443. data/app/serializers/spree/api/v3/payment_session_serializer.rb +10 -3
  444. data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +1 -1
  445. data/app/serializers/spree/api/v3/policy_serializer.rb +7 -2
  446. data/app/serializers/spree/api/v3/product_filter_option_serializer.rb +1 -1
  447. data/app/serializers/spree/api/v3/product_serializer.rb +42 -10
  448. data/app/serializers/spree/api/v3/product_type_serializer.rb +17 -0
  449. data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +11 -0
  450. data/app/serializers/spree/api/v3/refund_serializer.rb +9 -3
  451. data/app/serializers/spree/api/v3/return_line_item_serializer.rb +42 -0
  452. data/app/serializers/spree/api/v3/return_reason_serializer.rb +20 -0
  453. data/app/serializers/spree/api/v3/return_serializer.rb +62 -0
  454. data/app/serializers/spree/api/v3/seller/balance_serializer.rb +35 -0
  455. data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +21 -0
  456. data/app/serializers/spree/api/v3/seller/claim_serializer.rb +25 -0
  457. data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +32 -0
  458. data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +59 -0
  459. data/app/serializers/spree/api/v3/seller/delivery_profile_serializer.rb +26 -0
  460. data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +35 -0
  461. data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +17 -0
  462. data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +26 -0
  463. data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +29 -0
  464. data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +30 -0
  465. data/app/serializers/spree/api/v3/seller/export_serializer.rb +44 -0
  466. data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +43 -0
  467. data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +76 -0
  468. data/app/serializers/spree/api/v3/seller/import_mapping_serializer.rb +20 -0
  469. data/app/serializers/spree/api/v3/seller/import_row_serializer.rb +17 -0
  470. data/app/serializers/spree/api/v3/seller/import_serializer.rb +77 -0
  471. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +29 -0
  472. data/app/serializers/spree/api/v3/seller/media_serializer.rb +26 -0
  473. data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +44 -0
  474. data/app/serializers/spree/api/v3/seller/order_serializer.rb +119 -0
  475. data/app/serializers/spree/api/v3/seller/package_type_serializer.rb +52 -0
  476. data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +34 -0
  477. data/app/serializers/spree/api/v3/seller/payout_serializer.rb +36 -0
  478. data/app/serializers/spree/api/v3/seller/policy_serializer.rb +11 -0
  479. data/app/serializers/spree/api/v3/seller/product_serializer.rb +60 -0
  480. data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +30 -0
  481. data/app/serializers/spree/api/v3/seller/product_type_serializer.rb +29 -0
  482. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +77 -0
  483. data/app/serializers/spree/api/v3/seller/reason_serializer.rb +24 -0
  484. data/app/serializers/spree/api/v3/seller/requirement_custom_field_serializer.rb +36 -0
  485. data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +62 -0
  486. data/app/serializers/spree/api/v3/seller/requirement_submission_serializer.rb +33 -0
  487. data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +24 -0
  488. data/app/serializers/spree/api/v3/seller/return_serializer.rb +51 -0
  489. data/app/serializers/spree/api/v3/seller/shipping_label_serializer.rb +23 -0
  490. data/app/serializers/spree/api/v3/seller/stock_level_serializer.rb +27 -0
  491. data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +17 -0
  492. data/app/serializers/spree/api/v3/seller/tax_identifier_serializer.rb +15 -0
  493. data/app/serializers/spree/api/v3/seller/team_member_serializer.rb +22 -0
  494. data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +49 -0
  495. data/app/serializers/spree/api/v3/seller/variant_serializer.rb +71 -0
  496. data/app/serializers/spree/api/v3/seller_serializer.rb +50 -0
  497. data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +11 -0
  498. data/app/serializers/spree/api/v3/{stock_item_serializer.rb → stock_level_serializer.rb} +5 -5
  499. data/app/serializers/spree/api/v3/stock_location_serializer.rb +11 -7
  500. data/app/serializers/spree/api/v3/stock_movement_serializer.rb +8 -15
  501. data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +11 -0
  502. data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +6 -6
  503. data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +29 -0
  504. data/app/serializers/spree/api/v3/supplier_event_serializer.rb +11 -0
  505. data/app/serializers/spree/api/v3/tax_identifier_serializer.rb +15 -0
  506. data/app/serializers/spree/api/v3/tax_line_serializer.rb +37 -0
  507. data/app/serializers/spree/api/v3/variant_serializer.rb +52 -2
  508. data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +6 -6
  509. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  510. data/app/services/spree/api/v3/filters_aggregator.rb +14 -12
  511. data/app/services/spree/webhooks/deliver_webhook.rb +62 -26
  512. data/app/subscribers/spree/webhook_event_subscriber.rb +9 -5
  513. data/config/brakeman.ignore +1 -1
  514. data/config/initializers/typelizer.rb +51 -4
  515. data/config/locales/en.yml +5 -0
  516. data/config/routes.rb +730 -22
  517. data/lib/spree/api/configuration.rb +2 -7
  518. data/lib/spree/api/dependencies.rb +173 -227
  519. data/lib/spree/api/openapi/schema_helper.rb +179 -13
  520. data/lib/spree/api/testing_support/v3/base.rb +45 -15
  521. data/lib/spree/api.rb +10 -4
  522. data/lib/typelizer/open_enums.rb +35 -0
  523. metadata +341 -27
  524. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +0 -25
  525. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +0 -42
  526. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +0 -21
  527. data/app/controllers/spree/api/v3/store/digitals_controller.rb +0 -38
  528. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +0 -24
  529. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +0 -143
  530. data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +0 -15
  531. data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +0 -19
  532. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +0 -34
  533. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +0 -19
  534. data/app/serializers/spree/api/v3/customer_return_serializer.rb +0 -17
  535. data/app/serializers/spree/api/v3/digital_serializer.rb +0 -17
  536. data/app/serializers/spree/api/v3/reimbursement_serializer.rb +0 -27
  537. data/app/serializers/spree/api/v3/report_serializer.rb +0 -34
  538. data/app/serializers/spree/api/v3/return_authorization_serializer.rb +0 -31
  539. data/app/serializers/spree/api/v3/return_item_serializer.rb +0 -53
  540. data/app/serializers/spree/api/v3/shipping_category_serializer.rb +0 -11
@@ -50,20 +50,25 @@ module Spree
50
50
  end
51
51
 
52
52
  # Per-parent scope check: reading a product's translations needs
53
- # `read_products`, a category's `read_categories`, etc.
53
+ # `read_products`, a category's `read_categories`, etc. The parent
54
+ # class resolves to its owning catalog resource (an option type's
55
+ # translations ride the `products` permission), falling back to the
56
+ # pluralized route segment for classes outside the catalog.
54
57
  def scoped_resource_name
55
- parent_lookup&.segment&.pluralize&.to_sym
58
+ return unless parent_lookup
59
+
60
+ Spree::Translations.permission_resource_name(parent_lookup.klass)
56
61
  end
57
62
 
58
63
  # Translatable by class hierarchy, not strict equality, so a subclass
59
- # instance (e.g. Spree::Category < Spree::Taxon) passes when its base
64
+ # instance (e.g. Spree::Category < Spree::Category) passes when its base
60
65
  # is registered.
61
66
  def ensure_translatable!
62
67
  # Compare by class NAME, not object identity: in dev the registry is
63
68
  # populated at boot, but the model constants are reloaded on edits,
64
69
  # so `is_a?(registered_class)` fails against a stale class object even
65
70
  # when @parent's live class (or an ancestor) matches by name. Walk the
66
- # ancestor names so a subclass (Spree::Category < Spree::Taxon) passes.
71
+ # ancestor names so a subclass (Spree::Category < Spree::Category) passes.
67
72
  registered = Spree.translatable_resources.map(&:name).to_set
68
73
  translatable = @parent.class.ancestors.any? { |ancestor| registered.include?(ancestor.name) }
69
74
  raise ActiveRecord::RecordNotFound unless translatable
@@ -78,7 +83,7 @@ module Spree
78
83
  def parent_route_map
79
84
  @parent_route_map ||= Spree.translatable_resources.each_with_object({}) do |klass, m|
80
85
  m[klass.model_name.element.to_s] = klass.name
81
- end.merge('category' => 'Spree::Taxon')
86
+ end.merge('category' => 'Spree::Category')
82
87
  end
83
88
 
84
89
  def parent_lookup
@@ -0,0 +1,150 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Translation coverage across a whole resource type: per-locale totals
6
+ # plus a paginated page of records carrying how many of their fields are
7
+ # translated in each locale. Drives the centralized Translations page.
8
+ #
9
+ # Registry-driven like the rest of this surface — `resource_type` names
10
+ # any member of Spree.translatable_resources, so a new translatable
11
+ # model needs no code here.
12
+ class TranslationsCoverageController < ResourceController
13
+ # GET /api/v3/admin/translations?resource_type=product
14
+ def index
15
+ records = collection
16
+ locales = translatable_locales
17
+
18
+ render json: {
19
+ data: {
20
+ 'resource_type' => Spree::Translations.public_resource_type(model_class),
21
+ 'default_locale' => current_store.default_locale,
22
+ 'locales' => locales,
23
+ 'field_count' => model_class.public_translatable_fields.size,
24
+ 'search_field' => search_field,
25
+ 'coverage' => Spree::Translations.coverage_for(scope, model_class, locales),
26
+ 'records' => serialize_records(records, locales)
27
+ },
28
+ meta: collection_meta(records)
29
+ }
30
+ end
31
+
32
+ protected
33
+
34
+ # Resolved from the required `resource_type` param. An unknown or
35
+ # untranslatable type is a 404 rather than a 500 from a nil class.
36
+ def model_class
37
+ @model_class ||=
38
+ Spree::Translations.resource_class(params[:resource_type]) ||
39
+ raise(ActiveRecord::RecordNotFound, "Unknown translatable resource type: #{params[:resource_type]}")
40
+ end
41
+
42
+ # Reading a product's coverage needs `read_products`, a category's
43
+ # `read_categories` — the same per-parent rule the per-resource
44
+ # translations endpoint applies.
45
+ def scoped_resource_name
46
+ return :settings if params[:resource_type].blank?
47
+
48
+ Spree::Translations.permission_resource_name(model_class)
49
+ end
50
+
51
+ # Store-scoped by the model itself, then ability-filtered the way the
52
+ # admin base class does so a host app's record-level rules still bind.
53
+ # Memoized: `index` reaches this for the paginated page and again for
54
+ # the store-wide totals, and rebuilding it re-runs the ability filter
55
+ # each time.
56
+ def scope
57
+ @scope ||= model_class.translatable_scope(current_store).
58
+ accessible_by(current_ability, ability_action_for_request)
59
+ end
60
+
61
+ # Coverage itself reads the translation tables in one grouped query,
62
+ # so nothing needs eager-loading for it. The per-row label is a
63
+ # different matter: it is normally answered from the record's own
64
+ # column, but `always_use_translations` sends even the default locale
65
+ # through the translation table, which without a preload is a query
66
+ # per row.
67
+ def collection_includes
68
+ Spree.always_use_translations? ? [:translations] : []
69
+ end
70
+
71
+ # The grid sends a plain `search` term and lets the server choose the
72
+ # predicate, since which one a model whitelists varies (`name` on
73
+ # products and categories, nothing usable on collections).
74
+ def ransack_params
75
+ term = params[:search].presence
76
+ field = search_field
77
+ return super unless term && field
78
+
79
+ super.to_h.merge(field => term)
80
+ end
81
+
82
+ private
83
+
84
+ # The Ransack predicate the client may filter this grid by, or nil
85
+ # when the model whitelists nothing usable. Reported rather than
86
+ # assumed: `name` is ransackable on products and categories but not
87
+ # on collections, and a client guessing `name_cont` either errors or
88
+ # silently returns the unfiltered list.
89
+ #
90
+ # @return [String, nil]
91
+ # The predicate the grid filters by. It has to match the column the
92
+ # grid DISPLAYS, which is the record's first public translatable
93
+ # field — for an option type that is `label`, while `name` holds a
94
+ # slug. Searching `name` there means typing the visible label
95
+ # ("Shirt Size") returns nothing.
96
+ #
97
+ # Falls back to `name` when the displayed column is not ransackable,
98
+ # since Ransack's defaults always carry it.
99
+ #
100
+ # @return [String, nil]
101
+ def search_field
102
+ return @search_field if defined?(@search_field)
103
+
104
+ attributes = model_class.ransackable_attributes
105
+ column = displayed_column
106
+ field = [column, 'name'].compact.find { |candidate| attributes.include?(candidate) }
107
+ @search_field = field && "#{field}_cont"
108
+ end
109
+
110
+ # The internal column behind the record's displayed label, resolving
111
+ # any public-name alias.
112
+ #
113
+ # @return [String, nil]
114
+ def displayed_column
115
+ public_field = model_class.public_translatable_fields.first
116
+ return if public_field.nil?
117
+
118
+ (model_class.translatable_field_aliases[public_field] || public_field).to_s
119
+ end
120
+
121
+ def translatable_locales
122
+ Spree::Translations.non_default_locales(current_store)
123
+ end
124
+
125
+ # Each record carries its identifying label (whatever its first
126
+ # translatable field is — `name` for most, `label` for option types)
127
+ # read in the default locale, so the grid needs no second request.
128
+ def serialize_records(records, locales)
129
+ counts = Spree::Translations.translated_counts(records, model_class, locales)
130
+ label_field = model_class.public_translatable_fields.first
131
+
132
+ Mobility.with_locale(current_store.default_locale) do
133
+ records.map do |record|
134
+ {
135
+ 'id' => record.prefixed_id,
136
+ 'label' => record.public_send(label_field),
137
+ 'locales' => locales.index_with { |locale| counts.dig(record.id, locale).to_i }
138
+ }
139
+ end
140
+ end
141
+ end
142
+
143
+ def action_kind
144
+ 'read'
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
@@ -15,15 +15,22 @@ module Spree
15
15
  Spree.api.admin_variant_serializer
16
16
  end
17
17
 
18
+ # Chains onto the base scope rather than replacing it: building the
19
+ # relation from scratch dropped `scope_includes`, so every listed
20
+ # variant fell back to per-row price and stock queries.
18
21
  def scope
19
- current_store.variants.eligible.accessible_by(current_ability, ability_action_for_request)
22
+ super.eligible.accessible_by(current_ability, ability_action_for_request)
20
23
  end
21
24
 
25
+ # `active_stock_reservations` rides along with the stock levels:
26
+ # without it the quantifier falls back to a SUM per variant, which
27
+ # is the whole cost of listing variants.
22
28
  def scope_includes
23
29
  [
24
- :prices, stock_items: :stock_location,
25
- option_values: :option_type,
26
- primary_media: [attachment_attachment: :blob]
30
+ :prices,
31
+ { stock_levels: [:stock_location, :active_stock_reservations] },
32
+ { option_values: :option_type },
33
+ { primary_media: [{ attachment_attachment: :blob }, { poster_attachment: :blob }] }
27
34
  ]
28
35
  end
29
36
  end
@@ -66,7 +66,7 @@ module Spree
66
66
  end
67
67
 
68
68
  def permitted_params
69
- params.permit(:name, :url, :active, subscriptions: [])
69
+ params.permit(*model_additional_permitted_attributes, :name, :url, :active, subscriptions: [])
70
70
  end
71
71
  end
72
72
  end
@@ -7,7 +7,6 @@ module Spree
7
7
 
8
8
  include ActiveStorage::SetCurrent
9
9
  include CanCan::ControllerAdditions
10
- include Spree::Core::ControllerHelpers::StrongParameters
11
10
  include Spree::Core::ControllerHelpers::Store
12
11
  include Spree::Api::V3::LocaleAndCurrency
13
12
  include Spree::Api::V3::JwtAuthentication
@@ -19,31 +18,75 @@ module Spree
19
18
  include Spree::Api::V3::Idempotent
20
19
  include Pagy::Method
21
20
 
22
- RATE_LIMIT_RESPONSE = -> {
23
- limit = Spree::Api::Config[:rate_limit_per_key]
24
- window = Spree::Api::Config[:rate_limit_window]
25
- body = { error: { code: 'rate_limit_exceeded', message: 'Too many requests. Please retry later.' } }
26
- headers = {
27
- 'Content-Type' => 'application/json',
28
- 'Retry-After' => window.to_s,
29
- 'X-RateLimit-Limit' => limit.to_s,
30
- 'X-RateLimit-Remaining' => '0'
31
- }
32
- [429, headers, [body.to_json]]
33
- }
21
+ RATE_LIMIT_RESPONSE = -> { render_rate_limited }
22
+
23
+ # One global budget per caller (see RateLimitHeaders for the bucket
24
+ # rules); the two declarations are mutually exclusive so a request
25
+ # only ever counts against one ceiling.
26
+ rate_limit to: Spree::Api::Config[:rate_limit_per_secret_key], within: Spree::Api::Config[:rate_limit_window].seconds,
27
+ store: Rails.cache,
28
+ scope: RateLimitHeaders::RATE_LIMIT_SCOPE,
29
+ by: :rate_limit_bucket,
30
+ with: RATE_LIMIT_RESPONSE,
31
+ if: :secret_key_request?
34
32
 
35
33
  rate_limit to: Spree::Api::Config[:rate_limit_per_key], within: Spree::Api::Config[:rate_limit_window].seconds,
36
34
  store: Rails.cache,
37
- by: -> { request.headers['X-Spree-Api-Key'] || request.remote_ip },
38
- with: RATE_LIMIT_RESPONSE
35
+ scope: RateLimitHeaders::RATE_LIMIT_SCOPE,
36
+ by: :rate_limit_bucket,
37
+ with: RATE_LIMIT_RESPONSE,
38
+ unless: :secret_key_request?
39
+
40
+ # Cross-store leak tripwire, active in development/test only:
41
+ # registered ahead of the authentication callbacks so resource
42
+ # lookups run inside the guarded window. Deliberately global lookups
43
+ # (credential searches) opt out with Spree::StoreScopeGuard.skip.
44
+ around_action { |_controller, action| Spree::StoreScopeGuard.watch(&action) }
39
45
 
40
46
  # Optional JWT authentication by default
41
47
  before_action :authenticate_user
42
48
 
43
49
  protected
44
50
 
51
+ # Refuses a throttled request. Must render (not return a value) —
52
+ # Rails runs `with:` responders via instance_exec inside a
53
+ # before_action, where only render/redirect halts the chain. Headers
54
+ # are set here because a halted chain skips after_actions, so
55
+ # RateLimitHeaders never runs for a 429. Endpoint throttles pass the
56
+ # +limit+ that actually tripped so the header reports their ceiling,
57
+ # not the API-wide one.
58
+ def render_rate_limited(limit: rate_limit_ceiling)
59
+ response.headers['Retry-After'] = Spree::Api::Config[:rate_limit_window].to_s
60
+ response.headers['X-RateLimit-Limit'] = limit.to_s
61
+ response.headers['X-RateLimit-Remaining'] = '0'
62
+ render json: { error: { code: 'rate_limit_exceeded', message: 'Too many requests. Please retry later.' } },
63
+ status: :too_many_requests
64
+ end
65
+
66
+ # Guest authorization for a specific order or cart. Defined here
67
+ # because Store::BaseController and Store::ResourceController anchor
68
+ # parallel inheritance branches — both need it.
69
+ def order_token
70
+ request.headers['x-spree-token']
71
+ end
72
+
73
+ # Renders a failed service/workflow Result: validation errors become a
74
+ # 422 field-error payload, anything else a plain service error. Shared
75
+ # by both APIs — Store endpoints surface workflow failures (a rejected
76
+ # return, a vetoed cart add) the same way Admin ones do.
77
+ def render_result_error(result)
78
+ error = result.error
79
+ errors = error.respond_to?(:value) ? error.value : error
80
+
81
+ if errors.is_a?(ActiveModel::Errors)
82
+ render_validation_error(errors)
83
+ else
84
+ render_service_error(error)
85
+ end
86
+ end
87
+
45
88
  # Override to use current_user from JWT authentication
46
- # @return [Spree.user_class]
89
+ # @return [Spree.customer_class]
47
90
  def spree_current_user
48
91
  current_user
49
92
  end
@@ -32,23 +32,40 @@ module Spree
32
32
  end
33
33
 
34
34
  # POST /api/v3/resource
35
+ #
36
+ # A controller whose resource is written through a workflow declares it
37
+ # with `create_workflow` and gets this action unchanged — same
38
+ # authorization, same rendering. Without one the record saves directly.
35
39
  def create
36
40
  @resource = build_resource
37
41
  authorize_resource!(@resource, :create)
38
42
 
39
- if @resource.save
43
+ return save_and_render(@resource, status: :created) if create_workflow.nil?
44
+
45
+ result = create_workflow.call(**create_workflow_arguments)
46
+
47
+ if result.success?
48
+ @resource = result.value
40
49
  render json: serialize_resource(@resource), status: :created
41
50
  else
42
- render_errors(@resource.errors)
51
+ render_result_error(result)
43
52
  end
44
53
  end
45
54
 
46
55
  # PATCH /api/v3/resource/:id
47
56
  def update
48
- if @resource.update(permitted_params)
57
+ if update_workflow.nil?
58
+ @resource.assign_attributes(permitted_params)
59
+ return save_and_render(@resource)
60
+ end
61
+
62
+ result = update_workflow.call(**update_workflow_arguments)
63
+
64
+ if result.success?
65
+ @resource = result.value
49
66
  render json: serialize_resource(@resource)
50
67
  else
51
- render_errors(@resource.errors)
68
+ render_result_error(result)
52
69
  end
53
70
  end
54
71
 
@@ -107,26 +124,112 @@ module Spree
107
124
  end
108
125
 
109
126
  # Builds a new resource, using parent association when @parent is set
127
+ # The workflow that writes this resource, or nil to save the record
128
+ # directly. Declaring one is all a controller needs to do — `create`
129
+ # and `update` keep their authorization and rendering.
130
+ #
131
+ # @return [#call, nil]
132
+ def create_workflow
133
+ nil
134
+ end
135
+
136
+ # @return [#call, nil]
137
+ def update_workflow
138
+ nil
139
+ end
140
+
141
+ # Keywords passed to `create_workflow`. The default suits a workflow
142
+ # taking `store:` and `attributes:`; override for anything else.
143
+ #
144
+ # @return [Hash]
145
+ def create_workflow_arguments
146
+ { store: current_store, attributes: permitted_params }
147
+ end
148
+
149
+ # Keywords passed to `update_workflow`, keyed by the resource's own
150
+ # name — `product:`, `price_list:` — which is how the workflows in
151
+ # app/workflows name their subject. `element` rather than `singular`,
152
+ # which would carry the `spree_` prefix.
153
+ #
154
+ # @return [Hash]
155
+ def update_workflow_arguments
156
+ { model_class.model_name.element.to_sym => @resource, attributes: permitted_params }
157
+ end
158
+
159
+ def save_and_render(resource, status: :ok)
160
+ if resource.save
161
+ render json: serialize_resource(resource), status: status
162
+ else
163
+ render_errors(resource.errors)
164
+ end
165
+ end
166
+
167
+ # Builds the record a create writes, through its owner's association so
168
+ # tenancy comes from where the record was built rather than from an
169
+ # attribute assigned afterwards.
170
+ #
171
+ # A workflow-written resource gets the bare scoped record: the workflow
172
+ # assigns the payload itself, and assigning it here would only be for
173
+ # the authorization check — which reads the record's owner, not its
174
+ # attributes — while raising on any bulk payload the model has no
175
+ # setter for (`product_ids`, `variants`).
110
176
  def build_resource
111
- resource = if @parent.present?
112
- @parent.send(parent_association).build(permitted_params)
113
- else
114
- model_class.new(permitted_params)
115
- end
116
- resource.store = current_store if resource.respond_to?(:store_id) && resource.store_id.blank?
177
+ resource = resource_scope.new
178
+ resource.assign_attributes(permitted_params) if create_workflow.nil?
117
179
  resource.created_by = try_spree_current_user if resource.respond_to?(:created_by_id)
118
180
  resource
119
181
  end
120
182
 
183
+ # The relation a new record is built on: a nested resource's parent
184
+ # association, the store's own association for this model, or the
185
+ # class itself for genuinely global data (countries, roles).
186
+ #
187
+ # @return [ActiveRecord::Relation, Class]
188
+ def resource_scope
189
+ return @parent.send(parent_association) if @parent.present?
190
+ return model_class unless store_association
191
+
192
+ current_store.public_send(store_association)
193
+ end
194
+
195
+ # The store association a new record of this model builds on, or nil
196
+ # when there is none it can build through.
197
+ #
198
+ # Found by asking the reflections which association actually points at
199
+ # this model rather than by inflecting its name, so a model whose
200
+ # association is not the plural of its own name still resolves. Two
201
+ # cases yield nil and build on the class instead, taking their tenancy
202
+ # from the record they belong to: a doubly-nested has_many :through
203
+ # (Store#prices, through variants through products) is readonly, and
204
+ # genuinely global data (countries, roles) has no store association.
205
+ #
206
+ # @return [Symbol, nil]
207
+ def store_association
208
+ reflections = current_store.class.reflect_on_all_associations(:has_many).select do |reflection|
209
+ !reflection.nested? && reflection.klass == model_class
210
+ rescue NameError
211
+ # A reflection naming a class this installation does not load.
212
+ false
213
+ end
214
+ return reflections.first&.name if reflections.one?
215
+
216
+ # More than one association reaches this model — a deprecated twin
217
+ # such as `shipments` beside `fulfillments` — so the conventional
218
+ # name decides which one a create belongs on.
219
+ conventional = model_class.model_name.element.pluralize.to_sym
220
+ reflections.find { |reflection| reflection.name == conventional }&.name
221
+ end
222
+
121
223
  # Finds a single resource within scope using prefixed ID
122
224
  def find_resource
123
225
  scope.find_by_prefix_id!(params[:id])
124
226
  end
125
227
 
126
- # Authorize resource with CanCanCan
127
- def authorize_resource!(resource = @resource, action = action_name.to_sym)
128
- authorize!(action, resource)
129
- end
228
+ # Per-record authorization hook. A no-op in the shared base: the Store
229
+ # API's resources are reachable only through owner-scoped queries, so
230
+ # loading one already proves the caller may act on it. The Admin API
231
+ # overrides this with a CanCanCan check.
232
+ def authorize_resource!(resource = @resource, action = action_name.to_sym); end
130
233
 
131
234
  # Returns ransack-filtered, sorted and paginated collection
132
235
  # ar_lazy_preload handles automatic association preloading
@@ -251,15 +354,16 @@ module Spree
251
354
  }
252
355
  end
253
356
 
254
- # Base scope with store and ability
255
- # When @parent is set (nested resources), uses parent association instead
357
+ # Base scope, store-scoped (or parent-scoped for nested resources).
358
+ # Deliberately free of CanCanCan: the Store API authorizes by ownership
359
+ # — every account controller scopes through `current_user` — while the
360
+ # Admin API layers `accessible_by` on top in its own subclass.
256
361
  def scope
257
362
  base_scope = if @parent.present?
258
363
  @parent.send(parent_association)
259
364
  else
260
365
  model_class.for_store(current_store)
261
366
  end
262
- base_scope = base_scope.accessible_by(current_ability, ability_action_for_request) unless @parent.present?
263
367
  base_scope = base_scope.includes(scope_includes) if scope_includes.any?
264
368
  base_scope = base_scope.preload_associations_lazily
265
369
  model_class.include?(Spree::TranslatableResource) ? base_scope.i18n : base_scope
@@ -300,21 +404,20 @@ module Spree
300
404
  read_actions.include?(action_name) ? :show : :update
301
405
  end
302
406
 
303
- # Authorizes the parent resource for nested controllers: a role that
304
- # can view a parent can't mutate its nested collection. Call from
305
- # +set_parent+ after loading the parent.
306
- def authorize_parent!(parent)
307
- authorize!(parent_ability_action, parent)
308
- end
407
+ # Parent authorization hook for nested controllers. A no-op in the
408
+ # shared base for the same reason as +authorize_resource!+; the Admin
409
+ # API overrides it so a role that can only view a parent cannot mutate
410
+ # its nested collection.
411
+ def authorize_parent!(parent); end
309
412
 
310
413
  # Override to specify the association name on @parent
311
- # Defaults to controller_name (e.g., 'wished_items' for WishlistItemsController)
414
+ # Defaults to controller_name (e.g., 'wishlist_items' for WishlistItemsController)
312
415
  def parent_association
313
416
  controller_name
314
417
  end
315
418
 
316
419
  # Override in subclass to eager load associations that don't work well
317
- # with ar_lazy_preload (e.g., prices, stock_items)
420
+ # with ar_lazy_preload (e.g., prices, stock_levels)
318
421
  def scope_includes
319
422
  []
320
423
  end
@@ -329,25 +432,38 @@ module Spree
329
432
  raise NotImplementedError, 'Subclass must implement serializer_class'
330
433
  end
331
434
 
332
- # Permit flat parameters based on model class
333
- # Automatically infers attribute list from Spree::PermittedAttributes
334
- # e.g., ProductsController -> Spree::PermittedAttributes.product_attributes
335
- #
336
- # Override in subclass for custom parameter handling
337
435
  def permitted_params
338
- normalize_params(params.permit(permitted_attributes))
436
+ normalize_params(params.permit(*permitted_attributes))
339
437
  end
340
438
 
341
- # Returns the permitted attributes list for the model
342
- # Override in subclass for custom attributes
439
+ # This resource's writable attributes, plus anything extensions have
440
+ # declared on the model. Override +resource_permitted_attributes+ rather
441
+ # than this, so the extension union is not lost.
343
442
  def permitted_attributes
344
- Spree::PermittedAttributes.public_send(permitted_attributes_key)
443
+ resource_permitted_attributes + model_additional_permitted_attributes
345
444
  end
346
445
 
347
- # Infers the PermittedAttributes key from model class
348
- # e.g., Spree::Product -> :product_attributes
349
- def permitted_attributes_key
350
- :"#{model_class.model_name.element}_attributes"
446
+ # Override in subclass to declare the resource's writable attributes.
447
+ def resource_permitted_attributes
448
+ raise NotImplementedError, 'Subclass must implement resource_permitted_attributes or permitted_params'
449
+ end
450
+
451
+ # Attributes extensions have declared on the model via
452
+ # +Spree::Product.additional_permitted_attributes += [...]+.
453
+ #
454
+ # Guarded on both sides: a controller need not define +model_class+
455
+ # (and one that does may raise NotImplementedError), and
456
+ # `Spree.base_class` is host-overridable, so the class_attribute is not
457
+ # guaranteed to be inherited from Spree::Base.
458
+ def model_additional_permitted_attributes
459
+ return [] unless respond_to?(:model_class, true)
460
+
461
+ model = model_class
462
+ return [] unless model.respond_to?(:additional_permitted_attributes)
463
+
464
+ Array(model.additional_permitted_attributes)
465
+ rescue NotImplementedError
466
+ []
351
467
  end
352
468
  end
353
469
  end