From 704ad63527dda16444b6d24409fcb29629b532d7 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 12 Jul 2024 16:42:57 -0400 Subject: [PATCH 01/57] #4398: Support units in requests --- .../partners/requests_controller.rb | 6 ++- .../controllers/item_units_controller.js | 40 +++++++++++++++++++ .../partners/request_create_service.rb | 1 + .../partners/requests/_item_request.html.erb | 16 +++++++- app/views/partners/requests/new.html.erb | 7 +++- ..._backfill_partner_child_requested_items.rb | 2 + 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 app/javascript/controllers/item_units_controller.js diff --git a/app/controllers/partners/requests_controller.rb b/app/controllers/partners/requests_controller.rb index eec3c8cf4a..014f48fbd7 100644 --- a/app/controllers/partners/requests_controller.rb +++ b/app/controllers/partners/requests_controller.rb @@ -12,6 +12,10 @@ def new @partner_request.item_requests.build @requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.id).call + # hash of (item ID => hash of (request unit name => request unit plural name)) + @item_units = current_partner.organization.items.to_h do |i| + [i.id, i.request_units.to_h { |u| [u.name, u.name.pluralize] }] + end end def show @@ -44,7 +48,7 @@ def create private def partner_request_params - params.require(:request).permit(:comments, item_requests_attributes: [:item_id, :quantity]) + params.require(:request).permit(:comments, item_requests_attributes: [:item_id, :quantity, :request_unit]) end end end diff --git a/app/javascript/controllers/item_units_controller.js b/app/javascript/controllers/item_units_controller.js new file mode 100644 index 0000000000..d964f364b0 --- /dev/null +++ b/app/javascript/controllers/item_units_controller.js @@ -0,0 +1,40 @@ +import { Controller } from "@hotwired/stimulus"; + +// Connects to data-controller="form-input" +export default class extends Controller { + static targets = ["itemSelect", "requestSelect"] + static values = { + // hash of (item ID => hash of (request unit name => request unit plural name)) + "itemUnits": Object + } + + addOption(val, text, selected) { + let option = document.createElement("option"); + option.value = val; + option.text = text; + if (selected) { + option.selected = true; + } + this.requestSelectTarget.appendChild(option); + } + + clearOptions() { + while (this.requestSelectTarget.options.length > 0) { + this.requestSelectTarget.remove(this.requestSelectTarget.options[0]) + } + } + + itemSelected() { + if (!this.hasRequestSelectTarget) { + return; + } + let option = this.itemSelectTarget.options[this.itemSelectTarget.selectedIndex] + let units = this.itemUnitsValue[option.value] + this.clearOptions() + this.addOption('', 'Units') + for (const [index, [name, displayName]] of Object.entries(Object.entries(units))) { + this.addOption(name, displayName, index === "0") + } + } + +} diff --git a/app/services/partners/request_create_service.rb b/app/services/partners/request_create_service.rb index 8df880ebbf..df1b5ecf6c 100644 --- a/app/services/partners/request_create_service.rb +++ b/app/services/partners/request_create_service.rb @@ -71,6 +71,7 @@ def populate_item_request(partner_request) else items[input_item['item_id']] = Partners::ItemRequest.new( item_id: input_item['item_id'], + request_unit: input_item['request_unit'], quantity: input_item['quantity'], children: input_item['children'] || [], # will create ChildItemRequests if there are any name: fetch_organization_item_name(input_item['item_id']), diff --git a/app/views/partners/requests/_item_request.html.erb b/app/views/partners/requests/_item_request.html.erb index bcb6bdcc17..595f0851e5 100644 --- a/app/views/partners/requests/_item_request.html.erb +++ b/app/views/partners/requests/_item_request.html.erb @@ -1,13 +1,25 @@ <%= form.fields_for :item_requests, defined?(object) ? object : nil do |field| %> - + <%= field.label :item_id, "Item Requested", {class: 'sr-only'} %> - <%= field.select :item_id, @requestable_items, {include_blank: 'Select an item'}, {class: 'form-control'} %> + <%= field.select :item_id, @requestable_items, {include_blank: 'Select an item'}, + data: { :'item-units-target' => 'itemSelect', + action: 'change->item-units#itemSelected', + class: 'form-control' } %> <%= field.label :quantity, "Quantity", {class: 'sr-only'} %> <%= field.number_field :quantity, label: false, step: 1, min: 1, class: 'form-control' %> + + <% if current_partner.organization.request_units.any? %> + + <%= field.label :request_unit, "Unit", {class: 'sr-only'} %> + <%= field.select :request_unit, [], {include_blank: 'Units'}, + { :'data-item-units-target' => 'requestSelect', class: 'form-control'} %> + + + <% end %> <%= remove_element_button "Remove", container_selector: "tr" %> diff --git a/app/views/partners/requests/new.html.erb b/app/views/partners/requests/new.html.erb index c25ee9e3d2..c973b6df6f 100644 --- a/app/views/partners/requests/new.html.erb +++ b/app/views/partners/requests/new.html.erb @@ -39,15 +39,18 @@ Item Requested Quantity + <% if current_partner.organization.request_units.any? %> + Units (if applicable) + <% end %> - <%= render 'item_request', form: form %> + <%= render partial: 'item_request', locals: { form: form, item_units: @item_units } %>
<%= add_element_button('Add Another Item', container_selector: '.fields') do %> - <%= render 'item_request', form: form, object: @partner_request.item_requests.build %> + <%= render partial: 'item_request', locals: { form: form, item_units: @item_units }, object: @partner_request.item_requests.build %> <% end %>
diff --git a/db/migrate/20240704214509_backfill_partner_child_requested_items.rb b/db/migrate/20240704214509_backfill_partner_child_requested_items.rb index 9e4cdba70d..dc6443933e 100644 --- a/db/migrate/20240704214509_backfill_partner_child_requested_items.rb +++ b/db/migrate/20240704214509_backfill_partner_child_requested_items.rb @@ -1,5 +1,7 @@ class BackfillPartnerChildRequestedItems < ActiveRecord::Migration[7.1] def change + return unless Rails.env.production? + Partners::Child.unscoped.where.not(item_needed_diaperid: nil).each do |child| child.requested_items << Item.find_by(id: child.item_needed_diaperid) end From ab8315c13616b0e1251fa94c5e22b7729ca65207 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 12 Jul 2024 16:44:34 -0400 Subject: [PATCH 02/57] fix style --- app/views/partners/requests/_item_request.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/partners/requests/_item_request.html.erb b/app/views/partners/requests/_item_request.html.erb index 595f0851e5..aa4576d5f0 100644 --- a/app/views/partners/requests/_item_request.html.erb +++ b/app/views/partners/requests/_item_request.html.erb @@ -4,8 +4,8 @@ <%= field.label :item_id, "Item Requested", {class: 'sr-only'} %> <%= field.select :item_id, @requestable_items, {include_blank: 'Select an item'}, data: { :'item-units-target' => 'itemSelect', - action: 'change->item-units#itemSelected', - class: 'form-control' } %> + action: 'change->item-units#itemSelected'}, + class: 'form-control' %> <%= field.label :quantity, "Quantity", {class: 'sr-only'} %> From 895c9806d988ec4234aad0a5184c3bcb24a9e964 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 12 Jul 2024 16:50:25 -0400 Subject: [PATCH 03/57] fixes --- .../controllers/item_units_controller.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/javascript/controllers/item_units_controller.js b/app/javascript/controllers/item_units_controller.js index d964f364b0..3a063f4caf 100644 --- a/app/javascript/controllers/item_units_controller.js +++ b/app/javascript/controllers/item_units_controller.js @@ -24,16 +24,26 @@ export default class extends Controller { } } + connect() { + this.itemSelected(); + } + itemSelected() { if (!this.hasRequestSelectTarget) { return; } let option = this.itemSelectTarget.options[this.itemSelectTarget.selectedIndex] let units = this.itemUnitsValue[option.value] - this.clearOptions() - this.addOption('', 'Units') - for (const [index, [name, displayName]] of Object.entries(Object.entries(units))) { - this.addOption(name, displayName, index === "0") + if (!units || Object.keys(units).length === 0) { + this.requestSelectTarget.style.display = 'none'; + } + else { + this.requestSelectTarget.style.display = 'inline'; + this.clearOptions() + this.addOption('', 'Units') + for (const [index, [name, displayName]] of Object.entries(Object.entries(units))) { + this.addOption(name, displayName, index === "0") + } } } From 9b929c45f8899b09eb64ba16e13e8e516029e0cf Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 19 Jul 2024 16:57:25 -0400 Subject: [PATCH 04/57] Add specs --- spec/requests/partners/requests_spec.rb | 3 + spec/system/partners/requests_system_spec.rb | 66 ++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 spec/system/partners/requests_system_spec.rb diff --git a/spec/requests/partners/requests_spec.rb b/spec/requests/partners/requests_spec.rb index ca4b2995ff..ddd6423810 100644 --- a/spec/requests/partners/requests_spec.rb +++ b/spec/requests/partners/requests_spec.rb @@ -100,6 +100,7 @@ item_requests_attributes: { "0" => { item_id: item1.id, + request_unit: 'pack', quantity: Faker::Number.within(range: 4..13) } } @@ -109,6 +110,8 @@ before do sign_in(partner_user) + FactoryBot.create(:unit, organization: organization, name: 'pack') + FactoryBot.create(:item_unit, item: item1, name: 'pack') end context 'when given valid parameters' do diff --git a/spec/system/partners/requests_system_spec.rb b/spec/system/partners/requests_system_spec.rb new file mode 100644 index 0000000000..fc3ace9f19 --- /dev/null +++ b/spec/system/partners/requests_system_spec.rb @@ -0,0 +1,66 @@ +RSpec.describe "Partners profile served area behaviour", type: :system, js: true do + let(:organization) { create(:organization) } + let(:partner) { create(:partner, organization: organization) } + let(:partner_user) { partner.primary_user } + + before(:each) do + sign_in(partner_user) + end + + describe "GET #index" do + let!(:item1) { FactoryBot.create(:item, organization: organization, name: "Item 1") } + let!(:item2) { FactoryBot.create(:item, organization: organization, name: "Item 2") } + before(:each) do + FactoryBot.create(:item_unit, name: "pack", item: item1) + end + + context "with packs off" do + before(:each) do + Flipper.disable(:enable_packs) + end + + it "should not show packs on selection" do + visit new_partners_request_path + select "Item 1", from: "request_item_requests_attributes_0_item_id" + expect(page).not_to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) + end + end + + context "with packs on" do + before(:each) do + Flipper.enable(:enable_packs) + end + + it "should show packs on selection" do + visit new_partners_request_path + expect(Request.count).to eq(0) + expect(page).not_to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) + select "Item 1", from: "request_item_requests_attributes_0_item_id" + expect(page).to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) + expect(page).to have_select("request_item_requests_attributes_0_request_unit", selected: "packs", options: ["Units", "packs"]) + select "packs", from: "request_item_requests_attributes_0_request_unit" + click_on "Add Another Item" + + # get selector to use in subsequent steps + new_item = find_all(:css, "select[data-item-units-target=itemSelect]")[1] + id = new_item[:id].match(/\d+/)[0] + + expect(page).not_to have_selector("request_item_requests_attributes_#{id}_request_unit", visible: true) + select "Item 2", from: "request_item_requests_attributes_#{id}_item_id" + expect(page).not_to have_selector("request_item_requests_attributes_#{id}_request_unit", visible: true) + fill_in "request_item_requests_attributes_0_quantity", with: 50 + fill_in "request_item_requests_attributes_#{id}_quantity", with: 20 + click_on "Submit Essentials Request" + + expect(Request.count).to eq(1) + request = Request.last + expect(request.item_requests[0].quantity).to eq("50") + expect(request.item_requests[0].item_id).to eq(item1.id) + expect(request.item_requests[0].request_unit).to eq("pack") + expect(request.item_requests[1].quantity).to eq("20") + expect(request.item_requests[1].item_id).to eq(item2.id) + expect(request.item_requests[1].request_unit).to eq("") + end + end + end +end From 3529e4c505bb9be9df00edb9e7ace7b04a62516b Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 26 Jul 2024 15:45:15 -0400 Subject: [PATCH 05/57] Fix error case --- app/controllers/partners/requests_controller.rb | 6 ++++++ app/javascript/controllers/item_units_controller.js | 1 + 2 files changed, 7 insertions(+) diff --git a/app/controllers/partners/requests_controller.rb b/app/controllers/partners/requests_controller.rb index bce7c84102..66c185422c 100644 --- a/app/controllers/partners/requests_controller.rb +++ b/app/controllers/partners/requests_controller.rb @@ -40,6 +40,12 @@ def create @errors = create_service.errors @requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.id).call + if Flipper.enabled?(:enable_packs) + # hash of (item ID => hash of (request unit name => request unit plural name)) + @item_units = current_partner.organization.items.to_h do |i| + [i.id, i.request_units.to_h { |u| [u.name, u.name.pluralize] }] + end + end Rails.logger.info("[Request Creation Failure] partner_user_id=#{current_user.id} reason=#{@errors.full_messages}") diff --git a/app/javascript/controllers/item_units_controller.js b/app/javascript/controllers/item_units_controller.js index 3a063f4caf..07b6334a0e 100644 --- a/app/javascript/controllers/item_units_controller.js +++ b/app/javascript/controllers/item_units_controller.js @@ -36,6 +36,7 @@ export default class extends Controller { let units = this.itemUnitsValue[option.value] if (!units || Object.keys(units).length === 0) { this.requestSelectTarget.style.display = 'none'; + this.requestSelectTarget.selectedIndex = -1; } else { this.requestSelectTarget.style.display = 'inline'; From e043ede3547aabf047aa2e751e79c3819cf08922 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 2 Aug 2024 09:57:34 -0400 Subject: [PATCH 06/57] Fix test --- spec/system/partners/requests_system_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/system/partners/requests_system_spec.rb b/spec/system/partners/requests_system_spec.rb index fc3ace9f19..cc6c608ad4 100644 --- a/spec/system/partners/requests_system_spec.rb +++ b/spec/system/partners/requests_system_spec.rb @@ -59,7 +59,7 @@ expect(request.item_requests[0].request_unit).to eq("pack") expect(request.item_requests[1].quantity).to eq("20") expect(request.item_requests[1].item_id).to eq(item2.id) - expect(request.item_requests[1].request_unit).to eq("") + expect(request.item_requests[1].request_unit).to eq(nil) end end end From cf069cc3cd64bea206b46a5241b848a2b5df2690 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 26 Jul 2024 17:05:56 -0400 Subject: [PATCH 07/57] 4403: Show units in new/edit distribution --- app/assets/stylesheets/application.scss | 27 ++++ app/controllers/distributions_controller.rb | 2 + app/models/concerns/itemizable.rb | 2 +- app/models/distribution.rb | 37 +++++- app/models/line_item.rb | 4 + app/views/distributions/_form.html.erb | 11 +- .../line_items/_line_item_fields.html.erb | 30 ++++- spec/factories/items.rb | 9 ++ spec/factories/requests.rb | 1 + spec/requests/distributions_requests_spec.rb | 122 +++++++++++++++++- 10 files changed, 229 insertions(+), 16 deletions(-) diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index d2ee0e734a..74c027ce0e 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -192,3 +192,30 @@ div.low_priority_warning { margin: 5px; text-align: center; } + +.distribution-title { + display: flex; +} + +legend.with-request { + float: none; + width: 80%; + display: inline-block; +} + +div.distribution-request-unit { + display: inline-block; + flex: 1; + text-align: right; + margin-right: 20px; + font-size: 1.5em; +} + +.li-requested { + font-size: 1.5em; + width: 100px; + min-width: 100px; + text-align: right; + margin-right: 20px; + white-space: nowrap; +} diff --git a/app/controllers/distributions_controller.rb b/app/controllers/distributions_controller.rb index e2a10393a9..9365cc85da 100644 --- a/app/controllers/distributions_controller.rb +++ b/app/controllers/distributions_controller.rb @@ -166,6 +166,7 @@ def show def edit @distribution = Distribution.includes(:line_items).includes(:storage_location).find(params[:id]) + @distribution.initialize_request_items if (!@distribution.complete? && @distribution.future?) || current_user.has_role?(Role::ORG_ADMIN, current_organization) @distribution.line_items.build if @distribution.line_items.size.zero? @@ -202,6 +203,7 @@ def update else flash[:error] = insufficient_error_message(result.error.message) @distribution.line_items.build if @distribution.line_items.size.zero? + @distribution.initialize_request_items @items = current_organization.items.alphabetized @storage_locations = current_organization.storage_locations.active_locations.alphabetized render :edit diff --git a/app/models/concerns/itemizable.rb b/app/models/concerns/itemizable.rb index 9248238f8b..9b34d257a3 100644 --- a/app/models/concerns/itemizable.rb +++ b/app/models/concerns/itemizable.rb @@ -96,7 +96,7 @@ def total_value has_many :items, through: :line_items accepts_nested_attributes_for :line_items, allow_destroy: true, - reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank? } + reject_if: proc { |l| l[:item_id].blank? } has_many :item_categories, through: :items diff --git a/app/models/distribution.rb b/app/models/distribution.rb index f8d591e25b..8423e0b798 100644 --- a/app/models/distribution.rb +++ b/app/models/distribution.rb @@ -102,6 +102,31 @@ def copy_from_donation(donation_id, storage_location_id) self.storage_location = StorageLocation.find(storage_location_id) if storage_location_id end + # This is meant for the Edit page - we will be adding any request items that aren't in the + # distribution for whatever reason, with zero quantity. + def initialize_request_items + return if request.nil? + + item_ids = Set.new + line_items.each do |line_item| + item_request = request.item_requests.find { |r| r.item_id == line_item.item_id } + if item_request + item_ids.add(item_request) + line_item.requested_item = item_request + end + end + + request.item_requests.each do |item_request| + next if item_ids.include?(item_request) + + line_items.new( + requested_item: item_request, + quantity: 0, + item_id: item_request.item_id + ) + end + end + def copy_from_request(request_id) request = Request.find(request_id) self.request = request @@ -110,12 +135,12 @@ def copy_from_request(request_id) self.agency_rep = request.partner_user&.formatted_email self.comment = request.comments self.issued_at = Time.zone.today + 1.day - request.request_items.each do |item| + request.item_requests.each do |item_request| line_items.new( - quantity: item["quantity"], - item: Item.eager_load(:base_item).find_by(organization: request.organization, id: item["item_id"]), - itemizable_id: request.id, - itemizable_type: "Distribution" + requested_item: item_request, + # if there is a custom unit, don't prefill with the quantity - they have to enter it + quantity: item_request.request_unit.present? ? nil : item_request.quantity, + item_id: item_request.item_id ) end end @@ -148,7 +173,7 @@ def past? private def line_items_quantity_is_positive - line_items_quantity_is_at_least(1) + line_items_quantity_is_at_least(0) end def reset_shipping_cost diff --git a/app/models/line_item.rb b/app/models/line_item.rb index e93a52e047..8cdcb79b7c 100644 --- a/app/models/line_item.rb +++ b/app/models/line_item.rb @@ -28,6 +28,10 @@ class LineItem < ApplicationRecord delegate :name, to: :item + # Used in a distribution that was initialized from a request. The `item_request` will be + # populated here. + attr_accessor :requested_item + def quantity_must_be_a_number_within_range if quantity && quantity > MAX_INT errors.add(:quantity, "must be less than #{MAX_INT}") diff --git a/app/views/distributions/_form.html.erb b/app/views/distributions/_form.html.erb index 2948b48d6c..b72329f950 100644 --- a/app/views/distributions/_form.html.erb +++ b/app/views/distributions/_form.html.erb @@ -33,13 +33,18 @@ <%= f.input :comment, label: "Comment" %>
- Items in this distribution +
+ Items in this distribution + <% if distribution.request %> +
Requested
+ <% end %> +
- <%= render 'line_items/line_item_fields', form: f %> + <%= render 'line_items/line_item_fields', form: f, locals: { show_request_items: true } %>
diff --git a/app/views/line_items/_line_item_fields.html.erb b/app/views/line_items/_line_item_fields.html.erb index 50721acfe8..5ccb188117 100644 --- a/app/views/line_items/_line_item_fields.html.erb +++ b/app/views/line_items/_line_item_fields.html.erb @@ -1,4 +1,5 @@ <%= form.simple_fields_for :line_items, defined?(object) ? object : nil do |field| %> + <% requested = field.object.requested_item %>
@@ -10,15 +11,34 @@
- <%= field.input :item_id, collection: @items, prompt: "Choose an item", include_blank: "", label: false, input_html: { class: "my-0 line_item_name", "data-controller": "select2" } %> + <%= field.input :item_id, + disabled: requested.present?, + collection: @items, prompt: "Choose an item", + include_blank: "", + label: false, + input_html: { class: "my-0 line_item_name", "data-controller": "select2" } %> + <% if requested.present? %> + <%= field.input :item_id, as: :hidden %> + <% end %>
<%= field.input :quantity, - as: :string, - placeholder: "Quantity", - label: false, - input_html: { class: "quantity my-0", data: { quantity: "" } } %> + as: :string, + placeholder: "Quantity", + label: false, + input_html: { class: "quantity my-0", data: { quantity: "" } } %>
+ <% if form.object.request %> +
+ <% if requested&.request_unit.present? %> + <%= pluralize(requested.quantity, requested.request_unit) %> + <% elsif requested %> + <%= requested.quantity %> + <% else %> + N/A + <% end %> +
+ <% end %>
diff --git a/spec/factories/items.rb b/spec/factories/items.rb index 4104d0872f..919c5e2a27 100644 --- a/spec/factories/items.rb +++ b/spec/factories/items.rb @@ -35,5 +35,14 @@ trait :inactive do active { false } end + + trait :with_unit do + transient do + unit { "pack" } + end + after(:create) do |item, evaluator| + create(:item_unit, name: evaluator.unit, item: item) + end + end end end diff --git a/spec/factories/requests.rb b/spec/factories/requests.rb index b0ddad8e1d..d8cdc20594 100644 --- a/spec/factories/requests.rb +++ b/spec/factories/requests.rb @@ -28,6 +28,7 @@ def random_request_items request_items { random_request_items } comments { "Urgent" } partner_user { ::User.partner_users.first || create(:partner_user) } + item_requests { [] } # For compatibility we can take in a list of request_items and turn it into a # list of item_requests diff --git a/spec/requests/distributions_requests_spec.rb b/spec/requests/distributions_requests_spec.rb index b4adc8fb97..a5b6243cfc 100644 --- a/spec/requests/distributions_requests_spec.rb +++ b/spec/requests/distributions_requests_spec.rb @@ -133,7 +133,19 @@ describe "GET #new" do let!(:partner) { create(:partner, organization: organization) } - let(:request) { create(:request, partner: partner, organization: organization) } + let(:request) { create(:request, partner: partner, organization: organization, item_requests: item_requests) } + let(:items) { + [ + create(:item, :with_unit, organization: organization, name: 'Item 1', unit: 'pack'), + create(:item, organization: organization, name: 'Item 2') + ] + } + let(:item_requests) { + [ + create(:item_request, item: items[0], quantity: 50, request_unit: 'pack'), + create(:item_request, item: items[1], quantity: 25) + ] + } let(:storage_location) { create(:storage_location, :with_items, organization: organization) } let(:default_params) { { request_id: request.id } } @@ -166,6 +178,44 @@ expect(page.css(%(#distribution_storage_location_id option[selected][value="#{storage_location.id}"]))).not_to be_empty end end + + context 'with units' do + before(:each) do + Flipper.enable(:enable_packs) + end + + it 'should behave correctly' do + get new_distribution_path(default_params) + expect(response).to be_successful + page = Nokogiri::HTML(response.body) + + # should have a disabled select and a hidden input + expect(page.css('select[disabled][name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + expect(page.css('input[name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + expect(page.css('select[disabled][name="distribution[line_items_attributes][1][item_id]"]')).not_to be_empty + expect(page.css('input[name="distribution[line_items_attributes][1][item_id]"]')).not_to be_empty + + # input with packs should be blank + expect(page.css('#distribution_line_items_attributes_0_quantity').attr('value')).to eq(nil) + + # input with no packs should show quantity + expect(page.css('#distribution_line_items_attributes_1_quantity').attr('value').value).to eq('25') + end + + context 'with no request' do + it 'should have no inputs' do + get new_distribution_path({}) + expect(response).to be_successful + page = Nokogiri::HTML(response.body) + + # blank input shown + expect(page.css('select[name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + expect(page.css('#distribution_line_items_attributes_0_quantity').attr('value')).to eq(nil) + # in the template + expect(page.css('select[name="distribution[line_items_attributes][1][item_id]"]')).not_to be_empty + end + end + end end describe "GET #show" do @@ -414,6 +464,76 @@ expect(response.body).not_to include("You’ve had an audit since this distribution was started.") end + context 'with units' do + let!(:request) { + create(:request, + partner: partner, + organization: organization, + distribution_id: distribution.id, + item_requests: item_requests) + } + let(:items) { + [ + create(:item, :with_unit, organization: organization, name: 'Item 1', unit: 'pack'), + create(:item, organization: organization, name: 'Item 2'), + create(:item, organization: organization, name: 'Item 3') + ] + } + let!(:item_requests) { + [ + create(:item_request, item: items[0], quantity: 50, request_unit: 'pack'), + create(:item_request, item: items[1], quantity: 25) + ] + } + before(:each) do + Flipper.enable(:enable_packs) + create(:line_item, itemizable: distribution, item_id: items[0].id, quantity: 25) + create(:line_item, itemizable: distribution, item_id: items[2].id, quantity: 10) + end + + it 'should behave correctly' do + get edit_distribution_path(id: distribution.id) + expect(response).to be_successful + page = Nokogiri::HTML(response.body) + + # should have a regular select and no hidden input + expect(page.css('select[disabled][name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + expect(page.css('input[name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + + # should have a regular select and no hidden input + expect(page.css('select[name="distribution[line_items_attributes][1][item_id]"]')).not_to be_empty + expect(page.css('select[disabled][name="distribution[line_items_attributes][1][item_id]"]')).to be_empty + expect(page.css('input[name="distribution[line_items_attributes][1][item_id]"]')).to be_empty + + # should have a disabled select and a hidden input + expect(page.css('select[disabled][name="distribution[line_items_attributes][2][item_id]"]')).not_to be_empty + expect(page.css('input[name="distribution[line_items_attributes][2][item_id]"]')).not_to be_empty + + # existing inputs should show numbers + expect(page.css('#distribution_line_items_attributes_0_quantity').attr('value').value).to eq('25') + expect(page.css('#distribution_line_items_attributes_1_quantity').attr('value').value).to eq('10') + + # input from request should show 0 + expect(page.css('#distribution_line_items_attributes_2_quantity').attr('value').value).to eq('0') + end + + context 'with no request' do + it 'should have everything enabled' do + request.destroy + get edit_distribution_path(id: distribution.id) + expect(response).to be_successful + page = Nokogiri::HTML(response.body) + + expect(page.css('select[name="distribution[line_items_attributes][0][item_id]"]')).not_to be_empty + expect(page.css('select[disabled][name="distribution[line_items_attributes][0][item_id]"]')).to be_empty + expect(page.css('input[name="distribution[line_items_attributes][0][item_id]"]')).to be_empty + expect(page.css('select[name="distribution[line_items_attributes][1][item_id]"]')).not_to be_empty + expect(page.css('select[disabled][name="distribution[line_items_attributes][1][item_id]"]')).to be_empty + expect(page.css('input[name="distribution[line_items_attributes][1][item_id]"]')).to be_empty + end + end + end + # Bug fix #4537 context "when distribution sets storage location total inventory to zero" do let(:item1) { create(:item, name: "Item 1", organization: organization) } From 5cd237a12d46b1814b0605d913d715b683301c5c Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 9 Aug 2024 16:39:11 -0400 Subject: [PATCH 08/57] put this back --- app/models/concerns/itemizable.rb | 2 +- app/models/distribution.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/concerns/itemizable.rb b/app/models/concerns/itemizable.rb index 9b34d257a3..71b7e7c728 100644 --- a/app/models/concerns/itemizable.rb +++ b/app/models/concerns/itemizable.rb @@ -96,7 +96,7 @@ def total_value has_many :items, through: :line_items accepts_nested_attributes_for :line_items, allow_destroy: true, - reject_if: proc { |l| l[:item_id].blank? } + reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank? || l[:quantity].to_i.zero? } has_many :item_categories, through: :items diff --git a/app/models/distribution.rb b/app/models/distribution.rb index 8423e0b798..bc5a652e9f 100644 --- a/app/models/distribution.rb +++ b/app/models/distribution.rb @@ -173,7 +173,7 @@ def past? private def line_items_quantity_is_positive - line_items_quantity_is_at_least(0) + line_items_quantity_is_at_least(1) end def reset_shipping_cost From 803f8b0ee163e0151758dc2cad8e6ecf17072f12 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 9 Aug 2024 16:53:01 -0400 Subject: [PATCH 09/57] do this here --- app/models/concerns/itemizable.rb | 2 +- app/services/distribution_update_service.rb | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/models/concerns/itemizable.rb b/app/models/concerns/itemizable.rb index 71b7e7c728..5d13779d8c 100644 --- a/app/models/concerns/itemizable.rb +++ b/app/models/concerns/itemizable.rb @@ -96,7 +96,7 @@ def total_value has_many :items, through: :line_items accepts_nested_attributes_for :line_items, allow_destroy: true, - reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank? || l[:quantity].to_i.zero? } + reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank?} has_many :item_categories, through: :items diff --git a/app/services/distribution_update_service.rb b/app/services/distribution_update_service.rb index 5889d2a622..741a9336fc 100644 --- a/app/services/distribution_update_service.rb +++ b/app/services/distribution_update_service.rb @@ -9,6 +9,9 @@ def call perform_distribution_service do @old_issued_at = distribution.issued_at @old_delivery_method = distribution.delivery_method + @params[:line_items_attributes].delete_if { |_, a| a[:quantity].to_i.zero?} + + # remove line_items with zero quantity ItemizableUpdateService.call( itemizable: distribution, From c4c37361117d39550ccd4477fee3e14df04bd355 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 9 Aug 2024 16:54:57 -0400 Subject: [PATCH 10/57] null safe --- app/services/distribution_update_service.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/distribution_update_service.rb b/app/services/distribution_update_service.rb index 741a9336fc..39d83d5594 100644 --- a/app/services/distribution_update_service.rb +++ b/app/services/distribution_update_service.rb @@ -9,7 +9,7 @@ def call perform_distribution_service do @old_issued_at = distribution.issued_at @old_delivery_method = distribution.delivery_method - @params[:line_items_attributes].delete_if { |_, a| a[:quantity].to_i.zero?} + @params[:line_items_attributes]&.delete_if { |_, a| a[:quantity].to_i.zero?} # remove line_items with zero quantity From 73fa7cb252e753dbd9db9f461ea2ebcdbb329248 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 9 Aug 2024 17:08:22 -0400 Subject: [PATCH 11/57] more fixes --- app/models/concerns/itemizable.rb | 2 +- app/services/distribution_update_service.rb | 2 +- app/views/line_items/_line_item_fields.html.erb | 2 +- spec/models/distribution_spec.rb | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/models/concerns/itemizable.rb b/app/models/concerns/itemizable.rb index 5d13779d8c..9248238f8b 100644 --- a/app/models/concerns/itemizable.rb +++ b/app/models/concerns/itemizable.rb @@ -96,7 +96,7 @@ def total_value has_many :items, through: :line_items accepts_nested_attributes_for :line_items, allow_destroy: true, - reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank?} + reject_if: proc { |l| l[:item_id].blank? || l[:quantity].blank? } has_many :item_categories, through: :items diff --git a/app/services/distribution_update_service.rb b/app/services/distribution_update_service.rb index 39d83d5594..da612d0f95 100644 --- a/app/services/distribution_update_service.rb +++ b/app/services/distribution_update_service.rb @@ -9,7 +9,7 @@ def call perform_distribution_service do @old_issued_at = distribution.issued_at @old_delivery_method = distribution.delivery_method - @params[:line_items_attributes]&.delete_if { |_, a| a[:quantity].to_i.zero?} + @params[:line_items_attributes]&.delete_if { |_, a| a[:quantity].to_i.zero? } # remove line_items with zero quantity diff --git a/app/views/line_items/_line_item_fields.html.erb b/app/views/line_items/_line_item_fields.html.erb index 5ccb188117..840568a43d 100644 --- a/app/views/line_items/_line_item_fields.html.erb +++ b/app/views/line_items/_line_item_fields.html.erb @@ -28,7 +28,7 @@ label: false, input_html: { class: "quantity my-0", data: { quantity: "" } } %>
- <% if form.object.request %> + <% if form.object.respond_to?(:request) && form_object.request %>
<% if requested&.request_unit.present? %> <%= pluralize(requested.quantity, requested.request_unit) %> diff --git a/spec/models/distribution_spec.rb b/spec/models/distribution_spec.rb index bd47938136..5cdab500de 100644 --- a/spec/models/distribution_spec.rb +++ b/spec/models/distribution_spec.rb @@ -250,11 +250,9 @@ item2 = create(:item, name: "Item2", organization: organization) request = create(:request, organization: organization, - partner_user: create(:partner_user), - request_items: [ - { item_id: item1.id, quantity: 15 }, - { item_id: item2.id, quantity: 18 } - ]) + partner_user: create(:partner_user)) + create(:item_request, request: request, item_id: item1.id, quantity: 15) + create(:item_request, request: request, item_id: item2.id, quantity: 18) distribution = Distribution.new distribution.copy_from_request(request.id) expect(distribution.line_items.size).to eq 2 From db0d89ce47075e9209b406ef90d7b59d149a38b3 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 9 Aug 2024 17:35:04 -0400 Subject: [PATCH 12/57] aw man --- app/views/line_items/_line_item_fields.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/line_items/_line_item_fields.html.erb b/app/views/line_items/_line_item_fields.html.erb index 840568a43d..fe7f27b132 100644 --- a/app/views/line_items/_line_item_fields.html.erb +++ b/app/views/line_items/_line_item_fields.html.erb @@ -28,7 +28,7 @@ label: false, input_html: { class: "quantity my-0", data: { quantity: "" } } %>
- <% if form.object.respond_to?(:request) && form_object.request %> + <% if form.object.respond_to?(:request) && form.object.request %>
<% if requested&.request_unit.present? %> <%= pluralize(requested.quantity, requested.request_unit) %> From f69ea5bd5526ad3ea498b181e8e50554714568af Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 11 Aug 2024 09:49:23 -0400 Subject: [PATCH 13/57] Fix tests --- spec/system/distribution_system_spec.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/system/distribution_system_spec.rb b/spec/system/distribution_system_spec.rb index 956a2a3111..05ebb31492 100644 --- a/spec/system/distribution_system_spec.rb +++ b/spec/system/distribution_system_spec.rb @@ -596,6 +596,8 @@ items = storage_location.items.pluck(:id).sample(2) request_items = [{ "item_id" => items[0], "quantity" => 10 }, { "item_id" => items[1], "quantity" => 10 }] @request = create :request, organization: organization, request_items: request_items + create(:item_request, request: @request, item_id: items[0], quantity: 10) + create(:item_request, request: @request, item_id: items[1], quantity: 10) visit request_path(id: @request.id) click_on "Fulfill request" @@ -629,6 +631,8 @@ items = storage_location.items.pluck(:id).sample(2) request_items = [{ "item_id" => items[0], "quantity" => 1000000 }, { "item_id" => items[1], "quantity" => 10 }] @request = create :request, organization: organization, request_items: request_items + create(:item_request, request: @request, item_id: items[0], quantity: 1000000) + create(:item_request, request: @request, item_id: items[1], quantity: 10) visit request_path(id: @request.id) click_on "Fulfill request" From 0a74e07a2f715db269da43b1a7d58ec07b95a30b Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 11 Aug 2024 10:04:21 -0400 Subject: [PATCH 14/57] CR changes --- .../partners/requests_controller.rb | 27 +++++++++---------- .../controllers/item_units_controller.js | 7 ++--- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/app/controllers/partners/requests_controller.rb b/app/controllers/partners/requests_controller.rb index 66c185422c..983e4049dc 100644 --- a/app/controllers/partners/requests_controller.rb +++ b/app/controllers/partners/requests_controller.rb @@ -11,13 +11,7 @@ def new @partner_request = ::Request.new @partner_request.item_requests.build - @requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.id).call - if Flipper.enabled?(:enable_packs) - # hash of (item ID => hash of (request unit name => request unit plural name)) - @item_units = current_partner.organization.items.to_h do |i| - [i.id, i.request_units.to_h { |u| [u.name, u.name.pluralize] }] - end - end + fetch_items end def show @@ -39,13 +33,7 @@ def create @partner_request = create_service.partner_request @errors = create_service.errors - @requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.id).call - if Flipper.enabled?(:enable_packs) - # hash of (item ID => hash of (request unit name => request unit plural name)) - @item_units = current_partner.organization.items.to_h do |i| - [i.id, i.request_units.to_h { |u| [u.name, u.name.pluralize] }] - end - end + fetch_items Rails.logger.info("[Request Creation Failure] partner_user_id=#{current_user.id} reason=#{@errors.full_messages}") @@ -58,5 +46,16 @@ def create def partner_request_params params.require(:request).permit(:comments, item_requests_attributes: [:item_id, :quantity, :request_unit]) end + + def fetch_items + @requestable_items = PartnerFetchRequestableItemsService.new(partner_id: current_partner.id).call + if Flipper.enabled?(:enable_packs) + # hash of (item ID => hash of (request unit name => request unit plural name)) + @item_units = Item.where(id: @requestable_items.to_h.values).to_h do |i| + [i.id, i.request_units.to_h { |u| [u.name, u.name.pluralize] }] + end + end + end + end end diff --git a/app/javascript/controllers/item_units_controller.js b/app/javascript/controllers/item_units_controller.js index 07b6334a0e..36418febdb 100644 --- a/app/javascript/controllers/item_units_controller.js +++ b/app/javascript/controllers/item_units_controller.js @@ -8,13 +8,10 @@ export default class extends Controller { "itemUnits": Object } - addOption(val, text, selected) { + addOption(val, text) { let option = document.createElement("option"); option.value = val; option.text = text; - if (selected) { - option.selected = true; - } this.requestSelectTarget.appendChild(option); } @@ -43,7 +40,7 @@ export default class extends Controller { this.clearOptions() this.addOption('', 'Units') for (const [index, [name, displayName]] of Object.entries(Object.entries(units))) { - this.addOption(name, displayName, index === "0") + this.addOption(name, displayName) } } } From 270c28f0cdf2da4bb062ffe25244a6e1dafd3e9b Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 11 Aug 2024 10:11:15 -0400 Subject: [PATCH 15/57] Fix tests --- app/controllers/partners/requests_controller.rb | 1 - spec/system/partners/requests_system_spec.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/partners/requests_controller.rb b/app/controllers/partners/requests_controller.rb index 983e4049dc..6d5ebdfd29 100644 --- a/app/controllers/partners/requests_controller.rb +++ b/app/controllers/partners/requests_controller.rb @@ -56,6 +56,5 @@ def fetch_items end end end - end end diff --git a/spec/system/partners/requests_system_spec.rb b/spec/system/partners/requests_system_spec.rb index cc6c608ad4..1c500463b8 100644 --- a/spec/system/partners/requests_system_spec.rb +++ b/spec/system/partners/requests_system_spec.rb @@ -37,7 +37,7 @@ expect(page).not_to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) select "Item 1", from: "request_item_requests_attributes_0_item_id" expect(page).to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) - expect(page).to have_select("request_item_requests_attributes_0_request_unit", selected: "packs", options: ["Units", "packs"]) + expect(page).to have_select("request_item_requests_attributes_0_request_unit", selected: "Units", options: ["Units", "packs"]) select "packs", from: "request_item_requests_attributes_0_request_unit" click_on "Add Another Item" From 9ce328ed16259a4e75a85236853d90c7f730d096 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 11 Aug 2024 10:33:28 -0400 Subject: [PATCH 16/57] Update based on feedback --- .../controllers/item_units_controller.js | 1 + .../partners/request_create_service.rb | 4 ++++ app/views/partners/requests/_error.html.erb | 3 +++ spec/system/partners/requests_system_spec.rb | 19 ++++++++++++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/app/javascript/controllers/item_units_controller.js b/app/javascript/controllers/item_units_controller.js index 36418febdb..c647c9e876 100644 --- a/app/javascript/controllers/item_units_controller.js +++ b/app/javascript/controllers/item_units_controller.js @@ -38,6 +38,7 @@ export default class extends Controller { else { this.requestSelectTarget.style.display = 'inline'; this.clearOptions() + this.addOption('-1', 'Please select a unit') this.addOption('', 'Units') for (const [index, [name, displayName]] of Object.entries(Object.entries(units))) { this.addOption(name, displayName) diff --git a/app/services/partners/request_create_service.rb b/app/services/partners/request_create_service.rb index df1b5ecf6c..732f4c2a31 100644 --- a/app/services/partners/request_create_service.rb +++ b/app/services/partners/request_create_service.rb @@ -69,6 +69,10 @@ def populate_item_request(partner_request) # object (either this one or the FamilyRequestCreateService). pre_existing_entry.children = (pre_existing_entry.children + (input_item['children'] || [])).uniq else + if input_item['request_unit'].to_s == '-1' # nothing selected + errors.add(:base, "Please select a unit for #{Item.find(input_item["item_id"]).name}") + next + end items[input_item['item_id']] = Partners::ItemRequest.new( item_id: input_item['item_id'], request_unit: input_item['request_unit'], diff --git a/app/views/partners/requests/_error.html.erb b/app/views/partners/requests/_error.html.erb index b9d46c399c..ecdb3fe320 100644 --- a/app/views/partners/requests/_error.html.erb +++ b/app/views/partners/requests/_error.html.erb @@ -8,6 +8,9 @@

