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.
- checksums.yaml +4 -4
- data/LICENSE +28 -0
- data/Rakefile +1 -1
- data/app/controllers/concerns/spree/api/v3/address_params.rb +17 -0
- data/app/controllers/concerns/spree/api/v3/admin/product_listing.rb +46 -0
- data/app/controllers/concerns/spree/api/v3/admin/product_membership.rb +110 -0
- data/app/controllers/concerns/spree/api/v3/admin/receivable_actions.rb +68 -0
- data/app/controllers/concerns/spree/api/v3/admin/reporting_authorization.rb +27 -0
- data/app/controllers/concerns/spree/api/v3/admin/role_grant_guard.rb +69 -33
- data/app/controllers/concerns/spree/api/v3/admin/stock_receipt_actions.rb +86 -0
- data/app/controllers/concerns/spree/api/v3/admin/store_context.rb +97 -0
- data/app/controllers/concerns/spree/api/v3/admin/subclassed_resource.rb +12 -6
- data/app/controllers/concerns/spree/api/v3/admin/validation_details.rb +91 -0
- data/app/controllers/concerns/spree/api/v3/admin_authentication.rb +9 -5
- data/app/controllers/concerns/spree/api/v3/api_key_authentication.rb +41 -5
- data/app/controllers/concerns/spree/api/v3/authentication_strategies.rb +48 -0
- data/app/controllers/concerns/spree/api/v3/bulk_operations.rb +4 -6
- data/app/controllers/concerns/spree/api/v3/cart_resolvable.rb +52 -16
- data/app/controllers/concerns/spree/api/v3/company_address_writes.rb +37 -0
- data/app/controllers/concerns/spree/api/v3/current_password_confirmation.rb +41 -0
- data/app/controllers/concerns/spree/api/v3/direct_uploads.rb +35 -0
- data/app/controllers/concerns/spree/api/v3/error_handler.rb +53 -11
- data/app/controllers/concerns/spree/api/v3/idempotent.rb +10 -4
- data/app/controllers/concerns/spree/api/v3/items_payload.rb +54 -0
- data/app/controllers/concerns/spree/api/v3/jwt_authentication.rb +23 -3
- data/app/controllers/concerns/spree/api/v3/key_store_context.rb +31 -0
- data/app/controllers/concerns/spree/api/v3/locale_and_currency.rb +3 -3
- data/app/controllers/concerns/spree/api/v3/order_lock.rb +22 -3
- data/app/controllers/concerns/spree/api/v3/orders/claim_actions.rb +112 -0
- data/app/controllers/concerns/spree/api/v3/orders/delivery_actions.rb +105 -0
- data/app/controllers/concerns/spree/api/v3/orders/exchange_actions.rb +117 -0
- data/app/controllers/concerns/spree/api/v3/orders/fulfillment_actions.rb +157 -0
- data/app/controllers/concerns/spree/api/v3/orders/post_sale_actions.rb +76 -0
- data/app/controllers/concerns/spree/api/v3/orders/return_actions.rb +116 -0
- data/app/controllers/concerns/spree/api/v3/orders/shipping_label_actions.rb +128 -0
- data/app/controllers/concerns/spree/api/v3/params_normalizer.rb +7 -4
- data/app/controllers/concerns/spree/api/v3/permission_serialization.rb +42 -0
- data/app/controllers/concerns/spree/api/v3/rate_limit_headers.rb +40 -6
- data/app/controllers/concerns/spree/api/v3/scoped_authorization.rb +80 -26
- data/app/controllers/concerns/spree/api/v3/seller/auth_cookies.rb +62 -0
- data/app/controllers/concerns/spree/api/v3/seller/seller_context.rb +127 -0
- data/app/controllers/concerns/spree/api/v3/seller_authentication.rb +40 -0
- data/app/controllers/concerns/spree/api/v3/storefront_access.rb +38 -0
- data/app/controllers/concerns/spree/api/v3/streams_shipping_label.rb +37 -0
- data/app/controllers/concerns/spree/api/v3/tax_identifier_validation.rb +41 -0
- data/app/controllers/spree/api/v3/admin/admin_users_controller.rb +11 -14
- data/app/controllers/spree/api/v3/admin/allowed_origins_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/api_keys_controller.rb +16 -7
- data/app/controllers/spree/api/v3/admin/auth_controller.rb +138 -22
- data/app/controllers/spree/api/v3/admin/base_controller.rb +2 -0
- data/app/controllers/spree/api/v3/admin/catalog_assignments_controller.rb +27 -0
- data/app/controllers/spree/api/v3/admin/catalogs/base_controller.rb +29 -0
- data/app/controllers/spree/api/v3/admin/catalogs/order_minimums_controller.rb +40 -0
- data/app/controllers/spree/api/v3/admin/catalogs/products_controller.rb +107 -0
- data/app/controllers/spree/api/v3/admin/catalogs/quantity_rules_controller.rb +75 -0
- data/app/controllers/spree/api/v3/admin/catalogs_controller.rb +191 -0
- data/app/controllers/spree/api/v3/admin/categories/products_controller.rb +28 -41
- data/app/controllers/spree/api/v3/admin/categories_controller.rb +16 -7
- data/app/controllers/spree/api/v3/admin/channels_controller.rb +50 -2
- data/app/controllers/spree/api/v3/admin/claim_reasons_controller.rb +25 -0
- data/app/controllers/spree/api/v3/admin/claims_controller.rb +31 -0
- data/app/controllers/spree/api/v3/admin/collection_rules_controller.rb +40 -0
- data/app/controllers/spree/api/v3/admin/collections/products_controller.rb +101 -0
- data/app/controllers/spree/api/v3/admin/collections_controller.rb +56 -0
- data/app/controllers/spree/api/v3/admin/commission_lines_controller.rb +39 -0
- data/app/controllers/spree/api/v3/admin/commission_rates_controller.rb +174 -0
- data/app/controllers/spree/api/v3/admin/companies/addresses_controller.rb +65 -0
- data/app/controllers/spree/api/v3/admin/companies/base_controller.rb +29 -0
- data/app/controllers/spree/api/v3/admin/companies/invitations_controller.rb +56 -0
- data/app/controllers/spree/api/v3/admin/companies/memberships_controller.rb +66 -0
- data/app/controllers/spree/api/v3/admin/companies/tax_exemption_certificates_controller.rb +137 -0
- data/app/controllers/spree/api/v3/admin/companies/tax_identifiers_controller.rb +46 -0
- data/app/controllers/spree/api/v3/admin/companies_controller.rb +59 -0
- data/app/controllers/spree/api/v3/admin/concerns/external_references.rb +166 -0
- data/app/controllers/spree/api/v3/admin/consent_records_controller.rb +31 -0
- data/app/controllers/spree/api/v3/admin/countries_controller.rb +12 -4
- data/app/controllers/spree/api/v3/admin/custom_field_definitions_controller.rb +19 -4
- data/app/controllers/spree/api/v3/admin/custom_fields_controller.rb +5 -5
- data/app/controllers/spree/api/v3/admin/customer_groups_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/customers/addresses_controller.rb +4 -4
- data/app/controllers/spree/api/v3/admin/customers/base_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/customers/store_credits_controller.rb +2 -3
- data/app/controllers/spree/api/v3/admin/customers/tax_identifiers_controller.rb +43 -0
- data/app/controllers/spree/api/v3/admin/customers_controller.rb +190 -11
- data/app/controllers/spree/api/v3/admin/dashboard_controller.rb +24 -20
- data/app/controllers/spree/api/v3/admin/data_requests_controller.rb +60 -0
- data/app/controllers/spree/api/v3/admin/delivery_method_rules_controller.rb +54 -0
- data/app/controllers/spree/api/v3/admin/delivery_methods/rules_controller.rb +114 -0
- data/app/controllers/spree/api/v3/admin/delivery_methods_controller.rb +243 -0
- data/app/controllers/spree/api/v3/admin/delivery_profiles/origin_groups_controller.rb +80 -0
- data/app/controllers/spree/api/v3/admin/delivery_profiles_controller.rb +107 -0
- data/app/controllers/spree/api/v3/admin/delivery_zones_controller.rb +116 -0
- data/app/controllers/spree/api/v3/admin/digital_links_controller.rb +48 -0
- data/app/controllers/spree/api/v3/admin/direct_uploads_controller.rb +17 -3
- data/app/controllers/spree/api/v3/admin/exchanges_controller.rb +31 -0
- data/app/controllers/spree/api/v3/admin/exports_controller.rb +2 -2
- data/app/controllers/spree/api/v3/admin/gift_card_batches_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/gift_cards_controller.rb +3 -2
- data/app/controllers/spree/api/v3/admin/imports_controller.rb +71 -8
- data/app/controllers/spree/api/v3/admin/integrations_controller.rb +67 -0
- data/app/controllers/spree/api/v3/admin/invitation_acceptances_controller.rb +5 -5
- data/app/controllers/spree/api/v3/admin/invitations_controller.rb +5 -1
- data/app/controllers/spree/api/v3/admin/locales_controller.rb +3 -1
- data/app/controllers/spree/api/v3/admin/markets_controller.rb +9 -5
- data/app/controllers/spree/api/v3/admin/me_controller.rb +4 -30
- data/app/controllers/spree/api/v3/admin/media_controller.rb +88 -38
- data/app/controllers/spree/api/v3/admin/media_library_controller.rb +156 -0
- data/app/controllers/spree/api/v3/admin/option_types_controller.rb +1 -0
- data/app/controllers/spree/api/v3/admin/order_cancellation_reasons_controller.rb +25 -0
- data/app/controllers/spree/api/v3/admin/order_groups_controller.rb +43 -0
- data/app/controllers/spree/api/v3/admin/order_routing_rules_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/orders/claims_controller.rb +56 -0
- data/app/controllers/spree/api/v3/admin/orders/deliveries_controller.rb +66 -0
- data/app/controllers/spree/api/v3/admin/orders/discount_codes_controller.rb +86 -0
- data/app/controllers/spree/api/v3/admin/orders/discounts_controller.rb +99 -0
- data/app/controllers/spree/api/v3/admin/orders/exchanges_controller.rb +62 -0
- data/app/controllers/spree/api/v3/admin/orders/fees_controller.rb +83 -0
- data/app/controllers/spree/api/v3/admin/orders/fulfillments_controller.rb +45 -67
- data/app/controllers/spree/api/v3/admin/orders/items_controller.rb +40 -22
- data/app/controllers/spree/api/v3/admin/orders/labels_controller.rb +75 -0
- data/app/controllers/spree/api/v3/admin/orders/payments_controller.rb +36 -18
- data/app/controllers/spree/api/v3/admin/orders/refunds_controller.rb +39 -18
- data/app/controllers/spree/api/v3/admin/orders/returns_controller.rb +70 -0
- data/app/controllers/spree/api/v3/admin/orders/store_credits_controller.rb +2 -2
- data/app/controllers/spree/api/v3/admin/orders/tax_identifiers_controller.rb +41 -0
- data/app/controllers/spree/api/v3/admin/orders/tax_lines_controller.rb +32 -0
- data/app/controllers/spree/api/v3/admin/orders_controller.rb +157 -32
- data/app/controllers/spree/api/v3/admin/package_types_controller.rb +39 -0
- data/app/controllers/spree/api/v3/admin/password_resets_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/payment_methods_controller.rb +15 -4
- data/app/controllers/spree/api/v3/admin/payout_providers_controller.rb +27 -0
- data/app/controllers/spree/api/v3/admin/permissions_controller.rb +30 -0
- data/app/controllers/spree/api/v3/admin/policies_controller.rb +42 -0
- data/app/controllers/spree/api/v3/admin/price_lists/products_controller.rb +93 -0
- data/app/controllers/spree/api/v3/admin/price_lists_controller.rb +43 -29
- data/app/controllers/spree/api/v3/admin/prices_controller.rb +41 -4
- data/app/controllers/spree/api/v3/admin/product_types_controller.rb +93 -0
- data/app/controllers/spree/api/v3/admin/products/digital_assets_controller.rb +148 -0
- data/app/controllers/spree/api/v3/admin/products/variants_controller.rb +24 -3
- data/app/controllers/spree/api/v3/admin/products_controller.rb +149 -33
- data/app/controllers/spree/api/v3/admin/promotion_actions_controller.rb +6 -2
- data/app/controllers/spree/api/v3/admin/promotion_rules_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/promotions_controller.rb +1 -5
- data/app/controllers/spree/api/v3/admin/purchase_orders/stock_receipts_controller.rb +32 -0
- data/app/controllers/spree/api/v3/admin/purchase_orders_controller.rb +161 -0
- data/app/controllers/spree/api/v3/admin/refund_reasons_controller.rb +25 -0
- data/app/controllers/spree/api/v3/admin/reporting/saved_reports_controller.rb +45 -0
- data/app/controllers/spree/api/v3/admin/reporting_controller.rb +95 -0
- data/app/controllers/spree/api/v3/admin/resource_controller.rb +27 -10
- data/app/controllers/spree/api/v3/admin/return_reasons_controller.rb +25 -0
- data/app/controllers/spree/api/v3/admin/returns_controller.rb +31 -0
- data/app/controllers/spree/api/v3/admin/roles_controller.rb +50 -6
- data/app/controllers/spree/api/v3/admin/seller_payouts_controller.rb +83 -0
- data/app/controllers/spree/api/v3/admin/seller_requirement_submissions_controller.rb +139 -0
- data/app/controllers/spree/api/v3/admin/seller_requirements_controller.rb +115 -0
- data/app/controllers/spree/api/v3/admin/seller_transfers_controller.rb +36 -0
- data/app/controllers/spree/api/v3/admin/sellers/balances_controller.rb +44 -0
- data/app/controllers/spree/api/v3/admin/sellers/invitations_controller.rb +77 -0
- data/app/controllers/spree/api/v3/admin/sellers/payouts_controller.rb +107 -0
- data/app/controllers/spree/api/v3/admin/sellers/team_controller.rb +64 -0
- data/app/controllers/spree/api/v3/admin/sellers_controller.rb +197 -0
- data/app/controllers/spree/api/v3/admin/setup_controller.rb +231 -0
- data/app/controllers/spree/api/v3/admin/stock_levels_controller.rb +172 -0
- data/app/controllers/spree/api/v3/admin/stock_locations_controller.rb +3 -2
- data/app/controllers/spree/api/v3/admin/stock_movements_controller.rb +37 -0
- data/app/controllers/spree/api/v3/admin/stock_reservations_controller.rb +1 -1
- data/app/controllers/spree/api/v3/admin/stock_transfers/stock_receipts_controller.rb +31 -0
- data/app/controllers/spree/api/v3/admin/stock_transfers_controller.rb +134 -38
- data/app/controllers/spree/api/v3/admin/store_controller.rb +65 -0
- data/app/controllers/spree/api/v3/admin/store_credits/events_controller.rb +47 -0
- data/app/controllers/spree/api/v3/admin/store_credits_controller.rb +87 -0
- data/app/controllers/spree/api/v3/admin/suppliers_controller.rb +30 -0
- data/app/controllers/spree/api/v3/admin/tags_controller.rb +2 -2
- data/app/controllers/spree/api/v3/admin/tax_categories_controller.rb +4 -0
- data/app/controllers/spree/api/v3/admin/tax_providers_controller.rb +25 -0
- data/app/controllers/spree/api/v3/admin/tax_rates_controller.rb +33 -0
- data/app/controllers/spree/api/v3/admin/tracking_carriers_controller.rb +33 -0
- data/app/controllers/spree/api/v3/admin/translatable_resources_controller.rb +37 -9
- data/app/controllers/spree/api/v3/admin/translations_controller.rb +10 -5
- data/app/controllers/spree/api/v3/admin/translations_coverage_controller.rb +150 -0
- data/app/controllers/spree/api/v3/admin/variants_controller.rb +11 -4
- data/app/controllers/spree/api/v3/admin/webhook_endpoints_controller.rb +1 -1
- data/app/controllers/spree/api/v3/base_controller.rb +59 -16
- data/app/controllers/spree/api/v3/resource_controller.rb +154 -38
- data/app/controllers/spree/api/v3/seller/auth_controller.rb +169 -0
- data/app/controllers/spree/api/v3/seller/balances_controller.rb +35 -0
- data/app/controllers/spree/api/v3/seller/base_controller.rb +25 -0
- data/app/controllers/spree/api/v3/seller/claim_reasons_controller.rb +20 -0
- data/app/controllers/spree/api/v3/seller/countries_controller.rb +38 -0
- data/app/controllers/spree/api/v3/seller/delivery_methods_controller.rb +265 -0
- data/app/controllers/spree/api/v3/seller/delivery_profiles_controller.rb +65 -0
- data/app/controllers/spree/api/v3/seller/delivery_zones_controller.rb +41 -0
- data/app/controllers/spree/api/v3/seller/direct_uploads_controller.rb +21 -0
- data/app/controllers/spree/api/v3/seller/exports_controller.rb +195 -0
- data/app/controllers/spree/api/v3/seller/import_rows_controller.rb +49 -0
- data/app/controllers/spree/api/v3/seller/imports_controller.rb +317 -0
- data/app/controllers/spree/api/v3/seller/invitation_acceptances_controller.rb +152 -0
- data/app/controllers/spree/api/v3/seller/invitations_controller.rb +71 -0
- data/app/controllers/spree/api/v3/seller/me_controller.rb +72 -0
- data/app/controllers/spree/api/v3/seller/onboarding_controller.rb +111 -0
- data/app/controllers/spree/api/v3/seller/order_cancellation_reasons_controller.rb +25 -0
- data/app/controllers/spree/api/v3/seller/orders/base_controller.rb +44 -0
- data/app/controllers/spree/api/v3/seller/orders/claims_controller.rb +45 -0
- data/app/controllers/spree/api/v3/seller/orders/deliveries_controller.rb +38 -0
- data/app/controllers/spree/api/v3/seller/orders/exchanges_controller.rb +50 -0
- data/app/controllers/spree/api/v3/seller/orders/fulfillments_controller.rb +79 -0
- data/app/controllers/spree/api/v3/seller/orders/labels_controller.rb +55 -0
- data/app/controllers/spree/api/v3/seller/orders/notes_controller.rb +82 -0
- data/app/controllers/spree/api/v3/seller/orders/returns_controller.rb +44 -0
- data/app/controllers/spree/api/v3/seller/orders_controller.rb +199 -0
- data/app/controllers/spree/api/v3/seller/package_types_controller.rb +100 -0
- data/app/controllers/spree/api/v3/seller/password_resets_controller.rb +155 -0
- data/app/controllers/spree/api/v3/seller/payouts_controller.rb +47 -0
- data/app/controllers/spree/api/v3/seller/policies_controller.rb +57 -0
- data/app/controllers/spree/api/v3/seller/product_types_controller.rb +35 -0
- data/app/controllers/spree/api/v3/seller/products_controller.rb +394 -0
- data/app/controllers/spree/api/v3/seller/profile_controller.rb +137 -0
- data/app/controllers/spree/api/v3/seller/reasons_controller.rb +45 -0
- data/app/controllers/spree/api/v3/seller/requirement_submissions_controller.rb +95 -0
- data/app/controllers/spree/api/v3/seller/resource_controller.rb +75 -0
- data/app/controllers/spree/api/v3/seller/return_reasons_controller.rb +20 -0
- data/app/controllers/spree/api/v3/seller/stock_locations_controller.rb +56 -0
- data/app/controllers/spree/api/v3/seller/tax_identifiers_controller.rb +48 -0
- data/app/controllers/spree/api/v3/seller/team_controller.rb +103 -0
- data/app/controllers/spree/api/v3/seller/tracking_carriers_controller.rb +35 -0
- data/app/controllers/spree/api/v3/seller/transfers_controller.rb +43 -0
- data/app/controllers/spree/api/v3/store/account/companies_controller.rb +42 -0
- data/app/controllers/spree/api/v3/store/auth_controller.rb +21 -34
- data/app/controllers/spree/api/v3/store/base_controller.rb +4 -0
- data/app/controllers/spree/api/v3/store/carts/discount_codes_controller.rb +24 -2
- data/app/controllers/spree/api/v3/store/carts/fulfillments_controller.rb +41 -15
- data/app/controllers/spree/api/v3/store/carts/items_controller.rb +53 -20
- data/app/controllers/spree/api/v3/store/carts/payment_sessions_controller.rb +36 -20
- data/app/controllers/spree/api/v3/store/carts/po_documents_controller.rb +111 -0
- data/app/controllers/spree/api/v3/store/carts/store_credits_controller.rb +2 -2
- data/app/controllers/spree/api/v3/store/carts/tax_identifiers_controller.rb +96 -0
- data/app/controllers/spree/api/v3/store/carts_controller.rb +57 -12
- data/app/controllers/spree/api/v3/store/categories_controller.rb +6 -3
- data/app/controllers/spree/api/v3/store/collections/products_controller.rb +59 -0
- data/app/controllers/spree/api/v3/store/collections_controller.rb +36 -0
- data/app/controllers/spree/api/v3/store/companies/addresses_controller.rb +81 -0
- data/app/controllers/spree/api/v3/store/companies/base_controller.rb +24 -0
- data/app/controllers/spree/api/v3/store/companies/invitations_controller.rb +50 -0
- data/app/controllers/spree/api/v3/store/companies/members_controller.rb +66 -0
- data/app/controllers/spree/api/v3/store/companies/orders_controller.rb +28 -0
- data/app/controllers/spree/api/v3/store/companies_controller.rb +47 -0
- data/app/controllers/spree/api/v3/store/company_invitations_controller.rb +90 -0
- data/app/controllers/spree/api/v3/store/countries_controller.rb +8 -6
- data/app/controllers/spree/api/v3/store/customer/addresses_controller.rb +3 -1
- data/app/controllers/spree/api/v3/store/customer/data_requests_controller.rb +78 -0
- data/app/controllers/spree/api/v3/store/customer/digital_links_controller.rb +52 -0
- data/app/controllers/spree/api/v3/store/customer/orders_controller.rb +6 -0
- data/app/controllers/spree/api/v3/store/customer/password_resets_controller.rb +7 -3
- data/app/controllers/spree/api/v3/store/customer/payment_setup_sessions_controller.rb +3 -3
- data/app/controllers/spree/api/v3/store/customer/store_credits_controller.rb +0 -3
- data/app/controllers/spree/api/v3/store/customer/tax_identifiers_controller.rb +91 -0
- data/app/controllers/spree/api/v3/store/customers_controller.rb +26 -31
- data/app/controllers/spree/api/v3/store/data_feeds_controller.rb +11 -0
- data/app/controllers/spree/api/v3/store/data_request_downloads_controller.rb +58 -0
- data/app/controllers/spree/api/v3/store/delivery_methods_controller.rb +108 -0
- data/app/controllers/spree/api/v3/store/digital_links_controller.rb +105 -0
- data/app/controllers/spree/api/v3/store/markets/countries_controller.rb +5 -9
- data/app/controllers/spree/api/v3/store/markets_controller.rb +4 -4
- data/app/controllers/spree/api/v3/store/newsletter_subscribers_controller.rb +8 -9
- data/app/controllers/spree/api/v3/store/orders/claims_controller.rb +94 -0
- data/app/controllers/spree/api/v3/store/orders/returns_controller.rb +116 -0
- data/app/controllers/spree/api/v3/store/orders/tax_identifiers_controller.rb +46 -0
- data/app/controllers/spree/api/v3/store/orders_controller.rb +12 -15
- data/app/controllers/spree/api/v3/store/products/filters_controller.rb +10 -3
- data/app/controllers/spree/api/v3/store/products_controller.rb +25 -6
- data/app/controllers/spree/api/v3/store/resource_controller.rb +2 -0
- data/app/controllers/spree/api/v3/store/sellers_controller.rb +43 -0
- data/app/controllers/spree/api/v3/store/wishlist_items_controller.rb +9 -6
- data/app/controllers/spree/api/v3/store/wishlists_controller.rb +3 -3
- data/app/controllers/spree/api/v3/webhooks/fulfillments_controller.rb +88 -0
- data/app/controllers/spree/api/v3/webhooks/payments_controller.rb +5 -2
- data/app/controllers/spree/api/v3/webhooks/payouts_controller.rb +61 -0
- data/app/models/spree/api/data_request_urls.rb +25 -0
- data/app/models/spree/api/digital_link_urls.rb +26 -0
- data/app/serializers/spree/api/v3/address_serializer.rb +17 -5
- data/app/serializers/spree/api/v3/admin/address_serializer.rb +27 -4
- data/app/serializers/spree/api/v3/admin/admin_user_serializer.rb +13 -10
- data/app/serializers/spree/api/v3/admin/api_key_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/applied_promotion_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/cart_serializer.rb +34 -0
- data/app/serializers/spree/api/v3/admin/catalog_assignment_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/admin/catalog_order_minimum_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/admin/catalog_price_serializer.rb +48 -0
- data/app/serializers/spree/api/v3/admin/catalog_price_tier_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/admin/catalog_product_serializer.rb +57 -0
- data/app/serializers/spree/api/v3/admin/catalog_product_term_serializer.rb +38 -0
- data/app/serializers/spree/api/v3/admin/catalog_quantity_rule_serializer.rb +37 -0
- data/app/serializers/spree/api/v3/admin/catalog_serializer.rb +46 -0
- data/app/serializers/spree/api/v3/admin/category_serializer.rb +3 -2
- data/app/serializers/spree/api/v3/admin/channel_serializer.rb +15 -1
- data/app/serializers/spree/api/v3/admin/claim_line_item_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/admin/claim_reason_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/admin/claim_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/collection_rule_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/admin/collection_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/commission_line_serializer.rb +67 -0
- data/app/serializers/spree/api/v3/admin/commission_rate_serializer.rb +69 -0
- data/app/serializers/spree/api/v3/admin/commission_rule_serializer.rb +61 -0
- data/app/serializers/spree/api/v3/admin/company_invitation_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/company_membership_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/company_serializer.rb +37 -0
- data/app/serializers/spree/api/v3/admin/concerns/external_references_attribute.rb +33 -0
- data/app/serializers/spree/api/v3/admin/consent_record_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/admin/country_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/credit_card_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/custom_field_definition_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/custom_field_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/admin/customer_serializer.rb +23 -22
- data/app/serializers/spree/api/v3/admin/dashboard_counter_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/admin/data_request_serializer.rb +36 -0
- data/app/serializers/spree/api/v3/admin/delivery_method_rule_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/admin/delivery_method_serializer.rb +66 -1
- data/app/serializers/spree/api/v3/admin/delivery_method_service_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/admin/delivery_origin_group_serializer.rb +34 -0
- data/app/serializers/spree/api/v3/admin/delivery_profile_serializer.rb +65 -0
- data/app/serializers/spree/api/v3/admin/delivery_rate_serializer.rb +10 -1
- data/app/serializers/spree/api/v3/admin/delivery_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/admin/delivery_zone_member_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/delivery_zone_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/digital_asset_serializer.rb +59 -0
- data/app/serializers/spree/api/v3/admin/discount_serializer.rb +3 -4
- data/app/serializers/spree/api/v3/admin/exchange_line_item_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/admin/exchange_serializer.rb +35 -0
- data/app/serializers/spree/api/v3/admin/export_serializer.rb +20 -1
- data/app/serializers/spree/api/v3/admin/fee_serializer.rb +14 -0
- data/app/serializers/spree/api/v3/admin/freight_summary_line_serializer.rb +46 -0
- data/app/serializers/spree/api/v3/admin/freight_summary_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/admin/fulfillment_item_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/admin/fulfillment_serializer.rb +31 -9
- data/app/serializers/spree/api/v3/admin/gift_card_serializer.rb +2 -3
- data/app/serializers/spree/api/v3/admin/import_serializer.rb +15 -2
- data/app/serializers/spree/api/v3/admin/integration_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/admin/invitation_serializer.rb +4 -4
- data/app/serializers/spree/api/v3/admin/line_item_serializer.rb +19 -5
- data/app/serializers/spree/api/v3/admin/market_serializer.rb +5 -1
- data/app/serializers/spree/api/v3/admin/media_serializer.rb +50 -2
- data/app/serializers/spree/api/v3/admin/membership_product_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/order_cancellation_reason_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/order_group_serializer.rb +50 -0
- data/app/serializers/spree/api/v3/admin/order_routing_rule_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/admin/order_serializer.rb +131 -19
- data/app/serializers/spree/api/v3/admin/package_type_serializer.rb +53 -0
- data/app/serializers/spree/api/v3/admin/payment_method_serializer.rb +8 -2
- data/app/serializers/spree/api/v3/admin/payment_serializer.rb +6 -0
- data/app/serializers/spree/api/v3/admin/payment_split_serializer.rb +41 -0
- data/app/serializers/spree/api/v3/admin/permission_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/admin/policy_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/admin/price_adjustment_tier_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/admin/price_list_product_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/admin/price_list_serializer.rb +20 -8
- data/app/serializers/spree/api/v3/admin/price_rule_serializer.rb +2 -12
- data/app/serializers/spree/api/v3/admin/price_serializer.rb +3 -0
- data/app/serializers/spree/api/v3/admin/product_serializer.rb +54 -8
- data/app/serializers/spree/api/v3/admin/product_submission_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/admin/product_type_custom_field_definition_serializer.rb +44 -0
- data/app/serializers/spree/api/v3/admin/product_type_serializer.rb +34 -0
- data/app/serializers/spree/api/v3/admin/promotion_action_serializer.rb +6 -12
- data/app/serializers/spree/api/v3/admin/promotion_rule_serializer.rb +17 -15
- data/app/serializers/spree/api/v3/admin/purchase_order_item_serializer.rb +80 -0
- data/app/serializers/spree/api/v3/admin/purchase_order_serializer.rb +94 -0
- data/app/serializers/spree/api/v3/admin/refund_reason_serializer.rb +27 -0
- data/app/serializers/spree/api/v3/admin/refund_serializer.rb +0 -5
- data/app/serializers/spree/api/v3/admin/reporting_result_serializer.rb +72 -0
- data/app/serializers/spree/api/v3/admin/return_line_item_serializer.rb +16 -0
- data/app/serializers/spree/api/v3/admin/return_reason_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/admin/return_serializer.rb +59 -0
- data/app/serializers/spree/api/v3/admin/role_serializer.rb +24 -6
- data/app/serializers/spree/api/v3/admin/saved_report_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/admin/seller_balance_serializer.rb +37 -0
- data/app/serializers/spree/api/v3/admin/seller_payout_serializer.rb +46 -0
- data/app/serializers/spree/api/v3/admin/seller_requirement_serializer.rb +68 -0
- data/app/serializers/spree/api/v3/admin/seller_requirement_status_serializer.rb +48 -0
- data/app/serializers/spree/api/v3/admin/seller_requirement_submission_serializer.rb +57 -0
- data/app/serializers/spree/api/v3/admin/seller_serializer.rb +92 -0
- data/app/serializers/spree/api/v3/admin/seller_team_member_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/admin/seller_transfer_serializer.rb +53 -0
- data/app/serializers/spree/api/v3/admin/shipping_label_serializer.rb +82 -0
- data/app/serializers/spree/api/v3/admin/state_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/admin/stock_level_serializer.rb +65 -0
- data/app/serializers/spree/api/v3/admin/stock_location_serializer.rb +20 -4
- data/app/serializers/spree/api/v3/admin/stock_movement_serializer.rb +116 -0
- data/app/serializers/spree/api/v3/admin/stock_receipt_item_serializer.rb +57 -0
- data/app/serializers/spree/api/v3/admin/stock_receipt_serializer.rb +49 -0
- data/app/serializers/spree/api/v3/admin/stock_reservation_serializer.rb +5 -5
- data/app/serializers/spree/api/v3/admin/stock_transfer_item_serializer.rb +57 -0
- data/app/serializers/spree/api/v3/admin/stock_transfer_serializer.rb +36 -16
- data/app/serializers/spree/api/v3/admin/store_credit_event_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/admin/store_credit_serializer.rb +42 -7
- data/app/serializers/spree/api/v3/admin/store_serializer.rb +63 -1
- data/app/serializers/spree/api/v3/admin/supplier_serializer.rb +39 -0
- data/app/serializers/spree/api/v3/admin/tax_exemption_certificate_serializer.rb +67 -0
- data/app/serializers/spree/api/v3/admin/tax_identifier_serializer.rb +43 -0
- data/app/serializers/spree/api/v3/admin/tax_line_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/admin/tax_rate_serializer.rb +49 -0
- data/app/serializers/spree/api/v3/admin/variant_serializer.rb +49 -8
- data/app/serializers/spree/api/v3/applied_promotion_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/base_serializer.rb +39 -2
- data/app/serializers/spree/api/v3/cart_serializer.rb +90 -12
- data/app/serializers/spree/api/v3/category_serializer.rb +3 -3
- data/app/serializers/spree/api/v3/claim_line_item_serializer.rb +50 -0
- data/app/serializers/spree/api/v3/claim_reason_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/claim_serializer.rb +62 -0
- data/app/serializers/spree/api/v3/collection_serializer.rb +41 -0
- data/app/serializers/spree/api/v3/company_invitation_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/company_membership_serializer.rb +28 -0
- data/app/serializers/spree/api/v3/company_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/custom_field_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/customer_serializer.rb +9 -1
- data/app/serializers/spree/api/v3/data_request_event_serializer.rb +30 -0
- data/app/serializers/spree/api/v3/data_request_serializer.rb +40 -0
- data/app/serializers/spree/api/v3/delivery_method_serializer.rb +12 -2
- data/app/serializers/spree/api/v3/delivery_rate_serializer.rb +34 -17
- data/app/serializers/spree/api/v3/delivery_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/delivery_zone_member_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/delivery_zone_serializer.rb +13 -0
- data/app/serializers/spree/api/v3/digital_asset_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/digital_link_serializer.rb +6 -2
- data/app/serializers/spree/api/v3/discount_serializer.rb +21 -7
- data/app/serializers/spree/api/v3/exchange_line_item_serializer.rb +53 -0
- data/app/serializers/spree/api/v3/exchange_serializer.rb +61 -0
- data/app/serializers/spree/api/v3/fee_serializer.rb +27 -0
- data/app/serializers/spree/api/v3/freight_summary_serializer.rb +38 -0
- data/app/serializers/spree/api/v3/fulfillment_serializer.rb +28 -15
- data/app/serializers/spree/api/v3/gift_card_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/import_row_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/import_serializer.rb +18 -4
- data/app/serializers/spree/api/v3/invitation_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/line_item_serializer.rb +18 -1
- data/app/serializers/spree/api/v3/market_serializer.rb +2 -2
- data/app/serializers/spree/api/v3/{asset_serializer.rb → media_event_serializer.rb} +4 -4
- data/app/serializers/spree/api/v3/media_serializer.rb +48 -7
- data/app/serializers/spree/api/v3/newsletter_subscriber_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/option_type_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/order_group_serializer.rb +60 -0
- data/app/serializers/spree/api/v3/order_serializer.rb +58 -6
- data/app/serializers/spree/api/v3/payment_method_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/payment_serializer.rb +2 -6
- data/app/serializers/spree/api/v3/payment_session_serializer.rb +10 -3
- data/app/serializers/spree/api/v3/payment_setup_session_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/policy_serializer.rb +7 -2
- data/app/serializers/spree/api/v3/product_filter_option_serializer.rb +1 -1
- data/app/serializers/spree/api/v3/product_serializer.rb +42 -10
- data/app/serializers/spree/api/v3/product_type_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/purchase_order_event_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/refund_serializer.rb +9 -3
- data/app/serializers/spree/api/v3/return_line_item_serializer.rb +42 -0
- data/app/serializers/spree/api/v3/return_reason_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/return_serializer.rb +62 -0
- data/app/serializers/spree/api/v3/seller/balance_serializer.rb +35 -0
- data/app/serializers/spree/api/v3/seller/claim_line_item_serializer.rb +21 -0
- data/app/serializers/spree/api/v3/seller/claim_serializer.rb +25 -0
- data/app/serializers/spree/api/v3/seller/delivery_method_rule_serializer.rb +32 -0
- data/app/serializers/spree/api/v3/seller/delivery_method_serializer.rb +59 -0
- data/app/serializers/spree/api/v3/seller/delivery_profile_serializer.rb +26 -0
- data/app/serializers/spree/api/v3/seller/delivery_rate_serializer.rb +35 -0
- data/app/serializers/spree/api/v3/seller/delivery_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/seller/delivery_zone_serializer.rb +26 -0
- data/app/serializers/spree/api/v3/seller/exchange_line_item_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/seller/exchange_serializer.rb +30 -0
- data/app/serializers/spree/api/v3/seller/export_serializer.rb +44 -0
- data/app/serializers/spree/api/v3/seller/fulfillment_item_serializer.rb +43 -0
- data/app/serializers/spree/api/v3/seller/fulfillment_serializer.rb +76 -0
- data/app/serializers/spree/api/v3/seller/import_mapping_serializer.rb +20 -0
- data/app/serializers/spree/api/v3/seller/import_row_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/seller/import_serializer.rb +77 -0
- data/app/serializers/spree/api/v3/seller/invitation_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/seller/media_serializer.rb +26 -0
- data/app/serializers/spree/api/v3/seller/order_line_item_serializer.rb +44 -0
- data/app/serializers/spree/api/v3/seller/order_serializer.rb +119 -0
- data/app/serializers/spree/api/v3/seller/package_type_serializer.rb +52 -0
- data/app/serializers/spree/api/v3/seller/payment_split_serializer.rb +34 -0
- data/app/serializers/spree/api/v3/seller/payout_serializer.rb +36 -0
- data/app/serializers/spree/api/v3/seller/policy_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/seller/product_serializer.rb +60 -0
- data/app/serializers/spree/api/v3/seller/product_submission_serializer.rb +30 -0
- data/app/serializers/spree/api/v3/seller/product_type_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/seller/profile_serializer.rb +77 -0
- data/app/serializers/spree/api/v3/seller/reason_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/seller/requirement_custom_field_serializer.rb +36 -0
- data/app/serializers/spree/api/v3/seller/requirement_status_serializer.rb +62 -0
- data/app/serializers/spree/api/v3/seller/requirement_submission_serializer.rb +33 -0
- data/app/serializers/spree/api/v3/seller/return_line_item_serializer.rb +24 -0
- data/app/serializers/spree/api/v3/seller/return_serializer.rb +51 -0
- data/app/serializers/spree/api/v3/seller/shipping_label_serializer.rb +23 -0
- data/app/serializers/spree/api/v3/seller/stock_level_serializer.rb +27 -0
- data/app/serializers/spree/api/v3/seller/stock_location_serializer.rb +17 -0
- data/app/serializers/spree/api/v3/seller/tax_identifier_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/seller/team_member_serializer.rb +22 -0
- data/app/serializers/spree/api/v3/seller/transfer_serializer.rb +49 -0
- data/app/serializers/spree/api/v3/seller/variant_serializer.rb +71 -0
- data/app/serializers/spree/api/v3/seller_serializer.rb +50 -0
- data/app/serializers/spree/api/v3/shipping_label_event_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/{stock_item_serializer.rb → stock_level_serializer.rb} +5 -5
- data/app/serializers/spree/api/v3/stock_location_serializer.rb +11 -7
- data/app/serializers/spree/api/v3/stock_movement_serializer.rb +8 -15
- data/app/serializers/spree/api/v3/stock_receipt_event_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/stock_transfer_serializer.rb +6 -6
- data/app/serializers/spree/api/v3/store_credit_event_serializer.rb +29 -0
- data/app/serializers/spree/api/v3/supplier_event_serializer.rb +11 -0
- data/app/serializers/spree/api/v3/tax_identifier_serializer.rb +15 -0
- data/app/serializers/spree/api/v3/tax_line_serializer.rb +37 -0
- data/app/serializers/spree/api/v3/variant_serializer.rb +52 -2
- data/app/serializers/spree/api/v3/wishlist_item_serializer.rb +6 -6
- data/app/serializers/spree/api/v3/wishlist_serializer.rb +1 -1
- data/app/services/spree/api/v3/filters_aggregator.rb +14 -12
- data/app/services/spree/webhooks/deliver_webhook.rb +62 -26
- data/app/subscribers/spree/webhook_event_subscriber.rb +9 -5
- data/config/brakeman.ignore +1 -1
- data/config/initializers/typelizer.rb +51 -4
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +730 -22
- data/lib/spree/api/configuration.rb +2 -7
- data/lib/spree/api/dependencies.rb +173 -227
- data/lib/spree/api/openapi/schema_helper.rb +179 -13
- data/lib/spree/api/testing_support/v3/base.rb +45 -15
- data/lib/spree/api.rb +10 -4
- data/lib/typelizer/open_enums.rb +35 -0
- metadata +341 -27
- data/app/controllers/spree/api/v3/admin/orders/adjustments_controller.rb +0 -25
- data/app/controllers/spree/api/v3/admin/stock_items_controller.rb +0 -42
- data/app/controllers/spree/api/v3/admin/store_credit_categories_controller.rb +0 -21
- data/app/controllers/spree/api/v3/store/digitals_controller.rb +0 -38
- data/app/serializers/spree/api/v3/admin/adjustment_serializer.rb +0 -24
- data/app/serializers/spree/api/v3/admin/dashboard_analytics_serializer.rb +0 -143
- data/app/serializers/spree/api/v3/admin/reimbursement_serializer.rb +0 -15
- data/app/serializers/spree/api/v3/admin/return_authorization_serializer.rb +0 -19
- data/app/serializers/spree/api/v3/admin/stock_item_serializer.rb +0 -34
- data/app/serializers/spree/api/v3/admin/store_credit_category_serializer.rb +0 -19
- data/app/serializers/spree/api/v3/customer_return_serializer.rb +0 -17
- data/app/serializers/spree/api/v3/digital_serializer.rb +0 -17
- data/app/serializers/spree/api/v3/reimbursement_serializer.rb +0 -27
- data/app/serializers/spree/api/v3/report_serializer.rb +0 -34
- data/app/serializers/spree/api/v3/return_authorization_serializer.rb +0 -31
- data/app/serializers/spree/api/v3/return_item_serializer.rb +0 -53
- data/app/serializers/spree/api/v3/shipping_category_serializer.rb +0 -11
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Seller
|
|
5
|
+
# A seller's own legal documents — their returns policy, shipping
|
|
6
|
+
# policy, whatever the marketplace asks them to publish.
|
|
7
|
+
#
|
|
8
|
+
# Rooted in `current_seller.policies`, so the operator's store policies
|
|
9
|
+
# and every other seller's are invisible here: an id belonging to
|
|
10
|
+
# either is a 404, not a permission error.
|
|
11
|
+
class PoliciesController < Seller::ResourceController
|
|
12
|
+
scoped_resource :seller_profile
|
|
13
|
+
|
|
14
|
+
protected
|
|
15
|
+
|
|
16
|
+
def model_class
|
|
17
|
+
Spree::Policy
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def serializer_class
|
|
21
|
+
Spree.api.seller_policy_serializer
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def resource_permitted_attributes
|
|
25
|
+
[:name, :slug, :body]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Accept slug or prefixed ID, matching the storefront's lookup.
|
|
29
|
+
def find_resource
|
|
30
|
+
if params[:id].to_s.start_with?('pol_')
|
|
31
|
+
scope.find_by_prefix_id!(params[:id])
|
|
32
|
+
else
|
|
33
|
+
scope.friendly.find(params[:id])
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def scope
|
|
38
|
+
super.order(:name)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Authorize the seller's own profile surface, not `Spree::Policy`.
|
|
42
|
+
#
|
|
43
|
+
# The catalog gives that class to `settings` — the operator's key,
|
|
44
|
+
# which a seller must never hold — so the inherited record check
|
|
45
|
+
# would ask for a grant no seller has and deny every request. The
|
|
46
|
+
# question this endpoint actually asks is "may this seller edit
|
|
47
|
+
# their own record", which is what `:seller_profile` answers; which
|
|
48
|
+
# policy they may touch is settled by the scope above, never by the
|
|
49
|
+
# ability.
|
|
50
|
+
def authorize_resource!(_resource = @resource, action = action_name.to_sym)
|
|
51
|
+
authorize!(action, :seller_profile)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Seller
|
|
5
|
+
# The product types a seller may list against.
|
|
6
|
+
#
|
|
7
|
+
# Read only, and deliberately so: a seller picks a type because it is
|
|
8
|
+
# the template that hands their product its option types and delivery
|
|
9
|
+
# profile, but what types the marketplace offers is the operator's
|
|
10
|
+
# decision (docs/plans/6.0-seller-product-submission.md, Decision 5).
|
|
11
|
+
#
|
|
12
|
+
# Types belong to the store rather than to a seller, so this is one of
|
|
13
|
+
# the few seller collections not rooted in `current_seller` — the
|
|
14
|
+
# store comes from the seller, which is what keeps it scoped.
|
|
15
|
+
class ProductTypesController < Seller::ResourceController
|
|
16
|
+
scoped_resource :product_types
|
|
17
|
+
|
|
18
|
+
protected
|
|
19
|
+
|
|
20
|
+
def model_class
|
|
21
|
+
Spree::ProductType
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def serializer_class
|
|
25
|
+
Spree.api.seller_product_type_serializer
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def scope
|
|
29
|
+
current_store.product_types
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Seller
|
|
5
|
+
# A seller's own products.
|
|
6
|
+
#
|
|
7
|
+
# The first consumer of `Seller::ResourceController`, and the shape
|
|
8
|
+
# every seller-side collection follows: the anchor roots `scope` in
|
|
9
|
+
# `current_seller.products`, so listing, finding, updating and
|
|
10
|
+
# deleting can only ever touch this seller's rows — a product id that
|
|
11
|
+
# belongs to another seller is a 404, not a 403, since the caller
|
|
12
|
+
# cannot tell whether it exists.
|
|
13
|
+
#
|
|
14
|
+
# Owned products only. Variants a seller lists against a shared
|
|
15
|
+
# master-catalog product are a separate surface (the shared catalog
|
|
16
|
+
# phase) and do not belong to this seller through `products`.
|
|
17
|
+
#
|
|
18
|
+
# What a seller may change is narrower than the operator's set. Tax
|
|
19
|
+
# category and `promotionable` are marketplace configuration, and so
|
|
20
|
+
# is how a product is filed: categories, collections and tags are the
|
|
21
|
+
# marketplace's own merchandising, set when the operator reviews the
|
|
22
|
+
# listing. The product type and the delivery profile are the seller's
|
|
23
|
+
# to pick — from the marketplace's list — because the type is what
|
|
24
|
+
# hands their product its option types, and the profile is what
|
|
25
|
+
# decides how their goods can be shipped at all
|
|
26
|
+
# (docs/plans/6.0-multi-vendor-marketplace.md, Decision 13).
|
|
27
|
+
#
|
|
28
|
+
# Tags are the clearest case — they are tenanted to the store
|
|
29
|
+
# (`acts_as_taggable_tenant :store_id`), so a seller typing one would
|
|
30
|
+
# be writing into the marketplace's shared vocabulary rather than
|
|
31
|
+
# labelling their product
|
|
32
|
+
# (docs/plans/6.0-multi-vendor-marketplace.md).
|
|
33
|
+
class ProductsController < Seller::ResourceController
|
|
34
|
+
# The statuses a seller may move a selection to, each paired with the
|
|
35
|
+
# workflow that gets it there. A map rather than a status list
|
|
36
|
+
# because these moves are not attribute writes: taking a listing down
|
|
37
|
+
# settles the submission the seller had open, which `update_all`
|
|
38
|
+
# would leave sitting as `pending` forever.
|
|
39
|
+
SELLER_BULK_STATUS_WORKFLOWS = {
|
|
40
|
+
'draft' => -> { Spree.product_draft_workflow },
|
|
41
|
+
'archived' => -> { Spree.product_archive_workflow }
|
|
42
|
+
}.freeze
|
|
43
|
+
|
|
44
|
+
scoped_resource :products
|
|
45
|
+
|
|
46
|
+
before_action :set_status_resource, only: [:submit, :draft, :archive]
|
|
47
|
+
before_action :require_ids!, only: [:bulk_submit, :bulk_status_update, :bulk_destroy]
|
|
48
|
+
|
|
49
|
+
# PATCH /api/v3/seller/products/:id/submit
|
|
50
|
+
#
|
|
51
|
+
# Asking the marketplace to put this product on sale.
|
|
52
|
+
def submit
|
|
53
|
+
run_status_workflow(Spree.product_propose_workflow,
|
|
54
|
+
submitted_by: try_spree_current_user)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# PATCH /api/v3/seller/products/:id/draft
|
|
58
|
+
#
|
|
59
|
+
# Taking a listing back down. Withdrawing your own product is not a
|
|
60
|
+
# review decision, so it needs nobody's approval.
|
|
61
|
+
def draft
|
|
62
|
+
run_status_workflow(Spree.product_draft_workflow)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# PATCH /api/v3/seller/products/:id/archive
|
|
66
|
+
def archive
|
|
67
|
+
run_status_workflow(Spree.product_archive_workflow)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# POST /api/v3/seller/products/bulk_submit
|
|
71
|
+
# Body: { ids: [...] }
|
|
72
|
+
#
|
|
73
|
+
# Asking the marketplace to review a selection.
|
|
74
|
+
def bulk_submit
|
|
75
|
+
authorize! :update, model_class
|
|
76
|
+
|
|
77
|
+
# Judged on whether the product moved, not on the result: where a
|
|
78
|
+
# store auto-approves, Propose commits the submission and then
|
|
79
|
+
# chains into Approve, returning *its* result. A product that went
|
|
80
|
+
# into review and then failed to go on sale was still submitted,
|
|
81
|
+
# and counting it as skipped would tell the seller their draft was
|
|
82
|
+
# not eligible when it is now sitting in review.
|
|
83
|
+
render json: run_bulk(seller_bulk_scope(:update)) { |product|
|
|
84
|
+
was = product.status
|
|
85
|
+
|
|
86
|
+
Spree.product_propose_workflow.call(product: product,
|
|
87
|
+
submitted_by: try_spree_current_user)
|
|
88
|
+
|
|
89
|
+
# A product Propose refused is untouched; one it accepted is in
|
|
90
|
+
# review or already through it.
|
|
91
|
+
product.reload.status != was
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# POST /api/v3/seller/products/bulk_status_update
|
|
96
|
+
# Body: { ids: [...], status: 'draft' | 'archived' }
|
|
97
|
+
#
|
|
98
|
+
# The two moves a seller makes alone. `active` is absent by design:
|
|
99
|
+
# a listing goes on sale when the operator approves it, so there is
|
|
100
|
+
# no status a seller can assign that reaches it
|
|
101
|
+
# (docs/plans/6.0-seller-product-submission.md).
|
|
102
|
+
def bulk_status_update
|
|
103
|
+
authorize! :update, model_class
|
|
104
|
+
|
|
105
|
+
resolve_workflow = SELLER_BULK_STATUS_WORKFLOWS[params[:status].to_s]
|
|
106
|
+
|
|
107
|
+
if resolve_workflow.nil?
|
|
108
|
+
return render_error(
|
|
109
|
+
code: 'invalid_status',
|
|
110
|
+
message: Spree.t(:invalid_status, scope: 'errors.messages', default: 'Invalid status'),
|
|
111
|
+
status: :unprocessable_content
|
|
112
|
+
)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Resolved at call time, not at load: the workflow is a
|
|
116
|
+
# configurable dependency, so a host that swaps it must be honoured
|
|
117
|
+
# rather than frozen into the constant at boot.
|
|
118
|
+
run_bulk_workflow(resolve_workflow.call)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# DELETE /api/v3/seller/products/bulk_destroy
|
|
122
|
+
# Body: { ids: [...] }
|
|
123
|
+
def bulk_destroy
|
|
124
|
+
authorize! :destroy, model_class
|
|
125
|
+
|
|
126
|
+
# Scoped by `:destroy` rather than reusing `bulk_collection`,
|
|
127
|
+
# which is `:update`-scoped: a seller who may edit their catalog
|
|
128
|
+
# but not delete from it must not delete through the bulk route.
|
|
129
|
+
#
|
|
130
|
+
# `Products::Destroy` exists so a store can refuse a deletion, so
|
|
131
|
+
# this reports refusals like the status actions do — a product that
|
|
132
|
+
# survives while the response says it was deleted is the one
|
|
133
|
+
# outcome a merchant must never be shown.
|
|
134
|
+
render json: run_bulk(seller_bulk_scope(:destroy)) { |product|
|
|
135
|
+
Spree.product_destroy_workflow.call(product: product)
|
|
136
|
+
}
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
protected
|
|
140
|
+
|
|
141
|
+
def model_class
|
|
142
|
+
Spree::Product
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def serializer_class
|
|
146
|
+
Spree.api.seller_product_serializer
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# The same workflows the operator's endpoint runs, so a seller's write
|
|
150
|
+
# gets the nested variant and media handling and the validate hooks
|
|
151
|
+
# rather than a bare assign_attributes.
|
|
152
|
+
def create_workflow
|
|
153
|
+
Spree.product_create_workflow
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def update_workflow
|
|
157
|
+
Spree.product_update_workflow
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# The workflow builds its own product, which would leave a seller's
|
|
161
|
+
# listing unowned. Handing it one built through `current_seller.products`
|
|
162
|
+
# keeps the seller on the record, whatever the payload claims.
|
|
163
|
+
def create_workflow_arguments
|
|
164
|
+
super.merge(record: build_resource)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def permitted_params
|
|
168
|
+
attrs = params.permit(
|
|
169
|
+
:name, :description, :slug,
|
|
170
|
+
:meta_title, :meta_description, :meta_keywords,
|
|
171
|
+
:product_type_id, :delivery_profile_id,
|
|
172
|
+
metadata: {},
|
|
173
|
+
prices: [:amount, :compare_at_amount, :currency],
|
|
174
|
+
# Inline media, the same shape the operator sends. `external_url`
|
|
175
|
+
# stays out for the same reason it does there — it would make the
|
|
176
|
+
# server fetch a URL the caller chose.
|
|
177
|
+
media: [*Spree::Media::WRITABLE_ATTRIBUTES, :id, :signed_id, { variant_ids: [] }],
|
|
178
|
+
# A seller's variants. Narrower than the operator's set:
|
|
179
|
+
# `seller_id` would let a payload hand a variant to somebody else,
|
|
180
|
+
# and `tax_category_id`/`delivery_profile_id` are marketplace
|
|
181
|
+
# configuration.
|
|
182
|
+
variants: [
|
|
183
|
+
:id, :sku, :barcode,
|
|
184
|
+
:cost_price, :cost_currency,
|
|
185
|
+
:weight, :height, :width, :depth, :weight_unit, :dimensions_unit,
|
|
186
|
+
:hs_code, :country_of_origin, :customs_description,
|
|
187
|
+
:minimum_order_quantity, :order_multiple, :purchase_unit, :units_per_carton,
|
|
188
|
+
:carton_package_type_id, :carton_weight, :cartons_per_pallet,
|
|
189
|
+
:track_inventory, :preorderable, :preorder_ships_at, :backorder_limit, :position,
|
|
190
|
+
options: [:name, :value],
|
|
191
|
+
prices: [:amount, :compare_at_amount, :currency],
|
|
192
|
+
stock_levels: [:id, :stock_location_id, :count_on_hand, :backorderable]
|
|
193
|
+
]
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Assigned only when present: writing a nil `prices` or
|
|
197
|
+
# `stock_levels` key reaches the association setter as nil, which
|
|
198
|
+
# raises rather than meaning "leave alone".
|
|
199
|
+
attrs[:prices] = default_price_currencies(attrs[:prices]) if attrs.key?(:prices)
|
|
200
|
+
attrs[:product_type_id] = own_product_type_id(attrs[:product_type_id]) if attrs.key?(:product_type_id)
|
|
201
|
+
attrs[:delivery_profile_id] = own_delivery_profile_id(attrs[:delivery_profile_id]) if attrs.key?(:delivery_profile_id)
|
|
202
|
+
|
|
203
|
+
attrs[:variants] = attrs[:variants]&.map do |variant|
|
|
204
|
+
variant = variant.merge(prices: default_price_currencies(variant[:prices])) if variant.key?(:prices)
|
|
205
|
+
variant = variant.merge(stock_levels: own_stock_levels(variant[:stock_levels])) if variant.key?(:stock_levels)
|
|
206
|
+
variant
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
attrs
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# A price the client did not name a currency for is priced in the
|
|
213
|
+
# store's. `Variant#prices=` matches base prices on the currency it is
|
|
214
|
+
# handed and drops the ones missing from the payload, so a guessed
|
|
215
|
+
# currency does not merely add a stray price — it removes the right
|
|
216
|
+
# one. Blank counts as unnamed: an empty form field would otherwise
|
|
217
|
+
# key a price on "".
|
|
218
|
+
def default_price_currencies(prices)
|
|
219
|
+
return prices if prices.blank?
|
|
220
|
+
|
|
221
|
+
prices.map do |price|
|
|
222
|
+
price[:currency].present? ? price : price.merge(currency: Spree::Current.currency)
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# A type or a profile is picked from the marketplace's own list, so
|
|
227
|
+
# the id is resolved against this seller's store here rather than
|
|
228
|
+
# handed to the model: a type from another store would seed its
|
|
229
|
+
# option types onto the product, and a picker value that cannot
|
|
230
|
+
# exist for this seller is a 404, not a validation error. Blank
|
|
231
|
+
# detaches the type; a product always carries a profile, so blank
|
|
232
|
+
# there is left for the model to refuse.
|
|
233
|
+
def own_product_type_id(value)
|
|
234
|
+
return nil if value.blank?
|
|
235
|
+
|
|
236
|
+
current_store.product_types.find_by_prefix_id!(value).id
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
def own_delivery_profile_id(value)
|
|
240
|
+
return nil if value.blank?
|
|
241
|
+
|
|
242
|
+
current_store.delivery_profiles.find_by_prefix_id!(value).id
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
# Stock belongs to the warehouse it sits in, and a seller has their
|
|
246
|
+
# own. `Variant#stock_levels=` resolves a location against the
|
|
247
|
+
# product's *store*, which on a marketplace spans every seller — so a
|
|
248
|
+
# payload naming somebody else's warehouse would write into it. The
|
|
249
|
+
# ids are narrowed to this seller's here, where `current_seller` is
|
|
250
|
+
# known; an id from elsewhere is dropped, matching how the model
|
|
251
|
+
# already skips one it cannot resolve.
|
|
252
|
+
def own_stock_levels(stock_levels)
|
|
253
|
+
return stock_levels if stock_levels.blank?
|
|
254
|
+
|
|
255
|
+
own_ids = current_seller.stock_locations.pluck(:id).to_set
|
|
256
|
+
|
|
257
|
+
stock_levels.select do |level|
|
|
258
|
+
id = Spree::StockLocation.decode_own_prefixed_id(level[:stock_location_id])
|
|
259
|
+
id.present? && own_ids.include?(id)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def collection_includes
|
|
264
|
+
[:default_variant, :primary_media]
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
private
|
|
268
|
+
|
|
269
|
+
# 422s when the caller omits `ids` entirely, matching the operator's
|
|
270
|
+
# bulk endpoints. An explicit empty array is a no-op, which is what a
|
|
271
|
+
# UI whose selection was cleared between render and submit sends.
|
|
272
|
+
def require_ids!
|
|
273
|
+
return if params.key?(:ids)
|
|
274
|
+
|
|
275
|
+
render_error(
|
|
276
|
+
code: 'missing_ids',
|
|
277
|
+
message: 'ids is required (send an empty array to no-op).',
|
|
278
|
+
status: :unprocessable_content
|
|
279
|
+
)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
# The selection, rooted in this seller's own catalog.
|
|
283
|
+
#
|
|
284
|
+
# Deliberately not the shared `BulkOperations#bulk_collection`, which
|
|
285
|
+
# roots at `for_store(current_store)` — on a marketplace that is
|
|
286
|
+
# every seller's catalog, so one seller's ids param would reach
|
|
287
|
+
# another's products. Ids outside this seller's rows are dropped
|
|
288
|
+
# silently, exactly as the operator's endpoints drop ids from
|
|
289
|
+
# another store.
|
|
290
|
+
#
|
|
291
|
+
# @param action [Symbol] the ability action to scope by
|
|
292
|
+
# @return [ActiveRecord::Relation]
|
|
293
|
+
def seller_bulk_scope(action)
|
|
294
|
+
current_seller.products.accessible_by(current_ability, action).
|
|
295
|
+
where(id: decode_bulk_ids(params[:ids]))
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# Runs a status workflow over the selection, one record at a time.
|
|
299
|
+
#
|
|
300
|
+
# A loop rather than `update_all`: each of these moves has side
|
|
301
|
+
# effects the column write does not carry — settling an open
|
|
302
|
+
# submission, announcing the change — and every workflow refuses a
|
|
303
|
+
# product it cannot legally move. A refusal is skipped rather than
|
|
304
|
+
# fatal, so a mixed selection still moves the rows that can move and
|
|
305
|
+
# the response says how many did not
|
|
306
|
+
# (docs/plans/6.0-seller-product-submission.md).
|
|
307
|
+
def run_bulk_workflow(workflow, **arguments)
|
|
308
|
+
render json: run_bulk(seller_bulk_scope(:update)) { |product|
|
|
309
|
+
workflow.call(product: product, **arguments)
|
|
310
|
+
}
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
# Runs a per-record operation over a selection and counts what
|
|
314
|
+
# happened.
|
|
315
|
+
#
|
|
316
|
+
# Each record is rescued on its own. Every one of these workflows
|
|
317
|
+
# opens its own transaction, so a raise partway through leaves the
|
|
318
|
+
# records before it committed — letting it escape would answer a
|
|
319
|
+
# half-done batch with "none of them worked", which is the one
|
|
320
|
+
# description of the outcome that is certainly false. A record that
|
|
321
|
+
# raises is counted as skipped, exactly like one that refused.
|
|
322
|
+
#
|
|
323
|
+
# @return [Hash] the response payload
|
|
324
|
+
def run_bulk(records)
|
|
325
|
+
done = 0
|
|
326
|
+
skipped = 0
|
|
327
|
+
|
|
328
|
+
records.each do |record|
|
|
329
|
+
begin
|
|
330
|
+
bulk_succeeded?(yield(record)) ? done += 1 : skipped += 1
|
|
331
|
+
rescue StandardError => error
|
|
332
|
+
# Surfaced rather than swallowed: a raise here is a bug or a
|
|
333
|
+
# host hook misbehaving, and the count alone would never lead
|
|
334
|
+
# anyone to it.
|
|
335
|
+
Rails.error.report(error, handled: true, context: { product_id: record.id })
|
|
336
|
+
skipped += 1
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
payload = { product_count: done }
|
|
341
|
+
# Only when it happened: a key on every response would tell clients
|
|
342
|
+
# that never skip anything that nothing was skipped.
|
|
343
|
+
payload[:skipped_count] = skipped if skipped.positive?
|
|
344
|
+
payload
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# A block may answer with the workflow's own Result, or with a plain
|
|
348
|
+
# boolean where the caller decides what counts as done by looking at
|
|
349
|
+
# the record rather than the result.
|
|
350
|
+
def bulk_succeeded?(outcome)
|
|
351
|
+
outcome.respond_to?(:success?) ? outcome.success? : !!outcome
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Inbound ids are a mix of prefixed (`prod_…`) and raw.
|
|
355
|
+
#
|
|
356
|
+
# Decoded through the model rather than `PrefixedId` directly, so the
|
|
357
|
+
# prefix class is checked: a `variant_…` id decodes to a bare integer
|
|
358
|
+
# that would otherwise match whichever product happens to carry it.
|
|
359
|
+
# A mismatched prefix drops out and matches nothing, which is what a
|
|
360
|
+
# mistyped id should do. Raw ids pass through for callers that send
|
|
361
|
+
# them.
|
|
362
|
+
def decode_bulk_ids(ids)
|
|
363
|
+
Array(ids).filter_map do |id|
|
|
364
|
+
next id unless Spree::PrefixedId.prefixed_id?(id)
|
|
365
|
+
|
|
366
|
+
model_class.decode_own_prefixed_id(id)
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# Named apart from the base class's own resource lookup: overriding
|
|
371
|
+
# that one changes every action, and these three are the only ones
|
|
372
|
+
# that move a status.
|
|
373
|
+
def set_status_resource
|
|
374
|
+
@resource = find_resource
|
|
375
|
+
# A status move is a change to the product, so it needs the write
|
|
376
|
+
# key rather than one of its own — a read-only seller role cannot
|
|
377
|
+
# submit, take down or archive.
|
|
378
|
+
authorize!(:update, @resource)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def run_status_workflow(workflow, **arguments)
|
|
382
|
+
result = workflow.call(product: @resource, **arguments)
|
|
383
|
+
|
|
384
|
+
if result.success?
|
|
385
|
+
render json: serialize_resource(@resource.reload)
|
|
386
|
+
else
|
|
387
|
+
render_service_error(@resource.errors.presence || result.error)
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
end
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Seller
|
|
5
|
+
# The seller's own record, as they maintain it.
|
|
6
|
+
#
|
|
7
|
+
# Singular by nature: there is exactly one seller in play, and it is
|
|
8
|
+
# `current_seller` — never an id from the request. A seller cannot
|
|
9
|
+
# address another seller here even by guessing one.
|
|
10
|
+
#
|
|
11
|
+
# What they may change is presentation, contact and addresses. Absent
|
|
12
|
+
# by design: `status` (the lifecycle belongs to the operator's
|
|
13
|
+
# workflows), the settlement and tax configuration, and `slug` — a
|
|
14
|
+
# seller renaming their own storefront address breaks every link
|
|
15
|
+
# pointing at it.
|
|
16
|
+
class ProfileController < Seller::BaseController
|
|
17
|
+
# A singular resource, so this extends the plain base rather than
|
|
18
|
+
# ResourceController — which is where the params normalizer lives.
|
|
19
|
+
include Spree::Api::V3::ParamsNormalizer
|
|
20
|
+
|
|
21
|
+
scoped_resource :seller_profile
|
|
22
|
+
|
|
23
|
+
def show
|
|
24
|
+
render json: serialize_seller
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def update
|
|
28
|
+
attributes = permitted_params.merge(terms_attributes)
|
|
29
|
+
# `normalize_params` rewrites `custom_fields` to the nested-attributes
|
|
30
|
+
# key. Narrow it, then hand it back under the original name: the
|
|
31
|
+
# model's `custom_fields=` upserts by definition, while the nested
|
|
32
|
+
# writer builds a row every time — so a seller correcting a value
|
|
33
|
+
# they had already saved would hit the uniqueness index instead.
|
|
34
|
+
if attributes.key?(:custom_fields_attributes)
|
|
35
|
+
attributes[:custom_fields] =
|
|
36
|
+
requested_custom_fields(attributes.delete(:custom_fields_attributes))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
current_seller.update!(attributes)
|
|
40
|
+
|
|
41
|
+
render json: serialize_seller
|
|
42
|
+
rescue ActiveRecord::RecordInvalid => error
|
|
43
|
+
render_validation_error(error.record.errors)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
protected
|
|
47
|
+
|
|
48
|
+
# The params normalizer resolves nested attributes against this.
|
|
49
|
+
def model_class
|
|
50
|
+
Spree::Seller
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def read_actions
|
|
54
|
+
%w[show]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Enumerated rather than borrowing the legacy global list, which
|
|
58
|
+
# permits :id, :user_id and :deleted_at.
|
|
59
|
+
# Accepting the marketplace's terms is a profile write, not an endpoint
|
|
60
|
+
# of its own: `accept_terms: true` stamps the time, which is what the
|
|
61
|
+
# AcceptTerms requirement reads.
|
|
62
|
+
#
|
|
63
|
+
# Re-stamped every time rather than only on a first acceptance: a
|
|
64
|
+
# marketplace that rewrites its terms advances the requirement's
|
|
65
|
+
# `terms_effective_from`, which puts everyone who accepted before
|
|
66
|
+
# that date back on the checklist — and a seller who could not
|
|
67
|
+
# re-accept would be stuck there with nothing to click.
|
|
68
|
+
#
|
|
69
|
+
# One-way all the same: sending `false` is a no-op, because the
|
|
70
|
+
# stamp records that acceptance happened.
|
|
71
|
+
def terms_attributes
|
|
72
|
+
return {} unless ActiveModel::Type::Boolean.new.cast(params[:accept_terms])
|
|
73
|
+
|
|
74
|
+
{ terms_accepted_at: Time.current }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# One registration per kind, so re-sending a kind corrects the number
|
|
78
|
+
# rather than stacking a second row the model would reject.
|
|
79
|
+
#
|
|
80
|
+
# A changed number drops its verdict — the validator's answer was
|
|
81
|
+
# about the old one, and carrying it over would show a number as
|
|
82
|
+
# verified that nobody has checked.
|
|
83
|
+
# Narrowed to the definitions this marketplace's onboarding actually
|
|
84
|
+
# asks this seller for.
|
|
85
|
+
#
|
|
86
|
+
# Custom fields on `Spree::Seller` are the operator's schema, and
|
|
87
|
+
# some of them are the operator's own — an internal risk note, a
|
|
88
|
+
# compliance flag. A seller may fill in what they were asked for;
|
|
89
|
+
# permitting the association wholesale would let them write, and
|
|
90
|
+
# then read back, every field the operator defined.
|
|
91
|
+
def requested_custom_fields(submitted)
|
|
92
|
+
return [] if submitted.blank?
|
|
93
|
+
|
|
94
|
+
allowed = Spree::SellerRequirementCustomField.
|
|
95
|
+
joins(:seller_requirement).
|
|
96
|
+
where(Spree::SellerRequirement.table_name => {
|
|
97
|
+
store_id: current_store.id, active: true
|
|
98
|
+
}).
|
|
99
|
+
pluck(:custom_field_definition_id).to_set
|
|
100
|
+
|
|
101
|
+
Array(submitted).select do |field|
|
|
102
|
+
allowed.include?(field[:custom_field_definition_id])
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def permitted_params
|
|
107
|
+
normalize_params(
|
|
108
|
+
params.permit(:name, :contact_email, :billing_email, :about,
|
|
109
|
+
:legal_name, :registration_number,
|
|
110
|
+
:logo, :square_logo, :cover_photo,
|
|
111
|
+
billing_address: Spree::Api::V3::AddressParams::ADDRESS_KEYS,
|
|
112
|
+
custom_fields: [:id, :custom_field_definition_id, :value,
|
|
113
|
+
{ value: [] }, { value: {} }])
|
|
114
|
+
)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
private
|
|
118
|
+
|
|
119
|
+
def serialize_seller
|
|
120
|
+
Spree.api.seller_profile_serializer.new(
|
|
121
|
+
current_seller.reload,
|
|
122
|
+
params: { store: current_store, expand: expand_list }
|
|
123
|
+
).to_h
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# This controller is not a ResourceController, so it does not get the
|
|
127
|
+
# shared `expand` plumbing — without this the serializer's optional
|
|
128
|
+
# associations (the seller's policies) are unreachable here whatever
|
|
129
|
+
# the client asks for.
|
|
130
|
+
def expand_list
|
|
131
|
+
params[:expand].to_s.split(',').map(&:strip)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Api
|
|
3
|
+
module V3
|
|
4
|
+
module Seller
|
|
5
|
+
# A marketplace-owned vocabulary a seller picks from — why goods came
|
|
6
|
+
# back, or what went wrong with a delivery.
|
|
7
|
+
#
|
|
8
|
+
# Read-only, because the vocabulary is the operator's to define: a
|
|
9
|
+
# seller chooses a reason, never adds one. Gated by `orders` rather
|
|
10
|
+
# than `settings` — a seller reads these to fill in a form on their own
|
|
11
|
+
# order, and `settings` is closed to the seller audience entirely.
|
|
12
|
+
#
|
|
13
|
+
# Store-scoped rather than seller-scoped, since these are the store's
|
|
14
|
+
# own rows. Retired reasons are left out so a seller cannot file
|
|
15
|
+
# against vocabulary the operator has withdrawn.
|
|
16
|
+
#
|
|
17
|
+
# Subclasses name the model and the association to read it through.
|
|
18
|
+
class ReasonsController < Seller::ResourceController
|
|
19
|
+
scoped_resource :orders
|
|
20
|
+
|
|
21
|
+
protected
|
|
22
|
+
|
|
23
|
+
def serializer_class
|
|
24
|
+
Spree.api.seller_reason_serializer
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def read_actions
|
|
28
|
+
%w[index]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def scope
|
|
32
|
+
current_store.public_send(reasons_association).active
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# The store association holding this vocabulary.
|
|
36
|
+
#
|
|
37
|
+
# @return [Symbol]
|
|
38
|
+
def reasons_association
|
|
39
|
+
raise NotImplementedError
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|