diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..1d085cacc9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +** diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index 82aa5567f7..a1c364bb68 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -8,7 +8,7 @@ def index .undiscarded .during(helpers.selected_range) .class_filter(filter_params) - @unfulfilled_requests_count = current_organization.requests.where(status: [:pending, :started]).count + @unfulfilled_requests_count = current_organization.requests.where(status: [:pending, :started]).during(helpers.selected_range).class_filter(filter_params).count @paginated_requests = @requests.includes(:partner).page(params[:page]) @calculate_product_totals = RequestsTotalItemsService.new(requests: @requests).calculate @items = current_organization.items.alphabetized.select(:id, :name) @@ -65,6 +65,8 @@ def print_unfulfilled .includes(:item_requests, partner: [:profile]) .where(status: [:pending, :started]) .order(created_at: :desc) + .during(helpers.selected_range) + .class_filter(filter_params) respond_to do |format| format.any do diff --git a/app/pdfs/picklists_pdf.rb b/app/pdfs/picklists_pdf.rb index 63e03f3eb8..8d91d69d2b 100644 --- a/app/pdfs/picklists_pdf.rb +++ b/app/pdfs/picklists_pdf.rb @@ -1,6 +1,6 @@ require "prawn/table" -# Configures a Prawn PDF template for generating Distribution manifests +# Configures a Prawn PDF template for generating Picklist pdfs class PicklistsPdf include Prawn::View include ItemsHelper diff --git a/app/views/requests/index.html.erb b/app/views/requests/index.html.erb index 74c48d3ea7..57462d00f5 100644 --- a/app/views/requests/index.html.erb +++ b/app/views/requests/index.html.erb @@ -69,7 +69,7 @@
<% if @unfulfilled_requests_count > 0 %> <%= print_button_to( - print_unfulfilled_requests_path(format: :pdf), + print_unfulfilled_requests_path(format: :pdf, filters: filter_params.merge(date_range: date_range_params)), text: "Print Unfulfilled Picklists (#{@unfulfilled_requests_count})", size: "md") %> <% end %> diff --git a/lib/test_helpers/pdf_comparison_test_factory.rb b/lib/test_helpers/pdf_comparison_test_factory.rb index 8a1b3796d5..77ba43a76b 100644 --- a/lib/test_helpers/pdf_comparison_test_factory.rb +++ b/lib/test_helpers/pdf_comparison_test_factory.rb @@ -4,7 +4,7 @@ module PDFComparisonTestFactory extend ActiveSupport::Testing::TimeHelpers StorageCreation = Data.define(:organization, :storage_location, :items) - FilePaths = Data.define(:expected_pickup_file_path, :expected_same_address_file_path, :expected_different_address_file_path, :expected_incomplete_address_file_path, :expected_no_contact_file_path) + FilePaths = Data.define(:expected_pickup_file_path, :expected_same_address_file_path, :expected_different_address_file_path, :expected_incomplete_address_file_path, :expected_no_contact_file_path, :expected_picklist_file_path) def self.get_logo_file Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures/files/logo.jpg"), "image/jpeg") @@ -41,17 +41,30 @@ def self.create_partner(organization) Partner.create!(name: "Leslie Sue", organization: organization, email: "leslie1@gmail.com") end + def self.create_partner_with_quota(organization) + Partner.create!(name: "Leslie Sue", organization: organization, email: "leslie1@gmail.com", quota: 100) + end + def self.get_file_paths expected_pickup_file_path = Rails.root.join("spec", "fixtures", "files", "distribution_pickup.pdf") expected_same_address_file_path = Rails.root.join("spec", "fixtures", "files", "distribution_same_address.pdf") expected_different_address_file_path = Rails.root.join("spec", "fixtures", "files", "distribution_program_address.pdf") expected_incomplete_address_file_path = Rails.root.join("spec", "fixtures", "files", "distribution_incomplete_address.pdf") expected_no_contact_file_path = Rails.root.join("spec", "fixtures", "files", "distribution_no_contact.pdf") - FilePaths.new(expected_pickup_file_path, expected_same_address_file_path, expected_different_address_file_path, expected_incomplete_address_file_path, expected_no_contact_file_path) + expected_picklist_file_path = Rails.root.join("spec", "fixtures", "files", "picklist.pdf") + + FilePaths.new( + expected_pickup_file_path, + expected_same_address_file_path, + expected_different_address_file_path, + expected_incomplete_address_file_path, + expected_no_contact_file_path, + expected_picklist_file_path + ) end private_class_method def self.create_profile(partner:, program_address1:, program_address2:, program_city:, program_state:, program_zip:, - address1: "Example Address 1", city: "Example City", state: "Example State", zip: "12345", primary_contact_name: "Jaqueline Kihn DDS", primary_contact_email: "van@durgan.example") + address1: "Example Address 1", city: "Example City", state: "Example State", zip: "12345", primary_contact_name: "Jaqueline Kihn DDS", primary_contact_email: "van@durgan.example", pick_up_name: nil, pick_up_email: nil, pick_up_phone: nil) Partners::Profile.create!( partner_id: partner.id, essentials_bank_id: partner.organization.id, @@ -66,7 +79,10 @@ def self.get_file_paths program_address2: program_address2, program_city: program_city, program_state: program_state, - program_zip_code: program_zip + program_zip_code: program_zip, + pick_up_name: pick_up_name, + pick_up_email: pick_up_email, + pick_up_phone: pick_up_phone ) end @@ -90,9 +106,26 @@ def self.create_profile_no_contact_with_program_address(partner) create_profile(partner: partner, program_address1: "Example Program Address 1", program_address2: "", program_city: "Example Program City", program_state: "Example Program State", program_zip: 54321, primary_contact_name: "", primary_contact_email: "") end - def self.create_line_items_request(distribution, partner, storage_creation) + def self.create_profile_with_pickup_person(partner) + create_profile( + partner: partner, + pick_up_name: "Pickup Person", + pick_up_email: "pickup@example.com", + pick_up_phone: "1234567890", + program_address1: "Example Program Address 1", + program_address2: "", + program_city: "Example Program City", + program_state: "Example Program State", + program_zip: 54321 + ) + end + + def self.create_line_items_for_distribution(distribution, storage_creation) LineItem.create!(itemizable: distribution, item: storage_creation.items[0], quantity: 50) LineItem.create!(itemizable: distribution, item: storage_creation.items[1], quantity: 100) + end + + def self.create_line_items_request(partner:, storage_creation:, distribution: nil) storage_creation.organization.request_units.find_or_create_by!(name: "pack") ItemUnit.find_or_create_by!(item: storage_creation.items[3], name: "pack") req1 = Partners::ItemRequest.new(item: storage_creation.items[1], quantity: 30, name: storage_creation.items[1].name, partner_key: storage_creation.items[1].partner_key) @@ -107,30 +140,48 @@ def self.create_line_items_request(distribution, partner, storage_creation) {"item_id" => storage_creation.items[2].id, "quantity" => 50}, {"item_id" => storage_creation.items[3].id, "quantity" => 120, "request_unit" => "pack"} ], - item_requests: [req1, req2, req3] + item_requests: [req1, req2, req3], + created_at: Time.zone.local(2024, 12, 30, 0, 0, 0) ) end def self.create_dist(partner, storage_creation, delivery_method) Time.zone = "America/Los_Angeles" dist = Distribution.create!(id: 123, partner: partner, delivery_method: delivery_method, issued_at: DateTime.new(2024, 7, 4, 0, 0, 0, "-07:00"), organization: storage_creation.organization, storage_location: storage_creation.storage_location) - create_line_items_request(dist, partner, storage_creation) + create_line_items_for_distribution(dist, storage_creation) + create_line_items_request(distribution: dist, partner: partner, storage_creation: storage_creation) dist end - def self.render_pdf_at_year_end(organization, distribution) + def self.render_distribution_pdf_at_year_end(organization, distribution) travel_to(Time.zone.local(2024, 12, 30, 0, 0, 0)) do return DistributionPdf.new(organization, distribution).compute_and_render end end - private_class_method def self.create_comparison_pdf(storage_creation, profile_create_method, expected_file_path, delivery_method) + def self.render_picklist_pdf(organization, requests) + PicklistsPdf.new(organization, requests).compute_and_render + end + + private_class_method def self.create_distribution_comparison_pdf(storage_creation, profile_create_method, expected_file_path, delivery_method) # Partner creation must be rolled back otherwise Items requested YTD will accumulate ActiveRecord::Base.transaction(requires_new: true) do partner = create_partner(storage_creation.organization) PDFComparisonTestFactory.public_send(profile_create_method, partner) dist = create_dist(partner, storage_creation, delivery_method) - pdf_file = render_pdf_at_year_end(storage_creation.organization, dist) + pdf_file = render_distribution_pdf_at_year_end(storage_creation.organization, dist) + File.binwrite(expected_file_path, pdf_file) + raise ActiveRecord::Rollback + end + end + + private_class_method def self.create_picklist_comparison_pdf(storage_creation, partner_create_method, profile_create_method, expected_file_path) + # Partner creation must be rolled back otherwise Items requested YTD will accumulate + ActiveRecord::Base.transaction(requires_new: true) do + partner = PDFComparisonTestFactory.public_send(partner_create_method, storage_creation.organization) + PDFComparisonTestFactory.public_send(profile_create_method, partner) + request = create_line_items_request(partner: partner, storage_creation: storage_creation) + pdf_file = render_picklist_pdf(storage_creation.organization, [request]) File.binwrite(expected_file_path, pdf_file) raise ActiveRecord::Rollback end @@ -151,11 +202,13 @@ def self.create_comparison_pdfs ActiveRecord::Base.transaction do storage_creation = create_organization_storage_items(logo) - create_comparison_pdf(storage_creation, :create_profile_no_address, file_paths.expected_pickup_file_path, :pick_up) - create_comparison_pdf(storage_creation, :create_profile_without_program_address, file_paths.expected_same_address_file_path, :shipped) - create_comparison_pdf(storage_creation, :create_profile_with_program_address, file_paths.expected_different_address_file_path, :delivery) - create_comparison_pdf(storage_creation, :create_profile_with_incomplete_address, file_paths.expected_incomplete_address_file_path, :delivery) - create_comparison_pdf(storage_creation, :create_profile_no_contact_with_program_address, file_paths.expected_no_contact_file_path, :delivery) + create_distribution_comparison_pdf(storage_creation, :create_profile_no_address, file_paths.expected_pickup_file_path, :pick_up) + create_distribution_comparison_pdf(storage_creation, :create_profile_without_program_address, file_paths.expected_same_address_file_path, :shipped) + create_distribution_comparison_pdf(storage_creation, :create_profile_with_program_address, file_paths.expected_different_address_file_path, :delivery) + create_distribution_comparison_pdf(storage_creation, :create_profile_with_incomplete_address, file_paths.expected_incomplete_address_file_path, :delivery) + create_distribution_comparison_pdf(storage_creation, :create_profile_no_contact_with_program_address, file_paths.expected_no_contact_file_path, :delivery) + + create_picklist_comparison_pdf(storage_creation, :create_partner_with_quota, :create_profile_with_pickup_person, file_paths.expected_picklist_file_path) raise ActiveRecord::Rollback end diff --git a/spec/fixtures/files/picklist.pdf b/spec/fixtures/files/picklist.pdf new file mode 100644 index 0000000000..216a6f10c6 Binary files /dev/null and b/spec/fixtures/files/picklist.pdf differ diff --git a/spec/pdfs/distribution_pdf_spec.rb b/spec/pdfs/distribution_pdf_spec.rb index 765dc1a825..0086dccd82 100644 --- a/spec/pdfs/distribution_pdf_spec.rb +++ b/spec/pdfs/distribution_pdf_spec.rb @@ -17,7 +17,8 @@ let(:partner) { create(:partner) } before(:each) do - PDFComparisonTestFactory.create_line_items_request(distribution, partner, storage_creation) + PDFComparisonTestFactory.create_line_items_for_distribution(distribution, storage_creation) + PDFComparisonTestFactory.create_line_items_request(distribution: distribution, partner: partner, storage_creation: storage_creation) end specify "#request_data with custom units feature" do @@ -133,7 +134,7 @@ describe "address pdf output" do def compare_pdf(distribution, expected_file_path) - pdf_file = PDFComparisonTestFactory.render_pdf_at_year_end(organization, distribution) + pdf_file = PDFComparisonTestFactory.render_distribution_pdf_at_year_end(organization, distribution) begin # Run the following from Rails sandbox console (bin/rails/console --sandbox) to regenerate these comparison PDFs: # => load "lib/test_helpers/pdf_comparison_test_factory.rb" diff --git a/spec/pdfs/picklists_pdf_spec.rb b/spec/pdfs/picklists_pdf_spec.rb index 49171f5fc8..b79d4c1925 100644 --- a/spec/pdfs/picklists_pdf_spec.rb +++ b/spec/pdfs/picklists_pdf_spec.rb @@ -1,3 +1,5 @@ +require_relative("../../lib/test_helpers/pdf_comparison_test_factory") + describe PicklistsPdf do let(:organization) { create(:organization) } let(:item1) { create(:item, name: "Item 1", organization: organization) } @@ -141,4 +143,42 @@ ]) end end + + describe "picklist pdf output" do + def compare_picklist_pdf(requests, expected_file_path) + pdf_file = PDFComparisonTestFactory.render_picklist_pdf(organization, requests) + begin + # Run the following from Rails sandbox console (bin/rails/console --sandbox) to regenerate these comparison PDFs: + # => load "lib/test_helpers/pdf_comparison_test_factory.rb" + # => Flipper.enable(:enable_packs) + # => PDFComparisonTestFactory.create_comparison_pdfs + expect(pdf_file).to eq(IO.binread(expected_file_path)) + rescue RSpec::Expectations::ExpectationNotMetError => e + Rails.root.join("tmp", "failed_match_picklist_" + expected_file_path.to_s.split("/").last + ".pdf").binwrite(pdf_file) + raise e.class, "PDF does not match, written to tmp/", cause: nil + end + end + + # The generated PDFs (PDFs to use for comparison) are expecting the packs feature to be enabled. + before(:each) do + Flipper.enable(:enable_packs) + end + + let(:storage_creation) { PDFComparisonTestFactory.create_organization_storage_items } + let(:organization) { storage_creation.organization } + let(:partner) { PDFComparisonTestFactory.create_partner_with_quota(organization) } + let(:file_paths) { PDFComparisonTestFactory.get_file_paths } + let(:expected_picklist_file_path) { file_paths.expected_picklist_file_path } + + context "when generating picklist PDF with comprehensive data" do + before(:each) do + PDFComparisonTestFactory.create_profile_with_pickup_person(partner) + end + + it "compares against expected PDF file" do + request = PDFComparisonTestFactory.create_line_items_request(partner: partner, storage_creation: storage_creation) + compare_picklist_pdf([request], expected_picklist_file_path) + end + end + end end diff --git a/spec/requests/requests_requests_spec.rb b/spec/requests/requests_requests_spec.rb index 6ff8095bfc..8ad8c05403 100644 --- a/spec/requests/requests_requests_spec.rb +++ b/spec/requests/requests_requests_spec.rb @@ -41,6 +41,21 @@ expect(response.body).to include('Print Unfulfilled Picklists (2)') end end + + context "when there is a filter applied" do + it "shows only filtered requests, print unfulfilled picklists button with correct quantity" do + Request.delete_all + + create(:request, :started, comments: "Started request - should appear") + create(:request, :pending, comments: "Pending request - should not appear") + + get requests_path({ filters: { by_status: :started} }) + + expect(response.body).to include("Print Unfulfilled Picklists (1)") + expect(response.body).to include("Started request - should appear") + expect(response.body).not_to include("Pending request - should not appear") + end + end end describe 'GET #show' do