Oops! Something went wrong with your Request

Ensure each line item has a item selected AND a quantity greater than 0. + <% if Flipper.enabled?(:enable_packs) && current_partner.organization.request_units.any? %> + Please ensure a unit is selected for each item that supports it. + <% end %>

Still need help? Please contact your essentials bank, <%= current_partner.organization.name %>, if you need further assistance.
diff --git a/spec/system/partners/requests_system_spec.rb b/spec/system/partners/requests_system_spec.rb index 1c500463b8..8343db0b29 100644 --- a/spec/system/partners/requests_system_spec.rb +++ b/spec/system/partners/requests_system_spec.rb @@ -31,13 +31,30 @@ Flipper.enable(:enable_packs) end + it "should require a unit selection" do + visit new_partners_request_path + expect(Request.count).to eq(0) + expect(page).not_to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) + select "Item 1", from: "request_item_requests_attributes_0_item_id" + expect(page).to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) + expect(page).to have_select("request_item_requests_attributes_0_request_unit", + selected: "Please select a unit", + options: ["Please select a unit", "Units", "packs"]) + fill_in "request_item_requests_attributes_0_quantity", with: 50 + click_on "Submit Essentials Request" + expect(Request.count).to eq(0) + expect(page).to have_text "Please ensure a unit is selected for each item that supports it." + end + it "should show packs on selection" do visit new_partners_request_path expect(Request.count).to eq(0) expect(page).not_to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) select "Item 1", from: "request_item_requests_attributes_0_item_id" expect(page).to have_selector("#request_item_requests_attributes_0_request_unit", visible: true) - expect(page).to have_select("request_item_requests_attributes_0_request_unit", selected: "Units", options: ["Units", "packs"]) + expect(page).to have_select("request_item_requests_attributes_0_request_unit", + selected: "Please select a unit", + options: ["Please select a unit", "Units", "packs"]) select "packs", from: "request_item_requests_attributes_0_request_unit" click_on "Add Another Item" From 1f6a66e13c4fc024aa6c99e277aa4abc6b890695 Mon Sep 17 00:00:00 2001 From: Norris Mei Date: Thu, 15 Aug 2024 21:21:01 -0700 Subject: [PATCH 17/57] Fix typo --- app/views/distributions/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/distributions/index.html.erb b/app/views/distributions/index.html.erb index 6466784bd1..fa99743927 100644 --- a/app/views/distributions/index.html.erb +++ b/app/views/distributions/index.html.erb @@ -99,7 +99,7 @@ ID Partner - Inital Allocation + Initial Allocation Date of Distribution Source Inventory From b7c8a5541ba09727a34e3d6dda84faa6cfee0c23 Mon Sep 17 00:00:00 2001 From: Norris Mei Date: Thu, 15 Aug 2024 21:22:37 -0700 Subject: [PATCH 18/57] Update state to status --- app/views/distributions/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/distributions/index.html.erb b/app/views/distributions/index.html.erb index fa99743927..0dc9b285c2 100644 --- a/app/views/distributions/index.html.erb +++ b/app/views/distributions/index.html.erb @@ -117,7 +117,7 @@ Delivery method Shipping Cost Comments - State + Status Actions From 310f623a1e3098358bfa24a0c69f1cba281ca527 Mon Sep 17 00:00:00 2001 From: Norris Mei Date: Thu, 15 Aug 2024 21:35:11 -0700 Subject: [PATCH 19/57] Make capitalization consistent --- app/views/distributions/index.html.erb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/views/distributions/index.html.erb b/app/views/distributions/index.html.erb index 0dc9b285c2..42da475824 100644 --- a/app/views/distributions/index.html.erb +++ b/app/views/distributions/index.html.erb @@ -38,17 +38,17 @@

