diff --git a/admin/app/components/solidus_admin/payment_methods/edit/component.html.erb b/admin/app/components/solidus_admin/payment_methods/edit/component.html.erb new file mode 100644 index 00000000000..c299cf773e0 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/edit/component.html.erb @@ -0,0 +1,12 @@ +<%= page id: :resource_form do %> + <%= page_header do %> + <%= page_header_back(back_url) %> + <%= page_header_title(t(".title")) %> + <%= page_header_actions do %> + <%= render component("ui/button").discard(path: back_url) %> + <%= render component("ui/button").save(form: form_id) %> + <% end %> + <% end %> + + <%= render component("payment_methods/form").new(payment_method: @resource, url: solidus_admin.payment_method_path(@resource), form_id:) %> +<% end %> diff --git a/admin/app/components/solidus_admin/payment_methods/edit/component.rb b/admin/app/components/solidus_admin/payment_methods/edit/component.rb new file mode 100644 index 00000000000..909c32b26da --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/edit/component.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class SolidusAdmin::PaymentMethods::Edit::Component < SolidusAdmin::Resources::Edit::Component + include SolidusAdmin::Layout::PageHelpers + + def back_url = solidus_admin.payment_methods_path +end diff --git a/admin/app/components/solidus_admin/payment_methods/edit/component.yml b/admin/app/components/solidus_admin/payment_methods/edit/component.yml new file mode 100644 index 00000000000..49390bdfcd6 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/edit/component.yml @@ -0,0 +1,2 @@ +en: + title: "Edit Payment Method" diff --git a/admin/app/components/solidus_admin/payment_methods/form/component.html.erb b/admin/app/components/solidus_admin/payment_methods/form/component.html.erb new file mode 100644 index 00000000000..92e5260415d --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/form/component.html.erb @@ -0,0 +1,27 @@ +<%= solidus_form_for @payment_method, as: "payment_method", url: @url, html: { id: @form_id } do |f| %> + <%= page_with_sidebar do %> + <%= page_with_sidebar_main do %> + <%= render component("ui/panel").new do %> + <%= f.text_field :name %> + <%= f.text_field :description %> + <%= f.switch_field :auto_capture, hint: t(".hints.autocapture").html_safe %> + <% end %> + + <%= render component("ui/panel").new(title: t(".deployment")) do %> + <%= f.select :type, available_types.map { [_1.model_name.human, _1.to_s] } %> + <%= f.select :preference_source, available_preference_sources, include_blank: t(".preference_source_none") %> + <%= f.text_field :preferred_server %> + <%= f.switch_field :preferred_test_mode, hint: t(".hints.test_mode").html_safe %> + <% end %> + <% end %> + + <%= page_with_sidebar_aside do %> + <%= render component("ui/panel").new(title: t(".availability")) do %> + <%= f.checkbox :active %> + <%= f.select :store_ids, store_select_values, multiple: true %> + <%= f.checkbox :available_to_admin %> + <%= f.checkbox :available_to_users %> + <% end %> + <% end %> + <% end %> +<% end %> diff --git a/admin/app/components/solidus_admin/payment_methods/form/component.rb b/admin/app/components/solidus_admin/payment_methods/form/component.rb new file mode 100644 index 00000000000..5c937dd2b79 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/form/component.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class SolidusAdmin::PaymentMethods::Form::Component < SolidusAdmin::BaseComponent + include SolidusAdmin::Layout::PageHelpers + + def initialize(payment_method:, url:, form_id:) + @payment_method = payment_method + @url = url + @form_id = form_id + end + + def available_preference_sources + Spree::PaymentMethod.available_preference_sources + end + + def available_types + Rails.application.config.spree.payment_methods.sort_by(&:name) + end + + def store_select_values + Spree::Store.pluck(:name, :id) + end +end diff --git a/admin/app/components/solidus_admin/payment_methods/form/component.yml b/admin/app/components/solidus_admin/payment_methods/form/component.yml new file mode 100644 index 00000000000..97e8ed8b578 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/form/component.yml @@ -0,0 +1,11 @@ +en: + availability: "Availability" + deployment: "Deployment" + hints: + autocapture: >- +

Auto-capture setting charges customer's account upon transaction authorization.

+

Enable to reduce manual intervention and streamline the payment process.

