diff --git a/app/controllers/concerns/importable.rb b/app/controllers/concerns/importable.rb
index f2bd1515bb..67e5644584 100644
--- a/app/controllers/concerns/importable.rb
+++ b/app/controllers/concerns/importable.rb
@@ -27,11 +27,15 @@ def import_csv
data = File.read(params[:file].path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
if csv.count.positive? && csv.first.headers.all? { |header| !header.nil? }
- errors = resource_model.import_csv(csv, current_organization.id)
- if errors.empty?
+ results = resource_model.import_csv(csv, current_organization.id)
+ if results[:errors].empty?
flash[:notice] = "#{resource_model_humanized} were imported successfully!"
else
- flash[:error] = "The following #{resource_model_humanized} did not import successfully:\n#{errors.join("\n")}"
+ flash[:error] = "The following #{resource_model_humanized} did not import successfully:\n#{results[:errors].join("\n")}"
+ end
+
+ if results[:warnings].present?
+ flash[:alert] = "The following #{resource_model_humanized} imported with warnings:\n#{results[:warnings].join("\n")}"
end
else
flash[:error] = "Check headers in file!"
diff --git a/app/models/concerns/provideable.rb b/app/models/concerns/provideable.rb
index 5f25f61810..5105c8b770 100644
--- a/app/models/concerns/provideable.rb
+++ b/app/models/concerns/provideable.rb
@@ -15,7 +15,8 @@ def self.import_csv(csv, organization)
loc.save!
end
- []
+
+ {errors: [], warnings: []}
end
def self.csv_export_headers
diff --git a/app/models/donation_site.rb b/app/models/donation_site.rb
index cc79d2f46e..83ab6382be 100644
--- a/app/models/donation_site.rb
+++ b/app/models/donation_site.rb
@@ -38,6 +38,7 @@ class DonationSite < ApplicationRecord
def self.import_csv(csv, organization)
errors = []
+
csv.each_with_index do |row, index|
loc = DonationSite.new(row.to_hash)
loc.organization_id = organization
@@ -47,7 +48,8 @@ def self.import_csv(csv, organization)
errors << "Row #{index + 2}, #{row.to_hash["name"]} - #{loc.errors.full_messages.join(", ")}"
end
end
- errors
+
+ {errors: errors, warnings: []}
end
def self.csv_export_headers
diff --git a/app/models/partner.rb b/app/models/partner.rb
index cbbd55e71b..3bcf64307f 100644
--- a/app/models/partner.rb
+++ b/app/models/partner.rb
@@ -56,6 +56,7 @@ class Partner < ApplicationRecord
validate :correct_document_mime_type
before_save { email&.downcase! }
+ before_create :default_send_reminders_to_false, if: :send_reminders_nil?
before_update :invite_new_partner, if: :should_invite_because_email_changed?
scope :alphabetized, -> { order(:name) }
@@ -103,18 +104,30 @@ def approvable?
# better to extract this outside of the model
def self.import_csv(csv, organization_id)
errors = []
+ warnings = []
organization = Organization.find(organization_id)
csv.each do |row|
hash_rows = Hash[row.to_hash.map { |k, v| [k.downcase, v] }]
- svc = PartnerCreateService.new(organization: organization, partner_attrs: hash_rows)
- svc.call
- if svc.errors.present?
- errors << "#{svc.partner.name}: #{svc.partner.errors.full_messages.to_sentence}"
+ partner_create_service = PartnerCreateService.new(organization: organization, partner_attrs: hash_rows)
+ partner_create_service.call
+
+ if partner_create_service.errors.present?
+ formatted_errors = partner_create_service.errors.map do |error|
+ "#{error.attribute.to_s.humanize} #{error.message.downcase}"
+ end
+ errors << "#{partner_create_service.partner.name}: #{formatted_errors.to_sentence}"
+
+ elsif partner_create_service.warnings.present?
+ formatted_warnings = partner_create_service.warnings.map do |warning|
+ "#{warning.attribute.to_s.humanize} #{warning.message.downcase}"
+ end
+ warnings << "#{partner_create_service.partner.name}: #{formatted_warnings.to_sentence}"
end
end
- errors
+
+ {errors: errors, warnings: warnings}
end
def partials_to_show
@@ -165,6 +178,14 @@ def correct_document_mime_type
end
end
+ def default_send_reminders_to_false
+ self.send_reminders = false
+ end
+
+ def send_reminders_nil?
+ send_reminders.nil?
+ end
+
def invite_new_partner
UserInviteService.invite(email: email, roles: [Role::PARTNER], resource: self)
end
diff --git a/app/models/storage_location.rb b/app/models/storage_location.rb
index 450002fa57..62ba6fd5c5 100644
--- a/app/models/storage_location.rb
+++ b/app/models/storage_location.rb
@@ -124,7 +124,8 @@ def self.import_csv(csv, organization)
loc.organization_id = organization
loc.save!
end
- []
+
+ {errors: [], warnings: []}
end
# NOTE: We should generalize this elsewhere -- Importable concern?
diff --git a/app/services/partner_create_service.rb b/app/services/partner_create_service.rb
index 6b81bfae59..bfc2b29b8c 100644
--- a/app/services/partner_create_service.rb
+++ b/app/services/partner_create_service.rb
@@ -9,6 +9,8 @@ def initialize(organization:, partner_attrs:)
end
def call
+ process_default_storage_location
+
@partner = organization.partners.build(partner_attrs)
if @partner.valid?
@@ -37,5 +39,27 @@ def call
private
+ def process_default_storage_location
+ return unless partner_attrs.has_key?("default_storage_location")
+
+ if partner_attrs["default_storage_location"].blank?
+ partner_attrs.delete("default_storage_location")
+ else
+ default_storage_location_name = partner_attrs["default_storage_location"]&.titlecase
+ default_storage_location_id = StorageLocation.find_by(
+ name: default_storage_location_name,
+ organization: organization.id
+ )&.id
+
+ if default_storage_location_id.nil?
+ add_warning(:default_storage_location,
+ "is not a storage location for this partner's organization")
+ end
+
+ partner_attrs.delete("default_storage_location")
+ partner_attrs["default_storage_location_id"] = default_storage_location_id
+ end
+ end
+
attr_reader :organization, :partner_attrs
end
diff --git a/app/services/service_object_errors_mixin.rb b/app/services/service_object_errors_mixin.rb
index 07338a62ee..714e2450db 100644
--- a/app/services/service_object_errors_mixin.rb
+++ b/app/services/service_object_errors_mixin.rb
@@ -31,6 +31,14 @@ def errors
@errors ||= ActiveModel::Errors.new(self)
end
+ def warnings
+ @warnings ||= ActiveModel::Errors.new(self)
+ end
+
+ def add_warning(attribute, message)
+ warnings.add(attribute, message)
+ end
+
def read_attribute_for_validation(attr)
send(attr)
end
@@ -45,4 +53,3 @@ def lookup_ancestors
end
end
end
-
diff --git a/app/views/dashboard/_getting_started_prompt.html.erb b/app/views/dashboard/_getting_started_prompt.html.erb
index 7c745cfef0..53f655dbcb 100644
--- a/app/views/dashboard/_getting_started_prompt.html.erb
+++ b/app/views/dashboard/_getting_started_prompt.html.erb
@@ -59,5 +59,17 @@
<%= button_to "Dismiss", "/manage", method: :patch, params: {organization: { bank_is_set_up: true }}, class: "btn btn-primary" %>
+ <%= render(
+ layout: "shared/csv_import_modal",
+ locals: {
+ import_type: "Partners",
+ csv_template_url: "/partners_template_updated.csv",
+ csv_import_url: import_csv_partners_path,
+ },
+ ) do %>
+
Open the CSV file with Excel or your favourite spreadsheet program.
+ Delete the sample data and enter your partner agency names and addresses in the appropriate columns.
+ Save the file as a CSV file.
+ <% end %>
<% end %>
<% end %>
diff --git a/app/views/partners/index.html.erb b/app/views/partners/index.html.erb
index ce3fc6def8..7215f8ed00 100644
--- a/app/views/partners/index.html.erb
+++ b/app/views/partners/index.html.erb
@@ -56,7 +56,7 @@
layout: "shared/csv_import_modal",
locals: {
import_type: "Partners",
- csv_template_url: "/partners_template.csv",
+ csv_template_url: "/partners_template_updated.csv",
csv_import_url: import_csv_partners_path
}
) do %>
diff --git a/public/partners_template.csv b/public/partners_template.csv
deleted file mode 100644
index bb62004176..0000000000
--- a/public/partners_template.csv
+++ /dev/null
@@ -1,4 +0,0 @@
-name,email
-Partner 1,partner1@example.com
-Partner 2,partner2@example.com
-Partner 3,partner3@example.com
\ No newline at end of file
diff --git a/public/partners_template_updated.csv b/public/partners_template_updated.csv
new file mode 100644
index 0000000000..17ac82af17
--- /dev/null
+++ b/public/partners_template_updated.csv
@@ -0,0 +1,4 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 1,partner1@example.com,"Smithsonian Conservation Center",false,20,"test note 1"
+Partner 2,partner2@example.com,"Smithsonian Conservation Center",false,30,"test note 2"
+Partner 3,partner3@example.com,"Smithsonian Conservation Center",true,10,"test note 3"
\ No newline at end of file
diff --git a/spec/fixtures/files/partners.csv b/spec/fixtures/files/partners.csv
deleted file mode 100644
index bb62004176..0000000000
--- a/spec/fixtures/files/partners.csv
+++ /dev/null
@@ -1,4 +0,0 @@
-name,email
-Partner 1,partner1@example.com
-Partner 2,partner2@example.com
-Partner 3,partner3@example.com
\ No newline at end of file
diff --git a/spec/fixtures/files/partners_missing_default_storage_location_field.csv b/spec/fixtures/files/partners_missing_default_storage_location_field.csv
new file mode 100644
index 0000000000..a3ad3a6abb
--- /dev/null
+++ b/spec/fixtures/files/partners_missing_default_storage_location_field.csv
@@ -0,0 +1,3 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 51,partner51@example.com,,false,50,"great partner"
+
diff --git a/spec/fixtures/files/partners_missing_default_storage_location_field_and_header.csv b/spec/fixtures/files/partners_missing_default_storage_location_field_and_header.csv
new file mode 100644
index 0000000000..986cd8d6c0
--- /dev/null
+++ b/spec/fixtures/files/partners_missing_default_storage_location_field_and_header.csv
@@ -0,0 +1,2 @@
+name,email,send_reminders,quota,notes
+Partner 71,partner71@example.com,false,50,"great partner"
diff --git a/spec/fixtures/files/partners_missing_send_reminders_field.csv b/spec/fixtures/files/partners_missing_send_reminders_field.csv
new file mode 100644
index 0000000000..33dc94979e
--- /dev/null
+++ b/spec/fixtures/files/partners_missing_send_reminders_field.csv
@@ -0,0 +1,3 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 51,partner51@example.com,"Smithsonian Conservation Center",,50,"great partner"
+
diff --git a/spec/fixtures/files/partners_missing_send_reminders_field_and_header.csv b/spec/fixtures/files/partners_missing_send_reminders_field_and_header.csv
new file mode 100644
index 0000000000..b29569b895
--- /dev/null
+++ b/spec/fixtures/files/partners_missing_send_reminders_field_and_header.csv
@@ -0,0 +1,3 @@
+name,email,default_storage_location,quota,notes
+Partner 51,partner51@example.com,"Smithsonian Conservation Center",50,"great partner"
+
diff --git a/spec/fixtures/files/partners_with_bom_encoding.csv b/spec/fixtures/files/partners_with_bom_encoding.csv
index 36d82c5129..a2d24f2914 100644
--- a/spec/fixtures/files/partners_with_bom_encoding.csv
+++ b/spec/fixtures/files/partners_with_bom_encoding.csv
@@ -1,21 +1,21 @@
-name,email
-Beaverton Police Department,krodriguez@beavertonoregon.gov
-Catholic Charities,lcrombie@catholiccharitiesoregon.org
-Clackamas Service Center,debramason@cscoregon.org
-Healthy Familes of Clackamas County,bkersens@healthyfamiliescc.org
-Dollar for Portland,jared@dollorfor.org
-Emmanuel Housing Center,shauntemeyers@emmanuelpdx.org
-Helensview School,hgandee@mesd.k12.or.us
-JOIN,ccarroll@joinpdx.org
-Job Corps (PIVOT),zutz.kayla@jobcorps.org
-NARA,christman@naranw.org
-NW Housing Alternatives,doty@nwhousing.org
-Pregnancy Resource Center,debbie@portlandprc.org
-Portland Homeless Family Solutions,emma@pdxhfs.org
-Raphael House,lvold@raphaelhouse.com
-The Rebecca Foundation's Cloth Diaper Closet,portland@clothforall.org
-Rose Haven,adeol@rosehaven.org
-Self Enhancement Inc.,stephaniep@selfenhancement.org
-Teen Parent Services (PPS),lgovan@pps.net
-Volunteers of America,cross@voaor.org
-Central City Concern,lindsey.ramsey@ccconcern.org
\ No newline at end of file
+name,email,default_storage_location,send_reminders,quota,notes
+Beaverton Police Department,krodriguez@beavertonoregon.gov,"Smithsonian Conservation Center",true,50,"great partner"
+Catholic Charities,lcrombie@catholiccharitiesoregon.org,"Smithsonian Conservation Center",true,50,"great partner"
+Clackamas Service Center,debramason@cscoregon.org,"Smithsonian Conservation Center",true,50,"great partner"
+Healthy Familes of Clackamas County,bkersens@healthyfamiliescc.org,"Smithsonian Conservation Center",true,50,"great partner"
+Dollar for Portland,jared@dollorfor.org,"Smithsonian Conservation Center",true,50,"great partner"
+Emmanuel Housing Center,shauntemeyers@emmanuelpdx.org,"Smithsonian Conservation Center",true,50,"great partner"
+Helensview School,hgandee@mesd.k12.or.us,"Smithsonian Conservation Center",true,50,"great partner"
+JOIN,ccarroll@joinpdx.org,"Smithsonian Conservation Center",true,50,"great partner"
+Job Corps (PIVOT),zutz.kayla@jobcorps.org,"Smithsonian Conservation Center",true,50,"great partner"
+NARA,christman@naranw.org,"Smithsonian Conservation Center",true,50,"great partner"
+NW Housing Alternatives,doty@nwhousing.org,"Smithsonian Conservation Center",true,50,"great partner"
+Pregnancy Resource Center,debbie@portlandprc.org,"Smithsonian Conservation Center",true,50,"great partner"
+Portland Homeless Family Solutions,emma@pdxhfs.org,"Smithsonian Conservation Center",true,50,"great partner"
+Raphael House,lvold@raphaelhouse.com,"Smithsonian Conservation Center",true,50,"great partner"
+The Rebecca Foundation's Cloth Diaper Closet,portland@clothforall.org,"Smithsonian Conservation Center",true,50,"great partner"
+Rose Haven,adeol@rosehaven.org,"Smithsonian Conservation Center",true,50,"great partner"
+Self Enhancement Inc.,stephaniep@selfenhancement.org,"Smithsonian Conservation Center",true,50,"great partner"
+Teen Parent Services (PPS),lgovan@pps.net,"Smithsonian Conservation Center",true,50,"great partner"
+Volunteers of America,cross@voaor.org,"Smithsonian Conservation Center",true,50,"great partner"
+Central City Concern,lindsey.ramsey@ccconcern.org,"Smithsonian Conservation Center",true,50,"great partner"
\ No newline at end of file
diff --git a/spec/fixtures/files/partners_with_duplicates.csv b/spec/fixtures/files/partners_with_duplicates.csv
deleted file mode 100644
index c4890e78af..0000000000
--- a/spec/fixtures/files/partners_with_duplicates.csv
+++ /dev/null
@@ -1,4 +0,0 @@
-name,email
-Partner 1,partner1@example.com
-Partner 2,partner2@example.com
-Partner 4,partner4@example.com
\ No newline at end of file
diff --git a/spec/fixtures/files/partners_with_final_line_blank.csv b/spec/fixtures/files/partners_with_final_line_blank.csv
new file mode 100644
index 0000000000..c8a10d842b
--- /dev/null
+++ b/spec/fixtures/files/partners_with_final_line_blank.csv
@@ -0,0 +1,3 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 31,partner31@example.com,"Smithsonian Conservation Center",true,50,"great partner"
+
diff --git a/spec/fixtures/files/partners_with_six_fields.csv b/spec/fixtures/files/partners_with_six_fields.csv
new file mode 100644
index 0000000000..797b65f0f6
--- /dev/null
+++ b/spec/fixtures/files/partners_with_six_fields.csv
@@ -0,0 +1,4 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 1,partner1@example.com,"Smithsonian Conservation Center",true,50,"great partner"
+Partner 2,partner2@example.com,"Smithsonian Conservation Center",true,75,"such a great partner"
+Partner 4,partner4@example.com,"Smithsonian Conservation Center",false,80,"really ten out of ten"
diff --git a/spec/fixtures/files/partners_with_six_fields_and_duplicates.csv b/spec/fixtures/files/partners_with_six_fields_and_duplicates.csv
new file mode 100644
index 0000000000..6250a90ae8
--- /dev/null
+++ b/spec/fixtures/files/partners_with_six_fields_and_duplicates.csv
@@ -0,0 +1,4 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 1,partner1@example.com,"Smithsonian Conservation Center",true,50,"great partner"
+Partner 2,partner2@example.com,"Smithsonian Conservation Center",true,75,"such a great partner"
+Partner 3,partner3@example.com,"Smithsonian Conservation Center",true,80,"yay, a partner"
diff --git a/spec/fixtures/files/partners_with_six_fields_capitalized_location.csv b/spec/fixtures/files/partners_with_six_fields_capitalized_location.csv
new file mode 100644
index 0000000000..0f8cfd6856
--- /dev/null
+++ b/spec/fixtures/files/partners_with_six_fields_capitalized_location.csv
@@ -0,0 +1,4 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 1,partner1@example.com,"SMITHSONIAN CONSERVATION CENTER",true,50,"great partner"
+Partner 2,partner2@example.com,"Smithsonian Conservation Center",true,75,"such a great partner"
+Partner 4,partner4@example.com,"Smithsonian Conservation Center",false,80,"really ten out of ten"
diff --git a/spec/fixtures/files/partners_with_six_fields_invalid_location.csv b/spec/fixtures/files/partners_with_six_fields_invalid_location.csv
new file mode 100644
index 0000000000..14daacbdd8
--- /dev/null
+++ b/spec/fixtures/files/partners_with_six_fields_invalid_location.csv
@@ -0,0 +1,2 @@
+name,email,default_storage_location,send_reminders,quota,notes
+Partner 4,partner4@example.com,"Invalid",false,80,"really ten out of ten"
\ No newline at end of file
diff --git a/spec/models/donation_site_spec.rb b/spec/models/donation_site_spec.rb
index 1f1a246b1b..25047cc758 100644
--- a/spec/models/donation_site_spec.rb
+++ b/spec/models/donation_site_spec.rb
@@ -43,7 +43,8 @@
data = File.read(duplicated_name_csv_path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
- errors = DonationSite.import_csv(csv, organization.id)
+ response = DonationSite.import_csv(csv, organization.id)
+ errors = response[:errors]
expect(errors).not_to be_empty
expect(errors.first).to match(/Row/)
expect(errors.first).to include("Name must be unique within the organization")
@@ -55,7 +56,8 @@
data = File.read(valid_csv_path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
- errors = DonationSite.import_csv(csv, organization.id)
+ response = DonationSite.import_csv(csv, organization.id)
+ errors = response[:errors]
expect(errors).to be_empty
expect(DonationSite.count).to eq 1
@@ -67,7 +69,8 @@
data = File.read(invalid_csv_path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
- errors = DonationSite.import_csv(csv, organization.id)
+ response = DonationSite.import_csv(csv, organization.id)
+ errors = response[:errors]
expect(errors).not_to be_empty
expect(errors.first).to match(/Row/)
expect(errors.first).to include("can't be blank")
@@ -79,7 +82,9 @@
import_file_path = Rails.root.join("spec", "fixtures", "files", "donation_sites.csv")
data = File.read(import_file_path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
- DonationSite.import_csv(csv, organization.id)
+ response = DonationSite.import_csv(csv, organization.id)
+ errors = response[:errors]
+ expect(errors).to be_empty
expect(DonationSite.count).to eq 1
end
end
diff --git a/spec/models/partner_spec.rb b/spec/models/partner_spec.rb
index f0dbc2066a..d19accd69f 100644
--- a/spec/models/partner_spec.rb
+++ b/spec/models/partner_spec.rb
@@ -258,19 +258,27 @@
describe "import_csv" do
let(:organization) { create(:organization) }
+ before do
+ create(:storage_location, organization: organization)
+ create(:storage_location, organization: organization, name: "shed")
+ create(:storage_location, organization: organization, name: "building")
+ create(:storage_location, organization: organization, name: "Smithsonian Conservation Center")
+ end
it "imports partners from a csv file and prevents multiple imports" do
- before_import = Partner.count
- import_file_path = Rails.root.join("spec", "fixtures", "files", "partners.csv")
+ import_file_path = Rails.root.join("spec", "fixtures", "files", "partners_with_six_fields.csv")
data = File.read(import_file_path, encoding: "BOM|UTF-8")
csv = CSV.parse(data, headers: true)
- Partner.import_csv(csv, organization.id)
- expect(Partner.count).to eq before_import + 3
- import_file_path2 = Rails.root.join("spec", "fixtures", "files", "partners_with_duplicates.csv")
+ expect do
+ Partner.import_csv(csv, organization.id)
+ end.to change { Partner.count }.by(3)
+
+ import_file_path2 = Rails.root.join("spec", "fixtures", "files", "partners_with_six_fields_and_duplicates.csv")
data2 = File.read(import_file_path2, encoding: "BOM|UTF-8")
csv2 = CSV.parse(data2, headers: true)
- Partner.import_csv(csv2, organization.id)
- expect(Partner.count).to eq before_import + 4
+ expect do
+ Partner.import_csv(csv2, organization.id)
+ end.to change { Partner.count }.by(1)
end
it "imports partners from a csv file with BOM encodings" do
@@ -281,6 +289,43 @@
Partner.import_csv(csv, organization.id)
end.to change { Partner.count }.by(20)
end
+
+ it "imports partners with the correct values for fields" do
+ import_file_path = Rails.root.join("spec", "fixtures", "files", "partners_with_six_fields.csv")
+ data = File.read(import_file_path, encoding: "BOM|UTF-8")
+ csv = CSV.parse(data, headers: true)
+ response = Partner.import_csv(csv, organization.id)
+
+ expect(response[:errors]).to be_empty
+ expect(response[:warnings]).to be_empty
+ partner = Partner.last
+ expect(StorageLocation.find(partner.default_storage_location_id).name).to eq("Smithsonian Conservation Center")
+ expect(partner.send_reminders).to eq(false)
+ expect(partner.quota).to eq(80)
+ expect(partner.notes).to eq("really ten out of ten")
+ end
+
+ it "imports partners with all caps storage location" do
+ import_file_path = Rails.root.join("spec", "fixtures", "files", "partners_with_six_fields_capitalized_location.csv")
+ data = File.read(import_file_path, encoding: "BOM|UTF-8")
+ csv = CSV.parse(data, headers: true)
+ expect do
+ response = Partner.import_csv(csv, organization.id)
+ expect(response[:warnings]).to be_empty
+ end.to change { Partner.count }.by(3)
+ end
+
+ context "when storage location is not found" do
+ it "returns a warning" do
+ import_file_path = Rails.root.join("spec", "fixtures", "files", "partners_with_six_fields_invalid_location.csv")
+ data = File.read(import_file_path, encoding: "BOM|UTF-8")
+ csv = CSV.parse(data, headers: true)
+ response = Partner.import_csv(csv, organization.id)
+ expect(response[:errors]).to be_empty
+ expect(response[:warnings]).to be_present
+ expect(response[:warnings].join).to include("Default storage location is not a storage location for this partner's organization")
+ end
+ end
end
describe '#quantity_year_to_date' do
diff --git a/spec/requests/partners_requests_spec.rb b/spec/requests/partners_requests_spec.rb
index 2e4255164f..9f333eb423 100644
--- a/spec/requests/partners_requests_spec.rb
+++ b/spec/requests/partners_requests_spec.rb
@@ -240,7 +240,7 @@
enable_quantity_based_requests: true)
end
- it "orders partners alphaetically" do
+ it "orders partners alphabetically" do
get partners_path(partner, format: response_format)
csv = CSV.parse(response.body)
@@ -433,9 +433,12 @@
describe "POST #import_csv" do
let(:model_class) { Partner }
+ let!(:outside_organization) { create(:organization) }
+ let!(:invalid_storage_location) { create(:storage_location, name: 'invalid', organization: outside_organization) }
+ let!(:valid_storage_location) { create(:storage_location, organization: organization) }
context "with a csv file" do
- let(:file) { fixture_file_upload("#{model_class.name.underscore.pluralize}.csv", "text/csv") }
+ let(:file) { fixture_file_upload("partners_with_six_fields.csv", "text/csv") }
subject { post import_csv_partners_path, params: { file: file } }
it "invokes .import_csv" do
@@ -480,6 +483,46 @@
end
end
+ context "csv file with send_reminders header and field missing" do
+ let(:file) { fixture_file_upload("partners_missing_send_reminders_field_and_header.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "defaults send_reminders to false" do
+ subject
+ partner = Partner.find_by(name: "Partner 51")
+ expect(partner.send_reminders).to be(false)
+ end
+ end
+
+ context "csv file with send_reminders field missing" do
+ let(:file) { fixture_file_upload("partners_missing_send_reminders_field.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "defaults send_reminders to false" do
+ subject
+ partner = Partner.find_by(name: "Partner 51")
+ expect(partner.send_reminders).to be(false)
+ end
+ end
+
context "csv file with invalid email address" do
let(:file) { fixture_file_upload("partners_with_invalid_email.csv", "text/csv") }
subject { post import_csv_partners_path, params: { file: file } }
@@ -499,6 +542,114 @@
expect(response).to have_error(/Partner 2: Email is invalid/)
end
end
+
+ context "csv file with default storage location header and field missing" do
+ let(:file) { fixture_file_upload("partners_missing_default_storage_location_field_and_header.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "presents a flash notice message" do
+ subject
+ expect(response).to have_notice "#{model_class.name.underscore.humanize.pluralize} were imported successfully!"
+ end
+ end
+
+ context "csv file with default storage location field missing" do
+ let(:file) { fixture_file_upload("partners_missing_default_storage_location_field.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "presents a flash notice message" do
+ subject
+ expect(response).to have_notice "#{model_class.name.underscore.humanize.pluralize} were imported successfully!"
+ end
+ end
+
+ context "csv file with default storage location, email preferences, quota, and notes" do
+ let(:file) { fixture_file_upload("partners_with_six_fields.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "presents a flash notice message" do
+ subject
+ expect(response).to have_notice "#{model_class.name.underscore.humanize.pluralize} were imported successfully!"
+ end
+ end
+
+ context "csv file with an invalid storage location" do
+ let!(:current_organization) { create(:organization) }
+ let!(:outside_organization) { create(:organization) }
+ let(:file) { fixture_file_upload("partners_with_six_fields_invalid_location.csv", "text/csv") }
+ before do
+ allow(controller).to receive(:current_organization).and_return(current_organization)
+ end
+
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "presents a flash error message" do
+ subject
+ expect(flash[:alert]).to be_present
+ expect(flash[:alert]).to match(/The following Partners imported with warnings/)
+ end
+ end
+
+ context "csv file with a valid all-caps storage location" do
+ let(:file) { fixture_file_upload("partners_with_six_fields.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "invokes .import_csv" do
+ expect(model_class).to respond_to(:import_csv).with(2).arguments
+ end
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "presents a flash notice message" do
+ subject
+ expect(response).to have_notice "#{model_class.name.underscore.humanize.pluralize} were imported successfully!"
+ end
+ end
+
+ context "csv file with a blank line at the file's bottom" do
+ let(:file) { fixture_file_upload("partners_with_final_line_blank.csv", "text/csv") }
+ subject { post import_csv_partners_path, params: { file: file } }
+
+ it "redirects to :index" do
+ subject
+ expect(response).to be_redirect
+ end
+
+ it "presents a flash notice message" do
+ subject
+ expect(response).to have_notice "#{model_class.name.underscore.humanize.pluralize} were imported successfully!"
+ end
+ end
end
describe "POST #create" do
diff --git a/spec/services/partner_create_service_spec.rb b/spec/services/partner_create_service_spec.rb
index cc55d748ab..86eec31693 100644
--- a/spec/services/partner_create_service_spec.rb
+++ b/spec/services/partner_create_service_spec.rb
@@ -43,6 +43,32 @@
expect(query.first.enable_quantity_based_requests).to eq(true)
end
+ context 'when send_reminders is nil' do
+ before do
+ partner_attrs.merge!(send_reminders: nil)
+ end
+
+ it 'defaults send_reminders to false' do
+ subject
+
+ partner = Partner.find_by(name: partner_attrs[:name])
+ expect(partner.send_reminders).to be(false)
+ end
+ end
+
+ context 'when send_reminders is missing' do
+ before do
+ partner_attrs.delete(:send_reminders)
+ end
+
+ it 'defaults send_reminders to false' do
+ subject
+
+ partner = Partner.find_by(name: partner_attrs[:name])
+ expect(partner.send_reminders).to be(false)
+ end
+ end
+
context 'but there was an unexpected issue with saving the' do
let(:error_message) { Faker::Games::ElderScrolls.dragon }