diff --git a/app/controllers/organizations/staff/external_form_upload_controller.rb b/app/controllers/organizations/staff/external_form_upload_controller.rb index 19d248982..bcf59fc12 100644 --- a/app/controllers/organizations/staff/external_form_upload_controller.rb +++ b/app/controllers/organizations/staff/external_form_upload_controller.rb @@ -7,6 +7,14 @@ def index authorize! :external_form_upload, context: {organization: Current.organization} end + + def create + authorize! :external_form_upload, + context: {organization: Current.organization} + file = params.require(:files).first + import_service = Organizations::Importers::GoogleCsvImportService.new(file) + import_service.call + end end end end diff --git a/app/policies/organizations/external_form_upload_policy.rb b/app/policies/organizations/external_form_upload_policy.rb index ab36d8e5e..8f2a50abd 100644 --- a/app/policies/organizations/external_form_upload_policy.rb +++ b/app/policies/organizations/external_form_upload_policy.rb @@ -6,5 +6,9 @@ class ExternalFormUploadPolicy < ApplicationPolicy def index? permission?(:manage_external_form_uploads) end + + def create? + permission?(:manage_external_form_uploads) + end end end diff --git a/app/services/organizations/csv_import_service.rb b/app/services/organizations/csv_import_service.rb deleted file mode 100644 index b138fe96b..000000000 --- a/app/services/organizations/csv_import_service.rb +++ /dev/null @@ -1,32 +0,0 @@ -require "csv" - -module Organizations - class CsvImportService - def initialize(file) - @file = file - @organization = Current.organization - end - - def call - CSV.foreach(@file.to_path, headers: true, skip_blanks: true) do |row| - # Using Google Form headers - email = row["Email"].downcase - csv_timestamp = Time.parse(row["Timestamp"]) - - person = Person.find_by(email:, organization: @organization) - previous = FormSubmission.where(person:, csv_timestamp:) - next unless person && previous.empty? - - ActiveRecord::Base.transaction do - form_submission = FormSubmission.create!(person:, csv_timestamp:) - row.each do |col| - next if col[0] == "Email" || col[0] == "Timestamp" - - FormAnswer.create!(form_submission:, - question_snapshot: col[0], value: col[1]) - end - end - end - end - end -end diff --git a/app/services/organizations/importers/google_csv_import_service.rb b/app/services/organizations/importers/google_csv_import_service.rb new file mode 100644 index 000000000..9c303d22f --- /dev/null +++ b/app/services/organizations/importers/google_csv_import_service.rb @@ -0,0 +1,34 @@ +require "csv" + +module Organizations + module Importers + class GoogleCsvImportService + def initialize(file) + @file = file + @organization = Current.organization + end + + def call + CSV.foreach(@file.to_path, headers: true, skip_blanks: true) do |row| + # Using Google Form headers + email = row["Email"].downcase + csv_timestamp = Time.parse(row["Timestamp"]) + + person = Person.find_by(email:, organization: @organization) + previous = FormSubmission.where(person:, csv_timestamp:) + next unless person && previous.empty? + + ActiveRecord::Base.transaction do + form_submission = FormSubmission.create!(person:, csv_timestamp:) + row.each do |col| + next if col[0] == "Email" || col[0] == "Timestamp" + + FormAnswer.create!(form_submission:, + question_snapshot: col[0], value: col[1]) + end + end + end + end + end + end +end diff --git a/app/views/organizations/staff/external_form_upload/index.html.erb b/app/views/organizations/staff/external_form_upload/index.html.erb index 26e060184..f13e66d6b 100644 --- a/app/views/organizations/staff/external_form_upload/index.html.erb +++ b/app/views/organizations/staff/external_form_upload/index.html.erb @@ -5,7 +5,8 @@

If you use a third party form service, like Google Forms, to provide questionnaires to potential adopters, and receive their answers, you can upload the CSV of data here to import the questions and responses to this application. This means the questionnaire data will live in one place, and you will be able to view it for a given adoption application at any time. Note that the adopter must have an account in this application using the same email address they used in the third party form.

- <%= render "organizations/staff/shared/attachment_form", instance: @external_form, title: 'Files', url: staff_external_form_upload_index_path(@pet), attachment_type: 'files' %> +

Current form service supported: Google Forms

