Skip to content

Commit 11ba41f

Browse files
5280 combine same items save (#5285)
* creates confirmation modal for transfers and sums up items * call combine! on line_items to merge duplicates * tests the merging of same items in modal and controller * fixes linting * fixes flakey capybara test * updates transfer markdown documentation with new confirmation modal info * fixes erb lint * fixes wording on inventory_transfers md * fixes unused test context
1 parent 180edd2 commit 11ba41f

File tree

9 files changed

+173
-16
lines changed

9 files changed

+173
-16
lines changed

app/controllers/transfers_controller.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def index
2121

2222
def create
2323
@transfer = current_organization.transfers.new(transfer_params)
24+
@transfer.line_items.combine!
2425

2526
TransferCreateService.call(@transfer)
2627
redirect_to transfers_path, notice: "#{@transfer.line_items.total} items have been transferred from #{@transfer.from.name} to #{@transfer.to.name}!"
@@ -57,6 +58,18 @@ def destroy
5758
redirect_to transfers_path
5859
end
5960

61+
def validate
62+
@transfer = current_organization.transfers.new(transfer_params)
63+
@transfer.line_items.combine!
64+
65+
if @transfer.valid?
66+
body = render_to_string(partial: "transfers/validate_modal", formats: [:html], layout: false)
67+
render json: {valid: true, body: body}
68+
else
69+
render json: {valid: false}, status: :unprocessable_entity
70+
end
71+
end
72+
6073
private
6174

6275
def load_form_collections
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<div class="modal-dialog modal-lg">
2+
<div class="modal-content">
3+
<div class="modal-header">
4+
<h5 class="modal-title">Transfer Confirmation</h5>
5+
<button id="modalClose" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
6+
</div>
7+
<div class="modal-body" style="max-height: 60vh; overflow-y: auto;">
8+
<%# Items and quantities %>
9+
<table class="table">
10+
<thead>
11+
<tr>
12+
<th>Item Name</th>
13+
<th>Total Items</th>
14+
</tr>
15+
</thead>
16+
<tbody>
17+
<% @transfer.line_items.each do |line_item| %>
18+
<tr>
19+
<td><%= line_item.name %></td>
20+
<td><%= line_item.quantity %></td>
21+
</tr>
22+
<% end %>
23+
</tbody>
24+
</table>
25+
26+
<% if @transfer.comment.present? %>
27+
<p><strong>Note:</strong> <%= @transfer.comment %></p>
28+
<% end %>
29+
30+
<%# Confirmation message %>
31+
<div class="message fs-5">
32+
<p>Please confirm that the above list is what you meant to transfer and that the comment is correct.</p>
33+
</div>
34+
</div>
35+
36+
<%# Actions %>
37+
<div class="modal-footer">
38+
<button id="modalNo" type="button" class="btn btn-secondary" data-bs-dismiss="modal" aria-label="No I need to make changes">No, I need to make changes</button>
39+
<button id="modalYes" type="button" class="btn btn-success" data-action="confirmation#submitForm">Yes, it's correct</button>
40+
</div>
41+
</div>
42+
</div>

app/views/transfers/new.html.erb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
<!-- left column -->
2929
<div class="col-md-12">
3030
<!-- jquery validation -->
31-
<div class="card card-primary">
31+
<div class="card card-primary"
32+
data-controller="confirmation"
33+
data-confirmation-pre-check-path-value="<%= validate_transfers_path(format: :json) %>">
3234
<!-- /.card-header -->
3335
<!-- form start -->
3436
<div class="card-body">
@@ -39,10 +41,9 @@
3941
storage location to another.</p>
4042
</div>
4143
<div class="box-body">
42-
4344
<%= simple_form_for @transfer,
44-
data: { controller: "form-input" },
45-
html: { class: "storage-location-required", id: 'new_transfer' } do |f| %>
45+
data: { controller: "form-input", confirmation_target: "form" },
46+
html: { class: "storage-location-required", id: "new_transfer" } do |f| %>
4647
<%= render partial: "storage_locations/source", object: f, locals: {label: "From storage location", error: "Which location are you moving inventory from?", association_field: :from} %>
4748

4849
<%= f.association :to,
@@ -69,10 +70,19 @@
6970

7071
</div>
7172
<div class="card-footer">
72-
<%= submit_button %>
73+
<%= submit_button({}, { action: "click->confirmation#openModal" }) %>
7374
</div>
7475
<% end %>
7576
</div>
77+
<div
78+
id="transferConfirmationModal"
79+
class="modal confirm"
80+
aria-labelledby="transferConfirmationModal"
81+
aria-hidden="true"
82+
tabindex="-1"
83+
data-bs-backdrop="static"
84+
data-confirmation-target="modal">
85+
</div>
7686
</div><!-- /.box -->
7787
</div>
7888
</div>

config/routes.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,9 @@ def set_up_flipper
119119
get :activity_graph
120120
end
121121

122-
resources :transfers, only: %i(index create new show destroy)
122+
resources :transfers, only: %i(index create new show destroy) do
123+
post :validate, on: :collection
124+
end
123125

124126
resources :storage_locations do
125127
put :deactivate
360 KB
Loading

docs/user_guide/bank/inventory_transfers.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ The Comment field is a good place to note the reason for the Transfer, but you c
2020

2121
Then select the Item and quantity for each Item that is being Transferred. If you have [barcodes](inventory_barcodes.md) set up, you can use your barcode reader to "boop" in the materials being Transferred.
2222

23-
When you are done, click "Save". The system will check that you have enough inventory in "From" to cover the Transfer. If so, the inventory changes will take place immediately.
23+
When you are done, click "Save". If so, a confirmation modal will pop up. Review the contents of the transfer and click the 'Yes, it's correct' button to begin the transfer. The system will check that you have enough inventory in "From" to cover the Transfer before the inventory changes take place.
24+
![Transfer Modal](images/inventory/inventory_transfers_confirmation_modal.png)
2425

2526
## Viewing the details of a Transfer
2627
To view the details of a Transfer, click the "view" button beside it in the Transfers list.

spec/controllers/transfers_controller_spec.rb

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,31 @@
4343
end
4444

4545
describe "POST #create" do
46+
context 'when duplicate line_items with different quantities submitted' do
47+
let!(:item1) { create(:item) }
48+
let(:params) {
49+
attributes_for(
50+
:transfer,
51+
organization_id: organization.id,
52+
to_id: create(:storage_location, organization: organization).id,
53+
from_id: create(:storage_location, organization: organization).id,
54+
line_items_attributes: {
55+
"0" => { item_id: item1.id, quantity: 2 },
56+
"1" => { item_id: item1.id, quantity: 3 }
57+
}
58+
)
59+
}
60+
61+
it "merges same line_items id items into one quantity" do
62+
post :create, params: { transfer: params }
63+
64+
transfer = assigns(:transfer)
65+
66+
expect(transfer.line_items.size).to eq 1
67+
expect(transfer.line_items.first.quantity).to eq 5
68+
end
69+
end
70+
4671
it "redirects to #show when successful" do
4772
attributes = attributes_for(
4873
:transfer,
@@ -76,6 +101,34 @@
76101
expect(subject).to be_successful
77102
end
78103
end
104+
105+
describe "POST #validate" do
106+
context 'when duplicate line_items with different quantities submitted' do
107+
let!(:item1) { create(:item) }
108+
let(:params) {
109+
attributes_for(
110+
:transfer,
111+
organization_id: organization.id,
112+
to_id: create(:storage_location, organization: organization).id,
113+
from_id: create(:storage_location, organization: organization).id,
114+
line_items_attributes: {
115+
"0" => { item_id: item1.id, quantity: 2 },
116+
"1" => { item_id: item1.id, quantity: 3 }
117+
}
118+
)
119+
}
120+
121+
it "merges same line_items id items into one quantity" do
122+
post :validate, params: { transfer: params }
123+
124+
transfer = assigns(:transfer)
125+
126+
expect(transfer.line_items.size).to eq 1
127+
expect(transfer.line_items.first.quantity).to eq 5
128+
end
129+
end
130+
end
131+
79132
context "Looking at a different organization" do
80133
let(:object) do
81134
org = create(:organization)

spec/system/distribution_system_spec.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -348,11 +348,13 @@
348348

349349
it "the user can make changes" do
350350
click_on "Edit", match: :first
351-
expect do
352-
fill_in "Agency representative", with: "SOMETHING DIFFERENT"
353-
click_on "Save", match: :first
354-
distribution.reload
355-
end.to change { distribution.agency_rep }.to("SOMETHING DIFFERENT")
351+
fill_in "Agency representative", with: "SOMETHING DIFFERENT"
352+
click_on "Save", match: :first
353+
# Make Capybara wait for events to finish before checking Db.
354+
expect(page).to have_content("SOMETHING DIFFERENT")
355+
356+
distribution.reload
357+
expect(distribution.agency_rep).to eq("SOMETHING DIFFERENT")
356358
end
357359

358360
it "sends an email if reminders are enabled" do

spec/system/transfer_system_spec.rb

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
end
99
let(:item) { create(:item) }
1010

11-
def create_transfer(amount, from_name, to_name)
11+
def create_transfer(amount, from_name, to_name, click_save: true, click_confirm: true)
1212
visit transfers_path
1313
click_link "New Transfer"
1414
within "form#new_transfer" do
@@ -18,13 +18,47 @@ def create_transfer(amount, from_name, to_name)
1818
select item.name, from: "transfer_line_items_attributes_0_item_id"
1919
fill_in "transfer_line_items_attributes_0_quantity", with: amount
2020
end
21-
click_on "Save"
21+
click_on "Save" if click_save
22+
click_on "Yes, it's correct" if click_save && click_confirm
23+
end
24+
25+
context "when transfer submitted" do
26+
it "shows the confirmation page" do
27+
from_storage_location = create(:storage_location, :with_items, item: item, name: "From me", organization: organization)
28+
to_storage_location = create(:storage_location, :with_items, name: "To me", organization: organization)
29+
create_transfer("10", from_storage_location.name, to_storage_location.name, click_confirm: false)
30+
31+
expect(page).to have_content("Transfer Confirmation")
32+
expect(page).to have_content("Please confirm that the above list is what you meant to transfer and that the comment is correct.")
33+
expect(page).to have_content("No, I need to make changes")
34+
expect(page).to have_content("Yes, it's correct")
35+
end
36+
37+
it "merges same items into one quantity" do
38+
from_storage_location = create(:storage_location, :with_items, item: item, name: "From me", organization: organization)
39+
to_storage_location = create(:storage_location, :with_items, name: "To me", organization: organization)
40+
41+
create_transfer("10", from_storage_location.name, to_storage_location.name, click_save: false, click_confirm: false)
42+
# grabs the dynamically generated new item
43+
click_on "Add Another Item"
44+
new_select = all("select[id$='_item_id']").last
45+
select_id = new_select[:id]
46+
select item.name, from: select_id
47+
index = select_id[/attributes_(\d+)_item_id$/, 1]
48+
quantity_field_id = "transfer_line_items_attributes_#{index}_quantity"
49+
fill_in quantity_field_id, with: "30"
50+
51+
click_on "Save"
52+
53+
expect(page).to have_content("40")
54+
end
2255
end
2356

2457
it "can transfer an inventory from a storage location to another as a user" do
2558
from_storage_location = create(:storage_location, :with_items, item: item, name: "From me", organization: organization)
2659
to_storage_location = create(:storage_location, :with_items, name: "To me", organization: organization)
2760
create_transfer("10", from_storage_location.name, to_storage_location.name)
61+
2862
expect(page).to have_content("10 items have been transferred")
2963
end
3064

@@ -96,7 +130,7 @@ def create_transfer(amount, from_name, to_name)
96130
# 4438 - Bug Fix
97131
it "add item button should be activated when from storage location is selected after rendering again on failure" do
98132
from_storage_location = create(:storage_location, :with_items, item: item, name: "From me", organization: organization)
99-
create_transfer('', '', '')
133+
create_transfer('', '', '', click_confirm: false)
100134
select from_storage_location.name, from: "From storage location"
101135
expect(page).not_to have_css("#__add_line_item.disabled")
102136
end
@@ -106,7 +140,7 @@ def create_transfer(amount, from_name, to_name)
106140
let!(:to_storage_location) { create(:storage_location, :with_items, name: "To me", organization: organization) }
107141

108142
scenario "User can transfer an inventory from a storage location to another" do
109-
create_transfer("100", from_storage_location.name, to_storage_location.name)
143+
create_transfer("100", from_storage_location.name, to_storage_location.name, click_confirm: false)
110144
expect(page).to have_content("insufficient inventory")
111145
end
112146
end

0 commit comments

Comments
 (0)