spree_api 5.6.1 → 6.0.0.beta2

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 (542) 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 +20 -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 +18 -9
  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 +164 -33
  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 +239 -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 +66 -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 +74 -16
  184. data/app/controllers/spree/api/v3/resource_controller.rb +170 -39
  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/actor_serializer.rb +28 -0
  282. data/app/serializers/spree/api/v3/admin/address_serializer.rb +27 -4
  283. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +13 -10
  284. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +15 -2
  285. data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +15 -0
  286. data/app/serializers/spree/api/v3/admin/cart_serializer.rb +34 -0
  287. data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +32 -0
  288. data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +23 -0
  289. data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +48 -0
  290. data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +23 -0
  291. data/app/serializers/spree/api/v3/admin/catalog_product_serializer.rb +57 -0
  292. data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +38 -0
  293. data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +37 -0
  294. data/app/serializers/spree/api/v3/admin/catalog_serializer.rb +46 -0
  295. data/app/serializers/spree/api/v3/admin/category_serializer.rb +3 -2
  296. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -1
  297. data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +16 -0
  298. data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +21 -0
  299. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +28 -0
  300. data/app/serializers/spree/api/v3/admin/collection_rule_serializer.rb +22 -0
  301. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +29 -0
  302. data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +67 -0
  303. data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +69 -0
  304. data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +61 -0
  305. data/app/serializers/spree/api/v3/admin/company_invitation_serializer.rb +15 -0
  306. data/app/serializers/spree/api/v3/admin/company_membership_serializer.rb +11 -0
  307. data/app/serializers/spree/api/v3/admin/company_serializer.rb +37 -0
  308. data/app/serializers/spree/api/v3/admin/concerns/external_references_attribute.rb +33 -0
  309. data/app/serializers/spree/api/v3/admin/consent_record_serializer.rb +28 -0
  310. data/app/serializers/spree/api/v3/admin/country_serializer.rb +2 -2
  311. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -1
  312. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +2 -2
  313. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +2 -2
  314. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +23 -22
  315. data/app/serializers/spree/api/v3/admin/dashboard_counter_serializer.rb +24 -0
  316. data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +36 -0
  317. data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +32 -0
  318. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +66 -1
  319. data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +15 -0
  320. data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +34 -0
  321. data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +65 -0
  322. data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +10 -1
  323. data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +20 -0
  324. data/app/serializers/spree/api/v3/admin/delivery_zone_member_serializer.rb +11 -0
  325. data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +29 -0
  326. data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +59 -0
  327. data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -4
  328. data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +16 -0
  329. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +34 -0
  330. data/app/serializers/spree/api/v3/admin/export_serializer.rb +20 -1
  331. data/app/serializers/spree/api/v3/admin/fee_serializer.rb +14 -0
  332. data/app/serializers/spree/api/v3/admin/freight_summary_line_serializer.rb +46 -0
  333. data/app/serializers/spree/api/v3/admin/freight_summary_serializer.rb +16 -0
  334. data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +39 -0
  335. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +31 -9
  336. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -3
  337. data/app/serializers/spree/api/v3/admin/import_serializer.rb +15 -2
  338. data/app/serializers/spree/api/v3/admin/integration_serializer.rb +32 -0
  339. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +4 -4
  340. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +46 -5
  341. data/app/serializers/spree/api/v3/admin/market_serializer.rb +5 -1
  342. data/app/serializers/spree/api/v3/admin/media_serializer.rb +50 -2
  343. data/app/serializers/spree/api/v3/admin/membership_product_serializer.rb +29 -0
  344. data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +29 -0
  345. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +50 -0
  346. data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +2 -6
  347. data/app/serializers/spree/api/v3/admin/order_serializer.rb +126 -31
  348. data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +53 -0
  349. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +8 -2
  350. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -0
  351. data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +41 -0
  352. data/app/serializers/spree/api/v3/admin/permission_serializer.rb +39 -0
  353. data/app/serializers/spree/api/v3/admin/policy_serializer.rb +11 -0
  354. data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +22 -0
  355. data/app/serializers/spree/api/v3/admin/price_list_product_serializer.rb +32 -0
  356. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +20 -8
  357. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +2 -12
  358. data/app/serializers/spree/api/v3/admin/price_serializer.rb +3 -0
  359. data/app/serializers/spree/api/v3/admin/product_serializer.rb +54 -8
  360. data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +39 -0
  361. data/app/serializers/spree/api/v3/admin/product_type_custom_field_definition_serializer.rb +44 -0
  362. data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +34 -0
  363. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +6 -12
  364. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +17 -15
  365. data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +80 -0
  366. data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +94 -0
  367. data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +27 -0
  368. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +6 -5
  369. data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +72 -0
  370. data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +16 -0
  371. data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +21 -0
  372. data/app/serializers/spree/api/v3/admin/return_serializer.rb +58 -0
  373. data/app/serializers/spree/api/v3/admin/role_serializer.rb +24 -6
  374. data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +32 -0
  375. data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +37 -0
  376. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +46 -0
  377. data/app/serializers/spree/api/v3/admin/seller_requirement_serializer.rb +68 -0
  378. data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +48 -0
  379. data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +57 -0
  380. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +92 -0
  381. data/app/serializers/spree/api/v3/admin/seller_team_member_serializer.rb +29 -0
  382. data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +53 -0
  383. data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +82 -0
  384. data/app/serializers/spree/api/v3/admin/state_serializer.rb +1 -1
  385. data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +65 -0
  386. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +20 -4
  387. data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +116 -0
  388. data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +57 -0
  389. data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +48 -0
  390. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +5 -5
  391. data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +57 -0
  392. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +36 -16
  393. data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +32 -0
  394. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +42 -7
  395. data/app/serializers/spree/api/v3/admin/store_serializer.rb +65 -1
  396. data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +39 -0
  397. data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +67 -0
  398. data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +43 -0
  399. data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +21 -0
  400. data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +49 -0
  401. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +49 -8
  402. data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +23 -0
  403. data/app/serializers/spree/api/v3/base_serializer.rb +61 -2
  404. data/app/serializers/spree/api/v3/cart_serializer.rb +90 -12
  405. data/app/serializers/spree/api/v3/category_serializer.rb +3 -3
  406. data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +50 -0
  407. data/app/serializers/spree/api/v3/claim_reason_serializer.rb +20 -0
  408. data/app/serializers/spree/api/v3/claim_serializer.rb +62 -0
  409. data/app/serializers/spree/api/v3/collection_serializer.rb +41 -0
  410. data/app/serializers/spree/api/v3/company_invitation_serializer.rb +28 -0
  411. data/app/serializers/spree/api/v3/company_membership_serializer.rb +28 -0
  412. data/app/serializers/spree/api/v3/company_serializer.rb +33 -0
  413. data/app/serializers/spree/api/v3/custom_field_serializer.rb +2 -2
  414. data/app/serializers/spree/api/v3/customer_serializer.rb +9 -1
  415. data/app/serializers/spree/api/v3/data_request_event_serializer.rb +30 -0
  416. data/app/serializers/spree/api/v3/data_request_serializer.rb +40 -0
  417. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +12 -2
  418. data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +34 -17
  419. data/app/serializers/spree/api/v3/delivery_serializer.rb +29 -0
  420. data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +29 -0
  421. data/app/serializers/spree/api/v3/delivery_zone_serializer.rb +13 -0
  422. data/app/serializers/spree/api/v3/digital_asset_serializer.rb +23 -0
  423. data/app/serializers/spree/api/v3/digital_link_serializer.rb +6 -2
  424. data/app/serializers/spree/api/v3/discount_serializer.rb +21 -7
  425. data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +53 -0
  426. data/app/serializers/spree/api/v3/exchange_serializer.rb +61 -0
  427. data/app/serializers/spree/api/v3/fee_serializer.rb +27 -0
  428. data/app/serializers/spree/api/v3/freight_summary_serializer.rb +38 -0
  429. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +28 -15
  430. data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
  431. data/app/serializers/spree/api/v3/import_row_serializer.rb +1 -1
  432. data/app/serializers/spree/api/v3/import_serializer.rb +18 -4
  433. data/app/serializers/spree/api/v3/invitation_serializer.rb +1 -1
  434. data/app/serializers/spree/api/v3/line_item_serializer.rb +18 -1
  435. data/app/serializers/spree/api/v3/market_serializer.rb +2 -2
  436. data/app/serializers/spree/api/v3/{asset_serializer.rb → media_event_serializer.rb} +4 -4
  437. data/app/serializers/spree/api/v3/media_serializer.rb +48 -7
  438. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +1 -1
  439. data/app/serializers/spree/api/v3/option_type_serializer.rb +1 -1
  440. data/app/serializers/spree/api/v3/order_group_serializer.rb +60 -0
  441. data/app/serializers/spree/api/v3/order_serializer.rb +58 -6
  442. data/app/serializers/spree/api/v3/payment_method_serializer.rb +1 -1
  443. data/app/serializers/spree/api/v3/payment_serializer.rb +2 -6
  444. data/app/serializers/spree/api/v3/payment_session_serializer.rb +10 -3
  445. data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +1 -1
  446. data/app/serializers/spree/api/v3/policy_serializer.rb +7 -2
  447. data/app/serializers/spree/api/v3/product_filter_option_serializer.rb +1 -1
  448. data/app/serializers/spree/api/v3/product_serializer.rb +42 -10
  449. data/app/serializers/spree/api/v3/product_type_serializer.rb +17 -0
  450. data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +11 -0
  451. data/app/serializers/spree/api/v3/refund_serializer.rb +9 -3
  452. data/app/serializers/spree/api/v3/return_line_item_serializer.rb +42 -0
  453. data/app/serializers/spree/api/v3/return_reason_serializer.rb +20 -0
  454. data/app/serializers/spree/api/v3/return_serializer.rb +62 -0
  455. data/app/serializers/spree/api/v3/seller/balance_serializer.rb +35 -0
  456. data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +21 -0
  457. data/app/serializers/spree/api/v3/seller/claim_serializer.rb +25 -0
  458. data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +32 -0
  459. data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +59 -0
  460. data/app/serializers/spree/api/v3/seller/delivery_profile_serializer.rb +26 -0
  461. data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +35 -0
  462. data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +17 -0
  463. data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +26 -0
  464. data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +29 -0
  465. data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +30 -0
  466. data/app/serializers/spree/api/v3/seller/export_serializer.rb +44 -0
  467. data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +43 -0
  468. data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +76 -0
  469. data/app/serializers/spree/api/v3/seller/import_mapping_serializer.rb +20 -0
  470. data/app/serializers/spree/api/v3/seller/import_row_serializer.rb +17 -0
  471. data/app/serializers/spree/api/v3/seller/import_serializer.rb +77 -0
  472. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +29 -0
  473. data/app/serializers/spree/api/v3/seller/media_serializer.rb +26 -0
  474. data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +44 -0
  475. data/app/serializers/spree/api/v3/seller/order_serializer.rb +119 -0
  476. data/app/serializers/spree/api/v3/seller/package_type_serializer.rb +52 -0
  477. data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +34 -0
  478. data/app/serializers/spree/api/v3/seller/payout_serializer.rb +36 -0
  479. data/app/serializers/spree/api/v3/seller/policy_serializer.rb +11 -0
  480. data/app/serializers/spree/api/v3/seller/product_serializer.rb +60 -0
  481. data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +30 -0
  482. data/app/serializers/spree/api/v3/seller/product_type_serializer.rb +29 -0
  483. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +77 -0
  484. data/app/serializers/spree/api/v3/seller/reason_serializer.rb +24 -0
  485. data/app/serializers/spree/api/v3/seller/requirement_custom_field_serializer.rb +36 -0
  486. data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +62 -0
  487. data/app/serializers/spree/api/v3/seller/requirement_submission_serializer.rb +33 -0
  488. data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +24 -0
  489. data/app/serializers/spree/api/v3/seller/return_serializer.rb +51 -0
  490. data/app/serializers/spree/api/v3/seller/shipping_label_serializer.rb +23 -0
  491. data/app/serializers/spree/api/v3/seller/stock_level_serializer.rb +27 -0
  492. data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +17 -0
  493. data/app/serializers/spree/api/v3/seller/tax_identifier_serializer.rb +15 -0
  494. data/app/serializers/spree/api/v3/seller/team_member_serializer.rb +22 -0
  495. data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +49 -0
  496. data/app/serializers/spree/api/v3/seller/variant_serializer.rb +71 -0
  497. data/app/serializers/spree/api/v3/seller_serializer.rb +50 -0
  498. data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +11 -0
  499. data/app/serializers/spree/api/v3/{stock_item_serializer.rb → stock_level_serializer.rb} +5 -5
  500. data/app/serializers/spree/api/v3/stock_location_serializer.rb +11 -7
  501. data/app/serializers/spree/api/v3/stock_movement_serializer.rb +8 -15
  502. data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +11 -0
  503. data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +6 -6
  504. data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +29 -0
  505. data/app/serializers/spree/api/v3/supplier_event_serializer.rb +11 -0
  506. data/app/serializers/spree/api/v3/tax_identifier_serializer.rb +15 -0
  507. data/app/serializers/spree/api/v3/tax_line_serializer.rb +37 -0
  508. data/app/serializers/spree/api/v3/variant_serializer.rb +52 -2
  509. data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +6 -6
  510. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  511. data/app/services/spree/api/v3/filters_aggregator.rb +14 -12
  512. data/app/services/spree/webhooks/deliver_webhook.rb +62 -26
  513. data/app/subscribers/spree/webhook_event_subscriber.rb +9 -5
  514. data/config/brakeman.ignore +1 -1
  515. data/config/initializers/typelizer.rb +51 -4
  516. data/config/locales/en.yml +5 -0
  517. data/config/routes.rb +730 -22
  518. data/lib/spree/api/configuration.rb +19 -19
  519. data/lib/spree/api/dependencies.rb +174 -227
  520. data/lib/spree/api/engine.rb +6 -0
  521. data/lib/spree/api/openapi/schema_helper.rb +179 -13
  522. data/lib/spree/api/testing_support/v3/base.rb +45 -15
  523. data/lib/spree/api.rb +10 -4
  524. data/lib/typelizer/open_enums.rb +35 -0
  525. metadata +342 -27
  526. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +0 -25
  527. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +0 -42
  528. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +0 -21
  529. data/app/controllers/spree/api/v3/store/digitals_controller.rb +0 -38
  530. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +0 -24
  531. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +0 -143
  532. data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +0 -15
  533. data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +0 -19
  534. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +0 -34
  535. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +0 -19
  536. data/app/serializers/spree/api/v3/customer_return_serializer.rb +0 -17
  537. data/app/serializers/spree/api/v3/digital_serializer.rb +0 -17
  538. data/app/serializers/spree/api/v3/reimbursement_serializer.rb +0 -27
  539. data/app/serializers/spree/api/v3/report_serializer.rb +0 -34
  540. data/app/serializers/spree/api/v3/return_authorization_serializer.rb +0 -31
  541. data/app/serializers/spree/api/v3/return_item_serializer.rb +0 -53
  542. data/app/serializers/spree/api/v3/shipping_category_serializer.rb +0 -11
