spree_api 6.0.0.rc1 → 6.0.0.rc3

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 (371) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +0 -17
  3. data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +10 -0
  4. data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +26 -4
  5. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +14 -28
  6. data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +1 -1
  7. data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +3 -2
  8. data/app/controllers/concerns/spree/api/v3/channel_resolution.rb +1 -1
  9. data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +3 -1
  10. data/app/controllers/concerns/spree/api/v3/error_handler.rb +48 -2
  11. data/app/controllers/concerns/spree/api/v3/file_uploads.rb +35 -0
  12. data/app/controllers/concerns/spree/api/v3/money_params.rb +52 -0
  13. data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +1 -5
  14. data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +6 -6
  15. data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +1 -4
  16. data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +1 -5
  17. data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +1 -4
  18. data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +5 -21
  19. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +5 -0
  20. data/app/controllers/concerns/spree/api/v3/purchase_serialization.rb +26 -0
  21. data/app/controllers/concerns/spree/api/v3/request_params.rb +65 -0
  22. data/app/controllers/concerns/spree/api/v3/store/search_provider_support.rb +8 -3
  23. data/app/controllers/concerns/spree/api/v3/strict_money_params.rb +94 -0
  24. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +10 -1
  25. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +8 -1
  26. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +15 -7
  27. data/app/controllers/spree/api/v3/admin/base_controller.rb +1 -0
  28. data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +3 -1
  29. data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +7 -5
  30. data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +60 -33
  31. data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +4 -1
  32. data/app/controllers/spree/api/v3/admin/categories_controller.rb +40 -20
  33. data/app/controllers/spree/api/v3/admin/channels_controller.rb +39 -6
  34. data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +5 -1
  35. data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +4 -1
  36. data/app/controllers/spree/api/v3/admin/collections_controller.rb +44 -15
  37. data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +60 -12
  38. data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +11 -0
  39. data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +9 -1
  40. data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +19 -18
  41. data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +6 -1
  42. data/app/controllers/spree/api/v3/admin/companies_controller.rb +17 -3
  43. data/app/controllers/spree/api/v3/admin/countries_controller.rb +5 -1
  44. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +21 -11
  45. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +12 -5
  46. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +9 -1
  47. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +12 -7
  48. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +11 -9
  49. data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +6 -1
  50. data/app/controllers/spree/api/v3/admin/customers_controller.rb +35 -7
  51. data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +8 -0
  52. data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +1 -1
  53. data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +15 -7
  54. data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +92 -57
  55. data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +8 -1
  56. data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +13 -1
  57. data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +21 -5
  58. data/app/controllers/spree/api/v3/admin/email_templates/drafts_controller.rb +14 -1
  59. data/app/controllers/spree/api/v3/admin/email_templates/previews_controller.rb +4 -0
  60. data/app/controllers/spree/api/v3/admin/email_templates/publications_controller.rb +7 -0
  61. data/app/controllers/spree/api/v3/admin/email_templates/restorations_controller.rb +8 -0
  62. data/app/controllers/spree/api/v3/admin/email_templates/test_emails_controller.rb +4 -0
  63. data/app/controllers/spree/api/v3/admin/exports_controller.rb +23 -6
  64. data/app/controllers/spree/api/v3/admin/files_controller.rb +29 -0
  65. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +20 -1
  66. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +19 -1
  67. data/app/controllers/spree/api/v3/admin/imports_controller.rb +36 -9
  68. data/app/controllers/spree/api/v3/admin/integrations_controller.rb +13 -1
  69. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +9 -2
  70. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +8 -1
  71. data/app/controllers/spree/api/v3/admin/locales_controller.rb +1 -1
  72. data/app/controllers/spree/api/v3/admin/markets_controller.rb +30 -9
  73. data/app/controllers/spree/api/v3/admin/me_controller.rb +12 -3
  74. data/app/controllers/spree/api/v3/admin/media_controller.rb +22 -9
  75. data/app/controllers/spree/api/v3/admin/media_library_controller.rb +4 -0
  76. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +24 -7
  77. data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +5 -1
  78. data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +13 -1
  79. data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +39 -1
  80. data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +19 -1
  81. data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +5 -1
  82. data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +29 -5
  83. data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +36 -1
  84. data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +22 -1
  85. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +66 -7
  86. data/app/controllers/spree/api/v3/admin/orders/gift_cards_controller.rb +6 -2
  87. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +11 -1
  88. data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +35 -2
  89. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +16 -5
  90. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +6 -0
  91. data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +37 -1
  92. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +6 -3
  93. data/app/controllers/spree/api/v3/admin/orders_controller.rb +74 -60
  94. data/app/controllers/spree/api/v3/admin/package_types_controller.rb +30 -5
  95. data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +17 -0
  96. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +38 -22
  97. data/app/controllers/spree/api/v3/admin/policies_controller.rb +8 -4
  98. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +27 -15
  99. data/app/controllers/spree/api/v3/admin/prices_controller.rb +51 -4
  100. data/app/controllers/spree/api/v3/admin/product_types_controller.rb +25 -8
  101. data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +27 -10
  102. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +9 -14
  103. data/app/controllers/spree/api/v3/admin/products_controller.rb +121 -70
  104. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +11 -2
  105. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +10 -1
  106. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +50 -14
  107. data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +54 -7
  108. data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +5 -1
  109. data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +9 -1
  110. data/app/controllers/spree/api/v3/admin/reporting_controller.rb +34 -0
  111. data/app/controllers/spree/api/v3/admin/resource_controller.rb +1 -0
  112. data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +5 -1
  113. data/app/controllers/spree/api/v3/admin/roles_controller.rb +13 -1
  114. data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +6 -0
  115. data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +15 -0
  116. data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +32 -6
  117. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +75 -22
  118. data/app/controllers/spree/api/v3/admin/setup_controller.rb +54 -15
  119. data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +38 -9
  120. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +41 -9
  121. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +48 -7
  122. data/app/controllers/spree/api/v3/admin/store_controller.rb +122 -53
  123. data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +1 -7
  124. data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +16 -6
  125. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +7 -4
  126. data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +21 -3
  127. data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +4 -0
  128. data/app/controllers/spree/api/v3/admin/translations/batches_controller.rb +17 -9
  129. data/app/controllers/spree/api/v3/admin/translations_controller.rb +4 -0
  130. data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +5 -0
  131. data/app/controllers/spree/api/v3/admin/updates_controller.rb +39 -0
  132. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +23 -1
  133. data/app/controllers/spree/api/v3/base_controller.rb +2 -0
  134. data/app/controllers/spree/api/v3/resource_controller.rb +63 -10
  135. data/app/controllers/spree/api/v3/seller/auth_controller.rb +8 -0
  136. data/app/controllers/spree/api/v3/seller/base_controller.rb +1 -0
  137. data/app/controllers/spree/api/v3/seller/countries_controller.rb +2 -2
  138. data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +49 -60
  139. data/app/controllers/spree/api/v3/seller/exports_controller.rb +18 -1
  140. data/app/controllers/spree/api/v3/seller/files_controller.rb +27 -0
  141. data/app/controllers/spree/api/v3/seller/imports_controller.rb +25 -9
  142. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +9 -1
  143. data/app/controllers/spree/api/v3/seller/me_controller.rb +14 -3
  144. data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +11 -0
  145. data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +35 -0
  146. data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +12 -0
  147. data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +33 -0
  148. data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +28 -2
  149. data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +22 -1
  150. data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +8 -1
  151. data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +32 -0
  152. data/app/controllers/spree/api/v3/seller/orders_controller.rb +35 -14
  153. data/app/controllers/spree/api/v3/seller/package_types_controller.rb +21 -9
  154. data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +10 -0
  155. data/app/controllers/spree/api/v3/seller/policies_controller.rb +12 -4
  156. data/app/controllers/spree/api/v3/seller/products_controller.rb +114 -28
  157. data/app/controllers/spree/api/v3/seller/profile_controller.rb +33 -10
  158. data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +12 -5
  159. data/app/controllers/spree/api/v3/seller/resource_controller.rb +12 -0
  160. data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +44 -13
  161. data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +10 -1
  162. data/app/controllers/spree/api/v3/seller/team_controller.rb +4 -0
  163. data/app/controllers/spree/api/v3/store/auth_controller.rb +10 -0
  164. data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +8 -1
  165. data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +10 -2
  166. data/app/controllers/spree/api/v3/store/carts/gift_cards_controller.rb +8 -1
  167. data/app/controllers/spree/api/v3/store/carts/items_controller.rb +17 -5
  168. data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +20 -6
  169. data/app/controllers/spree/api/v3/store/carts/payments_controller.rb +11 -0
  170. data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +24 -26
  171. data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +19 -1
  172. data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +5 -1
  173. data/app/controllers/spree/api/v3/store/carts_controller.rb +54 -47
  174. data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +12 -4
  175. data/app/controllers/spree/api/v3/store/companies/members_controller.rb +4 -0
  176. data/app/controllers/spree/api/v3/store/companies_controller.rb +5 -1
  177. data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +9 -1
  178. data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +8 -7
  179. data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +5 -0
  180. data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +17 -0
  181. data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +10 -5
  182. data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +5 -1
  183. data/app/controllers/spree/api/v3/store/customers_controller.rb +28 -2
  184. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +22 -0
  185. data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +11 -2
  186. data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +10 -1
  187. data/app/controllers/spree/api/v3/store/orders_controller.rb +47 -10
  188. data/app/controllers/spree/api/v3/store/products_controller.rb +8 -0
  189. data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +10 -4
  190. data/app/controllers/spree/api/v3/store/wishlists_controller.rb +12 -4
  191. data/app/request_schemas/spree/api/v3/address_request_schema.rb +27 -0
  192. data/app/request_schemas/spree/api/v3/admin/address_request_schema.rb +13 -0
  193. data/app/request_schemas/spree/api/v3/admin/bulk_tags_request_schema.rb +17 -0
  194. data/app/request_schemas/spree/api/v3/admin/catalog_order_minimum_request_schema.rb +17 -0
  195. data/app/request_schemas/spree/api/v3/admin/email_template_language_request_schema.rb +17 -0
  196. data/app/request_schemas/spree/api/v3/admin/email_template_preview_request_schema.rb +32 -0
  197. data/app/request_schemas/spree/api/v3/admin/price_adjustment_tier_request_schema.rb +21 -0
  198. data/app/request_schemas/spree/api/v3/admin/price_list_price_request_schema.rb +21 -0
  199. data/app/request_schemas/spree/api/v3/admin/price_list_rule_request_schema.rb +19 -0
  200. data/app/request_schemas/spree/api/v3/admin/product_membership_reposition_request_schema.rb +17 -0
  201. data/app/request_schemas/spree/api/v3/admin/promotion_action_calculator_request_schema.rb +18 -0
  202. data/app/request_schemas/spree/api/v3/admin/promotion_action_line_item_request_schema.rb +15 -0
  203. data/app/request_schemas/spree/api/v3/admin/promotion_action_request_schema.rb +19 -0
  204. data/app/request_schemas/spree/api/v3/admin/promotion_rule_request_schema.rb +22 -0
  205. data/app/request_schemas/spree/api/v3/admin/reason_request_schema.rb +14 -0
  206. data/app/request_schemas/spree/api/v3/admin/tax_identifier_request_schema.rb +15 -0
  207. data/app/request_schemas/spree/api/v3/custom_field_value_request_schema.rb +15 -0
  208. data/app/request_schemas/spree/api/v3/file_upload_request_schema.rb +20 -0
  209. data/app/request_schemas/spree/api/v3/media_request_schema.rb +27 -0
  210. data/app/request_schemas/spree/api/v3/price_request_schema.rb +17 -0
  211. data/app/request_schemas/spree/api/v3/stock_level_request_schema.rb +18 -0
  212. data/app/request_schemas/spree/api/v3/store/address_request_schema.rb +31 -0
  213. data/app/request_schemas/spree/api/v3/tax_identifier_request_schema.rb +18 -0
  214. data/app/request_schemas/spree/api/v3/variant_option_request_schema.rb +13 -0
  215. data/app/request_schemas/spree/api/v3/variant_request_schema.rb +52 -0
  216. data/app/serializers/concerns/spree/api/v3/purchase_summary.rb +48 -0
  217. data/app/serializers/spree/api/v3/address_serializer.rb +4 -2
  218. data/app/serializers/spree/api/v3/admin/address_serializer.rb +3 -0
  219. data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +3 -1
  220. data/app/serializers/spree/api/v3/admin/cart_serializer.rb +3 -1
  221. data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +3 -2
  222. data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +3 -4
  223. data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +4 -3
  224. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +5 -7
  225. data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +7 -0
  226. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +5 -0
  227. data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +7 -18
  228. data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +7 -11
  229. data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +0 -2
  230. data/app/serializers/spree/api/v3/admin/country_serializer.rb +4 -0
  231. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +3 -7
  232. data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +0 -2
  233. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +14 -10
  234. data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +9 -1
  235. data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +8 -0
  236. data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -1
  237. data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +5 -0
  238. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +5 -0
  239. data/app/serializers/spree/api/v3/admin/fee_serializer.rb +3 -1
  240. data/app/serializers/spree/api/v3/admin/file_upload_serializer.rb +11 -0
  241. data/app/serializers/spree/api/v3/admin/file_upload_target_serializer.rb +10 -0
  242. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +13 -11
  243. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +3 -3
  244. data/app/serializers/spree/api/v3/admin/import_serializer.rb +2 -2
  245. data/app/serializers/spree/api/v3/admin/integration_serializer.rb +1 -3
  246. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +12 -12
  247. data/app/serializers/spree/api/v3/admin/locale_serializer.rb +13 -0
  248. data/app/serializers/spree/api/v3/admin/market_serializer.rb +3 -0
  249. data/app/serializers/spree/api/v3/admin/media_serializer.rb +3 -2
  250. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +2 -0
  251. data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +1 -3
  252. data/app/serializers/spree/api/v3/admin/order_serializer.rb +33 -33
  253. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +1 -4
  254. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -3
  255. data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +8 -9
  256. data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +3 -6
  257. data/app/serializers/spree/api/v3/admin/price_history_serializer.rb +6 -2
  258. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +1 -5
  259. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +1 -3
  260. data/app/serializers/spree/api/v3/admin/price_serializer.rb +4 -0
  261. data/app/serializers/spree/api/v3/admin/product_serializer.rb +2 -0
  262. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +4 -6
  263. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +0 -2
  264. data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +5 -11
  265. data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +4 -4
  266. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +7 -3
  267. data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +9 -2
  268. data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +8 -0
  269. data/app/serializers/spree/api/v3/admin/return_serializer.rb +8 -4
  270. data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +15 -10
  271. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +3 -5
  272. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +3 -1
  273. data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +7 -8
  274. data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +4 -4
  275. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +3 -0
  276. data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +2 -6
  277. data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +5 -0
  278. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +9 -4
  279. data/app/serializers/spree/api/v3/admin/store_serializer.rb +17 -98
  280. data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +1 -1
  281. data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +3 -1
  282. data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +4 -2
  283. data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +2 -12
  284. data/app/serializers/spree/api/v3/admin/update_status_serializer.rb +28 -0
  285. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +7 -3
  286. data/app/serializers/spree/api/v3/base_serializer.rb +112 -7
  287. data/app/serializers/spree/api/v3/cart_serializer.rb +16 -30
  288. data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +5 -13
  289. data/app/serializers/spree/api/v3/claim_serializer.rb +2 -3
  290. data/app/serializers/spree/api/v3/country_serializer.rb +2 -1
  291. data/app/serializers/spree/api/v3/currency_serializer.rb +9 -1
  292. data/app/serializers/spree/api/v3/customer_serializer.rb +3 -2
  293. data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +8 -12
  294. data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +1 -1
  295. data/app/serializers/spree/api/v3/discount_serializer.rb +4 -1
  296. data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +2 -8
  297. data/app/serializers/spree/api/v3/exchange_serializer.rb +2 -3
  298. data/app/serializers/spree/api/v3/file_upload_serializer.rb +28 -0
  299. data/app/serializers/spree/api/v3/file_upload_target_serializer.rb +17 -0
  300. data/app/serializers/spree/api/v3/gift_card_batch_serializer.rb +2 -4
  301. data/app/serializers/spree/api/v3/gift_card_serializer.rb +4 -2
  302. data/app/serializers/spree/api/v3/import_serializer.rb +0 -12
  303. data/app/serializers/spree/api/v3/line_item_serializer.rb +15 -5
  304. data/app/serializers/spree/api/v3/locale_serializer.rb +3 -1
  305. data/app/serializers/spree/api/v3/market_serializer.rb +5 -5
  306. data/app/serializers/spree/api/v3/media_serializer.rb +7 -2
  307. data/app/serializers/spree/api/v3/order_group_serializer.rb +12 -4
  308. data/app/serializers/spree/api/v3/order_serializer.rb +5 -23
  309. data/app/serializers/spree/api/v3/payment_session_serializer.rb +2 -4
  310. data/app/serializers/spree/api/v3/price_history_serializer.rb +11 -6
  311. data/app/serializers/spree/api/v3/price_serializer.rb +17 -10
  312. data/app/serializers/spree/api/v3/product_filter_price_range_serializer.rb +10 -4
  313. data/app/serializers/spree/api/v3/product_serializer.rb +3 -3
  314. data/app/serializers/spree/api/v3/refund_serializer.rb +8 -5
  315. data/app/serializers/spree/api/v3/return_line_item_serializer.rb +3 -11
  316. data/app/serializers/spree/api/v3/return_serializer.rb +3 -6
  317. data/app/serializers/spree/api/v3/seller/address_serializer.rb +12 -0
  318. data/app/serializers/spree/api/v3/seller/balance_serializer.rb +15 -10
  319. data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +7 -0
  320. data/app/serializers/spree/api/v3/seller/claim_serializer.rb +5 -0
  321. data/app/serializers/spree/api/v3/seller/country_serializer.rb +19 -0
  322. data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +1 -3
  323. data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +4 -8
  324. data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +9 -8
  325. data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +5 -0
  326. data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +5 -0
  327. data/app/serializers/spree/api/v3/seller/file_upload_serializer.rb +11 -0
  328. data/app/serializers/spree/api/v3/seller/file_upload_target_serializer.rb +10 -0
  329. data/app/serializers/spree/api/v3/seller/import_serializer.rb +2 -2
  330. data/app/serializers/spree/api/v3/seller/media_serializer.rb +2 -5
  331. data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +4 -3
  332. data/app/serializers/spree/api/v3/seller/order_serializer.rb +16 -16
  333. data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +8 -9
  334. data/app/serializers/spree/api/v3/seller/payout_serializer.rb +2 -4
  335. data/app/serializers/spree/api/v3/seller/price_history_serializer.rb +12 -0
  336. data/app/serializers/spree/api/v3/seller/price_serializer.rb +13 -0
  337. data/app/serializers/spree/api/v3/seller/product_serializer.rb +2 -0
  338. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +7 -7
  339. data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +8 -0
  340. data/app/serializers/spree/api/v3/seller/return_serializer.rb +8 -5
  341. data/app/serializers/spree/api/v3/seller/state_serializer.rb +10 -0
  342. data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +3 -0
  343. data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +6 -7
  344. data/app/serializers/spree/api/v3/seller/variant_serializer.rb +8 -4
  345. data/app/serializers/spree/api/v3/stock_location_serializer.rb +8 -1
  346. data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +1 -3
  347. data/app/serializers/spree/api/v3/store_credit_serializer.rb +3 -5
  348. data/app/serializers/spree/api/v3/tax_line_serializer.rb +2 -4
  349. data/app/serializers/spree/api/v3/variant_serializer.rb +3 -3
  350. data/app/services/spree/api/v3/filter_predicates.rb +29 -0
  351. data/app/services/spree/api/v3/filter_table.rb +337 -0
  352. data/app/services/spree/api/v3/filters_aggregator.rb +2 -2
  353. data/app/services/spree/api/v3/request_schema.rb +430 -0
  354. data/app/services/spree/webhooks/deliver_webhook.rb +7 -3
  355. data/config/initializers/typelizer.rb +1 -1
  356. data/config/routes.rb +5 -3
  357. data/lib/spree/api/configuration.rb +5 -0
  358. data/lib/spree/api/dependencies.rb +7 -6
  359. data/lib/spree/api/middleware/request_size_limit.rb +24 -3
  360. data/lib/spree/api/openapi/filter_documentation.rb +136 -0
  361. data/lib/spree/api/openapi/schema_helper.rb +126 -80
  362. data/lib/spree/api/preference_families.rb +46 -0
  363. data/lib/spree/api/preference_types.rb +138 -0
  364. data/lib/spree/api/typelizer_generation.rb +4 -0
  365. data/lib/tasks/filters.rake +12 -0
  366. data/lib/typelizer/open_enums.rb +10 -0
  367. metadata +60 -10
  368. data/app/controllers/concerns/spree/api/v3/address_params.rb +0 -17
  369. data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +0 -35
  370. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +0 -54
  371. data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3816f80ebaf4e6b8bc42854938340dce8bc17f6190d55337a7e08950fedf7fb1
