Class: CustomerFilter
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- CustomerFilter
- Includes:
- Memery, Models::Auditable
- Defined in:
- app/models/customer_filter.rb
Overview
== Schema Information
Table name: customer_filters
Database name: primary
id :integer not null, primary key
cities :string(255) default([]), is an Array
customer_states :string(255) default([]), is an Array
digest :string(32)
exclude_buying_group_ids :boolean default(FALSE)
exclude_catalog_ids :boolean default(FALSE)
exclude_cities :boolean default(FALSE)
exclude_customer_states :boolean default(FALSE)
exclude_parties :boolean default(FALSE)
exclude_postal_codes :boolean default(FALSE)
exclude_profile_ids :boolean default(FALSE)
exclude_report_groupings :boolean default(FALSE)
exclude_source_ids :boolean default(FALSE)
exclude_state_codes :boolean default(FALSE)
exclude_tier2_program_pricing_ids :boolean default(FALSE)
has_email :integer default(0), not null
has_fax :integer default(0), not null
has_phone :integer default(0), not null
has_sales_order :integer default(0), not null
is_auto_generated :boolean
name :string(120) not null
opportunity_count_max :integer
opportunity_count_min :integer
opportunity_value_max :integer
opportunity_value_min :integer
phone_number_starts_with :string(12)
position :integer
postal_codes :string(10) default([]), is an Array
report_groupings :string default([]), is an Array
state_codes :string(2) default([]), is an Array
created_at :datetime not null
updated_at :datetime not null
creator_id :integer
store_id :integer
updater_id :integer
Indexes
index_customer_filters_on_digest (digest) UNIQUE
index_customer_filters_on_is_auto_generated (is_auto_generated)
index_customer_filters_on_store_id_and_name (store_id,name) UNIQUE
index_phone_number_starts_with_trgrm (phone_number_starts_with) USING gin
Foreign Keys
customer_filters_store_id_fk (store_id => stores.id)
Defined Under Namespace
Classes: QueryBuilder
Constant Summary collapse
- DEFAULT =
"All w/out DB/ETL/HD/COSTCO"
138- CONDITIONS =
Represent all the accessor methods to conditional values
%i[party_ids customer_states report_groupings catalogs store profiles buying_groups sources state_codes postal_codes cities tier2_program_pricings phone_number_starts_with has_sales_order].freeze
- UNIQUE_FIELDS =
These fields will be used to compare uniqueness of customer filters
%i[store_id exclude_catalog_ids exclude_profile_ids exclude_state_codes exclude_cities exclude_postal_codes exclude_buying_group_ids exclude_source_ids exclude_tier2_program_pricing_ids exclude_report_groupings exclude_customer_states exclude_parties state_codes cities postal_codes report_groupings customer_states catalog_ids profile_ids buying_group_ids source_ids tier2_program_pricing_ids party_ids has_phone has_email has_fax has_sales_order].freeze
- NA =
Na.
0- YES =
Yes.
1- NO =
No.
2- TRIPLE_STATE =
Triple state.
{ NA => 'Not Applicable', YES => 'Must Have One', NO => 'Must Have None' }.freeze
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Belongs to collapse
-
#store ⇒ Store?
The store this filter is scoped to, when set.
Has many collapse
-
#activity_types ⇒ ActiveRecord::Associations::CollectionProxy<ActivityType>
Activity types using this filter.
-
#auto_apply_coupons ⇒ ActiveRecord::Associations::CollectionProxy<Coupon>
Coupons auto-applied via this filter.
-
#coupons ⇒ ActiveRecord::Associations::CollectionProxy<Coupon>
Coupons using this filter.
-
#iq_accessory_filters ⇒ ActiveRecord::Associations::CollectionProxy<IqAccessoryFilter>
IQ accessory filters using this filter.
-
#sales_rep_queue_entries ⇒ ActiveRecord::Associations::CollectionProxy<SalesRepQueueEntry>
Queue entries using this filter.
-
#topics ⇒ ActiveRecord::Associations::CollectionProxy<Topic>
Topics using this filter.
Has and belongs to many collapse
-
#buying_groups ⇒ ActiveRecord::Associations::CollectionProxy<BuyingGroup>
Buying groups matched by this filter.
-
#catalogs ⇒ ActiveRecord::Associations::CollectionProxy<Catalog>
Catalogs matched by this filter.
-
#parties ⇒ ActiveRecord::Associations::CollectionProxy<Party>
Individual parties matched by this filter.
-
#profiles ⇒ ActiveRecord::Associations::CollectionProxy<Profile>
Profiles matched by this filter.
-
#sources ⇒ ActiveRecord::Associations::CollectionProxy<Source>
Sources matched by this filter.
-
#tier2_program_pricings ⇒ ActiveRecord::Associations::CollectionProxy<Coupon::Tier2ProgramPricing>
Program pricings matched by this filter.
Class Method Summary collapse
-
.create_single_customer_filter(customer) ⇒ CustomerFilter?
Finds or creates the auto-generated single-customer filter for a customer.
-
.duplicate_filters ⇒ ActiveRecord::Relation<CustomerFilter>
A relation of CustomerFilters that are duplicate filters.
-
.options_for_select {|cfs| ... } ⇒ Array<Array(String, Integer)>
Builds the [name, id] option pairs for select dropdowns.
-
.sorted ⇒ ActiveRecord::Relation<CustomerFilter>
A relation of CustomerFilters that are sorted.
Instance Method Summary collapse
-
#all_catalog_ids ⇒ Array<Integer>
Convenience method that will retrieve all catalog_ids associated with the filter.
-
#applies_to_customer?(customer) ⇒ Boolean
Runs the full rule chain against a customer.
-
#build_matcher(customer) ⇒ CustomerRuleMatcher
Builds the rule matcher that evaluates every *_match? rule against a customer.
-
#buying_group_match?(customer) ⇒ Boolean
True when the customer's buying group matches the filter.
-
#calculate_digest ⇒ String
MD5 hex digest of the raw digest fields.
-
#catalog_match?(customer) ⇒ Boolean
True when the customer's catalog matches the filter.
-
#chain_buying_groups_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by buying_group_ids.
-
#chain_catalogs_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by catalog_ids.
-
#chain_cities_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by cities.
-
#chain_customer_states_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by customer_states.
-
#chain_parties_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by party_ids.
-
#chain_postal_codes_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by postal_codes.
-
#chain_profiles_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by profile_ids.
-
#chain_program_pricing_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by tier2_program_pricing_ids.
-
#chain_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Narrows a customer relation by every populated filter condition.
-
#chain_report_groupings_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by report_groupings.
-
#chain_sources_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by source_ids.
-
#chain_state_codes_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by state_codes.
-
#chain_store_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Relation filtered by store_id.
-
#city_match?(customer) ⇒ Boolean
True when the customer's city matches the filter.
-
#customer_state_match?(customer) ⇒ Boolean
True when the customer's lifecycle state matches the filter.
-
#duplicate_filters ⇒ ActiveRecord::Relation<CustomerFilter>
Filters sharing this filter's digest.
-
#fields_array ⇒ Array<String>
Sorted "field:value" strings for populated UNIQUE_FIELDS.
-
#friendly_digest ⇒ String
Human-readable sentence of the populated filter fields.
-
#has_a_condition? ⇒ Boolean
True when at least one filter condition is populated.
-
#has_duplicate_filter? ⇒ Boolean
True when another filter has the same digest.
-
#has_email_match?(customer) ⇒ Boolean
True per the has_email triple-state against email contact points.
-
#has_fax_match?(customer) ⇒ Boolean
True per the has_fax triple-state against fax contact points.
-
#has_opportunity_match?(customer) ⇒ Boolean
Checks open sales-opportunity count/value bounds.
-
#has_phone_match?(customer) ⇒ Boolean
True per the has_phone triple-state against voice-callable contact points.
-
#has_phone_number_match?(customer) ⇒ Boolean, ...
True when no dialable phones, else the first phone matching the prefix.
-
#has_sales_order_match?(customer) ⇒ Boolean
True per the has_sales_order triple-state against active sales orders.
-
#meta_assoc_match(assoc, value, exclude) ⇒ Boolean
Convenience method to rescue us from repetition.
-
#meta_string_match(value, values, exclude, allow_partial = false) ⇒ Boolean
Matches a scalar value against a list of strings, honoring exclude mode.
-
#party_match?(customer) ⇒ Boolean
True when the customer is (or is excluded from) the party list.
-
#postal_code_match?(customer) ⇒ Boolean
True when the customer's postal code matches the filter (partial allowed).
-
#profile_match?(customer) ⇒ Boolean
True when the customer's profile matches the filter.
-
#raw_digest_fields ⇒ String
Pipe-joined raw digest input string.
-
#referenced? ⇒ Boolean
Whether any queue entry, topic, activity type, or coupon references this filter.
-
#report_grouping_match?(customer) ⇒ Boolean
True when the customer's report grouping matches the filter.
-
#source_match?(customer) ⇒ Boolean
True when the customer's source matches the filter.
-
#state_code_match?(customer) ⇒ Boolean
True when the customer's state code matches the filter.
-
#store_match?(customer) ⇒ Boolean
True when the filter has no store or the customer's store matches.
-
#tier2_program_pricing_match?(customer) ⇒ Boolean
True when the customer's tier2 program pricing matches the filter.
-
#to_s ⇒ String
Name and id, e.g.
Methods included from Models::Auditable
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Instance Attribute Details
#activity_types ⇒ ActiveRecord::Associations::CollectionProxy<ActivityType>
Returns activity types using this filter.
99 |
# File 'app/models/customer_filter.rb', line 99 has_many :activity_types, inverse_of: :customer_filter |
#auto_apply_coupons ⇒ ActiveRecord::Associations::CollectionProxy<Coupon>
Returns coupons auto-applied via this filter.
105 |
# File 'app/models/customer_filter.rb', line 105 has_many :auto_apply_coupons, inverse_of: :auto_apply_customer_filter, class_name: 'Coupon', foreign_key: :auto_apply_customer_filter_id |
#buying_groups ⇒ ActiveRecord::Associations::CollectionProxy<BuyingGroup>
Returns buying groups matched by this filter.
118 |
# File 'app/models/customer_filter.rb', line 118 has_and_belongs_to_many :buying_groups |
#catalogs ⇒ ActiveRecord::Associations::CollectionProxy<Catalog>
Returns catalogs matched by this filter.
112 |
# File 'app/models/customer_filter.rb', line 112 has_and_belongs_to_many :catalogs |
#coupons ⇒ ActiveRecord::Associations::CollectionProxy<Coupon>
Returns coupons using this filter.
102 |
# File 'app/models/customer_filter.rb', line 102 has_many :coupons, inverse_of: :customer_filter |
#iq_accessory_filters ⇒ ActiveRecord::Associations::CollectionProxy<IqAccessoryFilter>
Returns IQ accessory filters using this filter.
108 |
# File 'app/models/customer_filter.rb', line 108 has_many :iq_accessory_filters, inverse_of: :customer_filter |
#parties ⇒ ActiveRecord::Associations::CollectionProxy<Party>
Returns individual parties matched by this filter.
124 |
# File 'app/models/customer_filter.rb', line 124 has_and_belongs_to_many :parties, validate: false |
#profiles ⇒ ActiveRecord::Associations::CollectionProxy<Profile>
Returns profiles matched by this filter.
115 |
# File 'app/models/customer_filter.rb', line 115 has_and_belongs_to_many :profiles |
#sales_rep_queue_entries ⇒ ActiveRecord::Associations::CollectionProxy<SalesRepQueueEntry>
Returns queue entries using this filter.
93 |
# File 'app/models/customer_filter.rb', line 93 has_many :sales_rep_queue_entries, inverse_of: :customer_filter |
#sources ⇒ ActiveRecord::Associations::CollectionProxy<Source>
Returns sources matched by this filter.
121 |
# File 'app/models/customer_filter.rb', line 121 has_and_belongs_to_many :sources |
#store ⇒ Store?
Returns the store this filter is scoped to, when set.
90 |
# File 'app/models/customer_filter.rb', line 90 belongs_to :store, optional: true |
#tier2_program_pricings ⇒ ActiveRecord::Associations::CollectionProxy<Coupon::Tier2ProgramPricing>
Returns program pricings matched by this filter.
127 128 129 |
# File 'app/models/customer_filter.rb', line 127 has_and_belongs_to_many :tier2_program_pricings, class_name: 'Coupon::Tier2ProgramPricing', join_table: 'customer_filters_program_pricings', association_foreign_key: 'tier2_program_pricing_id' |
#topics ⇒ ActiveRecord::Associations::CollectionProxy<Topic>
Returns topics using this filter.
96 |
# File 'app/models/customer_filter.rb', line 96 has_many :topics, inverse_of: :customer_filter |
Class Method Details
.create_single_customer_filter(customer) ⇒ CustomerFilter?
Finds or creates the auto-generated single-customer filter for a customer.
152 153 154 155 156 157 158 159 160 |
# File 'app/models/customer_filter.rb', line 152 def self.create_single_customer_filter(customer) cf = nil if customer.is_a?(Customer) # ensure we are dealing with a real customer party_criteria = { parties: { id: customer.id }, is_auto_generated: true } create_criteria = { name: "#{customer.full_name} - #{customer.reference_number} - Customer Preference", is_auto_generated: true, party_ids: [customer.id] } cf = CustomerFilter.joins(:parties).where(party_criteria).first_or_create(create_criteria) end cf end |
.duplicate_filters ⇒ ActiveRecord::Relation<CustomerFilter>
A relation of CustomerFilters that are duplicate filters. Active Record Scope
135 |
# File 'app/models/customer_filter.rb', line 135 scope :duplicate_filters, -> { where("EXISTS(select digest from customer_filters cf where cf.digest = customer_filters.digest group by digest having count(digest) > 1)") } |
.options_for_select {|cfs| ... } ⇒ Array<Array(String, Integer)>
Builds the [name, id] option pairs for select dropdowns.
143 144 145 146 147 |
# File 'app/models/customer_filter.rb', line 143 def self. cfs = CustomerFilter.all cfs = yield(cfs) if block_given? cfs.sorted.pluck(:name, :id) end |
.sorted ⇒ ActiveRecord::Relation<CustomerFilter>
A relation of CustomerFilters that are sorted. Active Record Scope
134 |
# File 'app/models/customer_filter.rb', line 134 scope :sorted, -> { order("customer_filters.name") } |
Instance Method Details
#all_catalog_ids ⇒ Array<Integer>
Convenience method that will retrieve all catalog_ids associated with the filter
581 582 583 584 585 586 587 588 589 590 591 592 593 |
# File 'app/models/customer_filter.rb', line 581 def all_catalog_ids # Convenience method that will retrieve all catalog_ids associated with the filter cids = [] cids += parties.map { |p| p.try(:catalog_id) } if catalog_ids.present? if exclude_catalog_ids cids -= catalog_ids else cids += catalog_ids end end cids.compact.uniq.sort end |
#applies_to_customer?(customer) ⇒ Boolean
Runs the full rule chain against a customer.
307 308 309 |
# File 'app/models/customer_filter.rb', line 307 def applies_to_customer?(customer) build_matcher(customer).match? end |
#build_matcher(customer) ⇒ CustomerRuleMatcher
Builds the rule matcher that evaluates every *_match? rule against a customer.
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 |
# File 'app/models/customer_filter.rb', line 475 def build_matcher(customer) CustomerRuleMatcher.new(self, customer, :party_match?, :customer_state_match?, :report_grouping_match?, :catalog_match?, :store_match?, :profile_match?, :tier2_program_pricing_match?, :buying_group_match?, :source_match?, :state_code_match?, :postal_code_match?, :city_match?, :has_phone_match?, :has_fax_match?, :has_email_match?, :has_phone_number_match?, :has_sales_order_match?, :has_opportunity_match?) end |
#buying_group_match?(customer) ⇒ Boolean
Returns true when the customer's buying group matches the filter.
199 200 201 |
# File 'app/models/customer_filter.rb', line 199 def (customer) , customer., end |
#calculate_digest ⇒ String
Returns MD5 hex digest of the raw digest fields.
530 531 532 533 534 |
# File 'app/models/customer_filter.rb', line 530 def calculate_digest dg = Digest::MD5.hexdigest raw_digest_fields logger.debug "Calculated digest #{dg} for customer filter #{id}" dg end |
#catalog_match?(customer) ⇒ Boolean
Returns true when the customer's catalog matches the filter.
205 206 207 |
# File 'app/models/customer_filter.rb', line 205 def catalog_match?(customer) catalogs, customer.catalog_id, exclude_catalog_ids end |
#chain_buying_groups_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by buying_group_ids.
449 450 451 452 453 454 455 456 457 |
# File 'app/models/customer_filter.rb', line 449 def (customers_query) return customers_query if .blank? if customers_query.where.not(buying_group_id: ) else customers_query.where(buying_group_id: ) end end |
#chain_catalogs_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by catalog_ids.
345 346 347 348 349 350 351 352 353 |
# File 'app/models/customer_filter.rb', line 345 def chain_catalogs_query(customers_query) return customers_query if catalog_ids.blank? if exclude_catalog_ids customers_query.where.not(catalog_id: catalog_ids) else customers_query.where(catalog_id: catalog_ids) end end |
#chain_cities_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by cities.
393 394 395 396 397 398 399 400 401 |
# File 'app/models/customer_filter.rb', line 393 def chain_cities_query(customers_query) return customers_query if cities.blank? if exclude_cities customers_query.joins(:addresses).where(Address[:city].not_in(cities).or(Address[:city].eq(nil))) else customers_query.joins(:addresses).where(Address[:city].in(cities)) end end |
#chain_customer_states_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by customer_states.
413 414 415 416 417 418 419 420 421 |
# File 'app/models/customer_filter.rb', line 413 def chain_customer_states_query(customers_query) return customers_query if customer_states.blank? if exclude_customer_states customers_query.where.not(state: customer_states) else customers_query.where(state: customer_states) end end |
#chain_parties_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by party_ids.
437 438 439 440 441 442 443 444 445 |
# File 'app/models/customer_filter.rb', line 437 def chain_parties_query(customers_query) return customers_query if party_ids.blank? if exclude_parties customers_query.where.not(id: party_ids) else customers_query.where(id: party_ids) end end |
#chain_postal_codes_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by postal_codes.
381 382 383 384 385 386 387 388 389 |
# File 'app/models/customer_filter.rb', line 381 def chain_postal_codes_query(customers_query) return customers_query if postal_codes.blank? if exclude_postal_codes customers_query.joins(:addresses).where(Address[:zip].not_in(postal_codes).or(Address[:zip].eq(nil))) else customers_query.joins(:addresses).where(Address[:zip].in(postal_codes)) end end |
#chain_profiles_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by profile_ids.
333 334 335 336 337 338 339 340 341 |
# File 'app/models/customer_filter.rb', line 333 def chain_profiles_query(customers_query) return customers_query if profile_ids.blank? if exclude_profile_ids customers_query.where(Customer[:profile_id].not_in(profile_ids).or(Customer[:profile_id].eq(nil))) else customers_query.where(profile_id: profile_ids) end end |
#chain_program_pricing_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by tier2_program_pricing_ids.
425 426 427 428 429 430 431 432 433 |
# File 'app/models/customer_filter.rb', line 425 def chain_program_pricing_query(customers_query) return customers_query if tier2_program_pricing_ids.blank? if exclude_tier2_program_pricing_ids customers_query.where.not(tier2_program_pricing_id: tier2_program_pricing_ids) else customers_query.where(tier2_program_pricing_id: tier2_program_pricing_ids) end end |
#chain_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Narrows a customer relation by every populated filter condition.
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
# File 'app/models/customer_filter.rb', line 315 def chain_query(customers_query) customers_query = chain_report_groupings_query(customers_query) customers_query = (customers_query) customers_query = chain_parties_query(customers_query) customers_query = chain_program_pricing_query(customers_query) customers_query = chain_customer_states_query(customers_query) customers_query = chain_store_query(customers_query) customers_query = chain_cities_query(customers_query) customers_query = chain_postal_codes_query(customers_query) customers_query = chain_state_codes_query(customers_query) customers_query = chain_sources_query(customers_query) customers_query = chain_catalogs_query(customers_query) chain_profiles_query(customers_query) # Todo phone match, email match, fax match, order match end |
#chain_report_groupings_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by report_groupings.
461 462 463 464 465 466 467 468 469 470 |
# File 'app/models/customer_filter.rb', line 461 def chain_report_groupings_query(customers_query) return customers_query if report_groupings.blank? if exclude_report_groupings # a customer with nil is considered excluded too we have to test for this condition specifically in sql customers_query.where(Customer[:report_grouping].eq(nil).or(Customer[:report_grouping].not_in(report_groupings))) else customers_query.where(Customer[:report_grouping].in(report_groupings)) end end |
#chain_sources_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by source_ids.
357 358 359 360 361 362 363 364 365 |
# File 'app/models/customer_filter.rb', line 357 def chain_sources_query(customers_query) return customers_query if source_ids.blank? if exclude_source_ids customers_query.where(Customer[:source_id].not_in(source_ids).or(Customer[:source_id].eq(nil))) else customers_query.where(Customer[:source_id].in(source_ids)) end end |
#chain_state_codes_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by state_codes.
369 370 371 372 373 374 375 376 377 |
# File 'app/models/customer_filter.rb', line 369 def chain_state_codes_query(customers_query) return customers_query if state_codes.blank? if exclude_state_codes customers_query.where(Customer[:state_code].not_in(state_codes).or(Customer[:state_code].eq(nil))) else customers_query.where(Customer[:state_code].in(state_codes)) end end |
#chain_store_query(customers_query) ⇒ ActiveRecord::Relation<Customer>
Returns relation filtered by store_id.
405 406 407 408 409 |
# File 'app/models/customer_filter.rb', line 405 def chain_store_query(customers_query) return customers_query if store_id.blank? customers_query.joins(:catalog).where(Catalog[:store_id].eq(store_id)) end |
#city_match?(customer) ⇒ Boolean
Returns true when the customer's city matches the filter.
241 242 243 |
# File 'app/models/customer_filter.rb', line 241 def city_match?(customer) customer.city, cities, exclude_cities end |
#customer_state_match?(customer) ⇒ Boolean
Returns true when the customer's lifecycle state matches the filter.
223 224 225 |
# File 'app/models/customer_filter.rb', line 223 def customer_state_match?(customer) customer.state, customer_states, exclude_customer_states end |
#duplicate_filters ⇒ ActiveRecord::Relation<CustomerFilter>
Returns filters sharing this filter's digest.
498 499 500 501 502 |
# File 'app/models/customer_filter.rb', line 498 def duplicate_filters filters = CustomerFilter.where(digest: calculate_digest) filters = filters.where(CustomerFilter[:id].not_eq(id)) unless new_record? filters end |
#fields_array ⇒ Array<String>
Returns sorted "field:value" strings for populated UNIQUE_FIELDS.
510 511 512 513 514 515 516 517 |
# File 'app/models/customer_filter.rb', line 510 def fields_array raw_fields = UNIQUE_FIELDS.each_with_object([]) do |field, array| val = send(field) val = val.compact.sort if !val.nil? && val.is_a?(Array) array << "#{field}:#{val}" if val.present? end (raw_fields || []).sort end |
#friendly_digest ⇒ String
Returns human-readable sentence of the populated filter fields.
520 521 522 |
# File 'app/models/customer_filter.rb', line 520 def friendly_digest fields_array.to_sentence end |
#has_a_condition? ⇒ Boolean
Returns true when at least one filter condition is populated.
575 576 577 |
# File 'app/models/customer_filter.rb', line 575 def has_a_condition? CONDITIONS.any? { |cnd| send(cnd).present? } end |
#has_duplicate_filter? ⇒ Boolean
Returns true when another filter has the same digest.
505 506 507 |
# File 'app/models/customer_filter.rb', line 505 def has_duplicate_filter? duplicate_filters.present? end |
#has_email_match?(customer) ⇒ Boolean
Returns true per the has_email triple-state against email contact points.
291 292 293 |
# File 'app/models/customer_filter.rb', line 291 def has_email_match?(customer) relation_triple_state_presence_check(customer.all_contact_points.emails, has_email) end |
#has_fax_match?(customer) ⇒ Boolean
Returns true per the has_fax triple-state against fax contact points.
259 260 261 |
# File 'app/models/customer_filter.rb', line 259 def has_fax_match?(customer) relation_triple_state_presence_check(customer.all_contact_points.faxes, has_fax) end |
#has_opportunity_match?(customer) ⇒ Boolean
Checks open sales-opportunity count/value bounds.
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'app/models/customer_filter.rb', line 272 def has_opportunity_match?(customer) # The lack of filter is a true check return true unless opportunity_value_min || opportunity_value_max || opportunity_count_min || opportunity_count_max opp_query = customer.opportunities.open_opportunities.where(opportunity_type: 'S') opp_query = opp_query.where(value: opportunity_value_min..) if opportunity_value_min.present? opp_query = opp_query.where(value: opportunity_value_max..) if opportunity_value_max.present? if opportunity_count_max.present? return false if opp_query.size > opportunity_count_max end if opportunity_count_min.present? return false if opp_query.size < opportunity_count_min end true # Logically you'll exit before this end |
#has_phone_match?(customer) ⇒ Boolean
Returns true per the has_phone triple-state against voice-callable contact points.
253 254 255 |
# File 'app/models/customer_filter.rb', line 253 def has_phone_match?(customer) relation_triple_state_presence_check(customer.all_contact_points.voice_callable, has_phone) end |
#has_phone_number_match?(customer) ⇒ Boolean, ...
Returns true when no dialable phones, else the first phone matching the prefix.
297 298 299 300 301 302 |
# File 'app/models/customer_filter.rb', line 297 def has_phone_number_match?(customer) phones = customer.all_contact_points.dialable return true if phones.empty? phones.find { |cp| cp.detail, phone_number_starts_with, false, :allow_partial } end |
#has_sales_order_match?(customer) ⇒ Boolean
Returns true per the has_sales_order triple-state against active sales orders.
265 266 267 |
# File 'app/models/customer_filter.rb', line 265 def has_sales_order_match?(customer) relation_triple_state_presence_check(customer.orders.so_only.active, has_sales_order) end |
#meta_assoc_match(assoc, value, exclude) ⇒ Boolean
Convenience method to rescue us from repetition. Association to check against, value to check for, exclude turned on or off
Optimized to use in-memory lookup when association is preloaded to avoid N+1 queries
542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
# File 'app/models/customer_filter.rb', line 542 def (assoc, value, exclude) # Use loaded? check to avoid N+1 - if preloaded, check in memory if assoc.loaded? return true if assoc.empty? value_in_list = assoc.any? { |record| record.id == value } else # When not preloaded, fall back to database queries return true if assoc.empty? value_in_list = assoc.exists?(id: value) end exclude ? !value_in_list : value_in_list end |
#meta_string_match(value, values, exclude, allow_partial = false) ⇒ Boolean
Matches a scalar value against a list of strings, honoring exclude mode.
563 564 565 566 567 568 569 570 571 572 |
# File 'app/models/customer_filter.rb', line 563 def (value, values, exclude, allow_partial = false) return true if values.blank? value_in_list = if allow_partial value&.starts_with?(*values) else value.in?(values) end exclude ? !value_in_list : value_in_list end |
#party_match?(customer) ⇒ Boolean
Returns true when the customer is (or is excluded from) the party list.
217 218 219 |
# File 'app/models/customer_filter.rb', line 217 def party_match?(customer) parties, customer.id, exclude_parties end |
#postal_code_match?(customer) ⇒ Boolean
Returns true when the customer's postal code matches the filter (partial allowed).
235 236 237 |
# File 'app/models/customer_filter.rb', line 235 def postal_code_match?(customer) customer.zip, postal_codes, exclude_postal_codes, :allow_partial end |
#profile_match?(customer) ⇒ Boolean
Returns true when the customer's profile matches the filter.
187 188 189 |
# File 'app/models/customer_filter.rb', line 187 def profile_match?(customer) profiles, customer.profile_id, exclude_profile_ids end |
#raw_digest_fields ⇒ String
Returns pipe-joined raw digest input string.
525 526 527 |
# File 'app/models/customer_filter.rb', line 525 def raw_digest_fields fields_array.join('|').to_s end |
#referenced? ⇒ Boolean
Whether any queue entry, topic, activity type, or coupon references this filter.
169 170 171 172 173 174 175 176 177 |
# File 'app/models/customer_filter.rb', line 169 def referenced? ( sales_rep_queue_entries.present? or topics.present? or activity_types.present? or coupons.present? or auto_apply_coupons.present? ) end |
#report_grouping_match?(customer) ⇒ Boolean
Returns true when the customer's report grouping matches the filter.
247 248 249 |
# File 'app/models/customer_filter.rb', line 247 def report_grouping_match?(customer) customer.effective_report_grouping, report_groupings, exclude_report_groupings end |
#source_match?(customer) ⇒ Boolean
Returns true when the customer's source matches the filter.
211 212 213 |
# File 'app/models/customer_filter.rb', line 211 def source_match?(customer) sources, customer.source_id, exclude_source_ids end |
#state_code_match?(customer) ⇒ Boolean
Returns true when the customer's state code matches the filter.
229 230 231 |
# File 'app/models/customer_filter.rb', line 229 def state_code_match?(customer) customer.state_code, state_codes, exclude_state_codes end |
#store_match?(customer) ⇒ Boolean
Returns true when the filter has no store or the customer's store matches.
181 182 183 |
# File 'app/models/customer_filter.rb', line 181 def store_match?(customer) store.nil? or customer.store == store end |
#tier2_program_pricing_match?(customer) ⇒ Boolean
Returns true when the customer's tier2 program pricing matches the filter.
193 194 195 |
# File 'app/models/customer_filter.rb', line 193 def tier2_program_pricing_match?(customer) tier2_program_pricings, customer.tier2_program_pricing_id, exclude_tier2_program_pricing_ids end |
#to_s ⇒ String
Returns name and id, e.g. "My Filter (12)".
163 164 165 |
# File 'app/models/customer_filter.rb', line 163 def to_s "#{name} (#{id})" end |