@@ -43,12 +43,23 @@ module Spree
43
43
  Spree.api.admin_payment_method_serializer
44
44
  end
45
45
 
46
- # Explicit allowlist per the v3 convention — flat params, no
47
- # reach into the global `Spree::PermittedAttributes` registry
48
- # (which is the legacy Rails admin's surface). `type` and
46
+ # Explicit allowlist per the v3 convention — flat params. `type` and
49
47
  # `preferences` are added by `SubclassedResource` on top.
48
+ # Deliberately NOT routed through `normalize_params`: gateway
49
+ # `preferences` are opaque provider values, and prefixed-ID resolution
50
+ # recurses into nested hashes — a Stripe `webhook_endpoint_id` like
51
+ # `we_1MqJ8b...` matches the prefixed-ID shape and would be decoded to
52
+ # an integer. `type` and `preferences` are added by `SubclassedResource`.
50
53
  def permitted_params
51
- params.permit(:name, :description, :active, :storefront_visible, :auto_capture, :position, metadata: {}, preferences: {})
54
+ params.permit(
55
+ :name, :description, :active, :storefront_visible, :auto_capture, :capture_method, :position,
56
+ *model_additional_permitted_attributes,
57
+ metadata: {}, preferences: {}
58
+ )
59
+ end
60
+
61
+ def scope
62
+ super.ordered
52
63
  end