+ <%= render "organizations/staff/shared/attachment_form", instance: nil, title: 'Files', url: staff_external_form_upload_index_path, multiple: false, attachment_type: 'files' %>
diff --git a/app/views/organizations/staff/pets/tabs/_files.html.erb b/app/views/organizations/staff/pets/tabs/_files.html.erb index b485daefd..bcb8e21f4 100644 --- a/app/views/organizations/staff/pets/tabs/_files.html.erb +++ b/app/views/organizations/staff/pets/tabs/_files.html.erb @@ -1,4 +1,4 @@
- <%= render "organizations/staff/shared/attachment_form", instance: @pet, title: 'Files', url: attach_files_staff_pet_path(@pet), attachment_type: 'files' %> + <%= render "organizations/staff/shared/attachment_form", multiple: true, instance: @pet, title: 'Files', url: attach_files_staff_pet_path(@pet), attachment_type: 'files' %> <%= render "organizations/shared/file_attachment_table", pet: @pet %>
diff --git a/app/views/organizations/staff/pets/tabs/_photos.html.erb b/app/views/organizations/staff/pets/tabs/_photos.html.erb index 47ed6a7c4..d1f2e98e4 100644 --- a/app/views/organizations/staff/pets/tabs/_photos.html.erb +++ b/app/views/organizations/staff/pets/tabs/_photos.html.erb @@ -1,4 +1,4 @@
- <%= render "organizations/staff/shared/attachment_form", instance: @pet, title: 'Photos', url: attach_images_staff_pet_path(@pet), attachment_type: 'images' %> + <%= render "organizations/staff/shared/attachment_form", multiple: true, instance: @pet, title: 'Photos', url: attach_images_staff_pet_path(@pet), attachment_type: 'images' %> <%= render ImageAttachmentTableComponent.new(images: @pet.images) %>
diff --git a/app/views/organizations/staff/shared/_attachment_form.html.erb b/app/views/organizations/staff/shared/_attachment_form.html.erb index aba2c57cc..96099ab70 100644 --- a/app/views/organizations/staff/shared/_attachment_form.html.erb +++ b/app/views/organizations/staff/shared/_attachment_form.html.erb @@ -10,7 +10,7 @@ <%= bootstrap_form_with(model: instance, url: url, method: :post) do |form| %>
- <%= form.file_field attachment_type.to_sym, multiple: true, direct_upload: true, + <%= form.file_field attachment_type.to_sym, multiple: multiple, direct_upload: true, class: "custom-attachments", hide_label: true %>
diff --git a/config/routes.rb b/config/routes.rb index e43a8f01a..7b84757d8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,7 +14,7 @@ resource :organization, only: %i[edit update] resource :custom_page, only: %i[edit update] resources :profile_reviews, only: [:show] - resources :external_form_upload, only: [:index] + resources :external_form_upload, only: %i[index create] resources :pets do resources :tasks diff --git a/test/controllers/organizations/staff/external_form_upload_controller_test.rb b/test/controllers/organizations/staff/external_form_upload_controller_test.rb new file mode 100644 index 000000000..99afd289a --- /dev/null +++ b/test/controllers/organizations/staff/external_form_upload_controller_test.rb @@ -0,0 +1,21 @@ +require "test_helper" + +class Organizations::Staff::ExternalFormUploadControllerTest < ActionDispatch::IntegrationTest + setup do + file = fixture_file_upload("google_form_sample.csv", "text/csv") + @params = {files: [file]} + user = create(:admin) + @user2 = create(:adopter, email: "adopter1@alta.com") + sign_in user + end + + test "Import from google_form_sample.csv creates FormAnswers" do + assert_difference "FormAnswer.count", 4 do + post staff_external_form_upload_index_path, params: @params + end + # No Form Answer is created when there is already existing Form submition with the csv_timestamp + assert_no_difference "FormAnswer.count" do + post staff_external_form_upload_index_path, params: @params + end + end +end diff --git a/test/fixtures/files/google_form_sample.csv b/test/fixtures/files/google_form_sample.csv new file mode 100644 index 000000000..4ab3ddda7 --- /dev/null +++ b/test/fixtures/files/google_form_sample.csv @@ -0,0 +1,2 @@ +Timestamp,Nombre,Email,Dirección,Número de teléfono,Comentarios +2024/10/05 7:14:21 p. m. GMT-4,dsf,adopter1@alta.com,dsfsdf,sdfsdf,ds diff --git a/test/services/organizations/csv_import_service_test.rb b/test/services/organizations/csv_import_service_test.rb index 76fc575c3..198a61d06 100644 --- a/test/services/organizations/csv_import_service_test.rb +++ b/test/services/organizations/csv_import_service_test.rb @@ -36,7 +36,7 @@ class CsvImportServiceTest < ActiveSupport::TestCase assert_difference "FormSubmission.count" do assert_difference("FormAnswer.count", + 7) do - Organizations::CsvImportService.new(@file).call + Organizations::Importers::GoogleCsvImportService.new(@file).call end end end @@ -48,7 +48,7 @@ class CsvImportServiceTest < ActiveSupport::TestCase end assert_no_difference "FormSubmission.count" do - Organizations::CsvImportService.new(@file).call + Organizations::Importers::GoogleCsvImportService.new(@file).call end end @@ -58,7 +58,7 @@ class CsvImportServiceTest < ActiveSupport::TestCase csv << @data end assert_difference "FormSubmission.count" do - Organizations::CsvImportService.new(@file).call + Organizations::Importers::GoogleCsvImportService.new(@file).call end end end