diff --git a/app/resources/api/rest/customer/v1/cdr_resource.rb b/app/resources/api/rest/customer/v1/cdr_resource.rb index d51e89367..5375159ae 100644 --- a/app/resources/api/rest/customer/v1/cdr_resource.rb +++ b/app/resources/api/rest/customer/v1/cdr_resource.rb @@ -43,7 +43,7 @@ def self.default_sort has_one :account, class_name: 'Account', relation_name: :customer_acc, foreign_key_on: :related ransack_filter :uuid, type: :uuid - ransack_filter :time_start, type: :datetime + ransack_filter :time_start, type: :datetime, default: { gteq: :apply_default_filter_time_start_gteq } ransack_filter :time_connect, type: :datetime ransack_filter :time_end, type: :datetime ransack_filter :duration, type: :number @@ -105,4 +105,11 @@ def self.apply_allowed_accounts(records, options) scope = scope.where_customer_account(context[:allowed_account_ids]) if context[:allowed_account_ids].present? scope end + + def self.apply_default_filter_time_start_gteq(options) + return nil if options.dig(:params, :filter, :time_start_gt).present? + return nil if options.dig(:params, :filter, :time_start_eq).present? + + 24.hours.ago.strftime('%F %T') + end end diff --git a/app/resources/base_resource.rb b/app/resources/base_resource.rb index 58cb3cfab..43963ad11 100644 --- a/app/resources/base_resource.rb +++ b/app/resources/base_resource.rb @@ -50,15 +50,22 @@ def self.type(custom_type) # @see RansackFilterBuilder::RANSACK_TYPE_SUFIXES_DIC # @param column [Symbol] # @param verify [Proc, nil] custom validate/change values (receives [Array] values) - def self.ransack_filter(attr, type:, column: nil, verify: nil, collection: nil) + def self.ransack_filter(attr, type:, column: nil, verify: nil, collection: nil, default: nil) raise ArgumentError, "type #{type} is not supported" unless RansackFilterBuilder.type_supported?(type) raise ArgumentError, ":collection option for type #{type} is not supported" if collection && type != :enum - RansackFilterBuilder.suffixes_for_type(type).each do |suf| + suffixes = RansackFilterBuilder.suffixes_for_type(type) + if default + wrong_suffixes = default.keys - suffixes.map(&:to_sym) + raise ArgumentError, "ransack_filter :#{attr} has wrong default suffixes: #{wrong_suffixes.join(', ')}" if wrong_suffixes.any? + end + suffixes.each do |suf| builder = RansackFilterBuilder.new(attr: attr, operator: suf, column: column, verify: verify, collection: collection) filter builder.filter_name, verify: ->(values, _ctx) { builder.verify(values) }, - apply: ->(records, values, _opts) { builder.apply(records, values) } + apply: ->(records, values, _opts) { builder.apply(records, values) }, + # see JsonapiRequestParserPatch#set_default_filters + default: default&.fetch(suf.to_sym, nil) end end diff --git a/config/initializers/jsonapi_resources.rb b/config/initializers/jsonapi_resources.rb index 3f9f76990..ad957dcb5 100644 --- a/config/initializers/jsonapi_resources.rb +++ b/config/initializers/jsonapi_resources.rb @@ -4,6 +4,7 @@ require 'jsonapi/exceptions/authentication_failed' require 'jsonapi/operation_dispatcher_patch' require 'jsonapi/relationship_patch' +require 'jsonapi/request_parser_patch' JSONAPI.configure do |config| # can be paged, offset, none (default) diff --git a/lib/jsonapi/request_parser_patch.rb b/lib/jsonapi/request_parser_patch.rb new file mode 100644 index 000000000..729fd5a8b --- /dev/null +++ b/lib/jsonapi/request_parser_patch.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module JsonapiRequestParserPatch + def set_default_filters + @resource_klass._allowed_filters.each do |filter, opts| + next if opts[:default].nil? || !@filters[filter].nil? + + if opts[:default].is_a?(Proc) + value = opts[:default].call({ params:, context: }) + elsif opts[:default].is_a?(Symbol) + value = @resource_klass.public_send(opts[:default], { params:, context: }) + else + value = opts[:default] + end + + @filters[filter] = value unless value.nil? + end + end +end + +JSONAPI::RequestParser.prepend(JsonapiRequestParserPatch) diff --git a/spec/controllers/api/rest/admin/accounts_controller_spec.rb b/spec/controllers/api/rest/admin/accounts_controller_spec.rb index 9e25e338f..11e158353 100755 --- a/spec/controllers/api/rest/admin/accounts_controller_spec.rb +++ b/spec/controllers/api/rest/admin/accounts_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end before { create_list :account, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create(:account) } @@ -36,6 +37,7 @@ end let(:factory) { :account } let(:trait) { :with_max_balance } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name it_behaves_like :jsonapi_filters_by_number_field, :balance diff --git a/spec/controllers/api/rest/admin/cdr/auth_logs_controller_spec.rb b/spec/controllers/api/rest/admin/cdr/auth_logs_controller_spec.rb index 5e372788b..2b273d151 100644 --- a/spec/controllers/api/rest/admin/cdr/auth_logs_controller_spec.rb +++ b/spec/controllers/api/rest/admin/cdr/auth_logs_controller_spec.rb @@ -93,6 +93,7 @@ end let(:factory) { :auth_log } let(:trait) { :with_id } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_datetime_field, :request_time it_behaves_like :jsonapi_filters_by_boolean_field, :success, type: :boolean diff --git a/spec/controllers/api/rest/admin/cdr/cdrs_controller_spec.rb b/spec/controllers/api/rest/admin/cdr/cdrs_controller_spec.rb index 99c5347de..f5e65fd3b 100644 --- a/spec/controllers/api/rest/admin/cdr/cdrs_controller_spec.rb +++ b/spec/controllers/api/rest/admin/cdr/cdrs_controller_spec.rb @@ -443,6 +443,7 @@ end let(:factory) { :cdr } let(:trait) { :with_id_and_uuid } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_datetime_field, :time_start it_behaves_like :jsonapi_filters_by_number_field, :destination_next_rate diff --git a/spec/controllers/api/rest/admin/codec_groups_controller_spec.rb b/spec/controllers/api/rest/admin/codec_groups_controller_spec.rb index 7c35c7dba..f0fa451ea 100644 --- a/spec/controllers/api/rest/admin/codec_groups_controller_spec.rb +++ b/spec/controllers/api/rest/admin/codec_groups_controller_spec.rb @@ -15,6 +15,7 @@ get :index, params: json_api_request_query end let(:factory) { :codec_group } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name end diff --git a/spec/controllers/api/rest/admin/contacts_controller_spec.rb b/spec/controllers/api/rest/admin/contacts_controller_spec.rb index 54785b309..01bf14c92 100644 --- a/spec/controllers/api/rest/admin/contacts_controller_spec.rb +++ b/spec/controllers/api/rest/admin/contacts_controller_spec.rb @@ -15,6 +15,7 @@ get :index, params: json_api_request_query end let(:factory) { :contact } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :email it_behaves_like :jsonapi_filters_by_string_field, :notes diff --git a/spec/controllers/api/rest/admin/contractors_controller_spec.rb b/spec/controllers/api/rest/admin/contractors_controller_spec.rb index 56311a94e..c30f1fdd9 100755 --- a/spec/controllers/api/rest/admin/contractors_controller_spec.rb +++ b/spec/controllers/api/rest/admin/contractors_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end before { create_list :contractor, 2, vendor: true } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create(:contractor, vendor: true) } @@ -35,6 +36,7 @@ get :index, params: json_api_request_query end let(:factory) { :vendor } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name it_behaves_like :jsonapi_filters_by_boolean_field, :enabled diff --git a/spec/controllers/api/rest/admin/dialpeers_controller_spec.rb b/spec/controllers/api/rest/admin/dialpeers_controller_spec.rb index f66f6df51..9a4f1c907 100755 --- a/spec/controllers/api/rest/admin/dialpeers_controller_spec.rb +++ b/spec/controllers/api/rest/admin/dialpeers_controller_spec.rb @@ -19,6 +19,7 @@ get :index, params: json_api_request_query end before { create_list :dialpeer, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_external_id do let(:subject_record) { create :dialpeer } @@ -46,6 +47,7 @@ get :index, params: json_api_request_query end let(:factory) { :dialpeer } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_boolean_field, :enabled it_behaves_like :jsonapi_filters_by_number_field, :next_rate diff --git a/spec/controllers/api/rest/admin/gateway_groups_controller_spec.rb b/spec/controllers/api/rest/admin/gateway_groups_controller_spec.rb index e40b30433..d2843d3e4 100755 --- a/spec/controllers/api/rest/admin/gateway_groups_controller_spec.rb +++ b/spec/controllers/api/rest/admin/gateway_groups_controller_spec.rb @@ -26,6 +26,7 @@ get :index, params: json_api_request_query end let(:factory) { :gateway_group } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name end @@ -53,6 +54,7 @@ get :index, params: json_api_request_query end before { create_list :gateway_group, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create :gateway_group } diff --git a/spec/controllers/api/rest/admin/gateways_controller_spec.rb b/spec/controllers/api/rest/admin/gateways_controller_spec.rb index 84e921f13..1443f6aff 100644 --- a/spec/controllers/api/rest/admin/gateways_controller_spec.rb +++ b/spec/controllers/api/rest/admin/gateways_controller_spec.rb @@ -9,6 +9,7 @@ end let(:factory) { :gateway } let(:trait) { :with_incoming_auth } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :host it_behaves_like :jsonapi_filters_by_number_field, :port diff --git a/spec/controllers/api/rest/admin/payments_controller_spec.rb b/spec/controllers/api/rest/admin/payments_controller_spec.rb index 7c2239060..abc6f58a2 100755 --- a/spec/controllers/api/rest/admin/payments_controller_spec.rb +++ b/spec/controllers/api/rest/admin/payments_controller_spec.rb @@ -26,6 +26,7 @@ get :index, params: json_api_request_query end let(:factory) { :payment } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_number_field, :amount it_behaves_like :jsonapi_filters_by_string_field, :notes diff --git a/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb b/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb index 314972b71..479a49d3a 100644 --- a/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb +++ b/spec/controllers/api/rest/admin/routing/area_prefixes_controller.rb @@ -20,6 +20,7 @@ get :index, params: json_api_request_query end let(:factory) { :area_prefix } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :prefix end diff --git a/spec/controllers/api/rest/admin/routing/areas_controller_spec.rb b/spec/controllers/api/rest/admin/routing/areas_controller_spec.rb index 87fac46bf..87242969e 100644 --- a/spec/controllers/api/rest/admin/routing/areas_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/areas_controller_spec.rb @@ -20,6 +20,7 @@ get :index, params: json_api_request_query end let(:factory) { :area } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name end diff --git a/spec/controllers/api/rest/admin/routing/destination_next_rates_spec.rb b/spec/controllers/api/rest/admin/routing/destination_next_rates_spec.rb index 4701d55a5..21de42598 100644 --- a/spec/controllers/api/rest/admin/routing/destination_next_rates_spec.rb +++ b/spec/controllers/api/rest/admin/routing/destination_next_rates_spec.rb @@ -9,6 +9,7 @@ end let(:factory) { :destination_next_rate } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_number_field, :initial_rate it_behaves_like :jsonapi_filters_by_number_field, :next_rate diff --git a/spec/controllers/api/rest/admin/routing/destinations_controller_spec.rb b/spec/controllers/api/rest/admin/routing/destinations_controller_spec.rb index e5dd9a5c7..3b5079880 100755 --- a/spec/controllers/api/rest/admin/routing/destinations_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/destinations_controller_spec.rb @@ -105,6 +105,7 @@ get :index, params: json_api_request_query end before { create_list :destination, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_external_id do let(:subject_record) { create(:destination) } @@ -152,6 +153,7 @@ get :index, params: json_api_request_query end let(:factory) { :destination } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_boolean_field, :enabled it_behaves_like :jsonapi_filters_by_string_field, :prefix diff --git a/spec/controllers/api/rest/admin/routing/dialpeer_next_rates_controller_spec.rb b/spec/controllers/api/rest/admin/routing/dialpeer_next_rates_controller_spec.rb index 94a36a67b..79671f9c1 100644 --- a/spec/controllers/api/rest/admin/routing/dialpeer_next_rates_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/dialpeer_next_rates_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end let(:factory) { :dialpeer_next_rate } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_number_field, :next_rate it_behaves_like :jsonapi_filters_by_number_field, :initial_rate diff --git a/spec/controllers/api/rest/admin/routing/numberlist_items_controller_spec.rb b/spec/controllers/api/rest/admin/routing/numberlist_items_controller_spec.rb index c91cd3926..e2f8c94e6 100644 --- a/spec/controllers/api/rest/admin/routing/numberlist_items_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/numberlist_items_controller_spec.rb @@ -21,6 +21,7 @@ get :index, params: json_api_request_query end let(:factory) { :numberlist_item } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :key it_behaves_like :jsonapi_filters_by_number_field, :action_id diff --git a/spec/controllers/api/rest/admin/routing/numberlists_controller_spec.rb b/spec/controllers/api/rest/admin/routing/numberlists_controller_spec.rb index d84319173..b95912699 100644 --- a/spec/controllers/api/rest/admin/routing/numberlists_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/numberlists_controller_spec.rb @@ -8,6 +8,7 @@ get :index, params: json_api_request_query end let(:factory) { :numberlist } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name it_behaves_like :jsonapi_filters_by_number_field, :default_action_id diff --git a/spec/controllers/api/rest/admin/routing/rateplans_controller_spec.rb b/spec/controllers/api/rest/admin/routing/rateplans_controller_spec.rb index de7fb1b22..f10b07acd 100755 --- a/spec/controllers/api/rest/admin/routing/rateplans_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/rateplans_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end before { create_list :rateplan, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create :rateplan } @@ -35,6 +36,7 @@ get :index, params: json_api_request_query end let(:factory) { :rateplan } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name end diff --git a/spec/controllers/api/rest/admin/routing/routing_groups_controller_spec.rb b/spec/controllers/api/rest/admin/routing/routing_groups_controller_spec.rb index 44b78041f..b7ba91f18 100755 --- a/spec/controllers/api/rest/admin/routing/routing_groups_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/routing_groups_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end before { create_list(:routing_group, 2) } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create(:routing_group) } diff --git a/spec/controllers/api/rest/admin/routing/routing_tag_detection_rules_controller_spec.rb b/spec/controllers/api/rest/admin/routing/routing_tag_detection_rules_controller_spec.rb index aa3ac78b0..5bc44bd00 100644 --- a/spec/controllers/api/rest/admin/routing/routing_tag_detection_rules_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing/routing_tag_detection_rules_controller_spec.rb @@ -31,6 +31,7 @@ get :index, params: json_api_request_query end let(:factory) { :routing_tag_detection_rule } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :src_prefix it_behaves_like :jsonapi_filters_by_string_field, :dst_prefix diff --git a/spec/controllers/api/rest/admin/routing_plans_controller_spec.rb b/spec/controllers/api/rest/admin/routing_plans_controller_spec.rb index 14d4bd134..c732dc655 100755 --- a/spec/controllers/api/rest/admin/routing_plans_controller_spec.rb +++ b/spec/controllers/api/rest/admin/routing_plans_controller_spec.rb @@ -24,6 +24,7 @@ get :index, params: json_api_request_query end before { create_list :routing_plan, 2 } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filter_by_name do let(:subject_record) { create :routing_plan } @@ -35,6 +36,7 @@ get :index, params: json_api_request_query end let(:factory) { :routing_plan } + let(:json_api_request_query) { nil } it_behaves_like :jsonapi_filters_by_string_field, :name it_behaves_like :jsonapi_filters_by_number_field, :rate_delta_max diff --git a/spec/requests/api/rest/customer/v1/cdrs_controller_spec.rb b/spec/requests/api/rest/customer/v1/cdrs_controller_spec.rb index 74221fd7a..8eb072141 100644 --- a/spec/requests/api/rest/customer/v1/cdrs_controller_spec.rb +++ b/spec/requests/api/rest/customer/v1/cdrs_controller_spec.rb @@ -19,6 +19,91 @@ it_behaves_like :json_api_customer_v1_check_authorization + context 'with default filters (time_start_gteq)' do + let!(:cdrs) do + [ + create(:cdr, customer_acc: account), + create(:cdr, customer_acc: account, time_start: 23.hours.ago) + ] + end + + before do + # ignored because default filter is time_start_gteq: 24.hours.ago + create(:cdr, customer_acc: account, time_start: 25.hours.ago) + create(:cdr, customer_acc: account, time_start: 35.hours.ago) + + # ignored because base collection has only records with is_last_cdr=true + create(:cdr, customer_acc: account, is_last_cdr: false) + end + + it 'returns records of this customer' do + subject + expect(response.status).to eq(200) + actual_ids = response_json[:data].pluck(:id) + expect(actual_ids).to match_array(cdrs.map(&:uuid)) + end + end + + context 'with time_start_gteq filter' do + let(:json_api_request_query) do + { filter: { time_start_gteq: 48.hours.ago.strftime('%F %T') } } + end + let!(:cdrs) do + [ + create(:cdr, customer_acc: account), + create(:cdr, customer_acc: account, time_start: 23.hours.ago), + # included in collection because passed filter time_start_gteq overrides default filter time_start_gteq + create(:cdr, customer_acc: account, time_start: 47.hours.ago) + ] + end + + before do + # ignored because passed filter is time_start_gteq: 48.hours.ago + create(:cdr, customer_acc: account, time_start: 49.hours.ago) + create(:cdr, customer_acc: account, time_start: 100.days.ago) + + # ignored because base collection has only records with is_last_cdr=true + create(:cdr, customer_acc: account, is_last_cdr: false) + end + + it 'returns records of this customer' do + subject + expect(response.status).to eq(200) + actual_ids = response_json[:data].pluck(:id) + expect(actual_ids).to match_array(cdrs.map(&:uuid)) + end + end + + context 'with time_start_gt filter' do + let(:json_api_request_query) do + { filter: { time_start_gt: 48.hours.ago.strftime('%F %T') } } + end + let!(:cdrs) do + [ + create(:cdr, customer_acc: account), + create(:cdr, customer_acc: account, time_start: 23.hours.ago), + # included in collection because default filter time_start_gteq skipped when filter time_start_gt passed + create(:cdr, customer_acc: account, time_start: 47.hours.ago) + ] + end + + before do + # ignored because passed filter is time_start_gteq: 48.hours.ago + create(:cdr, customer_acc: account, time_start: 49.hours.ago) + create(:cdr, customer_acc: account, time_start: 100.days.ago) + + # ignored because base collection has only records with is_last_cdr=true + create(:cdr, customer_acc: account, is_last_cdr: false) + end + + it 'returns records of this customer' do + subject + expect(response.status).to eq(200) + actual_ids = response_json[:data].pluck(:id) + expect(actual_ids).to match_array(cdrs.map(&:uuid)) + end + end + context 'account_ids is empty' do let(:cdrs) { Cdr::Cdr.where(customer_id: customer.id, is_last_cdr: true) } let(:records_qty) { 2 } @@ -129,7 +214,12 @@ let(:pk) { :uuid } it_behaves_like :jsonapi_filters_by_uuid_field, :uuid - it_behaves_like :jsonapi_filters_by_datetime_field, :time_start + it_behaves_like :jsonapi_filters_by_datetime_field, :time_start do + # overrides default filter to avoid conflicts with tests + let(:json_api_request_query) do + { filter: { time_start_gteq: 50.days.ago.strftime('%F %T') } } + end + end it_behaves_like :jsonapi_filters_by_datetime_field, :time_connect it_behaves_like :jsonapi_filters_by_datetime_field, :time_end it_behaves_like :jsonapi_filters_by_number_field, :duration diff --git a/spec/support/contexts/ransack_filter_setup.rb b/spec/support/contexts/ransack_filter_setup.rb index 948ee1abb..d0e081516 100644 --- a/spec/support/contexts/ransack_filter_setup.rb +++ b/spec/support/contexts/ransack_filter_setup.rb @@ -27,6 +27,7 @@ def primary_key_for(record) response_data.map { |r| r['id'] } end let(:json_api_request_query) do - { filter: { filter_key => filter_value } } + current = super() || {} + current.deep_merge(filter: { filter_key => filter_value }) end end