<% if @items.present? %>
- <%= filter_select(label: "Filter by item", scope: :by_item_id, collection: @items, selected: @selected_item) %> + <%= filter_select(label: "Filter by Item", scope: :by_item_id, collection: @items, selected: @selected_item) %>
<% end %> <% if @item_categories.present? %>
- <%= filter_select(label: "Filter by item category", scope: :by_item_category_id, collection: @item_categories, selected: @selected_item_category) %> + <%= filter_select(label: "Filter by Item Category", scope: :by_item_category_id, collection: @item_categories, selected: @selected_item_category) %>
<% end %> <% if @partners.present? %>
- <%= filter_select(scope: :by_partner, collection: @partners, selected: @selected_partner) %> + <%= filter_select(label: "Filter by Partner", scope: :by_partner, collection: @partners, selected: @selected_partner) %>
<% end %> <% if @storage_locations.present? %> @@ -60,7 +60,7 @@ <%= filter_select(label: "Filter by Status", scope: :by_state, collection: @statuses, key: :last, value: :first, selected: @selected_status) %>
- <%= label_tag "Date Range" %> + <%= label_tag "Date Range", "Date Range" %> <%= render partial: "shared/date_range_picker", locals: {css_class: "form-control"} %>
@@ -109,12 +109,12 @@ <% elsif filter_params[:by_item_category_id].present? %> Total in <%= @item_categories.find { |ic| ic.id == filter_params[:by_item_category_id].to_i }&.name %> <% else %> - Total items + Total Items <% end %> - Total value - Delivery method + Total Value + Delivery Method Shipping Cost Comments Status From bac69b755df46fe6450c02bfcee083a35646a288 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 16 Aug 2024 15:21:23 -0400 Subject: [PATCH 20/57] Don't show barcode for requested items --- app/views/line_items/_line_item_fields.html.erb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/views/line_items/_line_item_fields.html.erb b/app/views/line_items/_line_item_fields.html.erb index fe7f27b132..437f278b12 100644 --- a/app/views/line_items/_line_item_fields.html.erb +++ b/app/views/line_items/_line_item_fields.html.erb @@ -3,12 +3,14 @@
-
- <%= render partial: "barcode_items/barcode_item_lookup", - locals: { index: field&.options[:child_index] || "new_item" } %> -
-
- + <% if requested.blank? %> +
+ <%= render partial: "barcode_items/barcode_item_lookup", + locals: { index: field&.options[:child_index] || "new_item" } %> +
+
+ + <% end %>
<%= field.input :item_id, From 7cba987b6715fd6bf37602b28b09e978ae26d62e Mon Sep 17 00:00:00 2001 From: Norris Mei Date: Fri, 16 Aug 2024 20:17:03 -0700 Subject: [PATCH 21/57] Revert status back to state --- app/views/distributions/index.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/distributions/index.html.erb b/app/views/distributions/index.html.erb index 42da475824..d0b7a55b96 100644 --- a/app/views/distributions/index.html.erb +++ b/app/views/distributions/index.html.erb @@ -117,7 +117,7 @@ Delivery Method Shipping Cost Comments - Status + State Actions From 579925665c3401b5403fb16fbd697a9adc9de2d6 Mon Sep 17 00:00:00 2001 From: Brock Wilcox Date: Mon, 19 Aug 2024 08:42:14 -0400 Subject: [PATCH 22/57] Update request verification pop-up and specs [#4398] --- app/views/partners/requests/validate.html.erb | 6 ++++++ spec/system/partners/requests_system_spec.rb | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/views/partners/requests/validate.html.erb b/app/views/partners/requests/validate.html.erb index 1455e3cb8c..37d53adebc 100644 --- a/app/views/partners/requests/validate.html.erb +++ b/app/views/partners/requests/validate.html.erb @@ -11,6 +11,9 @@ Item Name Total Items + <% if Flipper.enabled?(:enable_packs) && @partner_request.item_requests.any?( &:request_unit ) %> + Units + <% end %> @@ -18,6 +21,9 @@ <%= line_item.name %> <%= line_item.quantity %> + <% if Flipper.enabled?(:enable_packs) && @partner_request.item_requests.any?( &:request_unit ) %> + <%= line_item.request_unit %> + <% end %> <% end %> diff --git a/spec/system/partners/requests_system_spec.rb b/spec/system/partners/requests_system_spec.rb index 8343db0b29..0c4bc9ebf2 100644 --- a/spec/system/partners/requests_system_spec.rb +++ b/spec/system/partners/requests_system_spec.rb @@ -42,8 +42,9 @@ options: ["Please select a unit", "Units", "packs"]) fill_in "request_item_requests_attributes_0_quantity", with: 50 click_on "Submit Essentials Request" - expect(Request.count).to eq(0) + expect(page).to have_text "Please ensure a unit is selected for each item that supports it." + expect(Request.count).to eq(0) end it "should show packs on selection" do @@ -68,6 +69,8 @@ fill_in "request_item_requests_attributes_0_quantity", with: 50 fill_in "request_item_requests_attributes_#{id}_quantity", with: 20 click_on "Submit Essentials Request" + click_on "Yes, it's correct" + expect(page).to have_text "Request has been successfully created" expect(Request.count).to eq(1) request = Request.last From 282d9ddacb567b5ca80372a22d9bce99fead6cec Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:39:39 -0700 Subject: [PATCH 23/57] Adds in action for reset_password_partner_user This commit adds in a new action to the partner_users_controller to reset the corresponding user's password. It also adds in a new route for the action -reset_password_partner_user -/partners/:partner_id/users/:id/reset_password(.:format) -partner_users#reset_password [Ticket: 4596] --- app/controllers/partner_users_controller.rb | 11 +++++++++++ config/routes.rb | 1 + 2 files changed, 12 insertions(+) diff --git a/app/controllers/partner_users_controller.rb b/app/controllers/partner_users_controller.rb index bb20c2f5f5..9b89665100 100644 --- a/app/controllers/partner_users_controller.rb +++ b/app/controllers/partner_users_controller.rb @@ -51,6 +51,17 @@ def resend_invitation end end + def reset_password + user = User.find(params[:id]) + + user.send_reset_password_instructions + if user.errors.none? + redirect_back(fallback_location: root_path, notice: "Password e-mail sent!") + else + redirect_back(fallback_location: "/", alert: user.errors.full_messages.to_sentence) + end end + + private def set_partner diff --git a/config/routes.rb b/config/routes.rb index d9595315dd..a97548c5cd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -206,6 +206,7 @@ def set_up_flipper resources :users, only: [:index, :create, :destroy], controller: 'partner_users' do member do post :resend_invitation + post :reset_password end end From 50650bc1dcdb4d74c47531b35fbf427076ac13c6 Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:14:13 -0700 Subject: [PATCH 24/57] Adds in and stylizes the reset password button on 'Manage Users' page --- app/views/partner_users/_users.html.erb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/views/partner_users/_users.html.erb b/app/views/partner_users/_users.html.erb index 74d7f6fb9d..f4fc9965c6 100644 --- a/app/views/partner_users/_users.html.erb +++ b/app/views/partner_users/_users.html.erb @@ -53,6 +53,9 @@ Resend Invitation <% end %> <% end %> + <%= button_to reset_password_partner_user_path(partner, user), method: :post, data: { confirm: "Are you sure?" }, class: "btn btn-info btn-xs mb-2" do %> + Reset Password + <% end %> <%= button_to partner_user_path(partner, user), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-danger btn-xs" do %> Remove Access <% end %> From 1a1fca8211a6e765ff98c563a0f909bc19e268ef Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:28:18 -0700 Subject: [PATCH 25/57] Adds in rspec for new controller action --- app/controllers/partner_users_controller.rb | 5 +++-- spec/requests/partner_users_requests_spec.rb | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/controllers/partner_users_controller.rb b/app/controllers/partner_users_controller.rb index 9b89665100..ed79519484 100644 --- a/app/controllers/partner_users_controller.rb +++ b/app/controllers/partner_users_controller.rb @@ -53,13 +53,14 @@ def resend_invitation def reset_password user = User.find(params[:id]) - + user.send_reset_password_instructions if user.errors.none? redirect_back(fallback_location: root_path, notice: "Password e-mail sent!") else redirect_back(fallback_location: "/", alert: user.errors.full_messages.to_sentence) - end end + end + end private diff --git a/spec/requests/partner_users_requests_spec.rb b/spec/requests/partner_users_requests_spec.rb index 3fd3a5d71f..841d039429 100644 --- a/spec/requests/partner_users_requests_spec.rb +++ b/spec/requests/partner_users_requests_spec.rb @@ -111,4 +111,23 @@ end end end + + describe "POST #reset_password" do + let!(:partner_user) do + UserInviteService.invite( + email: "meow@example.com", + name: "Meow Mix", + roles: [Role::PARTNER], + resource: partner + ) + end + + context "when the partner needs to reset a user's password" do + it "resends the reset password email and redirects back to root_path" do + post reset_password_partner_user_path(default_params.merge(partner_id: partner, id: partner_user)) + + expect(response).to redirect_to(root_path) + end + end + end end From f3a9dc45f1ca3e1c19e80445094fe432974149e5 Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:58:46 -0700 Subject: [PATCH 26/57] Updates rspec for reset password Adds in check for ActionMailer count increases by 1 Adds in check for the expected notice message [Ticket: 4596] --- app/controllers/partner_users_controller.rb | 7 +------ spec/requests/partner_users_requests_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/controllers/partner_users_controller.rb b/app/controllers/partner_users_controller.rb index ed79519484..102da47f34 100644 --- a/app/controllers/partner_users_controller.rb +++ b/app/controllers/partner_users_controller.rb @@ -55,14 +55,9 @@ def reset_password user = User.find(params[:id]) user.send_reset_password_instructions - if user.errors.none? - redirect_back(fallback_location: root_path, notice: "Password e-mail sent!") - else - redirect_back(fallback_location: "/", alert: user.errors.full_messages.to_sentence) - end + redirect_back(fallback_location: root_path, notice: "Password e-mail sent!") end - private def set_partner diff --git a/spec/requests/partner_users_requests_spec.rb b/spec/requests/partner_users_requests_spec.rb index 841d039429..87cc19ad02 100644 --- a/spec/requests/partner_users_requests_spec.rb +++ b/spec/requests/partner_users_requests_spec.rb @@ -124,9 +124,9 @@ context "when the partner needs to reset a user's password" do it "resends the reset password email and redirects back to root_path" do - post reset_password_partner_user_path(default_params.merge(partner_id: partner, id: partner_user)) - + expect { post reset_password_partner_user_path(default_params.merge(partner_id: partner, id: partner_user)) }.to change { ActionMailer::Base.deliveries.count }.by(1) expect(response).to redirect_to(root_path) + expect(flash[:notice]).to eq("Password e-mail sent!") end end end From b91207d258ef0cfecd66aa5c3ee3c831dd757ce6 Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Thu, 22 Aug 2024 11:08:03 -0700 Subject: [PATCH 27/57] Changes icon on reset-password to a key --- app/views/partner_users/_users.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/partner_users/_users.html.erb b/app/views/partner_users/_users.html.erb index f4fc9965c6..7018148cdf 100644 --- a/app/views/partner_users/_users.html.erb +++ b/app/views/partner_users/_users.html.erb @@ -54,7 +54,7 @@ <% end %> <% end %> <%= button_to reset_password_partner_user_path(partner, user), method: :post, data: { confirm: "Are you sure?" }, class: "btn btn-info btn-xs mb-2" do %> - Reset Password + Reset Password <% end %> <%= button_to partner_user_path(partner, user), method: :delete, data: { confirm: "Are you sure?" }, class: "btn btn-danger btn-xs" do %> Remove Access From 54165f17b40d0b2671233379d6f9dd80e45b357e Mon Sep 17 00:00:00 2001 From: Ahmed Ejaz Date: Sat, 24 Aug 2024 00:44:30 +0500 Subject: [PATCH 28/57] 4575: handle nil zip codes (#4600) --- .../reports/partner_info_report_service.rb | 2 +- .../partner_info_report_service_spec.rb | 69 +++++++++++++------ 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/app/services/reports/partner_info_report_service.rb b/app/services/reports/partner_info_report_service.rb index 9db4d27199..b27f583115 100644 --- a/app/services/reports/partner_info_report_service.rb +++ b/app/services/reports/partner_info_report_service.rb @@ -37,7 +37,7 @@ def partner_agency_counts end def partner_zipcodes_serviced - partner_agency_profiles.map(&:zips_served).uniq.sort.join(', ') + partner_agency_profiles.map(&:zips_served).uniq.compact.sort.join(', ') end end end diff --git a/spec/services/reports/partner_info_report_service_spec.rb b/spec/services/reports/partner_info_report_service_spec.rb index c858307768..a8f26e8ae5 100644 --- a/spec/services/reports/partner_info_report_service_spec.rb +++ b/spec/services/reports/partner_info_report_service_spec.rb @@ -8,29 +8,58 @@ end describe '#report' do - it 'should report zero values' do - expect(report.report).to eq({ - entries: { "Number of Partner Agencies" => 0, - "Zip Codes Served" => "" }, - name: "Partner Agencies and Service Area" - }) + context "with no partners available" do + it 'should report zero values' do + expect(report.report).to eq({ + entries: { "Number of Partner Agencies" => 0, + "Zip Codes Served" => "" }, + name: "Partner Agencies and Service Area" + }) + end end - it 'should report normal values' do - p1 = create(:partner, :uninvited, organization: organization, name: 'Partner 1') - p1.profile.update!(zips_served: '90210-1234', agency_type: Partner::AGENCY_TYPES['CAREER']) - p2 = create(:partner, :uninvited, organization: organization, name: 'Partner 2') - p2.profile.update!(zips_served: '12345', agency_type: Partner::AGENCY_TYPES['CAREER']) - p3 = create(:partner, :uninvited, organization: organization, name: 'Partner 3') - p3.profile.update!(zips_served: '09876-3564', agency_type: Partner::AGENCY_TYPES['EDU']) + context "with partners available" do + let!(:p1) do + create(:partner, :uninvited, organization: organization, name: 'Partner 1') do |p| + p.profile.update!(zips_served: '90210-1234', agency_type: Partner::AGENCY_TYPES['CAREER']) + end + end + let!(:p2) do + create(:partner, :uninvited, organization: organization, name: 'Partner 2') do |p| + p.profile.update!(zips_served: '12345', agency_type: Partner::AGENCY_TYPES['CAREER']) + end + end + let!(:p3) do + create(:partner, :uninvited, organization: organization, name: 'Partner 3') do |p| + p.profile.update!(zips_served: '09876-3564', agency_type: Partner::AGENCY_TYPES['EDU']) + end + end - expect(report.report).to eq({ - entries: { "Agency Type: Career technical training" => 2, - "Agency Type: Education program" => 1, - "Number of Partner Agencies" => 3, - "Zip Codes Served" => "09876-3564, 12345, 90210-1234" }, - name: "Partner Agencies and Service Area" - }) + context "with all profiles have zips_served" do + it 'should report normal values' do + expect(report.report).to eq({ + entries: { "Agency Type: Career technical training" => 2, + "Agency Type: Education program" => 1, + "Number of Partner Agencies" => 3, + "Zip Codes Served" => "09876-3564, 12345, 90210-1234" }, + name: "Partner Agencies and Service Area" + }) + end + end + + context "with some profiles missing zip_served" do + before { p2.profile.update!(zips_served: nil) } + + it 'should report normal values' do + expect(report.report).to eq({ + entries: { "Agency Type: Career technical training" => 2, + "Agency Type: Education program" => 1, + "Number of Partner Agencies" => 3, + "Zip Codes Served" => "09876-3564, 90210-1234" }, + name: "Partner Agencies and Service Area" + }) + end + end end end end From b44acbbaeb2e7f115c2212d39fdcbd522b369eaf Mon Sep 17 00:00:00 2001 From: Brock Wilcox Date: Fri, 23 Aug 2024 15:45:59 -0400 Subject: [PATCH 29/57] Require a partner for the partner dashboard (#4063) * Require a partner for the partner dashboard * Validate that a non-partner user gets redirected * Centralize partner-user requirement to partner base controller * Clean out the lint! * Fix redirect spec --- app/controllers/partners/base_controller.rb | 11 +++++++++++ spec/requests/partners/dashboard_requests_spec.rb | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/app/controllers/partners/base_controller.rb b/app/controllers/partners/base_controller.rb index 0b217375d1..37435df4a6 100644 --- a/app/controllers/partners/base_controller.rb +++ b/app/controllers/partners/base_controller.rb @@ -2,12 +2,23 @@ module Partners class BaseController < ApplicationController layout 'partners/application' + before_action :require_partner + private def redirect_to_root redirect_to root_path end + def require_partner + unless current_partner + respond_to do |format| + format.html { redirect_to dashboard_path, flash: {error: "Logged in user is not set up as a 'partner'."} } + format.json { render body: nil, status: :forbidden } + end + end + end + def verify_partner_is_active if current_partner.deactivated? flash[:alert] = 'Your account has been disabled, contact the organization via their email to reactivate' diff --git a/spec/requests/partners/dashboard_requests_spec.rb b/spec/requests/partners/dashboard_requests_spec.rb index 761f379abb..b800f4f776 100644 --- a/spec/requests/partners/dashboard_requests_spec.rb +++ b/spec/requests/partners/dashboard_requests_spec.rb @@ -86,6 +86,16 @@ end end + context "without a partner role" do + it "should redirect to the organization dashboard" do + partner_user.add_role(Role::ORG_USER, @organization) + partner_user.remove_role(Role::PARTNER, partner) + allow(UsersRole).to receive(:current_role_for).and_return(partner_user.roles.find_by(name: "partner")) + get partners_dashboard_path + expect(response).to redirect_to(dashboard_path) + end + end + context "BroadcastAnnouncement card" do it "displays announcements if there are valid ones" do BroadcastAnnouncement.create(message: "test announcement", user_id: user.id, organization_id: organization.id) From ba546122b7bc7f7b83ce0d8701ce94861dff5cee Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Fri, 23 Aug 2024 15:56:44 -0400 Subject: [PATCH 30/57] fix bug on create error --- app/controllers/distributions_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/distributions_controller.rb b/app/controllers/distributions_controller.rb index 9365cc85da..f7f0e0d62a 100644 --- a/app/controllers/distributions_controller.rb +++ b/app/controllers/distributions_controller.rb @@ -109,7 +109,11 @@ def create # does not match any known Request @distribution.request = Request.find(request_id) end - @distribution.line_items.build if @distribution.line_items.size.zero? + if @distribution.line_items.size.zero? + @distribution.line_items.build + elsif request_id + @distribution.initialize_request_items + end @items = current_organization.items.alphabetized if Event.read_events?(current_organization) inventory = View::Inventory.new(@distribution.organization_id) From 44a816b044908fd289f58724ed7b0184be3a154d Mon Sep 17 00:00:00 2001 From: Enoch Hsu <1529929+ewoknock@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:01:45 -0700 Subject: [PATCH 31/57] Updating rspec test description to be more accurate --- spec/requests/partner_users_requests_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/requests/partner_users_requests_spec.rb b/spec/requests/partner_users_requests_spec.rb index 87cc19ad02..c15a59828b 100644 --- a/spec/requests/partner_users_requests_spec.rb +++ b/spec/requests/partner_users_requests_spec.rb @@ -122,7 +122,7 @@ ) end - context "when the partner needs to reset a user's password" do + context "when a bank needs to reset a partner user's password" do it "resends the reset password email and redirects back to root_path" do expect { post reset_password_partner_user_path(default_params.merge(partner_id: partner, id: partner_user)) }.to change { ActionMailer::Base.deliveries.count }.by(1) expect(response).to redirect_to(root_path) From 1813bf30d21e96019c8ce4d4c0b0a16fd1d48482 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Aug 2024 16:10:49 -0400 Subject: [PATCH 32/57] build(deps-dev): bump standard from 1.39.1 to 1.39.2 (#4566) Bumps [standard](https://github.com/standardrb/standard) from 1.39.1 to 1.39.2. - [Release notes](https://github.com/standardrb/standard/releases) - [Changelog](https://github.com/standardrb/standard/blob/main/CHANGELOG.md) - [Commits](https://github.com/standardrb/standard/compare/v1.39.1...v1.39.2) --- updated-dependencies: - dependency-name: standard dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3b8cd2768b..54039a468f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -648,7 +648,7 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - standard (1.39.1) + standard (1.39.2) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) rubocop (~> 1.64.0) From fb96b33f98f96d848ed70a13a3eca8513c7be9d9 Mon Sep 17 00:00:00 2001 From: Daniel Orner Date: Sun, 25 Aug 2024 10:19:15 -0400 Subject: [PATCH 33/57] Fix bad kits --- db/migrate/20240825141541_fix_bad_kits.rb | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 db/migrate/20240825141541_fix_bad_kits.rb diff --git a/db/migrate/20240825141541_fix_bad_kits.rb b/db/migrate/20240825141541_fix_bad_kits.rb new file mode 100644 index 0000000000..3aa7ade4be --- /dev/null +++ b/db/migrate/20240825141541_fix_bad_kits.rb @@ -0,0 +1,25 @@ +class FixBadKits < ActiveRecord::Migration[7.1] + def change + return unless Rails.env.production? + + ids = [78, 204,189] + kit_base_item = BaseItem.find_or_create_by!({ + name: 'Kit', + category: 'kit', + partner_key: 'kit' + }) + Kit.where(id: ids).each do |kit| + result = ItemCreateService.new( + organization_id: kit.organization.id, + item_params: { + name: kit.name, + partner_key: kit_base_item.partner_key, + kit_id: kit.id + } + ).call + unless result.success? + raise result.error + end + end + end +end From f22114ad894353e09cb44705e905abb369ed0940 Mon Sep 17 00:00:00 2001 From: isaiah3031 Date: Mon, 26 Aug 2024 06:17:50 -0400 Subject: [PATCH 34/57] Adds required to Payment Total. --- app/views/purchases/_purchase_form.html.erb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/views/purchases/_purchase_form.html.erb b/app/views/purchases/_purchase_form.html.erb index f2e0d35bb4..f0765e4dd2 100644 --- a/app/views/purchases/_purchase_form.html.erb +++ b/app/views/purchases/_purchase_form.html.erb @@ -27,7 +27,8 @@
<%= f.input :amount_spent, label: "Purchase Total", - wrapper: :input_group %> + wrapper: :input_group, + required: true %>
From 4cda3aafbb11054e0e8beb9884fe64e5dd924a0a Mon Sep 17 00:00:00 2001 From: isaiah3031 Date: Thu, 29 Aug 2024 13:39:02 -0400 Subject: [PATCH 35/57] Adds wsl install note to CONTRIBUTING.md --- CONTRIBUTING.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a1c7e260a3..49235123b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,15 @@ You won't be yelled at for giving your best effort. The worst that can happen is # Getting Started ## Local Environment 🛠️ + +Do you develop on Windows? +#### Windows Subsystem for Linux (WSL2) - Windows Only +Follow [documentation](https://docs.microsoft.com/en-us/windows/wsl/install-win10) from Microsoft for enabling and installing WSL2 on your machine. + +Make sure to install **Ubuntu** as your Linux distribution. (This should be default.) + +**Note:** If you run into any issues with a command not running, restart your machine. + 1. Install Ruby - Install the version specified in [`.ruby-version`](.ruby-version). - Visit the [Install Ruby on Rails](https://gorails.com/setup/osx/12-monterey) guide by GoRails for Ubuntu, Windows, and macOSX setup. ⚠️ Follow only the Installing Ruby step, as our project setup differs ⚠️ It is highly recommended you use a ruby version manager such as [rbenv](https://github.com/rbenv/rbenv), [asdf](https://asdf-vm.com/), or [rvm](https://rvm.io/). From 39e7b3ba476070ef7a9d0ecfaeabdd7ab0ba559f Mon Sep 17 00:00:00 2001 From: isaiah3031 Date: Thu, 29 Aug 2024 14:06:42 -0400 Subject: [PATCH 36/57] Remove request. Rewording. --- CONTRIBUTING.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 49235123b3..f8a23fd295 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,21 +18,20 @@ You won't be yelled at for giving your best effort. The worst that can happen is # Getting Started ## Local Environment 🛠️ -Do you develop on Windows? -#### Windows Subsystem for Linux (WSL2) - Windows Only -Follow [documentation](https://docs.microsoft.com/en-us/windows/wsl/install-win10) from Microsoft for enabling and installing WSL2 on your machine. +#### Install WSL2 first if Using Windows +Follow [documentation](https://docs.microsoft.com/en-us/windows/wsl/install-win10) from Microsoft for enabling and installing Windows Subsystem For Linux 2 on your machine. Make sure to install **Ubuntu** as your Linux distribution. (This should be default.) **Note:** If you run into any issues with a command not running, restart your machine. + 1. Install Ruby - Install the version specified in [`.ruby-version`](.ruby-version). - Visit the [Install Ruby on Rails](https://gorails.com/setup/osx/12-monterey) guide by GoRails for Ubuntu, Windows, and macOSX setup. ⚠️ Follow only the Installing Ruby step, as our project setup differs ⚠️ It is highly recommended you use a ruby version manager such as [rbenv](https://github.com/rbenv/rbenv), [asdf](https://asdf-vm.com/), or [rvm](https://rvm.io/). - Verify that your Ruby installation works by running `ruby -v`. 2. Install Postgres - Follow one of these guides: [MacOSX](https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-ruby-on-rails-application-on-macos), [Ubuntu](https://www.digitalocean.com/community/tutorials/how-to-use-postgresql-with-your-ruby-on-rails-application-on-ubuntu-18-04). - - Do you develop on Windows? We'd love to hear (and for you to submit a PR explaining) how you do it. 🙏🏻 - Create a `database.yml` file on `config/` directory with your database configurations. You can also copy the existing files called [`database.yml.example`](config/database.yml.example) and [`.env.example`](.env.example) and change the credentials. 3. Clone the project and switch to its directory 4. Run `bin/setup` From 5800bf9efd4bd070575a842890ba5e3941a7f0d3 Mon Sep 17 00:00:00 2001 From: Brock Wilcox Date: Thu, 29 Aug 2024 21:59:54 -0400 Subject: [PATCH 37/57] Add data migration to fix errant distribution+event --- .../20240830015517_fix_invalid_distribution_event.rb | 12 ++++++++++++ db/schema.rb | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20240830015517_fix_invalid_distribution_event.rb diff --git a/db/migrate/20240830015517_fix_invalid_distribution_event.rb b/db/migrate/20240830015517_fix_invalid_distribution_event.rb new file mode 100644 index 0000000000..cace57fead --- /dev/null +++ b/db/migrate/20240830015517_fix_invalid_distribution_event.rb @@ -0,0 +1,12 @@ +class FixInvalidDistributionEvent < ActiveRecord::Migration[7.1] + def change + return unless Rails.env.production? + + # We are not sure why yet, but this org was able to create a distribution + # that put them at a negative inventory. Later playback of the events with + # validation turned on then raised it as an error. For now we are deleting + # the distribution and event directly. + Event.where(id: 34416, eventable_type: 'Distribution', eventable_id: 75002).first.destroy + Distribution.find(75002).destroy + end +end diff --git a/db/schema.rb b/db/schema.rb index bcc773347a..91483f028f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_18_010905) do +ActiveRecord::Schema[7.1].define(version: 2024_08_30_015517) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" From bb25ab6b25f18492eddfc364eb5fbb2a72547dc9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 04:20:54 +0000 Subject: [PATCH 38/57] build(deps): bump omniauth-google-oauth2 from 1.1.2 to 1.1.3 Bumps [omniauth-google-oauth2](https://github.com/zquestz/omniauth-google-oauth2) from 1.1.2 to 1.1.3. - [Release notes](https://github.com/zquestz/omniauth-google-oauth2/releases) - [Changelog](https://github.com/zquestz/omniauth-google-oauth2/blob/master/CHANGELOG.md) - [Commits](https://github.com/zquestz/omniauth-google-oauth2/compare/v1.1.2...v1.1.3) --- updated-dependencies: - dependency-name: omniauth-google-oauth2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 54039a468f..fe9ae9d6c3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -243,7 +243,7 @@ GEM faraday-httpclient (1.0.1) faraday-multipart (1.0.4) multipart-post (~> 2) - faraday-net_http (1.0.1) + faraday-net_http (1.0.2) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) faraday-rack (1.0.0) @@ -383,8 +383,9 @@ GEM monetize (~> 1.9) money (~> 6.13) railties (>= 3.0) - multi_xml (0.6.0) - multipart-post (2.4.0) + multi_xml (0.7.1) + bigdecimal (~> 3.1) + multipart-post (2.4.1) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) mutex_m (0.2.0) @@ -422,7 +423,7 @@ GEM hashie (>= 3.4.6) rack (>= 2.2.3) rack-protection - omniauth-google-oauth2 (1.1.2) + omniauth-google-oauth2 (1.1.3) jwt (>= 2.0) oauth2 (~> 2.0) omniauth (~> 2.0) From 86bb7eef5292c07ddbbb11fcd4b2fe278557428f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 04:22:02 +0000 Subject: [PATCH 39/57] build(deps-dev): bump rspec-rails from 6.1.3 to 6.1.4 Bumps [rspec-rails](https://github.com/rspec/rspec-rails) from 6.1.3 to 6.1.4. - [Changelog](https://github.com/rspec/rspec-rails/blob/main/Changelog.md) - [Commits](https://github.com/rspec/rspec-rails/compare/v6.1.3...v6.1.4) --- updated-dependencies: - dependency-name: rspec-rails dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Gemfile b/Gemfile index 8bc1e4f459..3e3e5f4ef9 100644 --- a/Gemfile +++ b/Gemfile @@ -150,7 +150,7 @@ group :development, :test do # Debugger which supports rdbg and Shopify Ruby LSP VSCode extension gem "debug", ">= 1.0.0" # RSpec behavioral testing framework for Rails. - gem "rspec-rails", "~> 6.1.3" + gem "rspec-rails", "~> 6.1.4" # Static analysis / linter. gem "rubocop" # Rails add-on for static analysis. diff --git a/Gemfile.lock b/Gemfile.lock index 54039a468f..39e090199d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,7 +141,7 @@ GEM activesupport tzinfo coderay (1.1.3) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) coverband (6.1.2) redis (>= 3.0) @@ -315,7 +315,7 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.7.2) - irb (1.13.2) + irb (1.14.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.12.0) @@ -373,7 +373,7 @@ GEM method_source (1.1.0) mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.24.1) + minitest (5.25.1) monetize (1.12.0) money (~> 6.12) money (6.16.0) @@ -562,13 +562,13 @@ GEM rspec-mocks (~> 3.13.0) rspec-core (3.13.0) rspec-support (~> 3.13.0) - rspec-expectations (3.13.1) + rspec-expectations (3.13.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) rspec-mocks (3.13.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-rails (6.1.3) + rspec-rails (6.1.4) actionpack (>= 6.1) activesupport (>= 6.1) railties (>= 6.1) @@ -668,7 +668,7 @@ GEM strscan (3.1.0) terser (1.2.3) execjs (>= 0.3.0, < 3) - thor (1.3.1) + thor (1.3.2) tilt (2.2.0) timeout (0.4.1) ttfunk (1.7.0) @@ -699,7 +699,7 @@ GEM xpath (3.2.0) nokogiri (~> 1.8) yard (0.9.34) - zeitwerk (2.6.16) + zeitwerk (2.6.17) PLATFORMS arm64-darwin-20 @@ -782,7 +782,7 @@ DEPENDENCIES recaptcha redis (~> 5.2) rolify (~> 6.0) - rspec-rails (~> 6.1.3) + rspec-rails (~> 6.1.4) rubocop rubocop-performance rubocop-rails (~> 2.25.1) From ac65e6a544ea02c635a6ed428b24ae55c3c6db5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 04:24:16 +0000 Subject: [PATCH 40/57] build(deps-dev): bump standard from 1.39.2 to 1.40.0 Bumps [standard](https://github.com/standardrb/standard) from 1.39.2 to 1.40.0. - [Release notes](https://github.com/standardrb/standard/releases) - [Changelog](https://github.com/standardrb/standard/blob/main/CHANGELOG.md) - [Commits](https://github.com/standardrb/standard/compare/v1.39.2...v1.40.0) --- updated-dependencies: - dependency-name: standard dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile | 2 +- Gemfile.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Gemfile b/Gemfile index 8bc1e4f459..439fa40e9a 100644 --- a/Gemfile +++ b/Gemfile @@ -157,7 +157,7 @@ group :development, :test do gem 'rubocop-performance' gem "rubocop-rails", "~> 2.25.1" # Default rules for Rubocop. - gem "standard", "~> 1.39" + gem "standard", "~> 1.40" # Erb linter. gem "erb_lint" end diff --git a/Gemfile.lock b/Gemfile.lock index 54039a468f..75ed7eab0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -440,8 +440,8 @@ GEM paper_trail (15.1.0) activerecord (>= 6.1) request_store (~> 1.4) - parallel (1.25.1) - parser (3.3.4.0) + parallel (1.26.3) + parser (3.3.4.2) ast (~> 2.4.1) racc pdf-core (0.9.0) @@ -552,7 +552,7 @@ GEM responders (3.1.1) actionpack (>= 5.2) railties (>= 5.2) - rexml (3.3.4) + rexml (3.3.6) strscan rolify (6.0.1) rouge (4.1.2) @@ -577,18 +577,18 @@ GEM rspec-mocks (~> 3.13) rspec-support (~> 3.13) rspec-support (3.13.1) - rubocop (1.64.1) + rubocop (1.65.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) + regexp_parser (>= 2.4, < 3.0) rexml (>= 3.2.5, < 4.0) rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.31.3) + rubocop-ast (1.32.1) parser (>= 3.3.1.0) rubocop-performance (1.21.1) rubocop (>= 1.48.1, < 2.0) @@ -648,10 +648,10 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - standard (1.39.2) + standard (1.40.0) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) - rubocop (~> 1.64.0) + rubocop (~> 1.65.0) standard-custom (~> 1.0.0) standard-performance (~> 1.4) standard-custom (1.0.2) @@ -791,7 +791,7 @@ DEPENDENCIES simple_form simplecov sprockets (~> 4.2.1) - standard (~> 1.39) + standard (~> 1.40) stimulus-rails strong_migrations (= 1.8.0) terser From 454b7951d0182563dd8ba9af893757d0a20a7bd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 04:24:44 +0000 Subject: [PATCH 41/57] build(deps): bump newrelic_rpm from 9.12.0 to 9.13.0 Bumps [newrelic_rpm](https://github.com/newrelic/newrelic-ruby-agent) from 9.12.0 to 9.13.0. - [Release notes](https://github.com/newrelic/newrelic-ruby-agent/releases) - [Changelog](https://github.com/newrelic/newrelic-ruby-agent/blob/dev/CHANGELOG.md) - [Commits](https://github.com/newrelic/newrelic-ruby-agent/compare/9.12.0...9.13.0) --- updated-dependencies: - dependency-name: newrelic_rpm dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 54039a468f..b7bc81edeb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -400,7 +400,7 @@ GEM timeout net-smtp (0.5.0) net-protocol - newrelic_rpm (9.12.0) + newrelic_rpm (9.13.0) nio4r (2.7.3) nokogiri (1.16.7-arm64-darwin) racc (~> 1.4) From e647ac89465bb2d9f55b8abef956a9b953b016a2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 04:25:11 +0000 Subject: [PATCH 42/57] build(deps): bump stimulus-rails from 1.3.3 to 1.3.4 Bumps [stimulus-rails](https://github.com/hotwired/stimulus-rails) from 1.3.3 to 1.3.4. - [Release notes](https://github.com/hotwired/stimulus-rails/releases) - [Commits](https://github.com/hotwired/stimulus-rails/compare/v1.3.3...v1.3.4) --- updated-dependencies: - dependency-name: stimulus-rails dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 54039a468f..702d5cdbd8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -141,7 +141,7 @@ GEM activesupport tzinfo coderay (1.1.3) - concurrent-ruby (1.3.3) + concurrent-ruby (1.3.4) connection_pool (2.4.1) coverband (6.1.2) redis (>= 3.0) @@ -315,7 +315,7 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.7.2) - irb (1.13.2) + irb (1.14.0) rdoc (>= 4.0.0) reline (>= 0.4.2) jbuilder (2.12.0) @@ -373,7 +373,7 @@ GEM method_source (1.1.0) mini_magick (4.13.2) mini_mime (1.1.5) - minitest (5.24.1) + minitest (5.25.1) monetize (1.12.0) money (~> 6.12) money (6.16.0) @@ -660,7 +660,7 @@ GEM standard-performance (1.4.0) lint_roller (~> 1.1) rubocop-performance (~> 1.21.0) - stimulus-rails (1.3.3) + stimulus-rails (1.3.4) railties (>= 6.0.0) stringio (3.1.1) strong_migrations (1.8.0) @@ -668,7 +668,7 @@ GEM strscan (3.1.0) terser (1.2.3) execjs (>= 0.3.0, < 3) - thor (1.3.1) + thor (1.3.2) tilt (2.2.0) timeout (0.4.1) ttfunk (1.7.0) @@ -699,7 +699,7 @@ GEM xpath (3.2.0) nokogiri (~> 1.8) yard (0.9.34) - zeitwerk (2.6.16) + zeitwerk (2.6.17) PLATFORMS arm64-darwin-20 From 742bfc10a8e1b4a8e5f2b09d5e8caa17e0b28749 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 13:50:15 -0400 Subject: [PATCH 43/57] build(deps-dev): bump brakeman from 6.1.2 to 6.2.1 (#4628) Bumps [brakeman](https://github.com/presidentbeef/brakeman) from 6.1.2 to 6.2.1. - [Release notes](https://github.com/presidentbeef/brakeman/releases) - [Changelog](https://github.com/presidentbeef/brakeman/blob/main/CHANGES.md) - [Commits](https://github.com/presidentbeef/brakeman/compare/v6.1.2...v6.2.1) --- updated-dependencies: - dependency-name: brakeman dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 39090ec92c..c8a029d17d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -115,7 +115,7 @@ GEM autoprefixer-rails (>= 9.1.0) popper_js (>= 2.11.6, < 3) sassc-rails (>= 2.0.0) - brakeman (6.1.2) + brakeman (6.2.1) racc bugsnag (6.27.1) concurrent-ruby (~> 1.0) From 5d854fe9e52a5b93a0b6582e0fe25f8a77dd017d Mon Sep 17 00:00:00 2001 From: Faizah Aulia R Date: Tue, 3 Sep 2024 00:53:29 +0700 Subject: [PATCH 44/57] Fix distribution export, item columns in alphabetically order (#4617) --- app/services/exports/export_distributions_csv_service.rb | 2 +- spec/services/exports/export_distributions_csv_service_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/exports/export_distributions_csv_service.rb b/app/services/exports/export_distributions_csv_service.rb index dae6df149c..64557e3369 100644 --- a/app/services/exports/export_distributions_csv_service.rb +++ b/app/services/exports/export_distributions_csv_service.rb @@ -118,7 +118,7 @@ def base_headers def item_headers return @item_headers if @item_headers - @item_headers = @organization.items.order(:created_at).distinct.select([:created_at, :name]).map(&:name) + @item_headers = @organization.items.select("DISTINCT ON (LOWER(name)) items.name").order("LOWER(name) ASC").map(&:name) end def build_row_data(distribution) diff --git a/spec/services/exports/export_distributions_csv_service_spec.rb b/spec/services/exports/export_distributions_csv_service_spec.rb index 5d31de5c75..89c041d825 100644 --- a/spec/services/exports/export_distributions_csv_service_spec.rb +++ b/spec/services/exports/export_distributions_csv_service_spec.rb @@ -44,7 +44,7 @@ let(:item_id) { duplicate_item.id } let(:item_name) { duplicate_item.name } let(:filters) { {by_item_id: item_id} } - let(:all_org_items) { Item.where(organization:).uniq.sort_by(&:created_at) } + let(:all_org_items) { Item.where(organization:).uniq.sort_by { |item| item.name.downcase } } let(:total_item_quantities) do template = all_org_items.pluck(:name).index_with(0) From d83c6dcd1083331f298e7f1c8df7e92a7a044dd4 Mon Sep 17 00:00:00 2001 From: Brock Wilcox Date: Tue, 3 Sep 2024 11:19:52 -0400 Subject: [PATCH 45/57] Enable read-events feature in dev/staging by default (#4591) * Enable read-events feature in dev/staging by default We have manually enabled this in production * Remove more Event Sourcing separation * Minor documentation whitespace cleanup * Put back read_events check in specs This is needed just a bit longer until we completely remove the feature flag for Events --- .github/workflows/rspec-events.yml | 92 ---------------------- .github/workflows/rspec-system-events.yml | 93 ----------------------- CONTRIBUTING.md | 36 +++++---- db/seeds.rb | 2 + spec/rails_helper.rb | 4 +- 5 files changed, 20 insertions(+), 207 deletions(-) delete mode 100644 .github/workflows/rspec-events.yml delete mode 100644 .github/workflows/rspec-system-events.yml diff --git a/.github/workflows/rspec-events.yml b/.github/workflows/rspec-events.yml deleted file mode 100644 index 4d490859a7..0000000000 --- a/.github/workflows/rspec-events.yml +++ /dev/null @@ -1,92 +0,0 @@ -name: rspec-events - -on: - push: - paths-ignore: - - "doc/**" - - "*.md" - - "bin/*" - pull_request: - paths-ignore: - - "doc/**" - - "*.md" - - "bin/*" - -jobs: - rspec-events: - runs-on: ubuntu-latest - - services: - db: - image: postgres:12.3 - env: - POSTGRES_PASSWORD: password - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - # https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix - strategy: - fail-fast: false - matrix: - # Set N number of parallel jobs you want to run tests on. - # Use higher number if you have slow tests to split them on more parallel jobs. - # Remember to update ci_node_index below to 0..N-1 - ci_node_total: [2] - # set N-1 indexes for parallel jobs - # When you run 2 parallel jobs then first job will have index 0, the second job will have index 1 etc - ci_node_index: [0, 1] - steps: - - uses: actions/checkout@v4 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - - name: Install PostgreSQL client - run: | - sudo apt-get -yqq install libpq-dev - - name: Build App - env: - POSTGRES_HOST: localhost - DATABASE_HOST: localhost - PG_USERNAME: postgres - PG_PASSWORD: password - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PORT: 5432 - RAILS_ENV: test - run: | - bundle exec rake db:create - bundle exec rake db:schema:load - - name: Run rspec with events - env: - POSTGRES_HOST: localhost - DATABASE_HOST: localhost - PG_USERNAME: postgres - PG_PASSWORD: password - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PORT: 5432 - PGHOST: localhost - PGUSER: postgres - RAILS_ENV: test - KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC }} - KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }} - KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }} - KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true - KNAPSACK_PRO_LOG_LEVEL: info - KNAPSACK_PRO_TEST_FILE_EXCLUDE_PATTERN: "{spec/system/**{,/*/**}/*_spec.rb,spec/requests/**{,/*/**}/*_spec.rb}" - EVENTS_READ: true - run: | - RUBYOPT='-W:no-deprecated -W:no-experimental' bin/knapsack_pro_rspec - - name: Upload artifacts - if: ${{ failure() }} - uses: actions/upload-artifact@v4 - with: - name: failed-browser-tests - path: | - tmp/screenshots - tmp/capybara diff --git a/.github/workflows/rspec-system-events.yml b/.github/workflows/rspec-system-events.yml deleted file mode 100644 index a8ac952e31..0000000000 --- a/.github/workflows/rspec-system-events.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: rspec-system-events - -on: - push: - paths-ignore: - - "doc/**" - - "*.md" - - "bin/*" - pull_request: - paths-ignore: - - "doc/**" - - "*.md" - - "bin/*" - -jobs: - rspec-system-events: - runs-on: ubuntu-latest - - services: - db: - image: postgres:12.3 - env: - POSTGRES_PASSWORD: password - ports: - - 5432:5432 - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - # https://help.github.com/en/articles/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix - strategy: - fail-fast: false - matrix: - # Set N number of parallel jobs you want to run tests on. - # Use higher number if you have slow tests to split them on more parallel jobs. - # Remember to update ci_node_index below to 0..N-1 - ci_node_total: [6] - # set N-1 indexes for parallel jobs - # When you run 2 parallel jobs then first job will have index 0, the second job will have index 1 etc - ci_node_index: [0, 1, 2, 3, 4, 5] - steps: - - uses: actions/checkout@v4 - - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - bundler-cache: true - - - name: Install PostgreSQL client - run: | - sudo apt-get -yqq install libpq-dev - - name: Build App with asset compilation - env: - POSTGRES_HOST: localhost - DATABASE_HOST: localhost - PG_USERNAME: postgres - PG_PASSWORD: password - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PORT: 5432 - RAILS_ENV: test - run: | - bundle exec rake db:create - bundle exec rake db:schema:load - bundle exec rails assets:precompile - - name: Run rspec with events - env: - POSTGRES_HOST: localhost - DATABASE_HOST: localhost - PG_USERNAME: postgres - PG_PASSWORD: password - POSTGRES_HOST_AUTH_METHOD: trust - POSTGRES_PORT: 5432 - PGHOST: localhost - PGUSER: postgres - RAILS_ENV: test - KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC: ${{ secrets.KNAPSACK_PRO_TEST_SUITE_TOKEN_RSPEC }} - KNAPSACK_PRO_CI_NODE_TOTAL: ${{ matrix.ci_node_total }} - KNAPSACK_PRO_CI_NODE_INDEX: ${{ matrix.ci_node_index }} - KNAPSACK_PRO_RSPEC_SPLIT_BY_TEST_EXAMPLES: true - KNAPSACK_PRO_LOG_LEVEL: info - KNAPSACK_PRO_TEST_FILE_PATTERN: "{spec/system/**{,/*/**}/*_spec.rb,spec/requests/**{,/*/**}/*_spec.rb}" - EVENTS_READ: true - run: | - RUBYOPT='-W:no-deprecated -W:no-experimental' bin/knapsack_pro_rspec - - name: Upload artifacts - if: ${{ failure() }} - uses: actions/upload-artifact@v4 - with: - name: failed-browser-tests - path: | - tmp/capybara - tmp/screenshots diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f8a23fd295..fef2335cc1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,8 +9,8 @@ If you're new here, here are some things you should know: - This project relies entirely on volunteers, so please be patient with communication # Communication 💬 -If you have any questions about an issue, comment on the issue, open a new issue, or ask in [the RubyForGood slack](https://join.slack.com/t/rubyforgood/shared_invite/zt-2k5ezv241-Ia2Iac3amxDS8CuhOr69ZA). human-essentials has a `#human-essentials` channel in the Slack. Our channel in slack also contains a zoom link for office hours every day office hours are held. - +If you have any questions about an issue, comment on the issue, open a new issue, or ask in [the RubyForGood slack](https://join.slack.com/t/rubyforgood/shared_invite/zt-2k5ezv241-Ia2Iac3amxDS8CuhOr69ZA). human-essentials has a `#human-essentials` channel in the Slack. Our channel in slack also contains a zoom link for office hours every day office hours are held. + Many helpful members are available to answer your questions. Just ask, and someone will be there to help you! You won't be yelled at for giving your best effort. The worst that can happen is that you'll be politely asked to change something. We appreciate any sort of contributions, and don't want a wall of rules to get in the way of that. @@ -37,7 +37,7 @@ Make sure to install **Ubuntu** as your Linux distribution. (This should be defa 4. Run `bin/setup` 5. Run `bin/start` and visit http://localhost:3000/ to see the human essentials page. 6. Log in as a sample user with the default [credentials](#credentials). - + ## Credentials These credentials also work for [staging](https://staging.humanessentials.app/): @@ -97,7 +97,7 @@ Make sure to install **Ubuntu** as your Linux distribution. (This should be defa - Or follow instructions to [create a new Codespace.](https://docs.github.com/en/codespaces/developing-in-a-codespace/creating-a-codespace-for-a-repository) - To clone this repo and run the container locally, follow instructions to [install VSCode and Docker](https://code.visualstudio.com/docs/devcontainers/containers). Click the Dev Container link above. Don't forget to add a git remote pointing to your fork once the container is setup and you want to push changes. 2. Wait for the container to start. This will take a few (10-15) minutes since Ruby needs to be installed, the database needs to be created, and the `bin/setup` script needs to run -3. Run `bin/start`. On the Ports tab, visit the forwarded port 3000 URL marked as Application to see the human essentials page. +3. Run `bin/start`. On the Ports tab, visit the forwarded port 3000 URL marked as Application to see the human essentials page. 4. Login as a sample user with the default [credentials](#credentials). ## Troubleshooting 👷🏼‍♀️ @@ -126,21 +126,21 @@ Please let us know by opening up an issue! We have many new contributors come th 10. **Squash smaller commits.** Read guidelines [here](#squashing-commits). 11. **Push** up the branch 12. **Create a pull request** and indicate the addressed issue (e.g. `Resolves #1`) in the title, which will ensure the issue gets closed automatically when the pull request gets merged. Read PR guidelines [here](#pull-requests). -13. **Code review**: At this point, someone will work with you on doing a code review. The automated tests will run linting, rspec, and brakeman tests. If the automated tests give :+1: to the PR merging, we can then do any additional (staging) testing as needed. +13. **Code review**: At this point, someone will work with you on doing a code review. The automated tests will run linting, rspec, and brakeman tests. If the automated tests give :+1: to the PR merging, we can then do any additional (staging) testing as needed. -14. **Merge**: Finally if all looks good the core team will merge your code in; if your feature branch was in this main repository, the branch will be deleted after the PR is merged. +14. **Merge**: Finally if all looks good the core team will merge your code in; if your feature branch was in this main repository, the branch will be deleted after the PR is merged. 15. Deploys are currently done about once a week! Read the deployment process [here](#deployment-process). -## Issues +## Issues Please feel free to contribute! While we welcome all contributions to this app, pull-requests that address outstanding Issues *and* have appropriate test coverage for them will be strongly prioritized. In particular, addressing issues that are tagged with the next milestone should be prioritized higher. -All work is organized by issues. -[Find issues here.](https://github.com/rubyforgood/human-essentials/issues) +All work is organized by issues. +[Find issues here.](https://github.com/rubyforgood/human-essentials/issues) -If you would like to contribute, please ask for an issue to be assigned to you. -If you would like to contribute something that is not represented by an issue, please make an issue and assign yourself. -Only take multiple issues if they are related and you can solve all of them at the same time with the same pull request. +If you would like to contribute, please ask for an issue to be assigned to you. +If you would like to contribute something that is not represented by an issue, please make an issue and assign yourself. +Only take multiple issues if they are related and you can solve all of them at the same time with the same pull request. ## Becoming a Repo Contributor @@ -165,7 +165,7 @@ Consider the balance of "polluting the git log with commit messages" vs. "provid Only commit the schema.rb only if you have committed anything that would change the DB schema (i.e. a migration). -## Pull Requests +## Pull Requests ### Stay scoped Try to keep your PRs limited to one particular issue, and don't make changes that are out of scope for that issue. If you notice something that needs attention but is out of scope, please [create a new issue](https://github.com/rubyforgood/human-essentials/issues/new). @@ -184,7 +184,6 @@ If you are inexperienced in writing tests or get stuck on one, please reach out #### Guidelines - Prefer request tests over system tests (which run much slower) unless you need to test Javascript or other interactivity - When creating factories, in each RSpec test, hard code all values that you check with a RSpec matcher. Don't check FactoryBot default values. See [#4217](https://github.com/rubyforgood/human-essentials/issues/4217) for why. -- Write tests to pass with Event Sourcing turned both on and off, see the [Event Sourcing wiki page](https://github.com/rubyforgood/human-essentials/wiki/Event-Sourcing). - Keep individual tests tightly scoped, only test the endpoint that you want to test. E.g. create inventory directly using `TestInventory` rather than using an additional endpoint. - You probably don't need to write new tests when simple re-stylings are done (ie. the page may look slightly different but the Test suite is unaffected by those changes). @@ -199,7 +198,7 @@ If you are inexperienced in writing tests or get stuck on one, please reach out magic_test end ``` - and run the spec using this command: + and run the spec using this command: ``` MAGIC_TEST=1 NOT_HEADLESS=true bundle exec rspec ` ``` @@ -210,13 +209,12 @@ If you are inexperienced in writing tests or get stuck on one, please reach out Before submitting a pull request, run all tests and lints. Fix any broken tests and lints before submitting a pull request. #### Continuous Integration -- There are Github Actions workflows which will run all tests with and without Event Sourcing in parallel using Knapsack and lints whenever you push a commit to your fork. +- There are Github Actions workflows which will run all tests in parallel using Knapsack and lints whenever you push a commit to your fork. - Once your first PR has been merged, all commits pushed to an open PR will also run these workflows. #### Local testing -- Run all lints with `bin/lint`. -- Run all tests without Event Sourcing with `bundle exec rspec` -- Run all tests with Event Sourcing with `EVENTS_READ=true bundle exec rspec` +- Run all lints with `bin/lint`. +- Run all tests with `bundle exec rspec` - You can run a single test with `bundle exec rspec {path_to_test_name}_spec.rb` or on a specific line by appending `:LineNumber` - If you need to skip a failing test, place `pending("Reason you are skipping the test")` into the `it` block rather than skipping with `xit`. This will allow rspec to deliver the error message without causing the test suite to fail. diff --git a/db/seeds.rb b/db/seeds.rb index 614143cbd0..3d89c8606a 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -707,6 +707,8 @@ def seed_quantity(item_name, organization, storage_location, quantity) # ---------------------------------------------------------------------------- Flipper::Adapters::ActiveRecord::Feature.find_or_create_by(key: "new_logo") +Flipper::Adapters::ActiveRecord::Feature.find_or_create_by(key: "read_events") +Flipper.enable(:read_events) # ---------------------------------------------------------------------------- # Account Requests diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index ec498f97c3..a8130707cd 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -171,9 +171,7 @@ def self.capybara_tmp_path end config.before(:each) do - if ENV['EVENTS_READ'] == 'true' - allow(Event).to receive(:read_events?).and_return(true) - end + allow(Event).to receive(:read_events?).and_return(true) end config.before do From df9a1bed38c05b71a2457d5c48d1a16f2243d5a4 Mon Sep 17 00:00:00 2001 From: Aaryanpal Date: Thu, 5 Sep 2024 01:31:23 +0530 Subject: [PATCH 46/57] Relocate product drives menu items under Community and fix system test for navigation --- app/views/layouts/_lte_sidebar.html.erb | 35 +++++++++---------------- spec/system/navigation_system_spec.rb | 2 +- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/app/views/layouts/_lte_sidebar.html.erb b/app/views/layouts/_lte_sidebar.html.erb index 6fea6b23db..7c1c4a0af5 100644 --- a/app/views/layouts/_lte_sidebar.html.erb +++ b/app/views/layouts/_lte_sidebar.html.erb @@ -5,27 +5,6 @@

Dashboard

<% end %> - - + +