diff --git a/app/controllers/file_uploads_controller.rb b/app/controllers/file_uploads_controller.rb index 4207743a95..1b5c7d473a 100644 --- a/app/controllers/file_uploads_controller.rb +++ b/app/controllers/file_uploads_controller.rb @@ -169,7 +169,7 @@ def create_product_survey_from_url begin url = params[survey_param][:location] ext = UrlService.find_or_create_by(location: url) - esp = ExternalServicePasser.where(passer_id: @product.id, external_service_id: ext.id).first + esp = ExternalServicePasser.where(passer: @product, external_service_id: ext.id).first if esp @flash_notice = "That Online Order Form already exists" diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 84f4288edc..6bf88bbb5c 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -1,4 +1,53 @@ # frozen_string_literal: true class ServicesController < ProductsCommonController + after_action :update_sanger_external_service, only: [:create, :update] + + private + + def permitted_params + params = super + + if current_facility.sanger_sequencing_enabled? + params += %i[sanger_sequencing_enabled] + end + + params + end + + def update_sanger_external_service + return unless @product.sanger_sequencing_enabled_previously_changed? + + if @product.sanger_sequencing_enabled? + ensure_sanger_url_service + flash[:info] = t("controllers.services.sanger_sequencing_enabled") + else + flash[:info] = t("controllers.services.sanger_sequencing_disabled") + end + end + + ## + # Ensures UrlService exists for the product + # pointing to Sanger Submission + def ensure_sanger_url_service + return unless defined? new_sanger_sequencing_submission_path + + sanger_external_service = + @product + .external_services + .matching_location(new_sanger_sequencing_submission_path) + .first + + if sanger_external_service.blank? + Service.transaction do + external_service = UrlService.find_or_create_by( + location: new_sanger_sequencing_submission_url + ) + ExternalServicePasser.create!( + external_service:, + passer: @product, + ) + end + end + end end diff --git a/app/models/external_services/external_service.rb b/app/models/external_services/external_service.rb index fd819c368c..f937ee9686 100644 --- a/app/models/external_services/external_service.rb +++ b/app/models/external_services/external_service.rb @@ -3,7 +3,9 @@ # # Represents a 3rd party service in use by the system class ExternalService < ApplicationRecord - validates_presence_of :location + def self.matching_location(value) + where("location like ?", "%#{value}%") + end end diff --git a/app/views/services/_service_fields.html.haml b/app/views/services/_service_fields.html.haml new file mode 100644 index 0000000000..30a32259c3 --- /dev/null +++ b/app/views/services/_service_fields.html.haml @@ -0,0 +1,6 @@ +- if current_facility.sanger_sequencing_enabled? + = f.input :sanger_sequencing_enabled, + as: :boolean, + label: false, + inline_label: Service.human_attribute_name(:sanger_sequencing_enabled), + hint: t("services.service_fields.sanger.instruct.sanger_sequencing_enabled") diff --git a/app/views/services/_service_manage_fields.html.haml b/app/views/services/_service_manage_fields.html.haml new file mode 100644 index 0000000000..c491c99d67 --- /dev/null +++ b/app/views/services/_service_manage_fields.html.haml @@ -0,0 +1,2 @@ +- if current_facility.sanger_sequencing_enabled? + = f.input :sanger_sequencing_enabled diff --git a/config/locales/en.controllers.yml b/config/locales/en.controllers.yml index 594ba438f0..6063f2035f 100644 --- a/config/locales/en.controllers.yml +++ b/config/locales/en.controllers.yml @@ -214,6 +214,10 @@ en: error: "Our apologies, but an error occurred while importing: %{error}" job_is_queued: "The bulk import is being processed. A report will be sent to %{email} when complete." + services: + sanger_sequencing_enabled: Sanger has been enabled, make sure the Order Form is inactive. + sanger_sequencing_disabled: Sanger has been disabled, make sure the Order Form is active. + schedule_rules: create: Schedule Rule was successfully created. update: Schedule Rule was successfully updated. diff --git a/config/locales/en.models.yml b/config/locales/en.models.yml index 744af156ac..ffcfa36262 100644 --- a/config/locales/en.models.yml +++ b/config/locales/en.models.yml @@ -322,6 +322,8 @@ en: unit_cost: Unit Cost unit_adjustment: Unit Adjustment unit_net_cost: Unit Net Cost + service: + sanger_sequencing_enabled: Sanger Enabled stored_file: file_file_size: File user_role: diff --git a/config/locales/en.yml b/config/locales/en.yml index ee9f12a903..4f23706cf8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1258,6 +1258,11 @@ en: shared: Shared schedule hints: schedule: You may share a schedule with other products. Choose an exisiting schedule or use an unshared schedule. + services: + service_fields: + sanger: + instruct: + sanger_sequencing_enabled: Enable Sanger submissions for this service notifications: index: diff --git a/db/migrate/20250110132703_add_product_sanger_sequencing_enabled.rb b/db/migrate/20250110132703_add_product_sanger_sequencing_enabled.rb new file mode 100644 index 0000000000..76c1b2d58d --- /dev/null +++ b/db/migrate/20250110132703_add_product_sanger_sequencing_enabled.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddProductSangerSequencingEnabled < ActiveRecord::Migration[7.0] + def change + add_column :products, :sanger_sequencing_enabled, :boolean, null: false, default: false + end +end diff --git a/db/schema.rb b/db/schema.rb index d361f726a8..5669d36e76 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.0].define(version: 2024_12_12_185208) do +ActiveRecord::Schema[7.0].define(version: 2025_01_10_132703) do create_table "account_facility_joins", id: :integer, charset: "utf8mb3", force: :cascade do |t| t.integer "facility_id", null: false t.integer "account_id", null: false @@ -664,6 +664,7 @@ t.integer "min_reserve_days" t.integer "max_reserve_days" t.boolean "start_time_disabled", default: false, null: false + t.boolean "sanger_sequencing_enabled", default: false, null: false t.index ["dashboard_token"], name: "index_products_on_dashboard_token" t.index ["facility_account_id"], name: "fk_facility_accounts" t.index ["facility_id"], name: "fk_rails_0c9fa1afbe" diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb index b07ee1e1b1..39078238ba 100644 --- a/spec/controllers/services_controller_spec.rb +++ b/spec/controllers/services_controller_spec.rb @@ -105,6 +105,33 @@ is_expected.to set_flash assert_redirected_to manage_facility_service_url(@authable, assigns(:product)) end + + context "when sanger is enabled" do + before do + sign_in @admin + facility.update(sanger_sequencing_enabled: true) + @params[:service][:sanger_sequencing_enabled] = true + end + + it "creates an external service" do + expect { do_request }.to change { + @service.reload.external_services.count + }.by(1) + end + + it "does not create an external service if it already exists" do + ExternalServicePasser.create( + passer: @service, + external_service: UrlService.create( + location: new_sanger_sequencing_submission_path + ) + ) + + expect { do_request }.to_not change { + @service.reload.external_services.count + } + end + end end context "destroy" do diff --git a/spec/system/admin/creating_a_service_spec.rb b/spec/system/admin/creating_a_service_spec.rb index b1d96ba908..34867cbba8 100644 --- a/spec/system/admin/creating_a_service_spec.rb +++ b/spec/system/admin/creating_a_service_spec.rb @@ -9,7 +9,7 @@ let(:logged_in_user) { director } before { login_as logged_in_user } - it "can create and edit a service" do + it "can create a service" do visit facility_products_path(facility) click_link "Services (0)", exact: true click_link "Add Service" @@ -20,13 +20,6 @@ expect(current_path).to eq(manage_facility_service_path(facility, Service.last)) expect(page).to have_content("My New Service") - - click_link "Edit" - fill_in "service[description]", with: "Some description" - click_button "Save" - - expect(current_path).to eq(manage_facility_service_path(facility, Service.last)) - expect(page).to have_content("Some description") end it "can add order forms" do @@ -62,4 +55,34 @@ context "when billing mode is Skip Review" do include_examples "creates a product with billing mode", "service", "Skip Review" end + + context "when sanger enable is checked" do + let(:service) { Service.last } + + it "does not show the checkbox if facility is not sanger enabled" do + expect(facility.sanger_sequencing_enabled).to be false + + visit new_facility_service_path(facility) + + expect(page).to_not have_field("service[sanger_sequencing_enabled]") + end + + it "can enable sanger on service if sanger is enabled for facility" do + facility.update(sanger_sequencing_enabled: true) + + visit new_facility_service_path(facility) + + fill_in "service[name]", with: "Sanger Sequencing" + fill_in "service[url_name]", with: "sanger-sequencing" + + check "service[sanger_sequencing_enabled]" + + click_button "Create" + + expect(page).to have_content("Service was successfully created") + expect(page).to have_content("Sanger has been enabled") + + expect(service.external_services.length).to eq(1) + end + end end diff --git a/spec/system/admin/editing_a_service_spec.rb b/spec/system/admin/editing_a_service_spec.rb new file mode 100644 index 0000000000..11e2d210e9 --- /dev/null +++ b/spec/system/admin/editing_a_service_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "Editing a Service" do + let(:facility) { create :setup_facility } + let(:service) { create :service, facility: } + let(:admin) { create :user, :administrator } + + before do + login_as admin + end + + it "can edit a service" do + visit edit_facility_service_path(facility, service) + + fill_in "service[description]", with: "Some description" + click_button "Save" + + expect(current_path).to eq(manage_facility_service_path(facility, Service.last)) + expect(page).to have_content("Some description") + end + + describe "sanger enable change" do + it "does not show sanger enable if facility is not sanger enabled" do + facility.update(sanger_sequencing_enabled: false) + + visit edit_facility_service_path(facility, service) + + expect(page).to_not have_field("service[sanger_sequencing_enabled]") + end + + context "when facility is sanger enabled" do + before do + facility.update(sanger_sequencing_enabled: true) + end + + it "can enable sanger for the service" do + visit edit_facility_service_path(facility, service) + + check "service[sanger_sequencing_enabled]" + click_button "Save" + + expect(page).to have_content("Service was successfully updated") + expect(page).to have_content("Sanger has been enabled") + end + + it "can disable sanger for the service" do + service.update(sanger_sequencing_enabled: true) + visit edit_facility_service_path(facility, service) + + uncheck "service[sanger_sequencing_enabled]" + click_button "Save" + + expect(page).to have_content("Service was successfully updated") + expect(page).to have_content("Sanger has been disabled") + end + end + end +end