4
- data.tar.gz: 42034e2f05201a30da2d13345b761e1376523ecf98f64668de3538de772a19f2
3
+ metadata.gz: 2bf002c9d8182f8a69971d92c1ba84a2fe26571baefa007570c1a6e30761bd48
4
+ data.tar.gz: 78504b7007e37077c04a3b75b33644ad3e127670d7ec221888743bac8f25c9aa
5
5
  SHA512:
6
- metadata.gz: f315aff41e1e8731961bfa6cf18bba36428e222aa11ed341b66c9b74bee863eb53b5cece23b361a73a036f5d744e25037e25ec1a49004653a8a7f0448f29a10c
7
- data.tar.gz: 34d2faa68118ec0bba15cf75b5711ade7aa0b1d817606180a3e7fb2a57bfdb816799f2911b83b41833f07251f0781d9d5e9046251eb6068356956839b38fc59e
6
+ metadata.gz: ab37287b927bcbcc8c0e79ecfad9795608390098243660a2bd0b79a0c8b104b72a0f7485b1b67790b5f7b0978ea3af18349b7870b50c85edfdeb1702e1eca87a
7
+ data.tar.gz: 2317c9ac3b2cd0aecdcf432d9c83dab6ec44b077b078c960ddda56b9a066a41080841779c2a1bd6838bfb2fe07c71b03d3e6b34b8ad37681df20f61bdd637c98
data/Rakefile CHANGED
@@ -45,23 +45,6 @@ namespace :rswag do
45
45
  puts "Reordered paths by tag → #{path}"