53
64
 
54
65
  # `types` is read-only discovery — maps to the read scope + :show ability.
@@ -0,0 +1,27 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # How this installation can pay its sellers, and which of those a store
6
+ # could use today.
7
+ #
8
+ # Discovery rather than CRUD: providers are classes registered in code,
9
+ # not rows — so there is no serializer, and each class describes itself
10
+ # (`to_api_hash`), the same shape `/tax_providers` uses.
11
+ #
12
+ # Whether a provider needs sellers to hold an account with it is the
13
+ # part worth surfacing at selection time: choosing one changes what a
14
+ # marketplace has to ask of its sellers before it can pay them, which
15
+ # is better known before the choice than after.
16
+ class PayoutProvidersController < BaseController
17
+ scoped_resource :settings
18
+
19
+ # GET /api/v3/admin/payout_providers
20
+ def index
21
+ render json: { data: Spree.payout_providers.map { |provider| provider.to_api_hash(current_store) } }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # The permission catalog discovery endpoint — the vocabulary the role
6
+ # editor and the API-key scope picker render. It is vocabulary, not
7
+ # data, so any authenticated admin credential may read it (same class
8
+ # of exemption as `/tags`).
9
+ #
10
+ # Staff keys only. Both surfaces this feeds build something owned by
11
+ # the store — a store role, a secret key — and a key another audience
12
+ # holds (a seller's own profile or books) would render as an option
13
+ # that fails validation the moment it is picked.
14
+ class PermissionsController < Admin::BaseController
15
+ skip_scope_check!
16
+
17
+ # GET /api/v3/admin/permissions
18
+ def index
19
+ entries = Spree.permissions.entries
20
+
21
+ render json: {
22
+ data: entries.map { |entry| Spree.api.admin_permission_serializer.new(entry).to_h },
23
+ meta: { count: entries.size }
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,42 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # The store's own legal documents. A seller's policies belong to the
6
+ # seller and are managed on the seller branch — this controller never
7
+ # reaches them, since its scope is the store's own association.
8
+ class PoliciesController < ResourceController
9
+ scoped_resource :settings
10
+
11
+ protected
12
+
13
+ def model_class
14
+ Spree::Policy
15
+ end
16
+
17
+ def serializer_class
18
+ Spree.api.admin_policy_serializer
19
+ end
20
+
21
+ def resource_permitted_attributes
22
+ [:name, :slug, :body]
23
+ end
24
+
25
+ # Accept slug (e.g. returns-policy) or prefixed ID (e.g. pol_abc123),
26
+ # matching the storefront's lookup.
27
+ def find_resource
28
+ if params[:id].to_s.start_with?('pol_')
29
+ scope.find_by_prefix_id!(params[:id])
30
+ else
31
+ scope.friendly.find(params[:id])
32
+ end
33
+ end
34
+
35
+ def scope
36
+ super.order(:name)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,93 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module PriceLists
6
+ # The products a price list covers — the uniform nested membership
7
+ # surface (see Spree::Api::V3::Admin::ProductMembership). Membership
8
+ # is derived from the list's price rows: adding a product
9
+ # materializes a placeholder price for every variant × store
10
+ # currency (the spreadsheet's empty cells), removing hard-deletes
11
+ # its price rows. Unordered — a price list prices, it never
12
+ # merchandises — so listing is by name.
13
+ class ProductsController < ResourceController
14
+ include Spree::Api::V3::Admin::ProductMembership
15
+
16
+ # Price lists ride the products scope like their parent
17
+ # controller — no separate read_price_lists scope.
18
+ scoped_resource :products
19
+
20
+ protected
21
+
22
+ def serializer_class
23
+ Spree.api.admin_price_list_product_serializer
24
+ end
25
+
26
+ # The resolver rides along in the serializer params, preloaded
27
+ # with this page's variants — one query for the page rather than
28
+ # one per row (see Catalogs::ProductsController, the same shape).
29
+ def serializer_params
30
+ return super unless expanded_keys.include?('price_list_price')
31
+
32
+ super.merge(price_list_price_resolver: price_list_price_resolver)
33
+ end
34
+
35
+ # The list read as it stands, draft or not: this is its editor.
36
+ def price_list_price_resolver
37
+ @price_list_price_resolver ||=
38
+ Spree::Catalogs::ResolvePrices.new(price_list: @price_list, currency: current_currency).
39
+ tap { |resolver| resolver.preload(priced_variants) }
40
+ end
41
+
42
+ def priced_variants
43
+ Array(@collection).flat_map { |product| product.variants.to_a }
44
+ end
45
+
46
+ # Every row lists its variants and prices each of them, so what
47
+ # the rows read comes down with the page: the prices the resolver
48
+ # picks from, the option values that name the variant, the stock
49
+ # levels behind the flags. `default_variant` separately, since it
50
+ # is its own belongs_to with a cache of its own.
51
+ # Only what this page reads: the card's thumbnail, and every
52
+ # variant with the rows and option values the resolver and the
53
+ # variant rows need. `default_variant` is deliberately absent —
54
+ # it is a separate `belongs_to` with a cache of its own, so
55
+ # reading it here would re-query option values per row. Publications, stock levels and the default
56
+ # variant's own prices are deliberately absent — the serializer
57
+ # here is not the admin product serializer and never asks for them.
58
+ def collection_includes
59
+ [
60
+ :primary_media,
61
+ { variants: [:prices, { option_values: :option_type }] }
62
+ ]
63
+ end
64
+
65
+ # DISTINCT (the base default): a product joins once per
66
+ # variant × currency price row.
67
+ def scope
68
+ product_scope.
69
+ joins(variants: :prices).
70
+ where(Spree::Price.table_name => { price_list_id: @price_list.id }).
71
+ order(:name)
72
+ end
73
+
74
+ def add_member_products(products)
75
+ @price_list.add_products(products.map(&:id))
76
+ end
77
+
78
+ def remove_member_products(products)
79
+ @price_list.remove_products(products.map(&:id))
80
+ end
81
+
82
+ def set_parent
83
+ @price_list = current_store.price_lists.
84
+ accessible_by(current_ability, parent_ability_action).
85
+ find_by_prefix_id!(params[:price_list_id])
86
+ authorize_parent!(@price_list)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -6,13 +6,12 @@ module Spree
6
6
  # (`activate` / `deactivate`) and the spreadsheet's data feed
7
7
  # (`prices`).
8
8
  #
9
- # Everything writable on the list — name, schedule, match policy,
10
- # product membership (`product_ids: [...]`), nested rules
11
- # (`rules: [...]`), and individual price overrides
12
- # (`prices: [...]`) — flows through the regular PATCH payload, so
13
- # the SPA saves the entire editor in one round-trip. No separate
14
- # add_products / remove_products / add_rule / bulk_update_prices
15
- # endpoints.
9
+ # Everything writable on the list itself — name, schedule, match
10
+ # policy, nested rules (`rules: [...]`), and individual price
11
+ # overrides (`prices: [...]`) — flows through the regular PATCH
12
+ # payload. Product membership lives on the uniform nested surface
13
+ # (PriceLists::ProductsController), the same protocol categories,
14
+ # collections and catalogs use.
16
15
  #
17
16
  # Scoped under the `products` API-key scope — price lists are a
18
17
  # product/pricing concern; we don't introduce a separate
@@ -43,17 +42,17 @@ module Spree
43
42
 
44
43
  # PATCH /api/v3/admin/price_lists/:id/activate
45
44
  #
46
- # State transition: draft|inactive → active (or → scheduled when
47
- # `starts_at` is in the future). Mirrors the old Rails admin's
48
- # "Activate" button which automatically scheduled future lists.
45
+ # draft|inactive → active, or → scheduled when `starts_at` is in the
46
+ # future. The workflow decides which, so a caller never has to.
49
47
  def activate
50
48
  authorize! :update, @resource
51
- event = @resource.starts_at.present? && @resource.starts_at.future? ? :schedule : :activate
52
49
 
53
- if @resource.send(event)
50
+ result = Spree.price_list_activate_workflow.call(price_list: @resource)
51
+
52
+ if result.success?
54
53
  render json: serialize_resource(@resource)
55
54
  else
56
- render_validation_error(@resource.errors)
55
+ render_service_error(result.error)
57
56
  end
58
57
  end
59
58
 
@@ -61,10 +60,12 @@ module Spree
61
60
  def deactivate
62
61
  authorize! :update, @resource
63
62
 
64
- if @resource.deactivate
63
+ result = Spree.price_list_deactivate_workflow.call(price_list: @resource)
64
+
65
+ if result.success?
65
66
  render json: serialize_resource(@resource)
66
67
  else
67
- render_validation_error(@resource.errors)
68
+ render_service_error(result.error)
68
69
  end
69
70
  end
70
71
 
@@ -83,6 +84,7 @@ module Spree
83
84
  .joins(variant: :product)
84
85
  .order(Arel.sql("#{Spree::Product.table_name}.name ASC"))
85
86
  .order(Arel.sql("#{Spree::Variant.table_name}.position ASC"))
87
+ .order(min_quantity: :asc)
86
88
 
87
89
  render json: {
88
90
  data: prices.map { |p| serialize_price(p) },
@@ -100,8 +102,23 @@ module Spree
100
102
  Spree.api.admin_price_list_serializer
101
103
  end
102
104
 
105
+ def create_workflow
106
+ Spree.price_list_create_workflow
107
+ end
108
+
109
+ def update_workflow
110
+ Spree.price_list_update_workflow
111
+ end
112
+
103
113
  def scope
104
- super.for_store(current_store)
114
+ super.ordered
115
+ end
116
+
117
+ # The serializer always renders a list's bands — the pricing card
118
+ # cannot show a percentage without them — so the index preloads them
119
+ # rather than paying a query per row.
120
+ def collection_includes
121
+ [:price_adjustment_tiers]
105
122
  end
106
123
 
107
124
  def permitted_params
@@ -109,24 +126,20 @@ module Spree
109
126
  params.permit(
110
127
  :name, :description, :position,
111
128
  :starts_at, :ends_at, :match_policy,
112
- product_ids: [],
129
+ :price_adjustment_percentage, :adjust_compare_at,
113
130
  rules: [:id, :type, { preferences: {} }],
114
- prices: [:id, :variant_id, :currency, :amount, :compare_at_amount]
131
+ price_adjustment_tiers: [:min_quantity, :percentage],
132
+ prices: [:id, :variant_id, :currency, :min_quantity, :amount, :compare_at_amount]
115
133
  )
116
134
  )
117
- reject_foreign_membership(attrs)
135
+ reject_foreign_variants(attrs)
118
136
  end
119
137
 
120
- # The PriceList model setters (`product_ids=`, `prices=`) resolve
121
- # member ids with no store scoping, so a list in this store could
122
- # otherwise be populated with another store's products/variants.
123
- # Drop any id that isn't in the current store before assignment.
124
- def reject_foreign_membership(attrs)
125
- if attrs[:product_ids].present?
126
- store_product_ids = current_store.products.where(id: attrs[:product_ids]).pluck(:id).map(&:to_s).to_set
127
- attrs[:product_ids] = Array(attrs[:product_ids]).select { |id| store_product_ids.include?(id.to_s) }
128
- end
129
-
138
+ # The price rows resolve variant ids with no store scoping, so a
139
+ # list in this store could otherwise be populated with another
140
+ # store's variants. Drop any id that isn't in the current store
141
+ # before assignment.
142
+ def reject_foreign_variants(attrs)
130
143
  if attrs[:prices].present?
131
144
  incoming = Array(attrs[:prices])
132
145
  store_variant_ids = current_store.variants.where(id: incoming.map { |r| r[:variant_id] }.compact).
@@ -167,6 +180,7 @@ module Spree
167
180
  variant_label: variant.options_text.presence,
168
181
  sku: variant.sku,
169
182
  currency: price.currency,
183
+ min_quantity: price.min_quantity,
170
184
  amount: price.amount&.to_s,
171
185
  compare_at_amount: price.compare_at_amount&.to_s
172
186
  }
