From 3d41c034f4b48ab38e28b425f4ce196bc30248ef Mon Sep 17 00:00:00 2001 From: Igor Fedoronchuk Date: Tue, 3 Apr 2018 16:25:07 +0300 Subject: [PATCH 1/5] customer vat cast from string while monotoring calls --- app/jobs/jobs/calls_monitoring.rb | 2 +- spec/jobs/calls_monitoring_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/jobs/jobs/calls_monitoring.rb b/app/jobs/jobs/calls_monitoring.rb index 64eb6af07..8303bd8ec 100644 --- a/app/jobs/jobs/calls_monitoring.rb +++ b/app/jobs/jobs/calls_monitoring.rb @@ -84,7 +84,7 @@ def call_price(attrs) initial_interval = attrs.fetch("#{key}_initial_interval").to_i #TODO: check if needed cast to int next_interval = attrs.fetch("#{key}_next_interval").to_i #TODO: check if needed cast to int connect_fee = attrs.fetch("#{key}_fee").to_f - vat = key == 'destination' ? attrs.fetch("customer_acc_vat", 0) : 0 + vat = key == 'destination' ? attrs.fetch("customer_acc_vat", 0).to_f : 0 initial_interval_billing = connect_fee + initial_interval * i_per_second_rate next_interval_billing = (duration > initial_interval ? 1 : 0) * ((duration - initial_interval).to_f / next_interval).ceil * next_interval * n_per_second_rate (initial_interval_billing + next_interval_billing) * (1 + vat / 100.0) diff --git a/spec/jobs/calls_monitoring_spec.rb b/spec/jobs/calls_monitoring_spec.rb index fd669c33a..5f779b2fe 100644 --- a/spec/jobs/calls_monitoring_spec.rb +++ b/spec/jobs/calls_monitoring_spec.rb @@ -94,7 +94,7 @@ # Customer 'customer_id' => account.contractor.id, 'customer_acc_id' => account.id, - 'customer_acc_vat' => account.vat, + 'customer_acc_vat' => account.vat.to_s, # Vendor 'vendor_id' => vendor_acc.contractor.id, 'vendor_acc_id' => vendor_acc.id, @@ -126,7 +126,7 @@ # Customer 'customer_id' => account.contractor.id, 'customer_acc_id' => account.id, - 'customer_acc_vat' => account.vat, + 'customer_acc_vat' => account.vat.to_s, # Vendor 'vendor_id' => vendor_acc.contractor.id, 'vendor_acc_id' => vendor_acc.id, From 7318fb0f969a59a30173733ebf256292e7c26769 Mon Sep 17 00:00:00 2001 From: Dmitry Sinina Date: Tue, 3 Apr 2018 13:56:04 +0300 Subject: [PATCH 2/5] Fix shared gw processing for termination --- config/locales/en.yml | 2 +- db/migrate/20180403104223_fix_shared_gw.rb | 178 +++++++++++++++++++++ db/structure.sql | 12 +- 3 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 db/migrate/20180403104223_fix_shared_gw.rb diff --git a/config/locales/en.yml b/config/locales/en.yml index 700ed8e58..f0a87d83b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -28,7 +28,7 @@ en: formtastic: hints: gateway: - is_shared: "Allows gateway to be used as origination equipment for any customer" + is_shared: "Allows gateway to be used as origination/termination equipment by any customer/vendor" max_30x_redirects: "How many 301/302 redirects Yeti will process" max_transfers: "How many SIP REFERs Yeti will process" system_sensor: diff --git a/db/migrate/20180403104223_fix_shared_gw.rb b/db/migrate/20180403104223_fix_shared_gw.rb new file mode 100644 index 000000000..ec712da3e --- /dev/null +++ b/db/migrate/20180403104223_fix_shared_gw.rb @@ -0,0 +1,178 @@ +class FixSharedGw < ActiveRecord::Migration + def up + execute %q{ + +CREATE OR REPLACE FUNCTION switch15.process_dp(i_profile switch15.callprofile58_ty, i_destination class4.destinations, i_dp class4.dialpeers, i_customer_acc billing.accounts, i_customer_gw class4.gateways, i_vendor_acc billing.accounts, i_pop_id integer, i_send_billing_information boolean, i_max_call_length integer) RETURNS SETOF switch15.callprofile58_ty + LANGUAGE plpgsql STABLE SECURITY DEFINER COST 10000 + AS $$ +DECLARE + /*dbg{*/ + v_start timestamp; + v_end timestamp; + /*}dbg*/ + v_gw class4.gateways%rowtype; +BEGIN + /*dbg{*/ + v_start:=now(); + --RAISE NOTICE 'process_dp in: %',i_profile;5 + v_end:=clock_timestamp(); + RAISE NOTICE '% ms -> process-DP. Found dialpeer: %',EXTRACT(MILLISECOND from v_end-v_start),row_to_json(i_dp,true); + /*}dbg*/ + + --RAISE NOTICE 'process_dp dst: %',i_destination; + if i_dp.gateway_id is null then + PERFORM id from class4.gateway_groups where id=i_dp.gateway_group_id and prefer_same_pop; + IF FOUND THEN + /*rel{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.contractor_id=i_dp.vendor_id and cg.enabled ORDER BY cg.pop_id=i_pop_id desc,cg.priority desc, random() LOOP + return query select * from process_gw_release(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}rel*/ + /*dbg{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id AND cg.enabled ORDER BY cg.pop_id=i_pop_id desc,cg.priority desc, random() LOOP + IF v_gw.contractor_id!=i_dp.vendor_id THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; + continue; + end if; + return query select * from process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}dbg*/ + else + /*rel{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.contractor_id=i_dp.vendor_id AND cg.enabled ORDER BY cg.priority desc, random() LOOP + return query select * from process_gw_release(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}rel*/ + /*dbg{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.enabled ORDER BY cg.priority desc, random() LOOP + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; + continue; + end if; + return query select * from process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}dbg*/ + end if; + else + select into v_gw * from class4.gateways cg where cg.id=i_dp.gateway_id and cg.enabled; + if FOUND THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Stop processing'; + return; + end if; + + /*rel{*/ + return query select * from + process_gw_release(i_profile, i_destination, i_dp, i_customer_acc,i_customer_gw, i_vendor_acc, v_gw, i_send_billing_information,i_max_call_length); + /*}rel*/ + /*dbg{*/ + return query select * from + process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc,i_customer_gw, i_vendor_acc, v_gw, i_send_billing_information,i_max_call_length); + /*}dbg*/ + else + return; + end if; + end if; +END; +$$; + + + set search_path TO switch15; + SELECT * from switch15.preprocess_all(); + set search_path TO gui, public, switch, billing, class4, runtime_stats, sys, logs, data_import; + + } + end + + def down + execute %q{ + +CREATE OR REPLACE FUNCTION switch15.process_dp(i_profile switch15.callprofile58_ty, i_destination class4.destinations, i_dp class4.dialpeers, i_customer_acc billing.accounts, i_customer_gw class4.gateways, i_vendor_acc billing.accounts, i_pop_id integer, i_send_billing_information boolean, i_max_call_length integer) RETURNS SETOF switch15.callprofile58_ty + LANGUAGE plpgsql STABLE SECURITY DEFINER COST 10000 + AS $$ +DECLARE + /*dbg{*/ + v_start timestamp; + v_end timestamp; + /*}dbg*/ + v_gw class4.gateways%rowtype; +BEGIN + /*dbg{*/ + v_start:=now(); + --RAISE NOTICE 'process_dp in: %',i_profile;5 + v_end:=clock_timestamp(); + RAISE NOTICE '% ms -> process-DP. Found dialpeer: %',EXTRACT(MILLISECOND from v_end-v_start),row_to_json(i_dp,true); + /*}dbg*/ + + --RAISE NOTICE 'process_dp dst: %',i_destination; + if i_dp.gateway_id is null then + PERFORM id from class4.gateway_groups where id=i_dp.gateway_group_id and prefer_same_pop; + IF FOUND THEN + /*rel{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.contractor_id=i_dp.vendor_id and cg.enabled ORDER BY cg.pop_id=i_pop_id desc,cg.priority desc, random() LOOP + return query select * from process_gw_release(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}rel*/ + /*dbg{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id AND cg.enabled ORDER BY cg.pop_id=i_pop_id desc,cg.priority desc, random() LOOP + IF v_gw.contractor_id!=i_dp.vendor_id THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; + continue; + end if; + return query select * from process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}dbg*/ + else + /*rel{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.contractor_id=i_dp.vendor_id AND cg.enabled ORDER BY cg.priority desc, random() LOOP + return query select * from process_gw_release(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}rel*/ + /*dbg{*/ + FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.enabled ORDER BY cg.priority desc, random() LOOP + IF v_gw.contractor_id!=i_dp.vendor_id THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; + continue; + end if; + return query select * from process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc, + i_customer_gw, i_vendor_acc , v_gw, i_send_billing_information,i_max_call_length); + end loop; + /*}dbg*/ + end if; + else + select into v_gw * from class4.gateways cg where cg.id=i_dp.gateway_id and cg.enabled; + if FOUND THEN + IF v_gw.contractor_id!=i_dp.vendor_id THEN + RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Stop processing'; + return; + end if; + + /*rel{*/ + return query select * from + process_gw_release(i_profile, i_destination, i_dp, i_customer_acc,i_customer_gw, i_vendor_acc, v_gw, i_send_billing_information,i_max_call_length); + /*}rel*/ + /*dbg{*/ + return query select * from + process_gw_debug(i_profile, i_destination, i_dp, i_customer_acc,i_customer_gw, i_vendor_acc, v_gw, i_send_billing_information,i_max_call_length); + /*}dbg*/ + else + return; + end if; + end if; +END; +$$; + + set search_path TO switch15; + SELECT * from switch15.preprocess_all(); + set search_path TO gui, public, switch, billing, class4, runtime_stats, sys, logs, data_import; + + } + end +end diff --git a/db/structure.sql b/db/structure.sql index 331ee8dfc..adc1ac712 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -14771,7 +14771,7 @@ BEGIN /*}rel*/ /*dbg{*/ FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.enabled ORDER BY cg.priority desc, random() LOOP - IF v_gw.contractor_id!=i_dp.vendor_id THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; continue; end if; @@ -14783,7 +14783,7 @@ BEGIN else select into v_gw * from class4.gateways cg where cg.id=i_dp.gateway_id and cg.enabled; if FOUND THEN - IF v_gw.contractor_id!=i_dp.vendor_id THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Stop processing'; return; end if; @@ -14844,7 +14844,7 @@ BEGIN /*dbg{*/ FOr v_gw in select * from class4.gateways cg where cg.gateway_group_id=i_dp.gateway_group_id and cg.enabled ORDER BY cg.priority desc, random() LOOP - IF v_gw.contractor_id!=i_dp.vendor_id THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Skip gateway'; continue; end if; @@ -14856,7 +14856,7 @@ BEGIN else select into v_gw * from class4.gateways cg where cg.id=i_dp.gateway_id and cg.enabled; if FOUND THEN - IF v_gw.contractor_id!=i_dp.vendor_id THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Stop processing'; return; end if; @@ -14910,7 +14910,7 @@ BEGIN else select into v_gw * from class4.gateways cg where cg.id=i_dp.gateway_id and cg.enabled; if FOUND THEN - IF v_gw.contractor_id!=i_dp.vendor_id THEN + IF v_gw.contractor_id!=i_dp.vendor_id AND NOT v_gw.is_shared THEN RAISE WARNING 'process_dp: Gateway owner !=dialpeer owner. Stop processing'; return; end if; @@ -26611,3 +26611,5 @@ INSERT INTO public.schema_migrations (version) VALUES ('20180318143341'); INSERT INTO public.schema_migrations (version) VALUES ('20180320120746'); +INSERT INTO public.schema_migrations (version) VALUES ('20180403104223'); + From e7fc2a7a7ef6d33a59643dea09cd510896ad8f6d Mon Sep 17 00:00:00 2001 From: Gena Date: Tue, 3 Apr 2018 18:11:27 +0300 Subject: [PATCH 3/5] update Gem `yetis_node` Update of Gem `yetis_node` contains fix for `request`-commands --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index ef88a5bb5..2ececdea0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -88,7 +88,7 @@ GIT GIT remote: https://github.com/yeti-switch/yetis_node.git - revision: 1b0b40789a5385ff3935d7739211f42402e385c4 + revision: 99440a719fde0904b4ad093ede27d6661e595190 specs: yetis_node (1.0.0) jrpc (~> 1.0, >= 0.4.6) From 13fc526db648bab3326279d63d61f1a3b627dc07 Mon Sep 17 00:00:00 2001 From: Gena Date: Fri, 13 Apr 2018 13:55:19 +0300 Subject: [PATCH 4/5] Add AdminAPI ednpoint for `Routing::AreaPrefix` Endpiont '/area-prefixes' with full CRUD --- .../admin/routing/area_prefixes_controller.rb | 2 + .../admin/routing/area_prefix_resource.rb | 7 ++ config/routes.rb | 1 + .../admin/api/routing/area_prefixes_spec.rb | 48 +++++++++++ .../admin/routing/area_prefixes_controller.rb | 80 +++++++++++++++++++ spec/factories/routing/area_prefix.rb | 7 ++ 6 files changed, 145 insertions(+) create mode 100644 app/controllers/api/rest/admin/routing/area_prefixes_controller.rb create mode 100644 app/resources/api/rest/admin/routing/area_prefix_resource.rb create mode 100644 spec/acceptance/rest/admin/api/routing/area_prefixes_spec.rb create mode 100644 spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb create mode 100644 spec/factories/routing/area_prefix.rb diff --git a/app/controllers/api/rest/admin/routing/area_prefixes_controller.rb b/app/controllers/api/rest/admin/routing/area_prefixes_controller.rb new file mode 100644 index 000000000..c2711b13d --- /dev/null +++ b/app/controllers/api/rest/admin/routing/area_prefixes_controller.rb @@ -0,0 +1,2 @@ +class Api::Rest::Admin::Routing::AreaPrefixesController < Api::Rest::Admin::BaseController +end diff --git a/app/resources/api/rest/admin/routing/area_prefix_resource.rb b/app/resources/api/rest/admin/routing/area_prefix_resource.rb new file mode 100644 index 000000000..e81403d13 --- /dev/null +++ b/app/resources/api/rest/admin/routing/area_prefix_resource.rb @@ -0,0 +1,7 @@ +class Api::Rest::Admin::Routing::AreaPrefixResource < ::BaseResource + model_name 'Routing::AreaPrefix' + + attributes :prefix + + has_one :area, class_name: 'Area' +end diff --git a/config/routes.rb b/config/routes.rb index fb8a73e85..096d3d766 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -110,6 +110,7 @@ namespace :routing do jsonapi_resources :areas + jsonapi_resources :area_prefixes jsonapi_resources :numberlists jsonapi_resources :numberlist_items jsonapi_resources :numberlist_actions diff --git a/spec/acceptance/rest/admin/api/routing/area_prefixes_spec.rb b/spec/acceptance/rest/admin/api/routing/area_prefixes_spec.rb new file mode 100644 index 000000000..3a0b469f1 --- /dev/null +++ b/spec/acceptance/rest/admin/api/routing/area_prefixes_spec.rb @@ -0,0 +1,48 @@ +require 'spec_helper' +require 'rspec_api_documentation/dsl' + +resource 'Routing AreaPrefix' do + include_context :acceptance_admin_user + + let(:collection) { create_list(:area_prefix, 2) } + let(:record) { collection.first } + + required_params = %i(prefix) + optional_params = %i() + + required_relationships = %i(area) + optional_relationships = %i() + + include_context :acceptance_index_show, namespace: 'routing', type: 'area-prefixes' + include_context :acceptance_delete, namespace: 'routing', type: 'area-prefixes' + + post '/api/rest/admin/routing/area-prefixes' do + parameter :type, 'Resource type (area-prefixes)', scope: :data, required: true + + jsonapi_attributes(required_params, optional_params) + jsonapi_relationships(required_relationships, optional_relationships) + + let(:prefix) { '777' } + let(:area) { wrap_relationship(:areas, create(:area).id) } + + example_request 'create new entry' do + expect(status).to eq(201) + end + end + + put '/api/rest/admin/routing/area-prefixes/:id' do + parameter :type, 'Resource type (area-prefixes)', scope: :data, required: true + parameter :id, 'AreaPrefix ID', scope: :data, required: true + + jsonapi_attributes(required_params, optional_params) + jsonapi_relationships(required_relationships, optional_relationships) + + let(:id) { create(:area_prefix).id } + let(:prefix) { '765' } + let(:area) { wrap_relationship(:areas, create(:area).id) } + + example_request 'update values' do + expect(status).to eq(200) + end + end +end diff --git a/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb b/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb new file mode 100644 index 000000000..cf316f19b --- /dev/null +++ b/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb @@ -0,0 +1,80 @@ +require 'spec_helper' + +describe Api::Rest::Admin::Routing::AreaPrefixesController, type: :controller do + + include_context :jsonapi_admin_headers + + let(:resource_type) { 'area-prefixes' } + + let(:record) { create :area_prefix } + + describe 'GET index' do + let!(:records) { create_list :area_prefix, 2 } + before { get :index } + + it { expect(response.status).to eq(200) } + it { expect(response_data.size).to eq(Routing::AreaPrefix.count) } + end + + describe 'GET show' do + before { get :show, id: record.id } + + it 'receive expected fields' do + expect(response_data.deep_symbolize_keys).to a_hash_including( + id: record.id.to_s, + attributes: { + prefix: record.prefix + } + ) + end + end + + describe 'POST create' do + before do + post :create, data: { type: resource_type, + attributes: attributes, + relationships: relationships } + end + + let(:attributes) do + { prefix: '777' } + end + + let(:relationships) do + { + 'area': wrap_relationship(:'areas', create(:area).to_param) + } + end + + it 'creates proper record' do + expect(response.status).to eq(201) + expect(Routing::AreaPrefix.last).to have_attributes( + prefix: attributes[:prefix], + area_id: Routing::Area.last.id + ) + end + end + + describe 'PUT update' do + before do + put :update, id: record.to_param, data: { type: resource_type, + id: record.to_param, + attributes: attributes } + end + + let(:attributes) do + { prefix: '888' } + end + + it { expect(response.status).to eq(200) } + it { expect(record.reload.prefix).to eq(attributes[:prefix]) } + end + + describe 'DELETE destroy' do + before { delete :destroy, id: record.to_param } + + it { expect(response.status).to eq(204) } + it { expect(Routing::AreaPrefix.count).to eq(0) } + end + +end diff --git a/spec/factories/routing/area_prefix.rb b/spec/factories/routing/area_prefix.rb new file mode 100644 index 000000000..d41048272 --- /dev/null +++ b/spec/factories/routing/area_prefix.rb @@ -0,0 +1,7 @@ +FactoryGirl.define do + factory :area_prefix, class: Routing::AreaPrefix do + sequence(:prefix) { |n| "#{n}#{n+1}#{n+2}" } # example: '123', '234'... + + association :area + end +end From 8389f866702b07c01ac1719506ef9c4c4b64beae Mon Sep 17 00:00:00 2001 From: Gena Date: Thu, 12 Apr 2018 18:54:01 +0300 Subject: [PATCH 5/5] Add filters by routing_tag_ids Add new filters for Destination, Dialpeer, RoutingTagDetectionRule: - routing_tag_ids_convers (`yeti_ext.tag_compare`) - routing_tag_ids_array_contaings (`@> ARRAY[...]`) - tagged (`<> '{}'` | `= '{}`) --- app/admin/routing/destinations.rb | 1 + app/admin/routing/dialpeers.rb | 2 ++ .../routing/routing_tag_detection_rules.rb | 1 + .../concerns/routing_tag_ids_scopeable.rb | 19 +++++++++++++++++++ app/models/destination.rb | 6 +++++- app/models/dialpeer.rb | 5 ++++- .../routing/routing_tag_detection_rule.rb | 10 ++++++++++ config/initializers/yeti.rb | 1 + .../acts_as_filter_by_routing_tag_ids.rb | 19 +++++++++++++++++++ 9 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 app/models/concerns/routing_tag_ids_scopeable.rb create mode 100644 lib/resource_dsl/acts_as_filter_by_routing_tag_ids.rb diff --git a/app/admin/routing/destinations.rb b/app/admin/routing/destinations.rb index f6e6a059d..81f56eb33 100644 --- a/app/admin/routing/destinations.rb +++ b/app/admin/routing/destinations.rb @@ -86,6 +86,7 @@ filter :external_id_eq, label: 'EXTERNAL_ID' + acts_as_filter_by_routing_tag_ids permit_params :enabled, :prefix, :dst_number_min_length, :dst_number_max_length, :rateplan_id, :next_rate, :connect_fee, diff --git a/app/admin/routing/dialpeers.rb b/app/admin/routing/dialpeers.rb index 7f5d9d447..9a0168b28 100644 --- a/app/admin/routing/dialpeers.rb +++ b/app/admin/routing/dialpeers.rb @@ -210,6 +210,8 @@ def update filter :external_id filter :exclusive_route, as: :select, collection: [["Yes", true], ["No", false]] + acts_as_filter_by_routing_tag_ids + form do |f| f.semantic_errors *f.object.errors.keys diff --git a/app/admin/routing/routing_tag_detection_rules.rb b/app/admin/routing/routing_tag_detection_rules.rb index 0a278c8b9..5f83713a6 100644 --- a/app/admin/routing/routing_tag_detection_rules.rb +++ b/app/admin/routing/routing_tag_detection_rules.rb @@ -79,4 +79,5 @@ def update filter :src_area, input_html: {class: 'chosen'} filter :dst_area, input_html: {class: 'chosen'} + acts_as_filter_by_routing_tag_ids end diff --git a/app/models/concerns/routing_tag_ids_scopeable.rb b/app/models/concerns/routing_tag_ids_scopeable.rb new file mode 100644 index 000000000..819e95910 --- /dev/null +++ b/app/models/concerns/routing_tag_ids_scopeable.rb @@ -0,0 +1,19 @@ +module RoutingTagIdsScopeable + extend ActiveSupport::Concern + + included do + + scope :routing_tag_ids_covers, ->(*id) do + where("yeti_ext.tag_compare(routing_tag_ids, ARRAY[#{id.join(',')}])>0") + end + + scope :tagged, ->(value) do + if ActiveRecord::Type::Boolean.new.type_cast_from_user(value) + where("routing_tag_ids <> '{}'") # has tags + else + where("routing_tag_ids = '{}'") # no tags + end + end + + end +end diff --git a/app/models/destination.rb b/app/models/destination.rb index 45a6bf214..65305274f 100644 --- a/app/models/destination.rb +++ b/app/models/destination.rb @@ -49,6 +49,8 @@ class Destination < Yeti::ActiveRecord include Yeti::NetworkDetector + include RoutingTagIdsScopeable + scope :low_quality, -> { where quality_alarm: true } scope :where_customer, -> (id) do @@ -152,7 +154,9 @@ def is_valid_till? def self.ransackable_scopes(auth_object = nil) [ - :routing_for_contains + :routing_for_contains, + :routing_tag_ids_covers, + :tagged ] end diff --git a/app/models/dialpeer.rb b/app/models/dialpeer.rb index 18a0a1269..25366bc11 100644 --- a/app/models/dialpeer.rb +++ b/app/models/dialpeer.rb @@ -88,6 +88,7 @@ class Dialpeer < Yeti::ActiveRecord include Yeti::ResourceStatus include Yeti::NetworkDetector + include RoutingTagIdsScopeable scope :locked, -> { where locked: true } @@ -197,7 +198,9 @@ def vendor_owners_the_gateway_group def self.ransackable_scopes(auth_object = nil) [ - :routing_for_contains + :routing_for_contains, + :routing_tag_ids_covers, + :tagged ] end diff --git a/app/models/routing/routing_tag_detection_rule.rb b/app/models/routing/routing_tag_detection_rule.rb index a49f775aa..6ce524d5e 100644 --- a/app/models/routing/routing_tag_detection_rule.rb +++ b/app/models/routing/routing_tag_detection_rule.rb @@ -24,8 +24,18 @@ class Routing::RoutingTagDetectionRule < Yeti::ActiveRecord array_belongs_to :routing_tags, class_name: 'Routing::RoutingTag', foreign_key: :routing_tag_ids array_belongs_to :tag_action_values, class_name: 'Routing::RoutingTag', foreign_key: :tag_action_value + include RoutingTagIdsScopeable + def display_name "#{self.id}" end + private + + def self.ransackable_scopes(auth_object = nil) + [ + :routing_tag_ids_covers, + :tagged + ] + end end diff --git a/config/initializers/yeti.rb b/config/initializers/yeti.rb index 06817492e..7c75eff44 100644 --- a/config/initializers/yeti.rb +++ b/config/initializers/yeti.rb @@ -22,6 +22,7 @@ ActiveAdmin::ResourceDSL.send :include, ResourceDSL::ActsAsAsyncDestroy ActiveAdmin::ResourceDSL.send :include, ResourceDSL::ActsAsAsyncUpdate ActiveAdmin::ResourceDSL.send :include, ResourceDSL::ActsAsDelayedJobLock +ActiveAdmin::ResourceDSL.send :include, ResourceDSL::ActsAsFilterByRoutingTagIds # ActiveAdmin::CSVBuilder.send(:include, Yeti::CSVBuilder) diff --git a/lib/resource_dsl/acts_as_filter_by_routing_tag_ids.rb b/lib/resource_dsl/acts_as_filter_by_routing_tag_ids.rb new file mode 100644 index 000000000..773c02a87 --- /dev/null +++ b/lib/resource_dsl/acts_as_filter_by_routing_tag_ids.rb @@ -0,0 +1,19 @@ +module ResourceDSL + module ActsAsFilterByRoutingTagIds + + def acts_as_filter_by_routing_tag_ids + + filter :routing_tag_ids_covers, as: :select, + collection: ->{ Routing::RoutingTag.pluck(:name, :id) }, + input_html: { class: 'chosen', multiple: true } + + filter :routing_tag_ids_array_contains, label: 'Routing Tag IDs Contains', as: :select, + collection: ->{ Routing::RoutingTag.pluck(:name, :id) }, + input_html: { class: 'chosen', multiple: true } + + filter :tagged, as: :select , collection: [ ["Yes", true], ["No", false]] + + end + + end +end