Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Admin] Introduce RMA reasons creation & modification capability #5829

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Create refund reasons via new admin UI modal
Co-authored-by: Chris Todorov <[email protected]>
Co-authored-by: Kendra Riga <[email protected]>
  • Loading branch information
3 people committed Aug 16, 2024
commit 00869ecf08576f57c46d9e2b87fa963ee7d99f08
Original file line number Diff line number Diff line change
@@ -17,6 +17,23 @@ def row_url(return_reason)
spree.edit_admin_return_reason_path(return_reason)
end

def turbo_frames
%w[
new_return_reason_modal
]
end

def page_actions
render component("ui/button").new(
tag: :a,
text: t('.add'),
href: solidus_admin.new_return_reason_path,
data: { turbo_frame: :new_return_reason_modal },
icon: "add-line",
class: "align-self-end w-full",
)
end

def batch_actions
[
{
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<%= turbo_frame_tag :new_return_reason_modal do %>
<%= render component("ui/modal").new(title: t(".title")) do |modal| %>
<%= form_for @return_reason, url: solidus_admin.return_reasons_path, html: { id: form_id } do |f| %>
<div class="flex flex-col gap-6 pb-4">
<%= render component("ui/forms/field").text_field(f, :name, class: "required") %>
<label class="flex gap-2 items-center">
<%= hidden_field_tag "#{f.object_name}[active]", "0" %>
<%= render component("ui/forms/checkbox").new(
name: "#{f.object_name}[active]",
value: "1",
checked: f.object.active
) %>
<span class="font-semibold text-xs ml-2"><%= Spree::ReturnReason.human_attribute_name :active %></span>
<%= render component("ui/toggletip").new(text: t(".hints.active")) %>
</label>
</div>
<% modal.with_actions do %>
<form method="dialog">
<%= render component("ui/button").new(scheme: :secondary, text: t('.cancel')) %>
</form>
<%= render component("ui/button").new(form: form_id, type: :submit, text: t('.submit')) %>
<% end %>
<% end %>
<% end %>
<% end %>

<%= render component("return_reasons/index").new(page: @page) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class SolidusAdmin::ReturnReasons::New::Component < SolidusAdmin::BaseComponent
def initialize(page:, return_reason:)
@page = page
@return_reason = return_reason
end

def form_id
dom_id(@return_reason, "#{stimulus_id}_new_return_reason_form")
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Add your component translations here.
# Use the translation in the example in your template with `t(".hello")`.
en:
title: "New Return Reason"
cancel: "Cancel"
submit: "Add Return Reason"
hints:
active: "When checked, this return reason will be available for selection when returning orders."
Original file line number Diff line number Diff line change
@@ -4,19 +4,52 @@ module SolidusAdmin
class ReturnReasonsController < SolidusAdmin::BaseController
include SolidusAdmin::ControllerHelpers::Search

def index
return_reasons = apply_search_to(
Spree::ReturnReason.unscoped.order(id: :desc),
param: :q,
)

set_page_and_extract_portion_from(return_reasons)
def index
set_index_page

respond_to do |format|
format.html { render component('return_reasons/index').new(page: @page) }
end
end

def new
@return_reason = Spree::ReturnReason.new

set_index_page

respond_to do |format|
format.html { render component('return_reasons/new').new(page: @page, return_reason: @return_reason) }
end
end

def create
@return_reason = Spree::ReturnReason.new(return_reason_params)

if @return_reason.save
respond_to do |format|
flash[:notice] = t('.success')

format.html do
redirect_to solidus_admin.return_reasons_path, status: :see_other
end

format.turbo_stream do
render turbo_stream: '<turbo-stream action="refresh" />'
end
end
else
set_index_page

respond_to do |format|
format.html do
page_component = component('return_reasons/new').new(page: @page, return_reason: @return_reason)
render page_component, status: :unprocessable_entity
end
end
end
end

def destroy
@return_reason = Spree::ReturnReason.find_by!(id: params[:id])

@@ -28,8 +61,21 @@ def destroy

private

def find_return_reason
@return_reason = Spree::ReturnReason.find(params[:id])
end

def set_index_page
return_reasons = apply_search_to(
Spree::ReturnReason.unscoped.order(id: :desc),
param: :q,
)

set_page_and_extract_portion_from(return_reasons)
end

def return_reason_params
params.require(:return_reason).permit(:return_reason_id, permitted_return_reason_attributes)
params.require(:return_reason).permit(:name, :active)
end
end
end
4 changes: 3 additions & 1 deletion admin/config/locales/return_reasons.en.yml
Original file line number Diff line number Diff line change
@@ -3,4 +3,6 @@ en:
return_reasons:
title: "Return Reasons"
destroy:
success: "Return Reasons were successfully removed."
success: "Return reasons were successfully removed."
create:
success: "Return reason was successfully created."
2 changes: 1 addition & 1 deletion admin/config/routes.rb
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@
admin_resources :zones, only: [:index, :destroy]
admin_resources :refund_reasons, except: [:show]
admin_resources :reimbursement_types, only: [:index]
admin_resources :return_reasons, only: [:index, :destroy]
admin_resources :return_reasons, only: [:index, :destroy, :new, :create]
admin_resources :adjustment_reasons, except: [:show]
admin_resources :store_credit_reasons, except: [:show]
end
43 changes: 42 additions & 1 deletion admin/spec/features/return_reasons_spec.rb
Original file line number Diff line number Diff line change
@@ -14,9 +14,50 @@

select_row("Default-return-reason")
click_on "Delete"
expect(page).to have_content("Return Reasons were successfully removed.")
expect(page).to have_content("Return reasons were successfully removed.")
expect(page).not_to have_content("Default-return-reason")
expect(Spree::ReturnReason.count).to eq(0)
expect(page).to be_axe_clean
end

context "when creating a new return reason" do
let(:query) { "?page=1&q%5Bname_cont%5D=new" }

before do
visit "/admin/return_reasons#{query}"
click_on "Add new"
expect(page).to have_content("New Return Reason")
expect(page).to be_axe_clean
end

it "opens a modal" do
expect(page).to have_selector("dialog")
within("dialog") { click_on "Cancel" }
expect(page).not_to have_selector("dialog")
expect(page.current_url).to include(query)
end

context "with valid data" do
it "successfully creates a new return reason, keeping page and q params" do
fill_in "Name", with: "New Reason"
page.uncheck "return_reason[active]"

click_on "Add Return Reason"

expect(page).to have_content("Return reason was successfully created.")
expect(Spree::ReturnReason.find_by(name: "New Reason")).to be_present
expect(Spree::ReturnReason.find_by(name: "New Reason").active).to be_falsey
expect(page.current_url).to include(query)
end
end

context "with invalid data" do
it "fails to create a new return reason, keeping page and q params" do
click_on "Add Return Reason"

expect(page).to have_content("can't be blank")
expect(page.current_url).to include(query)
end
end
end
end
84 changes: 84 additions & 0 deletions admin/spec/requests/solidus_admin/return_reasons_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe "SolidusAdmin::ReturnReasonsController", type: :request do
let(:admin_user) { create(:admin_user) }
let(:return_reason) { create(:return_reason) }

before do
allow_any_instance_of(SolidusAdmin::BaseController).to receive(:spree_current_user).and_return(admin_user)
end

describe "GET /index" do
it "renders the index template with a 200 OK status" do
get solidus_admin.return_reasons_path
expect(response).to have_http_status(:ok)
end
end

describe "GET /new" do
it "renders the new template with a 200 OK status" do
get solidus_admin.new_return_reason_path
expect(response).to have_http_status(:ok)
end
end

describe "POST /create" do
context "with valid parameters" do
let(:valid_attributes) { { name: "Damaged item", active: true } }

it "creates a new ReturnReason" do
expect {
post solidus_admin.return_reasons_path, params: { return_reason: valid_attributes }
}.to change(Spree::ReturnReason, :count).by(1)
end

it "redirects to the index page with a 303 See Other status" do
post solidus_admin.return_reasons_path, params: { return_reason: valid_attributes }
expect(response).to redirect_to(solidus_admin.return_reasons_path)
expect(response).to have_http_status(:see_other)
end

it "displays a success flash message" do
post solidus_admin.return_reasons_path, params: { return_reason: valid_attributes }
follow_redirect!
expect(response.body).to include("Return reason was successfully created.")
end
end

context "with invalid parameters" do
let(:invalid_attributes) { { name: "" } }

it "does not create a new ReturnReason" do
expect {
post solidus_admin.return_reasons_path, params: { return_reason: invalid_attributes }
}.not_to change(Spree::ReturnReason, :count)
end

it "renders the new template with unprocessable_entity status" do
post solidus_admin.return_reasons_path, params: { return_reason: invalid_attributes }
expect(response).to have_http_status(:unprocessable_entity)
end
end
end

describe "DELETE /destroy" do
let!(:return_reason_to_delete) { create(:return_reason) }

it "deletes the return reason and redirects to the index page with a 303 See Other status" do
expect {
delete solidus_admin.return_reason_path(return_reason_to_delete)
}.to change(Spree::ReturnReason, :count).by(-1)

expect(response).to redirect_to(solidus_admin.return_reasons_path)
expect(response).to have_http_status(:see_other)
end

it "displays a success flash message after deletion" do
delete solidus_admin.return_reason_path(return_reason_to_delete)
follow_redirect!
expect(response.body).to include("Return reasons were successfully removed.")
end
end
end