@@ -13,8 +13,9 @@ module Spree
13
13
  before_action :require_ids!, only: [:bulk_destroy]
14
14
  before_action :require_prices!, only: [:bulk_upsert]
15
15
 
16
- # Bulk-upserts prices on the unique-key triple
17
- # `(variant_id, currency, price_list_id)`.
16
+ # Bulk-upserts prices on the unique key
17
+ # `(variant_id, currency, price_list_id, min_quantity)` — one row per
18
+ # rung of a variant's ladder (docs/plans/6.0-volume-pricing.md).
18
19
  #
19
20
  # @return [void]
20
21
  def bulk_upsert
@@ -52,6 +53,41 @@ module Spree
52
53
  end
53
54
 
54
55
  result = Spree::Prices::BulkUpsert.call(rows: rows)
56
+ # The quantity check and the cap both live in the service, since
57
+ # every write path reaches it and none of them run model
58
+ # validations (docs/plans/6.0-volume-pricing.md). Each branch is
59
+ # guarded on the key its own failure carries, so a failure mode the
60
+ # service grows later is not reported under one of these names.
61
+ if (invalid = result.error&.value.try(:[], :invalid_quantities))
62
+ return render_error(
63
+ code: 'invalid_min_quantity',
64
+ message: 'Each quantity break must start at a whole number of units.',
65
+ status: :unprocessable_content,
66
+ details: { rows: invalid }
67
+ )
68
+ end
69
+
70
+ if (negative = result.error&.value.try(:[], :invalid_amounts))
71
+ return render_error(
72
+ code: 'invalid_amount',
73
+ message: Spree.t('activerecord.errors.models.spree/price_list.attributes.base.negative_price').upcase_first,
74
+ status: :unprocessable_content,
75
+ details: { rows: negative }
76
+ )
77
+ end
78
+
79
+ if (over_cap = result.error&.value.try(:[], :over_cap))
80
+ return render_error(
81
+ code: 'too_many_breaks',
82
+ message: Spree.t(
83
+ 'activerecord.errors.models.spree/price.attributes.min_quantity.too_many_breaks',
84
+ count: Spree::Price::MAXIMUM_BREAKS_PER_VARIANT
85
+ ).upcase_first,
86
+ status: :unprocessable_content,
87
+ details: { ladders: over_cap }
88
+ )
89
+ end
90
+
55
91
  render json: result.value