46
46
  end
47
47
  end
48
-
49
- # Keep the CLI's bundled offline spec (@spree/cli's `admin-spec.json` /
50
- # `resource-paths.json`) in sync with the freshly generated admin.yaml,
51
- # so `spree api endpoints`/`schema` never drift from the published docs.
52
- # Best-effort: skipped with a notice when the JS toolchain isn't present
53
- # (this is a Ruby/doc task and shouldn't hard-fail on a missing runtime).
54
- bundler = File.expand_path('../../packages/cli/scripts/bundle-spec.mjs', __dir__)
55
- if File.exist?(bundler) && system('node', '--version', out: File::NULL, err: File::NULL)
56
- cli_dir = File.expand_path('../../packages/cli', __dir__)
57
- if system('node', bundler, chdir: cli_dir)
58
- puts 'Regenerated CLI offline spec → packages/cli/src/generated/'
59
- else
60
- warn 'WARNING: failed to regenerate CLI offline spec (bundle-spec.mjs); run `pnpm --filter @spree/cli build` to resync.'
61
- end
62
- else
63
- puts 'Skipping CLI offline spec regeneration (node/bundle-spec.mjs unavailable).'
64
- end
65
48
  end
66
49
  end
67
50
  end
@@ -32,6 +32,16 @@ module Spree
32
32
  # Membership actions resolve products themselves; the base
