From cd014c38e1c8c3233174f54d21f3d74e5e7fc86f Mon Sep 17 00:00:00 2001 From: Anton-Ivanov Date: Wed, 5 Feb 2025 22:28:49 +0200 Subject: [PATCH] #1677, add the "Any tag" for batch update form --- app/assets/javascripts/build_tags.js | 2 +- app/forms/batch_update_form/base.rb | 15 ++--- app/forms/batch_update_form/destination.rb | 4 +- app/forms/batch_update_form/dialpeer.rb | 4 +- .../batch_update_form/routing_tag_methods.rb | 28 +++++++++ .../routing/destinations/batch_update_spec.rb | 61 ++++++++++++++++--- .../routing/dialpeers/batch_update_spec.rb | 26 +++++++- 7 files changed, 122 insertions(+), 18 deletions(-) create mode 100644 app/forms/batch_update_form/routing_tag_methods.rb diff --git a/app/assets/javascripts/build_tags.js b/app/assets/javascripts/build_tags.js index 99b11ea34..28e59ad46 100644 --- a/app/assets/javascripts/build_tags.js +++ b/app/assets/javascripts/build_tags.js @@ -5,7 +5,7 @@ $(document).on('mass_update_modal_dialog:after_open', function (event, form) { 'name': 'routing_tag_ids[]', 'class': 'chosen', 'id': 'batch_update_routing_tag_ids', - 'value': '', // reset default value + 'value': null, // reset default value 'multiple': true }); var tagsCheckbox = $('#mass_update_dialog_routing_tag_ids'); diff --git a/app/forms/batch_update_form/base.rb b/app/forms/batch_update_form/base.rb index 36bdbd984..baf8f0047 100644 --- a/app/forms/batch_update_form/base.rb +++ b/app/forms/batch_update_form/base.rb @@ -97,21 +97,21 @@ def form_data _attributes.each do |name, options| type = options.fetch(:type, 'string') - data[name] = public_send("form_data_#{type}", options) + data[name] = public_send("form_data_#{type}", name, options) end data end - def form_data_string(_options) + def form_data_string(_attribute_name, _options) 'text' end - def form_data_date(_options) + def form_data_date(_attribute_name, _options) 'datepicker' end - def form_data_boolean(_options) + def form_data_boolean(_attribute_name, _options) [%w[Yes true], %w[No false]] end @@ -121,7 +121,7 @@ def form_data_boolean(_options) # :primary_key [Symbol] default :id. # :scope [Proc,Symbol,nil] optional. # @return [Array] - def form_data_foreign_key(options) + def form_data_foreign_key(_attribute_name, options = {}) klass = options.fetch(:class_name).constantize display_name = options.fetch(:display_name, :name) primary_key = options.fetch(:primary_key, :id) @@ -130,10 +130,11 @@ def form_data_foreign_key(options) scope = klass.all scope = scope.public_send(custom_scope) if custom_scope.is_a?(Symbol) scope = custom_scope.call(scope) if custom_scope.is_a?(Proc) - scope.pluck(display_name, primary_key) + result = scope.pluck(display_name, primary_key) + result end - def form_data_integer_collection(options) + def form_data_integer_collection(_attribute_name, options) c = options.fetch(:collection) c end diff --git a/app/forms/batch_update_form/destination.rb b/app/forms/batch_update_form/destination.rb index efd632ae5..52d188d33 100644 --- a/app/forms/batch_update_form/destination.rb +++ b/app/forms/batch_update_form/destination.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class BatchUpdateForm::Destination < BatchUpdateForm::Base + include BatchUpdateForm::RoutingTagMethods + model_class 'Routing::Destination' attribute :enabled, type: :boolean attribute :prefix @@ -25,7 +27,7 @@ class BatchUpdateForm::Destination < BatchUpdateForm::Base attribute :asr_limit attribute :acd_limit attribute :short_calls_limit - attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag' + attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag', any_tag: true, scope: ->(scope) { scope.order(:name) } # presence validations validates :dst_number_min_length, presence: true, if: :dst_number_min_length_changed? diff --git a/app/forms/batch_update_form/dialpeer.rb b/app/forms/batch_update_form/dialpeer.rb index 93405801f..7c8a7cde6 100644 --- a/app/forms/batch_update_form/dialpeer.rb +++ b/app/forms/batch_update_form/dialpeer.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true class BatchUpdateForm::Dialpeer < BatchUpdateForm::Base + include BatchUpdateForm::RoutingTagMethods + model_class 'Dialpeer' attribute :enabled, type: :boolean attribute :prefix @@ -34,7 +36,7 @@ class BatchUpdateForm::Dialpeer < BatchUpdateForm::Base attribute :src_rewrite_result attribute :dst_rewrite_rule attribute :dst_rewrite_result - attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag' + attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag', any_tag: true, scope: ->(scope) { scope.order(:name) } # presence validates :dst_number_min_length, presence: true, if: :dst_number_min_length_changed? diff --git a/app/forms/batch_update_form/routing_tag_methods.rb b/app/forms/batch_update_form/routing_tag_methods.rb new file mode 100644 index 000000000..136a9c978 --- /dev/null +++ b/app/forms/batch_update_form/routing_tag_methods.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module BatchUpdateForm::RoutingTagMethods + extend ActiveSupport::Concern + + class_methods do + def form_data_foreign_key(attribute_name, options = {}) + return super(attribute_name, options) unless attribute_name == :routing_tag_ids + + display_name = options.fetch(:display_name, :name) + primary_key = options.fetch(:primary_key, :id) + + scope = Routing::RoutingTag.order(:name) + scope = scope.pluck(display_name, primary_key) + scope = add_any_tag_option(scope, options) + scope + end + + def add_any_tag_option(scope, options) + if options[:any_tag] == true + scope.prepend([[Routing::RoutingTag::ANY_TAG]]) + elsif options[:any_tag] != false + raise ArgumentError, 'options[:any_tag] must be a boolean' + end + scope + end + end +end diff --git a/spec/features/routing/destinations/batch_update_spec.rb b/spec/features/routing/destinations/batch_update_spec.rb index e12ff63a5..a5190267c 100644 --- a/spec/features/routing/destinations/batch_update_spec.rb +++ b/spec/features/routing/destinations/batch_update_spec.rb @@ -10,12 +10,6 @@ let!(:profit_control_mode_id) { Routing::RateProfitControlMode::MODE_PER_CALL } let!(:routing_tags) { create_list(:routing_tag, 5) } - before do - visit destinations_path - click_button 'Update batch' - expect(page).to have_selector('.ui-dialog') - end - subject do fill_batch_form click_button 'OK' @@ -46,7 +40,7 @@ asr_limit: '0.9', acd_limit: '1', short_calls_limit: '4', - routing_tag_ids: routing_tags.map { |tag| tag.id.to_s } + routing_tag_ids: routing_tags.sort_by(&:name).map { |tag| tag.id.to_s } } end @@ -178,6 +172,12 @@ end context 'should check validates' do + before do + visit destinations_path + click_button 'Update batch' + expect(page).to have_selector('.ui-dialog') + end + context 'when change :dp_margin_percent' do let(:assign_params) { { dp_margin_percent: '0' } } @@ -207,4 +207,51 @@ end end end + + context 'when user wants to change routing_tag_ids to "NOT TAGGED"' do + subject { click_button :OK } + + let(:_destinations) { nil } + let(:assign_params) { {} } + + before do + visit destinations_path + click_button 'Update batch' + page.scroll_to find_button('OK') + check :Routing_tag_ids + end + + it 'should create Job to update routing_tag_ids field of desctination to default value: []' do + expect do + subject + expect(page).to have_selector '.flash', text: success_message + end.to enqueue_job(AsyncBatchUpdateJob).with('Routing::Destination', be_present, { routing_tag_ids: '' }, be_present) + + # ensure that destination model converts "" to [] because the system consider [] as Routing::RoutingTag::NOT_TAGGED + expect(Routing::Destination.new(routing_tag_ids: '')).to have_attributes(routing_tag_ids: []) + end + end + + context 'when user wants to change routing_tag_ids to "ANY TAG"' do + let(:_destinations) { nil } + let(:assign_params) { {} } + + before do + visit destinations_path + click_button 'Update batch' + page.scroll_to find_button('OK') + check :Routing_tag_ids + end + + it 'should created Job to update routing_tag_ids to any tag: [nil]' do + fill_in_chosen 'routing_tag_ids[]', with: Routing::RoutingTag::ANY_TAG, multiple: true + expect do + subject + expect(page).to have_selector '.flash', text: success_message + end.to enqueue_job(AsyncBatchUpdateJob).with('Routing::Destination', be_present, { routing_tag_ids: [''] }, be_present) + + # ensure that destination model converts [""] to [nil] because the system consider [nil] as Routing::RoutingTag::ANY_TAG + expect(Routing::Destination.new(routing_tag_ids: [''])).to have_attributes(routing_tag_ids: [nil]) + end + end end diff --git a/spec/features/routing/dialpeers/batch_update_spec.rb b/spec/features/routing/dialpeers/batch_update_spec.rb index 0efcb7cce..251d7febc 100644 --- a/spec/features/routing/dialpeers/batch_update_spec.rb +++ b/spec/features/routing/dialpeers/batch_update_spec.rb @@ -60,7 +60,7 @@ src_rewrite_result: '12', dst_rewrite_rule: '12', dst_rewrite_result: '12', - routing_tag_ids: routing_tags.map { |tag| tag.id.to_s } + routing_tag_ids: routing_tags.sort_by(&:name).map { |tag| tag.id.to_s } } end let(:fill_batch_form) do @@ -266,4 +266,28 @@ end end end + + context 'when user wants to change routing_tag_ids to "ANY TAG"' do + subject { click_button :OK } + + let(:_dialpeers) { nil } + let(:routing_group) { nil } + let!(:routeset_discriminator) { nil } + let(:assign_params) { {} } + + before do + check :Routing_tag_ids + fill_in_chosen 'routing_tag_ids[]', with: Routing::RoutingTag::ANY_TAG, multiple: true + end + + it 'should created Job to update routing_tag_ids to any tag: [nil]' do + expect do + subject + expect(page).to have_selector '.flash', text: success_message + end.to enqueue_job(AsyncBatchUpdateJob).with('Dialpeer', be_present, { routing_tag_ids: [''] }, be_present) + + # ensure that dialpeer model converts "" to [] because the system considers [""] as Routing::RoutingTag::ANY_TAG + expect(Dialpeer.new(routing_tag_ids: [''])).to have_attributes(routing_tag_ids: [nil]) + end + end end