spree_api 5.6.1 → 6.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (540) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +28 -0
  3. data/Rakefile +1 -1
  4. data/app/controllers/concerns/spree/api/v3/address_params.rb +17 -0
  5. data/app/controllers/concerns/spree/api/v3/admin/product_listing.rb +46 -0
  6. data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +110 -0
  7. data/app/controllers/concerns/spree/api/v3/admin/receivable_actions.rb +68 -0
  8. data/app/controllers/concerns/spree/api/v3/admin/reporting_authorization.rb +27 -0
  9. data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +69 -33
  10. data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +86 -0
  11. data/app/controllers/concerns/spree/api/v3/admin/store_context.rb +97 -0
  12. data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +12 -6
  13. data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +91 -0
  14. data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +9 -5
  15. data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +41 -5
  16. data/app/controllers/concerns/spree/api/v3/authentication_strategies.rb +48 -0
  17. data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +4 -6
  18. data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +52 -16
  19. data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +37 -0
  20. data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +41 -0
  21. data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +35 -0
  22. data/app/controllers/concerns/spree/api/v3/error_handler.rb +53 -11
  23. data/app/controllers/concerns/spree/api/v3/idempotent.rb +10 -4
  24. data/app/controllers/concerns/spree/api/v3/items_payload.rb +54 -0
  25. data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +23 -3
  26. data/app/controllers/concerns/spree/api/v3/key_store_context.rb +31 -0
  27. data/app/controllers/concerns/spree/api/v3/locale_and_currency.rb +3 -3
  28. data/app/controllers/concerns/spree/api/v3/order_lock.rb +22 -3
  29. data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +112 -0
  30. data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +105 -0
  31. data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +117 -0
  32. data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +157 -0
  33. data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +76 -0
  34. data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +116 -0
  35. data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +128 -0
  36. data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +7 -4
  37. data/app/controllers/concerns/spree/api/v3/permission_serialization.rb +42 -0
  38. data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +40 -6
  39. data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +80 -26
  40. data/app/controllers/concerns/spree/api/v3/seller/auth_cookies.rb +62 -0
  41. data/app/controllers/concerns/spree/api/v3/seller/seller_context.rb +127 -0
  42. data/app/controllers/concerns/spree/api/v3/seller_authentication.rb +40 -0
  43. data/app/controllers/concerns/spree/api/v3/storefront_access.rb +38 -0
  44. data/app/controllers/concerns/spree/api/v3/streams_shipping_label.rb +37 -0
  45. data/app/controllers/concerns/spree/api/v3/tax_identifier_validation.rb +41 -0
  46. data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +11 -14
  47. data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +1 -1
  48. data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +16 -7
  49. data/app/controllers/spree/api/v3/admin/auth_controller.rb +138 -22
  50. data/app/controllers/spree/api/v3/admin/base_controller.rb +2 -0
  51. data/app/controllers/spree/api/v3/admin/catalog_assignments_controller.rb +27 -0
  52. data/app/controllers/spree/api/v3/admin/catalogs/base_controller.rb +29 -0
  53. data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +40 -0
  54. data/app/controllers/spree/api/v3/admin/catalogs/products_controller.rb +107 -0
  55. data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +75 -0
  56. data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +191 -0
  57. data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +28 -41
  58. data/app/controllers/spree/api/v3/admin/categories_controller.rb +16 -7
  59. data/app/controllers/spree/api/v3/admin/channels_controller.rb +50 -2
  60. data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +25 -0
  61. data/app/controllers/spree/api/v3/admin/claims_controller.rb +31 -0
  62. data/app/controllers/spree/api/v3/admin/collection_rules_controller.rb +40 -0
  63. data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +101 -0
  64. data/app/controllers/spree/api/v3/admin/collections_controller.rb +56 -0
  65. data/app/controllers/spree/api/v3/admin/commission_lines_controller.rb +39 -0
  66. data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +174 -0
  67. data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +65 -0
  68. data/app/controllers/spree/api/v3/admin/companies/base_controller.rb +29 -0
  69. data/app/controllers/spree/api/v3/admin/companies/invitations_controller.rb +56 -0
  70. data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +66 -0
  71. data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +137 -0
  72. data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +46 -0
  73. data/app/controllers/spree/api/v3/admin/companies_controller.rb +59 -0
  74. data/app/controllers/spree/api/v3/admin/concerns/external_references.rb +166 -0
  75. data/app/controllers/spree/api/v3/admin/consent_records_controller.rb +31 -0
  76. data/app/controllers/spree/api/v3/admin/countries_controller.rb +12 -4
  77. data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +19 -4
  78. data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +5 -5
  79. data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +1 -1
  80. data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +4 -4
  81. data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +1 -1
  82. data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +2 -3
  83. data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +43 -0
  84. data/app/controllers/spree/api/v3/admin/customers_controller.rb +190 -11
  85. data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +24 -20
  86. data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +60 -0
  87. data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +54 -0
  88. data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +114 -0
  89. data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +243 -0
  90. data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +80 -0
  91. data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +107 -0
  92. data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +116 -0
  93. data/app/controllers/spree/api/v3/admin/digital_links_controller.rb +48 -0
  94. data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +17 -3
  95. data/app/controllers/spree/api/v3/admin/exchanges_controller.rb +31 -0
  96. data/app/controllers/spree/api/v3/admin/exports_controller.rb +2 -2
  97. data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +1 -1
  98. data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +3 -2
  99. data/app/controllers/spree/api/v3/admin/imports_controller.rb +71 -8
  100. data/app/controllers/spree/api/v3/admin/integrations_controller.rb +67 -0
  101. data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +5 -5
  102. data/app/controllers/spree/api/v3/admin/invitations_controller.rb +5 -1
  103. data/app/controllers/spree/api/v3/admin/locales_controller.rb +3 -1
  104. data/app/controllers/spree/api/v3/admin/markets_controller.rb +9 -5
  105. data/app/controllers/spree/api/v3/admin/me_controller.rb +4 -30
  106. data/app/controllers/spree/api/v3/admin/media_controller.rb +88 -38
  107. data/app/controllers/spree/api/v3/admin/media_library_controller.rb +156 -0
  108. data/app/controllers/spree/api/v3/admin/option_types_controller.rb +1 -0
  109. data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +25 -0
  110. data/app/controllers/spree/api/v3/admin/order_groups_controller.rb +43 -0
  111. data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +1 -1
  112. data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +56 -0
  113. data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +66 -0
  114. data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +86 -0
  115. data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +99 -0
  116. data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +62 -0
  117. data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +83 -0
  118. data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +45 -67
  119. data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +40 -22
  120. data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +75 -0
  121. data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +36 -18
  122. data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +39 -18
  123. data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +70 -0
  124. data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +2 -2
  125. data/app/controllers/spree/api/v3/admin/orders/tax_identifiers_controller.rb +41 -0
  126. data/app/controllers/spree/api/v3/admin/orders/tax_lines_controller.rb +32 -0
  127. data/app/controllers/spree/api/v3/admin/orders_controller.rb +157 -32
  128. data/app/controllers/spree/api/v3/admin/package_types_controller.rb +39 -0
  129. data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +1 -1
  130. data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +15 -4
  131. data/app/controllers/spree/api/v3/admin/payout_providers_controller.rb +27 -0
  132. data/app/controllers/spree/api/v3/admin/permissions_controller.rb +30 -0
  133. data/app/controllers/spree/api/v3/admin/policies_controller.rb +42 -0
  134. data/app/controllers/spree/api/v3/admin/price_lists/products_controller.rb +93 -0
  135. data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +43 -29
  136. data/app/controllers/spree/api/v3/admin/prices_controller.rb +41 -4
  137. data/app/controllers/spree/api/v3/admin/product_types_controller.rb +93 -0
  138. data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +148 -0
  139. data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +24 -3
  140. data/app/controllers/spree/api/v3/admin/products_controller.rb +149 -33
  141. data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +6 -2
  142. data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +1 -1
  143. data/app/controllers/spree/api/v3/admin/promotions_controller.rb +1 -5
  144. data/app/controllers/spree/api/v3/admin/purchase_orders/stock_receipts_controller.rb +32 -0
  145. data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +161 -0
  146. data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +25 -0
  147. data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +45 -0
  148. data/app/controllers/spree/api/v3/admin/reporting_controller.rb +95 -0
  149. data/app/controllers/spree/api/v3/admin/resource_controller.rb +27 -10
  150. data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +25 -0
  151. data/app/controllers/spree/api/v3/admin/returns_controller.rb +31 -0
  152. data/app/controllers/spree/api/v3/admin/roles_controller.rb +50 -6
  153. data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +83 -0
  154. data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +139 -0
  155. data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +115 -0
  156. data/app/controllers/spree/api/v3/admin/seller_transfers_controller.rb +36 -0
  157. data/app/controllers/spree/api/v3/admin/sellers/balances_controller.rb +44 -0
  158. data/app/controllers/spree/api/v3/admin/sellers/invitations_controller.rb +77 -0
  159. data/app/controllers/spree/api/v3/admin/sellers/payouts_controller.rb +107 -0
  160. data/app/controllers/spree/api/v3/admin/sellers/team_controller.rb +64 -0
  161. data/app/controllers/spree/api/v3/admin/sellers_controller.rb +197 -0
  162. data/app/controllers/spree/api/v3/admin/setup_controller.rb +231 -0
  163. data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +172 -0
  164. data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +3 -2
  165. data/app/controllers/spree/api/v3/admin/stock_movements_controller.rb +37 -0
  166. data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +1 -1
  167. data/app/controllers/spree/api/v3/admin/stock_transfers/stock_receipts_controller.rb +31 -0
  168. data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +134 -38
  169. data/app/controllers/spree/api/v3/admin/store_controller.rb +65 -0
  170. data/app/controllers/spree/api/v3/admin/store_credits/events_controller.rb +47 -0
  171. data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +87 -0
  172. data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +30 -0
  173. data/app/controllers/spree/api/v3/admin/tags_controller.rb +2 -2
  174. data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +4 -0
  175. data/app/controllers/spree/api/v3/admin/tax_providers_controller.rb +25 -0
  176. data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +33 -0
  177. data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +33 -0
  178. data/app/controllers/spree/api/v3/admin/translatable_resources_controller.rb +37 -9
  179. data/app/controllers/spree/api/v3/admin/translations_controller.rb +10 -5
  180. data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +150 -0
  181. data/app/controllers/spree/api/v3/admin/variants_controller.rb +11 -4
  182. data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +1 -1
  183. data/app/controllers/spree/api/v3/base_controller.rb +59 -16
  184. data/app/controllers/spree/api/v3/resource_controller.rb +154 -38
  185. data/app/controllers/spree/api/v3/seller/auth_controller.rb +169 -0
  186. data/app/controllers/spree/api/v3/seller/balances_controller.rb +35 -0
  187. data/app/controllers/spree/api/v3/seller/base_controller.rb +25 -0
  188. data/app/controllers/spree/api/v3/seller/claim_reasons_controller.rb +20 -0
  189. data/app/controllers/spree/api/v3/seller/countries_controller.rb +38 -0
  190. data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +265 -0
  191. data/app/controllers/spree/api/v3/seller/delivery_profiles_controller.rb +65 -0
  192. data/app/controllers/spree/api/v3/seller/delivery_zones_controller.rb +41 -0
  193. data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +21 -0
  194. data/app/controllers/spree/api/v3/seller/exports_controller.rb +195 -0
  195. data/app/controllers/spree/api/v3/seller/import_rows_controller.rb +49 -0
  196. data/app/controllers/spree/api/v3/seller/imports_controller.rb +317 -0
  197. data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +152 -0
  198. data/app/controllers/spree/api/v3/seller/invitations_controller.rb +71 -0
  199. data/app/controllers/spree/api/v3/seller/me_controller.rb +72 -0
  200. data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +111 -0
  201. data/app/controllers/spree/api/v3/seller/order_cancellation_reasons_controller.rb +25 -0
  202. data/app/controllers/spree/api/v3/seller/orders/base_controller.rb +44 -0
  203. data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +45 -0
  204. data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +38 -0
  205. data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +50 -0
  206. data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +79 -0
  207. data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +55 -0
  208. data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +82 -0
  209. data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +44 -0
  210. data/app/controllers/spree/api/v3/seller/orders_controller.rb +199 -0
  211. data/app/controllers/spree/api/v3/seller/package_types_controller.rb +100 -0
  212. data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +155 -0
  213. data/app/controllers/spree/api/v3/seller/payouts_controller.rb +47 -0
  214. data/app/controllers/spree/api/v3/seller/policies_controller.rb +57 -0
  215. data/app/controllers/spree/api/v3/seller/product_types_controller.rb +35 -0
  216. data/app/controllers/spree/api/v3/seller/products_controller.rb +394 -0
  217. data/app/controllers/spree/api/v3/seller/profile_controller.rb +137 -0
  218. data/app/controllers/spree/api/v3/seller/reasons_controller.rb +45 -0
  219. data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +95 -0
  220. data/app/controllers/spree/api/v3/seller/resource_controller.rb +75 -0
  221. data/app/controllers/spree/api/v3/seller/return_reasons_controller.rb +20 -0
  222. data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +56 -0
  223. data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +48 -0
  224. data/app/controllers/spree/api/v3/seller/team_controller.rb +103 -0
  225. data/app/controllers/spree/api/v3/seller/tracking_carriers_controller.rb +35 -0
  226. data/app/controllers/spree/api/v3/seller/transfers_controller.rb +43 -0
  227. data/app/controllers/spree/api/v3/store/account/companies_controller.rb +42 -0
  228. data/app/controllers/spree/api/v3/store/auth_controller.rb +21 -34
  229. data/app/controllers/spree/api/v3/store/base_controller.rb +4 -0
  230. data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +24 -2
  231. data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +41 -15
  232. data/app/controllers/spree/api/v3/store/carts/items_controller.rb +53 -20
  233. data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +36 -20
  234. data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +111 -0
  235. data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +2 -2
  236. data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +96 -0
  237. data/app/controllers/spree/api/v3/store/carts_controller.rb +57 -12
  238. data/app/controllers/spree/api/v3/store/categories_controller.rb +6 -3
  239. data/app/controllers/spree/api/v3/store/collections/products_controller.rb +59 -0
  240. data/app/controllers/spree/api/v3/store/collections_controller.rb +36 -0
  241. data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +81 -0
  242. data/app/controllers/spree/api/v3/store/companies/base_controller.rb +24 -0
  243. data/app/controllers/spree/api/v3/store/companies/invitations_controller.rb +50 -0
  244. data/app/controllers/spree/api/v3/store/companies/members_controller.rb +66 -0
  245. data/app/controllers/spree/api/v3/store/companies/orders_controller.rb +28 -0
  246. data/app/controllers/spree/api/v3/store/companies_controller.rb +47 -0
  247. data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +90 -0
  248. data/app/controllers/spree/api/v3/store/countries_controller.rb +8 -6
  249. data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +3 -1
  250. data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +78 -0
  251. data/app/controllers/spree/api/v3/store/customer/digital_links_controller.rb +52 -0
  252. data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +6 -0
  253. data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +7 -3
  254. data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +3 -3
  255. data/app/controllers/spree/api/v3/store/customer/store_credits_controller.rb +0 -3
  256. data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +91 -0
  257. data/app/controllers/spree/api/v3/store/customers_controller.rb +26 -31
  258. data/app/controllers/spree/api/v3/store/data_feeds_controller.rb +11 -0
  259. data/app/controllers/spree/api/v3/store/data_request_downloads_controller.rb +58 -0
  260. data/app/controllers/spree/api/v3/store/delivery_methods_controller.rb +108 -0
  261. data/app/controllers/spree/api/v3/store/digital_links_controller.rb +105 -0
  262. data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +5 -9
  263. data/app/controllers/spree/api/v3/store/markets_controller.rb +4 -4
  264. data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +8 -9
  265. data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +94 -0
  266. data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +116 -0
  267. data/app/controllers/spree/api/v3/store/orders/tax_identifiers_controller.rb +46 -0
  268. data/app/controllers/spree/api/v3/store/orders_controller.rb +12 -15
  269. data/app/controllers/spree/api/v3/store/products/filters_controller.rb +10 -3
  270. data/app/controllers/spree/api/v3/store/products_controller.rb +25 -6
  271. data/app/controllers/spree/api/v3/store/resource_controller.rb +2 -0
  272. data/app/controllers/spree/api/v3/store/sellers_controller.rb +43 -0
  273. data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +9 -6
  274. data/app/controllers/spree/api/v3/store/wishlists_controller.rb +3 -3
  275. data/app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb +88 -0
  276. data/app/controllers/spree/api/v3/webhooks/payments_controller.rb +5 -2
  277. data/app/controllers/spree/api/v3/webhooks/payouts_controller.rb +61 -0
  278. data/app/models/spree/api/data_request_urls.rb +25 -0
  279. data/app/models/spree/api/digital_link_urls.rb +26 -0
  280. data/app/serializers/spree/api/v3/address_serializer.rb +17 -5
  281. data/app/serializers/spree/api/v3/admin/address_serializer.rb +27 -4
  282. data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +13 -10
  283. data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +1 -1
  284. data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +15 -0
  285. data/app/serializers/spree/api/v3/admin/cart_serializer.rb +34 -0
  286. data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +32 -0
  287. data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +23 -0
  288. data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +48 -0
  289. data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +23 -0
  290. data/app/serializers/spree/api/v3/admin/catalog_product_serializer.rb +57 -0
  291. data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +38 -0
  292. data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +37 -0
  293. data/app/serializers/spree/api/v3/admin/catalog_serializer.rb +46 -0
  294. data/app/serializers/spree/api/v3/admin/category_serializer.rb +3 -2
  295. data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -1
  296. data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +16 -0
  297. data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +21 -0
  298. data/app/serializers/spree/api/v3/admin/claim_serializer.rb +29 -0
  299. data/app/serializers/spree/api/v3/admin/collection_rule_serializer.rb +22 -0
  300. data/app/serializers/spree/api/v3/admin/collection_serializer.rb +29 -0
  301. data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +67 -0
  302. data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +69 -0
  303. data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +61 -0
  304. data/app/serializers/spree/api/v3/admin/company_invitation_serializer.rb +15 -0
  305. data/app/serializers/spree/api/v3/admin/company_membership_serializer.rb +11 -0
  306. data/app/serializers/spree/api/v3/admin/company_serializer.rb +37 -0
  307. data/app/serializers/spree/api/v3/admin/concerns/external_references_attribute.rb +33 -0
  308. data/app/serializers/spree/api/v3/admin/consent_record_serializer.rb +28 -0
  309. data/app/serializers/spree/api/v3/admin/country_serializer.rb +2 -2
  310. data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -1
  311. data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +2 -2
  312. data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +2 -2
  313. data/app/serializers/spree/api/v3/admin/customer_serializer.rb +23 -22
  314. data/app/serializers/spree/api/v3/admin/dashboard_counter_serializer.rb +24 -0
  315. data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +36 -0
  316. data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +32 -0
  317. data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +66 -1
  318. data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +15 -0
  319. data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +34 -0
  320. data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +65 -0
  321. data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +10 -1
  322. data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +20 -0
  323. data/app/serializers/spree/api/v3/admin/delivery_zone_member_serializer.rb +11 -0
  324. data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +29 -0
  325. data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +59 -0
  326. data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -4
  327. data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +16 -0
  328. data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +35 -0
  329. data/app/serializers/spree/api/v3/admin/export_serializer.rb +20 -1
  330. data/app/serializers/spree/api/v3/admin/fee_serializer.rb +14 -0
  331. data/app/serializers/spree/api/v3/admin/freight_summary_line_serializer.rb +46 -0
  332. data/app/serializers/spree/api/v3/admin/freight_summary_serializer.rb +16 -0
  333. data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +39 -0
  334. data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +31 -9
  335. data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -3
  336. data/app/serializers/spree/api/v3/admin/import_serializer.rb +15 -2
  337. data/app/serializers/spree/api/v3/admin/integration_serializer.rb +32 -0
  338. data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +4 -4
  339. data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +19 -5
  340. data/app/serializers/spree/api/v3/admin/market_serializer.rb +5 -1
  341. data/app/serializers/spree/api/v3/admin/media_serializer.rb +50 -2
  342. data/app/serializers/spree/api/v3/admin/membership_product_serializer.rb +29 -0
  343. data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +29 -0
  344. data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +50 -0
  345. data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +2 -6
  346. data/app/serializers/spree/api/v3/admin/order_serializer.rb +131 -19
  347. data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +53 -0
  348. data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +8 -2
  349. data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -0
  350. data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +41 -0
  351. data/app/serializers/spree/api/v3/admin/permission_serializer.rb +39 -0
  352. data/app/serializers/spree/api/v3/admin/policy_serializer.rb +11 -0
  353. data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +22 -0
  354. data/app/serializers/spree/api/v3/admin/price_list_product_serializer.rb +32 -0
  355. data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +20 -8
  356. data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +2 -12
  357. data/app/serializers/spree/api/v3/admin/price_serializer.rb +3 -0
  358. data/app/serializers/spree/api/v3/admin/product_serializer.rb +54 -8
  359. data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +39 -0
  360. data/app/serializers/spree/api/v3/admin/product_type_custom_field_definition_serializer.rb +44 -0
  361. data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +34 -0
  362. data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +6 -12
  363. data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +17 -15
  364. data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +80 -0
  365. data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +94 -0
  366. data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +27 -0
  367. data/app/serializers/spree/api/v3/admin/refund_serializer.rb +0 -5
  368. data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +72 -0
  369. data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +16 -0
  370. data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +21 -0
  371. data/app/serializers/spree/api/v3/admin/return_serializer.rb +59 -0
  372. data/app/serializers/spree/api/v3/admin/role_serializer.rb +24 -6
  373. data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +33 -0
  374. data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +37 -0
  375. data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +46 -0
  376. data/app/serializers/spree/api/v3/admin/seller_requirement_serializer.rb +68 -0
  377. data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +48 -0
  378. data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +57 -0
  379. data/app/serializers/spree/api/v3/admin/seller_serializer.rb +92 -0
  380. data/app/serializers/spree/api/v3/admin/seller_team_member_serializer.rb +29 -0
  381. data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +53 -0
  382. data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +82 -0
  383. data/app/serializers/spree/api/v3/admin/state_serializer.rb +1 -1
  384. data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +65 -0
  385. data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +20 -4
  386. data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +116 -0
  387. data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +57 -0
  388. data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +49 -0
  389. data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +5 -5
  390. data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +57 -0
  391. data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +36 -16
  392. data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +32 -0
  393. data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +42 -7
  394. data/app/serializers/spree/api/v3/admin/store_serializer.rb +63 -1
  395. data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +39 -0
  396. data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +67 -0
  397. data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +43 -0
  398. data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +21 -0
  399. data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +49 -0
  400. data/app/serializers/spree/api/v3/admin/variant_serializer.rb +49 -8
  401. data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +23 -0
  402. data/app/serializers/spree/api/v3/base_serializer.rb +39 -2
  403. data/app/serializers/spree/api/v3/cart_serializer.rb +90 -12
  404. data/app/serializers/spree/api/v3/category_serializer.rb +3 -3
  405. data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +50 -0
  406. data/app/serializers/spree/api/v3/claim_reason_serializer.rb +20 -0
  407. data/app/serializers/spree/api/v3/claim_serializer.rb +62 -0
  408. data/app/serializers/spree/api/v3/collection_serializer.rb +41 -0
  409. data/app/serializers/spree/api/v3/company_invitation_serializer.rb +28 -0
  410. data/app/serializers/spree/api/v3/company_membership_serializer.rb +28 -0
  411. data/app/serializers/spree/api/v3/company_serializer.rb +33 -0
  412. data/app/serializers/spree/api/v3/custom_field_serializer.rb +2 -2
  413. data/app/serializers/spree/api/v3/customer_serializer.rb +9 -1
  414. data/app/serializers/spree/api/v3/data_request_event_serializer.rb +30 -0
  415. data/app/serializers/spree/api/v3/data_request_serializer.rb +40 -0
  416. data/app/serializers/spree/api/v3/delivery_method_serializer.rb +12 -2
  417. data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +34 -17
  418. data/app/serializers/spree/api/v3/delivery_serializer.rb +29 -0
  419. data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +29 -0
  420. data/app/serializers/spree/api/v3/delivery_zone_serializer.rb +13 -0
  421. data/app/serializers/spree/api/v3/digital_asset_serializer.rb +23 -0
  422. data/app/serializers/spree/api/v3/digital_link_serializer.rb +6 -2
  423. data/app/serializers/spree/api/v3/discount_serializer.rb +21 -7
  424. data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +53 -0
  425. data/app/serializers/spree/api/v3/exchange_serializer.rb +61 -0
  426. data/app/serializers/spree/api/v3/fee_serializer.rb +27 -0
  427. data/app/serializers/spree/api/v3/freight_summary_serializer.rb +38 -0
  428. data/app/serializers/spree/api/v3/fulfillment_serializer.rb +28 -15
  429. data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
  430. data/app/serializers/spree/api/v3/import_row_serializer.rb +1 -1
  431. data/app/serializers/spree/api/v3/import_serializer.rb +18 -4
  432. data/app/serializers/spree/api/v3/invitation_serializer.rb +1 -1
  433. data/app/serializers/spree/api/v3/line_item_serializer.rb +18 -1
  434. data/app/serializers/spree/api/v3/market_serializer.rb +2 -2
  435. data/app/serializers/spree/api/v3/{asset_serializer.rb → media_event_serializer.rb} +4 -4
  436. data/app/serializers/spree/api/v3/media_serializer.rb +48 -7
  437. data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +1 -1
  438. data/app/serializers/spree/api/v3/option_type_serializer.rb +1 -1
  439. data/app/serializers/spree/api/v3/order_group_serializer.rb +60 -0
  440. data/app/serializers/spree/api/v3/order_serializer.rb +58 -6
  441. data/app/serializers/spree/api/v3/payment_method_serializer.rb +1 -1
  442. data/app/serializers/spree/api/v3/payment_serializer.rb +2 -6
  443. data/app/serializers/spree/api/v3/payment_session_serializer.rb +10 -3
  444. data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +1 -1
  445. data/app/serializers/spree/api/v3/policy_serializer.rb +7 -2
  446. data/app/serializers/spree/api/v3/product_filter_option_serializer.rb +1 -1
  447. data/app/serializers/spree/api/v3/product_serializer.rb +42 -10
  448. data/app/serializers/spree/api/v3/product_type_serializer.rb +17 -0
  449. data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +11 -0
  450. data/app/serializers/spree/api/v3/refund_serializer.rb +9 -3
  451. data/app/serializers/spree/api/v3/return_line_item_serializer.rb +42 -0
  452. data/app/serializers/spree/api/v3/return_reason_serializer.rb +20 -0
  453. data/app/serializers/spree/api/v3/return_serializer.rb +62 -0
  454. data/app/serializers/spree/api/v3/seller/balance_serializer.rb +35 -0
  455. data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +21 -0
  456. data/app/serializers/spree/api/v3/seller/claim_serializer.rb +25 -0
  457. data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +32 -0
  458. data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +59 -0
  459. data/app/serializers/spree/api/v3/seller/delivery_profile_serializer.rb +26 -0
  460. data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +35 -0
  461. data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +17 -0
  462. data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +26 -0
  463. data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +29 -0
  464. data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +30 -0
  465. data/app/serializers/spree/api/v3/seller/export_serializer.rb +44 -0
  466. data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +43 -0
  467. data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +76 -0
  468. data/app/serializers/spree/api/v3/seller/import_mapping_serializer.rb +20 -0
  469. data/app/serializers/spree/api/v3/seller/import_row_serializer.rb +17 -0
  470. data/app/serializers/spree/api/v3/seller/import_serializer.rb +77 -0
  471. data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +29 -0
  472. data/app/serializers/spree/api/v3/seller/media_serializer.rb +26 -0
  473. data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +44 -0
  474. data/app/serializers/spree/api/v3/seller/order_serializer.rb +119 -0
  475. data/app/serializers/spree/api/v3/seller/package_type_serializer.rb +52 -0
  476. data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +34 -0
  477. data/app/serializers/spree/api/v3/seller/payout_serializer.rb +36 -0
  478. data/app/serializers/spree/api/v3/seller/policy_serializer.rb +11 -0
  479. data/app/serializers/spree/api/v3/seller/product_serializer.rb +60 -0
  480. data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +30 -0
  481. data/app/serializers/spree/api/v3/seller/product_type_serializer.rb +29 -0
  482. data/app/serializers/spree/api/v3/seller/profile_serializer.rb +77 -0
  483. data/app/serializers/spree/api/v3/seller/reason_serializer.rb +24 -0
  484. data/app/serializers/spree/api/v3/seller/requirement_custom_field_serializer.rb +36 -0
  485. data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +62 -0
  486. data/app/serializers/spree/api/v3/seller/requirement_submission_serializer.rb +33 -0
  487. data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +24 -0
  488. data/app/serializers/spree/api/v3/seller/return_serializer.rb +51 -0
  489. data/app/serializers/spree/api/v3/seller/shipping_label_serializer.rb +23 -0
  490. data/app/serializers/spree/api/v3/seller/stock_level_serializer.rb +27 -0
  491. data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +17 -0
  492. data/app/serializers/spree/api/v3/seller/tax_identifier_serializer.rb +15 -0
  493. data/app/serializers/spree/api/v3/seller/team_member_serializer.rb +22 -0
  494. data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +49 -0
  495. data/app/serializers/spree/api/v3/seller/variant_serializer.rb +71 -0
  496. data/app/serializers/spree/api/v3/seller_serializer.rb +50 -0
  497. data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +11 -0
  498. data/app/serializers/spree/api/v3/{stock_item_serializer.rb → stock_level_serializer.rb} +5 -5
  499. data/app/serializers/spree/api/v3/stock_location_serializer.rb +11 -7
  500. data/app/serializers/spree/api/v3/stock_movement_serializer.rb +8 -15
  501. data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +11 -0
  502. data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +6 -6
  503. data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +29 -0
  504. data/app/serializers/spree/api/v3/supplier_event_serializer.rb +11 -0
  505. data/app/serializers/spree/api/v3/tax_identifier_serializer.rb +15 -0
  506. data/app/serializers/spree/api/v3/tax_line_serializer.rb +37 -0
  507. data/app/serializers/spree/api/v3/variant_serializer.rb +52 -2
  508. data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +6 -6
  509. data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
  510. data/app/services/spree/api/v3/filters_aggregator.rb +14 -12
  511. data/app/services/spree/webhooks/deliver_webhook.rb +62 -26
  512. data/app/subscribers/spree/webhook_event_subscriber.rb +9 -5
  513. data/config/brakeman.ignore +1 -1
  514. data/config/initializers/typelizer.rb +51 -4
  515. data/config/locales/en.yml +5 -0
  516. data/config/routes.rb +730 -22
  517. data/lib/spree/api/configuration.rb +2 -7
  518. data/lib/spree/api/dependencies.rb +173 -227
  519. data/lib/spree/api/openapi/schema_helper.rb +179 -13
  520. data/lib/spree/api/testing_support/v3/base.rb +45 -15
  521. data/lib/spree/api.rb +10 -4
  522. data/lib/typelizer/open_enums.rb +35 -0
  523. metadata +341 -27
  524. data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +0 -25
  525. data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +0 -42
  526. data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +0 -21
  527. data/app/controllers/spree/api/v3/store/digitals_controller.rb +0 -38
  528. data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +0 -24
  529. data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +0 -143
  530. data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +0 -15
  531. data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +0 -19
  532. data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +0 -34
  533. data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +0 -19
  534. data/app/serializers/spree/api/v3/customer_return_serializer.rb +0 -17
  535. data/app/serializers/spree/api/v3/digital_serializer.rb +0 -17
  536. data/app/serializers/spree/api/v3/reimbursement_serializer.rb +0 -27
  537. data/app/serializers/spree/api/v3/report_serializer.rb +0 -34
  538. data/app/serializers/spree/api/v3/return_authorization_serializer.rb +0 -31
  539. data/app/serializers/spree/api/v3/return_item_serializer.rb +0 -53
  540. data/app/serializers/spree/api/v3/shipping_category_serializer.rb +0 -11