56
92
  end
57
93
 
@@ -84,7 +120,7 @@ module Spree
84
120
  :prices,
85
121
  product: :tax_category,
86
122
  option_values: :option_type,
87
- stock_items: [:stock_location, :active_stock_reservations]
123
+ stock_levels: [:stock_location, :active_stock_reservations]
88
124
  ]
89
125
  }
90
126
  end
@@ -101,7 +137,7 @@ module Spree
101
137
  # scopes so a foreign or unknown id 404s instead of binding the
102
138
  # price to another store's record.
103
139
  def permitted_params
104
- permitted = params.permit(:variant_id, :currency, :amount, :compare_at_amount, :price_list_id)
140
+ permitted = params.permit(*model_additional_permitted_attributes, :variant_id, :currency, :min_quantity, :amount, :compare_at_amount, :price_list_id)
105
141
  permitted[:variant_id] = store_variants.find_by_prefix_id!(permitted[:variant_id]).id if permitted[:variant_id].present?
106
142
  permitted[:price_list_id] = store_price_lists.find_by_prefix_id!(permitted[:price_list_id]).id if permitted[:price_list_id].present?
107
143
  permitted
@@ -140,6 +176,7 @@ module Spree
140
176
  variant_id: decode_id(row[:variant_id]),
141
177
  price_list_id: row.key?(:price_list_id) ? decode_id(row[:price_list_id]) : nil,