33
33
  # single-resource load has nothing to look up.
34
34
  skip_before_action :set_resource
35
+
36
+ # Adding (create) and removing (destroy) take the same body.
37
+ [nil, :destroy].each do |action|
38
+ request_params 'ProductMembershipParams', action: action do |body|
39
+ body.attribute :product_ids, :array, of: :id,
40
+ required: true,
41
+ example: %w[prod_abc123],
42
+ description: 'Products from other stores, or ones the caller cannot see, are ignored.'
43
+ end
44
+ end
35
45
  end
36
46
 
37
47
  # POST /{parents}/:parent_id/products
@@ -15,6 +15,32 @@ module Spree
15
15
 
16
16
  included do
17
17
  before_action :authorize_parent_access!
18
+
19
+ # Read from the raw params by `create_workflow_arguments`, with
20
+ # every line resolved through the document.
21
+ request_params :stock_receipt do |body|
22
+ body.attribute :reference, :string,
23
+ nullable: true,
24
+ example: 'DN-4471',
25
+ description: "The supplier's delivery note, or the carrier's reference."
26
+ body.attribute :received_at, :datetime,
27
+ nullable: true,
28
+ description: 'When the goods were counted in. Defaults to now.'
29
+ body.attribute :notes, :string, nullable: true
30
+ body.attribute :items, :array,
31
+ permit: false,
32
+ as: 'StockReceiptItemParams',
33
+ description: 'Omit to book in everything still outstanding, intact. Naming lines, even none, records exactly what the dock counted: `quantity_accepted` reaches the shelf; `quantity_rejected` is refused, recorded with a `rejection_reason` and never stocked.' do |item|
34
+ item.attribute :id, :id, required: true, description: 'The purchase order or transfer line.'
35
+ item.attribute :quantity_accepted, :integer, example: 58
36
+ item.attribute :quantity_rejected, :integer, example: 2
37
+ item.attribute :rejection_reason, :string,
38
+ nullable: true,
39
+ choices: Spree::StockReceiptItem::REJECTION_REASONS,
40
+ example: 'damaged'
41
+ item.attribute :notes, :string, nullable: true
42
+ end
43
+ end
18
44
  end