+ test_mode: >- +

Payment methods test mode allows users to simulate transactions using dummy data, ensuring the payment gateway's functionality without real transactions.

+

In test mode, users can check if payment methods, such as credit cards or digital wallets, are functioning correctly before going live with real transactions.

+ preference_source_none: "Custom" diff --git a/admin/app/components/solidus_admin/payment_methods/index/component.rb b/admin/app/components/solidus_admin/payment_methods/index/component.rb index aadf5f08487..2cf57219657 100644 --- a/admin/app/components/solidus_admin/payment_methods/index/component.rb +++ b/admin/app/components/solidus_admin/payment_methods/index/component.rb @@ -13,8 +13,8 @@ def search_url solidus_admin.payment_methods_path end - def row_url(payment_method) - spree.edit_admin_payment_method_path(payment_method) + def edit_path(payment_method) + solidus_admin.edit_payment_method_path(payment_method) end def sortable_options @@ -28,7 +28,7 @@ def page_actions render component("ui/button").new( tag: :a, text: t(".add"), - href: spree.new_admin_payment_method_path, + href: solidus_admin.new_payment_method_path, icon: "add-line" ) end @@ -39,7 +39,8 @@ def batch_actions label: t(".batch_actions.delete"), action: solidus_admin.payment_methods_path, method: :delete, - icon: "delete-bin-7-line" + icon: "delete-bin-7-line", + require_confirmation: true } ] end @@ -59,13 +60,13 @@ def columns { header: :name, data: ->(payment_method) do - content_tag :div, payment_method.name + link_to payment_method.name, edit_path(payment_method), class: "body-link" end }, { header: :type, data: ->(payment_method) do - content_tag :div, payment_method.model_name.human + link_to payment_method.model_name.human, edit_path(payment_method), class: "body-link" end }, { diff --git a/admin/app/components/solidus_admin/payment_methods/new/component.html.erb b/admin/app/components/solidus_admin/payment_methods/new/component.html.erb new file mode 100644 index 00000000000..32c6fe90029 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/new/component.html.erb @@ -0,0 +1,12 @@ +<%= page id: :resource_form do %> + <%= page_header do %> + <%= page_header_back(back_url) %> + <%= page_header_title(t(".title")) %> + <%= page_header_actions do %> + <%= render component("ui/button").discard(path: back_url) %> + <%= render component("ui/button").save(form: form_id) %> + <% end %> + <% end %> + + <%= render component("payment_methods/form").new(payment_method: @resource, url: solidus_admin.payment_methods_path, form_id:) %> +<% end %> diff --git a/admin/app/components/solidus_admin/payment_methods/new/component.rb b/admin/app/components/solidus_admin/payment_methods/new/component.rb new file mode 100644 index 00000000000..8ad6be786d7 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/new/component.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class SolidusAdmin::PaymentMethods::New::Component < SolidusAdmin::Resources::New::Component + include SolidusAdmin::Layout::PageHelpers + + def back_url = solidus_admin.payment_methods_path +end diff --git a/admin/app/components/solidus_admin/payment_methods/new/component.yml b/admin/app/components/solidus_admin/payment_methods/new/component.yml new file mode 100644 index 00000000000..176ffc14cc0 --- /dev/null +++ b/admin/app/components/solidus_admin/payment_methods/new/component.yml @@ -0,0 +1,2 @@ +en: + title: "New Payment Method" diff --git a/admin/app/controllers/solidus_admin/payment_methods_controller.rb b/admin/app/controllers/solidus_admin/payment_methods_controller.rb index cb2b213003b..36db482a969 100644 --- a/admin/app/controllers/solidus_admin/payment_methods_controller.rb +++ b/admin/app/controllers/solidus_admin/payment_methods_controller.rb @@ -1,8 +1,7 @@ # frozen_string_literal: true module SolidusAdmin - class PaymentMethodsController < SolidusAdmin::BaseController - include SolidusAdmin::ControllerHelpers::Search + class PaymentMethodsController < SolidusAdmin::ResourcesController include SolidusAdmin::Moveable search_scope(:all) @@ -11,26 +10,17 @@ class PaymentMethodsController < SolidusAdmin::BaseController search_scope(:storefront, &:available_to_users) search_scope(:admin, &:available_to_admin) - def index - payment_methods = apply_search_to( - Spree::PaymentMethod.ordered_by_position, - param: :q - ) + private - set_page_and_extract_portion_from(payment_methods) + def resource_class = Spree::PaymentMethod - respond_to do |format| - format.html { render component("payment_methods/index").new(page: @page) } - end - end - - def destroy - @payment_methods = Spree::PaymentMethod.where(id: params[:id]) + def resources_collection = resource_class.all - Spree::PaymentMethod.transaction { @payment_methods.destroy_all } + def resources_sorting_options = {position: :asc} - flash[:notice] = t(".success") - redirect_back_or_to payment_methods_path, status: :see_other + def permitted_resource_params + params.require(:payment_method).permit(:name, :description, :auto_capture, :type, :preference_source, + :preferred_server, :preferred_test_mode, :active, :available_to_admin, :available_to_users, store_ids: []) end end end diff --git a/admin/config/locales/payment_methods.en.yml b/admin/config/locales/payment_methods.en.yml index c9b1308e35e..53ef2fc2c00 100644 --- a/admin/config/locales/payment_methods.en.yml +++ b/admin/config/locales/payment_methods.en.yml @@ -2,5 +2,9 @@ en: solidus_admin: payment_methods: title: "Payment Methods" + create: + success: "Payment method was successfully created." destroy: - success: "Payment Methods were successfully removed." + success: "Payment methods were successfully removed." + update: + success: "Payment method was successfully updated." diff --git a/admin/config/routes.rb b/admin/config/routes.rb index 4234dc6af3e..8e565deb1e3 100644 --- a/admin/config/routes.rb +++ b/admin/config/routes.rb @@ -47,6 +47,11 @@ end end + admin_resources :payment_methods, + constraints: -> { SolidusAdmin::Config.enable_alpha_features? }, + except: [:show], + sortable: true + admin_resources :users, only: [:index, :edit, :destroy] do member do get :addresses @@ -77,7 +82,6 @@ admin_resources :promotion_categories, only: [:index, :destroy] admin_resources :tax_categories, except: [:show] admin_resources :tax_rates, except: [:show] - admin_resources :payment_methods, only: [:index, :destroy], sortable: true admin_resources :stock_items, only: [:index, :edit, :update] admin_resources :shipping_methods, only: [:index, :destroy] admin_resources :shipping_categories, except: [:show] diff --git a/admin/spec/components/solidus_admin/payment_methods/form/component_spec.rb b/admin/spec/components/solidus_admin/payment_methods/form/component_spec.rb new file mode 100644 index 00000000000..457f8251602 --- /dev/null +++ b/admin/spec/components/solidus_admin/payment_methods/form/component_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe SolidusAdmin::PaymentMethods::Form::Component, type: :component do + let(:component) { + described_class.new payment_method: create(:payment_method), + url: "/test-url", + form_id: "test-form-id" + } + + describe "#available_preference_sources" do + subject { component.available_preference_sources } + + it "requests available sources from Spree::PaymentMethod" do + allow(Spree::PaymentMethod).to receive(:available_preference_sources) + + subject + + expect(Spree::PaymentMethod) + .to have_received(:available_preference_sources) + .once + end + end + + describe ".available_types" do + subject { component.available_types } + + let(:fake_payment_methods_set) { + Spree::Core::ClassConstantizer::Set.new( + default: [ + "Spree::PaymentMethod::CreditCard", + "Spree::PaymentMethod::Check" + ] + ) + } + let(:fake_subconfig) { double(payment_methods: fake_payment_methods_set) } + + before do + allow(Rails.application) + .to receive(:config) + .and_return(double(spree: fake_subconfig)) + end + + it "requests available payment method types from the Rails application configuration", :aggregate_failures do + subject + + expect(Rails.application).to have_received(:config).once + expect(fake_subconfig).to have_received(:payment_methods).once + end + + it "sorts the available payment method types by name" do + expect(subject).to eq [ + Spree::PaymentMethod::Check, + Spree::PaymentMethod::CreditCard + ] + end + end + + describe "#store_select_values" do + subject { component.store_select_values } + + let!(:store) { create :store, name: "Selectable Store" } + + it "gets all store name and IDs for a form