142
178
  currency: row[:currency],
179
+ min_quantity: row[:min_quantity],
143
180
  amount: row[:amount],
144
181
  compare_at_amount: row[:compare_at_amount]
145
182
  }.compact
@@ -0,0 +1,93 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ # Product types are back-office only — there is no Store API counterpart.
6
+ #
7
+ # Editing a type never mutates existing products: option types and
8
+ # categories seed onto products when the type is attached, and the
9
+ # custom field list is read live when a product form renders. The one
10
+ # path from a type edit to existing products is `apply_to_products`.
11
+ class ProductTypesController < ResourceController
12
+ scoped_resource :product_types
13
+
14
+ # Backfills this type's option types and categories onto the products
15
+ # that already carry it. Additive and idempotent — nothing is removed.
16
+ def apply_to_products
17
+ @resource = find_resource
18
+ authorize!(:update, @resource)
19
+
20
+ Spree::ProductTypes::ApplyToProductsJob.perform_later(@resource.id)
21
+
22
+ render json: { products_count: @resource.products_count.to_i }, status: :accepted
23
+ end
24
+
25
+ protected
26
+
27
+ def model_class
28
+ Spree::ProductType
29
+ end
30
+
31
+ def serializer_class
32
+ Spree.api.admin_product_type_serializer
33
+ end
34
+
35
+ # The join tables, not the targets — the serializer reports association
36
+ # ids, so loading the option types and categories themselves would pay
37
+ # for records nothing reads.
38
+ def collection_includes
39
+ [
40
+ :option_type_product_types,
41
+ :product_type_categories,
42
+ { product_type_custom_field_definitions: :custom_field_definition }
43
+ ]
44
+ end
45
+
46
+ # Single-resource actions need the same eager-loading; without it every
47
+ # custom field row re-queries its definition.
48
+ def find_resource
49
+ scope.includes(collection_includes).find_by_prefix_id!(params[:id])
50
+ end
51
+
52
+ def permitted_params
53
+ attrs = params.permit(
54
+ *model_additional_permitted_attributes,
55
+ :name,
56
+ :delivery_profile_id,
57
+ option_type_ids: [],
58
+ category_ids: [],
59
+ custom_field_definitions: [:id, :required, :sort_order]
60
+ )
61
+ attrs = scope_delivery_profile(attrs)
62
+ scope_category_ids(attrs)
63
+ end
64
+
65
+ # The template profile must belong to this store — a cross-store id
66
+ # 404s instead of silently linking.
67
+ def scope_delivery_profile(attrs)
68
+ return attrs unless params.key?(:delivery_profile_id)
69
+
70
+ attrs[:delivery_profile] = if params[:delivery_profile_id].present?
71
+ current_store.delivery_profiles.accessible_by(current_ability, :show).find_by_prefix_id!(params[:delivery_profile_id])
72
+ end
73
+ attrs.except(:delivery_profile_id)
74
+ end
75
+
76
+ # `category_ids=` resolves prefixed ids with no store scoping, so a
77
+ # type in this store could otherwise be pointed at another store's
78
+ # categories. Mirrors ProductsController#apply_categories.
79
+ # (OptionType is global — nothing to scope there.)
80
+ def scope_category_ids(attrs)
81
+ return attrs if attrs[:category_ids].blank?
82
+
83
+ category_ids = decode_ids(attrs[:category_ids], Spree::Category)
84
+ attrs[:category_ids] = current_store.categories.
85
+ accessible_by(current_ability, :update).
86
+ where(id: category_ids).pluck(:id)
87
+ attrs
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,148 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Admin
5
+ module Products
6
+ class DigitalAssetsController < ResourceController
7
+ scoped_resource :products
8
+
9
+ # PATCH /api/v3/admin/products/:product_id/digital_assets/:id
10
+ #
11
+ # Replacing the file keeps every already-issued link working, since
12
+ # links resolve through the asset rather than the blob.
13
+ def update
14
+ return render_private_storage_error unless uploaded_blob_private?
15
+
16
+ # The asset already exists, so attaching a replacement blob writes
17
+ # to the database immediately, while the update below renders a 422
18
+ # without raising when it fails. Wrap both so a failed update rolls
19
+ # the new attachment back rather than leaving the file swapped but
20
+ # the record unchanged.
21
+ model_class.transaction do
22
+ @resource.variant = requested_variant if params[:variant_id].present?
23
+ attach_uploaded_file(@resource)
24
+
25
+ super
26
+
27
+ raise ActiveRecord::Rollback if @resource.errors.any?
28
+ end
29
+ end
30
+
31
+ # POST /api/v3/admin/products/:product_id/digital_assets
32
+ def create
33
+ return render_private_storage_error unless uploaded_blob_private?
34
+
35
+ super
36
+ end
37
+
38
+ # GET /api/v3/admin/products/:product_id/digital_assets/providers
39
+ #
40
+ # The sources a merchant can pick for a new asset: the uploaded-file
41
+ # default plus any host-registered provider. Drives the dashboard's
42
+ # source selector; a host with only the default sees just "upload".
43
+ def providers
44
+ authorize! :create, model_class
45
+
46
+ data = Spree.digital_asset_providers.map do |provider_class|
47
+ {
48
+ type: provider_class.to_s,
49
+ name: provider_class.provider_name,
50
+ requires_attachment: provider_class.requires_attachment?,
51
+ settings_schema: provider_class.settings_schema
52
+ }
53
+ end
54
+
55
+ render json: { data: data }
56
+ end
57
+
58
+ protected
59
+
60
+ def model_class
61
+ Spree::DigitalAsset
62
+ end
63
+
64
+ def serializer_class
65
+ Spree.api.admin_digital_asset_serializer
66
+ end
67
+
68
+ def set_parent
69
+ @parent = current_store.products.find_by_prefix_id!(params[:product_id])
70
+ authorize!(:show, @parent)
71
+ end
72
+
73
+ def parent_association
74
+ :digital_assets
75
+ end
76
+
77
+ # The parent association reaches assets through `variants`, which
78
+ # carries an ORDER BY on the variants table. Combined with the
79
+ # collection's DISTINCT, PostgreSQL rejects the query outright
80
+ # (ordering columns must appear in the select list), so order by
81
+ # the assets' own table instead. SQLite accepts either form, so
82
+ # this only fails on a real deployment.
83
+ def scope
84
+ super.reorder(created_at: :asc)
85
+ end
86
+
87
+ def scope_includes
88
+ [:variant, { attachment_attachment: :blob }]
89
+ end
90
+
91
+ # variant_id is resolved through the parent rather than assigned:
92
+ # mass-assigning it would let a caller point an asset at a variant
93
+ # of any product, in any store. signed_id likewise names a blob
94
+ # rather than a column, so it is attached separately.
95
+ # provider_type is mass-assignable: the model validates it names a
96
+ # registered provider, so an unknown value is a 422, not a hazard.
97
+ # provider_settings is an open hash — its keys are declared by the
98
+ # provider, not fixed here — so it is permitted as arbitrary scalars
99
+ # and lands verbatim under one key in the asset's metadata.
100
+ def permitted_params
101
+ params.permit(:authorized_clicks, :authorized_days, :provider_type, provider_settings: {})
102
+ end
103
+
104
+ private
105
+
106
+ # A product without explicit variants keeps its file on the default
107
+ # variant, mirroring how the rest of the admin treats such products.
108
+ def build_resource
109
+ digital_asset = super
110
+ digital_asset.variant = requested_variant || @parent.default_variant
111
+ attach_uploaded_file(digital_asset)
112
+ digital_asset
113
+ end
114
+
115
+ # Scoped to the parent, not merely to the store: an asset reached
116
+ # through a product's route has no business pointing at another
117
+ # product's variant. An id from anywhere else is a 404.
118
+ def requested_variant
119
+ return if params[:variant_id].blank?
120
+
121
+ @parent.variants.find_by_prefix_id!(params[:variant_id])
122
+ end
123
+
124
+ def attach_uploaded_file(digital_asset)
125
+ return if params[:signed_id].blank?
126
+
127
+ digital_asset.attachment.attach(params[:signed_id])
128
+ end
129
+
130
+ # Attaching never moves a blob between storage services, so a file
131
+ # uploaded to the public bucket would stay publicly readable while
132
+ # looking attached. Refuse it rather than storing it wrongly.
133
+ def uploaded_blob_private?
134
+ return true if params[:signed_id].blank?
135
+
136
+ blob = ActiveStorage::Blob.find_signed(params[:signed_id])
137
+ blob.present? && blob.service_name.to_s == Spree.private_storage_service_name.to_s
138
+ end
139
+
140
+ def render_private_storage_error
141
+ render_validation_error(Spree.t(:digital_assets_attachment_must_be_private))
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end