19
45
 
20
46
  protected
@@ -39,10 +65,6 @@ module Spree
39
65
  [items: :line]
40
66
  end
41
67
 
42
- def resource_permitted_attributes
43
- [:received_at, :reference, :notes]
44
- end
45
-
46
68
  def create_workflow_arguments
47
69
  {
48
70
  receivable_keyword => @parent,
@@ -13,11 +13,10 @@ module Spree
13
13
  #
14
14
  # The body picks the subclass against the registry (returns 422 with
15
15
  # the configured error code on miss), strips `type`/`preferences`
16
- # from the permitted attrs, builds/assigns the rest, and routes
17
- # preference values through the typed `preferred_<name>=` setters
18
- # so booleans/decimals/etc. get coerced. Unknown preference keys
19
- # are silently dropped — the schema endpoint is the source of truth
20
- # for what's settable.
16
+ # from the permitted attrs, builds/assigns the rest, and writes the
17
+ # preferences after checking them against the subclass's schema —
18
+ # an unknown key or a value of the wrong type is a 422
19
+ # `invalid_preferences`.
21
20
  module SubclassedResource
22
21
  extend ActiveSupport::Concern
23
22
 
@@ -45,9 +44,9 @@ module Spree
45
44
  attrs, preferences, calculator = extract_subclass_params(permitted)
46
45
 
47
46
  @resource = build_subclassed_resource(klass, attrs)
47
+ authorize_resource!(@resource, :create)
48
48
  apply_preferences(@resource, preferences) if preferences.present?
49
49
  apply_calculator(@resource, calculator) if calculator.present?
50
- authorize_resource!(@resource, :create)
51
50
 
52
51
  if @resource.save
53
52
  render json: serialize_resource(@resource), status: :created
@@ -63,11 +62,13 @@ module Spree
63
62
  permitted = permitted_params_for(@resource.class)
64
63
  attrs, preferences, calculator = extract_subclass_params(permitted)
65
64
 
66
- @resource.assign_attributes(attrs)
67
- apply_preferences(@resource, preferences) if preferences.present?
68
- apply_calculator(@resource, calculator) if calculator.present?
65
+ saved = save_atomically do
66
+ @resource.assign_attributes(attrs)
67
+ apply_preferences(@resource, preferences) if preferences.present?
68
+ apply_calculator(@resource, calculator) if calculator.present?
69
+ end
69
70
 
70
- if @resource.save
71
+ if saved
71
72
  render json: serialize_resource(@resource)
72
73
  else
73
74
  render_validation_error(@resource.errors)
@@ -109,25 +110,10 @@ module Spree
109
110
  )
110
111
  end
111
112
 
113
+ # Validated against the subclass's schema before anything is written
114
+ # (see `Spree::Preferences::Preferable#assign_preferences`).
112
115
  def apply_preferences(resource, preferences)
113
- password_keys = resource.password_preference_keys
114
-
115
- preferences.each do |key, value|
116
- pref_name = key.to_sym
117
- next unless resource.has_preference?(pref_name)
118
- # Internal preferences are Spree's to write — a secret a
119
- # provider issued, an id it gave back. They are absent from the
120
- # schema, so no form offers them; ignoring them here is what
121
- # stops a client writing one anyway and breaking the signature
122
- # check that depends on it.
123
- next if resource.preference_internal(pref_name)
124
- # Round-trip guard: clients fetching a record see masked
125
- # `:password` values. Submitting the mask back unchanged
126
- # must NOT overwrite the real secret with `••••cret`.
127
- next if password_keys.include?(pref_name) && Spree::Preferences::Masking.masked?(value)
128
-
129
- resource.set_preference(pref_name, value)
130
- end
116
+ resource.assign_preferences(preferences)
131
117
  end
132
118
 
133
119
  # Pulls `preferences` and `calculator` out of the permitted
@@ -26,7 +26,7 @@ module Spree
26
26
  # nil code, which the dashboard reads as "render the message".
27
27
  details = errors.details[attribute] || []
28
28
 
29
- result[attribute] = messages.each_with_index.map do |message, index|
29
+ result[wire_error_attribute(errors, attribute)] = messages.each_with_index.map do |message, index|
30
30
  detail = details[index] || {}
31
31
  code = detail[:error].is_a?(Symbol) ? detail[:error] : nil
32
32
 
