Class: ContactPoint
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- ContactPoint
- Includes:
- Models::Auditable, PgSearch::Model
- Defined in:
- app/models/contact_point.rb
Overview
rubocop:disable Metrics/ClassLength
== Schema Information
Table name: contact_points
Database name: primary
id :integer not null, primary key
area_code :string(10)
category :string(255)
country_code :integer
detail :string(255)
extension :string(10)
notes :string(255)
position :integer
restricted_notes :text
skip_validation :boolean default(FALSE), not null
sms_status :integer default("sms_none"), not null
state :string(25)
system_notes :text
timezone_name :string
created_at :datetime
updated_at :datetime
locator_record_id :integer
party_id :integer
Indexes
by_pid_category_w (party_id,category) WHERE (detail IS NOT NULL)
contact_points_party_id_index (party_id)
idx_category_party_id_detail (category,party_id,detail)
idx_detail_party_id (detail,party_id)
idx_trigram_detail (detail) USING gin
index_contact_points_locator_record_id (locator_record_id)
index_contact_points_on_position_and_party_id (position,party_id)
Foreign Keys
contact_points_party_id_fk (party_id => parties.id) ON DELETE => nullify
Defined Under Namespace
Classes: AddressBookBuilder
Constant Summary collapse
- HOUZZ_REGEX =
Platform-specific regexes — require https:// (normalise_format ensures this before validation)
%r{\Ahttps?://(www\.)?houzz\.com/}i- INSTAGRAM_REGEX =
%r{\Ahttps?://(www\.)?instagram\.com/}i- FACEBOOK_REGEX =
%r{\Ahttps?://(www\.)?facebook\.com/}i- PINTEREST_REGEX =
%r{\Ahttps?://(www\.)?pinterest\.com/}i- LINKEDIN_REGEX =
%r{\Ahttps?://(www\.)?linkedin\.com/}i- WEBSITE_REGEX =
Generic website: must start with https:// or http://, have a real host with a dot.
Full structural validation is done via Addressable::URI in valid_website_url?. %r{\Ahttps?://[^/\s]+\.[^/\s]}i- TWITTER_REGEX =
/@.*/- EMAIL_REGEXP =
RFC822::EMAIL
- PHONE =
'phone'.freeze
- EMAIL =
'email'.freeze
- FAX =
'fax'.freeze
- CELL =
'cell'.freeze
- WEBSITE =
'website'.freeze
- FACEBOOK =
'facebook'.freeze
- TWITTER =
'twitter'.freeze
- PINTEREST =
'pinterest'.freeze
- LINKEDIN =
'linkedin'.freeze
- INSTAGRAM =
'instagram'.freeze
- HOUZZ =
'houzz'.freeze
- CAN_DIAL =
[CELL, FAX, PHONE].freeze
- CAN_TRANSMIT =
[FAX, EMAIL].freeze
- CAN_VOICE =
[CELL, PHONE].freeze
- ALL_CATEGORIES =
[PHONE, CELL, FAX, EMAIL, WEBSITE, FACEBOOK, TWITTER, PINTEREST, LINKEDIN, INSTAGRAM, HOUZZ].freeze
- CONTACTABLE =
[EMAIL, PHONE, CELL, FAX].freeze
- INVALID_URL_MESSAGE =
'must be a valid URL starting with https:// (e.g. https://example.com)'.freeze
Constants included from Models::Auditable
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
-
#category ⇒ Object
readonly
rubocop:disable Rails/I18nLocaleTexts -- validation messages intentionally inline; locale extraction deferred.
-
#detail ⇒ Object
readonly
rubocop:disable Rails/I18nLocaleTexts -- validation messages intentionally inline; locale extraction deferred.
-
#extension ⇒ Object
readonly
rubocop:enable Rails/I18nLocaleTexts.
-
#required ⇒ Object
Returns the value of attribute required.
Belongs to collapse
- #area_code_object ⇒ AreaCode
- #do_not_call ⇒ DoNotCall
-
#email_preference ⇒ EmailPreference
rubocop:disable Rails/InverseOf -- polymorphic FK/PK pair; inverse not supported.
- #locator_record ⇒ LocatorRecord
- #party ⇒ Party
Methods included from Models::Auditable
Has one collapse
-
#employee_phone_status ⇒ EmployeePhoneStatus
rubocop:enable Rails/InverseOf.
Has many collapse
- #communication_recipients ⇒ ActiveRecord::Relation<CommunicationRecipient>
- #email_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
- #fax_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
- #notification_channels ⇒ ActiveRecord::Relation<NotificationChannel>
-
#opportunity_participants ⇒ ActiveRecord::Relation<OpportunityParticipant>
rubocop:enable Rails/InverseOf, Rails/HasManyOrHasOneDependent.
- #phone_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
- #room_configurations ⇒ ActiveRecord::Relation<RoomConfiguration>
-
#subscribers ⇒ ActiveRecord::Relation<Subscriber>
rubocop:disable Rails/InverseOf, Rails/HasManyOrHasOneDependent -- string FK on detail; no cascade appropriate.
Has and belongs to many collapse
- #feeds ⇒ ActiveRecord::Relation<Feed>
-
#quotes ⇒ ActiveRecord::Relation<Quote>
rubocop:disable Rails/HasAndBelongsToMany -- join tables pre-date has_many :through; migrate when touched.
Class Method Summary collapse
-
.begins_with ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are begins with.
-
.belonging_to_party ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are belonging to party.
-
.build_from_string(val, contact_points = nil, category = nil) ⇒ Object
Tries to build a contact point identifying the string.
-
.by_category ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are by category.
- .category_options_for_select ⇒ Object
-
.company_sms_numbers ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are company sms numbers.
-
.contactable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are contactable.
- .contactable_options_for_select ⇒ Object
-
.contains ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are contains.
-
.dialable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are dialable.
-
.emails ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are emails.
-
.failed ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are failed.
-
.faxes ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are faxes.
-
.find_emails ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are find emails.
-
.find_phones ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are find phones.
- .mark_email_as_failed(email, notes = nil) ⇒ Object
- .mark_email_as_working(email) ⇒ Object
-
.migrate_data ⇒ Object
One-time migration utility — run via rails runner, not in production request cycle.
-
.pbx_dids ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are pbx dids.
-
.sms_numbers ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are sms numbers.
- .sms_statuses_for_select ⇒ Object
-
.sorted ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are sorted.
-
.transmittable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are transmittable.
-
.under_customer_ids ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are under customer ids.
-
.voice_callable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are voice callable.
-
.website_category(uri) ⇒ Object
Returns the canonical ContactPoint category string for the given URL, or nil.
-
.websites ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are websites.
Instance Method Summary collapse
- #blocked? ⇒ Boolean
- #call_blocked? ⇒ Boolean
- #callable? ⇒ Boolean
- #can_be_dialed? ⇒ Boolean
- #category_and_detail ⇒ Object
- #contactable? ⇒ Boolean
- #dependents? ⇒ Boolean
- #dial_string ⇒ Object
- #dnc_blocked? ⇒ Boolean
- #email? ⇒ Boolean
- #email_blocked? ⇒ Boolean
- #facebook? ⇒ Boolean
- #failed_before? ⇒ Boolean
- #fax? ⇒ Boolean
- #fax_blocked? ⇒ Boolean
- #formatted_dial_string ⇒ Object
- #formatted_for_sms ⇒ Object
- #linkedin? ⇒ Boolean
- #mark_as_working_if_detail_changed ⇒ Object protected
-
#normalize_format ⇒ Object
rubocop:enable Rails/SkipsModelValidations, Metrics/AbcSize.
- #phone_number ⇒ Object
- #phone_number? ⇒ Boolean
- #pinterest? ⇒ Boolean
- #preferred? ⇒ Boolean
- #set_default_sms_status ⇒ Object
- #text_blocked? ⇒ Boolean
- #time_at_location ⇒ Object
- #timezone ⇒ Object
- #to_s ⇒ Object
- #transmittable? ⇒ Boolean
- #twitter? ⇒ Boolean
- #website? ⇒ Boolean
- #website_url_format ⇒ Object
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::EventPublishable
Instance Attribute Details
#category ⇒ Object (readonly)
rubocop:disable Rails/I18nLocaleTexts -- validation messages intentionally inline; locale extraction deferred
Validations:
114 |
# File 'app/models/contact_point.rb', line 114 validates :category, :detail, presence: true |
#detail ⇒ Object (readonly)
rubocop:disable Rails/I18nLocaleTexts -- validation messages intentionally inline; locale extraction deferred
Validations:
- Presence
- Format ({ with: FACEBOOK_REGEX, if: :facebook?, message: 'must be a valid facebook.com url starting with http:// or https://' })
- Format ({ with: TWITTER_REGEX, if: :twitter?, message: 'must be a valid twitter @username' })
- Format ({ with: PINTEREST_REGEX, if: :pinterest?, message: 'must be a valid pinterest.com url starting with http:// or https://' })
- Format ({ with: LINKEDIN_REGEX, if: :linkedin?, message: 'must be a valid linkedin.com url starting with http:// or https://' })
- Length ({ maximum: 255 })
Validations (if => -> { !skip_validation && can_be_dialed? } ):
- Phone_format
Validations (if => #email? ):
- Email_format
114 |
# File 'app/models/contact_point.rb', line 114 validates :category, :detail, presence: true |
#extension ⇒ Object (readonly)
rubocop:enable Rails/I18nLocaleTexts
Validations:
- Length ({ maximum: 10 })
132 |
# File 'app/models/contact_point.rb', line 132 validates :extension, length: { maximum: 10 } |
#required ⇒ Object
Returns the value of attribute required.
157 158 159 |
# File 'app/models/contact_point.rb', line 157 def required @required end |
Class Method Details
.begins_with ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are begins with. Active Record Scope
148 |
# File 'app/models/contact_point.rb', line 148 scope :begins_with, ->(term) { where(ContactPoint[:detail].matches("#{term}%")) } |
.belonging_to_party ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are belonging to party. Active Record Scope
150 |
# File 'app/models/contact_point.rb', line 150 scope :belonging_to_party, -> { where ContactPoint[:party_id].not_eq(nil) } |
.build_from_string(val, contact_points = nil, category = nil) ⇒ Object
Tries to build a contact point identifying the string.
Returns an existing contact point from the collection if detail matches,
otherwise builds a new one.
207 208 209 210 211 212 213 214 215 216 |
# File 'app/models/contact_point.rb', line 207 def self.build_from_string(val, contact_points = nil, category = nil) return if val.blank? found = contact_points.detect { |cp| cp.detail == val } return found if found ncp = (contact_points || ContactPoint).new(detail: val, category: category) ncp.normalize_format ncp end |
.by_category ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are by category. Active Record Scope
135 |
# File 'app/models/contact_point.rb', line 135 scope :by_category, ->(categories) { where(category: categories).where.not(detail: nil) } |
.category_options_for_select ⇒ Object
218 219 220 |
# File 'app/models/contact_point.rb', line 218 def self. ALL_CATEGORIES.map { |cat| [cat.humanize, cat] } end |
.company_sms_numbers ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are company sms numbers. Active Record Scope
154 |
# File 'app/models/contact_point.rb', line 154 scope :company_sms_numbers, -> { joins(:employee_phone_status).sorted } |
.contactable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are contactable. Active Record Scope
143 |
# File 'app/models/contact_point.rb', line 143 scope :contactable, -> { by_category(CAN_DIAL + [EMAIL]) } |
.contactable_options_for_select ⇒ Object
222 223 224 |
# File 'app/models/contact_point.rb', line 222 def self. CONTACTABLE.map { |cat| [cat.humanize, cat] } end |
.contains ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are contains. Active Record Scope
147 |
# File 'app/models/contact_point.rb', line 147 scope :contains, ->(term) { where(ContactPoint[:detail].matches("%#{term}%")) } |
.dialable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are dialable. Active Record Scope
141 |
# File 'app/models/contact_point.rb', line 141 scope :dialable, -> { by_category(CAN_DIAL) } |
.emails ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are emails. Active Record Scope
137 |
# File 'app/models/contact_point.rb', line 137 scope :emails, -> { by_category(EMAIL) } |
.failed ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are failed. Active Record Scope
149 |
# File 'app/models/contact_point.rb', line 149 scope :failed, -> { where(state: 'failed') } |
.faxes ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are faxes. Active Record Scope
139 |
# File 'app/models/contact_point.rb', line 139 scope :faxes, -> { by_category(FAX) } |
.find_emails ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are find emails. Active Record Scope
145 |
# File 'app/models/contact_point.rb', line 145 scope :find_emails, ->(email) { emails.where(ContactPoint[:detail].matches(email)) } |
.find_phones ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are find phones. Active Record Scope
146 |
# File 'app/models/contact_point.rb', line 146 scope :find_phones, ->(phone) { dialable.begins_with(phone) } |
.mark_email_as_failed(email, notes = nil) ⇒ Object
170 171 172 173 174 175 |
# File 'app/models/contact_point.rb', line 170 def self.mark_email_as_failed(email, notes = nil) ContactPoint.find_emails(email).each do |cp| cp.system_notes = notes if notes.present? cp.mark_as_failed end end |
.mark_email_as_working(email) ⇒ Object
188 189 190 191 192 193 194 |
# File 'app/models/contact_point.rb', line 188 def self.mark_email_as_working(email) ContactPoint.find_emails(email).where(state: %w[unknown failed]).find_each do |cp| cp.system_notes = nil Sendgrid::Toolkit.delete_invalids(emails: [email]) cp.mark_as_working end end |
.migrate_data ⇒ Object
One-time migration utility — run via rails runner, not in production request cycle.
rubocop:disable Rails/SkipsModelValidations, Metrics/AbcSize
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'app/models/contact_point.rb', line 363 def self.migrate_data contact_points = ContactPoint.dialable total_records = contact_points.size current_record = 0 contact_points.find_each do |cp| Rails.logger.info "[#{current_record += 1}/#{total_records}] #{cp.id}" cp.send(:normalize_format) raise "Encountered anomaly: #{cp.id} #{cp.detail}" if cp.detail.blank? cp.update_columns(cp.attributes) end CallRecord.connection.execute "update call_records set origin_number = '+1' || origin_number where length(origin_number) = 10;" CallRecord.connection.execute "update call_records set destination_number = '+1' || destination_number where length(destination_number) = 10;" CallLog.connection.execute "update call_logs set from_number = '+1' || from_number where length(from_number) = 10;" CallLog.connection.execute "update call_logs set to_number = '+1' || to_number where length(to_number) = 10;" DoNotCall.connection.execute "update do_not_calls set number = '+1' || number where length(number) = 10" Order.connection.execute "update orders set shipping_phone = '+1' || shipping_phone where length(shipping_phone) = 10" end |
.pbx_dids ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are pbx dids. Active Record Scope
144 |
# File 'app/models/contact_point.rb', line 144 scope :pbx_dids, -> { by_category(PHONE).joins(:employee_phone_status) } |
.sms_numbers ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are sms numbers. Active Record Scope
155 |
# File 'app/models/contact_point.rb', line 155 scope :sms_numbers, -> { where(sms_status: [1, 2]) } |
.sms_statuses_for_select ⇒ Object
226 227 228 229 230 231 |
# File 'app/models/contact_point.rb', line 226 def self.sms_statuses_for_select [ ['Not SMS capable', 'sms_none'], ['SMS enabled', 'sms_enabled'] ] end |
.sorted ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are sorted. Active Record Scope
142 |
# File 'app/models/contact_point.rb', line 142 scope :sorted, -> { order('contact_points.category, contact_points.position') } |
.transmittable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are transmittable. Active Record Scope
136 |
# File 'app/models/contact_point.rb', line 136 scope :transmittable, -> { by_category(CAN_TRANSMIT) } |
.under_customer_ids ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are under customer ids. Active Record Scope
151 152 153 |
# File 'app/models/contact_point.rb', line 151 scope :under_customer_ids, ->(customer_ids) { where('contact_points.party_id IN (:customer_ids) or exists(select 1 from parties cnt where cnt.customer_id IN (:customer_ids) and cnt.id = contact_points.party_id)', customer_ids: [customer_ids].flatten) } |
.voice_callable ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are voice callable. Active Record Scope
140 |
# File 'app/models/contact_point.rb', line 140 scope :voice_callable, -> { by_category(CAN_VOICE) } |
.website_category(uri) ⇒ Object
Returns the canonical ContactPoint category string for the given URL, or nil.
178 179 180 181 182 183 184 185 186 |
# File 'app/models/contact_point.rb', line 178 def self.website_category(uri) return HOUZZ if HOUZZ_REGEX.match?(uri) return INSTAGRAM if INSTAGRAM_REGEX.match?(uri) return FACEBOOK if FACEBOOK_REGEX.match?(uri) return PINTEREST if PINTEREST_REGEX.match?(uri) return LINKEDIN if LINKEDIN_REGEX.match?(uri) WEBSITE if WEBSITE_REGEX.match?(uri) end |
.websites ⇒ ActiveRecord::Relation<ContactPoint>
A relation of ContactPoints that are websites. Active Record Scope
138 |
# File 'app/models/contact_point.rb', line 138 scope :websites, -> { by_category(WEBSITE) } |
Instance Method Details
#area_code_object ⇒ AreaCode
81 |
# File 'app/models/contact_point.rb', line 81 belongs_to :area_code_object, class_name: 'AreaCode', inverse_of: :contact_points, foreign_key: :area_code, primary_key: :code, optional: true |
#blocked? ⇒ Boolean
312 313 314 |
# File 'app/models/contact_point.rb', line 312 def blocked? email_blocked? || dnc_blocked? end |
#call_blocked? ⇒ Boolean
296 297 298 |
# File 'app/models/contact_point.rb', line 296 def call_blocked? callable? && do_not_call&.do_not_call&.to_b end |
#callable? ⇒ Boolean
284 285 286 |
# File 'app/models/contact_point.rb', line 284 def callable? CAN_VOICE.include?(category) end |
#can_be_dialed? ⇒ Boolean
248 249 250 |
# File 'app/models/contact_point.rb', line 248 def can_be_dialed? CAN_DIAL.include?(category) end |
#category_and_detail ⇒ Object
244 245 246 |
# File 'app/models/contact_point.rb', line 244 def category_and_detail "#{category}: #{detail}" end |
#communication_recipients ⇒ ActiveRecord::Relation<CommunicationRecipient>
90 |
# File 'app/models/contact_point.rb', line 90 has_many :communication_recipients, dependent: :nullify, inverse_of: :contact_point |
#contactable? ⇒ Boolean
196 197 198 |
# File 'app/models/contact_point.rb', line 196 def contactable? (CAN_DIAL + [EMAIL]).include?(category) end |
#dependents? ⇒ Boolean
320 321 322 323 324 325 326 327 |
# File 'app/models/contact_point.rb', line 320 def dependents? quotes.exists? || room_configurations.exists? || communication_recipients.exists? || opportunity_participants.exists? || feeds.exists? || service_job_dependent? end |
#dial_string ⇒ Object
333 334 335 336 337 |
# File 'app/models/contact_point.rb', line 333 def dial_string return phone_number.to_s if phone_number? detail end |
#dnc_blocked? ⇒ Boolean
308 309 310 |
# File 'app/models/contact_point.rb', line 308 def dnc_blocked? call_blocked? || fax_blocked? || text_blocked? end |
#do_not_call ⇒ DoNotCall
84 |
# File 'app/models/contact_point.rb', line 84 belongs_to :do_not_call, foreign_key: :detail, primary_key: :number, optional: true |
#email? ⇒ Boolean
252 253 254 |
# File 'app/models/contact_point.rb', line 252 def email? category == ContactPoint::EMAIL end |
#email_blocked? ⇒ Boolean
292 293 294 |
# File 'app/models/contact_point.rb', line 292 def email_blocked? email? && email_preference&.any? end |
#email_preference ⇒ EmailPreference
rubocop:disable Rails/InverseOf -- polymorphic FK/PK pair; inverse not supported
83 |
# File 'app/models/contact_point.rb', line 83 belongs_to :email_preference, foreign_key: :detail, primary_key: :email, optional: true |
#email_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
96 |
# File 'app/models/contact_point.rb', line 96 has_many :email_support_case_participants, class_name: 'SupportCaseParticipant', dependent: :nullify, foreign_key: :email_id, inverse_of: :email |
#employee_phone_status ⇒ EmployeePhoneStatus
rubocop:enable Rails/InverseOf
86 |
# File 'app/models/contact_point.rb', line 86 has_one :employee_phone_status, dependent: :destroy |
#facebook? ⇒ Boolean
260 261 262 |
# File 'app/models/contact_point.rb', line 260 def facebook? category == ContactPoint::FACEBOOK end |
#failed_before? ⇒ Boolean
200 201 202 |
# File 'app/models/contact_point.rb', line 200 def failed_before? ContactPoint.exists?(detail: detail, state: 'failed') end |
#fax? ⇒ Boolean
288 289 290 |
# File 'app/models/contact_point.rb', line 288 def fax? category == ContactPoint::FAX end |
#fax_blocked? ⇒ Boolean
300 301 302 |
# File 'app/models/contact_point.rb', line 300 def fax_blocked? fax? && do_not_call&.do_not_fax&.to_b end |
#fax_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
97 |
# File 'app/models/contact_point.rb', line 97 has_many :fax_support_case_participants, class_name: 'SupportCaseParticipant', dependent: :nullify, foreign_key: :fax_id, inverse_of: :fax |
#feeds ⇒ ActiveRecord::Relation<Feed>
101 |
# File 'app/models/contact_point.rb', line 101 has_and_belongs_to_many :feeds, inverse_of: :contact_points |
#formatted_dial_string ⇒ Object
339 340 341 342 343 344 345 346 347 348 349 |
# File 'app/models/contact_point.rb', line 339 def formatted_dial_string if phone_number? && phone_number if party&.is_employee? && party.employee_record.hide_signature_pbx_extension phone_number.format(:crm_no_extension) else phone_number.format(:crm) end else detail end end |
#formatted_for_sms ⇒ Object
351 352 353 354 355 |
# File 'app/models/contact_point.rb', line 351 def formatted_for_sms return unless phone_number? && sms_enabled? phone_number&.format(:pbx_dial) end |
#linkedin? ⇒ Boolean
272 273 274 |
# File 'app/models/contact_point.rb', line 272 def linkedin? category == ContactPoint::LINKEDIN end |
#locator_record ⇒ LocatorRecord
80 |
# File 'app/models/contact_point.rb', line 80 belongs_to :locator_record, inverse_of: :contact_points, optional: true |
#mark_as_working_if_detail_changed ⇒ Object (protected)
415 416 417 |
# File 'app/models/contact_point.rb', line 415 protected def mark_as_working_if_detail_changed self.state = 'working' if (category == EMAIL) && detail_changed? end |
#normalize_format ⇒ Object
rubocop:enable Rails/SkipsModelValidations, Metrics/AbcSize
384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'app/models/contact_point.rb', line 384 def normalize_format return if detail.blank? normalize_detail_characters if RFC822::EMAIL.match?(detail) normalize_as_email elsif website? normalize_as_website elsif (parsed = PhoneNumber.parse(detail)) normalize_as_phone(parsed) end true end |
#notification_channels ⇒ ActiveRecord::Relation<NotificationChannel>
89 |
# File 'app/models/contact_point.rb', line 89 has_many :notification_channels, dependent: :destroy |
#opportunity_participants ⇒ ActiveRecord::Relation<OpportunityParticipant>
rubocop:enable Rails/InverseOf, Rails/HasManyOrHasOneDependent
94 |
# File 'app/models/contact_point.rb', line 94 has_many :opportunity_participants, dependent: :nullify, inverse_of: :contact_point |
#party ⇒ Party
79 |
# File 'app/models/contact_point.rb', line 79 belongs_to :party, inverse_of: :contact_points, optional: true |
#phone_number ⇒ Object
329 330 331 |
# File 'app/models/contact_point.rb', line 329 def phone_number PhoneNumber.parse(detail) end |
#phone_number? ⇒ Boolean
280 281 282 |
# File 'app/models/contact_point.rb', line 280 def phone_number? CAN_DIAL.include?(category) end |
#phone_support_case_participants ⇒ ActiveRecord::Relation<SupportCaseParticipant>
95 |
# File 'app/models/contact_point.rb', line 95 has_many :phone_support_case_participants, class_name: 'SupportCaseParticipant', dependent: :nullify, foreign_key: :phone_id, inverse_of: :phone |
#pinterest? ⇒ Boolean
268 269 270 |
# File 'app/models/contact_point.rb', line 268 def pinterest? category == ContactPoint::PINTEREST end |
#preferred? ⇒ Boolean
316 317 318 |
# File 'app/models/contact_point.rb', line 316 def preferred? position == 1 end |
#quotes ⇒ ActiveRecord::Relation<Quote>
rubocop:disable Rails/HasAndBelongsToMany -- join tables pre-date has_many :through; migrate when touched
100 |
# File 'app/models/contact_point.rb', line 100 has_and_belongs_to_many :quotes, inverse_of: :contact_points |
#room_configurations ⇒ ActiveRecord::Relation<RoomConfiguration>
88 |
# File 'app/models/contact_point.rb', line 88 has_many :room_configurations, dependent: :nullify |
#set_default_sms_status ⇒ Object
407 408 409 410 411 412 413 |
# File 'app/models/contact_point.rb', line 407 def set_default_sms_status if phone_number? self.sms_status = :sms_enabled if category == CELL else self.sms_status = :sms_none end end |
#subscribers ⇒ ActiveRecord::Relation<Subscriber>
rubocop:disable Rails/InverseOf, Rails/HasManyOrHasOneDependent -- string FK on detail; no cascade appropriate
92 |
# File 'app/models/contact_point.rb', line 92 has_many :subscribers, foreign_key: :email_address, primary_key: :detail |
#text_blocked? ⇒ Boolean
304 305 306 |
# File 'app/models/contact_point.rb', line 304 def text_blocked? phone_number? && sms_enabled? && do_not_call&.do_not_text&.to_b end |
#time_at_location ⇒ Object
238 239 240 241 242 |
# File 'app/models/contact_point.rb', line 238 def time_at_location return unless (tz = timezone) tz.utc_to_local(Time.current).strftime('%I:%M %P') end |
#timezone ⇒ Object
233 234 235 236 |
# File 'app/models/contact_point.rb', line 233 def timezone tzn = timezone_name || area_code_object&.timezone_name Timezone[tzn.to_s] # returns nil for invalid timezone strings end |
#to_s ⇒ Object
357 358 359 |
# File 'app/models/contact_point.rb', line 357 def to_s "#{category} : #{formatted_dial_string}" end |
#transmittable? ⇒ Boolean
276 277 278 |
# File 'app/models/contact_point.rb', line 276 def transmittable? CAN_TRANSMIT.include?(category) end |
#twitter? ⇒ Boolean
264 265 266 |
# File 'app/models/contact_point.rb', line 264 def twitter? category == ContactPoint::TWITTER end |
#website? ⇒ Boolean
256 257 258 |
# File 'app/models/contact_point.rb', line 256 def website? [ContactPoint::WEBSITE, ContactPoint::FACEBOOK, ContactPoint::PINTEREST, ContactPoint::LINKEDIN].include?(category) end |
#website_url_format ⇒ Object
399 400 401 402 403 404 405 |
# File 'app/models/contact_point.rb', line 399 def website_url_format return if detail.blank? errors.add(:detail, INVALID_URL_MESSAGE) unless valid_website_uri? rescue Addressable::URI::InvalidURIError errors.add(:detail, INVALID_URL_MESSAGE) end |