@@ -0,0 +1,152 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # Public invitation acceptance for the seller panel — mounted under
6
+ # `/api/v3/seller/auth/...` so the issued refresh-token cookie's path
7
+ # matches `/auth/refresh`.
8
+ #
9
+ # Parallel to the admin controller rather than a subclass of it, per
10
+ # Decision 10: what differs is the audience it issues and the
11
+ # invitations it will touch, and both are the point.
12
+ class InvitationAcceptancesController < Spree::Api::V3::BaseController
13
+ include Spree::Api::V3::Seller::AuthCookies
14
+ include Spree::Api::V3::JwtAuthentication
15
+
16
+ # No `skip_scope_check!`: this extends the plain v3 base, which has
17
+ # no authentication or scope gate to lift. The emailed token is the
18
+ # only credential, exactly as on the admin twin.
19
+ rate_limit to: Spree::Api::Config[:rate_limit_login],
20
+ within: Spree::Api::Config[:rate_limit_window].seconds,
21
+ store: Rails.cache,
22
+ only: [:lookup, :accept],
23
+ with: -> { render_rate_limited(limit: Spree::Api::Config[:rate_limit_login]) }
24
+
25
+ # GET /api/v3/seller/auth/invitations/:id/lookup?token=:token
26
+ def lookup
27
+ return unless load_invitation
28
+
29
+ render json: Spree.api.seller_invitation_serializer.new(
30
+ @invitation, params: { store: @invitation.store }
31
+ ).serializable_hash
32
+ end
33
+
34
+ # POST /api/v3/seller/auth/invitations/:id/accept?token=:token
35
+ # Body: { password?, password_confirmation?, first_name?, last_name? }
36
+ def accept
37
+ return unless load_invitation
38
+
39
+ user = resolve_or_create_invitee(@invitation)
40
+ return if performed?
41
+
42
+ @invitation.invitee = user
43
+ result = Spree.invitation_accept_workflow.call(invitation: @invitation)
44
+
45
+ return render_service_error(result.error) unless result.success?
46
+
47
+ set_refresh_cookie(
48
+ Spree::RefreshToken.create_for(
49
+ user,
50
+ audience: Spree::Api::V3::JwtAuthentication::JWT_AUDIENCE_SELLER,
51
+ request_env: request_env_for_token
52
+ )
53
+ )
54
+
55
+ render json: auth_response(user)
56
+ end
57
+
58
+ private
59
+
60
+ # Only invitations onto a seller are acceptable here. A staff
61
+ # invitation carries no seller membership, so accepting one through
62
+ # this endpoint would mint a seller token for someone who runs no
63
+ # seller — and it is indistinguishable from "not found" on purpose,
64
+ # since the caller is unauthenticated either way.
65
+ #
66
+ # Token mismatch is treated identically to "not found" to avoid
67
+ # leaking whether an ID exists.
68
+ def load_invitation
69
+ decoded_id = Spree::Invitation.decode_prefixed_id(params[:id])
70
+ @invitation = Spree::Invitation.pending.not_expired.
71
+ where(resource_type: Spree::Seller.to_s).
72
+ find_by(id: decoded_id, token: params[:token])
73
+
74
+ unless @invitation
75
+ render_error(
76
+ code: ErrorHandler::ERROR_CODES[:record_not_found],
77
+ message: Spree.t(:invitation_not_acceptable),
78
+ status: :not_found
79
+ )
80
+ return false
81
+ end
82
+
83
+ true
84
+ end
85
+
86
+ # Email match between the invitation and any existing account is
87
+ # implicit: we look the user up by `invitation.email`, never by a
88
+ # client-supplied email. The token is the credential.
89
+ def resolve_or_create_invitee(invitation)
90
+ existing = Spree.admin_user_class.find_by(email: invitation.email)
91
+ return authenticate_existing(existing) if existing
92
+
93
+ create_new_invitee(invitation)
94
+ end
95
+
96
+ def authenticate_existing(user)
97
+ return user if user.valid_password?(params[:password].to_s)
98
+
99
+ render_error(
100
+ code: ErrorHandler::ERROR_CODES[:authentication_failed],
101
+ message: Spree.t(:invalid_password),
102
+ status: :unauthorized
103
+ )
104
+ nil
105
+ end
106
+
107
+ def create_new_invitee(invitation)
108
+ if params[:password].blank?
109
+ render_error(
110
+ code: ErrorHandler::ERROR_CODES[:parameter_missing],
111
+ message: Spree.t(:password_required_to_create_account),
112
+ status: :unprocessable_content
113
+ )
114
+ return nil
115
+ end
116
+
117
+ Spree.admin_user_class.create!(signup_params(invitation))
118
+ end
119
+
120
+ def signup_params(invitation)
121
+ params.permit(:password, :password_confirmation, :first_name, :last_name).
122
+ merge(email: invitation.email)
123
+ end
124
+
125
+ # Same shape as the login response, so the panel can sign the new
126
+ # member straight in rather than bouncing them to a login form.
127
+ def auth_response(user)
128
+ {
129
+ token: generate_jwt(user, audience: Spree::Api::V3::JwtAuthentication::JWT_AUDIENCE_SELLER),
130
+ user: Spree.api.seller_team_member_serializer.new(
131
+ user, params: { store: @invitation.store }
132
+ ).to_h,
133
+ sellers: serialized_sellers(user)
134
+ }
135
+ end
136
+
137
+ def serialized_sellers(user)
138
+ user.sellers.map { |seller| { id: seller.prefixed_id, name: seller.name, status: seller.status } }
139
+ end
140
+
141
+ def request_env_for_token
142
+ { ip_address: request.remote_ip, user_agent: request.user_agent&.truncate(255) }
143
+ end
144
+
145
+ def jwt_expiration
146
+ Spree::Api::Config[:admin_jwt_expiration]
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,71 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # Invitations this seller has sent that nobody has accepted yet.
6
+ #
7
+ # Separate from `TeamController` because they are different things: a
8
+ # member is a person who can sign in, an invitation is an offer that
9
+ # may lapse. Creating one still belongs to the team endpoint — hiring
10
+ # is what the seller is doing — while chasing or withdrawing one is
11
+ # bookkeeping on the offer itself.
12
+ #
13
+ # Rooted at `current_seller.invitations` throughout, so a seller can
14
+ # neither see nor touch an invitation sent by anyone else.
15
+ class InvitationsController < Seller::BaseController
16
+ scoped_resource :seller_profile
17
+
18
+ before_action :set_invitation, only: [:destroy, :resend]
19
+
20
+ # Pending only: an accepted invitation is a team member, and the
21
+ # panel already lists those.
22
+ def index
23
+ invitations = current_seller.invitations.pending.order(created_at: :desc)
24
+
25
+ render json: { data: invitations.map { |invitation| serialize(invitation) } }
26
+ end
27
+
28
+ # Withdraws an offer that has not been accepted.
29
+ def destroy
30
+ @invitation.destroy
31
+ head :no_content
32
+ end
33
+
34
+ # Sends the invitation email again, for a colleague who never got
35
+ # the first one. The model refuses once the invitation has expired
36
+ # or been accepted, and says so rather than silently doing nothing.
37
+ def resend
38
+ if @invitation.expired?
39
+ return render_error(
40
+ code: ErrorHandler::ERROR_CODES[:processing_error],
41
+ message: Spree.t(:invitation_expired),
42
+ status: :unprocessable_content
43
+ )
44
+ end
45
+
46
+ @invitation.resend!
47
+ render json: serialize(@invitation)
48
+ end
49
+
50
+ protected
51
+
52
+ def read_actions
53
+ %w[index]
54
+ end
55
+
56
+ private
57
+
58
+ def set_invitation
59
+ @invitation = current_seller.invitations.pending.find_by_prefix_id!(params[:id])
60
+ end
61
+
62
+ def serialize(invitation)
63
+ Spree.api.seller_invitation_serializer.new(
64
+ invitation, params: { store: current_store }
65
+ ).to_h
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,72 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # The signed-in seller: who they are, which sellers they act for, and
6
+ # what they may do on the selected one.
7
+ #
8
+ # Structurally exempt from seller scoping — this is what tells the
9
+ # panel which X-Spree-Seller-Id to send, so it has to answer before one
10
+ # is chosen. Sending the header still narrows `permission_keys` to that
11
+ # seller.
12
+ class MeController < Seller::BaseController
13
+ include Spree::Api::V3::PermissionSerialization
14
+
15
+ skip_scope_check!
16
+ skip_before_action :set_current_seller_context
17
+ before_action :require_current_user!
18
+
19
+ def show
20
+ render json: me_response
21
+ end
22
+
23
+ private
24
+
25
+ def me_response
26
+ {
27
+ user: Spree.api.seller_team_member_serializer.new(current_user, params: serializer_params).to_h,
28
+ sellers: serialized_sellers,
29
+ # Both shapes, exactly as the admin `/me`: the panel's `<Can>`
30
+ # reads CanCanCan rules, the key gate reads keys. Sending only
31
+ # keys left `<Can>` answering false for everything on the seller
32
+ # panel — silently, since nothing gated on it yet.
33
+ permissions: serialize_permissions(seller_ability),
34
+ permission_keys: serialize_permission_keys(seller_ability)
35
+ }
36
+ end
37
+
38
+ def serialized_sellers
39
+ current_user.sellers.map do |seller|
40
+ { id: seller.prefixed_id, name: seller.name, slug: seller.slug, status: seller.status }
41
+ end
42
+ end
43
+
44
+ # Empty until a seller is named: capability is per seller, so there is
45
+ # no meaningful answer spanning all of them. A bare ability (no
46
+ # resource) serializes to nothing rather than raising, so the panel
47
+ # can call `/me` before choosing a seller.
48
+ def seller_ability
49
+ return Spree::Ability.new(nil) if current_seller.nil?
50
+
51
+ current_ability
52
+ end
53
+
54
+ def serializer_params
55
+ { store: current_store || current_user.sellers.first&.store }
56
+ end
57
+
58
+ def require_current_user!
59
+ return true if current_user
60
+
61
+ render_error(
62
+ code: ErrorHandler::ERROR_CODES[:record_not_found],
63
+ message: Spree.t(:me_no_current_user),
64
+ status: :not_found
65
+ )
66
+ false
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,111 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # What the marketplace asks of this seller, and how far along they are.
6
+ #
7
+ # Singular by nature: there is exactly one seller in play and it is
8
+ # `current_seller`, never an id from the request. The checklist is
9
+ # computed on read through the one evaluator the operator's view and
10
+ # the approval gate also use, so the panel and the operator can never
11
+ # be looking at different answers.
12
+ class OnboardingController < Seller::BaseController
13
+ scoped_resource :seller_profile
14
+
15
+ # GET /api/v3/seller/onboarding
16
+ def show
17
+ render json: onboarding_payload
18
+ end
19
+
20
+ # POST /api/v3/seller/onboarding/submit_for_review
21
+ #
22
+ # The seller says they are ready. Refused with the blocking
23
+ # requirements named — a bare "not ready" leaves them guessing which
24
+ # of eight things it meant.
25
+ def submit_for_review
26
+ result = Spree.seller_submit_for_review_workflow.call(
27
+ seller: current_seller,
28
+ submitted_by: try_spree_current_user
29
+ )
30
+
31
+ return render_service_error(result.error) unless result.success?
32
+
33
+ render json: onboarding_payload
34
+ end
35
+
36
+ # POST /api/v3/seller/onboarding/payout_account
37
+ #
38
+ # A fresh link to wherever the provider collects what it needs before
39
+ # it will pay this seller. Minted per request rather than rendered
40
+ # with the checklist, because these links are short-lived and
41
+ # single-use — one made while drawing a page is often dead by the
42
+ # time the seller clicks it.
43
+ #
44
+ # The panel says where to come back to. Core does not know the
45
+ # panel's routes, and a marketplace may host it anywhere.
46
+ def payout_account
47
+ provider = current_store.payout_provider_instance
48
+ url = provider.onboarding_url(
49
+ current_seller,
50
+ refresh_url: panel_url(params.require(:refresh_url)),
51
+ return_url: panel_url(params.require(:return_url))
52
+ )
53
+
54
+ # A null link rather than an empty response: the panel has to tell
55
+ # "this provider hosts nothing" from "the request failed", and a
56
+ # 204 makes the client infer that from an absence.
57
+ render json: { url: url.presence }
58
+ rescue Spree::Core::GatewayError => e
59
+ render_service_error(e.message)
60
+ end
61
+
62
+ protected
63
+
64
+ def read_actions
65
+ %w[show]
66
+ end
67
+
68
+ private
69
+
70
+ # Where a provider may send the seller back to.
71
+ #
72
+ # Checked against the panel's own origin rather than echoed: a seller
73
+ # could otherwise name any address and turn the marketplace's genuine
74
+ # provider flow into a redirect to a page of their choosing, which is
75
+ # a convincing place to ask somebody for credentials. Anything else
76
+ # falls back to the panel's own root.
77
+ def panel_url(candidate)
78
+ panel = Spree::Sellers::PanelUrl.call(store: current_store)
79
+ return panel if candidate.blank?
80
+
81
+ uri = URI.parse(candidate.to_s)
82
+ allowed = URI.parse(panel)
83
+
84
+ same_origin = uri.scheme == allowed.scheme && uri.host == allowed.host && uri.port == allowed.port
85
+ same_origin ? candidate.to_s : panel
86
+ rescue URI::InvalidURIError
87
+ panel
88
+ end
89
+
90
+ def requirements
91
+ @requirements ||= Spree::Sellers::Requirements.new(current_seller.reload)
92
+ end
93
+
94
+ def onboarding_payload
95
+ {
96
+ status: current_seller.status,
97
+ progress: requirements.progress,
98
+ requirements: requirements.statuses.map { |status| serialize_status(status) }
99
+ }
100
+ end
101
+
102
+ def serialize_status(status)
103
+ Spree.api.seller_requirement_status_serializer.new(
104
+ status, params: { store: current_store }
105
+ ).to_h
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,25 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ # Why an order was called off.
6
+ #
7
+ # Read-only here, like the other vocabularies, but gated by `orders`
8
+ # rather than the `settings` key the operator's own CRUD sits behind —
9
+ # `settings` is never seller-grantable, and a seller cancelling their
10
+ # own order needs to name a reason from the marketplace's list.
11
+ class OrderCancellationReasonsController < ReasonsController
12
+ protected
13
+
14
+ def model_class
15
+ Spree::OrderCancellationReason
16
+ end
17
+
18
+ def reasons_association
19
+ :order_cancellation_reasons
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,44 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ module Orders
6
+ # Anchor for everything nested under one of this seller's orders.
7
+ #
8
+ # Mirrors Admin::Orders::BaseController: the parent order is fetched
9
+ # once here rather than in each controller. The difference is the
10
+ # root — `current_seller_orders`, which is the seller's own orders
11
+ # minus drafts, since neither an in-flight checkout nor the
12
+ # operator's working document is this seller's to act on.
13
+ #
14
+ # Deliberately not a subclass of the admin base: that one resolves
15
+ # through `current_store`, and inheriting its lookups is precisely
16
+ # how a seller would come to read the whole marketplace.
17
+ class BaseController < Seller::ResourceController
18
+ include Spree::Api::V3::OrderLock
19
+
20
+ before_action :authorize_order_access!
21
+
22
+ scoped_resource :orders
23
+
24
+ protected
25
+
26
+ def set_parent
27
+ @parent = current_seller_orders.find_by_prefix_id!(params[:order_id])
28
+ @order = @parent
29
+ end
30
+
31
+ # Reads need only `:show` on the order; every write needs
32
+ # `:update`, so a seller who may only view an order cannot ship,
33
+ # refund or cancel against it. Derived from +read_actions+ rather
34
+ # than a hand-kept list, so a new write action is a write by
35
+ # default instead of silently unauthorized.
36
+ def authorize_order_access!
37
+ authorize_parent!(@parent)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,45 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ module Orders
6
+ # Something went wrong with a delivery on one of this seller's
7
+ # orders, and the seller makes it right.
8
+ #
9
+ # The workflows are the operator's, shared through the concern, so a
10
+ # claim settled here credits and restocks exactly as it does when
11
+ # the marketplace handles it. What is here is what makes it the
12
+ # seller's: the order comes from `current_seller_orders`, so a claim
13
+ # on somebody else's order reads as missing rather than denied, and
14
+ # a replacement may only be promised out of this seller's catalogue.
15
+ class ClaimsController < BaseController
16
+ include Spree::Api::V3::Orders::ClaimActions
17
+
18
+ before_action :set_resource, only: [:show, :approve, :resolve, :deny, :cancel]
19
+
20
+ protected
21
+
22
+ def serializer_class
23
+ Spree.api.seller_claim_serializer
24
+ end
25
+
26
+ def collection_includes
27
+ [:reason, { claim_line_items: [:variant, :line_item, :replacement_variant] }]
28
+ end
29
+
30
+ private
31
+
32
+ # The seller's own catalogue: a replacement is stock this seller
33
+ # sends, so a variant belonging to another seller is not theirs to
34
+ # promise.
35
+ def replacement_variant_for(variant_id)
36
+ return nil if variant_id.blank?
37
+
38
+ current_seller.variants.find_by_prefix_id!(variant_id)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,38 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ module Orders
6
+ # The consignments on a parcel the seller ships themselves.
7
+ #
8
+ # CRUD is shared with the operator's branch through the concern.
9
+ # What is here is what makes it the seller's: the order comes from
10
+ # `current_seller_orders`, so a fulfillment on somebody else's order
11
+ # reads as missing rather than denied.
12
+ #
13
+ # No `mark_delivered`: that a parcel arrived is the buyer's word,
14
+ # not the sender's, so confirming receipt stays with the operator
15
+ # and the carrier feed.
16
+ class DeliveriesController < BaseController
17
+ include Spree::Api::V3::Orders::DeliveryActions
18
+
19
+ before_action :set_resource, only: [:show, :update, :destroy]
20
+
21
+ protected
22
+
23
+ def serializer_class
24
+ Spree.api.seller_delivery_serializer
25
+ end
26
+
27
+ # The labels and consignments hang off the fulfillment, not the
28
+ # order, so the parent is narrowed one step past the base's.
29
+ def set_parent
30
+ super
31
+ @parent = @order.fulfillments.find_by_prefix_id!(params[:fulfillment_id])
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,50 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ module Orders
6
+ # Swapping goods on one of this seller's orders — a different size,
7
+ # colour or product.
8
+ #
9
+ # The workflows are the operator's, shared through the concern. What
10
+ # is here is what makes it the seller's: the order comes from
11
+ # `current_seller_orders`, and the replacement variant is resolved
12
+ # through `current_seller.variants` rather than the store's, because
13
+ # a seller exchanges into their own catalogue and reaching a rival's
14
+ # variant here would put that seller's stock on this seller's order.
15
+ class ExchangesController < BaseController
16
+ include Spree::Api::V3::Orders::ExchangeActions
17
+
18
+ before_action :set_resource, only: [:show, :approve, :receive, :fulfill, :cancel]
19
+
20
+ protected
21
+
22
+ def serializer_class
23
+ Spree.api.seller_exchange_serializer
24
+ end
25
+
26
+ def collection_includes
27
+ [:reason, :stock_location,
28
+ { exchange_line_items: [:original_variant, :new_variant, :line_item] }]
29
+ end
30
+
31
+ private
32
+
33
+ # The seller's own catalogue and their own shelves — a rival's
34
+ # variant is not theirs to send, nor a marketplace warehouse
35
+ # theirs to restock.
36
+ def replacement_variant_for(variant_id)
37
+ current_seller.variants.find_by_prefix_id!(variant_id)
38
+ end
39
+
40
+ def stock_location_for_create
41
+ return nil if create_params[:stock_location_id].blank?
42
+
43
+ current_seller.stock_locations.find_by_prefix_id!(create_params[:stock_location_id])
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,79 @@
1
+ module Spree
2
+ module Api
3
+ module V3
4
+ module Seller
5
+ module Orders
6
+ # The parcels this seller owes on one of their orders.
7
+ #
8
+ # Shipping, cancelling and splitting are the operator's workflows,
9
+ # shared through the concern, so the customer email, the label
10
+ # purchase and the extension hooks all happen exactly as they do
11
+ # when the marketplace ships on the seller's behalf.
12
+ #
13
+ # What is here is what makes them the seller's: the order comes from
14
+ # `current_seller_orders`, so a fulfillment on somebody else's order
15
+ # reads as missing rather than denied, and both the goods that may
16
+ # be split and the shelves they ship from are the seller's own.
17
+ #
18
+ # No `mark_delivered` and no `create`: that goods arrived is the
19
+ # buyer's word rather than the sender's, and a parcel comes into
20
+ # being from the order, not from the seller.
21
+ class FulfillmentsController < BaseController
22
+ include Spree::Api::V3::Orders::FulfillmentActions
23
+
24
+ before_action :set_resource, only: [:show, :update, :fulfill, :cancel, :split]
25
+
26
+ protected
27
+
28
+ def serializer_class
29
+ Spree.api.seller_fulfillment_serializer
30
+ end
31
+
32
+ def collection_includes
33
+ [:deliveries, :shipping_labels, :fulfillment_items]
34
+ end
35
+
36
+ def permitted_params
37
+ params.permit(:tracking, :tracking_carrier, :stock_location_id,
38
+ :selected_delivery_rate_id)
39
+ end
40
+
41
+ private
42
+
43
+ # What may be split out is what this parcel is actually carrying,
44
+ # resolved through the order rather than the catalogue.
45
+ def variant_for_split
46
+ @order.variants.find_by_prefix_id!(params[:variant_id])
47
+ end
48
+
49
+ # The seller's own shelves only — defaulting to where this parcel
50
+ # already sits.
51
+ def stock_location_for_split
52
+ return @resource.stock_location if params[:stock_location_id].blank?
53
+
54
+ seller_stock_location!(params[:stock_location_id])
55
+ end
56
+
57
+ # The workflow assigns the origin raw, so the prefixed id is
58
+ # resolved through the seller's own shelves first — a marketplace
59
+ # warehouse 404s here rather than reaching the assignment.
60
+ def update_attributes
61
+ attributes = permitted_params.to_h
62
+
63
+ if permitted_params[:stock_location_id].present?
64
+ attributes['stock_location_id'] =
65
+ seller_stock_location!(permitted_params[:stock_location_id]).id
66
+ end
67
+
68
+ attributes
69
+ end
70
+
71
+ def seller_stock_location!(id)
72
+ current_seller.stock_locations.find_by_prefix_id!(id)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end