@@ -4,6 +4,8 @@ module Spree
4
4
  module CartResolvable
5
5
  extend ActiveSupport::Concern
6
6
 
7
+ include Spree::Api::V3::PurchaseSerialization
8
+
7
9
  protected
8
10
 
9
11
  # Find cart by prefixed ID and authorize read access (owner or guest
@@ -73,9 +75,8 @@ module Spree
73
75
  # needs there.
74
76
  def render_order(status: :ok)
75
77
  record = @cart.reload
76
- serializer = record.is_a?(Spree::OrderGroup) ? Spree.api.order_group_serializer : Spree.api.order_serializer
77
78
 
78
- render json: serializer.new(record, params: serializer_params).to_h, status: status
79
+ render json: purchase_serializer_for(record).new(record, params: serializer_params).to_h, status: status
79
80
  end
80
81
 
81
82
  # Return the cart token from the request headers.
@@ -60,7 +60,7 @@ module Spree
60
60
  render_error(
61
61
  code: ErrorHandler::ERROR_CODES[:channel_mismatch],
62
62
  message: I18n.t('spree.api.errors.channel_mismatch'),
63
- status: :unprocessable_entity
63
+ status: :unprocessable_content
64
64
  )
65
65
  return
66
66
  end
@@ -13,8 +13,10 @@ module Spree
13
13
 
14
14
  protected
15
15
 
16
+ # Each including controller declares the address it takes with
17
+ # `request_params`.
16
18
  def permitted_params
17
- params.permit(:label, *Spree::Api::V3::AddressParams::ADDRESS_KEYS)
19
+ params.permit(*declared_permitted_attributes)
18
20
  end
19
21
 
20
22
  # @return [Hash] default keywords for Spree::Addresses::Create / Update
@@ -48,10 +48,12 @@ module Spree
48
48
  insufficient_stock: 'insufficient_stock',
49
49
  invalid_quantity: 'invalid_quantity',
50
50
  invalid_price: 'invalid_price',
51
+ invalid_money_format: 'invalid_money_format',
51
52
  price_override_not_allowed: 'price_override_not_allowed',
52
53
 
53
54
  # Validation errors
54
55
  validation_error: 'validation_error',
56
+ invalid_preferences: 'invalid_preferences',
55
57
  parameter_missing: 'parameter_missing',
56
58
  parameter_invalid: 'parameter_invalid',
57
59
 
@@ -101,8 +103,11 @@ module Spree
101
103
  rescue_from Spree::Core::GatewayError, with: :handle_gateway_error
102
104
  rescue_from ActionController::ParameterMissing, with: :handle_parameter_missing
103
105
  rescue_from ActiveRecord::RecordInvalid, with: :handle_record_invalid
106
+ rescue_from Spree::Preferences::InvalidPreferences, with: :handle_invalid_preferences
107
+ rescue_from ActiveRecord::RecordNotSaved, with: :handle_record_not_saved
104
108
  rescue_from ArgumentError, with: :handle_argument_error
105
109
  rescue_from ActionDispatch::Http::Parameters::ParseError, with: :handle_parse_error
110
+ rescue_from ActiveSupport::MessageVerifier::InvalidSignature, with: :handle_invalid_signature
106
111
  end
107
112
 
108
113
  protected
@@ -244,6 +249,26 @@ module Spree
244
249
  render_validation_error(exception.record.errors)
245
250
  end
246
251
 
252
+ # Each failing value is keyed by its JSON pointer into the request,
253
+ # e.g. `/preferences/channel_ids/1`.
254
+ def handle_invalid_preferences(exception)
255
+ render_error(
256
+ code: ERROR_CODES[:invalid_preferences],
257
+ message: exception.message,
258
+ status: :unprocessable_content,
259
+ details: exception.failures.group_by { |failure| failure[:pointer] }.transform_values { |failures| failures.pluck(:message) }
260
+ )
261
+ end
262
+
263
+ # Replacing a has_one on a saved record saves the new one at once, and
264
+ # raises when that one fails its own validations.
265
+ def handle_record_not_saved(exception)
266
+ errors = exception.record&.errors
267
+ return render_validation_error(errors) if errors.present?
268
+
269
+ render_error(code: ERROR_CODES[:validation_error], message: exception.message, status: :unprocessable_content)
270
+ end
271
+
247
272
  def handle_argument_error(exception)
248
273
  Rails.error.report(exception, context: error_context, source: 'spree.api.v3')
249
274
  render_error(
@@ -253,6 +278,16 @@ module Spree
253
278
  )
254
279
  end
255
280
 
281
+ # A `signed_id` that was tampered with, or has expired (they last a
282
+ # day), is a bad parameter rather than a server fault.
283
+ def handle_invalid_signature(_exception)
284
+ render_error(
285
+ code: ERROR_CODES[:parameter_invalid],
286
+ message: I18n.t('spree.upload_reference_invalid'),
287
+ status: :unprocessable_content
288
+ )
289
+ end
290
+
256
291
  def handle_parse_error(exception)
257
292
  Rails.error.report(exception, context: error_context, source: 'spree.api.v3')
258
293
  message = exception.respond_to?(:original_message) ? exception.original_message : exception.message
@@ -268,11 +303,22 @@ module Spree
268
303
 
269
304
  # Format validation errors for details field
270
305
  def format_validation_details(errors)
271
- errors.messages.transform_values do |messages|
272
- messages.map { |msg| msg }
306
+ errors.messages.to_h do |attribute, messages|
307
+ [wire_error_attribute(errors, attribute), messages.map { |msg| msg }]
273
308
  end
274
309
  end
275
310
 
311
+ # A setting the API reads and writes under its plain name reports its
312
+ # errors under that name too, never the `preferred_` one the model uses;
313
+ # an attachment slot reports them under the `<slot>_signed_id` it is
314
+ # written with.
315
+ def wire_error_attribute(errors, attribute)
316
+ record_class = errors.objects.first&.base&.class
317
+ (record_class.exposed_preference_name(attribute) if record_class.respond_to?(:exposed_preference_name)) ||
318
+ (record_class.signed_id_attribute_for(attribute) if record_class.respond_to?(:signed_id_attribute_for)) ||
319
+ attribute
320
+ end
321
+
276
322
  # Infer error code from context
277
323
  def infer_error_code(errors, status)
278
324
  case status
@@ -0,0 +1,35 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # `POST /files`: accepts a file for the current store and returns the
5
+ # opaque, expiring `signed_id` an endpoint that uses the file takes
6
+ # (docs/plans/6.0-uploads-and-file-ownership.md).
7
+ #
8
+ # A JSON request carries the file's metadata and gets back a storage
9
+ # target to send the bytes to; a multipart request carries the bytes in
10
+ # its `file` part. Shared by the admin and seller branches: a file
11
+ # stored here is attached to nothing, so what differs is only the gate
12
+ # each branch puts in front of it, which stays on the including
13
+ # controller as its `scoped_resource`.
14
+ module FileUploads
15
+ extend ActiveSupport::Concern
16
+
17
+ def create
18
+ file_upload = Spree::FileUpload.new(store: current_store, **file_upload_params)
19
+
20
+ if file_upload.save
21
+ render json: file_upload_serializer.new(file_upload, params: serializer_params).to_h, status: :created
22
+ else
23
+ render_validation_error(file_upload.errors)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def file_upload_params
30
+ params.permit(*declared_permitted_attributes).to_h.symbolize_keys
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,52 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Money read from a request. The contract is a canonical decimal string
5
+ # ("19.99"); a JSON number, a localized string or more decimals than the
6
+ # currency has is answered with `invalid_money_format`, naming the field.
7
+ module MoneyParams
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ rescue_from Spree::Money::InvalidFormat, with: :render_invalid_money_format
12
+ end
13
+
14
+ protected
15
+
16
+ # @param name [Symbol] the request parameter
17
+ # @param currency [String] the currency the amount is in
18
+ # @param unit_price [Boolean] allows up to four decimals
19
+ # @return [BigDecimal, nil] nil when the parameter is absent
20
+ # @raise [Spree::Money::InvalidFormat]
21
+ def money_param(name, currency, unit_price: false)
22
+ Spree::Money::Rounding.parse_canonical(params[name], currency, unit_price: unit_price)
23
+ rescue Spree::Money::InvalidFormat => error
24
+ raise Spree::Money::InvalidFormat.new(error.message, field: name)
25
+ end
26
+
27
+ # A rate or other plain decimal: any number of decimals, but still a
28
+ # canonical decimal string.
29
+ #
30
+ # @param name [Symbol] the request parameter
31
+ # @return [BigDecimal, nil] nil when the parameter is absent
32
+ # @raise [Spree::Money::InvalidFormat]
33
+ def decimal_param(name)
34
+ Spree::Money::Rounding.parse_canonical_decimal(params[name])
35
+ rescue Spree::Money::InvalidFormat => error
36
+ raise Spree::Money::InvalidFormat.new(error.message, field: name)
37
+ end
38
+
39
+ private
40
+
41
+ def render_invalid_money_format(error)
42
+ render_error(
43
+ code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:invalid_money_format],
44
+ message: [error.field, error.message].compact.join(' '),
45
+ status: :unprocessable_content,
46
+ details: error.field ? { error.field => [error.message] } : nil
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -59,11 +59,7 @@ module Spree
59
59
  private
60
60
 
61
61
  def create_params
62
- @create_params ||= params.permit(
63
- :memo, :reason_id,
64
- items: [:line_item_id, :quantity, :description, :send_replacement,
65
- :replacement_variant_id, :refund_amount]
66
- )
62
+ @create_params ||= params.permit(*declared_permitted_attributes)
67
63
  end
68
64
 
69
65
  # Every claimed line is resolved through the order itself, so a line
@@ -25,7 +25,7 @@ module Spree
25
25
  # reject rather than a keyword it was never given.
26
26
  result = Spree.delivery_create_service.call(
27
27
  owner: @parent,
28
- **resource_permitted_attributes.index_with { |key| delivery_params[key] }
28
+ **delivery_keys.index_with { |key| delivery_params[key] }
29
29
  )
30
30
 
31
31
  render_result(result, status: :created)
@@ -77,14 +77,14 @@ module Spree
77
77
  [:shipping_label]
78
78
  end
79
79
 
80
- def resource_permitted_attributes
81
- [:tracking_number, :carrier, :service, :tracking_url]
82
- end
83
-
84
80
  private
85
81
 
86
82
  def delivery_params
87
- @delivery_params ||= params.permit(*resource_permitted_attributes)
83
+ @delivery_params ||= params.permit(*declared_permitted_attributes)
84
+ end
85
+
86
+ def delivery_keys
87
+ declared_permitted_attributes.grep(Symbol)
88
88
  end
89
89
 
90
90
  # Deliveries can hang off something other than a fulfillment, which
@@ -61,10 +61,7 @@ module Spree
61
61
  private
62
62
 
63
63
  def create_params
64
- @create_params ||= params.permit(
65
- :memo, :reason_id, :stock_location_id,
66
- items: [:fulfillment_item_id, :new_variant_id, :quantity]
67
- )
64
+ @create_params ||= params.permit(*declared_permitted_attributes)
68
65
  end
69
66
 
70
67
  # The units going back are resolved through the order; what comes
@@ -94,11 +94,7 @@ module Spree
94
94
  private
95
95
 
96
96
  def fulfill_params
97
- @fulfill_params ||= params.permit(*fulfill_permitted_keys)
98
- end
99
-
100
- def fulfill_permitted_keys
101
- [:tracking, :tracking_carrier, :notify_customer, { items: [:item_id, :quantity] }]
97
+ @fulfill_params ||= params.permit(*declared_permitted_attributes)
102
98
  end
103
99
 
104
100
  # Extra keywords the branch's own fulfil accepts — forcing past a
@@ -61,10 +61,7 @@ module Spree
61
61
  private
62
62
 
63
63
  def create_params
64
- @create_params ||= params.permit(
65
- :memo, :reason_id, :stock_location_id,
66
- items: [:fulfillment_item_id, :quantity]
67
- )
64
+ @create_params ||= params.permit(*declared_permitted_attributes)
68
65
  end
69
66
 
70
67
  # The units coming back, resolved through the order itself, so a
@@ -18,9 +18,6 @@ module Spree
18
18
  included do
19
19
  include ActiveStorage::SetCurrent
20
20
  include Spree::Api::V3::StreamsShippingLabel
21
-
22
- rescue_from ActiveSupport::MessageVerifier::InvalidSignature,
23
- with: :render_invalid_signature
24
21
  end
25
22
 
26
23
  # GET .../labels/:id/download
@@ -83,40 +80,27 @@ module Spree
83
80
 
84
81
  private
85
82
 
86
- def label_permitted_keys
87
- [:file, :tracking_number, :carrier, :service,
88
- :cost, :currency, :file_format, :tracking_url]
89
- end
90
-
91
83
  def label_params
92
- @label_params ||= params.permit(*label_permitted_keys)
84
+ @label_params ||= params.permit(*declared_permitted_attributes)
93
85
  end
94
86
 
95
87
  # Records a label bought outside Spree.
96
88
  #
97
89
  # Every key is passed whether or not the request carried it, so the
98
90
  # workflow sees a missing tracking number as a blank one to reject
99
- # rather than a keyword it was never given.
91
+ # rather than a keyword it was never given. The workflow takes any
92
+ # attachable as `file`; the API names the reference `file_signed_id`.
100
93
  def record_uploaded_label
101
94
  with_order_lock do
102
95
  result = Spree.shipping_label_record_workflow.call(
103
96
  owner: @parent,
104
- **label_permitted_keys.index_with { |key| label_params[key] }
97
+ file: label_params[:file_signed_id],
98
+ **(declared_permitted_attributes.grep(Symbol) - [:file_signed_id]).index_with { |key| label_params[key] }
105
99
  )
106
100
 
107
101
  render_result(result, status: :created)
108
102
  end
109
103
  end
110
-
111
- # A tampered or expired direct-upload signature is a bad parameter,
112
- # not a server fault.
113
- def render_invalid_signature
114
- render_error(
115
- code: Spree::Api::V3::ErrorHandler::ERROR_CODES[:parameter_invalid],
116
- message: I18n.t('spree.shipping_labels.errors.file_required'),
117
- status: :unprocessable_content
118
- )
119
- end
120
104
  end
121
105
  end
122
106
  end
@@ -30,6 +30,11 @@ module Spree
30
30
  def resolve_prefixed_ids(hash)
31
31
  hash.each_with_object({}.with_indifferent_access) do |(key, value), result|
32
32
  result[key] = case
33
+ # Preferences declare which of their values are ids
34
+ # and decode only those, after checking them against
35
+ # their schema.
36
+ when key.to_s == 'preferences'
37
+ value
33
38
  when key.to_s.end_with?('_id') && prefixed_id?(value)
34
39
  decode_prefixed_id(value)
35
40
  when key.to_s.end_with?('_ids') && value.is_a?(Array)
@@ -0,0 +1,26 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Which serializer describes what a checkout produced.
5
+ #
6
+ # A checkout answers with one record: the order it placed, or — when the
7
+ # basket reached several sellers — the group holding one order per
8
+ # seller. Which of the two it is follows the record, never the endpoint,
9
+ # so every surface that resolves a checkout hands back the whole purchase
10
+ # rather than one seller's share of it.
11
+ module PurchaseSerialization
12
+ extend ActiveSupport::Concern
13
+
14
+ protected
15
+
16
+ # @param record [Spree::Order, Spree::OrderGroup, Spree::Cart]
17
+ # @return [Class] the serializer that describes it
18
+ def purchase_serializer_for(record)
19
+ return Spree.api.order_group_serializer if record.is_a?(Spree::OrderGroup)
20
+
21
+ Spree.api.order_serializer
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,65 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ # Declares what a controller's write actions accept (see
5
+ # Spree::Api::V3::RequestSchema). The resource controller permits from the
6
+ # declaration, and the integration specs document it with
7
+ # `request_body_for`, which is where the SDK request types come from.
8
+ #
9
+ # request_params :product do ... end # create and update
10
+ # request_params 'ProductBulkStatusParams', action: :bulk_status_update do ... end
11
+ module RequestParams
12
+ extend ActiveSupport::Concern
13
+
14
+ RESOURCE_ACTIONS = %w[create update].freeze
15
+
16
+ included do
17
+ class_attribute :request_params_schemas, instance_writer: false, default: {}
18
+ end
19
+
20
+ class_methods do
21
+ # @param name [String, Symbol, nil] the resource the published types
22
+ # are named after (defaults to the singular controller name), or a
23
+ # name ending in `Params` for a single action's body
24
+ # @param action [Symbol, nil] an action other than create and update
25
+ def request_params(name = nil, action: nil, &block)
26
+ if action && !name.to_s.end_with?('Params')
27
+ raise ArgumentError, "name the body of #{action} with a name ending in Params"
28
+ end
29
+
30
+ schema = Spree::Api::V3::RequestSchema.new(name || controller_name.singularize, &block)
31
+ self.request_params_schemas = request_params_schemas.merge((action || :resource).to_sym => schema)
32
+ end
33
+
34
+ # @param action [Symbol, String]
35
+ # @return [Spree::Api::V3::RequestSchema, nil] what the action accepts
36
+ def request_params_schema(action = :create)
37
+ action = action.to_s
38
+ request_params_schemas[action.to_sym] || (request_params_schemas[:resource] if RESOURCE_ACTIONS.include?(action))
39
+ end
40
+ end
41
+
42
+ protected
43
+
44
+ # The current action's declaration. An action without its own (a
45
+ # custom one writing through +permitted_params+) accepts what update
46
+ # does.
47
+ #
48
+ # @return [Spree::Api::V3::RequestSchema, nil]
49
+ def request_params_schema
50
+ self.class.request_params_schema(action_name) || request_params_schemas[:resource]
51
+ end
52
+
53
+ # The declared `params.permit` list for the current action.
54
+ #
55
+ # @return [Array<Symbol, Hash>]
56
+ def declared_permitted_attributes
57
+ action = action_name.to_s
58
+ # A member action with no body of its own changes an existing
59
+ # record, so it takes what update takes — never a create-only field.
60
+ request_params_schema.permit_list(RESOURCE_ACTIONS.include?(action) ? action : :update)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end